forked from mttu-developers/konabot
188 lines
6.1 KiB
Python
188 lines
6.1 KiB
Python
"""
|
|
生成各种各样的 Message 的函数集合
|
|
"""
|
|
|
|
|
|
import datetime
|
|
import functools
|
|
import re
|
|
from typing import Any
|
|
|
|
from nonebot_plugin_alconna import UniMessage
|
|
|
|
from konabot.common.username import get_username
|
|
from konabot.plugins.kona_ph.core.image import get_image_manager
|
|
from konabot.plugins.kona_ph.core.storage import (DailyPuzzleInfo, Puzzle,
|
|
PuzzleManager,
|
|
PuzzleSubmission)
|
|
|
|
|
|
def get_puzzle_description(puzzle: Puzzle, with_answer: bool = False) -> UniMessage[Any]:
|
|
"""
|
|
获取一个谜题的描述
|
|
"""
|
|
|
|
img_manager = get_image_manager()
|
|
|
|
result = UniMessage.text(f"[KonaPH#{puzzle.index_id}] {puzzle.title}")
|
|
result = result.text(f"\n\n{puzzle.content}")
|
|
|
|
if puzzle.img_name:
|
|
result = result.text("\n\n").image(
|
|
raw=img_manager.read_puzzle_image(puzzle.img_name)
|
|
)
|
|
|
|
result = result.text(f"\n\n出题者:{get_username(puzzle.author_id)}")
|
|
|
|
if with_answer:
|
|
result = result.text(f"\n\n题目答案:{puzzle.flag}")
|
|
else:
|
|
result = result.text("\n\nAt 我或者私聊我「提交答案 答案」来提交你的解答")
|
|
|
|
return result
|
|
|
|
|
|
def get_submission_message(
|
|
puzzle: Puzzle,
|
|
submission: PuzzleSubmission,
|
|
daily_puzzle_info: DailyPuzzleInfo | None = None,
|
|
) -> str:
|
|
"""
|
|
获得提交答案的反馈信息
|
|
"""
|
|
|
|
if submission.success:
|
|
rank = -1
|
|
if daily_puzzle_info is not None:
|
|
rank = len(daily_puzzle_info.success_users)
|
|
return f"🎉 恭喜你答对了!你是今天第 {rank} 个解出来的!"
|
|
if submission.hint_id >= 0 and (
|
|
hint := puzzle.hints.get(submission.hint_id)
|
|
) is not None:
|
|
if hint.is_checkpoint:
|
|
hint_msg = "✨ 恭喜!这是本题的中间答案,加油!"
|
|
else:
|
|
hint_msg = "🤔 答错啦!请检查你的答案。"
|
|
return f"{hint_msg}\n\n提示:{hint.message}"
|
|
return "❌ 答错啦!请检查你的答案。"
|
|
|
|
|
|
def get_daily_report(
|
|
manager: PuzzleManager,
|
|
date: datetime.date,
|
|
) -> str | None:
|
|
"""
|
|
获得某日的提交的报告信息
|
|
"""
|
|
|
|
index_id = manager.daily_puzzle_of_date.get(date)
|
|
if index_id is None:
|
|
return None
|
|
info = manager.daily_puzzle[index_id]
|
|
puzzle = manager.puzzle_data[info.raw_id]
|
|
|
|
msg = f"[KonaPH#{puzzle.index_id}] 「{puzzle.title}」解答报告\n\n"
|
|
if len(info.success_users) == 0:
|
|
msg += "昨日,无人解出此题 😭😭\n\n"
|
|
else:
|
|
msg += f"昨日,共有 {len(info.success_users)} 人解出此题。\n\n"
|
|
msg += "前五名的解答者:\n\n"
|
|
us = [(u, d) for u, d in info.success_users.items()]
|
|
us = sorted(us, key=lambda t: t[1])
|
|
us = us[:5]
|
|
for u, _ in us:
|
|
m = manager.submissions[puzzle.raw_id][u][-1]
|
|
msg += f"- {get_username(u)} 于 {m.time.strftime('%H:%M')}\n"
|
|
msg += "\n"
|
|
msg += f"出题人:{get_username(puzzle.author_id)}"
|
|
return msg
|
|
|
|
|
|
def get_daily_report_v2(manager: PuzzleManager, gid: int | None = None):
|
|
p = manager.get_today_puzzle()
|
|
if p is None:
|
|
return "今天无题"
|
|
msg = "==== 今日答题情况 ====\n\n"
|
|
|
|
subcount = len(functools.reduce(
|
|
lambda x, y: x + y,
|
|
manager.submissions.get(p.raw_id, {}).values(),
|
|
[],
|
|
))
|
|
info = manager.daily_puzzle[p.index_id]
|
|
|
|
msg += (
|
|
f"总体情况:答对 {len(info.success_users)} / "
|
|
f"参与 {len(info.tried_users)} / "
|
|
f"提交 {subcount}\n"
|
|
)
|
|
|
|
success_users = sorted(list(info.success_users.items()), key=lambda v: v[1])
|
|
for u, d in success_users:
|
|
uname = u
|
|
if re.match(r"^\d+$", u):
|
|
uname = get_username(int(u), gid)
|
|
t = d.strftime("%H:%M")
|
|
tries = len(manager.submissions[p.raw_id][u])
|
|
msg += f"\n- {uname} [🎉 {t} 完成 | {tries} 提交]"
|
|
for u in info.tried_users - set(info.success_users.keys()):
|
|
uname = u
|
|
if re.match(r"^\d+$", u):
|
|
uname = get_username(int(u), gid)
|
|
tries = len(manager.submissions[p.raw_id][u])
|
|
checkpoints_touched = len(set((
|
|
s.hint_id for s in manager.submissions[p.raw_id][u]
|
|
if (
|
|
s.hint_id >= 0
|
|
and s.hint_id in p.hints
|
|
and p.hints[s.hint_id].is_checkpoint
|
|
)
|
|
)))
|
|
checkpoint_message = ""
|
|
if checkpoints_touched > 0:
|
|
checkpoint_message = f" | 🚩 {checkpoints_touched} 记录点"
|
|
msg += f"\n- {uname} [💦 {tries} 提交{checkpoint_message}]"
|
|
|
|
return msg
|
|
|
|
|
|
def get_puzzle_info_message(manager: PuzzleManager, puzzle: Puzzle) -> UniMessage[Any]:
|
|
image_manager = get_image_manager()
|
|
|
|
status = "✅ 已准备,待发布" if puzzle.ready and not manager.is_puzzle_published(puzzle.raw_id) else \
|
|
(f"🟢 已发布: #{puzzle.index_id}" if manager.is_puzzle_published(puzzle.raw_id) else "⚙️ 未准备")
|
|
|
|
status_suffix = ""
|
|
if puzzle.raw_id == manager.puzzle_pinned:
|
|
status_suffix += " | 📌 已被管理员置顶"
|
|
|
|
msg = UniMessage.text(
|
|
f"--- 谜题信息 ---\n"
|
|
f"Raw ID: {puzzle.raw_id}\n"
|
|
f"出题者: {get_username(puzzle.author_id)} | {puzzle.author_id}\n"
|
|
f"创建时间: {puzzle.created_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
|
|
f"状态: {status}{status_suffix}\n\n"
|
|
f"标题: {puzzle.title}\n"
|
|
f"Flag: {puzzle.flag}\n\n"
|
|
f"{puzzle.content}"
|
|
)
|
|
|
|
if puzzle.img_name:
|
|
msg = msg.image(raw=image_manager.read_puzzle_image(puzzle.img_name))
|
|
|
|
msg = msg.text(f"\n---------\n使用 `konaph ready {puzzle.raw_id}` 完成编辑")
|
|
|
|
return msg
|
|
|
|
|
|
def get_puzzle_hint_list(puzzle: Puzzle) -> str:
|
|
msg = f"==== {puzzle.title} 提示与中间答案 ====\n"
|
|
if len(puzzle.hints) == 0:
|
|
msg += "\n你没有添加任何中间答案。"
|
|
return msg
|
|
for hint_id, hint in puzzle.hints.items():
|
|
n = {False: "[提示]", True: "[中间答案]"}[hint.is_checkpoint]
|
|
msg += f"\n{n}[{hint_id}] {hint.pattern}"
|
|
msg += f"\n {hint.message}"
|
|
return msg
|