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

python-telegram-bot内联按钮长时间延迟后无响应问题求助

长期交互式Telegram内联按钮失效问题排查与解决方案咨询

问题背景

我正在开发一个基于PySide6构建GUI的Python应用,通过python-telegram-bot v13.7与用户交互。应用的自动化工作流可能耗时数小时,因此搭建了Telegram状态消息系统:当流程阻塞或需要用户修改输入时,会通过内联键盘提供「修改输入」或「停止流程」的选项,要求这些按钮在用户8小时以上未交互后仍能正常响应。

当前症状

机器人发送的内联按钮数小时后无响应,具体表现为:

  • 用户点击"旧"按钮时,Telegram显示无限加载动画但无反应
  • 机器人的CallbackQueryHandler未触发(无回调日志)
  • 多数情况下python-telegram-bot的错误处理器未记录明确错误

已尝试的解决方案

为解决回调查询超时问题,实现了消息刷新机制:

  1. 追踪带按钮的消息
  2. 定时器每约45分钟运行一次
  3. 若消息超过阈值,执行:
    • 用bot.delete_message()删除旧消息
    • 用bot.send_message()发送含相同内容和新内联按钮的消息
    • 追踪新消息ID

该机制在1小时、2小时、7小时测试中有效,但长期运行仍频繁失效,尤其是在蜂窝网络环境、PC短暂休眠(虽已配置不休眠)场景下。

运行环境

  • Python 3.11.6
  • python-telegram-bot v13.7
  • Windows 10 Pro
  • 采用轮询模式(updater.start_polling())

咨询问题

  1. PTB v13.7中处理长期交互式按钮的更可靠方式?
  2. 是否忽略了回调查询生命周期或轮询持久性的核心知识点?
  3. 网络中断或短暂休眠是否会导致轮询无法自动恢复,进而错过回调?
  4. 除切换为文本回复或ConversationHandler外,确保按钮长期有效的最佳实践?

最小复现脚本

import os
import time
import logging
import threading
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, Bot
# Assumes pip install python-telegram-bot==13.7 (or your specific v13 version)
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, CallbackContext, MessageHandler, Filters
from dotenv import load_dotenv # Optional: pip install python-dotenv

# --- Configuration ---
load_dotenv() # Load .env file if it exists
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "YOUR_BOT_TOKEN") # <<< REPLACE or use .env file
TARGET_CHAT_ID = 123456789 # <<< REPLACE with your Telegram Chat ID (integer)

# --- Logging ---
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# --- State ---
last_callback_data = None
callback_received_event = threading.Event() # Used to signal if callback arrives during wait

# --- Handlers ---
def start(update: Update, context: CallbackContext) -> None:
    logger.info(f"Received /start from user {update.effective_user.id}")
    update.message.reply_text(f"Bot started. Use /sendmre to send the test message to chat ID {TARGET_CHAT_ID}.")

def send_mre_message_command(update: Update, context: CallbackContext) -> None:
    logger.info(f"Received /sendmre from user {update.effective_user.id}")
    if send_initial_mre_message(context.bot):
        update.message.reply_text("MRE test message sent.")
    else:
        update.message.reply_text("Failed to send MRE test message. Check logs and config.")

def send_initial_mre_message(bot_instance: Bot) -> bool:
    """Sends the message with buttons for the long wait test."""
    if not isinstance(TARGET_CHAT_ID, int) or TARGET_CHAT_ID == 123456789:
         logger.error("TARGET_CHAT_ID is not set correctly (must be an integer).")
         return False

    keyboard = [
        [InlineKeyboardButton("Option 1 (Long Wait)", callback_data='opt_1_long')],
        [InlineKeyboardButton("Option 2 (Long Wait)", callback_data='opt_2_long')],
        [InlineKeyboardButton("Cancel (Long Wait)", callback_data='cancel_long')],
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    try:
        logger.info(f"Sending MRE message to chat ID {TARGET_CHAT_ID}...")
        bot_instance.send_message(
            chat_id=TARGET_CHAT_ID,
            text='MRE Started: Try clicking a button on this message after 8+ hours:',
            reply_markup=reply_markup
        )
        logger.info(f"MRE message sent successfully to {TARGET_CHAT_ID}.")
        return True
    except Exception as e:
        logger.error(f"Failed to send MRE message to {TARGET_CHAT_ID}: {e}")
        return False

def button_callback(update: Update, context: CallbackContext) -> None:
    """Handles button clicks."""
    global last_callback_data
    query = update.callback_query
    logger.info(f"--- Button Callback Received (Data: {query.data}) ---")

    try:
        query.answer()
    except Exception as e:
        logger.warning(f"Could not answer callback query: {e}")

    last_callback_data = query.data
    logger.info(f"Stored callback data: {last_callback_data}")

    try:
        query.edit_message_text(text=f"✅ Selection received: {query.data}\n(Processed: {time.strftime('%H:%M:%S')})")
    except Exception as e:
        logger.warning(f"Could not edit message: {e}")

    callback_received_event.set()
    logger.info(f"--- Button Callback Finished ---")

def text_handler(update: Update, context: CallbackContext) -> None:
    logger.info(f"Ignoring text message from {update.effective_user.id}")

def error_handler(update: object, context: CallbackContext) -> None:
    logger.error(f'Update "{update}" caused error "{context.error}"', exc_info=context.error)

# --- Main ---
def main() -> None:
    if not BOT_TOKEN or BOT_TOKEN == "YOUR_BOT_TOKEN":
        print("ERROR: Telegram Bot Token not found.")
        print("Set the BOT_TOKEN variable or use a .env file.")
        return
    if not isinstance(TARGET_CHAT_ID, int) or TARGET_CHAT_ID == 123456789:
        print("ERROR: Please replace TARGET_CHAT_ID with your integer chat ID.")
        return

    # Ensure use_context=True for PTB v13.x
    updater = Updater(BOT_TOKEN, use_context=True)
    dispatcher = updater.dispatcher

    dispatcher.add_handler(CommandHandler("start", start))
    dispatcher.add_handler(CommandHandler("sendmre", send_mre_message_command))
    dispatcher.add_handler(CallbackQueryHandler(button_callback))
    dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, text_handler))
    dispatcher.add_handler(error_handler)

    logger.info("Starting bot polling...")
    updater.start_polling()
    logger.info("Bot polling started.")
    print("Bot started. Send /start to the bot, then /sendmre.")
    print(f"(Test message will be sent to Chat ID: {TARGET_CHAT_ID})")
    print(f"Wait 8+ hours after the message appears, then click a button.")
    print("Check console logs for callback details. Press Ctrl+C to stop.")

    updater.idle()
    logger.info("Bot stopping.")

if __name__ == '__main__':
    main()

内容的提问来源于stack exchange,提问作者Kingston

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:15:56