koishi-plugin-steam-info-check 1.0.10 → 1.1.0

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 (32) hide show
  1. package/dist/index.js +59 -56
  2. package/nonebot-plugin-steam-info-main/.github/actions/setup-python/action.yml +21 -0
  3. package/nonebot-plugin-steam-info-main/.github/workflows/release.yml +37 -0
  4. package/nonebot-plugin-steam-info-main/LICENSE +21 -0
  5. package/nonebot-plugin-steam-info-main/README.md +117 -0
  6. package/nonebot-plugin-steam-info-main/fonts/MiSans-Bold.ttf +0 -0
  7. package/nonebot-plugin-steam-info-main/fonts/MiSans-Light.ttf +0 -0
  8. package/nonebot-plugin-steam-info-main/fonts/MiSans-Regular.ttf +0 -0
  9. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/__init__.py +487 -0
  10. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/config.py +19 -0
  11. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/data_source.py +264 -0
  12. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/draw.py +921 -0
  13. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/models.py +82 -0
  14. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/bg_dots.png +0 -0
  15. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/busy.png +0 -0
  16. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/default_achievement_image.png +0 -0
  17. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/default_header_image.jpg +0 -0
  18. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/friends_search.png +0 -0
  19. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/gaming.png +0 -0
  20. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/parent_status.png +0 -0
  21. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/unknown_avatar.jpg +0 -0
  22. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/zzz_gaming.png +0 -0
  23. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/res/zzz_online.png +0 -0
  24. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/steam.py +259 -0
  25. package/nonebot-plugin-steam-info-main/nonebot_plugin_steam_info/utils.py +112 -0
  26. package/nonebot-plugin-steam-info-main/pdm.lock +966 -0
  27. package/nonebot-plugin-steam-info-main/preview.png +0 -0
  28. package/nonebot-plugin-steam-info-main/preview_1.png +0 -0
  29. package/nonebot-plugin-steam-info-main/preview_2.png +0 -0
  30. package/nonebot-plugin-steam-info-main/pyproject.toml +29 -0
  31. package/package.json +1 -1
  32. package/src/index.ts +42 -58
package/dist/index.js CHANGED
@@ -291,59 +291,7 @@ async function ensureChannelMeta(ctx, session) {
291
291
  }
292
292
  // OneBot 群名补充
293
293
  if (!name && session.platform?.includes('onebot') && session.bot?.internal?.getGroupInfo) {
294
- // 柔性尝试多种参数传递方式,记录每次调用结果以便定位 napcat/onebot 的参数格式差异
295
- const argVariants = [
296
- { group_id: channelId },
297
- { group_id: { group_id: channelId } },
298
- { group_id: Number(channelId) },
299
- { group_id: { group_id: Number(channelId) } },
300
- ];
301
- // 先尝试对象参数变体
302
- for (const args of argVariants) {
303
- try {
304
- exports.logger.error(`getGroupInfo 尝试 args=${JSON.stringify(args)}`);
305
- const info = await session.bot.internal.getGroupInfo(args);
306
- exports.logger.error(`getGroupInfo 返回: ${JSON.stringify(info)}`);
307
- if (!info)
308
- continue;
309
- // 支持多种返回结构:直接 group_name、data.group_name(napcat)、或嵌套情况
310
- if (info.group_name) {
311
- name = info.group_name;
312
- break;
313
- }
314
- if (info.data && info.data.group_name) {
315
- name = info.data.group_name;
316
- break;
317
- }
318
- if (info.data && info.data.group && info.data.group.group_name) {
319
- name = info.data.group.group_name;
320
- break;
321
- }
322
- // 某些实现会把返回包在 ret.data 或直接在 ret
323
- if (info.ret && info.ret.data && info.ret.data.group_name) {
324
- name = info.ret.data.group_name;
325
- break;
326
- }
327
- // 如果未识别结构,记录并继续尝试下一个参数形态
328
- exports.logger.error('getGroupInfo 返回了未识别结构(尝试 参数:' + JSON.stringify(args) + '): ' + JSON.stringify(info) + ' EEE');
329
- }
330
- catch (err) {
331
- // 记录详细错误以便分析 retcode/args
332
- try {
333
- exports.logger.error('getGroupInfo 调用失败,args=' + JSON.stringify(args) + ',错误:' + String(err) + ' EEE');
334
- // 如果错误信息里包含 server-side 的 args 表示 RPC 层可能对参数进行了二次包装,记录原始错误便于排查
335
- if (err && err.message) {
336
- exports.logger.error('getGroupInfo 原始错误信息: ' + String(err.message));
337
- }
338
- }
339
- catch (e) {
340
- exports.logger.error('getGroupInfo 调用失败但记录 args 时出错:' + String(e) + ' EEE');
341
- }
342
- // 如果错误中包含 retcode,记录方便排查
343
- // 继续尝试下一个参数变体
344
- }
345
- }
346
- // 再尝试直接传入原始值(避免内部框架二次封装)
294
+ // 先尝试原始(primitive)参数,许多 adapter/napcat 期望直接的字符串或数字
347
295
  const primitiveVariants = [channelId, Number(channelId)];
348
296
  for (const arg of primitiveVariants) {
349
297
  try {
@@ -359,10 +307,67 @@ async function ensureChannelMeta(ctx, session) {
359
307
  name = info.data.group_name;
360
308
  break;
361
309
  }
310
+ if (info.data && info.data.group && info.data.group.group_name) {
311
+ name = info.data.group.group_name;
312
+ break;
313
+ }
314
+ if (info.ret && info.ret.data && info.ret.data.group_name) {
315
+ name = info.ret.data.group_name;
316
+ break;
317
+ }
362
318
  }
363
319
  }
364
320
  catch (err) {
365
321
  exports.logger.error('getGroupInfo 原始参数调用失败,arg=' + JSON.stringify(arg) + ',错误:' + String(err) + ' EEE');
322
+ if (err && err.message) {
323
+ exports.logger.error('getGroupInfo 原始错误信息: ' + String(err.message));
324
+ }
325
+ }
326
+ }
327
+ // 如果 primitive 未成功,再尝试对象参数包裹形式
328
+ if (!name) {
329
+ const argVariants = [
330
+ { group_id: channelId },
331
+ { group_id: { group_id: channelId } },
332
+ { group_id: Number(channelId) },
333
+ { group_id: { group_id: Number(channelId) } },
334
+ ];
335
+ for (const args of argVariants) {
336
+ try {
337
+ exports.logger.error(`getGroupInfo 尝试 args=${JSON.stringify(args)}`);
338
+ const info = await session.bot.internal.getGroupInfo(args);
339
+ exports.logger.error(`getGroupInfo 返回: ${JSON.stringify(info)}`);
340
+ if (!info)
341
+ continue;
342
+ if (info.group_name) {
343
+ name = info.group_name;
344
+ break;
345
+ }
346
+ if (info.data && info.data.group_name) {
347
+ name = info.data.group_name;
348
+ break;
349
+ }
350
+ if (info.data && info.data.group && info.data.group.group_name) {
351
+ name = info.data.group.group_name;
352
+ break;
353
+ }
354
+ if (info.ret && info.ret.data && info.ret.data.group_name) {
355
+ name = info.ret.data.group_name;
356
+ break;
357
+ }
358
+ exports.logger.error('getGroupInfo 返回了未识别结构(尝试 参数:' + JSON.stringify(args) + '): ' + JSON.stringify(info) + ' EEE');
359
+ }
360
+ catch (err) {
361
+ try {
362
+ exports.logger.error('getGroupInfo 调用失败,args=' + JSON.stringify(args) + ',错误:' + String(err) + ' EEE');
363
+ if (err && err.message) {
364
+ exports.logger.error('getGroupInfo 原始错误信息: ' + String(err.message));
365
+ }
366
+ }
367
+ catch (e) {
368
+ exports.logger.error('getGroupInfo 调用失败但记录 args 时出错:' + String(e) + ' EEE');
369
+ }
370
+ }
366
371
  }
367
372
  }
368
373
  // 所有尝试失败,记录最终失败并使用回退值
@@ -434,13 +439,11 @@ async function broadcast(ctx, config) {
434
439
  const oldGame = old.gameextrainfo;
435
440
  const newGame = current.gameextrainfo;
436
441
  const name = bind.nickname || current.personaname;
442
+ // 只在玩家开始游戏或从一个游戏切换到另一个游戏时推送
437
443
  if (newGame && !oldGame) {
438
444
  msgs.push(`${name} 开始玩 ${newGame} 了`);
439
445
  startGamingPlayers.push({ ...current, nickname: bind.nickname });
440
446
  }
441
- else if (!newGame && oldGame) {
442
- msgs.push(`${name} 玩了 ${oldGame} 后不玩了`);
443
- }
444
447
  else if (newGame && oldGame && newGame !== oldGame) {
445
448
  msgs.push(`${name} 停止玩 ${oldGame},开始玩 ${newGame} 了`);
446
449
  }
@@ -0,0 +1,21 @@
1
+ name: Setup Python
2
+ description: Setup Python
3
+
4
+ inputs:
5
+ python-version:
6
+ description: Python version
7
+ required: false
8
+ default: "3.10"
9
+
10
+ runs:
11
+ using: "composite"
12
+ steps:
13
+ - uses: pdm-project/setup-pdm@v3
14
+ name: Setup PDM
15
+ with:
16
+ python-version: ${{ inputs.python-version }}
17
+ architecture: "x64"
18
+ cache: true
19
+
20
+ - run: pdm sync -G:all
21
+ shell: bash
@@ -0,0 +1,37 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - v*
7
+
8
+ jobs:
9
+ pypi-publish:
10
+ name: upload release to PyPI
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ id-token: write
14
+ contents: write
15
+ steps:
16
+ - uses: actions/checkout@v3
17
+
18
+ - name: Setup Python environment
19
+ uses: ./.github/actions/setup-python
20
+
21
+ - name: Get Version
22
+ id: version
23
+ run: |
24
+ echo "VERSION=$(pdm show --version)" >> $GITHUB_OUTPUT
25
+ echo "TAG_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
26
+ echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
27
+
28
+ - name: Check Version
29
+ if: steps.version.outputs.VERSION != steps.version.outputs.TAG_VERSION
30
+ run: exit 1
31
+
32
+ - name: Publish Package
33
+ run: |
34
+ pdm publish
35
+ gh release upload --clobber ${{ steps.version.outputs.TAG_NAME }} dist/*.tar.gz dist/*.whl
36
+ env:
37
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Gitai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,117 @@
1
+ # Nonebot-Plugin-Steam-Info
2
+ ✨ Steam 好友状态播报 NoneBot 插件 ✨
3
+
4
+ ## 介绍
5
+
6
+ 这是一个基于 NoneBot2 的 Steam 好友状态播报插件,拥有绑定 Steam ID,查询群友状态,展示个人 Steam 主页等功能,支持跨平台,画图部分 100% 使用 Pillow 实现,较无头浏览器渲染更加轻量高效
7
+
8
+ ## 功能
9
+ - [x] 绑定 Steam ID
10
+ - [x] 群友状态变更播报
11
+ - [x] 群友游戏时间播报
12
+ - [x] 主动查询群友状态
13
+ - [x] 展示个人 Steam 主页
14
+
15
+ ## 预览
16
+ 仿照了 Steam 好友列表的样式
17
+
18
+ 图 1. 全部播报
19
+ ![image](./preview.png)
20
+
21
+ 图 2. 部分播报
22
+ ![image](./preview_1.png)
23
+
24
+ 图 3. 个人 Steam 主页
25
+ ![image](./preview_2.png)
26
+
27
+
28
+ ## 使用
29
+ | 命令 | 别名 | 说明 |
30
+ | --- | --- | --- |
31
+ | steambind [Steam ID 或 Steam好友代码] | 绑定steam | 绑定 Steam |
32
+ | steamunbind | 解绑steam | 解绑 Steam |
33
+ | steaminfo (可选)[@某人 或 Steam ID 或 Steam好友代码] | steam信息 | 查看个人主页 |
34
+ | steamcheck | 查看steam, 查steam | 查询群友 Steam 状态 |
35
+ | steamupdate [名称] [图片] | 更新群信息 | 更新群聊头像和名称 |
36
+ | steamenable | 启用steam | 启用群友状态播报 |
37
+ | steamdisable | 禁用steam | 禁用群友状态播报 |
38
+ | steamnickname [昵称] | steam昵称 | 设置 Steam 玩家昵称,用于辨识 Steam 名称与群昵称不一致的群友 |
39
+
40
+ > 记得加上你配置的命令头哦
41
+
42
+ ## 安装方法
43
+ <details open>
44
+ <summary>使用 nb-cli 安装</summary>
45
+ 在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
46
+
47
+ nb plugin install nonebot-plugin-steam-info
48
+
49
+ </details>
50
+
51
+ <details>
52
+ <summary>使用包管理器安装</summary>
53
+ 在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
54
+
55
+ <details>
56
+ <summary>pip</summary>
57
+
58
+ pip install nonebot-plugin-steam-info
59
+ </details>
60
+ <details>
61
+ <summary>pdm</summary>
62
+
63
+ pdm add nonebot-plugin-steam-info
64
+ </details>
65
+ <details>
66
+ <summary>poetry</summary>
67
+
68
+ poetry add nonebot-plugin-steam-info
69
+ </details>
70
+ <details>
71
+ <summary>conda</summary>
72
+
73
+ conda install nonebot-plugin-steam-info
74
+ </details>
75
+
76
+ 打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
77
+
78
+ plugins = ["nonebot_plugin_steam_info"]
79
+
80
+ </details>
81
+
82
+
83
+
84
+
85
+ ## 配置
86
+ 在 .env 文件中配置以下内容
87
+
88
+ | 配置项 | 默认值 | 说明 |
89
+ | --- | --- | --- |
90
+ | STEAM_API_KEY | 无 | Steam API Key,可以是一个字符串,也可以是一列表的字符串,即支持多个API Key,在 [此处](https://partner.steamgames.com/doc/webapi_overview/auth) 获取 |
91
+ | PROXY | 无 | 代理地址 |
92
+ | STEAM_REQUEST_INTERVAL | 300 | Steam 请求间隔 & 播报间隔。单位为秒 |
93
+ | STEAM_BROADCAST_TYPE | `"part"` | 播报类型。`"part"` 为部分播报(图 2),`"all"` 为全部播报(图 1),`"none"` 为只播报文字消息 |
94
+ | STEAM_DISABLE_BROADCAST_ON_STARTUP | `False` | Bot 启动时是否禁用播报 |
95
+ | STEAM_FONT_REGULAR_PATH | fonts/MiSans-Regular.ttf | Regular 字体相对目录 |
96
+ | STEAM_FONT_LIGHT_PATH | fonts/MiSans-Light.ttf | Light 字体相对目录 |
97
+ | STEAM_FONT_BOLD_PATH |fonts/MiSans-Bold.ttf | Bold 字体相对目录 |
98
+
99
+ 最后再把仓库中 `fonts` 文件夹放到 Bot 的 **运行目录** 下,配置就完毕啦
100
+
101
+ 在默认配置下,项目结构大致如下:
102
+ ```
103
+ your_project/
104
+ ├── bot.py
105
+ ├── .env.*
106
+ ├── fonts/
107
+ │ ├── MiSans-Regular.ttf
108
+ │ ├── MiSans-Light.ttf
109
+ │ └── MiSans-Bold.ttf
110
+ └── ...
111
+ ```
112
+
113
+ > 这里使用了 MiSans 字体,感谢 [MiSans](https://hyperos.mi.com/font/zh/)
114
+
115
+ > 如果你希望使用其他字体,请参考配置版块。
116
+
117
+ > 如果配置中不填写 `font/`,则会在`your_project/`下寻找字体文件。