Skip to content

Commit b119ea7

Browse files
committed
feat(album): 支持 LLBot 群相册接口并优化 OneBot 适配器
1 parent d36bf49 commit b119ea7

2 files changed

Lines changed: 83 additions & 30 deletions

File tree

_conf_schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@
424424
"qq_group_upload": {
425425
"description": "群文件/群相册上传设置",
426426
"type": "object",
427-
"hint": "图片报告生成后自动上传到群文件目录或群相册。群文件上传基于 OneBot upload_group_file API,群相册上传为 NapCat 扩展 API。仅对 QQ(OneBot)平台的图片格式报告生效",
427+
"hint": "图片报告生成后自动上传到群文件目录或群相册。群文件上传基于 OneBot upload_group_file API。仅对 QQ(OneBot)平台的图片格式报告生效",
428428
"items": {
429429
"enable_group_file_upload": {
430430
"type": "bool",
@@ -440,7 +440,7 @@
440440
},
441441
"enable_group_album_upload": {
442442
"type": "bool",
443-
"description": "启用群相册上传(NapCat 通过测试)",
443+
"description": "启用群相册上传",
444444
"default": false,
445445
"hint": "图片报告生成后,自动上传到群相册(确保 Bot 有权限上传群相册)。此功能为 NapCat 扩展 API,其他 OneBot 实现可能不支持"
446446
},

src/infrastructure/platform/adapters/onebot_adapter.py

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,30 @@ def __init__(self, bot_instance: Any, config: dict | None = None):
6262
if not self.bot_self_ids and config:
6363
self.bot_self_ids = [str(id) for id in config.get("bot_qq_ids", [])]
6464

65+
# LLBot 探测标志
66+
self._is_llbot = False
67+
self._llbot_checked = False
68+
6569
def _init_capabilities(self) -> PlatformCapabilities:
6670
"""返回预定义的 OneBot v11 能力集。"""
6771
return ONEBOT_V11_CAPABILITIES
6872

73+
async def _detect_llbot(self):
74+
"""探测是否为 LLBot"""
75+
if self._llbot_checked:
76+
return
77+
try:
78+
# 避免在一些不支持 get_version_info 的老版本上卡死
79+
result = await self.bot.call_action("get_version_info")
80+
if isinstance(result, dict):
81+
app_name = result.get("app_name", "")
82+
self._is_llbot = app_name == "LLOneBot"
83+
if self._is_llbot:
84+
logger.info("[OneBot] 探测到当前协议端为 LLBot")
85+
except Exception:
86+
self._is_llbot = False
87+
self._llbot_checked = True
88+
6989
def _get_nearest_size(self, requested_size: int) -> int:
7090
"""从支持的尺寸列表中找到最接近请求尺寸的一个。"""
7191
return min(self.AVAILABLE_SIZES, key=lambda x: abs(x - requested_size))
@@ -946,7 +966,7 @@ async def upload_group_album(
946966
if not album_id:
947967
albums = await self.get_group_album_list(group_id)
948968
album_id = self._find_item_in_list(
949-
albums, album_name, ["album_id", "id"], ["name", "album_name"]
969+
albums, album_name, ["album_id"], ["name", "album_name"]
950970
)
951971
# 如果仍没指定且没搜到特定相册,取第一个
952972
if not album_id and not album_name and albums:
@@ -959,6 +979,27 @@ async def upload_group_album(
959979
return False
960980

961981
async def do_upload(content: str, label: str):
982+
await self._detect_llbot()
983+
984+
if self._is_llbot:
985+
# LLBot 模式:使用 files 参数 (列表)
986+
# LLBot 的 upload_group_album 接收 files 作为数组
987+
llbot_params = {
988+
"group_id": int(group_id),
989+
"album_id": str(album_id),
990+
"files": [content],
991+
}
992+
try:
993+
await self.bot.call_action("upload_group_album", **llbot_params)
994+
logger.debug(
995+
f"[群分析相册] 上传成功 (LLBot, {label}): 群 {group_id}"
996+
)
997+
return
998+
except Exception as e:
999+
logger.warning(
1000+
f"[群分析相册] LLBot 上传接口调用失败: {e},尝试 NapCat 模式..."
1001+
)
1002+
9621003
params = {
9631004
"group_id": int(group_id),
9641005
"file": content,
@@ -994,28 +1035,29 @@ async def get_group_album_list(
9941035
获取群分析相册列表(兼容多种 OneBot 扩展实现)。
9951036
"""
9961037

997-
def extract_list(data: Any) -> list[dict]:
998-
if not data:
1038+
def extract_list(payload: Any) -> list[dict]:
1039+
"""从不同结构的响应中提取相册列表:直接列表、嵌套在 data 中、或直接在根字段中。"""
1040+
if isinstance(payload, list):
1041+
return [item for item in payload if isinstance(item, dict)]
1042+
if not isinstance(payload, dict):
1043+
logger.debug(
1044+
f"[群分析相册] 提取相册列表失败: payload 非字典/列表类型 ({type(payload)})"
1045+
)
9991046
return []
1000-
if isinstance(data, list):
1001-
return data
1047+
1048+
data = payload.get("data")
10021049
if isinstance(data, dict):
1003-
# 探测常见键名
1004-
lst = (
1005-
data.get("albums")
1006-
or data.get("album_list")
1007-
or data.get("albumList")
1008-
or data.get("list")
1009-
or []
1010-
)
1011-
if isinstance(lst, list):
1012-
return lst
1013-
# 如果 'data' 键本身存在且为列表
1014-
inner_data = data.get("data")
1015-
if isinstance(inner_data, list):
1016-
return inner_data
1017-
if isinstance(inner_data, dict):
1018-
return extract_list(inner_data)
1050+
album_list = data.get("album_list") or data.get("list")
1051+
if isinstance(album_list, list):
1052+
return [item for item in album_list if isinstance(item, dict)]
1053+
else:
1054+
logger.debug(f"[群分析相册] 在 data 字段中未找到列表: data={data}")
1055+
1056+
album_list = payload.get("album_list") or payload.get("list")
1057+
if isinstance(album_list, list):
1058+
return [item for item in album_list if isinstance(item, dict)]
1059+
1060+
logger.debug(f"[群分析相册] 无法从响应中提取相册列表: payload={payload}")
10191061
return []
10201062

10211063
# 候选 API 名称
@@ -1033,13 +1075,14 @@ def extract_list(data: Any) -> list[dict]:
10331075
)
10341076
result = await self.bot.call_action(
10351077
action,
1036-
group_id=int(group_id), # 确保传整型,对齐 NapCat 等实现
1078+
group_id=int(group_id),
10371079
)
1080+
logger.debug(f"[群分析相册] 接口 {action} 原始响应内容: {result}")
10381081
if result:
10391082
albums = extract_list(result)
10401083
if albums:
10411084
logger.debug(
1042-
f"[群分析相册] {action} 成功获取到 {len(albums)} 个相册"
1085+
f"[群分析相册] {action} 成功获取并提取到 {len(albums)} 个相册对象"
10431086
)
10441087
return albums
10451088
except Exception as e:
@@ -1070,11 +1113,21 @@ async def find_album_id(
10701113
)
10711114
albums = await self.get_group_album_list(group_id)
10721115
for album in albums:
1073-
name = album.get("name") or album.get("album_name", "")
1074-
aid = album.get("album_id") or album.get("id", "")
1075-
if name == album_name and aid:
1076-
logger.info(f"[群分析相册] 成功定位相册: '{album_name}' -> ID: {aid}")
1077-
return str(aid)
1116+
name = album.get("name") or album.get("album_name")
1117+
logger.debug(
1118+
f"[群分析相册] 正在匹配相册: 目标='{album_name}', 当前相册名称='{name}', 原始数据={album}"
1119+
)
1120+
if name == album_name:
1121+
aid = album.get("album_id")
1122+
if aid:
1123+
logger.info(
1124+
f"[群分析相册] 成功定位相册: '{album_name}' -> ID: {aid}"
1125+
)
1126+
return str(aid)
1127+
else:
1128+
logger.debug(
1129+
f"[群分析相册] 相册 '{name}' 名称匹配,但未找到有效的 album_id"
1130+
)
10781131

10791132
logger.info(f"[群分析相册] 未能找到名为 '{album_name}' 的相册 (群 {group_id})")
10801133
return None

0 commit comments

Comments
 (0)