# Telegram Bot 按钮与键盘实现指南 > 完整的 Telegram Bot 交互式功能开发参考 --- ## 📋 目录 1. [按钮和键盘类型](#按钮和键盘类型) 2. [实现方式对比](#实现方式对比) 3. [核心代码示例](#核心代码示例) 4. [最佳实践](#最佳实践) --- ## 按钮和键盘类型 ### 1. Inline Keyboard(内联键盘) **特点**: - 显示在消息下方 - 点击后触发回调,不发送消息 - 支持回调数据、URL、切换查询等 **应用场景**:确认/取消、菜单导航、分页控制、设置选项 ### 2. Reply Keyboard(底部虚拟键盘) **特点**: - 显示在输入框上方 - 点击后发送文本消息 - 可设置持久化或一次性 **应用场景**:快捷命令、常用操作、表单输入、主菜单 ### 3. Bot Command Menu(命令菜单) **特点**: - 显示在输入框左侧 "/" 按钮 - 通过 BotFather 或 API 设置 - 提供命令列表和描述 **应用场景**:功能索引、新用户引导、快速命令访问 ### 4. 类型对比 | 特性 | Inline | Reply | Command Menu | |------|--------|-------|--------------| | 位置 | 消息下方 | 输入框上方 | "/" 菜单 | | 触发 | 回调查询 | 文本消息 | 命令 | | 持久化 | 随消息 | 可配置 | 始终存在 | | 场景 | 临时交互 | 常驻功能 | 命令索引 | --- ## 实现方式对比 ### python-telegram-bot(推荐 Bot 开发) **优点**: - 官方推荐,完整的 Handler 系统 - 丰富的按钮和键盘支持 - 异步版本性能优异 **安装**: ```bash pip install python-telegram-bot==20.7 ``` ### Telethon(适合用户账号自动化) **优点**: - 完整的 MTProto API 访问 - 可使用用户账号和 Bot - 强大的消息监听能力 **安装**: ```bash pip install telethon cryptg ``` --- ## 核心代码示例 ### 1. Inline Keyboard 实现 **python-telegram-bot:** ```python from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): """显示内联键盘""" keyboard = [ [ InlineKeyboardButton("📊 查看数据", callback_data="view_data"), InlineKeyboardButton("⚙️ 设置", callback_data="settings"), ], [ InlineKeyboardButton("🔗 访问网站", url="https://example.com"), ], ] reply_markup = InlineKeyboardMarkup(keyboard) await update.message.reply_text("请选择:", reply_markup=reply_markup) async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): """处理按钮点击""" query = update.callback_query await query.answer() # 必须调用 if query.data == "view_data": await query.edit_message_text("显示数据...") elif query.data == "settings": await query.edit_message_text("设置选项...") # 注册处理器 app = Application.builder().token("TOKEN").build() app.add_handler(CommandHandler("start", start)) app.add_handler(CallbackQueryHandler(button_callback)) app.run_polling() ``` **Telethon:** ```python from telethon import TelegramClient, events, Button client = TelegramClient('bot', api_id, api_hash).start(bot_token=BOT_TOKEN) @client.on(events.NewMessage(pattern='/start')) async def start(event): buttons = [ [Button.inline("📊 查看数据", b"view_data"), Button.inline("⚙️ 设置", b"settings")], [Button.url("🔗 访问网站", "https://example.com")] ] await event.respond("请选择:", buttons=buttons) @client.on(events.CallbackQuery) async def callback(event): if event.data == b"view_data": await event.edit("显示数据...") elif event.data == b"settings": await event.edit("设置选项...") client.run_until_disconnected() ``` ### 2. Reply Keyboard 实现 **python-telegram-bot:** ```python from telegram import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove async def menu(update: Update, context: ContextTypes.DEFAULT_TYPE): """显示底部键盘""" keyboard = [ [KeyboardButton("📊 查看数据"), KeyboardButton("⚙️ 设置")], [KeyboardButton("📚 帮助"), KeyboardButton("❌ 隐藏键盘")], ] reply_markup = ReplyKeyboardMarkup( keyboard, resize_keyboard=True, one_time_keyboard=False ) await update.message.reply_text("菜单已激活", reply_markup=reply_markup) async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE): """处理文本消息""" text = update.message.text if text == "📊 查看数据": await update.message.reply_text("显示数据...") elif text == "❌ 隐藏键盘": await update.message.reply_text("已隐藏", reply_markup=ReplyKeyboardRemove()) ``` **Telethon:** ```python @client.on(events.NewMessage(pattern='/menu')) async def menu(event): buttons = [ [Button.text("📊 查看数据"), Button.text("⚙️ 设置")], [Button.text("📚 帮助"), Button.text("❌ 隐藏键盘")] ] await event.respond("菜单已激活", buttons=buttons) @client.on(events.NewMessage) async def handle_text(event): if event.text == "📊 查看数据": await event.respond("显示数据...") ``` ### 3. Bot Command Menu 设置 **通过 BotFather:** ``` 1. 发送 /setcommands 到 @BotFather 2. 选择你的 Bot 3. 输入命令列表(每行格式:command - description) start - 启动机器人 help - 获取帮助 menu - 显示主菜单 settings - 配置设置 ``` **通过 API(python-telegram-bot):** ```python from telegram import BotCommand async def set_commands(app: Application): """设置命令菜单""" commands = [ BotCommand("start", "启动机器人"), BotCommand("help", "获取帮助"), BotCommand("menu", "显示主菜单"), BotCommand("settings", "配置设置"), ] await app.bot.set_my_commands(commands) # 在启动时调用 app.post_init = set_commands ``` ### 4. 项目结构示例 ``` telegram_bot/ ├── bot.py # 主程序 ├── config.py # 配置管理 ├── requirements.txt ├── .env ├── handlers/ │ ├── command_handlers.py # 命令处理器 │ ├── callback_handlers.py # 回调处理器 │ └── message_handlers.py # 消息处理器 ├── keyboards/ │ ├── inline_keyboards.py # 内联键盘布局 │ └── reply_keyboards.py # 回复键盘布局 └── utils/ ├── logger.py # 日志 └── database.py # 数据库 ``` **模块化示例(keyboards/inline_keyboards.py):** ```python from telegram import InlineKeyboardButton, InlineKeyboardMarkup def get_main_menu(): """主菜单键盘""" return InlineKeyboardMarkup([ [ InlineKeyboardButton("📊 数据", callback_data="data"), InlineKeyboardButton("⚙️ 设置", callback_data="settings"), ], [InlineKeyboardButton("📚 帮助", callback_data="help")], ]) def get_data_menu(): """数据菜单键盘""" return InlineKeyboardMarkup([ [ InlineKeyboardButton("📈 实时", callback_data="data_realtime"), InlineKeyboardButton("📊 历史", callback_data="data_history"), ], [InlineKeyboardButton("⬅️ 返回", callback_data="back")], ]) ``` --- ## 最佳实践 ### 1. Handler 优先级 ```python # 先注册先匹配,按从特殊到通用的顺序 app.add_handler(CommandHandler("start", start)) # 1. 特定命令 app.add_handler(CallbackQueryHandler(callback)) # 2. 回调查询 app.add_handler(ConversationHandler(...)) # 3. 对话流程 app.add_handler(MessageHandler(filters.TEXT, text_msg)) # 4. 通用消息(最后) ``` ### 2. 错误处理 ```python async def error_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): """全局错误处理""" logger.error(f"更新 {update} 引起错误", exc_info=context.error) # 通知用户 if update and update.effective_message: await update.effective_message.reply_text("操作失败,请重试") app.add_error_handler(error_handler) ``` ### 3. 回调数据管理 ```python # 使用结构化的 callback_data callback_data = "action:page:item" # 例如 "view:1:product_123" # 解析回调数据 async def callback(update: Update, context: ContextTypes.DEFAULT_TYPE): query = update.callback_query parts = query.data.split(":") action, page, item = parts if action == "view": await show_item(query, page, item) ``` ### 4. 键盘设计原则 - **简洁**:每行最多 2-3 个按钮 - **清晰**:使用 emoji 增强识别度 - **一致**:保持统一的布局风格 - **响应**:及时反馈用户操作 ### 5. 安全考虑 ```python # 验证用户权限 ADMIN_IDS = [123456789] async def admin_only(update: Update, context: ContextTypes.DEFAULT_TYPE): user_id = update.effective_user.id if user_id not in ADMIN_IDS: await update.message.reply_text("无权限") return # 执行管理员操作 ``` ### 6. 部署方案 **Webhook(推荐生产环境):** ```python from flask import Flask, request app_flask = Flask(__name__) @app_flask.route('/webhook', methods=['POST']) def webhook(): update = Update.de_json(request.get_json(), bot) application.update_queue.put(update) return "OK" # 设置 webhook bot.set_webhook(f"https://yourdomain.com/webhook") ``` **Systemd Service(Linux):** ```ini [Unit] Description=Telegram Bot After=network.target [Service] Type=simple User=your_user WorkingDirectory=/path/to/bot ExecStart=/path/to/venv/bin/python bot.py Restart=always [Install] WantedBy=multi-user.target ``` ### 7. 常用库版本 ```txt # requirements.txt python-telegram-bot==20.7 python-dotenv==1.0.0 aiosqlite==0.19.0 httpx==0.25.2 ``` --- ## 快速参考 ### Inline Keyboard 按钮类型 ```python InlineKeyboardButton("文本", callback_data="data") # 回调按钮 InlineKeyboardButton("链接", url="https://...") # URL按钮 InlineKeyboardButton("切换", switch_inline_query="") # 内联查询 InlineKeyboardButton("登录", login_url=...) # 登录按钮 InlineKeyboardButton("支付", pay=True) # 支付按钮 InlineKeyboardButton("应用", web_app=WebAppInfo(...)) # Mini App ``` ### 常用事件类型 - `events.NewMessage` - 新消息 - `events.CallbackQuery` - 回调查询 - `events.InlineQuery` - 内联查询 - `events.ChatAction` - 群组动作 --- **这份指南涵盖了 Telegram Bot 按钮和键盘的所有核心实现!**