diff --git a/liteyuki/__init__.py b/liteyuki/__init__.py index 3bde5ff4..c96f3ed1 100644 --- a/liteyuki/__init__.py +++ b/liteyuki/__init__.py @@ -33,7 +33,9 @@ __all__ = [ "logger", ] -__version__ = "6.3.8" # 测试版本号 +__version__ = "6.3.9" # 测试版本号 +# 6.3.9 +# 更改了on语法 # 6.3.8 # 1. 初步添加对聊天的支持 diff --git a/liteyuki/comm/channel.py b/liteyuki/comm/channel.py index 8adb487d..6ab737b0 100644 --- a/liteyuki/comm/channel.py +++ b/liteyuki/comm/channel.py @@ -38,7 +38,7 @@ class Channel(Generic[T]): 有两种接收工作方式,但是只能选择一种,主动接收和被动接收,主动接收使用 `receive` 方法,被动接收使用 `on_receive` 装饰器 """ - def __init__(self, _id: str, type_check: Optional[bool] = None): + def __init__(self, _id: str = "", type_check: Optional[bool] = None): """ 初始化通道 Args: diff --git a/liteyuki/comm/storage.py b/liteyuki/comm/storage.py index e3f34aa5..97c3de76 100644 --- a/liteyuki/comm/storage.py +++ b/liteyuki/comm/storage.py @@ -8,7 +8,7 @@ from typing import Any, Coroutine, Optional, TypeAlias, Callable from liteyuki.comm import channel from liteyuki.comm.channel import Channel, ON_RECEIVE_FUNC, ASYNC_ON_RECEIVE_FUNC -from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable, run_coroutine +from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable, run_coroutine, run_coroutine_in_thread if IS_MAIN_PROCESS: _locks = {} @@ -220,10 +220,10 @@ class KeyValueStore: """ if IS_MAIN_PROCESS: if channel_ in _on_main_subscriber_receive_funcs and _on_main_subscriber_receive_funcs[channel_]: - run_coroutine(*[func(data) for func in _on_main_subscriber_receive_funcs[channel_]]) + run_coroutine_in_thread(*[func(data) for func in _on_main_subscriber_receive_funcs[channel_]]) else: if channel_ in _on_sub_subscriber_receive_funcs and _on_sub_subscriber_receive_funcs[channel_]: - run_coroutine(*[func(data) for func in _on_sub_subscriber_receive_funcs[channel_]]) + run_coroutine_in_thread(*[func(data) for func in _on_sub_subscriber_receive_funcs[channel_]]) def _start_receive_loop(self): """ diff --git a/liteyuki/message/matcher.py b/liteyuki/message/matcher.py index 5585fa98..d2add762 100644 --- a/liteyuki/message/matcher.py +++ b/liteyuki/message/matcher.py @@ -34,16 +34,17 @@ class Matcher: def __str__(self): return f"Matcher(rule={self.rule}, priority={self.priority}, block={self.block})" - def handle(self, handler: EventHandler) -> EventHandler: + def handle(self) -> Callable[[EventHandler], EventHandler]: """ 添加处理函数,装饰器 - Args: - handler: Returns: - EventHandler + 装饰器 handler """ - self.handlers.append(handler) - return handler + def decorator(handler: EventHandler) -> EventHandler: + self.handlers.append(handler) + return handler + + return decorator async def run(self, event: MessageEvent) -> None: """ diff --git a/liteyuki/message/on.py b/liteyuki/message/on.py index bbc161e4..a450a85f 100644 --- a/liteyuki/message/on.py +++ b/liteyuki/message/on.py @@ -15,7 +15,7 @@ from liteyuki.comm.storage import shared_memory from liteyuki.log import logger from liteyuki.message.event import MessageEvent from liteyuki.message.matcher import Matcher -from liteyuki.message.rule import Rule +from liteyuki.message.rule import Rule, empty_rule _matcher_list: list[Matcher] = [] _queue: Queue = Queue() @@ -34,7 +34,7 @@ async def _(event: MessageEvent): break -def on_message(rule: Rule = Rule(), priority: int = 0, block: bool = True) -> Matcher: +def on_message(rule: Rule = empty_rule, priority: int = 0, block: bool = False) -> Matcher: matcher = Matcher(rule, priority, block) # 按照优先级插入 for i, m in enumerate(_matcher_list): @@ -44,3 +44,10 @@ def on_message(rule: Rule = Rule(), priority: int = 0, block: bool = True) -> Ma else: _matcher_list.append(matcher) return matcher + + +def on_keywords(keywords: list[str], rule=empty_rule, priority: int = 0, block: bool = False) -> Matcher: + @Rule + async def on_keywords_rule(event: MessageEvent): + return any(keyword in event.raw_message for keyword in keywords) + return on_message(on_keywords_rule & rule, priority, block) diff --git a/liteyuki/message/rule.py b/liteyuki/message/rule.py index 31af299e..56c4c541 100644 --- a/liteyuki/message/rule.py +++ b/liteyuki/message/rule.py @@ -8,26 +8,37 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved @File : rule.py @Software: PyCharm """ - +import inspect from typing import Optional, TypeAlias, Callable, Coroutine from liteyuki.message.event import MessageEvent -RuleHandler: TypeAlias = Callable[[MessageEvent], Coroutine[None, None, bool]] +RuleHandlerFunc: TypeAlias = Callable[[MessageEvent], Coroutine[None, None, bool]] """规则函数签名""" class Rule: - def __init__(self, handler: Optional[RuleHandler] = None): + def __init__(self, handler: RuleHandlerFunc): self.handler = handler def __or__(self, other: "Rule") -> "Rule": - return Rule(lambda event: self.handler(event) or other.handler(event)) + async def combined_handler(event: MessageEvent) -> bool: + return await self.handler(event) or await other.handler(event) + + return Rule(combined_handler) def __and__(self, other: "Rule") -> "Rule": - return Rule(lambda event: self.handler(event) and other.handler(event)) + async def combined_handler(event: MessageEvent) -> bool: + return await self.handler(event) and await other.handler(event) + + return Rule(combined_handler) async def __call__(self, event: MessageEvent) -> bool: if self.handler is None: return True return await self.handler(event) + + +@Rule +async def empty_rule(event: MessageEvent) -> bool: + return True diff --git a/liteyuki/utils.py b/liteyuki/utils.py index 90a2048f..6eb646a1 100644 --- a/liteyuki/utils.py +++ b/liteyuki/utils.py @@ -5,6 +5,7 @@ import asyncio import inspect import multiprocessing +import threading from pathlib import Path from typing import Any, Callable, Coroutine @@ -61,6 +62,16 @@ def run_coroutine(*coro: Coroutine): # 捕获其他异常,防止协程被重复等待 logger.error(f"Exception occurred: {e}") +def run_coroutine_in_thread(*coro: Coroutine): + """ + 在新线程中运行协程 + Args: + coro: + + Returns: + + """ + threading.Thread(target=run_coroutine, args=coro, daemon=True).start() def path_to_module_name(path: Path) -> str: """ diff --git a/src/liteyuki_plugins/anti_dislink.py b/src/liteyuki_plugins/anti_dislink.py new file mode 100644 index 00000000..7ef8387d --- /dev/null +++ b/src/liteyuki_plugins/anti_dislink.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved + +@Time : 2024/8/22 上午9:06 +@Author : snowykami +@Email : snowykami@outlook.com +@File : anti_dislink.py +@Software: PyCharm +""" +import random +from liteyuki.plugin import PluginMetadata, PluginType + +from liteyuki.message.on import on_keywords + +__plugin_meta__ = PluginMetadata( + name="严禁断联化", + type=PluginType.APPLICATION +) + + +@on_keywords(["看看你的", "看看j", "给我看看"]).handle() +async def _(event): + event.reply(random.choice(["No dislink", "严禁断联化"])) diff --git a/src/liteyuki_plugins/hello_liteyuki.py b/src/liteyuki_plugins/hello_liteyuki.py index 72d1ac42..86314c34 100644 --- a/src/liteyuki_plugins/hello_liteyuki.py +++ b/src/liteyuki_plugins/hello_liteyuki.py @@ -14,11 +14,11 @@ from liteyuki.message.event import MessageEvent __plugin_meta__ = PluginMetadata( name="你好轻雪", - type=PluginType.TEST + type=PluginType.APPLICATION ) -@on_message().handle +@on_message().handle() async def _(event: MessageEvent): if str(event.raw_message) == "你好轻雪": event.reply("你好呀") diff --git a/src/liteyuki_plugins/ts_chan_main.py b/src/liteyuki_plugins/ts_chan_main.py new file mode 100644 index 00000000..4b5f3280 --- /dev/null +++ b/src/liteyuki_plugins/ts_chan_main.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +""" +Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved + +@Time : 2024/8/22 上午8:37 +@Author : snowykami +@Email : snowykami@outlook.com +@File : ts_chan_main.py +@Software: PyCharm +""" +import asyncio + +from liteyuki.comm import Channel, set_channel, get_channel +from liteyuki import get_bot + +set_channel("chan-main", Channel("chan-main")) +set_channel("chan-sub", Channel("chan-sub")) + +chan_main = get_channel("chan-main") + + +# @get_bot().on_after_start +# async def _(): +# while True: +# chan_main.send("Hello, World!") +# await asyncio.sleep(5) diff --git a/src/nonebot_plugins/to_liteyuki.py b/src/nonebot_plugins/to_liteyuki.py index ddf0c15d..cba15f22 100644 --- a/src/nonebot_plugins/to_liteyuki.py +++ b/src/nonebot_plugins/to_liteyuki.py @@ -41,6 +41,4 @@ async def _(bot: Bot, event: MessageEvent): @shared_memory.on_subscriber_receive("event_to_nonebot") async def _(event: LiteyukiMessageEvent): bot: Bot = get_bot(event.bot_id) - print("A") await bot.send_msg(message_type=event.message_type, user_id=int(event.session_id), group_id=int(event.session_id), message=event.data["message"]) - print("B") \ No newline at end of file diff --git a/src/nonebot_plugins/ts_chan_sub.py b/src/nonebot_plugins/ts_chan_sub.py new file mode 100644 index 00000000..3a2c6665 --- /dev/null +++ b/src/nonebot_plugins/ts_chan_sub.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +""" +Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved + +@Time : 2024/8/22 上午8:39 +@Author : snowykami +@Email : snowykami@outlook.com +@File : ts_chan_sub.py +@Software: PyCharm +""" +import asyncio + +from liteyuki.comm import Channel, get_channel +from nonebot import get_bot +from nonebot.adapters.onebot.v11 import Bot +chan_main = get_channel("chan-main") + + +# @chan_main.on_receive() +# async def _(data: str): +# print("Received data from chan-main:", data) +# try: +# bot: Bot = get_bot("2443429204") # type: ignore +# +# def send_msg(): +# +# bot.send_msg(message_type="private", user_id=2443429204, message=data) +# +# print("tsA") +# print("tsA1") +# await asyncio.ensure_future(c) +# print("tsB") +# except Exception as e: +# print(e) +# pass