15 Commits

Author SHA1 Message Date
5e454bc971 性能提升200倍 2024-10-20 23:36:49 +08:00
70bfb0fcee 性能提升200倍 2024-10-20 23:35:44 +08:00
13b95c2732 🐛 修复一些细节小问题 2024-10-20 20:59:30 +08:00
ef5866343d add: nonebot-plugin-gotify 2024-10-20 04:12:17 +08:00
d5ccd105a2 add: nonebot-plugin-gotify 2024-10-20 03:11:26 +08:00
20ad8dc53f 🐛 hotfix: from mypy import 2024-10-19 21:15:37 +08:00
de9c91d8bd 🐛 hotfix: from mypy import 2024-10-19 21:12:55 +08:00
6b64a0c379 🐛 hotfix: from mypy import 2024-10-19 21:10:18 +08:00
f117da7ff3 🎨 更新轻雪依赖版本
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 7m29s
2024-10-14 20:57:30 +08:00
f548a07230 📝 文档删除常规部署,强制使用虚拟环境 2024-10-14 20:51:37 +08:00
e2e53c21fa 📝 文档删除常规部署,强制使用虚拟环境
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 15s
2024-10-14 01:03:06 +08:00
3eaf23a56b 📝 文档删除常规部署,强制使用虚拟环境 2024-10-14 01:02:57 +08:00
4a5dd1f727 🐛 修复一些细节小问题 2024-10-14 00:57:33 +08:00
c2cb416b4e 🐛 hotfix: ubl
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 7m36s
2024-10-13 17:44:24 +08:00
5cd528d5e9 🐛 hotfix: ubl 2024-10-13 17:44:17 +08:00
38 changed files with 1750 additions and 1375 deletions

View File

@ -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

View File

@ -6,3 +6,4 @@ nonebot:
default_language: zh
driver: ~fastapi+~httpx+~websockets
alconna_use_command_start: true
gotify_token: "empty token"

View File

@ -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 `$&#40;pwd&#41;` <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+`

2202
docs/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -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 # 绑定端口

View File

@ -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,15 +16,21 @@ 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/)
@ -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直接下载源代码运行你将无法使用更新功能

View File

@ -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):
"""

View File

@ -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]:
"""

View File

@ -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

View File

@ -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(

View File

@ -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()

View File

@ -12,12 +12,11 @@ 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> "
"<lvl>[{level.icon}{level}]</lvl> "
"<c><{name}.{module}.{function}:{line}></c> "
"{message}"
)
@ -25,13 +24,22 @@ debug_format: str = (
# 默认日志格式
default_format: str = (
"<c>{time:MM-DD HH:mm:ss}</c> "
"<lvl>[{level.icon}]</lvl> "
"<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})

View File

@ -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
"""

View File

@ -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
"""

View File

@ -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()

View 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}")

View File

@ -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:

View File

@ -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]]

View File

View 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"

View File

@ -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:

View File

@ -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
View File

@ -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]]

View File

@ -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]

View File

@ -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

View File

@ -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="你好轻雪",

View File

View 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", {})
)

View File

@ -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,
)

View File

@ -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

View File

@ -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]

View File

@ -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)

View File

@ -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"])

View File

@ -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")

View File

@ -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):

View File

@ -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)

View File

@ -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
View 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!")