nonebot-plugin-cs2radar 0.2.0__tar.gz → 0.2.1__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 (23) hide show
  1. nonebot_plugin_cs2radar-0.2.1/PKG-INFO +206 -0
  2. nonebot_plugin_cs2radar-0.2.1/README.md +173 -0
  3. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/__init__.py +93 -41
  4. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/crawler.py +59 -0
  5. nonebot_plugin_cs2radar-0.2.1/nonebot_plugin_cs2radar/llm.py +652 -0
  6. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/storage.py +4 -1
  7. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/pw_stats.html +95 -5
  8. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/stats.html +3 -3
  9. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/pyproject.toml +1 -1
  10. nonebot_plugin_cs2radar-0.2.0/PKG-INFO +0 -145
  11. nonebot_plugin_cs2radar-0.2.0/README.md +0 -112
  12. nonebot_plugin_cs2radar-0.2.0/nonebot_plugin_cs2radar/llm.py +0 -346
  13. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/.gitignore +0 -0
  14. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/LICENSE +0 -0
  15. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/binding_store.py +0 -0
  16. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/config.py +0 -0
  17. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/match_service.py +0 -0
  18. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/renderer.py +0 -0
  19. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/events.html +0 -0
  20. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/match_detail.html +0 -0
  21. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/match_results.html +0 -0
  22. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/matches.html +0 -0
  23. {nonebot_plugin_cs2radar-0.2.0 → nonebot_plugin_cs2radar-0.2.1}/nonebot_plugin_cs2radar/templates/player_detail.html +0 -0
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.5
2
+ Name: nonebot-plugin-cs2radar
3
+ Version: 0.2.1
4
+ Summary: NoneBot2 CS2 雷达插件,支持赛事/选手、5E、完美与官匹战绩查询及对局分析
5
+ Project-URL: Homepage, https://github.com/luojisama/nonebot-plugin-cs2radar
6
+ Project-URL: Repository, https://github.com/luojisama/nonebot-plugin-cs2radar
7
+ Project-URL: Bug Tracker, https://github.com/luojisama/nonebot-plugin-cs2radar/issues
8
+ Author-email: luojisama <2534316454@qq.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: 5e,cs2,csgo,nonebot,nonebot2,onebot,perfectworld
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Framework :: AsyncIO
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Communications :: Chat
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx>=0.23.0
25
+ Requires-Dist: jinja2>=3.0.0
26
+ Requires-Dist: nonebot-adapter-onebot>=2.2.0
27
+ Requires-Dist: nonebot-plugin-htmlrender>=0.6.0
28
+ Requires-Dist: nonebot-plugin-localstore>=0.6.0
29
+ Requires-Dist: nonebot2>=2.2.0
30
+ Requires-Dist: playwright>=1.30.0
31
+ Requires-Dist: pydantic<3.0,>=1.10
32
+ Description-Content-Type: text/markdown
33
+
34
+ # nonebot-plugin-cs2radar
35
+
36
+ NoneBot2 CS2 综合数据插件,支持职业选手查询、近期赛事与赛果、5E / 完美世界 / 官匹战绩查询、详细对局深度复盘及基于 HLTV 官方职业选手的智能战术画像与天梯瓶颈突破诊断。
37
+
38
+ ---
39
+
40
+ ## 功能特性
41
+
42
+ - **职业与赛事追踪**:支持查询 HLTV 职业选手资料卡、近期国际大赛赛程与赛果。
43
+ - **双平台天梯战绩**:支持 5E 对战平台(专属橙色主题)与完美世界电竞平台(科技蓝主题)综合生涯战绩查询,卡片视口统一为 960px 宽度并针对移动端进行排版优化。
44
+ - **智能战术画像与职业对标**:对接 HLTV 近 3 个月 Top 30 职业选手 7 维基准库(donk, b1t, ropz, sh1ro, m0NESY, apEX 等),将玩家数据结构化呈现为 4 维微卡片(【战力定位】【技术风格与职业对标】【偏科与武器地图】【天梯瓶颈突破】)。
45
+ - **零依赖智能兜底**:大模型未配置、网络超时或额度耗尽时,系统自动根据玩家真实 Rating、ADR、爆头率、首杀率及六维雷达指标进行智能模式匹配,100% 优雅生成结构化分析卡片。
46
+ - **单局详细复盘**:支持通过 `/match` 命令查询最近第 N 把比赛(5E、完美、官匹),呈现双方攻防半场走势、回合序列、击杀贡献与深度战局走势复盘。
47
+ - **元数据支持**:插件元数据内置完整的 `usage`、`extra["help"]` 与结构化 `extra["menu"]`,便于其他帮助插件或管理菜单反射查询。
48
+
49
+ ---
50
+
51
+ ## 安装
52
+
53
+ ### 使用 nb-cli
54
+
55
+ ```bash
56
+ nb plugin install nonebot-plugin-cs2radar
57
+ ```
58
+
59
+ ### 使用 pip
60
+
61
+ ```bash
62
+ pip install nonebot-plugin-cs2radar
63
+ ```
64
+
65
+ ### 安装 Playwright 渲染依赖
66
+
67
+ 本插件依赖 Playwright 渲染战绩图片,安装插件后需执行:
68
+
69
+ ```bash
70
+ playwright install chromium
71
+ ```
72
+
73
+ ---
74
+
75
+ ## 适配器支持
76
+
77
+ - `OneBot V11`
78
+
79
+ ---
80
+
81
+ ## 命令列表
82
+
83
+ | 命令 | 别名 | 参数说明 | 功能说明 |
84
+ | :--- | :--- | :--- | :--- |
85
+ | `cs查询` | `cs选手`, `csplayer` | `<选手名>` | 查询职业选手资料卡与能力评分 |
86
+ | `cs赛事` | `赛事`, `csgo赛事`, `cs2赛事` | 无 | 查询近期国际赛事与进行中赛程 |
87
+ | `赛果` | `cs赛果`, `赛事赛果` | 无 | 查询近几日完赛赛果与比分 |
88
+ | `5e` | `5e战绩`, `5e查询`, `cs战绩` | `[ID/昵称] [-r]` | 查询 5E 平台综合战绩与 4 维战术画像,无参数查绑定 |
89
+ | `pw` | `pw战绩`, `pw查询`, `完美战绩` | `[昵称/SteamID] [-r]` | 查询完美平台综合战绩与 4 维战术画像,无参数查绑定 |
90
+ | `pwlogin` | `完美登录` | `<手机号> <验证码>` | 登录完美世界电竞平台并保存本地会话 |
91
+ | `bind` | `绑定`, `添加`, `绑定用户` | `<5e\|pw> <玩家名>` | 绑定发送者 QQ 的常用查询玩家 |
92
+ | `match` | `战绩`, `查询战绩` | `[5e\|pw\|mm] [@群友] [局数] [-r]` | 查询指定平台最近第 N 把详细对局并生成四维战术复盘 |
93
+
94
+ > **提示**:查询命令后缀加上 `-r`(例如 `/pw 丰川NiKola -r` 或 `/5e -r`)可强制跳过本地缓存,刷新战绩与 AI 战术分析结果。
95
+
96
+ ---
97
+
98
+ ## 配置项说明
99
+
100
+ 环境变量统一使用 `cs2radar_*` 前缀;旧版 `cs_pro_*` 前缀保持向后兼容。在 NoneBot2 项目根目录的 `.env` 或 `.env.prod` 中按需配置:
101
+
102
+ ```env
103
+ # 基础配置
104
+ cs2radar_priority=5
105
+ cs2radar_http_timeout=15
106
+
107
+ # 主 LLM 配置
108
+ cs2radar_llm_enabled=true
109
+ cs2radar_llm_api_type=openai
110
+ cs2radar_llm_api_url=https://api.openai.com/v1
111
+ cs2radar_llm_api_key=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
112
+ cs2radar_llm_model=gpt-4o-mini
113
+ cs2radar_llm_timeout=30
114
+
115
+ # 备用 LLM 配置(可选容灾)
116
+ cs2radar_llm_backup_enabled=false
117
+ cs2radar_llm_backup_api_type=openai
118
+ cs2radar_llm_backup_api_url=https://api.openai.com/v1
119
+ cs2radar_llm_backup_api_key=
120
+ cs2radar_llm_backup_model=gpt-4o-mini
121
+ ```
122
+
123
+ ### 完整配置项清单
124
+
125
+ | 配置项 | 类型 | 默认值 | 旧版兼容名称 | 说明 |
126
+ | :--- | :--- | :--- | :--- | :--- |
127
+ | `cs2radar_priority` | int | `5` | `cs_pro_priority` | 插件事件响应优先级(1-20) |
128
+ | `cs2radar_bind_db_path` | str | `None` | `cs_pro_bind_db_path` | 账号绑定 SQLite 数据库路径,留空时默认存放在 localstore 数据目录 |
129
+ | `cs2radar_http_timeout` | int | `15` | `cs_pro_http_timeout` | 战绩与接口数据抓取超时时间(秒,5-60) |
130
+ | `cs2radar_llm_enabled` | bool | `true` | `cs_pro_llm_enabled` | 是否启用 LLM 战术分析与智能对标画像 |
131
+ | `cs2radar_llm_api_type` | str | `"openai"` | `cs_pro_llm_api_type` | 主大模型接口协议类型,支持 `openai`、`gemini`、`anthropic` |
132
+ | `cs2radar_llm_api_url` | str | `"https://api.openai.com/v1"` | `cs_pro_llm_api_url` | 主大模型接口 Base URL(支持各大中转/代理格式) |
133
+ | `cs2radar_llm_api_key` | str | `""` | `cs_pro_llm_api_key` | 主大模型 API Key(未配置时自动降级走智能动态兜底算法) |
134
+ | `cs2radar_llm_model` | str | `"gpt-4o-mini"` | `cs_pro_llm_model` | 主大模型调用模型名称 |
135
+ | `cs2radar_llm_timeout` | int | `30` | `cs_pro_llm_timeout` | 大模型请求超时时间(秒,5-120) |
136
+ | `cs2radar_llm_system_prompt` | str | `None` | `cs_pro_llm_system_prompt` | 自定义单局复盘 System Prompt(为空时使用内置电竞分析师预设) |
137
+ | `cs2radar_llm_backup_enabled` | bool | `false` | `cs_pro_llm_backup_enabled` | 是否启用备用大模型容灾链路 |
138
+ | `cs2radar_llm_backup_api_type` | str | `"openai"` | `cs_pro_llm_backup_api_type` | 备用大模型接口协议类型 |
139
+ | `cs2radar_llm_backup_api_url` | str | `"https://api.openai.com/v1"` | `cs_pro_llm_backup_api_url` | 备用大模型接口 Base URL |
140
+ | `cs2radar_llm_backup_api_key` | str | `""` | `cs_pro_llm_backup_api_key` | 备用大模型 API Key |
141
+ | `cs2radar_llm_backup_model` | str | `"gpt-4o-mini"` | `cs_pro_llm_backup_model` | 备用大模型调用模型名称 |
142
+
143
+ ---
144
+
145
+ ## 元数据与插件联动
146
+
147
+ 为便于第三方插件(如帮助菜单、权限管理或机器人总控后台)自动获取命令信息,本插件在 `__plugin_meta__` 中暴露了标准化的元数据结构:
148
+
149
+ ```python
150
+ from nonebot import get_plugin
151
+
152
+ plugin = get_plugin("nonebot_plugin_cs2radar")
153
+ if plugin and plugin.metadata:
154
+ # 纯文本帮助内容
155
+ help_text = plugin.metadata.usage
156
+ # 或者通过 extra 读取扩展字典
157
+ menu_list = plugin.metadata.extra.get("menu", [])
158
+ config_dict = plugin.metadata.extra.get("configs", {})
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 数据存储与旧版本迁移
164
+
165
+ 插件严格遵循 NoneBot2 `nonebot-plugin-localstore` 标准规范,自动管理数据与持久化存储。启动时会自动检测并平滑迁移旧版本(如 `data/cs_pro/`)中的以下历史文件:
166
+
167
+ - `user_bindings.db`(用户平台绑定数据)
168
+ - `user_data.db` / `user_data.json`(历史战绩缓存)
169
+ - `pw_session.json`(完美平台登录态)
170
+
171
+ ---
172
+
173
+ ## 常见问题
174
+
175
+ ### 1. 提示找不到浏览器或渲染失败
176
+ Playwright 核心依赖未安装,请在运行环境中执行:
177
+ ```bash
178
+ playwright install chromium
179
+ ```
180
+
181
+ ### 2. 完美战绩查询提示请先登录
182
+ 完美世界官方接口需要已绑定的移动端登录态。初次使用时请执行一次:
183
+ ```text
184
+ /pwlogin <手机号> <验证码>
185
+ ```
186
+ 会话态将加密保存在本地并自动保持心跳。
187
+
188
+ ### 3. 未配置大模型或 API 欠费时能否正常使用?
189
+ 可以。插件内置了全量智能动态兜底算法。当未配置 API Key 或上游接口不可用时,系统会自动基于玩家的实际数据(Rating、ADR、爆头率、首杀率及雷达指标)对标职业选手并输出 4 维微报告,不会中断查询流程。
190
+
191
+ ---
192
+
193
+ ## 构建与发布
194
+
195
+ 本仓库已配置 GitHub Actions 自动构建与发布工作流。推送语义化版本 Tag 即可自动构建并发布 Wheel 至 PyPI:
196
+
197
+ ```bash
198
+ git tag v0.2.1
199
+ git push origin v0.2.1
200
+ ```
201
+
202
+ ---
203
+
204
+ ## License
205
+
206
+ [MIT](LICENSE)
@@ -0,0 +1,173 @@
1
+ # nonebot-plugin-cs2radar
2
+
3
+ NoneBot2 CS2 综合数据插件,支持职业选手查询、近期赛事与赛果、5E / 完美世界 / 官匹战绩查询、详细对局深度复盘及基于 HLTV 官方职业选手的智能战术画像与天梯瓶颈突破诊断。
4
+
5
+ ---
6
+
7
+ ## 功能特性
8
+
9
+ - **职业与赛事追踪**:支持查询 HLTV 职业选手资料卡、近期国际大赛赛程与赛果。
10
+ - **双平台天梯战绩**:支持 5E 对战平台(专属橙色主题)与完美世界电竞平台(科技蓝主题)综合生涯战绩查询,卡片视口统一为 960px 宽度并针对移动端进行排版优化。
11
+ - **智能战术画像与职业对标**:对接 HLTV 近 3 个月 Top 30 职业选手 7 维基准库(donk, b1t, ropz, sh1ro, m0NESY, apEX 等),将玩家数据结构化呈现为 4 维微卡片(【战力定位】【技术风格与职业对标】【偏科与武器地图】【天梯瓶颈突破】)。
12
+ - **零依赖智能兜底**:大模型未配置、网络超时或额度耗尽时,系统自动根据玩家真实 Rating、ADR、爆头率、首杀率及六维雷达指标进行智能模式匹配,100% 优雅生成结构化分析卡片。
13
+ - **单局详细复盘**:支持通过 `/match` 命令查询最近第 N 把比赛(5E、完美、官匹),呈现双方攻防半场走势、回合序列、击杀贡献与深度战局走势复盘。
14
+ - **元数据支持**:插件元数据内置完整的 `usage`、`extra["help"]` 与结构化 `extra["menu"]`,便于其他帮助插件或管理菜单反射查询。
15
+
16
+ ---
17
+
18
+ ## 安装
19
+
20
+ ### 使用 nb-cli
21
+
22
+ ```bash
23
+ nb plugin install nonebot-plugin-cs2radar
24
+ ```
25
+
26
+ ### 使用 pip
27
+
28
+ ```bash
29
+ pip install nonebot-plugin-cs2radar
30
+ ```
31
+
32
+ ### 安装 Playwright 渲染依赖
33
+
34
+ 本插件依赖 Playwright 渲染战绩图片,安装插件后需执行:
35
+
36
+ ```bash
37
+ playwright install chromium
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 适配器支持
43
+
44
+ - `OneBot V11`
45
+
46
+ ---
47
+
48
+ ## 命令列表
49
+
50
+ | 命令 | 别名 | 参数说明 | 功能说明 |
51
+ | :--- | :--- | :--- | :--- |
52
+ | `cs查询` | `cs选手`, `csplayer` | `<选手名>` | 查询职业选手资料卡与能力评分 |
53
+ | `cs赛事` | `赛事`, `csgo赛事`, `cs2赛事` | 无 | 查询近期国际赛事与进行中赛程 |
54
+ | `赛果` | `cs赛果`, `赛事赛果` | 无 | 查询近几日完赛赛果与比分 |
55
+ | `5e` | `5e战绩`, `5e查询`, `cs战绩` | `[ID/昵称] [-r]` | 查询 5E 平台综合战绩与 4 维战术画像,无参数查绑定 |
56
+ | `pw` | `pw战绩`, `pw查询`, `完美战绩` | `[昵称/SteamID] [-r]` | 查询完美平台综合战绩与 4 维战术画像,无参数查绑定 |
57
+ | `pwlogin` | `完美登录` | `<手机号> <验证码>` | 登录完美世界电竞平台并保存本地会话 |
58
+ | `bind` | `绑定`, `添加`, `绑定用户` | `<5e\|pw> <玩家名>` | 绑定发送者 QQ 的常用查询玩家 |
59
+ | `match` | `战绩`, `查询战绩` | `[5e\|pw\|mm] [@群友] [局数] [-r]` | 查询指定平台最近第 N 把详细对局并生成四维战术复盘 |
60
+
61
+ > **提示**:查询命令后缀加上 `-r`(例如 `/pw 丰川NiKola -r` 或 `/5e -r`)可强制跳过本地缓存,刷新战绩与 AI 战术分析结果。
62
+
63
+ ---
64
+
65
+ ## 配置项说明
66
+
67
+ 环境变量统一使用 `cs2radar_*` 前缀;旧版 `cs_pro_*` 前缀保持向后兼容。在 NoneBot2 项目根目录的 `.env` 或 `.env.prod` 中按需配置:
68
+
69
+ ```env
70
+ # 基础配置
71
+ cs2radar_priority=5
72
+ cs2radar_http_timeout=15
73
+
74
+ # 主 LLM 配置
75
+ cs2radar_llm_enabled=true
76
+ cs2radar_llm_api_type=openai
77
+ cs2radar_llm_api_url=https://api.openai.com/v1
78
+ cs2radar_llm_api_key=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
79
+ cs2radar_llm_model=gpt-4o-mini
80
+ cs2radar_llm_timeout=30
81
+
82
+ # 备用 LLM 配置(可选容灾)
83
+ cs2radar_llm_backup_enabled=false
84
+ cs2radar_llm_backup_api_type=openai
85
+ cs2radar_llm_backup_api_url=https://api.openai.com/v1
86
+ cs2radar_llm_backup_api_key=
87
+ cs2radar_llm_backup_model=gpt-4o-mini
88
+ ```
89
+
90
+ ### 完整配置项清单
91
+
92
+ | 配置项 | 类型 | 默认值 | 旧版兼容名称 | 说明 |
93
+ | :--- | :--- | :--- | :--- | :--- |
94
+ | `cs2radar_priority` | int | `5` | `cs_pro_priority` | 插件事件响应优先级(1-20) |
95
+ | `cs2radar_bind_db_path` | str | `None` | `cs_pro_bind_db_path` | 账号绑定 SQLite 数据库路径,留空时默认存放在 localstore 数据目录 |
96
+ | `cs2radar_http_timeout` | int | `15` | `cs_pro_http_timeout` | 战绩与接口数据抓取超时时间(秒,5-60) |
97
+ | `cs2radar_llm_enabled` | bool | `true` | `cs_pro_llm_enabled` | 是否启用 LLM 战术分析与智能对标画像 |
98
+ | `cs2radar_llm_api_type` | str | `"openai"` | `cs_pro_llm_api_type` | 主大模型接口协议类型,支持 `openai`、`gemini`、`anthropic` |
99
+ | `cs2radar_llm_api_url` | str | `"https://api.openai.com/v1"` | `cs_pro_llm_api_url` | 主大模型接口 Base URL(支持各大中转/代理格式) |
100
+ | `cs2radar_llm_api_key` | str | `""` | `cs_pro_llm_api_key` | 主大模型 API Key(未配置时自动降级走智能动态兜底算法) |
101
+ | `cs2radar_llm_model` | str | `"gpt-4o-mini"` | `cs_pro_llm_model` | 主大模型调用模型名称 |
102
+ | `cs2radar_llm_timeout` | int | `30` | `cs_pro_llm_timeout` | 大模型请求超时时间(秒,5-120) |
103
+ | `cs2radar_llm_system_prompt` | str | `None` | `cs_pro_llm_system_prompt` | 自定义单局复盘 System Prompt(为空时使用内置电竞分析师预设) |
104
+ | `cs2radar_llm_backup_enabled` | bool | `false` | `cs_pro_llm_backup_enabled` | 是否启用备用大模型容灾链路 |
105
+ | `cs2radar_llm_backup_api_type` | str | `"openai"` | `cs_pro_llm_backup_api_type` | 备用大模型接口协议类型 |
106
+ | `cs2radar_llm_backup_api_url` | str | `"https://api.openai.com/v1"` | `cs_pro_llm_backup_api_url` | 备用大模型接口 Base URL |
107
+ | `cs2radar_llm_backup_api_key` | str | `""` | `cs_pro_llm_backup_api_key` | 备用大模型 API Key |
108
+ | `cs2radar_llm_backup_model` | str | `"gpt-4o-mini"` | `cs_pro_llm_backup_model` | 备用大模型调用模型名称 |
109
+
110
+ ---
111
+
112
+ ## 元数据与插件联动
113
+
114
+ 为便于第三方插件(如帮助菜单、权限管理或机器人总控后台)自动获取命令信息,本插件在 `__plugin_meta__` 中暴露了标准化的元数据结构:
115
+
116
+ ```python
117
+ from nonebot import get_plugin
118
+
119
+ plugin = get_plugin("nonebot_plugin_cs2radar")
120
+ if plugin and plugin.metadata:
121
+ # 纯文本帮助内容
122
+ help_text = plugin.metadata.usage
123
+ # 或者通过 extra 读取扩展字典
124
+ menu_list = plugin.metadata.extra.get("menu", [])
125
+ config_dict = plugin.metadata.extra.get("configs", {})
126
+ ```
127
+
128
+ ---
129
+
130
+ ## 数据存储与旧版本迁移
131
+
132
+ 插件严格遵循 NoneBot2 `nonebot-plugin-localstore` 标准规范,自动管理数据与持久化存储。启动时会自动检测并平滑迁移旧版本(如 `data/cs_pro/`)中的以下历史文件:
133
+
134
+ - `user_bindings.db`(用户平台绑定数据)
135
+ - `user_data.db` / `user_data.json`(历史战绩缓存)
136
+ - `pw_session.json`(完美平台登录态)
137
+
138
+ ---
139
+
140
+ ## 常见问题
141
+
142
+ ### 1. 提示找不到浏览器或渲染失败
143
+ Playwright 核心依赖未安装,请在运行环境中执行:
144
+ ```bash
145
+ playwright install chromium
146
+ ```
147
+
148
+ ### 2. 完美战绩查询提示请先登录
149
+ 完美世界官方接口需要已绑定的移动端登录态。初次使用时请执行一次:
150
+ ```text
151
+ /pwlogin <手机号> <验证码>
152
+ ```
153
+ 会话态将加密保存在本地并自动保持心跳。
154
+
155
+ ### 3. 未配置大模型或 API 欠费时能否正常使用?
156
+ 可以。插件内置了全量智能动态兜底算法。当未配置 API Key 或上游接口不可用时,系统会自动基于玩家的实际数据(Rating、ADR、爆头率、首杀率及雷达指标)对标职业选手并输出 4 维微报告,不会中断查询流程。
157
+
158
+ ---
159
+
160
+ ## 构建与发布
161
+
162
+ 本仓库已配置 GitHub Actions 自动构建与发布工作流。推送语义化版本 Tag 即可自动构建并发布 Wheel 至 PyPI:
163
+
164
+ ```bash
165
+ git tag v0.2.1
166
+ git push origin v0.2.1
167
+ ```
168
+
169
+ ---
170
+
171
+ ## License
172
+
173
+ [MIT](LICENSE)
@@ -27,7 +27,7 @@ from .renderer import (
27
27
  )
28
28
  from .storage import get_bind_db_path
29
29
 
30
- __version__ = "0.2.0"
30
+ __version__ = "0.2.1"
31
31
 
32
32
  plugin_config = get_plugin_config(Config)
33
33
  driver_config = get_driver().config
@@ -52,19 +52,25 @@ for legacy_name in (
52
52
  if getattr(plugin_config, legacy_name, None) is not None:
53
53
  logger.warning(f"[nonebot_plugin_cs2radar] `{legacy_name}` is deprecated; migrate to `cs2radar_*` config names.")
54
54
 
55
+ _USAGE_HELP = """CS2 Radar 插件命令一览:
56
+ 1. 职业与赛事:
57
+ - cs查询 <选手名> - 查询职业选手资料卡与能力评分 (别名: cs选手, csplayer)
58
+ - cs赛事 - 查询近期重要赛事与进行中比赛 (别名: 赛事, csgo赛事, cs2赛事)
59
+ - 赛果 - 查询近几日完赛比分与赛果 (别名: cs赛果, 赛事赛果)
60
+ 2. 平台生涯战绩:
61
+ - 5e [ID/昵称] [-r] - 查询 5E 平台综合战绩与 4 维智能战术画像 (别名: 5e战绩, 5e查询, cs战绩)
62
+ - pw [昵称/SteamID] [-r] - 查询完美平台综合战绩与 4 维智能战术画像 (别名: pw战绩, pw查询, 完美战绩)
63
+ - pwlogin <手机号> <验证码> - 登录完美世界电竞平台并保存本地会话 (别名: 完美登录)
64
+ 3. 账号绑定与复盘:
65
+ - bind <5e|pw> <玩家名> - 绑定当前 QQ 的默认查询对象 (别名: 绑定, 添加)
66
+ - match [5e|pw|mm] [@群友] [局数] [-r] - 查询最近第 N 把详细对局并生成四维战术复盘 (别名: 战绩, 查询战绩)
67
+
68
+ 说明:命令支持 [-r] 参数强制刷新战绩与 AI 战术分析缓存。未配置大模型时会自动基于选手真实数据智能对标职业哥并诊断天梯瓶颈。"""
69
+
55
70
  __plugin_meta__ = PluginMetadata(
56
71
  name="CS2 Radar",
57
72
  description="CS2 赛事、选手、5E/完美/官匹战绩查询与详细对局分析",
58
- usage=(
59
- "cs查询 [选手]\n"
60
- "cs赛事\n"
61
- "赛果\n"
62
- "5e [ID/昵称] [-r]\n"
63
- "pw [ID/昵称/SteamID] [-r]\n"
64
- "pwlogin [手机号] [验证码]\n"
65
- "bind [5e|pw] [玩家名]\n"
66
- "match [platform] [@群友] [round] [-r]"
67
- ),
73
+ usage=_USAGE_HELP,
68
74
  type="application",
69
75
  homepage="https://github.com/luojisama/nonebot-plugin-cs2radar",
70
76
  config=Config,
@@ -73,6 +79,34 @@ __plugin_meta__ = PluginMetadata(
73
79
  "author": "luojisama",
74
80
  "version": __version__,
75
81
  "pypi": "nonebot-plugin-cs2radar",
82
+ "help": _USAGE_HELP,
83
+ "menu": [
84
+ {"cmd": "cs查询 <选手>", "desc": "查询职业选手战队与技术画像", "alias": ["cs选手", "csplayer"]},
85
+ {"cmd": "cs赛事", "desc": "查询近期国际大赛与重要赛程", "alias": ["赛事", "csgo赛事", "cs2赛事"]},
86
+ {"cmd": "赛果", "desc": "查询近几日比赛赛果与比分", "alias": ["cs赛果", "赛事赛果"]},
87
+ {"cmd": "5e [ID/昵称] [-r]", "desc": "查询 5E 平台综合战绩与 4 维智能战术画像", "alias": ["5e战绩", "5e查询", "cs战绩"]},
88
+ {"cmd": "pw [ID/昵称/SteamID] [-r]", "desc": "查询完美平台综合战绩与 4 维智能战术画像", "alias": ["pw战绩", "pw查询", "完美战绩"]},
89
+ {"cmd": "pwlogin <手机号> <验证码>", "desc": "登录完美平台获取会话态", "alias": ["完美登录"]},
90
+ {"cmd": "bind <5e|pw> <玩家名>", "desc": "绑定当前 QQ 的常用查询玩家", "alias": ["绑定", "添加"]},
91
+ {"cmd": "match [5e|pw|mm] [@群友] [局数] [-r]", "desc": "查询最近第 N 把详细对局并生成四维战术复盘", "alias": ["战绩", "查询战绩"]},
92
+ ],
93
+ "configs": {
94
+ "cs2radar_priority": "插件优先级 (默认: 5)",
95
+ "cs2radar_bind_db_path": "绑定数据库路径 (默认: 自动定位至 localstore)",
96
+ "cs2radar_http_timeout": "HTTP 请求超时秒数 (默认: 15)",
97
+ "cs2radar_llm_enabled": "是否启用 LLM 战术分析与智能对标 (默认: true)",
98
+ "cs2radar_llm_api_type": "LLM 接口类型 (openai/gemini/anthropic, 默认: openai)",
99
+ "cs2radar_llm_api_url": "LLM 接口地址 (默认: https://api.openai.com/v1)",
100
+ "cs2radar_llm_api_key": "LLM API Key",
101
+ "cs2radar_llm_model": "LLM 模型名称 (默认: gpt-4o-mini)",
102
+ "cs2radar_llm_backup_enabled": "是否启用备用 LLM (默认: false)",
103
+ "cs2radar_llm_backup_api_type": "备用 LLM 接口类型",
104
+ "cs2radar_llm_backup_api_url": "备用 LLM 接口地址",
105
+ "cs2radar_llm_backup_api_key": "备用 LLM API Key",
106
+ "cs2radar_llm_backup_model": "备用 LLM 模型名称",
107
+ "cs2radar_llm_timeout": "LLM 请求超时秒数 (默认: 30)",
108
+ "cs2radar_llm_system_prompt": "自定义战术复盘 System Prompt",
109
+ },
76
110
  },
77
111
  )
78
112
 
@@ -171,7 +205,7 @@ def _parse_llm_sections(text: str) -> list[dict]:
171
205
  return [{"tag": "复盘点评", "content": text.strip()}]
172
206
 
173
207
 
174
- def _build_profile_context_5e(data: dict) -> dict:
208
+ def _build_profile_context_5e(data: dict, hltv_benchmarks: list[dict] | None = None) -> dict:
175
209
  nickname = data.get("nickname", "5E玩家")
176
210
  stats = data.get("stats", {})
177
211
  career = stats.get("career", {})
@@ -205,7 +239,7 @@ def _build_profile_context_5e(data: dict) -> dict:
205
239
  "adr": rm.get("adr"),
206
240
  })
207
241
 
208
- return {
242
+ ctx = {
209
243
  "platform": "5E ARENA 对战平台",
210
244
  "player_name": nickname,
211
245
  "elo": career.get("elo_9") or career.get("elo", 0),
@@ -224,9 +258,12 @@ def _build_profile_context_5e(data: dict) -> dict:
224
258
  "role_level": role.get("score_level", ""),
225
259
  "recent_matches": recent_list,
226
260
  }
261
+ if hltv_benchmarks:
262
+ ctx["hltv_pro_benchmarks"] = hltv_benchmarks[:6]
263
+ return ctx
227
264
 
228
265
 
229
- def _build_profile_context(data: dict) -> dict:
266
+ def _build_profile_context(data: dict, hltv_benchmarks: list[dict] | None = None) -> dict:
230
267
  summary = data.get("summary", {})
231
268
  stats = data.get("stats", {})
232
269
  recent_matches = data.get("recent_matches", [])
@@ -258,7 +295,7 @@ def _build_profile_context(data: dict) -> dict:
258
295
  for rm in recent_matches[:5]
259
296
  ]
260
297
 
261
- return {
298
+ ctx = {
262
299
  "player_name": summary.get("nickname", "未知"),
263
300
  "steam_id": str(summary.get("steamId", "")),
264
301
  "season": stats.get("seasonId", "当前赛季"),
@@ -288,6 +325,9 @@ def _build_profile_context(data: dict) -> dict:
288
325
  "hot_weapons": hot_weapons,
289
326
  "recent_matches": recent_list
290
327
  }
328
+ if hltv_benchmarks:
329
+ ctx["hltv_pro_benchmarks"] = hltv_benchmarks[:6]
330
+ return ctx
291
331
 
292
332
 
293
333
  def _build_match_view_data(match_data, llm_title: str, llm_detail: str) -> dict:
@@ -439,15 +479,25 @@ async def handle_match(bot: Bot, event: MessageEvent, args: Message = CommandArg
439
479
  except Exception as e:
440
480
  await match_cmd.finish(f"查询失败: {e}")
441
481
 
442
- llm_title = "评价暂不可用"
443
- llm_detail = "未配置或调用失败,本次仅展示战绩数据。"
482
+ llm_title = "风格待定"
483
+ llm_detail = "【战局走势】比赛数据分析中。【核心表现】战术复盘计算中。【团队对比】正在比对双方攻防数据。【改进建议】保持稳定沟通与道具配合。"
444
484
  try:
445
485
  result = await llm.evaluate(match_data.llm_context(), refresh=refresh)
446
486
  if result:
447
487
  llm_title = result.title
448
488
  llm_detail = result.detail
489
+ else:
490
+ fallback = llm._generate_smart_match_fallback(match_data.llm_context())
491
+ llm_title = fallback.title
492
+ llm_detail = fallback.detail
449
493
  except Exception as e:
450
494
  logger.warning(f"[cs2radar] llm evaluate failed: {e}")
495
+ try:
496
+ fallback = llm._generate_smart_match_fallback(match_data.llm_context())
497
+ llm_title = fallback.title
498
+ llm_detail = fallback.detail
499
+ except Exception:
500
+ pass
451
501
 
452
502
  view_data = _build_match_view_data(match_data, llm_title, llm_detail)
453
503
  image_bytes = await render_match_detail_card(view_data)
@@ -591,7 +641,12 @@ async def handle_five_e_stats(bot: Bot, event: MessageEvent, arg: Message = Comm
591
641
 
592
642
  # 生成 / 获取 LLM 主页评价
593
643
  try:
594
- profile_ctx = _build_profile_context_5e(data)
644
+ benchmarks = []
645
+ try:
646
+ benchmarks = await event_crawler.get_hltv_pro_benchmarks()
647
+ except Exception:
648
+ pass
649
+ profile_ctx = _build_profile_context_5e(data, hltv_benchmarks=benchmarks)
595
650
  career = data.get("stats", {}).get("career", {})
596
651
  cnt = int(career.get("match_total") or 0)
597
652
  season_id = str(career.get("best_season") or "")
@@ -603,19 +658,15 @@ async def handle_five_e_stats(bot: Bot, event: MessageEvent, arg: Message = Comm
603
658
  match_cnt=cnt,
604
659
  season_id=season_id,
605
660
  )
606
- if llm_res:
607
- data["llm_title"] = llm_res.title
608
- data["llm_detail"] = llm_res.detail
609
- data["llm_sections"] = _parse_llm_sections(llm_res.detail)
610
- else:
611
- data["llm_title"] = "天梯强力进攻先锋"
612
- data["llm_detail"] = "【战力定位】在5E高分天梯打出极高攻防效率。【技术风格】拼抢激进,单兵摧毁力强。【武器地图】主力枪械覆盖全面。【进阶建议】保持进攻侵略性,协同团队进退。"
613
- data["llm_sections"] = _parse_llm_sections(data["llm_detail"])
661
+ data["llm_title"] = llm_res.title
662
+ data["llm_detail"] = llm_res.detail
663
+ data["llm_sections"] = _parse_llm_sections(llm_res.detail)
614
664
  except Exception as e:
615
665
  logger.warning(f"生成5E主页LLM评价失败: {e}")
616
- data["llm_title"] = "天梯强力进攻先锋"
617
- data["llm_detail"] = "【战力定位】在5E高分天梯打出极高攻防效率。【技术风格】拼抢激进,单兵摧毁力强。【武器地图】主力枪械覆盖全面。【进阶建议】保持进攻侵略性,协同团队进退。"
618
- data["llm_sections"] = _parse_llm_sections(data["llm_detail"])
666
+ fallback_res = llm._generate_smart_profile_fallback(_build_profile_context_5e(data))
667
+ data["llm_title"] = fallback_res.title
668
+ data["llm_detail"] = fallback_res.detail
669
+ data["llm_sections"] = _parse_llm_sections(fallback_res.detail)
619
670
 
620
671
  image_bytes = await render_stats_card(data)
621
672
  await five_e_stats.finish(MessageSegment.image(image_bytes))
@@ -714,7 +765,12 @@ async def handle_pw_stats(bot: Bot, event: MessageEvent, arg: Message = CommandA
714
765
 
715
766
  # 生成 / 获取 LLM 主页评价
716
767
  try:
717
- profile_ctx = _build_profile_context(data)
768
+ benchmarks = []
769
+ try:
770
+ benchmarks = await event_crawler.get_hltv_pro_benchmarks()
771
+ except Exception:
772
+ pass
773
+ profile_ctx = _build_profile_context(data, hltv_benchmarks=benchmarks)
718
774
  cnt = data.get("stats", {}).get("cnt", 0)
719
775
  season_id = str(data.get("stats", {}).get("seasonId") or "")
720
776
  llm_res = await llm.evaluate_profile(
@@ -724,19 +780,15 @@ async def handle_pw_stats(bot: Bot, event: MessageEvent, arg: Message = CommandA
724
780
  match_cnt=cnt,
725
781
  season_id=season_id,
726
782
  )
727
- if llm_res:
728
- data["llm_title"] = llm_res.title
729
- data["llm_detail"] = llm_res.detail
730
- data["llm_sections"] = _parse_llm_sections(llm_res.detail)
731
- else:
732
- data["llm_title"] = "全能型竞技核心"
733
- data["llm_detail"] = "该玩家数据积累中,展现出扎实的技术功底与极高的成长潜力。"
734
- data["llm_sections"] = []
783
+ data["llm_title"] = llm_res.title
784
+ data["llm_detail"] = llm_res.detail
785
+ data["llm_sections"] = _parse_llm_sections(llm_res.detail)
735
786
  except Exception as e:
736
787
  logger.warning(f"生成主页LLM评价失败: {e}")
737
- data["llm_title"] = "全能型竞技核心"
738
- data["llm_detail"] = "该玩家数据积累中,展现出扎实的技术功底与极高的成长潜力。"
739
- data["llm_sections"] = []
788
+ fallback_res = llm._generate_smart_profile_fallback(_build_profile_context(data))
789
+ data["llm_title"] = fallback_res.title
790
+ data["llm_detail"] = fallback_res.detail
791
+ data["llm_sections"] = _parse_llm_sections(fallback_res.detail)
740
792
 
741
793
  image_bytes = await render_pw_stats_card(data)
742
794
  await pw_stats.finish(MessageSegment.image(image_bytes))