mirror of
https://github.com/Maks1mS/nestjs-telegraf.git
synced 2024-12-24 23:14:39 +03:00
Merge pull request #183 from Morb0/feature/v2
This commit is contained in:
commit
85bb916709
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,7 @@
|
|||||||
|
# lock
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# source
|
# source
|
||||||
lib
|
lib
|
||||||
index.ts
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
.prettierrc
|
.prettierrc
|
||||||
|
1
index.d.ts
vendored
1
index.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
export * from './dist';
|
|
6
index.js
6
index.js
@ -1,6 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
function __export(m) {
|
|
||||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
||||||
}
|
|
||||||
exports.__esModule = true;
|
|
||||||
__export(require("./dist"));
|
|
@ -1,19 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
import { HearsTriggers } from 'telegraf/typings/composer';
|
|
||||||
import { Context } from '../interfaces';
|
|
||||||
|
|
||||||
export type TelegrafActionTriggers = HearsTriggers<Context>;
|
|
||||||
|
|
||||||
export interface ActionOptions {
|
|
||||||
triggers: TelegrafActionTriggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling callback_data actions with regular expressions.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=action
|
|
||||||
*/
|
|
||||||
export const Action = (triggers: TelegrafActionTriggers): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.ACTION, { triggers });
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export type TelegrafCashtagCashtag = string | string[];
|
|
||||||
|
|
||||||
export interface CashtagOptions {
|
|
||||||
cashtag: TelegrafCashtagCashtag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cashtag handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=cashtag
|
|
||||||
*/
|
|
||||||
export const Cashtag = (cashtag: TelegrafCashtagCashtag): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.CASHTAG, { cashtag });
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export type TelegrafCommandCommands = string | string[];
|
|
||||||
|
|
||||||
export interface CommandOptions {
|
|
||||||
commands: TelegrafCommandCommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Command handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=command
|
|
||||||
*/
|
|
||||||
export const Command = (commands: TelegrafCommandCommands): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.COMMAND, { commands });
|
|
||||||
};
|
|
3
lib/decorators/core/index.ts
Normal file
3
lib/decorators/core/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './update.decorator';
|
||||||
|
export * from './scene.decorator';
|
||||||
|
export * from './inject-bot.decorator';
|
4
lib/decorators/core/inject-bot.decorator.ts
Normal file
4
lib/decorators/core/inject-bot.decorator.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { Inject } from '@nestjs/common';
|
||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
|
||||||
|
export const InjectBot = (): ParameterDecorator => Inject(Telegraf);
|
8
lib/decorators/core/scene.decorator.ts
Normal file
8
lib/decorators/core/scene.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
import { SCENE_METADATA } from '../../telegraf.constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
export const Scene = (id: string): ClassDecorator =>
|
||||||
|
SetMetadata(SCENE_METADATA, id);
|
@ -1,8 +1,8 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
import { SetMetadata } from '@nestjs/common';
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
import { UPDATE_METADATA } from '../../telegraf.constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `@Update` decorator, it's like NestJS `@Controller` decorator,
|
* `@Update` decorator, it's like NestJS `@Controller` decorator,
|
||||||
* but for Telegram Bot API updates.
|
* but for Telegram Bot API updates.
|
||||||
*/
|
*/
|
||||||
export const Update = (): ClassDecorator => SetMetadata(DECORATORS.UPDATE, {});
|
export const Update = (): ClassDecorator => SetMetadata(UPDATE_METADATA, true);
|
@ -1,22 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export type TelegrafEntityEntity =
|
|
||||||
| string
|
|
||||||
| string[]
|
|
||||||
| RegExp
|
|
||||||
| RegExp[]
|
|
||||||
| Function;
|
|
||||||
|
|
||||||
export interface EntityOptions {
|
|
||||||
entity: TelegrafEntityEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entity handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=entity
|
|
||||||
*/
|
|
||||||
export const Entity = (entity: TelegrafEntityEntity): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.ENTITY, { entity });
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling callback_data actions with game query.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=inlinequery
|
|
||||||
*/
|
|
||||||
export const GameQuery = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.GAME_QUERY, {});
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export type TelegrafHashtagHashtag = string | string[];
|
|
||||||
|
|
||||||
export interface HashtagOptions {
|
|
||||||
hashtag: TelegrafHashtagHashtag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashtag handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=hashtag
|
|
||||||
*/
|
|
||||||
export const Hashtag = (hashtag: TelegrafHashtagHashtag): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.HASHTAG, { hashtag });
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
import { HearsTriggers } from 'telegraf/typings/composer';
|
|
||||||
import { Context } from '../interfaces';
|
|
||||||
|
|
||||||
export type TelegrafHearsTriggers = HearsTriggers<Context>;
|
|
||||||
|
|
||||||
export interface HearsOptions {
|
|
||||||
triggers: TelegrafHearsTriggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling text messages.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=hears
|
|
||||||
*/
|
|
||||||
export const Hears = (triggers: TelegrafHearsTriggers): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.HEARS, { triggers: triggers });
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for /help command.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=help
|
|
||||||
*/
|
|
||||||
export const Help = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.HELP, {});
|
|
||||||
};
|
|
@ -1,18 +1,3 @@
|
|||||||
export * from './action.decorator';
|
export * from './core';
|
||||||
export * from './cashtag.decorator';
|
export * from './listeners';
|
||||||
export * from './command.decorator';
|
export * from './scene';
|
||||||
export * from './entity.decorator';
|
|
||||||
export * from './game-query.decorator';
|
|
||||||
export * from './hashtag.decorator';
|
|
||||||
export * from './hears.decorator';
|
|
||||||
export * from './help.decorator';
|
|
||||||
export * from './inject-bot.decorator';
|
|
||||||
export * from './inline-query.decorator';
|
|
||||||
export * from './mention.decorator';
|
|
||||||
export * from './on.decorator';
|
|
||||||
export * from './phone.decorator';
|
|
||||||
export * from './settings.decorator';
|
|
||||||
export * from './start.decorator';
|
|
||||||
export * from './update.decorator';
|
|
||||||
export * from './update-hooks.decorators';
|
|
||||||
export * from './use.decorator';
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
import { Inject } from '@nestjs/common';
|
|
||||||
import { TELEGRAF_PROVIDER } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export const InjectBot = (): ParameterDecorator => Inject(TELEGRAF_PROVIDER);
|
|
@ -1,28 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
import * as tt from 'telegraf/typings/telegram-types';
|
|
||||||
|
|
||||||
export type TelegrafInlineQueryTriggers = string | string[] | RegExp | RegExp[];
|
|
||||||
|
|
||||||
export interface InlineQueryOptions {
|
|
||||||
triggers?: TelegrafInlineQueryTriggers;
|
|
||||||
updateType:
|
|
||||||
| tt.UpdateType
|
|
||||||
| tt.UpdateType[]
|
|
||||||
| tt.MessageSubTypes
|
|
||||||
| tt.MessageSubTypes[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for handling inline_query actions with regular expressions.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=inlinequery
|
|
||||||
*/
|
|
||||||
export const InlineQuery = (
|
|
||||||
triggers?: TelegrafInlineQueryTriggers,
|
|
||||||
): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.INLINE_QUERY, {
|
|
||||||
triggers,
|
|
||||||
updateType: 'inline_query',
|
|
||||||
});
|
|
||||||
};
|
|
8
lib/decorators/listeners/action.decorator.ts
Normal file
8
lib/decorators/listeners/action.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling callback_data actions with regular expressions.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=action
|
||||||
|
*/
|
||||||
|
export const Action = createUpdateListenerDecorator('action');
|
8
lib/decorators/listeners/cashtag.decorator.ts
Normal file
8
lib/decorators/listeners/cashtag.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashtag handling.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=cashtag
|
||||||
|
*/
|
||||||
|
export const Cashtag = createUpdateListenerDecorator('cashtag');
|
8
lib/decorators/listeners/command.decorator.ts
Normal file
8
lib/decorators/listeners/command.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command handling.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=command
|
||||||
|
*/
|
||||||
|
export const Command = createUpdateListenerDecorator('command');
|
8
lib/decorators/listeners/email.decorator.ts
Normal file
8
lib/decorators/listeners/email.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling messages with email entity.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=telegraf-email
|
||||||
|
*/
|
||||||
|
export const Email = createUpdateListenerDecorator('email');
|
8
lib/decorators/listeners/game-query.decorator.ts
Normal file
8
lib/decorators/listeners/game-query.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling callback_data actions with game query.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=inlinequery
|
||||||
|
*/
|
||||||
|
export const GameQuery = createUpdateListenerDecorator('gameQuery');
|
8
lib/decorators/listeners/hashtag.decorator.ts
Normal file
8
lib/decorators/listeners/hashtag.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashtag handling.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=hashtag
|
||||||
|
*/
|
||||||
|
export const Hashtag = createUpdateListenerDecorator('hashtag');
|
8
lib/decorators/listeners/hears.decorator.ts
Normal file
8
lib/decorators/listeners/hears.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling text messages.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=hears
|
||||||
|
*/
|
||||||
|
export const Hears = createUpdateListenerDecorator('hears');
|
8
lib/decorators/listeners/help.decorator.ts
Normal file
8
lib/decorators/listeners/help.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for /help command.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=help
|
||||||
|
*/
|
||||||
|
export const Help = createUpdateListenerDecorator('help');
|
18
lib/decorators/listeners/index.ts
Normal file
18
lib/decorators/listeners/index.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export * from './on.decorator';
|
||||||
|
export * from './use.decorator';
|
||||||
|
export * from './action.decorator';
|
||||||
|
export * from './cashtag.decorator';
|
||||||
|
export * from './command.decorator';
|
||||||
|
export * from './game-query.decorator';
|
||||||
|
export * from './hashtag.decorator';
|
||||||
|
export * from './hears.decorator';
|
||||||
|
export * from './help.decorator';
|
||||||
|
export * from './inline-query.decorator';
|
||||||
|
export * from './mention.decorator';
|
||||||
|
export * from './phone.decorator';
|
||||||
|
export * from './settings.decorator';
|
||||||
|
export * from './start.decorator';
|
||||||
|
export * from './email.decorator';
|
||||||
|
export * from './url.decorator';
|
||||||
|
export * from './text-link.decorator';
|
||||||
|
export * from './text-mention.decorator';
|
8
lib/decorators/listeners/inline-query.decorator.ts
Normal file
8
lib/decorators/listeners/inline-query.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling inline_query actions with regular expressions.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=inlinequery
|
||||||
|
*/
|
||||||
|
export const InlineQuery = createUpdateListenerDecorator('inlineQuery');
|
8
lib/decorators/listeners/mention.decorator.ts
Normal file
8
lib/decorators/listeners/mention.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mention handling.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=mention
|
||||||
|
*/
|
||||||
|
export const Mention = createUpdateListenerDecorator('mention');
|
8
lib/decorators/listeners/on.decorator.ts
Normal file
8
lib/decorators/listeners/on.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for provided update type.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=on
|
||||||
|
*/
|
||||||
|
export const On = createUpdateListenerDecorator('on');
|
8
lib/decorators/listeners/phone.decorator.ts
Normal file
8
lib/decorators/listeners/phone.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phone number handling.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=phone
|
||||||
|
*/
|
||||||
|
export const Phone = createUpdateListenerDecorator('phone');
|
8
lib/decorators/listeners/settings.decorator.ts
Normal file
8
lib/decorators/listeners/settings.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for /settings command.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=settings
|
||||||
|
*/
|
||||||
|
export const Settings = createUpdateListenerDecorator('settings');
|
8
lib/decorators/listeners/start.decorator.ts
Normal file
8
lib/decorators/listeners/start.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for /start command.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=start
|
||||||
|
*/
|
||||||
|
export const Start = createUpdateListenerDecorator('start');
|
8
lib/decorators/listeners/text-link.decorator.ts
Normal file
8
lib/decorators/listeners/text-link.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling messages with text_link entity.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
||||||
|
*/
|
||||||
|
export const TextLink = createUpdateListenerDecorator('textLink');
|
8
lib/decorators/listeners/text-mention.decorator.ts
Normal file
8
lib/decorators/listeners/text-mention.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling messages with text_mention entity.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=telegraf-textlink
|
||||||
|
*/
|
||||||
|
export const TextMention = createUpdateListenerDecorator('textMention');
|
8
lib/decorators/listeners/url.decorator.ts
Normal file
8
lib/decorators/listeners/url.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers middleware for handling messages with url entity.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=telegraf-url
|
||||||
|
*/
|
||||||
|
export const Url = createUpdateListenerDecorator('url');
|
8
lib/decorators/listeners/use.decorator.ts
Normal file
8
lib/decorators/listeners/use.decorator.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { createUpdateListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a middleware.
|
||||||
|
*
|
||||||
|
* @see https://telegraf.js.org/#/?id=use
|
||||||
|
*/
|
||||||
|
export const Use = createUpdateListenerDecorator('use');
|
@ -1,17 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export type TelegrafMentionUsername = string | string[];
|
|
||||||
|
|
||||||
export interface MentionOptions {
|
|
||||||
username: TelegrafMentionUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mention handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=mention
|
|
||||||
*/
|
|
||||||
export const Mention = (username: TelegrafMentionUsername): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.MENTION, { username });
|
|
||||||
};
|
|
@ -1,22 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
import { UpdateType, MessageSubTypes } from 'telegraf/typings/telegram-types';
|
|
||||||
|
|
||||||
export type TelegrafOnUpdateTypes =
|
|
||||||
| UpdateType
|
|
||||||
| UpdateType[]
|
|
||||||
| MessageSubTypes
|
|
||||||
| MessageSubTypes[];
|
|
||||||
|
|
||||||
export interface OnOptions {
|
|
||||||
updateTypes: TelegrafOnUpdateTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers middleware for provided update type.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=on
|
|
||||||
*/
|
|
||||||
export const On = (updateTypes: TelegrafOnUpdateTypes): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.ON, { updateTypes: updateTypes });
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
export type TelegrafPhonePhone = string | string[];
|
|
||||||
|
|
||||||
export interface PhoneOptions {
|
|
||||||
phone: TelegrafPhonePhone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Phone number handling.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=phone
|
|
||||||
*/
|
|
||||||
export const Phone = (phone: TelegrafPhonePhone): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.PHONE, { phone });
|
|
||||||
};
|
|
2
lib/decorators/scene/index.ts
Normal file
2
lib/decorators/scene/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './scene-enter.decorator';
|
||||||
|
export * from './scene-leave.decorator';
|
3
lib/decorators/scene/scene-enter.decorator.ts
Normal file
3
lib/decorators/scene/scene-enter.decorator.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { createSceneListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
export const SceneEnter = createSceneListenerDecorator('enter');
|
3
lib/decorators/scene/scene-leave.decorator.ts
Normal file
3
lib/decorators/scene/scene-leave.decorator.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { createSceneListenerDecorator } from '../../helpers';
|
||||||
|
|
||||||
|
export const SceneLeave = createSceneListenerDecorator('leave');
|
@ -1,11 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for /settings command.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=settings
|
|
||||||
*/
|
|
||||||
export const Settings = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.SETTINGS, {});
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for /start command.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=start
|
|
||||||
*/
|
|
||||||
export const Start = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.START, {});
|
|
||||||
};
|
|
@ -1,104 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
import * as tt from 'telegraf/typings/telegram-types';
|
|
||||||
|
|
||||||
export interface UpdateHookOptions {
|
|
||||||
updateType:
|
|
||||||
| tt.UpdateType
|
|
||||||
| tt.UpdateType[]
|
|
||||||
| tt.MessageSubTypes
|
|
||||||
| tt.MessageSubTypes[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New incoming message of any kind — text, photo, sticker, etc.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const Message = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'message',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New version of a message that is known to the bot and was edited
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const EditedMessage = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'edited_message',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New incoming channel post of any kind — text, photo, sticker, etc.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const ChannelPost = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'channel_post',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New version of a channel post that is known to the bot and was edited
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const EditedChannelPost = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'edited_channel_post',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New incoming inline query
|
|
||||||
* See this decorator in inline-query.decorator.ts
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
// export const InlineQuery = (): MethodDecorator => {
|
|
||||||
// return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
// updateType: 'inline_query',
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The result of an inline query that was chosen by a user and sent to their chat partner.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const ChosenInlineResult = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'chosen_inline_result',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New incoming callback query
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const CallbackQuery = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'callback_query',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New incoming shipping query. Only for invoices with flexible price
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const ShippingQuery = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'shipping_query',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New incoming pre-checkout query. Contains full information about checkout
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
export const PreCheckoutQuery = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.UPDATE_HOOK, {
|
|
||||||
updateType: 'pre_checkout_query',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Two more decorators are missing here. For 'poll' and 'poll_answer' update types.
|
|
@ -1,11 +0,0 @@
|
|||||||
import { SetMetadata } from '@nestjs/common';
|
|
||||||
import { DECORATORS } from '../telegraf.constants';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a middleware.
|
|
||||||
*
|
|
||||||
* @see https://telegraf.js.org/#/?id=use
|
|
||||||
*/
|
|
||||||
export const Use = (): MethodDecorator => {
|
|
||||||
return SetMetadata(DECORATORS.USE, {});
|
|
||||||
};
|
|
73
lib/explorers/telegraf-scene.explorer.ts
Normal file
73
lib/explorers/telegraf-scene.explorer.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
||||||
|
import { DiscoveryService } from '@nestjs/core';
|
||||||
|
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
||||||
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||||
|
import { BaseScene as Scene, Stage, Telegraf } from 'telegraf';
|
||||||
|
import { TelegrafMetadataAccessor } from '../telegraf.metadata-accessor';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TelegrafSceneExplorer implements OnModuleInit {
|
||||||
|
private readonly stage = new Stage([]);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(Telegraf)
|
||||||
|
private readonly telegraf: Telegraf<never>,
|
||||||
|
private readonly discoveryService: DiscoveryService,
|
||||||
|
private readonly metadataAccessor: TelegrafMetadataAccessor,
|
||||||
|
private readonly metadataScanner: MetadataScanner,
|
||||||
|
) {
|
||||||
|
this.telegraf.use(this.stage.middleware());
|
||||||
|
}
|
||||||
|
|
||||||
|
onModuleInit(): void {
|
||||||
|
this.explore();
|
||||||
|
}
|
||||||
|
|
||||||
|
private explore(): void {
|
||||||
|
const sceneClasses = this.filterSceneClasses();
|
||||||
|
|
||||||
|
sceneClasses.forEach((wrapper) => {
|
||||||
|
const { instance } = wrapper;
|
||||||
|
|
||||||
|
const sceneId = this.metadataAccessor.getSceneMetadata(
|
||||||
|
instance.constructor,
|
||||||
|
);
|
||||||
|
const scene = new Scene(sceneId);
|
||||||
|
this.stage.register(scene);
|
||||||
|
|
||||||
|
const prototype = Object.getPrototypeOf(instance);
|
||||||
|
this.metadataScanner.scanFromPrototype(
|
||||||
|
instance,
|
||||||
|
prototype,
|
||||||
|
(methodKey: string) =>
|
||||||
|
this.registerIfListener(scene, instance, methodKey),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterSceneClasses(): InstanceWrapper[] {
|
||||||
|
return this.discoveryService
|
||||||
|
.getProviders()
|
||||||
|
.filter((wrapper) => wrapper.instance)
|
||||||
|
.filter((wrapper) =>
|
||||||
|
this.metadataAccessor.isScene(wrapper.instance.constructor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerIfListener(
|
||||||
|
scene: Scene<never>,
|
||||||
|
instance: Record<string, Function>,
|
||||||
|
methodKey: string,
|
||||||
|
): void {
|
||||||
|
const methodRef = instance[methodKey];
|
||||||
|
const middlewareFn = methodRef.bind(instance);
|
||||||
|
|
||||||
|
const listenerMetadata = this.metadataAccessor.getListenerMetadata(
|
||||||
|
methodRef,
|
||||||
|
);
|
||||||
|
if (!listenerMetadata) return;
|
||||||
|
|
||||||
|
const { method, args } = listenerMetadata;
|
||||||
|
(scene[method] as any)(...args, middlewareFn);
|
||||||
|
}
|
||||||
|
}
|
63
lib/explorers/telegraf-update.explorer.ts
Normal file
63
lib/explorers/telegraf-update.explorer.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
||||||
|
import { DiscoveryService } from '@nestjs/core';
|
||||||
|
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
||||||
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
import { TelegrafMetadataAccessor } from '../telegraf.metadata-accessor';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TelegrafUpdateExplorer implements OnModuleInit {
|
||||||
|
constructor(
|
||||||
|
@Inject(Telegraf)
|
||||||
|
private readonly telegraf: Telegraf<never>,
|
||||||
|
private readonly discoveryService: DiscoveryService,
|
||||||
|
private readonly metadataAccessor: TelegrafMetadataAccessor,
|
||||||
|
private readonly metadataScanner: MetadataScanner,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
onModuleInit(): void {
|
||||||
|
this.explore();
|
||||||
|
}
|
||||||
|
|
||||||
|
private explore(): void {
|
||||||
|
const updateClasses = this.filterUpdateClasses();
|
||||||
|
|
||||||
|
updateClasses.forEach((wrapper) => {
|
||||||
|
const { instance } = wrapper;
|
||||||
|
|
||||||
|
const prototype = Object.getPrototypeOf(instance);
|
||||||
|
this.metadataScanner.scanFromPrototype(
|
||||||
|
instance,
|
||||||
|
prototype,
|
||||||
|
(methodKey: string) => this.registerIfListener(instance, methodKey),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterUpdateClasses(): InstanceWrapper[] {
|
||||||
|
return this.discoveryService
|
||||||
|
.getProviders()
|
||||||
|
.filter((wrapper) => wrapper.instance)
|
||||||
|
.filter((wrapper) =>
|
||||||
|
this.metadataAccessor.isUpdate(wrapper.instance.constructor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerIfListener(
|
||||||
|
instance: Record<string, Function>,
|
||||||
|
methodKey: string,
|
||||||
|
): void {
|
||||||
|
const methodRef = instance[methodKey];
|
||||||
|
const middlewareFn = methodRef.bind(instance);
|
||||||
|
|
||||||
|
const listenerMetadata = this.metadataAccessor.getListenerMetadata(
|
||||||
|
methodRef,
|
||||||
|
);
|
||||||
|
if (!listenerMetadata) return;
|
||||||
|
|
||||||
|
const { method, args } = listenerMetadata;
|
||||||
|
// NOTE: Use "any" to disable "Expected at least 1 arguments, but got 1 or more." error.
|
||||||
|
// Use telegraf instance for non-scene listeners
|
||||||
|
(this.telegraf[method] as any)(...args, middlewareFn);
|
||||||
|
}
|
||||||
|
}
|
18
lib/helpers/create-scene-listener-decorator.helper.ts
Normal file
18
lib/helpers/create-scene-listener-decorator.helper.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
import { BaseScene as Scene } from 'telegraf';
|
||||||
|
import { ComposerMethodArgs, SceneMethods } from '../telegraf.types';
|
||||||
|
import { UPDATE_LISTENER_METADATA } from '../telegraf.constants';
|
||||||
|
import { ListenerMetadata } from '../interfaces';
|
||||||
|
|
||||||
|
export function createSceneListenerDecorator<Method extends SceneMethods>(
|
||||||
|
method: Method,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
...args: ComposerMethodArgs<Scene<never>, Method>
|
||||||
|
): MethodDecorator => {
|
||||||
|
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
||||||
|
method,
|
||||||
|
args,
|
||||||
|
} as ListenerMetadata);
|
||||||
|
};
|
||||||
|
}
|
18
lib/helpers/create-update-listener-decorator.helper.ts
Normal file
18
lib/helpers/create-update-listener-decorator.helper.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
import { Composer } from 'telegraf';
|
||||||
|
import { ComposerMethodArgs, UpdateMethods } from '../telegraf.types';
|
||||||
|
import { UPDATE_LISTENER_METADATA } from '../telegraf.constants';
|
||||||
|
import { ListenerMetadata } from '../interfaces';
|
||||||
|
|
||||||
|
export function createUpdateListenerDecorator<Method extends UpdateMethods>(
|
||||||
|
method: Method,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
...args: ComposerMethodArgs<Composer<never>, Method>
|
||||||
|
): MethodDecorator => {
|
||||||
|
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
||||||
|
method,
|
||||||
|
args,
|
||||||
|
} as ListenerMetadata);
|
||||||
|
};
|
||||||
|
}
|
2
lib/helpers/index.ts
Normal file
2
lib/helpers/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './create-update-listener-decorator.helper';
|
||||||
|
export * from './create-scene-listener-decorator.helper';
|
11
lib/index.ts
11
lib/index.ts
@ -1,12 +1,5 @@
|
|||||||
export * as Composer from 'telegraf/composer';
|
|
||||||
export * as Markup from 'telegraf/markup';
|
|
||||||
export * as BaseScene from 'telegraf/scenes/base';
|
|
||||||
export * as session from 'telegraf/session';
|
|
||||||
export * as Stage from 'telegraf/stage';
|
|
||||||
export * as WizardScene from 'telegraf/scenes/wizard';
|
|
||||||
export * as Extra from 'telegraf/extra';
|
|
||||||
|
|
||||||
export * from './decorators';
|
export * from './decorators';
|
||||||
export * from './interfaces';
|
export * from './interfaces';
|
||||||
|
export * from './helpers';
|
||||||
export * from './telegraf.module';
|
export * from './telegraf.module';
|
||||||
export * from './telegraf.provider';
|
export * from './telegraf.types';
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import { Context as TelegrafContext } from 'telegraf';
|
|
||||||
|
|
||||||
export interface Context extends TelegrafContext {}
|
|
@ -1,2 +1,2 @@
|
|||||||
export * from './context.interface';
|
|
||||||
export * from './telegraf-options.interface';
|
export * from './telegraf-options.interface';
|
||||||
|
export * from './listener-metadata.interface';
|
||||||
|
4
lib/interfaces/listener-metadata.interface.ts
Normal file
4
lib/interfaces/listener-metadata.interface.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface ListenerMetadata {
|
||||||
|
method: string;
|
||||||
|
args: unknown[];
|
||||||
|
}
|
@ -1,17 +1,19 @@
|
|||||||
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
import { ModuleMetadata, Type } from '@nestjs/common/interfaces';
|
||||||
|
import { Middleware, Context } from 'telegraf';
|
||||||
import {
|
import {
|
||||||
TelegrafOptions,
|
|
||||||
LaunchPollingOptions,
|
LaunchPollingOptions,
|
||||||
LaunchWebhookOptions,
|
LaunchWebhookOptions,
|
||||||
|
TelegrafOptions,
|
||||||
} from 'telegraf/typings/telegraf';
|
} from 'telegraf/typings/telegraf';
|
||||||
|
|
||||||
export interface TelegrafModuleOptions {
|
export interface TelegrafModuleOptions<C extends Context = Context> {
|
||||||
token: string;
|
token: string;
|
||||||
options?: TelegrafOptions;
|
options?: TelegrafOptions;
|
||||||
launchOptions?: {
|
launchOptions?: {
|
||||||
polling?: LaunchPollingOptions;
|
polling?: LaunchPollingOptions;
|
||||||
webhook?: LaunchWebhookOptions;
|
webhook?: LaunchWebhookOptions;
|
||||||
};
|
};
|
||||||
|
middlewares?: Middleware<C>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TelegrafOptionsFactory {
|
export interface TelegrafOptionsFactory {
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
import { DiscoveryModule } from '@nestjs/core';
|
|
||||||
import { Module, DynamicModule, Provider, Type } from '@nestjs/common';
|
|
||||||
import {
|
|
||||||
TelegrafModuleOptions,
|
|
||||||
TelegrafModuleAsyncOptions,
|
|
||||||
TelegrafOptionsFactory,
|
|
||||||
} from './interfaces';
|
|
||||||
import {
|
|
||||||
TELEGRAF_MODULE_OPTIONS,
|
|
||||||
TELEGRAF_PROVIDER,
|
|
||||||
} from './telegraf.constants';
|
|
||||||
import { TelegrafMetadataAccessor } from './telegraf-metadata.accessor';
|
|
||||||
import { TelegrafExplorer } from './telegraf.explorer';
|
|
||||||
import { TelegrafProvider } from './telegraf.provider';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [DiscoveryModule],
|
|
||||||
providers: [TelegrafMetadataAccessor, TelegrafExplorer],
|
|
||||||
})
|
|
||||||
export class TelegrafCoreModule {
|
|
||||||
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
|
||||||
const telegrafProvider = {
|
|
||||||
provide: TELEGRAF_PROVIDER,
|
|
||||||
useClass: TelegrafProvider,
|
|
||||||
inject: [TELEGRAF_MODULE_OPTIONS],
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
module: TelegrafCoreModule,
|
|
||||||
providers: [
|
|
||||||
{ provide: TELEGRAF_MODULE_OPTIONS, useValue: options },
|
|
||||||
telegrafProvider,
|
|
||||||
],
|
|
||||||
exports: [telegrafProvider],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static forRootAsync(
|
|
||||||
options: TelegrafModuleAsyncOptions,
|
|
||||||
): DynamicModule {
|
|
||||||
const telegrafProvider = {
|
|
||||||
provide: TELEGRAF_PROVIDER,
|
|
||||||
useClass: TelegrafProvider,
|
|
||||||
inject: [TELEGRAF_MODULE_OPTIONS],
|
|
||||||
};
|
|
||||||
const asyncProviders = this.createAsyncProviders(options);
|
|
||||||
return {
|
|
||||||
module: TelegrafCoreModule,
|
|
||||||
imports: options.imports,
|
|
||||||
providers: [...asyncProviders, telegrafProvider],
|
|
||||||
exports: [telegrafProvider],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static createAsyncProviders(
|
|
||||||
options: TelegrafModuleAsyncOptions,
|
|
||||||
): Provider[] {
|
|
||||||
if (options.useExisting || options.useFactory) {
|
|
||||||
return [this.createAsyncOptionsProvider(options)];
|
|
||||||
}
|
|
||||||
const useClass = options.useClass as Type<TelegrafOptionsFactory>;
|
|
||||||
return [
|
|
||||||
this.createAsyncOptionsProvider(options),
|
|
||||||
{
|
|
||||||
provide: useClass,
|
|
||||||
useClass,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static createAsyncOptionsProvider(
|
|
||||||
options: TelegrafModuleAsyncOptions,
|
|
||||||
): Provider {
|
|
||||||
if (options.useFactory) {
|
|
||||||
return {
|
|
||||||
provide: TELEGRAF_MODULE_OPTIONS,
|
|
||||||
useFactory: options.useFactory,
|
|
||||||
inject: options.inject || [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// `as Type<TelegrafOptionsFactory>` is a workaround for microsoft/TypeScript#31603
|
|
||||||
const inject = [
|
|
||||||
(options.useClass || options.useExisting) as Type<TelegrafOptionsFactory>,
|
|
||||||
];
|
|
||||||
return {
|
|
||||||
provide: TELEGRAF_MODULE_OPTIONS,
|
|
||||||
useFactory: async (optionsFactory: TelegrafOptionsFactory) =>
|
|
||||||
await optionsFactory.createTelegrafOptions(),
|
|
||||||
inject,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,204 +0,0 @@
|
|||||||
import { Injectable, Type } from '@nestjs/common';
|
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
import {
|
|
||||||
ActionOptions,
|
|
||||||
CashtagOptions,
|
|
||||||
CommandOptions,
|
|
||||||
EntityOptions,
|
|
||||||
HashtagOptions,
|
|
||||||
HearsOptions,
|
|
||||||
InlineQueryOptions,
|
|
||||||
MentionOptions,
|
|
||||||
OnOptions,
|
|
||||||
PhoneOptions,
|
|
||||||
UpdateHookOptions,
|
|
||||||
} from './decorators';
|
|
||||||
import { DECORATORS } from './telegraf.constants';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TelegrafMetadataAccessor {
|
|
||||||
constructor(private readonly reflector: Reflector) {}
|
|
||||||
|
|
||||||
isUpdate(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.UPDATE, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isUpdateHook(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.UPDATE_HOOK, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUpdateHookMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): UpdateHookOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.UPDATE_HOOK, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafUse(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.USE, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafOn(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.ON, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafOnMetadata(target: Type<any> | Function): OnOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.ON, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafHears(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.HEARS, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafHearsMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): HearsOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.HEARS, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafCommand(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.COMMAND, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafCommandMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): CommandOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.COMMAND, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafStart(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.START, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafHelp(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.HELP, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafSettings(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.SETTINGS, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafEntity(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.ENTITY, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafEntityMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): EntityOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.ENTITY, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafMention(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.MENTION, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafMentionMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): MentionOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.MENTION, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafPhone(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.PHONE, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafPhoneMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): PhoneOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.PHONE, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafHashtag(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.HASHTAG, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafHashtagMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): HashtagOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.HASHTAG, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafCashtag(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.CASHTAG, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafCashtagMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): CashtagOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.CASHTAG, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafAction(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.ACTION, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafActionMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): ActionOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.ACTION, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafInlineQuery(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.INLINE_QUERY, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTelegrafInlineQueryMetadata(
|
|
||||||
target: Type<any> | Function,
|
|
||||||
): InlineQueryOptions | undefined {
|
|
||||||
return this.reflector.get(DECORATORS.INLINE_QUERY, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
isTelegrafGameQuery(target: Type<any> | Function): boolean {
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!this.reflector.get(DECORATORS.GAME_QUERY, target);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +1,6 @@
|
|||||||
export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
||||||
export const TELEGRAF_PROVIDER = 'TelegrafProvider';
|
|
||||||
|
|
||||||
export const DECORATORS_PREFIX = 'TELEGRAF';
|
export const UPDATE_METADATA = 'UPDATE_METADATA';
|
||||||
export const DECORATORS = {
|
export const UPDATE_LISTENER_METADATA = 'UPDATE_LISTENER_METADATA';
|
||||||
USE: `${DECORATORS_PREFIX}/USE`,
|
|
||||||
ON: `${DECORATORS_PREFIX}/ON`,
|
export const SCENE_METADATA = 'SCENE_METADATA';
|
||||||
HEARS: `${DECORATORS_PREFIX}/HEARS`,
|
|
||||||
COMMAND: `${DECORATORS_PREFIX}/COMMAND`,
|
|
||||||
START: `${DECORATORS_PREFIX}/START`,
|
|
||||||
HELP: `${DECORATORS_PREFIX}/HELP`,
|
|
||||||
SETTINGS: `${DECORATORS_PREFIX}/SETTINGS`,
|
|
||||||
ENTITY: `${DECORATORS_PREFIX}/ENTITY`,
|
|
||||||
MENTION: `${DECORATORS_PREFIX}/MENTION`,
|
|
||||||
PHONE: `${DECORATORS_PREFIX}/PHONE`,
|
|
||||||
HASHTAG: `${DECORATORS_PREFIX}/HASHTAG`,
|
|
||||||
CASHTAG: `${DECORATORS_PREFIX}/CASHTAG`,
|
|
||||||
ACTION: `${DECORATORS_PREFIX}/ACTION`,
|
|
||||||
INLINE_QUERY: `${DECORATORS_PREFIX}/INLINE_QUERY`,
|
|
||||||
GAME_QUERY: `${DECORATORS_PREFIX}/GAME_QUERY`,
|
|
||||||
UPDATE: `${DECORATORS_PREFIX}/UPDATE`,
|
|
||||||
UPDATE_HOOK: `${DECORATORS_PREFIX}/UPDATE_HOOK`,
|
|
||||||
};
|
|
||||||
|
@ -1,238 +0,0 @@
|
|||||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
|
||||||
import { DiscoveryService, ModuleRef } from '@nestjs/core';
|
|
||||||
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
|
||||||
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
|
||||||
import { TelegrafMetadataAccessor } from './telegraf-metadata.accessor';
|
|
||||||
import { TelegrafProvider } from './telegraf.provider';
|
|
||||||
import { TELEGRAF_PROVIDER } from './telegraf.constants';
|
|
||||||
import {
|
|
||||||
ActionOptions,
|
|
||||||
CashtagOptions,
|
|
||||||
CommandOptions,
|
|
||||||
EntityOptions,
|
|
||||||
HashtagOptions,
|
|
||||||
HearsOptions,
|
|
||||||
InlineQueryOptions,
|
|
||||||
MentionOptions,
|
|
||||||
OnOptions,
|
|
||||||
PhoneOptions,
|
|
||||||
UpdateHookOptions,
|
|
||||||
} from './decorators';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TelegrafExplorer implements OnModuleInit {
|
|
||||||
constructor(
|
|
||||||
private readonly moduleRef: ModuleRef,
|
|
||||||
private readonly discoveryService: DiscoveryService,
|
|
||||||
private readonly metadataAccessor: TelegrafMetadataAccessor,
|
|
||||||
private readonly metadataScanner: MetadataScanner,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private telegraf: TelegrafProvider;
|
|
||||||
|
|
||||||
onModuleInit() {
|
|
||||||
this.telegraf = this.moduleRef.get<TelegrafProvider>(TELEGRAF_PROVIDER, {
|
|
||||||
strict: false,
|
|
||||||
});
|
|
||||||
this.explore();
|
|
||||||
}
|
|
||||||
|
|
||||||
explore() {
|
|
||||||
/**
|
|
||||||
* Update providers section is only for decorators under Update decorator
|
|
||||||
*/
|
|
||||||
const updateProviders: InstanceWrapper[] = this.discoveryService
|
|
||||||
.getProviders()
|
|
||||||
.filter((wrapper: InstanceWrapper) =>
|
|
||||||
this.metadataAccessor.isUpdate(wrapper.metatype),
|
|
||||||
);
|
|
||||||
|
|
||||||
updateProviders.forEach((wrapper: InstanceWrapper) => {
|
|
||||||
const { instance } = wrapper;
|
|
||||||
|
|
||||||
this.metadataScanner.scanFromPrototype(
|
|
||||||
instance,
|
|
||||||
Object.getPrototypeOf(instance),
|
|
||||||
(key: string) => {
|
|
||||||
if (this.metadataAccessor.isUpdateHook(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getUpdateHookMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleUpdateHook(instance, key, metadata);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const providers: InstanceWrapper[] = this.discoveryService.getProviders();
|
|
||||||
|
|
||||||
providers.forEach((wrapper: InstanceWrapper) => {
|
|
||||||
const { instance } = wrapper;
|
|
||||||
|
|
||||||
if (!instance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.metadataScanner.scanFromPrototype(
|
|
||||||
instance,
|
|
||||||
Object.getPrototypeOf(instance),
|
|
||||||
(key: string) => {
|
|
||||||
if (this.metadataAccessor.isTelegrafUse(instance[key])) {
|
|
||||||
this.handleTelegrafUse(instance, key);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafOn(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafOnMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafOn(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafHears(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafHearsMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafHears(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafCommand(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafCommandMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafCommand(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafStart(instance[key])) {
|
|
||||||
this.handleTelegrafStart(instance, key);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafHelp(instance[key])) {
|
|
||||||
this.handleTelegrafHelp(instance, key);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafSettings(instance[key])) {
|
|
||||||
this.handleTelegrafSettings(instance, key);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafEntity(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafEntityMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafEntity(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafMention(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafMentionMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafMention(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafPhone(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafPhoneMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafPhone(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafHashtag(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafHashtagMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafHashtag(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafCashtag(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafCashtagMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafCashtag(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafAction(instance[key])) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafActionMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafAction(instance, key, metadata);
|
|
||||||
} else if (
|
|
||||||
this.metadataAccessor.isTelegrafInlineQuery(instance[key])
|
|
||||||
) {
|
|
||||||
const metadata = this.metadataAccessor.getTelegrafInlineQueryMetadata(
|
|
||||||
instance[key],
|
|
||||||
);
|
|
||||||
this.handleTelegrafInlineQuery(instance, key, metadata);
|
|
||||||
} else if (this.metadataAccessor.isTelegrafGameQuery(instance[key])) {
|
|
||||||
this.handleTelegrafGameQuery(instance, key);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleUpdateHook(instance: object, key: string, metadata: UpdateHookOptions) {
|
|
||||||
this.telegraf.on(metadata.updateType, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafUse(instance: object, key: string) {
|
|
||||||
this.telegraf.use(instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafOn(instance: object, key: string, metadata: OnOptions) {
|
|
||||||
this.telegraf.on(metadata.updateTypes, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafHears(instance: object, key: string, metadata: HearsOptions) {
|
|
||||||
this.telegraf.hears(metadata.triggers, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafCommand(
|
|
||||||
instance: object,
|
|
||||||
key: string,
|
|
||||||
metadata: CommandOptions,
|
|
||||||
) {
|
|
||||||
this.telegraf.command(metadata.commands, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafStart(instance: object, key: string) {
|
|
||||||
this.telegraf.start(instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafHelp(instance: object, key: string) {
|
|
||||||
this.telegraf.help(instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafSettings(instance: object, key: string) {
|
|
||||||
this.telegraf.settings(instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafEntity(instance: object, key: string, metadata: EntityOptions) {
|
|
||||||
this.telegraf.entity(metadata.entity, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafMention(
|
|
||||||
instance: object,
|
|
||||||
key: string,
|
|
||||||
metadata: MentionOptions,
|
|
||||||
) {
|
|
||||||
this.telegraf.mention(metadata.username, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafPhone(instance: object, key: string, metadata: PhoneOptions) {
|
|
||||||
this.telegraf.phone(metadata.phone, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafHashtag(
|
|
||||||
instance: object,
|
|
||||||
key: string,
|
|
||||||
metadata: HashtagOptions,
|
|
||||||
) {
|
|
||||||
this.telegraf.hashtag(metadata.hashtag, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafCashtag(
|
|
||||||
instance: object,
|
|
||||||
key: string,
|
|
||||||
metadata: CashtagOptions,
|
|
||||||
) {
|
|
||||||
this.telegraf.cashtag(metadata.cashtag, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafAction(instance: object, key: string, metadata: ActionOptions) {
|
|
||||||
this.telegraf.action(metadata.triggers, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafInlineQuery(
|
|
||||||
instance: object,
|
|
||||||
key: string,
|
|
||||||
metadata: InlineQueryOptions,
|
|
||||||
) {
|
|
||||||
if (metadata.triggers) {
|
|
||||||
this.telegraf.inlineQuery(
|
|
||||||
metadata.triggers,
|
|
||||||
instance[key].bind(instance),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.telegraf.on(metadata.updateType, instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTelegrafGameQuery(instance: object, key: string) {
|
|
||||||
this.telegraf.gameQuery(instance[key].bind(instance));
|
|
||||||
}
|
|
||||||
}
|
|
29
lib/telegraf.metadata-accessor.ts
Normal file
29
lib/telegraf.metadata-accessor.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Reflector } from '@nestjs/core';
|
||||||
|
import {
|
||||||
|
SCENE_METADATA,
|
||||||
|
UPDATE_LISTENER_METADATA,
|
||||||
|
UPDATE_METADATA,
|
||||||
|
} from './telegraf.constants';
|
||||||
|
import { ListenerMetadata } from './interfaces';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TelegrafMetadataAccessor {
|
||||||
|
constructor(private readonly reflector: Reflector) {}
|
||||||
|
|
||||||
|
isUpdate(target: Function): boolean {
|
||||||
|
return !!this.reflector.get(UPDATE_METADATA, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
isScene(target: Function): boolean {
|
||||||
|
return !!this.reflector.get(SCENE_METADATA, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
getListenerMetadata(target: Function): ListenerMetadata | undefined {
|
||||||
|
return this.reflector.get(UPDATE_LISTENER_METADATA, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSceneMetadata(target: Function): string | undefined {
|
||||||
|
return this.reflector.get(SCENE_METADATA, target);
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,106 @@
|
|||||||
import { Module, DynamicModule } from '@nestjs/common';
|
import { DiscoveryModule, ModuleRef } from '@nestjs/core';
|
||||||
import { TelegrafCoreModule } from './telegraf-core.module';
|
import {
|
||||||
|
DynamicModule,
|
||||||
|
Inject,
|
||||||
|
Module,
|
||||||
|
OnApplicationBootstrap,
|
||||||
|
OnApplicationShutdown,
|
||||||
|
Provider,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { Telegraf } from 'telegraf';
|
||||||
import {
|
import {
|
||||||
TelegrafModuleOptions,
|
|
||||||
TelegrafModuleAsyncOptions,
|
TelegrafModuleAsyncOptions,
|
||||||
|
TelegrafModuleOptions,
|
||||||
|
TelegrafOptionsFactory,
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
|
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
||||||
|
import { TelegrafMetadataAccessor } from './telegraf.metadata-accessor';
|
||||||
|
import { TelegrafUpdateExplorer } from './explorers/telegraf-update.explorer';
|
||||||
|
import { TelegrafSceneExplorer } from './explorers/telegraf-scene.explorer';
|
||||||
|
import { createProviders, TelegrafProvider } from './telegraf.providers';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [DiscoveryModule],
|
||||||
|
providers: [
|
||||||
|
TelegrafMetadataAccessor,
|
||||||
|
TelegrafSceneExplorer,
|
||||||
|
TelegrafUpdateExplorer,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class TelegrafModule
|
||||||
|
implements OnApplicationBootstrap, OnApplicationShutdown {
|
||||||
|
constructor(
|
||||||
|
@Inject(TELEGRAF_MODULE_OPTIONS)
|
||||||
|
private readonly options: TelegrafModuleOptions,
|
||||||
|
private readonly moduleRef: ModuleRef,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async onApplicationBootstrap(): Promise<void> {
|
||||||
|
const { launchOptions } = this.options;
|
||||||
|
const telegraf = this.moduleRef.get(Telegraf);
|
||||||
|
await telegraf.launch(launchOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onApplicationShutdown(): Promise<void> {
|
||||||
|
const telegraf = this.moduleRef.get(Telegraf);
|
||||||
|
await telegraf.stop();
|
||||||
|
}
|
||||||
|
|
||||||
@Module({})
|
|
||||||
export class TelegrafModule {
|
|
||||||
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
public static forRoot(options: TelegrafModuleOptions): DynamicModule {
|
||||||
|
const providers = [...createProviders(options), TelegrafProvider];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
module: TelegrafModule,
|
module: TelegrafModule,
|
||||||
imports: [TelegrafCoreModule.forRoot(options)],
|
providers,
|
||||||
exports: [TelegrafCoreModule],
|
exports: providers,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static forRootAsync(
|
public static forRootAsync(
|
||||||
options: TelegrafModuleAsyncOptions,
|
options: TelegrafModuleAsyncOptions,
|
||||||
): DynamicModule {
|
): DynamicModule {
|
||||||
|
const providers = [...this.createAsyncProviders(options), TelegrafProvider];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
module: TelegrafModule,
|
module: TelegrafModule,
|
||||||
imports: [TelegrafCoreModule.forRootAsync(options)],
|
imports: options.imports || [],
|
||||||
exports: [TelegrafCoreModule],
|
providers,
|
||||||
|
exports: providers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static createAsyncProviders(
|
||||||
|
options: TelegrafModuleAsyncOptions,
|
||||||
|
): Provider[] {
|
||||||
|
if (options.useExisting || options.useFactory) {
|
||||||
|
return [this.createAsyncOptionsProvider(options)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.createAsyncOptionsProvider(options),
|
||||||
|
{
|
||||||
|
provide: options.useClass,
|
||||||
|
useClass: options.useClass,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static createAsyncOptionsProvider(
|
||||||
|
options: TelegrafModuleAsyncOptions,
|
||||||
|
): Provider {
|
||||||
|
if (options.useFactory) {
|
||||||
|
return {
|
||||||
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useFactory: options.useFactory,
|
||||||
|
inject: options.inject || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useFactory: async (optionsFactory: TelegrafOptionsFactory) =>
|
||||||
|
await optionsFactory.createTelegrafOptions(),
|
||||||
|
inject: [options.useExisting || options.useClass],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
import {
|
|
||||||
Injectable,
|
|
||||||
Inject,
|
|
||||||
OnApplicationBootstrap,
|
|
||||||
Logger,
|
|
||||||
OnApplicationShutdown,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { Telegraf } from 'telegraf';
|
|
||||||
import { Context, TelegrafModuleOptions } from './interfaces';
|
|
||||||
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TelegrafProvider extends Telegraf<Context>
|
|
||||||
implements OnApplicationBootstrap, OnApplicationShutdown {
|
|
||||||
private logger = new Logger('Telegraf');
|
|
||||||
private readonly launchOptions;
|
|
||||||
|
|
||||||
constructor(@Inject(TELEGRAF_MODULE_OPTIONS) options: TelegrafModuleOptions) {
|
|
||||||
super(options.token, options.options);
|
|
||||||
this.launchOptions = options.launchOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApplicationBootstrap() {
|
|
||||||
this.catch((err, ctx: Context) => {
|
|
||||||
this.logger.error(
|
|
||||||
`Encountered an error for ${ctx.updateType} update type`,
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.launch(this.launchOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApplicationShutdown() {
|
|
||||||
await this.stop();
|
|
||||||
}
|
|
||||||
}
|
|
23
lib/telegraf.providers.ts
Normal file
23
lib/telegraf.providers.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Provider } from '@nestjs/common';
|
||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
import { TELEGRAF_MODULE_OPTIONS } from './telegraf.constants';
|
||||||
|
import { TelegrafModuleOptions } from './interfaces';
|
||||||
|
|
||||||
|
export const TelegrafProvider = {
|
||||||
|
provide: Telegraf,
|
||||||
|
useFactory: (options: TelegrafModuleOptions) => {
|
||||||
|
const telegraf = new Telegraf(options.token, options.options);
|
||||||
|
telegraf.use(...options.middlewares);
|
||||||
|
return telegraf;
|
||||||
|
},
|
||||||
|
inject: [TELEGRAF_MODULE_OPTIONS],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function createProviders(options: TelegrafModuleOptions): Provider[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
provide: TELEGRAF_MODULE_OPTIONS,
|
||||||
|
useValue: options,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
21
lib/telegraf.types.ts
Normal file
21
lib/telegraf.types.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { BaseScene, Composer, Middleware } from 'telegraf';
|
||||||
|
|
||||||
|
export type Filter<T extends any[], F> = T extends []
|
||||||
|
? []
|
||||||
|
: T extends [infer Head, ...infer Tail]
|
||||||
|
? Head extends F
|
||||||
|
? Filter<Tail, F>
|
||||||
|
: [Head, ...Filter<Tail, F>]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
export type OnlyFunctionPropertyNames<T> = {
|
||||||
|
[K in keyof T]: T[K] extends (...args: any) => any ? K : never;
|
||||||
|
}[keyof T];
|
||||||
|
|
||||||
|
export type ComposerMethodArgs<
|
||||||
|
T extends Composer<never>,
|
||||||
|
U extends OnlyFunctionPropertyNames<T> = OnlyFunctionPropertyNames<T>
|
||||||
|
> = Filter<Parameters<T[U]>, Middleware<never>>;
|
||||||
|
|
||||||
|
export type UpdateMethods = OnlyFunctionPropertyNames<Composer<never>>;
|
||||||
|
export type SceneMethods = OnlyFunctionPropertyNames<BaseScene<never>>;
|
1239
package-lock.json
generated
1239
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
31
package.json
31
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nestjs-telegraf",
|
"name": "nestjs-telegraf",
|
||||||
"version": "2.0.0-alpha.1",
|
"version": "2.0.0",
|
||||||
"description": "Telegraf module for NestJS",
|
"description": "Telegraf module for NestJS",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"nest",
|
"nest",
|
||||||
@ -30,25 +30,28 @@
|
|||||||
"precommit": "lint-staged",
|
"precommit": "lint-staged",
|
||||||
"prepublish:npm": "npm run build",
|
"prepublish:npm": "npm run build",
|
||||||
"publish:npm": "npm publish --access public",
|
"publish:npm": "npm publish --access public",
|
||||||
"test": ""
|
"test": "",
|
||||||
|
"sample-app": "ts-node --transpile-only -r tsconfig-paths/register sample/main.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"telegraf": "git://github.com/telegraf/telegraf.git#addd845af3a20948ba0ee32fe6b1b4374bff1f09"
|
"telegraf": "^3.38.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/common": "7.4.4",
|
"@nestjs/common": "7.6.1",
|
||||||
"@nestjs/core": "7.4.4",
|
"@nestjs/core": "7.6.1",
|
||||||
"@typescript-eslint/eslint-plugin": "4.0.0",
|
"@typescript-eslint/eslint-plugin": "4.9.1",
|
||||||
"@typescript-eslint/parser": "3.10.1",
|
"@typescript-eslint/parser": "4.9.1",
|
||||||
"eslint": "7.8.1",
|
"eslint": "7.15.0",
|
||||||
"eslint-config-prettier": "6.11.0",
|
"eslint-config-prettier": "7.0.0",
|
||||||
"eslint-plugin-import": "2.22.0",
|
"eslint-plugin-import": "2.22.1",
|
||||||
"husky": "4.3.0",
|
"husky": "4.3.5",
|
||||||
"lint-staged": "10.3.0",
|
"lint-staged": "10.5.3",
|
||||||
"prettier": "2.1.1",
|
"prettier": "2.2.1",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"rxjs": "6.6.3",
|
"rxjs": "6.6.3",
|
||||||
"typescript": "4.0.2"
|
"ts-node": "^9.1.1",
|
||||||
|
"tsconfig-paths": "^3.9.0",
|
||||||
|
"typescript": "4.1.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@nestjs/common": "^6.7.0 || ^7.0.0",
|
"@nestjs/common": "^6.7.0 || ^7.0.0",
|
||||||
|
1
sample/app.constants.ts
Normal file
1
sample/app.constants.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const HELLO_SCENE_ID = 'HELLO_SCENE_ID';
|
17
sample/app.module.ts
Normal file
17
sample/app.module.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TelegrafModule } from '../lib';
|
||||||
|
import { EchoService } from './echo.service';
|
||||||
|
import { AppUpdate } from './app.update';
|
||||||
|
import { HelloScene } from './scenes/hello.scene';
|
||||||
|
import { sessionMiddleware } from './middleware/session.middleware';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TelegrafModule.forRoot({
|
||||||
|
token: '1467731595:AAHCvH65H9VQYKF9jE-E8c2rXsQBVAYseg8', // Don't steal >:(
|
||||||
|
middlewares: [sessionMiddleware],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
providers: [EchoService, AppUpdate, HelloScene],
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
43
sample/app.update.ts
Normal file
43
sample/app.update.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { SceneContext, Telegraf } from 'telegraf';
|
||||||
|
import { Command, Help, InjectBot, On, Start, Update } from '../lib';
|
||||||
|
import { EchoService } from './echo.service';
|
||||||
|
import { HELLO_SCENE_ID } from './app.constants';
|
||||||
|
import { Context } from './interfaces/context.interface';
|
||||||
|
|
||||||
|
@Update()
|
||||||
|
export class AppUpdate {
|
||||||
|
constructor(
|
||||||
|
@InjectBot()
|
||||||
|
private readonly bot: Telegraf<SceneContext>,
|
||||||
|
private readonly echoService: EchoService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Start()
|
||||||
|
async onStart(ctx: Context): Promise<void> {
|
||||||
|
const me = await this.bot.telegram.getMe();
|
||||||
|
await ctx.reply(`Hey, I'm ${me.first_name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Help()
|
||||||
|
async onHelp(ctx: Context): Promise<void> {
|
||||||
|
await ctx.reply('Send me any text');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command('scene')
|
||||||
|
async onSceneCommand(ctx: Context): Promise<void> {
|
||||||
|
await ctx.scene.enter(HELLO_SCENE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@On('message')
|
||||||
|
async onMessage(ctx: Context): Promise<void> {
|
||||||
|
console.log('New message received');
|
||||||
|
|
||||||
|
if ('text' in ctx.message) {
|
||||||
|
const messageText = ctx.message.text;
|
||||||
|
const echoText = this.echoService.echo(messageText);
|
||||||
|
await ctx.reply(echoText);
|
||||||
|
} else {
|
||||||
|
await ctx.reply('Only text messages');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
sample/echo.service.ts
Normal file
8
sample/echo.service.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EchoService {
|
||||||
|
echo(text: string): string {
|
||||||
|
return `Echo: ${text}`;
|
||||||
|
}
|
||||||
|
}
|
4
sample/interfaces/context.interface.ts
Normal file
4
sample/interfaces/context.interface.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { SceneContextMessageUpdate } from 'telegraf/typings/stage';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface Context extends SceneContextMessageUpdate {}
|
7
sample/main.ts
Normal file
7
sample/main.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
async function bootstrap() {
|
||||||
|
await NestFactory.createApplicationContext(AppModule);
|
||||||
|
}
|
||||||
|
bootstrap();
|
3
sample/middleware/session.middleware.ts
Normal file
3
sample/middleware/session.middleware.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { session } from 'telegraf';
|
||||||
|
|
||||||
|
export const sessionMiddleware = session();
|
29
sample/scenes/hello.scene.ts
Normal file
29
sample/scenes/hello.scene.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { HELLO_SCENE_ID } from '../app.constants';
|
||||||
|
import { Context } from '../interfaces/context.interface';
|
||||||
|
import { Scene, SceneEnter, SceneLeave, Command } from '../../lib';
|
||||||
|
|
||||||
|
@Scene(HELLO_SCENE_ID)
|
||||||
|
export class HelloScene {
|
||||||
|
@SceneEnter()
|
||||||
|
async onSceneEnter(ctx: Context): Promise<void> {
|
||||||
|
console.log('Enter to scene');
|
||||||
|
await ctx.reply('Welcome on scene ✋');
|
||||||
|
}
|
||||||
|
|
||||||
|
@SceneLeave()
|
||||||
|
async onSceneLeave(ctx: Context): Promise<void> {
|
||||||
|
console.log('Leave from scene');
|
||||||
|
await ctx.reply('Bye Bye 👋');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command('hello')
|
||||||
|
async onHelloCommand(ctx: Context): Promise<void> {
|
||||||
|
console.log('Use say hello');
|
||||||
|
await ctx.reply('Hi');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command('leave')
|
||||||
|
async onLeaveCommand(ctx: Context): Promise<void> {
|
||||||
|
await ctx.scene.leave();
|
||||||
|
}
|
||||||
|
}
|
@ -9,10 +9,10 @@
|
|||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
|
"baseUrl": "./",
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"rootDir": "./lib",
|
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"include": ["lib/**/*", "../index.ts"],
|
"include": ["lib/**/*", "sample/**/*"],
|
||||||
"exclude": ["node_modules", "**/*.spec.ts"]
|
"exclude": ["node_modules", "**/*.spec.ts"]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user