Telegram机器人发送图片后无响应问题求助
问题描述
使用Telegram机器人时出现以下异常:
- 单独发送
/photo命令:机器人正常响应,Docker日志生成正常 - 发送
/photo命令+图片/文件:机器人无任何响应,Docker中无相关日志
相关代码如下:
主命令代码
from telegram import Update from telegram.ext import CallbackContext from . import BaseCommand, command_with_logs, CommandManager class UploadPhotoCommand(BaseCommand): name = "photo" description = "send photo" def __init__(self, manager: CommandManager) -> None: self.__manager = manager @command_with_logs async def callback(self, update, context): try: photos = await update.message.photo await update.message.reply_text(f'Zdjęcia: {photos}') except Exception as e: await update.message.reply_text(f'Error: {e}')
补充代码
装饰器与基类
from abc import ABC, abstractmethod from dataclasses import dataclass from telegram import Update from telegram.ext import CommandHandler, CallbackContext from logs import logger def command_with_logs(func): async def wrapper(self, update: Update, context: CallbackContext): logger.info(f'User {update.message.from_user.id} use command /{self.name}') await func(self, update, context) return wrapper class BaseCommand(ABC): name: str description: str = None def get_handler(self) -> CommandHandler: return CommandHandler(self.name, self.callback) @abstractmethod async def callback(self, update: Update, context: CallbackContext): pass
命令管理器
from typing import List, Dict from telegram.ext import Application, CommandHandler from . import BaseCommand class CommandManager: def __init__(self, app: Application) -> None: self.handlers: Dict[str, CommandHandler] = dict() self.descriptions: Dict[str, str] = {} self.__app = app def setup(self, commands: List[BaseCommand]): for command in commands: self.handlers[command.name] = command.get_handler() self.descriptions[command.name] = command.description self.__app.add_handler(self.handlers[command.name]) def add_command(self, command: BaseCommand): handler = command.get_handler() self.handlers[command.name] = handler self.descriptions[command.name] = command.description self.__app.add_handler(handler) def remove_command(self, name: str): self.__app.remove_handler(self.handlers[name]) self.handlers.pop(name) self.descriptions.pop(name)
问题排查与修复
核心原因
- Handler类型不匹配:当前使用的
CommandHandler仅能处理纯文本命令消息。当命令与图片/文件一起发送时,Telegram会将消息标记为photo或document类型,而非command类型,导致CommandHandler无法捕获该消息,自然不会触发回调,也不会生成日志。 - 代码语法错误:
photos = await update.message.photo写法错误,update.message.photo是属性而非可等待对象,不需要添加await关键字。
修复步骤
1. 替换为MessageHandler处理带附件的命令
将CommandHandler替换为MessageHandler,配合过滤器捕获带图片/文件的命令消息。修改UploadPhotoCommand的get_handler方法:
from telegram.ext import MessageHandler, Filters class UploadPhotoCommand(BaseCommand): name = "photo" description = "send photo" def __init__(self, manager: CommandManager) -> None: self.__manager = manager def get_handler(self): # 捕获包含/photo命令且带有图片的消息 return MessageHandler(Filters.command([self.name]) & Filters.photo, self.callback) @command_with_logs async def callback(self, update, context): try: # 移除多余的await photos = update.message.photo # photo是按尺寸从小到大排列的列表,取最大的那张 if photos: largest_photo = photos[-1] await update.message.reply_text(f'收到图片,文件ID: {largest_photo.file_id}') else: await update.message.reply_text('未检测到图片') except Exception as e: await update.message.reply_text(f'Error: {str(e)}')
2. 支持多种文件类型(可选)
如果需要同时支持图片和文档,修改过滤器并扩展回调逻辑:
def get_handler(self): # 捕获包含/photo命令且带有图片或文档的消息 return MessageHandler(Filters.command([self.name]) & (Filters.photo | Filters.document), self.callback) @command_with_logs async def callback(self, update, context): try: if update.message.photo: photos = update.message.photo largest_photo = photos[-1] await update.message.reply_text(f'收到图片,文件ID: {largest_photo.file_id}') elif update.message.document: doc = update.message.document await update.message.reply_text(f'收到文档:{doc.file_name},文件ID: {doc.file_id}') else: await update.message.reply_text('未检测到支持的文件类型') except Exception as e: await update.message.reply_text(f'Error: {str(e)}')
3. 兼容纯文本命令(可选)
若需保留纯文本/photo命令的响应,可在回调中添加无附件情况的处理:
@command_with_logs async def callback(self, update, context): try: if update.message.photo: # 处理图片逻辑 ... elif update.message.document: # 处理文档逻辑 ... else: # 纯文本命令的提示响应 await update.message.reply_text('请在发送/photo命令时附上图片或文件') except Exception as e: await update.message.reply_text(f'Error: {str(e)}')
验证修复
修改后重新部署机器人,测试以下场景:
- 单独发送
/photo:机器人回复提示信息,日志正常生成 - 发送
/photo+图片:机器人回复图片ID,日志正常生成 - 发送
/photo+文档:机器人回复文档信息,日志正常生成
内容的提问来源于stack exchange,提问作者kacper1236
相关产品推荐
相关产品推荐

