2020-12-29 22:41:06 +03:00
|
|
|
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
2020-12-26 23:19:30 +03:00
|
|
|
import { DiscoveryService } from '@nestjs/core';
|
2020-03-19 16:21:35 +03:00
|
|
|
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
2020-12-27 21:35:01 +03:00
|
|
|
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
2020-12-29 22:41:06 +03:00
|
|
|
import { BaseScene as Scene, Stage, Telegraf } from 'telegraf';
|
2020-12-30 01:49:09 +03:00
|
|
|
import { TelegrafMetadataAccessor } from '../telegraf.metadata-accessor';
|
2020-03-19 16:21:35 +03:00
|
|
|
|
|
|
|
@Injectable()
|
2020-12-29 22:41:06 +03:00
|
|
|
export class TelegrafSceneExplorer implements OnModuleInit {
|
2021-01-02 15:23:30 +03:00
|
|
|
private readonly stage = new Stage([]);
|
2020-12-30 01:49:09 +03:00
|
|
|
|
2020-03-19 16:21:35 +03:00
|
|
|
constructor(
|
2020-12-29 22:41:06 +03:00
|
|
|
@Inject(Telegraf)
|
2021-01-02 15:23:30 +03:00
|
|
|
private readonly telegraf: Telegraf<never>,
|
2020-03-19 16:21:35 +03:00
|
|
|
private readonly discoveryService: DiscoveryService,
|
|
|
|
private readonly metadataAccessor: TelegrafMetadataAccessor,
|
|
|
|
private readonly metadataScanner: MetadataScanner,
|
2020-12-30 01:49:09 +03:00
|
|
|
) {
|
|
|
|
this.telegraf.use(this.stage.middleware());
|
|
|
|
}
|
2020-03-19 16:21:35 +03:00
|
|
|
|
2020-12-25 23:11:16 +03:00
|
|
|
onModuleInit(): void {
|
2020-03-19 16:21:35 +03:00
|
|
|
this.explore();
|
|
|
|
}
|
|
|
|
|
2020-12-29 22:41:06 +03:00
|
|
|
private explore(): void {
|
|
|
|
const sceneClasses = this.filterSceneClasses();
|
2020-12-26 16:11:09 +03:00
|
|
|
|
2020-12-29 22:41:06 +03:00
|
|
|
sceneClasses.forEach((wrapper) => {
|
2020-12-26 16:11:09 +03:00
|
|
|
const { instance } = wrapper;
|
2020-12-25 23:11:16 +03:00
|
|
|
|
2020-12-29 22:41:06 +03:00
|
|
|
const sceneId = this.metadataAccessor.getSceneMetadata(
|
|
|
|
instance.constructor,
|
|
|
|
);
|
|
|
|
const scene = new Scene(sceneId);
|
2020-12-30 01:49:09 +03:00
|
|
|
this.stage.register(scene);
|
2020-12-29 22:41:06 +03:00
|
|
|
|
2020-12-26 16:11:09 +03:00
|
|
|
const prototype = Object.getPrototypeOf(instance);
|
|
|
|
this.metadataScanner.scanFromPrototype(
|
|
|
|
instance,
|
|
|
|
prototype,
|
2020-12-29 22:41:06 +03:00
|
|
|
(methodKey: string) =>
|
|
|
|
this.registerIfListener(scene, instance, methodKey),
|
2020-12-26 16:11:09 +03:00
|
|
|
);
|
|
|
|
});
|
2020-12-25 23:11:16 +03:00
|
|
|
}
|
|
|
|
|
2020-12-29 22:41:06 +03:00
|
|
|
private filterSceneClasses(): InstanceWrapper[] {
|
2020-12-26 16:11:09 +03:00
|
|
|
return this.discoveryService
|
|
|
|
.getProviders()
|
|
|
|
.filter((wrapper) => wrapper.instance)
|
2020-12-26 16:24:38 +03:00
|
|
|
.filter((wrapper) =>
|
2020-12-29 22:41:06 +03:00
|
|
|
this.metadataAccessor.isScene(wrapper.instance.constructor),
|
2020-12-26 16:24:38 +03:00
|
|
|
);
|
2020-12-26 14:54:10 +03:00
|
|
|
}
|
|
|
|
|
2020-12-26 16:24:38 +03:00
|
|
|
private registerIfListener(
|
2021-01-02 15:23:30 +03:00
|
|
|
scene: Scene<never>,
|
2020-12-25 23:11:16 +03:00
|
|
|
instance: Record<string, Function>,
|
|
|
|
methodKey: string,
|
|
|
|
): void {
|
|
|
|
const methodRef = instance[methodKey];
|
|
|
|
const middlewareFn = methodRef.bind(instance);
|
|
|
|
|
2020-12-27 21:35:01 +03:00
|
|
|
const listenerMetadata = this.metadataAccessor.getListenerMetadata(
|
|
|
|
methodRef,
|
|
|
|
);
|
|
|
|
if (!listenerMetadata) return;
|
|
|
|
|
|
|
|
const { method, args } = listenerMetadata;
|
2020-12-29 22:41:06 +03:00
|
|
|
(scene[method] as any)(...args, middlewareFn);
|
2020-03-19 17:25:47 +03:00
|
|
|
}
|
2020-03-19 16:21:35 +03:00
|
|
|
}
|