From 832ddaf15c70d56a6aec297a829d8d1ee0e206d8 Mon Sep 17 00:00:00 2001 From: Alexander Bukhalo Date: Sat, 2 Jan 2021 21:40:13 +0300 Subject: [PATCH] fix(): working after merge --- .npmignore | 1 + lib/decorators/core/inject-bot.decorator.ts | 5 +- lib/decorators/inject-bot.decorator.ts | 5 - lib/explorers/telegraf-scene.explorer.ts | 73 ------- lib/explorers/telegraf-update.explorer.ts | 63 ------ .../create-scene-listener-decorator.helper.ts | 2 +- ...create-update-listener-decorator.helper.ts | 2 +- lib/index.ts | 2 +- lib/interfaces/context.interface.ts | 11 - lib/interfaces/index.ts | 1 - lib/interfaces/telegraf-options.interface.ts | 7 +- lib/services/index.ts | 2 + lib/services/metadata-accessor.service.ts | 194 ++--------------- lib/services/scenes-explorer.service.ts | 98 +++++++++ lib/services/updates-explorer.service.ts | 197 +----------------- lib/telegraf-core.module.ts | 45 ++-- lib/telegraf.metadata-accessor.ts | 29 --- lib/telegraf.module.ts | 97 +-------- lib/telegraf.providers.ts | 25 --- lib/{telegraf.types.ts => types/index.ts} | 0 package-lock.json | 14 ++ 21 files changed, 167 insertions(+), 706 deletions(-) delete mode 100644 lib/decorators/inject-bot.decorator.ts delete mode 100644 lib/explorers/telegraf-scene.explorer.ts delete mode 100644 lib/explorers/telegraf-update.explorer.ts delete mode 100644 lib/interfaces/context.interface.ts create mode 100644 lib/services/scenes-explorer.service.ts delete mode 100644 lib/telegraf.metadata-accessor.ts delete mode 100644 lib/telegraf.providers.ts rename lib/{telegraf.types.ts => types/index.ts} (100%) diff --git a/.npmignore b/.npmignore index 267876c..130fdb1 100644 --- a/.npmignore +++ b/.npmignore @@ -1,5 +1,6 @@ # source lib +index.ts package-lock.json tsconfig.json .prettierrc diff --git a/lib/decorators/core/inject-bot.decorator.ts b/lib/decorators/core/inject-bot.decorator.ts index d010fbe..73299e8 100644 --- a/lib/decorators/core/inject-bot.decorator.ts +++ b/lib/decorators/core/inject-bot.decorator.ts @@ -1,4 +1,5 @@ import { Inject } from '@nestjs/common'; -import { Telegraf } from 'telegraf'; +import { getBotToken } from '../../utils'; -export const InjectBot = (): ParameterDecorator => Inject(Telegraf); +export const InjectBot = (name?: string): ParameterDecorator => + Inject(getBotToken(name)); diff --git a/lib/decorators/inject-bot.decorator.ts b/lib/decorators/inject-bot.decorator.ts deleted file mode 100644 index 47808e3..0000000 --- a/lib/decorators/inject-bot.decorator.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Inject } from '@nestjs/common'; -import { getBotToken } from '../utils'; - -export const InjectBot = (name?: string): ParameterDecorator => - Inject(getBotToken(name)); diff --git a/lib/explorers/telegraf-scene.explorer.ts b/lib/explorers/telegraf-scene.explorer.ts deleted file mode 100644 index 2ab2c49..0000000 --- a/lib/explorers/telegraf-scene.explorer.ts +++ /dev/null @@ -1,73 +0,0 @@ -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, - 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, - instance: Record, - 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); - } -} diff --git a/lib/explorers/telegraf-update.explorer.ts b/lib/explorers/telegraf-update.explorer.ts deleted file mode 100644 index a848806..0000000 --- a/lib/explorers/telegraf-update.explorer.ts +++ /dev/null @@ -1,63 +0,0 @@ -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, - 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, - 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); - } -} diff --git a/lib/helpers/create-scene-listener-decorator.helper.ts b/lib/helpers/create-scene-listener-decorator.helper.ts index c997ffc..b089ebf 100644 --- a/lib/helpers/create-scene-listener-decorator.helper.ts +++ b/lib/helpers/create-scene-listener-decorator.helper.ts @@ -1,6 +1,6 @@ import { SetMetadata } from '@nestjs/common'; import { BaseScene as Scene } from 'telegraf'; -import { ComposerMethodArgs, SceneMethods } from '../telegraf.types'; +import { ComposerMethodArgs, SceneMethods } from '../types'; import { UPDATE_LISTENER_METADATA } from '../telegraf.constants'; import { ListenerMetadata } from '../interfaces'; diff --git a/lib/helpers/create-update-listener-decorator.helper.ts b/lib/helpers/create-update-listener-decorator.helper.ts index a27f85b..28343e2 100644 --- a/lib/helpers/create-update-listener-decorator.helper.ts +++ b/lib/helpers/create-update-listener-decorator.helper.ts @@ -1,6 +1,6 @@ import { SetMetadata } from '@nestjs/common'; import { Composer } from 'telegraf'; -import { ComposerMethodArgs, UpdateMethods } from '../telegraf.types'; +import { ComposerMethodArgs, UpdateMethods } from '../types'; import { UPDATE_LISTENER_METADATA } from '../telegraf.constants'; import { ListenerMetadata } from '../interfaces'; diff --git a/lib/index.ts b/lib/index.ts index e45daa6..ace41d2 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -11,5 +11,5 @@ export * from './interfaces'; export * from './helpers'; export * from './utils'; export * from './telegraf.module'; -export * from './telegraf.types'; +export * from './types'; export { Telegraf } from 'telegraf'; diff --git a/lib/interfaces/context.interface.ts b/lib/interfaces/context.interface.ts deleted file mode 100644 index 169e5fb..0000000 --- a/lib/interfaces/context.interface.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TelegrafContext } from 'telegraf/typings/context'; - -export interface Context extends TelegrafContext { - [key: string]: any; // TBD -} - -/** - * Removed type from Telegraf v3.38.0, added for backward compatibility. - * TODO: remove on next major release - */ -export interface ContextMessageUpdate extends Context {} diff --git a/lib/interfaces/index.ts b/lib/interfaces/index.ts index 5d0c244..6be0df9 100644 --- a/lib/interfaces/index.ts +++ b/lib/interfaces/index.ts @@ -1,4 +1,3 @@ -export * from './context.interface'; export * from './telegraf-options.interface'; export * from './listener-metadata.interface'; export * from './update-metadata.interface'; diff --git a/lib/interfaces/telegraf-options.interface.ts b/lib/interfaces/telegraf-options.interface.ts index 6ac30d1..cfdb594 100644 --- a/lib/interfaces/telegraf-options.interface.ts +++ b/lib/interfaces/telegraf-options.interface.ts @@ -4,10 +4,7 @@ import { TelegrafOptions, LaunchPollingOptions, LaunchWebhookOptions, - TelegrafOptions, } from 'telegraf/typings/telegraf'; -import { Middleware } from 'telegraf/typings/composer'; -import { Context } from './context.interface'; export interface TelegrafModuleOptions { token: string; @@ -18,9 +15,7 @@ export interface TelegrafModuleOptions { }; botName?: string; include?: Function[]; - middlewares?: ReadonlyArray>; - disableGlobalCatch?: boolean; - middlewares?: Middleware[]; + middlewares?: ReadonlyArray>; } export interface TelegrafOptionsFactory { diff --git a/lib/services/index.ts b/lib/services/index.ts index 9514e05..9859475 100644 --- a/lib/services/index.ts +++ b/lib/services/index.ts @@ -1,2 +1,4 @@ export * from './updates-explorer.service'; export * from './metadata-accessor.service'; +export * from './scenes-explorer.service'; +export * from './updates-explorer.service'; diff --git a/lib/services/metadata-accessor.service.ts b/lib/services/metadata-accessor.service.ts index a4c0ac7..3e7e044 100644 --- a/lib/services/metadata-accessor.service.ts +++ b/lib/services/metadata-accessor.service.ts @@ -1,204 +1,42 @@ -import { Injectable, Type } from '@nestjs/common'; +import { Injectable } 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'; + SCENE_METADATA, + UPDATE_LISTENER_METADATA, + UPDATE_METADATA, +} from '../telegraf.constants'; +import { ListenerMetadata } from '../interfaces'; @Injectable() export class MetadataAccessorService { constructor(private readonly reflector: Reflector) {} - isUpdate(target: Type | Function): boolean { + isUpdate(target: Function): boolean { if (!target) { return false; } - return !!this.reflector.get(DECORATORS.UPDATE, target); + return !!this.reflector.get(UPDATE_METADATA, target); } - isUpdateHook(target: Type | Function): boolean { + isUpdateListener(target: Function) { if (!target) { return false; } - return !!this.reflector.get(DECORATORS.UPDATE_HOOK, target); + return !!this.reflector.get(UPDATE_LISTENER_METADATA, target); } - getUpdateHookMetadata( - target: Type | Function, - ): UpdateHookOptions | undefined { - return this.reflector.get(DECORATORS.UPDATE_HOOK, target); - } - - isTelegrafUse(target: Type | Function): boolean { + isScene(target: Function): boolean { if (!target) { return false; } - return !!this.reflector.get(DECORATORS.USE, target); + return !!this.reflector.get(SCENE_METADATA, target); } - isTelegrafOn(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.ON, target); + getListenerMetadata(target: Function): ListenerMetadata | undefined { + return this.reflector.get(UPDATE_LISTENER_METADATA, target); } - getTelegrafOnMetadata(target: Type | Function): OnOptions | undefined { - return this.reflector.get(DECORATORS.ON, target); - } - - isTelegrafHears(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.HEARS, target); - } - - getTelegrafHearsMetadata( - target: Type | Function, - ): HearsOptions | undefined { - return this.reflector.get(DECORATORS.HEARS, target); - } - - isTelegrafCommand(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.COMMAND, target); - } - - getTelegrafCommandMetadata( - target: Type | Function, - ): CommandOptions | undefined { - return this.reflector.get(DECORATORS.COMMAND, target); - } - - isTelegrafStart(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.START, target); - } - - isTelegrafHelp(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.HELP, target); - } - - isTelegrafSettings(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.SETTINGS, target); - } - - isTelegrafEntity(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.ENTITY, target); - } - - getTelegrafEntityMetadata( - target: Type | Function, - ): EntityOptions | undefined { - return this.reflector.get(DECORATORS.ENTITY, target); - } - - isTelegrafMention(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.MENTION, target); - } - - getTelegrafMentionMetadata( - target: Type | Function, - ): MentionOptions | undefined { - return this.reflector.get(DECORATORS.MENTION, target); - } - - isTelegrafPhone(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.PHONE, target); - } - - getTelegrafPhoneMetadata( - target: Type | Function, - ): PhoneOptions | undefined { - return this.reflector.get(DECORATORS.PHONE, target); - } - - isTelegrafHashtag(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.HASHTAG, target); - } - - getTelegrafHashtagMetadata( - target: Type | Function, - ): HashtagOptions | undefined { - return this.reflector.get(DECORATORS.HASHTAG, target); - } - - isTelegrafCashtag(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.CASHTAG, target); - } - - getTelegrafCashtagMetadata( - target: Type | Function, - ): CashtagOptions | undefined { - return this.reflector.get(DECORATORS.CASHTAG, target); - } - - isTelegrafAction(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.ACTION, target); - } - - getTelegrafActionMetadata( - target: Type | Function, - ): ActionOptions | undefined { - return this.reflector.get(DECORATORS.ACTION, target); - } - - isTelegrafInlineQuery(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.INLINE_QUERY, target); - } - - getTelegrafInlineQueryMetadata( - target: Type | Function, - ): InlineQueryOptions | undefined { - return this.reflector.get(DECORATORS.INLINE_QUERY, target); - } - - isTelegrafGameQuery(target: Type | Function): boolean { - if (!target) { - return false; - } - return !!this.reflector.get(DECORATORS.GAME_QUERY, target); + getSceneMetadata(target: Function): string | undefined { + return this.reflector.get(SCENE_METADATA, target); } } diff --git a/lib/services/scenes-explorer.service.ts b/lib/services/scenes-explorer.service.ts new file mode 100644 index 0000000..be3d47d --- /dev/null +++ b/lib/services/scenes-explorer.service.ts @@ -0,0 +1,98 @@ +import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; +import { DiscoveryService, ModuleRef, ModulesContainer } 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 { MetadataAccessorService } from './metadata-accessor.service'; +import { BaseExplorerService } from './base-explorer.service'; +import { + TELEGRAF_BOT_NAME, + TELEGRAF_MODULE_OPTIONS, +} from '../telegraf.constants'; +import { TelegrafModuleOptions } from '../interfaces'; +import { Module } from '@nestjs/core/injector/module'; + +@Injectable() +export class ScenesExplorerService + extends BaseExplorerService + implements OnModuleInit { + private readonly stage = new Stage([]); + + constructor( + @Inject(TELEGRAF_BOT_NAME) + private readonly botName: string, + @Inject(TELEGRAF_MODULE_OPTIONS) + private readonly telegrafModuleOptions: TelegrafModuleOptions, + private readonly moduleRef: ModuleRef, + private readonly discoveryService: DiscoveryService, + private readonly metadataAccessor: MetadataAccessorService, + private readonly metadataScanner: MetadataScanner, + private readonly modulesContainer: ModulesContainer, + ) { + super(); + } + + private bot: Telegraf; + + onModuleInit(): void { + this.bot = this.moduleRef.get>(this.botName, { + strict: false, + }); + this.bot.use(this.stage.middleware()); + this.explore(); + } + + private explore(): void { + const modules = this.getModules( + this.modulesContainer, + this.telegrafModuleOptions.include || [], + ); + const scenes = this.flatMap(modules, (instance, moduleRef) => + this.applyScenes(instance, moduleRef), + ); + } + + private applyScenes(wrapper: InstanceWrapper, moduleRef: Module) { + const { instance } = wrapper; + if (!instance) { + return undefined; + } + const prototype = Object.getPrototypeOf(instance); + + const providers: InstanceWrapper[] = this.discoveryService.getProviders(); + const sceneProviders: InstanceWrapper[] = providers.filter( + (wrapper: InstanceWrapper) => + this.metadataAccessor.isScene(wrapper.metatype), + ); + + sceneProviders.forEach((wrapper) => { + const { instance } = wrapper; + if (!instance) { + return undefined; + } + + const sceneId = this.metadataAccessor.getSceneMetadata( + instance.constructor, + ); + + const scene = new Scene(sceneId); + this.stage.register(scene); + + this.metadataScanner.scanFromPrototype( + instance, + prototype, + (methodKey: string) => { + const methodRef = instance[methodKey]; + if (this.metadataAccessor.isUpdateListener(methodRef)) { + const metadata = this.metadataAccessor.getListenerMetadata( + methodRef, + ); + const middlewareFn = methodRef.bind(instance); + const { method, args } = metadata; + (scene[method] as any)(...args, middlewareFn); + } + }, + ); + }); + } +} diff --git a/lib/services/updates-explorer.service.ts b/lib/services/updates-explorer.service.ts index f1d785c..09fa250 100644 --- a/lib/services/updates-explorer.service.ts +++ b/lib/services/updates-explorer.service.ts @@ -7,19 +7,6 @@ import { TELEGRAF_BOT_NAME, TELEGRAF_MODULE_OPTIONS, } from '../telegraf.constants'; -import { - ActionOptions, - CashtagOptions, - CommandOptions, - EntityOptions, - HashtagOptions, - HearsOptions, - InlineQueryOptions, - MentionOptions, - OnOptions, - PhoneOptions, - UpdateHookOptions, -} from '../decorators'; import { Telegraf } from 'telegraf'; import { TelegrafModuleOptions } from '../interfaces'; import { BaseExplorerService } from './base-explorer.service'; @@ -81,184 +68,16 @@ export class UpdatesExplorerService return undefined; } this.metadataScanner.scanFromPrototype(instance, prototype, (name) => { - if (this.metadataAccessor.isUpdateHook(instance[name])) { - const metadata = this.metadataAccessor.getUpdateHookMetadata( - instance[name], - ); - this.handleUpdateHook(instance, name, metadata); + const methodRef = instance[name]; + if (this.metadataAccessor.isUpdateListener(methodRef)) { + const metadata = this.metadataAccessor.getListenerMetadata(methodRef); + const middlewareFn = methodRef.bind(instance); + const { method, args } = metadata; + // NOTE: Use "any" to disable "Expected at least 1 arguments, but got 1 or more." error. + // Use telegraf instance for non-scene listeners + (this.bot[method] as any)(...args, middlewareFn); } }); }); - - providers.forEach((wrapper: InstanceWrapper) => { - const { instance } = wrapper; - if (!instance) { - return undefined; - } - this.metadataScanner.scanFromPrototype( - instance, - prototype, - (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.bot.on(metadata.updateType, instance[key].bind(instance)); - } - - handleTelegrafUse(instance: object, key: string) { - this.bot.use(instance[key].bind(instance)); - } - - handleTelegrafOn(instance: object, key: string, metadata: OnOptions) { - this.bot.on(metadata.updateTypes, instance[key].bind(instance)); - } - - handleTelegrafHears(instance: object, key: string, metadata: HearsOptions) { - this.bot.hears(metadata.triggers, instance[key].bind(instance)); - } - - handleTelegrafCommand( - instance: object, - key: string, - metadata: CommandOptions, - ) { - this.bot.command(metadata.commands, instance[key].bind(instance)); - } - - handleTelegrafStart(instance: object, key: string) { - this.bot.start(instance[key].bind(instance)); - } - - handleTelegrafHelp(instance: object, key: string) { - this.bot.help(instance[key].bind(instance)); - } - - handleTelegrafSettings(instance: object, key: string) { - // @ts-ignore - this.bot.settings(instance[key].bind(instance)); - } - - handleTelegrafEntity(instance: object, key: string, metadata: EntityOptions) { - // @ts-ignore - this.bot.entity(metadata.entity, instance[key].bind(instance)); - } - - handleTelegrafMention( - instance: object, - key: string, - metadata: MentionOptions, - ) { - // @ts-ignore - this.bot.mention(metadata.username, instance[key].bind(instance)); - } - - handleTelegrafPhone(instance: object, key: string, metadata: PhoneOptions) { - // @ts-ignore - this.bot.phone(metadata.phone, instance[key].bind(instance)); - } - - handleTelegrafHashtag( - instance: object, - key: string, - metadata: HashtagOptions, - ) { - // @ts-ignore - this.bot.hashtag(metadata.hashtag, instance[key].bind(instance)); - } - - handleTelegrafCashtag( - instance: object, - key: string, - metadata: CashtagOptions, - ) { - // @ts-ignore - this.bot.cashtag(metadata.cashtag, instance[key].bind(instance)); - } - - handleTelegrafAction(instance: object, key: string, metadata: ActionOptions) { - this.bot.action(metadata.triggers, instance[key].bind(instance)); - } - - handleTelegrafInlineQuery( - instance: object, - key: string, - metadata: InlineQueryOptions, - ) { - if (metadata.triggers) { - // @ts-ignore - this.bot.inlineQuery(metadata.triggers, instance[key].bind(instance)); - } else { - this.bot.on(metadata.updateType, instance[key].bind(instance)); - } - } - - handleTelegrafGameQuery(instance: object, key: string) { - this.bot.gameQuery(instance[key].bind(instance)); } } diff --git a/lib/telegraf-core.module.ts b/lib/telegraf-core.module.ts index 66566f2..f33d5cc 100644 --- a/lib/telegraf-core.module.ts +++ b/lib/telegraf-core.module.ts @@ -13,13 +13,16 @@ import { TelegrafModuleOptions, TelegrafModuleAsyncOptions, TelegrafOptionsFactory, - Context, } from './interfaces'; import { TELEGRAF_BOT_NAME, TELEGRAF_MODULE_OPTIONS, } from './telegraf.constants'; -import { MetadataAccessorService, UpdatesExplorerService } from './services'; +import { + MetadataAccessorService, + ScenesExplorerService, + UpdatesExplorerService, +} from './services'; import { getBotToken } from './utils'; import { Telegraf } from 'telegraf'; import { defer } from 'rxjs'; @@ -27,7 +30,11 @@ import { defer } from 'rxjs'; @Global() @Module({ imports: [DiscoveryModule], - providers: [UpdatesExplorerService, MetadataAccessorService], + providers: [ + UpdatesExplorerService, + ScenesExplorerService, + MetadataAccessorService, + ], }) export class TelegrafCoreModule implements OnApplicationShutdown { private static logger = new Logger(TelegrafCoreModule.name); @@ -44,22 +51,8 @@ export class TelegrafCoreModule implements OnApplicationShutdown { provide: telegrafBotName, useFactory: async (): Promise => await defer(async () => { - const bot = new Telegraf(options.token); + const bot = new Telegraf(options.token); this.applyBotMiddlewares(bot, options.middlewares); - - /** - * Backward compatibility with versions < 1.4.0, - * TODO: remove that on next major release, - * after exception filters has been added - */ - if (!options.disableGlobalCatch) { - bot.catch((err, ctx: Context) => { - this.logger.error( - `Encountered an error for ${ctx.updateType} update type`, - err, - ); - }); - } await bot.launch(options.launchOptions); return bot; }).toPromise(), @@ -95,22 +88,8 @@ export class TelegrafCoreModule implements OnApplicationShutdown { const { botName, ...telegrafOptions } = telegrafModuleOptions; return await defer(async () => { - const bot = new Telegraf(telegrafOptions.token); + const bot = new Telegraf(telegrafOptions.token); this.applyBotMiddlewares(bot, telegrafOptions.middlewares); - - /** - * Backward compatibility with versions < 1.4.0, - * TODO: remove that on next major release, - * after exception filters has been added - */ - if (!telegrafOptions.disableGlobalCatch) { - bot.catch((err, ctx: Context) => { - this.logger.error( - `Encountered an error for ${ctx.updateType} update type`, - err, - ); - }); - } await bot.launch(telegrafOptions.launchOptions); return bot; }).toPromise(); diff --git a/lib/telegraf.metadata-accessor.ts b/lib/telegraf.metadata-accessor.ts deleted file mode 100644 index 5c4394d..0000000 --- a/lib/telegraf.metadata-accessor.ts +++ /dev/null @@ -1,29 +0,0 @@ -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); - } -} diff --git a/lib/telegraf.module.ts b/lib/telegraf.module.ts index 4e9f958..fb3cdeb 100644 --- a/lib/telegraf.module.ts +++ b/lib/telegraf.module.ts @@ -1,106 +1,27 @@ -import { DiscoveryModule, ModuleRef } from '@nestjs/core'; +import { Module, DynamicModule } from '@nestjs/common'; +import { TelegrafCoreModule } from './telegraf-core.module'; import { - DynamicModule, - Inject, - Module, - OnApplicationBootstrap, - OnApplicationShutdown, - Provider, -} from '@nestjs/common'; -import { Telegraf } from 'telegraf'; -import { - TelegrafModuleAsyncOptions, TelegrafModuleOptions, - TelegrafOptionsFactory, + TelegrafModuleAsyncOptions, } 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 { - const { launchOptions } = this.options; - const telegraf = this.moduleRef.get(Telegraf); - await telegraf.launch(launchOptions); - } - - async onApplicationShutdown(): Promise { - const telegraf = this.moduleRef.get(Telegraf); - await telegraf.stop(); - } +@Module({}) +export class TelegrafModule { public static forRoot(options: TelegrafModuleOptions): DynamicModule { - const providers = [...createProviders(options), TelegrafProvider]; - return { module: TelegrafModule, - providers, - exports: providers, + imports: [TelegrafCoreModule.forRoot(options)], + exports: [TelegrafCoreModule], }; } public static forRootAsync( options: TelegrafModuleAsyncOptions, ): DynamicModule { - const providers = [...this.createAsyncProviders(options), TelegrafProvider]; - return { module: TelegrafModule, - imports: options.imports || [], - 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], + imports: [TelegrafCoreModule.forRootAsync(options)], + exports: [TelegrafCoreModule], }; } } diff --git a/lib/telegraf.providers.ts b/lib/telegraf.providers.ts deleted file mode 100644 index b13de54..0000000 --- a/lib/telegraf.providers.ts +++ /dev/null @@ -1,25 +0,0 @@ -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); - if (options.middlewares?.length > 0) { - telegraf.use(...options.middlewares); - } - return telegraf; - }, - inject: [TELEGRAF_MODULE_OPTIONS], -}; - -export function createProviders(options: TelegrafModuleOptions): Provider[] { - return [ - { - provide: TELEGRAF_MODULE_OPTIONS, - useValue: options, - }, - ]; -} diff --git a/lib/telegraf.types.ts b/lib/types/index.ts similarity index 100% rename from lib/telegraf.types.ts rename to lib/types/index.ts diff --git a/package-lock.json b/package-lock.json index 7490ee2..acbfe97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "devDependencies": { "@nestjs/common": "7.6.5", "@nestjs/core": "7.6.5", + "@types/lodash": "^4.14.167", "@typescript-eslint/eslint-plugin": "4.11.1", "@typescript-eslint/parser": "4.11.1", "eslint": "7.17.0", @@ -20,6 +21,7 @@ "eslint-plugin-import": "2.22.1", "husky": "4.3.6", "lint-staged": "10.5.3", + "lodash": "^4.17.20", "prettier": "2.2.1", "reflect-metadata": "0.1.13", "rxjs": "6.6.3", @@ -292,6 +294,12 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.167", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.167.tgz", + "integrity": "sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw==", + "dev": true + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -3880,6 +3888,12 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/lodash": { + "version": "4.14.167", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.167.tgz", + "integrity": "sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw==", + "dev": true + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",