nonebot-plugin-werewolf 1.1.2__py3-none-any.whl → 1.1.3__py3-none-any.whl

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 (30) hide show
  1. nonebot_plugin_werewolf/__init__.py +8 -4
  2. nonebot_plugin_werewolf/config.py +11 -15
  3. nonebot_plugin_werewolf/constant.py +17 -2
  4. nonebot_plugin_werewolf/game.py +77 -98
  5. nonebot_plugin_werewolf/matchers/__init__.py +2 -0
  6. nonebot_plugin_werewolf/matchers/message_in_game.py +15 -0
  7. nonebot_plugin_werewolf/{ob11_ext.py → matchers/ob11_ext.py} +26 -20
  8. nonebot_plugin_werewolf/matchers/start_game.py +56 -0
  9. nonebot_plugin_werewolf/player_set.py +6 -4
  10. nonebot_plugin_werewolf/players/__init__.py +10 -0
  11. nonebot_plugin_werewolf/players/can_shoot.py +59 -0
  12. nonebot_plugin_werewolf/players/civilian.py +7 -0
  13. nonebot_plugin_werewolf/players/guard.py +37 -0
  14. nonebot_plugin_werewolf/players/hunter.py +8 -0
  15. nonebot_plugin_werewolf/players/idiot.py +44 -0
  16. nonebot_plugin_werewolf/players/joker.py +21 -0
  17. nonebot_plugin_werewolf/players/player.py +161 -0
  18. nonebot_plugin_werewolf/players/prophet.py +30 -0
  19. nonebot_plugin_werewolf/players/werewolf.py +67 -0
  20. nonebot_plugin_werewolf/players/witch.py +72 -0
  21. nonebot_plugin_werewolf/players/wolfking.py +14 -0
  22. nonebot_plugin_werewolf/utils.py +83 -64
  23. {nonebot_plugin_werewolf-1.1.2.dist-info → nonebot_plugin_werewolf-1.1.3.dist-info}/METADATA +11 -3
  24. nonebot_plugin_werewolf-1.1.3.dist-info/RECORD +29 -0
  25. nonebot_plugin_werewolf/matchers.py +0 -62
  26. nonebot_plugin_werewolf/player.py +0 -462
  27. nonebot_plugin_werewolf-1.1.2.dist-info/RECORD +0 -16
  28. {nonebot_plugin_werewolf-1.1.2.dist-info → nonebot_plugin_werewolf-1.1.3.dist-info}/LICENSE +0 -0
  29. {nonebot_plugin_werewolf-1.1.2.dist-info → nonebot_plugin_werewolf-1.1.3.dist-info}/WHEEL +0 -0
  30. {nonebot_plugin_werewolf-1.1.2.dist-info → nonebot_plugin_werewolf-1.1.3.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,16 @@
1
1
  import asyncio
2
+ import itertools
2
3
  import re
3
4
  from collections import defaultdict
4
- from typing import Annotated, Any, ClassVar
5
+ from typing import Any, ClassVar
5
6
 
7
+ import nonebot
6
8
  import nonebot_plugin_waiter as waiter
7
- from nonebot.adapters import Event
8
- from nonebot.log import logger
9
+ from nonebot.adapters import Bot, Event
9
10
  from nonebot.rule import to_me
10
- from nonebot_plugin_alconna import MsgTarget, UniMessage, UniMsg
11
- from nonebot_plugin_userinfo import EventUserInfo, UserInfo
11
+ from nonebot.utils import escape_tag
12
+ from nonebot_plugin_alconna import MsgTarget, Target, UniMessage, UniMsg
13
+ from nonebot_plugin_uninfo import Uninfo
12
14
 
13
15
  from .config import config
14
16
 
@@ -24,49 +26,66 @@ def check_index(text: str, arrlen: int) -> int | None:
24
26
  class InputStore:
25
27
  locks: ClassVar[dict[str, asyncio.Lock]] = defaultdict(asyncio.Lock)
26
28
  futures: ClassVar[dict[str, asyncio.Future[UniMessage]]] = {}
29
+ clear_handle: ClassVar[dict[str, asyncio.Handle]] = {}
30
+
31
+ @classmethod
32
+ def clear_lock(cls, key: str) -> None:
33
+ if key in cls.locks and not cls.locks[key].locked():
34
+ del cls.locks[key]
35
+ if key in cls.clear_handle:
36
+ del cls.clear_handle[key]
27
37
 
28
38
  @classmethod
29
39
  async def fetch(cls, user_id: str, group_id: str | None = None) -> UniMessage[Any]:
30
40
  key = f"{group_id}_{user_id}"
31
41
  async with cls.locks[key]:
32
- cls.futures[key] = asyncio.get_event_loop().create_future()
42
+ cls.futures[key] = fut = asyncio.get_event_loop().create_future()
33
43
  try:
34
- return await cls.futures[key]
44
+ return await fut
35
45
  finally:
36
46
  del cls.futures[key]
47
+ if key in cls.clear_handle:
48
+ cls.clear_handle[key].cancel()
49
+ loop = asyncio.get_event_loop()
50
+ cls.clear_handle[key] = loop.call_later(120, cls.clear_lock, key)
37
51
 
38
52
  @classmethod
39
- def put(cls, user_id: str, group_id: str | None, msg: UniMessage) -> None:
53
+ def put(cls, msg: UniMessage, user_id: str, group_id: str | None = None) -> None:
40
54
  key = f"{group_id}_{user_id}"
41
- if future := cls.futures.get(key):
55
+ if (future := cls.futures.get(key)) and not future.cancelled():
42
56
  future.set_result(msg)
43
57
 
44
58
 
45
- def user_in_game(user_id: str, group_id: str | None) -> bool:
46
- from .game import running_games
59
+ def user_in_game(self_id: str, user_id: str, group_id: str | None) -> bool:
60
+ from .game import Game
47
61
 
48
- if group_id is not None and group_id not in running_games:
49
- return False
50
- games = running_games.values() if group_id is None else [running_games[group_id]]
51
- for game in games:
62
+ if group_id is None:
63
+ return any(
64
+ self_id == p.user.self_id and user_id == p.user_id
65
+ for p in itertools.chain(*[g.players for g in Game.running_games])
66
+ )
67
+
68
+ def check(game: Game) -> bool:
69
+ return self_id == game.group.self_id and group_id == game.group.id
70
+
71
+ if game := next(filter(check, Game.running_games), None):
52
72
  return any(user_id == player.user_id for player in game.players)
73
+
53
74
  return False
54
75
 
55
76
 
56
- async def rule_in_game(event: Event, target: MsgTarget) -> bool:
57
- from .game import running_games
77
+ async def rule_in_game(bot: Bot, event: Event, target: MsgTarget) -> bool:
78
+ from .game import Game
58
79
 
59
- if not running_games:
80
+ if not Game.running_games:
60
81
  return False
61
82
  if target.private:
62
- return user_in_game(target.id, None)
63
- if target.id in running_games:
64
- return user_in_game(event.get_user_id(), target.id)
65
- return False
83
+ return user_in_game(bot.self_id, target.id, None)
84
+ return user_in_game(bot.self_id, event.get_user_id(), target.id)
66
85
 
67
86
 
68
- async def rule_not_in_game(event: Event, target: MsgTarget) -> bool:
69
- return not await rule_in_game(event, target)
87
+ async def rule_not_in_game(bot: Bot, event: Event, target: MsgTarget) -> bool:
88
+ return not await rule_in_game(bot, event, target)
70
89
 
71
90
 
72
91
  async def is_group(target: MsgTarget) -> bool:
@@ -76,35 +95,35 @@ async def is_group(target: MsgTarget) -> bool:
76
95
  async def _prepare_game_receive(
77
96
  queue: asyncio.Queue[tuple[str, str, str]],
78
97
  event: Event,
79
- group_id: str,
98
+ group: Target,
80
99
  ) -> None:
81
- async def rule(target_: MsgTarget) -> bool:
82
- return not target_.private and target_.id == group_id
100
+ async def same_group(target: MsgTarget) -> bool:
101
+ return group.verify(target)
83
102
 
84
103
  @waiter.waiter(
85
104
  waits=[event.get_type()],
86
105
  keep_session=False,
87
- rule=to_me() & rule & rule_not_in_game,
106
+ rule=to_me() & same_group & rule_not_in_game,
88
107
  )
89
108
  def wait(
90
109
  event: Event,
91
- info: Annotated[UserInfo | None, EventUserInfo()],
92
110
  msg: UniMsg,
111
+ session: Uninfo,
93
112
  ) -> tuple[str, str, str]:
113
+ user_id = event.get_user_id()
114
+ name = session.user.nick or session.user.name or user_id
115
+ if session.member:
116
+ name = session.member.nick or name
94
117
  return (
95
- event.get_user_id(),
96
- (
97
- (info.user_displayname or info.user_name)
98
- if info is not None
99
- else event.get_user_id()
100
- ),
118
+ user_id,
101
119
  msg.extract_plain_text().strip(),
120
+ name,
102
121
  )
103
122
 
104
- async for user, name, text in wait(default=(None, "", "")):
123
+ async for user, text, name in wait(default=(None, "", "")):
105
124
  if user is None:
106
125
  continue
107
- await queue.put((user, re.sub(r"[\u2066-\u2069]", "", name), text))
126
+ await queue.put((user, text, re.sub(r"[\u2066-\u2069]", "", name)))
108
127
 
109
128
 
110
129
  async def _prepare_game_handle(
@@ -112,12 +131,12 @@ async def _prepare_game_handle(
112
131
  players: dict[str, str],
113
132
  admin_id: str,
114
133
  ) -> None:
115
- log = logger.opt(colors=True)
134
+ logger = nonebot.logger.opt(colors=True)
116
135
 
117
136
  while True:
118
- user, name, text = await queue.get()
119
- msg = UniMessage.at(user)
120
- colored = f"<y>{name}</y>(<c>{user}</c>)"
137
+ user, text, name = await queue.get()
138
+ msg = UniMessage.at(user).text("\n")
139
+ colored = f"<y>{escape_tag(name)}</y>(<c>{escape_tag(user)}</c>)"
121
140
 
122
141
  match (text, user == admin_id):
123
142
  case ("开始游戏", True):
@@ -125,77 +144,77 @@ async def _prepare_game_handle(
125
144
  role_preset = config.get_role_preset()
126
145
  if player_num < min(role_preset):
127
146
  await (
128
- msg.text(f"游戏至少需要 {min(role_preset)} 人, ")
147
+ msg.text(f"⚠️游戏至少需要 {min(role_preset)} 人, ")
129
148
  .text(f"当前已有 {player_num} 人")
130
149
  .send()
131
150
  )
132
151
  elif player_num > max(role_preset):
133
152
  await (
134
- msg.text(f"游戏最多需要 {max(role_preset)} 人, ")
153
+ msg.text(f"⚠️游戏最多需要 {max(role_preset)} 人, ")
135
154
  .text(f"当前已有 {player_num} 人")
136
155
  .send()
137
156
  )
138
157
  elif player_num not in role_preset:
139
158
  await (
140
- msg.text(f"不存在总人数为 {player_num} 的预设, ")
159
+ msg.text(f"⚠️不存在总人数为 {player_num} 的预设, ")
141
160
  .text("无法开始游戏")
142
161
  .send()
143
162
  )
144
163
  else:
145
- await msg.text("游戏即将开始...").send()
146
- log.info(f"游戏发起者 {colored} 开始游戏")
164
+ await msg.text("✏️游戏即将开始...").send()
165
+ logger.info(f"游戏发起者 {colored} 开始游戏")
147
166
  return
148
167
 
149
168
  case ("开始游戏", False):
150
- await msg.text("只有游戏发起者可以开始游戏").send()
169
+ await msg.text("⚠️只有游戏发起者可以开始游戏").send()
151
170
 
152
171
  case ("结束游戏", True):
153
- log.info(f"游戏发起者 {colored} 结束游戏")
154
- await msg.text("已结束当前游戏").finish()
172
+ logger.info(f"游戏发起者 {colored} 结束游戏")
173
+ await msg.text("ℹ️已结束当前游戏").finish()
155
174
 
156
175
  case ("结束游戏", False):
157
- await msg.text("只有游戏发起者可以结束游戏").send()
176
+ await msg.text("⚠️只有游戏发起者可以结束游戏").send()
158
177
 
159
178
  case ("加入游戏", True):
160
- await msg.text("游戏发起者已经加入游戏了").send()
179
+ await msg.text("ℹ️游戏发起者已经加入游戏了").send()
161
180
 
162
181
  case ("加入游戏", False):
163
182
  if user not in players:
164
183
  players[user] = name
165
- log.info(f"玩家 {colored} 加入游戏")
166
- await msg.text("成功加入游戏").send()
184
+ logger.info(f"玩家 {colored} 加入游戏")
185
+ await msg.text("✅成功加入游戏").send()
167
186
  else:
168
- await msg.text("你已经加入游戏了").send()
187
+ await msg.text("ℹ️你已经加入游戏了").send()
169
188
 
170
189
  case ("退出游戏", True):
171
- await msg.text("游戏发起者无法退出游戏").send()
190
+ await msg.text("ℹ️游戏发起者无法退出游戏").send()
172
191
 
173
192
  case ("退出游戏", False):
174
193
  if user in players:
175
194
  del players[user]
176
- log.info(f"玩家 {colored} 退出游戏")
177
- await msg.text("成功退出游戏").send()
195
+ logger.info(f"玩家 {colored} 退出游戏")
196
+ await msg.text("✅成功退出游戏").send()
178
197
  else:
179
- await msg.text("你还没有加入游戏").send()
198
+ await msg.text("ℹ️你还没有加入游戏").send()
180
199
 
181
200
  case ("当前玩家", _):
182
- msg.text("\n当前玩家:\n")
201
+ msg.text("✨当前玩家:\n")
183
202
  for idx, name in enumerate(players.values(), 1):
184
203
  msg.text(f"\n{idx}. {name}")
185
204
  await msg.send()
186
205
 
187
206
 
188
207
  async def prepare_game(event: Event, players: dict[str, str]) -> None:
189
- from .game import starting_games
208
+ from .game import Game
190
209
 
191
- group_id = UniMessage.get_target(event).id
192
- starting_games[group_id] = players
210
+ group = UniMessage.get_target(event)
211
+ Game.starting_games[group] = players
193
212
 
194
213
  queue: asyncio.Queue[tuple[str, str, str]] = asyncio.Queue()
195
- task_receive = asyncio.create_task(_prepare_game_receive(queue, event, group_id))
214
+ task_receive = asyncio.create_task(_prepare_game_receive(queue, event, group))
196
215
 
197
216
  try:
198
217
  await _prepare_game_handle(queue, players, event.get_user_id())
199
218
  finally:
200
219
  task_receive.cancel()
201
- del starting_games[group_id]
220
+ del Game.starting_games[group]
@@ -1,15 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-werewolf
3
- Version: 1.1.2
3
+ Version: 1.1.3
4
4
  Summary: 适用于 Nonebot2 的狼人杀插件
5
5
  Author-email: wyf7685 <wyf7685@163.com>
6
6
  License: MIT
7
+ Project-URL: homepage, https://github.com/wyf7685/nonebot-plugin-werewolf
8
+ Project-URL: repository, https://github.com/wyf7685/nonebot-plugin-werewolf
9
+ Project-URL: bug-tracker, https://github.com/wyf7685/nonebot-plugin-werewolf/issues
7
10
  Requires-Python: >=3.10
8
11
  Description-Content-Type: text/markdown
9
12
  License-File: LICENSE
10
13
  Requires-Dist: nonebot2 >=2.3.3
11
14
  Requires-Dist: nonebot-plugin-alconna >=0.52.1
12
- Requires-Dist: nonebot-plugin-userinfo >=0.2.6
15
+ Requires-Dist: nonebot-plugin-uninfo >=0.4.0
13
16
  Requires-Dist: nonebot-plugin-waiter >=0.7.1
14
17
 
15
18
  <div align="center">
@@ -240,6 +243,11 @@ werewolf__priesthood_proirity=[11, 12, 13, 14, 15]
240
243
 
241
244
  <!-- CHANGELOG -->
242
245
 
246
+ - 2024.10.06 v1.1.3
247
+
248
+ - 使用 `RF-Tar-Railt/nonebot-plugin-uninfo` 获取用户数据
249
+ - 优化交互文本
250
+
243
251
  - 2024.09.18 v1.1.2
244
252
 
245
253
  - 修改 Python 需求为 `>=3.10`
@@ -284,6 +292,6 @@ werewolf__priesthood_proirity=[11, 12, 13, 14, 15]
284
292
 
285
293
  - [`nonebot/nonebot2`](https://github.com/nonebot/nonebot2): 跨平台 Python 异步机器人框架
286
294
  - [`nonebot/plugin-alconna`](https://github.com/nonebot/plugin-alconna): 跨平台的消息处理接口
287
- - [`noneplugin/nonebot-plugin-userinfo`](https://github.com/noneplugin/nonebot-plugin-userinfo): 用户信息获取
295
+ - [`RF-Tar-Railt/nonebot-plugin-uninfo`](https://github.com/RF-Tar-Railt/nonebot-plugin-uninfo): 用户信息获取
288
296
  - [`RF-Tar-Railt/nonebot-plugin-waiter`](https://github.com/RF-Tar-Railt/nonebot-plugin-waiter): 灵活获取用户输入
289
297
  - `热心群友`: 协助测试插件
@@ -0,0 +1,29 @@
1
+ nonebot_plugin_werewolf/__init__.py,sha256=Im_u8hP6N6qA2SwnNSGu1MsewLoyHUa3v0Paj1yC3T0,862
2
+ nonebot_plugin_werewolf/_timeout.py,sha256=MVkA5oMoxOTV8Luc0BH2QPP8wwz4Tr9CJjeYgiPu_O4,3649
3
+ nonebot_plugin_werewolf/config.py,sha256=FKQDkb57ujcBYJZX-sLgxWmTVqSeR7T1ywphp7GOCcE,2803
4
+ nonebot_plugin_werewolf/constant.py,sha256=-S-KjlrSc_wJwsXCkQOMFVqyu4RwR4GLXIRZEp_0mlI,2300
5
+ nonebot_plugin_werewolf/exception.py,sha256=YSwxeogIB0YJqH9MP1bgxojiu-I_xQE44XnSk5bC1AQ,400
6
+ nonebot_plugin_werewolf/game.py,sha256=LWxn2OCnkTAF8NdLt1BQzyAtyUfk477xisCf5mbfK_E,17376
7
+ nonebot_plugin_werewolf/player_set.py,sha256=BlK7wHv_9YrCINMAPWL36TLkRjAiI_GXSHlZySVemoo,2777
8
+ nonebot_plugin_werewolf/utils.py,sha256=50bJGhJU7b9kQEqmc2V8-5wYkukilDtchZBSBKcwwq4,7633
9
+ nonebot_plugin_werewolf/matchers/__init__.py,sha256=_MwAZsXlpBLXyzHWqNLTQdMWw9z_O01L5Yo02dzGC9I,88
10
+ nonebot_plugin_werewolf/matchers/message_in_game.py,sha256=hpQCaNaxCikma8DJTJLCttP5B1vBWlqMDEukSqfPlRk,452
11
+ nonebot_plugin_werewolf/matchers/ob11_ext.py,sha256=TGhI4yWfb5N3K9hXkI8k8Rs6cMVXDwp05cXtu3a-_jU,2597
12
+ nonebot_plugin_werewolf/matchers/start_game.py,sha256=DZPQ88hiobuJejIbKsIc8ZcoKDw7wcjawWfTC3wjIto,1884
13
+ nonebot_plugin_werewolf/players/__init__.py,sha256=djAI5XxR2I-XvnH-lVqX_YCHB_AiT-6jdmwFE1ffN_0,379
14
+ nonebot_plugin_werewolf/players/can_shoot.py,sha256=6u_luXfNOWO0svTpb78h74HcG65kh1GZyFPJFYNuOG0,2068
15
+ nonebot_plugin_werewolf/players/civilian.py,sha256=6iKEWRRWDGq1qgVZZZ9pX7kBVpMN-yfxeLq9hIp17hU,165
16
+ nonebot_plugin_werewolf/players/guard.py,sha256=pDH66q-KoU5oRD-tn542x3siXv9BM824-KRxsVb0Gvk,1408
17
+ nonebot_plugin_werewolf/players/hunter.py,sha256=nqYGCVppd4mdCPhFHZbjbbNvZfyCNT0bZ3raQFXmELA,203
18
+ nonebot_plugin_werewolf/players/idiot.py,sha256=7-BTsYUSOcs5rPOJx1hsHPOWcmGcv2rSO8IfUGPdqEE,1456
19
+ nonebot_plugin_werewolf/players/joker.py,sha256=uUK6EuoOWd8_35yvBTkM14XCplOFwFCRsbhR7bjeiD8,699
20
+ nonebot_plugin_werewolf/players/player.py,sha256=ejEjbsrIKpUJql3-qLMFsZY_jGFtQ3OTjcN1lFZ4yKo,4697
21
+ nonebot_plugin_werewolf/players/prophet.py,sha256=nh8eB9T9LMBiqNgnqE-ygAFiYvTZS8bGUKYsNBPm8F0,1078
22
+ nonebot_plugin_werewolf/players/werewolf.py,sha256=kyZjwijEGG0EkP80VOlu8HFzReg33v8a-o670fZN_xI,2560
23
+ nonebot_plugin_werewolf/players/witch.py,sha256=P1odgjFc9kAIUxmlz9aV69aYzl76OVcsQQGhigmRTgc,2571
24
+ nonebot_plugin_werewolf/players/wolfking.py,sha256=hgxOugrIOF6wC5wKcjflPuQ2K4d99eWpF9E69ishbsg,440
25
+ nonebot_plugin_werewolf-1.1.3.dist-info/LICENSE,sha256=B_WbEqjGr6GYVNfEJPY31T1Opik7OtgOkhRs4Ig3e2M,1064
26
+ nonebot_plugin_werewolf-1.1.3.dist-info/METADATA,sha256=uLZxheMxeLRL70cOrpZtr1Nqy2gP1sAIFNiiNtkEwi4,10707
27
+ nonebot_plugin_werewolf-1.1.3.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
28
+ nonebot_plugin_werewolf-1.1.3.dist-info/top_level.txt,sha256=wLTfg8sTKbH9lLT9LtU118C9cTspEBJareLsrYM52YA,24
29
+ nonebot_plugin_werewolf-1.1.3.dist-info/RECORD,,
@@ -1,62 +0,0 @@
1
- from typing import Annotated
2
-
3
- from nonebot import on_command, on_message
4
- from nonebot.adapters import Bot, Event
5
- from nonebot.exception import FinishedException
6
- from nonebot.rule import to_me
7
- from nonebot_plugin_alconna import MsgTarget, UniMessage, UniMsg
8
- from nonebot_plugin_userinfo import EventUserInfo, UserInfo
9
-
10
- from ._timeout import timeout
11
- from .game import Game
12
- from .ob11_ext import ob11_ext_enabled
13
- from .utils import InputStore, is_group, prepare_game, rule_in_game, rule_not_in_game
14
-
15
- in_game_message = on_message(rule=rule_in_game)
16
- start_game = on_command(
17
- "werewolf",
18
- rule=to_me() & is_group & rule_not_in_game,
19
- aliases={"狼人杀"},
20
- )
21
-
22
-
23
- @in_game_message.handle()
24
- async def handle_input(event: Event, target: MsgTarget, msg: UniMsg) -> None:
25
- if target.private:
26
- InputStore.put(target.id, None, msg)
27
- else:
28
- InputStore.put(event.get_user_id(), target.id, msg)
29
-
30
-
31
- @start_game.handle()
32
- async def handle_start(
33
- bot: Bot,
34
- event: Event,
35
- target: MsgTarget,
36
- admin_info: Annotated[UserInfo, EventUserInfo()],
37
- ) -> None:
38
- admin_id = event.get_user_id()
39
- msg = (
40
- UniMessage.at(admin_id)
41
- .text("成功创建游戏\n")
42
- .text("玩家请 @我 发送 “加入游戏”、“退出游戏”\n")
43
- .text("玩家 @我 发送 “当前玩家” 可查看玩家列表\n")
44
- .text("游戏发起者 @我 发送 “结束游戏” 可结束当前游戏\n")
45
- .text("玩家均加入后,游戏发起者请 @我 发送 “开始游戏”\n")
46
- )
47
- if ob11_ext_enabled():
48
- msg.text("\n可使用戳一戳代替游戏交互中的 “/stop” 命令")
49
- await msg.text("\n\n游戏准备阶段限时5分钟,超时将自动结束").send()
50
-
51
- players = {admin_id: admin_info.user_name}
52
-
53
- try:
54
- async with timeout(5 * 60):
55
- await prepare_game(event, players)
56
- except FinishedException:
57
- raise
58
- except TimeoutError:
59
- await UniMessage.text("游戏准备超时,已自动结束").finish()
60
-
61
- game = Game(bot, target, players)
62
- game.start()