nonebot-plugin-werewolf 1.1.10__py3-none-any.whl → 1.1.12__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 +1 -1
  2. nonebot_plugin_werewolf/config.py +57 -35
  3. nonebot_plugin_werewolf/constant.py +0 -19
  4. nonebot_plugin_werewolf/dead_channel.py +79 -0
  5. nonebot_plugin_werewolf/game.py +48 -117
  6. nonebot_plugin_werewolf/matchers/_prepare_game.py +223 -0
  7. nonebot_plugin_werewolf/matchers/depends.py +4 -4
  8. nonebot_plugin_werewolf/matchers/edit_behavior.py +2 -2
  9. nonebot_plugin_werewolf/matchers/edit_preset.py +20 -20
  10. nonebot_plugin_werewolf/matchers/message_in_game.py +5 -1
  11. nonebot_plugin_werewolf/matchers/poke/__init__.py +2 -1
  12. nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py +7 -12
  13. nonebot_plugin_werewolf/matchers/poke/ob11_poke.py +8 -11
  14. nonebot_plugin_werewolf/matchers/start_game.py +23 -233
  15. nonebot_plugin_werewolf/matchers/superuser_ops.py +16 -12
  16. nonebot_plugin_werewolf/models.py +19 -0
  17. nonebot_plugin_werewolf/player.py +35 -31
  18. nonebot_plugin_werewolf/player_set.py +10 -0
  19. nonebot_plugin_werewolf/players/guard.py +2 -2
  20. nonebot_plugin_werewolf/players/prophet.py +2 -2
  21. nonebot_plugin_werewolf/players/shooter.py +2 -2
  22. nonebot_plugin_werewolf/players/werewolf.py +18 -19
  23. nonebot_plugin_werewolf/players/witch.py +4 -4
  24. nonebot_plugin_werewolf/utils.py +18 -56
  25. {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/METADATA +122 -58
  26. nonebot_plugin_werewolf-1.1.12.dist-info/RECORD +37 -0
  27. {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/WHEEL +1 -1
  28. nonebot_plugin_werewolf-1.1.10.dist-info/RECORD +0 -35
  29. {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/licenses/LICENSE +0 -0
  30. {nonebot_plugin_werewolf-1.1.10.dist-info → nonebot_plugin_werewolf-1.1.12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,223 @@
1
+ import re
2
+ from collections.abc import AsyncIterator, Awaitable, Callable
3
+ from dataclasses import dataclass
4
+
5
+ import anyio
6
+ import nonebot
7
+ import nonebot_plugin_waiter.unimsg as waiter
8
+ from nonebot.adapters import Event
9
+ from nonebot.internal.matcher import current_bot
10
+ from nonebot.matcher import Matcher
11
+ from nonebot.permission import SuperUser
12
+ from nonebot.rule import Rule
13
+ from nonebot.utils import escape_tag
14
+ from nonebot_plugin_alconna import (
15
+ Button,
16
+ MsgTarget,
17
+ Target,
18
+ UniMessage,
19
+ UniMsg,
20
+ get_target,
21
+ )
22
+ from nonebot_plugin_uninfo import Uninfo
23
+
24
+ from ..config import PresetData
25
+ from ..utils import SendHandler as BaseSendHandler
26
+ from ..utils import btn, extract_session_member_nick
27
+ from .depends import rule_not_in_game
28
+
29
+ preparing_games: dict[Target, "PrepareGame"] = {}
30
+
31
+
32
+ def solve_button(msg: UniMessage) -> UniMessage:
33
+ def _btn(text: str) -> Button:
34
+ return btn(text, text)
35
+
36
+ return (
37
+ msg.keyboard(_btn("当前玩家"))
38
+ .keyboard(_btn("加入游戏"), _btn("退出游戏"))
39
+ .keyboard(_btn("开始游戏"), _btn("结束游戏"))
40
+ )
41
+
42
+
43
+ class SendHandler(BaseSendHandler):
44
+ def __init__(self) -> None:
45
+ self.reply_to = True
46
+
47
+ def solve_msg(self, msg: UniMessage) -> UniMessage:
48
+ return solve_button(msg)
49
+
50
+ async def send_finished(self) -> None:
51
+ msg = (
52
+ UniMessage.text("ℹ️已结束当前游戏")
53
+ .keyboard(btn("发起游戏", "werewolf"))
54
+ .keyboard(btn("重开上次游戏", "werewolf restart"))
55
+ )
56
+ async with anyio.create_task_group() as tg:
57
+ tg.start_soon(self._edit)
58
+ tg.start_soon(self._send, msg)
59
+
60
+
61
+ def create_waiter(
62
+ event: Event, group: Target
63
+ ) -> AsyncIterator[tuple[Event | None, str, str]]:
64
+ async def same_group(target: MsgTarget) -> bool:
65
+ return group.verify(target)
66
+
67
+ @waiter.waiter(
68
+ waits=[event.get_type()],
69
+ keep_session=False,
70
+ rule=Rule(same_group, rule_not_in_game),
71
+ )
72
+ def wait(event: Event, msg: UniMsg, session: Uninfo) -> tuple[Event, str, str]:
73
+ text = msg.extract_plain_text().strip()
74
+ name = (
75
+ re.sub(r"[\u2066-\u2069]", "", (extract_session_member_nick(session) or ""))
76
+ or event.get_user_id()
77
+ )
78
+ return (event, text, name)
79
+
80
+ return wait(default=(None, "", ""))
81
+
82
+
83
+ @dataclass
84
+ class Current:
85
+ id: str
86
+ name: str
87
+ colored: str
88
+ is_admin: bool
89
+ is_super_user: Callable[[], Awaitable[bool]]
90
+
91
+
92
+ class PrepareGame:
93
+ def __init__(self, event: Event, players: dict[str, str]) -> None:
94
+ self.bot = current_bot.get()
95
+ self.event = event
96
+ self.admin_id = event.get_user_id()
97
+ self.group = get_target(event)
98
+ self.stream = anyio.create_memory_object_stream[tuple[Event, str, str]](16)
99
+ self.players = players
100
+ self.send_handler = SendHandler()
101
+ self.logger = nonebot.logger.opt(colors=True)
102
+ self.shoud_start_game = False
103
+ preparing_games[self.group] = self
104
+
105
+ self._handlers: dict[str, Callable[[], Awaitable[None]]] = {
106
+ "开始游戏": self._handle_start,
107
+ "结束游戏": self._handle_end,
108
+ "加入游戏": self._handle_join,
109
+ "退出游戏": self._handle_quit,
110
+ "当前玩家": self._handle_list,
111
+ }
112
+
113
+ async def run(self) -> None:
114
+ try:
115
+ async with anyio.create_task_group() as tg:
116
+ self.task_group = tg
117
+ async for event, text, name in create_waiter(self.event, self.group):
118
+ if event is not None:
119
+ tg.start_soon(self._handle, event, text, name)
120
+ except Exception as err:
121
+ await UniMessage(f"狼人杀准备阶段出现未知错误: {err!r}").finish()
122
+
123
+ del preparing_games[self.group]
124
+ if not self.shoud_start_game:
125
+ await Matcher.finish()
126
+
127
+ async def _handle(self, event: Event, text: str, name: str) -> None:
128
+ user_id = event.get_user_id()
129
+
130
+ # 更新用户名
131
+ # 当用户通过 chronoca:poke 加入游戏时, 插件无法获取用户名, 原字典值为用户ID
132
+ if user_id in self.players and self.players.get(user_id) != name:
133
+ self.logger.debug(f"更新玩家显示名称: {self.current.colored}")
134
+ self.players[user_id] = name
135
+
136
+ if (handler := self._handlers.get(text)) is None:
137
+ return
138
+
139
+ self.current = Current(
140
+ id=user_id,
141
+ name=name,
142
+ colored=f"<y>{escape_tag(name)}</y>(<c>{escape_tag(user_id)}</c>)",
143
+ is_admin=user_id == self.admin_id,
144
+ is_super_user=lambda: SuperUser()(self.bot, event),
145
+ )
146
+ self.send_handler.update(event, self.bot)
147
+ await handler()
148
+
149
+ async def _send(self, msg: str | UniMessage) -> None:
150
+ await self.send_handler.send(msg)
151
+
152
+ async def _send_finished(self) -> None:
153
+ await self.send_handler.send_finished()
154
+
155
+ def _finish(self) -> None:
156
+ self.task_group.cancel_scope.cancel()
157
+
158
+ async def _handle_start(self) -> None:
159
+ if not self.current.is_admin:
160
+ await self._send("⚠️只有游戏发起者可以开始游戏")
161
+ return
162
+
163
+ player_num = len(self.players)
164
+ role_preset = PresetData.get().role_preset
165
+ if player_num < min(role_preset):
166
+ await self._send(
167
+ f"⚠️游戏至少需要 {min(role_preset)} 人, 当前已有 {player_num} 人"
168
+ )
169
+ elif player_num > max(role_preset):
170
+ await self._send(
171
+ f"⚠️游戏最多需要 {max(role_preset)} 人, 当前已有 {player_num} 人"
172
+ )
173
+ elif player_num not in role_preset:
174
+ await self._send(
175
+ f"⚠️不存在总人数为 {player_num} 的预设, 无法开始游戏\n"
176
+ f"可用的预设总人数: {', '.join(map(str, role_preset))}"
177
+ )
178
+ else:
179
+ self.logger.info(f"游戏发起者 {self.current.colored} 开始游戏")
180
+ await self._send("✏️游戏即将开始...")
181
+ self._finish()
182
+ self.shoud_start_game = True
183
+
184
+ async def _handle_end(self) -> None:
185
+ if not (self.current.is_admin or await self.current.is_super_user()):
186
+ await self._send("⚠️只有游戏发起者或超级用户可以结束游戏")
187
+ return
188
+
189
+ prefix = "游戏发起者" if self.current.is_admin else "超级用户"
190
+ self.logger.info(f"{prefix} {self.current.colored} 结束游戏")
191
+ await self._send_finished()
192
+ self._finish()
193
+
194
+ async def _handle_join(self) -> None:
195
+ if self.current.is_admin:
196
+ await self._send("⚠️只有游戏发起者可以开始游戏")
197
+ return
198
+
199
+ if self.current.id not in self.players:
200
+ self.players[self.current.id] = self.current.name
201
+ self.logger.info(f"玩家 {self.current.colored} 加入游戏")
202
+ await self._send("✅成功加入游戏")
203
+ else:
204
+ await self._send("ℹ️你已经加入游戏了")
205
+
206
+ async def _handle_quit(self) -> None:
207
+ if self.current.is_admin:
208
+ await self._send("ℹ️游戏发起者无法退出游戏")
209
+ return
210
+
211
+ if self.current.id in self.players:
212
+ del self.players[self.current.id]
213
+ self.logger.info(f"玩家 {self.current.colored} 退出游戏")
214
+ await self._send("✅成功退出游戏")
215
+ else:
216
+ await self._send("ℹ️你还没有加入游戏")
217
+
218
+ async def _handle_list(self) -> None:
219
+ lines = (
220
+ f"{idx}. {self.players[user_id]}"
221
+ for idx, user_id in enumerate(self.players, 1)
222
+ )
223
+ await self._send("✨当前玩家:\n" + "\n".join(lines))
@@ -1,7 +1,7 @@
1
1
  import itertools
2
2
 
3
3
  from nonebot.adapters import Bot, Event
4
- from nonebot_plugin_alconna import MsgTarget, UniMessage
4
+ from nonebot_plugin_alconna import MsgTarget, get_target
5
5
 
6
6
  from ..game import Game, get_running_games
7
7
 
@@ -10,13 +10,13 @@ def user_in_game(self_id: str, user_id: str, group_id: str | None) -> bool:
10
10
  if group_id is None:
11
11
  return any(
12
12
  self_id == p.bot.self_id and user_id == p.user_id
13
- for p in itertools.chain(*[g.players for g in get_running_games()])
13
+ for p in itertools.chain(*[g.players for g in get_running_games().values()])
14
14
  )
15
15
 
16
16
  def check(game: Game) -> bool:
17
17
  return self_id == game.group.self_id and group_id == game.group.id
18
18
 
19
- if game := next(filter(check, get_running_games()), None):
19
+ if game := next(filter(check, get_running_games().values()), None):
20
20
  return any(user_id == player.user_id for player in game.players)
21
21
 
22
22
  return False
@@ -27,7 +27,7 @@ async def rule_in_game(bot: Bot, event: Event) -> bool:
27
27
  return False
28
28
 
29
29
  try:
30
- target = UniMessage.get_target(event, bot)
30
+ target = get_target(event, bot)
31
31
  except NotImplementedError:
32
32
  return False
33
33
 
@@ -15,7 +15,7 @@ from nonebot_plugin_alconna import (
15
15
  on_alconna,
16
16
  )
17
17
 
18
- from ..config import GameBehavior
18
+ from ..config import GameBehavior, config
19
19
 
20
20
  GAME_BEHAVIOR_CACHE_KEY = "GAME_BEHAVIOR_CACHE_KEY"
21
21
 
@@ -118,7 +118,7 @@ alc = Alconna(
118
118
  edit_behavior = on_alconna(
119
119
  alc,
120
120
  permission=SUPERUSER,
121
- use_cmd_start=True,
121
+ priority=config.matcher_priority.behavior,
122
122
  )
123
123
 
124
124
 
@@ -1,6 +1,6 @@
1
1
  from typing import Any, NoReturn
2
2
 
3
- import nonebot_plugin_waiter as waiter
3
+ import nonebot_plugin_waiter.unimsg as waiter
4
4
  from arclet.alconna import AllParam
5
5
  from nonebot.permission import SUPERUSER
6
6
  from nonebot.typing import T_State
@@ -14,8 +14,7 @@ from nonebot_plugin_alconna import (
14
14
  on_alconna,
15
15
  )
16
16
 
17
- from ..config import PresetData
18
- from ..constant import ROLE_NAME_CONV
17
+ from ..config import PresetData, config
19
18
  from ..models import Role
20
19
 
21
20
  alc = Alconna(
@@ -48,8 +47,8 @@ alc = Alconna(
48
47
  help_text="设置神职优先级",
49
48
  ),
50
49
  Subcommand(
51
- "joker",
52
- Args["probability?#概率", float],
50
+ "jester",
51
+ Args["probability?#概率(百分比)", float],
53
52
  alias={"小丑"},
54
53
  help_text="设置小丑概率",
55
54
  ),
@@ -73,7 +72,7 @@ alc = Alconna(
73
72
  edit_preset = on_alconna(
74
73
  alc,
75
74
  permission=SUPERUSER,
76
- use_cmd_start=True,
75
+ priority=config.matcher_priority.preset,
77
76
  )
78
77
 
79
78
 
@@ -82,8 +81,7 @@ async def finish(text: str) -> NoReturn:
82
81
 
83
82
 
84
83
  def display_roles(roles: list[Role]) -> str:
85
- role_name = ROLE_NAME_CONV.__getitem__
86
- return ", ".join(map(role_name, roles))
84
+ return ", ".join(role.display for role in roles)
87
85
 
88
86
 
89
87
  @edit_preset.assign("role")
@@ -165,7 +163,7 @@ async def assign_werewolf(state: T_State) -> None:
165
163
 
166
164
  data.werewolf_priority = result
167
165
  data.save()
168
- await finish("设置成功: " + display_roles(result))
166
+ await finish(f"设置成功: {display_roles(result)}")
169
167
 
170
168
 
171
169
  @edit_preset.assign("priesthood")
@@ -214,11 +212,11 @@ async def assign_priesthood(state: T_State) -> None:
214
212
 
215
213
  data.priesthood_proirity = result
216
214
  data.save()
217
- await finish("设置成功: " + display_roles(result))
215
+ await finish(f"设置成功: {display_roles(result)}")
218
216
 
219
217
 
220
- @edit_preset.assign("joker")
221
- async def assign_joker(probability: Match[float]) -> None:
218
+ @edit_preset.assign("jester")
219
+ async def assign_jester(probability: Match[float]) -> None:
222
220
  if not probability.available:
223
221
  result = await waiter.prompt_until(
224
222
  message="请发送小丑概率,范围 0-100\n发送 “取消” 取消操作",
@@ -249,15 +247,17 @@ async def reset_preset() -> None:
249
247
 
250
248
  @edit_preset.handle()
251
249
  async def handle_default() -> None:
252
- lines = ["当前游戏预设:", ""]
253
250
  data = PresetData.load()
254
251
 
255
- for total, (w, p, c) in data.role_preset.items():
256
- lines.append(f"{total} 人: 狼人x{w}, 神职x{p}, 平民x{c}")
257
- lines.append("")
258
-
259
- lines.append("狼人优先级: " + display_roles(data.werewolf_priority))
260
- lines.append("神职优先级: " + display_roles(data.priesthood_proirity))
261
- lines.append(f"小丑概率: {data.jester_probability:.0%}")
252
+ lines = ["当前游戏预设:\n"]
253
+ lines.extend(
254
+ f"{total} 人: 狼人x{w}, 神职x{p}, 平民x{c}"
255
+ for total, (w, p, c) in data.role_preset.items()
256
+ )
257
+ lines.append(
258
+ f"\n狼人优先级: {display_roles(data.werewolf_priority)}"
259
+ f"\n神职优先级: {display_roles(data.priesthood_proirity)}"
260
+ f"\n小丑概率: {data.jester_probability:.0%}"
261
+ )
262
262
 
263
263
  await finish("\n".join(lines))
@@ -7,7 +7,10 @@ from ..constant import STOP_COMMAND
7
7
  from ..utils import InputStore
8
8
  from .depends import rule_in_game
9
9
 
10
- message_in_game = on_message(rule=rule_in_game, priority=10)
10
+ message_in_game = on_message(
11
+ rule=rule_in_game,
12
+ priority=config.matcher_priority.in_game,
13
+ )
11
14
 
12
15
 
13
16
  @message_in_game.handle()
@@ -24,6 +27,7 @@ stopcmd = on_alconna(
24
27
  block=True,
25
28
  use_cmd_start=True,
26
29
  aliases=set(aliases) if (aliases := config.get_stop_command()[1:]) else None,
30
+ priority=config.matcher_priority.stop,
27
31
  )
28
32
 
29
33
 
@@ -1,3 +1,4 @@
1
+ from ...config import config
1
2
  from .chronocat_poke import chronocat_poke_enabled
2
3
  from .ob11_poke import ob11_poke_enabled
3
4
 
@@ -5,4 +6,4 @@ checks = [chronocat_poke_enabled, ob11_poke_enabled]
5
6
 
6
7
 
7
8
  def poke_enabled() -> bool:
8
- return any(check() for check in checks)
9
+ return config.enable_poke and any(check() for check in checks)
@@ -6,8 +6,8 @@ from nonebot_plugin_alconna import MsgTarget, UniMessage
6
6
 
7
7
  from ...config import config
8
8
  from ...constant import STOP_COMMAND
9
- from ...game import get_starting_games
10
9
  from ...utils import InputStore
10
+ from .._prepare_game import preparing_games
11
11
  from ..depends import user_in_game
12
12
 
13
13
 
@@ -15,7 +15,10 @@ def chronocat_poke_enabled() -> bool:
15
15
  return False
16
16
 
17
17
 
18
- with contextlib.suppress(ImportError):
18
+ with contextlib.suppress(ImportError, RuntimeError):
19
+ if not config.enable_poke:
20
+ raise RuntimeError # skip matcher definition
21
+
19
22
  from nonebot.adapters.satori import Bot
20
23
  from nonebot.adapters.satori.event import (
21
24
  MessageCreatedEvent,
@@ -46,8 +49,6 @@ with contextlib.suppress(ImportError):
46
49
 
47
50
  # 游戏内戳一戳等效 "stop" 命令
48
51
  async def _rule_poke_stop(bot: Bot, event: MessageCreatedEvent) -> bool:
49
- if not config.enable_poke:
50
- return False
51
52
  return extract_poke_tome(event) is not None and (
52
53
  user_in_game(bot.self_id, *extract_user_group(event))
53
54
  )
@@ -66,9 +67,6 @@ with contextlib.suppress(ImportError):
66
67
  event: PublicMessageCreatedEvent,
67
68
  target: MsgTarget,
68
69
  ) -> bool:
69
- if not config.enable_poke:
70
- return False
71
-
72
70
  return (
73
71
  (user_id := extract_poke_tome(event)) is not None
74
72
  and not user_in_game(
@@ -76,7 +74,7 @@ with contextlib.suppress(ImportError):
76
74
  user_id=user_id,
77
75
  group_id=(event.guild and event.guild.id) or event.channel.id,
78
76
  )
79
- and target in get_starting_games()
77
+ and target in preparing_games
80
78
  )
81
79
 
82
80
  @on_message(rule=_rule_poke_join).handle()
@@ -86,7 +84,7 @@ with contextlib.suppress(ImportError):
86
84
  target: MsgTarget,
87
85
  ) -> None:
88
86
  user_id = extract_poke_tome(event) or event.get_user_id()
89
- players = get_starting_games()[target]
87
+ players = preparing_games[target].players
90
88
 
91
89
  if user_id not in players:
92
90
  # XXX:
@@ -110,9 +108,6 @@ with contextlib.suppress(ImportError):
110
108
  await UniMessage.at(user_id).text("\n✅成功加入游戏").send(target, bot)
111
109
 
112
110
  def chronocat_poke_enabled() -> bool:
113
- if not config.enable_poke:
114
- return False
115
-
116
111
  event = current_event.get()
117
112
  return (
118
113
  isinstance(event, MessageCreatedEvent)
@@ -6,8 +6,8 @@ from nonebot_plugin_alconna import MsgTarget, UniMessage
6
6
 
7
7
  from ...config import config
8
8
  from ...constant import STOP_COMMAND
9
- from ...game import get_starting_games
10
9
  from ...utils import InputStore
10
+ from .._prepare_game import preparing_games
11
11
  from ..depends import user_in_game
12
12
 
13
13
 
@@ -15,15 +15,15 @@ def ob11_poke_enabled() -> bool:
15
15
  return False
16
16
 
17
17
 
18
- with contextlib.suppress(ImportError):
18
+ with contextlib.suppress(ImportError, RuntimeError):
19
+ if not config.enable_poke:
20
+ raise RuntimeError # skip matcher definition
21
+
19
22
  from nonebot.adapters.onebot.v11 import Bot
20
23
  from nonebot.adapters.onebot.v11.event import PokeNotifyEvent
21
24
 
22
25
  # 游戏内戳一戳等效 "stop" 命令
23
26
  async def _rule_poke_stop(bot: Bot, event: PokeNotifyEvent) -> bool:
24
- if not config.enable_poke:
25
- return False
26
-
27
27
  user_id = str(event.user_id)
28
28
  group_id = str(event.group_id) if event.group_id is not None else None
29
29
  return (event.target_id == event.self_id) and user_in_game(
@@ -42,7 +42,7 @@ with contextlib.suppress(ImportError):
42
42
  async def _rule_poke_join(
43
43
  bot: Bot, event: PokeNotifyEvent, target: MsgTarget
44
44
  ) -> bool:
45
- if not config.enable_poke or event.group_id is None:
45
+ if event.group_id is None:
46
46
  return False
47
47
 
48
48
  user_id = str(event.user_id)
@@ -50,7 +50,7 @@ with contextlib.suppress(ImportError):
50
50
  return (
51
51
  (event.target_id == event.self_id)
52
52
  and not user_in_game(bot.self_id, user_id, group_id)
53
- and target in get_starting_games()
53
+ and target in preparing_games
54
54
  )
55
55
 
56
56
  @on_notice(rule=_rule_poke_join).handle()
@@ -60,7 +60,7 @@ with contextlib.suppress(ImportError):
60
60
  target: MsgTarget,
61
61
  ) -> None:
62
62
  user_id = event.get_user_id()
63
- players = get_starting_games()[target]
63
+ players = preparing_games[target].players
64
64
 
65
65
  if event.group_id is None or user_id in players:
66
66
  return
@@ -74,7 +74,4 @@ with contextlib.suppress(ImportError):
74
74
  await UniMessage.at(user_id).text("\n✅成功加入游戏").send(target, bot)
75
75
 
76
76
  def ob11_poke_enabled() -> bool:
77
- if not config.enable_poke:
78
- return False
79
-
80
77
  return isinstance(current_bot.get(), Bot)