本地运行python-telegram-bot(v20.5)无报错但Bot无法启动求助
Telegram聊天摘要Bot无响应问题排查与修复
以下是你的代码中导致Bot无响应的核心问题及修复方案:
问题1:新旧API混合使用
python-telegram-bot v20.x采用全异步架构,不再兼容旧版Updater类。你代码中创建的Updater和update_queue完全多余,且会干扰Application的正常运行,直接删除即可。
问题2:处理器函数未遵循异步规范
v20.x要求所有命令/消息处理器必须是异步函数(带async关键字),同步函数会阻塞事件循环,导致Bot无法响应。同时,Bot的所有方法(如get_chats、send_message)都是异步的,调用时必须加await。
问题3:无效的get_chat_history方法
Telegram官方Bot API没有提供获取聊天历史的接口,原代码中bot.get_chat_history是不存在的方法,这是导致功能失效的核心原因。如果需要获取聊天消息,只能收集Bot启动后接收到的新消息;若需获取历史消息,需使用Telegram客户端API(如pyrogram),但客户端API需要用户登录会话,不适合Bot场景。
问题4:变量作用域错误
enter_date函数中引用的chat_titles是choose_chat的局部变量,无法跨函数访问,会触发NameError。需将chat_titles存储到context.user_data中传递。
问题5:同步HTTP请求阻塞事件循环
get_summary中使用requests.post同步请求MeaningCloud API,会阻塞Bot的事件循环,导致无响应。需替换为异步HTTP库aiohttp。
修复后的完整代码
import asyncio import datetime import aiohttp from telegram import Update from telegram.ext import ( Application, CommandHandler, MessageHandler, filters, ConversationHandler, ContextTypes ) # Bot Token TOKEN = '你的Bot Token' MEANINGCLOUD_KEY = '你的MeaningCloud API Key' # 对话状态常量 CHAT, DATE = range(2) async def get_summary(chat_id, start_date, end_date): # 注意:Telegram Bot API无法获取历史消息,此处用模拟数据演示 # 实际场景中,需改为收集Bot启动后收到的消息 mock_messages = [ "今天下午要开项目会,讨论新版本需求", "会议时间改到明天上午10点了", "需要准备好需求文档和原型图", "会后要同步给所有团队成员" ] text = '\n'.join(mock_messages) if not text: return '该日期范围内没有消息' # 异步请求MeaningCloud API async with aiohttp.ClientSession() as session: data = { 'key': MEANINGCLOUD_KEY, 'txt': text, 'sentences': 5 } try: async with session.post('https://api.meaningcloud.com/summarization-1.0', data=data) as response: if response.status == 200: result = await response.json() return result.get('summary', '生成摘要失败') else: return f'MeaningCloud API请求失败,状态码:{response.status}' except Exception as e: return f'请求API时出错:{str(e)}' async def choose_chat(update: Update, context: ContextTypes.DEFAULT_TYPE): # 获取用户对话列表(Bot只能获取自己参与的对话) chats = await context.bot.get_chats() chat_titles = [chat.title for chat in chats if chat.title] if not chat_titles: await update.message.reply_text('未找到可选择的对话') return ConversationHandler.END # 将对话标题存入用户数据,供后续验证使用 context.user_data['chat_titles'] = chat_titles await update.message.reply_text(f'请选择要摘要的对话:{", ".join(chat_titles)}') return CHAT async def enter_date(update: Update, context: ContextTypes.DEFAULT_TYPE): user_input = update.message.text.strip() chat_titles = context.user_data.get('chat_titles', []) if user_input not in chat_titles: await update.message.reply_text(f'无效的对话名称,请从以下选项选择:{", ".join(chat_titles)}') return CHAT # 通过对话标题获取chat_id chat = await context.bot.get_chat(user_input) context.user_data['chat_id'] = chat.id await update.message.reply_text('请输入日期范围,格式:YYYY-MM-DD - YYYY-MM-DD') return DATE async def summarize(update: Update, context: ContextTypes.DEFAULT_TYPE): date_range = update.message.text.strip() try: start_str, end_str = date_range.split('-') start_date = datetime.datetime.strptime(start_str.strip(), '%Y-%m-%d').date() end_date = datetime.datetime.strptime(end_str.strip(), '%Y-%m-%d').date() if start_date > end_date: await update.message.reply_text('开始日期不能晚于结束日期,请重新输入') return DATE summary = await get_summary( context.user_data['chat_id'], start_date, end_date ) await update.message.reply_text(summary) return ConversationHandler.END except ValueError as e: await update.message.reply_text(f'日期格式错误,请按照要求输入:{str(e)}') return DATE except Exception as e: await update.message.reply_text(f'处理时出错:{str(e)}') return DATE async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE): user_input = update.message.text.lower().strip() if user_input == 'cancel': await update.message.reply_text('对话已取消') return ConversationHandler.END elif user_input == 'restart': await update.message.reply_text('对话已重启') return await choose_chat(update, context) else: await update.message.reply_text('输入无效,可输入"cancel"取消或"restart"重启对话') return ConversationHandler.END def main(): # 创建Application实例 application = Application.builder().token(TOKEN).build() # 创建对话处理器 conv_handler = ConversationHandler( entry_points=[CommandHandler('summarize', choose_chat)], states={ CHAT: [MessageHandler(filters.TEXT & ~filters.COMMAND, enter_date)], DATE: [MessageHandler(filters.TEXT & ~filters.COMMAND, summarize)] }, fallbacks=[MessageHandler(filters.TEXT & ~filters.COMMAND, cancel)] ) application.add_handler(conv_handler) # 启动Bot application.run_polling() if __name__ == '__main__': main()
额外说明
- 关于聊天历史:由于Telegram Bot API限制,Bot无法获取启动前的历史消息。如果需要历史消息功能,建议使用
pyrogram或telethon等客户端库,但需要用户提供会话文件,不适合公开Bot使用。 - 异步规范:所有涉及IO操作的逻辑(Bot方法调用、HTTP请求)都必须用异步方式处理,避免阻塞事件循环。
内容的提问来源于stack exchange,提问作者maash mohamed
相关产品推荐
相关产品推荐

