nonebot-plugin-werewolf 1.1.9__tar.gz → 1.1.11__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 (42) hide show
  1. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/PKG-INFO +89 -41
  2. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/README.md +84 -36
  3. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/__init__.py +1 -1
  4. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/config.py +22 -1
  5. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/constant.py +4 -6
  6. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/game.py +16 -18
  7. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/depends.py +2 -2
  8. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/edit_behavior.py +8 -4
  9. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/edit_preset.py +8 -9
  10. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/message_in_game.py +5 -1
  11. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/poke/__init__.py +2 -1
  12. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py +4 -9
  13. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/poke/ob11_poke.py +5 -8
  14. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/start_game.py +8 -5
  15. nonebot_plugin_werewolf-1.1.11/nonebot_plugin_werewolf/matchers/superuser_ops.py +32 -0
  16. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/player.py +1 -2
  17. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/player_set.py +10 -0
  18. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/utils.py +12 -1
  19. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf.egg-info/PKG-INFO +89 -41
  20. nonebot_plugin_werewolf-1.1.11/nonebot_plugin_werewolf.egg-info/requires.txt +6 -0
  21. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/pyproject.toml +5 -5
  22. nonebot_plugin_werewolf-1.1.9/nonebot_plugin_werewolf/matchers/superuser_ops.py +0 -24
  23. nonebot_plugin_werewolf-1.1.9/nonebot_plugin_werewolf.egg-info/requires.txt +0 -6
  24. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/LICENSE +0 -0
  25. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/exception.py +0 -0
  26. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/matchers/__init__.py +0 -0
  27. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/models.py +0 -0
  28. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/__init__.py +0 -0
  29. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/civilian.py +0 -0
  30. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/guard.py +0 -0
  31. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/hunter.py +0 -0
  32. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/idiot.py +0 -0
  33. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/jester.py +0 -0
  34. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/prophet.py +0 -0
  35. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/shooter.py +0 -0
  36. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/werewolf.py +0 -0
  37. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/witch.py +0 -0
  38. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf/players/wolfking.py +0 -0
  39. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf.egg-info/SOURCES.txt +0 -0
  40. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf.egg-info/dependency_links.txt +0 -0
  41. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/nonebot_plugin_werewolf.egg-info/top_level.txt +0 -0
  42. {nonebot_plugin_werewolf-1.1.9 → nonebot_plugin_werewolf-1.1.11}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-werewolf
3
- Version: 1.1.9
3
+ Version: 1.1.11
4
4
  Summary: 适用于 Nonebot2 的狼人杀插件
5
5
  Author-email: wyf7685 <wyf7685@163.com>
6
6
  License: MIT
@@ -10,11 +10,11 @@ Project-URL: bug-tracker, https://github.com/wyf7685/nonebot-plugin-werewolf/iss
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: nonebot2>=2.3.3
14
- Requires-Dist: nonebot-plugin-alconna>=0.52.1
13
+ Requires-Dist: nonebot2>=2.4.0
14
+ Requires-Dist: nonebot-plugin-alconna>=0.57.0
15
15
  Requires-Dist: nonebot-plugin-localstore>=0.7.1
16
- Requires-Dist: nonebot-plugin-uninfo>=0.4.0
17
- Requires-Dist: nonebot-plugin-waiter>=0.7.1
16
+ Requires-Dist: nonebot-plugin-uninfo>=0.7.3
17
+ Requires-Dist: nonebot-plugin-waiter>=0.8.0
18
18
  Requires-Dist: anyio>=4.6.0
19
19
  Dynamic: license-file
20
20
 
@@ -39,7 +39,8 @@ _✨ 简单的狼人杀插件 ✨_
39
39
  [![pre-commit](https://results.pre-commit.ci/badge/github/wyf7685/nonebot-plugin-werewolf/master.svg)](https://results.pre-commit.ci/latest/github/wyf7685/nonebot-plugin-werewolf/master)
40
40
  [![lint](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/lint.yml/badge.svg?branch=master&event=push)](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/lint.yml)
41
41
 
42
- <!-- https://github.com/lgc2333/nonebot-registry-badge -->
42
+ <!-- ref: https://github.com/lgc2333/nonebot-registry-badge -->
43
+
43
44
  [![NoneBot Registry](https://img.shields.io/endpoint?url=https%3A%2F%2Fnbbdg.lgc2333.top%2Fplugin%2Fnonebot-plugin-werewolf)](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
44
45
  [![Supported Adapters](https://img.shields.io/endpoint?url=https%3A%2F%2Fnbbdg.lgc2333.top%2Fplugin-adapters%2Fnonebot-plugin-werewolf)](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
45
46
 
@@ -53,7 +54,7 @@ _✨ 简单的狼人杀插件 ✨_
53
54
 
54
55
  > [!note]
55
56
  >
56
- > 请确保 NoneBot2 使用的 Python 解释器版本 >=3.10
57
+ > 请确保 [NoneBot2](https://nonebot.dev/) 使用的 Python 解释器版本 >=3.10
57
58
 
58
59
  <details open>
59
60
  <summary>使用 nb-cli 安装</summary>
@@ -65,12 +66,14 @@ _✨ 简单的狼人杀插件 ✨_
65
66
 
66
67
  <details>
67
68
  <summary>使用包管理器安装</summary>
69
+ <!-- 会用包管理器的用户真的需要这节吗 -->
70
+
68
71
  在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
69
72
 
70
- <details>
71
- <summary>pip</summary>
73
+ <details open>
74
+ <summary>uv</summary>
72
75
 
73
- pip install nonebot-plugin-werewolf
76
+ uv add nonebot-plugin-werewolf
74
77
 
75
78
  </details>
76
79
  <details>
@@ -90,6 +93,12 @@ _✨ 简单的狼人杀插件 ✨_
90
93
 
91
94
  conda install nonebot-plugin-werewolf
92
95
 
96
+ </details>
97
+ <details>
98
+ <summary>pip</summary>
99
+
100
+ pip install nonebot-plugin-werewolf
101
+
93
102
  </details>
94
103
 
95
104
  打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
@@ -102,16 +111,39 @@ _✨ 简单的狼人杀插件 ✨_
102
111
 
103
112
  在 nonebot2 项目的 `.env` 文件中添加如下配置:
104
113
 
105
- | 配置项 | 必填 | 默认值 | 说明 |
106
- | :-----------------------: | :---: | :-----: | :--------------------------: |
107
- | `werewolf__enable_poke` | 否 | `True` | 是否使用戳一戳简化操作流程 |
108
- | `werewolf__enable_button` | 否 | `False` | 是否在交互中添加按钮 |
109
- | `werewolf__stop_command` | 否 | `stop` | 修改游戏进程中的 `stop` 命令 |
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 注册的优先级 |
110
121
 
111
122
  `werewolf__enable_poke` 仅在 `OneBot V11` 适配器 / `Satori/chronocat` 下生效
112
123
 
113
124
  `werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性。如有疑问欢迎提出。
114
125
 
126
+ <details>
127
+ <summary> werewolf__require_at 示例 </summary>
128
+
129
+ ```ini
130
+ # 所有命令均需 at 触发
131
+ werewolf__require_at=true
132
+
133
+ # 所有命令均不需 at 触发
134
+ werewolf__require_at=false
135
+
136
+ # 狼人杀命令需要 at, 中止游戏命令不需要 at
137
+ werewolf__require_at='{"start": true, "terminate": false}'
138
+ ```
139
+ </details>
140
+ <br/>
141
+
142
+ `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
+
115
147
  ## 🎉 使用
116
148
 
117
149
  > [!note]
@@ -135,28 +167,29 @@ _✨ 简单的狼人杀插件 ✨_
135
167
 
136
168
  ### 指令表
137
169
 
138
- | 指令 | 权限 | 需要@ | 范围 | 说明 |
139
- | :-----------------: | :-----------------: | :---: | :---: | :---------------------------------------: |
140
- | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 | 发起游戏 (进入准备阶段) |
141
- | `开始游戏` | 游戏发起者 | 否 | 群聊 | _[准备阶段]_ 游戏发起者开始游戏 |
142
- | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 | _[准备阶段]_ 游戏发起者/超级用户 结束游戏 |
143
- | `当前玩家` | 群员 | 否 | 群聊 | _[准备阶段]_ 列出参与游戏的玩家列表 |
144
- | `加入游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家加入游戏 |
145
- | `退出游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家退出游戏 |
146
- | `中止游戏` | 超级用户 | 是 | 群聊 | _[游戏内]_ 超级用户强制中止游戏 |
147
- | `狼人杀预设` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏预设 |
148
- | `狼人杀配置` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏配置 |
170
+ | 指令 | 权限 | 需要@ | 范围 | 说明 |
171
+ | :-----------------: | :-----------------: | :---: | :--: | :---------------------------------------: |
172
+ | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 | 发起游戏 (进入准备阶段) |
173
+ | `开始游戏` | 游戏发起者 | 否 | 群聊 | _[准备阶段]_ 游戏发起者开始游戏 |
174
+ | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 | _[准备阶段]_ 游戏发起者/超级用户 结束游戏 |
175
+ | `当前玩家` | 群员 | 否 | 群聊 | _[准备阶段]_ 列出参与游戏的玩家列表 |
176
+ | `加入游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家加入游戏 |
177
+ | `退出游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家退出游戏 |
178
+ | `中止游戏` | 超级用户 | 是 | 群聊 | _[游戏内]_ 超级用户强制中止游戏 |
179
+ | `狼人杀预设` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏预设 |
180
+ | `狼人杀配置` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏配置 |
149
181
 
150
- - 发起游戏时添加 `restart`/`重开`, 可加载上一次游戏的玩家列表, 快速发起游戏。例: `werewolf restart`/`狼人杀 重开`
182
+ - `超级用户` nonebot2 配置项中的 `SUPERUSERS`, 配置说明参考 [官方文档](https://nonebot.dev/docs/appendices/config#superusers)
151
183
 
152
- - `狼人杀预设` 命令用法可通过 `狼人杀预设 --help` 获取,或参考 [游戏内容](#游戏内容) 部分的介绍
184
+ - 发起游戏时添加 `restart`/`重开`, 可加载上一次游戏的玩家列表, 快速发起游戏。例: `werewolf restart`/`狼人杀 重开`
153
185
 
154
- - `狼人杀配置` 命令用法可通过 `狼人杀预设 --help` 获取
186
+ - `狼人杀预设` 命令用法可通过 `狼人杀预设 --help` 获取,或参考 [游戏内容](#游戏内容) 部分的介绍
155
187
 
156
- - 对于 `OneBot V11` 适配器和 `Satori` 适配器的 `chronocat`, 启用配置项 `werewolf__enable_poke` 后, 可以使用戳一戳代替 _准备阶段_ 的 `加入游戏` 操作 和 游戏内的 `stop` 命令
188
+ - `狼人杀配置` 命令用法可通过 `狼人杀预设 --help` 获取
157
189
 
158
- - _其他交互参考游戏内提示_
190
+ - 对于 `OneBot V11` 适配器和 `Satori` 适配器的 `chronocat`, 启用配置项 `werewolf__enable_poke` 后, 可以使用戳一戳代替 _准备阶段_ 的 `加入游戏` 操作 和 游戏内的 `stop` 命令
159
191
 
192
+ - _其他交互参考游戏内提示_
160
193
 
161
194
  ### 游戏内容
162
195
 
@@ -183,9 +216,9 @@ _✨ 简单的狼人杀插件 ✨_
183
216
  <details>
184
217
  <summary>示例</summary>
185
218
 
186
- - 命令: `狼人杀预设 职业 6 1 3 2`
219
+ - 命令: `狼人杀预设 职业 6 1 3 2`
187
220
 
188
- - 上述命令指定当总人数为 6 时,狼人、神职、平民的数量分别为 1、3、2
221
+ - 上述命令指定当总人数为 6 时,狼人、神职、平民的数量分别为 1、3、2
189
222
 
190
223
  </details>
191
224
  <br/>
@@ -202,19 +235,19 @@ _✨ 简单的狼人杀插件 ✨_
202
235
 
203
236
  #### 命令 `狼人杀预设 狼人`
204
237
 
205
- - 命令: `狼人杀预设 狼人 狼 狼王 狼 狼`
238
+ - 命令: `狼人杀预设 狼人 狼 狼王 狼 狼`
206
239
 
207
- - 上述命令指定狼人的职业优先级为 `狼人`, `狼王`, `狼人`, `狼人`
240
+ - 上述命令指定狼人的职业优先级为 `狼人`, `狼王`, `狼人`, `狼人`
208
241
 
209
242
  #### 命令 `狼人杀预设 神职`
210
243
 
211
- - 命令: `狼人杀预设 神职 预言家 女巫 猎人 守卫 白痴`
244
+ - 命令: `狼人杀预设 神职 预言家 女巫 猎人 守卫 白痴`
212
245
 
213
- - 上述命令指定狼人的职业优先级为 `预言家`, `女巫`, `猎人`, `守卫`, `白痴`
246
+ - 上述命令指定神职的职业优先级为 `预言家`, `女巫`, `猎人`, `守卫`, `白痴`
214
247
 
215
248
  > [!note]
216
249
  >
217
- > 以上两条命令均支持交互式输入
250
+ > 以上两条命令均支持交互式输入 ~~waiter 真好用~~
218
251
  >
219
252
  > 例:向机器人发送命令 `狼人杀预设 狼人`,在接下来的一条消息中发送 `狼人 狼王 狼人 狼人`
220
253
  >
@@ -223,7 +256,7 @@ _✨ 简单的狼人杀插件 ✨_
223
256
  </details>
224
257
  <br/>
225
258
 
226
- 对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 *一定概率* 将其中一个平民替换为小丑。
259
+ 对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 _一定概率_ 将其中一个平民替换为小丑。
227
260
 
228
261
  小丑属于第三方阵营,胜利条件为在投票阶段被票出,在预言家查验及游戏进程判断时视作平民。
229
262
 
@@ -231,8 +264,13 @@ _✨ 简单的狼人杀插件 ✨_
231
264
 
232
265
  ### 已知问题
233
266
 
267
+ <details>
268
+ <summary>已知问题</summary>
269
+
234
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
235
271
 
272
+ </details>
273
+
236
274
  ## 📝 更新日志
237
275
 
238
276
  <details>
@@ -240,11 +278,21 @@ _✨ 简单的狼人杀插件 ✨_
240
278
 
241
279
  <!-- CHANGELOG -->
242
280
 
281
+ - 2025.04.20 v1.1.11
282
+
283
+ - 添加配置项 `werewolf__require_at`, 用于配置命令是否需要 at 机器人触发
284
+ - 添加配置项 `werewolf__matcher_priority`, 用于配置插件 matcher 注册优先级
285
+
286
+ - 2025.04.17 v1.1.10
287
+
288
+ - 添加狼人多选目标配置项显示
289
+ - 在游戏开始时打乱并固定轮流发言模式的发言顺序 (#20)
290
+
243
291
  - 2025.04.15 v1.1.9
244
292
 
245
293
  - 添加游戏行为配置 `werewolf_multi_select`
246
294
  - 重构玩家类
247
- - 添加轮流发言模式缺失的 at 消息段
295
+ - 添加轮流发言模式缺失的 at 消息段 (#19)
248
296
 
249
297
  - 2025.02.13 v1.1.8
250
298
 
@@ -254,7 +302,7 @@ _✨ 简单的狼人杀插件 ✨_
254
302
 
255
303
  - 2024.10.31 v1.1.7
256
304
 
257
- - *Bug fix*
305
+ - _Bug fix_
258
306
 
259
307
  - 2024.10.31 v1.1.6
260
308
 
@@ -19,7 +19,8 @@ _✨ 简单的狼人杀插件 ✨_
19
19
  [![pre-commit](https://results.pre-commit.ci/badge/github/wyf7685/nonebot-plugin-werewolf/master.svg)](https://results.pre-commit.ci/latest/github/wyf7685/nonebot-plugin-werewolf/master)
20
20
  [![lint](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/lint.yml/badge.svg?branch=master&event=push)](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/lint.yml)
21
21
 
22
- <!-- https://github.com/lgc2333/nonebot-registry-badge -->
22
+ <!-- ref: https://github.com/lgc2333/nonebot-registry-badge -->
23
+
23
24
  [![NoneBot Registry](https://img.shields.io/endpoint?url=https%3A%2F%2Fnbbdg.lgc2333.top%2Fplugin%2Fnonebot-plugin-werewolf)](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
24
25
  [![Supported Adapters](https://img.shields.io/endpoint?url=https%3A%2F%2Fnbbdg.lgc2333.top%2Fplugin-adapters%2Fnonebot-plugin-werewolf)](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
25
26
 
@@ -33,7 +34,7 @@ _✨ 简单的狼人杀插件 ✨_
33
34
 
34
35
  > [!note]
35
36
  >
36
- > 请确保 NoneBot2 使用的 Python 解释器版本 >=3.10
37
+ > 请确保 [NoneBot2](https://nonebot.dev/) 使用的 Python 解释器版本 >=3.10
37
38
 
38
39
  <details open>
39
40
  <summary>使用 nb-cli 安装</summary>
@@ -45,12 +46,14 @@ _✨ 简单的狼人杀插件 ✨_
45
46
 
46
47
  <details>
47
48
  <summary>使用包管理器安装</summary>
49
+ <!-- 会用包管理器的用户真的需要这节吗 -->
50
+
48
51
  在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
49
52
 
50
- <details>
51
- <summary>pip</summary>
53
+ <details open>
54
+ <summary>uv</summary>
52
55
 
53
- pip install nonebot-plugin-werewolf
56
+ uv add nonebot-plugin-werewolf
54
57
 
55
58
  </details>
56
59
  <details>
@@ -70,6 +73,12 @@ _✨ 简单的狼人杀插件 ✨_
70
73
 
71
74
  conda install nonebot-plugin-werewolf
72
75
 
76
+ </details>
77
+ <details>
78
+ <summary>pip</summary>
79
+
80
+ pip install nonebot-plugin-werewolf
81
+
73
82
  </details>
74
83
 
75
84
  打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
@@ -82,16 +91,39 @@ _✨ 简单的狼人杀插件 ✨_
82
91
 
83
92
  在 nonebot2 项目的 `.env` 文件中添加如下配置:
84
93
 
85
- | 配置项 | 必填 | 默认值 | 说明 |
86
- | :-----------------------: | :---: | :-----: | :--------------------------: |
87
- | `werewolf__enable_poke` | 否 | `True` | 是否使用戳一戳简化操作流程 |
88
- | `werewolf__enable_button` | 否 | `False` | 是否在交互中添加按钮 |
89
- | `werewolf__stop_command` | 否 | `stop` | 修改游戏进程中的 `stop` 命令 |
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 注册的优先级 |
90
101
 
91
102
  `werewolf__enable_poke` 仅在 `OneBot V11` 适配器 / `Satori/chronocat` 下生效
92
103
 
93
104
  `werewolf__enable_button` 仅在 `Telegram` 适配器下通过测试,不保证在其他适配器的可用性。如有疑问欢迎提出。
94
105
 
106
+ <details>
107
+ <summary> werewolf__require_at 示例 </summary>
108
+
109
+ ```ini
110
+ # 所有命令均需 at 触发
111
+ werewolf__require_at=true
112
+
113
+ # 所有命令均不需 at 触发
114
+ werewolf__require_at=false
115
+
116
+ # 狼人杀命令需要 at, 中止游戏命令不需要 at
117
+ werewolf__require_at='{"start": true, "terminate": false}'
118
+ ```
119
+ </details>
120
+ <br/>
121
+
122
+ `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
+
95
127
  ## 🎉 使用
96
128
 
97
129
  > [!note]
@@ -115,28 +147,29 @@ _✨ 简单的狼人杀插件 ✨_
115
147
 
116
148
  ### 指令表
117
149
 
118
- | 指令 | 权限 | 需要@ | 范围 | 说明 |
119
- | :-----------------: | :-----------------: | :---: | :---: | :---------------------------------------: |
120
- | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 | 发起游戏 (进入准备阶段) |
121
- | `开始游戏` | 游戏发起者 | 否 | 群聊 | _[准备阶段]_ 游戏发起者开始游戏 |
122
- | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 | _[准备阶段]_ 游戏发起者/超级用户 结束游戏 |
123
- | `当前玩家` | 群员 | 否 | 群聊 | _[准备阶段]_ 列出参与游戏的玩家列表 |
124
- | `加入游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家加入游戏 |
125
- | `退出游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家退出游戏 |
126
- | `中止游戏` | 超级用户 | 是 | 群聊 | _[游戏内]_ 超级用户强制中止游戏 |
127
- | `狼人杀预设` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏预设 |
128
- | `狼人杀配置` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏配置 |
150
+ | 指令 | 权限 | 需要@ | 范围 | 说明 |
151
+ | :-----------------: | :-----------------: | :---: | :--: | :---------------------------------------: |
152
+ | `werewolf`/`狼人杀` | 群员 | 是 | 群聊 | 发起游戏 (进入准备阶段) |
153
+ | `开始游戏` | 游戏发起者 | 否 | 群聊 | _[准备阶段]_ 游戏发起者开始游戏 |
154
+ | `结束游戏` | 游戏发起者/超级用户 | 否 | 群聊 | _[准备阶段]_ 游戏发起者/超级用户 结束游戏 |
155
+ | `当前玩家` | 群员 | 否 | 群聊 | _[准备阶段]_ 列出参与游戏的玩家列表 |
156
+ | `加入游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家加入游戏 |
157
+ | `退出游戏` | 群员 | 否 | 群聊 | _[准备阶段]_ 玩家退出游戏 |
158
+ | `中止游戏` | 超级用户 | 是 | 群聊 | _[游戏内]_ 超级用户强制中止游戏 |
159
+ | `狼人杀预设` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏预设 |
160
+ | `狼人杀配置` | 超级用户 | 否 | 任意 | _[游戏外]_ 超级用户编辑游戏配置 |
129
161
 
130
- - 发起游戏时添加 `restart`/`重开`, 可加载上一次游戏的玩家列表, 快速发起游戏。例: `werewolf restart`/`狼人杀 重开`
162
+ - `超级用户` nonebot2 配置项中的 `SUPERUSERS`, 配置说明参考 [官方文档](https://nonebot.dev/docs/appendices/config#superusers)
131
163
 
132
- - `狼人杀预设` 命令用法可通过 `狼人杀预设 --help` 获取,或参考 [游戏内容](#游戏内容) 部分的介绍
164
+ - 发起游戏时添加 `restart`/`重开`, 可加载上一次游戏的玩家列表, 快速发起游戏。例: `werewolf restart`/`狼人杀 重开`
133
165
 
134
- - `狼人杀配置` 命令用法可通过 `狼人杀预设 --help` 获取
166
+ - `狼人杀预设` 命令用法可通过 `狼人杀预设 --help` 获取,或参考 [游戏内容](#游戏内容) 部分的介绍
135
167
 
136
- - 对于 `OneBot V11` 适配器和 `Satori` 适配器的 `chronocat`, 启用配置项 `werewolf__enable_poke` 后, 可以使用戳一戳代替 _准备阶段_ 的 `加入游戏` 操作 和 游戏内的 `stop` 命令
168
+ - `狼人杀配置` 命令用法可通过 `狼人杀预设 --help` 获取
137
169
 
138
- - _其他交互参考游戏内提示_
170
+ - 对于 `OneBot V11` 适配器和 `Satori` 适配器的 `chronocat`, 启用配置项 `werewolf__enable_poke` 后, 可以使用戳一戳代替 _准备阶段_ 的 `加入游戏` 操作 和 游戏内的 `stop` 命令
139
171
 
172
+ - _其他交互参考游戏内提示_
140
173
 
141
174
  ### 游戏内容
142
175
 
@@ -163,9 +196,9 @@ _✨ 简单的狼人杀插件 ✨_
163
196
  <details>
164
197
  <summary>示例</summary>
165
198
 
166
- - 命令: `狼人杀预设 职业 6 1 3 2`
199
+ - 命令: `狼人杀预设 职业 6 1 3 2`
167
200
 
168
- - 上述命令指定当总人数为 6 时,狼人、神职、平民的数量分别为 1、3、2
201
+ - 上述命令指定当总人数为 6 时,狼人、神职、平民的数量分别为 1、3、2
169
202
 
170
203
  </details>
171
204
  <br/>
@@ -182,19 +215,19 @@ _✨ 简单的狼人杀插件 ✨_
182
215
 
183
216
  #### 命令 `狼人杀预设 狼人`
184
217
 
185
- - 命令: `狼人杀预设 狼人 狼 狼王 狼 狼`
218
+ - 命令: `狼人杀预设 狼人 狼 狼王 狼 狼`
186
219
 
187
- - 上述命令指定狼人的职业优先级为 `狼人`, `狼王`, `狼人`, `狼人`
220
+ - 上述命令指定狼人的职业优先级为 `狼人`, `狼王`, `狼人`, `狼人`
188
221
 
189
222
  #### 命令 `狼人杀预设 神职`
190
223
 
191
- - 命令: `狼人杀预设 神职 预言家 女巫 猎人 守卫 白痴`
224
+ - 命令: `狼人杀预设 神职 预言家 女巫 猎人 守卫 白痴`
192
225
 
193
- - 上述命令指定狼人的职业优先级为 `预言家`, `女巫`, `猎人`, `守卫`, `白痴`
226
+ - 上述命令指定神职的职业优先级为 `预言家`, `女巫`, `猎人`, `守卫`, `白痴`
194
227
 
195
228
  > [!note]
196
229
  >
197
- > 以上两条命令均支持交互式输入
230
+ > 以上两条命令均支持交互式输入 ~~waiter 真好用~~
198
231
  >
199
232
  > 例:向机器人发送命令 `狼人杀预设 狼人`,在接下来的一条消息中发送 `狼人 狼王 狼人 狼人`
200
233
  >
@@ -203,7 +236,7 @@ _✨ 简单的狼人杀插件 ✨_
203
236
  </details>
204
237
  <br/>
205
238
 
206
- 对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 *一定概率* 将其中一个平民替换为小丑。
239
+ 对于 `小丑` 职业,当预设中的平民数量大于或等于 2 时,将有 _一定概率_ 将其中一个平民替换为小丑。
207
240
 
208
241
  小丑属于第三方阵营,胜利条件为在投票阶段被票出,在预言家查验及游戏进程判断时视作平民。
209
242
 
@@ -211,8 +244,13 @@ _✨ 简单的狼人杀插件 ✨_
211
244
 
212
245
  ### 已知问题
213
246
 
247
+ <details>
248
+ <summary>已知问题</summary>
249
+
214
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
215
251
 
252
+ </details>
253
+
216
254
  ## 📝 更新日志
217
255
 
218
256
  <details>
@@ -220,11 +258,21 @@ _✨ 简单的狼人杀插件 ✨_
220
258
 
221
259
  <!-- CHANGELOG -->
222
260
 
261
+ - 2025.04.20 v1.1.11
262
+
263
+ - 添加配置项 `werewolf__require_at`, 用于配置命令是否需要 at 机器人触发
264
+ - 添加配置项 `werewolf__matcher_priority`, 用于配置插件 matcher 注册优先级
265
+
266
+ - 2025.04.17 v1.1.10
267
+
268
+ - 添加狼人多选目标配置项显示
269
+ - 在游戏开始时打乱并固定轮流发言模式的发言顺序 (#20)
270
+
223
271
  - 2025.04.15 v1.1.9
224
272
 
225
273
  - 添加游戏行为配置 `werewolf_multi_select`
226
274
  - 重构玩家类
227
- - 添加轮流发言模式缺失的 at 消息段
275
+ - 添加轮流发言模式缺失的 at 消息段 (#19)
228
276
 
229
277
  - 2025.02.13 v1.1.8
230
278
 
@@ -234,7 +282,7 @@ _✨ 简单的狼人杀插件 ✨_
234
282
 
235
283
  - 2024.10.31 v1.1.7
236
284
 
237
- - *Bug fix*
285
+ - _Bug fix_
238
286
 
239
287
  - 2024.10.31 v1.1.6
240
288
 
@@ -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.9"
13
+ __version__ = "1.1.11"
14
14
  __plugin_meta__ = PluginMetadata(
15
15
  name="狼人杀",
16
16
  description="适用于 Nonebot2 的狼人杀插件",
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from pathlib import Path
3
- from typing import Any, ClassVar, Final
3
+ from typing import Any, ClassVar, Final, Literal
4
4
  from typing_extensions import Self
5
5
 
6
6
  import nonebot
@@ -83,10 +83,26 @@ class GameBehavior(ConfigFile):
83
83
  timeout: Final[_Timeout] = _Timeout()
84
84
 
85
85
 
86
+ class RequireAtConfig(BaseModel):
87
+ start: bool = True
88
+ terminate: bool = True
89
+
90
+
91
+ class MatcherPriorityConfig(BaseModel):
92
+ start: int = 1
93
+ terminate: int = 1
94
+ preset: int = 1
95
+ behavior: int = 1
96
+ in_game: int = 10
97
+ stop: int = 10
98
+
99
+
86
100
  class PluginConfig(BaseModel):
87
101
  enable_poke: bool = True
88
102
  enable_button: bool = False
89
103
  stop_command: str | set[str] = "stop"
104
+ require_at: bool | RequireAtConfig = True
105
+ matcher_priority: MatcherPriorityConfig = MatcherPriorityConfig()
90
106
 
91
107
  def get_stop_command(self) -> list[str]:
92
108
  return (
@@ -95,6 +111,11 @@ class PluginConfig(BaseModel):
95
111
  else sorted(self.stop_command, key=len)
96
112
  )
97
113
 
114
+ def get_require_at(self, cmd: Literal["start", "terminate"]) -> bool:
115
+ if isinstance(self.require_at, bool):
116
+ return self.require_at
117
+ return getattr(self.require_at, cmd)
118
+
98
119
 
99
120
  class Config(BaseModel):
100
121
  werewolf: PluginConfig = PluginConfig()
@@ -1,20 +1,18 @@
1
1
  import functools
2
2
  from typing import TYPE_CHECKING
3
3
 
4
- import nonebot
5
-
6
4
  from .models import GameStatus, KillReason, Role, RoleGroup
7
5
 
8
6
  STOP_COMMAND = "{{stop}}"
9
- COMMAND_START = next(
10
- iter(sorted(nonebot.get_driver().config.command_start, key=len)), ""
11
- )
12
7
 
13
8
 
14
9
  def stop_command_prompt() -> str:
10
+ import nonebot
11
+
15
12
  from .config import config # circular import
16
13
 
17
- return COMMAND_START + config.get_stop_command()[0]
14
+ cmd_starts = sorted(nonebot.get_driver().config.command_start, key=len)
15
+ return next(iter(cmd_starts), "") + config.get_stop_command()[0]
18
16
 
19
17
 
20
18
  if not TYPE_CHECKING:
@@ -1,7 +1,7 @@
1
1
  import contextlib
2
2
  import functools
3
3
  import secrets
4
- from collections import defaultdict
4
+ from collections import Counter
5
5
  from typing import NoReturn, final
6
6
  from typing_extensions import Self
7
7
 
@@ -10,8 +10,8 @@ import nonebot
10
10
  from nonebot.adapters import Bot
11
11
  from nonebot.utils import escape_tag
12
12
  from nonebot_plugin_alconna import At, Target, UniMessage
13
- from nonebot_plugin_alconna.uniseg.message import Receipt
14
- from nonebot_plugin_uninfo import Interface, SceneType
13
+ from nonebot_plugin_alconna.uniseg.receipt import Receipt
14
+ from nonebot_plugin_uninfo import Interface, Scene, SceneType
15
15
 
16
16
  from .config import GameBehavior, PresetData
17
17
  from .constant import GAME_STATUS_CONV, REPORT_TEXT, ROLE_EMOJI, ROLE_NAME_CONV
@@ -162,11 +162,10 @@ class Game:
162
162
  self.state = GameState(0)
163
163
  self.killed_players = []
164
164
  self._player_map: dict[str, Player] = {}
165
- self._scene = None
166
- self._finished = None
167
- self._task_group = None
168
- self._send_handler = _SendHandler()
169
- self._send_handler.update(group, bot)
165
+ self._shuffled: list[Player] = []
166
+ self._scene: Scene | None = None
167
+ self._finished = self._task_group = None
168
+ self._send_handler = _SendHandler(group, bot)
170
169
 
171
170
  @final
172
171
  @classmethod
@@ -185,6 +184,7 @@ class Game:
185
184
 
186
185
  self.players = await init_players(bot, self, players, interface)
187
186
  self._player_map |= {p.user_id: p for p in self.players}
187
+ self._shuffled = self.players.shuffled
188
188
 
189
189
  return self
190
190
 
@@ -258,12 +258,9 @@ class Game:
258
258
  )
259
259
 
260
260
  if self.behavior.show_roles_list_on_start:
261
- role_cnt: dict[Role, int] = defaultdict(lambda: 0)
262
- for role in sorted((p.role for p in self.players), key=lambda r: r.value):
263
- role_cnt[role] += 1
264
-
265
261
  msg.text("\n\n📚职业列表:\n")
266
- for role, cnt in role_cnt.items():
262
+ counter = Counter(p.role for p in self.players)
263
+ for role, cnt in sorted(counter.items(), key=lambda x: x[0].value):
267
264
  msg.text(f"- {ROLE_EMOJI[role]}{ROLE_NAME_CONV[role]}x{cnt}\n")
268
265
 
269
266
  async with anyio.create_task_group() as tg:
@@ -340,23 +337,24 @@ class Game:
340
337
  timeout = self.behavior.timeout
341
338
 
342
339
  if not self.behavior.speak_in_turn:
343
- speak_timeout = timeout.group_speak
344
340
  await self.send(
345
341
  f"💬接下来开始自由讨论\n{timeout.group_speak_timeout_prompt}",
346
342
  stop_btn_label="结束发言",
347
343
  )
348
- await self.wait_stop(*self.players.alive(), timeout_secs=speak_timeout)
344
+ await self.wait_stop(
345
+ *self.players.alive(),
346
+ timeout_secs=timeout.group_speak,
347
+ )
349
348
  else:
350
349
  await self.send("💬接下来开始轮流发言")
351
- speak_timeout = timeout.speak
352
- for player in self.players.alive().sorted:
350
+ for player in filter(lambda p: p.alive, self._shuffled):
353
351
  await self.send(
354
352
  UniMessage.text("💬")
355
353
  .at(player.user_id)
356
354
  .text(f"\n轮到你发言\n{timeout.speak_timeout_prompt}"),
357
355
  stop_btn_label="结束发言",
358
356
  )
359
- await self.wait_stop(player, timeout_secs=speak_timeout)
357
+ await self.wait_stop(player, timeout_secs=timeout.speak)
360
358
  await self.send("💬所有玩家发言结束")
361
359
 
362
360
  async def run_vote(self) -> None: