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
相关产品推荐
相关产品推荐

