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

多人使用Telegram Bot触发400空消息文本错误的问题求助

问题根因

多用户场景崩溃+400 Bad Request: message text is empty报错由四个代码逻辑缺陷直接导致:

  • 协议文本文件句柄全局初始化后未重置:全局作用域打开的txt文件对象,第一次被/start指令调用txt.read()后,文件指针会移动到内容末尾,后续所有用户触发/start时读取到的都是空字符串,向Telegram API发送空文本就会触发400错误。
  • 未做非文本消息拦截:如果用户在交互过程中发送贴纸、图片、语音等非文本内容,message.text会返回None,直接用这个值作为消息内容发送就会触发空消息错误。
  • 注册流程存在并发安全问题:手动循环查找表格空行生成userId的逻辑在多用户同时提交时会生成重复ID,嵌套的下一步回调未做用户隔离,高并发下会出现消息路由错乱。
  • TeleBot默认未开启多线程模式,串行处理消息时容易出现请求阻塞、回调覆盖问题。
修复步骤

1. 修复协议文本读取逻辑

删除全局打开文件的写法,程序启动时一次性把协议内容读取到内存字符串中,避免文件指针偏移问题:

# 替换原全局txt = open(...)的写法
with open("C:/Users/nmash/Desktop/Cloud/terms_of_the_agreement.txt", encoding="utf-8") as f:
    terms_text = f.read()

后续/start逻辑中直接传入terms_text发送即可,不需要重复调用read()。

2. 初始化Bot时开启多线程支持

修改TeleBot初始化参数,支持多用户并发处理:

self.bot = telebot.TeleBot(token, threaded=True)

3. 增加非文本消息拦截

在所有文本处理逻辑前增加message.text非空判断,非文本内容直接提示用户发送文字,避免空值传入发送接口:

@self.bot.message_handler(content_types=['text', 'sticker', 'photo', 'voice', 'document'])
def message_worker(message):
    if not message.text:
        self.bot.send_message(message.from_user.id, "Пожалуйста, отправляйте текстовые сообщения для работы с ботом")
        return
    # 后续保留原/start、同意协议的判断逻辑即可

4. 修复注册流程的并发问题

删除手动循环查找表格空行的逻辑,gspread自带的append_row方法会自动定位到最后一个空行写入,同时从写入返回结果中解析实际行号作为userId,避免并发下ID重复;在接收姓名输入的回调中也增加非空判断,输入不符合要求时重新注册下一步回调要求用户重输:

def registration(self, message):        
    def ask_name(message):
        sent = self.bot.send_message(message.from_user.id, 'Введите своё имя:')
        self.bot.register_next_step_handler(sent, save_name)

    def save_name(message):
        if not message.text:
            self.bot.send_message(message.from_user.id, "Имя должно быть текстом, попробуйте снова:")
            self.bot.register_next_step_handler(message, save_name)
            return
        name = message.text.strip()
        worksheet = sh.sheet1 
        append_res = worksheet.append_row([name])
        # 解析写入结果中的行号作为用户ID
        user_id = int(append_res['updates']['updatedRange'].split('A')[-1].split(':')[0])
        self.bot.send_message(message.from_user.id,  f"Ваше имя: {name}\nВаше ID: {user_id}")

    ask_name(message)
修复后完整代码
import telebot
from telebot import types
import gspread
from registration_sheet import gs, sh
from button import button1, button2, mm


token = 'token'
with open("C:/Users/nmash/Desktop/Cloud/terms_of_the_agreement.txt", encoding="utf-8") as f:
    terms_text = f.read()

class Telegrambot():

    def __init__(self, token):
        super(Telegrambot, self).__init__()
        self.bot = telebot.TeleBot(token, threaded=True)
        self.message_handler()
        self.start()

    def start(self):
        self.bot.polling(none_stop=True, interval=1)
    
    def message_handler(self):
        @self.bot.message_handler(content_types=['text', 'sticker', 'photo', 'voice', 'document'])
        def message_worker(message):            
            if not message.text:
                self.bot.send_message(message.from_user.id, "Пожалуйста, отправляйте текстовые сообщения для работы с ботом")
                return

            if message.text == '/start':
                button1()
                self.bot.send_message(message.from_user.id, terms_text, reply_markup=mm)            
            
            if message.text == "Принять условия соглашения✅":
                self.bot.send_message(message.from_user.id, "Вы приняли условия соглашения✅", reply_markup=types.ReplyKeyboardRemove())
                self.registration(message)

    def registration(self, message):        
        def ask_name(message):
            sent = self.bot.send_message(message.from_user.id, 'Введите своё имя:')
            self.bot.register_next_step_handler(sent, save_name)

        def save_name(message):
            if not message.text:
                self.bot.send_message(message.from_user.id, "Имя должно быть текстом, попробуйте снова:")
                self.bot.register_next_step_handler(message, save_name)
                return
            name = message.text.strip()
            worksheet = sh.sheet1 
            append_res = worksheet.append_row([name])
            user_id = int(append_res['updates']['updatedRange'].split('A')[-1].split(':')[0])
            self.bot.send_message(message.from_user.id,  f"Ваше имя: {name}\nВаше ID: {user_id}")

        ask_name(message)    

Telegrambot(token=token)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:51:31