mirror of
https://github.com/Maks1mS/nestjs-telegraf.git
synced 2025-09-30 12:27:39 +03:00
3
sample/01-complete-app/src/app.constants.ts
Normal file
3
sample/01-complete-app/src/app.constants.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const HELLO_SCENE_ID = 'HELLO_SCENE_ID';
|
||||
|
||||
export const GreeterBotName = 'greeter';
|
26
sample/01-complete-app/src/app.module.ts
Normal file
26
sample/01-complete-app/src/app.module.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TelegrafModule } from 'nestjs-telegraf';
|
||||
import { EchoModule } from './echo/echo.module';
|
||||
import { GreeterModule } from './greeter/greeter.module';
|
||||
import { sessionMiddleware } from './middleware/session.middleware';
|
||||
import { GreeterBotName } from './app.constants';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TelegrafModule.forRoot({
|
||||
token: process.env.ECHO_BOT_TOKEN,
|
||||
include: [EchoModule],
|
||||
}),
|
||||
TelegrafModule.forRootAsync({
|
||||
botName: GreeterBotName,
|
||||
useFactory: () => ({
|
||||
token: process.env.GREETER_BOT_TOKEN,
|
||||
middlewares: [sessionMiddleware],
|
||||
include: [GreeterModule],
|
||||
}),
|
||||
}),
|
||||
EchoModule,
|
||||
GreeterModule,
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
@@ -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,
|
||||
);
|
@@ -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<void> {
|
||||
const telegrafHost = TelegrafArgumentsHost.create(host);
|
||||
const ctx = telegrafHost.getContext<Context>();
|
||||
|
||||
await ctx.replyWithHTML(`<b>Error</b>: ${exception.message}`);
|
||||
}
|
||||
}
|
20
sample/01-complete-app/src/common/guards/admin.guard.ts
Normal file
20
sample/01-complete-app/src/common/guards/admin.guard.ts
Normal file
@@ -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<Context>();
|
||||
|
||||
const isAdmin = this.ADMIN_IDS.includes(from.id);
|
||||
if (!isAdmin) {
|
||||
throw new TelegrafException('You are not admin 😡');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -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`)));
|
||||
}
|
||||
}
|
@@ -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('');
|
||||
}
|
||||
}
|
9
sample/01-complete-app/src/echo/echo.module.ts
Normal file
9
sample/01-complete-app/src/echo/echo.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { EchoUpdate } from './echo.update';
|
||||
import { EchoService } from './echo.service';
|
||||
import { RandomNumberScene } from '../greeter/scenes/random-number.scene';
|
||||
|
||||
@Module({
|
||||
providers: [EchoUpdate, EchoService, RandomNumberScene],
|
||||
})
|
||||
export class EchoModule {}
|
8
sample/01-complete-app/src/echo/echo.service.ts
Normal file
8
sample/01-complete-app/src/echo/echo.service.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class EchoService {
|
||||
echo(text: string): string {
|
||||
return `Echo: ${text}`;
|
||||
}
|
||||
}
|
53
sample/01-complete-app/src/echo/echo.update.ts
Normal file
53
sample/01-complete-app/src/echo/echo.update.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { UseFilters, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||
import {
|
||||
Help,
|
||||
InjectBot,
|
||||
On,
|
||||
Message,
|
||||
Start,
|
||||
Update,
|
||||
Command,
|
||||
} from 'nestjs-telegraf';
|
||||
import { Telegraf } from 'telegraf';
|
||||
import { EchoService } from './echo.service';
|
||||
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)
|
||||
private readonly bot: Telegraf<Context>,
|
||||
private readonly echoService: EchoService,
|
||||
) {}
|
||||
|
||||
@Start()
|
||||
async onStart(): Promise<string> {
|
||||
const me = await this.bot.telegram.getMe();
|
||||
return `Hey, I'm ${me.first_name}`;
|
||||
}
|
||||
|
||||
@Help()
|
||||
async onHelp(): Promise<string> {
|
||||
return 'Send me any text';
|
||||
}
|
||||
|
||||
@Command('admin')
|
||||
@UseGuards(AdminGuard)
|
||||
onAdminCommand(): string {
|
||||
return 'Welcome judge';
|
||||
}
|
||||
|
||||
@On('text')
|
||||
onMessage(
|
||||
@Message('text', new ReverseTextPipe()) reversedText: string,
|
||||
): string {
|
||||
return this.echoService.echo(reversedText);
|
||||
}
|
||||
}
|
8
sample/01-complete-app/src/greeter/greeter.module.ts
Normal file
8
sample/01-complete-app/src/greeter/greeter.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { GreeterUpdate } from './greeter.update';
|
||||
import { RandomNumberScene } from './scenes/random-number.scene';
|
||||
|
||||
@Module({
|
||||
providers: [GreeterUpdate, RandomNumberScene],
|
||||
})
|
||||
export class GreeterModule {}
|
26
sample/01-complete-app/src/greeter/greeter.update.ts
Normal file
26
sample/01-complete-app/src/greeter/greeter.update.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
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()
|
||||
onStart(): string {
|
||||
return 'Say hello to me';
|
||||
}
|
||||
|
||||
@Hears(['hi', 'hello', 'hey', 'qq'])
|
||||
onGreetings(
|
||||
@UpdateType() updateType: TelegrafUpdateType,
|
||||
@Sender('first_name') firstName: string,
|
||||
): string {
|
||||
return `Hey ${firstName}`;
|
||||
}
|
||||
|
||||
@Command('scene')
|
||||
async onSceneCommand(@Ctx() ctx: Context): Promise<void> {
|
||||
await ctx.scene.enter(HELLO_SCENE_ID);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
import { Scene, SceneEnter, SceneLeave, Command } from 'nestjs-telegraf';
|
||||
import { HELLO_SCENE_ID } from '../../app.constants';
|
||||
import { Context } from '../../interfaces/context.interface';
|
||||
|
||||
@Scene(HELLO_SCENE_ID)
|
||||
export class RandomNumberScene {
|
||||
@SceneEnter()
|
||||
onSceneEnter(): string {
|
||||
console.log('Enter to scene');
|
||||
return 'Welcome on scene ✋';
|
||||
}
|
||||
|
||||
@SceneLeave()
|
||||
onSceneLeave(): string {
|
||||
console.log('Leave from scene');
|
||||
return 'Bye Bye 👋';
|
||||
}
|
||||
|
||||
@Command(['rng', 'random'])
|
||||
onRandomCommand(): number {
|
||||
console.log('Use "random" command');
|
||||
return Math.floor(Math.random() * 11);
|
||||
}
|
||||
|
||||
@Command('leave')
|
||||
async onLeaveCommand(ctx: Context): Promise<void> {
|
||||
await ctx.scene.leave();
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
import { Scenes } from 'telegraf';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface Context extends Scenes.SceneContext {}
|
8
sample/01-complete-app/src/main.ts
Normal file
8
sample/01-complete-app/src/main.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import 'dotenv/config';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
await NestFactory.createApplicationContext(AppModule);
|
||||
}
|
||||
bootstrap();
|
@@ -0,0 +1,3 @@
|
||||
import { session } from 'telegraf';
|
||||
|
||||
export const sessionMiddleware = session();
|
Reference in New Issue
Block a user