NestJs+Telegraf:如何为Markup.keyboard配置处理器?是否可行?
NestJs + Telegraf 普通回复键盘(Markup.keyboard)的事件处理方案
首先明确:普通的Markup.keyboard(屏幕底部的回复键盘)不支持@Action装饰器。原因是两种键盘的交互逻辑完全不同:
- Inline键盘(Markup.inlineKeyboard)的按钮点击会向Bot发送回调数据,因此能用@Action监听回调事件;
- 普通回复键盘的按钮点击后,会直接向聊天窗口发送按钮上的文本内容,触发的是文本消息事件,而非回调事件。
正确实现步骤
- 修正键盘按钮类型:普通键盘必须使用
Markup.button.text()创建按钮,Markup.button.callback()是Inline键盘专属,在普通键盘中无法触发回调逻辑。 - 监听文本消息事件:可以用
@Hears()装饰器精准监听特定按钮文本,也可以用@On('text')统一处理所有文本消息并分支判断。
代码示例
方式一:用@Hears精准监听单个按钮
import { Start, Ctx, Hears } from 'nestjs-telegraf'; import { Context, Markup } from 'telegraf'; @Start() async start(@Ctx() ctx: Context) { await ctx.reply( 'test', Markup.keyboard([ [ Markup.button.text('🏆 Button1'), Markup.button.text('🏆 Button2'), Markup.button.text('🏆 Button3'), ], ]).resize(), // 可选:自动适配键盘尺寸 ); } @Hears('🏆 Button1') async handleButton1(@Ctx() ctx: Context) { await ctx.reply('button1 clicked'); } @Hears('🏆 Button2') async handleButton2(@Ctx() ctx: Context) { await ctx.reply('button2 clicked'); }
方式二:用@On('text')统一处理多按钮
如果按钮数量较多,可在一个方法内分支判断文本内容:
import { Start, Ctx, On } from 'nestjs-telegraf'; import { Context, Markup } from 'telegraf'; @Start() async start(@Ctx() ctx: Context) { await ctx.reply( 'test', Markup.keyboard([ [ Markup.button.text('🏆 Button1'), Markup.button.text('🏆 Button2'), Markup.button.text('🏆 Button3'), ], ]), ); } @On('text') async handleTextMessages(@Ctx() ctx: Context) { const messageText = (ctx.message as any).text; switch(messageText) { case '🏆 Button1': await ctx.reply('button1 clicked'); break; case '🏆 Button2': await ctx.reply('button2 clicked'); break; case '🏆 Button3': await ctx.reply('button3 clicked'); break; default: // 处理非按钮触发的文本消息 await ctx.reply('未知命令'); } }
注意事项
- 普通键盘的按钮文本会被用户直接发送到聊天窗口,需确保文本唯一,避免和其他用户输入逻辑冲突;
- 若需要隐藏键盘,可使用
Markup.removeKeyboard()方法。
内容的提问来源于stack exchange,提问作者user31020060
相关产品推荐
相关产品推荐

