1
0
forked from bot/app

fix: 插件列表显示错误问题

This commit is contained in:
远野千束 2024-03-23 19:55:12 +08:00
parent ca0bfe0181
commit de0c073c26
24 changed files with 145 additions and 63 deletions

View File

@ -14,18 +14,19 @@
<div align=center><h4>轻量,高效,易于扩展</h4></div> <div align=center><h4>轻量,高效,易于扩展</h4></div>
- 基于[Nonebot2]("https://github.com/nonebot/nonebot2"),有良好的生态支持 - 基于[Nonebot2]("https://github.com/nonebot/nonebot2"),有良好的生态支持
- 集成了上一代轻雪的优点和~~缺点~~ - 开箱即用,无需复杂配置
- 新的点击交互模式,拒绝手打指令
- 支持一切Onebot标准通信后续会支持更多的平台 - 支持一切Onebot标准通信后续会支持更多的平台
## 手动安装和部署 ## 手动安装和部署
1. 安装`Git`和`Python3.10+` 1. 安装`Git`和`Python3.10+`
2. 克隆项目到本地`git clone https://github.com/snowykami/LiteyukiBot` 2. 克隆项目`git clone https://github.com/snowykami/LiteyukiBot`
3. 切换到轻雪目录`cd LiteyukiBot` 3. 切换目录`cd LiteyukiBot`
4. 安装依赖`pip install -r requirements.txt` 4. 安装依赖`pip install -r requirements.txt`(如果多个Python环境请指定后安装`pythonx -m pip install -r requirements.txt`)
5. 启动`python main.py` 5. 启动`python main.py`
## 一键部署脚本(复制到本地保存执行) ## 一键部署脚本
#### 提前部署好`Python3.10+`环境和`Git`环境 #### 提前部署好`Python3.10+`环境和`Git`环境
@ -41,12 +42,11 @@ echo Install finished! Please click "start.bat" to start the bot!
``` ```
#### Linux #### Linux
```bash ```bash
git clone https://github.com/snowykami/LiteyukiBot git clone https://github.com/snowykami/LiteyukiBot
cd LiteyukiBot cd LiteyukiBot
pip install -r requirements.txt pip install -r requirements.txt
echo python3 main.py > start.sh echo python3.10 main.py > start.sh
chmod +x start.sh chmod +x start.sh
echo Install finished! Please run "sh start.sh" to start the bot! echo Install finished! Please run "sh start.sh" to start the bot!
``` ```
@ -65,7 +65,7 @@ echo Install finished! Please run "sh start.sh" to start the bot!
| 地址 | ws://`host`:`port`/onebot/v11 | 地址取决于配置文件,默认为`20216`端口 | | 地址 | ws://`host`:`port`/onebot/v11 | 地址取决于配置文件,默认为`20216`端口 |
### 推荐方案(QQ) ### 推荐方案(QQ)
1. 使用`Lagrange.Core``Lagrange.Core`支持多种协议 1. 使用`Lagrange.OneBot`,点按交互目前仅支持`Lagrange.OneBot`,详细请看[Lagrange.OneBot]()
2. 云崽的`icqq-plugin`和`ws-plugin`进行通信 2. 云崽的`icqq-plugin`和`ws-plugin`进行通信
3. `Go-cqhttp`(目前已经半死不活了) 3. `Go-cqhttp`(目前已经半死不活了)
4. 人工实现的`Onebot`协议自己整一个WebSocket客户端看着QQ的消息然后给轻雪传输数据 4. 人工实现的`Onebot`协议自己整一个WebSocket客户端看着QQ的消息然后给轻雪传输数据

View File

@ -1,12 +1,16 @@
import nonebot import nonebot
from nonebot.adapters.onebot import v11, v12 from nonebot.adapters.onebot import v11, v12
from src.utils import logger
from src.utils.config import load_from_yaml from src.utils.config import load_from_yaml
nonebot.logger = logger
nonebot.init(**load_from_yaml("config.yml")) nonebot.init(**load_from_yaml("config.yml"))
adapters = [v11.Adapter, v12.Adapter] adapters = [v11.Adapter, v12.Adapter]
driver = nonebot.get_driver() driver = nonebot.get_driver()
for adapter in adapters: for adapter in adapters:
driver.register_adapter(adapter) driver.register_adapter(adapter)

View File

@ -11,6 +11,4 @@ psutil==5.9.8
pydantic==2.6.4 pydantic==2.6.4
pytz==2024.1 pytz==2024.1
PyYAML~=6.0.1 PyYAML~=6.0.1
typing_extensions~=4.10.0
starlette~=0.36.3 starlette~=0.36.3
pip==24.0

View File

@ -3,7 +3,6 @@ import os
import nonebot.plugin import nonebot.plugin
from src.utils.data_manager import InstalledPlugin, plugin_db from src.utils.data_manager import InstalledPlugin, plugin_db
from src.utils.language import load_from_dir
from src.utils.resource import load_resource_from_dir from src.utils.resource import load_resource_from_dir
THIS_PLUGIN_NAME = os.path.basename(os.path.dirname(__file__)) THIS_PLUGIN_NAME = os.path.basename(os.path.dirname(__file__))

View File

@ -7,7 +7,7 @@ from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from src.utils.message import send_markdown from src.utils.message import send_markdown
from src.utils.typing import T_Message, T_Bot, v11, T_MessageEvent from src.utils.ly_typing import T_Message, T_Bot, v11, T_MessageEvent
md_test = on_command("mdts", aliases={"会话md"}, permission=SUPERUSER) md_test = on_command("mdts", aliases={"会话md"}, permission=SUPERUSER)
md_group = on_command("mdg", aliases={"群md"}, permission=SUPERUSER) md_group = on_command("mdg", aliases={"群md"}, permission=SUPERUSER)

View File

@ -7,7 +7,7 @@ from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import on_alconna from nonebot_plugin_alconna import on_alconna
from src.utils.data import LiteModel from src.utils.data import LiteModel
from src.utils.message import send_markdown from src.utils.message import send_markdown
from src.utils.typing import T_Bot, T_MessageEvent from src.utils.ly_typing import T_Bot, T_MessageEvent
from src.utils.data import Database from src.utils.data import Database

View File

@ -6,7 +6,7 @@ import nonebot.plugin
from src.utils.data import Database, LiteModel from src.utils.data import Database, LiteModel
from src.utils.data_manager import GroupChat, InstalledPlugin, User, group_db, plugin_db, user_db from src.utils.data_manager import GroupChat, InstalledPlugin, User, group_db, plugin_db, user_db
from src.utils.typing import T_MessageEvent from src.utils.ly_typing import T_MessageEvent
LNPM_COMMAND_START = "lnpm" LNPM_COMMAND_START = "lnpm"

View File

@ -1,11 +1,7 @@
import json
import os.path import os.path
import shutil
import sys import sys
from io import StringIO from io import StringIO
from typing import Optional
import aiofiles
import aiohttp import aiohttp
import nonebot import nonebot
import pip import pip
@ -14,11 +10,9 @@ from nonebot.permission import SUPERUSER
from nonebot_plugin_alconna import Alconna, Args, Subcommand, on_alconna from nonebot_plugin_alconna import Alconna, Args, Subcommand, on_alconna
from src.utils.language import get_user_lang from src.utils.language import get_user_lang
from src.utils.ly_typing import T_Bot
from src.utils.message import Markdown as md, send_markdown from src.utils.message import Markdown as md, send_markdown
from src.utils.resource import get_res
from src.utils.typing import T_Bot, T_MessageEvent
from .common import * from .common import *
from src.utils.data_manager import InstalledPlugin
npm_alc = on_alconna( npm_alc = on_alconna(
Alconna( Alconna(
@ -38,7 +32,7 @@ npm_alc = on_alconna(
alias=["i", "安装"], alias=["i", "安装"],
), ),
Subcommand( Subcommand(
"remove", "uninstall",
Args["plugin_name", str], Args["plugin_name", str],
alias=["rm", "移除", "卸载"], alias=["rm", "移除", "卸载"],
), ),
@ -136,12 +130,12 @@ async def _(result: Arparma, event: T_MessageEvent, bot: T_Bot):
event=event event=event
) )
elif result.subcommands.get("remove"): elif result.subcommands.get("uninstall"):
plugin_module_name: str = result.subcommands["remove"].args.get("plugin_name") plugin_module_name: str = result.subcommands["uninstall"].args.get("plugin_name")
found_installed_plugin: InstalledPlugin = plugin_db.first(InstalledPlugin, "module_name = ?", plugin_module_name) found_installed_plugin: InstalledPlugin = plugin_db.first(InstalledPlugin, "module_name = ?", plugin_module_name)
if found_installed_plugin: if found_installed_plugin:
plugin_db.delete(InstalledPlugin, "module_name = ?", plugin_module_name) plugin_db.delete(InstalledPlugin, "module_name = ?", plugin_module_name)
reply = f"{ulang.get('npm.remove_success', NAME=found_installed_plugin.module_name)}" reply = f"{ulang.get('npm.uninstall_success', NAME=found_installed_plugin.module_name)}"
await npm_alc.finish(reply) await npm_alc.finish(reply)
else: else:
await npm_alc.finish(ulang.get("npm.plugin_not_installed", NAME=plugin_module_name)) await npm_alc.finish(ulang.get("npm.plugin_not_installed", NAME=plugin_module_name))

View File

@ -2,6 +2,7 @@ import os
import nonebot.plugin import nonebot.plugin
from nonebot import on_command from nonebot import on_command
from nonebot.exception import FinishedException
from nonebot.internal.matcher import Matcher from nonebot.internal.matcher import Matcher
from nonebot.message import run_preprocessor from nonebot.message import run_preprocessor
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
@ -10,7 +11,7 @@ from nonebot_plugin_alconna import on_alconna, Alconna, Args, Arparma
from src.utils.data_manager import GroupChat, InstalledPlugin, User, group_db, plugin_db, user_db from src.utils.data_manager import GroupChat, InstalledPlugin, User, group_db, plugin_db, user_db
from src.utils.message import Markdown as md, send_markdown from src.utils.message import Markdown as md, send_markdown
from src.utils.permission import GROUP_ADMIN, GROUP_OWNER from src.utils.permission import GROUP_ADMIN, GROUP_OWNER
from src.utils.typing import T_Bot, T_MessageEvent from src.utils.ly_typing import T_Bot, T_MessageEvent
from src.utils.language import get_user_lang from src.utils.language import get_user_lang
from .common import get_plugin_can_be_toggle, get_plugin_current_enable, get_plugin_default_enable from .common import get_plugin_can_be_toggle, get_plugin_current_enable, get_plugin_default_enable
from .installer import get_store_plugin, npm_update from .installer import get_store_plugin, npm_update
@ -62,12 +63,12 @@ async def _(event: T_MessageEvent, bot: T_Bot):
if await SUPERUSER(bot, event): if await SUPERUSER(bot, event):
plugin_in_database = plugin_db.first(InstalledPlugin, 'module_name = ?', plugin.module_name) plugin_in_database = plugin_db.first(InstalledPlugin, 'module_name = ?', plugin.module_name)
# 添加移除插件 # 添加移除插件
btn_remove = ( btn_uninstall = (
md.button(lang.get('npm.uninstall'), f'npm remove {plugin.module_name}')) if plugin_in_database else lang.get( md.button(lang.get('npm.uninstall'), f'npm uninstall {plugin.module_name}')) if plugin_in_database else lang.get(
'npm.uninstall') 'npm.uninstall')
btn_toggle_global = lang.get('npm.disable') if plugin.metadata and not plugin.metadata.extra.get('toggleable') \ btn_toggle_global = lang.get('npm.disable') if plugin.metadata and not plugin.metadata.extra.get('toggleable') \
else md.button(lang.get('npm.disable_global'), f'disable-plugin {plugin.module_name} true') else md.button(lang.get('npm.disable_global'), f'disable-plugin {plugin.module_name} true')
reply += f" {btn_remove} {btn_toggle_global}" reply += f" {btn_uninstall} {btn_toggle_global}"
reply += "\n\n***\n" reply += "\n\n***\n"
await send_markdown(reply, bot, event=event) await send_markdown(reply, bot, event=event)
@ -100,7 +101,7 @@ async def _(result: Arparma, event: T_MessageEvent, bot: T_Bot):
if await GROUP_ADMIN(bot, event) or await GROUP_OWNER(bot, event) or await SUPERUSER(bot, event): if await GROUP_ADMIN(bot, event) or await GROUP_OWNER(bot, event) or await SUPERUSER(bot, event):
session = group_db.first(GroupChat, "group_id = ?", event.group_id, default=GroupChat(group_id=event.group_id)) session = group_db.first(GroupChat, "group_id = ?", event.group_id, default=GroupChat(group_id=event.group_id))
else: else:
return raise FinishedException(ulang.get("Permission Denied"))
# 启用 已停用的默认启用插件 将其从停用列表移除 # 启用 已停用的默认启用插件 将其从停用列表移除
# 启用 已停用的默认停用插件 将其放到启用列表 # 启用 已停用的默认停用插件 将其放到启用列表
# 停用 已启用的默认启用插件 将其放到停用列表 # 停用 已启用的默认启用插件 将其放到停用列表
@ -134,4 +135,5 @@ async def _(result: Arparma, event: T_MessageEvent, bot: T_Bot):
@run_preprocessor @run_preprocessor
async def _(event: T_MessageEvent, matcher: Matcher): async def _(event: T_MessageEvent, matcher: Matcher):
plugin = matcher.plugin plugin = matcher.plugin
# TODO 插件启用/停用检查hook
nonebot.logger.info(f"Plugin: {plugin.module_name}") nonebot.logger.info(f"Plugin: {plugin.module_name}")

View File

@ -1,14 +1,11 @@
from typing import Optional from typing import Optional
from arclet.alconna import Arparma from nonebot_plugin_alconna import Alconna, Args, Arparma, Subcommand, on_alconna
from nonebot import on_command
from nonebot.params import CommandArg
from nonebot_plugin_alconna import on_alconna, Alconna, Args, Arparma, Option, Subcommand
from src.utils.data import LiteModel from src.utils.data import LiteModel
from src.utils.typing import T_Bot, T_Message, T_MessageEvent
from src.utils.data_manager import User, user_db from src.utils.data_manager import User, user_db
from src.utils.language import Language, get_all_lang, get_user_lang from src.utils.language import Language, get_all_lang, get_user_lang
from src.utils.ly_typing import T_Bot, T_MessageEvent
from src.utils.message import Markdown as md, send_markdown from src.utils.message import Markdown as md, send_markdown
profile_alc = on_alconna( profile_alc = on_alconna(
@ -134,5 +131,5 @@ def set_profile(key: str, value: str) -> bool:
return True return True
return False return False
elif key == 'timezone': elif key == 'timezone':
# TODO # TODO 其他个人信息项目的实现
pass pass

View File

@ -32,8 +32,8 @@ npm.search_no_result=No result found
npm.too_many_results=Too many results found, {HIDE_NUM} hidden, please refine your search npm.too_many_results=Too many results found, {HIDE_NUM} hidden, please refine your search
npm.install_success={NAME} installed successfully npm.install_success={NAME} installed successfully
npm.install_failed={NAME} installation failed, please check the console for more information, or visit the plugin's {HOMEPAGE} npm.install_failed={NAME} installation failed, please check the console for more information, or visit the plugin's {HOMEPAGE}
npm.remove_success={NAME} uninstalled successfully npm.uninstall_success={NAME} uninstalled successfully
npm.remove_failed={NAME} uninstallation failed npm.uninstall_failed={NAME} uninstallation failed
npm.load_failed={NAME} loading failed, please check the console for more information, or visit the plugin's {HOMEPAGE} npm.load_failed={NAME} loading failed, please check the console for more information, or visit the plugin's {HOMEPAGE}
npm.plugin_not_found={NAME} not found, please check the plugin's name npm.plugin_not_found={NAME} not found, please check the plugin's name
npm.plugin_not_installed={NAME} is not installed npm.plugin_not_installed={NAME} is not installed

View File

@ -32,8 +32,8 @@ npm.search_no_result = 検索結果がありません
npm.too_many_results = 検索結果が多すぎます。{HIDE_NUM} 件の結果が非表示になりました npm.too_many_results = 検索結果が多すぎます。{HIDE_NUM} 件の結果が非表示になりました
npm.install_success = {NAME} が正常にインストールされました npm.install_success = {NAME} が正常にインストールされました
npm.install_failed = {NAME} のインストールに失敗しました, 詳細はログを参照してください, またはプラグインの作者に連絡してください{HOMEPAGE} npm.install_failed = {NAME} のインストールに失敗しました, 詳細はログを参照してください, またはプラグインの作者に連絡してください{HOMEPAGE}
npm.remove_success = {NAME} が正常にアンインストールされました npm.uninstall_success = {NAME} が正常にアンインストールされました
npm.remove_failed = {NAME} のアンインストールに失敗しました npm.uninstall_failed = {NAME} のアンインストールに失敗しました
npm.load_failed = {NAME} の読み込みに失敗しました,詳細はログを参照してください, またはプラグインの作者に連絡してください{HOMEPAGE} npm.load_failed = {NAME} の読み込みに失敗しました,詳細はログを参照してください, またはプラグインの作者に連絡してください{HOMEPAGE}
npm.plugin_not_found = {NAME} は見つかりません,スペルをチェックしてください npm.plugin_not_found = {NAME} は見つかりません,スペルをチェックしてください
npm.plugin_not_installed = {NAME} はインストールされていません npm.plugin_not_installed = {NAME} はインストールされていません

View File

@ -32,8 +32,8 @@ npm.search_no_result=无搜索结果
npm.too_many_results=内容过多,{HIDE_NUM}项已隐藏,请限制关键字搜索 npm.too_many_results=内容过多,{HIDE_NUM}项已隐藏,请限制关键字搜索
npm.install_success={NAME} 安装成功 npm.install_success={NAME} 安装成功
npm.install_failed={NAME} 安装失败,请查看日志获取详细信息,如不能解决,请访问{HOMEPAGE}寻求帮助 npm.install_failed={NAME} 安装失败,请查看日志获取详细信息,如不能解决,请访问{HOMEPAGE}寻求帮助
npm.remove_success={NAME} 卸载成功 npm.uninstall_success={NAME} 卸载成功
npm.remove_failed={NAME} 卸载失败 npm.uninstall_failed={NAME} 卸载失败
npm.load_failed={NAME} 加载失败,请在控制台查看详细信息,检查依赖或配置是否正确,如不能解决,请访问{HOMEPAGE}寻求帮助 npm.load_failed={NAME} 加载失败,请在控制台查看详细信息,检查依赖或配置是否正确,如不能解决,请访问{HOMEPAGE}寻求帮助
npm.plugin_not_found=未在商店中找到 {NAME},请尝试更新商店信息或检查拼写 npm.plugin_not_found=未在商店中找到 {NAME},请尝试更新商店信息或检查拼写
npm.plugin_not_installed={NAME} 未安装 npm.plugin_not_installed={NAME} 未安装

View File

@ -32,8 +32,8 @@ npm.search_no_result=無搜尋結果
npm.too_many_results=結果過多,已隱藏 {HIDE_NUM} 項,請儘量精確搜尋 npm.too_many_results=結果過多,已隱藏 {HIDE_NUM} 項,請儘量精確搜尋
npm.install_success={NAME} 安裝成功 npm.install_success={NAME} 安裝成功
npm.install_failed={NAME} 安裝失敗,請查看日誌以獲取詳細資訊,如無法解決,請訪問{HOMEPAGE}尋求協助 npm.install_failed={NAME} 安裝失敗,請查看日誌以獲取詳細資訊,如無法解決,請訪問{HOMEPAGE}尋求協助
npm.remove_success={NAME} 卸載成功 npm.uninstall_success={NAME} 卸載成功
npm.remove_failed={NAME} 卸載失敗 npm.uninstall_failed={NAME} 卸載失敗
npm.load_failed={NAME} 載入失敗,請在控制台檢查詳細資訊,確認依賴項目或配置是否正確,如無法解決,請訪問{HOMEPAGE}尋求協助 npm.load_failed={NAME} 載入失敗,請在控制台檢查詳細資訊,確認依賴項目或配置是否正確,如無法解決,請訪問{HOMEPAGE}尋求協助
npm.plugin_not_found=在商店中找不到 {NAME},請嘗試更新商店資訊或檢查拼寫 npm.plugin_not_found=在商店中找不到 {NAME},請嘗試更新商店資訊或檢查拼寫
npm.plugin_not_installed={NAME} 未安裝 npm.plugin_not_installed={NAME} 未安裝

View File

@ -32,8 +32,8 @@ npm.search_no_result=没找到任何东西哦~
npm.too_many_results=好多东西,隐藏了 {HIDE_NUM} 个,搜寻更准确些吧! npm.too_many_results=好多东西,隐藏了 {HIDE_NUM} 个,搜寻更准确些吧!
npm.install_success={NAME} 安装成功啦~ npm.install_success={NAME} 安装成功啦~
npm.install_failed={NAME} 安装失败了,去 {HOMEPAGE} 寻求帮助吧! npm.install_failed={NAME} 安装失败了,去 {HOMEPAGE} 寻求帮助吧!
npm.remove_success={NAME} 卸载成功啦~ npm.uninstall_success={NAME} 卸载成功啦~
npm.remove_failed={NAME} 卸载失败了~ npm.uninstall_failed={NAME} 卸载失败了~
npm.load_failed={NAME} 装载失败了,去 {HOMEPAGE} 寻求帮助吧! npm.load_failed={NAME} 装载失败了,去 {HOMEPAGE} 寻求帮助吧!
npm.plugin_not_found=没在商店里找到 {NAME} 呢~ npm.plugin_not_found=没在商店里找到 {NAME} 呢~
npm.plugin_not_installed={NAME} 没有安装~ npm.plugin_not_installed={NAME} 没有安装~

View File

@ -32,8 +32,8 @@ npm.search_no_result=無搜尋之結果
npm.too_many_results=内容過多,{HIDE_NUM}項已隱藏,請限制關鍵字搜尋 npm.too_many_results=内容過多,{HIDE_NUM}項已隱藏,請限制關鍵字搜尋
npm.install_success={NAME} 安裝成功 npm.install_success={NAME} 安裝成功
npm.install_failed={NAME} 安裝失敗,詳情可見於日誌,如不能解決,請訪{HOMEPAGE}求助 npm.install_failed={NAME} 安裝失敗,詳情可見於日誌,如不能解決,請訪{HOMEPAGE}求助
npm.remove_success={NAME} 卸載成功 npm.uninstall_success={NAME} 卸載成功
npm.remove_failed={NAME} 卸載失敗 npm.uninstall_failed={NAME} 卸載失敗
npm.load_failed={NAME} 載入失敗,詳細信息可於控制臺查詢,檢查依賴或設置是否正確,如不能解決,請訪{HOMEPAGE}求助 npm.load_failed={NAME} 載入失敗,詳細信息可於控制臺查詢,檢查依賴或設置是否正確,如不能解決,請訪{HOMEPAGE}求助
npm.plugin_not_found=未在商店中見{NAME},可嘗試更新商店信息或檢查拼寫 npm.plugin_not_found=未在商店中見{NAME},可嘗試更新商店信息或檢查拼寫
npm.plugin_not_installed={NAME} 未安裝 npm.plugin_not_installed={NAME} 未安裝

1
src/utils/__init__.py Normal file
View File

@ -0,0 +1 @@
from .log import logger

View File

@ -7,7 +7,7 @@ from collections.abc import Iterable
import nonebot import nonebot
from pydantic import BaseModel from pydantic import BaseModel
from typing_extensions import Any from typing import Any
BaseIterable = list | tuple | set | dict BaseIterable = list | tuple | set | dict

View File

@ -5,7 +5,7 @@
import json import json
import locale import locale
import os import os
from typing_extensions import Any from typing import Any
import nonebot import nonebot

88
src/utils/log.py Normal file
View File

@ -0,0 +1,88 @@
import sys
import logging
from typing import TYPE_CHECKING
import loguru
if TYPE_CHECKING:
# avoid sphinx autodoc resolve annotation failed
# because loguru module do not have `Logger` class actually
from loguru import Logger, Record
# logger = logging.getLogger("nonebot")
logger: "Logger" = loguru.logger
"""NoneBot 日志记录器对象。
默认信息:
- 格式: `[%(asctime)s %(name)s] %(levelname)s: %(message)s`
- 等级: `INFO` 根据 `config.log_level` 配置改变
- 输出: 输出至 stdout
用法:
```python
from nonebot.log import logger
```
"""
# default_handler = logging.StreamHandler(sys.stdout)
# default_handler.setFormatter(
# logging.Formatter("[%(asctime)s %(name)s] %(levelname)s: %(message)s"))
# logger.addHandler(default_handler)
class LoguruHandler(logging.Handler): # pragma: no cover
"""logging 与 loguru 之间的桥梁,将 logging 的日志转发到 loguru。"""
def emit(self, record: logging.LogRecord):
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
frame, depth = sys._getframe(6), 6
while frame and frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(
level, record.getMessage()
)
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
default_format: str = (
"<g>{time:MM-DD HH:mm:ss}</g> "
"<lvl>[{level.icon}]</lvl> "
"<c><{name}></c> "
"{message}"
)
"""默认日志格式"""
logger.remove()
logger_id = logger.add(
sys.stdout,
level=0,
diagnose=False,
filter=default_filter,
format=default_format,
)
logger.level("DEBUG", color="<cyan>", icon="DEBU")
logger.level("INFO", color="<white>", icon="INFO")
logger.level("SUCCESS", color="<green>", icon="✅SUCC")
logger.level("WARNING", color="<yellow>", icon="WARN")
logger.level("ERROR", color="<red>", icon="ERRO")
"""默认日志处理器 id"""
__autodoc__ = {
"logger_id": False
}

View File

@ -1,20 +1,20 @@
import nonebot import nonebot
from nonebot.adapters.onebot import v11, v12 from nonebot.adapters.onebot import v11, v12
from typing_extensions import Any from typing import Any
from .tools import de_escape, encode_url from .tools import de_escape, encode_url
from .typing import T_Bot, T_MessageEvent from .ly_typing import T_Bot, T_MessageEvent
async def send_markdown(markdown: str, bot: T_Bot, *, message_type: str = None, session_id: str | int = None, event: T_MessageEvent = None, **kwargs) -> dict[str, Any]: async def send_markdown(markdown: str, bot: T_Bot, *, message_type: str = None, session_id: str | int = None, event: T_MessageEvent = None, **kwargs) -> dict[
str, Any]:
formatted_md = de_escape(markdown).replace("\n", r"\n").replace("\"", r'\\\"') formatted_md = de_escape(markdown).replace("\n", r"\n").replace("\"", r'\\\"')
if event is not None and message_type is None: if event is not None and message_type is None:
message_type = event.message_type message_type = event.message_type
session_id = event.user_id if event.message_type == "private" else event.group_id session_id = event.user_id if event.message_type == "private" else event.group_id
try: try:
forward_data = await bot.call_api( forward_id = await bot.call_api(
api="send_private_forward_msg", api="send_forward_msg",
user_id=bot.self_id,
messages=[ messages=[
v11.MessageSegment( v11.MessageSegment(
type="node", type="node",
@ -27,7 +27,7 @@ async def send_markdown(markdown: str, bot: T_Bot, *, message_type: str = None,
"data": { "data": {
"content": '{"content":"%s"}' % formatted_md "content": '{"content":"%s"}' % formatted_md
} }
} },
] ]
}, },
) )
@ -41,15 +41,14 @@ async def send_markdown(markdown: str, bot: T_Bot, *, message_type: str = None,
v11.MessageSegment( v11.MessageSegment(
type="longmsg", type="longmsg",
data={ data={
"id": forward_data["forward_id"] "id": forward_id
} }
), ),
], ],
**kwargs **kwargs
) )
except Exception as e: except Exception as e:
nonebot.logger.warning("send_markdown error, send as plane text: %s" % e) nonebot.logger.warning("send_markdown error, send as plain text: %s" % e.__repr__())
if isinstance(bot, v11.Bot): if isinstance(bot, v11.Bot):
data = await bot.send_msg( data = await bot.send_msg(
message_type=message_type, message_type=message_type,

View File

@ -1,6 +1,6 @@
from nonebot.adapters.onebot import v11 from nonebot.adapters.onebot import v11
from src.utils.typing import T_GroupMessageEvent, T_MessageEvent from src.utils.ly_typing import T_GroupMessageEvent, T_MessageEvent
GROUP_ADMIN = v11.GROUP_ADMIN GROUP_ADMIN = v11.GROUP_ADMIN
GROUP_OWNER = v11.GROUP_OWNER GROUP_OWNER = v11.GROUP_OWNER

View File

@ -2,7 +2,7 @@ import os
import nonebot import nonebot
import yaml import yaml
from typing_extensions import Any from typing import Any
from src.utils.data import LiteModel from src.utils.data import LiteModel