nestjs-telegraf/lib/explorers/telegraf-scene.explorer.ts

74 lines
2.1 KiB
TypeScript
Raw Normal View History

import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { DiscoveryService } from '@nestjs/core';
2020-03-19 16:21:35 +03:00
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';
2020-03-19 16:21:35 +03:00
@Injectable()
export class TelegrafSceneExplorer implements OnModuleInit {
private readonly stage = new Stage();
2020-03-19 16:21:35 +03:00
constructor(
@Inject(Telegraf)
private readonly telegraf: Telegraf,
2020-03-19 16:21:35 +03:00
private readonly discoveryService: DiscoveryService,
private readonly metadataAccessor: TelegrafMetadataAccessor,
private readonly metadataScanner: MetadataScanner,
) {
this.telegraf.use(this.stage.middleware());
}
2020-03-19 16:21:35 +03:00
onModuleInit(): void {
2020-03-19 16:21:35 +03:00
this.explore();
}
private explore(): void {
const sceneClasses = this.filterSceneClasses();
2020-12-26 16:11:09 +03:00
sceneClasses.forEach((wrapper) => {
2020-12-26 16:11:09 +03:00
const { instance } = wrapper;
const sceneId = this.metadataAccessor.getSceneMetadata(
instance.constructor,
);
const scene = new Scene(sceneId);
this.stage.register(scene);
2020-12-26 16:11:09 +03:00
const prototype = Object.getPrototypeOf(instance);
this.metadataScanner.scanFromPrototype(
instance,
prototype,
(methodKey: string) =>
this.registerIfListener(scene, instance, methodKey),
2020-12-26 16:11:09 +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) =>
this.metadataAccessor.isScene(wrapper.instance.constructor),
2020-12-26 16:24:38 +03:00
);
}
2020-12-26 16:24:38 +03:00
private registerIfListener(
scene: Scene,
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);
}
2020-03-19 16:21:35 +03:00
}