fix(): working after merge

This commit is contained in:
Alexander Bukhalo
2021-01-02 21:40:13 +03:00
parent b808fb646a
commit 832ddaf15c
21 changed files with 167 additions and 706 deletions

View File

@@ -1,2 +1,4 @@
export * from './updates-explorer.service';
export * from './metadata-accessor.service';
export * from './scenes-explorer.service';
export * from './updates-explorer.service';

View File

@@ -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<any> | 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<any> | 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<any> | Function,
): UpdateHookOptions | undefined {
return this.reflector.get(DECORATORS.UPDATE_HOOK, target);
}
isTelegrafUse(target: Type<any> | 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<any> | 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<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);
getSceneMetadata(target: Function): string | undefined {
return this.reflector.get(SCENE_METADATA, target);
}
}

View File

@@ -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<any>;
onModuleInit(): void {
this.bot = this.moduleRef.get<Telegraf<any>>(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);
}
},
);
});
}
}

View File

@@ -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));
}
}