From 0acffea86d87f30a069da61281ba77894f853154 Mon Sep 17 00:00:00 2001 From: passthem Date: Sun, 26 Oct 2025 12:45:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8E=92=E8=A1=8C=E6=A6=9C?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=20UX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- konabot/common/username.py | 54 +++++++++++++++++++ konabot/plugins/kona_ph/__init__.py | 49 +++++++++++++++++ konabot/plugins/kona_ph/core/storage.py | 7 +-- .../plugins/{auto_accept.py => routine.py} | 15 ++++++ 4 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 konabot/common/username.py rename konabot/plugins/{auto_accept.py => routine.py} (66%) diff --git a/konabot/common/username.py b/konabot/common/username.py new file mode 100644 index 0000000..c5209e4 --- /dev/null +++ b/konabot/common/username.py @@ -0,0 +1,54 @@ +import re +import nonebot + +from nonebot.adapters.onebot.v11 import Bot as OBBot + + +class UsernameManager: + grouped_data: dict[int, dict[int, str]] + individual_data: dict[int, str] + + def __init__(self) -> None: + self.grouped_data = {} + self.individual_data = {} + + async def update(self): + for bot in nonebot.get_bots().values(): + if isinstance(bot, OBBot): + for user in await bot.get_friend_list(): + uid = user["user_id"] + nickname = user["nickname"] + self.individual_data[uid] = nickname + for group in await bot.get_group_list(): + gid = group["group_id"] + for member in await bot.get_group_member_list(group_id=gid): + uid = member["user_id"] + card = member.get("card", "") + nickname = member.get("nickname", "") + if card: + self.grouped_data.setdefault(gid, {})[uid] = card + if nickname: + self.individual_data[uid] = nickname + + def get(self, qqid: int, groupid: int | None = None) -> str: + if groupid is not None and groupid in self.grouped_data: + n = self.grouped_data[groupid].get(qqid) + if n is not None: + return n + if qqid in self.individual_data: + return self.individual_data[qqid] + return str(qqid) + + +manager = UsernameManager() + +def get_username(qqid: int | str, group: int | str | None = None): + if isinstance(group, str): + group = None if not re.match(r"^\d+$", group) else int(group) + if isinstance(qqid, str): + if re.match(r"^\d+$", qqid): + qqid = int(qqid) + else: + return qqid + return manager.get(qqid, group) + diff --git a/konabot/plugins/kona_ph/__init__.py b/konabot/plugins/kona_ph/__init__.py index f3e4a9f..8b53ea6 100644 --- a/konabot/plugins/kona_ph/__init__.py +++ b/konabot/plugins/kona_ph/__init__.py @@ -1,7 +1,10 @@ +from functools import reduce from math import ceil +import re from loguru import logger from nonebot_plugin_alconna import Alconna, Args, UniMessage, on_alconna from konabot.common.nb.qq_broadcast import qq_broadcast +from konabot.common.username import get_username from konabot.plugins.kona_ph.core.storage import get_today_date from konabot.plugins.kona_ph.manager import PUZZLE_PAGE_SIZE, create_admin_commands, config, puzzle_manager from konabot.common.longtask import DepLongTaskTarget @@ -45,6 +48,52 @@ async def _(target: DepLongTaskTarget): await target.send_message(p.get_unimessage()) +cmd_query_submission = on_alconna(Alconna( + "今日答题情况" +), rule=is_play_group) + +@cmd_query_submission.handle() +async def _(target: DepLongTaskTarget): + async with puzzle_manager() as manager: + p = manager.get_today_puzzle() + if p is None: + return await target.send_message("今天无题") + msg = UniMessage.text("==== 今日答题情况 ====\n\n") + + subcount = len(reduce( + lambda x, y: x + y, + manager.submissions.get(p.raw_id, {}).values(), + [], + )) + info = manager.daily_puzzle[p.index_id] + + msg = msg.text( + 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]) + gid = None + if re.match(r"^\d+$", target.channel_id): + gid = int(target.channel_id) + 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 = msg.text(f"\n- {uname} [Solved at {t} in {tries} times]") + 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]) + msg = msg.text(f"\n- {uname} [Unsolved in {tries} times]") + + await target.send_message(msg) + + cmd_history = on_alconna(Alconna( "历史题目", Args["page?", int], diff --git a/konabot/plugins/kona_ph/core/storage.py b/konabot/plugins/kona_ph/core/storage.py index 467e546..dd5a1fe 100644 --- a/konabot/plugins/kona_ph/core/storage.py +++ b/konabot/plugins/kona_ph/core/storage.py @@ -12,6 +12,7 @@ from nonebot_plugin_alconna import UniMessage from pydantic import BaseModel, Field, ValidationError from konabot.common.path import DATA_PATH +from konabot.common.username import get_username KONAPH_BASE = DATA_PATH / "KonaPH" @@ -49,7 +50,7 @@ class Puzzle(BaseModel): if self.img_name: result = result.text("\n\n").image(raw=self.get_image_path().read_bytes()) - result = result.text("\n\n出题者:").at(self.author_id) + result = result.text(f"\n\n出题者:{get_username(self.author_id)}") result = result.text("\n\n输入「提交答案 答案」来提交你的解答") return result @@ -294,9 +295,9 @@ class PuzzleManager(BaseModel): us = us[:5] for u, _ in us: m = self.submissions[puzzle.raw_id][u][-1] - message = message.text("- ").at(u).text(f" 于 {m.time.strftime('%H:%M')}") + message = message.text(f"- {get_username(u)} 于 {m.time.strftime('%H:%M')}") - message = message.text("\n\n出题者:").at(puzzle.author_id) + message = message.text(f"\n\n出题者:{get_username(puzzle.author_id)}") return message diff --git a/konabot/plugins/auto_accept.py b/konabot/plugins/routine.py similarity index 66% rename from konabot/plugins/auto_accept.py rename to konabot/plugins/routine.py index 3283f03..5305435 100644 --- a/konabot/plugins/auto_accept.py +++ b/konabot/plugins/routine.py @@ -4,10 +4,13 @@ from typing import cast from loguru import logger from nonebot import get_bot, on_request +import nonebot from nonebot.adapters.onebot.v11.event import FriendRequestEvent from nonebot.adapters.onebot.v11.bot import Bot as OnebotBot +from nonebot_plugin_apscheduler import scheduler from konabot.common.nb.is_admin import cfg as adminConfig +from konabot.common.username import manager add_request = on_request() @@ -23,3 +26,15 @@ async def _(req: FriendRequestEvent): await req.approve(bot) logger.info(f"已经自动同意 {req.user_id} 的好友请求") +@scheduler.scheduled_job("cron", minute="*/5") +async def _(): + logger.info("尝试更新群成员信息") + await manager.update() + +driver = nonebot.get_driver() + +@driver.on_bot_connect +async def _(): + logger.info("有 Bot 连接,5 秒后试着更新群成员信息") + await asyncio.sleep(5) + await manager.update()