From cba19b5fe0b32a81f243719be181f887c290aa85 Mon Sep 17 00:00:00 2001 From: dnslin Date: Fri, 12 Dec 2025 10:31:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(telegram):=20=E6=B7=BB=E5=8A=A0=20/menu=20?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E5=8F=8A=E5=BF=AB=E6=8D=B7=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=20Reply=20Keyboard=20=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/telegram/app.py | 1 + src/telegram/handlers.py | 51 +++++++++++++++++++++++++++++++++++++++ src/telegram/keyboards.py | 13 +++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/telegram/app.py b/src/telegram/app.py index e7461fe..b51b7d7 100644 --- a/src/telegram/app.py +++ b/src/telegram/app.py @@ -28,6 +28,7 @@ BOT_COMMANDS = [ BotCommand("clear_logs", "清空日志"), BotCommand("set_secret", "设置自定义 RPC 密钥"), BotCommand("reset_secret", "重新生成随机 RPC 密钥"), + BotCommand("menu", "显示快捷菜单"), BotCommand("help", "显示帮助"), ] diff --git a/src/telegram/handlers.py b/src/telegram/handlers.py index 2317c2f..623f173 100644 --- a/src/telegram/handlers.py +++ b/src/telegram/handlers.py @@ -29,8 +29,21 @@ from src.telegram.keyboards import ( build_delete_confirm_keyboard, build_detail_keyboard, build_after_add_keyboard, + build_main_reply_keyboard, ) +# Reply Keyboard 按钮文本到命令的映射 +BUTTON_COMMANDS = { + "📥 下载列表": "list", + "📊 统计": "stats", + "▶️ 启动": "start", + "⏹ 停止": "stop", + "🔄 重启": "restart", + "📋 状态": "status", + "📜 日志": "logs", + "❓ 帮助": "help", +} + logger = get_logger("handlers") @@ -325,10 +338,42 @@ class Aria2BotAPI: "/list - 查看下载列表", "/stats - 全局下载统计", "", + "/menu - 显示快捷菜单", "/help - 显示此帮助", ] await self._reply(update, context, "可用命令:\n" + "\n".join(commands), parse_mode="Markdown") + async def menu_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: + """处理 /menu 命令,显示 Reply Keyboard 主菜单""" + logger.info(f"收到 /menu 命令 - {_get_user_info(update)}") + keyboard = build_main_reply_keyboard() + await self._reply( + update, context, + "📋 *快捷菜单*\n\n使用下方按钮快速操作,或输入命令:\n/add - 添加下载任务", + parse_mode="Markdown", + reply_markup=keyboard + ) + + async def handle_button_text(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: + """处理 Reply Keyboard 按钮点击""" + text = update.message.text + if text not in BUTTON_COMMANDS: + return + + cmd = BUTTON_COMMANDS[text] + handler_map = { + "list": self.list_downloads, + "stats": self.global_stats, + "start": self.start_service, + "stop": self.stop_service, + "restart": self.restart_service, + "status": self.status, + "logs": self.view_logs, + "help": self.help_command, + } + if cmd in handler_map: + await handler_map[cmd](update, context) + # === 下载管理命令 === async def add_download(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: @@ -670,6 +715,9 @@ class Aria2BotAPI: def build_handlers(api: Aria2BotAPI) -> list: """构建 Handler 列表""" + # 构建按钮文本过滤器 + button_pattern = "^(" + "|".join(BUTTON_COMMANDS.keys()).replace("▶️", "▶️").replace("⏹", "⏹") + ")$" + return [ # 服务管理命令 CommandHandler("install", api.install), @@ -683,10 +731,13 @@ def build_handlers(api: Aria2BotAPI) -> list: CommandHandler("set_secret", api.set_secret), CommandHandler("reset_secret", api.reset_secret), CommandHandler("help", api.help_command), + CommandHandler("menu", api.menu_command), # 下载管理命令 CommandHandler("add", api.add_download), CommandHandler("list", api.list_downloads), CommandHandler("stats", api.global_stats), + # Reply Keyboard 按钮文本处理 + MessageHandler(filters.TEXT & filters.Regex(button_pattern), api.handle_button_text), # 种子文件处理 MessageHandler(filters.Document.FileExtension("torrent"), api.handle_torrent), # Callback Query 处理 diff --git a/src/telegram/keyboards.py b/src/telegram/keyboards.py index 54dd05d..9d81192 100644 --- a/src/telegram/keyboards.py +++ b/src/telegram/keyboards.py @@ -1,7 +1,7 @@ """Telegram 键盘构建工具""" from __future__ import annotations -from telegram import InlineKeyboardButton, InlineKeyboardMarkup +from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardMarkup, KeyboardButton # 状态 emoji 映射 STATUS_EMOJI = { @@ -104,3 +104,14 @@ def build_after_add_keyboard(gid: str) -> InlineKeyboardMarkup: InlineKeyboardButton("📥 查看列表", callback_data="list:menu"), ], ]) + + +def build_main_reply_keyboard() -> ReplyKeyboardMarkup: + """构建主菜单 Reply Keyboard""" + keyboard = [ + [KeyboardButton("📥 下载列表"), KeyboardButton("📊 统计")], + [KeyboardButton("▶️ 启动"), KeyboardButton("⏹ 停止")], + [KeyboardButton("🔄 重启"), KeyboardButton("📋 状态")], + [KeyboardButton("📜 日志"), KeyboardButton("❓ 帮助")], + ] + return ReplyKeyboardMarkup(keyboard, resize_keyboard=True, is_persistent=True)