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

本地运行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()

额外说明

  1. 关于聊天历史:由于Telegram Bot API限制,Bot无法获取启动前的历史消息。如果需要历史消息功能,建议使用pyrogram或telethon等客户端库,但需要用户提供会话文件,不适合公开Bot使用。
  2. 异步规范:所有涉及IO操作的逻辑(Bot方法调用、HTTP请求)都必须用异步方式处理,避免阻塞事件循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:19:52