猜成语:还没做更新拼音的功能,即将加入。

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-09 21:38:59 +08:00
parent 0cc59d212b
commit 5fd6fc88b2
7 changed files with 272662 additions and 5682 deletions
@@ -13,6 +13,7 @@ from nonebot.utils import run_sync
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
import json import json
from pypinyin import Style, pinyin
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
require("nonebot_plugin_session") require("nonebot_plugin_session")
@@ -38,12 +39,12 @@ 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,
HANDLE_ANSWER_PHRASES, HANDLE_COMMON_PHRASES,
HANDLE_HARD_ANSWER_PHRASES,
HANDLE_LEGAL_PHRASES, HANDLE_LEGAL_PHRASES,
handle_answer_hard_path, HANDLE_ANSWER_PHRASES,
handle_common_idiom_path,
handle_all_idiom_path,
handle_answer_path, handle_answer_path,
handle_idiom_path,
) )
__plugin_meta__ = PluginMetadata( __plugin_meta__ = PluginMetadata(
@@ -177,7 +178,7 @@ async def _(
set_timeout(matcher, user_id) set_timeout(matcher, user_id)
msg = Text( msg = Text(
f"你有{game.times}次机会猜一个四字成语," "你有{}次机会猜一个四字成语,".format(game.times)
+ ("发送有效成语以参与游戏。" if is_strict else "发送任意四字词语以参与游戏。") + ("发送有效成语以参与游戏。" if is_strict else "发送任意四字词语以参与游戏。")
) + Image(raw=await run_sync(game.draw)()) ) + Image(raw=await run_sync(game.draw)())
await msg.send() await msg.send()
@@ -221,7 +222,7 @@ async def _(matcher: Matcher, user_id: UserId, matched: Dict[str, Any] = RegexDi
if result == GuessResult.WIN if result == GuessResult.WIN
else "很遗憾,没有人猜出来呢" else "很遗憾,没有人猜出来呢"
) )
+ f"\n{game.result}" + "\n{}".format(game.result)
) + Image(raw=await run_sync(game.draw)()) ) + Image(raw=await run_sync(game.draw)())
await msg.send() await msg.send()
@@ -229,7 +230,7 @@ async def _(matcher: Matcher, user_id: UserId, matched: Dict[str, Any] = RegexDi
await matcher.finish("你已经猜过这个成语了呢") await matcher.finish("你已经猜过这个成语了呢")
elif result == GuessResult.ILLEGAL: elif result == GuessResult.ILLEGAL:
await matcher.finish(f"你确定“{idiom}”是个成语吗?") await matcher.finish("你确定“{}”是个成语吗?".format(idiom))
else: else:
await UniMessage.image(raw=await run_sync(game.draw)()).send() await UniMessage.image(raw=await run_sync(game.draw)()).send()
@@ -285,39 +286,40 @@ async def _(
HANDLE_LEGAL_PHRASES.append(idiom) HANDLE_LEGAL_PHRASES.append(idiom)
json.dump( json.dump(
HANDLE_LEGAL_PHRASES, HANDLE_LEGAL_PHRASES,
handle_idiom_path.open("w", encoding="utf-8"), handle_all_idiom_path.open("w", encoding="utf-8"),
ensure_ascii=False, ensure_ascii=False,
indent=4, indent=4,
sort_keys=True, sort_keys=True,
) )
if not hard:
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,
)
if explanation: if explanation:
if hard: HANDLE_ANSWER_PHRASES[idiom] = {
HANDLE_HARD_ANSWER_PHRASES.append( "explanation": explanation,
{"word": idiom, "explanation": explanation} "pinyin": [
) j for i in pinyin(idiom, style=Style.TONE3, v_to_u=True) for j in i
json.dump( ],
HANDLE_HARD_ANSWER_PHRASES, }
handle_answer_hard_path.open("w", encoding="utf-8"), json.dump(
ensure_ascii=False, HANDLE_ANSWER_PHRASES,
indent=4, handle_answer_path.open("w", encoding="utf-8"),
sort_keys=True, ensure_ascii=False,
) indent=4,
else: sort_keys=True,
HANDLE_ANSWER_PHRASES.append({"word": idiom, "explanation": explanation}) )
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(
"新增成功,当前词库总数:{}\n可用普通模式成语:{}\n可用困难模式成语:{}".format( "新增成功,当前词库总数:{}\n可用普通模式成语:{}".format(
len(HANDLE_LEGAL_PHRASES), len(HANDLE_LEGAL_PHRASES),
len(HANDLE_ANSWER_PHRASES), len(HANDLE_COMMON_PHRASES),
len(HANDLE_HARD_ANSWER_PHRASES),
) )
) )
@@ -47,7 +47,7 @@ class Handle:
self.idiom: str = idiom # 成语 self.idiom: str = idiom # 成语
self.explanation: str = explanation # 释义 self.explanation: str = explanation # 释义
self.strict: bool = strict # 是否判断输入词语为成语 self.strict: bool = strict # 是否判断输入词语为成语
self.result = f"【成语】:{idiom}\n【释义】:{explanation}" self.result = "【成语】:{}\n【释义】:{}".format(self.idiom, self.explanation)
self.pinyin: List[Tuple[str, str, str]] = get_pinyin(idiom) # 拼音 self.pinyin: List[Tuple[str, str, str]] = get_pinyin(idiom) # 拼音
self.length = 4 self.length = 4
self.times: int = 10 # 可猜次数 self.times: int = 10 # 可猜次数
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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 from typing import Dict, List, Tuple, Union, Literal, TypedDict
# from watchdog.observers import Observer # from watchdog.observers import Observer
# from watchdog.events import FileSystemEventHandler, FileModifiedEvent # from watchdog.events import FileSystemEventHandler, FileModifiedEvent
@@ -15,20 +15,29 @@ from pypinyin import Style, pinyin
resource_dir = Path(__file__).parent / "resources" resource_dir = Path(__file__).parent / "resources"
fonts_dir = resource_dir / "fonts" fonts_dir = resource_dir / "fonts"
data_dir = resource_dir / "data" data_dir = resource_dir / "data"
handle_idiom_path = data_dir / "idioms.json" handle_common_idiom_path = data_dir / "common_idioms.json"
handle_all_idiom_path = data_dir / "idioms.json"
handle_answer_path = data_dir / "answers.json" handle_answer_path = data_dir / "answers.json"
handle_answer_hard_path = data_dir / "answers_hard.json"
class IdiomEntry(TypedDict):
"""
成语答案类型
"""
explanation: str
pinyin: List[str]
HANDLE_COMMON_PHRASES: List[str] = json.load(
handle_common_idiom_path.open("r", encoding="utf-8")
)
HANDLE_LEGAL_PHRASES: List[str] = json.load( HANDLE_LEGAL_PHRASES: List[str] = json.load(
handle_idiom_path.open("r", encoding="utf-8") handle_all_idiom_path.open("r", encoding="utf-8")
) )
HANDLE_ANSWER_PHRASES: List[Dict[str, str]] = json.load( HANDLE_ANSWER_PHRASES: Dict[str, IdiomEntry] = json.load(
handle_answer_path.open("r", encoding="utf-8") handle_answer_path.open("r", encoding="utf-8")
) )
HANDLE_HARD_ANSWER_PHRASES: List[Dict[str, str]] = json.load(
handle_answer_hard_path.open("r", encoding="utf-8")
)
# class LegalPhrasesModifiedHandler(FileSystemEventHandler): # class LegalPhrasesModifiedHandler(FileSystemEventHandler):
# """ # """
@@ -57,16 +66,17 @@ HANDLE_HARD_ANSWER_PHRASES: List[Dict[str, str]] = json.load(
# event_filter=FileModifiedEvent, # event_filter=FileModifiedEvent,
# ) # )
# 答案转换器
# 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 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( answer = random.choice(HANDLE_LEGAL_PHRASES if is_hard else HANDLE_COMMON_PHRASES)
HANDLE_HARD_ANSWER_PHRASES if is_hard else HANDLE_ANSWER_PHRASES return answer, HANDLE_ANSWER_PHRASES[answer]["explanation"]
)
return answer["word"], answer["explanation"]
# fmt: off # fmt: off
@@ -85,28 +95,53 @@ FINALS = [
# fmt: on # fmt: on
def get_pinyin(idiom: str) -> List[Tuple[str, str, str]]: def split_pinyin(py: str) -> Tuple[str, str, str]:
pys = pinyin(idiom, style=Style.TONE3, v_to_u=True) """
results = [] py: 输入的拼音
for p in pys: return: 返回一个三元组分别表示该拼音的声母韵母声调
py = p[0] """
if py[-1].isdigit():
tone = py[-1] if py[-1].isdigit():
py = py[:-1] tone = py[-1]
else: py = py[:-1]
tone = "" else:
initial = "" tone = ""
for i in INITIALS: initial = ""
if py.startswith(i): for i in INITIALS:
initial = i if py.startswith(i):
break initial = i
final = "" break
for f in FINALS: final = ""
if py.endswith(f): for f in FINALS:
final = f if py.endswith(f):
break final = f
results.append((initial, final, tone)) # 声母,韵母,声调 break
return results return initial, final, tone
def get_pinyin(
idiom: str,
) -> List[Tuple[str, str, str]]:
"""
idiom: 输入的汉字
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]
def save_jpg(frame: IMG) -> BytesIO: def save_jpg(frame: IMG) -> BytesIO: