From d110e7f4b1126c03735b6d010a2aaf147cceb16c Mon Sep 17 00:00:00 2001 From: Dody Date: Thu, 4 Apr 2024 14:45:59 +0700 Subject: [PATCH] feat: seamless scene transition --- src/sale/sale.common.ts | 33 ++++++++++++++++++++++++++++ src/sale/sale.module.ts | 3 +-- src/sale/sale.update.ts | 2 +- src/sale/sale.wizard.ts | 39 --------------------------------- src/sale/scene/sale.scene.ts | 24 +++++--------------- src/sale/scene/welcome.scene.ts | 28 ++++++++++------------- 6 files changed, 53 insertions(+), 76 deletions(-) create mode 100644 src/sale/sale.common.ts delete mode 100644 src/sale/sale.wizard.ts diff --git a/src/sale/sale.common.ts b/src/sale/sale.common.ts new file mode 100644 index 0000000..8a68173 --- /dev/null +++ b/src/sale/sale.common.ts @@ -0,0 +1,33 @@ +import { Markup } from 'telegraf'; +import { InlineKeyboardButton } from 'telegraf/typings/core/types/typegram'; +import { ExtraEditMessageText } from 'telegraf/typings/telegram-types'; +import { SceneContext } from 'telegraf/scenes'; + +type Hideable = B & { hide?: boolean }; +type HideableIKBtn = Hideable; + +const extra = (keyboard: HideableIKBtn[][]): ExtraEditMessageText => { + return { + parse_mode: 'MarkdownV2', + link_preview_options: { + is_disabled: true, + }, + reply_markup: Markup.inlineKeyboard(keyboard).reply_markup, + }; +}; + +export const editMessage = async ( + ctx: SceneContext, + message: string, + keyboard: HideableIKBtn[][], +): Promise => { + await ctx.editMessageText(message, extra(keyboard)); +}; + +export const sendMessage = async ( + ctx: SceneContext, + message: string, + keyboard: HideableIKBtn[][], +): Promise => { + await ctx.reply(message, extra(keyboard)); +}; diff --git a/src/sale/sale.module.ts b/src/sale/sale.module.ts index 654a318..8073cfb 100644 --- a/src/sale/sale.module.ts +++ b/src/sale/sale.module.ts @@ -3,12 +3,11 @@ import { SaleUpdate } from './sale.update'; import { PrismaModule } from 'src/prisma/prisma.module'; import { ConfigModule } from '@nestjs/config'; import { SaleService } from './sale.service'; -import { SaleWizard } from './sale.wizard'; import { SaleScene } from './scene/sale.scene'; import { WelcomeScene } from './scene/welcome.scene'; @Module({ - providers: [SaleUpdate, SaleService, SaleWizard, SaleScene, WelcomeScene], + providers: [SaleUpdate, SaleService, SaleScene, WelcomeScene], imports: [ConfigModule, PrismaModule], }) export class SaleModule {} diff --git a/src/sale/sale.update.ts b/src/sale/sale.update.ts index d344011..a2eeaf5 100644 --- a/src/sale/sale.update.ts +++ b/src/sale/sale.update.ts @@ -10,6 +10,6 @@ export class SaleUpdate { @Hears(/.+/) async onFallback(): Promise { - return 'Wrong command or input, please restart by clicking /start.'; + return 'Wrong input, invalid command or something error.\n\nPlease restart by clicking /start.'; } } diff --git a/src/sale/sale.wizard.ts b/src/sale/sale.wizard.ts deleted file mode 100644 index c4ea10a..0000000 --- a/src/sale/sale.wizard.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Ctx, Message, On, Wizard, WizardStep } from 'nestjs-telegraf'; -import { WizardContext } from 'telegraf/scenes'; - -interface State { - name: string; -} - -@Wizard('SALE_WIZARD') -export class SaleWizard { - @WizardStep(1) - async onSceneEnter(@Ctx() ctx: WizardContext): Promise { - console.log('Enter to scene'); - await ctx.wizard.next(); - return 'Welcome to wizard scene ✋ Send me your name'; - } - - @On('text') - @WizardStep(2) - async onName( - @Ctx() ctx: WizardContext, - @Message() msg: { text: string }, - ): Promise { - console.log('Enter to step 1'); - (ctx.wizard.state as State).name = msg.text; - await ctx.wizard.next(); - return 'Send me where are you from'; - } - - @On('text') - @WizardStep(3) - async onLocation( - @Ctx() ctx: WizardContext, - @Message() msg: { text: string }, - ): Promise { - console.log('Enter to step 3'); - await ctx.scene.leave(); - return `Hello ${(ctx.wizard.state as State).name} from ${msg.text}. I'm Greater bot from 127.0.0.1 👋`; - } -} diff --git a/src/sale/scene/sale.scene.ts b/src/sale/scene/sale.scene.ts index 8394893..7a582e9 100644 --- a/src/sale/scene/sale.scene.ts +++ b/src/sale/scene/sale.scene.ts @@ -1,31 +1,19 @@ import { Scene, SceneEnter, Ctx, Action } from 'nestjs-telegraf'; import { SceneContext } from 'telegraf/scenes'; -import { Context, Markup } from 'telegraf'; +import { Markup } from 'telegraf'; import { SaleUpdate } from '../sale.update'; +import { editMessage } from '../sale.common'; @Scene('SALE_SCENE') export class SaleScene { constructor(private saleUpdate: SaleUpdate) {} @SceneEnter() - async onSceneEnter(@Ctx() ctx: Context): Promise { - const keyboard = Markup.inlineKeyboard([ - [ - Markup.button.callback('🔙 Back', 'back'), - // Markup.button.callback('👤 My Profile', 'profile'), - ], - // [ - // Markup.button.callback('❓ Tutorial', 'tutorial'), - // Markup.button.callback('🤖 About', 'about'), - // ], - ]); + async onSceneEnter(@Ctx() ctx: SceneContext): Promise { + const keyboard = [[Markup.button.callback('🔙 Back', 'back')]]; + const message = ' sale scene'; - await ctx.editMessageText('this is sale scene', { - link_preview_options: { - is_disabled: true, - }, - reply_markup: keyboard.reply_markup, - }); + await editMessage(ctx, message, keyboard); } @Action('back') diff --git a/src/sale/scene/welcome.scene.ts b/src/sale/scene/welcome.scene.ts index 44aa943..05017b3 100644 --- a/src/sale/scene/welcome.scene.ts +++ b/src/sale/scene/welcome.scene.ts @@ -1,24 +1,21 @@ import { Scene, SceneEnter, Ctx, Action, Sender } from 'nestjs-telegraf'; import { SceneContext } from 'telegraf/scenes'; -import { Context, Markup } from 'telegraf'; -import { SaleUpdate } from '../sale.update'; +import { Markup } from 'telegraf'; import { ConfigService } from '@nestjs/config'; import { RESET_DAY, SALE_DAY, TIMEZONE, TODAY } from '../sale.constant'; +import { editMessage, sendMessage } from '../sale.common'; @Scene('WELCOME_SCENE') export class WelcomeScene { - constructor( - private saleUpdate: SaleUpdate, - private configService: ConfigService, - ) {} + constructor(private configService: ConfigService) {} @SceneEnter() async onSceneEnter( - @Ctx() ctx: Context, + @Ctx() ctx: SceneContext, @Sender('first_name') firstName: string, @Sender('last_name') lastName: string, ): Promise { - const keyboard = Markup.inlineKeyboard([ + const keyboard = [ [ Markup.button.callback('💰 My Sale', 'sale'), Markup.button.callback('👤 My Profile', 'profile'), @@ -27,13 +24,13 @@ export class WelcomeScene { Markup.button.callback('❓ Tutorial', 'tutorial'), Markup.button.callback('🤖 About', 'about'), ], - ]); + ]; const user_joined = ['creator', 'administrator', 'member'].includes( ( await ctx.telegram.getChatMember( this.configService.get('TELEGRAM_GROUP_ID')!, - ctx.message?.from.id ?? 0, + ctx.from?.id ?? 0, ) ).status, ); @@ -55,12 +52,11 @@ export class WelcomeScene { message += `├ Joined : \`${user_joined ? 'Yes' : 'No'}\`\n`; message += `└ Link : [Click Here](${this.configService.get('TELEGRAM_GROUP_LINK')})`; - await ctx.replyWithMarkdownV2(message, { - link_preview_options: { - is_disabled: true, - }, - reply_markup: keyboard.reply_markup, - }); + if (ctx.callbackQuery) { + await editMessage(ctx, message, keyboard); + } else { + await sendMessage(ctx, message, keyboard); + } } @Action('sale')