fix(telegram): Photo_invalid_dimensions: Telegram 报错提示图片长宽比例或总尺寸不合规时,尝试以文件形式发送

This commit is contained in:
SXP-Simon
2026-03-16 00:43:41 +08:00
parent 4745fbccad
commit 451dbaa470
@@ -521,7 +521,8 @@ class TelegramAdapter(PlatformAdapter):
try:
chat_id, message_thread_id = self._parse_group_id(group_id)
photo_obj: Any = None
file_obj: Any = None
is_temp_obj = False
kwargs: dict[str, Any] = {"chat_id": chat_id}
if message_thread_id:
@@ -529,41 +530,62 @@ class TelegramAdapter(PlatformAdapter):
if caption:
kwargs["caption"] = caption
# 处理本地文件或 URL
if image_path.startswith(("http://", "https://")):
# 远程 URL - 需要下载后发送
# 1. 统一处理输入源 (Base64 / URL / Local File)
import base64
import os
from datetime import datetime
if image_path.startswith("base64://"):
data = base64.b64decode(image_path[len("base64://") :])
file_obj = BytesIO(data)
is_temp_obj = True
elif image_path.startswith("data:"):
parts = image_path.split(",", 1)
if len(parts) == 2:
data = base64.b64decode(parts[1])
file_obj = BytesIO(data)
is_temp_obj = True
elif image_path.startswith(("http://", "https://")):
try:
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get(
image_path, timeout=aiohttp.ClientTimeout(total=30)
) as resp:
async with session.get(image_path, timeout=aiohttp.ClientTimeout(total=30)) as resp:
if resp.status == 200:
data = await resp.read()
kwargs["photo"] = BytesIO(data)
file_obj = BytesIO(data)
is_temp_obj = True
else:
# 尝试直接发 URL
kwargs["photo"] = image_path
file_obj = image_path # 尝试直接发 URL
except Exception as e:
logger.warning(f"[Telegram] 下载图片失败,尝试直接发送: {e}")
kwargs["photo"] = image_path
photo_obj = kwargs["photo"]
await client.send_photo(**kwargs)
file_obj = image_path
else:
# 本地文件
with open(image_path, "rb") as f:
kwargs["photo"] = f
await client.send_photo(**kwargs)
if os.path.exists(image_path):
file_obj = open(image_path, "rb")
is_temp_obj = True
else:
file_obj = image_path
if isinstance(photo_obj, BytesIO):
photo_obj.close()
# 2. 发送图片
kwargs["photo"] = file_obj
try:
await client.send_photo(**kwargs)
finally:
if is_temp_obj and hasattr(file_obj, "close"):
file_obj.close()
return True
except Exception as e:
if "photo_obj" in locals() and isinstance(photo_obj, BytesIO):
photo_obj.close()
err_msg = str(e)
# Photo_invalid_dimensions: Telegram 报错提示图片长宽比例或总尺寸不合规
if "Photo_invalid_dimensions" in err_msg or "Photo invalid dimensions" in err_msg:
logger.warning("[Telegram] 图片尺寸超限,正在尝试以文件形式发送...")
# 构造一个更有意义的文件名
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
fn = f"analysis_report_{group_id}_{ts}.png"
return await self.send_file(group_id, image_path, filename=fn)
logger.error(f"[Telegram] 发送图片失败: {e}")
return False
@@ -581,21 +603,51 @@ class TelegramAdapter(PlatformAdapter):
try:
import os
import base64
from io import BytesIO
chat_id, message_thread_id = self._parse_group_id(group_id)
file_obj: Any = None
is_temp_obj = False
kwargs: dict[str, Any] = {"chat_id": chat_id}
if message_thread_id:
kwargs["message_thread_id"] = int(message_thread_id)
if filename:
kwargs["filename"] = filename
else:
kwargs["filename"] = os.path.basename(file_path)
# 打开文件
with open(file_path, "rb") as f:
kwargs["document"] = f
# 1. 统一处理输入源 (Base64 / Local File)
if file_path.startswith("base64://"):
data = base64.b64decode(file_path[len("base64://") :])
file_obj = BytesIO(data)
is_temp_obj = True
if not filename:
filename = "file.png"
elif file_path.startswith("data:"):
parts = file_path.split(",", 1)
if len(parts) == 2:
data = base64.b64decode(parts[1])
file_obj = BytesIO(data)
is_temp_obj = True
if not filename:
filename = "file.png"
elif os.path.isfile(file_path):
file_obj = open(file_path, "rb")
is_temp_obj = True
if not filename:
filename = os.path.basename(file_path)
else:
# 可能是 URL 或缓存 ID
file_obj = file_path
if not filename:
filename = "file"
kwargs["document"] = file_obj
kwargs["filename"] = filename
try:
await client.send_document(**kwargs)
finally:
if is_temp_obj and hasattr(file_obj, "close"):
file_obj.close()
return True
except Exception as e: