猜成语:优化代码结构,提升可读性,修复小bug

This commit is contained in:
Eilles
2026-05-10 17:08:50 +08:00
parent d29efcbc9e
commit 226a2a336c
2 changed files with 120 additions and 120 deletions
@@ -4,26 +4,22 @@ from typing import Any, Dict
from typing_extensions import Annotated from typing_extensions import Annotated
import nonebot import nonebot
from nonebot import on_regex, require, on_command from nonebot import on_regex, require
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.params import RegexDict from nonebot.params import RegexDict
from nonebot.plugin import PluginMetadata, inherit_supported_adapters from nonebot.plugin import PluginMetadata, inherit_supported_adapters
from nonebot.rule import to_me from nonebot.rule import to_me
from nonebot.utils import run_sync from nonebot.utils import run_sync
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from nonebot.internal.adapter import Bot
import json
from pypinyin import Style, pinyin
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
require("nonebot_plugin_session") require("nonebot_plugin_session")
from nonebot_plugin_alconna import ( from nonebot_plugin_alconna import (
Alconna, Alconna,
AlconnaQuery,
Image, Image,
Option, Option,
Query,
Text, Text,
UniMessage, UniMessage,
on_alconna, on_alconna,
@@ -33,18 +29,13 @@ from nonebot_plugin_alconna import (
) )
from nonebot_plugin_session import SessionId, SessionIdType from nonebot_plugin_session import SessionId, SessionIdType
from src.utils.base.ly_typing import T_Bot
from .config import Config, handle_config from .config import Config, handle_config
from .data_source import GuessResult, Handle from .data_source import GuessResult, Handle
from .utils import ( from .utils import (
random_idiom, random_idiom,
wordbase_updater,
HANDLE_COMMON_PHRASES, HANDLE_COMMON_PHRASES,
HANDLE_LEGAL_PHRASES, HANDLE_LEGAL_PHRASES,
HANDLE_ANSWER_PHRASES,
handle_common_idiom_path,
handle_all_idiom_path,
handle_answer_path,
) )
__plugin_meta__ = PluginMetadata( __plugin_meta__ = PluginMetadata(
@@ -94,7 +85,7 @@ handle = on_alconna(
Alconna( Alconna(
"handle", "handle",
Option("-s|--strict", default=False, action=store_true), Option("-s|--strict", default=False, action=store_true),
Option("-d|--hard", default=False, action=store_true), Option("-d|--difficult", default=False, action=store_true),
), ),
aliases=("猜成语",), aliases=("猜成语",),
rule=to_me() & game_not_running, rule=to_me() & game_not_running,
@@ -171,7 +162,7 @@ async def _(
): ):
nonebot.logger.info(result.options) nonebot.logger.info(result.options)
is_strict = handle_config.handle_strict_mode or result.options["strict"].value is_strict = handle_config.handle_strict_mode or result.options["strict"].value
idiom, explanation = random_idiom(result.options["hard"].value) idiom, explanation = random_idiom(result.options["difficult"].value)
game = Handle(idiom, explanation, strict=is_strict) game = Handle(idiom, explanation, strict=is_strict)
games[user_id] = game games[user_id] = game
@@ -262,9 +253,6 @@ handle_update_pinyin = on_alconna(
@handle_update_pinyin.handle() @handle_update_pinyin.handle()
async def _( async def _(
result: Arparma, result: Arparma,
matcher: Matcher,
user_id: UserId,
bot: T_Bot,
): ):
if not ( if not (
@@ -283,28 +271,24 @@ async def _(
"未在词库中找到该成语,请使用 `新成语 <成语>` 来添加成语" "未在词库中找到该成语,请使用 `新成语 <成语>` 来添加成语"
) )
HANDLE_ANSWER_PHRASES[idiom]["pinyin"] = pynow = [ _, explanation, pinyin_now = wordbase_updater(
pinyin1, idiom,
pinyin2, explanation=None,
pinyin3, pinyin=[
pinyin4, pinyin1,
] pinyin2,
pinyin3,
json.dump( pinyin4,
HANDLE_ANSWER_PHRASES, ],
handle_answer_path.open("w", encoding="utf-8"), hard=None,
ensure_ascii=False,
indent=4,
sort_keys=True,
) )
await handle_update_idiom.finish( await handle_update_idiom.finish(
"成功修改:{}\n当前词库总数:{}个,普通模式成语:{}\n当前成语信息如下:{}".format( "成功修改:{}\n当前词库总数:{}个,普通模式成语:{}\n当前成语信息如下:{}".format(
idiom, idiom,
len(HANDLE_LEGAL_PHRASES), len(HANDLE_LEGAL_PHRASES),
len(HANDLE_COMMON_PHRASES), len(HANDLE_COMMON_PHRASES),
"\n\t释义:{}\n\t拼音:{}".format( "\n\t释义:{}\n\t拼音:{}".format(explanation, " ".join(pinyin_now)),
HANDLE_ANSWER_PHRASES[idiom]["explanation"], " ".join(pynow)
),
) )
) )
@@ -318,7 +302,7 @@ handle_update_idiom = on_alconna(
args=Args["explanation", str, ""], args=Args["explanation", str, ""],
), ),
Option( Option(
"-d|--hard", "-d|--difficult",
default=False, default=False,
action=store_true, action=store_true,
), ),
@@ -335,76 +319,18 @@ handle_update_idiom = on_alconna(
@handle_update_idiom.handle() @handle_update_idiom.handle()
async def _( async def _(
result: Arparma, result: Arparma,
matcher: Matcher,
user_id: UserId,
bot: T_Bot,
): ):
if not (idiom := result.main_args["idiom"]): if not (idiom := result.main_args["idiom"]):
await handle_update_idiom.finish("用法:新成语 <成语> [-e|--explanation <释义>] [-d|--hard]") await handle_update_idiom.finish(
"用法:新成语 <成语> [-e|--explanation <释义>] [-d|--difficult]"
existance = idiom in HANDLE_LEGAL_PHRASES
try:
explanation = result.options["explanation"].args["explanation"] or None
except:
explanation = None
if existance and (not explanation):
# 这个判断的顺序必须高于下面的判断语句
explanation = HANDLE_ANSWER_PHRASES[idiom]["explanation"]
if not explanation:
explanation = "未提供该成语的解释说明"
if not existance:
HANDLE_LEGAL_PHRASES.append(idiom)
json.dump(
HANDLE_LEGAL_PHRASES,
handle_all_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
) )
if hard := result.options["hard"].value:
if idiom in HANDLE_COMMON_PHRASES:
HANDLE_COMMON_PHRASES.remove(idiom)
json.dump(
HANDLE_COMMON_PHRASES,
handle_common_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
)
else:
if idiom not in HANDLE_COMMON_PHRASES:
HANDLE_COMMON_PHRASES.append(idiom)
json.dump(
HANDLE_COMMON_PHRASES,
handle_common_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
)
HANDLE_ANSWER_PHRASES[idiom] = { existance, explanation, pinyin_now = wordbase_updater(
"explanation": explanation, idiom,
"pinyin": ( explanation=(result.options["explanation"].args["explanation"] or None),
pynow := ( pinyin=None,
HANDLE_ANSWER_PHRASES[idiom]["pinyin"].copy() hard=(hard := result.options["difficult"].value),
if existance
else [
j for i in pinyin(idiom, style=Style.TONE3, v_to_u=True) for j in i
]
)
),
}
json.dump(
HANDLE_ANSWER_PHRASES,
handle_answer_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
) )
await handle_update_idiom.finish( await handle_update_idiom.finish(
@@ -414,7 +340,7 @@ async def _(
idiom, idiom,
len(HANDLE_LEGAL_PHRASES), len(HANDLE_LEGAL_PHRASES),
len(HANDLE_COMMON_PHRASES), len(HANDLE_COMMON_PHRASES),
"\n\t释义:{}\n\t拼音:{}".format(explanation, " ".join(pynow)), "\n\t释义:{}\n\t拼音:{}".format(explanation, " ".join(pinyin_now)),
) )
) )
@@ -445,9 +371,8 @@ handle_answer = on_alconna(
@handle_answer.handle() @handle_answer.handle()
async def _( async def _(
result: Arparma, result: Arparma,
matcher: Matcher,
user_id: UserId, user_id: UserId,
bot: T_Bot, bot: Bot,
): ):
if result.options["list"].value: if result.options["list"].value:
@@ -2,7 +2,7 @@ import json
import random import random
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path
from typing import Dict, List, Tuple, Union, Literal, TypedDict from typing import Dict, List, Tuple, TypedDict, Optional
# from watchdog.observers import Observer # from watchdog.observers import Observer
# from watchdog.events import FileSystemEventHandler, FileModifiedEvent # from watchdog.events import FileSystemEventHandler, FileModifiedEvent
@@ -10,7 +10,7 @@ from typing import Dict, List, Tuple, Union, Literal, TypedDict
from PIL import ImageFont from PIL import ImageFont
from PIL.Image import Image as IMG from PIL.Image import Image as IMG
from PIL.ImageFont import FreeTypeFont from PIL.ImageFont import FreeTypeFont
from pypinyin import Style, pinyin from pypinyin import Style, pinyin as py_get_pinyin
resource_dir = Path(__file__).parent / "resources" resource_dir = Path(__file__).parent / "resources"
fonts_dir = resource_dir / "fonts" fonts_dir = resource_dir / "fonts"
@@ -70,10 +70,88 @@ HANDLE_ANSWER_PHRASES: Dict[str, IdiomEntry] = json.load(
# json.dump({ i["word"]:{"explanation":i["explanation"], "pinyin":(lambda x : [i for j in pinyin(x, style=Style.TONE3, v_to_u=True) for i in j])(i["word"])} for i in json.load(open("answers_hard-old.json",encoding="utf-8"))},open("answers.json", "w",encoding="utf-8"), ensure_ascii=False, indent=4) # json.dump({ i["word"]:{"explanation":i["explanation"], "pinyin":(lambda x : [i for j in pinyin(x, style=Style.TONE3, v_to_u=True) for i in j])(i["word"])} for i in json.load(open("answers_hard-old.json",encoding="utf-8"))},open("answers.json", "w",encoding="utf-8"), ensure_ascii=False, indent=4)
def wordbase_updater(
idiom: str,
explanation: Optional[str] = None,
pinyin: Optional[List[str]] = None,
hard: Optional[bool] = None,
) -> Tuple[bool, str, List[str]]:
"""
idiom: 需要更新或新增的成语词条
explanation: 词条的释义,若 `None` 且在词库中不存在,则默认为“未提供该成语的解释说明”
pinyin: 词条的拼音,若 `None` 则默认求出拼音
hard: 是否为难词,若 `None` 则不对难易词库修改
return: 是否为新增成语,成语释义,词条的拼音
"""
if (not idiom) or (len(idiom) != 4):
raise ValueError("不可以非四字成语载入词库")
if (existance := (idiom in HANDLE_LEGAL_PHRASES)) and (explanation is None):
# 这个判断的顺序必须高于下面的判断语句
explanation = HANDLE_ANSWER_PHRASES[idiom]["explanation"]
if explanation is None:
explanation = "未提供该成语的解释说明"
if not existance:
HANDLE_LEGAL_PHRASES.append(idiom)
json.dump(
HANDLE_LEGAL_PHRASES,
handle_all_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
)
else:
pinyin = pinyin or HANDLE_ANSWER_PHRASES[idiom]["pinyin"].copy()
if hard:
if idiom in HANDLE_COMMON_PHRASES:
HANDLE_COMMON_PHRASES.remove(idiom)
json.dump(
HANDLE_COMMON_PHRASES,
handle_common_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
)
else:
if (idiom not in HANDLE_COMMON_PHRASES) and (hard is not None):
HANDLE_COMMON_PHRASES.append(idiom)
json.dump(
HANDLE_COMMON_PHRASES,
handle_common_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
)
HANDLE_ANSWER_PHRASES[idiom] = {
"explanation": explanation,
"pinyin": (
pinyin := (
pinyin
or [
j
for i in py_get_pinyin(idiom, style=Style.TONE3, v_to_u=True)
for j in i
]
)
),
}
json.dump(
HANDLE_ANSWER_PHRASES,
handle_answer_path.open("w", encoding="utf-8"),
ensure_ascii=False,
indent=4,
sort_keys=True,
)
return not existance, explanation, pinyin
def legal_idiom(word: str) -> bool: def legal_idiom(word: str) -> bool:
return word in HANDLE_LEGAL_PHRASES return word in HANDLE_LEGAL_PHRASES
def random_idiom(is_hard: bool = False) -> Tuple[str, str]: def random_idiom(is_hard: bool = False) -> Tuple[str, str]:
answer = random.choice(HANDLE_LEGAL_PHRASES if is_hard else HANDLE_COMMON_PHRASES) answer = random.choice(HANDLE_LEGAL_PHRASES if is_hard else HANDLE_COMMON_PHRASES)
return answer, HANDLE_ANSWER_PHRASES[answer]["explanation"] return answer, HANDLE_ANSWER_PHRASES[answer]["explanation"]
@@ -126,22 +204,19 @@ def get_pinyin(
idiom: 输入的汉字 idiom: 输入的汉字
return: 返回一个元组,每个元素是一个三元组,分别表示该汉字的声母,韵母,声调 return: 返回一个元组,每个元素是一个三元组,分别表示该汉字的声母,韵母,声调
""" """
if idiom_entry := HANDLE_ANSWER_PHRASES.get(idiom):
pinyin_per_char = idiom_entry["pinyin"]
if not pinyin_per_char:
pinyin_per_char = [
j for i in pinyin(idiom, style=Style.TONE3, v_to_u=True) for j in i
]
idiom_entry["pinyin"] = pinyin_per_char.copy()
handle_answer_path.open("w", encoding="utf-8").write(
json.dumps(HANDLE_ANSWER_PHRASES, ensure_ascii=False, indent=4)
)
else:
pinyin_per_char = [
j for i in pinyin(idiom, style=Style.TONE3, v_to_u=True) for j in i
]
return [split_pinyin(py) for py in pinyin_per_char] return [
split_pinyin(py)
for py in (
wordbase_updater(idiom, explanation=None, pinyin=None, hard=None)[2]
if HANDLE_ANSWER_PHRASES.get(idiom, None)
else [
j
for i in py_get_pinyin(idiom, style=Style.TONE3, v_to_u=True)
for j in i
]
)
]
def save_jpg(frame: IMG) -> BytesIO: def save_jpg(frame: IMG) -> BytesIO: