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

Telegram机器人发送带Inline键盘的图片返回400错误求助

Telegram Bot 发送带Inline键盘图片返回400错误的排查与解决

问题背景

实现了TgSender.tgSendImage静态方法发送图片,不带Inline键盘时请求正常,添加Inline键盘后Telegram API返回400错误。相关代码如下:

TgSender类实现

class TgSender:
    TOKEN = os.getenv('BOT_TOKEN')

    @staticmethod
    def tgSendImage(chat_id, photo_path, keyboard=None, caption=None):
        TELEGRAM_API_URL = f"https://api.telegram.org/bot{TgSender.TOKEN}/sendPhoto"
        try:
            with open(photo_path, 'rb') as photo:
                files = {'photo': photo}
                data = {'chat_id': chat_id, 'parse_mode': 'HTML'}
                if caption:
                    data['caption'] = caption
                if keyboard:
                    data['reply_markup'] = keyboard.to_dict()
                response = requests.post(TELEGRAM_API_URL, files=files, data=data)
            return response
        except Exception as e:
            print("Error:", e)
            return e

调用逻辑

async def SendImageMessage(chat_id, photo_path, keyboard=None, caption=None):
    reply_markup = None
    if keyboard:
        reply_markup = InlineKeyboardMarkup(keyboard)
    response = TgSender.tgSendImage(chat_id, photo_path, reply_markup, caption)
    print(response.status_code)
    return response

async def dash_buttons(request: Request):
    data = await request.json()
    chat_id = data["message"]["chat"]["id"]
    fname = data["message"]["chat"]["first_name"]
    keyboard = [
        [
            InlineKeyboardButton("🎲 Main Menu! 🃏", callback_data="main_menu"),
        ]
    ]
    photo_url = 'assets/img/9rwq9asd4rymrq9823hf.jpeg'
    message_text = "Welcome!"
    response = await SendImageMessage(chat_id, photo_url, keyboard, message_text)    
    print(response.status_code)

排查方向

  • 检查reply_markup序列化方式:发送multipart/form-data请求(带files参数)时,Telegram API要求reply_markup必须是JSON字符串,直接传入Python字典会导致格式错误。
  • 查看API返回的具体错误信息:打印response.text而非仅status_code,能获取详细错误描述(比如"Bad Request: reply_markup must be JSON-serialized object")。
  • 验证键盘结构合法性:确认InlineKeyboardMarkup和InlineKeyboardButton的构造符合Telegram规范,比如callback_data长度是否在64字节以内。
  • 检查requests参数处理逻辑:同时传入files和data时,requests会自动转为multipart/form-data,但字典类型的data值会被直接转成字符串,复杂结构无法被API正确解析。

解决方案

核心修复:将reply_markup序列化为JSON字符串

修改TgSender.tgSendImage方法中键盘处理逻辑,用json.dumps()把字典转为JSON字符串:

import json  # 需导入json模块

class TgSender:
    TOKEN = os.getenv('BOT_TOKEN')

    @staticmethod
    def tgSendImage(chat_id, photo_path, keyboard=None, caption=None):
        TELEGRAM_API_URL = f"https://api.telegram.org/bot{TgSender.TOKEN}/sendPhoto"
        try:
            with open(photo_path, 'rb') as photo:
                files = {'photo': photo}
                data = {'chat_id': chat_id, 'parse_mode': 'HTML'}
                if caption:
                    data['caption'] = caption
                if keyboard:
                    # 将字典转为JSON字符串
                    data['reply_markup'] = json.dumps(keyboard.to_dict())
                response = requests.post(TELEGRAM_API_URL, files=files, data=data)
            # 打印错误详情方便排查
            if response.status_code != 200:
                print("API Error Response:", response.text)
            return response
        except Exception as e:
            print("Error:", e)
            return e

额外优化:捕获API错误详情

在请求后添加状态码判断,打印response.text,快速定位问题根源。

验证键盘结构

确保callback_data符合Telegram要求:长度不超过64字节,无换行等特殊字符。当前代码中的"main_menu"是合法的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:23:15