You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 19:15:05