From 770d7567fbebb16791d712f98974149a6d67fbb4 Mon Sep 17 00:00:00 2001 From: MixBadGun <1059129006@qq.com> Date: Tue, 16 Dec 2025 16:13:55 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=B2=E9=AA=A8=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/oracle | 2 +- konabot/plugins/idiomgame/__init__.py | 20 ++++++-- konabot/plugins/oracle_game/__init__.py | 40 ++++++++++++---- konabot/plugins/oracle_game/find_path.py | 59 ++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 konabot/plugins/oracle_game/find_path.py diff --git a/assets/oracle b/assets/oracle index 29eea55..5a3ef41 160000 --- a/assets/oracle +++ b/assets/oracle @@ -1 +1 @@ -Subproject commit 29eea55632f7a8a51ac0c758798dfbd1a23676f3 +Subproject commit 5a3ef41d618d87ff0ab2cb722f3fb1d79ac74502 diff --git a/konabot/plugins/idiomgame/__init__.py b/konabot/plugins/idiomgame/__init__.py index 36911d8..9eca7a0 100644 --- a/konabot/plugins/idiomgame/__init__.py +++ b/konabot/plugins/idiomgame/__init__.py @@ -1,11 +1,12 @@ import asyncio as asynkio import datetime +from io import BytesIO import json import secrets from enum import Enum from pathlib import Path from typing import Optional - +from PIL import Image from loguru import logger from nonebot import on_message import nonebot @@ -617,14 +618,23 @@ async def _(event: BaseEvent, target: DepLongTaskTarget): # 打开好吧狗本地文件 with open(ASSETS_PATH / "img" / "dog" / "haoba_dog.jpg", "rb") as f: img_data = f.read() + # 把好吧狗变成 GIF 格式以缩小尺寸 + img_data = await convert_image_to_gif(img_data) await evt.send(await UniMessage().image(raw=img_data).export()) await end_game(event, group_id) else: - await evt.send( - await UniMessage().text("当前没有成语接龙游戏在进行中!").export() - ) + # await evt.send( + # await UniMessage().text("当前没有成语接龙游戏在进行中!").export() + # ) + return +async def convert_image_to_gif(image_data: bytes) -> bytes: + with Image.open(BytesIO(image_data)) as img: + with BytesIO() as output: + img.save(output, format="GIF") + return output.getvalue() + # 跳过 evt = on_alconna( Alconna("跳过成语"), use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=True @@ -642,6 +652,8 @@ async def _(target: DepLongTaskTarget): # 发送哈哈狗图片 with open(ASSETS_PATH / "img" / "dog" / "haha_dog.jpg", "rb") as f: img_data = f.read() + # 把哈哈狗变成 GIF 格式以缩小尺寸 + img_data = await convert_image_to_gif(img_data) await evt.send(await UniMessage().image(raw=img_data).export()) await evt.send(await UniMessage().text(f"你们太菜了,全部扣100分!明明还可以接「{avaliable_idiom}」的!").export()) idiom = await instance.skip_idiom(-100) diff --git a/konabot/plugins/oracle_game/__init__.py b/konabot/plugins/oracle_game/__init__.py index 3101ed7..0a59982 100644 --- a/konabot/plugins/oracle_game/__init__.py +++ b/konabot/plugins/oracle_game/__init__.py @@ -4,6 +4,8 @@ import json import secrets import csv import zipfile +from PIL import Image +from io import BytesIO from enum import Enum from pathlib import Path from typing import Optional @@ -126,12 +128,12 @@ class oracleGame: def get_oracle_image(self) -> bytes: IMAGE_PATH = ASSETS_PATH / "oracle" / "image" - with open(IMAGE_PATH / self.current_oracle_id / self.current_oracle_id / f"{self.current_oracle_id}.png", "rb") as f: + with open(IMAGE_PATH / self.ALL_ORACLES[self.current_oracle_id]["image"], "rb") as f: img_data = f.read() return img_data def get_oracle_name(self) -> str: - return self.ALL_ORACLES.get(self.current_oracle_id, "?")[0] + return self.ALL_ORACLES.get(self.current_oracle_id, {}).get("oracle", "?")[0] @staticmethod async def random_oracle() -> str: @@ -205,14 +207,19 @@ class oracleGame: async def _verify_oracle(self, oracle: str, user_id: str) -> list[TryVerifyState]: state = [] - if oracle not in self.ALL_ORACLES[self.current_oracle_id]: + if oracle.strip() not in self.ALL_ORACLES[self.current_oracle_id].get("oracle", ""): + return [TryVerifyState.NOT_ORACLE] + if oracle.strip() == "": return [TryVerifyState.NOT_ORACLE] # 甲骨文合法,更新状态 + state.append(TryVerifyState.VERIFIED) self.add_score(user_id, 1) # 加 1 分 self.remain_rounds -= 1 if self.remain_rounds <= 0: self.now_playing = False state.append(TryVerifyState.GAME_END) + else: + await self._skip_oracle_async() return state def get_user_score(self, user_id: str) -> float: @@ -248,7 +255,11 @@ class oracleGame: for row in reader: char = row["子字头"].strip() oracle = row["释文"].strip() - cls.ALL_ORACLES[char] = oracle + img_path = row.get("路径", "").strip() + cls.ALL_ORACLES[char] = { + "oracle": oracle, + "image": img_path, + } logger.info(f"加载甲骨文字典,共计 {len(cls.ALL_ORACLES)} 条记录") @@ -377,14 +388,22 @@ async def _(event: BaseEvent, target: DepLongTaskTarget): # 打开好吧狗本地文件 with open(ASSETS_PATH / "img" / "dog" / "haoba_dog.jpg", "rb") as f: img_data = f.read() + # 把好吧狗变成 GIF 格式以缩小尺寸 + img_data = await convert_image_to_gif(img_data) await evt.send(await UniMessage().image(raw=img_data).export()) await end_game(event, group_id) else: - await evt.send( - await UniMessage().text("当前没有甲骨文游戏在进行中!").export() - ) + # await evt.send( + # await UniMessage().text("当前没有甲骨文游戏在进行中!").export() + # ) + return +async def convert_image_to_gif(image_data: bytes) -> bytes: + with Image.open(BytesIO(image_data)) as img: + with BytesIO() as output: + img.save(output, format="GIF") + return output.getvalue() # 跳过 evt = on_alconna( Alconna("跳过甲骨文"), use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=True @@ -401,6 +420,8 @@ async def _(target: DepLongTaskTarget): # 发送哈哈狗图片 with open(ASSETS_PATH / "img" / "dog" / "haha_dog.jpg", "rb") as f: img_data = f.read() + # 把哈哈狗变成 GIF 格式以缩小尺寸 + img_data = await convert_image_to_gif(img_data) oracle = instance.get_oracle_name() await evt.send(await UniMessage().image(raw=img_data).export()) await evt.send(await UniMessage().text(f"你们太菜了,全部扣100分!这个甲骨文是「{oracle}」!").export()) @@ -438,10 +459,11 @@ async def _(event: BaseEvent, msg: UniMsg, target: DepLongTaskTarget): state = await instance.try_verify_oracle(user_oracle, user_id) if TryVerifyState.NOT_ORACLE in state: return - if TryVerifyState.VERIFIED: + if TryVerifyState.VERIFIED in state: await evt.send( await UniMessage() - .text(f"{user_name} 答对了!获得 1 分!") + .at(user_id) + .text(" 答对了!获得 1 分!") .export() ) if TryVerifyState.GAME_END in state: diff --git a/konabot/plugins/oracle_game/find_path.py b/konabot/plugins/oracle_game/find_path.py new file mode 100644 index 0000000..5aff67b --- /dev/null +++ b/konabot/plugins/oracle_game/find_path.py @@ -0,0 +1,59 @@ +import csv +import os +import sys + +from loguru import logger + +# 获取当前文件所在目录 +current_dir = os.path.dirname(os.path.abspath(__file__)) +# 向上两级到 konabot 目录 +konabot_dir = os.path.abspath(os.path.join(current_dir, '../../../')) + +if konabot_dir not in sys.path: + sys.path.insert(0, konabot_dir) + +from konabot.common.path import ASSETS_PATH + + +ORACLE_PATH = ASSETS_PATH / "oracle" + +final_zi_dict = {} +with open(ORACLE_PATH / "zi_dict.csv", "r", encoding="utf-8-sig") as f: + reader = csv.DictReader(f) + for row in reader: + logger.info(f"Progress: {reader.line_num}") + # 找到子字头字段,并找到对应的图像路径 + char = row["子字头"].strip() + # 寻找路径 + image_path = ORACLE_PATH / "image" + # 遍历所有子目录,寻找对应的图片文件 + found_image = None + for subdir in image_path.iterdir(): + if subdir.is_dir(): + candidate = subdir / char + if candidate.exists(): + # 寻找该目录下有没有以 char 命名的图片文件,没有就选第一个图片文件 + if (candidate / f"{char}.png").exists(): + found_image = candidate / f"{char}.png" + break + else: + for file in candidate.iterdir(): + if file.suffix.lower() in [".png", ".jpg", ".jpeg", ".gif", ".bmp"]: + found_image = file + break + if found_image is not None: + # 提取相对路径 + found_image = found_image.relative_to(ORACLE_PATH / "image") + # 反斜杠改正为斜杠 + found_image = found_image.as_posix() + # 更新行数据 + row.update({"路径": str(found_image)}) + final_zi_dict[char] = row + +# 将最终的字典写入新的 CSV 文件 +with open(ORACLE_PATH / "zi_dict_with_images.csv", "w", encoding="utf-8-sig", newline="") as f: + fieldnames = list(final_zi_dict[next(iter(final_zi_dict))].keys()) + writer = csv.DictWriter(f, fieldnames=fieldnames) + writer.writeheader() + for char, data in final_zi_dict.items(): + writer.writerow(data) \ No newline at end of file