我拿 AI 改坏枪代码!
This commit is contained in:
@ -8,6 +8,7 @@ from typing import Optional
|
||||
|
||||
from loguru import logger
|
||||
from nonebot import on_message
|
||||
import nonebot
|
||||
from nonebot.adapters import Event as BaseEvent
|
||||
from nonebot.adapters.discord.event import MessageEvent as DiscordMessageEvent
|
||||
from nonebot_plugin_alconna import (
|
||||
@ -32,6 +33,9 @@ DATA_FILE_PATH = (
|
||||
DATA_DIR / "idiom_banned.json"
|
||||
)
|
||||
|
||||
# 创建全局数据库管理器实例
|
||||
db_manager = DatabaseManager()
|
||||
|
||||
def load_banned_ids() -> list[str]:
|
||||
if not DATA_FILE_PATH.exists():
|
||||
return []
|
||||
@ -61,6 +65,15 @@ def remove_banned_id(group_id: str):
|
||||
DATA_FILE_PATH.write_text(json.dumps(banned_ids, ensure_ascii=False, indent=4), "utf-8")
|
||||
|
||||
|
||||
driver = nonebot.get_driver()
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def register_startup_hook():
|
||||
"""注册启动时需要执行的函数"""
|
||||
await IdiomGame.init_lexicon()
|
||||
|
||||
|
||||
class TryStartState(Enum):
|
||||
STARTED = 0
|
||||
ALREADY_PLAYING = 1
|
||||
@ -98,7 +111,7 @@ class IdiomGameLLM:
|
||||
@classmethod
|
||||
async def storage_idiom(cls, idiom: str):
|
||||
# 将 idiom 存入数据库
|
||||
DatabaseManager.execute_by_sql_file(
|
||||
await db_manager.execute_by_sql_file(
|
||||
ROOT_PATH / "sql" / "insert_custom_word.sql",
|
||||
(idiom,)
|
||||
)
|
||||
@ -130,11 +143,11 @@ class IdiomGame:
|
||||
IdiomGame.INSTANCE_LIST[group_id] = self
|
||||
|
||||
@classmethod
|
||||
def append_into_word_list(cls, word: str):
|
||||
async def append_into_word_list(cls, word: str):
|
||||
'''
|
||||
将一个新词加入到词语列表中
|
||||
'''
|
||||
DatabaseManager.execute_by_sql_file(
|
||||
await db_manager.execute_by_sql_file(
|
||||
ROOT_PATH / "sql" / "insert_custom_word.sql",
|
||||
(word,)
|
||||
)
|
||||
@ -149,26 +162,27 @@ class IdiomGame:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def random_idiom() -> str:
|
||||
return DatabaseManager.query_by_sql_file(
|
||||
async def random_idiom() -> str:
|
||||
result = await db_manager.query_by_sql_file(
|
||||
ROOT_PATH / "sql" / "random_choose_idiom.sql"
|
||||
)[0]["idiom"]
|
||||
)
|
||||
return result[0]["idiom"]
|
||||
|
||||
def choose_start_idiom(self) -> str:
|
||||
async def choose_start_idiom(self) -> str:
|
||||
"""
|
||||
随机选择一个成语作为起始成语
|
||||
"""
|
||||
self.last_idiom = IdiomGame.random_idiom()
|
||||
self.last_idiom = await IdiomGame.random_idiom()
|
||||
self.last_char = self.last_idiom[-1]
|
||||
if not self.is_nextable(self.last_char):
|
||||
self.choose_start_idiom()
|
||||
if not await self.is_nextable(self.last_char):
|
||||
await self.choose_start_idiom()
|
||||
else:
|
||||
self.add_history_idiom(self.last_idiom, new_chain=True)
|
||||
return self.last_idiom
|
||||
|
||||
@classmethod
|
||||
def try_start_game(cls, group_id: str, force: bool = False) -> TryStartState:
|
||||
cls.init_lexicon()
|
||||
async def try_start_game(cls, group_id: str, force: bool = False) -> TryStartState:
|
||||
await cls.init_lexicon()
|
||||
if not cls.INSTANCE_LIST.get(group_id):
|
||||
cls(group_id)
|
||||
instance = cls.INSTANCE_LIST[group_id]
|
||||
@ -179,10 +193,10 @@ class IdiomGame:
|
||||
instance.now_playing = True
|
||||
return TryStartState.STARTED
|
||||
|
||||
def start_game(self, rounds: int = 100):
|
||||
async def start_game(self, rounds: int = 100):
|
||||
self.now_playing = True
|
||||
self.remain_rounds = rounds
|
||||
self.choose_start_idiom()
|
||||
await self.choose_start_idiom()
|
||||
|
||||
@classmethod
|
||||
def try_stop_game(cls, group_id: str) -> TryStopState:
|
||||
@ -212,20 +226,20 @@ class IdiomGame:
|
||||
跳过当前成语,选择下一个成语
|
||||
"""
|
||||
async with self.lock:
|
||||
self._skip_idiom_async()
|
||||
await self._skip_idiom_async()
|
||||
self.add_buff_score(buff_score)
|
||||
return self.last_idiom
|
||||
|
||||
def _skip_idiom_async(self) -> str:
|
||||
self.last_idiom = IdiomGame.random_idiom()
|
||||
async def _skip_idiom_async(self) -> str:
|
||||
self.last_idiom = await IdiomGame.random_idiom()
|
||||
self.last_char = self.last_idiom[-1]
|
||||
if not self.is_nextable(self.last_char):
|
||||
self._skip_idiom_async()
|
||||
if not await self.is_nextable(self.last_char):
|
||||
await self._skip_idiom_async()
|
||||
else:
|
||||
self.add_history_idiom(self.last_idiom, new_chain=True)
|
||||
return self.last_idiom
|
||||
|
||||
async def try_verify_idiom(self, idiom: str, user_id: str) -> TryVerifyState:
|
||||
async def try_verify_idiom(self, idiom: str, user_id: str) -> list[TryVerifyState]:
|
||||
"""
|
||||
用户发送成语
|
||||
"""
|
||||
@ -233,14 +247,15 @@ class IdiomGame:
|
||||
state = await self._verify_idiom(idiom, user_id)
|
||||
return state
|
||||
|
||||
def is_nextable(self, last_char: str) -> bool:
|
||||
async def is_nextable(self, last_char: str) -> bool:
|
||||
"""
|
||||
判断是否有成语可以接
|
||||
"""
|
||||
return DatabaseManager.query_by_sql_file(
|
||||
result = await db_manager.query_by_sql_file(
|
||||
ROOT_PATH / "sql" / "is_nextable.sql",
|
||||
(last_char,)
|
||||
)[0]["DEED"] == 1
|
||||
)
|
||||
return result[0]["DEED"] == 1
|
||||
|
||||
def add_already_idiom(self, idiom: str):
|
||||
if idiom in self.already_idioms:
|
||||
@ -272,11 +287,12 @@ class IdiomGame:
|
||||
state.append(TryVerifyState.WRONG_FIRST_CHAR)
|
||||
return state
|
||||
# 成语是否存在
|
||||
result = DatabaseManager.query_by_sql_file(
|
||||
result = await db_manager.query_by_sql_file(
|
||||
ROOT_PATH / "sql" / "query_idiom.sql",
|
||||
(idiom, idiom, idiom)
|
||||
)[0]["status"]
|
||||
if result == -1:
|
||||
)
|
||||
status_result = result[0]["status"]
|
||||
if status_result == -1:
|
||||
logger.info(f"用户 {user_id} 发送了未知词语 {idiom},正在使用 LLM 进行验证")
|
||||
try:
|
||||
if not await IdiomGameLLM.verify_idiom_with_llm(idiom):
|
||||
@ -298,16 +314,16 @@ class IdiomGame:
|
||||
self.last_idiom = idiom
|
||||
self.last_char = idiom[-1]
|
||||
self.add_score(user_id, 1 * score_k) # 先加 1 分
|
||||
if result == 1:
|
||||
if status_result == 1:
|
||||
state.append(TryVerifyState.VERIFIED_AND_REAL)
|
||||
self.add_score(user_id, 4 * score_k) # 再加 4 分
|
||||
self.remain_rounds -= 1
|
||||
if self.remain_rounds <= 0:
|
||||
self.now_playing = False
|
||||
state.append(TryVerifyState.GAME_END)
|
||||
if not self.is_nextable(self.last_char):
|
||||
if not await self.is_nextable(self.last_char):
|
||||
# 没有成语可以接了,自动跳过
|
||||
self._skip_idiom_async()
|
||||
await self._skip_idiom_async()
|
||||
self.add_buff_score(-100)
|
||||
state.append(TryVerifyState.BUT_NO_NEXT)
|
||||
return state
|
||||
@ -334,9 +350,9 @@ class IdiomGame:
|
||||
return self.last_char
|
||||
|
||||
@classmethod
|
||||
def random_idiom_starting_with(cls, first_char: str) -> Optional[str]:
|
||||
cls.init_lexicon()
|
||||
result = DatabaseManager.query_by_sql_file(
|
||||
async def random_idiom_starting_with(cls, first_char: str) -> Optional[str]:
|
||||
await cls.init_lexicon()
|
||||
result = await db_manager.query_by_sql_file(
|
||||
ROOT_PATH / "sql" / "query_idiom_start_with.sql",
|
||||
(first_char,)
|
||||
)
|
||||
@ -345,10 +361,10 @@ class IdiomGame:
|
||||
return result[0]["idiom"]
|
||||
|
||||
@classmethod
|
||||
def init_lexicon(cls):
|
||||
async def init_lexicon(cls):
|
||||
if cls.__inited:
|
||||
return
|
||||
DatabaseManager.execute_by_sql_file(
|
||||
await db_manager.execute_by_sql_file(
|
||||
ROOT_PATH / "sql" / "create_table.sql"
|
||||
) # 确保数据库初始化
|
||||
cls.__inited = True
|
||||
@ -417,7 +433,7 @@ class IdiomGame:
|
||||
ALL_IDIOMS = [idiom["word"] for idiom in ALL_IDIOMS_INFOS] + THUOCL_IDIOMS
|
||||
ALL_IDIOMS = list(set(ALL_IDIOMS)) # 去重
|
||||
# 批量插入数据库
|
||||
DatabaseManager.execute_many_values_by_sql_file(
|
||||
await db_manager.execute_many_values_by_sql_file(
|
||||
ROOT_PATH / "sql" / "insert_idiom.sql",
|
||||
[(idiom,) for idiom in ALL_IDIOMS]
|
||||
)
|
||||
@ -430,13 +446,13 @@ class IdiomGame:
|
||||
+ COMMON_WORDS
|
||||
)
|
||||
# 插入数据库
|
||||
DatabaseManager.execute_many_values_by_sql_file(
|
||||
await db_manager.execute_many_values_by_sql_file(
|
||||
ROOT_PATH / "sql" / "insert_word.sql",
|
||||
[(word,) for word in ALL_WORDS]
|
||||
)
|
||||
|
||||
# 自定义词语 LOCAL_LLM_WORDS 插入数据库,兼容用
|
||||
DatabaseManager.execute_many_values_by_sql_file(
|
||||
await db_manager.execute_many_values_by_sql_file(
|
||||
ROOT_PATH / "sql" / "insert_custom_word.sql",
|
||||
[(word,) for word in LOCAL_LLM_WORDS]
|
||||
)
|
||||
@ -483,7 +499,7 @@ async def play_game(
|
||||
if rounds <= 0:
|
||||
await evt.send(await UniMessage().text("干什么!你想玩负数局吗?").export())
|
||||
return
|
||||
state = IdiomGame.try_start_game(group_id, force)
|
||||
state = await IdiomGame.try_start_game(group_id, force)
|
||||
if state == TryStartState.ALREADY_PLAYING:
|
||||
await evt.send(
|
||||
await UniMessage()
|
||||
@ -502,7 +518,7 @@ async def play_game(
|
||||
.export()
|
||||
)
|
||||
instance = IdiomGame.INSTANCE_LIST[group_id]
|
||||
instance.start_game(rounds)
|
||||
await instance.start_game(rounds)
|
||||
# 发布成语
|
||||
await evt.send(
|
||||
await UniMessage()
|
||||
@ -595,7 +611,7 @@ async def _(target: DepLongTaskTarget):
|
||||
instance = IdiomGame.INSTANCE_LIST.get(group_id)
|
||||
if not instance or not instance.get_playing_state():
|
||||
return
|
||||
avaliable_idiom = IdiomGame.random_idiom_starting_with(instance.get_last_char())
|
||||
avaliable_idiom = await IdiomGame.random_idiom_starting_with(instance.get_last_char())
|
||||
# 发送哈哈狗图片
|
||||
with open(ASSETS_PATH / "img" / "dog" / "haha_dog.jpg", "rb") as f:
|
||||
img_data = f.read()
|
||||
|
||||
Reference in New Issue
Block a user