diff --git a/src/tg_bot.py b/src/tg_bot.py index f26fb61..be49fe0 100644 --- a/src/tg_bot.py +++ b/src/tg_bot.py @@ -42,11 +42,22 @@ def send_summary(tg_cfg: TelegramConfig, chat_id: str, summary_text: str, @retry() -def send_text(tg_cfg: TelegramConfig, chat_id: str, text: str): - _tg_req(tg_cfg, "sendMessage", { +def send_text(tg_cfg: TelegramConfig, chat_id: str, text: str) -> int: + result = _tg_req(tg_cfg, "sendMessage", { "chat_id": chat_id, "text": text, }) + return result["result"]["message_id"] + + +def delete_message(tg_cfg: TelegramConfig, chat_id: str, msg_id: int): + try: + _tg_req(tg_cfg, "deleteMessage", { + "chat_id": chat_id, + "message_id": msg_id, + }) + except Exception: + pass def poll_telegram(tg_cfg: TelegramConfig, cfg: Config, last_update_id: int) -> int: @@ -110,7 +121,6 @@ CALLBACK_VIEW_SUMM = "s" CALLBACK_REPLY = "r" CALLBACK_AI_REPLY = "a" CALLBACK_SELECT_REPLY = "sr" -CALLBACK_CONFIRM_REPLY = "cr" CALLBACK_CANCEL = "c" @@ -147,17 +157,6 @@ def _ai_reply_keyboard(msg_id: int, suggestions: list) -> dict: return {"inline_keyboard": kb} -def _confirm_keyboard(msg_id: int, idx: int) -> dict: - return { - "inline_keyboard": [ - [ - {"text": "确认发送", "callback_data": f"{CALLBACK_CONFIRM_REPLY}|{msg_id}|{idx}"}, - {"text": "取消", "callback_data": CALLBACK_CANCEL}, - ], - ] - } - - # ── Telegram API ──────────────────────────────────────── def _tg_req(tg_cfg: TelegramConfig, method: str, payload: dict) -> dict: @@ -213,8 +212,11 @@ def _handle_callback(tg_cfg: TelegramConfig, cfg: Config, cb: dict): }) elif action == CALLBACK_REPLY and ctx: - _conversations[chat_id] = {"state": "awaiting_reply", "msg_id": msg_id} - send_text(tg_cfg, str(chat_id), "请输入你的回复内容:") + prompt_msg_id = send_text(tg_cfg, str(chat_id), "请输入你的回复内容(或发送 \"取消\" 取消):") + _conversations[chat_id] = { + "state": "awaiting_reply", "msg_id": msg_id, + "prompt_msg_id": prompt_msg_id, + } elif action == CALLBACK_AI_REPLY and ctx: suggestions = ctx["summary_data"].get("reply_suggestions", []) @@ -230,8 +232,7 @@ def _handle_callback(tg_cfg: TelegramConfig, cfg: Config, cb: dict): text = "*AI 建议回复,请选择:*\n\n" for i, s in enumerate(suggestions, 1): - tag = "✅ 无需确认" if s.get("is_simple") else "📝 需确认后发送" - text += f"{i}\\. {_escape(s['text'])}\n *{tag}*\n" + text += f"{i}\\. {_escape(s['text'])}\n" _tg_req(tg_cfg, "editMessageText", { "chat_id": chat_id, "message_id": msg_id, "text": text, "parse_mode": "MarkdownV2", @@ -247,31 +248,15 @@ def _handle_callback(tg_cfg: TelegramConfig, cfg: Config, cb: dict): if idx >= len(suggestions): return sel = suggestions[idx] - - if sel.get("is_simple"): - _do_send_reply(tg_cfg, cfg, chat_id, msg_id, ctx, sel["text"]) - send_text(tg_cfg, str(chat_id), f"✅ 已发送: {sel['text']}") - _conversations.pop(chat_id, None) - else: - _conversations[chat_id]["selected_idx"] = idx - _tg_req(tg_cfg, "editMessageText", { - "chat_id": chat_id, "message_id": msg_id, - "text": f"确认发送此回复?\n\n{_escape(sel['text'])}", - "parse_mode": "MarkdownV2", - "reply_markup": _confirm_keyboard(msg_id, idx), - }) - - elif action == CALLBACK_CONFIRM_REPLY and ctx: - idx = int(parts[2]) - conv = _conversations.get(chat_id) - if not conv or conv.get("msg_id") != msg_id: - return - suggestions = conv.get("ai_suggestions", []) - if idx >= len(suggestions): - return - _do_send_reply(tg_cfg, cfg, chat_id, msg_id, ctx, suggestions[idx]["text"]) - send_text(tg_cfg, str(chat_id), "✅ 回复已发送!") + _do_send_reply(tg_cfg, cfg, chat_id, msg_id, ctx, sel["text"]) + send_text(tg_cfg, str(chat_id), f"✅ 已发送: {sel['text']}") _conversations.pop(chat_id, None) + can_reply = ctx.get("can_reply", True) + _tg_req(tg_cfg, "editMessageText", { + "chat_id": chat_id, "message_id": msg_id, + "text": ctx["summary_text"], "parse_mode": "MarkdownV2", + "reply_markup": _summary_keyboard(can_reply), + }) elif action == CALLBACK_CANCEL: _conversations.pop(chat_id, None) @@ -292,13 +277,26 @@ def _handle_message(tg_cfg: TelegramConfig, cfg: Config, msg: dict): if not conv or conv.get("state") != "awaiting_reply": return - ctx = _email_contexts.get(conv["msg_id"]) - if not ctx: + prompt_msg_id = conv.get("prompt_msg_id") + chat_id_str = str(chat_id) + + if text in ("取消", "/cancel"): + if prompt_msg_id: + delete_message(tg_cfg, chat_id_str, prompt_msg_id) _conversations.pop(chat_id, None) return + ctx = _email_contexts.get(conv["msg_id"]) + if not ctx: + _conversations.pop(chat_id, None) + if prompt_msg_id: + delete_message(tg_cfg, chat_id_str, prompt_msg_id) + return + + if prompt_msg_id: + delete_message(tg_cfg, chat_id_str, prompt_msg_id) _do_send_reply(tg_cfg, cfg, chat_id, conv["msg_id"], ctx, text) - send_text(tg_cfg, str(chat_id), "✅ 回复已发送!") + send_text(tg_cfg, chat_id_str, "✅ 回复已发送!") _conversations.pop(chat_id, None)