Compare commits

...

940 Commits
v6.0.0 ... main

Author SHA1 Message Date
1ae45808fd 📝 更新banner链接以优化显示效果
Some checks failed
Docker Image Build / build (push) Failing after 26s
Pre-commit checks / pre-commit (3.11) (push) Failing after 2m32s
Pre-commit checks / pre-commit (3.10) (push) Failing after 3m2s
Pre-commit checks / pre-commit (3.13) (push) Failing after 4m46s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 9m56s
Pre-commit checks / pre-commit (3.12) (push) Failing after 1h12m10s
2025-05-17 00:53:51 +08:00
800dbbba43 📝 更新发布URL为 "https://dash.apage.dev"
Some checks failed
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 2m21s
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m35s
Pre-commit checks / pre-commit (3.11) (push) Failing after 3m16s
Docker Image Build / build (push) Failing after 7m6s
Pre-commit checks / pre-commit (3.12) (push) Failing after 8m32s
Pre-commit checks / pre-commit (3.13) (push) Failing after 14m49s
2025-05-16 20:01:30 +08:00
c627c07aa1 📝 Update Liteyuki logo URLs in Chinese documentation
Some checks failed
Docker Image Build / build (push) Failing after 1m52s
Pre-commit checks / pre-commit (3.10) (push) Failing after 4m38s
Pre-commit checks / pre-commit (3.12) (push) Failing after 5m11s
Pre-commit checks / pre-commit (3.11) (push) Failing after 9m50s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 10m22s
Pre-commit checks / pre-commit (3.13) (push) Failing after 14m46s
2025-05-16 19:03:52 +08:00
4a9259dad4
Update README.md 2025-05-16 18:58:57 +08:00
Nanaloveyuki
fc017c8255 📝 文档与代码注释信息微调
Some checks failed
Docker Image Build / build (push) Failing after 15s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 1m2s
Pre-commit checks / pre-commit (3.10) (push) Failing after 1m46s
Pre-commit checks / pre-commit (3.11) (push) Failing after 1m38s
Pre-commit checks / pre-commit (3.12) (push) Failing after 1m45s
Pre-commit checks / pre-commit (3.13) (push) Failing after 1m43s
2025-04-04 11:44:50 +08:00
Nanaloveyuki
908812a3d9 📝 重置了deploy下的文档
Some checks failed
Docker Image Build / build (push) Failing after 2m10s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 2m30s
Pre-commit checks / pre-commit (3.10) (push) Failing after 3m7s
Pre-commit checks / pre-commit (3.11) (push) Failing after 2m37s
Pre-commit checks / pre-commit (3.12) (push) Failing after 2m42s
Pre-commit checks / pre-commit (3.13) (push) Failing after 3m18s
新添加了adapter.md用来转移配置器相关内容; 修改了部分文件的版权归属日期;
2025-04-03 21:54:03 +08:00
6c7d073cb1
📝 添加文档uptime
Some checks failed
Docker Image Build / build (push) Failing after 36s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 1m34s
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m1s
Pre-commit checks / pre-commit (3.11) (push) Failing after 2m10s
Pre-commit checks / pre-commit (3.12) (push) Failing after 2m5s
Pre-commit checks / pre-commit (3.13) (push) Failing after 2m29s
2025-03-19 02:12:28 +08:00
8677286bd4
📝 更新pages部署地址
Some checks failed
Docker Image Build / build (push) Failing after 40s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 1m46s
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m58s
Pre-commit checks / pre-commit (3.11) (push) Failing after 16s
Pre-commit checks / pre-commit (3.12) (push) Failing after 36s
Pre-commit checks / pre-commit (3.13) (push) Failing after 35s
2025-03-10 23:07:21 +08:00
232ffcf714 📝 修正文档中的LSO LICENSE拼写错误
Some checks failed
Docker Image Build / build (push) Failing after 29s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 2m12s
Pre-commit checks / pre-commit (3.10) (push) Failing after 3m37s
Pre-commit checks / pre-commit (3.11) (push) Failing after 3m17s
Pre-commit checks / pre-commit (3.12) (push) Failing after 3m49s
Pre-commit checks / pre-commit (3.13) (push) Failing after 3m48s
2025-03-09 20:01:36 +08:00
6871bc0d22 更新配置,重新引入 liteyuki_footer.js 脚本
Some checks failed
Docker Image Build / build (push) Failing after 28s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 2m55s
Pre-commit checks / pre-commit (3.10) (push) Failing after 3m27s
Pre-commit checks / pre-commit (3.11) (push) Failing after 3m9s
Pre-commit checks / pre-commit (3.12) (push) Failing after 4m2s
Pre-commit checks / pre-commit (3.13) (push) Failing after 4m17s
2025-03-08 23:26:54 +08:00
641c16ee7a 📝 文档引入神秘js 2025-03-08 23:21:14 +08:00
75c67bdffc 更新配置,禁用清理 URL 功能
Some checks failed
Docker Image Build / build (push) Failing after 54s
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m47s
Pre-commit checks / pre-commit (3.11) (push) Failing after 2m36s
Pre-commit checks / pre-commit (3.12) (push) Failing after 2m35s
Pre-commit checks / pre-commit (3.13) (push) Failing after 2m45s
Deploy VitePress site to Liteyuki PaaS / build (push) Failing after 11m59s
2025-03-07 21:35:21 +08:00
3a60450358 📝 更新文档页脚信息,修正链接文本
Some checks are pending
Docker Image Build / build (push) Waiting to run
Deploy VitePress site to Liteyuki PaaS / build (push) Waiting to run
Pre-commit checks / pre-commit (3.10) (push) Waiting to run
Pre-commit checks / pre-commit (3.11) (push) Waiting to run
Pre-commit checks / pre-commit (3.12) (push) Waiting to run
Pre-commit checks / pre-commit (3.13) (push) Waiting to run
2025-03-07 17:43:43 +08:00
7b97210a31 📝 更新文档页脚信息,添加网站部署链接
Some checks are pending
Docker Image Build / build (push) Waiting to run
Deploy VitePress site to Liteyuki PaaS / build (push) Waiting to run
Pre-commit checks / pre-commit (3.10) (push) Waiting to run
Pre-commit checks / pre-commit (3.11) (push) Waiting to run
Pre-commit checks / pre-commit (3.12) (push) Waiting to run
Pre-commit checks / pre-commit (3.13) (push) Waiting to run
2025-03-07 17:21:01 +08:00
d97145ee5e 📝 更新文档部署工作流程,添加对状态的写入权限并恢复 GITHUB_TOKEN 环境变量 2025-03-07 17:09:01 +08:00
bc3a4355c3 🐛 移除文档部署工作流程中的 GITHUB_TOKEN 环境变量 2025-03-07 17:00:27 +08:00
d835a32683 🗑️ 删除文档部署工作流程文件 2025-03-07 16:49:25 +08:00
aedea1acb9 Merge branch 'main' of https://github.com/LiteyukiStudio/LiteyukiBot 2025-03-07 16:37:18 +08:00
3bce8325c1 📝 新增 Liteyuki PaaS 部署工作流程,优化文档构建和发布步骤 2025-03-07 16:37:15 +08:00
d1c1320963
📝 Create .domain
Some checks failed
Docker Image Build / build (push) Failing after 1m1s
Deploy VitePress site to Pages / build (push) Failing after 1m42s
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m42s
Pre-commit checks / pre-commit (3.11) (push) Failing after 2m55s
Pre-commit checks / pre-commit (3.13) (push) Failing after 3m9s
Pre-commit checks / pre-commit (3.12) (push) Failing after 5m0s
2025-03-07 00:12:44 +08:00
317e07eb71 🐛 更新文档页脚信息,添加Liteyukiflare CDN加速说明
Some checks failed
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m43s
Deploy VitePress site to Pages / build (push) Failing after 3m7s
Pre-commit checks / pre-commit (3.13) (push) Failing after 3m10s
Pre-commit checks / pre-commit (3.12) (push) Failing after 13m53s
Pre-commit checks / pre-commit (3.11) (push) Failing after 13m56s
Docker Image Build / build (push) Failing after 14m14s
2025-03-01 03:05:04 +08:00
37749ae15e 📝 使用Liteyukiflare对GitHub Page进行亚太地区加速 2025-03-01 03:04:34 +08:00
f94c10de61 🐛 修正 Docker 镜像标签的大小写,更新相关文档中的镜像拉取命令
Some checks failed
Pre-commit checks / pre-commit (3.10) (push) Failing after 5s
Pre-commit checks / pre-commit (3.12) (push) Failing after 4s
Pre-commit checks / pre-commit (3.11) (push) Failing after 11s
Pre-commit checks / pre-commit (3.13) (push) Failing after 5s
Docker Image Build / build (push) Failing after 1m41s
Deploy VitePress site to Pages / build (push) Failing after 1m46s
2025-02-18 09:08:50 +08:00
5ccef735be 🐛 更新 Docker 镜像拉取地址,修正文档中的镜像源 2025-02-18 09:07:37 +08:00
262002b49a 🐛 更新 GitHub 容器注册表登录配置,修正 Docker 镜像构建和推送步骤 2025-02-18 09:06:52 +08:00
40c6ba6d9e 🐛 更新管道依赖,修复管道句柄错误
Some checks failed
Pre-commit checks / pre-commit (3.10) (push) Failing after 32s
Docker Image Build / build (push) Failing after 55s
Pre-commit checks / pre-commit (3.12) (push) Failing after 39s
Pre-commit checks / pre-commit (3.11) (push) Failing after 3m28s
Pre-commit checks / pre-commit (3.13) (push) Failing after 3m59s
Deploy VitePress site to Pages / build (push) Failing after 10m0s
2025-02-18 06:47:31 +08:00
60093b562b 🐛 移除 Gotify 插件及相关配置,更新依赖项版本 2025-02-18 06:42:42 +08:00
30880ec13b 在 README 中添加 LiteyukiLab 的徽章链接
Some checks failed
Docker Image Build / build (push) Failing after 32s
Deploy VitePress site to Pages / build (push) Failing after 53s
Pre-commit checks / pre-commit (3.10) (push) Failing after 1m36s
Pre-commit checks / pre-commit (3.11) (push) Failing after 1m38s
Pre-commit checks / pre-commit (3.12) (push) Failing after 1m58s
Pre-commit checks / pre-commit (3.13) (push) Failing after 1m47s
2025-01-13 00:57:50 +08:00
cc1d82312a 添加新的图标配置,更新链接以指向新的资源 2025-01-13 00:49:01 +08:00
efca13d397 🐛 移除 requirements.txt 中的 pip 依赖项
Some checks failed
Docker Image Build / build (push) Failing after 18s
Deploy VitePress site to Pages / build (push) Failing after 52s
Pre-commit checks / pre-commit (3.10) (push) Failing after 1m25s
Pre-commit checks / pre-commit (3.11) (push) Failing after 1m7s
Pre-commit checks / pre-commit (3.12) (push) Failing after 1m27s
Pre-commit checks / pre-commit (3.13) (push) Failing after 1m25s
2024-12-14 02:59:55 +08:00
3a8c09d6db 🐛 删除 __pypackages__ 目录的 .gitignore 文件,并更新主 .gitignore 文件以忽略 pdm 相关文件 2024-12-14 02:57:51 +08:00
cc1bb8e5e4 添加 pre-commit 配置和工作流,集成代码格式化和静态检查工具
Some checks failed
Docker Image Build / build (push) Failing after 29s
Deploy VitePress site to Pages / build (push) Failing after 53s
Pre-commit checks / pre-commit (3.10) (push) Failing after 2m17s
Pre-commit checks / pre-commit (3.11) (push) Failing after 2m1s
Pre-commit checks / pre-commit (3.13) (push) Failing after 2m18s
Pre-commit checks / pre-commit (3.12) (push) Failing after 2m57s
2024-12-13 19:35:07 +08:00
93c17b6026 添加新的配置加载器,支持从YAML、TOML、JSON和环境变量加载配置,并修改默认主机地址
Some checks failed
Docker Image Build / build (push) Failing after 1m25s
Deploy VitePress site to Pages / build (push) Failing after 1m50s
2024-12-02 21:46:29 +08:00
fd3f6272f1 🐛 修复获取系统语言代码的逻辑,处理None值的情况
Some checks failed
Docker Image Build / build (push) Failing after 35s
Deploy VitePress site to Pages / build (push) Failing after 2m11s
2024-11-29 00:04:34 +08:00
4d87a3c0b7 Merge branch 'main' of https://git.liteyuki.icu/bot/app 2024-11-29 00:03:14 +08:00
86f47ee411 🐛 修复获取系统语言代码的逻辑,添加对None值的处理 2024-11-29 00:01:49 +08:00
1d6b8d60f3
Merge pull request #89 from Asankilp/main
Some checks failed
Docker Image Build / build (push) Failing after 21s
Deploy VitePress site to Pages / build (push) Failing after 53s
添加uninfo依赖项
2024-11-27 01:47:23 +08:00
3890704045 添加uninfo依赖项 2024-11-27 01:44:49 +08:00
b0761e9873 🐛 更新docker-compose.yml,修改时区设置为Asia/Chongqing
Some checks failed
Docker Image Build / build (push) Failing after 19s
Deploy VitePress site to Pages / build (push) Failing after 55s
2024-11-23 22:31:51 +08:00
291314de93 新增docker-compose.yml文件,定义应用服务及其配置 2024-11-23 22:31:06 +08:00
fd835e9406 更新.gitignore,新增Python工具链缓存目录排除项;更新README.md,调整标题并添加monorepo说明
Some checks failed
Docker Image Build / build (push) Failing after 37s
Deploy VitePress site to Pages / build (push) Failing after 57s
2024-11-22 20:15:04 +08:00
d681c5645a 🐛 更新Dockerfile,新增libpango-1.0-0和libcairo2依赖
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m0s
Docker Image Build / build (push) Failing after 1m8s
2024-11-21 19:53:49 +08:00
d0619f1fe8 优化Dockerfile,移除不必要的sources.list复制步骤,简化pip安装命令
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m2s
Docker Image Build / build (push) Failing after 1m29s
2024-11-16 02:24:47 +08:00
b022a364e3 更新GitHub Actions工作流,修改并发组名称为“docker-build” 2024-11-16 02:20:06 +08:00
df00c61dd8 新增GitHub Actions工作流以构建和推送Docker镜像,更新.gitignore以排除.github目录 2024-11-16 02:19:31 +08:00
94a021bab0 更新安装文档,替换Docker构建步骤为拉取最新夜间版镜像 2024-11-16 02:17:06 +08:00
6b20e9eae0 更新README.md,将“参考及鸣”更正为“参考及鸣谢”
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 2m9s
2024-11-10 01:20:14 +08:00
0a35a3c6f8 修正README.md中的链接错误,将“lightyuki-link”更正为“liteyuki-link” 2024-11-10 01:19:58 +08:00
2e75c7bc65 更新README.md,新增GitHub和官方仓库链接,优化内容结构
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m17s
2024-11-10 01:15:34 +08:00
3341505715 更新LiteyukiBot克隆命令中的镜像链接
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 2m52s
2024-11-09 23:52:17 +08:00
bdde9c45fd 优化配置文件格式和清理无用调试信息,修改gitea仓库路径 2024-11-09 23:51:35 +08:00
7bf94a15c8 📝 文档新增插件通信部分内容
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m10s
2024-10-26 02:34:58 +08:00
4510477026 Merge branch 'main' of https://github.com/LiteyukiStudio/LiteyukiBot
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 15s
2024-10-23 01:06:47 +08:00
86e50e369b 初步对Uninfo的支持 2024-10-23 01:04:42 +08:00
796fc6f233
Merge pull request #88 from EillesWan/main
🌠也许,大家的测试环境都是*nix?
2024-10-22 13:36:57 +08:00
金羿ELS
80c6875567
🌠也许,大家的测试环境都是*nix?
Update file.py
2024-10-22 13:34:09 +08:00
ab89cd1c72 性能提升200倍
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 11m46s
2024-10-20 23:37:40 +08:00
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
980fca650b 🐛 hotfix: ubl 2024-10-13 13:44:07 +08:00
9c525141f6 分离magicocacroterline
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 6m48s
2024-10-13 02:56:29 +08:00
3d218a0e8d Merge remote-tracking branch 'origin/main'
# Conflicts:
#	src/liteyuki_plugins/nonebot/__init__.py
#	src/liteyuki_plugins/nonebot/nb_utils/adapter_manager/__init__.py
#	src/liteyuki_plugins/nonebot/nb_utils/adapter_manager/onebot.py
#	src/liteyuki_plugins/nonebot/nb_utils/adapter_manager/satori.py
#	src/liteyuki_plugins/nonebot/nb_utils/driver_manager/__init__.py
#	src/liteyuki_plugins/nonebot/nb_utils/driver_manager/auto_set_env.py
#	src/liteyuki_plugins/nonebot/nb_utils/driver_manager/defines.py
2024-10-13 02:55:04 +08:00
db385f597b 分离magicocacroterline 2024-10-13 02:54:47 +08:00
98a9d6413a 分离magicocacroterline 2024-10-13 02:51:33 +08:00
a77f97fd4b 🐛 hotfix: 移除状态卡片Linux下非储存分区
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 8m9s
2024-09-29 22:57:04 +08:00
e6ea1b700f 🐛 hotfix: 天气拉取异常 2024-09-29 22:52:34 +08:00
596f4d06ea 🐛 bug: 修复状态卡片显示问题 2024-09-29 22:35:24 +08:00
8e3d3b3b5d Merge remote-tracking branch 'origin/main'
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 50s
2024-09-27 00:50:05 +08:00
a34ad87e01 todo: add todo file 2024-09-27 00:49:54 +08:00
6c4c7f34cd
📝 Update resource_publish_en.yml
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m32s
2024-09-22 01:56:00 +08:00
0c859957b4 🐛 docs: 添加发布插件表单 2024-09-22 01:48:53 +08:00
fbb9ed82ee 🐛 docs: 添加发布插件表单 2024-09-22 01:42:03 +08:00
b469c9420e 🐛 docs: 添加发布插件表单 2024-09-22 01:38:44 +08:00
aa4d930cc4 🐛 docs: 添加发布插件表单 2024-09-21 23:16:37 +08:00
76be748160
:docs: Update resource_publish_zh.yml 2024-09-21 22:36:04 +08:00
a9dd37b8a5
📝 Update resource_publish_zh.yml 2024-09-21 22:32:47 +08:00
5900d621f2
Create resource_publish_zh.yml 2024-09-21 22:28:58 +08:00
7442a3651b
Create config.yml 2024-09-21 22:28:13 +08:00
413f438689
Rename resource_publish.md to resource_publish.yml 2024-09-21 22:21:20 +08:00
1fc4999b09
:docs: add resource_publish to resource_publish.md 2024-09-21 22:20:43 +08:00
975446a096
Create resource_publish 2024-09-21 22:19:34 +08:00
98cdd2f4b8 🐛 docs: 商店点击主页改为新窗口,修复插件商店仅轻雪不显示的问题
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m33s
2024-09-21 03:22:40 +08:00
c0beec0429 🐛 docs: 商店点击主页改为新窗口,修复插件商店仅轻雪不显示的问题 2024-09-21 03:16:32 +08:00
614d78b3fa 🐛 docs: 商店点击主页改为新窗口,修复插件商店仅轻雪不显示的问题 2024-09-21 03:12:32 +08:00
24b0f345e4 📦 docs: 主页添加开发按钮 2024-09-21 02:51:59 +08:00
0ae10aa1b2 Merge remote-tracking branch 'origin/main' 2024-09-21 02:49:11 +08:00
9fe7478840 📦 docs: 修复文档404 2024-09-21 02:49:01 +08:00
liteyuki-flow[bot]
efca0bc7b3 📦 发布资源: 测试资源包2
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m16s
2024-09-18 01:41:24 +08:00
50c5e99b98 📦 docs: 修改发布按钮样式 2024-09-18 01:38:13 +08:00
7415efcc90 📦 docs: 修改发布按钮样式 2024-09-18 01:32:12 +08:00
5bb4584e6a Merge remote-tracking branch 'origin/main' 2024-09-18 01:31:13 +08:00
795a6f3f76 📦 docs: 修改发布按钮样式 2024-09-18 01:31:03 +08:00
liteyuki-flow[bot]
fa74e08514 📦 发布资源: 测试资源包2 2024-09-18 01:30:26 +08:00
e6cf6e0c68 📦 docs: 修改发布按钮样式 2024-09-18 01:25:43 +08:00
6789c16773 📦 docs: 修改发布按钮样式 2024-09-18 01:24:32 +08:00
cdea0f8563 📦 docs: 修改发布按钮样式 2024-09-18 01:23:21 +08:00
9df55671ac 📦 docs: 修改发布按钮样式 2024-09-18 01:22:08 +08:00
d96c6f13c1 📦 docs: 修改发布按钮样式 2024-09-18 01:05:23 +08:00
bce1bf8704 Merge remote-tracking branch 'origin/main' 2024-09-18 01:04:47 +08:00
8eb626b8da 📦 docs: 修改发布按钮样式 2024-09-18 01:04:37 +08:00
liteyuki-flow[bot]
e6505d335b 📦 发布资源: 测试资源包2 2024-09-18 00:59:47 +08:00
c8cb341afb Merge remote-tracking branch 'origin/main'
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m32s
2024-09-17 16:30:30 +08:00
e99cb88b13 📦 docs: 修改发布按钮样式 2024-09-17 16:30:19 +08:00
liteyuki-flow[bot]
78c3e299d0 📦 发布资源: 轻雪Kakyo语言包 托管版 2024-09-17 16:27:24 +08:00
23338437e9 📦 docs: 资源商店新增发布资源功能 2024-09-17 16:23:07 +08:00
f95899aebd 📦 docs: 资源商店新增发布资源功能
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m16s
2024-09-17 16:21:45 +08:00
5df10c66b6 📦 docs: 资源商店新增发布资源功能 2024-09-17 16:21:18 +08:00
811d1594cd 📦 docs: 资源商店新增发布资源功能 2024-09-17 16:19:47 +08:00
c162208638 📦 docs: 资源商店新增发布资源功能 2024-09-17 16:16:29 +08:00
679d6597d8 Merge remote-tracking branch 'origin/main' 2024-09-17 16:14:18 +08:00
f402799f28 📦 docs: 资源商店新增发布资源功能 2024-09-17 16:14:08 +08:00
liteyuki-flow[bot]
60542d7426 📦 发布资源: 轻雪Kakyo语言包 稳定版 2024-09-17 16:06:05 +08:00
db1fb58717 📦 docs: 资源商店新增发布资源功能 2024-09-17 16:01:19 +08:00
7d5675ec97 Merge remote-tracking branch 'origin/main' 2024-09-17 15:58:56 +08:00
d8c50752f7 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:58:45 +08:00
liteyuki-flow[bot]
c674b837bb 📦 发布资源: 测试资源包 2024-09-17 15:53:47 +08:00
d867996072 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:53:17 +08:00
7ef36c6933 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:52:32 +08:00
982aae4dbf 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:50:10 +08:00
b5d3c6aaa8 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:48:02 +08:00
5537bc32df 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:45:43 +08:00
5c0c723c5d 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:33:32 +08:00
0ed3b307d9 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:31:59 +08:00
53a603d4ee 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:26:21 +08:00
fbf906bea7 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:16:54 +08:00
a87e8bc3e8 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:04:19 +08:00
a16a67dbc9 📦 docs: 资源商店新增发布资源功能 2024-09-17 15:03:48 +08:00
4c2231feb5 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:59:49 +08:00
3932dd60da 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:57:27 +08:00
3c6380cb82 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:55:05 +08:00
2612f99f35 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:52:26 +08:00
0b4b9a6241 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:48:48 +08:00
2d100885ee 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:46:06 +08:00
cb335720b7 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:44:43 +08:00
dc8ad30b84 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:42:22 +08:00
09e00652c3 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:40:54 +08:00
b5b15c82f8 📦 docs: 资源商店新增发布资源功能 2024-09-17 14:37:45 +08:00
72e71124b8 📝 docs: 资源商店新增发布资源功能
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m14s
2024-09-17 01:35:26 +08:00
d2be2acc95 📝 docs: add egg
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m14s
2024-09-15 00:20:22 +08:00
d95614e960
📝 使用复数代替单数visitor
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 22s
2024-09-10 08:17:24 +08:00
dad9482d7a
📝 update readme
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m43s
2024-09-07 04:42:45 +08:00
fff5d09ad9 📝 docs: remove docstring from src of docs
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m18s
2024-09-06 20:05:29 +08:00
e6ffd1fcc0 📝 docs: remove docstring from src of docs 2024-09-06 19:57:53 +08:00
a97747b7c4 Merge remote-tracking branch 'origin/main' 2024-09-06 19:50:15 +08:00
1921dcd023 📝 docs: remove docstring from src of docs 2024-09-06 19:50:01 +08:00
18af1d00bd
📝 update i18n.ts
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m7s
2024-09-05 11:45:12 +08:00
30cdc1da23
Merge pull request #73 from ElapsingDreams/main
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m6s
📝更新轻雪文档url
2024-09-04 20:45:32 +08:00
ElapsingDreams
bb84958ce4
📝更新轻雪文档url
https://bot.liteyuki.icu/usage/  -->  https://bot.liteyuki.icu/
2024-09-04 20:40:31 +08:00
ElapsingDreams
44de3fd00a
📝更新轻雪文档url
https://bot.liteyuki.icu/usage/  -->  https://bot.liteyuki.icu/usage/basic.html
2024-09-04 20:34:13 +08:00
39b1920532 📝 docs: 修改侧边栏选项 2024-09-04 19:15:11 +08:00
aa591ec29e 📝 更新开发规范 2024-09-04 19:10:32 +08:00
310c3f065d 📝 更新开发规范
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m2s
2024-09-04 03:23:18 +08:00
2311ef82c3
🐛 fix: logo display error 2024-09-04 02:57:21 +08:00
b4b931fc95 📝 更新开发规范 2024-09-04 02:43:44 +08:00
d1b887fcaa 📝https://github.com/jooy2/vitepress-sidebar/issues/170#event-14113011263一起更新
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m5s
2024-09-03 22:26:58 +08:00
5a2990770c 📝 新增gitea数据
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 1m27s
2024-09-02 21:28:08 +08:00
1d0f0a2539 📝 新增gitea数据 2024-09-02 21:27:41 +08:00
dbc4d83b08 📝 新增gitea数据 2024-09-02 21:27:28 +08:00
da905d21bd 📝 新增gitea数据 2024-09-02 21:26:11 +08:00
7d91079500 🚀 workflows: 新增gitea工作流
Some checks failed
Deploy VitePress site to Pages / build (push) Failing after 3m1s
2024-09-02 17:08:29 +08:00
81a006a308 🐛 [docs]: 增加访客记录 2024-09-02 11:20:53 +08:00
be59e241c6 🐛 [docs]: 增加访客记录 2024-09-02 00:13:37 +08:00
e493139d85 🐛 [docs]: 英文文档未适配暗色模式的问题 2024-09-01 22:58:24 +08:00
1f59ec2ef9 📝 [docs]: 新增统计信息 2024-09-01 22:52:00 +08:00
20d05f609d 📝 [docs]: 新增统计信息 2024-09-01 22:42:20 +08:00
0f9683de89 📝 [docs]: 新增统计信息 2024-09-01 22:30:46 +08:00
c805db3371 📝 [docs]: 新增在线展示 2024-09-01 22:14:09 +08:00
58d0d12c1f 📝 [docs]: 新增在线展示 2024-09-01 22:00:17 +08:00
359683dbae 📝 [docs]: 新增在线展示 2024-09-01 21:21:04 +08:00
94cab8b743 📝 [docs]: 新增在线展示 2024-09-01 21:16:45 +08:00
837447b6e4 📝 [docs]: 新增在线展示 2024-09-01 20:45:06 +08:00
ad52eade07 📝 [docs]: 新增在线展示 2024-09-01 20:44:50 +08:00
9cae3edb6b 📝 [docs]: 新增在线展示 2024-09-01 20:39:51 +08:00
0860b61ccd 📝 [docs]: 新增在线展示 2024-09-01 18:29:00 +08:00
d125c52b50 📝 [docs]: 新增在线展示 2024-09-01 18:27:45 +08:00
d485e095ae 📝 [docs]: 新增在线展示 2024-09-01 18:25:37 +08:00
499caca7e3 📝 [docs]: 新增在线展示 2024-09-01 17:57:21 +08:00
83a2d36209 📝 [docs]: 新增在线展示 2024-09-01 17:20:33 +08:00
8b77ced05e 📝 [docs]: 新增在线展示 2024-09-01 16:52:10 +08:00
49a9617f08 📝 [docs]: 修改开源协议 2024-09-01 15:45:03 +08:00
06aa919d9b 📝 [docs]: 修改开源协议 2024-09-01 15:34:52 +08:00
77b77c285b 📝 [docs]: 重新更改开发文档侧边栏顺序 2024-09-01 15:31:22 +08:00
bdc32b26fe 🐛 [plugin]: 暂时关闭轻雪推送功能 2024-09-01 13:22:12 +08:00
736125f4ee 🐛 [plugin]: remove crt-util 2024-09-01 11:27:39 +08:00
89cb75f105 🐛 [plugin]: 修复htmlredner造成的错误 2024-09-01 11:21:45 +08:00
34a6261f27 🐛 [plugin]: 移除sign状态插件 2024-09-01 11:06:30 +08:00
ae18bfaee1 🐛 [channel]: 暂停通道接收功能 2024-09-01 11:05:01 +08:00
8510b0ed3f 🐛 [utils]: htmlrender load error 2024-09-01 11:02:58 +08:00
967f1a0e5b 🐛 [utils]: htmlrender load error 2024-09-01 10:59:52 +08:00
6c1fc62ef1 🔥 [plugin]: 移除liteyuki_docs 2024-09-01 10:53:42 +08:00
433c6b3b85 📝 新增开发规范 2024-09-01 10:51:31 +08:00
ee1ae5a071 📝 新增开发规范 2024-09-01 10:35:54 +08:00
49a15d512e 📝 新增开发规范 2024-09-01 10:35:26 +08:00
fd1d73cc32 📝 添加项目结构说明 | add project structure description 2024-09-01 10:23:06 +08:00
29c2aa9404
📝 fix docs index usage 404 2024-09-01 09:46:47 +08:00
0ec1195930
📝 修复中文文档 主页 使用手册404的问题 2024-09-01 09:45:50 +08:00
d7a625bedb
📝 修正英文文档中的liteyuki docstring 跳转路径 2024-09-01 08:27:50 +08:00
3854376210
📝 修正中文文档中的Liteyuki docstring跳转路径 2024-09-01 08:26:47 +08:00
5253d0e515
Merge pull request #71 from ElapsingDreams/main
暂时使用nonebot_plugin_htmlrender以解决issue#68
2024-09-01 08:14:05 +08:00
Envision
3bc7fa82b1 暂时使用nonebot_plugin_htmlrender以解决issue#68 2024-09-01 01:11:24 +08:00
7d98d5819d
🐛 点击 编辑这页 跳转后404 2024-09-01 00:16:34 +08:00
8316c0ff63
📝 修改函数头 2024-09-01 00:03:20 +08:00
315b8c91e5
Merge pull request #70 from ElapsingDreams/main
🐛“__version__”
2024-08-31 23:52:58 +08:00
ElapsingDreams
405eb10a8a
🐛“__version__” 2024-08-31 22:53:08 +08:00
c3072e93c7 📝 修复暗黑模式下商店物品显示对比度不高的问题 2024-08-31 22:06:04 +08:00
ae34ff622d 📝 插件商店支持 2024-08-31 21:50:58 +08:00
d2704818d9 📝 新增开发指南 2024-08-31 20:23:45 +08:00
2ab4184314 📝 新增开发指南 2024-08-31 20:21:26 +08:00
9aade6599c 📝 文档初步大迁移 vuepress -> vitepress 2024-08-31 19:51:34 +08:00
2f87b06c83 📝 文档初步大迁移 vuepress -> vitepress 2024-08-31 19:07:34 +08:00
8bb3f15bd9 📝 文档初步大迁移 vuepress -> vitepress 2024-08-31 19:05:37 +08:00
7f198c83b5 📝 文档初步大迁移 vuepress -> vitepress 2024-08-31 18:57:48 +08:00
f70c75e9c4 ⬇️ 更新文档样式 2024-08-31 16:17:27 +08:00
be5a4b270d ⬇️ 更新文档样式 2024-08-29 15:50:26 +08:00
50c0216435 ⬇️ 更新文档样式 2024-08-29 14:23:13 +08:00
4910de74fd Merge remote-tracking branch 'origin/main'
# Conflicts:
#	.github/workflows/deploy-docs.yml
#	docs/dev/api/README.md
#	docs/dev/api/bot/README.md
#	docs/dev/api/bot/lifespan.md
#	docs/dev/api/comm/README.md
#	docs/dev/api/comm/channel.md
#	docs/dev/api/comm/event.md
#	docs/dev/api/comm/storage.md
#	docs/dev/api/config.md
#	docs/dev/api/core/README.md
#	docs/dev/api/core/manager.md
#	docs/dev/api/dev/README.md
#	docs/dev/api/dev/observer.md
#	docs/dev/api/dev/plugin.md
#	docs/dev/api/exception.md
#	docs/dev/api/log.md
#	docs/dev/api/message/README.md
#	docs/dev/api/message/event.md
#	docs/dev/api/message/matcher.md
#	docs/dev/api/message/on.md
#	docs/dev/api/message/rule.md
#	docs/dev/api/message/session.md
#	docs/dev/api/mkdoc.md
#	docs/dev/api/plugin/README.md
#	docs/dev/api/plugin/load.md
#	docs/dev/api/plugin/manager.md
#	docs/dev/api/plugin/model.md
#	docs/dev/api/utils.md
#	docs/en/dev/api/README.md
#	docs/en/dev/api/bot/README.md
#	docs/en/dev/api/bot/lifespan.md
#	docs/en/dev/api/comm/README.md
#	docs/en/dev/api/comm/channel.md
#	docs/en/dev/api/comm/event.md
#	docs/en/dev/api/comm/storage.md
#	docs/en/dev/api/config.md
#	docs/en/dev/api/core/README.md
#	docs/en/dev/api/core/manager.md
#	docs/en/dev/api/dev/README.md
#	docs/en/dev/api/dev/observer.md
#	docs/en/dev/api/dev/plugin.md
#	docs/en/dev/api/exception.md
#	docs/en/dev/api/log.md
#	docs/en/dev/api/message/README.md
#	docs/en/dev/api/message/event.md
#	docs/en/dev/api/message/matcher.md
#	docs/en/dev/api/message/on.md
#	docs/en/dev/api/message/rule.md
#	docs/en/dev/api/message/session.md
#	docs/en/dev/api/mkdoc.md
#	docs/en/dev/api/plugin/README.md
#	docs/en/dev/api/plugin/load.md
#	docs/en/dev/api/plugin/manager.md
#	docs/en/dev/api/plugin/model.md
#	docs/en/dev/api/utils.md
#	litedoc/__main__.py
#	litedoc/docstring/docstring.py
#	litedoc/output.py
#	litedoc/style/markdown.py
#	litedoc/syntax/astparser.py
2024-08-29 14:20:19 +08:00
f12b6854b7 ⬇️ 更新文档样式 2024-08-29 14:19:39 +08:00
b0b61fbaf7 ⬇️ 2024-08-29 13:54:24 +08:00
7c0b0df6ed ⬇️ 2024-08-29 13:52:19 +08:00
cb3ee4b72f ⬇️ 2024-08-29 13:50:12 +08:00
3a3ef4d6ae
Merge pull request #69 from ElapsingDreams/patch-1
🌐 翻译修正
2024-08-25 14:26:08 +08:00
ElapsingDreams
9b3dea840e
🌐 翻译修正
🌐 翻译修正
Weather service by QWeather
来源:和风天气官方文档
2024-08-25 13:01:22 +08:00
ca89fa7efd ⬇️ 修复部分依赖问题,目前请勿使用清华镜像源安装 2024-08-24 21:19:51 +08:00
4705eac79c 📦 插件商店上新:liteyukibot-plugin-htmlrender及liteyukibot-plugin-lagrange 2024-08-24 11:57:53 +08:00
ebe0c5bcbb 📦 插件商店上新:liteyukibot-plugin-htmlrender及liteyukibot-plugin-lagrange 2024-08-24 11:39:10 +08:00
93c287bbd9
Merge pull request #67 from EillesWan/main
__liteyuki_plugin_meta__支持
2024-08-24 01:46:39 +08:00
0defb00ede 🧨新增未指定metadata的空判断 2024-08-24 01:43:35 +08:00
81c1d0286d 🎇新增依赖 liteyukibot-plugin-htmlrender 以便兼容其他需要 nonebot-plugin-htmlrender 渲染的插件 2024-08-24 01:14:46 +08:00
fb25005bd5 __liteyuki_plugin_meta__支持 2024-08-24 01:09:54 +08:00
2eb5aae23f [nonebot-plugin]状态提供更多品牌的cpu支持 2024-08-23 23:47:01 +08:00
a7d0560932
Merge pull request #66 from EillesWan/main
👻新增内置的页面渲染组件
2024-08-23 20:50:57 +08:00
391f112bb3 😅少改个东西.给改过去 2024-08-23 18:10:09 +08:00
bc8d13ba8a 😅不小心多改了个东西,给改回来 2024-08-23 18:08:11 +08:00
e8ec2ee28a Merge branch 'main' of https://github.com/LiteyukiStudio/LiteyukiBot 2024-08-23 17:58:49 +08:00
b6c8fcbccd 🧐内置页面渲染组件,弃用nonebot-plugin-htmlrender,避免playwright对多平台的不友好绑架 2024-08-23 17:58:36 +08:00
71476560e4 📝 商店新增anti-dislink插件和tag展示 2024-08-22 10:41:41 +08:00
aa2d182840 🐛 修复轻雪与NoneBot对接回复的错误 2024-08-22 10:10:03 +08:00
4bf8512a7d 新增on_keywords 2024-08-22 09:35:02 +08:00
a3a31a2c94 🔥 移除通道的部分特性 2024-08-22 07:23:44 +08:00
9ed4c1abb1 📝 文档新增源代码展示 2024-08-21 18:05:04 +08:00
a9c6ea0452 🐛 修复npm无法显示的问题 2024-08-21 17:59:21 +08:00
9e2bbe2e5c 🐛 修复npm无法显示的问题 2024-08-20 21:39:01 +08:00
598bff8c49 擴展event字段 2024-08-20 20:38:10 +08:00
eb7c8300fa 擴展event字段 2024-08-20 20:30:50 +08:00
287ab63091 移除测试插件 2024-08-20 06:24:00 +08:00
0c942d9806 添加对主流框架的消息io支持 2024-08-20 06:20:41 +08:00
237789e0d4 🚀 测试文档工作流 2024-08-19 23:50:15 +08:00
e656fa6a48 🚀 测试文档工作流 2024-08-19 23:49:21 +08:00
6dcb085b53 🚀 测试文档工作流 2024-08-19 23:47:39 +08:00
55a427e344 📝 修复生成文档中self多出类型注解的问题,修复__init__丢失的问题 2024-08-19 10:24:13 +08:00
43eef20b71 📝 修复生成文档中self多出类型注解的问题,修复__init__丢失的问题 2024-08-19 10:22:24 +08:00
b8fdb4146e 📝 修复生成文档中self多出类型注解的问题,修复__init__丢失的问题 2024-08-19 10:09:38 +08:00
cdbede7135 📝 修复生成文档中self多出类型注解的问题,修复__init__丢失的问题 2024-08-19 10:04:24 +08:00
85a3a9ad52 📝 生成了api文档 2024-08-19 09:55:47 +08:00
943e0c2665 修正工作流 2024-08-19 09:43:46 +08:00
fd4d680e87 修正工作流 2024-08-19 00:14:34 +08:00
0b763135c9 Merge remote-tracking branch 'origin/main' 2024-08-19 00:12:12 +08:00
832cc2ec44 修正工作流 2024-08-19 00:11:54 +08:00
3160b4be69 添加依赖版本检测 2024-08-19 00:06:24 +08:00
775596b5bf 🔥 remove melobot 2024-08-19 00:00:12 +08:00
84782a92d8 ⬆️ 更新nonebot依赖版本 2024-08-18 23:54:35 +08:00
6e817111cb 🐛 修复依赖pdm错误的问题 2024-08-18 23:52:59 +08:00
cd8d631348 📝 添加快速启动说明 2024-08-18 23:52:26 +08:00
af37e61d05 📝 修复中文文档 快速部署 路由错误 2024-08-18 23:43:48 +08:00
803b65e08e add color plugin name 2024-08-18 23:39:19 +08:00
aa9abde63a 🔖 liteyuki 6.3.6 2024-08-18 21:45:59 +08:00
9c35abc6e2 🔖 liteyuki 6.3.6 2024-08-18 21:45:11 +08:00
1af95a15aa 🔖 liteyuki 6.3.6 2024-08-18 21:29:19 +08:00
d2b693b1e0 Merge remote-tracking branch 'origin/main' 2024-08-18 21:26:29 +08:00
b05bbf2f19 🐛 Linux下创建子进程出错的问题 fork -> spawn 2024-08-18 21:26:19 +08:00
37ed3b0824
🐛 修复注册失败的问题 2024-08-18 19:58:36 +08:00
b56ec5ce38 Merge remote-tracking branch 'origin/main' 2024-08-18 11:51:18 +08:00
1fb3f6cd58 🐛 修复pdm依赖缺失 2024-08-18 11:51:07 +08:00
1dfe1a5819
🔖 发布NoneBot插件 liteyukibot-plugin-nonebot 2024-08-18 08:12:29 +08:00
5d194b8ebe 新增插件类型枚举 2024-08-18 08:06:25 +08:00
78810d2ca8 新增开发者模式,快速运行插件 2024-08-18 05:19:52 +08:00
87d4202ed3 新增开发者模式,快速运行插件 2024-08-18 05:11:10 +08:00
1d0b18291e 新增开发者模式,快速运行插件 2024-08-18 05:10:57 +08:00
16df5706ff 🚸 添加发布工作流 2024-08-18 04:40:02 +08:00
1b24157f08 🚸 添加发布工作流 2024-08-18 04:37:58 +08:00
8ba50b7bd6 🚸 添加发布工作流 2024-08-18 04:34:54 +08:00
502ccb46bb 🚸 添加发布工作流 2024-08-18 04:29:57 +08:00
fcbc410f1a 🚸 添加发布工作流 2024-08-18 04:26:50 +08:00
85a7c28a3a 🚸 添加发布工作流 2024-08-18 04:24:38 +08:00
7bd0da9316 🚸 添加发布工作流 2024-08-18 04:24:32 +08:00
212c338fcd 🚸 添加发布工作流 2024-08-18 04:22:55 +08:00
137270b886 🚸 添加发布工作流 2024-08-18 04:22:03 +08:00
079b940d8e 🚸 添加发布工作流 2024-08-18 04:18:20 +08:00
e396db67ce 🚸 添加发布工作流 2024-08-18 04:15:09 +08:00
f37b469ab9 🚸 添加发布工作流 2024-08-18 04:05:33 +08:00
0a3363ebce 🚸 添加发布工作流 2024-08-18 03:58:13 +08:00
53291822c0 🚸 添加发布工作流 2024-08-18 03:57:15 +08:00
5f5dcc7f99 🚸 添加发布工作流 2024-08-18 03:49:00 +08:00
9d27abfe04 🚸 添加发布工作流 2024-08-18 03:40:06 +08:00
4b4f030fe3 🚸 添加发布工作流 2024-08-18 03:31:29 +08:00
d5b0f947e0 🚸 添加发布工作流 2024-08-18 02:24:12 +08:00
9e6372185f Merge remote-tracking branch 'origin/main' 2024-08-18 02:20:21 +08:00
0e125f7c81 🚸 添加发布工作流 2024-08-18 02:20:09 +08:00
a3ea422ec3 支持通道通过通道在进程中传递 2024-08-18 01:25:11 +08:00
8d78e643e0 支持通道通过通道在进程中传递 2024-08-17 23:46:43 +08:00
aa9cae7008 Merge remote-tracking branch 'origin/main' 2024-08-17 19:12:22 +08:00
48085a946d 对通道类添加类型检查和泛型 2024-08-17 19:12:11 +08:00
8e27f6b9b0 对通道类添加类型检查和泛型 2024-08-17 19:10:03 +08:00
f980e77a4a 对通道类添加类型检查和泛型 2024-08-17 17:41:56 +08:00
01798f7b11
📝 fix docs router error 2024-08-17 04:50:27 +08:00
03057c8ef9 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/.vuepress/public/js/zh/get_data.js
#	docs/.vuepress/theme.ts
#	docs/README.md
#	docs/en/README.md
2024-08-17 02:38:58 +08:00
ee851116d8 🐛 文档构建失败的问题 2024-08-17 02:38:24 +08:00
d367903946 📝 添加英文文档框架 2024-08-17 02:24:25 +08:00
66ade9efc6 Merge remote-tracking branch 'origin/main' 2024-08-17 01:28:08 +08:00
ff41e72378 📝 添加英文文档框架 2024-08-17 01:27:57 +08:00
169f1645a4
📝 Update dev_comm.md
📝
2024-08-17 00:39:49 +08:00
c3914b2b15 📝 添加shared_memory文档 2024-08-17 00:31:05 +08:00
b356524a9e 📝 添加shared_memory文档 2024-08-17 00:18:06 +08:00
85a13251a5 🐛 Ctrl+C 无法终止Channel接收线程的问题 2024-08-16 23:43:43 +08:00
0417805e46 🚚 移除通信测试插件 2024-08-16 22:53:54 +08:00
d3f1e35a12 📝 新增NoneBot插件 2024-08-16 21:53:12 +08:00
ff585ac7c2 新增线程安全共享内存储存器(注释) 2024-08-16 21:44:27 +08:00
1b692dd13f 新增线程安全共享内存储存器 2024-08-16 21:43:29 +08:00
dd00e6ecec Merge remote-tracking branch 'origin/main' 2024-08-16 21:38:34 +08:00
222250bc41 新增线程安全共享内存储存器 2024-08-16 21:38:22 +08:00
c36e706731
Merge pull request #64 from ElapsingDreams/main
🐛 继续修复liteyuki_status目录名过长布局问题, 💄 更新其显示布局
2024-08-16 03:00:01 +08:00
adc9b76688 🐛 修复无法重启进程的问题(未启动生命监视器) 2024-08-16 02:56:50 +08:00
Envision
2e3ea96972 🐛 继续修复liteyuki_status目录名过长布局问题, 💄 更新其显示布局 2024-08-15 23:22:25 +08:00
9b07d41f86 在结束进程时无法杀死进程的问题 2024-08-15 17:32:02 +08:00
65ad377099 Merge remote-tracking branch 'origin/main' 2024-08-15 16:40:58 +08:00
a61357f4e2 🐛 在结束进程时无法杀死进程的问题 2024-08-15 16:40:46 +08:00
60403b2a4f
Merge pull request #63 from ElapsingDreams/main
🐛 尝试修复liteyuki_status插件目录过长的布局问题
2024-08-15 03:06:16 +08:00
Envision
624afa57ba 🐛 尝试修复liteyuki_status插件目录过长的布局问题 2024-08-15 02:59:03 +08:00
36a39e1ed7
Merge pull request #62 from ElapsingDreams/main
🌐 liteyuki_weather i18n (虽然仅支持三种语言)
2024-08-13 02:35:03 +08:00
ElapsingDreams
4a872c3435
Merge branch 'LiteyukiStudio:main' into main 2024-08-12 22:14:25 +08:00
Envision
90b9d1af1e 🌐 liteyuki_weather i18n (虽然仅支持三种语言) 2024-08-12 22:13:59 +08:00
551ca06ea7
Merge pull request #61 from ElapsingDreams/main
🩹非关键问题的简单修复:插件服务声明
2024-08-12 20:40:22 +08:00
ElapsingDreams
61c0cf2c2d
Update weather_now.js 2024-08-12 20:01:29 +08:00
Envision
e801a99f67 🩹非关键问题的简单修复:插件服务声明 2024-08-12 19:13:03 +08:00
ElapsingDreams
beebfe7deb
Merge branch 'LiteyukiStudio:main' into main 2024-08-12 16:48:24 +08:00
Envision
32e1963d5a 🎨热修复前端显示 🙈更新.gitignore 2024-08-12 16:47:16 +08:00
facf5bedb1
Merge pull request #59 from ElapsingDreams/main
🎨🐛 修复了一个潜在的前端显示bug,优化代码结构
2024-08-12 16:37:38 +08:00
Envision
035d43fb18 🎨🐛 修复了一个潜在的前端显示bug,优化代码结构 2024-08-12 16:04:27 +08:00
0d5f9fee52 📝 尝试修复文档有些段落显示两次的问题 2024-08-12 15:47:59 +08:00
3cb03fa4dc 📝 添加轻雪插件编写的一些注释 2024-08-12 06:07:01 +08:00
47ef3f2a49 📝 添加轻雪插件编写简易文档和轻雪进程通信说明 2024-08-12 05:50:12 +08:00
8568c7bb99 新增observer类和开发调试器 2024-08-12 05:26:36 +08:00
02cf058552 Merge remote-tracking branch 'origin/main' 2024-08-12 04:46:33 +08:00
c9157f0e2c 新增observer类和开发调试器 2024-08-12 04:45:59 +08:00
83325e63ea 添加默认配置文件,支持多种及多个配置文件 2024-08-12 02:47:53 +08:00
37b8d969b1 🐛 fix 通道无法在进程内传递消息的问题 2024-08-12 02:41:53 +08:00
298bdc7b8c
Merge pull request #58 from ElapsingDreams/main
Add New function and layout for liteyuki_weather
2024-08-11 21:45:30 +08:00
Envision
81a191f8ba Add New function and layout for liteyuki_weather 2024-08-11 01:40:26 +08:00
c3fc5d429b 🐛 fix 多线程占用数据库的问题 2024-08-10 23:35:32 +08:00
b08c934c78 🐛 fix 多线程占用数据库的问题 2024-08-10 23:34:34 +08:00
1b1ddbdd8d 🐛 fix 多线程占用数据库的问题 2024-08-10 22:54:00 +08:00
0d16d53cb7 🐛 fix 通道类回调函数在进程间传递时无法序列号的问题 2024-08-10 22:42:01 +08:00
6c39ed8ab5 🐛 fix 通道类回调函数在进程间传递时无法序列号的问题 2024-08-10 22:36:30 +08:00
2f8999b5ad 🐛 fix 通道类回调函数在进程间传递时无法序列号的问题 2024-08-10 22:27:42 +08:00
7107d03b72 🐛 fix 通道类回调函数在进程间传递时无法序列号的问题 2024-08-10 22:25:41 +08:00
3bd40e7271 🐛 修复生命周期钩子函数的问题 2024-08-08 18:10:18 +08:00
8ace3e68f4 Merge remote-tracking branch 'origin/main' 2024-08-08 18:06:14 +08:00
f69feb1def 🐛 修复生命周期钩子函数的问题 2024-08-08 18:06:03 +08:00
9fb423d5e0
Merge pull request #55 from ElapsingDreams/main
📝Hot Fixed Dev judgment
2024-08-08 16:57:16 +08:00
ElapsingDreams
e9df67a661
📝Hot Fixed Dev judgment 2024-08-08 16:55:58 +08:00
b6871ea13a
Merge pull request #54 from ElapsingDreams/main
Add Dev judgement
2024-08-08 16:49:00 +08:00
ElapsingDreams
cb84a7d0d9
Add Dev judgment 2024-08-08 16:41:23 +08:00
ElapsingDreams
25f7540f86
Add Dev judgment 2024-08-08 16:40:34 +08:00
c29a3fd6d4 🐛 数据库未进行迁移前初始化 2024-08-05 07:23:04 +08:00
ab48396db9 🐛 数据库未进行迁移前初始化 2024-08-05 07:13:41 +08:00
51982b63c3 📝 新增全球统计 2024-08-05 06:05:37 +08:00
2b537d27ec 📝 新增全球统计 2024-08-05 06:02:53 +08:00
16930e96aa 📝 新增全球统计 2024-08-05 06:00:07 +08:00
d63ba4943a 📝 新增全球统计 2024-08-01 13:17:48 +08:00
5d22f20ce3 📝 新增全球统计 2024-08-01 13:11:05 +08:00
2451849fd6 📝 新增全球统计 2024-08-01 12:33:36 +08:00
61680d9e87 📝 新增全球统计 2024-08-01 12:28:44 +08:00
850dd75822 📝 新增全球统计 2024-08-01 12:23:56 +08:00
6ba983fae3 🐛 fix: Channel的接收者过滤器的问题,优化重启部分 2024-07-31 02:35:05 +08:00
ca34f9c2a1 🐛 fix: Channel的接收者过滤器的问题,优化重启部分 2024-07-31 02:28:25 +08:00
0fb5b84392 🐛 移除liteyuki.channel.on_receive() wrapper对async和sync function的判断冗余代码 2024-07-27 10:21:31 +08:00
39a9c39924 添加liteyuki.channel.Channel通道,可安全跨进程通信 2024-07-27 10:12:45 +08:00
13692228c6 添加进程及生命周期管理器,添加轻雪框架支持 2024-07-26 14:35:47 +08:00
f22f4d229d 添加进程及生命周期管理器,添加轻雪框架支持 2024-07-24 02:58:16 +08:00
97dbf42a4d 添加进程及生命周期管理器,添加轻雪框架支持 2024-07-24 02:57:35 +08:00
041a219151 添加进程及生命周期管理器,添加轻雪框架支持 2024-07-24 02:54:59 +08:00
c137f2f916 添加进程及生命周期管理器,添加轻雪框架支持 2024-07-24 02:36:46 +08:00
6ef3b09ec9 📝 恢复pyproject.toml 2024-07-21 16:06:50 +08:00
263b78e995 📝 修改文档语言风格 2024-07-21 00:40:55 +08:00
0d87848a7e
📝 修改文档语言风格 2024-07-20 18:32:40 +08:00
44ad0832ba
📝 修改文档语言风格 2024-07-20 18:31:51 +08:00
93ced26e07
Merge pull request #52 from EillesWan/main
🎇修复liteyuki_pacman在执行disable时因session_id导致的反馈不当 & 🀄优化文言文翻译,修复翻译漏洞
2024-07-15 02:40:30 +08:00
363daf6251 🎇修复liteyuki_pacman在执行disable时因session_id导致的反馈不当
🀄优化文言文翻译,修复翻译漏洞
2024-07-15 02:31:47 +08:00
a6b1d1c9e0
Merge pull request #51 from EillesWan/main
🥠修复状态缓存出错的问题 & 📃规范化文言文本地化文本
2024-07-15 02:26:07 +08:00
576d8c23b3 🥠修复状态缓存出错的问题
🧾规范化文言文本地化文本
2024-07-15 02:07:15 +08:00
c232c6e5f6 插件商店及资源商店新增搜索功能 2024-07-15 00:22:52 +08:00
5d6ae52157 插件商店及资源商店新增搜索功能 2024-07-15 00:03:22 +08:00
01e6256ed4 插件商店及资源商店新增搜索功能 2024-07-14 23:50:31 +08:00
dbc114a529 插件商店及资源商店新增搜索功能 2024-07-14 13:46:54 +08:00
4d77af8f0c 插件商店及资源商店新增搜索功能 2024-07-14 13:43:47 +08:00
c36a925bb5 插件商店及资源商店新增搜索功能 2024-07-14 13:38:25 +08:00
605dd035d4
Merge pull request #49 from EillesWan/main
完善翻译文本 & 优化状态缓存
2024-07-14 02:38:51 +08:00
7526ae13d7 补一个错 2024-07-14 02:30:04 +08:00
0eb41f70d2 Merge branch 'main' of https://github.com/LiteyukiStudio/LiteyukiBot 2024-07-14 02:21:10 +08:00
a4c7ee738c 更改内容:
1. 更新文言文翻译
2. 删除重复的翻译键
3. 重写status缓存机制并black格式化
请注意:未经过本地测试,需要观察者辅助测试,谢谢!
2024-07-14 02:19:57 +08:00
8d4602c40d
📝 add more background rp 2024-07-13 01:26:32 +08:00
bb20d9623d
🐛 fix typo 2024-07-06 12:01:09 +08:00
73cc28d1cf
📝 update README.md 2024-07-06 11:29:05 +08:00
ae54cd923c
📝 update README.md 2024-07-06 11:25:36 +08:00
9d3c9a7d70
📝 update and rename Lisence to LICENSE 2024-07-06 10:59:22 +08:00
92a4274be7
Merge pull request #47 from Nanaloveyuki/main
📄 更新许可证 MIT -> LSO & LSO-AGC
2024-07-06 10:54:07 +08:00
Nanaloveyuki
4800b3f46c
📄 更新许可证文件
完成MIT->LSO的更迭工作
2024-07-06 10:35:47 +08:00
Nanaloveyuki
cce593b2f4
📄 移除原MIT许可 2024-07-06 10:32:08 +08:00
Nanaloveyuki
c491642713
📄 移除AGC非许可形式协议 2024-07-06 10:31:50 +08:00
Nanaloveyuki
5b4dd638a4
📄 移除原LSO许可 2024-07-06 10:31:31 +08:00
8440952167
📝 update repo url in src 2024-07-06 02:26:33 +08:00
4e4227e204
📝 update repo url 2024-07-06 02:25:12 +08:00
effb01d43c
📝 add 2nd license 2024-07-04 02:08:07 +08:00
28d730a2ca
Merge pull request #46 from Nanaloveyuki/main
🌐 📝 日常优化文档, 提供多语言支持
2024-07-01 17:30:16 +08:00
Nanaloveyuki
0bd135a5c9
🌐 为statistics提供基础多语言支持 2024-07-01 16:08:15 +08:00
Nanaloveyuki
5522391942
Add files via upload 2024-07-01 16:00:46 +08:00
7576355e95
📝 商店新增轻雪Kakyo语言包 2024-06-30 03:28:28 +08:00
c9e518f2ed
Merge pull request #45 from Nanaloveyuki/main
📄 更新反克隆文件`Anti-Gitcode-Clone.md`
2024-06-29 23:09:22 +08:00
Nanaloveyuki
593cf2407b
Merge branch 'main' into main 2024-06-29 00:53:23 +08:00
Nanaloveyuki
bdb4c76d70
📄 Add Anti-Gitcode-Clone md-file 2024-06-29 00:40:14 +08:00
Nanaloveyuki
7cce805d39
📄 Delete Dis-CSDN-Gitcode.md 2024-06-29 00:25:59 +08:00
b9d3ecc15d
Merge pull request #44 from Nanaloveyuki/main
📄 Add Anti-Gitcode-Clone md-file
2024-06-29 00:20:19 +08:00
Nanaloveyuki
ec5eae08f7
📄 Add Anti-Gitcode-Clone md-file 2024-06-29 00:15:44 +08:00
c1edf31577
🔥 create dependabot.yml 2024-06-27 04:17:39 +08:00
5262c04e46 🔥 小型重构 2024-06-26 13:53:15 +08:00
8b01943d14 🔥 小型重构 2024-06-26 13:52:04 +08:00
35823be13e 新增 stat rank 功能 2024-06-25 20:06:49 +08:00
4162ea33ff orm框架新增@db.on_save回调函数,用于检测数据库更新时的变动 2024-06-22 14:17:14 +08:00
1787ef4db7 📝 更新夜间logo 2024-06-19 23:38:53 +08:00
38b13611c9 📝 更新夜间logo 2024-06-19 23:31:11 +08:00
52fa143e75 📝 更新夜间logo 2024-06-19 22:30:27 +08:00
89047a0c8a 📝 更新小logo 2024-06-19 17:59:57 +08:00
9fbded7d6a 📝 部署部分文档优化 2024-06-19 12:34:38 +08:00
c657781599 🔥 移除测试工作流 2024-06-19 12:16:42 +08:00
ecbe1ff79e 新logo 2024-06-19 12:15:22 +08:00
d6811ab9b3 新logo 2024-06-18 23:57:15 +08:00
d45170db3e 新logo 2024-06-18 23:36:04 +08:00
6e63768c71 新logo 2024-06-18 23:32:58 +08:00
1424bc2cf6 Merge remote-tracking branch 'origin/main' 2024-06-18 23:25:33 +08:00
051fe3d15d 新logo 2024-06-18 23:25:23 +08:00
fcae485071 新logo 2024-06-18 23:23:44 +08:00
2e9a7fdf94
Merge pull request #42 from Nanaloveyuki/main
📝  主要更新06-17
2024-06-17 18:46:12 +08:00
Nanaloveyuki
570d7e18a4 Docs 主要更新: 优化表格
主要改动:
- 表格
- 标点符号
- 愚人节主页
2024-06-16 23:33:58 +08:00
8ac53970a3 Merge remote-tracking branch 'origin/main' 2024-06-16 02:02:25 +08:00
dd3e108e10 新logo 2024-06-16 02:01:53 +08:00
Snowykami
c29bd81ffb
Merge pull request #41 from MiaoMioLint/patch-1
详细化 lyfunc.md
2024-06-13 09:54:15 +08:00
Nanaloveyuki
a1173e4d84
详细化 lyfunc.md 2024-06-13 09:47:13 +08:00
Snowykami
d877e30a05
📝 添加2次quote的解释 2024-06-10 07:33:44 +08:00
33ad54090d 新版本npm 2024-06-09 22:36:58 +08:00
83ee6cfdbd 新版本npm 2024-06-04 18:04:25 +08:00
f48971a0c4 🐛 orm框架在解析字段值时遇到None报错的问题 2024-06-04 18:00:38 +08:00
a4b71aa73c 🐛 orm框架在解析字段值时遇到None报错的问题 2024-06-03 17:58:46 +08:00
4b7df662e8 Merge remote-tracking branch 'origin/main' 2024-06-03 17:54:32 +08:00
4cd7b6718b 🐛 orm框架在解析字段值时遇到None报错的问题 2024-06-03 17:53:44 +08:00
Snowykami
ac2a94dda0
Merge pull request #40 from yuhan2680/patch-1
添加词库w
2024-06-03 13:54:18 +08:00
神楽坂小涵🍥
de7e65b32a
添加词库w 2024-06-03 13:52:34 +08:00
1b283261c3 词库性格区分 2024-06-02 23:21:14 +08:00
39cbfc1baa 词库性格区分 2024-06-02 23:18:00 +08:00
e563f18d31 词库性格区分 2024-06-02 23:15:38 +08:00
1d03b3f28f 词库性格区分 2024-06-02 23:12:24 +08:00
ae0025a203 词库性格区分 2024-06-02 23:09:59 +08:00
b5bd7acb7f 词库性格区分 2024-06-02 22:56:37 +08:00
657e7e52ac 📝 空字符串 2024-06-02 15:03:50 +08:00
d6341c88cd 📝 函数指引 2024-06-02 13:58:41 +08:00
bdb1191f9e 🐛 智障回复分词bug 2024-06-02 02:32:54 +08:00
3b29b67c0b 📝 函数指引 2024-06-02 02:23:00 +08:00
cc43e53c4b npm 会话开关功能新增群号可选项 2024-06-02 02:22:16 +08:00
a25c900d49 智障回复功能支持切断回复 2024-06-02 01:41:46 +08:00
206651da94 智障回复功能 2024-06-02 01:32:52 +08:00
be28116a98 优化状态卡片速度 2024-06-01 15:32:41 +08:00
4cdf29557c 新增启动时对本地仓库的检测 2024-06-01 15:26:13 +08:00
62928e47eb 新增启动时对本地仓库的检测 2024-06-01 15:25:54 +08:00
9b50b719d9 🚀 对lyfunction命令添加鉴权 2024-06-01 15:05:45 +08:00
def60bf298 对lyfunction命令添加鉴权 2024-06-01 15:01:14 +08:00
6496b6e463 对lyfunction命令添加鉴权 2024-06-01 15:01:04 +08:00
6ce4c972a0 对lyfunction命令添加鉴权 2024-06-01 14:16:04 +08:00
70e3c9968a 添加对lyfunction的支持 2024-05-31 23:15:40 +08:00
074882f092 添加对lyfunction的支持 2024-05-31 22:59:02 +08:00
c2b3018908 添加对lyfunction的支持 2024-05-31 22:42:04 +08:00
96c85d9dca Merge remote-tracking branch 'origin/main' 2024-05-31 19:17:31 +08:00
e15aafd781 添加对zip格式的资源包的支持,对function的支持 2024-05-31 19:17:25 +08:00
Snowykami
9e17b84a5d
🐛 一些单词复数形式 2024-05-28 18:28:20 +08:00
c66d470166 🐛 mdts反转义错误的问题 2024-05-27 18:32:58 +08:00
4deb7d11a1 新增开发者选项是否允许更新 2024-05-26 18:15:57 +08:00
6f069f83d4 📝 文档新增特性 2024-05-26 18:11:18 +08:00
fa53df1e8a 📝 文档新增特性 2024-05-26 17:25:20 +08:00
ba17f9d159 📝 文档新增特性 2024-05-26 17:19:32 +08:00
b558b51601 📝 文档新增特性 2024-05-26 17:12:06 +08:00
3ea0acd48b 修改启动逻辑和插件加载逻辑 2024-05-26 16:38:38 +08:00
c171873fa6 优化圆角样式 2024-05-25 12:09:54 +08:00
1ccf94883a 消息统计新增指定用户选项 2024-05-25 00:13:29 +08:00
b26f8e0d24 消息统计新增指定用户选项 2024-05-24 23:46:24 +08:00
5bc2725d1b 消息统计新增指定用户选项 2024-05-24 23:41:33 +08:00
8e06244311 🐛 修复了消息模型储存时类型不兼容的问题 2024-05-23 23:37:24 +08:00
0f35613e50 🐛 修复了消息模型储存时类型不兼容的问题 2024-05-23 23:32:02 +08:00
4cfad0b5ca 添加了外部资源热重载 2024-05-21 13:13:16 +08:00
c2593e71c0 Merge remote-tracking branch 'origin/main' 2024-05-20 23:31:45 +08:00
bb331232ca 添加了外部资源热重载 2024-05-20 23:31:11 +08:00
Snowykami
96e8293bf4
Merge pull request #39 from expliyh/qweather_on_satori
🐛 在使用 satori 适配器时不能响应例如 武汉天气 的指令
2024-05-20 13:54:04 +08:00
Expliyh
e13464cb7c
拼写错了(尴尬) 2024-05-20 08:51:21 +08:00
Expliyh
c5f8fbe86d
🐛 在使用 satori 适配器时不能响应例如 武汉天气 的指令 2024-05-20 08:22:06 +08:00
Expliyh
8667706377
使用 alc 发送例如 天气武汉 的回复 2024-05-20 08:20:20 +08:00
Snowykami
86e47ab226
Merge pull request #38 from expliyh/satori
对昨晚 PR 的一些修正
2024-05-19 23:27:43 +08:00
Expliyh
10c383d66a
删除无用的 print 2024-05-17 18:16:57 +08:00
Expliyh
4c65a308d6
🐛 当没有 .env 文件时意外加载错误的环境变量 2024-05-17 18:00:07 +08:00
Expliyh
246e43317f
📝 添加 onebot_v12_event_monitor 2024-05-17 17:53:38 +08:00
Expliyh
974b97b744
📝 初次启动生成默认配置文件时添加 satori 相关配置
📝 将适配器配置初始化和注册移动到 utils.adapter_manager
2024-05-17 17:51:42 +08:00
Expliyh
c914ddc0ee
📝 NapCat.Onebot 显示头像 2024-05-17 17:48:37 +08:00
Expliyh
6509b293db
📝 使用 driver_manager 自动管理启用的驱动器,无需手动配置环境变量 (当配置了环境变量时环境变量优先) 2024-05-17 16:33:48 +08:00
Expliyh
a72eeb4c3f
📝 使用 driver_manager自动管理启用的驱动器,无需手动配置环境变量 (当配置了环境变量时环境变量优先) 2024-05-17 16:26:30 +08:00
Expliyh
309397b72c
📝 将从事件中获取信息的工具函数移动到单独的 utils.event 2024-05-17 15:00:01 +08:00
Expliyh
077658c68d
📝 将 Satori 用户缓存更新日志的输出时机由原来的每次调用函数调整为每次用户信息发生变更 2024-05-17 14:42:37 +08:00
Expliyh
322ad19889
🐛 在使用 satori 时部分指令无响应
🐛 使用 onebot 时部分事件在 postprocessor 阶段报错
2024-05-17 14:18:55 +08:00
ab9d3d3d3e 🐛 satori.Adapter TypeError: 'HeartbeatMetaEvent' object is not subscriptable 2024-05-17 00:25:27 +08:00
Snowykami
06a109d2b5
Merge pull request #37 from expliyh/satori
试着添加了对于 NoneBot-Adapter-Satori 的支持
2024-05-16 23:31:54 +08:00
Expliyh
351743068a
判断配置文件是否启用satori 2024-05-16 22:15:04 +08:00
Expliyh
4e6532ff0d
pacman和profile适配satori 2024-05-16 21:28:18 +08:00
Expliyh
eaf57f2c33
status适配satori 2024-05-16 21:17:10 +08:00
Expliyh
7abdac7c9c
statistic适配satori 2024-05-16 20:28:46 +08:00
Expliyh
002df66878
weather适配satori(bind city未找到) 2024-05-16 20:22:07 +08:00
Expliyh
251bfaf410
Core适配satori 2024-05-16 20:09:20 +08:00
Expliyh
24722447da
使用satori时维护一个有昵称的用户列表
get_plugin_session_enable 判断当前使用的适配器
2024-05-16 19:20:54 +08:00
Expliyh
90e7a90bcf
添加 nonebot-adapter-satori~=0.11.5 2024-05-16 17:32:06 +08:00
6d3d3fc52c output to latest 2024-05-14 10:37:32 +08:00
e843d790b1 message 统计 2024-05-13 19:37:10 +08:00
c90ac1d21a message 统计 2024-05-12 03:04:26 +08:00
041ceb81d8 message 统计 2024-05-12 02:47:14 +08:00
c6f2a29320 使用webp背景图压缩资源包大小 2024-05-12 00:25:51 +08:00
0532d7592e Merge remote-tracking branch 'origin/main' 2024-05-12 00:23:36 +08:00
f9fe1922d4 使用webp背景图压缩资源包大小 2024-05-12 00:18:53 +08:00
Snowykami
88b5b55062
Update issue templates 2024-05-11 10:57:36 +08:00
afe501a06d 使用webp背景图压缩资源包大小 2024-05-11 10:05:01 +08:00
43dfc9a940 Add sign status for Lagrange.Core 2024-05-11 01:16:48 +08:00
7fbfafe2db Add sign status for Lagrange.Core 2024-05-11 01:00:13 +08:00
f22f8f772a Add sign status for Lagrange.Core 2024-05-11 00:34:11 +08:00
205b69e5cb Add sign status for Lagrange.Core 2024-05-11 00:16:38 +08:00
75a4d1fdcb Add sign status for Lagrange.Core 2024-05-10 20:43:16 +08:00
b3aa5c9e02 启用联合黑名单 2024-05-10 00:12:48 +08:00
38b496d800 Merge remote-tracking branch 'origin/main' 2024-05-09 21:38:45 +08:00
Snowykami
d2bb672f65
fix: main.py 2024-05-09 20:49:39 +08:00
6c267c6072 📝 更新调试模式配置 2024-05-09 16:37:50 +08:00
598260895c 📝 更新调试模式配置 2024-05-09 16:36:45 +08:00
e02dfdf5d6 更新NoneBot依赖版本 2024-05-09 16:25:47 +08:00
154b342057 New plugin Minecraft工具箱 2024-05-09 13:06:04 +08:00
b8375013a3 联合黑名单支持 2024-05-09 00:14:14 +08:00
5913528d32 Merge remote-tracking branch 'origin/main' 2024-05-09 00:09:44 +08:00
773137591f 联合黑名单支持 2024-05-09 00:09:18 +08:00
8fa0470187 联合黑名单支持 2024-05-08 23:40:16 +08:00
Snowykami
bf768b6cb5
update status.css 2024-05-07 08:48:37 +08:00
9b8c38cac0 docker支持 2024-05-01 02:39:28 +08:00
1f96372196 docker支持 2024-05-01 02:17:21 +08:00
148d671b5d 使用内存换速度 2024-04-30 15:23:12 +08:00
61d91ea0a9 🐛 状态卡片部分css样式异常 2024-04-29 17:05:55 +08:00
f9317802f4 Merge remote-tracking branch 'origin/main' 2024-04-29 16:59:03 +08:00
8809459f1b 🐛 轻雪天气获取空aqi值的异常错误 2024-04-29 16:58:52 +08:00
Snowykami
8f906f2d12
fix: 天气显示错误 2024-04-29 07:35:17 +08:00
Snowykami
269dd5ced2
fix: 轻雪天气星期几显示错误 2024-04-29 07:29:08 +08:00
c063c69dea 🐛 修复群聊启用在带参数不正确的问题 2024-04-28 18:52:22 +08:00
d43fe327c2 🔥 remove some of requirements.txt 2024-04-28 12:49:12 +08:00
d80c4a7c90 feat: pydantic v2 支持
fix: 自动更新后更新依赖
2024-04-27 21:38:37 +08:00
Snowykami
4d274df6b2
fix: weather timezone 2024-04-27 13:18:59 +08:00
431ebb59c2 轻雪天气更新 2024-04-27 11:45:31 +08:00
3713bf397c 轻雪天气更新 2024-04-27 11:42:58 +08:00
86c7b70e63 轻雪天气更新 2024-04-27 02:20:44 +08:00
9cfdd375ca 更新语言包至2024.4.26版本 2024-04-26 20:20:56 +08:00
c4e00e3402 更新语言包至2024.4.26版本 2024-04-26 20:20:53 +08:00
93e1a0ff77 全新资源包结构 2024-04-26 15:11:31 +08:00
f69844717f 新版状态页面 2024-04-26 15:06:21 +08:00
5100ca6c77 新版状态页面 2024-04-26 15:02:46 +08:00
857e58d635 : zap: 添加api请求超时限制 2024-04-26 12:39:43 +08:00
bb9b8a1ced : bug: 放宽依赖限制 2024-04-26 00:50:28 +08:00
b240d75552 : bug: 哈哈哈哈哈哈哈,markdown又寄了 2024-04-24 20:09:23 +08:00
0a1d96c434 : bug: 哈哈哈哈哈哈哈,markdown又活了 2024-04-24 16:33:58 +08:00
fe2ca8b05b 🐛 哈哈哈哈哈哈哈,markdown寄了,发图片 2024-04-24 15:20:32 +08:00
bfb5cf2cf0 🐛 api命令字符串错误输出 2024-04-24 15:12:26 +08:00
a6408a3397 📝 添加字体原有版权声明 2024-04-24 15:07:57 +08:00
5db29c7e2c 📝 添加字体原有版权声明 2024-04-24 00:44:45 +08:00
a38e2b887c 📝 添加字体原有版权声明 2024-04-24 00:23:05 +08:00
4a8ddaba2d 更新依赖 2024-04-23 23:10:58 +08:00
e1879bbebd 更新依赖 2024-04-23 22:59:30 +08:00
6b51b5fe9d Merge remote-tracking branch 'origin/main' 2024-04-23 21:49:54 +08:00
acfc70ea50 🐛 在读取数据库前进行迁移 fix #35 2024-04-23 21:49:16 +08:00
Snowykami
fb495d34d5
fix: typo 2024-04-23 07:45:38 +08:00
Snowykami
af038cb789
feat: 修改菜单样式 2024-04-23 07:42:56 +08:00
53bc6df30f 独立status插件... 2024-04-22 23:55:33 +08:00
ece71ca1e7 预渲染数据,发送更快 2024-04-22 21:08:08 +08:00
a0079da01b Merge remote-tracking branch 'origin/main' 2024-04-22 21:06:42 +08:00
bd5f6c5205 预渲染数据,发送更快 2024-04-22 21:05:35 +08:00
Snowykami
9687ddb842
docs: 资源包主页文档指引 2024-04-22 14:05:10 +08:00
ae19113141 Merge remote-tracking branch 'origin/main' 2024-04-21 14:15:34 +08:00
8b55156da9 新增api命令 2024-04-21 14:15:12 +08:00
Snowykami
34ba5ffde3
Merge pull request #34 from MoeSnowyFox/main
💩修复npm帮助部分文本错误
2024-04-21 01:10:08 +08:00
SnowyFox
e948b9e94e
💩补充文本 2024-04-20 23:09:22 +08:00
SnowyFox
e3ec25790f
💩 修复npm帮助界面输出错误 2024-04-20 23:08:07 +08:00
SnowyFox
6ea3b2c1e2
Merge pull request #2 from snowykami/main
1
2024-04-20 23:01:58 +08:00
1a930dc604 轻雪API文档 2024-04-20 17:02:57 +08:00
e0982f3a24 新增安全模式启动 2024-04-20 12:47:42 +08:00
18d9ac3249 新增安全模式启动 2024-04-20 12:46:49 +08:00
7585a5473d 🐛 npm显示异常 2024-04-20 04:42:11 +08:00
4dd3b4aedc 📝 插件商店支持 2024-04-20 04:10:20 +08:00
5a9e8449cc 📝 add help command 2024-04-19 00:45:57 +08:00
62a2755ecf 🐛 fix typo update -> upsert 2024-04-19 00:31:49 +08:00
SnowyFox
6e66c95487
Merge pull request #1 from snowykami/main
1
2024-04-18 23:35:25 +08:00
Snowykami
5c1170f6fb
Merge pull request #33 from MoeSnowyFox/main
一些修改
2024-04-18 23:27:49 +08:00
SnowyFox
dc83d6b469
Update npm.py 2024-04-18 22:41:02 +08:00
SnowyFox
46715e17aa
Update runtime.py 2024-04-18 22:40:18 +08:00
SnowyFox
2e4013e948
Update runtime.py 2024-04-18 22:38:53 +08:00
SnowyFox
b284e52203
Update runtime.py 2024-04-18 22:37:57 +08:00
SnowyFox
391a183402
Update runtime.py 2024-04-18 22:36:16 +08:00
6722eeffa9 🐛 markdown暂时不可用 2024-04-18 18:15:11 +08:00
SnowyFox
2cfd0de8e3
Update runtime.py 2024-04-18 00:24:02 +08:00
SnowyFox
778bcf7623
Update npm.py 2024-04-18 00:23:29 +08:00
SnowyFox
0fcde73178
Update rpm.py 2024-04-18 00:23:14 +08:00
SnowyFox
8a0f25b5b0
Update zh-CN.lang 2024-04-18 00:22:36 +08:00
0e47e3c163 插件管理添加翻页按钮,支持从内存快速获取当前session状态 2024-04-17 20:45:44 +08:00
0e02af59ca 优先从内存读取用户信息 2024-04-17 17:45:32 +08:00
c4db4dc6a6 fix: 天气查询失败的问题 2024-04-15 20:46:09 +08:00
016fe3ef72 fix: 天气查询失败的问题 2024-04-15 20:43:39 +08:00
0d3361dc99 fix: 天气查询失败的问题 2024-04-15 20:21:50 +08:00
79d8063b5d feat: 轻雪天气实时天气功能已更新 2024-04-15 18:04:19 +08:00
Snowykami
7d0b9662f4
fix: update error 2024-04-15 06:38:06 +08:00
afbcad3a1c Merge remote-tracking branch 'origin/main' 2024-04-14 21:39:48 +08:00
15a329029d feat: 更清晰的目录结构,新的markdown构建 2024-04-14 21:39:27 +08:00
Snowykami
190e7ebdea
fix: npm search 缺失 show_num 2024-04-13 13:45:57 +08:00
65dcf36fe7 Merge remote-tracking branch 'origin/main' 2024-04-12 13:07:30 +08:00
e2779bdfd7 feat: 对nb-cli的支持 2024-04-12 13:07:19 +08:00
Snowykami
87061fb5cb
fix: Update core.py 2024-04-12 07:17:42 +08:00
Snowykami
50b851a2c4
fix: Update core.py 2024-04-12 07:16:16 +08:00
6a4c88a6ba feat: 自动更新功能 2024-04-12 01:15:05 +08:00
185b1d8a21 feat: 自动更新功能 2024-04-12 01:07:53 +08:00
7046c0d10e Merge remote-tracking branch 'origin/main' 2024-04-12 00:40:53 +08:00
83cd164a45 fix: 状态卡片百分比错误
feat: 群聊Bot开关,防止Bot乱窜
2024-04-12 00:40:41 +08:00
33dd2f104d fix: 状态卡片百分比错误
feat: 群聊Bot开关,防止Bot乱窜
2024-04-12 00:32:08 +08:00
58278fa735 feat: 同步天气api 2024-04-11 14:41:46 +08:00
f9e5742821 feat: 状态卡片模糊半径更改 2024-04-11 13:17:45 +08:00
d37442bc9d feat: 状态卡片模糊半径更改 2024-04-11 13:15:29 +08:00
Snowykami
79451ac24f
docs: Update README.md 2024-04-11 08:38:29 +08:00
38f658edf9 feat: 重启时间显示 2024-04-10 23:47:10 +08:00
db0542279b docs: Update 2024-04-10 23:06:55 +08:00
23353a3673 feat: 提供插件更新功能 2024-04-10 12:18:45 +08:00
e0dc840197 feat: 提供插件更新功能 2024-04-10 12:16:40 +08:00
f2fda7f92e fix: stats -> status 2024-04-10 10:01:41 +08:00
Snowykami
cd0812af42
docs: Update basic_command.md 2024-04-10 09:39:38 +08:00
Snowykami
6f207a54aa
docs: Update basic_command.md 2024-04-10 07:38:13 +08:00
Snowykami
aaebccf7ab
fix: arguments index 2024-04-09 07:59:45 +08:00
Snowykami
655fb0999a
docs: Update basic_command.md 2024-04-09 07:14:24 +08:00
c400eae7c8 fix: 插件安装提示找不到 2024-04-08 17:42:04 +08:00
3fba4c78dc feat: 字体 2024-04-08 17:31:03 +08:00
9346144f0e feat: 字体 2024-04-08 17:21:01 +08:00
edc86990a7 feat: 字体 2024-04-08 17:13:25 +08:00
83692ffd55 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/.vuepress/theme.js
2024-04-08 17:02:24 +08:00
8e1ec22679 feat: 野兽先辈主题包
fix: 插件模块名问题
feat: `nps` -> `npm`
2024-04-08 17:01:55 +08:00
Snowykami
29867dd187
Merge pull request #32 from Liteyuki/main
fix: 移除注释
2024-04-08 11:20:30 +08:00
Liteyuki
0f9b8fcca8
fix: 移除注释 2024-04-08 11:19:49 +08:00
195c98ddd2 fix: liteyuki_api.py -> ly_api.py 2024-04-08 10:04:31 +08:00
Snowykami
6e521497db
docs: update logo 2024-04-07 07:42:16 +08:00
Snowykami
64ce2a2971
docs: Update fandq.md 2024-04-07 07:24:07 +08:00
Snowykami
2781c8bdfb
docs: Update resource_pack.md 2024-04-07 04:16:53 +08:00
c45061a95a feat: 优化插件商店排版 2024-04-07 03:28:31 +08:00
16c1ba440c feat: 优化插件商店排版 2024-04-07 03:24:37 +08:00
e271059720 feat: 优化插件商店排版 2024-04-07 03:24:13 +08:00
9743868cce fix: npm对插件无法启用的bug
feat: 资源包的管理器
2024-04-07 00:35:53 +08:00
72742d805c docs: 资源包相关内容 2024-04-06 09:10:01 +08:00
08564b3ac6 feat: 新的资源包加载逻辑
feat: 主题商店支持
2024-04-06 08:50:25 +08:00
a76bc3de92 feat: 新的资源包加载逻辑
feat: 主题商店支持
2024-04-06 08:48:21 +08:00
be0b5e6de1 feat: 新的背景图
fix: 命令冲突
docs: 添加了命令头和nickname冲突的解释
2024-04-06 04:27:37 +08:00
bc856b4aa9 feat: 新的背景图
fix: 命令冲突
docs: 添加了命令头和nickname冲突的解释
2024-04-06 04:23:01 +08:00
468a534d85 fix: typo of config.yaml -> config.yml 2024-04-05 20:19:39 +08:00
9bfe173f92 fix: typo of config.yaml -> config.yml 2024-04-05 20:07:33 +08:00
26a15229cf fix: 内存计算误差 2024-04-05 10:26:46 +08:00
a9426ca48f feat: 系统版本显示 2024-04-05 09:44:32 +08:00
844f04d555 feat: 系统版本显示 2024-04-05 09:32:55 +08:00
731f07e062 fix: CPU频率显示位数超出范围
fix: 空驱动器显示在面板位置
2024-04-05 09:27:00 +08:00
1b3d82ebe2 feat: 新版本 2024-04-05 09:20:49 +08:00
b275a646ac feat: 新版本 2024-04-05 09:18:35 +08:00
90e059af32 feat: 新版本 2024-04-05 09:18:22 +08:00
321f19953d feat: 新版本 2024-04-05 09:15:57 +08:00
110b0cfc21 feat: 新版本 2024-04-05 09:14:26 +08:00
d9a32328b2 feat: 新版本 2024-04-05 08:55:24 +08:00
71faffaa44 feat: 更多的字体 2024-04-05 08:48:51 +08:00
edc0a16cad feat: 更多的字体 2024-04-05 07:14:35 +08:00
c5d2c040fe feat: 更多的字体 2024-04-05 07:02:18 +08:00
Snowykami
813f1c2ded
Merge pull request #30 from MoeSnowyFox/main
fix: requirements.txt
2024-04-04 17:06:23 +08:00
SnowyFox
b965d4d005
Update requirements.txt
谁家好心人写pip==24.0啊
2024-04-04 16:46:58 +08:00
d0c5385534 feat: 国产某聊天软件的图床支持 2024-04-03 14:59:40 +08:00
eaae8ceaad feat: 国产某聊天软件的图床支持 2024-04-03 14:59:00 +08:00
ad543dd738 feat: 国产某聊天软件的图床支持 2024-04-03 14:57:11 +08:00
7df870e65d feat: 国产某聊天软件的图床支持 2024-04-03 14:24:43 +08:00
263b28b2f9 feat: 国产某聊天软件的图床支持 2024-04-03 14:18:41 +08:00
4c60f09d94 Merge remote-tracking branch 'origin/main' 2024-04-03 14:10:23 +08:00
86e6397fa7 feat: 国产某聊天软件的图床支持 2024-04-03 14:10:10 +08:00
6c41a36d8e fix: nonebot未定义 2024-04-03 01:11:38 +08:00
955d9f6d62 feat: 优化了排版和渲染 2024-04-03 01:03:25 +08:00
14fb96fec2 feat:
- markdown发送失败后可以转为图片发送
- 轻雪图床支持
fix:
- 数据库删除时不提交
2024-04-02 20:32:28 +08:00
Snowykami
e7765a4513
fix: stats.html 2024-04-02 08:51:34 +08:00
Snowykami
7e302922c5
fix: 你写的垂直居中在我机子上没对齐 2024-04-02 08:01:19 +08:00
209d636919 feat: 愚人节快乐 2024-04-02 00:01:28 +08:00
55ea08cf11 feat: 愚人节快乐 2024-04-01 23:56:03 +08:00
e58e853445 feat: 愚人节快乐 2024-04-01 13:33:50 +08:00
e97bd0a50b feat: 愚人节快乐 2024-04-01 13:33:21 +08:00
31f266bf21 feat: 可以设置发送高清大图 2024-04-01 13:06:08 +08:00
b611ec1714 feat: 可以设置发送高清大图 2024-04-01 12:33:35 +08:00
4e549af1c9 feat: 可以设置发送高清大图 2024-04-01 12:30:13 +08:00
54cc57a2b2 feat: 可以设置发送高清大图 2024-04-01 12:29:04 +08:00
e43cb0ab07 feat: 愚人节快乐 2024-04-01 11:46:47 +08:00
c1ba64e7c3 feat: 愚人节快乐 2024-04-01 11:39:38 +08:00
19308ffc53 feat: 支持天气 2024-04-01 11:37:29 +08:00
Snowykami
6a03003d41
docs: Update basic_command.md 2024-04-01 07:35:34 +08:00
Snowykami
0e7e731080
Rename ISSUE_TEMPLATE_1.md to ISSUE_TEMPLATE.md 2024-04-01 03:15:43 +08:00
Snowykami
1993b46750
create: ISSUE_TEMPLATE_1.md 2024-04-01 03:14:11 +08:00
Snowykami
7ee18c4334
docs: Update config.md 2024-04-01 03:01:27 +08:00
Snowykami
00166e0ff3
Delete CNAME 2024-04-01 02:56:45 +08:00
Snowykami
b43a5827c9
docs: 修正连接路由错误 2024-04-01 01:04:16 +08:00
1619504059 docs: 修改描述 2024-03-31 19:23:15 +08:00
80a61a6eed fix: 讨论功能 2024-03-31 19:08:35 +08:00
7c551aecb2 fix: alconna响应器命令头别名配置错误的问题 2024-03-31 18:54:58 +08:00
3065122059 fix: alconna响应器命令头别名配置错误的问题 2024-03-31 18:54:04 +08:00
d3f3ee6dfa docs: 美化文档 2024-03-31 11:20:43 +08:00
d3fce1f145 docs: 美化文档 2024-03-31 11:15:32 +08:00
83468af6c7 docs: 美化文档 2024-03-31 11:14:04 +08:00
9365aec559 docs: 美化文档 2024-03-31 11:12:32 +08:00
9315af3dfd docs: 美化文档 2024-03-31 11:09:48 +08:00
41e389d690 docs: 美化文档 2024-03-31 10:59:17 +08:00
c80919ff1e docs: 添加了更多实现端建议 2024-03-31 09:22:42 +08:00
f446308e2a feat: 添加了对自定义命令前缀的支持 2024-03-31 09:06:02 +08:00
724e13180c feat: 添加了对自定义命令前缀的支持 2024-03-31 09:03:28 +08:00
2ad2bb4182 feat: 添加了对指令前缀的支持 2024-03-31 08:20:20 +08:00
76359ba83e fix: 取消了本地引用js 2024-03-31 07:25:29 +08:00
d8efa08d2f feat: 新增内容的多语言支持 2024-03-31 07:17:33 +08:00
b87e150e34 feat: 新增内容的多语言支持 2024-03-31 07:13:00 +08:00
9f3a451b6d feat: 新增内容的多语言支持 2024-03-31 07:11:59 +08:00
41ee427040 feat: 状态卡片 2024-03-31 06:32:04 +08:00
93569fcd99 feat: 状态卡片 2024-03-31 06:27:56 +08:00
807e552f8a feat: 状态卡片 2024-03-31 06:26:01 +08:00
84e2223dbb feat: 状态卡片 2024-03-31 06:23:23 +08:00
f9e61fd184 feat: 配置项目的热修改 2024-03-31 06:22:53 +08:00
c8851bd696 Merge remote-tracking branch 'origin/main' 2024-03-30 19:24:45 +08:00
9b2b0a7c7d feat: 配置项目的热修改 2024-03-30 19:24:09 +08:00
c15c604752 feat: 配置项目的热修改 2024-03-30 06:04:17 +08:00
65866488c6 feat: 添加了对菜单的初步支持 2024-03-29 17:44:48 +08:00
392376248d feat: 配置项目的热修改 2024-03-29 17:00:36 +08:00
d20699ee0f feat: 配置项目的热修改 2024-03-29 16:02:22 +08:00
a5f9247b32 Merge remote-tracking branch 'origin/main' 2024-03-29 15:12:30 +08:00
dd30b64004 feat: 配置项目的热修改 2024-03-29 15:12:14 +08:00
aed63c34c9 feat: 配置项目的热修改 2024-03-29 14:58:24 +08:00
Snowykami
9cf05fd8fd
fix: 扫雷布局错误 2024-03-29 07:07:11 +08:00
Snowykami
6a49a70481
fix: 扫雷布局 2024-03-29 07:05:53 +08:00
Snowykami
205a28eb56
fix: index out of list 2024-03-29 07:03:09 +08:00
f23567194c fix: type has no TABLE_NAME attr 2024-03-29 00:05:46 +08:00
bb17d2949a feat: 扫雷游戏,测试 2024-03-28 23:53:38 +08:00
9e0b065566 docs: vuepress构建文档 2024-03-28 18:30:56 +08:00
6dffb0f581 docs: vuepress构建文档 2024-03-28 13:37:17 +08:00
2e37bd546b docs: vuepress构建文档 2024-03-28 13:27:40 +08:00
37b1346361 docs: vuepress构建文档 2024-03-28 12:05:03 +08:00
7cecfd1053 docs: vuepress构建文档 2024-03-28 11:12:55 +08:00
de75849cc3 docs: vuepress构建文档 2024-03-28 11:11:14 +08:00
edafffcbb5 docs: vuepress构建文档 2024-03-28 11:10:01 +08:00
ea35147938 docs: vuepress构建文档 2024-03-28 11:09:01 +08:00
86add474f4 docs: vuepress构建文档 2024-03-28 11:08:32 +08:00
6c02bfc783 docs: vuepress构建文档 2024-03-28 10:59:52 +08:00
dcae427c60 docs: vuepress构建文档 2024-03-28 10:51:22 +08:00
47f00c48c5 docs: vuepress构建文档 2024-03-28 10:50:19 +08:00
7db0617a5b docs: vuepress构建文档 2024-03-28 10:50:13 +08:00
19d79d356d docs: vuepress构建文档 2024-03-28 10:42:44 +08:00
57a302a71e docs: vuepress构建文档 2024-03-28 10:39:53 +08:00
bff728b7f1 docs: vuepress构建文档 2024-03-28 10:35:26 +08:00
1e0ebe0d30 docs: vuepress构建文档 2024-03-28 10:34:25 +08:00
42248dbc71 docs: vuepress构建文档 2024-03-28 10:33:13 +08:00
d0318c47d3 docs: vuepress构建文档 2024-03-28 10:31:52 +08:00
388946e56b docs: vuepress构建文档 2024-03-28 10:30:48 +08:00
b24489ae80 docs: vuepress构建文档 2024-03-28 10:28:34 +08:00
acb7a752de docs: vuepress构建文档 2024-03-28 10:26:19 +08:00
16b7347ca3 docs: vuepress构建文档 2024-03-28 10:24:12 +08:00
8763dfbe85 docs: vuepress构建文档 2024-03-28 10:22:45 +08:00
3a1e1b6b92 docs: vuepress构建文档 2024-03-28 10:20:50 +08:00
0b0e63f1d5 docs: vuepress构建文档 2024-03-28 10:19:39 +08:00
602636520e docs: vuepress构建文档 2024-03-28 10:18:53 +08:00
1f3231c0b4 docs: vuepress构建文档 2024-03-28 10:18:20 +08:00
f9ee8c0aed docs: vuepress构建文档 2024-03-28 10:17:04 +08:00
41b2b13442 docs: vuepress构建文档 2024-03-28 10:13:58 +08:00
58b756eb67 docs: vuepress构建文档 2024-03-28 10:11:28 +08:00
e18b9b5317 docs: vuepress构建文档 2024-03-28 10:07:09 +08:00
d602467b80 docs: vuepress构建文档 2024-03-28 10:05:40 +08:00
58ebf6efea docs: vuepress构建文档 2024-03-28 10:03:12 +08:00
7633ab444c docs: vuepress构建文档 2024-03-28 09:59:18 +08:00
e1a3e9a16c docs: vuepress构建文档 2024-03-28 09:57:44 +08:00
4ff78d0a6f docs: vuepress构建文档 2024-03-28 09:56:10 +08:00
7f7a66d639 docs: vuepress构建文档 2024-03-28 09:53:50 +08:00
1d268e6f97 docs: vuepress构建文档 2024-03-28 09:49:41 +08:00
97d936f9be docs: vuepress构建文档 2024-03-28 09:44:13 +08:00
f3e45c895d docs: vuepress构建文档 2024-03-28 09:38:46 +08:00
fafdbea96c docs: vuepress构建文档 2024-03-28 08:51:57 +08:00
70cabc2383 docs: vuepress构建文档 2024-03-28 08:39:36 +08:00
d44b5ea143 docs: vuepress构建文档 2024-03-28 08:33:38 +08:00
0ac374f5df docs: vuepress构建文档 2024-03-28 08:31:49 +08:00
a8f6a25369 docs: vuepress构建文档 2024-03-28 08:31:18 +08:00
1bbd1dd234 docs: vuepress构建文档 2024-03-28 08:26:44 +08:00
0880623930 perf: 优化插件搜索逻辑,避免重复关键词 2024-03-28 07:46:50 +08:00
Snowykami
8a8e9c62ab
update: README.md 2024-03-28 07:21:11 +08:00
Snowykami
c5d850ac13
fix: typo of README.md 2024-03-28 07:04:20 +08:00
Snowykami
8eb693aee9
Create CNAME 2024-03-28 07:01:22 +08:00
570a46a840 docs: 使用vuepress重新构建文档 2024-03-27 23:51:35 +08:00
6e23542296 Merge remote-tracking branch 'origin/main' 2024-03-27 23:51:15 +08:00
Snowykami
f53aa6aa23
Delete docs directory 2024-03-27 23:47:15 +08:00
7baaaebef8 docs: 使用vuepress重新构建文档 2024-03-27 23:42:50 +08:00
630b6dc0ce docs: 使用vuepress重新构建文档 2024-03-27 23:37:14 +08:00
aaf4a752f7 docs: 使用vuepress重新构建文档 2024-03-27 23:36:18 +08:00
adcbc79c1a docs: 使用vuepress重新构建文档 2024-03-27 23:36:13 +08:00
Snowykami
b95c2b2e7e
Create CNAME 2024-03-27 23:33:21 +08:00
58ab62c03b docs: 使用vuepress重新构建文档 2024-03-27 23:32:44 +08:00
7bd1b36ec9 docs: 使用vuepress重新构建文档 2024-03-27 23:28:57 +08:00
c7a2ebb4ea docs: 使用vuepress重新构建文档 2024-03-27 23:09:36 +08:00
75795a5b13 docs: 使用vuepress重新构建文档 2024-03-27 23:05:44 +08:00
Snowykami
505dfe3254
update: README.md 2024-03-27 13:34:00 +08:00
Snowykami
9594c6163f
fix: lang 香港 -> 中國香港 2024-03-27 08:38:31 +08:00
f6ee13c263 feat: 忽略键盘中断类错误 2024-03-27 08:16:53 +08:00
f15bd985af feat: 忽略键盘中断类错误 2024-03-27 08:03:19 +08:00
e78a3cdab6 feat: 更新并重启 2024-03-27 08:02:05 +08:00
cf2ba6fe3b feat: 更新并重启 2024-03-27 07:59:18 +08:00
6edad57470 feat: 更新并重启 2024-03-27 07:58:14 +08:00
90216c1a60 feat: 更新并重启 2024-03-27 07:57:04 +08:00
1d352d1fce Merge remote-tracking branch 'origin/main' 2024-03-27 07:49:35 +08:00
0552cdfd05 fix: 个人信息显示隐藏属性的bug 2024-03-27 07:49:18 +08:00
Snowykami
980c8e6ee4
update: log.py 2024-03-27 07:13:42 +08:00
Snowykami
bf51f5a83b
update: log.py 2024-03-27 07:10:52 +08:00
e22fadcf44 docs: 添加了命令手册 2024-03-27 00:15:12 +08:00
Snowykami
0bdd2d9b1d
Update ys.lang 2024-03-27 00:12:42 +08:00
Snowykami
bd29df4f67
Update ys.lang 2024-03-27 00:10:48 +08:00
Snowykami
4b6226dfd7
feat: ys.lang 2024-03-27 00:09:47 +08:00
fca93a7c66 docs: 添加了命令手册 2024-03-27 00:05:51 +08:00
76ce54f68b docs: 优化排版 2024-03-26 23:37:12 +08:00
e5fd1ce9ae docs: 优化排版 2024-03-26 23:36:29 +08:00
3932366955 docs: 优化排版 2024-03-26 23:34:29 +08:00
423ba84908 fix: 数据库迁移报错"''" 2024-03-26 22:41:34 +08:00
5d7c201018 feat: 插件启用停用检测 2024-03-26 22:36:16 +08:00
ac234544a3 feat: 插件启用停用检测 2024-03-26 22:33:17 +08:00
58e603e1ad fix: 数据库支持 2024-03-26 21:33:40 +08:00
90c9ef31a1 Merge remote-tracking branch 'origin/main' 2024-03-26 17:15:20 +08:00
ecbe06a9e8 feat: 统一双引号 2024-03-26 17:14:41 +08:00
Snowykami
0e17762427
Update README.md 2024-03-26 14:32:13 +08:00
04fc9c3dd7 Merge remote-tracking branch 'origin/main' 2024-03-26 12:20:18 +08:00
eff60d8294 feat: 时区设定支持 2024-03-26 12:20:08 +08:00
Snowykami
ee55a9b9e9
Update README.md 2024-03-26 11:03:49 +08:00
Snowykami
365b2fcba2
Update README.md 2024-03-26 11:00:57 +08:00
Snowykami
475506273d
Update README.md 2024-03-26 11:00:40 +08:00
Snowykami
e9d2a1fe86
Update README.md 2024-03-26 11:00:18 +08:00
c2e43fff7a feat: 新的orm框架 2024-03-26 10:01:26 +08:00
Snowykami
45c3bf3a5e
Update README.md 2024-03-26 09:14:49 +08:00
Snowykami
d6c7c292d4
Update profile_manager.py 2024-03-26 08:39:30 +08:00
Snowykami
2eb60b3e1b
Update profile_manager.py 2024-03-26 08:35:41 +08:00
Snowykami
d4a8aa1f87
Update profile_manager.py 2024-03-26 08:29:14 +08:00
Snowykami
615c7e6681
Create es.lang 2024-03-26 08:27:30 +08:00
Snowykami
23b13595b0
Create de.lang 2024-03-26 08:22:49 +08:00
Snowykami
e85292fdec
Create ru.lang 2024-03-26 08:16:31 +08:00
Snowykami
573716e24e
Create fr.lang 2024-03-26 08:15:17 +08:00
Snowykami
ede65d91a1
Create ko.lang 2024-03-26 08:12:28 +08:00
987b00d2ad feat: 当程序异常退出时给轻雪提交错误报告 2024-03-25 12:55:16 +08:00
172f45208f fix: require()插件错误 2024-03-25 00:33:23 +08:00
91b14d568c fix: require()插件错误 2024-03-24 23:09:59 +08:00
581aa7d6cc fix: require()插件错误 2024-03-24 23:07:08 +08:00
cc70a8ab2c fix: require()插件错误 2024-03-24 22:04:51 +08:00
4bfed64586 docs: 添加了部分内容 2024-03-24 21:45:43 +08:00
788bca7113 docs: 添加了部分内容 2024-03-24 21:21:57 +08:00
bb27eea0c2 docs: 添加了部分内容 2024-03-24 20:47:05 +08:00
d239a8a63d docs: 添加了部分内容 2024-03-24 20:41:40 +08:00
d87bd6c3b2 feat: 字体 2024-03-24 20:40:09 +08:00
d66fd31a4a feat: 字体 2024-03-24 20:24:00 +08:00
9d950a89ba feat: 自动向轻雪服务器上报错误信息 2024-03-24 20:17:03 +08:00
98634c1f4c feat: 自动向轻雪服务器上报错误信息 2024-03-24 19:58:42 +08:00
beb6f63199 feat: 自动向轻雪服务器上报错误信息 2024-03-24 19:57:27 +08:00
45f9afb73c feat: 自动向轻雪服务器上报错误信息 2024-03-24 19:15:49 +08:00
ccef8ca125 feat: 自动向轻雪服务器上报错误信息 2024-03-24 14:43:41 +08:00
5a929d3e99 fix: pydantic数据类型错误 2024-03-24 13:36:28 +08:00
c6f65d544f feat: log样式在不同等级下的支持 2024-03-24 10:26:40 +08:00
66e18a9c8d fix: 数据库迁移错误 2024-03-24 09:45:13 +08:00
81089523a1 Merge remote-tracking branch 'origin/main' 2024-03-24 09:44:37 +08:00
0e996c07df fix: 数据库迁移错误 2024-03-24 09:44:23 +08:00
fab5be70b3 fix: 插件列表显示错误问题 2024-03-24 09:43:34 +08:00
Snowykami
71bd9ab000
Create LICENSE 2024-03-24 03:11:16 +08:00
de0c073c26 fix: 插件列表显示错误问题 2024-03-23 19:55:12 +08:00
ca0bfe0181 feat: 添加了对菜单的初步支持 2024-03-22 14:13:02 +08:00
Snowykami
4f20089e57
Create zh-Kawaii.lang 2024-03-22 13:55:29 +08:00
Snowykami
500c68c6d5
Rename zh-WY to zh-WY.lang 2024-03-22 13:53:15 +08:00
Snowykami
a0e8bd36c9
Rename zh-HK to zh-HK.lang 2024-03-22 13:53:05 +08:00
Snowykami
96d7763c7d
Create zh-HK 2024-03-22 13:52:49 +08:00
Snowykami
ca2c5b0911
feat: 添加了文言文支持 2024-03-22 13:51:22 +08:00
bcc5cb77ad feat: 添加了语言设置界面 2024-03-22 13:39:01 +08:00
1aacceecf0 feat: 添加了对菜单的初步支持 2024-03-22 12:44:56 +08:00
0bd415961c snowy 进行的更改 2024-03-22 12:41:38 +08:00
367b8a5e5d fix: 事件推送目标的逻辑错误 2024-03-22 10:24:38 +08:00
0b4217b592 fix: 事件推送目标的逻辑错误 2024-03-22 08:09:20 +08:00
5737b75d26 fix: 事件推送目标的逻辑错误 2024-03-22 08:08:48 +08:00
73b593ff98 feat: 添加插件启用和停用功能 2024-03-22 07:44:41 +08:00
2711d8844b fix: 插件列表显示错误问题 2024-03-21 14:52:02 +08:00
933979ceaa fix: 链接主页不显示 2024-03-21 13:02:08 +08:00
59506fcc76 fix: 修复了plugins.json报错的问题 2024-03-21 12:55:15 +08:00
a3d60fb435 feat: 添加了自动安装插件功能 2024-03-21 12:18:15 +08:00
e24c5c912e feat: 添加了自动安装插件功能 2024-03-21 12:10:24 +08:00
Snowykami
ca997f727a
Create CNAME 2024-03-21 02:26:38 +08:00
Snowykami
c4b1cb15be
Create ja.lang 2024-03-21 02:17:13 +08:00
49bf677da5 fix: 修复了plugins.json报错的问题 2024-03-21 02:04:51 +08:00
3657e6b93b fix: 修复了plugins.json报错的问题 2024-03-21 01:56:04 +08:00
db900a17d6 feat: 添加了对markdown的简单封装 2024-03-21 01:52:25 +08:00
d8a25c6ba5 feat: 添加了对markdown的简单封装 2024-03-21 01:47:30 +08:00
Snowykami
71cd7e6250
Create plugins.json 2024-03-21 01:46:22 +08:00
Snowykami
a1f99b74cf
Create plugins.json 2024-03-21 01:43:22 +08:00
79f6d50e82 feat: 更新了插件商店部分功能 2024-03-21 01:20:18 +08:00
14d9f041ce feat: 对部分消息回复用markdown进行了重新排版 2024-03-20 22:30:52 +08:00
2b8cb2afb6 feat: 对部分消息回复用markdown进行了重新排版 2024-03-20 21:10:56 +08:00
8a1c981666 feat: 对部分消息回复用markdown进行了重新排版 2024-03-20 18:27:49 +08:00
fdefedf288 feat: 添加了对markdown的简单封装 2024-03-20 12:30:17 +08:00
e351465d97 feat: 添加了网页监控面板 2024-03-20 00:44:36 +08:00
ab5dc2200a feat: 添加了对markdown的简单封装 2024-03-19 22:43:55 +08:00
0bf56f79f1 feat: 添加了对markdown的简单封装 2024-03-19 22:06:30 +08:00
edf390ff43 feat: 添加了对markdown的简单封装 2024-03-19 21:56:31 +08:00
15c751b1c8 Changes 2024-03-19 20:38:25 +08:00
9585910623 feat: 添加了网页监控面板 2024-03-19 15:58:02 +08:00
d739c4cde6 feat: 添加了网页监控面板 2024-03-19 13:16:25 +08:00
3adc265876 feat: 添加了网页监控面板 2024-03-19 00:27:40 +08:00
51cb1a87b8 first commit 2024-03-18 18:21:56 +08:00
9e9f6e4ad6 update: r 2024-03-03 21:25:29 +08:00
d1795f0ca8 update: r 2024-03-03 21:22:49 +08:00
433ecf39ee update: Liteyuki ORM 2024-03-02 02:44:11 +08:00
e7c29c1597 update: Liteyuki ORM 2024-03-02 02:43:18 +08:00
8303514fa0 update: Liteyuki ORM 2024-03-01 23:24:36 +08:00
a3f63e383d Merge remote-tracking branch 'origin/main' 2024-03-01 00:08:08 +08:00
12231d08a8 update: Liteyuki ORM 2024-03-01 00:07:49 +08:00
408 changed files with 35051 additions and 177 deletions

0
src/api/data.py → .dockerignore Normal file → Executable file
View File

2
.domain Normal file
View File

@ -0,0 +1,2 @@
bot.liteyuki.icu
docs.app.bot.pages.git.liteyuki.icu

1
.github/ISSUE_TEMPLATE/config.yml vendored Executable file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

View File

@ -0,0 +1,59 @@
name: Publish Resource
title: "Resource: {name}"
description: Publish the resource to the LiteyukiBot official store
labels: [ "Resource" ]
body:
- type: input
id: name
attributes:
label: Name
description: The readable name of the resource pack
placeholder: e.g. Cute UI Resource Pack
validations:
required: true
- type: input
id: description
attributes:
label: Description
description: A brief description of the resource
placeholder: e.g. Makes the rendering card style more beautiful
validations:
required: true
- type: input
id: author
attributes:
label: Author
description: The GitHub username of the author
placeholder: e.g. snowykami
validations:
required: true
- type: input
id: link
attributes:
label: Link
description: Direct download link of the resource pack
placeholder: e.g. https://aaa.com/r.zip
validations:
required: true
- type: input
id: homepage
attributes:
label: Homepage
description: Homepage of the resource pack
placeholder: e.g. https://github.com/user/repo
validations:
required: false
- type: input
id: tags
attributes:
label: Tags
description: Tags
placeholder: 'e.g. [{"label": "Tag Name", "color": "#ea5252"}]'
value: '[ { "label": "Text", "color": "#a2d8f4" } ]'
validations:
required: false

View File

@ -0,0 +1,59 @@
name: 发布资源
title: "Resource: {name}"
description: 发布资源到轻雪机器人官方商店
labels: [ "Resource" ]
body:
- type: input
id: name
attributes:
label: 名称
description: 资源包的可读名称
placeholder: e.g. 可爱UI资源包
validations:
required: true
- type: input
id: description
attributes:
label: 描述
description: 资源的简短描述
placeholder: e.g. 使渲染卡片的样式更美观
validations:
required: true
- type: input
id: author
attributes:
label: 作者
description: 作者的github用户名
placeholder: e.g. snowykami
validations:
required: true
- type: input
id: link
attributes:
label: 下载链接
description: 资源包直接下载链接
placeholder: e.g. https://aaa.com/r.zip
validations:
required: true
- type: input
id: homepage
attributes:
label: 主页
description: 资源包主页
placeholder: e.g. https://github.com/user/repo
validations:
required: false
- type: input
id: tags
attributes:
label: 标签
description: 标签
placeholder: 'e.g. [{"label": "标签名", "color": "#ea5252"}]'
value: '[ { "label": "标签名", "color": "#a2d8f4" } ]'
validations:
required: false

53
.github/ISSUE_TEMPLATE/问题反馈.md vendored Executable file
View File

@ -0,0 +1,53 @@
---
name: 问题反馈
about: 反馈你在使用轻雪中遇到的问题
title: ''
labels: ''
assignees: ''
---
# 问题反馈
## **请确保**
- 已认真阅读[文档]("https://bot.liteyuki.icu"),该问题不是文档提及的或你自己操作不当造成的
- 你的问题是在最新版本的代码上测试的
- 请勿重复提交相同或类似的issue
## **描述问题**
请在此简单描述问题
## **如何复现**
请阐述一下如何重现这个问题
### 预期
描述你期望发生的事情
### 实际
描述实际发生的事情
## **日志或截图**
```
日志内容
```
## **设备信息**
- **系统**: [例如 Ubuntu 22.04]
- **CPU**: [例如 Intel i7-7700K]
- **内存**: [例如 16GB]
- **Python**: [例如CPython 3.10.7]
**补充内容**
可选,推荐提供`pip freeze`的输出,以及其他相关信息,以及你的建议

11
.github/dependabot.yml vendored Executable file
View File

@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

43
.github/workflows/build-image.yml vendored Executable file
View File

@ -0,0 +1,43 @@
name: Docker Image Build
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: write
concurrency:
group: docker-build
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/liteyukistudio/liteyukibot:latest
- name: Log out from GitHub Container Registry
run: docker logout ghcr.io

View File

@ -0,0 +1,66 @@
name: Deploy VitePress site to Liteyuki PaaS
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: write
statuses: write
concurrency:
group: pages
cancel-in-progress: false
env:
MELI_SITE: "800a7c09-dd9c-4ba7-a43f-af9bc69808c4"
jobs:
# 构建工作
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # 如果未启用 lastUpdated则不需要
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: "3.11"
- name: Setup API markdown
run: |-
python -m pip install litedoc
litedoc liteyuki -o docs/zh/dev/api -l zh-Hans -cd class -fd func -md func -vd var -bu https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki/
litedoc liteyuki -o docs/en/dev/api -l en -cd class -fd func -md func -vd var -bu https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki/
- name: 安装 pnpm
uses: pnpm/action-setup@v2
with:
run_install: true
version: 8
- name: 设置 Node.js
run: |-
cd docs
pnpm install
- name: 构建文档
env:
NODE_OPTIONS: --max_old_space_size=8192
run: |-
cd docs
pnpm run docs:build
> .vitepress/dist/.nojekyll
- name: "发布"
run: |
npx -p "@getmeli/cli" meli upload docs/.vitepress/dist \
--url "https://dash.apage.dev" \
--site "$MELI_SITE" \
--token "$MELI_TOKEN" \
--release "$GITHUB_SHA"
env:
MELI_TOKEN: ${{ secrets.MELI_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

51
.github/workflows/issue_handler.yml vendored Executable file
View File

@ -0,0 +1,51 @@
name: Issue Handler
on:
issues:
types: [ opened, edited, closed ]
concurrency:
group: issue_handler
cancel-in-progress: false
jobs:
check-issue:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Check issue title
id: check_title
run: |
ISSUE_TITLE="${{ github.event.issue.title }}"
if [[ "$ISSUE_TITLE" == Plugin:* || "$ISSUE_TITLE" == Resource:* ]]; then
echo "Title starts with Plugin: or Resource:."
echo "::set-output name=title_match::true"
else
echo "Title does not start with Plugin: or Resource:."
echo "::set-output name=title_match::false"
fi
- name: Set up Python
uses: actions/setup-python@v2
if: steps.check_title.outputs.title_match == 'true'
with:
python-version: '3.12'
- name: Install dependencies
if: steps.check_title.outputs.title_match == 'true'
run: |
echo "Installing dependencies."
pip install -r liteyuki_flow/requirements.txt
- name: Run Plugin/Resource issue handler
if: steps.check_title.outputs.title_match == 'true'
run: |
echo "Running Plugin/Resource issue handler."
python -m liteyuki_flow --handle
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
ACT_TYPE: ${{ github.event.action }}

30
.github/workflows/pre-commit.yml vendored Executable file
View File

@ -0,0 +1,30 @@
name: Pre-commit checks
on: [push, pull_request]
jobs:
pre-commit:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13'] # 添加你想要测试的 Python 版本
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }} # 使用矩阵中的 Python 版本
- name: Install dependencies
run: |
python -m pip install pdm
python -m pip install pre-commit
pdm config python.use_venv false
pdm install --no-lock
pre-commit install
- name: Run pre-commit
run: pre-commit run --all-files

21
.github/workflows/pypi-publish.yml vendored Executable file
View File

@ -0,0 +1,21 @@
name: Publish
on:
push:
tags:
- 'v*'
jobs:
pypi-publish:
name: upload release to PyPI
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v3
- uses: pdm-project/setup-pdm@v3
- name: Publish package distributions to PyPI
run: pdm publish

78
.gitignore vendored Normal file → Executable file
View File

@ -1,12 +1,74 @@
# idea
plugin/
.venv/
.idea/
.vscode/
.cache/
# config
config.yml
venv/
# external plugins
node_modules/
data/
db/
/resources/
__pycache__/
*.pyc
*.pyo
*.pyd
*.pyw
/plugins/
# pyc/pyo
**/*.pyc
**/*.pyo
#config
/config/
!config/default.yml
_config.yml
config.yml
config.example.yml
# vuepress
# mupy
mypy.ini
# nuitka
compile.bat
src/resources/templates/latest-debug.html
main.build/
main.dist/
main.exe
main.cmd
docs/.vuepress/.cache/
docs/.vuepress/.temp/
docs/.vuepress/dist/
prompt.txt
# js
**/echarts.js
.env
# pdm
.pdm-python
.pdm-build
dist
doc
mkdoc2.py
result.json
# litedoc
docs/zh/dev/api
docs/en/dev/api
mkdoc.bat
# vitepress
docs/.vitepress/dist/
docs/.vitepress/cache
docs/.vitepress/.temp
# python toolchain
.mypy_cache/
.pytest_cache/
# pdm
__pypackages__/
pdm.lock

26
.pre-commit-config.yaml Executable file
View File

@ -0,0 +1,26 @@
fail_fast: true
repos:
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
args: [--config=./pyproject.toml]
- repo: https://github.com/timothycrosley/isort
rev: 5.13.2
hooks:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
hooks:
- id: mypy
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files

1
CNAME
View File

@ -1 +0,0 @@
bot.liteyuki.icu

17
Dockerfile Executable file
View File

@ -0,0 +1,17 @@
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.10-slim-bullseye
ENV TZ Asia/Shanghai
RUN apt-get update && apt-get install -y git
WORKDIR /liteyukibot
COPY . /liteyukibot
RUN pip install --no-cache-dir -r requirements.txt
RUN apt-get install -y libnss3 libnspr4 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libatspi2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libxkbcommon0 libasound2 libpango-1.0-0 libcairo2
EXPOSE 20216
CMD ["python", "main.py"]

31
LICENSE Executable file
View File

@ -0,0 +1,31 @@
LSO license
LiteyukiStudio Opensource license
---
版权所有 © 2024 Snowykami
---
免费向任何获得副本的人或组织授予以相同许可为基础的权利
包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件的副本
本软件及相关文档文件(以下简称"本软件")在相同方式许可为基础, 以开源的形式发布于互联网抑或其他媒体介质平台
任何人都有权利获取副本并以上述方式获取许可传播和/或使用
但获取副本时仍需注意:
- 上述版权声明和本许可声明应包含在本软件的副本中
- 使用本软件及其副本时仍需保持与原有形式相同
- 在使用时仍需将本软件的副本以相同许可公开表现:
- 不得未经原作者允许将本软件的副本以非原许可的形式对外盈利
---
该软件按"原样"之副本提供,不提供任何形式的任意保证,明示或暗示:
包括但不限于适销性保证, 适用于特定目的非侵权
在任何情况下, 作者或版权所有者对任何非因作者或版权所有者使用该软件造成的索赔、损害或其他责任, 无论是在合同诉讼、侵权行为还是其他诉讼中都不具有责任, 作者及其版权所有者有权利驳回使用者因个人原因造成的任何损失之赔付

108
README.md Normal file → Executable file
View File

@ -1,80 +1,70 @@
<div align="center">
<img src="https://ks.liteyuki.icu:809/static/img/liteyuki_icon.png" style="width: 30%; margin-top:10%;" alt="a">
[//]: # (<img src="https://cdn.liteyuki.icu/logos/bot.svg" style="align-content: center; width: 50%; margin-top:10%;" alt="a">)
[![][banner]][liteyuki-link]
<h2><a href="https://bot.liteyuki.icu"> <span style="color: #a2d8f4">轻雪</span> <span style="color: #d0e9ff">6</span></a></h2>
<h4> <span style="color: #a2d8f4">✨ 轻量,高效,易于扩展✨</span></h4>
[![][Liteyuki6.0]][liteyuki-link]
[![][Python3.10+]][python-link]
[![][Usage]][usage-link]
[![][Repo]][repo-link]
[![][Github]][github-link]
[![][LiteyukiLab]][liteyukilab-link]
![docs uptime](https://uptime.liteyuki.icu/api/badge/8/uptime?labelPrefix=Docs+&style=for-the-badge)
</div>
<div align=center>
<h2>
<font color="#d0e9ff">
轻雪
</font>
<font color="#a2d8f4">
6.0
</font>
</h2>
</div>
<div align=center><h4>轻量,高效,易于扩展</h4></div>
- 基于[Nonebot2]("https://github.com/nonebot/nonebot2"),有良好的生态支持
- 集成了上一代轻雪的优点和~~缺点~~
- 支持一切Onebot标准通信后续会支持更多的平台
## 关于
## 手动安装和部署
访问[轻雪6.0](https://bot.liteyuki.icu)主页获取更多信息
1. 安装`Git``Python3.10+`后,使用命令`git clone https://github.com/snowykami/LiteyukiBot` 克隆项目至本地。
一定要安装GitBot自带功能需要git支持
2. 切换到轻雪目录,使用`pip install -r requirements.txt`安装依赖
## 特点及优势
3. `python main.py`启动!
- 原生支持与任意`Python`Bot框架互联有良好的生态支持
- 开箱即用,无需复杂配置
- 集成包管理器,支持一键安装插件
- 自定义主题支持,满足审美需求
- 国际化支持,支持多种语言
- 高性能500插件2s内启动
## 一键部署脚本(复制到本地保存执行)
## 服务及支持(敬请期待)
- 提供Liteyuki Cloud官方的容器化托管服务无需担心服务器问题
#### 提前部署好`Python3.10+`环境和`Git`环境
**👇所有内容请访问👇**: [bot.liteyuki.icu](https://bot.liteyuki.icu)
#### Windows
## 参考及鸣谢
- [nonebot-plugin-uninfo](https://github.com/RF-Tar-Railt/nonebot-plugin-uninfo)为会话部分用户信息提供了参考
- [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna/)为消息部分提供了参考
```bash
chcp 65001
git clone https://github.com/snowykami/LiteyukiBot
cd LiteyukiBot
pip install -r requirements.txt
echo python3 main.py > start.bat
echo Install finished! Please run start.bat to start the bot!
```
## 其他
- 本仓库是一个monorepo包含了框架文档测试内置资源包内置插件预设配置等
#### Linux
```bash
git clone https://github.com/snowykami/LiteyukiBot
cd LiteyukiBot
pip install -r requirements.txt
echo python3 main.py > start.sh
chmod +x start.sh
echo Install finished! Please run start.sh to start the bot!
```
[Liteyuki6.0]: https://img.shields.io/badge/Liteyuki-6.0-blue?style=for-the-badge
## 注意事项
[Python3.10+]: https://img.shields.io/badge/Python-3.10+-blue?style=for-the-badge
- 尽可能不要去动配置文件通过与bot交互进行配置即可若仍然想自定义配置请在`config.yml`中修改
[Usage]: https://img.shields.io/badge/主页-文档-blue?style=for-the-badge
- 首次启动会提醒用户注册超级用户
[Repo]: https://img.shields.io/badge/官方托管-仓库-blue?style=for-the-badge
- Bot会自动检测新版本若出现新版本可用`git pull`命令更新
[Github]: https://img.shields.io/badge/Github-仓库-blue?style=for-the-badge
### Onebot实现端配置
[LiteyukiLab]: https://img.shields.io/badge/轻雪社区-官方-blue?style=for-the-badge
| 字段 | 参考值 | 说明 |
|----|-------------------------------|-------------------------|
| 协议 | 反向WebSocket | 轻雪使用反向ws协议进行通信即轻雪作为服务端 |
| 地址 | ws://`host`:`port`/onebot/v11 | 地址取决于配置文件,默认为`20216`端口 |
### 推荐方案
1. 使用`Lagrange.Core``Lagrange.Core`支持多种协议
2. 云崽的`icqq-plugin``ws-plugin`进行通信
3. `Go-cqhttp`(目前已经半死不活了)
4. 人工实现的`Onebot`协议自己整一个WebSocket客户端看着QQ的消息然后给轻雪传输数据
请先自行查阅文档若有困难请联系相关开发者而不是Liteyuki的开发者
## 鸣谢
[python-link]:https://www.python.org/
- html转图片使用的[kexue-z](https://github.com/kexue-z)的[nonebot-plugin-htmlrender](https://github.com/kexue-z/nonebot-plugin-htmlrender)插件的部分代码
- 重启方案用的[18870](https://github.com/18870)的[Nonebot-plugin-reboot](https://github.com/18870/nonebot-plugin-reboot)插件的部分代码
- Lagrange.Core的测试环境支持
[usage-link]:https://bot.liteyuki.icu/
[liteyuki-link]:https://bot.liteyuki.icu/
[repo-link]:https://git.liteyuki.icu/bot/app
[github-link]:https://github.com/LiteyukiStudio/LiteyukiBot
[liteyukilab-link]:https://lab.liteyuki.icu/@LiteyukiBot
[banner]: https://socialify.git.ci/LiteyukiStudio/LiteyukiBot/image?description=1&font=Source+Code+Pro&forks=1&issues=1&logo=https%3A%2F%2Fcdn.liteyuki.icu%2Flogos%2Fbot.svg&name=1&owner=1&pattern=Floating+Cogs&pulls=1&stargazers=1&theme=Auto

10
config/default.yml Executable file
View File

@ -0,0 +1,10 @@
nonebot:
host: 0.0.0.0
port: 20216
command_start: ["", "/"]
nickname: [ "liteyuki" ]
default_language: zh
driver: ~fastapi+~httpx+~websockets
alconna_use_command_start: true
gotify_token: "empty token"

View File

@ -1,4 +0,0 @@
{
"name": "Liteyuki Default",
"version": "1.0"
}

View File

@ -1,4 +0,0 @@
{
"name": "Liteyuki Language Pack",
"version": "1.0"
}

12
docker-compose.yml Executable file
View File

@ -0,0 +1,12 @@
version: '3.8'
services:
app:
image: git.liteyuki.icu/bot/app:latest
ports:
- "20216:20216"
environment:
- TZ=Asia/Chongqing
volumes:
- .:/liteyukibot
command: [ "python", "main.py" ]

10
docker/sources.list Executable file
View File

@ -0,0 +1,10 @@
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free

138
docs/.vitepress/config/common.ts Executable file
View File

@ -0,0 +1,138 @@
// 共有配置项导入index用
import { defineConfig } from "vitepress";
import { generateSidebar } from "vitepress-sidebar";
import { zh } from "./zh";
import { en } from "./en";
let defaultLocale = "zh";
const commonSidebarOptions = {
collapsed: true,
convertSameNameSubFileToGroupIndexPage: true,
useTitleFromFrontmatter: true,
useFolderTitleFromIndexFile: true,
useFolderLinkFromIndexFile: true,
includeFolderIndexFile: true,
sortMenusByFrontmatterOrder: true,
rootGroupText: "LITEYUKIBOT",
};
/**
* Generate sidebar config
* multiple languages and sections
* @returns {any[]}
*/
function generateSidebarConfig(): any[] {
let sections = ["dev", "store", "usage", "deploy"];
let languages = ["zh", "en"];
let ret = [];
for (let language of languages) {
for (let section of sections) {
if (language === defaultLocale) {
ret.push({
basePath: `/${section}/`,
scanStartPath: `${language}/${section}`,
resolvePath: `/${section}/`,
...commonSidebarOptions,
});
} else {
ret.push({
basePath: `/${language}/${section}/`,
scanStartPath: `${language}/${section}`,
resolvePath: `/${language}/${section}/`,
...commonSidebarOptions,
});
}
}
}
return ret;
}
export const common = defineConfig({
head: [
// 配置favicon.ico
["link", { rel: "icon", type: "image/x-icon", href: "favicon.ico" }],
[
"link",
{
rel: "stylesheet",
href: "https://fonts.font.im/css?family=Cousine:400,400i,700,700i|Poppins:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i",
},
],
["script", { src: "https://cdn.liteyuki.icu/js/liteyuki_footer.js" }],
],
rewrites: {
[`${defaultLocale}/:rest*`]: ":rest*",
},
cleanUrls: false,
themeConfig: {
logo: {
light: "https://cdn.liteyuki.icu/logos/bot.svg",
dark: "https://cdn.liteyuki.icu/logos/bot.svg",
alt: "LiteyukiBot Logo",
},
sidebar: generateSidebar([...generateSidebarConfig()]),
socialLinks: [
{ icon: "github", link: "https://github.com/LiteyukiStudio/LiteyukiBot" },
{
icon: {
svg: '<svg t="1725391346807" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5067" width="256" height="256"><path d="M1004.692673 466.396616l-447.094409-447.073929c-25.743103-25.763582-67.501405-25.763582-93.264987 0l-103.873521 103.873521 78.171378 78.171378c12.533635-6.00058 26.562294-9.359266 41.389666-9.359266 53.02219 0 96.00928 42.98709 96.00928 96.00928 0 14.827372-3.358686 28.856031-9.359266 41.389666l127.97824 127.97824c12.533635-6.00058 26.562294-9.359266 41.389666-9.359266 53.02219 0 96.00928 42.98709 96.00928 96.00928s-42.98709 96.00928-96.00928 96.00928-96.00928-42.98709-96.00928-96.00928c0-14.827372 3.358686-28.856031 9.359266-41.389666l-127.97824-127.97824c-3.051489 1.454065-6.184898 2.744293-9.379746 3.870681l0 266.97461c37.273227 13.188988 63.99936 48.721433 63.99936 90.520695 0 53.02219-42.98709 96.00928-96.00928 96.00928s-96.00928-42.98709-96.00928-96.00928c0-41.799262 26.726133-77.331707 63.99936-90.520695l0-266.97461c-37.273227-13.188988-63.99936-48.721433-63.99936-90.520695 0-14.827372 3.358686-28.856031 9.359266-41.389666l-78.171378-78.171378-295.892081 295.871601c-25.743103 25.784062-25.743103 67.542365 0 93.285467l447.114889 447.073929c25.743103 25.743103 67.480925 25.743103 93.264987 0l445.00547-445.00547c25.763582-25.763582 25.763582-67.542365 0-93.285467z" fill="#a2d8f4" p-id="5068"></path></svg>',
},
link: "https://git.liteyuki.icu/bot/app",
},
{
icon: {
svg: '<svg t="1736700504329" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14158" width="200" height="200"><path d="M944.355556 142.222222c-17.066667-22.755556-45.511111-34.133333-79.644445-34.133333-28.444444 0-68.266667 5.688889-108.088889 22.755555h-5.688889c17.066667 11.377778 34.133333 28.444444 51.2 39.822223 56.888889-17.066667 91.022222-11.377778 96.711111 0 11.377778 11.377778 5.688889 45.511111-22.755555 91.022222 11.377778 17.066667 17.066667 34.133333 28.444444 51.2 0 0 0 5.688889 5.688889 5.688889 22.755556-34.133333 34.133333-62.577778 45.511111-91.022222 11.377778-28.444444 5.688889-62.577778-11.377777-85.333334z" p-id="14159" fill="#a2d8f4"></path><path d="M267.377778 512a45.511111 45.511111 0 1 0 91.022222 0 45.511111 45.511111 0 1 0-91.022222 0Z" p-id="14160" fill="#a2d8f4"></path><path d="M625.777778 614.4c-113.777778 85.333333-227.555556 153.6-324.266667 193.422222-11.377778 5.688889-17.066667 5.688889-28.444444 11.377778 22.755556 17.066667 51.2 34.133333 79.644444 45.511111 51.2 22.755556 108.088889 34.133333 164.977778 34.133333s113.777778-11.377778 164.977778-34.133333c51.2-22.755556 96.711111-51.2 136.533333-91.022222 39.822222-39.822222 68.266667-85.333333 91.022222-130.844445 22.755556-51.2 34.133333-108.088889 34.133334-159.288888 0-51.2-11.377778-102.4-28.444445-153.6-5.688889 5.688889-11.377778 17.066667-17.066667 22.755555-68.266667 79.644444-164.977778 176.355556-273.066666 261.688889zM813.511111 187.733333c-5.688889-5.688889-11.377778-5.688889-11.377778-11.377777-17.066667-17.066667-34.133333-28.444444-51.2-39.822223-22.755556-11.377778-45.511111-28.444444-68.266666-34.133333-56.888889-28.444444-108.088889-39.822222-164.977778-39.822222s-113.777778 11.377778-164.977778 34.133333c-51.2 22.755556-96.711111 51.2-136.533333 91.022222-39.822222 34.133333-68.266667 79.644444-91.022222 130.844445-22.755556 51.2-34.133333 108.088889-34.133334 159.288889 0 51.2 11.377778 96.711111 22.755556 142.222222-22.755556 34.133333-39.822222 68.266667-51.2 96.711111-11.377778 39.822222-5.688889 68.266667 11.377778 91.022222 17.066667 22.755556 45.511111 34.133333 79.644444 34.133334h11.377778c28.444444 0 62.577778-11.377778 96.711111-22.755556-17.066667-11.377778-34.133333-28.444444-51.2-39.822222-51.2 11.377778-85.333333 11.377778-96.711111 0 0-17.066667 5.688889-45.511111 34.133333-96.711111 17.066667 34.133333 39.822222 62.577778 68.266667 91.022222h5.688889c17.066667-5.688889 39.822222-11.377778 62.577777-17.066667 91.022222-34.133333 204.8-102.4 307.2-187.733333 108.088889-85.333333 199.111111-170.666667 256-250.311111l34.133334-51.2c-22.755556-28.444444-39.822222-56.888889-68.266667-79.644445z m-500.622222 420.977778c-56.888889 0-102.4-45.511111-102.4-102.4s45.511111-102.4 102.4-102.4S409.6 455.111111 409.6 512c0 51.2-45.511111 96.711111-96.711111 96.711111z" p-id="14161" fill="#a2d8f4"></path></svg>',
},
link: "https://lab.liteyuki.icu/@LiteyukiBot",
},
],
search: {
provider: "local",
options: {
locales: {
root: {
translations: {
button: {
buttonText: "搜索文档",
buttonAriaLabel: "打开搜索框",
},
modal: {
noResultsText: "没有找到搜索结果",
resetButtonTitle: "清除查询条件",
footer: {
selectText: "选择",
navigateText: "切换",
},
},
},
},
en: {
translations: {
button: {
buttonText: "Search",
buttonAriaLabel: "Search",
},
modal: {
noResultsText: "No results found",
resetButtonTitle: "Reset search query",
footer: {
selectText: "Select",
navigateText: "Navigate",
},
},
},
},
},
},
},
},
sitemap: {
hostname: "https://bot.liteyuki.icu",
},
lastUpdated: true,
locales: {
root: { label: "简体中文", ...zh },
en: { label: "English", ...en },
},
});

35
docs/.vitepress/config/en.ts Executable file
View File

@ -0,0 +1,35 @@
import {defineConfig} from 'vitepress'
import {ThemeConfig} from "./utils";
export const en = defineConfig({
lang: "en-US",
title: "LiteyukiBot",
description: "A high-performance, easy-to-use chatbot framework and application",
themeConfig: {
nav: [
{text: 'Deploy', link: '/en/deploy/install'},
{text: 'Usage', link: '/en/usage/basic'},
{text: 'Extension', link: '/en/store/resource'},
{text: 'Develop', link: '/en/dev/guide'},
],
docFooter: {
prev: 'Prev Page',
next: 'Next Page'
},
editLink: ThemeConfig.getEditLink(
'Edit this page on GitHub',
),
footer: {
message: 'Page is deployed at <a href="https://meli.liteyuki.icu" target="_blank">Liteyuki Meli</a> and accelerated by <a href="https://cdn.liteyuki.icu" target="_blank">Liteyukiflare</a><br>Documentation built with <a href="https://vitepress.dev/">VitePress</a> | API references generated by <a href="https://github.com/LiteyukiStudio/litedoc">litedoc</a>',
copyright: ThemeConfig.copyright
},
outline: ThemeConfig.getOutLine("Page Content"),
langMenuLabel: 'Language',
returnToTopLabel: 'Back to top',
sidebarMenuLabel: 'Menu',
darkModeSwitchLabel: 'Theme',
lightModeSwitchTitle: 'Light Mode',
darkModeSwitchTitle: 'Dark Mode',
},
})

View File

@ -0,0 +1,6 @@
import {defineConfig} from "vitepress";
import {common} from './common'
export default defineConfig({
...common,
})

40
docs/.vitepress/config/utils.ts Executable file
View File

@ -0,0 +1,40 @@
// 本模块储存一些工具函数和引用
/**
* GetEditLink Options
* @param text Edit link text
*/
export const ThemeConfig = {
getEditLink: (editPageText: string): { pattern: (params: { filePath: string; }) => string; text: string; } => {
return {
pattern: ({filePath}: { filePath: string; }): string => {
// 匹配 /dev/api或 /{lang}/dev/api
const regex = /^[^\/]+\/dev\/api/;
console.log(filePath);
if (regex.test(filePath)) {
// remove {lang}/api prefix
filePath = filePath.replace(regex, '')
.replace('index.md', '__init__.py')
.replace('.md', '.py');
// 若文件名(不含扩展)和上级文件夹相同,返回文件夹/__init__.py
if (filePath.split('/').pop().split('.')[0] === filePath.split('/').slice(-2, -1)[0]) {
filePath = filePath.split('/').slice(0, -1).join('/') + '/__init__.py';
}
return `https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki${filePath}`;
} else {
return `https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/docs/${filePath}`;
}
},
text: editPageText
};
},
getOutLine: (label: string): { label: string; level: [number, number]; } => {
return {
label: label,
level: [2, 6]
};
},
copyright: 'Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved'
}

35
docs/.vitepress/config/zh.ts Executable file
View File

@ -0,0 +1,35 @@
import {defineConfig} from 'vitepress'
import {ThemeConfig} from "./utils";
export const zh = defineConfig({
lang: "zh-Hans",
title: "轻雪机器人",
description: "一个综合性的机器人应用及管理框架",
themeConfig: {
nav: [
{text: '部署', link: '/deploy/install'},
{text: '使用', link: '/usage/basic'},
{text: '扩展', link: '/store/resource'},
{text: '开发', link: '/dev/guide'},
],
docFooter: {
prev: '上一页',
next: '下一页'
},
editLink: ThemeConfig.getEditLink(
'在 GitHub 上编辑此页',
),
footer: {
message: '网站部署在 <a href="https://meli.liteyuki.icu" target="_blank">Liteyuki Meli</a> 由 <a href="https://cdn.liteyuki.icu" target="_blank">Liteyukiflare</a> 提供加速服务<br>文档由 <a href="https://vitepress.dev/">VitePress</a> 构建 | API引用由 <a href="https://github.com/LiteyukiStudio/litedoc">litedoc</a> 生成',
copyright: ThemeConfig.copyright
},
outline: ThemeConfig.getOutLine("页面内容"),
langMenuLabel: '语言',
returnToTopLabel: '返回顶部',
sidebarMenuLabel: '菜单',
darkModeSwitchLabel: '主题',
lightModeSwitchTitle: '轻色模式',
darkModeSwitchTitle: '深色模式',
},
})

18
docs/.vitepress/theme/index.ts Executable file
View File

@ -0,0 +1,18 @@
import DefaultTheme from 'vitepress/theme'
import './liteyuki.scss'
import StatsBar from '../../components/StatsBar.vue'
import PluginStore from '../../components/PluginStore.vue'
import ResStore from '../../components/ResStore.vue'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('StatsBar', StatsBar);
app.component('PluginStore', PluginStore);
app.component('ResStore', ResStore);
},
Layout: StatsBar
}

View File

@ -0,0 +1,149 @@
:root {
--vp-c-brand-1: #149ef8;
--vp-c-brand-2: #0434ad;
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #34a3fe 30%, #8d44ff);
--vp-home-hero-image-background-image: linear-gradient(-45deg, #d0e9ff 50%, #a2d8f4 50%);
--vp-home-hero-image-filter: blur(44px);
--vp-c-gray-1: #eee;
--vp-c-gray-2: #aaa;
--border-radius-1: 10px;
--border-radius-2: 20px;
--border-radius-3: 40px;
--vp-font-family-base: 'Poppins', 'Punctuation SC', 'Inter', ui-sans-serif, system-ui,
'PingFang SC', 'Noto Sans CJK SC', 'Noto Sans SC', 'Heiti SC',
'Microsoft YaHei', 'DengXian', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--vp-font-family-mono: 'Cousine', monospace;
--red: #ef4444;
--liteyuki-color: #149ef8;
--button-radius: 6px;
}
.dark {
--vp-home-hero-image-background-image: linear-gradient(-45deg, #004785 50%, #0374ad 50%);
--vp-c-gray-1: #333;
--vp-c-gray-2: #666;
}
.tab-buttons {
padding: 7px;
flex: 1;
display: flex;
justify-content: flex-start;
height: 60%;
align-items: center;
}
.tab-title {
text-align: center;
justify-content: center;
flex: 1;
}
.item-search-box {
border-radius: 100px;
width: 80%;
padding: 10px;
margin: 10px 0;
border: 1px solid #ccc;
}
.search-box-div {
display: flex;
justify-content: space-around;
margin: 10px 0;
}
.item-search-box {
width: 80%;
}
.item-card {
position: relative;
border-radius: 15px;
background-color: var(--vp-c-gray-1);
height: 160px;
padding: 16px;
margin: 10px;
box-sizing: border-box;
transition: background 0.3s ease;
}
.item-name {
font-size: 20px;
margin-bottom: 10px;
}
.item-description {
color: var(--vp-c-gray-2);
font-size: 13px;
white-space: pre-wrap;
}
.author-info {
display: flex;
justify-content: left;
align-items: center;
}
.author-name {
font-size: 15px;
font-weight: normal;
}
.avatar {
border-radius: 50%;
margin: 0 10px;
}
/*store*/
.store-tabs {
display: flex;
justify-content: flex-end;
margin: 10px 0;
}
.publish-button {
right: 10px;
bottom: 10px;
padding: 5px 10px;
border-radius: 10px;
background-color: var(--vp-c-brand-1);
color: white;
font-size: 15px;
cursor: pointer;
}
.pub-window {
input {
width: 100%;
padding: 10px;
margin: 10px 0;
border-radius: 10px;
border: 1px solid #ccc;
}
}
.pub-option {
margin: 10px;
padding: 5px;
border: 2px solid var(--vp-c-gray-1);
border-radius: var(--button-radius);
background-color: var(--vp-c-gray-1);
&.close {
}
&.submit {
background-color: var(--vp-c-brand-1);
}
}

View File

@ -0,0 +1,26 @@
<script setup lang="ts">
import {getTextRef} from "./scripts/i18n";
import {repoPath, repoURL} from "./scripts/const";
const contributorImgSrc = `https://contrib.rocks/image?repo=${repoPath}`
const contributorsUrl = `${repoURL}/graphs/contributors`
</script>
<template>
<div class="contributor-bar">
<h2>{{ getTextRef('thx_contributors') }}</h2>
<a :href="contributorsUrl">
<div class="contributor-list">
<img :src=contributorImgSrc alt="Contributors">
</div>
</a>
</div>
</template>
<style scoped>
.contributor-bar {
display: flex;
flex-direction: column;
align-items: center;
}
</style>

38
docs/components/Dash.vue Executable file
View File

@ -0,0 +1,38 @@
<script setup lang="ts">
import {ref} from "vue";
let total = ref(0);
let online = ref(0);
fetch("https://api.liteyuki.icu/count")
.then(res => res.json())
.then(data => {
total.value = data.register;
})
.catch(err => console.error(err));
fetch("https://api.liteyuki.icu/online")
.then(res => res.json())
.then(data => {
online.value = data.online;
})
.catch(err => console.error(err));
</script>
<template>
<div class="info-box">
<h1>Dashboard</h1>
<div class="info">
<div class="info-item">
<h2>Total</h2>
<p>{{ total }}</p>
</div>
<div class="info-item">
<h2>Online</h2>
<p>{{ online }}</p>
</div>
</div>
</div>
</template>
<style scoped>
</style>

20
docs/components/Geo.vue Executable file
View File

@ -0,0 +1,20 @@
<script setup>
</script>
<template>
<div>
<div style="text-align: center">
<h2>地理分布</h2>
<p>数据来源于Liteyuki API</p>
</div>
<div id="main-chart" style="width: 100%; height: 600px;"></div>
</div>
</template>
<style scoped>
#main-chart {
width: 100px;
height: 600px;
}
</style>

10
docs/components/Home.vue Executable file
View File

@ -0,0 +1,10 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,109 @@
<template>
<div class="item-card">
<div class="item-name">{{ props.item.name }}</div>
<div class="item-description">{{ props.item.desc }}</div>
<div class="tags">
<span class="tag" v-for="tag in props.item.tags" :key="tag" :style=getTagStyle(tag.color)>{{ tag.label }}</span>
</div>
<div class="item-bar">
<!-- 三个可点击svg一个github一个下载一个可点击"https://github.com/{{ username }}.png?size=80"个人头像配上id-->
<a :href=props.item.homepage class="btn" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16">
<path fill="currentColor"
d="m7.775 3.275l1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0a.751.751 0 0 1 .018-1.042a.751.751 0 0 1 1.042-.018a1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018a.751.751 0 0 1-.018-1.042m-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018a.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018a1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83"/>
</svg>
</a>
<!-- <button class="copy-btn btn"><div @click="copyToClipboard">安装</div></button> 点击后把安装命令写入剪贴板-->
<button class="btn copy-btn" @click="copyToClipboard">复制安装命令</button>
<div class="btn">
<a class="author-info" :href="`https://github.com/${props.item.author }`">
<img class="icon avatar" :src="`https://github.com/${ props.item.author }.png?size=80`" alt="">
<div class="author-name">{{ props.item.author }}</div>
</a>
</div>
<!-- 复制键复制安装命令npm install props.item.module_name-->
</div>
</div>
</template>
<script setup lang="ts">
import {defineProps, onMounted} from 'vue'
import Clipboard from 'clipboard'
//
//
const props = defineProps({
item: Object
})
const copyToClipboard = () => {
const clipboard = new Clipboard('.copy-btn', {
text: () => `npm install ${props.item.module_name}`
})
clipboard.on('success', () => {
})
clipboard.on('error', () => {
})
}
const getTagStyle = (backgroundColor: string) => {
// RGB
const rgb = backgroundColor.replace(/^#/, '');
const [r, g, b] = rgb.match(/.{2}/g).map(x => parseInt(x, 16));
//
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
//
return {
backgroundColor: backgroundColor,
color: brightness > 128 ? '#000' : '#fff'
};
};
//
</script>
<style scoped>
.btn {
margin-right: 15px;
}
button {
background-color: #00000000;
border: none;
}
.copy-btn {
cursor: pointer;
color: #666;
}
.icon {
width: 20px;
height: 20px;
}
.item-bar {
position: absolute;
bottom: 0;
height: 50px;
display: flex;
align-items: center;
box-sizing: border-box;
justify-content: space-between;
color: #00000055;
}
.tag {
display: inline-block;
padding: 0 5px;
margin-right: 5px;
border-radius: 5px;
font-size: 12px;
}
</style>

91
docs/components/PluginStore.vue Executable file
View File

@ -0,0 +1,91 @@
<script setup lang="ts">
import {computed, ref} from 'vue'
import ItemCard from './PluginItemCard.vue'
import ToggleSwitch from "./ToggleSwitch.vue";
import {getTextRef} from "./scripts/i18n";
import pluginsJson from "../public/plugins.json"
let showLiteyukiPluginOnly = ref(false)
let filteredItems = computed(() => {
let filtered = items.value
if (search.value) {
filtered = filtered.filter(item =>
item.name.toLowerCase().includes(search.value.toLowerCase()) ||
item.desc.toLowerCase().includes(search.value.toLowerCase()) ||
item.author.toLowerCase().includes(search.value.toLowerCase()) ||
item.module_name.toLowerCase().includes(search.value.toLowerCase())
)
}
if (showLiteyukiPluginOnly.value) {
filtered = filtered.filter(item => item.is_liteyuki_plugin)
}
return filtered
})
// Nonebot
let items = ref([])
let search = ref('')
//
items.value = pluginsJson
items.value.forEach(item => {
item.is_liteyuki_plugin = true
})
//
fetch('https://registry.nonebot.dev/plugins.json')
.then(response => response.json())
.then(data => {
// datais_officialfalse
data.forEach(item => {
item.is_official = false
})
items.value = items.value.concat(data)
})
</script>
<template>
<div class="market">
<h1>{{ getTextRef('pluginStore') }}</h1>
<p>{{ getTextRef('pluginStoreDesc') }}</p>
<!-- 搜索框-->
<div class="search-box-div">
<input class="item-search-box" type="text" v-model="search" :placeholder="getTextRef('search')"/>
<ToggleSwitch v-model:modelValue="showLiteyukiPluginOnly"/>
{{ getTextRef('liteyukiOnly') }}
</div>
<!-- 按钮们-->
<!-- <div class="tab">-->
<!-- <button @click="open"-->
<!-- </div>-->
<div class="items">
<!-- 使用filteredItems来布局商品 -->
<ItemCard v-for="item in filteredItems" :key="item.id" :item="item"/>
</div>
</div>
</template>
<style scoped>
h1 {
color: #00a6ff;
text-align: center;
font-weight: bold;
}
.items {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 10px;
}
.search-box-div {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
}
.search-box-div input {
margin-right: 10px;
}
</style>

54
docs/components/ResItemCard.vue Executable file
View File

@ -0,0 +1,54 @@
<template>
<div class="item-card">
<div class="item-name">{{ props.item.name }}</div>
<div class="item-description">{{ props.item.description }}</div>
<div class="item-bar">
<!-- 三个可点击svg一个github一个下载一个可点击"https://github.com/{{ username }}.png?size=80"个人头像配上id-->
<a :href=props.item.link class="" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16">
<path fill="currentColor"
d="m7.775 3.275l1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0a.751.751 0 0 1 .018-1.042a.751.751 0 0 1 1.042-.018a1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018a.751.751 0 0 1-.018-1.042m-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018a.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018a1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83"/>
</svg>
</a>
<div><a class="author-info" :href="`https://github.com/${props.item.author }`">
<img class="icon avatar" :src="`https://github.com/${ props.item.author }.png?size=80`" alt="">
<div class="author-name">{{ props.item.author }}</div>
</a>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {defineProps} from 'vue'
const props = defineProps({
item: Object
})
</script>
<style scoped>
.icon {
width: 20px;
height: 20px;
color: $themeColor;
}
.item-bar {
position: absolute;
bottom: 0;
height: 50px;
display: flex;
align-items: center;
box-sizing: border-box;
justify-content: space-between;
color: #00000055;
}
</style>

View File

@ -0,0 +1,38 @@
<template>
<div v-if="isVisible" class="floating-window">
<div class="window-content">
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
import {defineProps} from 'vue'
const props = defineProps({
isVisible: Boolean,
})
</script>
<style scoped>
.floating-window {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.window-content {
background: var(--vp-c-gray-1);
padding: 20px;
border-radius: 5px;
max-width: 60%;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>

105
docs/components/ResStore.vue Executable file
View File

@ -0,0 +1,105 @@
<script setup lang="ts">
import {computed, ref} from 'vue'
import ItemCard from './ResItemCard.vue'
import ResPubWindow from "./ResPubWindow.vue";
import {getTextRef, formatLang} from "./scripts/i18n";
import {RepoUrl} from "./scripts/statsApi";
import resourcesJson from "../public/resources.json"
import {useData} from "vitepress";
// formLan
// public/assets/resources.json
let filteredItems = computed(() => {
if (!search.value) {
return items.value.reverse()
}
return items.value.filter(item =>
item.name.toLowerCase().includes(search.value.toLowerCase()) ||
item.description.toLowerCase().includes(search.value.toLowerCase()) ||
item.author.toLowerCase().includes(search.value.toLowerCase())
).reverse()
})
// Nonebot
let items = ref([])
let search = ref('')
items.value = resourcesJson
//
const isPublishWindowOpen = ref(false)
let newRes = ref({
name: '',
})
function openPublishWindow() {
isPublishWindowOpen.value = true
}
function closePublishWindow() {
isPublishWindowOpen.value = false
}
let submitLang = ""
if (formatLang(useData().site.value.lang) === "zh") {
submitLang = "zh"
} else {
submitLang = "en"
}
function submitForm() {
const title = encodeURI(`Resource: ${newRes.value.name}`)
const issueURL = `${RepoUrl}/issues/new?assignees=&labels=Resource&template=resource_publish_${submitLang}.yml&title=${title}`
console.log(issueURL)
window.open(issueURL, '_blank')
}
</script>
<template>
<div class="market">
<h1>{{ getTextRef('resourceStore') }}</h1>
<div class="search-box-div"><input class="item-search-box" type="text" :placeholder="getTextRef('search')"
v-model="search"/></div>
<div class="store-tabs" style="display: flex">
<button class="store-button publish-button" @click="openPublishWindow">{{ getTextRef('publishRes') }}</button>
</div>
<div class="items">
<!-- 使用filteredItems来布局商品 -->
<ItemCard v-for="item in filteredItems" :key="item.id" :item="item"/>
</div>
<ResPubWindow class="pub-window" :is-visible="isPublishWindowOpen">
<h2>{{ getTextRef("publishRes") }}</h2>
<form @submit.prevent="submitForm">
<label for="name">{{ getTextRef("resName") }}</label>
<input type="text" id="name" v-model="newRes.name" :placeholder="getTextRef('resNameText')"/>
<div class="pub-options" style="display: flex; justify-content: center">
<button class="pub-option close" type="button" @click="closePublishWindow">{{
getTextRef("closeButtonText")
}}
</button>
<button class="pub-option submit" type="submit" @click="submitForm">{{
getTextRef("submitButtonText")
}}
</button>
</div>
</form>
</ResPubWindow>
</div>
</template>
<style scoped>
h1 {
color: #00a6ff;
text-align: center;
font-weight: bold;
}
.items {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 10px;
}
</style>

301
docs/components/StatsBar.vue Executable file
View File

@ -0,0 +1,301 @@
<script setup lang="ts">
import DefaultTheme from "vitepress/theme";
import {ref, onMounted, onUnmounted} from "vue";
import {statsApi, GithubStats, RepoUrl, StarMapUrl, uploadVisitRecord} from "./scripts/statsApi";
import {getTextRef, updateRefData} from "./scripts/i18n";
import {onBeforeRouteUpdate} from 'vue-router';
const {Layout} = DefaultTheme;
let githubStats: GithubStats | null = null;
const dataSections = {
total: {
name: 'total',
color: '#00a6ff',
value: ref(-1),
link: StarMapUrl
},
online: {
name: 'online',
color: '#7eff7e',
value: ref(-1),
link: StarMapUrl
},
stars: {
name: 'stars',
color: '#ffcc00',
value: ref(-1),
link: `${RepoUrl}/stargazers`
},
forks: {
name: 'forks',
color: '#ff6600',
value: ref(-1),
link: `${RepoUrl}/forks`
},
issues: {
name: 'issues',
color: '#ff0000',
value: ref(-1),
link: `${RepoUrl}/issues`
},
prs: {
name: 'prs',
color: '#f15df1',
value: ref(-1),
link: `${RepoUrl}/pulls`
},
plugins: {
name: 'plugins',
color: '#a766ff',
value: ref(-1),
link: './store/plugin'
},
resources: {
name: 'resources',
color: '#5a54fa',
value: ref(-1),
link: './store/resource'
},
visitors: {
name: 'visitors',
color: '#00a6ff',
value: ref(-1),
link: RepoUrl
},
}
async function updateData() {
// dataSections.online.value.value = await statsApi.getOnline();
// dataSections.total.value.value = await statsApi.getTotal();
[
dataSections.online.value.value,
dataSections.total.value.value,
dataSections.plugins.value.value,
dataSections.resources.value.value,
dataSections.visitors.value.value,
githubStats,
] = await Promise.all([
statsApi.getOnline(),
statsApi.getTotal(),
statsApi.getPluginNum(),
statsApi.getResourceNum(),
statsApi.getVisitCount(),
statsApi.getGithubStats(),
]);
dataSections.stars.value.value = githubStats?.stars || 0;
dataSections.forks.value.value = githubStats?.forks || 0;
dataSections.issues.value.value = githubStats?.issues || 0;
dataSections.prs.value.value = githubStats?.prs || 0;
}
function formatNumber(num: { value: number }): string {
return num.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
onMounted(() => {
const intervalId = setInterval(updateData, 10000);
updateData();
uploadVisitRecord();
onUnmounted(() => {
clearInterval(intervalId);
});
});
onBeforeRouteUpdate(() => {
updateRefData();
});
console.log(
" _ _ _ _ _ ____ _ \n" +
" | | (_) | | | (_) _ \\ | | \n" +
" | | _| |_ ___ _ _ _ _| | ___| |_) | ___ | |_ \n" +
" | | | | __/ _ \\ | | | | | | |/ / | _ < / _ \\| __|\n" +
" | |____| | || __/ |_| | |_| | <| | |_) | (_) | |_ \n" +
" |______|_|\\__\\___|\\__, |\\__,_|_|\\_\\_|____/ \\___/ \\__|\n" +
" __/ | \n" +
" |___/ "
)
console.log(
getTextRef('easterEgg')
)
</script>
<template>
<Layout>
<template #home-features-before>
<div class="stats-bar-content">
<div class="stats-bar">
<div class="stats-info">
<div class="stats-title">{{ getTextRef('stats') }}</div>
<div class="sections">
<div v-for="section in Object.values(dataSections)" :key="section.name" class="section">
<a :href="section.link" target="_blank">
<div class="section-tab">
<span class="dot" :style="{backgroundColor: section.color}"></span>
<span class="text">{{ getTextRef(section.name) }}</span>
</div>
<div class="number">{{ formatNumber(section.value) }}</div>
</a>
</div>
</div>
</div>
<div class="starmap">
<iframe src="https://starmap.liteyuki.icu/" width="100%" height="300px" class="gamma">
</iframe>
</div>
</div>
</div>
</template>
</Layout>
</template>
<style scoped>
.stats-bar-content {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.gamma {
filter: brightness(1.8);
}
.dark .gamma {
filter: brightness(1.0);
}
.stats-bar {
width: 80%;
max-width: 1150px;
display: flex;
justify-content: space-between;
padding: 20px;
margin: 10px;
border-radius: var(--border-radius-2);
background-color: var(--vp-c-gray-1);
flex-direction: column; /* 默认纵向布局 */
}
.stats-info{
margin-bottom: 20px;
}
.stats-title {
font-size: 20px;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
}
.sections {
height: 100%;
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 15px;
margin: 10px;
}
.section {
display: flex;
flex-direction: column;
position: relative; /* 使伪元素相对于父元素定位 */
border-radius: var(--border-radius-2);
}
.section::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 0 solid transparent; /* 初始边框为透明 */
transition: border 0.1s ease-in-out; /* 添加过渡效果 */
border-radius: var(--border-radius-2);
pointer-events: none; /* 确保伪元素不会阻挡点击事件 */
}
.section:hover::before {
border: 1px solid #00a6ff; /* 悬停时添加边框 */
border-radius: var(--border-radius-2);
}
.section-tab {
margin-left: 15px;
display: flex;
justify-content: flex-start;
align-items: center; /* 确保垂直居中 */
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 5px;
}
.text {
font-size: 14px;
white-space: nowrap;
align-items: center;
}
.number {
font-size: 27px;
font-weight: bold;
margin-top: 5px;
margin-left: 15px;
}
.starmap {
position: relative;
width: 100%;
height: 200px;
overflow: hidden;
border-radius: var(--border-radius-2);
}
.starmap iframe {
position: absolute;
top: -150px; /* 根据需要调整裁剪位置 */
left: -40px; /* 根据需要调整裁剪位置 */;
width: calc(100% + 80px); /* 根据需要调整裁剪宽度 */
height: calc(100% + 300px); /* 根据需要调整裁剪高度 */
}
@media (min-width: 768px) {
/* PC模式下的样式 */
.stats-bar {
flex-direction: row;
margin: 30px;
}
.stats-info {
width: 40%;
margin: 10px 30px 30px 30px;
}
.starmap {
width: 60%;
height: 400px;
}
.starmap iframe {
position: absolute;
top: -130px; /* 根据需要调整裁剪位置 */
left: -60px; /* 根据需要调整裁剪位置 */;
width: calc(100% + 120px); /* 根据需要调整裁剪宽度 */
height: calc(100% + 280px); /* 根据需要调整裁剪高度 */
}
}
</style>

0
docs/components/Tabs.vue Executable file
View File

View File

@ -0,0 +1,67 @@
<template>
<label class="switch">
<input type="checkbox" :checked="modelValue" @change="updateValue($event.target.checked)">
<span class="slider round"></span>
</label>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
const props = defineProps({
modelValue: Boolean
})
const emit = defineEmits(['update:modelValue'])
const updateValue = (value: boolean) => {
emit('update:modelValue', value)
}
</script>
<style scoped>
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #2196F3;
}
input:checked + .slider:before {
transform: translateX(26px); /* 调整为 26px 以确保对齐 */
}
</style>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,4 @@
export const platformBaseURL = "https://github.com/"
export const repoPath = "LiteyukiStudio/LiteyukiBot"
export const repoURL = `${platformBaseURL}${repoPath}`

112
docs/components/scripts/i18n.ts Executable file
View File

@ -0,0 +1,112 @@
import {ref} from "vue";
import {useData} from "vitepress";
const i18nData = {
en: {
stats: 'Stats',
online: 'Online',
offline: 'Offline',
total: 'Total',
fetching: 'Fetching',
stars: 'Stars',
forks: 'Forks',
issues: 'Issues',
prs: 'Pull Requests',
visitors: 'Visitors',
size: 'Size',
plugins: 'Plugins',
resources: 'Resources',
pluginStore: 'Plugin Store',
pluginStoreDesc: 'Content from the LightSnow Plugin Store, LightSnow supports NoneBot through the lpnonebot plugin, and references some NoneBot plugins',
liteyukiOnly: 'Liteyuki Only',
search: 'Search',
resourceStore: 'Resources Store',
thx_contributors: 'Thanks the following contributors!',
easterEgg: 'Congratulations on finding the Easter egg!',
publishPlugin: 'Publish Plugin',
publishRes: 'Publish Resource',
closeButtonText: 'Close',
submitButtonText: 'Submit',
resName: 'Name',
resDesc: 'Description',
resAuthor: 'Author',
resLink: 'Download Link',
resHomepage: 'Homepage',
resNameText: 'Example: Kawaii Style Theme',
resDescText: 'Example: A kawaii style and color theme',
resAuthorText: 'Usually the github username, Example: yanyongyu',
resLinkText: 'Direct download link, usually zip package link',
resHomepageText: 'Optional, can be the name of the git platform repository"',
},
zh: {
stats: '统计信息',
online: '在线',
offline: '离线',
total: '实例',
fetching: '获取中',
stars: '星星',
forks: '分叉',
issues: '议题',
prs: '拉取请求',
visitors: '访客',
size: '大小',
plugins: '插件',
resources: '主题资源',
store: '商店',
pluginStore: '插件商店',
pluginStoreDesc: '内容来自轻雪插件商店轻雪通过lpnonebot插件对NoneBot实现支持引用了部分NoneBot插件',
liteyukiOnly: '仅轻雪',
search: '搜索',
resourceStore: '资源商店',
thx_contributors: '感谢以下贡献者!',
easterEgg: '恭喜你发现了彩蛋!',
publishPlugin: '发布插件',
publishRes: '发布资源',
closeButtonText: '关闭',
submitButtonText: '提交',
resName: '名称',
resDesc: '描述',
resAuthor: '作者',
resLink: '下载链接',
resHomepage: '主页',
resNameText: '示例:可爱风格主题',
resDescText: '示例:一个可爱风格和配色的主题',
resAuthorText: '通常为github用户名示例yanyongyu',
resLinkText: '直接下载链接通常为zip包链接',
resHomepageText: '可选可为git平台仓库名',
}
}
let refData = {}
function getText(lang: string, key: string): string {
lang = formatLang(lang);
return i18nData[lang][key];
}
export function formatLang(lang: string): string {
if (lang.includes('-')) {
return lang.split('-')[0];
}
return lang;
}
export function updateRefData() {
const lang = formatLang(useData().site.value.lang);
for (let key in refData) {
refData[key].value = getText(lang, key);
}
}
export function getTextRef(key: string): any {
const lang = formatLang(useData().site.value.lang);
refData[key] = getText(lang, key);
return refData[key] || key;
}

View File

@ -0,0 +1,182 @@
// URL
export const OWNER = "LiteyukiStudio"
export const REPO = "LiteyukiBot"
const githubAPIUrl = "https://api.github.com"
const giteaAPIUrl = "https://git.liteyuki.icu/api/v1"
const onlineFetchUrl = "https://api.liteyuki.icu/online";
const totalFetchUrl = "https://api.liteyuki.icu/count";
const visitRecordUrl = "https://api.liteyuki.icu/visit";
const visitCountUrl = "https://api.liteyuki.icu/visit_count";
export const RepoUrl = `https://github.com/${OWNER}/${REPO}`
export const StarMapUrl = "https://starmap.liteyuki.icu"
type GithubStats = {
stars: number;
forks: number;
watchers: number;
issues?: number;
prs?: number;
size?: number;
}
// 异步接口
interface StatsApi {
getTotal: () => Promise<number>;
getOnline: () => Promise<number>;
getGithubStats: () => Promise<GithubStats>;
getPluginNum: () => Promise<number>;
getResourceNum: () => Promise<number>;
getVisitCount: () => Promise<number>;
}
export type {GithubStats};
async function getGiteaStats() {
try {
const url = `${giteaAPIUrl}/repos/${OWNER}/${REPO}`;
console.log(url);
const res = await fetch(url);
const data = await res.json();
return {
stars: data.stars_count,
forks: data.forks_count,
watchers: data.watchers_count,
issues: 0,
prs: 0,
size: data.size,
};
} catch (e) {
return {
stars: -1,
forks: -1,
watchers: -1,
issues: -1,
prs: -1,
size: -1,
};
}
}
async function getGithubStats() {
try {
const res = await fetch(`${githubAPIUrl}/repos/${OWNER}/${REPO}`);
const data = await res.json();
return {
stars: data.stargazers_count,
forks: data.forks_count,
watchers: data.watchers_count,
issues: data.open_issues_count,
prs: data.open_issues_count,
size: data.size,
};
} catch (e) {
return {
stars: -1,
forks: -1,
watchers: -1,
issues: -1,
prs: -1,
size: -1,
};
}
}
async function getRepoStats() {
// 两个接口各数据,加和返回
const githubStats = await getGithubStats();
const giteaStats = await getGiteaStats();
return {
stars: githubStats.stars + giteaStats.stars,
forks: githubStats.forks + giteaStats.forks,
watchers: githubStats.watchers + giteaStats.watchers,
issues: githubStats.issues + giteaStats.issues,
prs: githubStats.prs + giteaStats.prs,
size: githubStats.size + giteaStats.size,
};
}
// 实现接口
export const statsApi: StatsApi = {
getTotal: async () => {
try {
const res = await fetch(totalFetchUrl);
const data = await res.json();
return data.register;
} catch (e) {
return -1;
}
},
getOnline: async () => {
try {
const res = await fetch(onlineFetchUrl);
const data = await res.json();
return data.online;
} catch (e) {
return -1;
}
},
getGithubStats: getRepoStats,
getPluginNum: async () => {
try {
const res = await fetch('/plugins.json');
const data = await res.json();
return data.length;
} catch (e) {
return -1;
}
},
getResourceNum: async () => {
try {
const res = await fetch('/resources.json');
const data = await res.json();
return data.length;
} catch (e) {
return -1;
}
},
getVisitCount: async () => {
try {
const res = await fetch(visitCountUrl);
const data = await res.json();
return data.count;
} catch (e) {
return -1;
}
}
};
function getDeviceId(): string {
// 用户每次访问时生成一个唯一的设备ID储存在localStorage中用于统计用户数量
const deviceIdKey = 'deviceId';
let deviceId = localStorage.getItem(deviceIdKey);
if (!deviceId) {
deviceId = generateUUID();
localStorage.setItem(deviceIdKey, deviceId);
}
return deviceId;
}
export async function uploadVisitRecord() {
const deviceId = getDeviceId();
try {
await fetch(visitRecordUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({'device_id': deviceId}).toString(),
});
} catch (e) {
console.error('Failed to upload visit record:', e);
}
}
function generateUUID(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}

77
docs/en/deploy/config.md Executable file
View File

@ -0,0 +1,77 @@
---
title: Configurations
order: 2
---
# Configurations
LiteyukiBot supports `yaml`, `json`, and `toml` as configuration files, depending on your personal preference.
When you first run LiteyukiBot, it will generate `config.yml` and the `config` directory. You can modify the configuration items and restart LiteyukiBot. In most cases, you only need to modify
the `superusers` and `nickname` fields.
When starting, LiteyukiBot will load all configuration files in the project directory `config.yml/yaml/json/toml` and the `config` directory. You can create multiple configuration files in
the `config` directory, and LiteyukiBot will automatically merge these configuration files.
## **Basic Configuration**
```yaml
# NoneBot configuration
nonebot:
command_start: [ "/", "" ] # Command prefix, if there is no "" empty command header, please enable alconna_use_command_start to ensure alconna parsing is normal
host: 127.0.0.1 # Listening address, default is local, if you want to receive external requests, please fill in
port: 20216 # Binding port
nickname: [ "liteyuki" ] # Bot nickname list
superusers: [ "1919810" ] # Superuser list
liteyuki:
log_level: "INFO" # Log level
log_icon: true # Whether to display the log level icon (some console fonts are not available)
auto_report: true # Whether to automatically report problems to Liteyuki server
auto_update: true # Whether to automatically update Liteyuki, check for updates at 4 am every day
plugins: [ ] # Liteyuki plugin list
plugin_dirs: [ ] # Liteyuki plugin directory list
```
## **Other configurations**
The following is the default value. If you need to customize it, please add it manually
```yaml
# Advanced configuration
nonebot:
onebot_access_token: "" # OneBot access token
default_language: "zh-CN" # Default language
alconna_auto_completion: false # alconna auto completion
safe_mode: false # Safe mode, if true, the bot will not load any plugins
# other nonebot configurations
custom_config_1: "custom_value1"
custom_config_2: "custom_value2"
# development configuration
liteyuki:
allow_update: true # Whether to allow Liteyuki to update
debug: false # Debug mode, if true, Liteyuki will output more detailed logs
dev_mode: false # development mode, if true, Liteyuki will load all plugins in the development directory
...
```
```yaml
```
## **Example: Configuration of OneBot implementation side connected to NoneBot**
In production environments, it is recommended to use reverse WebSocket
The fields provided by different implementation sides may be different, but basically the same. Here is a reference value
| Fields | Value | Description |
|-------------|------------------------------------|---------------------------------------------------------------------------------------|
| protocol | Reverse WebSocket | Liteyuki-NoneBot as server |
| address | ws://127.0.0.1:20216/onebot/v11/ws | The address depends on the configuration file, the default is ` |
| AccessToken | `""` | If you have configured `AccessToken` for Liteyuki, please fill in the same value here |
- To use other communication methods, please visit [OneBot Adapter](https://onebot.adapters.nonebot.dev/) for detailed information
## **Other**
- Liteyuki is not limited to the OneBot adapter and NoneBot2. You can use any adapter supported by NoneBot2 or use the Liteyuki message delivery plugin

30
docs/en/deploy/fandq.md Executable file
View File

@ -0,0 +1,30 @@
---
title: FAQ
order: 3
---
# FAQ
## **Frequently Asked Questions**
- There are too many python interpreters on my computer, how do I know which one to use?
- You can specify which python interpreter to use by using the full path to the python executable, for example, `/path/to/python main.py`
- Use virtual environments to avoid conflicts between different python interpreters
- Update Liteyuki failed, error `InvalidGitRepositoryError`
- Please install `Git` correctly and deploy Liteyuki using cloning instead of direct download
- How to log in to chat platforms?
- Some plugins provide the ability to log in to specific platforms, for example, using the NoneBot plugin to log in to supported adapter platforms
- `Playwright` installation failed
- Enter `playwright install` to install the browser
- Some plugins report errors after installation and cannot be started
- Please refer to the plugin documentation first, confirm that the necessary configuration items of the plugin are intact,
and if the problem persists, please contact the plugin author or start Liteyuki in safe mode `safe_mode: true`.
In safe mode, you can use `npm uninstall` to uninstall problematic plugins
## Other questions
- Join chat group[775840726](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=SzmDYbfR6jY94o9KFNon7AwelRyI6M_u&authKey=ygeBdEmdFNyCWuNR4w0M1M8%2B5oDg7k%2FDfN0tzBkYcnbB%2FGHNnlVEnCIGbdftsnn7&noverify=0&group_code=775840726)
- If you don't have a QQ account, you can [submit an issue on GitHub](https://github.com/LiteyukiStudio/LiteyukiBot/issues/new?assignees=&labels=&projects=&template=%E9%97%AE%E9%A2%98%E5%8F%8D%E9%A6%88.md&title=)

62
docs/en/deploy/install.md Executable file
View File

@ -0,0 +1,62 @@
---
title: Install
order: 1
---
# Install
## **Normal Installation**
1. Install [`Git`](https://git-scm.com/download/) and [`Python3.10+`](https://www.python.org/downloads/release/python-31010/) Environment.
```bash
# Clone Repo
git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1
# Change directory
cd LiteyukiBot
# 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
# Run Liteyuki
python main.py
```
> [!tip]
> It is recommended to use a virtual environment to run Liteyuki to avoid dependency conflicts.
> You can use `python -m venv .venv` to create a virtual environment, and then use `.venv\Scripts\activate` to activate the virtual environment
> (use `source .venv/bin/activate` to activate on Linux).
## **Run with Docker**
```bash
docker pull ghcr.io/liteyukistudio/liteyukibot:latest # Nightly build
```
> [!tip]
> 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
## **Device Requirements**
- Windows system version minimum `Windows10+`/`Windows Server 2019+`
- Linux system requires Python3.10+, recommended `Ubuntu 20.04+`
- CPU: at least `1vCPU`
- Memory: Bot without other plugins will occupy `300~500MB`, including `chromium` and `node` processes, other plugins depend on specific plugins, recommended `1GB` or more
- Disk: at least `1GB` of space
> [!warning]
> If there are multiple environments on the device, please use `path/to/python -m pip install -r requirements.txt` to install dependencies, `path/to/python` is the path to your Python executable
> [!warning]
> Liteyuki's update function depends on Git. If you do not have Git installed and run the source code directly, you will not be able to use the update function
#### For other questions, please refer to [FAQ](./fandq)

21
docs/en/dev/best_practices.md Executable file
View File

@ -0,0 +1,21 @@
---
title: Best Practices
order: 10
---
# Best Practices
## Bot applications
- [LiteyukiBot](https://github.com/LiteyukiStudio/LiteyukiBot): Liteyuki Official Bot
- [LiteyukiBot-TriM](https://github.com/TriM-Organization/LiteyukiBot-TriM): TriM Official Custom Liteyuki Bot
- [Liteyuki Marsho](https://git.liteyuki.icu/LiteyukiStudio/marsho-alpha): A cute cat girl bot based on Liteyuki and the github model
## plugins
- [liteyukibot-plugin-nonebot](https://github.com/LiteyukiStudio/liteyukibot-plugin-nonebot): Liteyuki Bot NoneBot plugin, allowing Liteyuki to support NoneBot
- [nonebot-plugin-liteyukibot](https://github.com/LiteyukiStudio/nonebot-plugin-liteyukibot): NoneBot plugin, allowing NoneBot to support Liteyuki
## Others
- [liteyuki starmap](https://starmap.liteyuki.icu): Liteyuki official star map, showing all instances of Liteyuki and their location distribution
- [TRSS_Liteyuki](https://timerainstarsky.github.io/TRSS_Liteyuki/): LiteyukiBot management script
- [litedoc](https://github.com/LiteyukiStudio/litedoc): Liteyuki API documentation generator
- liteyukibot-api (closed source): Liteyuki Bot stat interface

98
docs/en/dev/comm.md Executable file
View File

@ -0,0 +1,98 @@
---
title: Process Communication
order: 4
---
# **Channel Communication**
### Introduction
LiteyukiBot is running in the main process MainProcess, and other plugin framework processes are child processes that come with it.
Therefore, it is impossible to communicate through shared memory and direct object transfer.
Liteyuki provides a channel [`Channel`](./api/comm/channel#class-channel-generic-t) for inter-process communication like `go`.
You can send messages to other processes through [`Channel`](./api/comm/channel#class-channel-generic-t) and listen to messages from other processes.
### Example
The channel is full-duplex, with two receiving modes, but only one mode can be used for a channel, that is, passive mode and active mode, passive mode is implemented by the `chan.on_receive()` decorator callback function, and active mode needs to call `chan.receive()` to implement
- 创建子进程的同时会初始化一个被动通道和一个主动通道,且通道标识为`{process_name}-active``{process_name}-passive`
- 主进程中通过`get_channel`函数获取通道对象
- 子进程中导入单例`active_channel``passive_channel`即可
> 在轻雪插件中(主进程中)
```python
import asyncio
from liteyuki.comm import get_channel, Channel
from liteyuki import get_bot
# get_channel函数获取通道对象参数为调用set_channel时的通道标识
channel_passive = get_channel("nonebot-passive") # 获取被动通道
channel_active = get_channel("nonebot-active") # 获取主动通道
liteyuki_bot = get_bot()
# 注册一个函数在轻雪启动后运行
@liteyuki_bot.on_after_start
async def send_data():
while True:
channel_passive.send("I am liteyuki main process passive")
channel_active.send("I am liteyuki main process active")
await asyncio.sleep(3) # 每3秒发送一次消息
```
> 在子进程中例如NoneBot插件中
```python
from nonebot import get_driver
from liteyuki.comm import active_channel, passive_channel # 子进程中获取通道直接导入进程全局单例即可
from liteyuki.log import logger
driver = get_driver()
# 被动模式,通过装饰器注册一个函数在接收到消息时运行,每次接收到字符串数据时都会运行
@passive_channel.on_receive(filter_func=lambda data: isinstance(data, str))
async def on_passive_receive(data):
logger.info(f"Passive receive: {data}")
# 注册一个函数在NoneBot启动后运行
@driver.on_startup
def on_startup():
while True:
data = active_channel.receive()
logger.info(f"Active receive: {data}")
```
> 启动后控制台输出
```log
0000-00-00 00:00:00 [ℹ️信息] Passive receive: I am liteyuki main process passive
0000-00-00 00:00:00 [ℹ️信息] Active receive: I am liteyuki main process active
0000-00-00 00:00:03 [ℹ️信息] Passive receive: I am liteyuki main process passive
0000-00-00 00:00:03 [ℹ️信息] Active receive: I am liteyuki main process active
...
```
## **共享内存通信**
### 简介
- 相比于普通进程通信,内存共享使得代码编写更加简洁,轻雪框架提供了一个内存共享通信的接口,你可以通过`storage`模块实现内存共享通信,该模块封装通道实现
- 内存共享是线程安全的,你可以在多个线程中读写共享内存,线程锁会自动保护共享内存的读写操作
### 示例
> 在任意进程中均可使用
```python
from liteyuki.comm.storage import shared_memory
shared_memory.set("key", "value") # 设置共享内存
value = shared_memory.get("key") # 获取共享内存
```
源代码:[liteyuki/comm/storage.py](https://github.com/LiteyukiStudio/LiteyukiBot/blob/main/liteyuki/comm/storage.py)

73
docs/en/dev/guide.md Executable file
View File

@ -0,0 +1,73 @@
---
title: Development Guide
order: 0
---
<script setup>
import ContributorBar from '../../components/ContributorBar.vue'
</script>
# Development Guide
## How to Develop
Please read the [Plugin Development](./plugin) and [API Reference](./api/) documents if you are developing a plugin.
If you need to submit code to the Liteyuki repository, please read the following:
1. First [fork](https://github.com/LiteyukiStudio/LiteyukiBot/fork) a copy of the Liteyuki repository to your personal/organization account.
2. Develop in your repository.
3. Create a new branch in your repository and submit your code to this branch.
4. Create a Pull Request in your repository to merge your branch into the `main` branch of the Liteyuki repository.
- Participation in development assumes that you are already familiar with the basic usage of the Python language and the Liteyuki framework.
- If you are developing documentation, please ensure that you are familiar with Markdown syntax and basic front-end knowledge.
- Contact the repository maintainer in case of conflicts.
### Suggestions
- During development, you can use tools such as `mypy`, `flake8`, and `black` for code checking and formatting.
- Enable developer mode by setting `dev_mode: true` in `config.yml` to see more debugging information in the console.
## Project Structure
- `main.py`: Bot entry file
- `liteyuki`: Framework directory (liteyukibot)
- `src`: Bot application source code directory
- `liteyuki_plugins`: Liteyuki plugin directory
- `nonebot_plugins`: Nonebot plugin directory
- `resources`: Built-in resource packs directory
- `utils`: Utility directory
- `tests`: Unit test directory
- `docs`: Documentation directory
- `en`: English documentation
- `zh`: Chinese documentation
- `docker`: Docker related content directory
The `liteyuki` framework is included in the `LiteyukiBot` application, so this project is both the `LiteyukiBot` application repository and the `liteyuki` framework repository.
The `src` directory is the application part, please develop business logic in this directory. `liteyuki_plugins` and `nonebot_plugins` directories are plugin directories, please develop plugins in these directories.
## Standardization
- Code should follow [`PEP8`](https://pep8.org/) and [`Google Python Style Guide`](https://google.github.io/styleguide/pyguide.html).
- In addition, code submitted to the Liteyuki repository should follow the following guidelines:
- Ensure that the code is runnable and harmless.
- Ensure that the type hints in the code are correct.
- Ensure that the comment style is [`Google Docstring`](https://google.github.io/styleguide/pyguide.html) or
[`Liteyuki Docstring`](https://github.com/LiteyukiStudio/litedoc?tab=readme-ov-file#liteyuki-docstring)(recommended) to ensure that Litedoc can parse and generate documentation correctly.
- Strings should be enclosed in double quotes `"` as much as possible, and single quotes `'` should be used when nesting strings.
- If there is a part for ordinary users, ensure that the documentation is complete (each language has corresponding documentation).
- commit message should follow the following guidelines:
- You should commit the code after completing a feature or fixing a bug, and not mix the code of multiple features or bugs together.
- We use gitmoji to mark the type of commit, such as `:sparkles:` for introducing new features, `:bug:` for fixing bugs, etc., please refer to [gitmoji](https://gitmoji.dev/) for details.
- The format of the commit message is `<emoji> [type:] <message>`, such as `:sparkles: feat: add new field to event`,
where the type field is the type of commit, not much is required, but please fill in as much as possible; the message field is a brief description, in summary, what you did.
- There is no restriction on the language of the commit message, and bilingual use is possible if conditions permit.
- The documentation should follow [`Markdown`](https://www.markdownguide.org/) syntax and support vitepress-related content:
- Revise the documentation for each language when editing.
- Ensure that the links in the document are correct and do not lead to inaccessible links.
- Ensure that the **User Documentation** is easy to understand and the **Development Documentation** is detailed.
## Finally
- This project is a non-profit open-source project, and we welcome anyone to participate in development. Your contributions will make Liteyuki better.
<ContributorBar />

72
docs/en/dev/lyfunc.md Executable file
View File

@ -0,0 +1,72 @@
---
title: Liteyuki Function
order: 2
---
# **轻雪函数**
轻雪函数 Liteyuki Function 是轻雪的一个功能它允许你在轻雪中运行一些自定义的由数据驱动的命令类似于Minecraft的mcfunction属于资源包的一部分但需单独起篇幅.
### **函数文件**
函数文件放在资源包的`functions`目录下,文件名以`.mcfunction` `.lyfunction` `.lyf`结尾,例如`test.mcfunction`,文件内容为一系列的命令,每行一个命令,支持单行注释`#`(编辑时的语法高亮可采取`shell`格式),例如:
```shell
# 在发信器输出"hello world"
cmd echo hello world
# 如果你想同时输出多行内容可以尝试换行符(Python格式)
cmd echo hello world\nLiteyuki bot
```
也支持句末注释,例如:
```shell
cmd echo hello world # 输出"hello world"
```
### **命令文档**
```shell
var <var1=value1> [var2=value2] ... # 定义变量
cmd <command> # 在设备上执行命令
api <api_name> [var=value...] # 调用Bot API
function <func_name> # 调用函数,可递归
sleep <time> # 异步等待单位s
nohup <command> # 使用新的task执行命令即不等待
end # 结束函数关键字包括子task
await # 等待所有异步任务结束若函数中启动了其他task需要在最后调用否则task对象会被销毁
```
#### **示例**
```shell
# 疯狂戳好友
# 使用 /function poke user_id=123456 执行
# 每隔0.2s戳两次,无限戳,会触发最大递归深度限制
# 若要戳20s后停止则需要删除await添加sleep 20和end
api friend_poke user_id=user_id
api friend_poke user_id=user_id
sleep 0.2
nohup function poke
await
```
### **API**
理论上所有基于onebotv11的api都可调用不同Adapter api也有差别.
[Onebot v11 API文档](https://283375.github.io/onebot_v11_vitepress/api/index.html)
### **结束关键字**
由于LiteyukiBot基于异步运行, 所以在编写lyfunction时也要注意异步的调用避免出现"单线程走到底"的情况是效率提升的关键.
`await` 异步任务结束关键字用于结束当前已完成function的执行
> [!warning]
> 但若出现非单function的情况有一个task任务没有完成而await被执行了那么当前所有函数包的task都会被截停销毁
> [!tip]
> 编写轻雪函数推荐你使用VS Code插件[Liteyuki Function](https://github.com/LiteyukiStudio/lyfunctionTextmate)实现语法高亮

80
docs/en/dev/plugin.md Executable file
View File

@ -0,0 +1,80 @@
---
title: Plugin
order: 3
---
# 简介
轻雪插件是轻雪内置的一部分功能,运行在主进程中,可以很高程度地扩展轻雪的功能。
## 开始
### 创建插件
一个`.py`文件或一个包含`__init__.py`的文件夹即可被识别为插件
首先创建一个文件夹,例如`watchdog_plugin`,并在其中创建一个`__init__.py`文件,即可创建一个插件
`__init__.py`
```python
from liteyuki.plugin import PluginMetadata, PluginType
from .watch_dog import * # 导入逻辑部分
# 定义插件元数据
__plugin_meta__ = PluginMetadata(
name="NoneDog", # 插件名称
version="1.0.0", # 插件版本
description="A simple plugin for nonebot developer", # 插件描述
type=PluginType.SERVICE # 插件类型
)
# 你的插件代码
...
```
### 编写逻辑部分
轻雪主进程不涉及聊天部分,因此插件主要是一些后台任务或者与聊天机器人的通信
以下我们会编写一个简单的插件用于开发NoneBot时进行文件系统变更重载
`watch_dog.py`
```python
import os
from liteyuki.dev import observer # 导入文件系统观察器
from liteyuki import get_bot, logger # 导入轻雪Bot和日志
from watchdog.events import FileSystemEvent # 导入文件系统事件
liteyuki = get_bot() # 获取唯一的轻雪Bot实例
exclude_extensions = (".pyc", ".pyo") # 排除的文件扩展名
# 用observer的on_file_system_event装饰器监听文件系统事件
@observer.on_file_system_event(
directories=("src/nonebot_plugins",),
event_filter=lambda event: not event.src_path.endswith(exclude_extensions) and ("__pycache__" not in event.src_path) and os.path.isfile(event.src_path)
)
def restart_nonebot_process(event: FileSystemEvent):
logger.debug(f"File {event.src_path} changed, reloading nonebot...")
liteyuki.restart_process("nonebot") # 调用重启进程方法
```
### 加载插件
#### 方法1
- 在配置文件中的`liteyuki.plugins`中添加你的插件路径,例如`watchdog_plugin`,重启轻雪即可加载插件。
#### 方法2
- 使用开发工具快速运行插件,无需手动创建实例
- 创建入口文件,例如`main.py`,并在其中写入以下代码
```python
from liteyuki.dev.plugin import run_plugins
run_plugins("watchdog_plugin")
```
然后运行`python main.py`即可启动插件
启用插件后我们在src/nonebot_plugins下创建一个文件例如`test.py`并在其中写入一些代码保存后轻雪会自动重载NoneBot进程

51
docs/en/dev/resource.md Executable file
View File

@ -0,0 +1,51 @@
---
title: Resource Pack
order: 1
---
# 简介
资源包,亦可根据用途称为主题包、字体包、语言包等,它允许你一定程度上自定义轻雪的外观,并且不用修改源代码
- [资源/主题商店](../store/resource)提供了一些资源包供你选择,你也可以自己制作资源包
- 资源包的制作很简单,如果你接触过`Minecraft`的资源包,那么你能够很快就上手,仅需按照原有路径进行文件替换即可,讲起打包成一个新的资源包。
- 部分内容制作需要一点点前端基础,例如`html``css`
- 轻雪原版资源包请查看`LiteyukiBot/liteyuki/resources`,可以在此基础上进行修改
- 欢迎各位投稿资源包到轻雪资源商店
请注意主题包中的html渲染使用Js来规定数据的渲染位置请确保您所编写的html代码能被Bot解析否则会导致渲染失败或渲染结果不理想/异常/错位等无法预料的事情发生。推荐在编写html时同时更改对应Js代码以避免出现无法预料的问题。
---
## 加载资源包
- 资源包通常是以`.zip`格式压缩的,只需要将其解压到根目录`resources`目录下即可,注意不要嵌套文件夹,正常的路径应该是这样的
```shell
main.py
resources
└─resource_pack_1
├─metadata.yml
├─templates
└───...
└─resource_pack_2
├─metadata.yml
└─...
```
- 你自己制作的资源包也应该遵循这个规则,并且应该在`metadata.yml`中填写一些信息
- 若没有`metadata.yml`文件,则该文件夹不会被识别为资源包
```yaml
name: "资源包名称"
version: "1.0.0"
description: "资源包描述"
# 你可以自定义一些信息,但请保证以上三个字段
...
```
- 资源包加载遵循一个优先级即后加载的资源包会覆盖前面的资源包例如你在A包中定义了一个`index.html`文件B包也定义了一个`index.html`文件那么加载B包后A包中的`index.html`文件会被覆盖
- 对于不同资源包的不同文件是可以相对引用的例如你在A中定义了`templates/index.html`在B中定义了`templates/style.css`可以在A的`index.html`中用`./style.css`相对路径引用B中的css
> [!tip]
> 资源包的结构会随着轻雪的更新而有变动,第三方资源包开发者需要注意版本兼容性,同时用户也应该自行选择可用的资源包

63
docs/en/index.md Executable file
View File

@ -0,0 +1,63 @@
---
layout: home
hero:
name: "LiteyukiBot"
tagline: "An integrated chat bot application and management framework"
actions:
- theme: brand
text: 🚀 Get Started
link: ./deploy/install
- theme: alt
text: 📖 Manual
link: ./usage/basic
- theme: alt
text: 📦 Extensions
link: ./store/
- theme: alt
text: 🛠️ Development
link: ./dev/guide
image:
light: https://cdn.liteyuki.icu/logos/bot.svg
dark: https://cdn.liteyuki.icu/logos/bot.svg
alt: Liteyuki Logo
features:
- title: Ecological Diversity
icon: 🛠️
details: Based on the liteyuki framework, compatible with any Python bot framework and application
link: ./dev/api
- title: Pluggable
icon: 🧩
details: Use package manager for convenient management of plugins and resource packs
link: ./store/plugin
- title: Customizable
icon: 🎨
details: Fully customize the appearance using resource packs
link: ./store/resource
- title: Localization
icon: 🌐
details: Support for multiple languages through resource packs
link: https://baike.baidu.com/item/i18n/6771940
- title: Easy to use
icon: ⚙️
details: No complicated pre-process, ready to use out of the box
link: ./deploy/config
- title: High Performance
icon: 🚀
details: 500 plugins, starts within 2 seconds
- title: Rolling Updates
icon: ☁️
details: Keep your robot up to date with the latest commits
- title: Open Source
icon: 📄
details: The project follows the LSO LICENSE and is open to contributions
link: https://github.com/LiteyukiStudio/LiteyukiStudioOpensourceLICENSE
---

6
docs/en/store/plugin.md Executable file
View File

@ -0,0 +1,6 @@
---
title: Plugin Store
order: 2
---
<PluginStore />

6
docs/en/store/resource.md Executable file
View File

@ -0,0 +1,6 @@
---
title: Resource Store
order: 1
---
<ResStore />

15
docs/en/usage/agreement.md Executable file
View File

@ -0,0 +1,15 @@
---
title: 用户协议
order: 3
---
# 用户协议
1. 本项目遵循`MIT`协议,你可以自由使用,修改,分发,但是请保留原作者信息
2. 你可以选择开启`auto_report`(默认开启),轻雪会收集以下内容
- 运行环境的设备信息CPU内存系统信息及Python信息
- 插件信息(不含插件数据)
- 部分异常信息,
- 会话负载信息(不含隐私部分)
以上内容仅用于项目的优化,不包含任何隐私信息,且通过安全的方式传输到轻雪的服务器,若你不希望提供这些信息,可以在配置文件中把`auto_report`设定为`false`
3. 本项目不会收集用户的任何隐私信息,但请注意甄别第三方插件的安全性
4. 使用此项目代表你已经同意以上协议

122
docs/en/usage/basic.md Executable file
View File

@ -0,0 +1,122 @@
---
title: 基础插件
order: 1
---
# 基础插件
---
> [!tip]
> **参数**`<param>`为必填参数,`[option]`为可选参数。
>
> **命令别名**:配置了命令别名的命令可以使用别名代替原命令,例如`npm install ~`可以使用`插件 安装 ~`代替。
## **轻雪命令`liteyuki_command`**
| 命令 | 说明 | 权限 | 举例 | 可用参数 |
| :----------------------------------------: | :---------------------------------------------------------------------------------------------: | :----------------------------------------: | :---------------------------------------------------------: | :----------------------------------------------------------------------------------: |
| `reload-liteyuki` | 重载轻雪 | 超级用户 | ❌ | ❌ |
| `update-liteyuki` | 更新轻雪 | 超级用户 | ❌ | ❌ |
| `liteecho` | 查看当前bot 版本 | 超级用户 | ❌ | ❌ |
| `status` | 查看统计信息和状态 | 超级用户 | ❌ | ❌ |
| `config set <key> value` | 添加配置项,若存在则会覆盖,输入值会被执行以转换为正确的类型,"10"和10是不一样的 | 超级用户 | `config set name 'liteyuki-bot'` | `<key>`: 若存在则覆盖, 若不存在则创建于`config.yml` ; `value`: yml格式的所有合法内容 |
| `config get [key] ` | 查询配置项不带key返回配置项列表推荐私聊使用 | 超级用户 | `config get name` | `<key>`: 若存在则返回, 若不存在则返回空 |
| `switch-image-mode ` | 在普通图片和Markdown大图之间切换该功能需要commit:505468b及以后的Lagrange.OneBot默认普通图片 | 超级用户 | `switch-image-mode` | ❌ |
| `/api api_name [args] ` | 调用机器人API | 超级用户 | `/api get_group_member_list group_id=1234567` | `<args>`: 参数列表, 格式为onebot v11协议api, 可用%20代替空格 |
| `/function function_name [args] [kwargs] ` | 调用机器人函数(`.lyfunction`语法) | 超级用户 | `/function send_group_msg group_id=1234567 message='hello'` | `<args>``<kwargs>`: 参数列表, api格式为onebot v11协议api |
| group enable/disable [group_id] | 在群聊启用/停用机器人group_id仅超级用户可用 | 超级用户,群聊仅群主、管理员、超级用户可用 | `group enable 1145141919810` | `<group_id>`: 群号 |
| liteyuki-docs | 查看轻雪文档 | 所有人 | ❌ | ❌ |
---
### **命令别名**
| 命令 | 别名 |
| :---------------: | :----------------------------------: |
| status | 状态 |
| reload-liteyuki | 重启轻雪 |
| update-liteyuki | 更新轻雪 |
| reload-resources | 重载资源 |
| config | 配置, `set` 设置 / `get` 查询 |
| switch-image-mode | 切换图片模式 |
| liteyuki-docs | 轻雪文档 |
| group | 群聊, `enable` 启用 / `disable` 停用 |
---
## **插件/包管理器 `liteyuki_pacman`**
- 插件管理
| 命令 | 说明 | 权限 |
| :-----------------------------------------------------: | :----------------------------------------: | :----------------------------------------------: |
| `npm update` | 更新插件商店索引 | 超级用户 |
| `npm install <plugin_name>` | 安装插件 | 超级用户 |
| `npm uninstall <plugin_name>` | 卸载插件 | 超级用户 |
| `npm search <keywords...>` | 通过关键词搜索插件 | 超级用户 |
| `npm enable-global/disable-global <plugin_name>` | 全局启用/停用插件 | 超级用户 |
| `npm enable/disable <plugin_name> [--group <group_id>]` | 当前会话启用/停用插件 | 群聊仅群主、管理员、超级用户可用,私聊所有人可用 |
| `npm list [page] [num]` | 列出所有插件 page为页数num为每页显示数量 | 群聊仅群主、管理员、超级用户可用,私聊所有人可用 |
| `help <plugin_name>` | 查看插件帮助 | 所有人 |
- 资源包管理
| 命令 | 说明 | 权限 |
| :----------------------: | :------------------------------------------: | :------: |
| `rpm list [page] [num]` | 列出所有资源包 page为页数num为每页显示数量 | 超级用户 |
| `rpm load <pack_name>` | 加载资源包 | 超级用户 |
| `rpm unload <pack_name>` | 卸载资源包 | 超级用户 |
| `rpm change <pack_name>` | 修改优先级 | 超级用户 |
| `rpm reload` | 重载所有资源包 | 超级用户 |
### 命令别名
| 命令 | 别名 |
| :--------------: | :------: |
| `npm` | 插件管理 |
| `update` | 更新 |
| `install` | 安装 |
| `uninstall` | 卸载 |
| `search` | 搜索 |
| `enable` | 启用 |
| `disable` | 停用 |
| `enable-global` | 全局启用 |
| `disable-global` | 全局停用 |
| `rpm` | 资源包 |
| `load` | 加载 |
| `unload` | 卸载 |
| `change` | 更改 |
| `reload` | 重载 |
| `list` | 列表 |
| `help` | 帮助 |
> [!warning]
> 受限于NoneBot2钩子函数的依赖注入参数插件停用只能阻断传入响应对于主动推送的插件不生效请阅读插件主页的说明。
>
---
## **用户管理`liteyuki_user`**
| 命令 | 说明 | 权限 |
| :-------------------------: | :----------------------------: | :----: |
| `profile` | 查看用户信息菜单 | 所有人 |
| `profile set <key> [value]` | 设置用户信息或打开属性设置菜单 | 所有人 |
| `profile get <key>` | 获取用户信息 | 所有人 |
###命令别名
| 命令 | 别名 |
| :-------: | :------: |
| `profile` | 个人信息 |
| `set` | 设置 |
| `get` | 查询 |

68
docs/en/usage/extra.md Executable file
View File

@ -0,0 +1,68 @@
---
title: 功能命令
order: 2
---
# 功能插件命令
### **轻雪天气`liteyuki_weather`**
查询实时天气,支持绑定城市,支持中英文城市名,支持多个关键词查询。
配置项
```yaml
weather_key: "" # 和风天气的天气key会自动判断key版本
```
命令
```shell
weather <keywords...> # Keywords为城市名支持中英文
```
查询目标地实时天气,例如:"天气 北京 海淀", "weather Tokyo Shinjuku"
```shell
bind-city <keywords...> # Keywords为城市名支持中英文
```
绑定查询城市,个人全局生效
#### 命令别名
| 命令 | 别名 |
| :-------: | :------- |
| weather | 天气 |
| bind-city | 绑定城市 |
---
### **统计信息`liteyuki_statistics`**
统计信息
命令
```shell
statistic message --duration <duration> --period <period> --group [current|group_id] --bot [current|bot_id]
```
功能: 用于统计Bot接收到的消息, 统计周期为`period`, 统计时间范围为`duration`
| 参数 | 格式 |
| :------: | :------------------------------------------------------------: |
| duration | 使用通用日期简写: `1d`(天), `1h`(小时), `45m`(分钟), `14s`(秒) |
| period | 使用通用日期简写: `1d`(天), `1h`(小时), `45m`(分钟), `14s`(秒) |
| group | `current` (当前群聊) 或 `group_id` (QQ群号) |
| bot | `current` (当前Bot) 或 `bot_id` |
#### 命令别名
| 命令 | 别名 |
| :----------: | :---: |
| `statistic` | stat |
| `message` | m |
| `--duration` | -d |
| --period` | -p |
| `--group` | -g |
| `--bot` | -b |
| `current` | c |

20
docs/package.json Executable file
View File

@ -0,0 +1,20 @@
{
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^4.0.0",
"sass-embedded": "^1.78.0",
"vitepress": "^1.3.4",
"vitepress-sidebar": "^1.25.3"
},
"scripts": {
"docs:dev": "vitepress dev --host",
"docs:build": "vitepress build",
"docs:preview": "vitepress preview"
},
"type": "module",
"dependencies": {
"clipboard": "^2.0.11",
"vue": "^3.4.38",
"vue-route": "^1.5.1",
"vue-router": "4"
}
}

2120
docs/pnpm-lock.yaml generated Executable file

File diff suppressed because it is too large Load Diff

BIN
docs/public/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

95
docs/public/plugins.json Executable file
View File

@ -0,0 +1,95 @@
[
{
"module_name": "liteyukibot-plugin-nonebot",
"project_link": "liteyukibot-plugin-nonebot",
"name": "NoneBot插件",
"desc": "在轻雪中使用NoneBot内置轻雪--NoneBot会话控制器插件为NoneBot开发者提供了更多便捷功能(已内置)",
"author": "snowykami",
"homepage": "https://github.com/LiteyukiStudio/liteyukibot-plugin-nonebot",
"tags": [
{
"label": "app",
"color": "#aeeaa8"
}
],
"is_official": true,
"type": "application",
"valid": true,
"version": "rolling"
},
{
"module_name": "liteyukibot-plugin-antidislink",
"project_link": "liteyukibot-plugin-antidislink",
"name": "防断联插件",
"desc": "防止你的群友断联化",
"author": "snowykami",
"homepage": "https://github.com/snowykami/liteyukibot-plugin-antidislink",
"tags": [
{
"label": "app",
"color": "#aeeaa8"
},
{
"label": "dislink",
"color": "#d0e9ff"
}
],
"is_official": true,
"type": "application",
"valid": true,
"version": "rolling"
},
{
"module_name": "liteyukibot-plugin-lagrange",
"project_link": "liteyukibot-plugin-lagrange",
"name": "LagrangePlugin",
"desc": "在轻雪中使用lagrange-python",
"author": "snowykami",
"homepage": "https://github.com/snowykami/liteyukibot-plugin-lagrange",
"tags": [
{
"label": "app",
"color": "#aeeaa8"
},
{
"label": "lagrange",
"color": "#ff89f7"
}
],
"is_official": true,
"type": "application",
"valid": true,
"version": "rolling"
},
{
"module_name": "liteyukibot-plugin-htmlrender",
"project_link": "liteyukibot-plugin-htmlrender",
"name": "htmlrender",
"desc": "使用系统中的浏览器对网页进行渲染,便于其他插件使用",
"author": "EillesWan",
"homepage": "https://github.com/LiteyukiStudio/liteyukibot-plugin-htmlrender",
"tags": [
{
"label": "ch",
"color": "#4285f4"
},
{
"label": "ro",
"color": "#db4437"
},
{
"label": "mi",
"color": "#f4b400"
},
{
"label": "um",
"color": "#0f9d58"
}
],
"is_official": true,
"type": "application",
"valid": true,
"version": "rolling"
}
]

77
docs/public/resources.json Executable file
View File

@ -0,0 +1,77 @@
[
{
"name": "KawaiiStatus",
"author": "SnowyKami",
"description": "可爱的状态卡片仿照koishi的制作",
"link": "https://cdn.liteyuki.icu/static/lrp/KawaiiStatus.zip"
},
{
"name": "MiSans字体包",
"author": "SnowyKami",
"description": "小米官方字体MiSans",
"link": "https://cdn.liteyuki.icu/static/lrp/MiSansFonts.zip"
},
{
"name": "MapleMono字体包",
"author": "SnowyKami",
"description": "适用于字母的字体包",
"link": "https://cdn.liteyuki.icu/static/lrp/MapleMonoFonts.zip"
},
{
"name": "野兽先辈主题HomoTheme",
"author": "SnowyKami",
"description": "野兽先辈主题包114514",
"link": "https://cdn.liteyuki.icu/static/lrp/HomoTheme.zip"
},
{
"name": "自定义设备信息",
"author": "SnowyKami",
"description": "自定义服务端的设备信息,自行修改使用",
"link": "https://cdn.liteyuki.icu/static/lrp/custom-device.zip"
},
{
"name": "轻雪傲娇系词库",
"author": "SnowyKami",
"description": "使用https://github.com/Kyomotoi/AnimeThesaurus的词库",
"link": "https://cdn.liteyuki.icu/static/lrp/liteyuki_words_aojiao.zip"
},
{
"name": "轻雪可爱系词库",
"author": "SnowyKami",
"description": "使用https://github.com/Kyomotoi/AnimeThesaurus的词库",
"link": "https://cdn.liteyuki.icu/static/lrp/liteyuki_words_kawaii.zip"
},
{
"name": "轻雪Kakyo语言包",
"author": "Nanaloveyuki",
"description": "Liteyuki Bot的语言包用于提供多种语言的翻译。",
"link": "https://github.com/Nanaloveyuki/liteyuki-langpack/releases/download/KakyoVer/Kakyo-pack.zip"
},
{
"name": "更多背景模板包",
"author": "snowykami",
"description": "自定义各种卡片的背景",
"link": "https://cdn.liteyuki.icu/static/lrp/morebg.zip"
},
{
"name": "测试资源包",
"desc": "test",
"link": "https://cdn.liteyuki.icu/static/lrp/liteyuki_words_aojiao.zip",
"homepage": "",
"author": "snowykami"
},
{
"name": "轻雪Kakyo语言包 稳定版",
"description": "Liteyuki Bot的语言包用于提供多种语言的翻译。",
"link": "https://cdn.liteyuki.icu/static/lrp/kakyo.zip",
"homepage": "https://github.com/Nanaloveyuki/liteyuki-langpack",
"author": "Nanaloveyuki"
},
{
"name": "测试资源包2",
"description": "test",
"link": "https://cdn.liteyuki.icu/static/lrp/liteyuki_words_aojiao.zip",
"homepage": "",
"author": "snowykami"
}
]

15
docs/tsconfig.json Executable file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"components/**/*.ts",
],
"exclude": [
"node_modules"
]
}

27
docs/zh/deploy/adapter.md Normal file
View File

@ -0,0 +1,27 @@
---
title: 适配器
order: 3
---
## **示例与NoneBot对接的OneBot实现端配置**
生产环境中推荐反向WebSocket
不同的实现端给出的字段可能不同,但是基本上都是一样的,这里给出一个参考值
| 字段 | 参考值 | 说明 |
|----------------|--------------------------------|----------------------------------------------------------------------|
| 协议 | 反向 WebSocket | 推荐使用反向 WebSocket 协议进行通信,即轻雪作为服务端运行。 |
| 地址 | `ws://127.0.0.1:20216/onebot/v11/ws` | 地址取决于配置文件,本机默认为 `127.0.0.1:20216`。 |
| AccessToken | `""` | 如果你给轻雪配置了 `AccessToken`,请在此填写相同的值。 |
> **注意**:要使用其他通信方式,请访问 [OneBot Adapter](https://onebot.adapters.nonebot.dev/) 获取详细信息。
## **其他**
轻雪不局限于OneBot适配器你可以使用[NoneBot2支持的任何适配器](https://github.com/nonebot/)(链接指向nonebot的github主页)或使用轻雪讯息传递插件
例如:
- [Console Adapter](https://github.com/nonebot/adapter-console)
- [Mirai Adapter](https://github.com/nonebot/adapter-mirai)

102
docs/zh/deploy/config.md Executable file
View File

@ -0,0 +1,102 @@
---
title: 配置
order: 2
---
# 配置
## 轻雪配置文件说明
轻雪支持 `.yaml``.json``.toml` 三种文件类型作为配置文件, 您可以根据个人喜好选择使用
### 配置文件生成
首次运行轻雪后,会生成以下文件和目录结构:
```
./
├── config.yml # 默认生成的配置文件
└── config/ # 配置目录,可包含多个配置文件
└── file1.yaml # 示例配置文件1
└── file2.json # 示例配置文件2
└── file3.toml # 示例配置文件3
```
### 配置文件修改
您可以修改生成的 `config.yml` 文件或在 `config` 目录下添加新的配置文件
绝大多数情况下,您只需要修改以下字段:
- `superusers`:超级用户列表
- `nickname`:昵称配置
修改完成后,重启轻雪以应用新的配置
### 配置文件加载
启动轻雪时,会加载项目目录下以下文件和 `config` 目录下的所有配置文件:
- `config.yml`
- `config.yaml`
- `config.json`
- `config.toml`
轻雪会自动合并 `config` 目录下的所有配置文件
这意味着您可以在 `config` 目录下创建多个配置文件, 轻雪会将它们的内容合并为一个完整的配置
## 示例配置文件
### **基础配置项**
> 请注意, 文档中的配置代码是被拆分的, 实际上为一个配置文件(`config.yml`),此处仅为方便阅读拆分
**Nonebot配置**
```yaml
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 # 绑定端口
nickname: [ "liteyuki" ] # 机器人昵称列表
superusers: [ "1919810" ] # 超级用户列表
```
**Liteyuki配置**
```yaml
liteyuki:
# 写在外层的配置项将会被覆盖建议迁移到liteyuki下
log_level: "INFO" # 日志等级
log_icon: true # 是否显示日志等级图标(某些控制台字体不可用)
auto_report: true # 是否自动上报问题给轻雪服务器
auto_update: true # 是否自动更新轻雪每天4点检查更新
plugins: [ ] # 轻雪插件列表
plugin_dirs: [ ] # 轻雪插件目录列表
```
## **其他配置**
以下为默认值,如需自定义请手动添加
```yaml
# 高级NoneBot配置
nonebot:
onebot_access_token: "" # 访问令牌,对公开放时建议设置
default_language: "zh-CN" # 默认语言
alconna_auto_completion: false # alconna是否自动补全指令默认false建议开启
safe_mode: false # 安全模式开启后将不会加载任何第三方NoneBot插件
# 其他Nonebot插件的配置项
custom_config_1: "custom_value1"
custom_config_2: "custom_value2"
```
```yaml
# 开发者选项
liteyuki:
allow_update: true # 是否允许更新
debug: false # 轻雪调试开启会自动重载Bot或者资源其他插件自带的调试功能也将开启
dev_mode: false # 开发者模式,开启后将会启动监视者,监视文件变化并自动重载
# ...其他配置项...
```

58
docs/zh/deploy/fandq.md Executable file
View File

@ -0,0 +1,58 @@
---
title: 答疑
order: 4
---
# 答疑
## 常见问题
以下是一些常见问题的解答和解决方案:
### **设备上 Python 环境太乱了pip 和 python 不对应怎么办?**
请使用以下命令来安装依赖, 并启动 Bot:
```bash
/path/to/python -m pip install -r requirements.txt
/path/to/python main.py
```
其中 `/path/to/python` 是你要用来运行 Bot 的 Python 可执行文件的路径
### **更新轻雪失败,报错 `InvalidGitRepositoryError`**
请确保正确安装了 `Git` , 并使用克隆而非直接下载的方式部署轻雪
如果你已经正确安装了 `Git` 但仍然遇到问题,请尝试使用手动下载的方式来更新轻雪(这对于一些特殊的网络环境有效)
### **怎么对接聊天平台?**
Bot 部分插件提供了对接特定平台的能力, 例如, 使用 NoneBot 插件可以对接支持的[适配器平台](https://bot.liteyuki.icu/deploy/adapter.html)
### **`Playwright` 安装失败**
运行以下命令来安装浏览器:
```bash
playwright install
```
### **有的插件安装后报错无法启动**
请先查阅插件文档,确认插件必要配置项完好, 如果问题仍然存在,请联系插件作者或在安全模式下启动轻雪:
```yaml
safe_mode: true
```
在安全模式下,你可以使用以下命令卸载问题插件:
```bash
npm uninstall <plugin-name>
```
## 其他问题
如果以上解答无法解决您的问题,欢迎加入我们的 QQ 群 [775840726](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=SzmDYbfR6jY94o9KFNon7AwelRyI6M_u&authKey=ygeBdEmdFNyCWuNR4w0M1M8%2B5oDg7k%2FDfN0tzBkYcnbB%2FGHNnlVEnCIGbdftsnn7&noverify=0&group_code=775840726) 进行进一步的交流和讨论

96
docs/zh/deploy/install.md Executable file
View File

@ -0,0 +1,96 @@
---
title: 安装
order: 1
---
# 安装
## **常规部署**
### 安装基本环境
**Git 版本管理工具**
[Git](https://git-scm.com/download/)
**Python3.10+**
[Python3.10+](https://www.python.org/downloads/release/python-31010/)
### 克隆项目到本地轻雪使用Git进行版本管理该步骤为必要项
`git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1`
> 若你不能访问Github可以使用Liteyuki镜像`https://git.liteyuki.icu/bot/app`
### 切换到Bot目录下
`cd LiteyukiBot`
> 如果存在文件夹缺失报错, 尝试使用绝对路径进行路径跳转
### 创建虚拟环境
`python -m venv venv`
> 如果出现相关虚拟环境错误, 建议查询 [Python Venv](https://docs.python.org/3/library/venv.html)
### 激活虚拟环境
Windows:
`.\venv\Scripts\activate`
> 出现`'activate' 不是内部或外部命令,也不是可运行的程序或批处理文件。`错误, 请使用完整路径激活虚拟环境
Linux:
`source venv/bin/activate`
> 如果出现`source: command not found`, 请使用完整路径激活虚拟环境
### 安装依赖
`pip install -r requirements.txt`
> 若出现`ERROR: Could not open requirements file: [Errno 2] No such file or directory`错误, 请检查是否在Bot目录下执行命令
> 若出现`ERROR: Could not build wheels for xx, which is required to install pyproject.toml-based projects`错误,请尝试使用手动命令安装相关依赖(虚拟环境下执行`pip install xx`,例如`pip install Pillow`)
### 启动Bot
`python main.py`
> 若出现`ModuleNotFoundError: No module named 'xx'`错误, 请尝试重新执行安装依赖步骤
## **使用Docker构建**
```bash
docker pull ghcr.io/liteyukistudio/liteyukibot:latest # 每夜版镜像
```
> [!tip]
> Windows请使用项目绝对目录`/path/to/LiteyukiBot`代替`$(pwd)` <br>
> 若你修改了端口号请将`20216:20216`中的`20216`替换为你的端口号
## **装置要求**
- Windows系统版本推荐最低版本: `Windows 10 21H2` / `Windows Server 2019+`
>版本低于`Windows 10 21H2` 可能无法正常使用Bot, 建议升级系统版本或使用Docker部署
- Linux系统要支持Python3.10+,推荐`Ubuntu 20.04+`(~~别用你那b CentOS~~)
- CPU: 至少`1vCPU`
- 内存: Bot无其他插件会占用`300~500MB`,包括`chromium``node`等进程,其他插件占用视具体插件而定,建议`1GB`以上
- 硬盘: 至少`1GB`空间
> [!warning]
> 如果装置上有多个环境,请使用`path/to/python -m pip install -r requirements.txt`来安装依赖,`path/to/python`
> 为你的Python可执行文件路径
> [!warning]
> 轻雪的更新功能依赖Git如果你没有安装Git直接下载源代码运行你将无法使用更新功能(除非你闲的手动下载源代码更新轻雪~~)
#### 其他问题请移步至[答疑](./fandq)

21
docs/zh/dev/best_practices.md Executable file
View File

@ -0,0 +1,21 @@
---
title: 最佳实践
order: 10
---
# 最佳实践
## 机器人应用
- [LiteyukiBot](https://github.com/LiteyukiStudio/LiteyukiBot):轻雪官方机器人
- [LiteyukiBot-TriM](https://github.com/TriM-Organization/LiteyukiBot-TriM)TriM 官方定制轻雪机器人
- [Liteyuki Marsho](https://git.liteyuki.icu/LiteyukiStudio/marsho-alpha):基于 轻雪 和 github model 的可爱猫娘机器人
## 插件
- [liteyukibot-plugin-nonebot](https://github.com/LiteyukiStudio/liteyukibot-plugin-nonebot):轻雪机器人 NoneBot 插件,让轻雪支持 NoneBot
- [nonebot-plugin-liteyukibot](https://github.com/LiteyukiStudio/nonebot-plugin-liteyukibot)NoneBot 插件,让 NoneBot 支持轻雪
## 其他
- [liteyuki starmap](https://starmap.liteyuki.icu):轻雪官方星图,展示轻雪的所有实例及其位置分布
- [TRSS_Liteyuki](https://timerainstarsky.github.io/TRSS_Liteyuki/)TRSS LiteyukiBot 管理脚本
- [litedoc](https://github.com/LiteyukiStudio/litedoc)轻雪API文档生成器
- liteyukibot-api (闭源):轻雪机器人统计接口

97
docs/zh/dev/comm.md Executable file
View File

@ -0,0 +1,97 @@
---
title: 进程通信
order: 4
---
# **通道通信**
### 简介
轻雪运行在主进程 MainProcess 里,有部分实现插件为了一些功能在子进程中运行,这样两个进程上下文是不会互相干扰的,因此无法通过共享内存和直接对象传递进行通信。
例如子进程接收到用户信息需要重启机器人,这时可以通过通道对主进程发送消息,主进程接收到消息后重启对应子进程。
### 示例
通道是全双工的,有两种接收模式,但一个通道只能使用一种,即被动模式和主动模式,被动模式由`chan.on_receive()`装饰回调函数实现,主动模式需调用`chan.receive()`实现
- 创建子进程的同时会初始化一个被动通道和一个主动通道,且通道标识为`{process_name}-active``{process_name}-passive`
- 主进程中通过`get_channel`函数获取通道对象
- 子进程中导入单例`active_channel``passive_channel`即可
> 在轻雪插件中(主进程中)
```python
import asyncio
from liteyuki.comm import get_channel, Channel
from liteyuki import get_bot
# get_channel函数获取通道对象参数为调用set_channel时的通道标识
channel_passive = get_channel("nonebot-passive") # 获取被动通道
channel_active = get_channel("nonebot-active") # 获取主动通道
liteyuki_bot = get_bot()
# 注册一个函数在轻雪启动后运行
@liteyuki_bot.on_after_start
async def send_data():
while True:
channel_passive.send("I am liteyuki main process passive")
channel_active.send("I am liteyuki main process active")
await asyncio.sleep(3) # 每3秒发送一次消息
```
> 在子进程中例如NoneBot插件中
```python
from nonebot import get_driver
from liteyuki.comm import active_channel, passive_channel # 子进程中获取通道直接导入进程全局单例即可
from liteyuki.log import logger
driver = get_driver()
# 被动模式,通过装饰器注册一个函数在接收到消息时运行,每次接收到字符串数据时都会运行
@passive_channel.on_receive(filter_func=lambda data: isinstance(data, str))
async def on_passive_receive(data):
logger.info(f"Passive receive: {data}")
# 注册一个函数在NoneBot启动后运行
@driver.on_startup
def on_startup():
while True:
data = active_channel.receive()
logger.info(f"Active receive: {data}")
```
> 启动后控制台输出
```log
0000-00-00 00:00:00 [ℹ️信息] Passive receive: I am liteyuki main process passive
0000-00-00 00:00:00 [ℹ️信息] Active receive: I am liteyuki main process active
0000-00-00 00:00:03 [ℹ️信息] Passive receive: I am liteyuki main process passive
0000-00-00 00:00:03 [ℹ️信息] Active receive: I am liteyuki main process active
...
```
## **共享内存通信**
### 简介
- 相比于普通进程通信,内存共享使得代码编写更加简洁,轻雪框架提供了一个内存共享通信的接口,你可以通过`storage`模块实现内存共享通信,该模块封装通道实现
- 内存共享是线程安全的,你可以在多个线程中读写共享内存,线程锁会自动保护共享内存的读写操作
### 示例
> 在任意进程中均可使用
```python
from liteyuki.comm.storage import shared_memory
shared_memory.set("key", "value") # 设置共享内存
value = shared_memory.get("key") # 获取共享内存
```
源代码:[liteyuki/comm/storage.py](https://github.com/LiteyukiStudio/LiteyukiBot/blob/main/liteyuki/comm/storage.py)

71
docs/zh/dev/guide.md Executable file
View File

@ -0,0 +1,71 @@
---
title: 开发指南
order: 0
---
<script setup>
import ContributorBar from '../../components/ContributorBar.vue'
</script>
# 开发指南
## 如何开发
插件开发无需阅读本文档,请阅读[插件开发文档](./plugin)和[API 引用](./api/)。
如需往轻雪仓库提交代码,请阅读以下内容:
1. 首先[fork](https://github.com/LiteyukiStudio/LiteyukiBot/fork)一份轻雪仓库到你的个人/组织账户下。
2. 在你的仓库中进行开发。
3. 在你的仓库中创建一个新的分支,将你的代码提交到这个分支。
4. 在你的仓库中创建一个Pull Request将你的分支合并到轻雪仓库的`main`分支。
参与开发默认你已经了解Python语言和轻雪框架的基本使用方法如果是文档相关的开发请确保你了解Markdown语法和基本前端知识。
出现冲突请与仓库维护者联系。
### 建议
- 开发过程中可以使用`mypy`, `flake8`, `black`等工具进行代码检查和格式化。
- 启用开发者模式,可以在`config.yml`中设置`dev_mode: true`,这样可以在控制台看到更多的调试信息。
## 项目结构
- `main.py`: 机器人入口文件
- `liteyuki`: 框架目录liteyukibot
- `src`: 机器人源码目录
- `liteyuki_plugins`: 轻雪插件目录
- `nonebot_plugins`: Nonebot插件目录
- `resources`: 内置资源包目录
- `utils`: 工具目录
- `tests`: 单元测试目录
- `docs`: 文档目录
- `en`: 英文文档
- `zh`: 中文文档
- `docker`: Docker相关内容目录
其中,`liteyuki`框架是包含在`LiteyukiBot`应用中的,所以此项目既是`LiteyukiBot`应用仓库,同时也是`liteyuki`框架的仓库
`src`目录下为应用程序部分,业务逻辑请在此目录下进行开发,`liteyuki_plugins``nonebot_plugins`目录下为插件目录,插件开发请在此目录下进行开发。
## 规范化
- 代码请遵循[`PEP8`](https://pep8.org/)和[`Google Python Style Guide`](https://google.github.io/styleguide/pyguide.html)
- 提交到轻雪仓库的代码,请遵循以下规范:
- 请确保代码是可运行的,没有危害的。
- 请确保代码的类型提示是正确的。
- 请确保注释风格为[`Google Docstring`](https://google.github.io/styleguide/pyguide.html)或[`Liteyuki Docstring`](https://github.com/LiteyukiStudio/litedoc?tab=readme-ov-file#liteyuki-docstring)(推荐)以保证Litedoc能够正确解析并生成文档。
- 字符串请使用双引号`"`,尽量避免使用单引号`'`,但在嵌套字符串时可以使用单引号。
- 若有面向普通用户部分,请确保文档是完善的(每种语言都有对应的文档)。
- commit message请遵循以下规范
- 应在每次完成一个功能或修复一个bug后提交代码不要将多个功能或多个bug的代码混在一起提交。
- 我们使用gitmoji来标记commit的类型`:sparkles:`表示引入新功能,`:bug:`表示修复bug等具体请参考[gitmoji](https://gitmoji.dev/)
- commit message的格式为`<emoji> [type:] <message>`,如`:sparkles: feat: 给event添加新字段`
其中`type`字段为commit类型且**可选**message字段为简短的描述总结来说就是你干了什么。
- 不限制commit message的语言有条件可以使用中英双语。
- 文档请遵循[`Markdown`](https://www.markdownguide.org/)语法并且支持vitepress相关内容
- 修订文档时,每个语言的文档都要修订。
- 请确保文档内的链接是正确的,不要出现无法访问的死链接。
- 请确保**用户文档**是通俗易懂的,**开发文档**是详细的。
## 最后
- 本项目是一个非盈利的开源项目,我们欢迎任何人参与开发,你的贡献将会使轻雪变得更好。
<ContributorBar />

72
docs/zh/dev/lyfunc.md Executable file
View File

@ -0,0 +1,72 @@
---
title: 轻雪函数
order: 2
---
# **轻雪函数**
轻雪函数 Liteyuki Function 是轻雪的一个功能它允许你在轻雪中运行一些自定义的由数据驱动的命令类似于Minecraft的mcfunction属于资源包的一部分但需单独起篇幅.
### **函数文件**
函数文件放在资源包的`functions`目录下,文件名以`.mcfunction` `.lyfunction` `.lyf`结尾,例如`test.mcfunction`,文件内容为一系列的命令,每行一个命令,支持单行注释`#`(编辑时的语法高亮可采取`shell`格式),例如:
```shell
# 在发信器输出"hello world"
cmd echo hello world
# 如果你想同时输出多行内容可以尝试换行符(Python格式)
cmd echo hello world\nLiteyuki bot
```
也支持句末注释,例如:
```shell
cmd echo hello world # 输出"hello world"
```
### **命令文档**
```shell
var <var1=value1> [var2=value2] ... # 定义变量
cmd <command> # 在设备上执行命令
api <api_name> [var=value...] # 调用Bot API
function <func_name> # 调用函数,可递归
sleep <time> # 异步等待单位s
nohup <command> # 使用新的task执行命令即不等待
end # 结束函数关键字包括子task
await # 等待所有异步任务结束若函数中启动了其他task需要在最后调用否则task对象会被销毁
```
#### **示例**
```shell
# 疯狂戳好友
# 使用 /function poke user_id=123456 执行
# 每隔0.2s戳两次,无限戳,会触发最大递归深度限制
# 若要戳20s后停止则需要删除await添加sleep 20和end
api friend_poke user_id=user_id
api friend_poke user_id=user_id
sleep 0.2
nohup function poke
await
```
### **API**
理论上所有基于onebotv11的api都可调用不同Adapter api也有差别.
[Onebot v11 API文档](https://283375.github.io/onebot_v11_vitepress/api/index.html)
### **结束关键字**
由于LiteyukiBot基于异步运行, 所以在编写lyfunction时也要注意异步的调用避免出现"单线程走到底"的情况是效率提升的关键.
`await` 异步任务结束关键字用于结束当前已完成function的执行
> [!warning]
> 但若出现非单function的情况有一个task任务没有完成而await被执行了那么当前所有函数包的task都会被截停销毁
> [!tip]
> 编写轻雪函数推荐你使用VS Code插件[Liteyuki Function](https://github.com/LiteyukiStudio/lyfunctionTextmate)实现语法高亮

90
docs/zh/dev/plugin.md Executable file
View File

@ -0,0 +1,90 @@
---
title: 插件开发
order: 3
---
# 简介
轻雪插件是轻雪内置的一部分功能,运行在主进程中,可以很高程度地扩展轻雪的功能
插件大致可分为应用(Application)、实现(Implementation)及服务(Service)等几种类型,大部分情况下一个插件通常承担着多个责任,可按需调整
应用:从总线通道接收到消息后进行处理,响应,以实现某些功能,例如`echo`
实现:对接特定平台,把平台的消息转换为轻雪消息格式传入总线通道
服务提供一系列对外的ipc/rpc/http等服务供其他插件调用
我们鼓励使用`magicoca`进行对象传递来进行插件间通信而不是依赖关系,这样可以避免很多潜在的问题。
## 开始
### 创建插件
一个`.py`文件或一个包含`__init__.py`的文件夹即可被识别为插件
首先创建一个文件夹,例如`watchdog_plugin`,并在其中创建一个`__init__.py`文件,即可创建一个插件
`__init__.py`
```python
from liteyuki.plugin import PluginMetadata, PluginType
from .watch_dog import * # 导入逻辑部分
# 定义插件元数据
__plugin_meta__ = PluginMetadata(
name="NoneDog", # 插件名称
version="1.0.0", # 插件版本
description="A simple plugin for nonebot developer", # 插件描述
type=PluginType.SERVICE # 插件类型
)
# 你的插件代码
...
```
### 编写逻辑部分
轻雪主进程不涉及聊天部分,因此插件主要是一些后台任务或者与聊天机器人的通信
以下我们会编写一个简单的插件用于开发NoneBot时进行文件系统变更重载
`watch_dog.py`
```python
import os
from liteyuki.dev import observer # 导入文件系统观察器
from liteyuki import get_bot, logger # 导入轻雪Bot和日志
from watchdog.events import FileSystemEvent # 导入文件系统事件
liteyuki = get_bot() # 获取唯一的轻雪Bot实例
exclude_extensions = (".pyc", ".pyo") # 排除的文件扩展名
# 用observer的on_file_system_event装饰器监听文件系统事件
@observer.on_file_system_event(
directories=("src/nonebot_plugins",),
event_filter=lambda event: not event.src_path.endswith(exclude_extensions) and ("__pycache__" not in event.src_path) and os.path.isfile(event.src_path)
)
def restart_nonebot_process(event: FileSystemEvent):
logger.debug(f"File {event.src_path} changed, reloading nonebot...")
liteyuki.restart_process("nonebot") # 调用重启进程方法
```
### 加载插件
#### 方法1
- 在配置文件中的`liteyuki.plugins`中添加你的插件路径,例如`watchdog_plugin`,重启轻雪即可加载插件。
#### 方法2
- 使用开发工具快速运行插件,无需手动创建实例
- 创建入口文件,例如`main.py`,并在其中写入以下代码
```python
from liteyuki.dev.plugin import run_plugins
run_plugins("watchdog_plugin")
```
然后运行`python main.py`即可启动插件
启用插件后我们在src/nonebot_plugins下创建一个文件例如`test.py`并在其中写入一些代码保存后轻雪会自动重载NoneBot进程

51
docs/zh/dev/resource.md Executable file
View File

@ -0,0 +1,51 @@
---
title: 资源包开发
order: 1
---
# 简介
资源包,亦可根据用途称为主题包、字体包、语言包等,它允许你一定程度上自定义轻雪的外观,并且不用修改源代码
- [资源/主题商店](../store/resource)提供了一些资源包供你选择,你也可以自己制作资源包
- 资源包的制作很简单,如果你接触过`Minecraft`的资源包,那么你能够很快就上手,仅需按照原有路径进行文件替换即可,讲起打包成一个新的资源包。
- 部分内容制作需要一点点前端基础,例如`html``css`
- 轻雪原版资源包请查看`LiteyukiBot/liteyuki/resources`,可以在此基础上进行修改
- 欢迎各位投稿资源包到轻雪资源商店
请注意主题包中的html渲染使用Js来规定数据的渲染位置请确保您所编写的html代码能被Bot解析否则会导致渲染失败或渲染结果不理想/异常/错位等无法预料的事情发生。推荐在编写html时同时更改对应Js代码以避免出现无法预料的问题。
---
## 加载资源包
- 资源包通常是以`.zip`格式压缩的,只需要将其解压到根目录`resources`目录下即可,注意不要嵌套文件夹,正常的路径应该是这样的
```shell
main.py
resources
└─resource_pack_1
├─metadata.yml
├─templates
└───...
└─resource_pack_2
├─metadata.yml
└─...
```
- 你自己制作的资源包也应该遵循这个规则,并且应该在`metadata.yml`中填写一些信息
- 若没有`metadata.yml`文件,则该文件夹不会被识别为资源包
```yaml
name: "资源包名称"
version: "1.0.0"
description: "资源包描述"
# 你可以自定义一些信息,但请保证以上三个字段
...
```
- 资源包加载遵循一个优先级即后加载的资源包会覆盖前面的资源包例如你在A包中定义了一个`index.html`文件B包也定义了一个`index.html`文件那么加载B包后A包中的`index.html`文件会被覆盖
- 对于不同资源包的不同文件是可以相对引用的例如你在A中定义了`templates/index.html`在B中定义了`templates/style.css`可以在A的`index.html`中用`./style.css`相对路径引用B中的css
> [!tip]
> 资源包的结构会随着轻雪的更新而有变动,第三方资源包开发者需要注意版本兼容性,同时用户也应该自行选择可用的资源包

63
docs/zh/index.md Executable file
View File

@ -0,0 +1,63 @@
---
layout: home
hero:
name: "轻雪机器人"
tagline: "一个综合性的聊天机器人应用及管理框架"
actions:
- theme: brand
text: 🚀 快速开始
link: ./deploy/install
- theme: alt
text: 📖 使用手册
link: ./usage/basic
- theme: alt
text: 📦 扩展
link: ./store/resource
- theme: alt
text: 🛠️ 开发
link: ./dev/guide
image:
light: https://cdn.liteyuki.icu/logos/bot.svg
dark: https://cdn.liteyuki.icu/logos/bot.svg
alt: Liteyuki Logo
features:
- title: 生态良好
icon: 🛠️
details: 基于轻雪框架原生支持任意Python Bot框架和应用程序
link: ./dev/api
- title: 插件管理
icon: 🧩
details: 使用包管理器,便捷管理插件及资源包
link: ./store/plugin
- title: 自由定制
icon: 🎨
details: 使用资源包对外观进行完全自定义
link: ./store/resource
- title: 国际化
icon: 🌐
details: 通过资源包支持多种语言
link: https://baike.baidu.com/item/i18n/6771940
- title: 简易使用
icon: ⚙️
details: 无需繁琐前期过程,开箱即用
link: ./deploy/config
- title: 超高性能
icon: 🚀
details: 500个插件2秒内启动
- title: 滚动更新
icon: ☁️
details: 让你的机器人保持最新提交
- title: 开源项目
icon: 📄
details: 项目遵循LSO LICENSE开源欢迎各位的贡献
link: https://github.com/LiteyukiStudio/LiteyukiStudioOpensourceLICENSE
---

6
docs/zh/store/plugin.md Executable file
View File

@ -0,0 +1,6 @@
---
title: 插件商店
order: 2
---
<PluginStore />

6
docs/zh/store/resource.md Executable file
View File

@ -0,0 +1,6 @@
---
title: 资源商店
order: 1
---
<ResStore />

15
docs/zh/usage/agreement.md Executable file
View File

@ -0,0 +1,15 @@
---
title: 用户协议
order: 3
---
# 用户协议
1. 本项目遵循`LSO`协议,你可以自由使用,修改,分发,但是请保留原作者信息
2. 你可以选择开启`auto_report`(默认开启),轻雪会收集以下内容
- 运行环境的设备信息CPU内存系统信息及Python信息
- 插件信息(不含插件数据)
- 部分异常信息,
- 会话负载信息(不含隐私部分)
以上内容仅用于项目的优化,不包含任何隐私信息,且通过安全的方式传输到轻雪的服务器,若你不希望提供这些信息,可以在配置文件中把`auto_report`设定为`false`
3. 本项目不会收集用户的任何隐私信息,但请注意甄别第三方插件的安全性
4. 使用此项目代表你已经同意以上协议

122
docs/zh/usage/basic.md Executable file
View File

@ -0,0 +1,122 @@
---
title: 基础插件
order: 1
---
# 基础插件
---
> [!tip]
> **参数**`<param>`为必填参数,`[option]`为可选参数。
>
> **命令别名**:配置了命令别名的命令可以使用别名代替原命令,例如`npm install ~`可以使用`插件 安装 ~`代替。
## **轻雪命令`liteyuki_command`**
| 命令 | 说明 | 权限 | 举例 | 可用参数 |
| :----------------------------------------: | :---------------------------------------------------------------------------------------------: | :----------------------------------------: | :---------------------------------------------------------: | :----------------------------------------------------------------------------------: |
| `reload-liteyuki` | 重载轻雪 | 超级用户 | ❌ | ❌ |
| `update-liteyuki` | 更新轻雪 | 超级用户 | ❌ | ❌ |
| `liteecho` | 查看当前bot 版本 | 超级用户 | ❌ | ❌ |
| `status` | 查看统计信息和状态 | 超级用户 | ❌ | ❌ |
| `config set <key> value` | 添加配置项,若存在则会覆盖,输入值会被执行以转换为正确的类型,"10"和10是不一样的 | 超级用户 | `config set name 'liteyuki-bot'` | `<key>`: 若存在则覆盖, 若不存在则创建于`config.yml` ; `value`: yml格式的所有合法内容 |
| `config get [key] ` | 查询配置项不带key返回配置项列表推荐私聊使用 | 超级用户 | `config get name` | `<key>`: 若存在则返回, 若不存在则返回空 |
| `switch-image-mode ` | 在普通图片和Markdown大图之间切换该功能需要commit:505468b及以后的Lagrange.OneBot默认普通图片 | 超级用户 | `switch-image-mode` | ❌ |
| `/api api_name [args] ` | 调用机器人API | 超级用户 | `/api get_group_member_list group_id=1234567` | `<args>`: 参数列表, 格式为onebot v11协议api, 可用%20代替空格 |
| `/function function_name [args] [kwargs] ` | 调用机器人函数(`.lyfunction`语法) | 超级用户 | `/function send_group_msg group_id=1234567 message='hello'` | `<args>``<kwargs>`: 参数列表, api格式为onebot v11协议api |
| group enable/disable [group_id] | 在群聊启用/停用机器人group_id仅超级用户可用 | 超级用户,群聊仅群主、管理员、超级用户可用 | `group enable 1145141919810` | `<group_id>`: 群号 |
| liteyuki-docs | 查看轻雪文档 | 所有人 | ❌ | ❌ |
---
### **命令别名**
| 命令 | 别名 |
| :---------------: | :----------------------------------: |
| status | 状态 |
| reload-liteyuki | 重启轻雪 |
| update-liteyuki | 更新轻雪 |
| reload-resources | 重载资源 |
| config | 配置, `set` 设置 / `get` 查询 |
| switch-image-mode | 切换图片模式 |
| liteyuki-docs | 轻雪文档 |
| group | 群聊, `enable` 启用 / `disable` 停用 |
---
## **插件/包管理器 `liteyuki_pacman`**
- 插件管理
| 命令 | 说明 | 权限 |
| :-----------------------------------------------------: | :----------------------------------------: | :----------------------------------------------: |
| `npm update` | 更新插件商店索引 | 超级用户 |
| `npm install <plugin_name>` | 安装插件 | 超级用户 |
| `npm uninstall <plugin_name>` | 卸载插件 | 超级用户 |
| `npm search <keywords...>` | 通过关键词搜索插件 | 超级用户 |
| `npm enable-global/disable-global <plugin_name>` | 全局启用/停用插件 | 超级用户 |
| `npm enable/disable <plugin_name> [--group <group_id>]` | 当前会话启用/停用插件 | 群聊仅群主、管理员、超级用户可用,私聊所有人可用 |
| `npm list [page] [num]` | 列出所有插件 page为页数num为每页显示数量 | 群聊仅群主、管理员、超级用户可用,私聊所有人可用 |
| `help <plugin_name>` | 查看插件帮助 | 所有人 |
- 资源包管理
| 命令 | 说明 | 权限 |
| :----------------------: | :------------------------------------------: | :------: |
| `rpm list [page] [num]` | 列出所有资源包 page为页数num为每页显示数量 | 超级用户 |
| `rpm load <pack_name>` | 加载资源包 | 超级用户 |
| `rpm unload <pack_name>` | 卸载资源包 | 超级用户 |
| `rpm change <pack_name>` | 修改优先级 | 超级用户 |
| `rpm reload` | 重载所有资源包 | 超级用户 |
### 命令别名
| 命令 | 别名 |
| :--------------: | :------: |
| `npm` | 插件管理 |
| `update` | 更新 |
| `install` | 安装 |
| `uninstall` | 卸载 |
| `search` | 搜索 |
| `enable` | 启用 |
| `disable` | 停用 |
| `enable-global` | 全局启用 |
| `disable-global` | 全局停用 |
| `rpm` | 资源包 |
| `load` | 加载 |
| `unload` | 卸载 |
| `change` | 更改 |
| `reload` | 重载 |
| `list` | 列表 |
| `help` | 帮助 |
> [!warning]
> 受限于NoneBot2钩子函数的依赖注入参数插件停用只能阻断传入响应对于主动推送的插件不生效请阅读插件主页的说明。
>
---
## **用户管理`liteyuki_user`**
| 命令 | 说明 | 权限 |
| :-------------------------: | :----------------------------: | :----: |
| `profile` | 查看用户信息菜单 | 所有人 |
| `profile set <key> [value]` | 设置用户信息或打开属性设置菜单 | 所有人 |
| `profile get <key>` | 获取用户信息 | 所有人 |
###命令别名
| 命令 | 别名 |
| :-------: | :------: |
| `profile` | 个人信息 |
| `set` | 设置 |
| `get` | 查询 |

68
docs/zh/usage/extra.md Executable file
View File

@ -0,0 +1,68 @@
---
title: 功能命令
order: 2
---
# 功能插件命令
### **轻雪天气`liteyuki_weather`**
查询实时天气,支持绑定城市,支持中英文城市名,支持多个关键词查询。
配置项
```yaml
weather_key: "" # 和风天气的天气key会自动判断key版本
```
命令
```shell
weather <keywords...> # Keywords为城市名支持中英文
```
查询目标地实时天气,例如:"天气 北京 海淀", "weather Tokyo Shinjuku"
```shell
bind-city <keywords...> # Keywords为城市名支持中英文
```
绑定查询城市,个人全局生效
#### 命令别名
| 命令 | 别名 |
| :-------: | :------- |
| weather | 天气 |
| bind-city | 绑定城市 |
---
### **统计信息`liteyuki_statistics`**
统计信息
命令
```shell
statistic message --duration <duration> --period <period> --group [current|group_id] --bot [current|bot_id]
```
功能: 用于统计Bot接收到的消息, 统计周期为`period`, 统计时间范围为`duration`
| 参数 | 格式 |
| :------: | :------------------------------------------------------------: |
| duration | 使用通用日期简写: `1d`(天), `1h`(小时), `45m`(分钟), `14s`(秒) |
| period | 使用通用日期简写: `1d`(天), `1h`(小时), `45m`(分钟), `14s`(秒) |
| group | `current` (当前群聊) 或 `group_id` (QQ群号) |
| bot | `current` (当前Bot) 或 `bot_id` |
#### 命令别名
| 命令 | 别名 |
| :----------: | :---: |
| `statistic` | stat |
| `message` | m |
| `--duration` | -d |
| --period` | -p |
| `--group` | -g |
| `--bot` | -b |
| `current` | c |

31
liteyuki/EN.LICENSE Executable file
View File

@ -0,0 +1,31 @@
LSO license
LiteyukiStudio Opensource license
---
Copyright © 2024 Snowykami
---
Free to grant the same license-based rights to any person or organization who obtains a copy
including but not limited to using, copying, modifying, merging, publishing, distributing, sublicenseing, and/or selling copies of the software
This software and related documentation files (hereinafter referred to as "this software") are licensed in the same way as the base, and are released in the form of open source on the Internet or other media platforms
Everyone has the right to obtain a copy and obtain permission to distribute and/or use it in the above manner
However, when obtaining a copy, it is still necessary to pay attention to the following:
- The above copyright notice and this permission notice shall be included in a copy of the Software
- When using this software and its copies, it is still necessary to maintain the same form as the original
- When using this software, you still need to disclose the copy of this software under the same license:
- Do not profit from copies of this software in a non-original license without the permission of the original author
---
The software is provided as a "copy as is" without any warranty of any kind, either express or implied:
including but not limited to the warranty of merchantability, non-infringement for specific purposes
In any case, the author or copyright owner shall not be liable for any claims, damages, or other liabilities arising from the use of the software by the author or copyright owner, whether in contract litigation, infringement litigation, or other litigation. The author and its copyright owner have the right to refuse compensation for any losses caused by the user for personal reasons

57
liteyuki/LICENSE Executable file
View File

@ -0,0 +1,57 @@
# 开源声明
MIT-LSO-AGC许可(cn)
本声明推荐Markdown格式阅读
## 版权声明
版权所有(c) 2024 Snowykami
## 开源许可声明
现授予任何人以同仓库许可的开源,包含:
本软件或本库和相关文档文件(以下简称“软件”)
在本软件或本库中不受限制,包括但不限于**非侵犯MIT-LSO-AGC许可**的:
- 使用
- 复制
- 修改
- 合并
- 发布
- 分发
- 再许可和/或受到许可的销售本软件的副本
并要求或强烈建议使用本软件或库时:
- 将上述版权声明和本许可声明包含在所有本软件或本库的副本或主要部分
---
本软件或本库按“原样”提供,不提供任何形式的、明确或隐含的,包括但不限于适销性保证,适合特定用途和非侵权性
## 责任声明
在任何情况下都不得在使用本软件或库时,在本协议许可的情况下,以损害或其他责任追责,无论是在合同诉讼、侵权行为或其他情况下,抑或是由以下原因引起:
由于或与本软件有关,或是使用,或其他交易
都与本软件,库作者无责任关系,非作者使用本软件或本库并造成任何损失的行为与作者无关
---
## 搬运声明
在前提开源许可的基础上:
**未经允许不得**搬运至商业性平台**并且**进行**付费行为或疑似未得到许可的交易行为**
**不得**在搬运本仓库至**其他私有/公有开源镜像代码托管网站**时未经允许修改**任何**关于**原库的内容**
### 包括但不限于:
- 将`github`修改为`gitcode`
- 篡改外链网址
- 修改贡献者名单
- 未经原作者允许私自占有仓库并声明为自己所有
- 未经允许修改库原先所有的开源协议许可
---

54
liteyuki/__init__.py Executable file
View File

@ -0,0 +1,54 @@
"""
---
title: liteyuki API
order: 100
---
此模块为liteyuki的框架整体
This module is the overall framework of liteyuki.
"""
from liteyuki.bot import (
LiteyukiBot,
get_bot,
get_config,
get_config_with_compat
)
from liteyuki.comm import (
Channel,
Event
)
from liteyuki.plugin import (
load_plugin,
load_plugins
)
from liteyuki.log import (
init_log,
logger
)
__all__ = [
"LiteyukiBot",
"get_bot",
"get_config",
"get_config_with_compat",
"Channel",
"Event",
"load_plugin",
"load_plugins",
"init_log",
"logger",
]
__version__ = "6.3.10" # 测试版本号
# 6.3.10
# 新增`on_command`装饰器
# 6.3.9
# 更改了on语法
# 6.3.8
# 1. 初步添加对聊天的支持
# 2. 优化了通道的性能

286
liteyuki/bot/__init__.py Executable file
View File

@ -0,0 +1,286 @@
import asyncio
import os
import platform
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
# 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",
"get_bot",
"get_config",
"get_config_with_compat",
]
class LiteyukiBot:
def __init__(self, **kwargs) -> None:
"""
初始化轻雪实例
Args:
**kwargs: 配置
"""
"""总通道"""
self.i_chan = Chan[Any]() # 外部输入通道
self.o_chan = Chan[Any]() # 外部输出通道
"""常规操作"""
print_logo()
global _BOT_INSTANCE
_BOT_INSTANCE = self # 引用
"""配置"""
self.config: dict[str, Any] = kwargs
"""初始化"""
self.init(**self.config) # 初始化
logger.info("Liteyuki is initializing...")
"""生命周期管理"""
self.lifespan = Lifespan()
self.process_manager: ProcessManager = ProcessManager(lifespan=self.lifespan)
"""事件循环"""
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
self.stop_event = threading.Event()
self.call_restart_count = 0
"""加载插件加载器"""
load_plugin("liteyuki.plugins.plugin_loader") # 加载轻雪插件
async def _run(self):
"""
启动逻辑
"""
await self.lifespan.before_start() # 启动前钩子
sub_process_manager.start_all()
await self.lifespan.after_start() # 启动后钩子
message_handler_thread([_.ctx.sub_chan for _ in sub_process_manager.processes.values()])
def run(self):
"""
外部启动接口
"""
self.process_manager.start_all()
try:
asyncio.run(self._run())
except KeyboardInterrupt:
logger.opt(colors=True).info("<y>Liteyuki is stopping...</y>")
self.stop()
logger.opt(colors=True).info("<y>Liteyuki is stopped !</y>")
def restart(self, delay: int = 0):
"""
重启轻雪本体
Args:
delay ([`int`](https%3A//docs.python.org/3/library/functions.html#int), optional): 延迟重启时间. Defaults to 0.
"""
if self.call_restart_count < 1:
executable = sys.executable
args = sys.argv
logger.info("Restarting LiteyukiBot...")
time.sleep(delay)
if platform.system() == "Windows":
cmd = "start"
elif platform.system() == "Linux":
cmd = "nohup"
elif platform.system() == "Darwin":
cmd = "open"
else:
cmd = "nohup"
self.process_manager.terminate_all()
# 进程退出后重启
threading.Thread(
target=os.system,
args=(f"{cmd} {executable} {' '.join(args)}",),
daemon=True,
).start()
sys.exit(0)
self.call_restart_count += 1
def restart_process(self, name: Optional[str] = None):
"""
停止轻雪
Args:
name ([`Optional`](https%3A//docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)]): 进程名. Defaults to None.
Returns:
"""
if name is not None:
chan_active = get_channel(f"{name}-active")
chan_active.send(1)
else:
for process_name in self.process_manager.processes:
chan_active = get_channel(f"{process_name}-active")
chan_active.send(1)
def init(self, *args, **kwargs):
"""
初始化轻雪, 自动调用
Args:
*args: 参数
**kwargs: 关键字参数
"""
self.init_logger()
def init_logger(self):
"""
初始化日志
"""
init_log(config=self.config)
def stop(self):
"""
停止轻雪
"""
self.process_manager.terminate_all()
self.stop_event.set()
def on_before_start(self, func: LIFESPAN_FUNC) -> LIFESPAN_FUNC:
"""
注册启动前的函数
Args:
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): 生命周期函数
"""
return self.lifespan.on_before_start(func)
def on_after_start(self, func: LIFESPAN_FUNC):
"""
注册启动后的函数
Args:
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): 生命周期函数
"""
return self.lifespan.on_after_start(func)
def on_after_shutdown(self, func: LIFESPAN_FUNC):
"""
注册停止后的函数未实现
Args:
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): 生命周期函数
"""
return self.lifespan.on_after_shutdown(func)
def on_before_process_shutdown(self, func: PROCESS_LIFESPAN_FUNC):
"""
注册进程停止前的函数为子进程停止时调用
Args:
func ([`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func)): 生命周期函数
Returns:
[`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func): 生命周期函数
"""
return self.lifespan.on_before_process_shutdown(func)
def on_before_process_restart(
self, func: PROCESS_LIFESPAN_FUNC
) -> PROCESS_LIFESPAN_FUNC:
"""
注册进程重启前的函数为子进程重启时调用
Args:
func ([`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func)): 生命周期函数
Returns:
[`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func): 生命周期函数
"""
return self.lifespan.on_before_process_restart(func)
def on_after_restart(self, func: LIFESPAN_FUNC):
"""
注册重启后的函数未实现
Args:
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): 生命周期函数
"""
return self.lifespan.on_after_restart(func)
_BOT_INSTANCE: LiteyukiBot | None = None
def get_bot() -> LiteyukiBot:
"""
获取轻雪实例
Returns:
[`LiteyukiBot`](#class-liteyukibot): 轻雪实例
"""
if IS_MAIN_PROCESS:
if _BOT_INSTANCE is None:
raise RuntimeError("Liteyuki instance not initialized.")
return _BOT_INSTANCE
else:
raise RuntimeError("Can't get bot instance in sub process.")
def get_config(key: str, default: Any = None) -> Any:
"""
获取配置
Args:
key ([`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): 配置键
default ([`Any`](https%3A//docs.python.org/3/library/functions.html#any), optional): 默认值. Defaults to None.
Returns:
[`Any`](https%3A//docs.python.org/3/library/functions.html#any): 配置值
"""
return get_bot().config.get(key, default)
def get_config_with_compat(
key: str, compat_keys: tuple[str], default: Any = None
) -> Any:
"""
获取配置兼容旧版本
Args:
key ([`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): 配置键
compat_keys ([`tuple`](https%3A//docs.python.org/3/library/stdtypes.html#tuple)[`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): 兼容键
default ([`Any`](https%3A//docs.python.org/3/library/functions.html#any), optional): 默认值. Defaults to None.
Returns:
[`Any`](https%3A//docs.python.org/3/library/functions.html#any): 配置值
"""
if key in get_bot().config:
return get_bot().config[key]
for compat_key in compat_keys:
if compat_key in get_bot().config:
logger.warning(
f'Config key "{compat_key}" will be deprecated, use "{key}" instead.'
)
return get_bot().config[compat_key]
return default
def print_logo():
"""@litedoc-hide"""
print(
"\033[34m"
+ r"""
__ ______ ________ ________ __ __ __ __ __ __ ______
/ | / |/ |/ |/ \ / |/ | / |/ | / |/ |
$$ | $$$$$$/ $$$$$$$$/ $$$$$$$$/ $$ \ /$$/ $$ | $$ |$$ | /$$/ $$$$$$/
$$ | $$ | $$ | $$ |__ $$ \/$$/ $$ | $$ |$$ |/$$/ $$ |
$$ | $$ | $$ | $$ | $$ $$/ $$ | $$ |$$ $$< $$ |
$$ | $$ | $$ | $$$$$/ $$$$/ $$ | $$ |$$$$$ \ $$ |
$$ |_____ _$$ |_ $$ | $$ |_____ $$ | $$ \__$$ |$$ |$$ \ _$$ |_
$$ |/ $$ | $$ | $$ | $$ | $$ $$/ $$ | $$ |/ $$ |
$$$$$$$$/ $$$$$$/ $$/ $$$$$$$$/ $$/ $$$$$$/ $$/ $$/ $$$$$$/
"""
+ "\033[0m"
)

159
liteyuki/bot/lifespan.py Executable file
View File

@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
@Time : 2024/7/23 下午8:24
@Author : snowykami
@Email : snowykami@outlook.com
@File : lifespan.py
@Software: PyCharm
"""
import asyncio
from typing import Any, Awaitable, Callable, TypeAlias, Sequence
from liteyuki.log import logger
from liteyuki.utils import is_coroutine_callable, async_wrapper
SYNC_LIFESPAN_FUNC: TypeAlias = Callable[[], Any] # 同步生命周期函数
ASYNC_LIFESPAN_FUNC: TypeAlias = Callable[[], Awaitable[Any]] # 异步生命周期函数
LIFESPAN_FUNC: TypeAlias = SYNC_LIFESPAN_FUNC | ASYNC_LIFESPAN_FUNC # 生命周期函数
SYNC_PROCESS_LIFESPAN_FUNC: TypeAlias = Callable[[str], Any] # 同步进程生命周期函数
ASYNC_PROCESS_LIFESPAN_FUNC: TypeAlias = Callable[[str], Awaitable[Any]] # 异步进程生命周期函数
PROCESS_LIFESPAN_FUNC: TypeAlias = SYNC_PROCESS_LIFESPAN_FUNC | ASYNC_PROCESS_LIFESPAN_FUNC # 进程函数
class Lifespan:
def __init__(self) -> None:
"""
轻雪生命周期管理启动停止重启
"""
self.life_flag: int = 0
self._before_start_funcs: list[LIFESPAN_FUNC] = []
self._after_start_funcs: list[LIFESPAN_FUNC] = []
self._before_process_shutdown_funcs: list[PROCESS_LIFESPAN_FUNC] = []
self._after_shutdown_funcs: list[LIFESPAN_FUNC] = []
self._before_process_restart_funcs: list[PROCESS_LIFESPAN_FUNC] = []
self._after_restart_funcs: list[LIFESPAN_FUNC] = []
@staticmethod
async def run_funcs(funcs: Sequence[LIFESPAN_FUNC | PROCESS_LIFESPAN_FUNC], *args, **kwargs) -> None:
"""
并发运行异步函数
Args:
funcs ([`Sequence`](https%3A//docs.python.org/3/library/typing.html#typing.Sequence)[[`ASYNC_LIFESPAN_FUNC`](#var-lifespan-func) | [`PROCESS_LIFESPAN_FUNC`](#var-process-lifespan-func)]): 函数列表
Returns:
"""
tasks = [func(*args, **kwargs) if is_coroutine_callable(func) else async_wrapper(func)(*args, **kwargs) for func in funcs]
await asyncio.gather(*tasks)
def on_before_start(self, func: LIFESPAN_FUNC) -> LIFESPAN_FUNC:
"""
注册启动时的函数
Args:
func ([`LIFESPAN_FUNC`](#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](#var-lifespan-func): 生命周期函数
"""
self._before_start_funcs.append(func)
return func
def on_after_start(self, func: LIFESPAN_FUNC) -> LIFESPAN_FUNC:
"""
注册启动时的函数
Args:
func ([`LIFESPAN_FUNC`](#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](#var-lifespan-func): 生命周期函数
"""
self._after_start_funcs.append(func)
return func
def on_before_process_shutdown(self, func: PROCESS_LIFESPAN_FUNC) -> PROCESS_LIFESPAN_FUNC:
"""
注册进程停止前的函数
Args:
func ([`PROCESS_LIFESPAN_FUNC`](#var-process-lifespan-func)): 进程生命周期函数
Returns:
[`PROCESS_LIFESPAN_FUNC`](#var-process-lifespan-func): 进程生命周期函数
"""
self._before_process_shutdown_funcs.append(func)
return func
def on_after_shutdown(self, func: LIFESPAN_FUNC) -> LIFESPAN_FUNC:
"""
注册停止后的函数
Args:
func ([`LIFESPAN_FUNC`](#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](#var-lifespan-func): 生命周期函数
"""
self._after_shutdown_funcs.append(func)
return func
def on_before_process_restart(self, func: PROCESS_LIFESPAN_FUNC) -> PROCESS_LIFESPAN_FUNC:
"""
注册进程重启前的函数
Args:
func ([`PROCESS_LIFESPAN_FUNC`](#var-process-lifespan-func)): 进程生命周期函数
Returns:
[`PROCESS_LIFESPAN_FUNC`](#var-process-lifespan-func): 进程生命周期函数
"""
self._before_process_restart_funcs.append(func)
return func
def on_after_restart(self, func: LIFESPAN_FUNC) -> LIFESPAN_FUNC:
"""
注册重启后的函数
Args:
func ([`LIFESPAN_FUNC`](#var-lifespan-func)): 生命周期函数
Returns:
[`LIFESPAN_FUNC`](#var-lifespan-func): 生命周期函数
"""
self._after_restart_funcs.append(func)
return func
async def before_start(self) -> None:
"""
启动前钩子
"""
logger.debug("Running before_start functions")
await self.run_funcs(self._before_start_funcs)
async def after_start(self) -> None:
"""
启动后钩子
"""
logger.debug("Running after_start functions")
await self.run_funcs(self._after_start_funcs)
async def before_process_shutdown(self, *args, **kwargs) -> None:
"""
停止前钩子
"""
logger.debug("Running before_shutdown functions")
await self.run_funcs(self._before_process_shutdown_funcs, *args, **kwargs)
async def after_shutdown(self) -> None:
"""
停止后钩子 未实现
"""
logger.debug("Running after_shutdown functions")
await self.run_funcs(self._after_shutdown_funcs)
async def before_process_restart(self, *args, **kwargs) -> None:
"""
重启前钩子
"""
logger.debug("Running before_restart functions")
await self.run_funcs(self._before_process_restart_funcs, *args, **kwargs)
async def after_restart(self) -> None:
"""
重启后钩子 未实现
"""
logger.debug("Running after_restart functions")
await self.run_funcs(self._after_restart_funcs)

38
liteyuki/comm/__init__.py Executable file
View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
"""
该模块用于轻雪主进程和Nonebot子进程之间的通信
依赖关系
event -> _
storage -> channel_
rpc -> channel_, storage
"""
from liteyuki.comm.channel import (
Channel,
get_channel,
set_channel,
set_channels,
get_channels,
active_channel,
passive_channel
)
from liteyuki.comm.event import Event
__all__ = [
"Channel",
"Event",
"get_channel",
"set_channel",
"set_channels",
"get_channels",
"active_channel",
"passive_channel"
]
from liteyuki.utils import IS_MAIN_PROCESS
# 第一次引用必定为赋值
_ref_count = 0
if not IS_MAIN_PROCESS:
if (active_channel is None or passive_channel is None) and _ref_count > 0:
raise RuntimeError("Error: Channel not initialized in sub process")
_ref_count += 1

327
liteyuki/comm/channel.py Executable file
View File

@ -0,0 +1,327 @@
# -*- coding: utf-8 -*-
"""
本模块定义了一个通用的通道类用于进程间通信
"""
import asyncio
from multiprocessing import Pipe
from typing import (
Any,
Callable,
Coroutine,
Generic,
Optional,
TypeAlias,
TypeVar,
get_args,
)
from liteyuki.log import logger
from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable
T = TypeVar("T")
SYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Any] # 同步接收函数
ASYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[
[T], Coroutine[Any, Any, Any]
] # 异步接收函数
ON_RECEIVE_FUNC: TypeAlias = SYNC_ON_RECEIVE_FUNC | ASYNC_ON_RECEIVE_FUNC # 接收函数
SYNC_FILTER_FUNC: TypeAlias = Callable[[T], bool] # 同步过滤函数
ASYNC_FILTER_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, bool]] # 异步过滤函数
FILTER_FUNC: TypeAlias = SYNC_FILTER_FUNC | ASYNC_FILTER_FUNC # 过滤函数
_func_id: int = 0
_channel: dict[str, "Channel"] = {}
_callback_funcs: dict[int, ON_RECEIVE_FUNC] = {}
class Channel(Generic[T]):
"""
通道类可以在进程间和进程内通信双向但同时只能有一个发送者和一个接收者
有两种接收工作方式但是只能选择一种主动接收和被动接收主动接收使用 `receive` 方法被动接收使用 `on_receive` 装饰器
"""
def __init__(self, name: str, type_check: Optional[bool] = None):
"""
初始化通道
Args:
name: 通道ID
type_check: 是否开启类型检查, 若为空则传入泛型默认开启否则默认关闭
"""
self.conn_send, self.conn_recv = Pipe()
self._conn_send_inner, self._conn_recv_inner = (
Pipe()
) # 内部通道,用于子进程通信
self._closed = False
self._on_main_receive_func_ids: list[int] = []
self._on_sub_receive_func_ids: list[int] = []
self.name: str = name
self.is_receive_loop_running = False
if type_check is None:
# 若传入泛型则默认开启类型检查
type_check = self._get_generic_type() is not None
elif type_check:
if self._get_generic_type() is None:
raise TypeError("Type hint is required for enforcing type check.")
self.type_check = type_check
if name in _channel:
raise ValueError(f"Channel {name} already exists")
if IS_MAIN_PROCESS:
if name in _channel:
raise ValueError(f"Channel {name} already exists")
_channel[name] = self
def _get_generic_type(self) -> Optional[type]:
"""
获取通道传递泛型类型
Returns:
Optional[type]: 泛型类型
"""
if hasattr(self, "__orig_class__"):
return get_args(self.__orig_class__)[0]
return None
def _validate_structure(self, data: Any, structure: type) -> bool:
"""
验证数据结构
Args:
data: 数据
structure: 结构
Returns:
bool: 是否通过验证
"""
if isinstance(structure, type):
return isinstance(data, structure)
elif isinstance(structure, tuple):
if not isinstance(data, tuple) or len(data) != len(structure):
return False
return all(self._validate_structure(d, s) for d, s in zip(data, structure))
elif isinstance(structure, list):
if not isinstance(data, list):
return False
return all(self._validate_structure(d, structure[0]) for d in data)
elif isinstance(structure, dict):
if not isinstance(data, dict):
return False
return all(
k in data and self._validate_structure(data[k], structure[k])
for k in structure
)
return False
def __str__(self):
return f"Channel({self.name})"
def send(self, data: T):
"""
发送数据发送函数为同步函数没有异步的必要
Args:
data (T): 数据
"""
if self.type_check:
_type = self._get_generic_type()
if _type is not None and not self._validate_structure(data, _type):
raise TypeError(
f"Data must be an instance of {_type}, {type(data)} found"
)
if self._closed:
raise RuntimeError("Cannot send to a closed channel")
self.conn_send.send(data)
def receive(self) -> T:
"""
同步接收数据会阻塞线程
Returns:
T: 数据
"""
if self._closed:
raise RuntimeError("Cannot receive from a closed channel")
while True:
data = self.conn_recv.recv()
return data
async def async_receive(self) -> T:
"""
异步接收数据会挂起等待
Returns:
T: 数据
"""
loop = asyncio.get_running_loop()
data = await loop.run_in_executor(None, self.receive)
return data
def on_receive(
self, filter_func: Optional[FILTER_FUNC] = None
) -> Callable[[Callable[[T], Any]], Callable[[T], Any]]:
"""
接收数据并执行函数
Args:
filter_func ([`Optional`](https%3A//docs.python.org/3/library/typing.html#typing.Optional)[[`FILTER_FUNC`](#var-FILTER_FUNC)], optional): 过滤函数. Defaults to None.
Returns:
Callable[[Callable[[T], Any]], Callable[[T], Any]]: 装饰器
"""
if not IS_MAIN_PROCESS:
raise RuntimeError("on_receive can only be used in main process")
def decorator(func: Callable[[T], Any]) -> Callable[[T], Any]:
global _func_id
async def wrapper(data: T) -> Any:
if filter_func is not None:
if is_coroutine_callable(filter_func):
if not (await filter_func(data)): # type: ignore
return
else:
if not filter_func(data):
return
if is_coroutine_callable(func):
return await func(data)
else:
return func(data)
_callback_funcs[_func_id] = wrapper
if IS_MAIN_PROCESS:
self._on_main_receive_func_ids.append(_func_id)
else:
self._on_sub_receive_func_ids.append(_func_id)
_func_id += 1
return func
return decorator
async def _run_on_receive_funcs(self, data: Any):
"""
运行接收函数
Args:
data: 数据
"""
if IS_MAIN_PROCESS:
[
asyncio.create_task(_callback_funcs[func_id](data))
for func_id in self._on_main_receive_func_ids
]
else:
[
asyncio.create_task(_callback_funcs[func_id](data))
for func_id in self._on_sub_receive_func_ids
]
"""子进程可用的主动和被动通道"""
active_channel: Channel = Channel(name="active_channel") # 主动通道
passive_channel: Channel = Channel(name="passive_channel") # 被动通道
publish_channel: Channel[tuple[str, dict[str, Any]]] = Channel(
name="publish_channel"
) # 发布通道
"""通道传递通道,主进程创建单例,子进程初始化时实例化"""
channel_deliver_active_channel: Channel[Channel[Any]] # 主动通道传递通道
channel_deliver_passive_channel: Channel[tuple[str, dict[str, Any]]] # 被动通道传递通道
if IS_MAIN_PROCESS:
channel_deliver_active_channel = Channel(
name="channel_deliver_active_channel"
) # 主动通道传递通道
channel_deliver_passive_channel = Channel(
name="channel_deliver_passive_channel"
) # 被动通道传递通道
@channel_deliver_passive_channel.on_receive(
filter_func=lambda data: data[0] == "set_channel"
)
def on_set_channel(data: tuple[str, dict[str, Any]]):
name, channel = data[1]["name"], data[1]["channel_"]
set_channel(name, channel)
@channel_deliver_passive_channel.on_receive(
filter_func=lambda data: data[0] == "get_channel"
)
def on_get_channel(data: tuple[str, dict[str, Any]]):
name, recv_chan = data[1]["name"], data[1]["recv_chan"]
recv_chan.send(get_channel(name))
@channel_deliver_passive_channel.on_receive(
filter_func=lambda data: data[0] == "get_channels"
)
def on_get_channels(data: tuple[str, dict[str, Any]]):
recv_chan = data[1]["recv_chan"]
recv_chan.send(get_channels())
def set_channel(name: str, channel: "Channel"):
"""
设置通道实例
Args:
name ([`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): 通道名称
channel ([`Channel`](#class-channel-generic-t)): 通道实例
"""
if not isinstance(channel, Channel):
raise TypeError(
f"channel_ must be an instance of Channel, {type(channel)} found"
)
if IS_MAIN_PROCESS:
if name in _channel:
raise ValueError(f"Channel {name} already exists")
_channel[name] = channel
else:
# 请求主进程设置通道
channel_deliver_passive_channel.send(
(
"set_channel",
{
"name": name,
"channel_": channel,
},
)
)
def set_channels(channels: dict[str, "Channel"]):
"""
设置通道实例
Args:
channels ([`dict`](https%3A//docs.python.org/3/library/stdtypes.html#dict)[[`str`](https%3A//docs.python.org/3/library/stdtypes.html#str), [`Channel`](#class-channel-generic-t)]): 通道实例
"""
for name, channel in channels.items():
set_channel(name, channel)
def get_channel(name: str) -> "Channel":
"""
获取通道实例
Args:
name ([`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): 通道名称
Returns:
[`Channel`](#class-channel-generic-t): 通道实例
"""
if IS_MAIN_PROCESS:
return _channel[name]
else:
recv_chan = Channel[Channel[Any]]("recv_chan")
channel_deliver_passive_channel.send(
("get_channel", {"name": name, "recv_chan": recv_chan})
)
return recv_chan.receive()
def get_channels() -> dict[str, "Channel"]:
"""
获取通道实例们
Returns:
[`dict`](https%3A//docs.python.org/3/library/stdtypes.html#dict)[[`str`](https%3A//docs.python.org/3/library/stdtypes.html#str), [`Channel`](#class-channel-generic-t)]: 通道实例
"""
if IS_MAIN_PROCESS:
return _channel
else:
recv_chan = Channel[dict[str, Channel[Any]]]("recv_chan")
channel_deliver_passive_channel.send(("get_channels", {"recv_chan": recv_chan}))
return recv_chan.receive()

15
liteyuki/comm/event.py Executable file
View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
"""
本模块用于轻雪主进程和子进程之间的通信的事件类
"""
from typing import Any
class Event:
"""
事件类
"""
def __init__(self, name: str, data: dict[str, Any]):
self.name = name
self.data = data

271
liteyuki/comm/storage.py Executable file
View File

@ -0,0 +1,271 @@
# -*- coding: utf-8 -*-
"""
共享内存模块类似于redis但是更加轻量级并且线程安全
"""
import asyncio
import threading
from typing import Any, Callable, Optional
from liteyuki.comm import channel
from liteyuki.comm.channel import ASYNC_ON_RECEIVE_FUNC, Channel, ON_RECEIVE_FUNC
from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable, run_coroutine_in_thread
if IS_MAIN_PROCESS:
_locks = {}
_on_main_subscriber_receive_funcs: dict[str, list[ASYNC_ON_RECEIVE_FUNC]] = {} # type: ignore
"""主进程订阅者接收函数"""
_on_sub_subscriber_receive_funcs: dict[str, list[ASYNC_ON_RECEIVE_FUNC]] = {} # type: ignore
"""子进程订阅者接收函数"""
def _get_lock(key) -> threading.Lock:
"""
获取锁
"""
if IS_MAIN_PROCESS:
if key not in _locks:
_locks[key] = threading.Lock()
return _locks[key]
else:
raise RuntimeError("Cannot get lock in sub process.")
class KeyValueStore:
def __init__(self):
self._store = {}
self.active_chan = Channel[tuple[str, Optional[dict[str, Any]]]](name="shared_memory-active")
self.passive_chan = Channel[tuple[str, Optional[dict[str, Any]]]](name="shared_memory-passive")
self.publish_channel = Channel[tuple[str, Any]](name="shared_memory-publish")
self.is_main_receive_loop_running = False
self.is_sub_receive_loop_running = False
def set(self, key: str, value: Any) -> None:
"""
设置键值对
Args:
key:
value:
"""
if IS_MAIN_PROCESS:
lock = _get_lock(key)
with lock:
self._store[key] = value
else:
# 向主进程发送请求拿取
self.passive_chan.send(
(
"set",
{
"key" : key,
"value": value
}
)
)
def get(self, key: str, default: Optional[Any] = None) -> Optional[Any]:
"""
获取键值对
Args:
key:
default: 默认值
Returns:
Any:
"""
if IS_MAIN_PROCESS:
lock = _get_lock(key)
with lock:
return self._store.get(key, default)
else:
recv_chan = Channel[Optional[Any]]("recv_chan")
self.passive_chan.send(
(
"get",
{
"key" : key,
"default" : default,
"recv_chan": recv_chan
}
)
)
return recv_chan.receive()
def delete(self, key: str, ignore_key_error: bool = True) -> None:
"""
删除键值对
Args:
key:
ignore_key_error: 是否忽略键不存在的错误
Returns:
"""
if IS_MAIN_PROCESS:
lock = _get_lock(key)
with lock:
if key in self._store:
try:
del self._store[key]
del _locks[key]
except KeyError as e:
if not ignore_key_error:
raise e
else:
# 向主进程发送请求删除
self.passive_chan.send(
(
"delete",
{
"key": key
}
)
)
def get_all(self) -> dict[str, Any]:
"""
获取所有键值对
Returns:
dict[str, Any]: 键值对
"""
if IS_MAIN_PROCESS:
return self._store
else:
recv_chan = Channel[dict[str, Any]]("recv_chan")
self.passive_chan.send(
(
"get_all",
{
"recv_chan": recv_chan
}
)
)
return recv_chan.receive()
def publish(self, channel_: str, data: Any) -> None:
"""
发布消息
Args:
channel_: 频道
data: 数据
Returns:
"""
self.active_chan.send(
(
"publish",
{
"channel": channel_,
"data" : data
}
)
)
def on_subscriber_receive(self, channel_: str) -> Callable[[ON_RECEIVE_FUNC], ON_RECEIVE_FUNC]:
"""
订阅者接收消息时的回调
Args:
channel_: 频道
Returns:
装饰器
"""
if not IS_MAIN_PROCESS:
raise RuntimeError("Cannot subscribe in sub process.")
def decorator(func: ON_RECEIVE_FUNC) -> ON_RECEIVE_FUNC:
async def wrapper(data: Any):
if is_coroutine_callable(func):
await func(data)
else:
func(data)
if IS_MAIN_PROCESS:
if channel_ not in _on_main_subscriber_receive_funcs:
_on_main_subscriber_receive_funcs[channel_] = []
_on_main_subscriber_receive_funcs[channel_].append(wrapper)
else:
if channel_ not in _on_sub_subscriber_receive_funcs:
_on_sub_subscriber_receive_funcs[channel_] = []
_on_sub_subscriber_receive_funcs[channel_].append(wrapper)
return wrapper
return decorator
@staticmethod
async def run_subscriber_receive_funcs(channel_: str, data: Any):
"""
运行订阅者接收函数
Args:
channel_: 频道
data: 数据
"""
[asyncio.create_task(func(data)) for func in _on_main_subscriber_receive_funcs[channel_]]
async def start_receive_loop(self):
"""
启动发布订阅接收器循环在主进程中运行若有子进程订阅则推送给子进程
"""
if not IS_MAIN_PROCESS:
raise RuntimeError("Cannot start receive loop in sub process.")
while True:
data = await self.active_chan.async_receive()
if data[0] == "publish":
# 运行主进程订阅函数
await self.run_subscriber_receive_funcs(data[1]["channel"], data[1]["data"])
# 推送给子进程
self.publish_channel.send(data)
class GlobalKeyValueStore:
_instance = None
_lock = threading.Lock()
@classmethod
def get_instance(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = KeyValueStore()
return cls._instance
shared_memory: KeyValueStore = GlobalKeyValueStore.get_instance() # 共享内存对象
# 全局单例访问点
if IS_MAIN_PROCESS:
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "get")
def on_get(data: tuple[str, dict[str, Any]]):
key = data[1]["key"]
default = data[1]["default"]
recv_chan = data[1]["recv_chan"]
recv_chan.send(shared_memory.get(key, default))
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "set")
def on_set(data: tuple[str, dict[str, Any]]):
key = data[1]["key"]
value = data[1]["value"]
shared_memory.set(key, value)
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "delete")
def on_delete(data: tuple[str, dict[str, Any]]):
key = data[1]["key"]
shared_memory.delete(key)
@shared_memory.passive_chan.on_receive(lambda d: d[0] == "get_all")
def on_get_all(data: tuple[str, dict[str, Any]]):
recv_chan = data[1]["recv_chan"]
recv_chan.send(shared_memory.get_all())
_ref_count = 0 # import 引用计数, 防止获取空指针
if not IS_MAIN_PROCESS:
if (shared_memory is None) and _ref_count > 1:
raise RuntimeError("Shared memory not initialized.")
_ref_count += 1

179
liteyuki/config.py Executable file
View File

@ -0,0 +1,179 @@
"""
该模块用于常用配置文件的加载
多配置文件编写原则
1. 尽量不要冲突: 一个键不要多次出现
2. 分工明确: 每个配置文件给一个或一类服务提供配置
3. 扁平化编写: 配置文件尽量扁平化不要出现过多的嵌套
4. 注意冲突时的优先级: 项目目录下的配置文件优先级高于config目录下的配置文件
5. 请不要将需要动态加载的内容写入配置文件你应该使用其他储存方式
"""
import os
import json
import copy
import toml # type: ignore
import yaml # type: ignore
from typing import Any
from liteyuki.log import logger
_SUPPORTED_CONFIG_FORMATS = (".yaml", ".yml", ".json", ".toml")
def flat_config(config: dict[str, Any]) -> dict[str, Any]:
"""
扁平化配置文件
{a:{b:{c:1}}} -> {"a.b.c": 1}
Args:
config: 配置项目
Returns:
扁平化后的配置文件但也包含原有的键值对
"""
new_config = copy.deepcopy(config)
for key, value in config.items():
if isinstance(value, dict):
for k, v in flat_config(value).items():
new_config[f"{key}.{k}"] = v
return new_config
def load_from_yaml(file_: str) -> dict[str, Any]:
"""
Load config from yaml file
"""
logger.debug(f"Loading YAML config from {file_}")
config = yaml.safe_load(open(file_, "r", encoding="utf-8"))
return flat_config(config if config is not None else {})
def load_from_json(file_: str) -> dict[str, Any]:
"""
Load config from json file
"""
logger.debug(f"Loading JSON config from {file_}")
config = json.load(open(file_, "r", encoding="utf-8"))
return flat_config(config if config is not None else {})
def load_from_toml(file_: str) -> dict[str, Any]:
"""
Load config from toml file
"""
logger.debug(f"Loading TOML config from {file_}")
config = toml.load(open(file_, "r", encoding="utf-8"))
return flat_config(config if config is not None else {})
def load_from_files(*files: str, no_warning: bool = False) -> dict[str, Any]:
"""
从指定文件加载配置项会自动识别文件格式
默认执行扁平化选项
"""
config = {}
for file in files:
if os.path.exists(file):
if file.endswith((".yaml", "yml")):
config.update(load_from_yaml(file))
elif file.endswith(".json"):
config.update(load_from_json(file))
elif file.endswith(".toml"):
config.update(load_from_toml(file))
else:
if not no_warning:
logger.warning(f"Unsupported config file format: {file}")
else:
if not no_warning:
logger.warning(f"Config file not found: {file}")
return config
def load_configs_from_dirs(
*directories: str, no_waring: bool = False
) -> dict[str, Any]:
"""
从目录下加载配置文件不递归
按照读取文件的优先级反向覆盖
默认执行扁平化选项
"""
config = {}
for directory in directories:
if not os.path.exists(directory):
if not no_waring:
logger.warning(f"Directory not found: {directory}")
continue
for file in os.listdir(directory):
if file.endswith(_SUPPORTED_CONFIG_FORMATS):
config.update(
load_from_files(os.path.join(directory, file), no_warning=no_waring)
)
return config
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(
load_from_files(
"config.yaml",
"config.toml",
"config.json",
"config.yml",
no_warning=no_waring,
)
)
return config
# new config loader
class Loader:
def __init__(self):
self.config = {}
def load_from_yaml(self, fp: str) -> "Loader":
"""从yaml文件加载配置
Args:
fp
"""
with open(fp, 'r') as file:
self.config.update(yaml.safe_load(file))
return self
def load_from_toml(self, fp: str) -> "Loader":
"""从toml文件加载配置"""
with open(fp, 'r') as file:
self.config.update(toml.load(file))
return self
def load_from_json(self, fp: str) -> "Loader":
"""从json文件加载配置"""
with open(fp, 'r') as file:
self.config.update(json.load(file))
return self
def load_from_env(self, prefix: str = "") -> "Loader":
"""从环境变量加载配置"""
for key, value in os.environ.items():
if key.startswith(prefix):
self.config[key[len(prefix):]] = value
return self
def merge(self, loader: "Loader") -> "Loader":
"""合并两个Loader键值对树"""
self.config.update(loader.config)
return self
def get(self, key: str, default: Any = None) -> Any:
"""获取配置值"""
return self.config.get(key, default)
def __repr__(self) -> str:
return f"Loader(config={self.config})"

2
liteyuki/core/__init__.py Executable file
View File

@ -0,0 +1,2 @@
from .manager import *

297
liteyuki/core/manager.py Executable file
View File

@ -0,0 +1,297 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2020-2025 LiteyukiStudio. All Rights Reserved
@Time : 2024/7/27 上午11:12
@Author : snowykami
@Email : snowykami@outlook.com
@File : manager.py
@Software: PyCharm
"""
import asyncio
import multiprocessing
import threading
from multiprocessing import Process
from typing import Any, Callable, TYPE_CHECKING, TypeAlias
from croterline.context import Context
from croterline.process import SubProcess, ProcessFuncType
from liteyuki.log import logger
from liteyuki.utils import IS_MAIN_PROCESS
if TYPE_CHECKING:
from liteyuki.bot.lifespan import Lifespan
from liteyuki.comm.storage import KeyValueStore
from liteyuki.comm import Channel
if IS_MAIN_PROCESS:
from liteyuki.comm.channel import get_channel, publish_channel, get_channels
from liteyuki.comm.storage import shared_memory
from liteyuki.comm.channel import (
channel_deliver_active_channel,
channel_deliver_passive_channel,
)
else:
from liteyuki.comm import channel
from liteyuki.comm import storage
TARGET_FUNC: TypeAlias = Callable[..., Any]
TIMEOUT = 10
__all__ = ["ProcessManager", "sub_process_manager"]
multiprocessing.set_start_method("spawn", force=True)
class ChannelDeliver:
def __init__(
self,
active: Channel[Any],
passive: Channel[Any],
channel_deliver_active: Channel[Channel[Any]],
channel_deliver_passive: Channel[tuple[str, dict]],
publish: Channel[tuple[str, Any]],
):
self.active = active
self.passive = passive
self.channel_deliver_active = channel_deliver_active
self.channel_deliver_passive = channel_deliver_passive
self.publish = publish
# 函数处理一些跨进程通道的
def _delivery_channel_wrapper(
func: TARGET_FUNC, cd: ChannelDeliver, sm: "KeyValueStore", *args, **kwargs
):
"""
子进程入口函数
处理一些操作
"""
# 给子进程设置通道
if IS_MAIN_PROCESS:
raise RuntimeError("Function should only be called in a sub process.")
channel.active_channel = cd.active # 子进程主动通道
channel.passive_channel = cd.passive # 子进程被动通道
channel.channel_deliver_active_channel = (
cd.channel_deliver_active
) # 子进程通道传递主动通道
channel.channel_deliver_passive_channel = (
cd.channel_deliver_passive
) # 子进程通道传递被动通道
channel.publish_channel = cd.publish # 子进程发布通道
# 给子进程创建共享内存实例
storage.shared_memory = sm
func(*args, **kwargs)
class ProcessManager:
"""
进程管理器
"""
def __init__(self, lifespan: "Lifespan"):
self.lifespan = lifespan
self.targets: dict[str, tuple[Callable, tuple, dict]] = {}
self.processes: dict[str, Process] = {}
def _run_process(self, name: str):
"""
开启后自动监控进程并添加到进程字典中会阻塞请创建task
Args:
name:
Returns:
"""
if name not in self.targets:
raise KeyError(f"Process {name} not found.")
chan_active = get_channel(f"{name}-active")
def _start_process():
process = Process(
target=self.targets[name][0],
args=self.targets[name][1],
kwargs=self.targets[name][2],
daemon=True,
)
self.processes[name] = process
process.start()
# 启动进程并监听信号
_start_process()
while True:
data = chan_active.receive()
if data == 0:
# 停止
logger.info(f"Stopping process {name}")
self.terminate(name)
break
elif data == 1:
# 重启
logger.info(f"Restarting process {name}")
self.terminate(name)
_start_process()
continue
else:
logger.warning("Unknown data received, ignored.")
def start_all(self):
"""
对外启动方法启动所有进程创建asyncio task
"""
# [asyncio.create_task(self._run_process(name)) for name in self.targets]
for name in self.targets:
logger.debug(f"Starting process {name}")
threading.Thread(
target=self._run_process, args=(name,), daemon=True
).start()
def add_target(self, name: str, target: TARGET_FUNC, args: tuple = (), kwargs=None):
"""
添加进程
Args:
name: 进程名用于获取和唯一标识
target: 进程函数
args: 进程函数参数
kwargs: 进程函数关键字参数通常会默认传入chan_active和chan_passive
"""
if kwargs is None:
kwargs = {}
chan_active: Channel = Channel(name=f"{name}-active")
chan_passive: Channel = Channel(name=f"{name}-passive")
channel_deliver = ChannelDeliver(
active=chan_active,
passive=chan_passive,
channel_deliver_active=channel_deliver_active_channel,
channel_deliver_passive=channel_deliver_passive_channel,
publish=publish_channel,
)
self.targets[name] = (
_delivery_channel_wrapper,
(target, channel_deliver, shared_memory, *args),
kwargs,
)
# 主进程通道
def join_all(self):
for name, process in self.targets:
process.join()
def terminate(self, name: str):
"""
终止进程并从进程字典中删除
Args:
name:
Returns:
"""
if name not in self.processes:
logger.warning(f"Process {name} not found.")
return
process = self.processes[name]
process.terminate()
process.join(TIMEOUT)
if process.is_alive():
process.kill()
logger.success(f"Process {name} terminated.")
def terminate_all(self):
for name in self.targets:
self.terminate(name)
def is_process_alive(self, name: str) -> bool:
"""
检查进程是否存活
Args:
name:
Returns:
"""
if name not in self.targets:
logger.warning(f"Process {name} not found.")
return self.processes[name].is_alive()
# new version
class _SubProcessManager:
"""
子进程管理器
若要子进程间通信请先在子进程A中发送通信事件给主进程包含当前进程信息及上下文信息主进程再将信息发送给子进程B子进程B再根据信息进行操作
"""
def __init__(self):
self.processes: dict[str, SubProcess] = {}
def add(self, name: str, func: ProcessFuncType, *args, **kwargs):
"""
添加子进程
Args:
func: 子进程函数
name: 子进程名称
args: 子进程函数参数
kwargs: 子进程函数关键字参数
Returns:
"""
self.processes[name] = SubProcess(name, func, *args, **kwargs)
def start(self, name: str):
"""
启动指定子进程
Args:
name: 子进程名称
Returns:
"""
if name not in self.processes:
raise KeyError(f"Process {name} not found.")
self.processes[name].start()
def start_all(self):
"""
启动所有子进程
"""
for name, process in self.processes.items():
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()

4
liteyuki/dev/__init__.py Executable file
View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
"""
该模块用于存放一些开发工具
"""

90
liteyuki/dev/observer.py Executable file
View File

@ -0,0 +1,90 @@
"""
此模块用于注册观察者函数使用watchdog监控文件变化并重启bot
启用该模块需要在配置文件中设置`dev_mode`为True
"""
import time
from typing import Callable, TypeAlias
from watchdog.events import FileSystemEvent, FileSystemEventHandler
from watchdog.observers import Observer
from liteyuki import get_bot, get_config_with_compat, logger
liteyuki_bot = get_bot()
CALLBACK_FUNC: TypeAlias = Callable[[FileSystemEvent], None] # 位置1为FileSystemEvent
FILTER_FUNC: TypeAlias = Callable[[FileSystemEvent], bool] # 位置1为FileSystemEvent
observer = Observer()
def debounce(wait):
"""
防抖函数
"""
def decorator(func):
def wrapper(*args, **kwargs):
nonlocal last_call_time
current_time = time.time()
if (current_time - last_call_time) > wait:
last_call_time = current_time
return func(*args, **kwargs)
last_call_time = None
return wrapper
return decorator
if get_config_with_compat("liteyuki.reload", ("dev_mode",), False):
logger.debug("Liteyuki Reload enabled, watching for file changes...")
observer.start()
class CodeModifiedHandler(FileSystemEventHandler):
"""
Handler for code file changes
"""
@debounce(1)
def on_modified(self, event):
raise NotImplementedError("on_modified must be implemented")
def on_created(self, event):
self.on_modified(event)
def on_deleted(self, event):
self.on_modified(event)
def on_moved(self, event):
self.on_modified(event)
def on_any_event(self, event):
self.on_modified(event)
def on_file_system_event(directories: tuple[str], recursive: bool = True, event_filter: FILTER_FUNC = None) -> Callable[[CALLBACK_FUNC], CALLBACK_FUNC]:
"""
注册文件系统变化监听器
Args:
directories: 监听目录们
recursive: 是否递归监听子目录
event_filter: 事件过滤器, 返回True则执行回调函数
Returns:
装饰器装饰一个函数在接收到数据后执行
"""
def decorator(func: CALLBACK_FUNC) -> CALLBACK_FUNC:
def wrapper(event: FileSystemEvent):
if event_filter is not None and not event_filter(event):
return
func(event)
code_modified_handler = CodeModifiedHandler()
code_modified_handler.on_modified = wrapper
for directory in directories:
observer.schedule(code_modified_handler, directory, recursive=recursive)
return func
return decorator

28
liteyuki/dev/plugin.py Executable file
View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2020-2025 LiteyukiStudio. All Rights Reserved
@Time : 2024/8/18 上午5:04
@Author : snowykami
@Email : snowykami@outlook.com
@File : plugin.py
@Software: PyCharm
"""
from pathlib import Path
from liteyuki.bot import LiteyukiBot
from liteyuki.config import load_config_in_default
def run_plugins(*module_path: str | Path):
"""
运行插件无需手动初始化bot
Args:
module_path: 插件路径参考`liteyuki.load_plugin`的函数签名
"""
cfg = load_config_in_default()
plugins = cfg.get("liteyuki.plugins", [])
plugins.extend(module_path)
cfg["liteyuki.plugins"] = plugins
bot = LiteyukiBot(**cfg)
bot.run()

10
liteyuki/exception.py Executable file
View File

@ -0,0 +1,10 @@
"""exception模块包含了liteyuki运行中的所有错误
"""
from typing import Any, Optional
class LiteyukiException(BaseException):
"""Liteyuki的异常基类。"""
def __str__(self) -> str:
return self.__repr__()

75
liteyuki/log.py Executable file
View File

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
@Time : 2024/7/27 上午9:12
@Author : snowykami
@Email : snowykami@outlook.com
@File : log.py
@Software: PyCharm
"""
import sys
import loguru
logger = loguru.logger.bind()
debug_format: str = (
"<c>{time:YYYY-MM-DD HH:mm:ss}</c> "
"<lvl>[{level.icon}{level}]</lvl> "
"<c><{name}.{module}.{function}:{line}></c> "
"{message}"
)
# 默认日志格式
default_format: str = (
"<c>{time:MM-DD HH:mm:ss}</c> "
"<lvl>[{level.icon}{level}]</lvl> "
"<c><{name}></c> "
"{message}"
)
def get_format(level: str) -> str:
"""
获取日志格式
Args:
level: 日志等级
Returns: 日志格式
"""
# DEBUG日志格式
if level == "DEBUG":
return debug_format
else:
return default_format
def init_log(config: dict):
"""
在语言加载完成后执行
Args:
config: 配置
"""
global logger
level = config.get("log_level", "DEBUG")
logger.remove()
logger.add(
sys.stdout,
level=level,
diagnose=False,
format=get_format(level),
)
show_icon = config.get("log_icon", True)
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={"log_level": "DEBUG", "log_icon": True})

Some files were not shown because too many files have changed in this diff Show More