From bd51cf8dc4fd8141455b98f409ab4aff65397950 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Mar 2026 17:34:41 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Telegram=20?= =?UTF-8?q?=E7=BF=BB=E9=A1=B5=E6=9C=89=E6=97=B6=E5=A4=B1=E6=95=88=E7=9A=84?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=20Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - search.py: build_result() 不再猜测 message_id (+1),改为直接 使用 msg.message_id(真实回复消息 ID),解决缓存键不匹配导致 翻页静默失败的根本原因;缓存未命中时弹出提示而非静默返回 - torrent_search.py: 引入 KEYWORD_CACHE,callback_data 不再拼接 keyword 字符串,防止中文关键词超过 Telegram 64 字节限制导致 按钮点击无响应;RESULT_INDEXER 改为精准清理当前 cmid 条目, 不再全局 clear,避免并发搜索互相覆盖结果 - tmdb_search.py: 缓存键由 chat_id 改为 chat_id|message_id, RESULT_TMDB 同步更新键格式,解决同一 chat 多次搜索时 旧消息翻页失效及搜索结果互相覆盖的问题 https://claude.ai/code/session_01HNCfZLiNXHZcchtifn6b5T --- module/search/search.py | 12 +++++--- module/tmdb_search/tmdb_search.py | 24 ++++++++------- module/torrent_search/torrent_search.py | 39 ++++++++++++++++++------- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/module/search/search.py b/module/search/search.py index 5270343..41bbd07 100644 --- a/module/search/search.py +++ b/module/search/search.py @@ -164,13 +164,13 @@ async def s_command(update: Update, context: ContextTypes.DEFAULT_TYPE): if not results: return await msg.edit_text("未搜索到文件,换个关键词试试吧") - text, button = await build_result(results, update, k) + text, button = await build_result(results, msg, k) await msg.edit_text(text=text, reply_markup=InlineKeyboardMarkup(button), disable_web_page_preview=True) -async def build_result(content: list[PanSouResult], update: Update, keyword: str): - chat_id = update.effective_chat.id - message_id = update.message.id + 1 +async def build_result(content: list[PanSouResult], msg, keyword: str): + chat_id = msg.chat.id + message_id = msg.message_id cmid = f"{chat_id}|{message_id}" page = Page(content, keyword) @@ -195,6 +195,10 @@ async def search_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): page = PAGE.get(cmid) if not page: + try: + await query.answer("搜索结果已过期,请重新搜索", show_alert=True) + except Exception: + pass return if data == "search_next_page": diff --git a/module/tmdb_search/tmdb_search.py b/module/tmdb_search/tmdb_search.py index f369a55..f927ea7 100644 --- a/module/tmdb_search/tmdb_search.py +++ b/module/tmdb_search/tmdb_search.py @@ -117,13 +117,16 @@ async def sm_command(update: Update, context: ContextTypes.DEFAULT_TYPE): return chat_id = update.effective_chat.id - RESULT_TMDB.clear() + cmid = f"{chat_id}|{search_msg.message_id}" + keys_to_delete = [k for k in RESULT_TMDB if k.startswith(f"{cmid}_")] + for k in keys_to_delete: + del RESULT_TMDB[k] for i, r in enumerate(results): - RESULT_TMDB[f"{chat_id}_{i}"] = r - + RESULT_TMDB[f"{cmid}_{i}"] = r + page = TMDbPage(results, keyword) - PAGE[chat_id] = page - + PAGE[cmid] = page + text, buttons = page.now_page_text() await search_msg.edit_text(text=text, reply_markup=InlineKeyboardMarkup(buttons), parse_mode="Markdown") except Exception as e: @@ -143,15 +146,16 @@ async def tmdb_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): data = query.data msg = query.message chat_id = msg.chat.id - - page = PAGE.get(chat_id) + cmid = f"{chat_id}|{msg.message_id}" + + page = PAGE.get(cmid) if not page: try: await query.answer("会话已过期,请重新搜索", show_alert=True) except Exception: pass return - + if data == "tmdb_next": page.next_page() text, buttons = page.now_page_text() @@ -167,8 +171,8 @@ async def tmdb_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): index = int(data.split("_")[-1]) except ValueError: return - - result_key = f"{chat_id}_{index}" + + result_key = f"{cmid}_{index}" result = RESULT_TMDB.get(result_key) if not result: try: diff --git a/module/torrent_search/torrent_search.py b/module/torrent_search/torrent_search.py index 750c704..ed88881 100644 --- a/module/torrent_search/torrent_search.py +++ b/module/torrent_search/torrent_search.py @@ -19,6 +19,7 @@ PAGE: dict[str, "TorrentPage"] = {} RESULT_INDEXER: dict[str, ProwlarrResult] = {} INDEXERS: dict[int, str] = {} +KEYWORD_CACHE: dict[int, str] = {} # 下载信息缓存(用于路径/工具选择) DOWNLOAD_INFO: dict[int, dict] = {} @@ -221,25 +222,28 @@ async def sb_command(update: Update, context: ContextTypes.DEFAULT_TYPE): return await update.message.reply_text("请加上关键词,例:`/sb 电影名称`") await load_indexers() - + if not INDEXERS: return await update.message.reply_text("无法获取索引器列表,请检查 Prowlarr 配置") - + + # 将关键词存入缓存,callback_data 只携带 chat_id,避免超过 64 字节限制 + KEYWORD_CACHE[chat.id] = keyword + keyboard = [] row = [] for idx_id, idx_name in INDEXERS.items(): row.append(InlineKeyboardButton( idx_name[:12], - callback_data=f"sb_indexer_{idx_id}_{keyword}" + callback_data=f"sb_indexer_{idx_id}_{chat.id}" )) if len(row) == 2: keyboard.append(row) row = [] if row: keyboard.append(row) - - keyboard.append([InlineKeyboardButton("🔍 全部索引器", callback_data=f"sb_indexer_all_{keyword}")]) - + + keyboard.append([InlineKeyboardButton("🔍 全部索引器", callback_data=f"sb_indexer_all_{chat.id}")]) + await update.message.reply_text( f"🔍 选择要使用的索引器:\n关键词: {keyword}", reply_markup=InlineKeyboardMarkup(keyboard) @@ -271,7 +275,9 @@ async def search_with_indexer(update: Update, context: ContextTypes.DEFAULT_TYPE if not results: return await original_msg.edit_text("未搜索到结果") - RESULT_INDEXER.clear() + keys_to_delete = [k for k in RESULT_INDEXER if k.startswith(f"{cmid}_")] + for k in keys_to_delete: + del RESULT_INDEXER[k] for i, r in enumerate(results): RESULT_INDEXER[f"{cmid}_{i}"] = r @@ -297,10 +303,21 @@ async def torrent_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): parts = data.replace("sb_indexer_", "").split("_", 1) if len(parts) != 2: return - + indexer_part = parts[0] - keyword = parts[1] - + try: + source_chat_id = int(parts[1]) + except ValueError: + return + + keyword = KEYWORD_CACHE.get(source_chat_id, "") + if not keyword: + try: + await query.answer("会话已过期,请重新搜索", show_alert=True) + except Exception: + pass + return + if indexer_part == "all": indexer_id = -1 else: @@ -308,7 +325,7 @@ async def torrent_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): indexer_id = int(indexer_part) except ValueError: return - + await search_with_indexer(update, context, indexer_id, keyword, query.message.text) return