mirror of
https://github.com/LiteyukiStudio/LiteyukiBot.git
synced 2024-11-22 20:17:39 +08:00
feat: 配置项目的热修改
This commit is contained in:
parent
f23567194c
commit
aed63c34c9
69
README.md
69
README.md
@ -10,78 +10,11 @@
|
||||
- 全新可视化`npm`包管理,支持一键安装插件
|
||||
- 支持OneBotv11/12标准通信,且使用`Alconna`命令解析,不再局限于OneBot
|
||||
|
||||
## 1.安装和部署
|
||||
### [文档](https://bot.liteyuki.icu)
|
||||
|
||||
1. 安装 `Git` 和 `Python3.10+` 环境
|
||||
2. 克隆项目 `git clone https://github.com/snowykami/LiteyukiBot` (无法连接可以用`https://gitee.com/snowykami/LiteyukiBot`)
|
||||
3. 切换目录`cd LiteyukiBot`
|
||||
4. 安装依赖`pip install -r requirements.txt`(如果多个Python环境请指定后安装`pythonx -m pip install -r requirements.txt`)
|
||||
5. 启动`python main.py`
|
||||
|
||||
## 2. 配置
|
||||
|
||||
### 轻雪配置项(Nonebot插件配置项也可以写在此,与dotenv格式不同,应为小写)
|
||||
|
||||
如果不确定字段的含义,请不要修改(部分在自动生成配置文件中未列出,需手动添加)
|
||||
|
||||
```yaml
|
||||
# 生成文件的配置项
|
||||
command_start: [ "/", " " ] # 指令前缀
|
||||
host: 127.0.0.1 # 监听地址
|
||||
port: 20216 # 绑定端口
|
||||
nickname: [ "liteyuki" ] # 机器人昵称
|
||||
superusers: [ "1919810" ] # 超级用户
|
||||
# 未列出的配置项(如要自定义请手动修改)
|
||||
onebot_access_token: "" # Onebot访问令牌[具体请看](https://onebot.adapters.nonebot.dev/docs/guide/configuration)
|
||||
default_language: "zh-CN" # 默认语言
|
||||
log_level: "INFO" # 日志等级
|
||||
log_icon: true # 是否显示日志等级图标(某些控制台不可用)
|
||||
auto_report: true # 是否自动上报问题给轻雪服务器,仅包含硬件信息和运行软件版本
|
||||
|
||||
# 其他Nonebot插件的配置项
|
||||
custom_config_1: "custom_value1"
|
||||
custom_config_2: "custom_value2"
|
||||
...
|
||||
```
|
||||
|
||||
### Onebot实现端配置
|
||||
|
||||
不同的实现端给出的字段可能不同,但是基本上都是一样的,这里给出一个参考值
|
||||
|
||||
| 字段 | 参考值 | 说明 |
|
||||
|-------------|--------------------------|----------------------------------|
|
||||
| 协议 | 反向WebSocket | 推荐使用反向ws协议进行通信,即轻雪作为服务端 |
|
||||
| 地址 | ws://`address`/onebot/v11 | 地址取决于配置文件,本机默认为`127.0.0.1:20216` |
|
||||
| AccessToken | `""` | 如果你给轻雪配置了`AccessToken`,请在此填写相同的值 |
|
||||
|
||||
## 3.其他
|
||||
|
||||
### 常见问题
|
||||
|
||||
- 设备上Python环境太乱了,pip和python不对应怎么办?
|
||||
- 请使用`/path/to/python -m pip install -r requirements.txt`来安装依赖,
|
||||
然后用`/path/to/python main.py`来启动Bot,
|
||||
其中`/path/to/python`是你要用来运行Bot可执行文件
|
||||
- 为什么我启动后机器人没有反应?
|
||||
- 请检查配置文件的`command_start`或`superusers`,确认你有权限使用命令并按照正确的命令发送
|
||||
|
||||
- 怎么登录QQ等聊天平台
|
||||
- 你有这个问题说明你不是很了解这个项目,本项目不负责实现登录功能,只负责处理消息
|
||||
你需要使用Onebot标准的实现端来连接到轻雪并将消息上报给轻雪,下面已经列出一些推荐的实现端
|
||||
|
||||
#### 推荐方案(QQ)
|
||||
|
||||
1. [Lagrange.OneBot](https://github.com/KonataDev/Lagrange.Core),目前点按交互目前仅支持Lagrange
|
||||
2. [LiteLoaderNTQQ+LLOneBot](https://github.com/LLOneBot/LLOneBot),基于NTQQ的Onebot实现
|
||||
3. 云崽的`icqq-plugin`和`ws-plugin`进行通信
|
||||
4. `Go-cqhttp`(目前已经半死不活了)
|
||||
5. 人工实现的`Onebot`协议,自己整一个WebSocket客户端,看着QQ的消息,然后给轻雪传输数据
|
||||
|
||||
#### 推荐方案(Minecraft)
|
||||
|
||||
1. 我们有专门为Minecraft开发的服务器Bot,支持OnebotV11/12标准,详细请看[MinecraftOneBot](https://github.com/snowykami/MinecraftOnebot)
|
||||
|
||||
使用其他项目连接请先自行查阅文档,若有困难请联系对应开发者而不是Liteyuki的开发者
|
||||
|
||||
## 4.用户协议
|
||||
|
||||
|
37
docs/deployment/fandq.md
Normal file
37
docs/deployment/fandq.md
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
title: 答疑
|
||||
icon: object-group
|
||||
order: 3
|
||||
category: 使用指南
|
||||
tag:
|
||||
- 配置
|
||||
- 部署
|
||||
---
|
||||
|
||||
### 常见问题
|
||||
|
||||
- 设备上Python环境太乱了,pip和python不对应怎么办?
|
||||
- 请使用`/path/to/python -m pip install -r requirements.txt`来安装依赖,
|
||||
然后用`/path/to/python main.py`来启动Bot,
|
||||
其中`/path/to/python`是你要用来运行Bot的可执行文件
|
||||
- 为什么我启动后机器人没有反应?
|
||||
- 请检查配置文件的`command_start`或`superusers`,确认你有权限使用命令并按照正确的命令发送
|
||||
|
||||
- 怎么登录聊天平台,例如QQ
|
||||
- 你有这个问题说明你不是很了解这个项目,本项目不负责实现登录功能,只负责处理和回应消息,登录功能由实现端(协议端)提供,
|
||||
实现端本身不负责处理响应逻辑,将消息按照OneBot标准处理好上报给轻雪
|
||||
你需要使用Onebot标准的实现端来连接到轻雪并将消息上报给轻雪,下面已经列出一些推荐的实现端
|
||||
|
||||
#### 推荐方案(QQ)
|
||||
|
||||
1. [Lagrange.OneBot](https://github.com/KonataDev/Lagrange.Core),目前Markdown点按交互目前仅支持Lagrange
|
||||
2. [LiteLoaderNTQQ+LLOneBot](https://github.com/LLOneBot/LLOneBot),基于NTQQ的Onebot实现
|
||||
3. 云崽的`icqq-plugin`和`ws-plugin`进行通信
|
||||
4. `Go-cqhttp`(目前已经半死不活了)
|
||||
5. 人工实现的`Onebot`协议,自己整一个WebSocket客户端,看着QQ的消息,然后给轻雪传输数据
|
||||
|
||||
#### 推荐方案(Minecraft)
|
||||
|
||||
1. 我们有专门为Minecraft开发的服务器Bot,支持OnebotV11/12标准,详细请看[MinecraftOneBot](https://github.com/snowykami/MinecraftOnebot)
|
||||
|
||||
使用其他项目连接请先自行查阅文档,若有困难请联系对应开发者而不是Liteyuki的开发者
|
@ -5,34 +5,41 @@ order: 1
|
||||
category: 使用手册
|
||||
---
|
||||
|
||||
## 基础插件命令
|
||||
|
||||
## 内置插件命令
|
||||
#### 命令前有[S]的表示仅超级用户可用,[O]和[A]分别为群主和群管可用
|
||||
|
||||
### 轻雪`liteyuki`
|
||||
|
||||
```shell
|
||||
reload-liteyuki # 重载轻雪
|
||||
update-liteyuki # 更新轻雪
|
||||
liteyuki # 查看轻雪信息
|
||||
[S]reload-liteyuki # 重载轻雪
|
||||
[S]update-liteyuki # 更新轻雪
|
||||
[S]liteyuki # 查看轻雪信息
|
||||
[S]config set <key> value # 添加配置项,若存在则会覆盖,输入值会被执行,以便于转换为正确的值,"10"和10是不一样的
|
||||
[S]config get [key] # 查询配置项,不带key返回配置项列表,推荐私聊使用
|
||||
# 上述两个命令修改的配置项在数据库中保存,但是优先级低于配置文件,如果配置文件中存在相同的配置项,将会使用配置文件中的配置
|
||||
------
|
||||
别名: reload-liteyuki 重启轻雪, update-liteyuki 更新轻雪, config 配置, set 设置, get 查询
|
||||
```
|
||||
|
||||
### 轻雪Nonebot插件管理 `liteyuki_npm`
|
||||
|
||||
```shell
|
||||
npm update # 更新插件索引
|
||||
npm install <plugin_name> # 安装插件
|
||||
npm uninstall <plugin_name> # 卸载插件
|
||||
npm search <keywords...> # 搜索插件
|
||||
[S]npm update # 更新插件索引
|
||||
[S]npm install <plugin_name> # 安装插件
|
||||
[S]npm uninstall <plugin_name> # 卸载插件
|
||||
[S]npm search <keywords...> # 通过关键词搜索插件
|
||||
------
|
||||
别名: npm 插件, update 更新, install 安装, uninstall 卸载, search 搜索
|
||||
```
|
||||
|
||||
```shell
|
||||
enable <plugin_name> # 启用插件
|
||||
disable <plugin_name> # 禁用插件
|
||||
enable-global <plugin_name> # 全局启用插件
|
||||
disable-global <plugin_name> # 全局禁用插件
|
||||
[SOA]enable <plugin_name> # 启用插件
|
||||
[SOA]disable <plugin_name> # 禁用插件
|
||||
[S]enable-global <plugin_name> # 全局启用插件
|
||||
[S]disable-global <plugin_name> # 全局禁用插件
|
||||
list-plugin # 列出所有插件
|
||||
# 受限于Nonebot的钩子函数,目前只能阻断消息事件的传入,对于主动推送消息的插件,无法将其阻止
|
||||
------
|
||||
别名: enable 启用, disable 停用, enable-global 全局启用, disable-global 全局停用, list-plugin 列出插件/插件列表
|
||||
```
|
||||
|
@ -4,3 +4,18 @@ icon: laptop-code
|
||||
order: 2
|
||||
category: 使用手册
|
||||
---
|
||||
|
||||
|
||||
## 功能插件命令
|
||||
|
||||
### 轻雪天气`liteyuki_weather`
|
||||
配置项
|
||||
```yaml
|
||||
weather-key # 和风天气的天气key
|
||||
```
|
||||
命令
|
||||
```shell
|
||||
weather <keywords...> # 查询目标地天气,例如:"天气 北京 海淀", "weather Tokyo Shinjuku"
|
||||
bind-city <keywords...> # 绑定查询城市,个人全局生效
|
||||
别名:weather 天气
|
||||
```
|
@ -1,17 +1,23 @@
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
import aiofiles
|
||||
import yaml
|
||||
from nonebot import require
|
||||
from nonebot.permission import SUPERUSER
|
||||
from git import Repo
|
||||
|
||||
from liteyuki.utils.config import config
|
||||
from liteyuki.utils.config import config, load_from_yaml
|
||||
from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent
|
||||
|
||||
from liteyuki.utils.language import get_user_lang
|
||||
from liteyuki.utils.message import Markdown as md, send_markdown
|
||||
|
||||
from .reloader import Reloader
|
||||
from liteyuki.utils.data_manager import StoredConfig, common_db
|
||||
|
||||
require("nonebot_plugin_alconna")
|
||||
from nonebot_plugin_alconna import on_alconna, Alconna
|
||||
from nonebot_plugin_alconna import on_alconna, Alconna, Args, Subcommand, Arparma
|
||||
|
||||
cmd_liteyuki = on_alconna(
|
||||
Alconna(
|
||||
@ -34,6 +40,24 @@ reload_liteyuki = on_alconna(
|
||||
permission=SUPERUSER
|
||||
)
|
||||
|
||||
cmd_config = on_alconna(
|
||||
Alconna(
|
||||
["config", "配置"],
|
||||
Subcommand(
|
||||
"set",
|
||||
Args["key", str]["value", Any],
|
||||
alias=["设置"],
|
||||
|
||||
),
|
||||
Subcommand(
|
||||
"get",
|
||||
Args["key", str, None],
|
||||
alias=["查询"]
|
||||
)
|
||||
),
|
||||
permission=SUPERUSER
|
||||
)
|
||||
|
||||
|
||||
@cmd_liteyuki.handle()
|
||||
async def _(bot: T_Bot):
|
||||
@ -64,3 +88,36 @@ async def _(bot: T_Bot, event: T_MessageEvent):
|
||||
async def _():
|
||||
await reload_liteyuki.send("Liteyuki reloading")
|
||||
Reloader.reload(3)
|
||||
|
||||
|
||||
@cmd_config.handle()
|
||||
async def _(result: Arparma, event: T_MessageEvent, bot: T_Bot):
|
||||
ulang = get_user_lang(str(event.user_id))
|
||||
stored_config: StoredConfig = common_db.first(StoredConfig(), default=StoredConfig())
|
||||
if result.subcommands.get("set"):
|
||||
key, value = result.subcommands.get("set").args.get("key"), result.subcommands.get("set").args.get("value")
|
||||
try:
|
||||
value = eval(value)
|
||||
except:
|
||||
pass
|
||||
stored_config.config[key] = value
|
||||
common_db.upsert(stored_config)
|
||||
await cmd_config.finish(f"{ulang.get('liteyuki.config_set_success', KEY=key, VAL=value)}")
|
||||
elif result.subcommands.get("get"):
|
||||
key = result.subcommands.get("get").args.get("key")
|
||||
file_config = load_from_yaml("config.yml")
|
||||
reply = f"{ulang.get('liteyuki.current_config')}"
|
||||
if key:
|
||||
reply += f"```dotenv\n{key}={file_config.get(key, stored_config.config.get(key))}\n```"
|
||||
else:
|
||||
reply = f"{ulang.get('liteyuki.current_config')}"
|
||||
reply += f"\n{ulang.get('liteyuki.static_config')}\n```dotenv"
|
||||
for k, v in file_config.items():
|
||||
reply += f"\n{k}={v}"
|
||||
reply += "\n```"
|
||||
if len(stored_config.config) > 0:
|
||||
reply += f"\n{ulang.get('liteyuki.stored_config')}\n```dotenv"
|
||||
for k, v in stored_config.config.items():
|
||||
reply += f"\n{k}={v}"
|
||||
reply += "\n```"
|
||||
await send_markdown(reply, bot, event=event)
|
||||
|
@ -9,6 +9,7 @@ log.success=Success
|
||||
liteyuki.restart=Restart
|
||||
liteyuki.restart_now=Restart now
|
||||
liteyuki.update_restart=Update completely, You can {RESTART} or later to apply the changes
|
||||
liteyuki.current_config=Current Config
|
||||
|
||||
main.current_language=Current config language: {LANG}
|
||||
main.enable_webdash=Web dashboard is enabled: {URL}
|
||||
|
@ -9,6 +9,10 @@ log.success=成功
|
||||
liteyuki.restart=重启
|
||||
liteyuki.restart_now=立即重启
|
||||
liteyuki.update_restart=更新完成,你可以{RESTART}或稍后手动重启以应用这些更新
|
||||
liteyuki.current_config=当前配置项如下
|
||||
liteyuki.static_config=静态文件配置项
|
||||
liteyuki.stored_config=储存的配置项
|
||||
liteyuki.config_set_success=配置项 {KEY}={VAL} 设置成功
|
||||
|
||||
main.current_language=当前配置语言为: {LANG}
|
||||
main.enable_webdash=已启用网页监控面板: {URL}
|
||||
|
@ -15,9 +15,9 @@ class LiteModel(BaseModel):
|
||||
|
||||
def dump(self, *args, **kwargs):
|
||||
if pydantic.__version__ < "1.8.2":
|
||||
return self.dict(by_alias=True)
|
||||
return self.dict(*args, **kwargs)
|
||||
else:
|
||||
return self.model_dump(by_alias=True)
|
||||
return self.model_dump(*args, **kwargs)
|
||||
|
||||
|
||||
class Database:
|
||||
@ -30,7 +30,7 @@ class Database:
|
||||
self.conn = sqlite3.connect(db_name)
|
||||
self.cursor = self.conn.cursor()
|
||||
|
||||
def first(self, model: LiteModel, condition: str, *args: Any, default: Any = None) -> LiteModel | Any | None:
|
||||
def first(self, model: LiteModel, condition: str = "", *args: Any, default: Any = None) -> LiteModel | Any | None:
|
||||
"""查询第一个
|
||||
Args:
|
||||
model: 数据模型实例
|
||||
|
@ -43,9 +43,14 @@ class GlobalPlugin(LiteModel):
|
||||
enabled: bool = Field(True, alias="enabled")
|
||||
|
||||
|
||||
class StoredConfig(LiteModel):
|
||||
TABLE_NAME = "stored_config"
|
||||
config: dict = {}
|
||||
|
||||
|
||||
def auto_migrate():
|
||||
print("Migrating databases...")
|
||||
user_db.auto_migrate(User())
|
||||
group_db.auto_migrate(Group())
|
||||
plugin_db.auto_migrate(InstalledPlugin(), GlobalPlugin())
|
||||
common_db.auto_migrate(GlobalPlugin())
|
||||
common_db.auto_migrate(GlobalPlugin(), StoredConfig())
|
||||
|
||||
|
@ -8,7 +8,7 @@ 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]:
|
||||
formatted_md = v11.unescape(markdown).replace("\n", r"\n").replace("\"", r'\\\"')
|
||||
formatted_md = v11.unescape(markdown).replace("\n", r"\n").replace('"', r'\\\"')
|
||||
if event is not None and message_type is None:
|
||||
message_type = event.message_type
|
||||
session_id = event.user_id if event.message_type == "private" else event.group_id
|
||||
|
Loading…
Reference in New Issue
Block a user