nonebot-plugin-bili-dynamic 0.2.7__tar.gz → 0.2.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/PKG-INFO +30 -7
  2. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/README.md +29 -3
  3. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/__init__.py +19 -4
  4. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/api.py +56 -26
  5. nonebot_plugin_bili_dynamic-0.2.9/nonebot_plugin_bili_dynamic/commands.py +676 -0
  6. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/monitor.py +58 -46
  7. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/qrcode_login.py +96 -99
  8. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/renderer.py +15 -5
  9. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic.egg-info/PKG-INFO +30 -7
  10. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic.egg-info/SOURCES.txt +5 -1
  11. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic.egg-info/requires.txt +0 -4
  12. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/pyproject.toml +1 -7
  13. nonebot_plugin_bili_dynamic-0.2.9/tests/test_api_client.py +87 -0
  14. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/tests/test_dynamic_expire.py +3 -1
  15. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/tests/test_live_stats.py +73 -0
  16. nonebot_plugin_bili_dynamic-0.2.9/tests/test_monitor_send.py +53 -0
  17. nonebot_plugin_bili_dynamic-0.2.9/tests/test_qrcode_login.py +100 -0
  18. nonebot_plugin_bili_dynamic-0.2.9/tests/test_reconnect.py +63 -0
  19. nonebot_plugin_bili_dynamic-0.2.9/tests/test_renderer_cache.py +34 -0
  20. nonebot_plugin_bili_dynamic-0.2.7/nonebot_plugin_bili_dynamic/commands.py +0 -816
  21. nonebot_plugin_bili_dynamic-0.2.7/tests/test_qrcode_login.py +0 -46
  22. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/LICENSE +0 -0
  23. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/config.py +0 -0
  24. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/cookie_store.py +0 -0
  25. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/database.py +0 -0
  26. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/link_parser.py +0 -0
  27. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/live_stats.py +0 -0
  28. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/models.py +0 -0
  29. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic/translator.py +0 -0
  30. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic.egg-info/dependency_links.txt +0 -0
  31. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic.egg-info/entry_points.txt +0 -0
  32. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/nonebot_plugin_bili_dynamic.egg-info/top_level.txt +0 -0
  33. {nonebot_plugin_bili_dynamic-0.2.7 → nonebot_plugin_bili_dynamic-0.2.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-bili-dynamic
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: B站动态/直播推送 NoneBot2 插件(基于 Colter23/mirai 插件移植)
5
5
  Author: Tony
6
6
  License: MIT
@@ -28,11 +28,8 @@ Requires-Dist: pillow>=10.0.0
28
28
  Requires-Dist: skia-python>=87.5
29
29
  Requires-Dist: qrcode[pil]>=7.4.2
30
30
  Requires-Dist: tortoise-orm[accel]<1.0,>=0.21.0
31
- Requires-Dist: aerich>=0.7.0
32
31
  Requires-Dist: pydantic>=2.0.0
33
32
  Requires-Dist: typing-extensions>=4.0.0
34
- Provides-Extra: render
35
- Requires-Dist: playwright>=1.40.0; extra == "render"
36
33
  Dynamic: license-file
37
34
 
38
35
  <div align="center">
@@ -108,29 +105,55 @@ B站动态/直播推送插件,基于 Colter23 bilibili-dynamic-mirai-plugin v3
108
105
 
109
106
  | 配置项 | 必填 | 默认值 | 说明 |
110
107
  |:-----:|:----:|:----:|:----:|
111
- | bili_account__sessdata | 否 | 空 | B站 SESSDATA Cookie |
108
+ | bili_account__sessdata | 否 | 空 | B站 SESSDATA Cookie(也可用 `/bi login` 扫码后自动保存) |
112
109
  | bili_account__bili_jct | 否 | 空 | B站 bili_jct Cookie |
110
+ | check__interval | 否 | 30 | 动态检测间隔(秒,≥10) |
111
+ | check__live_interval | 否 | 20 | 直播检测间隔(秒,≥10) |
112
+ | check__timeout | 否 | 10 | 单次请求超时(秒) |
113
113
  | push__max_age_hours | 否 | 24 | 动态推送最大时效(小时),超过的仅记录不推送,0为不限制 |
114
+ | push__max_images | 否 | 4 | 每条推送附带的最大原图数(0-9) |
115
+ | push__text_only | 否 | false | 仅文本推送(不渲染卡片图) |
116
+ | push__live_close_notify | 否 | true | 下播通知(含直播时长) |
117
+ | push__message_interval | 否 | 0.5 | 同群连续消息间隔(秒) |
118
+ | push__push_interval | 否 | 1.0 | 群之间推送间隔(秒) |
119
+ | image__quality | 否 | 1000w | 渲染质量:`800w` / `1000w` / `1200w` / `1500w` |
120
+ | image__theme | 否 | v3 | 绘图主题:`v3` / `v3RainbowOutline` / `v2` |
121
+ | image__default_color | 否 | #FB7299 | 默认主题色 |
122
+ | image__font | 否 | 空 | 自定义字体路径,多个用 `;` 分隔 |
123
+ | image__badge_enable | 否 | true | 是否绘制卡片顶部标签 |
124
+ | image__card_ornament | 否 | None | 卡片装饰,设为 `QrCode` 时绘制二维码 |
114
125
  | live_report__enable | 否 | true | 每日直播时长播报开关 |
115
126
  | live_report__time | 否 | 18:00 | 每日时长播报时间(可用命令覆盖) |
116
127
  | live_report__start_date | 否 | 空 | 时长统计起始日期 YYYY-MM-DD,空为不限制(可用命令覆盖) |
128
+ | database_url | 否 | sqlite://db.sqlite3 | 数据库连接串,相对路径会转换为绝对路径 |
129
+ | superusers | 否 | 空 | 额外管理员 QQ 列表(与 NoneBot 的 superusers 合并) |
117
130
 
118
131
  > 注意:嵌套配置项需使用双下划线 `__` 连接,如 `push__max_age_hours=48`。
119
132
 
120
133
  ## 🎉 使用
121
134
  ### 指令表
135
+
136
+ `/bi <子命令>` 与 `/bi.<子命令>` 两种写法等价,下表以空格形式为例。
137
+
122
138
  | 指令 | 权限 | 需要@ | 范围 | 说明 |
123
139
  |:-----:|:----:|:----:|:----:|:----:|
124
140
  | /bi add <UID> | 群员 | 否 | 群/私聊 | 订阅UP主 |
125
141
  | /bi del <UID> | 群员 | 否 | 群/私聊 | 取消订阅 |
126
142
  | /bi list | 群员 | 否 | 群/私聊 | 查看订阅列表 |
127
143
  | /bi live <UID> | 群员 | 否 | 群/私聊 | 查询直播状态 |
128
- | /bi new <UID> [n] | 群员 | 否 | 群/私聊 | 查看最新n条动态 |
144
+ | /bi new <UID> [n] | 群员 | 否 | 群/私聊 | 查看最新n条动态(默认1,最多3) |
129
145
  | /bi login | 群员 | 否 | 群/私聊 | B站扫码登录 |
130
- | /bi color <HEX> | 群员 | 否 | 群/私聊 | 设置主题色 |
146
+ | /bi config [UID] | 群员 | 否 | 群/私聊 | 查看订阅配置 |
147
+ | /bi color <UID> <HEX> | 群员 | 否 | 群/私聊 | 设置指定UP主的主题色 |
148
+ | /bi filter <UID> <类型> [模式] | 群员 | 否 | 群/私聊 | 设置类型过滤,模式 `blacklist` / `whitelist` |
149
+ | /bi addat <QQ...> | 群员 | 否 | 群/私聊 | 添加@提醒(可一次多个) |
150
+ | /bi delat <QQ...> | 群员 | 否 | 群/私聊 | 移除@提醒 |
151
+ | /bi atlist | 群员 | 否 | 群/私聊 | 查看@提醒列表 |
131
152
  | /bi livetime [UID] | 群员 | 否 | 群/私聊 | 直播时长统计(今日+累计,可指定UID) |
132
153
  | /bi livetime time <HH:MM> | 管理员 | 否 | 群/私聊 | 设置每日时长播报时间 |
133
154
  | /bi livetime from <日期> | 管理员 | 否 | 群/私聊 | 设置统计起始日期,如 2026-09-01 或 9-1 |
155
+ | /bi listall | 超级用户 | 否 | 群/私聊 | 查看全部订阅 |
156
+ | /bi clear | 超级用户 | 否 | 群/私聊 | 清理失效订阅(当前仅提示手动管理) |
134
157
 
135
158
  > 时长统计说明:插件自动记录每次开播/下播,每天到点(默认 18:00)向各群/私聊播报其订阅主播的时长统计卡片;
136
159
  > 只能统计插件运行期间检测到的直播,功能上线前的历史直播无法补录。
@@ -71,29 +71,55 @@ B站动态/直播推送插件,基于 Colter23 bilibili-dynamic-mirai-plugin v3
71
71
 
72
72
  | 配置项 | 必填 | 默认值 | 说明 |
73
73
  |:-----:|:----:|:----:|:----:|
74
- | bili_account__sessdata | 否 | 空 | B站 SESSDATA Cookie |
74
+ | bili_account__sessdata | 否 | 空 | B站 SESSDATA Cookie(也可用 `/bi login` 扫码后自动保存) |
75
75
  | bili_account__bili_jct | 否 | 空 | B站 bili_jct Cookie |
76
+ | check__interval | 否 | 30 | 动态检测间隔(秒,≥10) |
77
+ | check__live_interval | 否 | 20 | 直播检测间隔(秒,≥10) |
78
+ | check__timeout | 否 | 10 | 单次请求超时(秒) |
76
79
  | push__max_age_hours | 否 | 24 | 动态推送最大时效(小时),超过的仅记录不推送,0为不限制 |
80
+ | push__max_images | 否 | 4 | 每条推送附带的最大原图数(0-9) |
81
+ | push__text_only | 否 | false | 仅文本推送(不渲染卡片图) |
82
+ | push__live_close_notify | 否 | true | 下播通知(含直播时长) |
83
+ | push__message_interval | 否 | 0.5 | 同群连续消息间隔(秒) |
84
+ | push__push_interval | 否 | 1.0 | 群之间推送间隔(秒) |
85
+ | image__quality | 否 | 1000w | 渲染质量:`800w` / `1000w` / `1200w` / `1500w` |
86
+ | image__theme | 否 | v3 | 绘图主题:`v3` / `v3RainbowOutline` / `v2` |
87
+ | image__default_color | 否 | #FB7299 | 默认主题色 |
88
+ | image__font | 否 | 空 | 自定义字体路径,多个用 `;` 分隔 |
89
+ | image__badge_enable | 否 | true | 是否绘制卡片顶部标签 |
90
+ | image__card_ornament | 否 | None | 卡片装饰,设为 `QrCode` 时绘制二维码 |
77
91
  | live_report__enable | 否 | true | 每日直播时长播报开关 |
78
92
  | live_report__time | 否 | 18:00 | 每日时长播报时间(可用命令覆盖) |
79
93
  | live_report__start_date | 否 | 空 | 时长统计起始日期 YYYY-MM-DD,空为不限制(可用命令覆盖) |
94
+ | database_url | 否 | sqlite://db.sqlite3 | 数据库连接串,相对路径会转换为绝对路径 |
95
+ | superusers | 否 | 空 | 额外管理员 QQ 列表(与 NoneBot 的 superusers 合并) |
80
96
 
81
97
  > 注意:嵌套配置项需使用双下划线 `__` 连接,如 `push__max_age_hours=48`。
82
98
 
83
99
  ## 🎉 使用
84
100
  ### 指令表
101
+
102
+ `/bi <子命令>` 与 `/bi.<子命令>` 两种写法等价,下表以空格形式为例。
103
+
85
104
  | 指令 | 权限 | 需要@ | 范围 | 说明 |
86
105
  |:-----:|:----:|:----:|:----:|:----:|
87
106
  | /bi add <UID> | 群员 | 否 | 群/私聊 | 订阅UP主 |
88
107
  | /bi del <UID> | 群员 | 否 | 群/私聊 | 取消订阅 |
89
108
  | /bi list | 群员 | 否 | 群/私聊 | 查看订阅列表 |
90
109
  | /bi live <UID> | 群员 | 否 | 群/私聊 | 查询直播状态 |
91
- | /bi new <UID> [n] | 群员 | 否 | 群/私聊 | 查看最新n条动态 |
110
+ | /bi new <UID> [n] | 群员 | 否 | 群/私聊 | 查看最新n条动态(默认1,最多3) |
92
111
  | /bi login | 群员 | 否 | 群/私聊 | B站扫码登录 |
93
- | /bi color <HEX> | 群员 | 否 | 群/私聊 | 设置主题色 |
112
+ | /bi config [UID] | 群员 | 否 | 群/私聊 | 查看订阅配置 |
113
+ | /bi color <UID> <HEX> | 群员 | 否 | 群/私聊 | 设置指定UP主的主题色 |
114
+ | /bi filter <UID> <类型> [模式] | 群员 | 否 | 群/私聊 | 设置类型过滤,模式 `blacklist` / `whitelist` |
115
+ | /bi addat <QQ...> | 群员 | 否 | 群/私聊 | 添加@提醒(可一次多个) |
116
+ | /bi delat <QQ...> | 群员 | 否 | 群/私聊 | 移除@提醒 |
117
+ | /bi atlist | 群员 | 否 | 群/私聊 | 查看@提醒列表 |
94
118
  | /bi livetime [UID] | 群员 | 否 | 群/私聊 | 直播时长统计(今日+累计,可指定UID) |
95
119
  | /bi livetime time <HH:MM> | 管理员 | 否 | 群/私聊 | 设置每日时长播报时间 |
96
120
  | /bi livetime from <日期> | 管理员 | 否 | 群/私聊 | 设置统计起始日期,如 2026-09-01 或 9-1 |
121
+ | /bi listall | 超级用户 | 否 | 群/私聊 | 查看全部订阅 |
122
+ | /bi clear | 超级用户 | 否 | 群/私聊 | 清理失效订阅(当前仅提示手动管理) |
97
123
 
98
124
  > 时长统计说明:插件自动记录每次开播/下播,每天到点(默认 18:00)向各群/私聊播报其订阅主播的时长统计卡片;
99
125
  > 只能统计插件运行期间检测到的直播,功能上线前的历史直播无法补录。
@@ -2,7 +2,7 @@
2
2
  NoneBot2 B站动态推送插件
3
3
  基于 Colter23/bilibili-dynamic-mirai-plugin 移植
4
4
  """
5
- from nonebot import require, logger, get_driver
5
+ from nonebot import require, logger, get_driver, get_bots
6
6
  from nonebot.plugin import PluginMetadata
7
7
 
8
8
  require("nonebot_plugin_apscheduler")
@@ -46,6 +46,8 @@ async def on_bot_connect():
46
46
  """Bot连接后初始化"""
47
47
  logger.info("[BiliDynamic] Bot已连接,初始化数据库...")
48
48
  await init_db()
49
+ # 断线期间客户端可能已被关闭,重连时重建
50
+ bili_api.ensure_client()
49
51
  # 加载本地保存的 Cookie(扫码登录持久化)
50
52
  cookies = load_cookie()
51
53
  if cookies.get("SESSDATA"):
@@ -61,8 +63,21 @@ async def on_bot_connect():
61
63
 
62
64
  @driver.on_bot_disconnect
63
65
  async def on_bot_disconnect():
64
- """Bot断开时清理"""
65
- logger.info("[BiliDynamic] Bot断开,清理资源...")
66
- await monitor.close() if hasattr(monitor, 'close') else None
66
+ """Bot断开时暂停轮询(仍有其他 Bot 在线时不做处理)
67
+
68
+ 注意:这里不关闭 API 客户端和数据库连接。NapCat 重启会触发断线钩子,
69
+ 若此时关闭客户端,重连后所有请求都会报 "client has been closed"。
70
+ """
71
+ if get_bots():
72
+ return
73
+ logger.info("[BiliDynamic] 所有 Bot 已断开,暂停检测...")
74
+ await monitor.close()
75
+
76
+
77
+ @driver.on_shutdown
78
+ async def on_shutdown():
79
+ """进程退出时释放资源"""
80
+ logger.info("[BiliDynamic] 插件关闭,释放资源...")
81
+ await monitor.close()
67
82
  await bili_api.close()
68
83
  await close_db()
@@ -56,23 +56,43 @@ class BiliAPI:
56
56
  """B站API客户端"""
57
57
 
58
58
  def __init__(self):
59
- self.client = httpx.AsyncClient(
59
+ self._runtime_cookies: Dict[str, str] = {}
60
+ self.client = self._create_client()
61
+ self._wbi_keys: Optional[tuple] = None
62
+ self._wbi_keys_expire = 0
63
+
64
+ def _create_client(self) -> httpx.AsyncClient:
65
+ """按当前配置和运行时 Cookie 创建客户端。"""
66
+ client = httpx.AsyncClient(
60
67
  timeout=plugin_config.check.timeout,
61
68
  headers={
62
69
  "User-Agent": UA,
63
70
  "Referer": REFERER,
64
71
  }
65
72
  )
66
- self._update_cookie()
67
- self._wbi_keys: Optional[tuple] = None
68
- self._wbi_keys_expire = 0
69
-
73
+ cookies = {}
74
+ if plugin_config.bili_account.sessdata:
75
+ cookies["SESSDATA"] = plugin_config.bili_account.sessdata
76
+ if plugin_config.bili_account.bili_jct:
77
+ cookies["bili_jct"] = plugin_config.bili_account.bili_jct
78
+ cookies.update(self._runtime_cookies)
79
+ if cookies:
80
+ client.cookies.update(cookies)
81
+ return client
82
+
83
+ def ensure_client(self) -> httpx.AsyncClient:
84
+ """客户端被关闭(如 Bot 断线)后重建,避免重连后请求全部失败。"""
85
+ if self.client.is_closed:
86
+ self.client = self._create_client()
87
+ logger.info("[BiliDynamic] 已重建 B站 API 客户端")
88
+ return self.client
89
+
70
90
  async def _get_wbi_keys(self) -> tuple:
71
91
  """获取 WBI img_key 和 sub_key,缓存约 6 小时"""
72
92
  if self._wbi_keys and time.time() < self._wbi_keys_expire:
73
93
  return self._wbi_keys
74
94
  try:
75
- resp = await self.client.get(
95
+ resp = await self.ensure_client().get(
76
96
  "https://api.bilibili.com/x/web-interface/nav",
77
97
  headers={"Referer": "https://www.bilibili.com/"}
78
98
  )
@@ -89,16 +109,6 @@ class BiliAPI:
89
109
  # 兜底:返回空,后续不做签名
90
110
  return ("", "")
91
111
 
92
- def _update_cookie(self):
93
- """更新Cookie"""
94
- cookies = {}
95
- if plugin_config.bili_account.sessdata:
96
- cookies["SESSDATA"] = plugin_config.bili_account.sessdata
97
- if plugin_config.bili_account.bili_jct:
98
- cookies["bili_jct"] = plugin_config.bili_account.bili_jct
99
- if cookies:
100
- self.client.cookies.update(cookies)
101
-
102
112
  def set_cookie(self, sessdata: str = "", bili_jct: str = "", dede_user_id: str = ""):
103
113
  """运行时更新 Cookie(扫码登录成功后使用)。"""
104
114
  cookies = {}
@@ -109,18 +119,20 @@ class BiliAPI:
109
119
  if dede_user_id:
110
120
  cookies["DedeUserID"] = dede_user_id
111
121
  if cookies:
112
- self.client.cookies.update(cookies)
122
+ self._runtime_cookies.update(cookies)
123
+ self.ensure_client().cookies.update(cookies)
113
124
 
114
125
  def has_login(self) -> bool:
115
- return bool(self.client.cookies.get("SESSDATA"))
126
+ return bool(self.ensure_client().cookies.get("SESSDATA"))
116
127
 
117
128
  async def close(self):
118
- await self.client.aclose()
129
+ if not self.client.is_closed:
130
+ await self.client.aclose()
119
131
 
120
132
  async def _get(self, url: str, params: Dict = None) -> Optional[Dict]:
121
133
  """GET请求"""
122
134
  try:
123
- resp = await self.client.get(url, params=params)
135
+ resp = await self.ensure_client().get(url, params=params)
124
136
  if resp.status_code != 200:
125
137
  logger.warning(f"API HTTP错误: {resp.status_code} - {url}")
126
138
  return None
@@ -134,10 +146,28 @@ class BiliAPI:
134
146
  return None
135
147
 
136
148
  async def get_user_info(self, uid: int) -> Optional[Dict]:
137
- """获取用户信息 (非WBI版本,避免-352风控)"""
138
- url = "https://api.bilibili.com/x/space/acc/info"
139
- data = await self._get(url, {"mid": uid})
140
- return data
149
+ """获取用户信息。
150
+
151
+ /x/space/acc/info 已被 B 站风控(-401 / -352),改用名片接口,
152
+ 再以直播批量接口兜底。
153
+ """
154
+ card = await self._get(
155
+ "https://api.bilibili.com/x/web-interface/card",
156
+ {"mid": uid},
157
+ )
158
+ info = (card or {}).get("card") or {}
159
+ if info.get("name"):
160
+ return {
161
+ "mid": info.get("mid", uid),
162
+ "name": info.get("name", ""),
163
+ "face": info.get("face", ""),
164
+ "sign": info.get("sign", ""),
165
+ }
166
+
167
+ live = await self.get_live_status(uid)
168
+ if live and live.get("name"):
169
+ return {"mid": uid, "name": live["name"], "face": live.get("face", "")}
170
+ return None
141
171
 
142
172
  async def get_user_name(self, uid: int) -> Optional[str]:
143
173
  """获取用户名"""
@@ -347,7 +377,7 @@ class BiliAPI:
347
377
  """获取用户直播状态。"""
348
378
  # 方法1: 原项目使用的批量直播状态接口
349
379
  try:
350
- resp = await self.client.get(LIVE_STATUS_BATCH, params={"uids[]": uid})
380
+ resp = await self.ensure_client().get(LIVE_STATUS_BATCH, params={"uids[]": uid})
351
381
  d = resp.json()
352
382
  if d.get("code") == 0:
353
383
  info = d.get("data", {}).get(str(uid), {})
@@ -383,7 +413,7 @@ class BiliAPI:
383
413
 
384
414
  # 方法2: 备用API
385
415
  try:
386
- resp = await self.client.post(LIVE_STATUS_BATCH, json={"uids": [uid]})
416
+ resp = await self.ensure_client().post(LIVE_STATUS_BATCH, json={"uids": [uid]})
387
417
  d = resp.json()
388
418
  if d.get("code") == 0:
389
419
  info = d.get("data", {}).get(str(uid), {})