feat!(): add custom execution context

This commit is contained in:
Morb0
2021-01-03 01:30:57 +03:00
parent 85bb916709
commit af632ea471
64 changed files with 899 additions and 69 deletions

View File

@@ -3,7 +3,7 @@ import { TelegrafModule } from '../lib';
import { EchoService } from './echo.service';
import { AppUpdate } from './app.update';
import { HelloScene } from './scenes/hello.scene';
import { sessionMiddleware } from './middleware/session.middleware';
import { sessionMiddleware } from './common/middleware/session.middleware';
@Module({
imports: [
@@ -12,6 +12,6 @@ import { sessionMiddleware } from './middleware/session.middleware';
middlewares: [sessionMiddleware],
}),
],
providers: [EchoService, AppUpdate, HelloScene],
providers: [EchoService, AppUpdate],
})
export class AppModule {}

View File

@@ -1,40 +1,63 @@
import { SceneContext, Telegraf } from 'telegraf';
import { Command, Help, InjectBot, On, Start, Update } from '../lib';
import { Telegraf } from 'telegraf';
import { SceneContextMessageUpdate } from 'telegraf/typings/stage';
import {
Command,
Ctx,
Help,
InjectBot,
MessageText,
On,
Start,
Update,
} from '../lib';
import { EchoService } from './echo.service';
import { HELLO_SCENE_ID } from './app.constants';
import { Context } from './interfaces/context.interface';
import { UseGuards, UseInterceptors } from '@nestjs/common';
import { AdminGuard } from './common/guards/admin.guard';
import { ResponseTimeInterceptor } from './common/interceptors/response-time.interceptor';
import { ReverseTextPipe } from './common/pipes/reverse-text.pipe';
@Update()
export class AppUpdate {
constructor(
@InjectBot()
private readonly bot: Telegraf<SceneContext>,
private readonly bot: Telegraf<SceneContextMessageUpdate>,
private readonly echoService: EchoService,
) {}
@Start()
async onStart(ctx: Context): Promise<void> {
async onStart(): Promise<string> {
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<void> {
@UseInterceptors(ResponseTimeInterceptor)
async onHelp(@Ctx() ctx: Context): Promise<void> {
await ctx.reply('Send me any text');
}
@UseGuards(AdminGuard)
@Command('admin')
async onAdminCommand(@Ctx() ctx: Context): Promise<void> {
await ctx.reply('Welcome judge');
}
@Command('scene')
async onSceneCommand(ctx: Context): Promise<void> {
async onSceneCommand(@Ctx() ctx: Context): Promise<void> {
await ctx.scene.enter(HELLO_SCENE_ID);
}
@On('message')
async onMessage(ctx: Context): Promise<void> {
async onMessage(
@Ctx() ctx: Context,
@MessageText(new ReverseTextPipe()) reversedMessage: string,
): Promise<void> {
console.log('New message received');
if ('text' in ctx.message) {
const messageText = ctx.message.text;
const echoText = this.echoService.echo(messageText);
const echoText = this.echoService.echo(reversedMessage);
await ctx.reply(echoText);
} else {
await ctx.reply('Only text messages');

View File

@@ -0,0 +1,7 @@
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { TelegrafExecutionContext } from '../../../lib/execution-context';
export const From = createParamDecorator(
(_, ctx: ExecutionContext) =>
TelegrafExecutionContext.create(ctx).getContext().from,
);

View File

@@ -0,0 +1,11 @@
import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
import { TelegrafArgumentsHost, TelegrafException } from '../../../lib';
@Catch()
export class TelegrafExceptionFilter<T> implements ExceptionFilter {
catch(exception: T, host: ArgumentsHost) {
const tgHost = TelegrafArgumentsHost.create(host);
console.log(tgHost);
return exception;
}
}

View File

@@ -0,0 +1,21 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { TelegrafExecutionContext } from '../../../lib/execution-context/telegraf-execution-context';
import { Context } from '../../interfaces/context.interface';
import { TelegrafException } from '../../../lib/errors';
@Injectable()
export class AdminGuard implements CanActivate {
private readonly ADMIN_IDS = [];
canActivate(context: ExecutionContext): boolean {
const ctx = TelegrafExecutionContext.create(context);
const { from } = ctx.getContext<Context>();
const isAdmin = this.ADMIN_IDS.includes(from.id);
if (!isAdmin) {
throw new TelegrafException('You are not admin >:(');
}
return true;
}
}

View File

@@ -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<any> {
console.log('Before...');
const start = Date.now();
return next
.handle()
.pipe(tap(() => console.log(`Response time: ${Date.now() - start}ms`)));
}
}

View File

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