diff --git a/metadata.yaml b/metadata.yaml index 460ad13..ca380ac 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,7 +1,7 @@ name: astrbot_plugin_qq_group_daily_analysis # 这是你的插件的唯一识别名。 display_name: 群分析总结插件 # 插件的显示名称 desc: "[多平台接入开发中] 群日常分析总结插件 - 支持 QQ (aiocqhttp)、Telegram、Discord;生成精美的群聊分析报告,支持话题分析、用户形象、群聊圣经等功能" # 插件简短描述 -version: v4.7.11 # 插件版本号。格式:v1.1.1 或者 v1.1 +version: v4.7.12 # 插件版本号。格式:v1.1.1 或者 v1.1 author: SXP-Simon # 作者 astrbot_version: ">=4.16.0" support_platforms: diff --git a/src/infrastructure/platform/adapters/onebot_adapter.py b/src/infrastructure/platform/adapters/onebot_adapter.py index 94cd1ed..e253984 100644 --- a/src/infrastructure/platform/adapters/onebot_adapter.py +++ b/src/infrastructure/platform/adapters/onebot_adapter.py @@ -475,8 +475,11 @@ class OneBotAdapter(PlatformAdapter): file_str = image_path if not image_path.startswith(("http://", "https://", "base64://")): if os.path.isabs(image_path): - # 如果是绝对路径,保持原样(兼容 Docker 中的 /AstrBot/ 路径) - file_str = f"file:///{image_path}" + # 如果是绝对路径且以 / 开头,只需加 file:// 即可构成 file:/// + if image_path.startswith("/"): + file_str = f"file://{image_path}" + else: + file_str = f"file:///{image_path}" else: # 如果是相对路径,转为绝对路径 file_str = f"file:///{os.path.abspath(image_path)}" diff --git a/src/infrastructure/reporting/generators.py b/src/infrastructure/reporting/generators.py index 07cc1d7..c906a4b 100644 --- a/src/infrastructure/reporting/generators.py +++ b/src/infrastructure/reporting/generators.py @@ -5,6 +5,7 @@ import asyncio import base64 +import os import re from datetime import datetime from pathlib import Path @@ -119,20 +120,43 @@ class ReportGenerator(IReportGenerator): ) if image_data: + # 校验是否为合法图片(防止 T2I 返回 500 错误 HTML 字符流) + is_valid = False + actual_data_head = None + if isinstance(image_data, bytes): - b64 = base64.b64encode(image_data).decode("utf-8") - image_url = f"base64://{b64}" - logger.info( - f"图片生成成功 ({image_options}): [Base64 Data {len(image_data)} bytes]" - ) - return image_url, html_content - elif isinstance(image_data, str): - # Fallback: 如果返回的是字符串(可能是URL或路径) - logger.info(f"图片生成成功 (String): {image_data}") + actual_data_head = image_data[:10] + elif isinstance(image_data, str) and os.path.exists(image_data): + try: + with open(image_data, "rb") as f: + actual_data_head = f.read(10) + except Exception as e: + logger.warning(f"读取图片临时文件失败: {e}") - return image_data, html_content + if actual_data_head: + # 检查 magic numbers (JPEG: FF D8, PNG: 89 50 4E 47) + if actual_data_head.startswith( + b"\xff\xd8" + ) or actual_data_head.startswith(b"\x89PNG"): + is_valid = True + else: + logger.warning( + f"渲染结果似乎不是有效的图片数据 (头部: {actual_data_head.hex()})" + ) - logger.warning(f"渲染策略 {image_options} 返回空数据") + if is_valid: + if isinstance(image_data, bytes): + b64 = base64.b64encode(image_data).decode("utf-8") + image_url = f"base64://{b64}" + logger.info( + f"图片生成成功 ({image_options}): [Base64 Data {len(image_data)} bytes]" + ) + return image_url, html_content + elif isinstance(image_data, str): + logger.info(f"图片生成成功 (String): {image_data}") + return image_data, html_content + + logger.warning(f"渲染策略 {image_options} 返回了无效或空数据") except Exception as e: logger.warning(f"渲染策略 {image_options} 失败: {e}")