nonebot-plugin-werewolf 1.1.11__tar.gz → 1.1.13__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 (45) hide show
  1. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/PKG-INFO +71 -41
  2. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/README.md +68 -38
  3. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/__init__.py +1 -1
  4. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/config.py +51 -37
  5. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/constant.py +0 -17
  6. nonebot_plugin_werewolf-1.1.13/nonebot_plugin_werewolf/dead_channel.py +79 -0
  7. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/game.py +46 -115
  8. nonebot_plugin_werewolf-1.1.13/nonebot_plugin_werewolf/matchers/_prepare_game.py +223 -0
  9. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/depends.py +2 -2
  10. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/edit_behavior.py +1 -0
  11. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/edit_preset.py +14 -12
  12. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/message_in_game.py +1 -1
  13. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py +3 -3
  14. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/poke/ob11_poke.py +3 -3
  15. nonebot_plugin_werewolf-1.1.13/nonebot_plugin_werewolf/matchers/start_game.py +124 -0
  16. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/superuser_ops.py +5 -8
  17. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/models.py +19 -0
  18. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/player.py +35 -31
  19. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/guard.py +2 -2
  20. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/prophet.py +2 -2
  21. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/shooter.py +2 -2
  22. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/werewolf.py +18 -19
  23. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/witch.py +4 -4
  24. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/utils.py +18 -56
  25. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf.egg-info/PKG-INFO +71 -41
  26. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf.egg-info/SOURCES.txt +5 -1
  27. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf.egg-info/requires.txt +2 -2
  28. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/pyproject.toml +37 -14
  29. nonebot_plugin_werewolf-1.1.13/tests/test_start_game.py +145 -0
  30. nonebot_plugin_werewolf-1.1.13/tests/test_utils.py +16 -0
  31. nonebot_plugin_werewolf-1.1.11/nonebot_plugin_werewolf/matchers/start_game.py +0 -336
  32. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/LICENSE +0 -0
  33. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/exception.py +0 -0
  34. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/__init__.py +0 -0
  35. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/matchers/poke/__init__.py +0 -0
  36. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/player_set.py +0 -0
  37. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/__init__.py +0 -0
  38. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/civilian.py +0 -0
  39. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/hunter.py +0 -0
  40. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/idiot.py +0 -0
  41. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/jester.py +0 -0
  42. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf/players/wolfking.py +0 -0
  43. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf.egg-info/dependency_links.txt +0 -0
  44. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/nonebot_plugin_werewolf.egg-info/top_level.txt +0 -0
  45. {nonebot_plugin_werewolf-1.1.11 → nonebot_plugin_werewolf-1.1.13}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-werewolf
3
- Version: 1.1.11
3
+ Version: 1.1.13
4
4
  Summary: 适用于 Nonebot2 的狼人杀插件
5
5
  Author-email: wyf7685 <wyf7685@163.com>
6
6
  License: MIT
@@ -11,9 +11,9 @@ Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
13
  Requires-Dist: nonebot2>=2.4.0
14
- Requires-Dist: nonebot-plugin-alconna>=0.57.0
14
+ Requires-Dist: nonebot-plugin-alconna>=0.58.0
15
15
  Requires-Dist: nonebot-plugin-localstore>=0.7.1
16
- Requires-Dist: nonebot-plugin-uninfo>=0.7.3
16
+ Requires-Dist: nonebot-plugin-uninfo>=0.8.0
17
17
  Requires-Dist: nonebot-plugin-waiter>=0.8.0
18
18
  Requires-Dist: anyio>=4.6.0
19
19
  Dynamic: license-file
@@ -50,6 +50,22 @@ _✨ 简单的狼人杀插件 ✨_
50
50
 
51
51
  和朋友们来一场紧张刺激的狼人杀游戏
52
52
 
53
+ <!-- ref: https://github.com/KomoriDev/Starify -->
54
+
55
+ > [!IMPORTANT]
56
+ >
57
+ > **收藏项目**,你将从 GitHub 上无延迟地接收所有发布通知~ ⭐️
58
+
59
+ <img width="100%" src="https://starify.komoridevs.icu/api/starify?owner=wyf7685&repo=nonebot-plugin-werewolf" alt="starify" />
60
+
61
+ <details>
62
+ <summary><kbd>Star History</kbd></summary>
63
+ <picture>
64
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=wyf7685/nonebot-plugin-werewolf&theme=dark&type=Date" />
65
+ <img width="100%" src="https://star-history.com/#wyf7685/nonebot-plugin-werewolf&Date" />
66
+ </picture>
67
+ </details>
68
+
53
69
  ## 💿 安装
54
70
 
55
71
  > [!note]
@@ -111,17 +127,18 @@ _✨ 简单的狼人杀插件 ✨_
111
127
 
112
128
  在 nonebot2 项目的 `.env` 文件中添加如下配置:
113
129
 
114
- | 配置项 | 必填 | 默认值 | 类型 | 说明 |
115
- | :--------------------------: | :--: | :-----: | :-----------------------: | :----------------------------: |
116
- | `werewolf__enable_poke` | 否 | `True` | `bool` | 是否使用戳一戳简化操作流程 |
117
- | `werewolf__enable_button` | 否 | `False` | `bool` | 是否在交互中添加按钮 |
118
- | `werewolf__stop_command` | 否 | `stop` | `str \| set[str]` | 修改游戏进程中的 `stop` 命令 |
119
- | `werewolf__require_at` | 否 | `True` | `bool \| RequireAtConfig` | 部分命令是否需要 at 机器人触发 |
120
- | `werewolf__matcher_priority` | 否 | - | `MatcherPriorityConfig` | 配置插件 matcher 注册的优先级 |
130
+ | 配置项 | 必填 | 默认值 | 类型 | 说明 |
131
+ | :--------------------------: | :--: | :-----: | :-----------------------: | :-------------------------------------------: |
132
+ | `werewolf__enable_poke` | 否 | `True` | `bool` | 是否使用戳一戳简化操作流程 |
133
+ | `werewolf__enable_button` | 否 | `False` | `bool` | 是否在交互中添加按钮 |
134
+ | `werewolf__stop_command` | 否 | `stop` | `str \| set[str]` | 修改游戏进程中的 `stop` 命令 |
135
+ | `werewolf__require_at` | 否 | `True` | `bool \| RequireAtConfig` | 部分命令是否需要 at 机器人触发 |
136
+ | `werewolf__matcher_priority` | 否 | - | `MatcherPriorityConfig` | 配置插件 matcher 注册的优先级 |
137
+ | `werewolf__use_cmd_start` | 否 | `None` | `bool \| None` | 是否使用配置项 `COMMAND_START` 来作为命令前缀 |
121
138
 
122
139
  `werewolf__enable_poke` 仅在 `OneBot V11` 适配器 / `Satori/chronocat` 下生效
123
140
 
124
- `werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性。如有疑问欢迎提出。
141
+ `werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性,如有疑问欢迎提出。
125
142
 
126
143
  <details>
127
144
  <summary> werewolf__require_at 示例 </summary>
@@ -136,15 +153,18 @@ werewolf__require_at=false
136
153
  # 狼人杀命令需要 at, 中止游戏命令不需要 at
137
154
  werewolf__require_at='{"start": true, "terminate": false}'
138
155
  ```
156
+
139
157
  </details>
140
- <br/>
141
158
 
142
159
  `werewolf__matcher_priority` 的 matcher 优先级参考 [官方文档](https://nonebot.dev/docs/advanced/matcher#%E5%93%8D%E5%BA%94%E4%BC%98%E5%85%88%E7%BA%A7)
143
- - 一般情况下不需要修改此配置, 插件的默认优先级可以参考 [这里](./nonebot_plugin_werewolf/config.py) 的 `MatcherPriorityConfig`
144
- - 如果遇到与其他插件的命令冲突, 可考虑修改此处的优先级配置
145
- - 配置应填入 JSON 对象, 可用键: `start` `terminate` `preset` `behavior` `in_game` `stop`
146
160
 
147
- ## 🎉 使用
161
+ - 一般情况下不需要修改此配置, 插件的默认优先级可以参考 [这里](./nonebot_plugin_werewolf/config.py) 的 `MatcherPriorityConfig`
162
+ - 如果遇到与其他插件的命令冲突, 可考虑修改此处的优先级配置
163
+ - 配置应填入 JSON 对象, 可用键: `start` `terminate` `preset` `behavior` `in_game` `stop`
164
+
165
+ `werewolf__use_cmd_start` 为 `None` 时,使用 alc 的 [全局配置](https://nonebot.dev/docs/next/best-practice/alconna/config#alconna_use_command_start)
166
+
167
+ ## 🚀 使用
148
168
 
149
169
  > [!note]
150
170
  >
@@ -165,19 +185,19 @@ werewolf__require_at='{"start": true, "terminate": false}'
165
185
 
166
186
  </details>
167
187
 
168
- ### 指令表
188
+ ### 📋 指令表
169
189
 
170
- | 指令 | 权限 | 需要@ | 范围 | 说明 |
171
- | :-----------------: | :-----------------: | :---: | :--: | :---------------------------------------: |
172
- | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 | 发起游戏 (进入准备阶段) |
173
- | `开始游戏` | 游戏发起者 | 否 | 群聊 | _[准备阶段]_ 游戏发起者开始游戏 |
174
- | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 | _[准备阶段]_ 游戏发起者/超级用户 结束游戏 |
175
- | `当前玩家` | 群员 | 否 | 群聊 | _[准备阶段]_ 列出参与游戏的玩家列表 |
176
- | `加入游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家加入游戏 |
177
- | `退出游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家退出游戏 |
178
- | `中止游戏` | 超级用户 | 是 | 群聊 | _[游戏内]_ 超级用户强制中止游戏 |
179
- | `狼人杀预设` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏预设 |
180
- | `狼人杀配置` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏配置 |
190
+ | 指令 | 权限 | 需要@ | 范围 | 说明 |
191
+ | :-----------------: | :-----------------: | :---: | :---------------: | :--------------------------: |
192
+ | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 _[游戏外]_ | 发起游戏 (进入准备阶段) |
193
+ | `开始游戏` | 游戏发起者 | 否 | 群聊 _[准备阶段]_ | 游戏发起者开始游戏 |
194
+ | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 _[准备阶段]_ | 游戏发起者/超级用户 结束游戏 |
195
+ | `当前玩家` | 群员 | 否 | 群聊 _[准备阶段]_ | 列出参与游戏的玩家列表 |
196
+ | `加入游戏` | 群员 | 否 | 群聊 _[准备阶段]_ | 玩家加入游戏 |
197
+ | `退出游戏` | 群员 | 否 | 群聊 _[准备阶段]_ | 玩家退出游戏 |
198
+ | `中止游戏` | 超级用户 | 是 | 群聊 _[游戏内]_ | 超级用户强制中止游戏 |
199
+ | `狼人杀预设` | 超级用户 | 否 | 任意 _[游戏外]_ | 超级用户编辑游戏预设 |
200
+ | `狼人杀配置` | 超级用户 | 否 | 任意 _[游戏外]_ | 超级用户编辑游戏配置 |
181
201
 
182
202
  - `超级用户` 为 nonebot2 配置项中的 `SUPERUSERS`, 配置说明参考 [官方文档](https://nonebot.dev/docs/appendices/config#superusers)
183
203
 
@@ -191,7 +211,7 @@ werewolf__require_at='{"start": true, "terminate": false}'
191
211
 
192
212
  - _其他交互参考游戏内提示_
193
213
 
194
- ### 游戏内容
214
+ ### 🎭 游戏内容
195
215
 
196
216
  > [!note]
197
217
  >
@@ -202,14 +222,14 @@ werewolf__require_at='{"start": true, "terminate": false}'
202
222
  插件中保存了一份 [职业预设](./nonebot_plugin_werewolf/constant.py), 内容如下
203
223
 
204
224
  | 总人数 | 狼人 | 神职 | 平民 |
205
- | ------ | ---- | ---- | ---- |
206
- | 6 | 1 | 2 | 3 |
207
- | 7 | 2 | 2 | 3 |
208
- | 8 | 2 | 3 | 3 |
209
- | 9 | 2 | 4 | 3 |
210
- | 10 | 3 | 4 | 3 |
211
- | 11 | 3 | 5 | 3 |
212
- | 12 | 4 | 5 | 3 |
225
+ | :----: | :--: | :--: | :--: |
226
+ | 6 | 1 | 2 | 3 |
227
+ | 7 | 2 | 2 | 3 |
228
+ | 8 | 2 | 3 | 3 |
229
+ | 9 | 2 | 4 | 3 |
230
+ | 10 | 3 | 4 | 3 |
231
+ | 11 | 3 | 5 | 3 |
232
+ | 12 | 4 | 5 | 3 |
213
233
 
214
234
  职业预设可以通过命令 `狼人杀预设 职业 ...` 修改
215
235
 
@@ -254,7 +274,6 @@ werewolf__require_at='{"start": true, "terminate": false}'
254
274
  > 其效果等同于以上描述中的单条命令 `狼人杀预设 狼人 狼人 狼王 狼人 狼人`
255
275
 
256
276
  </details>
257
- <br/>
258
277
 
259
278
  对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 _一定概率_ 将其中一个平民替换为小丑。
260
279
 
@@ -262,12 +281,14 @@ werewolf__require_at='{"start": true, "terminate": false}'
262
281
 
263
282
  小丑生成概率可以通过命令 `狼人杀预设 小丑 <概率>` 设置,默认值为 0 (不生成小丑)。
264
283
 
265
- ### 已知问题
284
+ ### 🔧 已知问题
266
285
 
267
286
  <details>
268
287
  <summary>已知问题</summary>
269
288
 
270
- - 截止 chronocat v0.2.19, 调用 [`guild.member.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/guild/member/get.ts) / [`user.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/user/get.ts) 均无法获取用户名,这将导致在交互过程中的玩家名显示为用户 ID
289
+ - 截止 chronocat [v0.2.19](https://github.com/chrononeko/chronocat/tree/v0.2.19), 调用 [`guild.member.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/guild/member/get.ts) / [`user.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/user/get.ts) 均无法获取用户名,这将导致在交互过程中的玩家名显示为用户 ID
290
+
291
+ - v1.1.6 添加的按钮操作在 `discord` 适配器中不可用, 已在 v1.1.12 禁用 (2e31d43)
271
292
 
272
293
  </details>
273
294
 
@@ -278,6 +299,15 @@ werewolf__require_at='{"start": true, "terminate": false}'
278
299
 
279
300
  <!-- CHANGELOG -->
280
301
 
302
+ - 2025.06.04 v1.1.13
303
+
304
+ - 添加配置项 `werewolf__use_cmd_start`, 用于配置插件命令前缀
305
+ - 调整 v1.1.11 优先级配置的默认值
306
+
307
+ - 2025.06.01 v1.1.12
308
+
309
+ - 禁用 `discord` 适配器中的按钮操作 ~~以后会写适配的...吗?~~
310
+
281
311
  - 2025.04.20 v1.1.11
282
312
 
283
313
  - 添加配置项 `werewolf__require_at`, 用于配置命令是否需要 at 机器人触发
@@ -362,7 +392,7 @@ werewolf__require_at='{"start": true, "terminate": false}'
362
392
 
363
393
  </details>
364
394
 
365
- ## 鸣谢
395
+ ## 🎉 鸣谢
366
396
 
367
397
  - [`nonebot/nonebot2`](https://github.com/nonebot/nonebot2): 跨平台 Python 异步机器人框架
368
398
  - [`nonebot/plugin-alconna`](https://github.com/nonebot/plugin-alconna): 跨平台的消息处理接口
@@ -30,6 +30,22 @@ _✨ 简单的狼人杀插件 ✨_
30
30
 
31
31
  和朋友们来一场紧张刺激的狼人杀游戏
32
32
 
33
+ <!-- ref: https://github.com/KomoriDev/Starify -->
34
+
35
+ > [!IMPORTANT]
36
+ >
37
+ > **收藏项目**,你将从 GitHub 上无延迟地接收所有发布通知~ ⭐️
38
+
39
+ <img width="100%" src="https://starify.komoridevs.icu/api/starify?owner=wyf7685&repo=nonebot-plugin-werewolf" alt="starify" />
40
+
41
+ <details>
42
+ <summary><kbd>Star History</kbd></summary>
43
+ <picture>
44
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=wyf7685/nonebot-plugin-werewolf&theme=dark&type=Date" />
45
+ <img width="100%" src="https://star-history.com/#wyf7685/nonebot-plugin-werewolf&Date" />
46
+ </picture>
47
+ </details>
48
+
33
49
  ## 💿 安装
34
50
 
35
51
  > [!note]
@@ -91,17 +107,18 @@ _✨ 简单的狼人杀插件 ✨_
91
107
 
92
108
  在 nonebot2 项目的 `.env` 文件中添加如下配置:
93
109
 
94
- | 配置项 | 必填 | 默认值 | 类型 | 说明 |
95
- | :--------------------------: | :--: | :-----: | :-----------------------: | :----------------------------: |
96
- | `werewolf__enable_poke` | 否 | `True` | `bool` | 是否使用戳一戳简化操作流程 |
97
- | `werewolf__enable_button` | 否 | `False` | `bool` | 是否在交互中添加按钮 |
98
- | `werewolf__stop_command` | 否 | `stop` | `str \| set[str]` | 修改游戏进程中的 `stop` 命令 |
99
- | `werewolf__require_at` | 否 | `True` | `bool \| RequireAtConfig` | 部分命令是否需要 at 机器人触发 |
100
- | `werewolf__matcher_priority` | 否 | - | `MatcherPriorityConfig` | 配置插件 matcher 注册的优先级 |
110
+ | 配置项 | 必填 | 默认值 | 类型 | 说明 |
111
+ | :--------------------------: | :--: | :-----: | :-----------------------: | :-------------------------------------------: |
112
+ | `werewolf__enable_poke` | 否 | `True` | `bool` | 是否使用戳一戳简化操作流程 |
113
+ | `werewolf__enable_button` | 否 | `False` | `bool` | 是否在交互中添加按钮 |
114
+ | `werewolf__stop_command` | 否 | `stop` | `str \| set[str]` | 修改游戏进程中的 `stop` 命令 |
115
+ | `werewolf__require_at` | 否 | `True` | `bool \| RequireAtConfig` | 部分命令是否需要 at 机器人触发 |
116
+ | `werewolf__matcher_priority` | 否 | - | `MatcherPriorityConfig` | 配置插件 matcher 注册的优先级 |
117
+ | `werewolf__use_cmd_start` | 否 | `None` | `bool \| None` | 是否使用配置项 `COMMAND_START` 来作为命令前缀 |
101
118
 
102
119
  `werewolf__enable_poke` 仅在 `OneBot V11` 适配器 / `Satori/chronocat` 下生效
103
120
 
104
- `werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性。如有疑问欢迎提出。
121
+ `werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性,如有疑问欢迎提出。
105
122
 
106
123
  <details>
107
124
  <summary> werewolf__require_at 示例 </summary>
@@ -116,15 +133,18 @@ werewolf__require_at=false
116
133
  # 狼人杀命令需要 at, 中止游戏命令不需要 at
117
134
  werewolf__require_at='{"start": true, "terminate": false}'
118
135
  ```
136
+
119
137
  </details>
120
- <br/>
121
138
 
122
139
  `werewolf__matcher_priority` 的 matcher 优先级参考 [官方文档](https://nonebot.dev/docs/advanced/matcher#%E5%93%8D%E5%BA%94%E4%BC%98%E5%85%88%E7%BA%A7)
123
- - 一般情况下不需要修改此配置, 插件的默认优先级可以参考 [这里](./nonebot_plugin_werewolf/config.py) 的 `MatcherPriorityConfig`
124
- - 如果遇到与其他插件的命令冲突, 可考虑修改此处的优先级配置
125
- - 配置应填入 JSON 对象, 可用键: `start` `terminate` `preset` `behavior` `in_game` `stop`
126
140
 
127
- ## 🎉 使用
141
+ - 一般情况下不需要修改此配置, 插件的默认优先级可以参考 [这里](./nonebot_plugin_werewolf/config.py) 的 `MatcherPriorityConfig`
142
+ - 如果遇到与其他插件的命令冲突, 可考虑修改此处的优先级配置
143
+ - 配置应填入 JSON 对象, 可用键: `start` `terminate` `preset` `behavior` `in_game` `stop`
144
+
145
+ `werewolf__use_cmd_start` 为 `None` 时,使用 alc 的 [全局配置](https://nonebot.dev/docs/next/best-practice/alconna/config#alconna_use_command_start)
146
+
147
+ ## 🚀 使用
128
148
 
129
149
  > [!note]
130
150
  >
@@ -145,19 +165,19 @@ werewolf__require_at='{"start": true, "terminate": false}'
145
165
 
146
166
  </details>
147
167
 
148
- ### 指令表
168
+ ### 📋 指令表
149
169
 
150
- | 指令 | 权限 | 需要@ | 范围 | 说明 |
151
- | :-----------------: | :-----------------: | :---: | :--: | :---------------------------------------: |
152
- | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 | 发起游戏 (进入准备阶段) |
153
- | `开始游戏` | 游戏发起者 | 否 | 群聊 | _[准备阶段]_ 游戏发起者开始游戏 |
154
- | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 | _[准备阶段]_ 游戏发起者/超级用户 结束游戏 |
155
- | `当前玩家` | 群员 | 否 | 群聊 | _[准备阶段]_ 列出参与游戏的玩家列表 |
156
- | `加入游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家加入游戏 |
157
- | `退出游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家退出游戏 |
158
- | `中止游戏` | 超级用户 | 是 | 群聊 | _[游戏内]_ 超级用户强制中止游戏 |
159
- | `狼人杀预设` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏预设 |
160
- | `狼人杀配置` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏配置 |
170
+ | 指令 | 权限 | 需要@ | 范围 | 说明 |
171
+ | :-----------------: | :-----------------: | :---: | :---------------: | :--------------------------: |
172
+ | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 _[游戏外]_ | 发起游戏 (进入准备阶段) |
173
+ | `开始游戏` | 游戏发起者 | 否 | 群聊 _[准备阶段]_ | 游戏发起者开始游戏 |
174
+ | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 _[准备阶段]_ | 游戏发起者/超级用户 结束游戏 |
175
+ | `当前玩家` | 群员 | 否 | 群聊 _[准备阶段]_ | 列出参与游戏的玩家列表 |
176
+ | `加入游戏` | 群员 | 否 | 群聊 _[准备阶段]_ | 玩家加入游戏 |
177
+ | `退出游戏` | 群员 | 否 | 群聊 _[准备阶段]_ | 玩家退出游戏 |
178
+ | `中止游戏` | 超级用户 | 是 | 群聊 _[游戏内]_ | 超级用户强制中止游戏 |
179
+ | `狼人杀预设` | 超级用户 | 否 | 任意 _[游戏外]_ | 超级用户编辑游戏预设 |
180
+ | `狼人杀配置` | 超级用户 | 否 | 任意 _[游戏外]_ | 超级用户编辑游戏配置 |
161
181
 
162
182
  - `超级用户` 为 nonebot2 配置项中的 `SUPERUSERS`, 配置说明参考 [官方文档](https://nonebot.dev/docs/appendices/config#superusers)
163
183
 
@@ -171,7 +191,7 @@ werewolf__require_at='{"start": true, "terminate": false}'
171
191
 
172
192
  - _其他交互参考游戏内提示_
173
193
 
174
- ### 游戏内容
194
+ ### 🎭 游戏内容
175
195
 
176
196
  > [!note]
177
197
  >
@@ -182,14 +202,14 @@ werewolf__require_at='{"start": true, "terminate": false}'
182
202
  插件中保存了一份 [职业预设](./nonebot_plugin_werewolf/constant.py), 内容如下
183
203
 
184
204
  | 总人数 | 狼人 | 神职 | 平民 |
185
- | ------ | ---- | ---- | ---- |
186
- | 6 | 1 | 2 | 3 |
187
- | 7 | 2 | 2 | 3 |
188
- | 8 | 2 | 3 | 3 |
189
- | 9 | 2 | 4 | 3 |
190
- | 10 | 3 | 4 | 3 |
191
- | 11 | 3 | 5 | 3 |
192
- | 12 | 4 | 5 | 3 |
205
+ | :----: | :--: | :--: | :--: |
206
+ | 6 | 1 | 2 | 3 |
207
+ | 7 | 2 | 2 | 3 |
208
+ | 8 | 2 | 3 | 3 |
209
+ | 9 | 2 | 4 | 3 |
210
+ | 10 | 3 | 4 | 3 |
211
+ | 11 | 3 | 5 | 3 |
212
+ | 12 | 4 | 5 | 3 |
193
213
 
194
214
  职业预设可以通过命令 `狼人杀预设 职业 ...` 修改
195
215
 
@@ -234,7 +254,6 @@ werewolf__require_at='{"start": true, "terminate": false}'
234
254
  > 其效果等同于以上描述中的单条命令 `狼人杀预设 狼人 狼人 狼王 狼人 狼人`
235
255
 
236
256
  </details>
237
- <br/>
238
257
 
239
258
  对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 _一定概率_ 将其中一个平民替换为小丑。
240
259
 
@@ -242,12 +261,14 @@ werewolf__require_at='{"start": true, "terminate": false}'
242
261
 
243
262
  小丑生成概率可以通过命令 `狼人杀预设 小丑 <概率>` 设置,默认值为 0 (不生成小丑)。
244
263
 
245
- ### 已知问题
264
+ ### 🔧 已知问题
246
265
 
247
266
  <details>
248
267
  <summary>已知问题</summary>
249
268
 
250
- - 截止 chronocat v0.2.19, 调用 [`guild.member.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/guild/member/get.ts) / [`user.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/user/get.ts) 均无法获取用户名,这将导致在交互过程中的玩家名显示为用户 ID
269
+ - 截止 chronocat [v0.2.19](https://github.com/chrononeko/chronocat/tree/v0.2.19), 调用 [`guild.member.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/guild/member/get.ts) / [`user.get`](https://github.com/chrononeko/chronocat/blob/8558ad9ff4319395d86abbfda22136939bf66780/packages/engine-chronocat-api/src/api/user/get.ts) 均无法获取用户名,这将导致在交互过程中的玩家名显示为用户 ID
270
+
271
+ - v1.1.6 添加的按钮操作在 `discord` 适配器中不可用, 已在 v1.1.12 禁用 (2e31d43)
251
272
 
252
273
  </details>
253
274
 
@@ -258,6 +279,15 @@ werewolf__require_at='{"start": true, "terminate": false}'
258
279
 
259
280
  <!-- CHANGELOG -->
260
281
 
282
+ - 2025.06.04 v1.1.13
283
+
284
+ - 添加配置项 `werewolf__use_cmd_start`, 用于配置插件命令前缀
285
+ - 调整 v1.1.11 优先级配置的默认值
286
+
287
+ - 2025.06.01 v1.1.12
288
+
289
+ - 禁用 `discord` 适配器中的按钮操作 ~~以后会写适配的...吗?~~
290
+
261
291
  - 2025.04.20 v1.1.11
262
292
 
263
293
  - 添加配置项 `werewolf__require_at`, 用于配置命令是否需要 at 机器人触发
@@ -342,7 +372,7 @@ werewolf__require_at='{"start": true, "terminate": false}'
342
372
 
343
373
  </details>
344
374
 
345
- ## 鸣谢
375
+ ## 🎉 鸣谢
346
376
 
347
377
  - [`nonebot/nonebot2`](https://github.com/nonebot/nonebot2): 跨平台 Python 异步机器人框架
348
378
  - [`nonebot/plugin-alconna`](https://github.com/nonebot/plugin-alconna): 跨平台的消息处理接口
@@ -10,7 +10,7 @@ from . import matchers as matchers
10
10
  from . import players as players
11
11
  from .config import Config
12
12
 
13
- __version__ = "1.1.11"
13
+ __version__ = "1.1.13"
14
14
  __plugin_meta__ = PluginMetadata(
15
15
  name="狼人杀",
16
16
  description="适用于 Nonebot2 的狼人杀插件",
@@ -1,10 +1,11 @@
1
1
  import json
2
+ import warnings
2
3
  from pathlib import Path
3
4
  from typing import Any, ClassVar, Final, Literal
4
5
  from typing_extensions import Self
5
6
 
6
7
  import nonebot
7
- from nonebot.compat import model_dump, type_validate_json
8
+ from nonebot.compat import model_dump, model_validator, type_validate_json
8
9
  from nonebot_plugin_localstore import get_plugin_data_file
9
10
  from pydantic import BaseModel, Field
10
11
 
@@ -12,37 +13,36 @@ from .constant import (
12
13
  DEFAULT_PRIESTHOOD_PRIORITY,
13
14
  DEFAULT_ROLE_PRESET,
14
15
  DEFAULT_WEREWOLF_PRIORITY,
15
- stop_command_prompt,
16
16
  )
17
17
  from .models import Role
18
18
 
19
19
 
20
20
  class ConfigFile(BaseModel):
21
- FILE: ClassVar[Path]
22
- _cache: ClassVar[Self | None] = None
21
+ _file_: ClassVar[Path]
22
+ _cache_: ClassVar[Self | None] = None
23
23
 
24
24
  def __init_subclass__(cls, **kwargs: Any) -> None: # noqa: ANN401
25
25
  super().__init_subclass__(**kwargs)
26
- if not cls.FILE.exists():
26
+ if not cls._file_.exists():
27
27
  cls().save()
28
28
 
29
29
  @classmethod
30
30
  def load(cls) -> Self:
31
- return type_validate_json(cls, cls.FILE.read_text())
31
+ return type_validate_json(cls, cls._file_.read_text())
32
32
 
33
33
  @classmethod
34
34
  def get(cls, *, use_cache: bool = True) -> Self:
35
- if cls._cache is None or not use_cache:
36
- cls._cache = cls.load()
37
- return cls._cache
35
+ if cls._cache_ is None or not use_cache:
36
+ cls._cache_ = cls.load()
37
+ return cls._cache_
38
38
 
39
39
  def save(self) -> None:
40
- self.FILE.write_text(json.dumps(model_dump(self)))
41
- type(self)._cache = self # noqa: SLF001
40
+ self._file_.write_text(json.dumps(model_dump(self)))
41
+ type(self)._cache_ = self
42
42
 
43
43
 
44
44
  class PresetData(ConfigFile):
45
- FILE: ClassVar[Path] = get_plugin_data_file("preset.json")
45
+ _file_: ClassVar[Path] = get_plugin_data_file("preset.json")
46
46
 
47
47
  role_preset: dict[int, tuple[int, int, int]] = DEFAULT_ROLE_PRESET.copy()
48
48
  werewolf_priority: list[Role] = DEFAULT_WEREWOLF_PRIORITY.copy()
@@ -50,36 +50,33 @@ class PresetData(ConfigFile):
50
50
  jester_probability: float = Field(default=0.0, ge=0.0, le=1.0)
51
51
 
52
52
 
53
+ class _Timeout(BaseModel):
54
+ prepare: int = Field(default=5 * 60, ge=5 * 60)
55
+ speak: int = Field(default=60, ge=60)
56
+ group_speak: int = Field(default=120, ge=120)
57
+ interact: int = Field(default=60, ge=60)
58
+ vote: int = Field(default=60, ge=60)
59
+ werewolf: int = Field(default=120, ge=120)
60
+
61
+ @property
62
+ def speak_timeout_prompt(self) -> str:
63
+ return f"限时{self.speak / 60:.1f}分钟, 发送 “{stop_command_prompt}” 结束发言"
64
+
65
+ @property
66
+ def group_speak_timeout_prompt(self) -> str:
67
+ return (
68
+ f"限时{self.group_speak / 60:.1f}分钟, "
69
+ f"全员发送 “{stop_command_prompt}” 结束发言"
70
+ )
71
+
72
+
53
73
  class GameBehavior(ConfigFile):
54
- FILE: ClassVar[Path] = get_plugin_data_file("behavior.json")
74
+ _file_: ClassVar[Path] = get_plugin_data_file("behavior.json")
55
75
 
56
76
  show_roles_list_on_start: bool = False
57
77
  speak_in_turn: bool = False
58
78
  dead_channel_rate_limit: int = 8 # per minute
59
79
  werewolf_multi_select: bool = False
60
-
61
- class _Timeout(BaseModel):
62
- prepare: int = Field(default=5 * 60, ge=5 * 60)
63
- speak: int = Field(default=60, ge=60)
64
- group_speak: int = Field(default=120, ge=120)
65
- interact: int = Field(default=60, ge=60)
66
- vote: int = Field(default=60, ge=60)
67
- werewolf: int = Field(default=120, ge=120)
68
-
69
- @property
70
- def speak_timeout_prompt(self) -> str:
71
- return (
72
- f"限时{self.speak / 60:.1f}分钟, "
73
- f"发送 “{stop_command_prompt()}” 结束发言"
74
- )
75
-
76
- @property
77
- def group_speak_timeout_prompt(self) -> str:
78
- return (
79
- f"限时{self.group_speak / 60:.1f}分钟, "
80
- f"全员发送 “{stop_command_prompt()}” 结束发言"
81
- )
82
-
83
80
  timeout: Final[_Timeout] = _Timeout()
84
81
 
85
82
 
@@ -94,7 +91,18 @@ class MatcherPriorityConfig(BaseModel):
94
91
  preset: int = 1
95
92
  behavior: int = 1
96
93
  in_game: int = 10
97
- stop: int = 10
94
+ stop: int = 9
95
+
96
+ @model_validator(mode="after")
97
+ @classmethod
98
+ def _validate(cls, model: Self) -> Self:
99
+ if model.in_game <= model.stop:
100
+ model.in_game = model.stop + 1
101
+ warnings.warn(
102
+ "in_game 的优先级必须低于 stop,已自动调整为 stop + 1",
103
+ stacklevel=2,
104
+ )
105
+ return model
98
106
 
99
107
 
100
108
  class PluginConfig(BaseModel):
@@ -103,6 +111,7 @@ class PluginConfig(BaseModel):
103
111
  stop_command: str | set[str] = "stop"
104
112
  require_at: bool | RequireAtConfig = True
105
113
  matcher_priority: MatcherPriorityConfig = MatcherPriorityConfig()
114
+ use_cmd_start: bool | None = None
106
115
 
107
116
  def get_stop_command(self) -> list[str]:
108
117
  return (
@@ -123,3 +132,8 @@ class Config(BaseModel):
123
132
 
124
133
  config = nonebot.get_plugin_config(Config).werewolf
125
134
  nonebot.logger.debug(f"加载插件配置: {config}")
135
+
136
+ stop_command_prompt = (
137
+ next(iter(sorted(nonebot.get_driver().config.command_start, key=len)), "")
138
+ + config.get_stop_command()[0]
139
+ )
@@ -1,25 +1,8 @@
1
- import functools
2
- from typing import TYPE_CHECKING
3
-
4
1
  from .models import GameStatus, KillReason, Role, RoleGroup
5
2
 
6
3
  STOP_COMMAND = "{{stop}}"
7
4
 
8
5
 
9
- def stop_command_prompt() -> str:
10
- import nonebot
11
-
12
- from .config import config # circular import
13
-
14
- cmd_starts = sorted(nonebot.get_driver().config.command_start, key=len)
15
- return next(iter(cmd_starts), "") + config.get_stop_command()[0]
16
-
17
-
18
- if not TYPE_CHECKING:
19
- stop_command_prompt = functools.cache(stop_command_prompt)
20
- del TYPE_CHECKING
21
-
22
-
23
6
  ROLE_NAME_CONV: dict[Role | RoleGroup, str] = {
24
7
  Role.WEREWOLF: "狼人",
25
8
  Role.WOLFKING: "狼王",