使用Python为Telegram bot开发两类内联菜单的技术咨询
Python Telegram Bot 内联菜单实现方案
前置依赖
使用python-telegram-bot v20.x异步版本,安装命令:
pip install python-telegram-bot==20.7
功能1:点击后移除对应按钮的实现逻辑
问题根因
你出现所有按钮同时删除的问题,是因为没有给每个按钮设置唯一标识的回调数据,触发回调后没有过滤保留未点击的按钮,直接清空了按钮列表。
实现步骤
- 给每个按钮的
callback_data设置统一前缀+唯一id,格式如remove:<按钮id> - 触发回调时,从当前消息的内联键盘中过滤掉
callback_data等于触发值的按钮 - 调用
edit_message_reply_markup方法更新消息的按钮列表即可
功能2:分页内联菜单的实现逻辑
核心思路
- 提前准备所有需要展示的条目列表,设置每页展示的条目数量
- 按钮的
callback_data设置为page:<目标页码> - 触发翻页回调时,根据目标页码从总条目列表中切片取出对应页的条目,生成按钮
- 边界处理:当前是第一页时隐藏「上一页」按钮,当前是最后一页时隐藏「下一页」按钮
最简可运行代码示例
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import ApplicationBuilder, CommandHandler, CallbackQueryHandler, ContextTypes # 替换为你自己的Bot Token BOT_TOKEN = "你的Bot Token" # ---------------------- 功能1:点击移除对应按钮 ---------------------- async def menu1(update: Update, context: ContextTypes.DEFAULT_TYPE): # 初始化3个按钮,每个按钮带唯一id的回调数据 keyboard = [ [InlineKeyboardButton("按钮1", callback_data="remove:1")], [InlineKeyboardButton("按钮2", callback_data="remove:2")], [InlineKeyboardButton("按钮3", callback_data="remove:3")], ] reply_markup = InlineKeyboardMarkup(keyboard) await update.message.reply_text("点击按钮移除对应项:", reply_markup=reply_markup) async def handle_remove(update: Update, context: ContextTypes.DEFAULT_TYPE): query = update.callback_query await query.answer() target_callback = query.data # 获取当前消息的原有按钮列表 current_keyboard = query.message.reply_markup.inline_keyboard # 过滤掉被点击的按钮 new_keyboard = [] for row in current_keyboard: new_row = [] for btn in row: if btn.callback_data != target_callback: new_row.append(btn) if new_row: new_keyboard.append(new_row) # 更新消息按钮 await query.edit_message_reply_markup(reply_markup=InlineKeyboardMarkup(new_keyboard)) # ---------------------- 功能2:分页菜单 ---------------------- # 模拟分页的总数据 ALL_ITEMS = [f"条目{i}" for i in range(1, 11)] # 每页展示3条 PER_PAGE = 3 async def menu2(update: Update, context: ContextTypes.DEFAULT_TYPE): # 默认展示第1页 page = 1 start = (page - 1) * PER_PAGE end = start + PER_PAGE current_items = ALL_ITEMS[start:end] # 生成当前页条目按钮 keyboard = [[InlineKeyboardButton(item, callback_data=f"item:{item}")] for item in current_items] # 生成翻页按钮 page_buttons = [] total_page = (len(ALL_ITEMS) + PER_PAGE - 1) // PER_PAGE if page > 1: page_buttons.append(InlineKeyboardButton("上一页", callback_data=f"page:{page-1}")) if page < total_page: page_buttons.append(InlineKeyboardButton("下一页", callback_data=f"page:{page+1}")) if page_buttons: keyboard.append(page_buttons) reply_markup = InlineKeyboardMarkup(keyboard) await update.message.reply_text(f"分页菜单(第{page}/{total_page}页):", reply_markup=reply_markup) async def handle_page(update: Update, context: ContextTypes.DEFAULT_TYPE): query = update.callback_query await query.answer() # 获取目标页码 page = int(query.data.split(":")[1]) start = (page - 1) * PER_PAGE end = start + PER_PAGE current_items = ALL_ITEMS[start:end] # 生成当前页条目按钮 keyboard = [[InlineKeyboardButton(item, callback_data=f"item:{item}")] for item in current_items] # 生成翻页按钮 page_buttons = [] total_page = (len(ALL_ITEMS) + PER_PAGE - 1) // PER_PAGE if page > 1: page_buttons.append(InlineKeyboardButton("上一页", callback_data=f"page:{page-1}")) if page < total_page: page_buttons.append(InlineKeyboardButton("下一页", callback_data=f"page:{page+1}")) if page_buttons: keyboard.append(page_buttons) # 更新消息内容和按钮 await query.edit_message_text( text=f"分页菜单(第{page}/{total_page}页):", reply_markup=InlineKeyboardMarkup(keyboard) ) # 处理普通条目点击 async def handle_item(update: Update, context: ContextTypes.DEFAULT_TYPE): query = update.callback_query await query.answer(f"你点击了{query.data.split(':')[1]}", show_alert=True) if __name__ == "__main__": application = ApplicationBuilder().token(BOT_TOKEN).build() # 注册命令 handler application.add_handler(CommandHandler("menu1", menu1)) application.add_handler(CommandHandler("menu2", menu2)) # 注册回调 handler application.add_handler(CallbackQueryHandler(handle_remove, pattern="^remove:")) application.add_handler(CallbackQueryHandler(handle_page, pattern="^page:")) application.add_handler(CallbackQueryHandler(handle_item, pattern="^item:")) # 运行bot application.run_polling()
使用说明
- 给Bot发送
/menu1可测试点击移除按钮功能 - 给Bot发送
/menu2可测试分页菜单功能
内容的提问来源于stack exchange,提问作者eZebda
相关产品推荐
相关产品推荐

