nonebot-plugin-osubot 6.22.1__py3-none-any.whl → 6.26.4__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.
- nonebot_plugin_osubot/api.py +13 -7
- nonebot_plugin_osubot/config.py +10 -10
- nonebot_plugin_osubot/draw/bmap.py +20 -22
- nonebot_plugin_osubot/draw/bp.py +3 -13
- nonebot_plugin_osubot/draw/catch_preview.py +2 -16
- nonebot_plugin_osubot/draw/echarts.py +8 -1
- nonebot_plugin_osubot/draw/info.py +59 -207
- nonebot_plugin_osubot/draw/info_templates/index.html +507 -0
- nonebot_plugin_osubot/draw/info_templates/output.css +2 -0
- nonebot_plugin_osubot/draw/map.py +9 -11
- nonebot_plugin_osubot/draw/osu_preview.py +50 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +110 -0
- nonebot_plugin_osubot/draw/rating.py +6 -3
- nonebot_plugin_osubot/draw/score.py +23 -81
- nonebot_plugin_osubot/draw/taiko_preview.py +14 -13
- nonebot_plugin_osubot/draw/templates/bpa_chart.html +1 -1
- nonebot_plugin_osubot/draw/utils.py +162 -16
- nonebot_plugin_osubot/file.py +184 -31
- nonebot_plugin_osubot/mania/__init__.py +9 -10
- nonebot_plugin_osubot/matcher/__init__.py +2 -0
- nonebot_plugin_osubot/matcher/bp_analyze.py +14 -9
- nonebot_plugin_osubot/matcher/guess.py +250 -294
- nonebot_plugin_osubot/matcher/map_convert.py +21 -13
- nonebot_plugin_osubot/matcher/medal.py +1 -1
- nonebot_plugin_osubot/matcher/osudl.py +5 -4
- nonebot_plugin_osubot/matcher/pr.py +0 -4
- nonebot_plugin_osubot/matcher/preview.py +10 -3
- nonebot_plugin_osubot/matcher/recommend.py +7 -12
- nonebot_plugin_osubot/mods.py +62 -61
- nonebot_plugin_osubot/network/first_response.py +1 -1
- nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
- nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
- nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
- nonebot_plugin_osubot/pp.py +7 -0
- nonebot_plugin_osubot/schema/__init__.py +0 -2
- nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
- nonebot_plugin_osubot/schema/draw_info.py +54 -0
- nonebot_plugin_osubot/schema/score.py +2 -0
- nonebot_plugin_osubot/schema/user.py +1 -0
- {nonebot_plugin_osubot-6.22.1.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/METADATA +18 -17
- {nonebot_plugin_osubot-6.22.1.dist-info → nonebot_plugin_osubot-6.26.4.dist-info}/RECORD +95 -52
- nonebot_plugin_osubot-6.26.4.dist-info/WHEEL +4 -0
- nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
- nonebot_plugin_osubot-6.22.1.dist-info/WHEEL +0 -4
|
@@ -26,21 +26,77 @@ from ..exceptions import NetworkError
|
|
|
26
26
|
from ..database.models import UserData
|
|
27
27
|
from ..mania import generate_preview_pic
|
|
28
28
|
from ..api import safe_async_get, get_user_scores
|
|
29
|
-
from ..file import map_path,
|
|
29
|
+
from ..file import map_path, download_osu
|
|
30
30
|
from ..draw.catch_preview import draw_cath_preview
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
|
|
33
|
+
class GameType:
|
|
34
|
+
AUDIO = "audio"
|
|
35
|
+
PIC = "pic"
|
|
36
|
+
CHART = "chart"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class GameManager:
|
|
40
|
+
def __init__(self):
|
|
41
|
+
self.games: dict[str, dict[str, NewScore]] = {GameType.AUDIO: {}, GameType.PIC: {}, GameType.CHART: {}}
|
|
42
|
+
self.timers: dict[str, dict[str, TimerHandle]] = {GameType.AUDIO: {}, GameType.PIC: {}, GameType.CHART: {}}
|
|
43
|
+
self.hint_templates = {
|
|
44
|
+
GameType.AUDIO: {"pic": False, "artist": False, "creator": False},
|
|
45
|
+
GameType.PIC: {"artist": False, "creator": False, "audio": False},
|
|
46
|
+
GameType.CHART: {"pic": False, "artist": False, "creator": False, "audio": False},
|
|
47
|
+
}
|
|
48
|
+
self.group_hints: dict[str, dict[str, dict[str, bool]]] = {
|
|
49
|
+
GameType.AUDIO: {},
|
|
50
|
+
GameType.PIC: {},
|
|
51
|
+
GameType.CHART: {},
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
def get_game(self, game_type: str, session_id: str):
|
|
55
|
+
return self.games[game_type].get(session_id)
|
|
56
|
+
|
|
57
|
+
def set_game(self, game_type: str, session_id: str, score: NewScore):
|
|
58
|
+
self.games[game_type][session_id] = score
|
|
59
|
+
|
|
60
|
+
def pop_game(self, game_type: str, session_id: str):
|
|
61
|
+
return self.games[game_type].pop(session_id, None)
|
|
62
|
+
|
|
63
|
+
def get_timer(self, game_type: str, session_id: str):
|
|
64
|
+
return self.timers[game_type].get(session_id)
|
|
65
|
+
|
|
66
|
+
def set_timer(self, game_type: str, session_id: str, timer: TimerHandle):
|
|
67
|
+
self.timers[game_type][session_id] = timer
|
|
68
|
+
|
|
69
|
+
def pop_timer(self, game_type: str, session_id: str):
|
|
70
|
+
return self.timers[game_type].pop(session_id, None)
|
|
71
|
+
|
|
72
|
+
def get_hint(self, game_type: str, session_id: str):
|
|
73
|
+
return self.group_hints[game_type].get(session_id)
|
|
74
|
+
|
|
75
|
+
def init_hint(self, game_type: str, session_id: str):
|
|
76
|
+
self.group_hints[game_type][session_id] = self.hint_templates[game_type].copy()
|
|
77
|
+
|
|
78
|
+
def reset_hint(self, game_type: str, session_id: str):
|
|
79
|
+
self.group_hints[game_type][session_id] = None
|
|
80
|
+
|
|
81
|
+
def is_game_running(self, game_type: str, session_id: str) -> bool:
|
|
82
|
+
return bool(self.games[game_type].get(session_id))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
game_manager = GameManager()
|
|
86
|
+
|
|
87
|
+
# Keep old references for backward compatibility during transition
|
|
88
|
+
games = game_manager.games[GameType.AUDIO]
|
|
89
|
+
pic_games = game_manager.games[GameType.PIC]
|
|
90
|
+
chart_games = game_manager.games[GameType.CHART]
|
|
91
|
+
timers = game_manager.timers[GameType.AUDIO]
|
|
92
|
+
pic_timers = game_manager.timers[GameType.PIC]
|
|
93
|
+
chart_timers = game_manager.timers[GameType.CHART]
|
|
94
|
+
hint_dic = game_manager.hint_templates[GameType.AUDIO]
|
|
95
|
+
pic_hint_dic = game_manager.hint_templates[GameType.PIC]
|
|
96
|
+
chart_hint_dic = game_manager.hint_templates[GameType.CHART]
|
|
97
|
+
group_hint = game_manager.group_hints[GameType.AUDIO]
|
|
98
|
+
pic_group_hint = game_manager.group_hints[GameType.PIC]
|
|
99
|
+
chart_group_hint = game_manager.group_hints[GameType.CHART]
|
|
44
100
|
guess_audio = on_command("音频猜歌", priority=11, block=True)
|
|
45
101
|
guess_chart = on_command("谱面猜歌", priority=11, block=True)
|
|
46
102
|
guess_song_cache = ExpiringDict(1000, 60 * 60 * 24)
|
|
@@ -71,62 +127,86 @@ async def get_random_beatmap_set(binded_id, group_id) -> (UnifiedScore, str):
|
|
|
71
127
|
return selected_score, osu_name
|
|
72
128
|
|
|
73
129
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
):
|
|
81
|
-
if "error" in state:
|
|
82
|
-
mode = str(random.randint(0, 3))
|
|
83
|
-
await UniMessage.text("由于未绑定OSU账号,本次随机挑选模式进行猜歌\n" + state["error"]).send(reply_to=True)
|
|
84
|
-
else:
|
|
85
|
-
mode = state["mode"]
|
|
86
|
-
group_id = session_id
|
|
130
|
+
async def select_score_from_user(state: T_State, msg: UniMsg, session_id: str):
|
|
131
|
+
"""
|
|
132
|
+
Common logic for selecting a score from a specific user or randomly.
|
|
133
|
+
Returns (selected_score, selected_user) or (None, error_msg).
|
|
134
|
+
"""
|
|
135
|
+
mode = state.get("mode", str(random.randint(0, 3)))
|
|
87
136
|
binded_id = await UserData.filter(osu_mode=mode).values_list("user_id", flat=True)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
137
|
+
|
|
138
|
+
if not guess_song_cache.get(session_id):
|
|
139
|
+
guess_song_cache[session_id] = set()
|
|
140
|
+
|
|
141
|
+
# Handle @mention
|
|
92
142
|
if msg.has(At):
|
|
93
143
|
qq = msg.get(At)[0].target
|
|
94
|
-
user_data = await UserData.get_or_none(user_id=qq)
|
|
144
|
+
user_data = await UserData.get_or_none(user_id=int(qq))
|
|
95
145
|
if not user_data:
|
|
96
|
-
|
|
146
|
+
return None, "该用户未绑定osu账号"
|
|
97
147
|
try:
|
|
98
148
|
bp_ls = await get_user_scores(user_data.osu_id, NGM[state["mode"]], "best")
|
|
99
149
|
except NetworkError as e:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[group_id]]
|
|
150
|
+
return None, f"在查找用户:{state['username']} {NGM[state['mode']]}模式bp时 {str(e)}"
|
|
151
|
+
|
|
152
|
+
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[session_id]]
|
|
104
153
|
if not filtered_bp_ls:
|
|
105
|
-
|
|
154
|
+
return None, f"{state['username']}的bp已经被你们猜过一遍了 -_-"
|
|
155
|
+
|
|
106
156
|
selected_score = random.choice(filtered_bp_ls)
|
|
107
|
-
guess_song_cache[
|
|
108
|
-
|
|
109
|
-
|
|
157
|
+
guess_song_cache[session_id].add(selected_score.beatmapset.id)
|
|
158
|
+
return selected_score, user_data.osu_name
|
|
159
|
+
|
|
160
|
+
# Handle specific user from state
|
|
161
|
+
elif state.get("user"):
|
|
110
162
|
try:
|
|
111
163
|
bp_ls = await get_user_scores(state["user"], NGM[state["mode"]], "best")
|
|
112
164
|
except NetworkError as e:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[group_id]]
|
|
165
|
+
return None, f"在查找用户:{state['username']} {NGM[state['mode']]}模式bp时 {str(e)}"
|
|
166
|
+
|
|
167
|
+
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[session_id]]
|
|
117
168
|
if not filtered_bp_ls:
|
|
118
|
-
|
|
169
|
+
return None, f"{state['username']}的bp已经被你们猜过一遍了 -_-"
|
|
170
|
+
|
|
119
171
|
selected_score = random.choice(filtered_bp_ls)
|
|
120
|
-
guess_song_cache[
|
|
121
|
-
|
|
172
|
+
guess_song_cache[session_id].add(selected_score.beatmapset.id)
|
|
173
|
+
return selected_score, state["username"]
|
|
174
|
+
|
|
175
|
+
# Random selection
|
|
122
176
|
else:
|
|
123
|
-
|
|
177
|
+
return await get_random_beatmap_set(binded_id, session_id)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@guess_audio.handle(parameterless=[split_msg()])
|
|
181
|
+
async def _(
|
|
182
|
+
state: T_State,
|
|
183
|
+
matcher: Matcher,
|
|
184
|
+
msg: UniMsg,
|
|
185
|
+
session_id: str = SessionId(SessionIdType.GROUP),
|
|
186
|
+
):
|
|
187
|
+
if "error" in state:
|
|
188
|
+
mode = str(random.randint(0, 3))
|
|
189
|
+
await UniMessage.text("由于未绑定OSU账号,本次随机挑选模式进行猜歌\n" + state["error"]).send(reply_to=True)
|
|
190
|
+
else:
|
|
191
|
+
mode = state["mode"]
|
|
192
|
+
|
|
193
|
+
binded_id = await UserData.filter(osu_mode=mode).values_list("user_id", flat=True)
|
|
194
|
+
if not binded_id:
|
|
195
|
+
await UniMessage.text("还没有人绑定该模式的osu账号呢,绑定了再来试试吧").finish(reply_to=True)
|
|
196
|
+
|
|
197
|
+
result = await select_score_from_user(state, msg, session_id)
|
|
198
|
+
if result[0] is None:
|
|
199
|
+
await UniMessage.text(result[1]).finish(reply_to=True)
|
|
200
|
+
selected_score, selected_user = result
|
|
201
|
+
|
|
124
202
|
if not selected_score:
|
|
125
203
|
await UniMessage.text("好像没有可以猜的歌了,今天的猜歌就到此结束吧!").finish(reply_to=True)
|
|
126
|
-
|
|
204
|
+
|
|
205
|
+
if games.get(session_id, None):
|
|
127
206
|
await UniMessage.text("现在还有进行中的猜歌呢,请等待当前猜歌结束").finish(reply_to=True)
|
|
128
|
-
|
|
129
|
-
|
|
207
|
+
|
|
208
|
+
games[session_id] = selected_score
|
|
209
|
+
set_timeout(matcher, session_id)
|
|
130
210
|
await UniMessage.text(
|
|
131
211
|
f"开始音频猜歌游戏,猜猜下面音频的曲名吧,该曲抽选自{selected_user} {NGM[mode]} 模式的bp"
|
|
132
212
|
).send(reply_to=True)
|
|
@@ -140,67 +220,48 @@ async def _(
|
|
|
140
220
|
await UniMessage.audio(raw=audio.read()).finish()
|
|
141
221
|
|
|
142
222
|
|
|
143
|
-
async def
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
group_hint[cid] = None
|
|
223
|
+
async def stop_game_generic(matcher: Matcher, game_type: str, cid: str):
|
|
224
|
+
game_manager.pop_timer(game_type, cid)
|
|
225
|
+
game = game_manager.pop_game(game_type, cid)
|
|
226
|
+
if game:
|
|
227
|
+
game_manager.reset_hint(game_type, cid)
|
|
149
228
|
msg = f"猜歌超时,游戏结束,正确答案是{game.beatmapset.title_unicode}"
|
|
150
229
|
if game.beatmapset.title_unicode != game.beatmapset.title:
|
|
151
230
|
msg += f" [{game.beatmapset.title}]"
|
|
152
231
|
await matcher.send(msg)
|
|
153
232
|
|
|
154
233
|
|
|
234
|
+
async def stop_game(matcher: Matcher, cid: str):
|
|
235
|
+
await stop_game_generic(matcher, GameType.AUDIO, cid)
|
|
236
|
+
|
|
237
|
+
|
|
155
238
|
async def pic_stop_game(matcher: Matcher, cid: str):
|
|
156
|
-
|
|
157
|
-
if pic_games.get(cid, None):
|
|
158
|
-
game = pic_games.pop(cid)
|
|
159
|
-
if pic_group_hint.get(cid, None):
|
|
160
|
-
pic_group_hint[cid] = None
|
|
161
|
-
msg = f"猜歌超时,游戏结束,正确答案是{game.beatmapset.title_unicode}"
|
|
162
|
-
if game.beatmapset.title_unicode != game.beatmapset.title:
|
|
163
|
-
msg += f" [{game.beatmapset.title}]"
|
|
164
|
-
await matcher.send(msg)
|
|
239
|
+
await stop_game_generic(matcher, GameType.PIC, cid)
|
|
165
240
|
|
|
166
241
|
|
|
167
242
|
async def chart_stop_game(matcher: Matcher, cid: str):
|
|
168
|
-
|
|
169
|
-
if chart_games.get(cid, None):
|
|
170
|
-
game = chart_games.pop(cid)
|
|
171
|
-
if chart_group_hint.get(cid, None):
|
|
172
|
-
chart_group_hint[cid] = None
|
|
173
|
-
msg = f"猜歌超时,游戏结束,正确答案是{game.beatmapset.title_unicode}"
|
|
174
|
-
if game.beatmapset.title_unicode != game.beatmapset.title:
|
|
175
|
-
msg += f" [{game.beatmapset.title}]"
|
|
176
|
-
await matcher.send(msg)
|
|
243
|
+
await stop_game_generic(matcher, GameType.CHART, cid)
|
|
177
244
|
|
|
178
245
|
|
|
179
|
-
def
|
|
180
|
-
timer =
|
|
246
|
+
def set_timeout_generic(matcher: Matcher, game_type: str, stop_func, cid: str, timeout: float = 300):
|
|
247
|
+
timer = game_manager.get_timer(game_type, cid)
|
|
181
248
|
if timer:
|
|
182
249
|
timer.cancel()
|
|
183
250
|
loop = asyncio.get_running_loop()
|
|
184
|
-
timer = loop.call_later(timeout, lambda: asyncio.ensure_future(
|
|
185
|
-
|
|
251
|
+
timer = loop.call_later(timeout, lambda: asyncio.ensure_future(stop_func(matcher, cid)))
|
|
252
|
+
game_manager.set_timer(game_type, cid, timer)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def set_timeout(matcher: Matcher, cid: str, timeout: float = 300):
|
|
256
|
+
set_timeout_generic(matcher, GameType.AUDIO, stop_game, cid, timeout)
|
|
186
257
|
|
|
187
258
|
|
|
188
259
|
def pic_set_timeout(matcher: Matcher, cid: str, timeout: float = 300):
|
|
189
|
-
|
|
190
|
-
if timer:
|
|
191
|
-
timer.cancel()
|
|
192
|
-
loop = asyncio.get_running_loop()
|
|
193
|
-
timer = loop.call_later(timeout, lambda: asyncio.ensure_future(pic_stop_game(matcher, cid)))
|
|
194
|
-
pic_timers[cid] = timer
|
|
260
|
+
set_timeout_generic(matcher, GameType.PIC, pic_stop_game, cid, timeout)
|
|
195
261
|
|
|
196
262
|
|
|
197
263
|
def chart_set_timeout(matcher: Matcher, cid: str, timeout: float = 300):
|
|
198
|
-
|
|
199
|
-
if timer:
|
|
200
|
-
timer.cancel()
|
|
201
|
-
loop = asyncio.get_running_loop()
|
|
202
|
-
timer = loop.call_later(timeout, lambda: asyncio.ensure_future(chart_stop_game(matcher, cid)))
|
|
203
|
-
chart_timers[cid] = timer
|
|
264
|
+
set_timeout_generic(matcher, GameType.CHART, chart_stop_game, cid, timeout)
|
|
204
265
|
|
|
205
266
|
|
|
206
267
|
def game_running(session_id: str = SessionId(SessionIdType.GROUP)) -> bool:
|
|
@@ -215,6 +276,29 @@ def chart_game_running(session_id: str = SessionId(SessionIdType.GROUP)) -> bool
|
|
|
215
276
|
return bool(chart_games.get(session_id, None))
|
|
216
277
|
|
|
217
278
|
|
|
279
|
+
def create_word_matcher_handler(game_type: str, games_dict: dict):
|
|
280
|
+
"""Factory function to create word matcher handlers for different game types."""
|
|
281
|
+
|
|
282
|
+
async def handler(event: Event, session_id: str = SessionId(SessionIdType.GROUP)):
|
|
283
|
+
song_name = games_dict[session_id].beatmapset.title
|
|
284
|
+
song_name_unicode = games_dict[session_id].beatmapset.title_unicode
|
|
285
|
+
user_input = event.get_plaintext().lower()
|
|
286
|
+
|
|
287
|
+
# Calculate similarity ratios
|
|
288
|
+
r1 = SequenceMatcher(None, song_name.lower(), user_input).ratio()
|
|
289
|
+
r2 = SequenceMatcher(None, song_name_unicode.lower(), user_input).ratio()
|
|
290
|
+
r3 = SequenceMatcher(None, re.sub(r"[(\[].*[)\]]", "", song_name.lower()), user_input).ratio()
|
|
291
|
+
r4 = SequenceMatcher(None, re.sub(r"[(\[].*[)\]]", "", song_name_unicode.lower()), user_input).ratio()
|
|
292
|
+
|
|
293
|
+
if r1 >= 0.5 or r2 >= 0.5 or r3 >= 0.5 or r4 >= 0.5:
|
|
294
|
+
game_manager.pop_game(game_type, session_id)
|
|
295
|
+
game_manager.reset_hint(game_type, session_id)
|
|
296
|
+
msg = f"恭喜猜出正确答案为{song_name_unicode}"
|
|
297
|
+
await UniMessage.text(msg).send(reply_to=True)
|
|
298
|
+
|
|
299
|
+
return handler
|
|
300
|
+
|
|
301
|
+
|
|
218
302
|
word_matcher = on_message(Rule(game_running), priority=12)
|
|
219
303
|
pic_word_matcher = on_message(Rule(pic_game_running), priority=12)
|
|
220
304
|
chart_word_matcher = on_message(Rule(chart_game_running), priority=12)
|
|
@@ -222,98 +306,48 @@ chart_word_matcher = on_message(Rule(chart_game_running), priority=12)
|
|
|
222
306
|
|
|
223
307
|
@word_matcher.handle()
|
|
224
308
|
async def _(event: Event, session_id: str = SessionId(SessionIdType.GROUP)):
|
|
225
|
-
|
|
226
|
-
song_name_unicode = games[session_id].beatmapset.title_unicode
|
|
227
|
-
r1 = SequenceMatcher(None, song_name.lower(), event.get_plaintext().lower()).ratio()
|
|
228
|
-
r2 = SequenceMatcher(None, song_name_unicode.lower(), event.get_plaintext().lower()).ratio()
|
|
229
|
-
r3 = SequenceMatcher(
|
|
230
|
-
None,
|
|
231
|
-
re.sub(r"[(\[].*[)\]]", "", song_name.lower()),
|
|
232
|
-
event.get_plaintext().lower(),
|
|
233
|
-
).ratio()
|
|
234
|
-
r4 = SequenceMatcher(
|
|
235
|
-
None,
|
|
236
|
-
re.sub(r"[(\[].*[)\]]", "", song_name_unicode.lower()),
|
|
237
|
-
event.get_plaintext().lower(),
|
|
238
|
-
).ratio()
|
|
239
|
-
if r1 >= 0.5 or r2 >= 0.5 or r3 >= 0.5 or r4 >= 0.5:
|
|
240
|
-
games.pop(session_id)
|
|
241
|
-
if group_hint.get(session_id, None):
|
|
242
|
-
group_hint[session_id] = None
|
|
243
|
-
msg = f"恭喜猜出正确答案为{song_name_unicode}"
|
|
244
|
-
await UniMessage.text(msg).send(reply_to=True)
|
|
309
|
+
await create_word_matcher_handler(GameType.AUDIO, games)(event, session_id)
|
|
245
310
|
|
|
246
311
|
|
|
247
312
|
@pic_word_matcher.handle()
|
|
248
313
|
async def _(event: Event, session_id: str = SessionId(SessionIdType.GROUP)):
|
|
249
|
-
|
|
250
|
-
song_name_unicode = pic_games[session_id].beatmapset.title_unicode
|
|
251
|
-
r1 = SequenceMatcher(None, song_name.lower(), event.get_plaintext().lower()).ratio()
|
|
252
|
-
r2 = SequenceMatcher(None, song_name_unicode.lower(), event.get_plaintext().lower()).ratio()
|
|
253
|
-
r3 = SequenceMatcher(
|
|
254
|
-
None,
|
|
255
|
-
re.sub(r"[(\[].*[)\]]", "", song_name.lower()),
|
|
256
|
-
event.get_plaintext().lower(),
|
|
257
|
-
).ratio()
|
|
258
|
-
r4 = SequenceMatcher(
|
|
259
|
-
None,
|
|
260
|
-
re.sub(r"[(\[].*[)\]]", "", song_name_unicode.lower()),
|
|
261
|
-
event.get_plaintext().lower(),
|
|
262
|
-
).ratio()
|
|
263
|
-
if r1 >= 0.5 or r2 >= 0.5 or r3 >= 0.5 or r4 >= 0.5:
|
|
264
|
-
pic_games.pop(session_id)
|
|
265
|
-
if pic_group_hint.get(session_id, None):
|
|
266
|
-
pic_group_hint[session_id] = None
|
|
267
|
-
msg = f"恭喜猜出正确答案为{song_name_unicode}"
|
|
268
|
-
await UniMessage.text(msg).send(reply_to=True)
|
|
314
|
+
await create_word_matcher_handler(GameType.PIC, pic_games)(event, session_id)
|
|
269
315
|
|
|
270
316
|
|
|
271
|
-
|
|
317
|
+
@chart_word_matcher.handle()
|
|
318
|
+
async def _(event: Event, session_id: str = SessionId(SessionIdType.GROUP)):
|
|
319
|
+
await create_word_matcher_handler(GameType.CHART, chart_games)(event, session_id)
|
|
272
320
|
|
|
273
321
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
score =
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
322
|
+
async def handle_hint_generic(game_type: str, games_dict: dict, session_id: str, matcher):
|
|
323
|
+
"""Generic hint handler for all game types."""
|
|
324
|
+
score = games_dict[session_id]
|
|
325
|
+
|
|
326
|
+
if not game_manager.get_hint(game_type, session_id):
|
|
327
|
+
game_manager.init_hint(game_type, session_id)
|
|
328
|
+
|
|
329
|
+
hints = game_manager.get_hint(game_type, session_id)
|
|
330
|
+
if all(hints.values()):
|
|
280
331
|
await UniMessage.text("已无更多提示,加油哦").finish(reply_to=True)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
332
|
+
|
|
333
|
+
# Get available hint types
|
|
334
|
+
available_hints = [key for key, value in hints.items() if not value]
|
|
335
|
+
action = random.choice(available_hints)
|
|
336
|
+
|
|
337
|
+
# Mark hint as used
|
|
338
|
+
hints[action] = True
|
|
339
|
+
|
|
340
|
+
# Provide hint based on action
|
|
286
341
|
if action == "pic":
|
|
287
|
-
group_hint[session_id]["pic"] = True
|
|
288
342
|
await UniMessage.image(url=score.beatmapset.covers.cover).finish(reply_to=True)
|
|
289
|
-
|
|
290
|
-
group_hint[session_id]["artist"] = True
|
|
343
|
+
elif action == "artist":
|
|
291
344
|
msg = f"曲师为:{score.beatmapset.artist_unicode}"
|
|
292
345
|
if score.beatmapset.artist_unicode != score.beatmapset.artist:
|
|
293
346
|
msg += f" [{score.beatmapset.artist}]"
|
|
294
|
-
await
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
pic_hint = on_command("图片提示", priority=11, block=True, rule=Rule(pic_game_running))
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
@pic_hint.handle()
|
|
304
|
-
async def _(session_id: str = SessionId(SessionIdType.GROUP)):
|
|
305
|
-
score = pic_games[session_id]
|
|
306
|
-
if not pic_group_hint.get(session_id, None):
|
|
307
|
-
pic_group_hint[session_id] = pic_hint_dic.copy()
|
|
308
|
-
if all(pic_group_hint[session_id].values()):
|
|
309
|
-
await pic_hint.finish("已无更多提示,加油哦")
|
|
310
|
-
true_keys = []
|
|
311
|
-
for key, value in pic_group_hint[session_id].items():
|
|
312
|
-
if not value:
|
|
313
|
-
true_keys.append(key)
|
|
314
|
-
action = random.choice(true_keys)
|
|
315
|
-
if action == "audio":
|
|
316
|
-
pic_group_hint[session_id]["audio"] = True
|
|
347
|
+
await matcher.finish(msg)
|
|
348
|
+
elif action == "creator":
|
|
349
|
+
await matcher.finish(f"谱师为:{score.beatmapset.creator}")
|
|
350
|
+
elif action == "audio":
|
|
317
351
|
path = map_path / f"{score.beatmapset.id}"
|
|
318
352
|
if not path.exists():
|
|
319
353
|
path.mkdir(parents=True, exist_ok=True)
|
|
@@ -321,15 +355,30 @@ async def _(session_id: str = SessionId(SessionIdType.GROUP)):
|
|
|
321
355
|
if not audio:
|
|
322
356
|
await UniMessage.text("音频下载失败了 qaq ").finish(reply_to=True)
|
|
323
357
|
await UniMessage.audio(raw=audio.read()).finish()
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
hint = on_command("音频提示", priority=11, block=True, rule=Rule(game_running))
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@hint.handle()
|
|
364
|
+
async def _(session_id: str = SessionId(SessionIdType.GROUP)):
|
|
365
|
+
await handle_hint_generic(GameType.AUDIO, games, session_id, hint)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
pic_hint = on_command("图片提示", priority=11, block=True, rule=Rule(pic_game_running))
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
@pic_hint.handle()
|
|
372
|
+
async def _(session_id: str = SessionId(SessionIdType.GROUP)):
|
|
373
|
+
await handle_hint_generic(GameType.PIC, pic_games, session_id, pic_hint)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
chart_hint = on_command("谱面提示", priority=11, block=True, rule=Rule(chart_game_running))
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
@chart_hint.handle()
|
|
380
|
+
async def _(session_id: str = SessionId(SessionIdType.GROUP)):
|
|
381
|
+
await handle_hint_generic(GameType.CHART, chart_games, session_id, chart_hint)
|
|
333
382
|
|
|
334
383
|
|
|
335
384
|
guess_pic = on_command("图片猜歌", priority=11, block=True)
|
|
@@ -347,47 +396,22 @@ async def _(
|
|
|
347
396
|
await UniMessage.text("由于未绑定OSU账号,本次随机选择模式进行猜歌\n" + state["error"]).send(reply_to=True)
|
|
348
397
|
else:
|
|
349
398
|
mode = state["mode"]
|
|
399
|
+
|
|
350
400
|
binded_id = await UserData.filter(osu_mode=mode).values_list("user_id", flat=True)
|
|
351
401
|
if not binded_id:
|
|
352
402
|
await guess_pic.finish("还没有人绑定该模式的osu账号呢,绑定了再来试试吧")
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
await UniMessage.text("该用户未绑定osu账号").finish(reply_to=True)
|
|
360
|
-
try:
|
|
361
|
-
bp_ls = await get_user_scores(user_data.osu_id, NGM[state["mode"]], "best")
|
|
362
|
-
except NetworkError as e:
|
|
363
|
-
await UniMessage.text(f"在查找用户:{state['username']} {NGM[state['mode']]}模式bp时 {str(e)}").finish(
|
|
364
|
-
reply_to=True
|
|
365
|
-
)
|
|
366
|
-
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[session_id]]
|
|
367
|
-
if not filtered_bp_ls:
|
|
368
|
-
await UniMessage.text(state["username"] + "的bp已经被你们猜过一遍了 -_-").finish(reply_to=True)
|
|
369
|
-
selected_score = random.choice(filtered_bp_ls)
|
|
370
|
-
guess_song_cache[session_id].add(selected_score.beatmapset.id)
|
|
371
|
-
selected_user = user_data.osu_name
|
|
372
|
-
elif state["user"]:
|
|
373
|
-
try:
|
|
374
|
-
bp_ls = await get_user_scores(state["user"], NGM[state["mode"]], "best")
|
|
375
|
-
except NetworkError as e:
|
|
376
|
-
await UniMessage.text(f"在查找用户:{state['username']} {NGM[state['mode']]}模式bp时 {str(e)}").finish(
|
|
377
|
-
reply_to=True
|
|
378
|
-
)
|
|
379
|
-
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[session_id]]
|
|
380
|
-
if not filtered_bp_ls:
|
|
381
|
-
await UniMessage.text(state["username"] + "的bp已经被你们猜过一遍了 -_-").finish(reply_to=True)
|
|
382
|
-
selected_score = random.choice(filtered_bp_ls)
|
|
383
|
-
guess_song_cache[session_id].add(selected_score.beatmapset.id)
|
|
384
|
-
selected_user = state["username"]
|
|
385
|
-
else:
|
|
386
|
-
selected_score, selected_user = await get_random_beatmap_set(binded_id, session_id)
|
|
403
|
+
|
|
404
|
+
result = await select_score_from_user(state, msg, session_id)
|
|
405
|
+
if result[0] is None:
|
|
406
|
+
await UniMessage.text(result[1]).finish(reply_to=True)
|
|
407
|
+
selected_score, selected_user = result
|
|
408
|
+
|
|
387
409
|
if not selected_score:
|
|
388
410
|
await guess_pic.finish("好像没有可以猜的歌了,今天的猜歌就到此结束吧!")
|
|
411
|
+
|
|
389
412
|
if pic_games.get(session_id, None):
|
|
390
413
|
await guess_pic.finish("现在还有进行中的猜歌呢,请等待当前猜歌结束")
|
|
414
|
+
|
|
391
415
|
pic_games[session_id] = selected_score
|
|
392
416
|
pic_set_timeout(matcher, session_id)
|
|
393
417
|
try:
|
|
@@ -424,56 +448,32 @@ async def _(
|
|
|
424
448
|
await UniMessage.text("由于未绑定OSU账号,本次随机选择模式进行猜歌\n" + state["error"]).send(reply_to=True)
|
|
425
449
|
else:
|
|
426
450
|
mode = state["mode"]
|
|
451
|
+
|
|
427
452
|
if mode == "0":
|
|
428
453
|
await UniMessage.text("该模式暂不支持猜歌").finish(reply_to=True)
|
|
454
|
+
|
|
429
455
|
binded_id = await UserData.filter(osu_mode=mode).values_list("user_id", flat=True)
|
|
430
456
|
if not binded_id:
|
|
431
457
|
await guess_pic.finish("还没有人绑定该模式的osu账号呢,绑定了再来试试吧")
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
await UniMessage.text("该用户未绑定osu账号").finish(reply_to=True)
|
|
439
|
-
try:
|
|
440
|
-
bp_ls = await get_user_scores(user_data.osu_id, NGM[state["mode"]], "best")
|
|
441
|
-
except NetworkError as e:
|
|
442
|
-
await UniMessage.text(f"在查找用户:{state['username']} {NGM[state['mode']]}模式bp时 {str(e)}").finish(
|
|
443
|
-
reply_to=True
|
|
444
|
-
)
|
|
445
|
-
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[session_id]]
|
|
446
|
-
if not filtered_bp_ls:
|
|
447
|
-
await UniMessage.text(state["username"] + "的bp已经被你们猜过一遍了 -_-").finish(reply_to=True)
|
|
448
|
-
selected_score = random.choice(filtered_bp_ls)
|
|
449
|
-
selected_user = user_data.osu_name
|
|
450
|
-
guess_song_cache[session_id].add(selected_score.beatmapset.id)
|
|
451
|
-
elif state["user"]:
|
|
452
|
-
try:
|
|
453
|
-
bp_ls = await get_user_scores(state["user"], NGM[state["mode"]], "best")
|
|
454
|
-
except NetworkError as e:
|
|
455
|
-
await UniMessage.text(f"在查找用户:{state['username']} {NGM[state['mode']]}模式bp时 {str(e)}").finish(
|
|
456
|
-
reply_to=True
|
|
457
|
-
)
|
|
458
|
-
filtered_bp_ls = [i for i in bp_ls if i.beatmapset.id not in guess_song_cache[session_id]]
|
|
459
|
-
if not filtered_bp_ls:
|
|
460
|
-
await UniMessage.text(state["username"] + "的bp已经被你们猜过一遍了 -_-").finish(reply_to=True)
|
|
461
|
-
selected_score = random.choice(filtered_bp_ls)
|
|
462
|
-
selected_user = state["username"]
|
|
463
|
-
guess_song_cache[session_id].add(selected_score.beatmapset.id)
|
|
464
|
-
else:
|
|
465
|
-
selected_score, selected_user = await get_random_beatmap_set(binded_id, session_id)
|
|
458
|
+
|
|
459
|
+
result = await select_score_from_user(state, msg, session_id)
|
|
460
|
+
if result[0] is None:
|
|
461
|
+
await UniMessage.text(result[1]).finish(reply_to=True)
|
|
462
|
+
selected_score, selected_user = result
|
|
463
|
+
|
|
466
464
|
if not selected_score:
|
|
467
465
|
await guess_pic.finish("好像没有可以猜的歌了,今天的猜歌就到此结束吧!")
|
|
466
|
+
|
|
468
467
|
if chart_games.get(session_id, None):
|
|
469
468
|
await guess_pic.finish("现在还有进行中的猜歌呢,请等待当前猜歌结束")
|
|
469
|
+
|
|
470
470
|
chart_games[session_id] = selected_score
|
|
471
471
|
chart_set_timeout(matcher, session_id)
|
|
472
472
|
if mode == "3":
|
|
473
|
-
osu = await
|
|
473
|
+
osu = await download_osu(selected_score.beatmapset.id, selected_score.beatmap.id)
|
|
474
474
|
pic = await generate_preview_pic(osu)
|
|
475
475
|
elif mode == "1":
|
|
476
|
-
osu = await
|
|
476
|
+
osu = await download_osu(selected_score.beatmapset.id, selected_score.beatmap.id)
|
|
477
477
|
beatmap = parse_map(osu)
|
|
478
478
|
pic = map_to_image(beatmap)
|
|
479
479
|
else:
|
|
@@ -487,21 +487,7 @@ async def _(
|
|
|
487
487
|
|
|
488
488
|
@chart_word_matcher.handle()
|
|
489
489
|
async def _(event: Event, session_id: str = SessionId(SessionIdType.GROUP)):
|
|
490
|
-
|
|
491
|
-
song_name_unicode = chart_games[session_id].beatmapset.title_unicode
|
|
492
|
-
r1 = SequenceMatcher(None, song_name.lower(), event.get_plaintext().lower()).ratio()
|
|
493
|
-
r2 = SequenceMatcher(None, song_name_unicode.lower(), event.get_plaintext().lower()).ratio()
|
|
494
|
-
r3 = SequenceMatcher(
|
|
495
|
-
None,
|
|
496
|
-
re.sub(r"[(\[].*[)\]]", "", song_name.lower()),
|
|
497
|
-
event.get_plaintext().lower(),
|
|
498
|
-
).ratio()
|
|
499
|
-
if r1 >= 0.5 or r2 >= 0.5 or r3 >= 0.5:
|
|
500
|
-
chart_games.pop(session_id)
|
|
501
|
-
if chart_group_hint.get(session_id, None):
|
|
502
|
-
chart_group_hint[session_id] = None
|
|
503
|
-
msg = f"恭喜猜出正确答案为{song_name_unicode}"
|
|
504
|
-
await UniMessage.text(msg).send(reply_to=True)
|
|
490
|
+
await create_word_matcher_handler(GameType.CHART, chart_games)(event, session_id)
|
|
505
491
|
|
|
506
492
|
|
|
507
493
|
chart_hint = on_command("谱面提示", priority=11, block=True, rule=Rule(chart_game_running))
|
|
@@ -509,34 +495,4 @@ chart_hint = on_command("谱面提示", priority=11, block=True, rule=Rule(chart
|
|
|
509
495
|
|
|
510
496
|
@chart_hint.handle()
|
|
511
497
|
async def _(session_id: str = SessionId(SessionIdType.GROUP)):
|
|
512
|
-
|
|
513
|
-
if not chart_group_hint.get(session_id, None):
|
|
514
|
-
chart_group_hint[session_id] = chart_hint_dic.copy()
|
|
515
|
-
if all(chart_group_hint[session_id].values()):
|
|
516
|
-
await chart_hint.finish("已无更多提示,加油哦")
|
|
517
|
-
true_keys = []
|
|
518
|
-
for key, value in chart_group_hint[session_id].items():
|
|
519
|
-
if not value:
|
|
520
|
-
true_keys.append(key)
|
|
521
|
-
action = random.choice(true_keys)
|
|
522
|
-
if action == "audio":
|
|
523
|
-
chart_group_hint[session_id]["audio"] = True
|
|
524
|
-
path = map_path / f"{score.beatmapset.id}"
|
|
525
|
-
if not path.exists():
|
|
526
|
-
path.mkdir(parents=True, exist_ok=True)
|
|
527
|
-
audio = await safe_async_get(f"https://b.ppy.sh/preview/{score.beatmapset.id}.mp3")
|
|
528
|
-
if not audio:
|
|
529
|
-
await UniMessage.text("音频下载失败了 qaq ").finish(reply_to=True)
|
|
530
|
-
await UniMessage.audio(raw=audio.read()).finish()
|
|
531
|
-
if action == "artist":
|
|
532
|
-
chart_group_hint[session_id]["artist"] = True
|
|
533
|
-
msg = f"曲师为:{score.beatmapset.artist_unicode}"
|
|
534
|
-
if score.beatmapset.artist_unicode != score.beatmapset.artist:
|
|
535
|
-
msg += f" [{score.beatmapset.artist}]"
|
|
536
|
-
await chart_hint.finish(msg)
|
|
537
|
-
if action == "creator":
|
|
538
|
-
chart_group_hint[session_id]["creator"] = True
|
|
539
|
-
await chart_hint.finish(f"谱师为:{score.beatmapset.creator}")
|
|
540
|
-
if action == "pic":
|
|
541
|
-
chart_group_hint[session_id]["pic"] = True
|
|
542
|
-
await UniMessage.image(url=score.beatmapset.covers.cover).finish(reply_to=True)
|
|
498
|
+
await handle_hint_generic(GameType.CHART, chart_games, session_id, chart_hint)
|