在处理需要外部API请求的语音消息时,异步Telegram机器人会卡住。

人工智能 2026-07-07
import os
import tempfile

import requests
from dotenv import load_dotenv
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes, MessageHandler, filters

load_dotenv()

BOT_TOKEN = os.getenv("BOT_TOKEN")
BACKEND_URL = os.getenv("BACKEND_URL", "http://localhost:3000")
VOICE_TIMEOUT = int(os.getenv("VOICE_TIMEOUT", 600))


def profile(update: Update):
    user = update.effective_user
    return {
        "telegramId": str(user.id),
        "username": user.username or "",
        "firstName": user.first_name or "",
    }


def keyboard(buttons):
    return InlineKeyboardMarkup([
        [InlineKeyboardButton(button["text"], callback_data=button["data"]) for button in row]
        for row in buttons
    ])


async def send(update: Update, data):
    target = update.message or update.callback_query.message
    markup = keyboard(data.get("buttons", [])) if data.get("buttons") else None
    await target.reply_text(data.get("reply", ""), reply_markup=markup)
    if data.get("imagePath"):
        with open(data["imagePath"], "rb") as image:
            await target.reply_photo(image)


def post(path, data=None, files=None, timeout=120):
    kwargs = {"data": data, "files": files} if files else {"json": data}
    response = requests.post(f"{BACKEND_URL}{path}", **kwargs, timeout=timeout)
    response.raise_for_status()
    return response.json()


def command(msg):
    async def _handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
        await send(update, post("/chat", {**profile(update), "message": msg}))
    return _handler


async def text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    data = post("/chat", {**profile(update), "message": update.message.text})
    await send(update, data)


async def callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    data = post("/callback", {"telegramId": str(query.from_user.id), "callbackData": query.data})
    await send(update, data)


async def voice(update: Update, context: ContextTypes.DEFAULT_TYPE):
    voice_file = await update.message.voice.get_file()
    path = None

    try:
        await update.message.reply_text("Processing your voice note. First run can take a little time.")

        with tempfile.NamedTemporaryFile(suffix=".oga", delete=False) as temp:
            path = temp.name

        await voice_file.download_to_drive(path)

        with open(path, "rb") as audio:
            data = post("/voice", profile(update), {"audio": ("voice.oga", audio, "audio/ogg")}, timeout=VOICE_TIMEOUT)

        await send(update, data)
    except requests.exceptions.Timeout:
        await update.message.reply_text("Voice processing is taking too long. Try a shorter voice note once the model finishes loading.")
    except Exception as error:
        print("[BOT ERROR]", error)
        await update.message.reply_text("Could not process voice. Please try again.")
    finally:
        if path and os.path.exists(path):
            os.remove(path)


def main():
    app = Application.builder().token(BOT_TOKEN).build()
    app.add_handler(CommandHandler("start", command("/start")))
    app.add_handler(CommandHandler("menu", command("/menu")))
    app.add_handler(CallbackQueryHandler(callback))
    app.add_handler(MessageHandler(filters.VOICE, voice))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, text))
    print("[BOT] ArthSaathi bot is running...")
    app.run_polling()


if __name__ == "__main__":
    main()

我正在用Python搭建一个Telegram机器人,使用 python-telegram-bot(v20+)和异步处理程序。 机器人接收文本消息、回调查询和语音消息。 对于语音消息,它会下载 .oga 文件,发送到外部后端API进行语音处理,然后再用API的返回结果进行回复。

问题在于,当语音消息正在处理时,机器人对所有其他用户和消息都无响应。看起来像是在“冻结”,直到外部API调用完成为止。这段时间内文本消息和回调查询都不会被处理。

后端处理可能需要从30秒到几分钟不等,因为它需要加载一个AI模型并执行语音转文本和大语言模型推断。

解决方案

你的函数 post 不是异步的。请将其改为异步,使用诸如 aiohttp 这样的异步工具,替代 requests

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章