From dca35a0c7f5dda6cb1ce2768d244d68274c544f3 Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Sun, 23 Jul 2023 15:38:05 +0300 Subject: [PATCH] feat: add GlobalUpdate decorator (#2) --- .../core/global-update.decorator.ts | 9 ++++++ lib/decorators/core/index.ts | 1 + lib/services/listeners-explorer.service.ts | 29 +++++++++++++++++-- lib/services/metadata-accessor.service.ts | 6 ++++ lib/telegraf.constants.ts | 1 + 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 lib/decorators/core/global-update.decorator.ts diff --git a/lib/decorators/core/global-update.decorator.ts b/lib/decorators/core/global-update.decorator.ts new file mode 100644 index 0000000..e9c6902 --- /dev/null +++ b/lib/decorators/core/global-update.decorator.ts @@ -0,0 +1,9 @@ +import { SetMetadata } from '@nestjs/common'; +import { GLOBAL_UPDATE_METADATA } from '../../telegraf.constants'; + +/** + * `@GlobalUpdate` decorator, it's like `@Update` decorator, + * but processed before the scenes + */ +export const GlobalUpdate = (): ClassDecorator => + SetMetadata(GLOBAL_UPDATE_METADATA, true); diff --git a/lib/decorators/core/index.ts b/lib/decorators/core/index.ts index cd0c9b0..abf9c75 100644 --- a/lib/decorators/core/index.ts +++ b/lib/decorators/core/index.ts @@ -1,4 +1,5 @@ export * from './update.decorator'; +export * from './global-update.decorator'; export * from './scene.decorator'; export * from './wizard.decorator'; export * from './inject-bot.decorator'; diff --git a/lib/services/listeners-explorer.service.ts b/lib/services/listeners-explorer.service.ts index ab3dfbf..1883798 100644 --- a/lib/services/listeners-explorer.service.ts +++ b/lib/services/listeners-explorer.service.ts @@ -48,8 +48,6 @@ export class ListenersExplorerService this.bot = this.moduleRef.get>(this.botName, { strict: false, }); - this.bot.use(this.stage.middleware()); - this.explore(); } @@ -59,10 +57,23 @@ export class ListenersExplorerService this.telegrafOptions.include || [], ); + this.registerGlobalUpdates(modules); + + this.bot.use(this.stage.middleware()); + this.registerUpdates(modules); this.registerScenes(modules); } + private registerGlobalUpdates(modules: Module[]): void { + const globalUpdates = this.flatMap(modules, (instance) => + this.filterGlobalUpdates(instance), + ); + globalUpdates.forEach((wrapper) => + this.registerListeners(this.bot, wrapper), + ); + } + private registerUpdates(modules: Module[]): void { const updates = this.flatMap(modules, (instance) => this.filterUpdates(instance), @@ -92,6 +103,20 @@ export class ListenersExplorerService }); } + private filterGlobalUpdates( + wrapper: InstanceWrapper, + ): InstanceWrapper { + const { instance } = wrapper; + if (!instance) return undefined; + + const isGlobalUpdate = this.metadataAccessor.isGlobalUpdate( + wrapper.metatype, + ); + if (!isGlobalUpdate) return undefined; + + return wrapper; + } + private filterUpdates(wrapper: InstanceWrapper): InstanceWrapper { const { instance } = wrapper; if (!instance) return undefined; diff --git a/lib/services/metadata-accessor.service.ts b/lib/services/metadata-accessor.service.ts index 5020773..a889294 100644 --- a/lib/services/metadata-accessor.service.ts +++ b/lib/services/metadata-accessor.service.ts @@ -3,6 +3,7 @@ import { Reflector } from '@nestjs/core'; import { SCENE_METADATA, LISTENERS_METADATA, + GLOBAL_UPDATE_METADATA, UPDATE_METADATA, WIZARD_STEP_METADATA, } from '../telegraf.constants'; @@ -16,6 +17,11 @@ import { export class MetadataAccessorService { constructor(private readonly reflector: Reflector) {} + isGlobalUpdate(target: Function): boolean { + if (!target) return false; + return !!this.reflector.get(GLOBAL_UPDATE_METADATA, target); + } + isUpdate(target: Function): boolean { if (!target) return false; return !!this.reflector.get(UPDATE_METADATA, target); diff --git a/lib/telegraf.constants.ts b/lib/telegraf.constants.ts index e5f824e..924fd75 100644 --- a/lib/telegraf.constants.ts +++ b/lib/telegraf.constants.ts @@ -5,6 +5,7 @@ export const TELEGRAF_BOT_NAME = 'TELEGRAF_BOT_NAME'; export const DEFAULT_BOT_NAME = 'DEFAULT_BOT_NAME'; export const UPDATE_METADATA = 'UPDATE_METADATA'; +export const GLOBAL_UPDATE_METADATA = 'GLOBAL_UPDATE_METADATA'; export const SCENE_METADATA = 'SCENE_METADATA'; export const LISTENERS_METADATA = 'LISTENERS_METADATA'; export const WIZARD_STEP_METADATA = 'WIZARD_STEP_METADATA';