mirror of
https://github.com/LiteyukiStudio/LiteyukiBot.git
synced 2025-07-17 19:50:53 +00:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
5e454bc971 | |||
70bfb0fcee | |||
13b95c2732 | |||
ef5866343d | |||
d5ccd105a2 | |||
20ad8dc53f | |||
de9c91d8bd | |||
6b64a0c379 | |||
f117da7ff3 | |||
f548a07230 | |||
e2e53c21fa | |||
3eaf23a56b | |||
4a5dd1f727 | |||
c2cb416b4e | |||
5cd528d5e9 |
@ -25,6 +25,10 @@
|
||||
### 感谢
|
||||
- 所有贡献者们
|
||||
|
||||
### 参考及鸣谢
|
||||
- [nonebot-plugin-uninfo](https://github.com/RF-Tar-Railt/nonebot-plugin-uninfo)为会话部分用户信息提供了参考
|
||||
- [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna/)为消息部分提供了参考
|
||||
|
||||
|
||||
[OneBot]: https://img.shields.io/badge/OneBot-11/12-blue?style=for-the-badge
|
||||
|
||||
|
@ -5,4 +5,5 @@ nonebot:
|
||||
nickname: [ "liteyuki" ]
|
||||
default_language: zh
|
||||
driver: ~fastapi+~httpx+~websockets
|
||||
alconna_use_command_start: true
|
||||
alconna_use_command_start: true
|
||||
gotify_token: "empty token"
|
@ -9,13 +9,23 @@ order: 1
|
||||
1. Install [`Git`](https://git-scm.com/download/) and [`Python3.10+`](https://www.python.org/downloads/release/python-31010/) Environment.
|
||||
|
||||
```bash
|
||||
# Clone the project
|
||||
# Clone Repo
|
||||
git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1
|
||||
# change directory
|
||||
|
||||
# Change directory
|
||||
cd LiteyukiBot
|
||||
# install dependencies
|
||||
|
||||
# Create virtual environment
|
||||
python -m venv venv
|
||||
|
||||
# Activate virtual environment
|
||||
.\venv\Scripts\activate # Windows
|
||||
source venv/bin/activate # Linux
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
# start the bot!
|
||||
|
||||
# Run Liteyuki
|
||||
python main.py
|
||||
```
|
||||
|
||||
@ -37,9 +47,6 @@ python main.py
|
||||
> If you are using Windows, please use the absolute project directory `/path/to/LiteyukiBot` instead of `$(pwd)` <br>
|
||||
> If you have modified the port number, please replace `20216:20216` with your port number
|
||||
|
||||
## **Use TRSS Script**
|
||||
[TRSS_Liteyuki Management Script](https://timerainstarsky.github.io/TRSS_Liteyuki/), which provides a more convenient way to manage LiteyukiBot, recommended to use `Arch Linux`
|
||||
|
||||
|
||||
## **Device Requirements**
|
||||
- Windows system version minimum `Windows10+`/`Windows Server 2019+`
|
||||
|
2248
docs/pnpm-lock.yaml
generated
2248
docs/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@ order: 2
|
||||
|
||||
```yaml
|
||||
nonebot:
|
||||
# Nonebot机器人的配置,以前的最外层配置项仍可为Nonebot服务,但是部分内容会被覆盖,请尽快迁移
|
||||
# Nonebot机器人的配置,6.3.10版本后,NoneBot下配置已迁移至nonebot键下,不再使用外层配置,但是部分内容会被覆盖,请尽快迁移
|
||||
command_start: [ "/", "" ] # 指令前缀,若没有""空命令头,请开启alconna_use_command_start保证alconna解析正常
|
||||
host: 127.0.0.1 # 监听地址,默认为本机,若要接收外部请求请填写0.0.0.0
|
||||
port: 20216 # 绑定端口
|
||||
|
@ -2,11 +2,13 @@
|
||||
title: 安装
|
||||
order: 1
|
||||
---
|
||||
|
||||
# 安装
|
||||
|
||||
## **常规部署**
|
||||
|
||||
1. 安装 [`Git`](https://git-scm.com/download/) 和 [`Python3.10+`](https://www.python.org/downloads/release/python-31010/) 环境
|
||||
1. 安装 [`Git`](https://git-scm.com/download/) 和 [
|
||||
`Python3.10+`](https://www.python.org/downloads/release/python-31010/) 环境
|
||||
|
||||
```bash
|
||||
# 克隆项目到本地,轻雪使用Git进行版本管理,该步骤为必要项
|
||||
@ -14,19 +16,25 @@ git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1 # 若你不能
|
||||
|
||||
# 切换到Bot目录下
|
||||
cd LiteyukiBot
|
||||
|
||||
# 创建虚拟环境
|
||||
python -m venv venv
|
||||
|
||||
# 激活虚拟环境
|
||||
.\venv\Scripts\activate # Windows
|
||||
source venv/bin/activate # Linux
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 启动Bot
|
||||
python main.py
|
||||
```
|
||||
|
||||
> [!tip]
|
||||
> 推荐使用虚拟环境来运行轻雪,以避免依赖冲突,你可以使用`python -m venv .venv`来创建虚拟环境,然后使用`.venv\Scripts\activate`来激活虚拟环境(Linux下使用`source .venv/bin/activate`激活)
|
||||
|
||||
## **使用Docker构建**
|
||||
|
||||
1. 安装 [`Docker`](https://docs.docker.com/get-docker/)
|
||||
2. 克隆项目 `git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1`
|
||||
2. 克隆项目 `git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1`
|
||||
3. 进入轻雪目录 `cd LiteyukiBot`
|
||||
4. 构建镜像 `docker build -t liteyukibot .`
|
||||
5. 启动容器 `docker run -p 20216:20216 -v $(pwd):/liteyukibot -v $(pwd)/.cache:/root/.cache liteyukibot`
|
||||
@ -35,10 +43,6 @@ python main.py
|
||||
> Windows请使用项目绝对目录`/path/to/LiteyukiBot`代替`$(pwd)` <br>
|
||||
> 若你修改了端口号请将`20216:20216`中的`20216`替换为你的端口号
|
||||
|
||||
## **使用TRSS Scripts部署**
|
||||
[TRSS_Liteyuki轻雪机器人管理脚本](https://timerainstarsky.github.io/TRSS_Liteyuki/),该功能由TRSS提供支持,不是LiteyukiBot官方提供的功能,推荐使用`Arch Linux`
|
||||
|
||||
|
||||
## **装置要求**
|
||||
|
||||
- Windows系统版本最低`Windows10+`/`Windows Server 2019+`
|
||||
@ -48,7 +52,8 @@ python main.py
|
||||
- 硬盘: 至少`1GB`空间
|
||||
|
||||
> [!warning]
|
||||
> 如果装置上有多个环境,请使用`path/to/python -m pip install -r requirements.txt`来安装依赖,`path/to/python`为你的Python可执行文件路径
|
||||
> 如果装置上有多个环境,请使用`path/to/python -m pip install -r requirements.txt`来安装依赖,`path/to/python`
|
||||
> 为你的Python可执行文件路径
|
||||
|
||||
> [!warning]
|
||||
> 轻雪的更新功能依赖Git,如果你没有安装Git直接下载源代码运行,你将无法使用更新功能
|
||||
|
@ -1,22 +1,22 @@
|
||||
import asyncio
|
||||
import atexit
|
||||
import os
|
||||
import platform
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
|
||||
from magicoca import Chan
|
||||
|
||||
from liteyuki.bot.lifespan import LIFESPAN_FUNC, Lifespan, PROCESS_LIFESPAN_FUNC
|
||||
from liteyuki.comm.channel import get_channel
|
||||
from liteyuki.core.manager import ProcessManager
|
||||
from liteyuki.log import init_log, logger
|
||||
from liteyuki.plugin import load_plugin
|
||||
from liteyuki.utils import IS_MAIN_PROCESS
|
||||
|
||||
# new version
|
||||
from liteyuki.core.manager import sub_process_manager
|
||||
from liteyuki.log import init_log, logger
|
||||
from liteyuki.plugin import load_plugin
|
||||
from liteyuki.session import message_handler_thread
|
||||
from liteyuki.utils import IS_MAIN_PROCESS
|
||||
|
||||
__all__ = [
|
||||
"LiteyukiBot",
|
||||
@ -33,6 +33,10 @@ class LiteyukiBot:
|
||||
Args:
|
||||
**kwargs: 配置
|
||||
"""
|
||||
"""总通道"""
|
||||
self.i_chan = Chan[Any]() # 外部输入通道
|
||||
self.o_chan = Chan[Any]() # 外部输出通道
|
||||
|
||||
"""常规操作"""
|
||||
print_logo()
|
||||
global _BOT_INSTANCE
|
||||
@ -65,7 +69,7 @@ class LiteyukiBot:
|
||||
await self.lifespan.before_start() # 启动前钩子
|
||||
sub_process_manager.start_all()
|
||||
await self.lifespan.after_start() # 启动后钩子
|
||||
await self.keep_alive()
|
||||
message_handler_thread([_.ctx.sub_chan for _ in sub_process_manager.processes.values()])
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
@ -77,19 +81,7 @@ class LiteyukiBot:
|
||||
except KeyboardInterrupt:
|
||||
logger.opt(colors=True).info("<y>Liteyuki is stopping...</y>")
|
||||
self.stop()
|
||||
logger.opt(colors=True).info("<y>Liteyuki is stopped...</y>")
|
||||
|
||||
async def keep_alive(self):
|
||||
"""
|
||||
保持轻雪运行
|
||||
"""
|
||||
logger.info("Liteyuki is keeping alive...")
|
||||
try:
|
||||
while not self.stop_event.is_set():
|
||||
await asyncio.sleep(0.1)
|
||||
except Exception:
|
||||
logger.info("Liteyuki is exiting...")
|
||||
self.stop()
|
||||
logger.opt(colors=True).info("<y>Liteyuki is stopped !</y>")
|
||||
|
||||
def restart(self, delay: int = 0):
|
||||
"""
|
||||
|
@ -75,11 +75,6 @@ class Channel(Generic[T]):
|
||||
if name in _channel:
|
||||
raise ValueError(f"Channel {name} already exists")
|
||||
_channel[name] = self
|
||||
logger.debug(f"Channel {name} initialized in main process")
|
||||
else:
|
||||
logger.debug(
|
||||
f"Channel {name} initialized in sub process, should manually set in main process"
|
||||
)
|
||||
|
||||
def _get_generic_type(self) -> Optional[type]:
|
||||
"""
|
||||
|
@ -1,48 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
基于socket的通道
|
||||
"""
|
||||
|
||||
|
||||
class SocksChannel:
|
||||
"""
|
||||
通道类,可以在进程间和进程内通信,双向但同时只能有一个发送者和一个接收者
|
||||
有两种接收工作方式,但是只能选择一种,主动接收和被动接收,主动接收使用 `receive` 方法,被动接收使用 `on_receive` 装饰器
|
||||
"""
|
||||
|
||||
def __init__(self, name: str):
|
||||
"""
|
||||
初始化通道
|
||||
Args:
|
||||
name: 通道ID
|
||||
"""
|
||||
|
||||
self._name = name
|
||||
self._conn_send = None
|
||||
self._conn_recv = None
|
||||
self._closed = False
|
||||
|
||||
def send(self, data):
|
||||
"""
|
||||
发送数据
|
||||
Args:
|
||||
data: 数据
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def receive(self):
|
||||
"""
|
||||
接收数据
|
||||
Returns:
|
||||
data: 数据
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
关闭通道
|
||||
"""
|
||||
|
||||
pass
|
@ -118,6 +118,8 @@ def load_config_in_default(no_waring: bool = False) -> dict[str, Any]:
|
||||
从一个标准的轻雪项目加载配置文件
|
||||
项目目录下的config.*和config目录下的所有配置文件
|
||||
项目目录下的配置文件优先
|
||||
Args:
|
||||
no_waring: 是否关闭警告
|
||||
"""
|
||||
config = load_configs_from_dirs("config", no_waring=no_waring)
|
||||
config.update(
|
||||
|
@ -225,17 +225,14 @@ class ProcessManager:
|
||||
|
||||
|
||||
class _SubProcessManager:
|
||||
"""
|
||||
子进程管理器
|
||||
若要子进程间通信,请先在子进程A中发送通信事件给主进程,包含当前进程信息及上下文信息,主进程再将信息发送给子进程B,子进程B再根据信息进行操作
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.processes: dict[str, SubProcess] = {}
|
||||
|
||||
def new_process(
|
||||
self, name: str, *args, **kwargs
|
||||
) -> Callable[[ProcessFuncType], None]:
|
||||
def decorator(func: ProcessFuncType):
|
||||
self.processes[name] = SubProcess(name, func, *args, **kwargs)
|
||||
|
||||
return decorator
|
||||
|
||||
def add(self, name: str, func: ProcessFuncType, *args, **kwargs):
|
||||
"""
|
||||
@ -268,5 +265,33 @@ class _SubProcessManager:
|
||||
process.start()
|
||||
logger.debug(f"Starting process {name}")
|
||||
|
||||
def terminate(self, name: str):
|
||||
"""
|
||||
终止指定子进程
|
||||
Args:
|
||||
name: 子进程名称
|
||||
Returns:
|
||||
"""
|
||||
if name not in self.processes:
|
||||
raise KeyError(f"Process {name} not found.")
|
||||
self.processes[name].terminate()
|
||||
|
||||
def terminate_all(self):
|
||||
"""
|
||||
终止所有子进程
|
||||
"""
|
||||
for name, process in self.processes.items():
|
||||
process.terminate()
|
||||
logger.debug(f"Terminating process {name}")
|
||||
|
||||
def get_process(self, name: str) -> SubProcess | None:
|
||||
"""
|
||||
获取指定子进程
|
||||
Args:
|
||||
name: 子进程名称
|
||||
Returns:
|
||||
"""
|
||||
return self.processes.get(name, None)
|
||||
|
||||
|
||||
sub_process_manager = _SubProcessManager()
|
||||
|
@ -12,26 +12,34 @@ import sys
|
||||
|
||||
import loguru
|
||||
|
||||
logger = loguru.logger
|
||||
logger = loguru.logger.bind()
|
||||
|
||||
# DEBUG日志格式
|
||||
debug_format: str = (
|
||||
"<c>{time:YYYY-MM-DD HH:mm:ss}</c> "
|
||||
"<lvl>[{level.icon}]</lvl> "
|
||||
"<c><{name}.{module}.{function}:{line}></c> "
|
||||
"{message}"
|
||||
"<c>{time:YYYY-MM-DD HH:mm:ss}</c> "
|
||||
"<lvl>[{level.icon}{level}]</lvl> "
|
||||
"<c><{name}.{module}.{function}:{line}></c> "
|
||||
"{message}"
|
||||
)
|
||||
|
||||
# 默认日志格式
|
||||
default_format: str = (
|
||||
"<c>{time:MM-DD HH:mm:ss}</c> "
|
||||
"<lvl>[{level.icon}]</lvl> "
|
||||
"<c><{name}></c> "
|
||||
"{message}"
|
||||
"<c>{time:MM-DD HH:mm:ss}</c> "
|
||||
"<lvl>[{level.icon}{level}]</lvl> "
|
||||
"<c><{name}></c> "
|
||||
"{message}"
|
||||
)
|
||||
|
||||
|
||||
def get_format(level: str) -> str:
|
||||
"""
|
||||
获取日志格式
|
||||
Args:
|
||||
level: 日志等级
|
||||
|
||||
Returns: 日志格式
|
||||
|
||||
"""
|
||||
# DEBUG日志格式
|
||||
|
||||
if level == "DEBUG":
|
||||
return debug_format
|
||||
else:
|
||||
@ -41,23 +49,27 @@ def get_format(level: str) -> str:
|
||||
def init_log(config: dict):
|
||||
"""
|
||||
在语言加载完成后执行
|
||||
Returns:
|
||||
|
||||
Args:
|
||||
config: 配置
|
||||
"""
|
||||
|
||||
global logger
|
||||
level = config.get("log_level", "DEBUG")
|
||||
logger.remove()
|
||||
logger.add(
|
||||
sys.stdout,
|
||||
level=0,
|
||||
level=level,
|
||||
diagnose=False,
|
||||
format=get_format(config.get("log_level", "INFO")),
|
||||
format=get_format(level),
|
||||
)
|
||||
show_icon = config.get("log_icon", True)
|
||||
logger.level("DEBUG", color="<blue>", icon=f"{'🐛' if show_icon else ''}DEBUG")
|
||||
logger.level("INFO", color="<normal>", icon=f"{'ℹ️' if show_icon else ''}INFO")
|
||||
logger.level("SUCCESS", color="<green>", icon=f"{'✅' if show_icon else ''}SUCCESS")
|
||||
logger.level("WARNING", color="<yellow>", icon=f"{'⚠️' if show_icon else ''}WARNING")
|
||||
logger.level("ERROR", color="<red>", icon=f"{'⭕' if show_icon else ''}ERROR")
|
||||
logger.level("DEBUG", color="<blue>", icon=f"{'🐛' if show_icon else ''}")
|
||||
logger.level("INFO", color="<normal>", icon=f"{'ℹ️' if show_icon else ''}")
|
||||
logger.level("SUCCESS", color="<green>", icon=f"{'✅' if show_icon else ''}")
|
||||
logger.level("WARNING", color="<yellow>", icon=f"{'⚠️' if show_icon else ''}")
|
||||
logger.level("ERROR", color="<red>", icon=f"{'⭕' if show_icon else ''}")
|
||||
logger.level("CRITICAL", color="<red>", icon=f"{'❌' if show_icon else ''}")
|
||||
logger.level("TRACE", color="<cyan>", icon=f"{'🔍' if show_icon else ''}")
|
||||
|
||||
logger.bind()
|
||||
|
||||
init_log(config={})
|
||||
init_log(config={"log_level": "DEBUG", "log_icon": True})
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
|
||||
@Time : 2024/8/19 下午10:44
|
||||
@Author : snowykami
|
||||
@Email : snowykami@outlook.com
|
||||
@File : __init__.py.py
|
||||
@Software: PyCharm
|
||||
"""
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
|
||||
@Time : 2024/8/19 下午10:47
|
||||
@Author : snowykami
|
||||
@Email : snowykami@outlook.com
|
||||
@File : session.py
|
||||
@Software: PyCharm
|
||||
"""
|
@ -9,9 +9,9 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
@Software: PyCharm
|
||||
"""
|
||||
|
||||
from liteyuki.message.on import on_startswith
|
||||
from liteyuki.message.event import MessageEvent
|
||||
from liteyuki.message.rule import is_su_rule
|
||||
from liteyuki.session.on import on_startswith
|
||||
from liteyuki.session.event import MessageEvent
|
||||
from liteyuki.session.rule import is_su_rule
|
||||
|
||||
|
||||
@on_startswith(["liteecho"], rule=is_su_rule).handle()
|
||||
|
21
liteyuki/session/__init__.py
Normal file
21
liteyuki/session/__init__.py
Normal file
@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
该模块参考并引用了nonebot-plugin-alconna的消息段定义
|
||||
"""
|
||||
from typing import Any
|
||||
from typing import Iterable
|
||||
|
||||
from magicoca import Chan, select
|
||||
|
||||
from liteyuki.log import logger
|
||||
|
||||
|
||||
def message_handler_thread(i_chans: Iterable[Chan[Any]]):
|
||||
"""
|
||||
Args:
|
||||
i_chans: 多路输入管道组
|
||||
Returns:
|
||||
"""
|
||||
for msg in select(*i_chans):
|
||||
logger.debug(f"Recv from anybot {msg}")
|
||||
logger.info(f"Recv from anybot {msg}")
|
@ -11,7 +11,6 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
from typing import Any, Optional
|
||||
|
||||
from liteyuki import Channel
|
||||
from liteyuki.comm.storage import shared_memory
|
||||
|
||||
|
||||
class MessageEvent:
|
@ -11,8 +11,8 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
import traceback
|
||||
from typing import Any, TypeAlias, Callable, Coroutine
|
||||
|
||||
from liteyuki.message.event import MessageEvent
|
||||
from liteyuki.message.rule import Rule
|
||||
from liteyuki.session.event import MessageEvent
|
||||
from liteyuki.session.rule import Rule
|
||||
|
||||
EventHandler: TypeAlias = Callable[[MessageEvent], Coroutine[None, None, Any]]
|
||||
|
0
liteyuki/session/message/segments.py
Normal file
0
liteyuki/session/message/segments.py
Normal file
51
liteyuki/session/models.py
Normal file
51
liteyuki/session/models.py
Normal file
@ -0,0 +1,51 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
class User(BaseModel):
|
||||
"""
|
||||
用户信息
|
||||
Attributes:
|
||||
id: 用户ID
|
||||
name: 用户名
|
||||
nick: 用户昵称
|
||||
avatar: 用户头像图链接
|
||||
"""
|
||||
id: str
|
||||
name: str | None
|
||||
nick: str | None
|
||||
avatar: str | None
|
||||
|
||||
class Scene(BaseModel):
|
||||
"""
|
||||
场景信息
|
||||
Attributes:
|
||||
id: 场景ID
|
||||
type: 场景类型
|
||||
name: 场景名
|
||||
avatar: 场景头像图链接
|
||||
parent: 父场景
|
||||
"""
|
||||
id: str
|
||||
type: str
|
||||
name: str | None
|
||||
avatar: str | None
|
||||
parent: "Scene | None"
|
||||
|
||||
class Session(BaseModel):
|
||||
"""
|
||||
会话信息
|
||||
Attributes:
|
||||
self_id: 机器人ID
|
||||
adapter: 适配器ID
|
||||
scope: 会话范围
|
||||
scene: 场景信息
|
||||
user: 用户信息
|
||||
member: 成员信息,仅频道及群聊有效
|
||||
operator: 操作者信息,仅频道及群聊有效
|
||||
"""
|
||||
self_id: str
|
||||
adapter: str
|
||||
scope: str
|
||||
scene: Scene
|
||||
user: User
|
||||
member: "Member | None"
|
||||
operator: "Member | None"
|
@ -11,33 +11,13 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
|
||||
from queue import Queue
|
||||
|
||||
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, empty_rule
|
||||
from liteyuki.session.event import MessageEvent
|
||||
from liteyuki.session.matcher import Matcher
|
||||
from liteyuki.session.rule import Rule, empty_rule
|
||||
|
||||
_matcher_list: list[Matcher] = []
|
||||
_queue: Queue = Queue()
|
||||
|
||||
|
||||
@shared_memory.on_subscriber_receive("event_to_liteyuki")
|
||||
async def _(event: MessageEvent):
|
||||
print("AA")
|
||||
current_priority = -1
|
||||
for i, matcher in enumerate(_matcher_list):
|
||||
logger.info(f"Running matcher {matcher} for event: {event}")
|
||||
await matcher.run(event)
|
||||
# 同优先级不阻断,不同优先级阻断
|
||||
if current_priority != matcher.priority:
|
||||
current_priority = matcher.priority
|
||||
if matcher.block:
|
||||
break
|
||||
else:
|
||||
logger.info(f"No matcher matched for event: {event}")
|
||||
print("BB")
|
||||
|
||||
|
||||
def add_matcher(matcher: Matcher):
|
||||
for i, m in enumerate(_matcher_list):
|
||||
if m.priority < matcher.priority:
|
@ -11,7 +11,7 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
import inspect
|
||||
from typing import Optional, TypeAlias, Callable, Coroutine
|
||||
|
||||
from liteyuki.message.event import MessageEvent
|
||||
from liteyuki.session.event import MessageEvent
|
||||
from liteyuki import get_config
|
||||
|
||||
_superusers: list[str] = get_config("liteyuki.superusers", [])
|
95
pdm.lock
generated
95
pdm.lock
generated
@ -5,7 +5,7 @@
|
||||
groups = ["default", "dev"]
|
||||
strategy = ["inherit_metadata"]
|
||||
lock_version = "4.5.0"
|
||||
content_hash = "sha256:ca1b7f108fb7c5bc51977cf165511cbc7a95f64bc4effd6b6597f60bf893ba77"
|
||||
content_hash = "sha256:b79773f31b417a430bc17fa770a0ff937c3ed0a3d1ac18950fdf4d5c405a28af"
|
||||
|
||||
[[metadata.targets]]
|
||||
requires_python = ">=3.10"
|
||||
@ -89,16 +89,16 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "croterline"
|
||||
version = "1.0.3"
|
||||
version = "1.0.9"
|
||||
requires_python = ">=3.10"
|
||||
summary = "Default template for PDM package"
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"magicoca>=1.0.1",
|
||||
"magicoca>=1.0.6",
|
||||
]
|
||||
files = [
|
||||
{file = "croterline-1.0.3-py3-none-any.whl", hash = "sha256:e934041248bba97382cc522c658d6c4f507dbcfe751e90a1d4cb3076b530e99b"},
|
||||
{file = "croterline-1.0.3.tar.gz", hash = "sha256:eb3874a96ed06d98fe210731ad9352a854df81218fb2c25e707e2b641b6daffb"},
|
||||
{file = "croterline-1.0.9-py3-none-any.whl", hash = "sha256:d2d62bd8038ea0a845175b4a2ac127e4c4fcdb8dab5d4a04804c8af0a30986eb"},
|
||||
{file = "croterline-1.0.9.tar.gz", hash = "sha256:417a3aa2b18ee362f6b22939d918db378dceb1992b0231f3b80cbbdde4cb2f0a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -142,18 +142,18 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "magicoca"
|
||||
version = "1.0.1"
|
||||
version = "1.0.6"
|
||||
requires_python = ">=3.10"
|
||||
summary = "A communication library for Python"
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "magicoca-1.0.1-py3-none-any.whl", hash = "sha256:69e04be77f9c02d3d0730dc4e739246f4bdefee8b78631040b464cd98cdde51c"},
|
||||
{file = "magicoca-1.0.1.tar.gz", hash = "sha256:0dbc9a35609db92ec79076f7126566c1e71bd4b853909ecbad9221dcc7fd6f31"},
|
||||
{file = "magicoca-1.0.6-py3-none-any.whl", hash = "sha256:3c62d6c3e87b3b5a13e0fd5b5fb674374355326684ab4421f2ac8a4c5127455e"},
|
||||
{file = "magicoca-1.0.6.tar.gz", hash = "sha256:e32ec57d67e64232dc7681c5095166e6a0ee3d27048d7115aa2b09ce4e7d9ff6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.11.2"
|
||||
version = "1.12.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Optional static typing for Python"
|
||||
groups = ["dev"]
|
||||
@ -163,23 +163,28 @@ dependencies = [
|
||||
"typing-extensions>=4.6.0",
|
||||
]
|
||||
files = [
|
||||
{file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"},
|
||||
{file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"},
|
||||
{file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"},
|
||||
{file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"},
|
||||
{file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"},
|
||||
{file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"},
|
||||
{file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"},
|
||||
{file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"},
|
||||
{file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"},
|
||||
{file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"},
|
||||
{file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"},
|
||||
{file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"},
|
||||
{file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"},
|
||||
{file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"},
|
||||
{file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"},
|
||||
{file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"},
|
||||
{file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"},
|
||||
{file = "mypy-1.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3d7d4371829184e22fda4015278fbfdef0327a4b955a483012bd2d423a788801"},
|
||||
{file = "mypy-1.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f59f1dfbf497d473201356966e353ef09d4daec48caeacc0254db8ef633a28a5"},
|
||||
{file = "mypy-1.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b947097fae68004b8328c55161ac9db7d3566abfef72d9d41b47a021c2fba6b1"},
|
||||
{file = "mypy-1.12.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96af62050971c5241afb4701c15189ea9507db89ad07794a4ee7b4e092dc0627"},
|
||||
{file = "mypy-1.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:d90da248f4c2dba6c44ddcfea94bb361e491962f05f41990ff24dbd09969ce20"},
|
||||
{file = "mypy-1.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1230048fec1380faf240be6385e709c8570604d2d27ec6ca7e573e3bc09c3735"},
|
||||
{file = "mypy-1.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:02dcfe270c6ea13338210908f8cadc8d31af0f04cee8ca996438fe6a97b4ec66"},
|
||||
{file = "mypy-1.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5a437c9102a6a252d9e3a63edc191a3aed5f2fcb786d614722ee3f4472e33f6"},
|
||||
{file = "mypy-1.12.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:186e0c8346efc027ee1f9acf5ca734425fc4f7dc2b60144f0fbe27cc19dc7931"},
|
||||
{file = "mypy-1.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:673ba1140a478b50e6d265c03391702fa11a5c5aff3f54d69a62a48da32cb811"},
|
||||
{file = "mypy-1.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9fb83a7be97c498176fb7486cafbb81decccaef1ac339d837c377b0ce3743a7f"},
|
||||
{file = "mypy-1.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:389e307e333879c571029d5b93932cf838b811d3f5395ed1ad05086b52148fb0"},
|
||||
{file = "mypy-1.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b2048a95a21f7a9ebc9fbd075a4fcd310410d078aa0228dbbad7f71335e042"},
|
||||
{file = "mypy-1.12.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ee5932370ccf7ebf83f79d1c157a5929d7ea36313027b0d70a488493dc1b179"},
|
||||
{file = "mypy-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:19bf51f87a295e7ab2894f1d8167622b063492d754e69c3c2fed6563268cb42a"},
|
||||
{file = "mypy-1.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d34167d43613ffb1d6c6cdc0cc043bb106cac0aa5d6a4171f77ab92a3c758bcc"},
|
||||
{file = "mypy-1.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:427878aa54f2e2c5d8db31fa9010c599ed9f994b3b49e64ae9cd9990c40bd635"},
|
||||
{file = "mypy-1.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5fcde63ea2c9f69d6be859a1e6dd35955e87fa81de95bc240143cf00de1f7f81"},
|
||||
{file = "mypy-1.12.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d54d840f6c052929f4a3d2aab2066af0f45a020b085fe0e40d4583db52aab4e4"},
|
||||
{file = "mypy-1.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:20db6eb1ca3d1de8ece00033b12f793f1ea9da767334b7e8c626a4872090cf02"},
|
||||
{file = "mypy-1.12.1-py3-none-any.whl", hash = "sha256:ce561a09e3bb9863ab77edf29ae3a50e65685ad74bba1431278185b7e5d5486e"},
|
||||
{file = "mypy-1.12.1.tar.gz", hash = "sha256:f5b3936f7a6d0e8280c9bdef94c7ce4847f5cdfc258fbb2c29a8c1711e8bb96d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -438,29 +443,29 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "uv"
|
||||
version = "0.4.20"
|
||||
version = "0.4.24"
|
||||
requires_python = ">=3.8"
|
||||
summary = "An extremely fast Python package and project manager, written in Rust."
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "uv-0.4.20-py3-none-linux_armv6l.whl", hash = "sha256:d0566f3ce596b0192099f7a01be08e1f37061d7399e0128804794cf83cdf2806"},
|
||||
{file = "uv-0.4.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1f20251b5a6a1cc92d844153b128b346bd0be8178beb4945df63d1a76a905176"},
|
||||
{file = "uv-0.4.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d37f02ae48540104d9c13d2dfe27bf84b246d5945b55d91568404da08e2a3bd8"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:555f0275c3db5b1cd13f6a6825b0b0f23e116a58a46da65f55d4f07915b36b16"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6faba47d13c1b916bfe9a1828a792ba21558871b4b81dbb79c157077f558fb3"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:092d4d3cee4a9680832c16d5c1a5e816b2d07a31328580f04e4ddf437821b1f3"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5d62655450d173a4dbe76b70b9af81ffa501501d97224f311f126b30924b42f7"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:865c5fbc2ebe73b4f4b71cbcc1b1bae90a335b15f6eaa9fa6495f77a6e86455e"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a65eaec88b084094f5b08c2ad73f0ae972f7d6afd0d3ee1d0eb29a76c010a39b"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8e3492d5f1613e88201b6f68a2e5fba48b0bdbe0f11179df9b222e9dd8d89d3"},
|
||||
{file = "uv-0.4.20-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:8ec4a7d0ab131ea749702d4885ff0f6734e1aca1dc26ebbc1c7c67969ba3c0fc"},
|
||||
{file = "uv-0.4.20-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:588aedc47fe02f8cf0dfe0dec3fd5e1f3a707fdf674964b3d31f0523351db9d2"},
|
||||
{file = "uv-0.4.20-py3-none-musllinux_1_1_i686.whl", hash = "sha256:309539e9b29f3fbbedb3835297a324a9206b42005e15b0af3fa73343ab966349"},
|
||||
{file = "uv-0.4.20-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:8ad94fb135bec5c061ba21b1f081f349c3de2b0f8660e168e5afc829d3069e6d"},
|
||||
{file = "uv-0.4.20-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:74f78748e72893a674351ca9d708003629ddc1a00bc51100c901b5d47db73e43"},
|
||||
{file = "uv-0.4.20-py3-none-win32.whl", hash = "sha256:dbf454b6f56f9181886426c7aed7a8dfc8258f80082365fe99b2044ff92261ba"},
|
||||
{file = "uv-0.4.20-py3-none-win_amd64.whl", hash = "sha256:653bfec188d199384451804a6c055fb1d28662adfee7697fe7108c6fb78924ba"},
|
||||
{file = "uv-0.4.20.tar.gz", hash = "sha256:b4c8a2027b1f19f8b8949132e728a750e4f9b4bb0ec02544d9b21df3f525ab1a"},
|
||||
{file = "uv-0.4.24-py3-none-linux_armv6l.whl", hash = "sha256:bbc24b232c5e874741d863c5bec2257533db86f91381f1a101872028a0502ec9"},
|
||||
{file = "uv-0.4.24-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8d467d4c4746127b2121d6f67686957a2b5431935d26767aa02fa4516694293"},
|
||||
{file = "uv-0.4.24-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7d076875e9fa4d8cda44d3e51c9b47efc578db830535c62f25884772bfa265bc"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c40f75df1f2c45a7f67fcc69d80231760f6a017b7c8e889a16e21348651a34d7"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b459913d8ba6edba2c4b299e87fccfbd7fca4b2e2abe5fd4fa0da56147e19fc8"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e3ce0350e74b3dba6854789dd253faeab2fdf8e84f2671b68573070bb40ff17"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d274f7ddc013697fb52962632bc7e77889a6ec87d2cd12316d218686cfece3d4"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ef6914a7294ac7df5bd15b21652cbe61d1c12a0f29a94d178dce6192f858092"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d8e5f66a8756d4908121cb59189e6f9992fdbd0f9c26a5a30a069b94f8acab3"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3ea6780e3451c81ce1635656abcd8a47e43f1b0f02542c433b4b6dd459df8e"},
|
||||
{file = "uv-0.4.24-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:beaff8fdaad3bcd781a8d28b60843b8d1cd2a04229847dc314c1bb7e0bb39ca2"},
|
||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:70a76cb5b8a459d6f6931becf2b5689599382c2512341d566ce335b8304c44e8"},
|
||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_i686.whl", hash = "sha256:29c514752873c1be259afd82b975e528ec6783564a306fd24deee0cccb2dc566"},
|
||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:c03a411f1b86ce7de25d6271d90358ba2d33e87b4922dc5378c4c07674909363"},
|
||||
{file = "uv-0.4.24-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a03bc4b2ca2236eece97fffb8b5605b7a2248cd8a4b9a9c67955ad08756a1ceb"},
|
||||
{file = "uv-0.4.24-py3-none-win32.whl", hash = "sha256:a97c347af12deb687c09fed82dc829efd6e5fbc4d76a38e98b2eaa2b065e4cfe"},
|
||||
{file = "uv-0.4.24-py3-none-win_amd64.whl", hash = "sha256:ec0570f5e2e4dbfd83a89e9a55d5f033050d749f684bd0e7d4c327fd49f89b12"},
|
||||
{file = "uv-0.4.24.tar.gz", hash = "sha256:f71a00f10cfa15b4f4f0184a67da19f35c48683bba9bb49cebe9c206f1b2bc1f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -15,13 +15,13 @@ license = { text = "MIT&LSO" }
|
||||
|
||||
dependencies = [
|
||||
"loguru~=0.7.2",
|
||||
"pydantic>=2.8.2",
|
||||
"pydantic>=2.9.2",
|
||||
"PyYAML>=6.0.2",
|
||||
"toml>=0.10.2",
|
||||
"watchdog>=4.0.1",
|
||||
"pdm-backend>=2.3.3",
|
||||
"magicoca>=1.0.1",
|
||||
"croterline>=1.0.3"
|
||||
"magicoca>=1.0.6",
|
||||
"croterline>=1.0.9",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
@ -1,15 +1,16 @@
|
||||
# app dependencies
|
||||
aiohttp>=3.9.3
|
||||
aiofiles>=23.2.1
|
||||
colored>=2.2.4
|
||||
croterline>=1.0.3
|
||||
GitPython>=3.1.43
|
||||
httpx>=0.27.0
|
||||
nonebot-plugin-htmlrender>=0.1.0
|
||||
nonebot2[fastapi,httpx,websockets]>=2.3.3
|
||||
nonebot-adapter-onebot>=2.4.3
|
||||
nonebot-plugin-alconna>=0.46.3
|
||||
nonebot-plugin-alconna>=0.53.1
|
||||
nonebot_plugin_apscheduler>=0.4.0
|
||||
nonebot-adapter-satori>=0.11.5
|
||||
mysql-connector-python>=9.1.0
|
||||
pyppeteer>=2.0.0
|
||||
markdown>=3.3.6
|
||||
zhDateTime>=1.0.3
|
||||
@ -31,4 +32,7 @@ loguru~=0.7.2
|
||||
pydantic~=2.9.2
|
||||
pip~=23.2.1
|
||||
fastapi~=0.115.0
|
||||
magicoca~=1.0.1
|
||||
|
||||
# liteyuki dependencies
|
||||
croterline>=1.0.7
|
||||
magicoca>=1.0.5
|
@ -9,8 +9,8 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
@Software: PyCharm
|
||||
"""
|
||||
from liteyuki.plugin import PluginMetadata, PluginType
|
||||
from liteyuki.message.on import on_message
|
||||
from liteyuki.message.event import MessageEvent
|
||||
from liteyuki.session.on import on_message
|
||||
from liteyuki.session.event import MessageEvent
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="你好轻雪",
|
||||
|
0
src/liteyuki_plugins/melobot/__init__.py
Normal file
0
src/liteyuki_plugins/melobot/__init__.py
Normal file
@ -1,10 +1,9 @@
|
||||
import os.path
|
||||
from pathlib import Path
|
||||
|
||||
import nonebot
|
||||
|
||||
from croterline.utils import IsMainProcess
|
||||
|
||||
from liteyuki import get_bot
|
||||
from liteyuki.core import sub_process_manager
|
||||
from liteyuki.plugin import PluginMetadata, PluginType
|
||||
|
||||
@ -15,9 +14,12 @@ __plugin_meta__ = PluginMetadata(
|
||||
|
||||
|
||||
def nb_run(*args, **kwargs):
|
||||
import nonebot
|
||||
|
||||
nonebot.init(**kwargs)
|
||||
|
||||
from .nb_utils import driver_manager, adapter_manager
|
||||
|
||||
driver_manager.init(config=kwargs)
|
||||
adapter_manager.init(kwargs)
|
||||
adapter_manager.register()
|
||||
@ -27,7 +29,9 @@ def nb_run(*args, **kwargs):
|
||||
|
||||
if IsMainProcess:
|
||||
from .dev_reloader import *
|
||||
|
||||
bot = get_bot()
|
||||
|
||||
sub_process_manager.add(
|
||||
name="nonebot", func=nb_run, **bot.config.get("nonebot", {})
|
||||
)
|
||||
|
@ -0,0 +1,109 @@
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from nonebot import logger, on_message, Bot
|
||||
from nonebot.internal.adapter import Event
|
||||
from nonebot.plugin import PluginMetadata
|
||||
from nonebot import get_driver
|
||||
|
||||
from .adapter_ctx import Context
|
||||
from .config import plugin_config, Config, NOTICE, MESSAGE
|
||||
from .gotify import Message, msg_chan, fetch_msg
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="Gotify",
|
||||
description="使用Gotify API发送消息",
|
||||
usage="后台服务插件,无需用户交互",
|
||||
)
|
||||
|
||||
# on plugin load
|
||||
driver = get_driver()
|
||||
|
||||
async def push_thread():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
while True:
|
||||
msg = await fetch_msg()
|
||||
try:
|
||||
logger.debug(f"Pushing message: {msg}")
|
||||
async with session.post(
|
||||
url=plugin_config.gotify_url + "/message",
|
||||
params={"token": plugin_config.gotify_token},
|
||||
data={
|
||||
"title": msg.title,
|
||||
"message": msg.message,
|
||||
"priority": msg.priority,
|
||||
},
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
logger.error(
|
||||
f"Push message to server failed: {await resp.text()}"
|
||||
)
|
||||
else:
|
||||
logger.info(f"Push message to server success: {msg}")
|
||||
except Exception as e:
|
||||
logger.error(f"Push message to server failed: {e}")
|
||||
|
||||
@driver.on_startup
|
||||
async def start_push_thread():
|
||||
asyncio.create_task(push_thread())
|
||||
logger.info(
|
||||
f"Gotify plugin loaded, server: {plugin_config.gotify_url}, token: {plugin_config.gotify_token}"
|
||||
)
|
||||
|
||||
if MESSAGE in plugin_config.gotify_includes:
|
||||
@on_message(block=False, priority=100).handle()
|
||||
async def _(event: Event):
|
||||
ctx = Context(
|
||||
user_id=event.get_user_id(),
|
||||
nickname="",
|
||||
message=event.get_plaintext(),
|
||||
message_type=event.get_type(),
|
||||
)
|
||||
ctx.handle(event)
|
||||
|
||||
msg_chan << Message(
|
||||
title=plugin_config.gotify_title.format(**ctx.model_dump()),
|
||||
message=plugin_config.gotify_message.format(**ctx.model_dump()),
|
||||
)
|
||||
|
||||
if NOTICE in plugin_config.gotify_includes:
|
||||
@driver.on_startup
|
||||
async def startup():
|
||||
if NOTICE in plugin_config.gotify_includes:
|
||||
msg_chan << Message(
|
||||
title=plugin_config.gotify_nickname,
|
||||
message="Bot started",
|
||||
priority=plugin_config.gotify_priority,
|
||||
)
|
||||
|
||||
|
||||
@driver.on_shutdown
|
||||
async def shutdown():
|
||||
if NOTICE in plugin_config.gotify_includes:
|
||||
msg_chan << Message(
|
||||
title=plugin_config.gotify_nickname,
|
||||
message="Bot stopped",
|
||||
priority=plugin_config.gotify_priority,
|
||||
)
|
||||
|
||||
|
||||
@driver.on_bot_connect
|
||||
async def bot_connect(bot: Bot):
|
||||
if NOTICE in plugin_config.gotify_includes:
|
||||
msg_chan << Message(
|
||||
title=plugin_config.gotify_nickname,
|
||||
message=f"Bot connected: {bot.self_id}",
|
||||
priority=plugin_config.gotify_priority,
|
||||
)
|
||||
|
||||
|
||||
@driver.on_bot_disconnect
|
||||
async def bot_disconnect(bot: Bot):
|
||||
if NOTICE in plugin_config.gotify_includes:
|
||||
msg_chan << Message(
|
||||
title=plugin_config.gotify_nickname,
|
||||
message=f"Bot disconnected: {bot.self_id}",
|
||||
priority=plugin_config.gotify_priority,
|
||||
)
|
||||
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Context(BaseModel):
|
||||
user_id: str
|
||||
nickname: str
|
||||
message: str
|
||||
message_type: str | None = None
|
||||
|
||||
def handle(self, event):
|
||||
pass
|
||||
|
@ -0,0 +1,22 @@
|
||||
from nonebot import get_plugin_config
|
||||
from pydantic import BaseModel
|
||||
|
||||
NOTICE = "notice"
|
||||
MESSAGE = "message"
|
||||
|
||||
class Config(BaseModel):
|
||||
# required fields
|
||||
gotify_token: str
|
||||
|
||||
# optional fields
|
||||
gotify_url: str = "http://127.0.0.1:40266"
|
||||
gotify_priority: int = 5
|
||||
gotify_nickname: str = "NoneBot"
|
||||
gotify_title: str = "{message_type}: {nickname}({user_id})"
|
||||
gotify_message: str = "{message}"
|
||||
gotify_includes: list[str, ...] = [NOTICE, MESSAGE]
|
||||
|
||||
|
||||
plugin_config = get_plugin_config(Config)
|
||||
if plugin_config.gotify_url.endswith("/"):
|
||||
plugin_config.gotify_url = plugin_config.gotify_url[:-1]
|
@ -0,0 +1,20 @@
|
||||
import asyncio
|
||||
from asyncio import Future
|
||||
from typing import Any
|
||||
|
||||
from magicoca import Chan
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .config import plugin_config
|
||||
|
||||
msg_chan = Chan["Message"]()
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
title: str
|
||||
message: str
|
||||
priority: int = plugin_config.gotify_priority
|
||||
|
||||
|
||||
def fetch_msg() -> Future[Any]:
|
||||
return asyncio.get_event_loop().run_in_executor(func=msg_chan.recv, executor=None)
|
@ -8,16 +8,12 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
@File : to_liteyuki.py
|
||||
@Software: PyCharm
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
from nonebot import Bot, get_bot, on_message, get_driver
|
||||
from croterline.process import get_ctx
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent
|
||||
from nonebot.plugin import PluginMetadata
|
||||
from nonebot.adapters.onebot.v11 import MessageEvent, Bot
|
||||
|
||||
from liteyuki import Channel
|
||||
from liteyuki.comm import get_channel
|
||||
from liteyuki.comm.storage import shared_memory
|
||||
from liteyuki.message.event import MessageEvent as LiteyukiMessageEvent
|
||||
from nonebot.log import logger
|
||||
from nonebot import on_message
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="轻雪push",
|
||||
@ -25,31 +21,13 @@ __plugin_meta__ = PluginMetadata(
|
||||
usage="用户无需使用",
|
||||
)
|
||||
|
||||
recv_channel = Channel[LiteyukiMessageEvent](name="event_to_nonebot")
|
||||
|
||||
|
||||
# @on_message().handle()
|
||||
# async def _(bot: Bot, event: MessageEvent):
|
||||
# liteyuki_event = LiteyukiMessageEvent(
|
||||
# message_type=event.message_type,
|
||||
# message=event.dict()["message"],
|
||||
# raw_message=event.raw_message,
|
||||
# data=event.dict(),
|
||||
# bot_id=bot.self_id,
|
||||
# user_id=str(event.user_id),
|
||||
# session_id=str(event.user_id if event.message_type == "private" else event.group_id),
|
||||
# session_type=event.message_type,
|
||||
# receive_channel=recv_channel,
|
||||
# )
|
||||
# shared_memory.publish("event_to_liteyuki", liteyuki_event)
|
||||
ctx = get_ctx()
|
||||
|
||||
@on_message(block=False, priority=100).handle()
|
||||
async def _(event: MessageEvent):
|
||||
logger.debug("Pushing message to Liteyuki")
|
||||
ctx.sub_chan << event.raw_message
|
||||
logger.debug("Pushed message to Liteyuki")
|
||||
|
||||
# @get_driver().on_bot_connect
|
||||
# async def _():
|
||||
# while True:
|
||||
# event = await recv_channel.async_receive()
|
||||
# bot: Bot = get_bot(event.bot_id) # type: ignore
|
||||
# if event.message_type == "private":
|
||||
# await bot.send_private_msg(user_id=int(event.session_id), message=event.data["message"])
|
||||
# elif event.message_type == "group":
|
||||
# await bot.send_group_msg(group_id=int(event.session_id), message=event.data["message"])
|
||||
|
@ -1,9 +1,6 @@
|
||||
import time
|
||||
from typing import AnyStr
|
||||
|
||||
import time
|
||||
from typing import AnyStr
|
||||
|
||||
import nonebot
|
||||
import pip
|
||||
from nonebot import get_driver, require
|
||||
@ -14,15 +11,15 @@ from nonebot.permission import SUPERUSER
|
||||
|
||||
# from src.liteyuki.core import Reloader
|
||||
from src.utils import event as event_utils, satori_utils
|
||||
from src.utils.base import reload # type: ignore
|
||||
from src.utils.base.config import get_config
|
||||
from src.utils.base.data_manager import TempConfig, common_db
|
||||
from src.utils.base.language import get_user_lang
|
||||
from src.utils.base.ly_function import get_function # type: ignore
|
||||
from src.utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||
from src.utils.message.html_tool import md_to_pic
|
||||
from src.utils.message.message import MarkdownMessage as md, broadcast_to_superusers
|
||||
from .api import update_liteyuki # type: ignore
|
||||
from src.utils.base import reload # type: ignore
|
||||
from src.utils.base.ly_function import get_function # type: ignore
|
||||
from src.utils.message.html_tool import md_to_pic
|
||||
|
||||
require("nonebot_plugin_alconna")
|
||||
require("nonebot_plugin_apscheduler")
|
||||
|
@ -4,21 +4,18 @@ from pathlib import Path
|
||||
|
||||
import nonebot.plugin
|
||||
from nonebot import get_driver
|
||||
from src.utils import init_log
|
||||
from src.utils.base.config import get_config
|
||||
from src.utils.base.data_manager import InstalledPlugin, plugin_db
|
||||
from src.utils.base.resource import load_resources
|
||||
from src.utils.message.tools import check_for_package
|
||||
|
||||
load_resources()
|
||||
init_log()
|
||||
|
||||
driver = get_driver()
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def load_plugins():
|
||||
print("load from", os.path.join(os.path.dirname(__file__), "../nonebot_plugins"))
|
||||
nonebot.plugin.load_plugins(os.path.abspath(os.path.join(os.path.dirname(__file__), "../nonebot_plugins")))
|
||||
# 从数据库读取已安装的插件
|
||||
if not get_config("safe_mode", False):
|
||||
|
@ -6,7 +6,6 @@ __NAME__ = "LiteyukiBot"
|
||||
__VERSION__ = "6.3.2" # 60201
|
||||
|
||||
from src.utils.base.config import load_from_yaml, config
|
||||
from src.utils.base.log import init_log
|
||||
from git import Repo
|
||||
|
||||
major, minor, patch = map(int, __VERSION__.split("."))
|
||||
@ -20,7 +19,6 @@ def init():
|
||||
|
||||
"""
|
||||
# 检测python版本是否高于3.10
|
||||
init_log()
|
||||
if sys.version_info < (3, 10):
|
||||
nonebot.logger.error("Requires Python3.10+ to run, please upgrade your Python Environment.")
|
||||
exit(1)
|
||||
|
@ -1,79 +1,79 @@
|
||||
import sys
|
||||
import loguru
|
||||
from typing import TYPE_CHECKING
|
||||
from .config import load_from_yaml
|
||||
from .language import Language, get_default_lang_code
|
||||
|
||||
logger = loguru.logger
|
||||
if TYPE_CHECKING:
|
||||
# avoid sphinx autodoc resolve annotation failed
|
||||
# because loguru module do not have `Logger` class actually
|
||||
from loguru import Record
|
||||
|
||||
|
||||
def default_filter(record: "Record"):
|
||||
"""默认的日志过滤器,根据 `config.log_level` 配置改变日志等级。"""
|
||||
log_level = record["extra"].get("nonebot_log_level", "INFO")
|
||||
levelno = logger.level(log_level).no if isinstance(log_level, str) else log_level
|
||||
return record["level"].no >= levelno
|
||||
|
||||
|
||||
# DEBUG日志格式
|
||||
debug_format: str = (
|
||||
"<c>{time:YYYY-MM-DD HH:mm:ss}</c> "
|
||||
"<lvl>[{level.icon}]</lvl> "
|
||||
"<c><{name}.{module}.{function}:{line}></c> "
|
||||
"{message}"
|
||||
)
|
||||
|
||||
# 默认日志格式
|
||||
default_format: str = (
|
||||
"<c>{time:MM-DD HH:mm:ss}</c> "
|
||||
"<lvl>[{level.icon}]</lvl> "
|
||||
"<c><{name}></c> "
|
||||
"{message}"
|
||||
)
|
||||
|
||||
|
||||
def get_format(level: str) -> str:
|
||||
if level == "DEBUG":
|
||||
return debug_format
|
||||
else:
|
||||
return default_format
|
||||
|
||||
|
||||
logger = loguru.logger.bind()
|
||||
|
||||
|
||||
def init_log():
|
||||
"""
|
||||
在语言加载完成后执行
|
||||
Returns:
|
||||
|
||||
"""
|
||||
global logger
|
||||
|
||||
config = load_from_yaml("config.yml")
|
||||
|
||||
logger.remove()
|
||||
logger.add(
|
||||
sys.stdout,
|
||||
level=0,
|
||||
diagnose=False,
|
||||
filter=default_filter,
|
||||
format=get_format(config.get("log_level", "INFO")),
|
||||
)
|
||||
show_icon = config.get("log_icon", True)
|
||||
lang = Language(get_default_lang_code())
|
||||
|
||||
debug = lang.get("log.debug", default="==DEBUG")
|
||||
info = lang.get("log.info", default="===INFO")
|
||||
success = lang.get("log.success", default="SUCCESS")
|
||||
warning = lang.get("log.warning", default="WARNING")
|
||||
error = lang.get("log.error", default="==ERROR")
|
||||
|
||||
logger.level("DEBUG", color="<blue>", icon=f"{'🐛' if show_icon else ''}{debug}")
|
||||
logger.level("INFO", color="<normal>", icon=f"{'ℹ️' if show_icon else ''}{info}")
|
||||
logger.level("SUCCESS", color="<green>", icon=f"{'✅' if show_icon else ''}{success}")
|
||||
logger.level("WARNING", color="<yellow>", icon=f"{'⚠️' if show_icon else ''}{warning}")
|
||||
logger.level("ERROR", color="<red>", icon=f"{'⭕' if show_icon else ''}{error}")
|
||||
# import sys
|
||||
# import loguru
|
||||
# from typing import TYPE_CHECKING
|
||||
# from .config import load_from_yaml
|
||||
# from .language import Language, get_default_lang_code
|
||||
#
|
||||
# logger = loguru.logger
|
||||
# if TYPE_CHECKING:
|
||||
# # avoid sphinx autodoc resolve annotation failed
|
||||
# # because loguru module do not have `Logger` class actually
|
||||
# from loguru import Record
|
||||
#
|
||||
#
|
||||
# def default_filter(record: "Record"):
|
||||
# """默认的日志过滤器,根据 `config.log_level` 配置改变日志等级。"""
|
||||
# log_level = record["extra"].get("nonebot_log_level", "INFO")
|
||||
# levelno = logger.level(log_level).no if isinstance(log_level, str) else log_level
|
||||
# return record["level"].no >= levelno
|
||||
#
|
||||
#
|
||||
# # DEBUG日志格式
|
||||
# debug_format: str = (
|
||||
# "<c>{time:YYYY-MM-DD HH:mm:ss}</c> "
|
||||
# "<lvl>[{level.icon}]</lvl> "
|
||||
# "<c><{name}.{module}.{function}:{line}></c> "
|
||||
# "{message}"
|
||||
# )
|
||||
#
|
||||
# # 默认日志格式
|
||||
# default_format: str = (
|
||||
# "<c>{time:MM-DD HH:mm:ss}</c> "
|
||||
# "<lvl>[{level.icon}]</lvl> "
|
||||
# "<c><{name}></c> "
|
||||
# "{message}"
|
||||
# )
|
||||
#
|
||||
#
|
||||
# def get_format(level: str) -> str:
|
||||
# if level == "DEBUG":
|
||||
# return debug_format
|
||||
# else:
|
||||
# return default_format
|
||||
#
|
||||
#
|
||||
# logger = loguru.logger.bind()
|
||||
#
|
||||
#
|
||||
# def init_log():
|
||||
# """
|
||||
# 在语言加载完成后执行
|
||||
# Returns:
|
||||
#
|
||||
# """
|
||||
# global logger
|
||||
#
|
||||
# config = load_from_yaml("config.yml")
|
||||
#
|
||||
# logger.remove()
|
||||
# logger.add(
|
||||
# sys.stdout,
|
||||
# level=0,
|
||||
# diagnose=False,
|
||||
# filter=default_filter,
|
||||
# format=get_format(config.get("log_level", "INFO")),
|
||||
# )
|
||||
# show_icon = config.get("log_icon", True)
|
||||
# lang = Language(get_default_lang_code())
|
||||
#
|
||||
# debug = lang.get("log.debug", default="==DEBUG")
|
||||
# info = lang.get("log.info", default="===INFO")
|
||||
# success = lang.get("log.success", default="SUCCESS")
|
||||
# warning = lang.get("log.warning", default="WARNING")
|
||||
# error = lang.get("log.error", default="==ERROR")
|
||||
#
|
||||
# logger.level("DEBUG", color="<blue>", icon=f"{'🐛' if show_icon else ''}{debug}")
|
||||
# logger.level("INFO", color="<normal>", icon=f"{'ℹ️' if show_icon else ''}{info}")
|
||||
# logger.level("SUCCESS", color="<green>", icon=f"{'✅' if show_icon else ''}{success}")
|
||||
# logger.level("WARNING", color="<yellow>", icon=f"{'⚠️' if show_icon else ''}{warning}")
|
||||
# logger.level("ERROR", color="<red>", icon=f"{'⭕' if show_icon else ''}{error}")
|
||||
|
9
tests/test_logger.py
Normal file
9
tests/test_logger.py
Normal file
@ -0,0 +1,9 @@
|
||||
from liteyuki import logger
|
||||
|
||||
def test_logger():
|
||||
logger.info('Hello, World!')
|
||||
logger.debug('Hello, World!')
|
||||
logger.warning('Hello, World!')
|
||||
logger.error('Hello, World!')
|
||||
logger.critical('Hello, World!')
|
||||
logger.success("Hello, World!")
|
Reference in New Issue
Block a user