升级到新版 SDK 并补充点歌业务日志

- 锁定 qqbotsdk b37a53f(含:健康断开零等待重连、静默常规连接日志、
  失败才记断开与退避)
- 新增业务日志:启动打印生效配置、点歌/查歌词/帮助、菜单已发、
  选歌、按钮点击、语音/文件/直链已发,失败项统一带群号前缀
  (此前 18 处日志 17 处是 warning,成功路径完全静默,故日志里
  看不到任何点歌消息)
This commit is contained in:
snowy-yang committed 2026-09-21 18:26:23 +08:00
1 parent a11c0b375f
commit 6b6492dc8d
3 files changed
+20 -19

No files matched your search

+18 -4
View File
@@ -404,6 +404,7 @@ async def send_menu(
logger.warning(f"文本菜单发送失败: {e!r}")
return
await _swap_message(api, config, group_openid, resp)
logger.info(f"[{group_openid}] 菜单已发:{keyword} 第{page}页 {len(songs)}首")
async def send_card(
@@ -451,6 +452,7 @@ async def send_card(
logger.warning(f"文本卡片发送失败: {e!r}")
return
await _swap_message(api, config, group_openid, resp)
logger.info(f"[{group_openid}] 选歌:{title}")
async def _upload_group_file(
@@ -489,6 +491,7 @@ async def send_song(
无论成败都撤回卡片。"""
found = await _fetchable_play(http, config, song, keyword)
if found is None:
logger.warning(f"[{group_openid}] 无可用直链:{song.name}")
await _reply(
api, group_openid, f"没拿到「{song.name}」的播放链接", msg_id, event_id
)
@@ -510,26 +513,28 @@ async def send_song(
)
if sent := _sent_id(resp):
_mark(sent)
logger.info(f"[{group_openid}] {label}已发:{_caption(song)}")
return
except _API_FAILS as e:
no_permission = isinstance(e, ApiError) and e.code == _NO_FILE_PERMISSION
if no_permission:
logger.warning("群文件上传仅限群主/管理员,改为直链文本")
logger.warning(f"[{group_openid}] 群文件上传无权限,改为直链文本")
else:
logger.warning(f"以{label}发送失败: {e!r}")
logger.warning(f"[{group_openid}] 以{label}发送失败: {e!r}")
# 回退直链文本;文件权限问题多给一句说明
text = f"{_caption(song)}\n{url}"
if no_permission:
text = f"{_caption(song)}\n(本群文件上传仅限群主/管理员,先给直链)\n{url}"
try:
await _reply(api, group_openid, text, msg_id, event_id)
logger.info(f"[{group_openid}] 直链已发:{_caption(song)}")
except _API_FAILS as e:
# 被动回复被拒(如互动 event_id 超时效)→ 降级为主动消息
logger.warning(f"被动回复失败,降级为主动消息: {e!r}")
logger.warning(f"[{group_openid}] 被动回复失败,降级为主动消息: {e!r}")
try:
await _reply(api, group_openid, text)
except _API_FAILS as e:
logger.warning(f"文本链接发送失败: {e!r}")
logger.warning(f"[{group_openid}] 文本链接发送失败: {e!r}")
async def send_lyric(
@@ -688,14 +693,17 @@ async def handle_command(
选歌/播放/下载现在都由内嵌按钮(回调)承担,这里只处理文字命令。"""
if match := _SONG_RE.search(content):
keyword = match.group(1).strip()
logger.info(f"[{group_openid}] 点歌:{keyword}")
await send_menu(api, http, config, group_openid, keyword, msg_id=msg_id)
return True
if match := _LYRIC_RE.search(content):
keyword = match.group(1).strip()
logger.info(f"[{group_openid}] 查歌词:{keyword}")
if song := await _find(api, http, config, group_openid, msg_id, keyword):
await send_lyric(api, http, config, group_openid, song, msg_id=msg_id)
return True
if "音乐帮助" in content:
logger.info(f"[{group_openid}] 查看帮助")
await _reply(api, group_openid, _HELP, msg_id=msg_id)
return True
return False
@@ -732,6 +740,11 @@ def register(ee: EventEmitter, config: BotConfig, http: ClientSession) -> None:
"""把点歌命令与按钮回调 handler 挂到 emitter(群场景);http 为 bot
自建连接池(不受 SDK 的 TIMEOUT 约束),经闭包供 handler 使用——不能
用形参注入,否则拿到的是 SDK 那个 5s 超时的连接池。"""
logger.info(
f"点歌已就绪:源={config.music_source or '聚合'} 音质={config.music_quality} "
f"每页={config.menu_page_size} 下载={config.send_mode} "
f"自动撤回={'开' if config.withdraw else '关'}"
)
# @机器人 的消息走前一个事件;开通「接收所有消息」后群内全部消息走
# 全量事件,两个事件字段一致,共用同一个 handler
@@ -743,6 +756,7 @@ def register(ee: EventEmitter, config: BotConfig, http: ClientSession) -> None:
@ee.on("INTERACTION_CREATE")
async def on_button(act: Interaction, ev: Event, api: BotApi) -> None:
if act.chat_type == 1 and act.id and act.group_openid:
logger.info(f"[{act.group_openid}] 按钮:{act.button_data[:40]}")
# 被动回复的 event_id 用网关帧最外层 id(Event.event_id),
# 裸 uuid(act.id)只用于回应互动
await handle_button(