diff --git a/liteyuki/bot/__init__.py b/liteyuki/bot/__init__.py index 0d0dc13..d75826b 100644 --- a/liteyuki/bot/__init__.py +++ b/liteyuki/bot/__init__.py @@ -271,9 +271,7 @@ def get_config_with_compat( def print_logo(): """@litedoc-hide""" - print( - "\033[34m" - + r""" + print("\033[34m" + r""" ▅▅▅▅▅▅▅▅▅▅▅▅▅▅██ ▅▅▅▅▅▅▅▅▅▅▅▅▅▅██ ██ ▅▅▅▅▅▅▅▅▅▅█™ ▛ ██ ██ ▛ ██ ███ ██ ██ ██ ██ ███████████████ ██ ████████▅ ██ @@ -285,10 +283,8 @@ def print_logo(): ███ ███ █████▛ ██ ██ ██ ██ ██ ███ ██ ███ █ ██ ██ ██ ██ ██ ███ █████ ██████ ███ ██████████████ - 商业标记 版权所有 © 2024 金羿Eilles - 机器软件 版权所有 © 2020-2024 神羽SnowyKami & 金羿Eilles\\ + 商业标记 版权所有 © 2026 金羿Eilles + 机器软件 版权所有 © 2020-2026 神羽SnowyKami & 金羿Eilles\\ 会同 LiteyukiStudio & 睿乐组织 保留所有权利 -""" - + "\033[0m" - ) +""" + "\033[0m") diff --git a/liteyuki/comm/channel.py b/liteyuki/comm/channel.py index 677f7f6..351554b 100644 --- a/liteyuki/comm/channel.py +++ b/liteyuki/comm/channel.py @@ -2,22 +2,34 @@ """ 本模块定义了一个通用的通道类,用于进程间通信 """ + import asyncio from multiprocessing import Pipe -from typing import Any, Callable, Coroutine, Generic, Optional, TypeAlias, TypeVar, get_args +from typing import ( + Any, + Callable, + Coroutine, + Generic, + Optional, + TypeAlias, + TypeVar, + get_args, +) from liteyuki.log import logger from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable T = TypeVar("T") -SYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Any] # 同步接收函数 -ASYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, Any]] # 异步接收函数 -ON_RECEIVE_FUNC: TypeAlias = SYNC_ON_RECEIVE_FUNC | ASYNC_ON_RECEIVE_FUNC # 接收函数 +SYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Any] # 同步接收函数 +ASYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[ + [T], Coroutine[Any, Any, Any] +] # 异步接收函数 +ON_RECEIVE_FUNC: TypeAlias = SYNC_ON_RECEIVE_FUNC | ASYNC_ON_RECEIVE_FUNC # 接收函数 -SYNC_FILTER_FUNC: TypeAlias = Callable[[T], bool] # 同步过滤函数 -ASYNC_FILTER_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, bool]] # 异步过滤函数 -FILTER_FUNC: TypeAlias = SYNC_FILTER_FUNC | ASYNC_FILTER_FUNC # 过滤函数 +SYNC_FILTER_FUNC: TypeAlias = Callable[[T], bool] # 同步过滤函数 +ASYNC_FILTER_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, bool]] # 异步过滤函数 +FILTER_FUNC: TypeAlias = SYNC_FILTER_FUNC | ASYNC_FILTER_FUNC # 过滤函数 _func_id: int = 0 _channel: dict[str, "Channel"] = {} @@ -39,7 +51,9 @@ class Channel(Generic[T]): """ self.conn_send, self.conn_recv = Pipe() - self._conn_send_inner, self._conn_recv_inner = Pipe() # 内部通道,用于子进程通信 + self._conn_send_inner, self._conn_recv_inner = ( + Pipe() + ) # 内部通道,用于子进程通信 self._closed = False self._on_main_receive_func_ids: list[int] = [] self._on_sub_receive_func_ids: list[int] = [] @@ -64,7 +78,9 @@ class Channel(Generic[T]): _channel[name] = self logger.debug(f"Channel {name} 已在主进程中初始化") else: - logger.debug(f"Channel {name} 已初始化于子进程中,之后应于主进程中手动设置为妙") + logger.debug( + f"Channel {name} 已初始化于子进程中,之后应于主进程中手动设置为妙" + ) def _get_generic_type(self) -> Optional[type]: """ @@ -72,7 +88,7 @@ class Channel(Generic[T]): Returns: Optional[type]: 泛型类型 """ - if hasattr(self, '__orig_class__'): + if hasattr(self, "__orig_class__"): return get_args(self.__orig_class__)[0] return None @@ -98,7 +114,10 @@ class Channel(Generic[T]): elif isinstance(structure, dict): if not isinstance(data, dict): return False - return all(k in data and self._validate_structure(data[k], structure[k]) for k in structure) + return all( + k in data and self._validate_structure(data[k], structure[k]) + for k in structure + ) return False def __str__(self): @@ -142,7 +161,9 @@ class Channel(Generic[T]): data = await loop.run_in_executor(None, self.receive) return data - def on_receive(self, filter_func: Optional[FILTER_FUNC] = None) -> Callable[[Callable[[T], Any]], Callable[[T], Any]]: + def on_receive( + self, filter_func: Optional[FILTER_FUNC] = None + ) -> Callable[[Callable[[T], Any]], Callable[[T], Any]]: """ 接收数据并执行函数 Args: @@ -187,37 +208,52 @@ class Channel(Generic[T]): data: 数据 """ if IS_MAIN_PROCESS: - [asyncio.create_task(_callback_funcs[func_id](data)) for func_id in self._on_main_receive_func_ids] + [ + asyncio.create_task(_callback_funcs[func_id](data)) + for func_id in self._on_main_receive_func_ids + ] else: - [asyncio.create_task(_callback_funcs[func_id](data)) for func_id in self._on_sub_receive_func_ids] + [ + asyncio.create_task(_callback_funcs[func_id](data)) + for func_id in self._on_sub_receive_func_ids + ] """子进程可用的主动和被动通道""" -active_channel: Channel = Channel(name="active_channel") # 主动通道 +active_channel: Channel = Channel(name="active_channel") # 主动通道 passive_channel: Channel = Channel(name="passive_channel") # 被动通道 -publish_channel: Channel[tuple[str, dict[str, Any]]] = Channel(name="publish_channel") # 发布通道 +publish_channel: Channel[tuple[str, dict[str, Any]]] = Channel( + name="publish_channel" +) # 发布通道 """通道传递通道,主进程创建单例,子进程初始化时实例化""" -channel_deliver_active_channel: Channel[Channel[Any]] # 主动通道传递通道 -channel_deliver_passive_channel: Channel[tuple[str, dict[str, Any]]] # 被动通道传递通道 +channel_deliver_active_channel: Channel[Channel[Any]] # 主动通道传递通道 +channel_deliver_passive_channel: Channel[tuple[str, dict[str, Any]]] # 被动通道传递通道 if IS_MAIN_PROCESS: - channel_deliver_active_channel = Channel(name="channel_deliver_active_channel") # 主动通道传递通道 - channel_deliver_passive_channel = Channel(name="channel_deliver_passive_channel") # 被动通道传递通道 + channel_deliver_active_channel = Channel( + name="channel_deliver_active_channel" + ) # 主动通道传递通道 + channel_deliver_passive_channel = Channel( + name="channel_deliver_passive_channel" + ) # 被动通道传递通道 - - @channel_deliver_passive_channel.on_receive(filter_func=lambda data: data[0] == "set_channel") + @channel_deliver_passive_channel.on_receive( + filter_func=lambda data: data[0] == "set_channel" + ) def on_set_channel(data: tuple[str, dict[str, Any]]): name, channel = data[1]["name"], data[1]["channel_"] set_channel(name, channel) - - @channel_deliver_passive_channel.on_receive(filter_func=lambda data: data[0] == "get_channel") + @channel_deliver_passive_channel.on_receive( + filter_func=lambda data: data[0] == "get_channel" + ) def on_get_channel(data: tuple[str, dict[str, Any]]): name, recv_chan = data[1]["name"], data[1]["recv_chan"] recv_chan.send(get_channel(name)) - - @channel_deliver_passive_channel.on_receive(filter_func=lambda data: data[0] == "get_channels") + @channel_deliver_passive_channel.on_receive( + filter_func=lambda data: data[0] == "get_channels" + ) def on_get_channels(data: tuple[str, dict[str, Any]]): recv_chan = data[1]["recv_chan"] recv_chan.send(get_channels()) @@ -241,10 +277,11 @@ def set_channel(name: str, channel: "Channel"): # 请求主进程设置通道 channel_deliver_passive_channel.send( ( - "set_channel", { - "name" : name, - "channel_": channel, - } + "set_channel", + { + "name": name, + "channel_": channel, + }, ) ) @@ -273,13 +310,7 @@ def get_channel(name: str) -> "Channel": else: recv_chan = Channel[Channel[Any]]("recv_chan") channel_deliver_passive_channel.send( - ( - "get_channel", - { - "name" : name, - "recv_chan": recv_chan - } - ) + ("get_channel", {"name": name, "recv_chan": recv_chan}) ) return recv_chan.receive() @@ -294,12 +325,5 @@ def get_channels() -> dict[str, "Channel"]: return _channel else: recv_chan = Channel[dict[str, Channel[Any]]]("recv_chan") - channel_deliver_passive_channel.send( - ( - "get_channels", - { - "recv_chan": recv_chan - } - ) - ) + channel_deliver_passive_channel.send(("get_channels", {"recv_chan": recv_chan})) return recv_chan.receive() diff --git a/liteyuki/dev/observer.py b/liteyuki/dev/observer.py index 6be869c..ada5d2d 100644 --- a/liteyuki/dev/observer.py +++ b/liteyuki/dev/observer.py @@ -2,6 +2,7 @@ 此模块用于注册观察者函数,使用watchdog监控文件变化并重启bot 启用该模块需要在配置文件中设置`dev_mode`为True """ + import time from typing import Callable, TypeAlias @@ -21,6 +22,7 @@ def debounce(wait): """ 防抖函数 """ + def decorator(func): def wrapper(*args, **kwargs): nonlocal last_call_time @@ -62,7 +64,9 @@ class CodeModifiedHandler(FileSystemEventHandler): self.on_modified(event) -def on_file_system_event(directories: tuple[str], recursive: bool = True, event_filter: FILTER_FUNC = None) -> Callable[[CALLBACK_FUNC], CALLBACK_FUNC]: +def on_file_system_event( + directories: tuple[str], recursive: bool = True, event_filter: FILTER_FUNC = None +) -> Callable[[CALLBACK_FUNC], CALLBACK_FUNC]: """ 注册文件系统变化监听器 Args: diff --git a/requirements.txt b/requirements.txt index 404daba..a27616b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,6 +28,7 @@ importlib_metadata>=7.0.2 watchdog>=4.0.0 jieba>=0.42.1 python-dotenv>=1.0.1 +pip nonebot_plugin_session pypinyin zhDateTime>=2.0.0 diff --git a/src/liteyuki_main/core.py b/src/liteyuki_main/core.py index 6905ec5..954a641 100644 --- a/src/liteyuki_main/core.py +++ b/src/liteyuki_main/core.py @@ -81,7 +81,7 @@ async def _(bot: T_Bot, event: T_MessageEvent, matcher: Matcher): reply = "尹灵温 更新完成!\n" reply += f"```\n{logs}\n```\n" btn_restart = md.btn_cmd(ulang.get("liteyuki.restart_now"), "reload-liteyuki") - pip.main(["install", "-r", "requirements.txt"]) + # pip.main(["install", "-r", "requirements.txt"]) reply += f"{ulang.get('liteyuki.update_restart', RESTART=btn_restart)}" # await md.send_md(reply, bot) img_bytes = await md_to_pic(reply) diff --git a/src/nonebot_plugins/liteyuki_uniblacklist/__init__.py b/src/nonebot_plugins/liteyuki_uniblacklist/__init__.py index 0f599d1..0aaf34c 100644 --- a/src/nonebot_plugins/liteyuki_uniblacklist/__init__.py +++ b/src/nonebot_plugins/liteyuki_uniblacklist/__init__.py @@ -9,9 +9,8 @@ __plugin_meta__ = PluginMetadata( type="application", homepage="https://github.com/snowykami/LiteyukiBot", extra={ - "liteyuki": True, - "toggleable" : True, - "default_enable" : True, - } + "liteyuki": True, + "toggleable": True, + "default_enable": True, + }, ) - diff --git a/src/nonebot_plugins/liteyuki_uniblacklist/api.py b/src/nonebot_plugins/liteyuki_uniblacklist/api.py index 0e63184..c00e165 100644 --- a/src/nonebot_plugins/liteyuki_uniblacklist/api.py +++ b/src/nonebot_plugins/liteyuki_uniblacklist/api.py @@ -22,13 +22,9 @@ async def update_blacklist(): async def request_for_blacklist(): global blacklist - urls = [ - "https://cdn.liteyuki.icu/static/ubl/" - ] + urls = ["https://cdn.liteyuki.icu/static/ubl/"] - platforms = [ - "qq" - ] + platforms = ["qq"] for plat in platforms: for url in urls: @@ -37,7 +33,7 @@ async def request_for_blacklist(): resp = await client.get(url) blacklist_data[plat] = set((await resp.text()).splitlines()) blacklist = get_uni_set() - nonebot.logger.info("blacklists updated") + nonebot.logger.info("轻雪联合黑名单已更新") def get_uni_set() -> set: @@ -55,4 +51,4 @@ async def pre_handle(event: Event): return if user_id in get_uni_set(): - raise IgnoredException("UserId in blacklist") + raise IgnoredException("用户处于黑名单之中,无法使用轻雪。") diff --git a/src/utils/__init__.py b/src/utils/__init__.py index d30e26b..d16f53f 100644 --- a/src/utils/__init__.py +++ b/src/utils/__init__.py @@ -34,7 +34,7 @@ def init(): repo = Repo(".") except Exception as e: nonebot.logger.error( - f"无法读取 Git 仓库 `{e}`,你是否是从仓库直接下载的Zip文件?请使用git clone。" + f"无法读取 Git 仓库 `{e}`,你是否是从仓库直接下载的 `Zip` 文件?请使用 `git clone`。" ) # temp_data: TempConfig = common_db.where_one(TempConfig(), default=TempConfig()) diff --git a/src/utils/base/config.py b/src/utils/base/config.py index 0f0a63c..df82b63 100644 --- a/src/utils/base/config.py +++ b/src/utils/base/config.py @@ -36,7 +36,7 @@ class BasicConfig(BaseModel): satori: SatoriConfig = SatoriConfig() data_path: str = "data/liteyuki" chromium_path: str = ( - "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome" # type: ignore + "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome" # pyright: ignore[reportInvalidStringEscapeSequence] if platform.system() == "Darwin" else ( "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe" diff --git a/src/utils/base/data.py b/src/utils/base/data.py index c3e3e95..912a7b2 100644 --- a/src/utils/base/data.py +++ b/src/utils/base/data.py @@ -273,7 +273,7 @@ class Database: """ table_name = model.TABLE_NAME - logger.debug(f"Deleting {model} WHERE {condition} {args}") + logger.debug(f"数据库 Deleting {model} WHERE {condition} {args}") if not table_name: raise ValueError(f"数据模型 {model.__class__.__name__} 未提供表名") if model.id is not None: diff --git a/src/utils/base/language.py b/src/utils/base/language.py index d5d277c..4f3d5d2 100644 --- a/src/utils/base/language.py +++ b/src/utils/base/language.py @@ -45,7 +45,7 @@ def load_from_lang(file_path: str, lang_code: str = None): _language_data[lang_code].update(data) nonebot.logger.debug(f"已从 {file_path} 读取语言文件") except Exception as e: - nonebot.logger.error(f"无法读取以下目录中的语言文件 {file_path},详阅:{e}") + nonebot.logger.error(f"无法读取语言文件 {file_path},详阅:{e}") def load_from_json(file_path: str, lang_code: str = None): @@ -64,9 +64,9 @@ def load_from_json(file_path: str, lang_code: str = None): if lang_code not in _language_data: _language_data[lang_code] = {} _language_data[lang_code].update(data) - nonebot.logger.debug(f"Loaded language data from {file_path}") + nonebot.logger.debug(f"已从 {file_path} 读取语言文件") except Exception as e: - nonebot.logger.error(f"Failed to load language data from {file_path}: {e}") + nonebot.logger.error(f"无法读取语言文件 {file_path},详阅:{e}") def load_from_dir(dir_path: str): @@ -85,7 +85,7 @@ def load_from_dir(dir_path: str): elif file.endswith(".json"): load_from_json(file_path) except Exception as e: - nonebot.logger.error(f"Failed to load language data from {file}: {e}") + nonebot.logger.error(f"无法读取以下目录中的语言文件 {file},详阅:{e}") continue diff --git a/src/utils/base/ly_function.py b/src/utils/base/ly_function.py index f97a508..8bf18dd 100644 --- a/src/utils/base/ly_function.py +++ b/src/utils/base/ly_function.py @@ -194,4 +194,4 @@ def load_from_file(path: str): continue func.functions.append(line) loaded_functions[name] = func - nonebot.logger.debug(f"Loaded function {name}") + nonebot.logger.debug(f"已加载轻雪函数:{name}") diff --git a/src/utils/base/word_bank.py b/src/utils/base/word_bank.py index 81772dc..5846075 100644 --- a/src/utils/base/word_bank.py +++ b/src/utils/base/word_bank.py @@ -22,7 +22,7 @@ def load_from_file(file_path: str): word_bank[key] = set() word_bank[key].update(value_list) - nonebot.logger.debug(f"Loaded word bank from {file_path}") + nonebot.logger.debug(f"已从 {file_path} 路径加载词库") def load_from_dir(dir_path: str): @@ -39,7 +39,7 @@ def load_from_dir(dir_path: str): if file.endswith(".json"): load_from_file(file_path) except Exception as e: - nonebot.logger.error(f"Failed to load language data from {file}: {e}") + nonebot.logger.error(f"无法从 {file} 加载语言数据,出现如下问题:{e}") continue diff --git a/src/utils/extension/lib_loader.py b/src/utils/extension/lib_loader.py index 40f3d91..51660e2 100644 --- a/src/utils/extension/lib_loader.py +++ b/src/utils/extension/lib_loader.py @@ -39,5 +39,5 @@ def load_lib(lib_name: str) -> ctypes.CDLL: """ whole_path = f"{lib_name}_{PLATFORM}_{ARCH}.{LIB_EXT}" if not os.path.exists(whole_path): - raise FileNotFoundError(f"未见动态链接库 {whole_path}") + raise FileNotFoundError(f"未找到动态链接库 {whole_path}") return ctypes.CDLL(whole_path) diff --git a/src/utils/message/html_tool.py b/src/utils/message/html_tool.py index 9f43824..c757038 100644 --- a/src/utils/message/html_tool.py +++ b/src/utils/message/html_tool.py @@ -71,7 +71,7 @@ async def template2image( os.path.join(template_path, random_file_name), "w", encoding="utf-8" ) as f: await f.write(raw_html) - nonebot.logger.info("Debug HTML: %s" % f"{random_file_name}") + nonebot.logger.info("生成调试用 HTML 文件于 `%s`" % f"{random_file_name}") return await template_to_pic( template_name=template_name, diff --git a/src/utils/message/message.py b/src/utils/message/message.py index 100677d..5181ecd 100644 --- a/src/utils/message/message.py +++ b/src/utils/message/message.py @@ -193,7 +193,7 @@ class MarkdownMessage: image = Image.open(io.BytesIO(await resp.read())) return MarkdownMessage.image(url, image.size) except Exception as e: - nonebot.logger.error(f"获取图片错误:{e}") + nonebot.logger.error("无法获取图片,详阅:{}".format(e)) return "[Image Error]" @staticmethod diff --git a/src/utils/message/string_tool.py b/src/utils/message/string_tool.py index 6193bd5..e5ea238 100644 --- a/src/utils/message/string_tool.py +++ b/src/utils/message/string_tool.py @@ -41,7 +41,7 @@ def convert_duration(text: str, default) -> float: return duration except BaseException as e: - nonebot.logger.info(f"convert_duration error: {e}") + nonebot.logger.info("无法转换自然语言时间为秒数,详阅:{}".format(e)) return default