Compare commits

..
140 Commits
Author SHA1 Message Date
HibiKier ae5df38c21 🐛 修复图片模板方法 2024-11-16 17:59:15 +08:00
HibiKier 545f6fd7f9 🎨 入群检测代码优化 2024-11-14 18:56:53 +08:00
HibiKier 4c7c223b2c 🐛 修复我的信息at用户时头像不正确 2024-11-14 15:27:17 +08:00
HibiKier 14b983cfa0 💬 修改md 2024-11-09 13:53:38 +08:00
HibiKier 229908207b 💬 更新md 2024-11-09 13:53:16 +08:00
HibiKier cfe7dfd6b5 💬 修改md 2024-11-08 21:00:48 +08:00
HibiKier b2da0a902d 🎨 playwright添加cookie参数 2024-11-07 13:38:20 +08:00
HibiKier 3f06131c34 💬 修改md 2024-11-07 00:29:31 +08:00
HibiKier 24f1a1ca9a 💬 修改测试url 2024-11-07 00:28:41 +08:00
HibiKier 54a74cdd91 🎨 更新md 2024-11-05 20:45:11 +08:00
HibiKier 7ca4c18e1c 🎨 修改md 2024-11-05 15:54:53 +08:00
HibiKier a2b7980ae2 💬 修改版本号 2024-11-05 15:51:19 +08:00
HibiKier e75a56fe08 🐛 修复自定义pixiv反向代理无法对涩图生效 2024-11-05 15:47:59 +08:00
HibiKier abd8b9b705 ✨ 添加用户消息撤回命令 (#1719) 2024-11-05 15:34:45 +08:00
HibiKier 54d2ba1df4 🐛 修复邀请群组强制退出 2024-11-05 14:47:07 +08:00
HibiKier dbfeeac313 Merge branch 'dev' of https://github.com/HibiKier/zhenxun_bot into dev 2024-10-29 08:27:02 +08:00
HibiKier 93316be5fe 🎨 工具代码优化 2024-10-29 08:26:41 +08:00
AkashiCoin 60b78a9f1c 🎉 chore(version): Update version to v0.2.4-6359ba6 (#1692) 2024-10-28 09:41:35 +08:00
HibiKier 6359ba63f9 💬 更新权限检查日志提示 2024-10-24 16:27:37 +08:00
HibiKier 2853a2feaa ✨ ban限制依赖类型插件 2024-10-24 11:09:01 +08:00
HibiKier c9b864ca54 🐛 修复合并转发在bytes传输下图片丢失 2024-10-23 15:21:53 +08:00
梦璃雨落 6519b1cad4 🐞 fix: 更新货物未找到异常的信息处理方式 (#1713) 2024-10-23 13:19:47 +08:00
HibiKier ebf3df046a 🎨 修改版本号 2024-10-22 10:40:00 +08:00
HibiKier b6611d6d0e 🐛 修复admin_check 2024-10-22 10:38:40 +08:00
HibiKier 23ea21380a 🐛 导入修复 2024-10-22 09:29:11 +08:00
梦璃雨落 54a93a2f54 🎈 perf(image_utils): 在image_utils中禁用代理下载 (#1710)
* 🎈 perf(image_utils): 在image_utils中禁用代理下载

get_download_image_hash使用场景是访问腾讯服务器获取图片,无需走代理

* ✨ Add optional proxy support to image hash download function
2024-10-21 23:49:32 +08:00
HibiKier 05f954eb8b ✨ 指定bot的功能管理 (#1706) 2024-10-21 19:07:35 +08:00
HibiKier 27d4630874 ✨ 修改版本 2024-10-20 19:24:47 +08:00
HibiKier 7ac2ff92c4 ✨ 本地引入echart.js 2024-10-20 13:34:47 +08:00
HibiKier 92b0c6b4bf 🎨 http_utils代码优化 2024-10-19 23:02:05 +08:00
HibiKier 75e10fe38a 🎨 修改早安时间 2024-10-19 18:12:35 +08:00
HibiKier 6dfebaae96 🎨 帮助界面优化 2024-10-19 01:26:30 +08:00
HibiKier 3ffe213652 🐛 修复签到金币排行bug以及添加官bot监控 2024-10-19 00:36:19 +08:00
HibiKier c9aa568767 ✨ 可以通过Bot判断是否为官bot 2024-10-18 23:13:16 +08:00
HibiKier 3d3a2a5f7f ✨ 部分功能适配QQ BOT (#1701) 2024-10-18 18:57:55 +08:00
HibiKier 7567bfb732 🐛 修复插件限制加载 2024-10-16 17:29:21 +08:00
HibiKier f0f0e94a9c 🎨 引用uninfo 2024-10-16 17:18:30 +08:00
HibiKier 41b0dac223 🐛 修复群组权限刷新 (#1700) 2024-10-16 13:29:44 +08:00
HibiKier 792bcaa711 ✨ 添加获取nb配置api 2024-10-16 12:58:01 +08:00
HibiKier fe1634eb2d 🎨 代码优化 (#1698) 2024-10-15 03:44:30 +08:00
HibiKier 4a52c4825b 🐛 修复webui接口 2024-10-14 22:24:47 +08:00
HibiKier 6358ce5266 🐛 修复webui好友数量显示和登录次数 2024-10-14 22:17:05 +08:00
HibiKier e98af0ac21 Merge branch 'dev' of https://github.com/HibiKier/zhenxun_bot into dev 2024-10-14 22:11:39 +08:00
HibiKier 48a48204f3 🐛 包优化 2024-10-14 11:00:39 +08:00
HibiKier 6f313986df 🎨 生成lock 2024-10-14 10:06:38 +08:00
HibiKier 3856ba09bb 🐛 功能调用统计只统计已加载的插件 2024-10-13 01:07:19 +08:00
HibiKier f982d862ee 🎨 添加分支 2024-10-12 22:44:08 +08:00
HibiKier c76566c2df 🔥 移除旧资源文件夹 2024-10-12 14:06:12 +08:00
HibiKier e7fffa3ef4 🔥 移除dinggong语音文件夹 2024-10-12 14:02:45 +08:00
HibiKier f7b28127e9 🐛 修复功能调用统计空白 (#1694) 2024-10-12 11:03:24 +08:00
AkashiCoin 7ea11a884b 🐳 chore: 补全release draft文件 (#1693) 2024-10-11 21:47:06 +08:00
AkashiCoin faa0785fa1 🐳 chore(update_version): 支持选择性的更新版本 (#1691)
* 🐳 chore(update_version): 支持选择性的更新版本

* 🐳 chore: 替换邮箱格式
2024-10-11 16:18:42 +08:00
HibiKier 9e5266a491 ✨ 使用uninfo进行群组成员更新 (#1690) 2024-10-10 23:25:46 +08:00
HibiKierandHibiKier 2f459719e8 🐛 修改禁用module (#1688)
* 🐛 修改禁用module

* chore(version): Update version to v0.2.3-4cde662

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
2024-10-09 17:45:53 +08:00
HibiKierandHibiKier 5f92efa658 🐛 webui 添加bot详情参数 (#1686)
* 🐛 webui 添加bot详情参数

* chore(version): Update version to v0.2.3-ba3a9f1

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
2024-10-07 15:37:55 +08:00
HibiKier 856976526f 🎨 修改限制配置文件key (#1685) 2024-10-06 18:16:35 +08:00
HibiKier 6852363a03 🐛 修复导入问题 (#1684) 2024-10-06 01:19:24 +08:00
HibiKier 862427a872 🎨 webui群组代码优化 (#1683) 2024-10-06 01:05:37 +08:00
HibiKierandHibiKier fd90e1ab82 🎨 notice响应期添加rule (#1682)
* 🎨 notice响应期添加rule

* chore(version): Update version to v0.2.3-f3e5c9e

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
2024-10-05 22:37:30 +08:00
HibiKier 3117dc264f ✨ unban支持使用id (#1681) 2024-10-05 19:07:18 +08:00
HibiKierandHibiKier a28a60d9c8 🎨 功能开关代码优化 (#1680)
* 🎨 功能开关代码优化

* chore(version): Update version to v0.2.3-5f361ff

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
2024-10-05 18:02:53 +08:00
HibiKier f0063283e7 🐛 优化功能开关管理 (#1679) 2024-10-05 16:45:02 +08:00
AkashiCoin 84680aa88d 🐳 chore(release_drafter): 支持release-drafter (#1672)
* 🐳 chore(release_drafter): 支持release-drafter

* 🐛 fix: 修复依赖字段
2024-10-05 16:37:29 +08:00
HibiKier bd50e17c58 🐛 修复调用统计异常 (#1674) 2024-10-04 00:14:36 +08:00
HibiKier f08114f6c5 ✨ 提供新webui api (#1673) 2024-10-03 23:56:17 +08:00
42b6e94564 ✨ 更新插件商店功能,支持通过模块名操作插件(#1670)
* 更新插件商店功能,支持通过模块名操作插件

- 扩展插件添加、移除和更新功能,支持使用插件ID或模块名
- 增加更新全部插件的功能
- 优化插件商店的命令使用说明
- 修复了一些与插件模块名相关的逻辑问题

* 优化插件更新和加载机制,提供测试函数

- 修复了插件更新函数中的条件判断逻辑

* 优化插件更新通知的格式

调整了插件更新通知的文本格式,去掉了多余的换行符,使消息内容更加紧凑和清晰。

* 更新测试用例中的消息格式,将插件更新通知中的空格改为换行符

* 移除版本号更新

* 重构插件管理器的数据源解析逻辑

- 将插件ID和模块名的检查逻辑移至单独的私有方法 _resolve_plugin_key
- 简化了 get_info 和 update_plugin 方法中的逻辑
- 提高了代码的可读性和可维护性

* 优化插件商店数据源类的插件查询逻辑

简化了ShopManage类中查询插件信息的逻辑。通过新增的_resolve_plugin_key类方法来解析插件ID或模块名,如果解析失败则捕获ValueError异常并返回错误信息。这样可以更清晰地处理插件查询逻辑,并避免冗余代码。

* 移除更新全部插件日志中的f-string

更新全部插件功能中,移除了日志记录中的f-string,简化了日志消息的格式。这个更改可能是为了统一日志记录的风格或者减少不必要的字符串格式化操作。

* Revert "移除版本号更新"

This reverts commit 2bcaa6f12e.

---------

Co-authored-by: molanp <molanp@users.noreply.github.com>
Co-authored-by: HibiKier <45528451+HibiKier@users.noreply.github.com>
Co-authored-by: AkashiCoin <l1040186796@gmail.com>
2024-10-02 18:32:21 +08:00
AkashiCoinandAkashiCoin d3a4a5bbf7 🐛 fix(github_utils): 修复路径解析问题 (#1668)
* 🐛 fix(github_utils): 修复路径解析问题

* chore(version): Update version to v0.2.3-a39d7a3

---------

Co-authored-by: AkashiCoin <AkashiCoin@users.noreply.github.com>
2024-10-02 12:54:12 +08:00
HibiKier 482eb1a214 🎨 修改requirements (#1665) 2024-10-01 00:29:29 +08:00
HibiKier 94e05944fd 🎨 修改版本号 (#1664) 2024-10-01 00:24:45 +08:00
HibiKier 2c8c46d6b1 🎨 修改README (#1663) 2024-10-01 00:17:14 +08:00
HibiKier 717a973807 ✨ 将cd,block,count限制复原配置文件 (#1662) 2024-10-01 00:05:43 +08:00
HibiKierandHibiKier d68a4099ba ✨ 新增插件商店api (#1659)
* ✨ 新增插件商店api

* chore(version): Update version to v0.2.2-7e15f20

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
2024-09-29 20:47:58 +08:00
HibiKier e8425f371c ✨ 修改个人信息菜单名称 (#1658) 2024-09-29 17:06:17 +08:00
HibiKier a3311adebb ✨ 新增个人信息命令 (#1657) 2024-09-29 17:00:31 +08:00
HibiKier 28b61e57cd ✨ 新增超级用户与管理员帮助模板 (#1655) 2024-09-27 16:59:41 +08:00
HibiKier 7890cc577f ✨ 安装/移除插件提供插件安装/卸载方法用于插件初始化 (#1654) 2024-09-27 10:29:59 +08:00
HibiKier b14220e6e3 ✨ 移除默认图片文件夹:爬 (#1653) 2024-09-27 10:27:01 +08:00
HibiKierandHibiKier 7ec1bc9fac 🐛 修复webui下载后首次启动错误 (#1652)
* 🐛 修复webui下载后首次启动错误

* chore(version): Update version to v0.2.2-4a8ef85

---------

Co-authored-by: HibiKier <HibiKier@users.noreply.github.com>
2024-09-25 19:41:45 +08:00
HibiKier e89d1d4688 🐛 修复群欢迎消息设置 (#1651) 2024-09-25 19:04:36 +08:00
HibiKier 6be9e477b1 🐛 修复群组中帮助功能状态显示问题 (#1650) 2024-09-25 18:29:01 +08:00
AkashiCoin 207f947a1c 🐛 fix(http_utils): 流式下载Content-Length错误 (#1647) 2024-09-22 17:12:21 +08:00
HibiKier 32c11b9919 🎨 更新README (#1645) 2024-09-21 23:36:17 +08:00
HibiKier 3fc4eaa39a 🐛 签到名称自适应 (#1644) 2024-09-21 23:08:48 +08:00
HibiKier a04475abc1 ✨ 重构qq群事件处理 (#1643) 2024-09-21 23:07:00 +08:00
AkashiCoin 38976589ec 🐳 chore: 修改运行检查触发路径 (#1642)
* 🐳 chore: 修改运行检查触发路径

* 🐳 chore: 添加tests目录
2024-09-21 18:01:45 +08:00
AkashiCoinandAkashiCoin f2c20b84bf 🎈 perf: 使用commit号下载插件 (#1641)
* 🎈 perf: 使用commit号下载插件

* chore(version): Update version to v0.2.2-f9c7360

---------

Co-authored-by: AkashiCoin <AkashiCoin@users.noreply.github.com>
2024-09-21 17:38:37 +08:00
HibiKier 983248374d ✨ message_build支持AtAll (#1639) 2024-09-19 20:25:45 +08:00
HibiKier 6f635ed978 🐛 修复群权限与插件等级匹配 (#1635) 2024-09-16 21:18:42 +08:00
HibiKier fcfaf56021 🐛 修复商店商品为空时报错 (#1634) 2024-09-16 21:17:09 +08:00
AkashiCoin 60f4406ec1 🧪 test(auto_update): 修复测试用例 (#1633) 2024-09-16 20:29:46 +08:00
AkashiCoinandAkashiCoin 51c010daa8 🎈 perf(github_utils): 支持github url下载遍历 (#1632)
* 🎈 perf(github_utils): 支持github url下载遍历

* 🐞 fix(http_utils): 修复一些下载问题

* 🦄 refactor(http_utils): 部分重构

* chore(version): Update version to v0.2.2-e6f17c4

---------

Co-authored-by: AkashiCoin <AkashiCoin@users.noreply.github.com>
2024-09-16 20:08:42 +08:00
AkashiCoin cd88d805ce 🐳 chore: 支持自动修改版本号 (#1629) 2024-09-16 19:13:20 +08:00
HibiKier e41e16370e ✨ 群组发言时间检测提供开关配置 (#1630) 2024-09-14 19:17:40 +08:00
HibiKier f2e354edeb ✨ 当管理员尝试ban真寻时将被反杀 (#1628) 2024-09-14 16:29:27 +08:00
HibiKier f1354c6264 🐛 修复群权限与插件等级匹配 (#1627) 2024-09-14 14:23:19 +08:00
HibiKier 029a731fb9 ✨ 重构帮助,限制普通用户查询管理插件 (#1626) 2024-09-14 05:23:55 +08:00
AkashiCoin d97e437e80 🎈 优先使用github api (#1625) 2024-09-13 20:41:33 +08:00
HibiKier 8a688eb4f0 🐛 好感度排行提供默认值 (#1624) 2024-09-12 22:15:04 +08:00
HibiKier 94ef33264b 🐛 签到文本适应 (#1622) 2024-09-11 12:53:12 +08:00
HibiKier a8355fbab9 🐛 修复功能少时zhenxun帮助图片排序问题 (#1620) 2024-09-11 11:53:49 +08:00
HibiKier 95762bdddd 🐛 修复路径解压与挂载 (#1619) 2024-09-10 20:17:09 +08:00
HibiKier 4e42d1dda1 🐛 修复超级用户id获取问题 2024-09-09 23:01:15 +08:00
HibiKier e4a92ea34b ✨ 签到/金币排行限制最大数量 (#1616)
* ✨ 签到/金币排行限制最大数量
2024-09-09 22:47:23 +08:00
AkashiCoin f11e9c58e4 🔨 提取GitHub相关操作 (#1609)
* 🔨 提取GitHub相关操作

* 🔨 重构API策略
2024-09-08 12:38:30 +08:00
AkashiCoinandHibiKier 342e70cc38 📝 修改README
Co-Authored-By: HibiKier <45528451+HibiKier@users.noreply.github.com>
2024-09-08 11:34:26 +08:00
AkashiCoinandHibiKier 440e7b54a5 ✨ 添加金币排行
Co-Authored-By: HibiKier <45528451+HibiKier@users.noreply.github.com>
2024-09-08 11:33:19 +08:00
AkashiCoin fe11ff0772 🔧 VSCode配置修改 2024-09-07 17:51:03 +08:00
AkashiCoin 2b006b8f5e 🔧 VSCode配置修改 2024-09-07 17:11:01 +08:00
HibiKier 1790a0b09e ✨提供sqlite和mysql连接url示例 2024-09-07 17:10:08 +08:00
HibiKier 057001f0bd ✨ 支持mysql,psql,sqlite随机函数 2024-09-07 16:46:56 +08:00
AkashiCoin e618b19283 🐛 修复自检在ARM上的问题 (#1607)
* 🐛 修复自检在ARM上的问题

* ✅ 优化测试
2024-09-07 16:17:29 +08:00
HibiKier 62fd93c1ff 🐛 过滤父插件 2024-09-07 13:54:25 +08:00
HibiKier 807b2f6504 🐛 私聊时修改插件时删除私聊帮助 2024-09-07 13:16:41 +08:00
HibiKier 0a5ab83ffe 🎨 代码结构优化 2024-09-07 12:46:25 +08:00
ElagaandHibiKier 3f4787d4c6 修复签到逻辑bug,并使代码更灵活以适应签到好感度等级配置 (#1606)
* 修复签到功能已知问题

* 修复签到功能已知问题

* 修改参数名称

* 修改uid判断

---------

Co-authored-by: HibiKier <45528451+HibiKier@users.noreply.github.com>
2024-09-07 12:35:39 +08:00
HibiKier db9153f42c 🐛 自检html修正 2024-09-07 01:50:24 +08:00
HibiKier 3b4c206a24 ✨ 重构自检ui 2024-09-07 01:25:42 +08:00
HibiKier 51371ba954 🐛 修复插件开关有时出现错误 2024-09-05 17:41:33 +08:00
HibiKier c36bb9771c 🎨 优化代码 2024-09-04 21:10:54 +08:00
AkashiCoin ce97dedc5f 🐛 文件下载逻辑修改 2024-09-03 17:13:31 +08:00
AkashiCoin 682d19aa2b 🎨 采取Sourcery建议 2024-09-03 16:52:11 +08:00
AkashiCoin c3927c7f2e ✨ 添加API缓存 2024-09-03 16:52:11 +08:00
AkashiCoin 8911bbfa21 🐛 修复测试用例 2024-09-03 16:52:11 +08:00
AkashiCoin 7288d5bdba ✨ 添加仓库目录多获取渠道 2024-09-03 16:52:11 +08:00
AkashiCoin 8615eb20d4 ⚡ 添加github镜像 2024-09-03 16:52:11 +08:00
AkashiCoin a61934650e ➕ 添加依赖aiocache 2024-09-03 16:52:11 +08:00
HibiKier a2549a0ae9 🎨 更新requirements 2024-09-03 11:03:30 +08:00
fanyinrumeng 405e2d3a4c 🚀 更新Dockerfile (#1599) 2024-09-02 23:12:27 +08:00
HibiKier 02aba68269 🎨 代码优化 2024-09-02 21:45:37 +08:00
HibiKier 8d071f853b 🐛 修复更新群组成员信息 2024-09-02 17:32:12 +08:00
AkashiCoin 44e0f2d410 🐛 增加插件状态检查 (#1598)
* ✅ 优化测试用例

* 🐛 更改插件更新与安装逻辑
2024-09-02 15:00:37 +08:00
AkashiCoin 9eca6a97ca 🐛 修复插件商店检查插件更新问题 (#1597)
* 🐛 修复插件商店检查插件更新问题

* 🐛 恶意命令检测问题
2024-09-02 12:00:27 +08:00
HibiKier a56d1f2bd8 🐛 修复超级用户对群组功能开关 2024-09-02 11:43:01 +08:00
HibiKier 133d4e193a 🐛 修改bug与版本锁定 2024-09-02 11:25:47 +08:00
HibiKier db75c4a433 Update README.md 2024-09-02 09:53:58 +08:00
HibiKier 15ad90da88 🎨 修改readme 2024-09-02 09:51:36 +08:00
AkashiCoin 29c48765ae 🐛修复添加插件返回403的问题 (#1595)
* 完善测试方法
* vscode测试配置
* 重构插件安装过程
2024-09-02 01:50:39 +08:00
HibiKier 8fe061738a 🐛 bug修复 2024-09-01 23:30:26 +08:00
AkashiCoin 7e7436f433 ✅ 添加测试:更新与添加插件 (#1594)
* ✅ 测试更新与添加插件

* ✅ Sourcery建议

* 👷 添加pytest

* 🎨 优化代码
2024-09-01 14:53:41 +08:00
HibiKier a3681216bd ✨ 父级插件加载 2024-08-30 23:50:45 +08:00
46 changed files with 404 additions and 615 deletions
+8 -1
View File
@@ -8,12 +8,19 @@ NICKNAME=["真寻", "小真寻", "绪山真寻", "小寻子"]
SESSION_EXPIRE_TIMEOUT=30 SESSION_EXPIRE_TIMEOUT=30
ALCONNA_USE_COMMAND_START=True
# 全局图片统一使用bytes发送,当真寻与协议端不在同一服务器上时为True # 全局图片统一使用bytes发送,当真寻与协议端不在同一服务器上时为True
IMAGE_TO_BYTES = False IMAGE_TO_BYTES = True
# 回复消息时自称 # 回复消息时自称
SELF_NICKNAME="小真寻" SELF_NICKNAME="小真寻"
# 官bot appid:bot账号
QBOT_ID_DATA = '{
}'
# 数据库配置 # 数据库配置
# 示例: "postgres://user:password@127.0.0.1:5432/database" # 示例: "postgres://user:password@127.0.0.1:5432/database"
# 示例: "mysql://user:password@127.0.0.1:3306/database" # 示例: "mysql://user:password@127.0.0.1:3306/database"
-65
View File
@@ -1,65 +0,0 @@
name: Update Version
on:
pull_request_target:
paths:
- zhenxun/**
- resources/**
- bot.py
types:
- opened
- synchronize
branches:
- main
- dev
jobs:
update-version:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Read current version
id: read_version
run: |
version_line=$(grep '__version__' __version__)
version=$(echo $version_line | sed -E 's/__version__:\s*v([0-9]+\.[0-9]+\.[0-9]+)(-.+)?/\1/')
echo "Current version: $version"
echo "current_version=$version" >> $GITHUB_OUTPUT
- name: Check for version file changes
id: check_diff
run: |
if git diff --name-only HEAD~1 HEAD | grep -q '__version__'; then
echo "Version file has changes"
echo "version_changed=true" >> $GITHUB_OUTPUT
else
echo "Version file has no changes"
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
- name: Get commit hash
id: get_commit_hash
run: echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Update version file
if: steps.check_diff.outputs.version_changed == 'false'
run: |
current_version="${{ steps.read_version.outputs.current_version }}"
commit_hash="${{ steps.get_commit_hash.outputs.commit_hash }}"
new_version="v${current_version}-${commit_hash}"
echo "Updating version to: $new_version"
echo "__version__: $new_version" > __version__
git config --global user.name "${{ github.event.pull_request.user.login }}"
git config --global user.email "${{ github.event.pull_request.user.login }}@users.noreply.github.com"
git add __version__
git remote set-url origin https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git
git commit -m "chore(version): Update version to $new_version"
git push origin HEAD:${{ github.event.pull_request.head.ref }}
- name: Check updated version
if: steps.check_diff.outputs.version_changed == 'false'
run: cat __version__
+2
View File
@@ -13,11 +13,13 @@
"getbbox", "getbbox",
"hibiapi", "hibiapi",
"httpx", "httpx",
"jsdelivr",
"kaiheila", "kaiheila",
"lolicon", "lolicon",
"nonebot", "nonebot",
"onebot", "onebot",
"pixiv", "pixiv",
"qbot",
"Setu", "Setu",
"tobytes", "tobytes",
"ujson", "ujson",
+53 -114
View File
@@ -60,7 +60,7 @@
<img width="350" height="350" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/help.png"/> <img width="350" height="350" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/help.png"/>
<img width="250" height="500" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/html_help.png"/> <img width="250" height="500" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/html_help.png"/>
<img width="180" height="450" src="https://github.com/HibiKier/zhenxun_bot/blob/dev/docs_image/zhenxun_help.png"/> <img width="180" height="450" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/zhenxun_help.png"/>
</div> </div>
@@ -68,11 +68,11 @@
### 1. 体验一下? ### 1. 体验一下?
这是一个免费的,版本为 dev 的 zhenxun,你可以通过 napcat 或拉格朗日等直接连接用于体验与测试 这是一个免费的,版本为 dev 的 zhenxun,你可以通过 [napcat](https://github.com/NapNeko/NapCatQQ) 或 [拉格朗日](https://github.com/LagrangeDev/Lagrange.Core) 以及 [matcha](https://github.com/A-kirami/matcha) 等直接连接用于体验与测试
(球球了测试君!) (球球了测试君!)
``` ```
Url: 43.143.112.57:11451/onebot/v11/ws Url: ws://test.zhenxun.org:8080/onebot/v11/ws
AccessToken: PUBLIC_ZHENXUN_TEST AccessToken: PUBLIC_ZHENXUN_TEST
注:你无法获得超级用户权限 注:你无法获得超级用户权限
@@ -95,13 +95,14 @@ AccessToken: PUBLIC_ZHENXUN_TEST
<details> <details>
<summary> <strong> WebUI </strong>后台示例图 </summary> <summary> <strong> WebUI </strong>后台示例图 </summary>
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui1.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui00.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui2.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui01.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui3.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui02.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui4.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui03.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui5.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui04.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui6.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui05.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui7.png) ![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui06.png)
![x](https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/webui07.png)
</details> </details>
@@ -111,7 +112,8 @@ AccessToken: PUBLIC_ZHENXUN_TEST
## ~~来点优点?~~ 可爱难道还不够吗 ## ~~来点优点?~~ 可爱难道还不够吗
- 实现了许多功能,且提供了大量功能管理命令 - 实现了许多功能,且提供了大量功能管理命令,进行了多平台适配,兼容 nb2 商店插件
- 拥有完善可用的 webui
- 通过 Config 配置项将所有插件配置统计保存至 config.yaml,利于统一用户修改 - 通过 Config 配置项将所有插件配置统计保存至 config.yaml,利于统一用户修改
- 方便增删插件,原生 nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息` - 方便增删插件,原生 nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
- 提供了 cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`PluginCdBlock` 等 - 提供了 cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`PluginCdBlock` 等
@@ -165,161 +167,97 @@ python bot.py
``` ```
<!-- ## 功能列表 (旧版列表) ## 功能列表
<details> <details>
<summary>已实现的功能</summary> <summary>内置功能</summary>
### 已实现的常用功能 **真寻原 `plugins` 插件文件夹已迁移至其他仓库,当前内置仅保留必要的功能**
- [x] 昵称系统(群与群与私聊分开.) ### 基础功能
- [x] 图灵 AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味 - [x] 昵称系统(群与群与私聊分开)
- [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置) - [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
- [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸) - [x] 商店/我的金币/购买道具/使用道具/金币排行(完整的商店添加/购买/使用流程)
- [x] 色图(这不是基础功能嘛喂)
- [x] coser
- [x] 黑白草图生成器
- [x] 鸡汤/语录
- [x] 骂我(钉宫语音)
- [x] 戳一戳(概率发送美图,钉宫语音或者戳回去)
- [x] 模拟开箱/我的开箱/群开箱统计/我的金色/设置 cookie(csgo,内置爬虫脚本,需要提前抓取数据和图片,需要 session,可能需要代理,阿里云服务器等 ip 也许已经被 ban 了(我无代理访问失败),如果访问太多账号 API 调用可能被禁止访问 api!)
- [x] 鲁迅说过
- [x] 构造假消息(自定义的分享链接)
- [x] 商店/我的金币/购买道具/使用道具
- [x] 8 种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
- [x] 我有一个朋友想问问..(借鉴 pcrbot 插件)
- [x] 原神黄历
- [x] 原神今日素材
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
- [x] 原神便笺查询
- [x] 原神玩家查询
- [x] 原神树脂提醒
- [x] 原神签到/自动签到
- [x] 金币红包
- [x] 微博热搜
- [x] B 站主播/UP/番剧订阅
- [x] pil 对图片的一些操作
- [x] BUFF 饰品底价查询(需要 session)
- [x] 天气查询
- [x] 疫情查询
- [x] bt 磁力搜索(咳咳,这功能我想 dddd)
- [x] reimu 搜索(上车) (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
- [x] 靠图识番 (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
- [x] 以图搜图 (使用[nonebot_plugin_picsearcher](https://github.com/synodriver/nonebot_plugin_picsearcher)插件)
- [x] 搜番
- [x] 点歌 [nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2)插件(删除了选歌和评论)
- [x] epic 免费游戏
- [x] p 站排行榜
- [x] p 站搜图
- [x] 翻译(日英韩)
- [x] pix 图库(一个自己的图库,含有增删查改,黑名单等命令)
- [x] 查看当前群欢迎消息 - [x] 查看当前群欢迎消息
- [x] 查看该群自己的权限 - [x] 个人信息查看(群组内权限,聊天频率等)
- [x] 我的信息(只是为了看看什么时候入群) - [x] 消息撤回
- [x] 更新信息(如果继续更新的话)
- [x] go-cqhttp 最新版下载和上传(不需要请删除)
- [x] 撤回
- [x] 滴滴滴-(用户对超级用户发送消息)
- [x] 金币红包/金币排行
- [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
- [x] 网易云热评
- [x] 念首古诗
- [x] 获取 b 站视频封面
- [x] 通过 PID 获取图片
- [x] 功能统计可视化 - [x] 功能统计可视化
- [x] 词云
- [x] 关于 - [x] 关于
- [x] 三种样式的帮助菜单
### 已实现的管理员功能 ### 管理员功能
- [x] 管理员帮助
- [x] 更新群组成员信息 - [x] 更新群组成员信息
- [x] 95%的群功能开关 - [x] 95%的群功能开关
- [x] 查看群内被动技能状态 - [x] 查看群内被动技能状态
- [x] 自定义群欢迎消息(是真寻的不是管家的!) - [x] 自定义群欢迎消息(是真寻的不是管家的!)
- [x] .ban/.unban(支持设置 ban 时长)= 黑白名单 - [x] ban/unban(支持设置 ban 时长)= 群组及用户的黑名单
- [x] 刷屏禁言相关:刷屏检测设置/设置禁言时长/设置检测次数 - [x] 休息吧/醒来(群组内真寻状态)
- [x] 上传图片/连续上传图片 (上传图片至指定图库)
- [x] 移动图片 (同上)
- [x] 删除图片 (同上)
- [x] 群内 B 站订阅
- [x] 词条设置
- [x] 休息吧/醒来
### 已实现的超级用户功能 ### 超级用户功能
- [x] 超级用户帮助
- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员) - [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
- [x] 群组管理,退群指令等
- [x] 开启/关闭指定群的广播通知
- [x] 广播 - [x] 广播
- [x] 自检(检查系统状态) - [x] 自检(检查系统状态)
- [x] 所有群组/所有好友 - [x] 所有群组/所有好友
- [x] 退出指定群 - [x] 退出指定群
- [x] 更新好友信息/更新群信息 - [x] 更新好友信息/更新群信息
- [x] /t(对用户进行回复或发送消息)
- [x] 上传/删除/修改商品(需要编写对应的商品功能)
- [x] 节日红包发送
- [x] 修改群权限 - [x] 修改群权限
- [x] ban - [x] 检查更新
- [x] 更新色图
- [x] 更新价格/更加图片(csgo 开箱)
- [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
- [x] 更新原神今日素材/更新原神资源信息
- [x] PIX 相关操作
- [x] 检查更新真寻
- [x] 重启 - [x] 重启
- [x] 添加/删除/查看群白名单 - [x] 添加/删除/查看群白名单
- [x] 功能开关(更多设置) - [x] 功能开关(更多设置)
- [x] 功能状态 - [x] 功能状态
- [x] b 了 - [x] 执行 SQL
- [x] 执行 sql
- [x] 重载配置 - [x] 重载配置
- [x] 清理临时数据 - [x] 清理临时数据
- [x] 增删群认证 - [x] 增删群认证
- [x] 同意/拒绝好友/群聊请求 - [x] 同意/拒绝好友/群聊请求
- [x] 配置重载 - [x] 添加/移除/更新插件/插件商店(plugins 库以及扩展库)
- [x] WebUI API(对真寻前端的支持)
#### 超级用户的被动技能 #### 超级用户的被动技能
- [x] 邀请入群提醒(别人邀请真寻入群) - [x] 邀请入群提醒(别人邀请真寻入群,可配置自动同意)
- [x] 添加好友提醒(别人添加真寻好友) - [x] 添加好友提醒(别人添加真寻好友,可配置自动同意)
### 已实现的被动技能 ### 被动技能
- [x] 进群欢迎消息
- [x] 群早晚安 - [x] 群早晚安
- [x] 每日开箱重置提醒
- [x] b 站转发解析(解析 b 站分享信息,支持 bv,bilibili 链接,b 站手机端转发卡片,cv,b23.tv),且 5 分钟内不解析相同 url
- [x] 丢人爬(爬表情包)
- [x] epic 通知(每日发送 epic 免费游戏链接)
- [x] 原神黄历提醒
- [x] 复读
### 已实现的看不见的技能 ### 看不见的技能
- [x] 刷屏禁言检测
- [x] 功能调用统计 - [x] 功能调用统计
- [x] 聊天记录统计
- [x] 检测恶意触发命令(将被最高权限 ban 掉 30 分钟,只有最高权限(9 级)可以进行 unban) - [x] 检测恶意触发命令(将被最高权限 ban 掉 30 分钟,只有最高权限(9 级)可以进行 unban)
- [x] 自动同意好友请求,加群请求将会提醒管理员,退群提示,加群欢迎等等 - [x] 自动同意好友/群组请求,加群请求将会提醒管理员,退群提示,加群欢迎等等
- [x] 群聊时间检测(当群聊最后一人发言时间大于当前 36 小时后将关闭该群所有通知(即被动技能)) - [x] 群聊时间检测(当群聊最后一人发言时间大于当前 48 小时后将关闭该群所有通知(即被动技能))
- [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限 - [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
- [x] 群权限系统 - [x] 群权限系统
- [x] 定时更新权限 - [x] 定时更新权限
- [x] 自动配置重载 - [x] 自动配置重载
- [x] 强制入群保护
- [x] 自定备份(可配置)
- [x] 笨蛋检测(当使用功能名称当指令时真寻会跳出来狠狠嘲笑并帮助)
</details> --> ### 更多插件...
## [爱发电](https://afdian.net/@HibiKier) - [更多插件](https://github.com/zhenxun-org/zhenxun_bot_plugins)
- [第三方插件索引库](https://github.com/zhenxun-org/zhenxun_bot_plugins_index)
</details>
## [爱发电](https://afdian.com/a/HibiKier)
<details> <details>
<summary>爱发电 以及 感谢投喂 </summary> <summary>爱发电 以及 感谢投喂 </summary>
<img width="365px" height="450px" src="https://user-images.githubusercontent.com/45528451/175059389-cfeb8174-fa07-4939-80ab-a039087a50f6.png"> <img width="365px" height="450px" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/afd.jpg">
### 感谢名单 ### 感谢名单
@@ -369,6 +307,7 @@ python bot.py
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377) [哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
[yajiwa](https://github.com/yajiwa) [yajiwa](https://github.com/yajiwa)
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377) [爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
...
</details> </details>
+1 -1
View File
@@ -1 +1 @@
__version__: v0.2.4 __version__: v0.2.4-fix2
Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

BIN
View File
Binary file not shown.
+6
View File
@@ -19,6 +19,8 @@ require("nonebot_plugin_htmlrender")
from zhenxun.services.log import logger from zhenxun.services.log import logger
from zhenxun.models.sign_user import SignUser from zhenxun.models.sign_user import SignUser
from zhenxun.models.goods_info import GoodsInfo from zhenxun.models.goods_info import GoodsInfo
from zhenxun.utils.platform import PlatformUtils
from zhenxun.models.bot_console import BotConsole
from zhenxun.models.user_console import UserConsole from zhenxun.models.user_console import UserConsole
from zhenxun.utils.decorator.shop import shop_register from zhenxun.utils.decorator.shop import shop_register
from zhenxun.models.bot_connect_log import BotConnectLog from zhenxun.models.bot_connect_log import BotConnectLog
@@ -33,6 +35,10 @@ async def _(bot: Bot):
await BotConnectLog.create( await BotConnectLog.create(
bot_id=bot.self_id, platform=bot.adapter, connect_time=datetime.now(), type=1 bot_id=bot.self_id, platform=bot.adapter, connect_time=datetime.now(), type=1
) )
if not await BotConsole.exists(bot_id=bot.self_id):
await BotConsole.create(
bot_id=bot.self_id, platform=PlatformUtils.get_platform(bot)
)
@driver.on_bot_disconnect @driver.on_bot_disconnect
+16 -1
View File
@@ -11,6 +11,7 @@ from zhenxun.services.log import logger
from zhenxun.configs.config import Config from zhenxun.configs.config import Config
from zhenxun.utils.message import MessageUtils from zhenxun.utils.message import MessageUtils
from zhenxun.models.level_user import LevelUser from zhenxun.models.level_user import LevelUser
from zhenxun.models.bot_console import BotConsole
from zhenxun.models.plugin_info import PluginInfo from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.plugin_limit import PluginLimit from zhenxun.models.plugin_limit import PluginLimit
from zhenxun.models.user_console import UserConsole from zhenxun.models.user_console import UserConsole
@@ -234,7 +235,10 @@ class AuthChecker:
return return
if plugin := await PluginInfo.get_or_none(module_path=module_path): if plugin := await PluginInfo.get_or_none(module_path=module_path):
if plugin.plugin_type == PluginType.HIDDEN: if plugin.plugin_type == PluginType.HIDDEN:
logger.debug("插件为HIDDEN,已跳过...") logger.debug(
f"插件: {plugin.name}:{plugin.module} "
"为HIDDEN,已跳过权限检查..."
)
return return
try: try:
cost_gold = await self.auth_cost(user, plugin, session) cost_gold = await self.auth_cost(user, plugin, session)
@@ -244,6 +248,7 @@ class AuthChecker:
if not plugin.limit_superuser: if not plugin.limit_superuser:
cost_gold = 0 cost_gold = 0
raise IsSuperuserException() raise IsSuperuserException()
await self.auth_bot(plugin, bot.self_id)
await self.auth_group(plugin, session, message) await self.auth_group(plugin, session, message)
await self.auth_admin(plugin, session) await self.auth_admin(plugin, session)
await self.auth_plugin(plugin, session, event) await self.auth_plugin(plugin, session, event)
@@ -278,6 +283,16 @@ class AuthChecker:
if is_ignore: if is_ignore:
raise IgnoredException("权限检测 ignore") raise IgnoredException("权限检测 ignore")
async def auth_bot(self, plugin: PluginInfo, bot_id: str):
"""机器人权限
参数:
plugin: PluginInfo
bot_id: bot_id
"""
if await BotConsole.is_block_plugin(plugin.module, bot_id):
raise IgnoredException("机器人权限检测 ignore")
async def auth_limit(self, plugin: PluginInfo, session: EventSession): async def auth_limit(self, plugin: PluginInfo, session: EventSession):
"""插件限制 """插件限制
+1 -1
View File
@@ -32,7 +32,7 @@ async def _(
if plugin := matcher.plugin: if plugin := matcher.plugin:
if metadata := plugin.metadata: if metadata := plugin.metadata:
extra = metadata.extra extra = metadata.extra
if extra.get("plugin_type") in [PluginType.HIDDEN, PluginType.DEPENDANT]: if extra.get("plugin_type") in [PluginType.HIDDEN]:
return return
user_id = session.id1 user_id = session.id1
group_id = session.id3 or session.id2 group_id = session.id3 or session.id2
@@ -0,0 +1,23 @@
from typing import Any
from nonebot.adapters import Bot
from zhenxun.services.log import logger
from zhenxun.utils.manager.message_manager import MessageManager
@Bot.on_called_api
async def handle_api_result(
bot: Bot, exception: Exception | None, api: str, data: dict[str, Any], result: Any
):
if not exception and api == "send_msg":
try:
if (uid := data.get("user_id")) and (msg_id := result.get("message_id")):
MessageManager.add(str(uid), str(msg_id))
logger.debug(
f"收集消息id,user_id: {uid}, msg_id: {msg_id}", "msg_hook"
)
except Exception as e:
logger.warning(
f"收集消息id发生错误...data: {data}, result: {result}", "msg_hook", e=e
)
+1 -1
View File
@@ -46,7 +46,7 @@ async def _(
nickname = user_id nickname = user_id
try: try:
result = await get_user_info( result = await get_user_info(
session, bot, user_id, session.group.id if session.group else None, nickname session, user_id, session.group.id if session.group else None, nickname
) )
await MessageUtils.build_message(result).send(at_sender=True) await MessageUtils.build_message(result).send(at_sender=True)
logger.info("获取用户信息", arparma.header_result, session=session) logger.info("获取用户信息", arparma.header_result, session=session)
+3 -4
View File
@@ -1,7 +1,6 @@
import random import random
from datetime import datetime, timedelta from datetime import datetime, timedelta
from nonebot.adapters import Bot
from tortoise.functions import Count from tortoise.functions import Count
from tortoise.expressions import RawSQL from tortoise.expressions import RawSQL
from nonebot_plugin_uninfo import Uninfo from nonebot_plugin_uninfo import Uninfo
@@ -131,7 +130,7 @@ async def get_chat_history(
async def get_user_info( async def get_user_info(
session: Uninfo, bot: Bot, user_id: str, group_id: str | None, nickname: str session: Uninfo, user_id: str, group_id: str | None, nickname: str
) -> bytes: ) -> bytes:
"""获取用户个人信息 """获取用户个人信息
@@ -145,7 +144,7 @@ async def get_user_info(
返回: 返回:
bytes: 图片数据 bytes: 图片数据
""" """
platform = PlatformUtils.get_platform(bot) or "" platform = PlatformUtils.get_platform(session) or "qq"
ava_url = PlatformUtils.get_user_avatar_url(user_id, platform) ava_url = PlatformUtils.get_user_avatar_url(user_id, platform)
user = await UserConsole.get_user(user_id, platform) user = await UserConsole.get_user(user_id, platform)
level = await LevelUser.get_user_level(user_id, group_id) level = await LevelUser.get_user_level(user_id, group_id)
@@ -164,7 +163,7 @@ async def get_user_info(
data = { data = {
"date": now.date(), "date": now.date(),
"weather": weather, "weather": weather,
"ava_url": session.user.avatar, "ava_url": ava_url,
"nickname": nickname, "nickname": nickname,
"title": "勇 者", "title": "勇 者",
"race": random.choice(RACE), "race": random.choice(RACE),
+22 -24
View File
@@ -1,30 +1,31 @@
import random import random
from typing import Any, List from typing import Any
from nonebot import on_regex from nonebot import on_regex
from nonebot.adapters import Bot
from nonebot.params import Depends, RegexGroup
from nonebot.plugin import PluginMetadata
from nonebot.rule import to_me from nonebot.rule import to_me
from nonebot_plugin_alconna import Alconna, Option, on_alconna, store_true from nonebot.adapters import Bot
from nonebot.plugin import PluginMetadata
from nonebot.params import Depends, RegexGroup
from nonebot_plugin_session import EventSession from nonebot_plugin_session import EventSession
from nonebot_plugin_userinfo import EventUserInfo, UserInfo from nonebot_plugin_userinfo import UserInfo, EventUserInfo
from nonebot_plugin_alconna import Option, Alconna, on_alconna, store_true
from zhenxun.configs.config import BotConfig, Config from zhenxun.services.log import logger
from zhenxun.configs.utils import PluginExtraData, RegisterConfig from zhenxun.utils.enum import PluginType
from zhenxun.utils.depends import UserName
from zhenxun.utils.message import MessageUtils
from zhenxun.models.ban_console import BanConsole from zhenxun.models.ban_console import BanConsole
from zhenxun.models.friend_user import FriendUser from zhenxun.models.friend_user import FriendUser
from zhenxun.configs.config import Config, BotConfig
from zhenxun.models.group_member_info import GroupInfoUser from zhenxun.models.group_member_info import GroupInfoUser
from zhenxun.services.log import logger from zhenxun.configs.utils import RegisterConfig, PluginExtraData
from zhenxun.utils.depends import UserName
from zhenxun.utils.enum import PluginType
from zhenxun.utils.message import MessageUtils
__plugin_meta__ = PluginMetadata( __plugin_meta__ = PluginMetadata(
name="昵称系统", name="昵称系统",
description="区区昵称,才不想叫呢!", description="区区昵称,才不想叫呢!",
usage=f""" usage=f"""
个人昵称,将替换{BotConfig.self_nickname}称呼你的名称,群聊 与 私聊 昵称相互独立,全局昵称设置将更改您目前所有群聊中及私聊的昵称 个人昵称,将替换{BotConfig.self_nickname}称呼你的名称,群聊 与 私聊 昵称相互独立,
全局昵称设置将更改您目前所有群聊中及私聊的昵称
指令: 指令:
以后叫我 [昵称]: 设置当前群聊/私聊的昵称 以后叫我 [昵称]: 设置当前群聊/私聊的昵称
全局昵称设置 [昵称]: 设置当前所有群聊和私聊的昵称 全局昵称设置 [昵称]: 设置当前所有群聊和私聊的昵称
@@ -39,9 +40,10 @@ __plugin_meta__ = PluginMetadata(
RegisterConfig( RegisterConfig(
key="BLACK_WORD", key="BLACK_WORD",
value=["爸", "爹", "爷", "父"], value=["爸", "爹", "爷", "父"],
help="昵称所屏蔽的关键词,已设置的昵称会被替换为 *,未设置的昵称会在设置时提示", help="昵称所屏蔽的关键词,已设置的昵称会被替换为 *,"
"未设置的昵称会在设置时提示",
default_value=None, default_value=None,
type=List[str], type=list[str],
) )
], ],
).dict(), ).dict(),
@@ -167,9 +169,8 @@ async def _(
): ):
if session.id1: if session.id1:
(name,) = reg_group (name,) = reg_group
if len(name) < 5: if len(name) < 5 and random.random() < 0.3:
if random.random() < 0.3: name = "~".join(name)
name = "~".join(name)
if gid := session.id3 or session.id2: if gid := session.id3 or session.id2:
await GroupInfoUser.set_user_nickname( await GroupInfoUser.set_user_nickname(
session.id1, session.id1,
@@ -181,9 +182,6 @@ async def _(
session.platform, session.platform,
) )
logger.info(f"设置群昵称成功: {name}", "昵称设置", session=session) logger.info(f"设置群昵称成功: {name}", "昵称设置", session=session)
await MessageUtils.build_message(
random.choice(CALL_NAME).format(name)
).finish(reply_to=True)
else: else:
await FriendUser.set_user_nickname( await FriendUser.set_user_nickname(
session.id1, session.id1,
@@ -194,9 +192,9 @@ async def _(
session.platform, session.platform,
) )
logger.info(f"设置私聊昵称成功: {name}", "昵称设置", session=session) logger.info(f"设置私聊昵称成功: {name}", "昵称设置", session=session)
await MessageUtils.build_message( await MessageUtils.build_message(random.choice(CALL_NAME).format(name)).finish(
random.choice(CALL_NAME).format(name) reply_to=True
).finish(reply_to=True) )
await MessageUtils.build_message("用户id为空...").send() await MessageUtils.build_message("用户id为空...").send()
@@ -1,321 +0,0 @@
import os
import re
import random
from datetime import datetime
import ujson as json
from nonebot.adapters import Bot
from nonebot_plugin_alconna import At
from nonebot import on_notice, on_request
from nonebot.plugin import PluginMetadata
from nonebot.adapters.onebot.v11 import (
GroupDecreaseNoticeEvent,
GroupIncreaseNoticeEvent,
)
from nonebot.adapters.onebot.v12 import (
GroupMemberDecreaseEvent,
GroupMemberIncreaseEvent,
)
from zhenxun.services.log import logger
from zhenxun.utils.utils import FreqLimiter
from zhenxun.utils.message import MessageUtils
from zhenxun.models.fg_request import FgRequest
from zhenxun.models.level_user import LevelUser
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.utils.common_utils import CommonUtils
from zhenxun.configs.config import Config, BotConfig
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.group_member_info import GroupInfoUser
from zhenxun.utils.enum import PluginType, RequestHandleType
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
from zhenxun.configs.utils import Task, RegisterConfig, PluginExtraData
__plugin_meta__ = PluginMetadata(
name="QQ群事件处理",
description="群事件处理",
usage="",
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.HIDDEN,
configs=[
RegisterConfig(
module="invite_manager",
key="message",
value=f"请不要未经同意就拉{BotConfig.self_nickname}入群!告辞!",
help="强制拉群后进群回复的内容",
),
RegisterConfig(
module="invite_manager",
key="flag",
value=True,
help="强制拉群后进群退出并回复内容",
default_value=True,
type=bool,
),
RegisterConfig(
module="invite_manager",
key="welcome_msg_cd",
value=5,
help="群欢迎消息cd",
default_value=5,
type=int,
),
RegisterConfig(
module="_task",
key="DEFAULT_GROUP_WELCOME",
value=True,
help="被动 进群欢迎 进群默认开关状态",
default_value=True,
type=bool,
),
RegisterConfig(
module="_task",
key="DEFAULT_REFUND_GROUP_REMIND",
value=True,
help="被动 退群提醒 进群默认开关状态",
default_value=True,
type=bool,
),
],
tasks=[
Task(module="group_welcome", name="进群欢迎"),
Task(module="refund_group_remind", name="退群提醒"),
],
).dict(),
)
base_config = Config.get("invite_manager")
limit_cd = base_config.get("welcome_msg_cd")
_flmt = FreqLimiter(limit_cd)
group_increase_handle = on_notice(priority=1, block=False)
"""群员增加处理"""
group_decrease_handle = on_notice(priority=1, block=False)
"""群员减少处理"""
add_group = on_request(priority=1, block=False)
"""加群同意请求"""
@group_increase_handle.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent | GroupMemberIncreaseEvent):
superusers = BotConfig.get_superuser("qq")
user_id = str(event.user_id)
group_id = str(event.group_id)
if user_id == bot.self_id:
"""新成员为bot本身"""
group = await GroupConsole.get_or_none(
group_id=group_id, channel_id__isnull=True
)
if not group or group.group_flag == 0:
"""群聊不存在或被强制拉群"""
if base_config.get("flag"):
"""退出群组"""
try:
if result_msg := base_config.get("message"):
await bot.send_group_msg(
group_id=event.group_id, message=result_msg
)
await bot.set_group_leave(group_id=event.group_id)
if superusers:
await bot.send_private_msg(
user_id=int(superusers[0]),
message=f"触发强制入群保护,已成功退出群聊 {group_id}...",
)
logger.info(
"强制拉群或未有群信息,退出群聊成功",
"入群检测",
group_id=event.group_id,
)
if req := await FgRequest.get_or_none(
group_id=group_id, handle_type__isnull=True
):
req.handle_type = RequestHandleType.IGNORE
await req.save(update_fields=["handle_type"])
except Exception as e:
logger.error(
"强制拉群或未有群信息,退出群聊失败",
"入群检测",
group_id=event.group_id,
e=e,
)
if superusers:
await bot.send_private_msg(
user_id=int(superusers[0]),
message="触发强制入群保护,"
f"退出群聊 {event.group_id} 失败...",
)
await GroupConsole.filter(group_id=group_id).delete()
else:
"""允许群组并设置群认证,默认群功能开关"""
if group:
await GroupConsole.filter(
group_id=group_id, channel_id__isnull=True
).update(group_flag=1)
else:
block_plugin = ""
if plugin_list := await PluginInfo.filter(
default_status=False
).all():
for plugin in plugin_list:
block_plugin += f"{plugin.module},"
group_info = await bot.get_group_info(group_id=event.group_id)
await GroupConsole.create(
group_id=group_info["group_id"],
group_name=group_info["group_name"],
max_member_count=group_info["max_member_count"],
member_count=group_info["member_count"],
group_flag=1,
block_plugin=block_plugin,
platform="qq",
)
"""刷新群管理员权限"""
admin_default_auth = Config.get_config(
"admin_bot_manage", "ADMIN_DEFAULT_AUTH"
)
# 即刻刷新权限
for user_info in await bot.get_group_member_list(
group_id=event.group_id
):
"""即刻刷新权限"""
if (
user_info["role"]
in [
"owner",
"admin",
]
and not await LevelUser.is_group_flag(
user_info["user_id"], group_id
)
and admin_default_auth is not None
):
await LevelUser.set_level(
user_info["user_id"],
user_info["group_id"],
admin_default_auth,
)
logger.debug(
f"添加默认群管理员权限: {admin_default_auth}",
"入群检测",
session=user_info["user_id"],
group_id=user_info["group_id"],
)
if str(user_info["user_id"]) in bot.config.superusers:
await LevelUser.set_level(
user_info["user_id"], user_info["group_id"], 9
)
logger.debug(
"添加超级用户权限: 9",
"入群检测",
session=user_info["user_id"],
group_id=user_info["group_id"],
)
else:
join_time = datetime.now()
user_info = await bot.get_group_member_info(
group_id=event.group_id, user_id=event.user_id
)
await GroupInfoUser.update_or_create(
user_id=str(user_info["user_id"]),
group_id=str(user_info["group_id"]),
defaults={"user_name": user_info["nickname"], "user_join_time": join_time},
)
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
if _flmt.check(group_id):
"""群欢迎消息"""
_flmt.start_cd(group_id)
path = DATA_PATH / "welcome_message" / "qq" / f"{group_id}"
file = path / "text.json"
msg_list = []
if file.exists():
data = json.load((path / "text.json").open(encoding="utf-8"))
message = data["message"]
msg_split = re.split(r"\[image:\d+\]", message)
if data["at"]:
msg_list.append(At(flag="user", target=user_id))
for i, text in enumerate(msg_split):
msg_list.append(text)
img_file = path / f"{i}.png"
if img_file.exists():
msg_list.append(img_file)
if not await CommonUtils.task_is_block("group_welcome", group_id):
logger.info("发送群欢迎消息...", "入群检测", group_id=group_id)
if msg_list:
await MessageUtils.build_message(msg_list).send()
else:
image = (
IMAGE_PATH
/ "qxz"
/ random.choice(os.listdir(IMAGE_PATH / "qxz"))
)
await MessageUtils.build_message(
[
"新人快跑啊!!本群现状↓(快使用自定义!)",
image,
]
).send()
@group_decrease_handle.handle()
async def _(bot: Bot, event: GroupDecreaseNoticeEvent | GroupMemberDecreaseEvent):
if event.sub_type == "kick_me":
"""踢出Bot"""
group_id = event.group_id
operator_id = event.operator_id
if user := await GroupInfoUser.get_or_none(
user_id=str(event.operator_id), group_id=str(event.group_id)
):
operator_name = user.user_name
else:
operator_name = "None"
group = await GroupConsole.filter(group_id=str(group_id)).first()
group_name = group.group_name if group else ""
if superusers := BotConfig.get_superuser("qq"):
coffee = int(superusers[0])
await bot.send_private_msg(
user_id=coffee,
message=f"****呜..一份踢出报告****\n"
f"我被 {operator_name}({operator_id})\n"
f"踢出了 {group_name}({group_id})\n"
f"日期:{str(datetime.now()).split('.')[0]}",
)
if group:
await group.delete()
return
if str(event.user_id) == bot.self_id:
"""踢出Bot"""
await GroupConsole.filter(group_id=str(event.group_id)).delete()
return
if user := await GroupInfoUser.get_or_none(
user_id=str(event.user_id), group_id=str(event.group_id)
):
user_name = user.user_name
else:
user_name = f"{event.user_id}"
await GroupInfoUser.filter(
user_id=str(event.user_id), group_id=str(event.group_id)
).delete()
logger.info(
f"名称: {user_name} 退出群聊",
"group_decrease_handle",
session=event.user_id,
group_id=event.group_id,
)
result = ""
if event.sub_type == "leave":
result = f"{user_name}离开了我们..."
if event.sub_type == "kick":
operator = await bot.get_group_member_info(
user_id=event.operator_id, group_id=event.group_id
)
operator_name = operator["card"] or operator["nickname"]
result = f"{user_name} 被 {operator_name} 送走了."
if not await CommonUtils.task_is_block("refund_group_remind", str(event.group_id)):
await group_decrease_handle.send(f"{result}")
@@ -49,9 +49,8 @@ class GroupManager:
group: GroupConsole group: GroupConsole
""" """
if group: if group:
await GroupConsole.filter( group.group_flag = 1
group_id=group_id, channel_id__isnull=True await group.save(update_fields=["group_flag"])
).update(group_flag=1)
else: else:
block_plugin = "" block_plugin = ""
if plugin_list := await PluginInfo.filter(default_status=False).all(): if plugin_list := await PluginInfo.filter(default_status=False).all():
@@ -113,7 +112,7 @@ class GroupManager:
@classmethod @classmethod
async def add_bot( async def add_bot(
cls, bot: Bot, operator_id: str, group_id: str, group: GroupConsole | None cls, bot: Bot, operator_id: str, group_id: str, group: GroupConsole
): ):
"""拉入bot """拉入bot
@@ -123,7 +122,11 @@ class GroupManager:
group_id: 群组id group_id: 群组id
group: GroupConsole group: GroupConsole
""" """
if base_config.get("flag") and operator_id not in bot.config.superusers: if (
base_config.get("flag")
and operator_id not in bot.config.superusers
and group.group_flag != 1
):
"""退出群组""" """退出群组"""
try: try:
if result_msg := base_config.get("message"): if result_msg := base_config.get("message"):
+1 -1
View File
@@ -184,7 +184,7 @@ async def _(
elif isinstance(result, UniMessage): elif isinstance(result, UniMessage):
await result.finish(reply_to=True) await result.finish(reply_to=True)
except GoodsNotFound: except GoodsNotFound:
await MessageUtils.build_message(f"没有找到道具 {name} 或道具数量不足...").send( await MessageUtils.build_message(f"没有找到道具 {name.result} 或道具数量不足...").send(
reply_to=True reply_to=True
) )
@@ -0,0 +1,30 @@
import os
import time
from nonebot.rule import to_me
from nonebot.utils import run_sync
from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata
from nonebot_plugin_session import EventSession
from nonebot_plugin_apscheduler import scheduler
from nonebot_plugin_alconna import Alconna, on_alconna
from zhenxun.services.log import logger
from zhenxun.utils.enum import PluginType
from zhenxun.utils.message import MessageUtils
from zhenxun.configs.path_config import TEMP_PATH
from zhenxun.configs.utils import PluginExtraData
from zhenxun.utils.utils import ResourceDirManager
__plugin_meta__ = PluginMetadata(
name="Bot管理",
description="指定bot对象的功能/被动开关和状态",
usage="""
清理临时数据
""".strip(),
extra=PluginExtraData(
author="",
version="0.1",
plugin_type=PluginType.SUPERUSER,
).dict(),
)
+61
View File
@@ -0,0 +1,61 @@
from nonebot.rule import Rule
from nonebot.adapters import Bot, Event
from nonebot_plugin_uninfo import Uninfo
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna.uniseg.tools import reply_fetch
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
from zhenxun.services.log import logger
from zhenxun.utils.message import MessageUtils
from zhenxun.utils.platform import PlatformUtils
from zhenxun.configs.utils import PluginExtraData
from zhenxun.utils.manager.message_manager import MessageManager
__plugin_meta__ = PluginMetadata(
name="消息撤回",
description="撤回自己触发的消息撤回,不允许撤回其他人触发消息的撤回哦",
usage="""
引用消息 撤回
""".strip(),
extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").dict(),
)
def reply_check() -> Rule:
"""
检查是否存在回复消息
返回:
Rule: Rule
"""
async def _rule(bot: Bot, event: Event, session: Uninfo):
if event.get_type() == "message":
return (
bool(await reply_fetch(event, bot))
and PlatformUtils.get_platform(session) == "qq"
)
return False
return Rule(_rule)
_matcher = on_alconna(Alconna("撤回"), priority=5, block=True, rule=reply_check())
@_matcher.handle()
async def _(bot: Bot, event: Event, session: Uninfo, arparma: Arparma):
if reply := await reply_fetch(event, bot):
if (
MessageManager.check(session.user.id, reply.id)
or session.user.id in bot.config.superusers
):
try:
await bot.delete_msg(message_id=reply.id)
logger.info("撤回消息", arparma.header_result, session=session)
except Exception:
await MessageUtils.build_message("撤回失败,可能消息已过期...").send()
else:
await MessageUtils.build_message(
"权限不足,不是你触发的消息不要胡乱撤回哦..."
).send()
+6 -13
View File
@@ -288,13 +288,6 @@ class ConfigsManager:
config.value = value config.value = value
config.default_value = default_value config.default_value = default_value
else: else:
_module = None
if ":" in module:
module_split = module.split(":")
if len(module_split) < 2:
raise ValueError(f"module: {module} 填写错误")
_module = module_split[-1]
module = module_split[0]
key = key.upper() key = key.upper()
if not self._data.get(module): if not self._data.get(module):
self._data[module] = ConfigGroup(module=module) self._data[module] = ConfigGroup(module=module)
@@ -311,7 +304,6 @@ class ConfigsManager:
key: str, key: str,
value: Any, value: Any,
auto_save: bool = False, auto_save: bool = False,
save_simple_data: bool = True,
): ):
"""设置配置值 """设置配置值
@@ -320,15 +312,16 @@ class ConfigsManager:
key: 配置名称 key: 配置名称
value: 值 value: 值
auto_save: 自动保存. auto_save: 自动保存.
save_simple_data: 保存至config.yaml.
""" """
key = key.upper()
if module in self._data: if module in self._data:
data = self._data[module].configs.get(key) if self._data[module].configs.get(key):
if data and data != value:
self._data[module].configs[key].value = value self._data[module].configs[key].value = value
self._simple_data[module][key] = value else:
self.add_plugin_config(module, key, value)
self._simple_data[module][key] = value
if auto_save: if auto_save:
self.save(save_simple_data=save_simple_data) self.save(save_simple_data=True)
def get_config(self, module: str, key: str, default: Any = None) -> Any: def get_config(self, module: str, key: str, default: Any = None) -> Any:
"""获取指定配置值 """获取指定配置值
+60
View File
@@ -0,0 +1,60 @@
from tortoise import fields
from zhenxun.services.db_context import Model
class BotConsole(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
bot_id = fields.CharField(255, unique=True, description="bot_id")
"""bot_id"""
status = fields.BooleanField(default=True, description="Bot状态")
"""Bot状态"""
block_plugin = fields.TextField(default="", description="禁用插件")
"""禁用插件"""
block_task = fields.TextField(default="", description="禁用被动技能")
"""禁用被动技能"""
create_time = fields.DatetimeField(auto_now_add=True, description="创建时间")
"""创建时间"""
platform = fields.CharField(255, null=True, description="平台")
"""平台"""
class Meta: # type: ignore
table = "bot_console"
table_description = "Bot数据表"
@classmethod
async def get_bot_status(cls, bot_id: str) -> bool:
result = await cls.get_or_none(bot_id=bot_id)
return result.status if result else False
@classmethod
async def set_block_plugin(cls, bot_id: str, module: str):
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
if f"<{module}," not in bot_data.block_plugin:
bot_data.block_plugin += f"<{module},"
await bot_data.save(update_fields=["block_plugin"])
@classmethod
async def set_unblock_plugin(cls, bot_id: str, module: str):
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
if f"<{module}," in bot_data.block_plugin:
bot_data.block_plugin = bot_data.block_plugin.replace(f"<{module},", "")
await bot_data.save(update_fields=["block_plugin"])
@classmethod
async def set_block_task(cls, bot_id: str, task: str):
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
if f"<{task}," not in bot_data.block_task:
bot_data.block_plugin += f"<{task},"
await bot_data.save(update_fields=["block_task"])
@classmethod
async def is_block_plugin(cls, bot_id: str, task: str) -> bool:
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
return f"<{task}," in bot_data.block_plugin
@classmethod
async def is_block_task(cls, bot_id: str, task: str) -> bool:
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
return f"<{task}," in bot_data.block_task
+5 -7
View File
@@ -1,5 +1,5 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Literal, Tuple from typing import Literal
from tortoise import fields from tortoise import fields
from tortoise.functions import Count from tortoise.functions import Count
@@ -27,7 +27,7 @@ class ChatHistory(Model):
platform = fields.CharField(255, null=True) platform = fields.CharField(255, null=True)
"""平台""" """平台"""
class Meta: class Meta: # type: ignore
table = "chat_history" table = "chat_history"
table_description = "聊天记录数据表" table_description = "聊天记录数据表"
@@ -53,7 +53,7 @@ class ChatHistory(Model):
query = query.filter(create_time__range=date_scope) query = query.filter(create_time__range=date_scope)
return list( return list(
await query.annotate(count=Count("user_id")) await query.annotate(count=Count("user_id"))
.order_by(o + "count") .order_by(f"{o}count")
.group_by("user_id") .group_by("user_id")
.limit(limit) .limit(limit)
.values_list("user_id", "count") .values_list("user_id", "count")
@@ -74,9 +74,7 @@ class ChatHistory(Model):
) )
else: else:
message = await cls.all().order_by("create_time").first() message = await cls.all().order_by("create_time").first()
if message: return message.create_time if message else None
return message.create_time
return None
@classmethod @classmethod
async def get_message( async def get_message(
@@ -85,7 +83,7 @@ class ChatHistory(Model):
gid: str, gid: str,
type_: Literal["user", "group"], type_: Literal["user", "group"],
msg_type: Literal["private", "group"] | None = None, msg_type: Literal["private", "group"] | None = None,
days: int | Tuple[datetime, datetime] | None = None, days: int | tuple[datetime, datetime] | None = None,
) -> list[Self]: ) -> list[Self]:
"""获取消息查询query """获取消息查询query
+2 -2
View File
@@ -37,8 +37,8 @@ class GroupConsole(Model):
default="", description="超级用户禁用插件" default="", description="超级用户禁用插件"
) )
"""超级用户禁用插件""" """超级用户禁用插件"""
block_task = fields.TextField(default="", description="禁用插件") block_task = fields.TextField(default="", description="禁用被动技能")
"""禁用插件""" """禁用被动技能"""
superuser_block_task = fields.TextField(default="", description="超级用户禁用被动") superuser_block_task = fields.TextField(default="", description="超级用户禁用被动")
"""超级用户禁用被动""" """超级用户禁用被动"""
platform = fields.CharField(255, default="qq", description="所属平台") platform = fields.CharField(255, default="qq", description="所属平台")
+9 -11
View File
@@ -10,7 +10,6 @@ from ._build_image import BuildImage
class RowStyle(BaseModel): class RowStyle(BaseModel):
font: FreeTypeFont | str | Path | None = "HYWenHei-85W.ttf" font: FreeTypeFont | str | Path | None = "HYWenHei-85W.ttf"
"""字体""" """字体"""
font_size: int = 20 font_size: int = 20
@@ -23,7 +22,6 @@ class RowStyle(BaseModel):
class ImageTemplate: class ImageTemplate:
color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"] # noqa: RUF012 color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"] # noqa: RUF012
@classmethod @classmethod
@@ -88,7 +86,7 @@ class ImageTemplate:
head_text: str, head_text: str,
tip_text: str | None, tip_text: str | None,
column_name: list[str], column_name: list[str],
data_list: list[list[str | tuple[Path | BuildImage, int, int]]], data_list: list[list[str | int | tuple[Path | BuildImage, int, int]]],
row_space: int = 35, row_space: int = 35,
column_space: int = 30, column_space: int = 30,
padding: int = 5, padding: int = 5,
@@ -137,7 +135,7 @@ class ImageTemplate:
async def table( async def table(
cls, cls,
column_name: list[str], column_name: list[str],
data_list: list[list[str | tuple[Path | BuildImage, int, int]]], data_list: list[list[str | int | tuple[Path | BuildImage, int, int]]],
row_space: int = 25, row_space: int = 25,
column_space: int = 10, column_space: int = 10,
padding: int = 5, padding: int = 5,
@@ -161,9 +159,11 @@ class ImageTemplate:
column_data = [] column_data = []
for i in range(len(column_name)): for i in range(len(column_name)):
c = [] c = []
for lst in data_list: for item in data_list:
if len(lst) > i: if len(item) > i:
c.append(lst[i]) c.append(
item[i] if isinstance(item[i], tuple | list) else str(item[i])
)
else: else:
c.append("") c.append("")
column_data.append(c) column_data.append(c)
@@ -176,7 +176,7 @@ class ImageTemplate:
if isinstance(s, tuple): if isinstance(s, tuple):
w = s[1] w = s[1]
else: else:
w, _ = BuildImage.get_text_size(s, font) w, _ = BuildImage.get_text_size(str(s), font)
if w > _temp["width"]: if w > _temp["width"]:
_temp["width"] = w _temp["width"] = w
build_data_list.append(_temp) build_data_list.append(_temp)
@@ -199,7 +199,7 @@ class ImageTemplate:
style = RowStyle(font=font) style = RowStyle(font=font)
if text_style: if text_style:
style = text_style(column_name[i], item) style = text_style(column_name[i], item)
if isinstance(item, tuple): if isinstance(item, tuple | list):
"""图片""" """图片"""
data, width, height = item data, width, height = item
image_ = None image_ = None
@@ -221,8 +221,6 @@ class ImageTemplate:
) )
cur_h += base_h + row_space cur_h += base_h + row_space
column_image_list.append(background) column_image_list.append(background)
# height = max([bk.height for bk in column_image_list])
# width = sum([bk.width for bk in column_image_list])
return await BuildImage.auto_paste( return await BuildImage.auto_paste(
column_image_list, len(column_image_list), column_space column_image_list, len(column_image_list), column_space
) )
-35
View File
@@ -1,35 +0,0 @@
import re
GITHUB_REPO_URL_PATTERN = re.compile(
r"^https://github.com/(?P<owner>[^/]+)/(?P<repo>[^/]+)(/tree/(?P<branch>[^/]+))?$"
)
"""github仓库地址正则"""
JSD_PACKAGE_API_FORMAT = (
"https://data.jsdelivr.com/v1/packages/gh/{owner}/{repo}@{branch}"
)
"""jsdelivr包地址格式"""
GIT_API_TREES_FORMAT = (
"https://api.github.com/repos/{owner}/{repo}/git/trees/{branch}?recursive=1"
)
"""git api trees地址格式"""
CACHED_API_TTL = 300
"""缓存api ttl"""
RAW_CONTENT_FORMAT = "https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}"
"""raw content格式"""
ARCHIVE_URL_FORMAT = "https://github.com/{owner}/{repo}/archive/refs/heads/{branch}.zip"
"""archive url格式"""
RELEASE_ASSETS_FORMAT = (
"https://github.com/{owner}/{repo}/releases/download/{version}/{filename}"
)
"""release assets格式"""
RELEASE_SOURCE_FORMAT = (
"https://codeload.github.com/{owner}/{repo}/legacy.{compress}/refs/tags/{version}"
)
"""release 源码格式"""
+12 -2
View File
@@ -431,14 +431,20 @@ class AsyncHttpx:
class AsyncPlaywright: class AsyncPlaywright:
@classmethod @classmethod
@asynccontextmanager @asynccontextmanager
async def new_page(cls, **kwargs) -> AsyncGenerator[Page, None]: async def new_page(
cls, cookies: list[dict[str, Any]] | dict[str, Any] | None = None, **kwargs
) -> AsyncGenerator[Page, None]:
"""获取一个新页面 """获取一个新页面
参数: 参数:
user_agent: 请求头 cookies: cookies
""" """
browser = await get_browser() browser = await get_browser()
ctx = await browser.new_context(**kwargs) ctx = await browser.new_context(**kwargs)
if cookies:
if isinstance(cookies, dict):
cookies = [cookies]
await ctx.add_cookies(cookies) # type: ignore
page = await ctx.new_page() page = await ctx.new_page()
try: try:
yield page yield page
@@ -461,6 +467,7 @@ class AsyncPlaywright:
timeout: float | None = None, timeout: float | None = None,
type_: Literal["jpeg", "png"] | None = None, type_: Literal["jpeg", "png"] | None = None,
user_agent: str | None = None, user_agent: str | None = None,
cookies: list[dict[str, Any]] | dict[str, Any] | None = None,
**kwargs, **kwargs,
) -> UniMessage | None: ) -> UniMessage | None:
"""截图,该方法仅用于简单快捷截图,复杂截图请操作 page """截图,该方法仅用于简单快捷截图,复杂截图请操作 page
@@ -474,6 +481,8 @@ class AsyncPlaywright:
wait_until: 等待类型 wait_until: 等待类型
timeout: 超时限制 timeout: 超时限制
type_: 保存类型 type_: 保存类型
user_agent: user_agent
cookies: cookies
""" """
if viewport_size is None: if viewport_size is None:
viewport_size = {"width": 2560, "height": 1080} viewport_size = {"width": 2560, "height": 1080}
@@ -482,6 +491,7 @@ class AsyncPlaywright:
wait_time = wait_time * 1000 if wait_time else None wait_time = wait_time * 1000 if wait_time else None
element_list = [element] if isinstance(element, str) else element element_list = [element] if isinstance(element, str) else element
async with cls.new_page( async with cls.new_page(
cookies,
viewport=viewport_size, viewport=viewport_size,
user_agent=user_agent, user_agent=user_agent,
**kwargs, **kwargs,
+2 -2
View File
@@ -390,7 +390,7 @@ def get_img_hash(image_file: str | Path) -> str:
return str(hash_value) return str(hash_value)
async def get_download_image_hash(url: str, mark: str) -> str: async def get_download_image_hash(url: str, mark: str, use_proxy: bool = False) -> str:
"""下载图片获取哈希值 """下载图片获取哈希值
参数: 参数:
@@ -402,7 +402,7 @@ async def get_download_image_hash(url: str, mark: str) -> str:
""" """
try: try:
if await AsyncHttpx.download_file( if await AsyncHttpx.download_file(
url, TEMP_PATH / f"compare_download_{mark}_img.jpg" url, TEMP_PATH / f"compare_download_{mark}_img.jpg", use_proxy=use_proxy
): ):
img_hash = get_img_hash(TEMP_PATH / f"compare_download_{mark}_img.jpg") img_hash = get_img_hash(TEMP_PATH / f"compare_download_{mark}_img.jpg")
return str(img_hash) return str(img_hash)
+27
View File
@@ -0,0 +1,27 @@
from typing import ClassVar
class MessageManager:
data: ClassVar[dict[str, list[str]]] = {}
@classmethod
def add(cls, uid: str, msg_id: str):
if uid not in cls.data:
cls.data[uid] = []
cls.data[uid].append(msg_id)
cls.remove_check(uid)
@classmethod
def check(cls, uid: str, msg_id: str) -> bool:
return msg_id in cls.data.get(uid, [])
@classmethod
def remove_check(cls, uid: str):
if len(cls.data[uid]) > 200:
cls.data[uid] = cls.data[uid][100:]
@classmethod
def get(cls, uid: str) -> list[str]:
if uid in cls.data:
return cls.data[uid]
return []
+42 -2
View File
@@ -4,7 +4,17 @@ from pathlib import Path
import nonebot import nonebot
from pydantic import BaseModel from pydantic import BaseModel
from nonebot.adapters.onebot.v11 import Message, MessageSegment from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot_plugin_alconna import At, Text, AtAll, Image, Video, Voice, UniMessage from nonebot_plugin_alconna import (
At,
Text,
AtAll,
Image,
Video,
Voice,
Reference,
CustomNode,
UniMessage,
)
from zhenxun.services.log import logger from zhenxun.services.log import logger
from zhenxun.configs.config import BotConfig from zhenxun.configs.config import BotConfig
@@ -89,6 +99,36 @@ class MessageUtils:
message_list += cls.__build_message(_data) # type: ignore message_list += cls.__build_message(_data) # type: ignore
return UniMessage(message_list) return UniMessage(message_list)
@classmethod
def alc_forward_msg(
cls,
msg_list: list,
uin: str,
name: str,
) -> UniMessage:
"""生成自定义合并消息
参数:
msg_list: 消息列表
uin: 发送者 QQ
name: 自定义名称
返回:
list[dict]: 转发消息
"""
node_list = []
for _message in msg_list:
if isinstance(_message, list):
for i in range(len(_message.copy())):
if isinstance(_message[i], Path):
_message[i] = Image(
raw=BuildImage.open(_message[i]).pic2bytes()
)
node_list.append(
CustomNode(uid=uin, name=name, content=UniMessage(_message))
)
return UniMessage(Reference(nodes=node_list))
@classmethod @classmethod
def custom_forward_msg( def custom_forward_msg(
cls, cls,
@@ -138,7 +178,7 @@ class MessageUtils:
if isinstance(r, Text): if isinstance(r, Text):
s += str(r) s += str(r)
elif isinstance(r, Image): elif isinstance(r, Image):
if v := r.url or r.path: if v := r.url or r.path or r.raw:
s += MessageSegment.image(v) s += MessageSegment.image(v)
elif isinstance(r_list, Image): elif isinstance(r_list, Image):
if v := r_list.url or r_list.path: if v := r_list.url or r_list.path:
+2 -2
View File
@@ -27,14 +27,14 @@ def admin_check(a: int | str, key: str | None = None) -> Rule:
if PlatformUtils.is_qbot(session): if PlatformUtils.is_qbot(session):
"""官bot接口,放弃所有权限检查""" """官bot接口,放弃所有权限检查"""
return False return False
if session.id and session.group: if session.group:
level = a level = a
if isinstance(a, str) and key: if isinstance(a, str) and key:
level = Config.get_config(a, key) level = Config.get_config(a, key)
if level is not None: if level is not None:
return bool( return bool(
await LevelUser.check_level( await LevelUser.check_level(
session.id, session.group.id, int(level) session.user.id, session.group.id, int(level)
) )
) )
return False return False
+1
View File
@@ -189,6 +189,7 @@ def change_pixiv_image_links(
url = ( url = (
url.replace("i.pximg.net", nginx_url) url.replace("i.pximg.net", nginx_url)
.replace("i.pixiv.cat", nginx_url) .replace("i.pixiv.cat", nginx_url)
.replace("i.pixiv.re", nginx_url)
.replace("_webp", "") .replace("_webp", "")
) )
return url return url