nonebot-plugin-maimaidx 3.1.2__tar.gz → 3.1.5__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.
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/PKG-INFO +14 -26
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/README.md +12 -24
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/__init__.py +2 -10
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/__init__.py +0 -1
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/depend.py +8 -2
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/mai_base.py +30 -32
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/mai_score.py +49 -40
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/mai_table.py +18 -18
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/config.py +0 -1
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/constants.py +14 -1
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/divingfish/client.py +9 -65
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/divingfish/models/__init__.py +8 -18
- nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/clients/divingfish/models/records.py +18 -0
- nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/clients/divingfish/models/score.py +57 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/handler.py +69 -72
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/handler_error.py +13 -8
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/rating_table.py +37 -28
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/__init__.py +6 -3
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/score.py +3 -2
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/play_result.py +5 -7
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/player.py +22 -5
- nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/oauth/__init__.py +59 -0
- nonebot_plugin_maimaidx-3.1.2/nonebot_plugin_maimaidx/commands/oauth_message.py → nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/oauth/message.py +2 -2
- {nonebot_plugin_maimaidx-3.1.2/nonebot_plugin_maimaidx/core → nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/oauth}/pending_binding.py +1 -1
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx.egg-info/PKG-INFO +14 -26
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx.egg-info/SOURCES.txt +6 -4
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx.egg-info/requires.txt +1 -1
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/pyproject.toml +2 -2
- nonebot_plugin_maimaidx-3.1.2/nonebot_plugin_maimaidx/core/clients/divingfish/models/score.py +0 -83
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/LICENSE +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/mai_alias.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/mai_guess.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/commands/mai_search.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/alias_sse_push.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/divingfish/exceptions.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/divingfish/models/music.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/divingfish/models/oauth.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/divingfish/oauth.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/exceptions.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/http.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/client.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/exceptions.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/__init__.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/base.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/collection.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/enum.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/music.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/oauth.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/player.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/lxns/models/score.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/client.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/exceptions.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/models/__init__.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/models/alias.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/models/enum.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/models/message.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/models/sse.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/clients/yuzuchan/models/status.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/database/qq.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/__init__.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/assets.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/base.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/best50.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/chart.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/info.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/plate_table.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/score.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/song.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/tools.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/image/update_table.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/alias.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/alias_list.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/__init__.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/alias.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/best50.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/enum.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/guess.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/player.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/models/song.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/merge/music_list.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2/nonebot_plugin_maimaidx/core → nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/oauth}/divingfish_oauth.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2/nonebot_plugin_maimaidx/core → nonebot_plugin_maimaidx-3.1.5/nonebot_plugin_maimaidx/core/oauth}/lxns_oauth.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/service/__init__.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/service/diving_fish.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/service/lxns.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/service/yuzuchan.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/tool.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/core/utils/calc.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/maimaidxhelp.png +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/resources.py +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx.egg-info/dependency_links.txt +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx.egg-info/top_level.txt +0 -0
- {nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nonebot-plugin-maimaidx
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.5
|
|
4
4
|
Summary: maimaidx plugin for nonebot2
|
|
5
5
|
Author-email: Yuri-YuzuChaN <806235364@qq.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -14,7 +14,7 @@ License-File: LICENSE
|
|
|
14
14
|
Requires-Dist: nonebot2<3.0.0,>=2.0.0
|
|
15
15
|
Requires-Dist: nonebot-adapter-onebot<3.0.0,>=2.2.2
|
|
16
16
|
Requires-Dist: nonebot-plugin-apscheduler<1.0.0,>=0.3.0
|
|
17
|
-
Requires-Dist: aiofiles
|
|
17
|
+
Requires-Dist: aiofiles>=23.2.1
|
|
18
18
|
Requires-Dist: httpx<1.0.0,>=0.23.1
|
|
19
19
|
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
20
20
|
Requires-Dist: pyecharts<3.0.0,>=2.0.0
|
|
@@ -40,6 +40,17 @@ Dynamic: license-file
|
|
|
40
40
|
|
|
41
41
|
## 重要更新
|
|
42
42
|
|
|
43
|
+
**2026-11-02**
|
|
44
|
+
|
|
45
|
+
1. 新版本已完全废弃水鱼开发者Token,请前往水鱼 [开发者控制台](https://auth.diving-fish.com/console) 申请新应用,使用OAuth认证,未配置或者未授权仅可使用 `b50` 指令
|
|
46
|
+
2. 修改了水鱼查分器的请求方式,移除废弃API端点
|
|
47
|
+
3. 修复使用水鱼查分器查询b50无法显示 `镜` 牌的问题,牌子可自行修改 `plate_version` 文件夹内的所有 `镜` 牌为繁体字的 `鏡`。以下压缩包包含新的曲目 `魔法仕掛けのファンタジア` 曲绘,新的 `鏡` 牌和 `廻` 牌文件
|
|
48
|
+
- [cloudreve](https://cloud.yuzuchan.moe/f/x3f3/Resource%203.1.5%20UPDATE.7z)
|
|
49
|
+
- [onedrive](https://yuzuai-my.sharepoint.com/:u:/g/personal/yuzu_yuzuchan_moe/IQBfiyOSmOXEQ6BU4NFfZdxmATlmua1cd1zGUlW3txCwTy8?e=uwrb3h)
|
|
50
|
+
- [openlist](https://share.yuzuchan.moe/d/downloads/Resource%203.1.5%20UPDATE.7z?sign=lpaSBMx8zCkfIYcyWWVVPu5ozDfs45_1-RMLVeAynH4=:0)
|
|
51
|
+
4. 修复 `我要上分` 指令计算问题
|
|
52
|
+
5. 修复合并别名的时,出现不存在的曲目ID
|
|
53
|
+
|
|
43
54
|
**2026-08-20**
|
|
44
55
|
|
|
45
56
|
1. 水鱼查分器新增 `OAuth` 认证,请根据 [配置](#配置) 示例填入相关 后续开发者Token将被废弃
|
|
@@ -48,26 +59,6 @@ Dynamic: license-file
|
|
|
48
59
|
4. 移除了申请别名通过和拒绝的推送
|
|
49
60
|
5. 修改部分绘图
|
|
50
61
|
|
|
51
|
-
**2026-06-09**
|
|
52
|
-
|
|
53
|
-
### 现仅支持 `Python 3.10+` !!!
|
|
54
|
-
|
|
55
|
-
#### 最好在更新 `舞萌DX 2026` 后再使用该版本
|
|
56
|
-
|
|
57
|
-
1. 更新支持 `舞萌DX2026`,应该是最后一次大改了
|
|
58
|
-
2. 新支持了 `落雪查分器`
|
|
59
|
-
3. 新功能:
|
|
60
|
-
- 新增 `舞`,`霸者` 牌子绘图
|
|
61
|
-
- 新增进度绘图
|
|
62
|
-
- 新增查询曲目过多时的绘图
|
|
63
|
-
- 新增切换主题功能
|
|
64
|
-
- 新增切换查分器功能
|
|
65
|
-
- 新增 `ap50` 指令(仅限落雪查分器)
|
|
66
|
-
- 新增 `lxbind`,`主题`,`数据源` 指令
|
|
67
|
-
- 新增 `牌子条件` 指令
|
|
68
|
-
4. 修改了别名推送的发送方式,防止刷屏
|
|
69
|
-
5. 修复了非常多的 BUG
|
|
70
|
-
|
|
71
62
|
## 温馨提示
|
|
72
63
|
|
|
73
64
|
**请务必看完 `README.MD` 所有内容**
|
|
@@ -120,8 +111,8 @@ Dynamic: license-file
|
|
|
120
111
|
DIVINGFISH_CLIENT_SECRET= # OAuth 应用秘钥
|
|
121
112
|
DIVINGFISH_SCOPE="" # OAuth 权限,根据应用权限进行填写,多个权限用空格隔开,默认值为 `"prober.profile.read"`
|
|
122
113
|
DIVINGFISH_AUTH_URL= # 水鱼账号地址,一般不需要填写,默认为 `https://auth.diving-fish.com`
|
|
123
|
-
DIVINGFISH_TOKEN= # 开发者 token,已弃用,见下方说明
|
|
124
114
|
DIVINGFISH_PROBER_PROXY=false # 是否使用中转访问水鱼查分器,适用于境外服务器
|
|
115
|
+
DIVINGFISH_TOKEN= # 开发者 token,已弃用,见下方说明
|
|
125
116
|
|
|
126
117
|
# lxns # 落雪查分器配置,均未填写将无法使用落雪查分器
|
|
127
118
|
LXNS_DEV_TOKEN= # 开发者 token
|
|
@@ -131,9 +122,6 @@ Dynamic: license-file
|
|
|
131
122
|
LXNS_BIND_PRIVATE_ONLY=false # 是否仅允许私聊完成 OAuth 绑定,默认允许群聊和私聊
|
|
132
123
|
```
|
|
133
124
|
|
|
134
|
-
> [!NOTE]
|
|
135
|
-
> 使用水鱼 OAuth 绑定时,用户发送 `dfbind`(或「绑定水鱼」),BOT 会返回一条授权链接,用户打开并确认页面上显示的绑定身份后点击「同意授权」即可,**不需要把授权码回贴给 BOT**。绑定关系与授权范围保存在水鱼服务端,BOT 只保管应用凭据,不保存任何用户令牌;用户可随时在 https://auth.diving-fish.com/apps 撤销授权。未绑定的用户仍可使用 `b50` 指令。
|
|
136
|
-
|
|
137
125
|
> [!WARNING]
|
|
138
126
|
> `DIVINGFISH_TOKEN`(开发者 token)已被水鱼查分器弃用:它能按 QQ 号读取任意用户的成绩,用户从未对 BOT 做过授权,也无法撤销。水鱼已停止签发新的开发者 token,并将在过渡期后关闭该鉴权方式。请改为申请 OAuth 应用并配置 `DIVINGFISH_CLIENT_ID` 与 `DIVINGFISH_CLIENT_SECRET`。两者同时配置时优先使用 OAuth 授权。
|
|
139
127
|
|
|
@@ -12,6 +12,17 @@
|
|
|
12
12
|
|
|
13
13
|
## 重要更新
|
|
14
14
|
|
|
15
|
+
**2026-11-02**
|
|
16
|
+
|
|
17
|
+
1. 新版本已完全废弃水鱼开发者Token,请前往水鱼 [开发者控制台](https://auth.diving-fish.com/console) 申请新应用,使用OAuth认证,未配置或者未授权仅可使用 `b50` 指令
|
|
18
|
+
2. 修改了水鱼查分器的请求方式,移除废弃API端点
|
|
19
|
+
3. 修复使用水鱼查分器查询b50无法显示 `镜` 牌的问题,牌子可自行修改 `plate_version` 文件夹内的所有 `镜` 牌为繁体字的 `鏡`。以下压缩包包含新的曲目 `魔法仕掛けのファンタジア` 曲绘,新的 `鏡` 牌和 `廻` 牌文件
|
|
20
|
+
- [cloudreve](https://cloud.yuzuchan.moe/f/x3f3/Resource%203.1.5%20UPDATE.7z)
|
|
21
|
+
- [onedrive](https://yuzuai-my.sharepoint.com/:u:/g/personal/yuzu_yuzuchan_moe/IQBfiyOSmOXEQ6BU4NFfZdxmATlmua1cd1zGUlW3txCwTy8?e=uwrb3h)
|
|
22
|
+
- [openlist](https://share.yuzuchan.moe/d/downloads/Resource%203.1.5%20UPDATE.7z?sign=lpaSBMx8zCkfIYcyWWVVPu5ozDfs45_1-RMLVeAynH4=:0)
|
|
23
|
+
4. 修复 `我要上分` 指令计算问题
|
|
24
|
+
5. 修复合并别名的时,出现不存在的曲目ID
|
|
25
|
+
|
|
15
26
|
**2026-08-20**
|
|
16
27
|
|
|
17
28
|
1. 水鱼查分器新增 `OAuth` 认证,请根据 [配置](#配置) 示例填入相关 后续开发者Token将被废弃
|
|
@@ -20,26 +31,6 @@
|
|
|
20
31
|
4. 移除了申请别名通过和拒绝的推送
|
|
21
32
|
5. 修改部分绘图
|
|
22
33
|
|
|
23
|
-
**2026-06-09**
|
|
24
|
-
|
|
25
|
-
### 现仅支持 `Python 3.10+` !!!
|
|
26
|
-
|
|
27
|
-
#### 最好在更新 `舞萌DX 2026` 后再使用该版本
|
|
28
|
-
|
|
29
|
-
1. 更新支持 `舞萌DX2026`,应该是最后一次大改了
|
|
30
|
-
2. 新支持了 `落雪查分器`
|
|
31
|
-
3. 新功能:
|
|
32
|
-
- 新增 `舞`,`霸者` 牌子绘图
|
|
33
|
-
- 新增进度绘图
|
|
34
|
-
- 新增查询曲目过多时的绘图
|
|
35
|
-
- 新增切换主题功能
|
|
36
|
-
- 新增切换查分器功能
|
|
37
|
-
- 新增 `ap50` 指令(仅限落雪查分器)
|
|
38
|
-
- 新增 `lxbind`,`主题`,`数据源` 指令
|
|
39
|
-
- 新增 `牌子条件` 指令
|
|
40
|
-
4. 修改了别名推送的发送方式,防止刷屏
|
|
41
|
-
5. 修复了非常多的 BUG
|
|
42
|
-
|
|
43
34
|
## 温馨提示
|
|
44
35
|
|
|
45
36
|
**请务必看完 `README.MD` 所有内容**
|
|
@@ -92,8 +83,8 @@
|
|
|
92
83
|
DIVINGFISH_CLIENT_SECRET= # OAuth 应用秘钥
|
|
93
84
|
DIVINGFISH_SCOPE="" # OAuth 权限,根据应用权限进行填写,多个权限用空格隔开,默认值为 `"prober.profile.read"`
|
|
94
85
|
DIVINGFISH_AUTH_URL= # 水鱼账号地址,一般不需要填写,默认为 `https://auth.diving-fish.com`
|
|
95
|
-
DIVINGFISH_TOKEN= # 开发者 token,已弃用,见下方说明
|
|
96
86
|
DIVINGFISH_PROBER_PROXY=false # 是否使用中转访问水鱼查分器,适用于境外服务器
|
|
87
|
+
DIVINGFISH_TOKEN= # 开发者 token,已弃用,见下方说明
|
|
97
88
|
|
|
98
89
|
# lxns # 落雪查分器配置,均未填写将无法使用落雪查分器
|
|
99
90
|
LXNS_DEV_TOKEN= # 开发者 token
|
|
@@ -103,9 +94,6 @@
|
|
|
103
94
|
LXNS_BIND_PRIVATE_ONLY=false # 是否仅允许私聊完成 OAuth 绑定,默认允许群聊和私聊
|
|
104
95
|
```
|
|
105
96
|
|
|
106
|
-
> [!NOTE]
|
|
107
|
-
> 使用水鱼 OAuth 绑定时,用户发送 `dfbind`(或「绑定水鱼」),BOT 会返回一条授权链接,用户打开并确认页面上显示的绑定身份后点击「同意授权」即可,**不需要把授权码回贴给 BOT**。绑定关系与授权范围保存在水鱼服务端,BOT 只保管应用凭据,不保存任何用户令牌;用户可随时在 https://auth.diving-fish.com/apps 撤销授权。未绑定的用户仍可使用 `b50` 指令。
|
|
108
|
-
|
|
109
97
|
> [!WARNING]
|
|
110
98
|
> `DIVINGFISH_TOKEN`(开发者 token)已被水鱼查分器弃用:它能按 QQ 号读取任意用户的成绩,用户从未对 BOT 做过授权,也无法撤销。水鱼已停止签发新的开发者 token,并将在过渡期后关闭该鉴权方式。请改为申请 OAuth 应用并配置 `DIVINGFISH_CLIENT_ID` 与 `DIVINGFISH_CLIENT_SECRET`。两者同时配置时优先使用 OAuth 授权。
|
|
111
99
|
|
{nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/__init__.py
RENAMED
|
@@ -64,19 +64,11 @@ async def get_music():
|
|
|
64
64
|
log.opt(colors=True).info(
|
|
65
65
|
"水鱼查分器已启用「<g>OAuth 授权</g>」,用户需使用「绑定水鱼」指令授权"
|
|
66
66
|
)
|
|
67
|
-
if dfconfig.divingfish_token:
|
|
68
|
-
log.opt(colors=True).warning(
|
|
69
|
-
"<y>已配置水鱼开发者Token,OAuth 授权优先,该配置项可以移除</y>"
|
|
70
|
-
)
|
|
71
|
-
elif dfconfig.divingfish_token:
|
|
72
|
-
log.opt(colors=True).warning(
|
|
73
|
-
"<y>水鱼开发者Token 已弃用,将在过渡期后停止工作,"
|
|
74
|
-
"请配置 DIVINGFISH_CLIENT_ID 与 DIVINGFISH_CLIENT_SECRET 改用 OAuth 授权</y>"
|
|
75
|
-
)
|
|
76
67
|
else:
|
|
77
68
|
log.opt(colors=True).warning(
|
|
78
|
-
"
|
|
69
|
+
"水鱼查分器未配置「<g>OAuth 授权</g>」,用户仅可使用「b50」指令"
|
|
79
70
|
)
|
|
71
|
+
|
|
80
72
|
if lxnsconfig.lxns_dev_token is None:
|
|
81
73
|
log.opt(colors=True).warning(
|
|
82
74
|
"<r>未配置落雪查分器开发者Token,无法使用落雪数据源</r>"
|
|
@@ -134,11 +134,17 @@ async def process_regex(
|
|
|
134
134
|
case [ds] if is_float(ds):
|
|
135
135
|
ds1 = ds2 = float(ds)
|
|
136
136
|
case [ds1_raw, ds2_raw] if is_float(ds1_raw) and is_float(ds2_raw):
|
|
137
|
-
|
|
137
|
+
# 帮助里的「定数」「页数」写法:第一个比第二个大时按页数处理
|
|
138
|
+
if float(ds1_raw) > float(ds2_raw):
|
|
139
|
+
ds1 = ds2 = float(ds1_raw)
|
|
140
|
+
page = max(1, int(float(ds2_raw)))
|
|
141
|
+
else:
|
|
142
|
+
ds1, ds2 = float(ds1_raw), float(ds2_raw)
|
|
138
143
|
case [ds1_raw, ds2_raw, p_raw] if (
|
|
139
144
|
is_float(ds1_raw) and is_float(ds2_raw) and p_raw.isdigit()
|
|
140
145
|
):
|
|
141
|
-
ds1, ds2
|
|
146
|
+
ds1, ds2 = float(ds1_raw), float(ds2_raw)
|
|
147
|
+
page = max(1, int(p_raw))
|
|
142
148
|
case _:
|
|
143
149
|
await matcher.finish(
|
|
144
150
|
(
|
|
@@ -27,7 +27,6 @@ from ..core.clients.divingfish.exceptions import (
|
|
|
27
27
|
from ..core.clients.divingfish.oauth import REVOKE_URL, binding_label
|
|
28
28
|
from ..core.clients.exceptions import HTTPError, UnknownError
|
|
29
29
|
from ..core.database.qq import User, update_user
|
|
30
|
-
from ..core.divingfish_oauth import extract_confirmation_code
|
|
31
30
|
from ..core.handler import (
|
|
32
31
|
bind_divingfish,
|
|
33
32
|
bind_lxns,
|
|
@@ -38,22 +37,8 @@ from ..core.handler import (
|
|
|
38
37
|
get_mai_what,
|
|
39
38
|
)
|
|
40
39
|
from ..core.image.tools import image_to_base64, song_chart
|
|
41
|
-
from ..core.lxns_oauth import (
|
|
42
|
-
extract_authorization_code,
|
|
43
|
-
is_binding_channel_allowed,
|
|
44
|
-
)
|
|
45
40
|
from ..core.merge.models import ServiceName, Theme
|
|
46
|
-
from ..core.
|
|
47
|
-
from ..core.service import mai
|
|
48
|
-
from ..core.tool import qqhash
|
|
49
|
-
from ..resources import Root
|
|
50
|
-
from .depend import (
|
|
51
|
-
GetOrCreateSender,
|
|
52
|
-
GetOrCreateUser,
|
|
53
|
-
GetUserAndAuth,
|
|
54
|
-
GetUserAndAuthOrNone,
|
|
55
|
-
)
|
|
56
|
-
from .oauth_message import (
|
|
41
|
+
from ..core.oauth import (
|
|
57
42
|
BINDING_TEMPORARY_FAILED_MSG,
|
|
58
43
|
DIVINGFISH_AUTHORIZE_MSG,
|
|
59
44
|
DIVINGFISH_BIND_FAILED_MSG,
|
|
@@ -70,6 +55,19 @@ from .oauth_message import (
|
|
|
70
55
|
LXNS_AUTHORIZE_MSG,
|
|
71
56
|
LXNS_ERROR,
|
|
72
57
|
OAUTH_FAILED_MSG,
|
|
58
|
+
PendingBindingStore,
|
|
59
|
+
extract_authorization_code,
|
|
60
|
+
extract_confirmation_code,
|
|
61
|
+
is_binding_channel_allowed,
|
|
62
|
+
)
|
|
63
|
+
from ..core.service import mai
|
|
64
|
+
from ..core.tool import qqhash
|
|
65
|
+
from ..resources import Root
|
|
66
|
+
from .depend import (
|
|
67
|
+
GetOrCreateSender,
|
|
68
|
+
GetOrCreateUser,
|
|
69
|
+
GetUserAndAuth,
|
|
70
|
+
GetUserAndAuthOrNone,
|
|
73
71
|
)
|
|
74
72
|
|
|
75
73
|
pending_bindings = PendingBindingStore()
|
|
@@ -115,6 +113,22 @@ async def complete_lxns_binding(user: User, code: str) -> tuple[str, bool]:
|
|
|
115
113
|
return result, result == "授权完成。"
|
|
116
114
|
|
|
117
115
|
|
|
116
|
+
async def complete_divingfish(qqid: int, code: str) -> tuple[str, bool]:
|
|
117
|
+
try:
|
|
118
|
+
await complete_divingfish_binding(qqid, code)
|
|
119
|
+
except DivingFishBindingMismatchError:
|
|
120
|
+
# 码有效,但兑出来的授权不是这个 QQ 的。多半是把别人转发来的码
|
|
121
|
+
# 当成自己的用了——照实说清楚,别让他以为是自己操作错了
|
|
122
|
+
log.warning("水鱼确认码与发起绑定的用户不一致")
|
|
123
|
+
return DIVINGFISH_MISMATCH_MSG, False
|
|
124
|
+
except DivingFishConfirmationCodeError:
|
|
125
|
+
return DIVINGFISH_CODE_FAILED_MSG, False
|
|
126
|
+
except (HTTPError, HTTPXError, UnknownError, ValidationError) as error:
|
|
127
|
+
log.warning(f"水鱼绑定暂时失败:{type(error).__name__}")
|
|
128
|
+
return DIVINGFISH_CODE_TEMPORARY_FAILED_MSG, False
|
|
129
|
+
return DIVINGFISH_BIND_SUCCESS_MSG, True
|
|
130
|
+
|
|
131
|
+
|
|
118
132
|
update_data = on_command("更新maimai数据", permission=SUPERUSER)
|
|
119
133
|
help = on_command("帮助maimaiDX", aliases={"帮助maimaidx"})
|
|
120
134
|
maimaidxrepo = on_command("项目地址maimaiDX", aliases={"项目地址maimaidx"})
|
|
@@ -234,22 +248,6 @@ async def _(
|
|
|
234
248
|
await bind_code.finish(result, reply_message=True)
|
|
235
249
|
|
|
236
250
|
|
|
237
|
-
async def complete_divingfish(qqid: int, code: str) -> tuple[str, bool]:
|
|
238
|
-
try:
|
|
239
|
-
await complete_divingfish_binding(qqid, code)
|
|
240
|
-
except DivingFishBindingMismatchError:
|
|
241
|
-
# 码有效,但兑出来的授权不是这个 QQ 的。多半是把别人转发来的码
|
|
242
|
-
# 当成自己的用了——照实说清楚,别让他以为是自己操作错了
|
|
243
|
-
log.warning("水鱼确认码与发起绑定的用户不一致")
|
|
244
|
-
return DIVINGFISH_MISMATCH_MSG, False
|
|
245
|
-
except DivingFishConfirmationCodeError:
|
|
246
|
-
return DIVINGFISH_CODE_FAILED_MSG, False
|
|
247
|
-
except (HTTPError, HTTPXError, UnknownError, ValidationError) as error:
|
|
248
|
-
log.warning(f"水鱼绑定暂时失败:{type(error).__name__}")
|
|
249
|
-
return DIVINGFISH_CODE_TEMPORARY_FAILED_MSG, False
|
|
250
|
-
return DIVINGFISH_BIND_SUCCESS_MSG, True
|
|
251
|
-
|
|
252
|
-
|
|
253
251
|
@df_bind.handle()
|
|
254
252
|
async def _(
|
|
255
253
|
event: GroupMessageEvent | PrivateMessageEvent,
|
|
@@ -10,7 +10,7 @@ from ..config import log
|
|
|
10
10
|
from ..core.database.qq import User
|
|
11
11
|
from ..core.handler import draw_best50, draw_play_data, draw_song_global_data
|
|
12
12
|
from ..core.image.tools import text_to_bytes_io
|
|
13
|
-
from ..core.merge.models import
|
|
13
|
+
from ..core.merge.models import Song
|
|
14
14
|
from ..core.service import mai
|
|
15
15
|
from .depend import GetUserAndAuth
|
|
16
16
|
|
|
@@ -29,39 +29,58 @@ async def _(
|
|
|
29
29
|
user: User = Depends(GetUserAndAuth),
|
|
30
30
|
):
|
|
31
31
|
username = message.extract_plain_text().strip()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
result = await draw_best50(
|
|
33
|
+
user, username=username, all_perfect=isinstance(matcher, ap50)
|
|
34
|
+
)
|
|
35
35
|
await matcher.send(result, reply_message=True)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
async def search_song(matcher: Matcher, data: str) -> Song | None:
|
|
39
|
+
if data.isdigit() and (by_id := mai.total_list.by_id(int(data))):
|
|
40
|
+
song = by_id
|
|
41
|
+
elif by_t := mai.total_list.by_name(data):
|
|
42
|
+
song = by_t
|
|
43
|
+
elif alias := mai.total_alias_list.by_alias(data):
|
|
44
|
+
if not alias:
|
|
45
|
+
await matcher.finish("未找到曲目", reply_message=True)
|
|
46
|
+
elif len(alias) != 1:
|
|
47
|
+
msg = "找到相同别名的曲目,请使用以下ID查询:\n"
|
|
48
|
+
for songs in alias:
|
|
49
|
+
msg += f"{songs.song_id}:{songs.alias[0]}\n"
|
|
50
|
+
await matcher.finish(msg.strip(), reply_message=True)
|
|
51
|
+
else:
|
|
52
|
+
song = mai.total_list.by_id(alias[0].song_id)
|
|
53
|
+
else:
|
|
54
|
+
by_t = mai.total_list.filter(title=data)
|
|
55
|
+
if (tn := len(by_t)) == 1:
|
|
56
|
+
song = by_t[0]
|
|
57
|
+
elif tn <= 5 and tn > 1:
|
|
58
|
+
msg = f"未找到别名为「{data}」的歌曲,但找到「{tn}」个相似标题的曲目:\n"
|
|
59
|
+
for s in sorted(by_t, key=lambda x: int(x.song_id)):
|
|
60
|
+
msg += f"{f'「{s.song_id}」':<7} {s.song_name}\n"
|
|
61
|
+
msg += "※ 请使用「info xxxxx」查询指定曲目"
|
|
62
|
+
await matcher.finish(msg, reply_message=True)
|
|
63
|
+
elif tn > 5:
|
|
64
|
+
await matcher.finish("查询相似的曲目过多,请缩小范围。", reply_message=True)
|
|
65
|
+
else:
|
|
66
|
+
song = None
|
|
67
|
+
|
|
68
|
+
return song
|
|
69
|
+
|
|
70
|
+
|
|
38
71
|
@info.handle()
|
|
39
72
|
async def _(
|
|
40
73
|
message: Message = CommandArg(),
|
|
41
74
|
user: User = Depends(GetUserAndAuth),
|
|
42
75
|
):
|
|
43
|
-
|
|
44
|
-
if not
|
|
76
|
+
args = message.extract_plain_text().strip().lower()
|
|
77
|
+
if not args:
|
|
45
78
|
await info.finish("请输入曲目id或曲名", reply_message=True)
|
|
46
79
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else:
|
|
52
|
-
aliases = mai.total_alias_list.by_alias(data)
|
|
53
|
-
if not aliases:
|
|
54
|
-
await info.finish("未找到曲目", reply_message=True)
|
|
55
|
-
elif len(aliases) != 1:
|
|
56
|
-
msg = "找到相同别名的曲目,请使用以下ID查询:\n"
|
|
57
|
-
for alias in aliases:
|
|
58
|
-
msg += f"{alias.song_id}:{alias.alias[0]}\n"
|
|
59
|
-
await info.finish(msg.strip(), reply_message=True)
|
|
60
|
-
else:
|
|
61
|
-
song_id = aliases[0].song_id
|
|
62
|
-
song = mai.total_list.by_id(song_id)
|
|
63
|
-
if song is None:
|
|
64
|
-
await info.finish("未找到曲目", reply_message=True)
|
|
80
|
+
song = await search_song(info, args)
|
|
81
|
+
|
|
82
|
+
if song is None:
|
|
83
|
+
await info.finish("未找到曲目", reply_message=True)
|
|
65
84
|
|
|
66
85
|
result = await draw_play_data(user, song)
|
|
67
86
|
await info.send(result, reply_message=True)
|
|
@@ -69,7 +88,7 @@ async def _(
|
|
|
69
88
|
|
|
70
89
|
@ginfo.handle()
|
|
71
90
|
async def _(message: Message = CommandArg()):
|
|
72
|
-
args = message.extract_plain_text().strip()
|
|
91
|
+
args = message.extract_plain_text().strip().lower()
|
|
73
92
|
if not args:
|
|
74
93
|
await ginfo.finish("请输入曲目id或曲名", reply_message=True)
|
|
75
94
|
|
|
@@ -80,21 +99,11 @@ async def _(message: Message = CommandArg()):
|
|
|
80
99
|
args = args[1:].strip()
|
|
81
100
|
if not args:
|
|
82
101
|
await ginfo.finish("请输入曲目id或曲名", reply_message=True)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
alias = mai.total_alias_list.by_alias(args)
|
|
89
|
-
if not alias:
|
|
90
|
-
await ginfo.finish("未找到曲目", reply_message=True)
|
|
91
|
-
elif len(alias) != 1:
|
|
92
|
-
msg = "找到相同别名的曲目,请使用以下ID查询:\n"
|
|
93
|
-
for songs in alias:
|
|
94
|
-
msg += f"{songs.song_id}:{songs.alias[0]}\n"
|
|
95
|
-
await ginfo.finish(msg.strip(), reply_message=True)
|
|
96
|
-
else:
|
|
97
|
-
song = mai.total_list.by_id(alias[0].song_id)
|
|
102
|
+
|
|
103
|
+
song = await search_song(ginfo, args)
|
|
104
|
+
if song is None:
|
|
105
|
+
await ginfo.finish("未找到曲目", reply_message=True)
|
|
106
|
+
|
|
98
107
|
if level_index >= len(song.difficulties):
|
|
99
108
|
await ginfo.finish("该乐曲没有这个等级", reply_message=True)
|
|
100
109
|
stats = song.difficulties[level_index].stats
|
|
@@ -8,7 +8,14 @@ from nonebot.params import Depends, RegexMatched
|
|
|
8
8
|
from nonebot.permission import SUPERUSER
|
|
9
9
|
from PIL import Image
|
|
10
10
|
|
|
11
|
-
from ..constants import
|
|
11
|
+
from ..constants import (
|
|
12
|
+
CB_SYNC_MAP,
|
|
13
|
+
COMBO_PLUS,
|
|
14
|
+
LEVEL_LIST,
|
|
15
|
+
PLATE_CN,
|
|
16
|
+
RANK_PLUS,
|
|
17
|
+
SYNC_PLUS,
|
|
18
|
+
)
|
|
12
19
|
from ..core.database.qq import User
|
|
13
20
|
from ..core.handler import (
|
|
14
21
|
draw_level_progress,
|
|
@@ -26,7 +33,7 @@ from .depend import GetUserAndAuth
|
|
|
26
33
|
|
|
27
34
|
RATING_PATTERN = r"^([0-9]+\+?)((s+|ap|fc|fs|fdx)\+?)?\s?完成表$"
|
|
28
35
|
TABLE_PATTERN = (
|
|
29
|
-
r"^([
|
|
36
|
+
r"^([真超檄橙暁晓桃櫻樱紫菫堇白雪輝辉舞霸熊華华爽煌星宙祭祝双宴镜鏡彩])"
|
|
30
37
|
r"([極极将舞神者]舞?){}表?\s?([0-9]+)?$"
|
|
31
38
|
)
|
|
32
39
|
LEVEL_PATTERN = r"^([0-9]+\+?)\s?((?:a+|b+|c|d|s+|ap|fc|fs|fdx)\+?)\s?([\u4e00-\u9fa5]+)?\s?进度\s?([0-9]+)?$"
|
|
@@ -70,11 +77,11 @@ async def _():
|
|
|
70
77
|
|
|
71
78
|
@rating_table.handle()
|
|
72
79
|
async def _(match: Match[str] = RegexMatched()):
|
|
73
|
-
|
|
74
|
-
if
|
|
80
|
+
level = match.group(1).strip()
|
|
81
|
+
if level in LEVEL_LIST[:6]:
|
|
75
82
|
result = "只支持查询lv7-15的定数表。"
|
|
76
|
-
elif
|
|
77
|
-
result = draw_rating_table_text(
|
|
83
|
+
elif level in LEVEL_LIST[6:]:
|
|
84
|
+
result = draw_rating_table_text(level)
|
|
78
85
|
else:
|
|
79
86
|
result = "无法识别的定数。"
|
|
80
87
|
await rating_table.send(result, reply_message=True)
|
|
@@ -82,19 +89,12 @@ async def _(match: Match[str] = RegexMatched()):
|
|
|
82
89
|
|
|
83
90
|
@rating_table_pfm.handle()
|
|
84
91
|
async def _(match: Match[str] = RegexMatched(), user: User = Depends(GetUserAndAuth)):
|
|
85
|
-
|
|
86
|
-
plan = match.group(2)
|
|
87
|
-
if
|
|
92
|
+
level = match.group(1)
|
|
93
|
+
plan = (match.group(2) or "").lower()
|
|
94
|
+
if level in LEVEL_LIST[:6]:
|
|
88
95
|
await rating_table_pfm.finish("只支持查询lv7-15的完成表。", reply_message=True)
|
|
89
|
-
elif
|
|
90
|
-
|
|
91
|
-
await rating_table_pfm.finish(
|
|
92
|
-
"完成表目前仅支持「fc」「ap」计划,例如「13fc完成表」「13ap完成表」。",
|
|
93
|
-
reply_message=True,
|
|
94
|
-
)
|
|
95
|
-
pic = await draw_rating_table(
|
|
96
|
-
user, ra, bool(plan and plan.lower() in COMBO_PLUS)
|
|
97
|
-
)
|
|
96
|
+
elif level in LEVEL_LIST[6:]:
|
|
97
|
+
pic = await draw_rating_table(user, level, CB_SYNC_MAP.get(plan))
|
|
98
98
|
await rating_table_pfm.finish(pic, reply_message=True)
|
|
99
99
|
else:
|
|
100
100
|
await rating_table_pfm.finish("无法识别的定数。", reply_message=True)
|
{nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/config.py
RENAMED
|
@@ -24,7 +24,6 @@ class BaseConfig(BaseModel):
|
|
|
24
24
|
|
|
25
25
|
class DivingFishConfig(BaseModel):
|
|
26
26
|
divingfish_prober_proxy: bool = False
|
|
27
|
-
divingfish_token: str | None = None
|
|
28
27
|
divingfish_client_id: str | None = None
|
|
29
28
|
divingfish_client_secret: str | None = None
|
|
30
29
|
divingfish_auth_url: str = "https://auth.diving-fish.com"
|
{nonebot_plugin_maimaidx-3.1.2 → nonebot_plugin_maimaidx-3.1.5}/nonebot_plugin_maimaidx/constants.py
RENAMED
|
@@ -83,6 +83,17 @@ SYNC_MAP = {
|
|
|
83
83
|
"sync": "Sync",
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
CB_SYNC_MAP: dict[str, tuple[str, ...]] = {
|
|
87
|
+
"fc": ("fc", "fcp", "ap", "app"),
|
|
88
|
+
"fc+": ("fcp", "ap", "app"),
|
|
89
|
+
"ap": ("ap", "app"),
|
|
90
|
+
"ap+": ("app",),
|
|
91
|
+
"fs": ("fs", "fsp", "fsd", "fsdp"),
|
|
92
|
+
"fs+": ("fsp", "fsd", "fsdp"),
|
|
93
|
+
"fdx": ("fsd", "fsdp"),
|
|
94
|
+
"fdx+": ("fsdp",),
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
DIFFS = ["Basic", "Advanced", "Expert", "Master", "Re:Master"]
|
|
87
98
|
LEVEL_LIST = [
|
|
88
99
|
"1",
|
|
@@ -174,6 +185,7 @@ DX_VERSION = {
|
|
|
174
185
|
"双": "maimai でらっくす BUDDiES",
|
|
175
186
|
"宴": "maimai でらっくす BUDDiES PLUS",
|
|
176
187
|
"镜": "maimai でらっくす PRiSM",
|
|
188
|
+
"鏡": "maimai でらっくす PRiSM",
|
|
177
189
|
"彩": "maimai でらっくす PRiSM PLUS",
|
|
178
190
|
# "丸": "maimai でらっくす CiRCLE"
|
|
179
191
|
# "": "maimai でらっくす CiRCLE PLUS"
|
|
@@ -215,11 +227,12 @@ VERSION_MAP = {
|
|
|
215
227
|
"双": ([DX_VERSION["双"]], "双&宴"),
|
|
216
228
|
"宴": ([DX_VERSION["双"]], "双&宴"),
|
|
217
229
|
"镜": ([DX_VERSION["镜"]], "镜"),
|
|
230
|
+
"鏡": ([DX_VERSION["鏡"]], "鏡"),
|
|
218
231
|
"彩": ([DX_VERSION["彩"]], "彩"),
|
|
219
232
|
# "丸": ([DX_VERSION["丸"]], "丸"),
|
|
220
233
|
# "": ([DX_VERSION["丸"]], "丸")
|
|
221
234
|
}
|
|
222
|
-
PLATE_CN = {"晓": "暁", "樱": "櫻", "堇": "菫", "辉": "輝", "华": "華"}
|
|
235
|
+
PLATE_CN = {"晓": "暁", "樱": "櫻", "堇": "菫", "辉": "輝", "华": "華", "镜": "鏡"}
|
|
223
236
|
CATEGORY = {
|
|
224
237
|
"流行&动漫": "anime",
|
|
225
238
|
"舞萌": "maimai",
|
|
@@ -12,7 +12,7 @@ from .exceptions import (
|
|
|
12
12
|
DivingFishUserDisabledQueryError,
|
|
13
13
|
DivingFishUserNotFoundError,
|
|
14
14
|
)
|
|
15
|
-
from .models import
|
|
15
|
+
from .models import RecordsQueryRequest, UserAllRecords, UserInfo, UserRanking
|
|
16
16
|
from .oauth import get_access_token
|
|
17
17
|
|
|
18
18
|
|
|
@@ -21,14 +21,8 @@ class DivingFishAPI(ApiClient):
|
|
|
21
21
|
base_url = "https://maimai.diving-fish.com/api/maimaidxprober"
|
|
22
22
|
|
|
23
23
|
def __init__(self, qqid: int | None = None, username: str | None = None):
|
|
24
|
-
#: 授权模式下查谁由令牌决定,请求里不再携带 `qq`,也不需要开发者 token
|
|
25
24
|
self.oauth = dfconfig.oauth_enabled and qqid is not None and not username
|
|
26
|
-
super().__init__(
|
|
27
|
-
base_url=self.base_url,
|
|
28
|
-
headers=None
|
|
29
|
-
if self.oauth or not dfconfig.divingfish_token
|
|
30
|
-
else {"developer-token": dfconfig.divingfish_token},
|
|
31
|
-
)
|
|
25
|
+
super().__init__(base_url=self.base_url)
|
|
32
26
|
self.qqid = qqid
|
|
33
27
|
self._retried = False
|
|
34
28
|
self.json = {}
|
|
@@ -36,7 +30,6 @@ class DivingFishAPI(ApiClient):
|
|
|
36
30
|
self.json["qq"] = qqid
|
|
37
31
|
if username:
|
|
38
32
|
self.json["username"] = username
|
|
39
|
-
self.json.pop("qq", None)
|
|
40
33
|
|
|
41
34
|
def _handle_error(self, resp: Response):
|
|
42
35
|
if resp.status_code == 200:
|
|
@@ -113,67 +106,18 @@ class DivingFishAPI(ApiClient):
|
|
|
113
106
|
result = await self._request_data("POST", "/query/player", json=self.json)
|
|
114
107
|
return UserInfo.model_validate(result)
|
|
115
108
|
|
|
116
|
-
async def
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
Params:
|
|
121
|
-
`version`: 版本
|
|
122
|
-
Returns:
|
|
123
|
-
`List[PlayInfoDefault]` 数据列表
|
|
124
|
-
"""
|
|
125
|
-
if self.oauth:
|
|
126
|
-
result = await self._request_oauth(
|
|
127
|
-
"POST", "/player/plate", json={"version": version}
|
|
128
|
-
)
|
|
129
|
-
else:
|
|
130
|
-
self.json["version"] = version
|
|
131
|
-
result = await self._request_data("POST", "/query/plate", json=self.json)
|
|
132
|
-
|
|
133
|
-
return [PlayInfoDefault.model_validate(d) for d in result["verlist"]]
|
|
134
|
-
|
|
135
|
-
async def query_user_records(self) -> UserInfoDev:
|
|
109
|
+
async def query_user_records(
|
|
110
|
+
self, query: RecordsQueryRequest | None = None
|
|
111
|
+
) -> UserAllRecords:
|
|
136
112
|
"""
|
|
137
113
|
获取用户所有成绩
|
|
138
114
|
|
|
139
115
|
Returns:
|
|
140
|
-
`
|
|
116
|
+
`UserAllRecords` 用户信息
|
|
141
117
|
"""
|
|
142
|
-
if
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
result = await self._request_data(
|
|
146
|
-
"GET", "/dev/player/records", params=self.json
|
|
147
|
-
)
|
|
148
|
-
return UserInfoDev.model_validate(result)
|
|
149
|
-
|
|
150
|
-
async def query_user_record(
|
|
151
|
-
self, *, song_id: str | int | list[str | int]
|
|
152
|
-
) -> list[PlayInfoDev]:
|
|
153
|
-
"""
|
|
154
|
-
获取用户指定曲目成绩
|
|
155
|
-
|
|
156
|
-
Params:
|
|
157
|
-
`song_id`: 曲目id,可以为单个ID或者列表
|
|
158
|
-
Returns:
|
|
159
|
-
`List[PlayInfoDev]` 成绩列表
|
|
160
|
-
"""
|
|
161
|
-
if not isinstance(song_id, list):
|
|
162
|
-
song_id = [song_id]
|
|
163
|
-
|
|
164
|
-
if self.oauth:
|
|
165
|
-
result = await self._request_oauth(
|
|
166
|
-
"POST", "/player/record", json={"music_id": song_id}
|
|
167
|
-
)
|
|
168
|
-
else:
|
|
169
|
-
self.json["music_id"] = song_id
|
|
170
|
-
result = await self._request_data(
|
|
171
|
-
"POST", "/dev/player/record", json=self.json
|
|
172
|
-
)
|
|
173
|
-
if result == {}:
|
|
174
|
-
return []
|
|
175
|
-
|
|
176
|
-
return [PlayInfoDev.model_validate(d) for k, v in result.items() for d in v]
|
|
118
|
+
params = query.model_dump(exclude_none=True) if query is not None else None
|
|
119
|
+
result = await self._request_oauth("GET", "/player/records", params=params)
|
|
120
|
+
return UserAllRecords.model_validate(result)
|
|
177
121
|
|
|
178
122
|
async def rating_ranking(self) -> list[UserRanking]:
|
|
179
123
|
"""
|