mirror of
https://github.com/Maks1mS/nestjs-telegraf.git
synced 2024-12-24 15:04:38 +03:00
feat(): wip
This commit is contained in:
parent
320ee3077e
commit
75ff810c34
@ -1,17 +1,19 @@
|
||||
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { Injectable as IInjectable } from '@nestjs/common/interfaces/injectable.interface';
|
||||
import { DiscoveryService, ModuleRef, ModulesContainer } from '@nestjs/core';
|
||||
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
||||
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
||||
import { isFunction, isNil } from '@nestjs/common/utils/shared.utils';
|
||||
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';
|
||||
import { fromPromise } from 'rxjs/internal-compatibility';
|
||||
import { filter, mergeAll } from 'rxjs/operators';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { Context, Telegraf } from 'telegraf';
|
||||
|
||||
import { TelegrafMetadataAccessor } from '../telegraf.metadata-accessor';
|
||||
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';
|
||||
import { TelegrafParamsFactory } from '../factories/telegraf-params-factory';
|
||||
|
||||
// TODO: DELETE THIS CLASS
|
||||
|
||||
@Injectable()
|
||||
export class TelegrafUpdateExplorer implements OnModuleInit {
|
||||
private readonly telegrafParamsFactory = new TelegrafParamsFactory();
|
||||
@ -37,7 +39,7 @@ export class TelegrafUpdateExplorer implements OnModuleInit {
|
||||
}
|
||||
|
||||
private exploreProviders(
|
||||
providers: Map<string, InstanceWrapper<IInjectable>>,
|
||||
providers: Map<string, InstanceWrapper<unknown>>,
|
||||
moduleName: string,
|
||||
): void {
|
||||
[...providers.values()]
|
||||
|
@ -1,15 +1,18 @@
|
||||
import { ParamsFactory } from '@nestjs/core/helpers/external-context-creator';
|
||||
import { Context } from 'telegraf';
|
||||
import { TelegrafParamtype } from '../enums/telegraf-paramtype.enum';
|
||||
|
||||
export class TelegrafParamsFactory {
|
||||
exchangeKeyForValue<
|
||||
TContext extends Record<string, any> = any,
|
||||
TResult = any
|
||||
>(type: number, ctx: TContext, next: Function): TResult {
|
||||
switch (type as TelegrafParamtype) {
|
||||
export class TelegrafParamsFactory implements ParamsFactory {
|
||||
exchangeKeyForValue(
|
||||
type: TelegrafParamtype,
|
||||
ctx: Context,
|
||||
next: Function,
|
||||
): unknown {
|
||||
switch (type) {
|
||||
case TelegrafParamtype.CONTEXT:
|
||||
return ctx as any;
|
||||
return ctx;
|
||||
case TelegrafParamtype.NEXT:
|
||||
return next as any;
|
||||
return next;
|
||||
case TelegrafParamtype.SENDER:
|
||||
return ctx.from;
|
||||
case TelegrafParamtype.MESSAGE:
|
||||
|
@ -6,17 +6,30 @@ import { Module } from '@nestjs/core/injector/module';
|
||||
import { BaseScene, Composer, Stage, Telegraf } from 'telegraf';
|
||||
|
||||
import { MetadataAccessorService } from './metadata-accessor.service';
|
||||
import { TELEGRAF_MODULE_OPTIONS } from '../telegraf.constants';
|
||||
import { TelegrafModuleOptions } from '../interfaces';
|
||||
import {
|
||||
PARAM_ARGS_METADATA,
|
||||
TELEGRAF_MODULE_OPTIONS,
|
||||
} from '../telegraf.constants';
|
||||
import { ListenerMetadata, TelegrafModuleOptions } from '../interfaces';
|
||||
import { BaseExplorerService } from './base-explorer.service';
|
||||
import { getBotToken } from '../utils';
|
||||
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';
|
||||
import { TelegrafParamsFactory } from '../factories/telegraf-params-factory';
|
||||
import { TelegrafContextType } from '../execution-context/telegraf-execution-context';
|
||||
import { ParamMetadata } from '@nestjs/core/helpers/interfaces';
|
||||
|
||||
interface ListenerCallbackMetadata {
|
||||
methodName: string;
|
||||
metadata: ListenerMetadata;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ListenersExplorerService
|
||||
extends BaseExplorerService
|
||||
implements OnModuleInit {
|
||||
private readonly telegrafParamsFactory = new TelegrafParamsFactory();
|
||||
private readonly stage = new Stage([]);
|
||||
private bot: Telegraf<any>;
|
||||
private bot: Telegraf<never>;
|
||||
|
||||
constructor(
|
||||
@Inject(TELEGRAF_MODULE_OPTIONS)
|
||||
@ -26,6 +39,7 @@ export class ListenersExplorerService
|
||||
private readonly metadataAccessor: MetadataAccessorService,
|
||||
private readonly metadataScanner: MetadataScanner,
|
||||
private readonly modulesContainer: ModulesContainer,
|
||||
private readonly externalContextCreator: ExternalContextCreator,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -58,17 +72,18 @@ export class ListenersExplorerService
|
||||
}
|
||||
|
||||
private registerScenes(modules: Module[]): void {
|
||||
const scenes = this.flatMap<InstanceWrapper>(modules, (instance) =>
|
||||
this.filterScenes(instance),
|
||||
const scenes = this.flatMap<InstanceWrapper>(
|
||||
modules,
|
||||
(instance, moduleRef) => this.filterScenes(instance),
|
||||
);
|
||||
scenes.forEach(({ instance }) => {
|
||||
scenes.forEach((wrapper) => {
|
||||
const sceneId = this.metadataAccessor.getSceneMetadata(
|
||||
instance.constructor,
|
||||
);
|
||||
const scene = new BaseScene(sceneId);
|
||||
this.stage.register(scene);
|
||||
|
||||
this.registerInstanceMethodListeners(scene, instance);
|
||||
this.registerInstanceMethodListeners(scene, wrapper);
|
||||
});
|
||||
}
|
||||
|
||||
@ -94,18 +109,63 @@ export class ListenersExplorerService
|
||||
|
||||
private registerInstanceMethodListeners(
|
||||
composer: Composer<never>,
|
||||
instance: Record<string, Function>,
|
||||
wrapper: InstanceWrapper<unknown>,
|
||||
): void {
|
||||
const { instance } = wrapper;
|
||||
const prototype = Object.getPrototypeOf(instance);
|
||||
this.metadataScanner.scanFromPrototype(instance, prototype, (name) => {
|
||||
const methodRef = instance[name];
|
||||
const listenersMetadata = this.metadataScanner.scanFromPrototype(
|
||||
instance,
|
||||
prototype,
|
||||
(name): ListenerCallbackMetadata =>
|
||||
this.extractListenerCallbackMetadata(prototype, name),
|
||||
);
|
||||
|
||||
const metadata = this.metadataAccessor.getListenerMetadata(methodRef);
|
||||
if (!metadata) return;
|
||||
const contextCallbackFn = this.createContextCallback(
|
||||
instance,
|
||||
prototype,
|
||||
wrapper,
|
||||
);
|
||||
}
|
||||
|
||||
const middlewareFn = methodRef.bind(instance);
|
||||
const { method, args } = metadata;
|
||||
composer[method](...args, middlewareFn);
|
||||
});
|
||||
private extractListenerCallbackMetadata(
|
||||
prototype: any,
|
||||
methodName: string,
|
||||
): ListenerCallbackMetadata {
|
||||
const callback = prototype[methodName];
|
||||
const metadata = this.metadataAccessor.getListenerMetadata(callback);
|
||||
|
||||
if (!metadata) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
methodName,
|
||||
metadata: metadata,
|
||||
};
|
||||
}
|
||||
|
||||
createContextCallback<T extends Record<string, unknown>>(
|
||||
instance: T,
|
||||
prototype: unknown,
|
||||
wrapper: InstanceWrapper,
|
||||
moduleRef: Module,
|
||||
listener: ListenerMetadata,
|
||||
) {
|
||||
const paramsFactory = this.telegrafParamsFactory;
|
||||
const resolverCallback = this.externalContextCreator.create<
|
||||
Record<number, ParamMetadata>,
|
||||
TelegrafContextType
|
||||
>(
|
||||
instance,
|
||||
prototype[listener.methodName],
|
||||
listener.methodName,
|
||||
PARAM_ARGS_METADATA,
|
||||
paramsFactory,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'telegraf',
|
||||
);
|
||||
return resolverCallback;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import {
|
||||
SCENE_METADATA,
|
||||
UPDATE_LISTENER_METADATA,
|
||||
LISTENER_METADATA,
|
||||
UPDATE_METADATA,
|
||||
} from '../telegraf.constants';
|
||||
import { ListenerMetadata } from '../interfaces';
|
||||
@ -27,7 +27,7 @@ export class MetadataAccessorService {
|
||||
}
|
||||
|
||||
getListenerMetadata(target: Function): ListenerMetadata | undefined {
|
||||
return this.reflector.get(UPDATE_LISTENER_METADATA, target);
|
||||
return this.reflector.get(LISTENER_METADATA, target);
|
||||
}
|
||||
|
||||
getSceneMetadata(target: Function): string | undefined {
|
||||
|
@ -4,8 +4,7 @@ export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS';
|
||||
export const DEFAULT_BOT_NAME = 'DEFAULT_BOT_NAME';
|
||||
|
||||
export const UPDATE_METADATA = 'UPDATE_METADATA';
|
||||
export const UPDATE_LISTENER_METADATA = 'UPDATE_LISTENER_METADATA';
|
||||
|
||||
export const SCENE_METADATA = 'SCENE_METADATA';
|
||||
export const LISTENER_METADATA = 'LISTENER_METADATA';
|
||||
|
||||
export const PARAM_ARGS_METADATA = ROUTE_ARGS_METADATA;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
import { BaseScene as Scene } from 'telegraf';
|
||||
import { ComposerMethodArgs, SceneMethods } from '../types';
|
||||
import { UPDATE_LISTENER_METADATA } from '../telegraf.constants';
|
||||
import { LISTENER_METADATA } from '../telegraf.constants';
|
||||
import { ListenerMetadata } from '../interfaces';
|
||||
|
||||
export function createListenerDecorator<TMethod extends SceneMethods>(
|
||||
@ -10,7 +10,7 @@ export function createListenerDecorator<TMethod extends SceneMethods>(
|
||||
return (
|
||||
...args: ComposerMethodArgs<Scene<never>, TMethod>
|
||||
): MethodDecorator => {
|
||||
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
||||
return SetMetadata(LISTENER_METADATA, {
|
||||
method,
|
||||
args,
|
||||
} as ListenerMetadata);
|
||||
@ -21,7 +21,7 @@ export function createMissedListenerDecorator<TArgs extends any[]>(
|
||||
method: string,
|
||||
) {
|
||||
return (...args: TArgs): MethodDecorator => {
|
||||
return SetMetadata(UPDATE_LISTENER_METADATA, {
|
||||
return SetMetadata(LISTENER_METADATA, {
|
||||
method,
|
||||
args,
|
||||
} as ListenerMetadata);
|
||||
|
@ -48,39 +48,3 @@ export const addPipesMetadata = (
|
||||
key,
|
||||
);
|
||||
};
|
||||
|
||||
// export function createTelegrafParamDecorator(
|
||||
// paramtype: TelegrafParamtype,
|
||||
// ): (...pipes: (Type<PipeTransform> | PipeTransform)[]) => ParameterDecorator {
|
||||
// return (...pipes: (Type<PipeTransform> | PipeTransform)[]) => (
|
||||
// target,
|
||||
// key,
|
||||
// index,
|
||||
// ) => {
|
||||
// const args =
|
||||
// Reflect.getMetadata(LISTENER_ARGS_METADATA, target.constructor, key) ||
|
||||
// {};
|
||||
// Reflect.defineMetadata(
|
||||
// LISTENER_ARGS_METADATA,
|
||||
// assignMetadata(args, paramtype, index, undefined, ...pipes),
|
||||
// target.constructor,
|
||||
// key,
|
||||
// );
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// export const createPipesTelegrafParamDecorator = (
|
||||
// paramtype: TelegrafParamtype,
|
||||
// ) => (
|
||||
// ...pipes: (Type<PipeTransform> | PipeTransform)[]
|
||||
// ): ParameterDecorator => (target, key, index) => {
|
||||
// const args =
|
||||
// Reflect.getMetadata(LISTENER_ARGS_METADATA, target.constructor, key) || {};
|
||||
//
|
||||
// Reflect.defineMetadata(
|
||||
// LISTENER_ARGS_METADATA,
|
||||
// assignMetadata(args, paramtype, index, undefined, ...pipes),
|
||||
// target.constructor,
|
||||
// key,
|
||||
// );
|
||||
// };
|
||||
|
Loading…
Reference in New Issue
Block a user