diff --git a/.gitignore b/.gitignore
index 4e1606a54..e51abc5cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -193,9 +193,8 @@ cython_debug/
# jieba
jieba.cache
-
-# vscode
-/.vscode
+# .vscode
+!.vscode/settings.json
# direnv
/.direnv
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..23fd35f0e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "editor.formatOnSave": true
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 5ae9c5f2c..f4ebca07d 100644
--- a/README.md
+++ b/README.md
@@ -29,16 +29,17 @@
-> ⚠️ **注意事项**
+> [!WARNING]
> - 项目处于活跃开发阶段,代码可能随时更改
> - 文档未完善,有问题可以提交 Issue 或者 Discussion
> - QQ机器人存在被限制风险,请自行了解,谨慎使用
> - 由于持续迭代,可能存在一些已知或未知的bug
> - 由于开发中,可能消耗较多token
-**交流群**: 766798517 一群人较多,建议加下面的(开发和建议相关讨论)不一定有空回复,会优先写文档和代码
-**交流群**: 571780722 另一个群(开发和建议相关讨论)不一定有空回复,会优先写文档和代码
-**交流群**: 1035228475 另一个群(开发和建议相关讨论)不一定有空回复,会优先写文档和代码
+## 💬交流群
+- [一群](https://qm.qq.com/q/VQ3XZrWgMs) 766798517 ,建议加下面的(开发和建议相关讨论)不一定有空回复,会优先写文档和代码
+- [二群](https://qm.qq.com/q/RzmCiRtHEW) 571780722 (开发和建议相关讨论)不一定有空回复,会优先写文档和代码
+- [三群](https://qm.qq.com/q/wlH5eT8OmQ) 1035228475(开发和建议相关讨论)不一定有空回复,会优先写文档和代码
**其他平台版本**
@@ -51,7 +52,7 @@
### 部署方式
-- 📦 **Windows 一键傻瓜式部署**:请运行项目根目录中的 ```run.bat```,部署完成后请参照后续配置指南进行配置
+- 📦 **Windows 一键傻瓜式部署**:请运行项目根目录中的 `run.bat`,部署完成后请参照后续配置指南进行配置
- [📦 Windows 手动部署指南 ](docs/manual_deploy_windows.md)
@@ -139,9 +140,10 @@
## 📌 注意事项
-SengokuCola已得到大脑升级
-> ⚠️ **警告**:本应用生成内容来自人工智能模型,由 AI 生成,请仔细甄别,请勿用于违反法律的用途,AI生成内容不代表本人观点和立场。
+SengokuCola纯编程外行,面向cursor编程,很多代码史一样多多包涵
+> [!WARNING]
+> 本应用生成内容来自人工智能模型,由 AI 生成,请仔细甄别,请勿用于违反法律的用途,AI生成内容不代表本人观点和立场。
## 致谢
[nonebot2](https://github.com/nonebot/nonebot2): 跨平台 Python 异步聊天机器人框架
diff --git a/bot.py b/bot.py
index c2ed3dfdf..471a98eaf 100644
--- a/bot.py
+++ b/bot.py
@@ -1,9 +1,12 @@
+import asyncio
import os
import shutil
import sys
import nonebot
import time
+
+import uvicorn
from dotenv import load_dotenv
from loguru import logger
from nonebot.adapters.onebot.v11 import Adapter
@@ -12,6 +15,8 @@ import platform
# 获取没有加载env时的环境变量
env_mask = {key: os.getenv(key) for key in os.environ}
+uvicorn_server = None
+
def easter_egg():
# 彩蛋
@@ -100,10 +105,12 @@ def load_logger():
"#777777>|> {name:.<8}:{function:.<8}:{line: >4} -> {message}",
colorize=True,
- level=os.getenv("LOG_LEVEL", "DEBUG") # 根据环境设置日志级别,默认为INFO
+ level=os.getenv("LOG_LEVEL", "INFO"), # 根据环境设置日志级别,默认为INFO
+ filter=lambda record: "nonebot" not in record["name"]
)
+
def scan_provider(env_config: dict):
provider = {}
@@ -138,7 +145,39 @@ def scan_provider(env_config: dict):
raise ValueError(f"请检查 '{provider_name}' 提供商配置是否丢失 BASE_URL 或 KEY 环境变量")
-if __name__ == "__main__":
+async def graceful_shutdown():
+ try:
+ global uvicorn_server
+ if uvicorn_server:
+ uvicorn_server.force_exit = True # 强制退出
+ await uvicorn_server.shutdown()
+
+ tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
+ for task in tasks:
+ task.cancel()
+ await asyncio.gather(*tasks, return_exceptions=True)
+
+ except Exception as e:
+ logger.error(f"麦麦关闭失败: {e}")
+
+
+async def uvicorn_main():
+ global uvicorn_server
+ config = uvicorn.Config(
+ app="__main__:app",
+ host=os.getenv("HOST", "127.0.0.1"),
+ port=int(os.getenv("PORT", 8080)),
+ reload=os.getenv("ENVIRONMENT") == "dev",
+ timeout_graceful_shutdown=5,
+ log_config=None,
+ access_log=False
+ )
+ server = uvicorn.Server(config)
+ uvicorn_server = server
+ await server.serve()
+
+
+def raw_main():
# 利用 TZ 环境变量设定程序工作的时区
# 仅保证行为一致,不依赖 localtime(),实际对生产环境几乎没有作用
if platform.system().lower() != 'windows':
@@ -165,10 +204,30 @@ if __name__ == "__main__":
nonebot.init(**base_config, **env_config)
# 注册适配器
+ global driver
driver = nonebot.get_driver()
driver.register_adapter(Adapter)
# 加载插件
nonebot.load_plugins("src/plugins")
- nonebot.run()
+
+if __name__ == "__main__":
+
+ try:
+ raw_main()
+
+ global app
+ app = nonebot.get_asgi()
+
+ loop = asyncio.new_event_loop()
+ asyncio.set_event_loop(loop)
+ loop.run_until_complete(uvicorn_main())
+ except KeyboardInterrupt:
+ logger.warning("麦麦会努力做的更好的!正在停止中......")
+ except Exception as e:
+ logger.error(f"主程序异常: {e}")
+ finally:
+ loop.run_until_complete(graceful_shutdown())
+ loop.close()
+ logger.info("进程终止完毕,麦麦开始休眠......下次再见哦!")
diff --git a/docker-compose.yml b/docker-compose.yml
index 512558558..227df606b 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -6,8 +6,6 @@ services:
- NAPCAT_UID=${NAPCAT_UID}
- NAPCAT_GID=${NAPCAT_GID} # 让 NapCat 获取当前用户 GID,UID,防止权限问题
ports:
- - 3000:3000
- - 3001:3001
- 6099:6099
restart: unless-stopped
volumes:
@@ -19,7 +17,7 @@ services:
mongodb:
container_name: mongodb
environment:
- - tz=Asia/Shanghai
+ - TZ=Asia/Shanghai
# - MONGO_INITDB_ROOT_USERNAME=your_username
# - MONGO_INITDB_ROOT_PASSWORD=your_password
expose:
diff --git a/docs/docker_deploy.md b/docs/docker_deploy.md
index 3958d2fc4..db759dfd0 100644
--- a/docs/docker_deploy.md
+++ b/docs/docker_deploy.md
@@ -1,67 +1,97 @@
# 🐳 Docker 部署指南
-## 部署步骤(推荐,但不一定是最新)
+## 部署步骤 (推荐,但不一定是最新)
+
+**"更新镜像与容器"部分在本文档 [Part 6](#6-更新镜像与容器)**
+
+### 0. 前提说明
+
+**本文假设读者已具备一定的 Docker 基础知识。若您对 Docker 不熟悉,建议先参考相关教程或文档进行学习,或选择使用 [📦Linux手动部署指南](./manual_deploy_linux.md) 或 [📦Windows手动部署指南](./manual_deploy_windows.md) 。**
-### 1. 获取Docker配置文件:
+### 1. 获取Docker配置文件
+
+- 建议先单独创建好一个文件夹并进入,作为工作目录
```bash
wget https://raw.githubusercontent.com/SengokuCola/MaiMBot/main/docker-compose.yml -O docker-compose.yml
```
-- 若需要启用MongoDB数据库的用户名和密码,可进入docker-compose.yml,取消MongoDB处的注释并修改变量`=`后方的值为你的用户名和密码\
-修改后请注意在之后配置`.env.prod`文件时指定MongoDB数据库的用户名密码
+- 若需要启用MongoDB数据库的用户名和密码,可进入docker-compose.yml,取消MongoDB处的注释并修改变量旁 `=` 后方的值为你的用户名和密码\
+修改后请注意在之后配置 `.env.prod` 文件时指定MongoDB数据库的用户名密码
-### 2. 启动服务:
+### 2. 启动服务
-- **!!! 请在第一次启动前确保当前工作目录下`.env.prod`与`bot_config.toml`文件存在 !!!**\
+- **!!! 请在第一次启动前确保当前工作目录下 `.env.prod` 与 `bot_config.toml` 文件存在 !!!**\
由于Docker文件映射行为的特殊性,若宿主机的映射路径不存在,可能导致意外的目录创建,而不会创建文件,由于此处需要文件映射到文件,需提前确保文件存在且路径正确,可使用如下命令:
+
```bash
touch .env.prod
touch bot_config.toml
```
- 启动Docker容器:
+
```bash
NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose up -d
+# 旧版Docker中可能找不到docker compose,请使用docker-compose工具替代
+NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose up -d
```
-- 旧版Docker中可能找不到docker compose,请使用docker-compose工具替代
+### 3. 修改配置并重启Docker
-### 3. 修改配置并重启Docker:
-
-- 请前往 [🎀 新手配置指南](docs/installation_cute.md) 或 [⚙️ 标准配置指南](docs/installation_standard.md) 完成`.env.prod`与`bot_config.toml`配置文件的编写\
-**需要注意`.env.prod`中HOST处IP的填写,Docker中部署和系统中直接安装的配置会有所不同**
+- 请前往 [🎀新手配置指南](./installation_cute.md) 或 [⚙️标准配置指南](./installation_standard.md) 完成 `.env.prod` 与 `bot_config.toml` 配置文件的编写\
+**需要注意 `.env.prod` 中HOST处IP的填写,Docker中部署和系统中直接安装的配置会有所不同**
- 重启Docker容器:
+
```bash
-docker restart maimbot # 若修改过容器名称则替换maimbot为你自定的名臣
+docker restart maimbot # 若修改过容器名称则替换maimbot为你自定的名称
```
- 下方命令可以但不推荐,只是同时重启NapCat、MongoDB、MaiMBot三个服务
+
```bash
NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose restart
+# 旧版Docker中可能找不到docker compose,请使用docker-compose工具替代
+NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose restart
```
-- 旧版Docker中可能找不到docker compose,请使用docker-compose工具替代
-
### 4. 登入NapCat管理页添加反向WebSocket
-- 在浏览器地址栏输入`http://<宿主机IP>:6099/`进入NapCat的管理Web页,添加一个Websocket客户端
+- 在浏览器地址栏输入 `http://<宿主机IP>:6099/` 进入NapCat的管理Web页,添加一个Websocket客户端
+
> 网络配置 -> 新建 -> Websocket客户端
-- Websocket客户端的名称自定,URL栏填入`ws://maimbot:8080/onebot/v11/ws`,启用并保存即可\
+- Websocket客户端的名称自定,URL栏填入 `ws://maimbot:8080/onebot/v11/ws`,启用并保存即可\
(若修改过容器名称则替换maimbot为你自定的名称)
-### 5. 愉快地和麦麦对话吧!
+### 5. 部署完成,愉快地和麦麦对话吧!
+
+
+### 6. 更新镜像与容器
+
+- 拉取最新镜像
+
+```bash
+docker-compose pull
+```
+
+- 执行启动容器指令,该指令会自动重建镜像有更新的容器并启动
+
+```bash
+NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose up -d
+# 旧版Docker中可能找不到docker compose,请使用docker-compose工具替代
+NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose up -d
+```
## ⚠️ 注意事项
- 目前部署方案仍在测试中,可能存在未知问题
- 配置文件中的API密钥请妥善保管,不要泄露
-- 建议先在测试环境中运行,确认无误后再部署到生产环境
\ No newline at end of file
+- 建议先在测试环境中运行,确认无误后再部署到生产环境
\ No newline at end of file
diff --git a/docs/installation_standard.md b/docs/installation_standard.md
index ec5a05149..03b66dc46 100644
--- a/docs/installation_standard.md
+++ b/docs/installation_standard.md
@@ -8,7 +8,7 @@
## API配置说明
-`.env.prod`和`bot_config.toml`中的API配置关系如下:
+`.env.prod` 和 `bot_config.toml` 中的API配置关系如下:
### 在.env.prod中定义API凭证:
```ini
diff --git a/docs/manual_deploy_linux.md b/docs/manual_deploy_linux.md
index d310ffc59..41f0390b8 100644
--- a/docs/manual_deploy_linux.md
+++ b/docs/manual_deploy_linux.md
@@ -66,7 +66,7 @@ pip install -r requirements.txt
## 数据库配置
### 3️⃣ **安装并启动MongoDB**
-- 安装与启动:Debian参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-debian/),Ubuntu参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/)
+- 安装与启动: Debian参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-debian/),Ubuntu参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/)
- 默认连接本地27017端口
---
@@ -76,15 +76,14 @@ pip install -r requirements.txt
- 参考[NapCat官方文档](https://www.napcat.wiki/guide/boot/Shell#napcat-installer-linux%E4%B8%80%E9%94%AE%E4%BD%BF%E7%94%A8%E8%84%9A%E6%9C%AC-%E6%94%AF%E6%8C%81ubuntu-20-debian-10-centos9)安装
-- 使用QQ小号登录,添加反向WS地址:
-`ws://127.0.0.1:8080/onebot/v11/ws`
+- 使用QQ小号登录,添加反向WS地址: `ws://127.0.0.1:8080/onebot/v11/ws`
---
## 配置文件设置
### 5️⃣ **配置文件设置,让麦麦Bot正常工作**
-- 修改环境配置文件:`.env.prod`
-- 修改机器人配置文件:`bot_config.toml`
+- 修改环境配置文件: `.env.prod`
+- 修改机器人配置文件: `bot_config.toml`
---
@@ -107,9 +106,9 @@ python3 bot.py
---
## 常见问题
-🔧 权限问题:在命令前加`sudo`
-🔌 端口占用:使用`sudo lsof -i :8080`查看端口占用
-🛡️ 防火墙:确保8080/27017端口开放
+🔧 权限问题: 在命令前加 `sudo`
+🔌 端口占用: 使用 `sudo lsof -i :8080` 查看端口占用
+🛡️ 防火墙: 确保8080/27017端口开放
```bash
sudo ufw allow 8080/tcp
sudo ufw allow 27017/tcp
diff --git a/docs/manual_deploy_windows.md b/docs/manual_deploy_windows.md
index 86238bcd4..eebdc4f41 100644
--- a/docs/manual_deploy_windows.md
+++ b/docs/manual_deploy_windows.md
@@ -30,7 +30,7 @@
在创建虚拟环境之前,请确保你的电脑上安装了Python 3.9及以上版本。如果没有,可以按以下步骤安装:
-1. 访问Python官网下载页面:https://www.python.org/downloads/release/python-3913/
+1. 访问Python官网下载页面: https://www.python.org/downloads/release/python-3913/
2. 下载Windows安装程序 (64-bit): `python-3.9.13-amd64.exe`
3. 运行安装程序,并确保勾选"Add Python 3.9 to PATH"选项
4. 点击"Install Now"开始安装
@@ -79,11 +79,11 @@ pip install -r requirements.txt
### 3️⃣ **配置NapCat,让麦麦bot与qq取得联系**
- 安装并登录NapCat(用你的qq小号)
-- 添加反向WS:`ws://127.0.0.1:8080/onebot/v11/ws`
+- 添加反向WS: `ws://127.0.0.1:8080/onebot/v11/ws`
### 4️⃣ **配置文件设置,让麦麦Bot正常工作**
-- 修改环境配置文件:`.env.prod`
-- 修改机器人配置文件:`bot_config.toml`
+- 修改环境配置文件: `.env.prod`
+- 修改机器人配置文件: `bot_config.toml`
### 5️⃣ **启动麦麦机器人**
- 打开命令行,cd到对应路径
diff --git a/flake.nix b/flake.nix
index 54737d640..3586857f0 100644
--- a/flake.nix
+++ b/flake.nix
@@ -22,6 +22,7 @@
pythonEnv = pkgs.python3.withPackages (
ps: with ps; [
+ ruff
pymongo
python-dotenv
pydantic
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index e54dcdacd..000000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,23 +0,0 @@
-[project]
-name = "Megbot"
-version = "0.1.0"
-description = "New Bot Project"
-
-[tool.nonebot]
-plugins = ["src.plugins.chat"]
-plugin_dirs = ["src/plugins"]
-
-[tool.ruff]
-# 设置 Python 版本
-target-version = "py39"
-
-# 启用的规则
-select = [
- "E", # pycodestyle 错误
- "F", # pyflakes
- "I", # isort
- "B", # flake8-bugbear
-]
-
-# 行长度设置
-line-length = 88
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 4f969682f..0acaade5e 100644
Binary files a/requirements.txt and b/requirements.txt differ
diff --git a/ruff.toml b/ruff.toml
new file mode 100644
index 000000000..54231339f
--- /dev/null
+++ b/ruff.toml
@@ -0,0 +1,40 @@
+include = ["*.py"]
+
+# 行长度设置
+line-length = 120
+
+[lint]
+fixable = ["ALL"]
+unfixable = []
+
+# 如果一个变量的名称以下划线开头,即使它未被使用,也不应该被视为错误或警告。
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+# 启用的规则
+select = [
+ "E", # pycodestyle 错误
+ "F", # pyflakes
+ "B", # flake8-bugbear
+]
+
+ignore = ["E711"]
+
+[format]
+docstring-code-format = true
+indent-style = "space"
+
+
+# 使用双引号表示字符串
+quote-style = "double"
+
+# 尊重魔法尾随逗号
+# 例如:
+# items = [
+# "apple",
+# "banana",
+# "cherry",
+# ]
+skip-magic-trailing-comma = false
+
+# 自动检测合适的换行符
+line-ending = "auto"
diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py
index 59d94b5e5..33a9c2f74 100644
--- a/src/plugins/chat/bot.py
+++ b/src/plugins/chat/bot.py
@@ -178,7 +178,7 @@ class ChatBot:
# 检查是否 <没有找到> emoji
if emoji_raw != None:
- emoji_path, discription = emoji_raw
+ emoji_path, description = emoji_raw
emoji_cq = CQCode.create_emoji_cq(emoji_path)
@@ -194,7 +194,7 @@ class ChatBot:
raw_message=emoji_cq,
plain_text=emoji_cq,
processed_plain_text=emoji_cq,
- detailed_plain_text=discription,
+ detailed_plain_text=description,
user_nickname=global_config.BOT_NICKNAME,
group_name=message.group_name,
time=bot_response_time,
diff --git a/src/plugins/chat/config.py b/src/plugins/chat/config.py
index 7ce570dc2..bc69ffd4e 100644
--- a/src/plugins/chat/config.py
+++ b/src/plugins/chat/config.py
@@ -12,6 +12,7 @@ from packaging.specifiers import SpecifierSet, InvalidSpecifier
@dataclass
class BotConfig:
"""机器人配置类"""
+
INNER_VERSION: Version = None
BOT_QQ: Optional[int] = 1
@@ -82,23 +83,25 @@ class BotConfig:
PROMPT_PERSONALITY = [
"曾经是一个学习地质的女大学生,现在学习心理学和脑科学,你会刷贴吧",
"是一个女大学生,你有黑色头发,你会刷小红书",
- "是一个女大学生,你会刷b站,对ACG文化感兴趣"
+ "是一个女大学生,你会刷b站,对ACG文化感兴趣",
]
- PROMPT_SCHEDULE_GEN="一个曾经学习地质,现在学习心理学和脑科学的女大学生,喜欢刷qq,贴吧,知乎和小红书"
-
- PERSONALITY_1: float = 0.6 # 第一种人格概率
- PERSONALITY_2: float = 0.3 # 第二种人格概率
- PERSONALITY_3: float = 0.1 # 第三种人格概率
-
- memory_ban_words: list = field(default_factory=lambda: ['表情包', '图片', '回复', '聊天记录']) # 添加新的配置项默认值
-
+ PROMPT_SCHEDULE_GEN = "一个曾经学习地质,现在学习心理学和脑科学的女大学生,喜欢刷qq,贴吧,知乎和小红书"
+
+ PERSONALITY_1: float = 0.6 # 第一种人格概率
+ PERSONALITY_2: float = 0.3 # 第二种人格概率
+ PERSONALITY_3: float = 0.1 # 第三种人格概率
+
+ memory_ban_words: list = field(
+ default_factory=lambda: ["表情包", "图片", "回复", "聊天记录"]
+ ) # 添加新的配置项默认值
+
@staticmethod
def get_config_dir() -> str:
"""获取配置文件目录"""
current_dir = os.path.dirname(os.path.abspath(__file__))
- root_dir = os.path.abspath(os.path.join(current_dir, '..', '..', '..'))
- config_dir = os.path.join(root_dir, 'config')
+ root_dir = os.path.abspath(os.path.join(current_dir, "..", "..", ".."))
+ config_dir = os.path.join(root_dir, "config")
if not os.path.exists(config_dir):
os.makedirs(config_dir)
return config_dir
@@ -109,48 +112,45 @@ class BotConfig:
Args:
value[str]: 版本表达式(字符串)
Returns:
- SpecifierSet
+ SpecifierSet
"""
try:
converted = SpecifierSet(value)
except InvalidSpecifier:
- logger.error(
- f"{value} 分类使用了错误的版本约束表达式\n",
- "请阅读 https://semver.org/lang/zh-CN/ 修改代码"
- )
+ logger.error(f"{value} 分类使用了错误的版本约束表达式\n", "请阅读 https://semver.org/lang/zh-CN/ 修改代码")
exit(1)
return converted
@classmethod
def get_config_version(cls, toml: dict) -> Version:
- """提取配置文件的 SpecifierSet 版本数据
+ """提取配置文件的 SpecifierSet 版本数据
Args:
toml[dict]: 输入的配置文件字典
Returns:
- Version
+ Version
"""
- if 'inner' in toml:
+ if "inner" in toml:
try:
config_version: str = toml["inner"]["version"]
except KeyError as e:
logger.error("配置文件中 inner 段 不存在, 这是错误的配置文件")
- raise KeyError(f"配置文件中 inner 段 不存在 {e}, 这是错误的配置文件")
+ raise KeyError(f"配置文件中 inner 段 不存在 {e}, 这是错误的配置文件") from e
else:
toml["inner"] = {"version": "0.0.0"}
config_version = toml["inner"]["version"]
try:
ver = version.parse(config_version)
- except InvalidVersion:
+ except InvalidVersion as e:
logger.error(
"配置文件中 inner段 的 version 键是错误的版本描述\n"
"请阅读 https://semver.org/lang/zh-CN/ 修改配置,并参考本项目指定的模板进行修改\n"
"本项目在不同的版本下有不同的模板,请注意识别"
)
- raise InvalidVersion("配置文件中 inner段 的 version 键是错误的版本描述\n")
+ raise InvalidVersion("配置文件中 inner段 的 version 键是错误的版本描述\n") from e
return ver
@@ -160,26 +160,26 @@ class BotConfig:
config = cls()
def personality(parent: dict):
- personality_config = parent['personality']
- personality = personality_config.get('prompt_personality')
+ personality_config = parent["personality"]
+ personality = personality_config.get("prompt_personality")
if len(personality) >= 2:
logger.debug(f"载入自定义人格:{personality}")
- config.PROMPT_PERSONALITY = personality_config.get('prompt_personality', config.PROMPT_PERSONALITY)
+ config.PROMPT_PERSONALITY = personality_config.get("prompt_personality", config.PROMPT_PERSONALITY)
logger.info(f"载入自定义日程prompt:{personality_config.get('prompt_schedule', config.PROMPT_SCHEDULE_GEN)}")
- config.PROMPT_SCHEDULE_GEN = personality_config.get('prompt_schedule', config.PROMPT_SCHEDULE_GEN)
+ config.PROMPT_SCHEDULE_GEN = personality_config.get("prompt_schedule", config.PROMPT_SCHEDULE_GEN)
if config.INNER_VERSION in SpecifierSet(">=0.0.2"):
- config.PERSONALITY_1 = personality_config.get('personality_1_probability', config.PERSONALITY_1)
- config.PERSONALITY_2 = personality_config.get('personality_2_probability', config.PERSONALITY_2)
- config.PERSONALITY_3 = personality_config.get('personality_3_probability', config.PERSONALITY_3)
+ config.PERSONALITY_1 = personality_config.get("personality_1_probability", config.PERSONALITY_1)
+ config.PERSONALITY_2 = personality_config.get("personality_2_probability", config.PERSONALITY_2)
+ config.PERSONALITY_3 = personality_config.get("personality_3_probability", config.PERSONALITY_3)
def emoji(parent: dict):
emoji_config = parent["emoji"]
config.EMOJI_CHECK_INTERVAL = emoji_config.get("check_interval", config.EMOJI_CHECK_INTERVAL)
config.EMOJI_REGISTER_INTERVAL = emoji_config.get("register_interval", config.EMOJI_REGISTER_INTERVAL)
- config.EMOJI_CHECK_PROMPT = emoji_config.get('check_prompt', config.EMOJI_CHECK_PROMPT)
- config.EMOJI_SAVE = emoji_config.get('auto_save', config.EMOJI_SAVE)
- config.EMOJI_CHECK = emoji_config.get('enable_check', config.EMOJI_CHECK)
+ config.EMOJI_CHECK_PROMPT = emoji_config.get("check_prompt", config.EMOJI_CHECK_PROMPT)
+ config.EMOJI_SAVE = emoji_config.get("auto_save", config.EMOJI_SAVE)
+ config.EMOJI_CHECK = emoji_config.get("enable_check", config.EMOJI_CHECK)
def cq_code(parent: dict):
cq_code_config = parent["cq_code"]
@@ -197,8 +197,9 @@ class BotConfig:
response_config = parent["response"]
config.MODEL_R1_PROBABILITY = response_config.get("model_r1_probability", config.MODEL_R1_PROBABILITY)
config.MODEL_V3_PROBABILITY = response_config.get("model_v3_probability", config.MODEL_V3_PROBABILITY)
- config.MODEL_R1_DISTILL_PROBABILITY = response_config.get("model_r1_distill_probability",
- config.MODEL_R1_DISTILL_PROBABILITY)
+ config.MODEL_R1_DISTILL_PROBABILITY = response_config.get(
+ "model_r1_distill_probability", config.MODEL_R1_DISTILL_PROBABILITY
+ )
config.max_response_length = response_config.get("max_response_length", config.max_response_length)
def model(parent: dict):
@@ -215,7 +216,7 @@ class BotConfig:
"llm_emotion_judge",
"vlm",
"embedding",
- "moderation"
+ "moderation",
]
for item in config_list:
@@ -224,13 +225,7 @@ class BotConfig:
# base_url 的例子: SILICONFLOW_BASE_URL
# key 的例子: SILICONFLOW_KEY
- cfg_target = {
- "name": "",
- "base_url": "",
- "key": "",
- "pri_in": 0,
- "pri_out": 0
- }
+ cfg_target = {"name": "", "base_url": "", "key": "", "pri_in": 0, "pri_out": 0}
if config.INNER_VERSION in SpecifierSet("<=0.0.0"):
cfg_target = cfg_item
@@ -249,7 +244,7 @@ class BotConfig:
cfg_target[i] = cfg_item[i]
except KeyError as e:
logger.error(f"{item} 中的必要字段不存在,请检查")
- raise KeyError(f"{item} 中的必要字段 {e} 不存在,请检查")
+ raise KeyError(f"{item} 中的必要字段 {e} 不存在,请检查") from e
provider = cfg_item.get("provider")
if provider is None:
@@ -274,17 +269,19 @@ class BotConfig:
if config.INNER_VERSION in SpecifierSet(">=0.0.2"):
config.thinking_timeout = msg_config.get("thinking_timeout", config.thinking_timeout)
- config.response_willing_amplifier = msg_config.get("response_willing_amplifier",
- config.response_willing_amplifier)
- config.response_interested_rate_amplifier = msg_config.get("response_interested_rate_amplifier",
- config.response_interested_rate_amplifier)
+ config.response_willing_amplifier = msg_config.get(
+ "response_willing_amplifier", config.response_willing_amplifier
+ )
+ config.response_interested_rate_amplifier = msg_config.get(
+ "response_interested_rate_amplifier", config.response_interested_rate_amplifier
+ )
config.down_frequency_rate = msg_config.get("down_frequency_rate", config.down_frequency_rate)
def memory(parent: dict):
memory_config = parent["memory"]
config.build_memory_interval = memory_config.get("build_memory_interval", config.build_memory_interval)
config.forget_memory_interval = memory_config.get("forget_memory_interval", config.forget_memory_interval)
-
+
# 在版本 >= 0.0.4 时才处理新增的配置项
if config.INNER_VERSION in SpecifierSet(">=0.0.4"):
config.memory_ban_words = set(memory_config.get("memory_ban_words", []))
@@ -305,10 +302,12 @@ class BotConfig:
config.chinese_typo_enable = chinese_typo_config.get("enable", config.chinese_typo_enable)
config.chinese_typo_error_rate = chinese_typo_config.get("error_rate", config.chinese_typo_error_rate)
config.chinese_typo_min_freq = chinese_typo_config.get("min_freq", config.chinese_typo_min_freq)
- config.chinese_typo_tone_error_rate = chinese_typo_config.get("tone_error_rate",
- config.chinese_typo_tone_error_rate)
- config.chinese_typo_word_replace_rate = chinese_typo_config.get("word_replace_rate",
- config.chinese_typo_word_replace_rate)
+ config.chinese_typo_tone_error_rate = chinese_typo_config.get(
+ "tone_error_rate", config.chinese_typo_tone_error_rate
+ )
+ config.chinese_typo_word_replace_rate = chinese_typo_config.get(
+ "word_replace_rate", config.chinese_typo_word_replace_rate
+ )
def groups(parent: dict):
groups_config = parent["groups"]
@@ -327,61 +326,19 @@ class BotConfig:
# 例如:"notice": "personality 将在 1.3.2 后被移除",那么在有效版本中的用户就会虽然可以
# 正常执行程序,但是会看到这条自定义提示
include_configs = {
- "personality": {
- "func": personality,
- "support": ">=0.0.0"
- },
- "emoji": {
- "func": emoji,
- "support": ">=0.0.0"
- },
- "cq_code": {
- "func": cq_code,
- "support": ">=0.0.0"
- },
- "bot": {
- "func": bot,
- "support": ">=0.0.0"
- },
- "response": {
- "func": response,
- "support": ">=0.0.0"
- },
- "model": {
- "func": model,
- "support": ">=0.0.0"
- },
- "message": {
- "func": message,
- "support": ">=0.0.0"
- },
- "memory": {
- "func": memory,
- "support": ">=0.0.0",
- "necessary": False
- },
- "mood": {
- "func": mood,
- "support": ">=0.0.0"
- },
- "keywords_reaction": {
- "func": keywords_reaction,
- "support": ">=0.0.2",
- "necessary": False
- },
- "chinese_typo": {
- "func": chinese_typo,
- "support": ">=0.0.3",
- "necessary": False
- },
- "groups": {
- "func": groups,
- "support": ">=0.0.0"
- },
- "others": {
- "func": others,
- "support": ">=0.0.0"
- }
+ "personality": {"func": personality, "support": ">=0.0.0"},
+ "emoji": {"func": emoji, "support": ">=0.0.0"},
+ "cq_code": {"func": cq_code, "support": ">=0.0.0"},
+ "bot": {"func": bot, "support": ">=0.0.0"},
+ "response": {"func": response, "support": ">=0.0.0"},
+ "model": {"func": model, "support": ">=0.0.0"},
+ "message": {"func": message, "support": ">=0.0.0"},
+ "memory": {"func": memory, "support": ">=0.0.0", "necessary": False},
+ "mood": {"func": mood, "support": ">=0.0.0"},
+ "keywords_reaction": {"func": keywords_reaction, "support": ">=0.0.2", "necessary": False},
+ "chinese_typo": {"func": chinese_typo, "support": ">=0.0.3", "necessary": False},
+ "groups": {"func": groups, "support": ">=0.0.0"},
+ "others": {"func": others, "support": ">=0.0.0"},
}
# 原地修改,将 字符串版本表达式 转换成 版本对象
@@ -393,7 +350,7 @@ class BotConfig:
with open(config_path, "rb") as f:
try:
toml_dict = tomli.load(f)
- except(tomli.TOMLDecodeError) as e:
+ except tomli.TOMLDecodeError as e:
logger.critical(f"配置文件bot_config.toml填写有误,请检查第{e.lineno}行第{e.colno}处:{e.msg}")
exit(1)
@@ -408,7 +365,7 @@ class BotConfig:
# 检查配置文件版本是否在支持范围内
if config.INNER_VERSION in group_specifierset:
# 如果版本在支持范围内,检查是否存在通知
- if 'notice' in include_configs[key]:
+ if "notice" in include_configs[key]:
logger.warning(include_configs[key]["notice"])
include_configs[key]["func"](toml_dict)
@@ -422,7 +379,7 @@ class BotConfig:
raise InvalidVersion(f"当前程序仅支持以下版本范围: {group_specifierset}")
# 如果 necessary 项目存在,而且显式声明是 False,进入特殊处理
- elif "necessary" in include_configs[key] and include_configs[key].get("necessary") == False:
+ elif "necessary" in include_configs[key] and include_configs[key].get("necessary") is False:
# 通过 pass 处理的项虽然直接忽略也是可以的,但是为了不增加理解困难,依然需要在这里显式处理
if key == "keywords_reaction":
pass
diff --git a/src/plugins/chat/emoji_manager.py b/src/plugins/chat/emoji_manager.py
index 5a601d434..feba23076 100644
--- a/src/plugins/chat/emoji_manager.py
+++ b/src/plugins/chat/emoji_manager.py
@@ -117,7 +117,7 @@ class EmojiManager:
try:
# 获取所有表情包
- all_emojis = list(self.db.db.emoji.find({}, {'_id': 1, 'path': 1, 'embedding': 1, 'discription': 1}))
+ all_emojis = list(self.db.db.emoji.find({}, {'_id': 1, 'path': 1, 'embedding': 1, 'description': 1}))
if not all_emojis:
logger.warning("数据库中没有任何表情包")
@@ -160,9 +160,9 @@ class EmojiManager:
{'$inc': {'usage_count': 1}}
)
logger.success(
- f"找到匹配的表情包: {selected_emoji.get('discription', '无描述')} (相似度: {similarity:.4f})")
+ f"找到匹配的表情包: {selected_emoji.get('description', '无描述')} (相似度: {similarity:.4f})")
# 稍微改一下文本描述,不然容易产生幻觉,描述已经包含 表情包 了
- return selected_emoji['path'], "[ %s ]" % selected_emoji.get('discription', '无描述')
+ return selected_emoji['path'], "[ %s ]" % selected_emoji.get('description', '无描述')
except Exception as search_error:
logger.error(f"搜索表情包失败: {str(search_error)}")
@@ -174,7 +174,7 @@ class EmojiManager:
logger.error(f"获取表情包失败: {str(e)}")
return None
- async def _get_emoji_discription(self, image_base64: str) -> str:
+ async def _get_emoji_description(self, image_base64: str) -> str:
"""获取表情包的标签"""
try:
prompt = '这是一个表情包,使用中文简洁的描述一下表情包的内容和表情包所表达的情感'
@@ -236,31 +236,31 @@ class EmojiManager:
continue
# 获取表情包的描述
- discription = await self._get_emoji_discription(image_base64)
+ description = await self._get_emoji_description(image_base64)
if global_config.EMOJI_CHECK:
check = await self._check_emoji(image_base64)
if '是' not in check:
os.remove(image_path)
- logger.info(f"描述: {discription}")
+ logger.info(f"描述: {description}")
logger.info(f"其不满足过滤规则,被剔除 {check}")
continue
logger.info(f"check通过 {check}")
- if discription is not None:
- embedding = await get_embedding(discription)
+ if description is not None:
+ embedding = await get_embedding(description)
# 准备数据库记录
emoji_record = {
'filename': filename,
'path': image_path,
'embedding': embedding,
- 'discription': discription,
+ 'description': description,
'timestamp': int(time.time())
}
# 保存到数据库
self.db.db['emoji'].insert_one(emoji_record)
logger.success(f"注册新表情包: {filename}")
- logger.info(f"描述: {discription}")
+ logger.info(f"描述: {description}")
else:
logger.warning(f"跳过表情包: {filename}")