diff --git a/.eslintrc.js b/.eslintrc.js index 0ed1b02..d02a15c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,10 +6,9 @@ module.exports = { }, plugins: ['@typescript-eslint/eslint-plugin'], extends: [ - 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', - 'prettier', 'prettier/@typescript-eslint', + 'plugin:prettier/recommended', ], root: true, env: { diff --git a/lib/decorators/index.ts b/lib/decorators/index.ts index 31fa986..ee4e5a9 100644 --- a/lib/decorators/index.ts +++ b/lib/decorators/index.ts @@ -1,3 +1,4 @@ export * from './core'; export * from './listeners'; export * from './scene'; +export * from './params'; diff --git a/lib/decorators/listeners/cashtag.decorator.ts b/lib/decorators/listeners/cashtag.decorator.ts index 2169873..1f9549d 100644 --- a/lib/decorators/listeners/cashtag.decorator.ts +++ b/lib/decorators/listeners/cashtag.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=cashtag */ -export const Cashtag = createMissedListenerDecorator<[string | string[]]>('cashtag'); +export const Cashtag = createMissedListenerDecorator<[string | string[]]>( + 'cashtag', +); diff --git a/lib/decorators/listeners/email.decorator.ts b/lib/decorators/listeners/email.decorator.ts index bf7b024..9459e08 100644 --- a/lib/decorators/listeners/email.decorator.ts +++ b/lib/decorators/listeners/email.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=telegraf-email */ -export const Email = createMissedListenerDecorator<[string | string[]]>('email'); +export const Email = createMissedListenerDecorator<[string | string[]]>( + 'email', +); diff --git a/lib/decorators/listeners/hashtag.decorator.ts b/lib/decorators/listeners/hashtag.decorator.ts index 266cd8d..d9edec9 100644 --- a/lib/decorators/listeners/hashtag.decorator.ts +++ b/lib/decorators/listeners/hashtag.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=hashtag */ -export const Hashtag = createMissedListenerDecorator<[string | string[]]>('hashtag'); +export const Hashtag = createMissedListenerDecorator<[string | string[]]>( + 'hashtag', +); diff --git a/lib/decorators/listeners/inline-query.decorator.ts b/lib/decorators/listeners/inline-query.decorator.ts index 30c15c1..57d13fb 100644 --- a/lib/decorators/listeners/inline-query.decorator.ts +++ b/lib/decorators/listeners/inline-query.decorator.ts @@ -6,4 +6,6 @@ import { HearsTriggers } from 'telegraf/typings/composer'; * * @see https://telegraf.js.org/#/?id=inlinequery */ -export const InlineQuery = createMissedListenerDecorator<[HearsTriggers]>('inlineQuery'); +export const InlineQuery = createMissedListenerDecorator< + [HearsTriggers] +>('inlineQuery'); diff --git a/lib/decorators/listeners/mention.decorator.ts b/lib/decorators/listeners/mention.decorator.ts index 0f2391a..bd9437b 100644 --- a/lib/decorators/listeners/mention.decorator.ts +++ b/lib/decorators/listeners/mention.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=mention */ -export const Mention = createMissedListenerDecorator<[string | string[]]>('mention'); +export const Mention = createMissedListenerDecorator<[string | string[]]>( + 'mention', +); diff --git a/lib/decorators/listeners/phone.decorator.ts b/lib/decorators/listeners/phone.decorator.ts index 9dc2a83..8ec5bed 100644 --- a/lib/decorators/listeners/phone.decorator.ts +++ b/lib/decorators/listeners/phone.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=phone */ -export const Phone = createMissedListenerDecorator<[string | string[]]>('phone'); +export const Phone = createMissedListenerDecorator<[string | string[]]>( + 'phone', +); diff --git a/lib/decorators/listeners/text-link.decorator.ts b/lib/decorators/listeners/text-link.decorator.ts index f116efe..ec38818 100644 --- a/lib/decorators/listeners/text-link.decorator.ts +++ b/lib/decorators/listeners/text-link.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=telegraf-textlink */ -export const TextLink = createMissedListenerDecorator<[string | string[]]>('textLink'); +export const TextLink = createMissedListenerDecorator<[string | string[]]>( + 'textLink', +); diff --git a/lib/decorators/listeners/text-mention.decorator.ts b/lib/decorators/listeners/text-mention.decorator.ts index 320128d..d17543c 100644 --- a/lib/decorators/listeners/text-mention.decorator.ts +++ b/lib/decorators/listeners/text-mention.decorator.ts @@ -5,4 +5,6 @@ import { createMissedListenerDecorator } from '../../utils'; * * @see https://telegraf.js.org/#/?id=telegraf-textlink */ -export const TextMention = createMissedListenerDecorator<[string | string[]]>('textMention'); +export const TextMention = createMissedListenerDecorator<[string | string[]]>( + 'textMention', +); diff --git a/lib/decorators/params/context.decorator.ts b/lib/decorators/params/context.decorator.ts new file mode 100644 index 0000000..e77fcd8 --- /dev/null +++ b/lib/decorators/params/context.decorator.ts @@ -0,0 +1,8 @@ +import { createTelegrafParamDecorator } from '../../utils/param-decorator.util'; +import { TelegrafParamtype } from '../../enums/telegraf-paramtype.enum'; + +export const Context: () => ParameterDecorator = createTelegrafParamDecorator( + TelegrafParamtype.CONTEXT, +); + +export const Ctx = Context; diff --git a/lib/decorators/params/index.ts b/lib/decorators/params/index.ts new file mode 100644 index 0000000..92a211a --- /dev/null +++ b/lib/decorators/params/index.ts @@ -0,0 +1,4 @@ +export * from './context.decorator'; +export * from './next.decorator'; +export * from './message.decorator'; +export * from './sender.decorator'; diff --git a/lib/decorators/params/message.decorator.ts b/lib/decorators/params/message.decorator.ts new file mode 100644 index 0000000..c77e512 --- /dev/null +++ b/lib/decorators/params/message.decorator.ts @@ -0,0 +1,21 @@ +import { PipeTransform, Type } from '@nestjs/common'; +import { createTelegrafPipesParamDecorator } from '../../utils/param-decorator.util'; +import { TelegrafParamtype } from '../../enums/telegraf-paramtype.enum'; + +export function Message(): ParameterDecorator; +export function Message( + ...pipes: (Type | PipeTransform)[] +): ParameterDecorator; +export function Message( + property: string, + ...pipes: (Type | PipeTransform)[] +): ParameterDecorator; +export function Message( + property?: string | (Type | PipeTransform), + ...pipes: (Type | PipeTransform)[] +) { + return createTelegrafPipesParamDecorator(TelegrafParamtype.MESSAGE)( + property, + ...pipes, + ); +} diff --git a/lib/decorators/params/next.decorator.ts b/lib/decorators/params/next.decorator.ts new file mode 100644 index 0000000..063623e --- /dev/null +++ b/lib/decorators/params/next.decorator.ts @@ -0,0 +1,6 @@ +import { createTelegrafParamDecorator } from '../../utils/param-decorator.util'; +import { TelegrafParamtype } from '../../enums/telegraf-paramtype.enum'; + +export const Next: () => ParameterDecorator = createTelegrafParamDecorator( + TelegrafParamtype.NEXT, +); diff --git a/lib/decorators/params/sender.decorator.ts b/lib/decorators/params/sender.decorator.ts new file mode 100644 index 0000000..bd504da --- /dev/null +++ b/lib/decorators/params/sender.decorator.ts @@ -0,0 +1,21 @@ +import { PipeTransform, Type } from '@nestjs/common'; +import { createTelegrafPipesParamDecorator } from '../../utils/param-decorator.util'; +import { TelegrafParamtype } from '../../enums/telegraf-paramtype.enum'; + +export function Sender(): ParameterDecorator; +export function Sender( + ...pipes: (Type | PipeTransform)[] +): ParameterDecorator; +export function Sender( + property: string, + ...pipes: (Type | PipeTransform)[] +): ParameterDecorator; +export function Sender( + property?: string | (Type | PipeTransform), + ...pipes: (Type | PipeTransform)[] +) { + return createTelegrafPipesParamDecorator(TelegrafParamtype.SENDER)( + property, + ...pipes, + ); +} diff --git a/lib/enums/telegraf-paramtype.enum.ts b/lib/enums/telegraf-paramtype.enum.ts new file mode 100644 index 0000000..980aeb6 --- /dev/null +++ b/lib/enums/telegraf-paramtype.enum.ts @@ -0,0 +1,7 @@ +export enum TelegrafParamtype { + CONTEXT, + NEXT, + SENDER, + MESSAGE, + // TODO-Possible-Feature: Add more paramtypes +} diff --git a/lib/errors/index.ts b/lib/errors/index.ts new file mode 100644 index 0000000..1290854 --- /dev/null +++ b/lib/errors/index.ts @@ -0,0 +1 @@ +export * from './telegraf.exception'; diff --git a/lib/errors/telegraf.exception.ts b/lib/errors/telegraf.exception.ts new file mode 100644 index 0000000..f87e7fc --- /dev/null +++ b/lib/errors/telegraf.exception.ts @@ -0,0 +1 @@ +export class TelegrafException extends Error {} diff --git a/lib/execution-context/index.ts b/lib/execution-context/index.ts new file mode 100644 index 0000000..4150b50 --- /dev/null +++ b/lib/execution-context/index.ts @@ -0,0 +1,3 @@ +export * from './tg-arguments-host.interace'; +export * from './telegraf-arguments-host'; +export * from './telegraf-execution-context'; diff --git a/lib/execution-context/telegraf-arguments-host.ts b/lib/execution-context/telegraf-arguments-host.ts new file mode 100644 index 0000000..79a2c10 --- /dev/null +++ b/lib/execution-context/telegraf-arguments-host.ts @@ -0,0 +1,22 @@ +import { ArgumentsHost } from '@nestjs/common'; +import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host'; +import { TgArgumentsHost } from './tg-arguments-host.interace'; + +export class TelegrafArgumentsHost + extends ExecutionContextHost + implements TgArgumentsHost { + static create(context: ArgumentsHost): TelegrafArgumentsHost { + const type = context.getType(); + const tgContext = new TelegrafArgumentsHost(context.getArgs()); + tgContext.setType(type); + return tgContext; + } + + getContext(): T { + return this.getArgByIndex(0); + } + + getNext(): T { + return this.getArgByIndex(1); + } +} diff --git a/lib/execution-context/telegraf-execution-context.ts b/lib/execution-context/telegraf-execution-context.ts new file mode 100644 index 0000000..d0c9613 --- /dev/null +++ b/lib/execution-context/telegraf-execution-context.ts @@ -0,0 +1,32 @@ +import { ContextType, ExecutionContext } from '@nestjs/common'; +import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host'; +import { TgArgumentsHost } from './tg-arguments-host.interace'; + +export type TelegrafContextType = 'telegraf' | ContextType; + +export class TelegrafExecutionContext + extends ExecutionContextHost + implements TgArgumentsHost { + static create(context: ExecutionContext): TelegrafExecutionContext { + const type = context.getType(); + const tgContext = new TelegrafExecutionContext( + context.getArgs(), + context.getClass(), + context.getHandler(), + ); + tgContext.setType(type); + return tgContext; + } + + getType(): TContext { + return super.getType(); + } + + getContext(): T { + return this.getArgByIndex(0); + } + + getNext(): T { + return this.getArgByIndex(0); + } +} diff --git a/lib/execution-context/tg-arguments-host.interace.ts b/lib/execution-context/tg-arguments-host.interace.ts new file mode 100644 index 0000000..fa5a8c1 --- /dev/null +++ b/lib/execution-context/tg-arguments-host.interace.ts @@ -0,0 +1,6 @@ +import { ArgumentsHost } from '@nestjs/common'; + +export interface TgArgumentsHost extends ArgumentsHost { + getContext(): T; + getNext(): T; +} diff --git a/lib/factories/telegraf-params-factory.ts b/lib/factories/telegraf-params-factory.ts new file mode 100644 index 0000000..2dad83b --- /dev/null +++ b/lib/factories/telegraf-params-factory.ts @@ -0,0 +1,28 @@ +import { ParamData } from '@nestjs/common'; +import { ParamsFactory } from '@nestjs/core/helpers/external-context-creator'; +import { Context } from 'telegraf'; +import { TelegrafParamtype } from '../enums/telegraf-paramtype.enum'; + +export class TelegrafParamsFactory implements ParamsFactory { + exchangeKeyForValue( + type: TelegrafParamtype, + data: ParamData, + args: unknown[], + ): unknown { + const ctx = args[0] as Context; + const next = args[1] as Function; + + switch (type) { + case TelegrafParamtype.CONTEXT: + return ctx; + case TelegrafParamtype.NEXT: + return next; + case TelegrafParamtype.SENDER: + return ctx.from ? ctx.from[data as string] : ctx.from; + case TelegrafParamtype.MESSAGE: + return ctx.message ? ctx.message[data as string] : ctx.message; + default: + return null; + } + } +} diff --git a/lib/index.ts b/lib/index.ts index ef6e2ba..620f652 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -2,5 +2,8 @@ export * from './decorators'; export * from './interfaces'; export * from './utils'; export * from './types'; +export * from './services'; +export * from './errors'; +export * from './execution-context'; export * from './telegraf.constants'; export * from './telegraf.module'; diff --git a/lib/interfaces/telegraf-exception-filter.interface.ts b/lib/interfaces/telegraf-exception-filter.interface.ts new file mode 100644 index 0000000..c1f4598 --- /dev/null +++ b/lib/interfaces/telegraf-exception-filter.interface.ts @@ -0,0 +1,5 @@ +import { ArgumentsHost } from '@nestjs/common'; + +export interface TelegrafExceptionFilter { + catch(exception: T, host: ArgumentsHost): any; +} diff --git a/lib/services/base-explorer.service.ts b/lib/services/base-explorer.service.ts index 2a87d66..89af422 100644 --- a/lib/services/base-explorer.service.ts +++ b/lib/services/base-explorer.service.ts @@ -19,9 +19,7 @@ export class BaseExplorerService { include: Function[], ): Module[] { const modules = [...modulesContainer.values()]; - return modules.filter(({ metatype }) => - include.includes(metatype), - ); + return modules.filter(({ metatype }) => include.includes(metatype)); } flatMap( diff --git a/lib/services/listeners-explorer.service.ts b/lib/services/listeners-explorer.service.ts index ac22b96..5bfee9c 100644 --- a/lib/services/listeners-explorer.service.ts +++ b/lib/services/listeners-explorer.service.ts @@ -3,33 +3,40 @@ import { DiscoveryService, ModuleRef, ModulesContainer } from '@nestjs/core'; import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper'; import { MetadataScanner } from '@nestjs/core/metadata-scanner'; import { Module } from '@nestjs/core/injector/module'; -import { BaseScene, Composer, Stage, Telegraf } from 'telegraf'; +import { ParamMetadata } from '@nestjs/core/helpers/interfaces'; +import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator'; +import { BaseScene, Composer, Context, Stage, Telegraf } from 'telegraf'; import { MetadataAccessorService } from './metadata-accessor.service'; import { + PARAM_ARGS_METADATA, TELEGRAF_BOT_NAME, TELEGRAF_MODULE_OPTIONS, } from '../telegraf.constants'; -import { TelegrafModuleOptions } from '../interfaces'; import { BaseExplorerService } from './base-explorer.service'; +import { TelegrafParamsFactory } from '../factories/telegraf-params-factory'; +import { TelegrafContextType } from '../execution-context'; +import { TelegrafModuleOptions } from '../interfaces'; @Injectable() export class ListenersExplorerService extends BaseExplorerService implements OnModuleInit { + private readonly telegrafParamsFactory = new TelegrafParamsFactory(); private readonly stage = new Stage([]); private bot: Telegraf; constructor( - @Inject(TELEGRAF_BOT_NAME) - private readonly botName: string, @Inject(TELEGRAF_MODULE_OPTIONS) private readonly telegrafOptions: TelegrafModuleOptions, + @Inject(TELEGRAF_BOT_NAME) + private readonly botName: string, private readonly moduleRef: ModuleRef, private readonly discoveryService: DiscoveryService, private readonly metadataAccessor: MetadataAccessorService, private readonly metadataScanner: MetadataScanner, private readonly modulesContainer: ModulesContainer, + private readonly externalContextCreator: ExternalContextCreator, ) { super(); } @@ -57,23 +64,21 @@ export class ListenersExplorerService const updates = this.flatMap(modules, (instance) => this.filterUpdates(instance), ); - updates.forEach(({ instance }) => - this.registerInstanceMethodListeners(this.bot, instance), - ); + updates.forEach((wrapper) => this.registerListeners(this.bot, wrapper)); } private registerScenes(modules: Module[]): void { - const scenes = this.flatMap(modules, (instance) => - this.filterScenes(instance), + const scenes = this.flatMap(modules, (wrapper) => + this.filterScenes(wrapper), ); - scenes.forEach(({ instance }) => { + scenes.forEach((wrapper) => { const sceneId = this.metadataAccessor.getSceneMetadata( - instance.constructor, + wrapper.instance.constructor, ); const scene = new BaseScene(sceneId); this.stage.register(scene); - this.registerInstanceMethodListeners(scene, instance); + this.registerListeners(scene, wrapper); }); } @@ -97,20 +102,73 @@ export class ListenersExplorerService return wrapper; } - private registerInstanceMethodListeners( - composer: Composer, - instance: Record, + private registerListeners( + composer: Composer, + wrapper: InstanceWrapper, ): void { + const { instance } = wrapper; const prototype = Object.getPrototypeOf(instance); - this.metadataScanner.scanFromPrototype(instance, prototype, (name) => { - const methodRef = instance[name]; + this.metadataScanner.scanFromPrototype(instance, prototype, (name) => + this.registerIfListener(composer, instance, prototype, name), + ); + } - const metadata = this.metadataAccessor.getListenerMetadata(methodRef); - if (!metadata) return; + private registerIfListener( + composer: Composer, + instance: any, + prototype: any, + methodName: string, + ): void { + const methodRef = prototype[methodName]; + const metadata = this.metadataAccessor.getListenerMetadata(methodRef); + if (!metadata) { + return undefined; + } - const middlewareFn = methodRef.bind(instance); - const { method, args } = metadata; - composer[method](...args, middlewareFn); - }); + const listenerCallbackFn = this.createContextCallback( + instance, + prototype, + methodName, + ); + + const { method, args } = metadata; + + /* Basic callback */ + // composer[method](...args, listenerCallbackFn); + + /* Complex callback return value handing */ + composer[method]( + ...args, + async (ctx: Context, next: Function): Promise => { + const result = await listenerCallbackFn(ctx, next); + if (result) { + await ctx.reply(String(result)); + } + // TODO-Possible-Feature: Add more supported return types + }, + ); + } + + createContextCallback>( + instance: T, + prototype: unknown, + methodName: string, + ) { + const paramsFactory = this.telegrafParamsFactory; + const resolverCallback = this.externalContextCreator.create< + Record, + TelegrafContextType + >( + instance, + prototype[methodName], + methodName, + PARAM_ARGS_METADATA, + paramsFactory, + undefined, + undefined, + undefined, + 'telegraf', + ); + return resolverCallback; } } diff --git a/lib/services/metadata-accessor.service.ts b/lib/services/metadata-accessor.service.ts index 0695e95..75fb79c 100644 --- a/lib/services/metadata-accessor.service.ts +++ b/lib/services/metadata-accessor.service.ts @@ -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'; @@ -12,21 +12,17 @@ export class MetadataAccessorService { constructor(private readonly reflector: Reflector) {} isUpdate(target: Function): boolean { - if (!target) { - return false; - } + if (!target) return false; return !!this.reflector.get(UPDATE_METADATA, target); } isScene(target: Function): boolean { - if (!target) { - return false; - } + if (!target) return false; return !!this.reflector.get(SCENE_METADATA, target); } 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 { diff --git a/lib/telegraf.constants.ts b/lib/telegraf.constants.ts index 3ac37e3..5d6888b 100644 --- a/lib/telegraf.constants.ts +++ b/lib/telegraf.constants.ts @@ -1,8 +1,11 @@ +import { ROUTE_ARGS_METADATA } from '@nestjs/common/constants'; + export const TELEGRAF_MODULE_OPTIONS = 'TELEGRAF_MODULE_OPTIONS'; export const TELEGRAF_BOT_NAME = 'TELEGRAF_BOT_NAME'; 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; diff --git a/lib/utils/create-listener-decorator.util.ts b/lib/utils/create-listener-decorator.util.ts index 88a852c..b880fcb 100644 --- a/lib/utils/create-listener-decorator.util.ts +++ b/lib/utils/create-listener-decorator.util.ts @@ -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( @@ -10,7 +10,7 @@ export function createListenerDecorator( return ( ...args: ComposerMethodArgs, TMethod> ): MethodDecorator => { - return SetMetadata(UPDATE_LISTENER_METADATA, { + return SetMetadata(LISTENER_METADATA, { method, args, } as ListenerMetadata); @@ -20,10 +20,8 @@ export function createListenerDecorator( export function createMissedListenerDecorator( method: string, ) { - return ( - ...args: TArgs - ): MethodDecorator => { - return SetMetadata(UPDATE_LISTENER_METADATA, { + return (...args: TArgs): MethodDecorator => { + return SetMetadata(LISTENER_METADATA, { method, args, } as ListenerMetadata); diff --git a/lib/utils/param-decorator.util.ts b/lib/utils/param-decorator.util.ts new file mode 100644 index 0000000..6a2d261 --- /dev/null +++ b/lib/utils/param-decorator.util.ts @@ -0,0 +1,50 @@ +import { assignMetadata, PipeTransform, Type } from '@nestjs/common'; +import { isNil, isString } from '@nestjs/common/utils/shared.utils'; +import { TelegrafParamtype } from '../enums/telegraf-paramtype.enum'; +import { PARAM_ARGS_METADATA } from '../telegraf.constants'; + +export type ParamData = object | string | number; + +export const createTelegrafParamDecorator = (paramtype: TelegrafParamtype) => { + return (data?: ParamData): ParameterDecorator => (target, key, index) => { + const args = + Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {}; + Reflect.defineMetadata( + PARAM_ARGS_METADATA, + assignMetadata(args, paramtype, index, data), + target.constructor, + key, + ); + }; +}; + +export const createTelegrafPipesParamDecorator = ( + paramtype: TelegrafParamtype, +) => ( + data?: any, + ...pipes: (Type | PipeTransform)[] +): ParameterDecorator => (target, key, index) => { + addPipesMetadata(paramtype, data, pipes, target, key, index); +}; + +export const addPipesMetadata = ( + paramtype: TelegrafParamtype, + data: any, + pipes: (Type | PipeTransform)[], + target: Record, + key: string | symbol, + index: number, +) => { + const args = + Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {}; + const hasParamData = isNil(data) || isString(data); + const paramData = hasParamData ? data : undefined; + const paramPipes = hasParamData ? pipes : [data, ...pipes]; + + Reflect.defineMetadata( + PARAM_ARGS_METADATA, + assignMetadata(args, paramtype, index, paramData, ...paramPipes), + target.constructor, + key, + ); +}; diff --git a/package-lock.json b/package-lock.json index a182b08..c1fbc12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4006,12 +4006,6 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, "@types/lodash": { "version": "4.14.167", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.167.tgz", @@ -4190,33 +4184,12 @@ "sprintf-js": "~1.0.2" } }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - } - }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -4356,12 +4329,6 @@ "integrity": "sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==", "dev": true }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, "cosmiconfig": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", @@ -4415,15 +4382,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4475,36 +4433,6 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -4619,146 +4547,13 @@ "integrity": "sha512-9sm5/PxaFG7qNJvJzTROMM1Bk1ozXVTKI0buKOyb0Bsr1hrwi0H/TzxF/COtf1uxikIK8SwhX7K6zg78jAzbeA==", "dev": true }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "eslint-plugin-prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - } + "prettier-linter-helpers": "^1.0.0" } }, "eslint-scope": { @@ -4872,6 +4667,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", @@ -4999,12 +4800,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -5099,33 +4894,12 @@ "wordwrap": "^1.0.0" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, "human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", @@ -5258,18 +5032,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5291,12 +5053,6 @@ "is-extglob": "^2.1.1" } }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5309,15 +5065,6 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, "is-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", @@ -5330,27 +5077,6 @@ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5397,15 +5123,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -5596,29 +5313,6 @@ } } }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - } - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -5811,12 +5505,6 @@ "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==" }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5834,26 +5522,6 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5875,64 +5543,6 @@ "integrity": "sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ==", "dev": true }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6076,12 +5686,6 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -6112,6 +5716,15 @@ "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -6134,89 +5747,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "dependencies": { - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - } - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -6439,38 +5969,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6494,26 +5992,6 @@ "strip-ansi": "^6.0.0" } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, "stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", @@ -6542,12 +6020,6 @@ } } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -6672,18 +6144,6 @@ "is-number": "^7.0.0" } }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - } - }, "tslib": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", @@ -6779,16 +6239,6 @@ "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "vscode-textmate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", diff --git a/package.json b/package.json index bf84789..6aced8e 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@typescript-eslint/parser": "4.12.0", "eslint": "7.17.0", "eslint-config-prettier": "7.1.0", - "eslint-plugin-import": "2.22.1", + "eslint-plugin-prettier": "^3.3.1", "husky": "4.3.6", "lint-staged": "10.5.3", "lodash": "4.17.20", diff --git a/sample/01-complete-app/src/app.module.ts b/sample/01-complete-app/src/app.module.ts index 408a307..6f7f595 100644 --- a/sample/01-complete-app/src/app.module.ts +++ b/sample/01-complete-app/src/app.module.ts @@ -9,7 +9,6 @@ import { GreeterBotName } from './app.constants'; imports: [ TelegrafModule.forRoot({ token: process.env.ECHO_BOT_TOKEN, - middlewares: [sessionMiddleware], include: [EchoModule], }), TelegrafModule.forRootAsync({ diff --git a/sample/01-complete-app/src/common/decorators/update-type.decorator.ts b/sample/01-complete-app/src/common/decorators/update-type.decorator.ts new file mode 100644 index 0000000..2639e6d --- /dev/null +++ b/sample/01-complete-app/src/common/decorators/update-type.decorator.ts @@ -0,0 +1,7 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; +import { TelegrafExecutionContext } from 'nestjs-telegraf'; + +export const UpdateType = createParamDecorator( + (_, ctx: ExecutionContext) => + TelegrafExecutionContext.create(ctx).getContext().updateType, +); diff --git a/sample/01-complete-app/src/common/filters/telegraf-exception.filter.ts b/sample/01-complete-app/src/common/filters/telegraf-exception.filter.ts new file mode 100644 index 0000000..8221b86 --- /dev/null +++ b/sample/01-complete-app/src/common/filters/telegraf-exception.filter.ts @@ -0,0 +1,13 @@ +import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common'; +import { TelegrafArgumentsHost } from 'nestjs-telegraf'; +import { Context } from '../../interfaces/context.interface'; + +@Catch() +export class TelegrafExceptionFilter implements ExceptionFilter { + async catch(exception: Error, host: ArgumentsHost): Promise { + const telegrafHost = TelegrafArgumentsHost.create(host); + const ctx = telegrafHost.getContext(); + + await ctx.replyWithHTML(`Error: ${exception.message}`); + } +} diff --git a/sample/01-complete-app/src/common/guards/admin.guard.ts b/sample/01-complete-app/src/common/guards/admin.guard.ts new file mode 100644 index 0000000..23030b0 --- /dev/null +++ b/sample/01-complete-app/src/common/guards/admin.guard.ts @@ -0,0 +1,20 @@ +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import { TelegrafExecutionContext, TelegrafException } from 'nestjs-telegraf'; +import { Context } from '../../interfaces/context.interface'; + +@Injectable() +export class AdminGuard implements CanActivate { + private readonly ADMIN_IDS = []; + + canActivate(context: ExecutionContext): boolean { + const ctx = TelegrafExecutionContext.create(context); + const { from } = ctx.getContext(); + + const isAdmin = this.ADMIN_IDS.includes(from.id); + if (!isAdmin) { + throw new TelegrafException('You are not admin 😡'); + } + + return true; + } +} diff --git a/sample/01-complete-app/src/common/interceptors/response-time.interceptor.ts b/sample/01-complete-app/src/common/interceptors/response-time.interceptor.ts new file mode 100644 index 0000000..96b1b37 --- /dev/null +++ b/sample/01-complete-app/src/common/interceptors/response-time.interceptor.ts @@ -0,0 +1,20 @@ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Injectable() +export class ResponseTimeInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + console.log('Before...'); + + const start = Date.now(); + return next + .handle() + .pipe(tap(() => console.log(`Response time: ${Date.now() - start}ms`))); + } +} diff --git a/sample/01-complete-app/src/common/pipes/reverse-text.pipe.ts b/sample/01-complete-app/src/common/pipes/reverse-text.pipe.ts new file mode 100644 index 0000000..82ee739 --- /dev/null +++ b/sample/01-complete-app/src/common/pipes/reverse-text.pipe.ts @@ -0,0 +1,8 @@ +import { Injectable, PipeTransform } from '@nestjs/common'; + +@Injectable() +export class ReverseTextPipe implements PipeTransform { + transform(value: string): string { + return value.split('').reverse().join(''); + } +} diff --git a/sample/01-complete-app/src/echo/echo.module.ts b/sample/01-complete-app/src/echo/echo.module.ts index 29c1bff..36c97ce 100644 --- a/sample/01-complete-app/src/echo/echo.module.ts +++ b/sample/01-complete-app/src/echo/echo.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; import { EchoUpdate } from './echo.update'; import { EchoService } from './echo.service'; -import { HelloScene } from './scenes/hello.scene'; +import { RandomNumberScene } from '../greeter/scenes/random-number.scene'; @Module({ - providers: [EchoUpdate, EchoService, HelloScene], + providers: [EchoUpdate, EchoService, RandomNumberScene], }) export class EchoModule {} diff --git a/sample/01-complete-app/src/echo/echo.update.ts b/sample/01-complete-app/src/echo/echo.update.ts index 1d0d6b3..eee15f0 100644 --- a/sample/01-complete-app/src/echo/echo.update.ts +++ b/sample/01-complete-app/src/echo/echo.update.ts @@ -1,18 +1,25 @@ -import { Telegraf } from 'telegraf'; +import { UseFilters, UseGuards, UseInterceptors } from '@nestjs/common'; import { - Command, - getBotToken, Help, InjectBot, On, + Message, Start, Update, + Command, } from 'nestjs-telegraf'; +import { Telegraf } from 'telegraf'; import { EchoService } from './echo.service'; -import { GreeterBotName, HELLO_SCENE_ID } from '../app.constants'; +import { GreeterBotName } from '../app.constants'; import { Context } from '../interfaces/context.interface'; +import { ReverseTextPipe } from '../common/pipes/reverse-text.pipe'; +import { ResponseTimeInterceptor } from '../common/interceptors/response-time.interceptor'; +import { AdminGuard } from '../common/guards/admin.guard'; +import { TelegrafExceptionFilter } from '../common/filters/telegraf-exception.filter'; @Update() +@UseInterceptors(ResponseTimeInterceptor) +@UseFilters(TelegrafExceptionFilter) export class EchoUpdate { constructor( @InjectBot(GreeterBotName) @@ -21,31 +28,26 @@ export class EchoUpdate { ) {} @Start() - async onStart(ctx: Context): Promise { + async onStart(): Promise { const me = await this.bot.telegram.getMe(); - await ctx.reply(`Hey, I'm ${me.first_name}`); + return `Hey, I'm ${me.first_name}`; } @Help() - async onHelp(ctx: Context): Promise { - await ctx.reply('Send me any text'); + async onHelp(): Promise { + return 'Send me any text'; } - @Command('scene') - async onSceneCommand(ctx: Context): Promise { - await ctx.scene.enter(HELLO_SCENE_ID); + @Command('admin') + @UseGuards(AdminGuard) + onAdminCommand(): string { + return 'Welcome judge'; } - @On('message') - async onMessage(ctx: Context): Promise { - console.log('New message received'); - - if ('text' in ctx.message) { - const messageText = ctx.message.text; - const echoText = this.echoService.echo(messageText); - await ctx.reply(echoText); - } else { - await ctx.reply('Only text messages'); - } + @On('text') + onMessage( + @Message('text', new ReverseTextPipe()) reversedText: string, + ): string { + return this.echoService.echo(reversedText); } } diff --git a/sample/01-complete-app/src/greeter/greeter.module.ts b/sample/01-complete-app/src/greeter/greeter.module.ts index 40160db..02e3284 100644 --- a/sample/01-complete-app/src/greeter/greeter.module.ts +++ b/sample/01-complete-app/src/greeter/greeter.module.ts @@ -1,7 +1,8 @@ import { Module } from '@nestjs/common'; import { GreeterUpdate } from './greeter.update'; +import { RandomNumberScene } from './scenes/random-number.scene'; @Module({ - providers: [GreeterUpdate], + providers: [GreeterUpdate, RandomNumberScene], }) export class GreeterModule {} diff --git a/sample/01-complete-app/src/greeter/greeter.update.ts b/sample/01-complete-app/src/greeter/greeter.update.ts index 8f50e9b..bef392f 100644 --- a/sample/01-complete-app/src/greeter/greeter.update.ts +++ b/sample/01-complete-app/src/greeter/greeter.update.ts @@ -1,16 +1,26 @@ -import { Hears, Start, Update } from '../../../../lib'; +import { Command, Ctx, Hears, Start, Update, Sender } from 'nestjs-telegraf'; +import { UpdateType as TelegrafUpdateType } from 'telegraf/typings/telegram-types'; import { Context } from '../interfaces/context.interface'; +import { HELLO_SCENE_ID } from '../app.constants'; +import { UpdateType } from '../common/decorators/update-type.decorator'; @Update() export class GreeterUpdate { @Start() - async onStart(ctx: Context): Promise { - await ctx.reply('Say hello to me'); + onStart(): string { + return 'Say hello to me'; } @Hears(['hi', 'hello', 'hey', 'qq']) - async onGreetings(ctx: Context): Promise { - const { first_name } = ctx.from; - await ctx.reply(`Hey ${first_name}`); + onGreetings( + @UpdateType() updateType: TelegrafUpdateType, + @Sender('first_name') firstName: string, + ): string { + return `Hey ${firstName}`; + } + + @Command('scene') + async onSceneCommand(@Ctx() ctx: Context): Promise { + await ctx.scene.enter(HELLO_SCENE_ID); } } diff --git a/sample/01-complete-app/src/echo/scenes/hello.scene.ts b/sample/01-complete-app/src/greeter/scenes/random-number.scene.ts similarity index 56% rename from sample/01-complete-app/src/echo/scenes/hello.scene.ts rename to sample/01-complete-app/src/greeter/scenes/random-number.scene.ts index 211b06f..3c04d46 100644 --- a/sample/01-complete-app/src/echo/scenes/hello.scene.ts +++ b/sample/01-complete-app/src/greeter/scenes/random-number.scene.ts @@ -3,23 +3,23 @@ import { HELLO_SCENE_ID } from '../../app.constants'; import { Context } from '../../interfaces/context.interface'; @Scene(HELLO_SCENE_ID) -export class HelloScene { +export class RandomNumberScene { @SceneEnter() - async onSceneEnter(ctx: Context): Promise { + onSceneEnter(): string { console.log('Enter to scene'); - await ctx.reply('Welcome on scene ✋'); + return 'Welcome on scene ✋'; } @SceneLeave() - async onSceneLeave(ctx: Context): Promise { + onSceneLeave(): string { console.log('Leave from scene'); - await ctx.reply('Bye Bye 👋'); + return 'Bye Bye 👋'; } - @Command('hello') - async onHelloCommand(ctx: Context): Promise { - console.log('Use say hello'); - await ctx.reply('Hi'); + @Command(['rng', 'random']) + onRandomCommand(): number { + console.log('Use "random" command'); + return Math.floor(Math.random() * 11); } @Command('leave') diff --git a/website/docs/api-reference/decorators.md b/website/docs/api-reference/decorators.md index d3a51d9..433c47c 100644 --- a/website/docs/api-reference/decorators.md +++ b/website/docs/api-reference/decorators.md @@ -12,6 +12,7 @@ The described functionality is under development, the functionality has not been ### Update `@Update` class decorator, it's like NestJS [`@Controller`](https://docs.nestjs.com/controllers) decorator, but for [Telegram Bot API updates](https://core.telegram.org/bots/api#getting-updates). +It is required for the class that will receive updates from Telegram. ```typescript {3} import { Update, Context } from 'nestjs-telegraf'; diff --git a/website/docs/telegraf-methods.md b/website/docs/telegraf-methods.md index aa39a30..7cdfa6b 100644 --- a/website/docs/telegraf-methods.md +++ b/website/docs/telegraf-methods.md @@ -18,8 +18,8 @@ import { Help, On, Hears, - Context, } from 'nestjs-telegraf'; +import { Context } from 'telegraf'; @Injectable() export class AppService {