Compare commits

..
101 Commits
Author SHA1 Message Date
HibiKier 216d32cf21 Update README.md 2022-06-19 23:16:11 +08:00
HibiKier 248fae4fe6 Update __version__ 2022-06-19 23:15:40 +08:00
HibiKier b479b6839d Update README.md 2022-06-19 22:29:44 +08:00
HibiKier 1a4e1e9515 Merge pull request #835 from yajiwa/main
词条优化问题展示,修改含机器人昵称和@逻辑
2022-06-19 22:29:20 +08:00
yajiwa e5160a4ee8 Merge branch 'HibiKier:main' into main 2022-06-19 17:26:13 +08:00
yajiwa 56ea3964a7 update word_bank 2022-06-19 17:24:50 +08:00
HibiKier ad73778286 update README.md 2022-06-19 16:55:02 +08:00
HibiKier 3e548f48c8 Merge pull request #828 from McElaga/main
修复原神树脂重复提醒的bug
2022-06-19 16:54:25 +08:00
HibiKier ae466931fa fix webui 2022-06-19 16:44:37 +08:00
HibiKier 68052b526f update image_utils 2022-06-18 15:23:36 +08:00
HibiKier 903b5b88a7 update image_utils 2022-06-18 15:09:55 +08:00
HibiKier 007823d6b2 update README.md 2022-06-18 15:03:05 +08:00
HibiKier db5c4fb349 Merge pull request #830 from po-lan/main
我不太会提交单个文件,我就把俄罗斯轮盘的文件 改回去了,再提交的
2022-06-18 15:00:46 +08:00
HibiKier c37901290a fix nickname 2022-06-18 14:57:54 +08:00
HibiKier da67f1f6f8 update webui 2022-06-18 14:48:46 +08:00
HibiKier 5172fa69e5 fix web ui 2022-06-18 14:31:44 +08:00
po-lan dd7280cd0d 恢复 原先的文件 2022-06-18 14:08:59 +08:00
McElaga 0d0f522c88 Merge branch 'HibiKier:main' into main 2022-06-18 09:27:12 +08:00
McElaga 5429e6ed5c Merge branch 'main' of https://github.com/McElaga/zhenxun_bot 2022-06-18 09:15:24 +08:00
McElaga 9db69fa05b 修复一点逻辑小问题 2022-06-18 09:15:19 +08:00
HibiKier 3b8d52bcb5 Update README.md 2022-06-17 18:50:37 +08:00
HibiKier 807f39a336 Update README.md 2022-06-17 18:50:15 +08:00
HibiKier fea2f30461 Merge pull request #820 from LambdaYH/patch-2
修复wordbank的一些小问题
2022-06-17 18:49:42 +08:00
po-lan 5d97e3f95f Update __init__.py 2022-06-16 16:15:39 +08:00
po-lan 63e6ca3e99 Update __init__.py 2022-06-16 15:40:46 +08:00
po-lan b11590ec3c ban掉被击毙的人一段时间 2022-06-16 15:38:20 +08:00
po-lan 3a43ed6919 如果需要 保存到 config 可以少调用一次 2022-06-16 14:38:41 +08:00
po-lan 15ce9c91fb Update __init__.py 2022-06-16 14:25:22 +08:00
LambdaYH 0e8d7537d4 fix wordbank 2022-06-16 00:43:32 +08:00
Cinte 1fca0787be fix: 修复之前更改正则引入的问题 2022-06-15 23:16:39 +08:00
HibiKier af30285c00 Update browser.py 2022-06-15 10:08:43 +08:00
HibiKier a84cab7afd replace bt url 2022-06-14 20:40:11 +08:00
HibiKier 593573ddfb fix pix 2022-06-14 19:48:32 +08:00
HibiKier e9e9f81bdb Merge pull request #806 from LambdaYH/patch-2
fix: 修复添加词条时对answer中图片的处理
2022-06-14 19:31:53 +08:00
HibiKier 61f624841b Merge pull request #810 from LambdaYH/patch-3
fix: 自动更新群组
2022-06-14 19:31:18 +08:00
HibiKier 4bb38a2730 Merge pull request #812 from po-lan/main
可关闭 ssl 验证
2022-06-14 19:22:25 +08:00
HibiKier d4ec0df00c Update http_utils.py 2022-06-14 19:22:12 +08:00
po-lan c8a7d855f8 Update http_utils.py 2022-06-14 18:47:43 +08:00
Cinte 73a126dcd5 fix: 自动更新群组 2022-06-14 09:18:03 +08:00
HibiKier 0736533389 fix search_image 2022-06-13 22:16:45 +08:00
Cinte 2695d658ab fix: 修复添加词条时对answer中图片的处理 2022-06-13 22:11:18 +08:00
HibiKier 947166e793 Merge pull request #804 from po-lan/main
Windows 重启适配
2022-06-13 20:20:30 +08:00
po-lan 80c49a7cf5 Update __init__.py 2022-06-13 15:34:28 +08:00
po-lan 55bfa8f669 Update __init__.py
Windows 重启适配
2022-06-13 15:24:28 +08:00
HibiKier 74ade14f5e Update README.md 2022-06-13 11:07:34 +08:00
HibiKier c9b5218ebc Merge pull request #798 from CopilotLaLaLa/main
webui中token.json文件写入补充
2022-06-13 11:07:11 +08:00
HibiKier b324b2bd65 Merge pull request #800 from yajiwa/main
update setu_img
2022-06-13 11:06:20 +08:00
HibiKier 35c038efa2 Update utils.py 2022-06-13 11:05:16 +08:00
HibiKier caa404d58d Update utils.py 2022-06-13 11:03:21 +08:00
yajiwa 830103b9d5 update change_img_md5 2022-06-13 10:59:29 +08:00
yajiwa 6e18379597 update setu_img 2022-06-13 10:08:51 +08:00
yajiwa 6effbacb28 add change_img_md5 2022-06-13 10:08:09 +08:00
CopilotLaLaLa a20a1a0234 同步原仓库 2022-06-12 15:23:10 +00:00
CopilotLaLaLa 3667724061 token_json文件写入 2022-06-12 15:16:07 +00:00
HibiKier 785179e4a7 update pix 2022-06-11 17:57:19 +08:00
HibiKier 715338f821 Merge pull request #791 from mmmjie/main
两处BUG的修复
2022-06-10 21:31:51 +08:00
mmmjie 7d5a82ab6d Update update_picture.py
对于temp/temp的错误路径,减少了一个temp
TEMP_PATH 已经指向了一个temp了
2022-06-10 00:37:18 +08:00
mmmjie e764cfcc1c Update white2black_image.py
随着7b836ac 对utils/image_utils.py 的改动
调整此插件对于 utils/image_utils.py改动的引用部分
2022-06-10 00:35:57 +08:00
HibiKier 363acf37bc fix bug and update 2022-06-09 20:39:48 +08:00
HibiKier 5fd687c1e4 Merge pull request #778 from SinKy-Yan/main
fix auto update bug
2022-06-09 19:37:26 +08:00
HibiKier dbedcbb93d Update pyproject.toml 2022-06-08 11:51:32 +08:00
HibiKier 9e9611f11f Update README.md 2022-06-08 11:43:10 +08:00
HibiKier 44002838da Merge pull request #779 from MingxuanGame/main
chore(deps): update `nonebot-adapter-onebot`
2022-06-08 11:42:43 +08:00
MingxuanGame 4daab8459f chore(deps): update nonebot-adapter-onebot 2022-06-07 11:57:34 +00:00
HibiKier 5a002f75cc Merge pull request #777 from LambdaYH/patch-1
fix image_utils.py
2022-06-07 19:27:31 +08:00
源源球球✨ a2180a1365 fix auto update bug 2022-06-07 10:19:23 +00:00
Cinte 7b836acf36 fix image_utils.py
https://github.com/HibiKier/zhenxun_bot/commit/ae8a214a3a5c08a51cacd1dc37583c0b32e6332f
之前这个commit里面看到函数参数有写着int类型就把`font_size`类型转换给去了,结果导致了部分地方输入float类型后报错。现在改回来
2022-06-07 17:06:16 +08:00
HibiKier a112a561cc Update README.md 2022-06-05 20:30:49 +08:00
HibiKier 6dcc2a69f4 Update README.md 2022-06-05 19:56:42 +08:00
HibiKier 74e9c55a09 update v0.1.5.8 2022-06-05 19:51:23 +08:00
HibiKier d4d6e736a4 Merge pull request #764 from McElaga/main
金币红包功能增加更多封面
2022-06-05 19:08:51 +08:00
HibiKier 5cf9938fa2 Merge pull request #763 from RShock/main
fix gold_redbag
2022-06-05 19:04:40 +08:00
McElaga 72ad0ad983 commit on main 2022-06-04 12:34:18 +08:00
咕咕型小r 690750d91e fix gold_redbag 2022-06-04 12:09:05 +08:00
HibiKier 9f1dfc4b9c Merge pull request #756 from McElaga/main
修复原神树脂提醒bug(已实测)
2022-06-03 16:15:50 +08:00
HibiKier 05eab5307f Update README.md 2022-06-03 16:13:29 +08:00
HibiKier b0fe70c960 Merge pull request #745 from LambdaYH/main
稍微调整了一下查看所有请求中的年龄绘制
2022-06-03 16:07:01 +08:00
McElaga 09d7992bc4 comit on main 2022-06-03 12:09:15 +08:00
McElaga c832a432c1 commit on main 2022-06-03 11:52:40 +08:00
HibiKier 41c22f4314 fix ShopRegister 2022-06-03 01:14:34 +08:00
HibiKier 252d45c79b fix webui update plugin_shop 2022-06-03 00:59:00 +08:00
Cinte ae8a214a3a Update image_utils.py 2022-06-02 10:06:55 +08:00
LambdaYH 86ce6d7664 fix: 稍微调整了一下查看所有请求中的年龄绘制 2022-06-02 10:02:03 +08:00
McElaga 67e96d6106 commit on main 2022-06-02 08:55:24 +08:00
HibiKier 24d9ec2b75 Update __init__.py 2022-06-01 11:05:12 +08:00
HibiKier 501e47c6ec fix image2text 2022-05-31 20:45:28 +08:00
HibiKier 5534a5a5c2 Merge pull request #707 from HiDolen/main
修复抽卡插件:方舟更新UP池信息时,若公告的第一个池子过期会导致无法更新UP池信息
2022-05-31 20:14:48 +08:00
HibiKier 7246aabf40 Merge pull request #712 from McElaga/main
修复发红包图片背景未透明化;修复原神树脂提醒参数错误
2022-05-31 20:07:35 +08:00
HibiKier 604ffae87e Merge pull request #711 from LambdaYH/patch-1
bot_friend_group将group_handle.修改为friend_handle.
2022-05-31 20:06:12 +08:00
HibiKier 2d5c16456b Merge pull request #721 from LambdaYH/patch-2
修复开启/关闭全部功能时帮助图片未重绘
2022-05-31 20:01:39 +08:00
Cinte d44f7633dc 修复开启/关闭全部功能时帮助图片未重绘 2022-05-30 20:43:48 +08:00
Cinte 469ac4035c 大概是把group_handle写成了friend_handle 2022-05-30 11:27:14 +08:00
McElaga dab218a6d7 commit on main 2022-05-30 11:14:47 +08:00
Dolen d6fc675d57 修复抽卡插件:避免被跳过的卡池信息污染后面的卡池信息 2022-05-30 11:11:49 +08:00
McElaga 04148f7365 commit on main 2022-05-30 11:00:19 +08:00
Dolen 4c34ac570f 修复抽卡插件:方舟更新UP池信息时,若公告的第一个池子过期会导致无法更新UP池信息 2022-05-29 23:13:36 +08:00
HibiKier fbdb8758a3 Update README.md 2022-05-29 22:21:26 +08:00
HibiKier 2d08747d70 Merge pull request #705 from yajiwa/main
商店插件判断是否有requirements.txt文件
2022-05-29 22:21:03 +08:00
yajiwa 0b4bacbbd1 update plugin_shop 2022-05-29 21:57:01 +08:00
yajiwa e0412c7edb Merge branch 'HibiKier:main' into main 2022-05-29 21:03:12 +08:00
github-actions[bot] 374b7b7261 Auto generate poetry.lock 2022-05-25 23:42:48 +00:00
102 changed files with 1012 additions and 294 deletions
+1
View File
@@ -140,6 +140,7 @@ cython_debug/
test.py test.py
server_ip.py server_ip.py
game_utils.py
member_activity_handle.py member_activity_handle.py
Yu-Gi-Oh/ Yu-Gi-Oh/
csgo/ csgo/
+68 -1
View File
@@ -243,6 +243,74 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
## 更新 ## 更新
### 2022/6/19 \[v0.1.6.0]
* 暂时使用hook修复webui中plugins2setting修改时会改变plugins2setting.cmd为字符串
* 修复原神树脂重复提醒的bug [@pull/828](https://github.com/HibiKier/zhenxun_bot/pull/828)
* 词条优化问题展示,修改含机器人昵称和@逻辑 [@pull/835](https://github.com/HibiKier/zhenxun_bot/pull/835)
### 2022/6/18
* 修复昵称系统`BLACK_WORD`为空时造成报错
* 修复特殊头像时背景透明化出错
* 修复text2image纯文本时换行时颜色不统一
* 优化webUI,当有插件出错时不会影响其他插件显示
* 优化Config类型注释 [@pull/830](https://github.com/HibiKier/zhenxun_bot/pull/830)
* 优化browser
### 2022/6/17
* 修复wordbank的一些小问题 @pull/820
### 2022/6/14
* AsyncHttpx提供可关闭 ssl 验证参数 [@pull/812](https://github.com/HibiKier/zhenxun_bot/pull/812)
* fix: 自动更新群组 [@pull/810](https://github.com/HibiKier/zhenxun_bot/pull/810)
* fix: 修复添加词条时对answer中图片的处理 [@pull/806](https://github.com/HibiKier/zhenxun_bot/pull/806)
* 修复pix中指定num无法生效
* 替换了bt URL
### 2022/6/13
* Windows 重启适配 [@pull/804](https://github.com/HibiKier/zhenxun_bot/pull/804)
* 色图等提供修改md5方法 [@pull/800](https://github.com/HibiKier/zhenxun_bot/pull/800)
* webui中token.json文件写入补充 [@pull/798](https://github.com/HibiKier/zhenxun_bot/pull/798)
* 修复识图某些图片可能会出错
### 2022/6/11
* pix当只有一个tag时且为数字时可以通过添加'#'防止判定为数量
### 2022/6/9
* 修复b站订阅同群二人以上相同订阅时发送多次信息
* 修复超级用户帮助中缺少了 ‘插件商店’ 相关帮助
* 昵称系统提供了详细帮助
### 2022/6/5 \[v0.1.5.9]
* webui修复plugin2setting中cmd从list转变为str
* 当命令`我的金币`被风控时将以图片形式发送
* fix gold_redbag [@pull/763](https://github.com/HibiKier/zhenxun_bot/pull/763)
* 金币红包功能增加更多封面 [@pull/764](https://github.com/HibiKier/zhenxun_bot/pull/764)
### 2022/6/3
* 插件仓库在已安装插件边上会提示\[已安装]
* 修复ShopRegister kwargs某些字段无效
* 调整了一下查看所有请求中的年龄绘制 [@pull/745](https://github.com/HibiKier/zhenxun_bot/pull/745)
* 修复原神树脂提醒bug [@pull/756](https://github.com/HibiKier/zhenxun_bot/pull/756)
### 2022/5/31
* 修复开启/关闭全部功能时帮助图片未重绘 [@pull/721](https://github.com/HibiKier/zhenxun_bot/pull/721)
* bot_friend_group将group_handle.修改为friend_handle. [@pull/711](https://github.com/HibiKier/zhenxun_bot/pull/711)
* 修复发红包图片背景未透明化;修复原神树脂提醒参数错误 [@pull/712](https://github.com/HibiKier/zhenxun_bot/pull/712)
* 修复抽卡插件:方舟更新UP池信息时,若公告的第一个池子过期会导致无法更新UP池信息 [@pull/707](https://github.com/HibiKier/zhenxun_bot/pull/707)
* 商店插件判断是否有requirements.txt文件 [@pull/705](https://github.com/HibiKier/zhenxun_bot/pull/705)
* 删除原神玩家查询api返回变更的多余键值
* 优化了text2image方法
### 2022/5/29 \[v0.1.5.8] ### 2022/5/29 \[v0.1.5.8]
* 提供了真寻适配仓库的插件 安装/卸载 操作 * 提供了真寻适配仓库的插件 安装/卸载 操作
@@ -259,7 +327,6 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
* 新增自动更新插件```UPDATE_REMIND```:新版本提醒,原配置项```AUTO_UPDATE_ZHENXUN```改为自动更新升级 * 新增自动更新插件```UPDATE_REMIND```:新版本提醒,原配置项```AUTO_UPDATE_ZHENXUN```改为自动更新升级
* black_word新增当群权限为-1时不再检测该群 * black_word新增当群权限为-1时不再检测该群
* 修复非超级用户绑定原神cookie会被black_word阻拦 * 修复非超级用户绑定原神cookie会被black_word阻拦
* 修复webui中plugins2setting修改时会改变plugins2setting.cmd为字符串
* 修复微博热搜报错,发红包小bug [@pull/688](https://github.com/HibiKier/zhenxun_bot/pull/688) * 修复微博热搜报错,发红包小bug [@pull/688](https://github.com/HibiKier/zhenxun_bot/pull/688)
* 更多的中文提示 * 更多的中文提示
+1 -1
View File
@@ -1 +1 @@
__version__: v0.1.5.8 __version__: v0.1.6.0
@@ -118,6 +118,8 @@ async def change_group_switch(cmd: str, group_id: int, is_super: bool = False):
group_manager.unblock_plugin(f, group_id) group_manager.unblock_plugin(f, group_id)
else: else:
group_manager.block_plugin(f, group_id) group_manager.block_plugin(f, group_id)
if group_help_file.exists():
group_help_file.unlink()
return f"已 {status} 全部功能!" return f"已 {status} 全部功能!"
if cmd in [task_data[x] for x in task_data.keys()]: if cmd in [task_data[x] for x in task_data.keys()]:
type_ = "task" type_ = "task"
+2 -1
View File
@@ -4,7 +4,7 @@ from nonebot import on_message
from services.log import logger from services.log import logger
from models.group_info import GroupInfo from models.group_info import GroupInfo
from models.friend_user import FriendUser from models.friend_user import FriendUser
from nonebot.adapters.onebot.v11.exception import ActionFailed from nonebot.adapters.onebot.v11 import ActionFailed
from configs.config import NICKNAME, Config from configs.config import NICKNAME, Config
from utils.manager import group_manager from utils.manager import group_manager
from pathlib import Path from pathlib import Path
@@ -107,6 +107,7 @@ async def _():
group_info["group_name"], group_info["group_name"],
group_info["max_member_count"], group_info["max_member_count"],
group_info["member_count"], group_info["member_count"],
1
) )
logger.info(f"自动更新群组 {g} 信息成功") logger.info(f"自动更新群组 {g} 信息成功")
except Exception as e: except Exception as e:
+1 -1
View File
@@ -7,10 +7,10 @@ from datetime import datetime
from services.log import logger from services.log import logger
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
ActionFailed,
GroupIncreaseNoticeEvent, GroupIncreaseNoticeEvent,
GroupDecreaseNoticeEvent, GroupDecreaseNoticeEvent,
) )
from nonebot.adapters.onebot.v11.exception import ActionFailed
from utils.manager import group_manager, plugins2settings_manager, requests_manager from utils.manager import group_manager, plugins2settings_manager, requests_manager
from configs.config import NICKNAME from configs.config import NICKNAME
from models.group_info import GroupInfo from models.group_info import GroupInfo
+1 -1
View File
@@ -1,6 +1,5 @@
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException from nonebot.message import run_preprocessor, run_postprocessor, IgnoredException
from nonebot.adapters.onebot.v11.exception import ActionFailed
from models.friend_user import FriendUser from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser from models.group_member_info import GroupInfoUser
from models.bag_user import BagUser from models.bag_user import BagUser
@@ -23,6 +22,7 @@ from nonebot.typing import T_State
from typing import Optional from typing import Optional
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
ActionFailed,
MessageEvent, MessageEvent,
GroupMessageEvent, GroupMessageEvent,
PokeNotifyEvent, PokeNotifyEvent,
+1 -1
View File
@@ -1,11 +1,11 @@
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException from nonebot.message import run_preprocessor, IgnoredException
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.typing import T_State from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
Event, Event,
MessageEvent, MessageEvent,
ActionFailed,
PokeNotifyEvent, PokeNotifyEvent,
GroupMessageEvent, GroupMessageEvent,
) )
+1 -1
View File
@@ -1,9 +1,9 @@
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException from nonebot.message import run_preprocessor, IgnoredException
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.typing import T_State from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
ActionFailed,
MessageEvent, MessageEvent,
GroupMessageEvent, GroupMessageEvent,
) )
+1 -1
View File
@@ -1,6 +1,7 @@
from nonebot import on_request, on_message from nonebot import on_request, on_message
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
ActionFailed,
FriendRequestEvent, FriendRequestEvent,
GroupRequestEvent, GroupRequestEvent,
MessageEvent, MessageEvent,
@@ -8,7 +9,6 @@ from nonebot.adapters.onebot.v11 import (
from models.friend_user import FriendUser from models.friend_user import FriendUser
from datetime import datetime from datetime import datetime
from configs.config import NICKNAME, Config from configs.config import NICKNAME, Config
from nonebot.adapters.onebot.v11.exception import ActionFailed
from utils.manager import requests_manager from utils.manager import requests_manager
from models.group_info import GroupInfo from models.group_info import GroupInfo
from utils.utils import scheduler from utils.utils import scheduler
+9 -2
View File
@@ -22,6 +22,12 @@ __plugin_des__ = "区区昵称,才不想叫呢!"
__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"] __plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
__plugin_version__ = 0.1 __plugin_version__ = 0.1
__plugin_author__ = "HibiKier" __plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["昵称", "昵称系统"],
}
__plugin_configs__ = { __plugin_configs__ = {
"BLACK_WORD": { "BLACK_WORD": {
"value": ["爸", "爹", "爷", "父亲"], "value": ["爸", "爹", "爷", "父亲"],
@@ -57,8 +63,9 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True) await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
_tmp = "" _tmp = ""
black_word = Config.get_config("nickname", "BLACK_WORD") black_word = Config.get_config("nickname", "BLACK_WORD")
for x in msg: if black_word:
_tmp += "*" if x in black_word else x for x in msg:
_tmp += "*" if x in black_word else x
msg = _tmp msg = _tmp
if isinstance(event, GroupMessageEvent): if isinstance(event, GroupMessageEvent):
if await GroupInfoUser.set_group_member_nickname( if await GroupInfoUser.set_group_member_nickname(
+2 -2
View File
@@ -16,11 +16,11 @@ usage:
指令: 指令:
查看插件仓库 查看插件仓库
更新插件仓库 更新插件仓库
安装插件 [name/id] 安装插件 [name/id] (重新安装等同于更新)
卸载插件 [name/id] 卸载插件 [name/id]
""".strip() """.strip()
__plugin_des__ = "从真寻适配仓库中下载插件" __plugin_des__ = "从真寻适配仓库中下载插件"
__plugin_cmd__ = [""] __plugin_cmd__ = ["查看插件仓库", "更新插件仓库", "安装插件 [name/id]", "卸载插件 [name/id]"]
__plugin_version__ = 0.1 __plugin_version__ = 0.1
__plugin_author__ = "HibiKier" __plugin_author__ = "HibiKier"
+18 -5
View File
@@ -3,6 +3,7 @@ import shutil
import zipfile import zipfile
from pathlib import Path from pathlib import Path
from typing import Union, Tuple from typing import Union, Tuple
from utils.manager import plugins_manager
import ujson as json import ujson as json
@@ -71,11 +72,16 @@ async def install_plugin(name: str) -> str:
os.system( os.system(
f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'pyproject.toml').absolute()}" f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'pyproject.toml').absolute()}"
) )
with open(extensive_plugin_path / f'{name}' / "plugin_info.json", 'w') as f: elif "requirements.txt" in os.listdir(extensive_plugin_path / f"{name}"):
tmp = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
os.system(
f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'requirements.txt').absolute()}"
)
with open(extensive_plugin_path / f"{name}" / "plugin_info.json", "w") as f:
json.dump(data[name], f, ensure_ascii=False, indent=4) json.dump(data[name], f, ensure_ascii=False, indent=4)
logger.debug("移动插件文件夹完成...") logger.debug("移动插件文件夹完成...")
logger.info(f"成功安装插件 {name} 成功!\n{tmp}") logger.info(f"成功安装插件 {name} 成功!\n{tmp}")
return f"成功安装插件 {name},请重启bot!" return f"成功安装插件 {name},请重启真寻!"
except Exception as e: except Exception as e:
logger.error(f"安装插件 {name} 失败 {type(e)}:{e}") logger.error(f"安装插件 {name} 失败 {type(e)}:{e}")
return f"安装插件 {name} 失败 {type(e)}:{e}" return f"安装插件 {name} 失败 {type(e)}:{e}"
@@ -110,6 +116,7 @@ async def show_plugin_repo() -> Union[int, str]:
if code != 200: if code != 200:
return code return code
plugin_info = json.load(open(plugin_json, "r", encoding="utf8")) plugin_info = json.load(open(plugin_json, "r", encoding="utf8"))
load_plugin_list = plugins_manager.get_data().keys()
image_list = [] image_list = []
w, h = 0, 0 w, h = 0, 0
line_height = 10 line_height = 10
@@ -123,11 +130,17 @@ async def show_plugin_repo() -> Union[int, str]:
"download_url": plugin_info[key]["download_url"], "download_url": plugin_info[key]["download_url"],
"github_url": plugin_info[key]["github_url"], "github_url": plugin_info[key]["github_url"],
} }
status = ""
version = ""
if key in load_plugin_list:
status = "<f font_color=#1a7e30>[已安装]</f>"
version = f"<f font_color=#1a7e30>[{plugins_manager.get_data()[key]['version']}]</f>"
s = ( s = (
f'id:{i+1}\n名称:{plugin_info[key]["plugin_name"]}\n' f'id:{i+1}\n名称:{plugin_info[key]["plugin_name"]}'
f'模块:{key}\n' f' \t\t{status}\n'
f"模块:{key}\n"
f'作者:{plugin_info[key]["author"]}\n' f'作者:{plugin_info[key]["author"]}\n'
f'版本:{plugin_info[key]["version"]}\n' f'版本:{plugin_info[key]["version"]} \t\t{version}\n'
f'简介:{plugin_info[key]["introduction"]}\n' f'简介:{plugin_info[key]["introduction"]}\n'
f"-------------------" f"-------------------"
) )
+7 -2
View File
@@ -1,9 +1,10 @@
from nonebot import on_command from nonebot import on_command
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, ActionFailed
from nonebot.params import CommandArg from nonebot.params import CommandArg
from nonebot.adapters.onebot.v11.permission import GROUP from nonebot.adapters.onebot.v11.permission import GROUP
from utils.data_utils import init_rank from utils.data_utils import init_rank
from models.bag_user import BagUser from models.bag_user import BagUser
from utils.image_utils import text2image
from utils.message_builder import image from utils.message_builder import image
from utils.utils import is_number from utils.utils import is_number
@@ -34,7 +35,11 @@ gold_rank = on_command("金币排行", priority=5, block=True, permission=GROUP)
@my_gold.handle() @my_gold.handle()
async def _(event: GroupMessageEvent): async def _(event: GroupMessageEvent):
await my_gold.finish(await BagUser.get_user_total_gold(event.user_id, event.group_id)) msg = await BagUser.get_user_total_gold(event.user_id, event.group_id)
try:
await my_gold.send(msg)
except ActionFailed:
await my_gold.send(image(b64=(await text2image(msg, color="#f9f6f2", padding=10)).pic2bs4()))
@gold_rank.handle() @gold_rank.handle()
+1 -1
View File
@@ -26,7 +26,7 @@ class GoodsUseFuncManager:
判断商品使用方法是否被注册 判断商品使用方法是否被注册
:param goods_name: 商品名称 :param goods_name: 商品名称
""" """
return bool(self._data.get(goods_name)) return bool(self ._data.get(goods_name))
def get_max_num_limit(self, goods_name: str) -> int: def get_max_num_limit(self, goods_name: str) -> int:
""" """
+6 -6
View File
@@ -119,18 +119,18 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
) )
flag = await requests_manager.approve(bot, id_, "group") flag = await requests_manager.approve(bot, id_, "group")
else: else:
await friend_handle.send("同意群聊请求失败,未找到此id的请求..") await group_handle.send("同意群聊请求失败,未找到此id的请求..")
else: else:
flag = await requests_manager.refused(bot, id_, "group") flag = await requests_manager.refused(bot, id_, "group")
if flag == 1: if flag == 1:
await friend_handle.send(f"{cmd[:2]}群聊请求失败,该请求已失效..") await group_handle.send(f"{cmd[:2]}群聊请求失败,该请求已失效..")
requests_manager.delete_request(id_, "group") requests_manager.delete_request(id_, "group")
elif flag == 2: elif flag == 2:
await friend_handle.send(f"{cmd[:2]}群聊请求失败,未找到此id的请求..") await group_handle.send(f"{cmd[:2]}群聊请求失败,未找到此id的请求..")
else: else:
await friend_handle.send(f"{cmd[:2]}群聊请求成功!") await group_handle.send(f"{cmd[:2]}群聊请求成功!")
else: else:
await friend_handle.send("id必须为纯数字!") await group_handle.send("id必须为纯数字!")
@cls_request.handle() @cls_request.handle()
@@ -150,4 +150,4 @@ async def _():
@clear_request.handle() @clear_request.handle()
async def _(): async def _():
requests_manager.clear() requests_manager.clear()
await cls_request.send("已清空所有好友/群聊请求..") await clear_request.send("已清空所有好友/群聊请求..")
+11 -11
View File
@@ -1,4 +1,11 @@
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GROUP, GroupMessageEvent, Message from nonebot.adapters.onebot.v11 import (
Bot,
MessageEvent,
GROUP,
GroupMessageEvent,
Message,
ActionFailed,
)
from nonebot import on_command, on_regex from nonebot import on_command, on_regex
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from nonebot.typing import T_State from nonebot.typing import T_State
@@ -8,7 +15,6 @@ from utils.manager import group_manager, plugins2settings_manager
from models.group_info import GroupInfo from models.group_info import GroupInfo
from services.log import logger from services.log import logger
from configs.config import NICKNAME from configs.config import NICKNAME
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.params import Command, CommandArg from nonebot.params import Command, CommandArg
from typing import Tuple from typing import Tuple
@@ -137,9 +143,7 @@ async def _():
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()): async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0] cmd = cmd[0]
msg = arg.extract_plain_text().strip().split() msg = arg.extract_plain_text().strip().split()
all_group = [ all_group = [g["group_id"] for g in await bot.get_group_list()]
g["group_id"] for g in await bot.get_group_list()
]
group_list = [] group_list = []
for group in msg: for group in msg:
if is_number(group) and int(group) in all_group: if is_number(group) and int(group) in all_group:
@@ -151,9 +155,7 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
else: else:
group_manager.delete_group_white_list(group) group_manager.delete_group_white_list(group)
group_list = [str(x) for x in group_list] group_list = [str(x) for x in group_list]
await manager_group_whitelist.send( await manager_group_whitelist.send("已成功将 " + "\n".join(group_list) + " " + cmd)
"已成功将 " + "\n".join(group_list) + " " + cmd
)
else: else:
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名") await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
@@ -199,6 +201,4 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
else: else:
if await GroupInfo.get_group_info(group_id): if await GroupInfo.get_group_info(group_id):
await GroupInfo.set_group_flag(group_id, 0) await GroupInfo.set_group_flag(group_id, 0)
await group_auth.send( await group_auth.send(f"已为 {group_id} {cmd[:2]}群认证..")
f'已为 {group_id} {cmd[:2]}群认证..'
)
+4 -3
View File
@@ -94,12 +94,13 @@ class ConfigsManager:
del self._data[module] del self._data[module]
self.save() self.save()
def set_config(self, module: str, key: str, value: str): def set_config(self, module: str, key: str, value: Any , save_simple_data: bool = False):
""" """
设置配置值 设置配置值
:param module: 模块名 :param module: 模块名
:param key: 配置名称 :param key: 配置名称
:param value: 值 :param value: 值
:param save_simple_data: 同时保存至config.yaml
""" """
if module in self._data.keys(): if module in self._data.keys():
if ( if (
@@ -108,7 +109,7 @@ class ConfigsManager:
): ):
self._data[module][key]["value"] = value self._data[module][key]["value"] = value
self._simple_data[module][key] = value self._simple_data[module][key] = value
self.save() self.save(save_simple_data = save_simple_data)
def set_help(self, module: str, key: str, help_: str): def set_help(self, module: str, key: str, help_: str):
""" """
@@ -122,7 +123,7 @@ class ConfigsManager:
self._data[module][key]["help"] = help_ self._data[module][key]["help"] = help_
self.save() self.save()
def set_default_value(self, module: str, key: str, value: str): def set_default_value(self, module: str, key: str, value: Any):
""" """
设置配置默认值 设置配置默认值
:param module: 模块名 :param module: 模块名
+4 -2
View File
@@ -228,12 +228,14 @@ async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
:param sub: BilibiliSub :param sub: BilibiliSub
:param bot: Bot :param bot: Bot
""" """
temp_group = []
if rst: if rst:
for x in sub.sub_users.split(",")[:-1]: for x in sub.sub_users.split(",")[:-1]:
try: try:
if ":" in x: if ":" in x and x.split(":")[1] not in temp_group:
temp_group.append(x.split(":")[1])
await bot.send_group_msg( await bot.send_group_msg(
group_id=int(x.split(":")[1]), message=Message(rst) group_id=int(x.split(":")[1]), message=Message(rst)
) )
else: else:
await bot.send_private_msg(user_id=int(x), message=Message(rst)) await bot.send_private_msg(user_id=int(x), message=Message(rst))
+1 -1
View File
@@ -6,7 +6,7 @@ from configs.config import Config
from pathlib import Path from pathlib import Path
from services.log import logger from services.log import logger
from models.ban_user import BanUser from models.ban_user import BanUser
from nonebot.adapters.onebot.v11.exception import ActionFailed from nonebot.adapters.onebot.v11 import ActionFailed
from models.group_member_info import GroupInfoUser from models.group_member_info import GroupInfoUser
from utils.http_utils import AsyncHttpx from utils.http_utils import AsyncHttpx
import random import random
+1 -1
View File
@@ -80,8 +80,8 @@ async def _(
except TimeoutError: except TimeoutError:
await bt.finish(f"搜索 {keyword} 超时...") await bt.finish(f"搜索 {keyword} 超时...")
except Exception as e: except Exception as e:
await bt.finish(f"bt 其他未知错误..")
logger.error(f"bt 错误 {type(e)}:{e}") logger.error(f"bt 错误 {type(e)}:{e}")
await bt.finish(f"bt 其他未知错误..")
if not send_flag: if not send_flag:
await bt.send(f"{keyword} 未搜索到...") await bt.send(f"{keyword} 未搜索到...")
logger.info(f"USER {event.user_id} BT搜索 {keyword} 第 {page} 页") logger.info(f"USER {event.user_id} BT搜索 {keyword} 第 {page} 页")
+1 -1
View File
@@ -9,7 +9,7 @@ import platform
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
url = "http://www.eclzz.win" url = "http://www.eclzz.one/"
async def get_bt_info(keyword: str, page: int): async def get_bt_info(keyword: str, page: int):
+10 -10
View File
@@ -5,7 +5,7 @@ from .data_source import check_update, get_latest_version_data
from services.log import logger from services.log import logger
from utils.utils import scheduler, get_bot from utils.utils import scheduler, get_bot
from pathlib import Path from pathlib import Path
from configs.config import Config from configs.config import NICKNAME, Config
from nonebot.rule import to_me from nonebot.rule import to_me
from nonebot.params import ArgStr from nonebot.params import ArgStr
import platform import platform
@@ -71,18 +71,18 @@ async def _(bot: Bot):
) )
@restart.handle()
async def _():
if str(platform.system()).lower() == "windows":
await restart.finish("暂无windows重启脚本...")
@restart.got("flag", prompt=f"确定是否重启{NICKNAME}?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)")
@restart.got("flag", prompt="确定是否重启真寻?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)")
async def _(flag: str = ArgStr("flag")): async def _(flag: str = ArgStr("flag")):
if flag.lower() in ["true", "是", "好", "确定", "确定是"]: if flag.lower() in ["true", "是", "好", "确定", "确定是"]:
await restart.send("开始重启真寻..请稍等...") await restart.send(f"开始重启{NICKNAME}..请稍等...")
open("is_restart", "w") open("is_restart", "w")
os.system("./restart.sh") if str(platform.system()).lower() == "windows":
import sys
python = sys.executable
os.execl(python, python, *sys.argv)
else:
os.system("./restart.sh")
else: else:
await restart.send("已取消操作...") await restart.send("已取消操作...")
@@ -126,5 +126,5 @@ async def _():
if code == 200: if code == 200:
await bot.send_private_msg( await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]), user_id=int(list(bot.config.superusers)[0]),
message=f"更新完毕,请重启真寻....", message=f"更新完毕,请重启{NICKNAME}....",
) )
+5 -2
View File
@@ -162,7 +162,7 @@ def _file_handle(latest_version: str) -> str:
if backup_file.exists(): if backup_file.exists():
backup_file.unlink() backup_file.unlink()
if file not in [config_file, config_path_file]: if file not in [config_file, config_path_file]:
os.rename(file.absolute(), backup_file.absolute()) shutil.move(file.absolute(), backup_file.absolute())
else: else:
with open(file, "r", encoding="utf8") as rf: with open(file, "r", encoding="utf8") as rf:
data = rf.read() data = rf.read()
@@ -174,7 +174,7 @@ def _file_handle(latest_version: str) -> str:
old_file = Path() / file old_file = Path() / file
if old_file not in [config_file, config_path_file] and file != "configs": if old_file not in [config_file, config_path_file] and file != "configs":
if not old_file.exists() and new_file.exists(): if not old_file.exists() and new_file.exists():
os.rename(new_file.absolute(), old_file.absolute()) shutil.move(new_file.absolute(), old_file.absolute())
logger.info(f"已更新文件:{file}") logger.info(f"已更新文件:{file}")
# except Exception as e: # except Exception as e:
# error = f'{type(e)}:{e}' # error = f'{type(e)}:{e}'
@@ -189,6 +189,9 @@ def _file_handle(latest_version: str) -> str:
local_update_info_file.unlink() local_update_info_file.unlink()
with open(_version_file, "w", encoding="utf8") as f: with open(_version_file, "w", encoding="utf8") as f:
f.write(f"__version__: {latest_version}") f.write(f"__version__: {latest_version}")
os.system(
f"poetry run pip install -r {(Path() / 'pyproject.toml').absolute()}"
)
return error return error
+4 -1
View File
@@ -288,7 +288,10 @@ class PrtsHandle(BaseHandle[Operator]):
up_chars.append( up_chars.append(
UpChar(name=name, star=star, limited=False, zoom=zoom) UpChar(name=name, star=star, limited=False, zoom=zoom)
) )
break # 这里break会导致个问题:如果一个公告里有两个池子,会漏掉下面的池子,比如 5.19 的定向寻访。但目前我也没啥好想法解决 if start_time <= datetime.now() <= end_time: # 跳过过时的卡池
break # 这里break会导致个问题:如果一个公告里有两个池子,会漏掉下面的池子,比如 5.19 的定向寻访。但目前我也没啥好想法解决
chars: List[str] = [] # 查找下一个卡池之前清空 chars
up_chars = [] # 查找下一个卡池之前清空 up_chars
if title and start_time and end_time: if title and start_time and end_time:
if start_time <= datetime.now() <= end_time: if start_time <= datetime.now() <= end_time:
self.UP_EVENT = UpEvent( self.UP_EVENT = UpEvent(
@@ -182,7 +182,7 @@ def parsed_data(
role_data = { role_data = {
"active_day_number": data["stats"]["active_day_number"], # 活跃天数 "active_day_number": data["stats"]["active_day_number"], # 活跃天数
"achievement_number": data["stats"]["achievement_number"], # 达成成就数量 "achievement_number": data["stats"]["achievement_number"], # 达成成就数量
"win_rate": data["stats"]["win_rate"], # "win_rate": data["stats"]["win_rate"],
"anemoculus_number": data["stats"]["anemoculus_number"], # 风神瞳已收集 "anemoculus_number": data["stats"]["anemoculus_number"], # 风神瞳已收集
"geoculus_number": data["stats"]["geoculus_number"], # 岩神瞳已收集 "geoculus_number": data["stats"]["geoculus_number"], # 岩神瞳已收集
"avatar_number": data["stats"]["avatar_number"], # 获得角色数量 "avatar_number": data["stats"]["avatar_number"], # 获得角色数量
@@ -86,30 +86,28 @@ async def _():
if await Genshin.get_user_resin_recovery_time(u.uid) > datetime.now( if await Genshin.get_user_resin_recovery_time(u.uid) > datetime.now(
pytz.timezone("Asia/Shanghai") pytz.timezone("Asia/Shanghai")
): ):
date = await Genshin.get_user_resin_recovery_time(u.uid) # date = await Genshin.get_user_resin_recovery_time(u.uid) # 不能要,因为可能在这期间用户使用了树脂
scheduler.add_job( add_job(u.user_qq, u.uid)
_remind, # scheduler.add_job(
"date", # _remind,
run_date=date.replace(microsecond=0), # "date",
id=f"genshin_resin_remind_{u.uid}_{u.user_qq}", # run_date=date.replace(microsecond=0),
args=[u.user_qq, u.uid], # id=f"genshin_resin_remind_{u.uid}_{u.user_qq}",
) # args=[u.user_qq, u.uid],
# )
logger.info( logger.info(
f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid} " f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
f"{date} 原神树脂提醒"
) )
else: else:
await Genshin.clear_resin_remind_time(u.uid) await Genshin.clear_resin_remind_time(u.uid)
add_job(u.user_qq, u.uid) add_job(u.user_qq, u.uid)
logger.info( logger.info(
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid} " f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
f"{date} 原神树脂提醒"
) )
else: else:
add_job(u.user_qq, u.uid) add_job(u.user_qq, u.uid)
logger.info( logger.info(
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid} " f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
f"{date} 原神树脂提醒"
) )
@@ -144,17 +142,19 @@ async def _remind(user_id: int, uid: str):
now = datetime.now(pytz.timezone("Asia/Shanghai")) now = datetime.now(pytz.timezone("Asia/Shanghai"))
next_time = None next_time = None
if code == 200: if code == 200:
current_resin = data["current_resin"] # 当前树脂 current_resin = int(data["current_resin"]) # 当前树脂
max_resin = data["max_resin"] # 最大树脂 max_resin = int(data["max_resin"]) # 最大树脂
msg = f"你的已经存了 {current_resin} 个树脂了!不要忘记刷掉!" msg = f"你的已经存了 {current_resin} 个树脂了!不要忘记刷掉!"
# resin_recovery_time = data["resin_recovery_time"] # 树脂全部回复时间 # resin_recovery_time = data["resin_recovery_time"] # 树脂全部回复时间
if current_resin < max_resin: if current_resin < max_resin:
user_manager.remove(uid) user_manager.remove(uid)
user_manager.remove_overflow(uid) user_manager.remove_overflow(uid)
if max_resin - 40 < current_resin <= max_resin - 20: if current_resin < max_resin - 40:
next_time = now + timedelta(minutes=(max_resin - 20 - current_resin + 1) * 8, seconds=10) next_time = now + timedelta(minutes=(max_resin - 40 - current_resin) * 8)
elif current_resin < max_resin: elif max_resin - 40 <= current_resin < max_resin - 20:
next_time = now + timedelta(minutes=(max_resin - current_resin) * 8, seconds=10) next_time = now + timedelta(minutes=(max_resin - 20 - current_resin) * 8)
elif max_resin - 20 <= current_resin < max_resin:
next_time = now + timedelta(minutes=(max_resin - current_resin) * 8)
elif current_resin == max_resin: elif current_resin == max_resin:
custom_overflow_resin = Config.get_config("resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND") custom_overflow_resin = Config.get_config("resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND")
if user_manager.is_overflow(uid) and custom_overflow_resin: if user_manager.is_overflow(uid) and custom_overflow_resin:
@@ -164,6 +164,7 @@ async def _remind(user_id: int, uid: str):
msg = f"你的树脂都溢出 {custom_overflow_resin} 个了!浪费可耻!" msg = f"你的树脂都溢出 {custom_overflow_resin} 个了!浪费可耻!"
else: else:
next_time = now + timedelta(minutes=40 * 8 + random.randint(5, 50)) next_time = now + timedelta(minutes=40 * 8 + random.randint(5, 50))
if not user_manager.exists(uid) and current_resin >= max_resin - 40: if not user_manager.exists(uid) and current_resin >= max_resin - 40:
if current_resin == max_resin: if current_resin == max_resin:
user_manager.append(uid) user_manager.append(uid)
@@ -187,6 +188,7 @@ async def _remind(user_id: int, uid: str):
) )
except ActionFailed as e: except ActionFailed as e:
logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}") logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}")
if not next_time: if not next_time:
if user_manager.check(uid) and Config.get_config("resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"): if user_manager.check(uid) and Config.get_config("resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"):
await Genshin.set_resin_remind(int(uid), False) await Genshin.set_resin_remind(int(uid), False)
@@ -197,10 +199,13 @@ async def _remind(user_id: int, uid: str):
user_manager.remove_error_count(uid) user_manager.remove_error_count(uid)
await Genshin.set_user_resin_recovery_time(int(uid), next_time) await Genshin.set_user_resin_recovery_time(int(uid), next_time)
scheduler.add_job( scheduler.add_job(
_remind,
_remind, _remind,
"date", "date",
run_date=next_time, run_date=next_time,
id=f"genshin_resin_remind_{uid}_{user_id}", id=f"genshin_resin_remind_{uid}_{user_id}",
args=[user_id, uid], args=[user_id, uid],
) )
logger.info(
f"genshin_resin_remind add_job:USER:{user_id} UID:{uid} "
f"{next_time} 原神树脂提醒"
)
+2 -2
View File
@@ -1,6 +1,7 @@
from nonebot import on_command, on_notice from nonebot import on_command, on_notice
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
ActionFailed,
GroupMessageEvent, GroupMessageEvent,
PokeNotifyEvent, PokeNotifyEvent,
Message Message
@@ -24,7 +25,6 @@ from nonebot.rule import to_me
from datetime import datetime, timedelta from datetime import datetime, timedelta
from configs.config import NICKNAME from configs.config import NICKNAME
from apscheduler.jobstores.base import JobLookupError from apscheduler.jobstores.base import JobLookupError
from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.params import CommandArg from nonebot.params import CommandArg
import random import random
import time import time
@@ -124,7 +124,7 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
redbag_data[event.group_id]["amount"] redbag_data[event.group_id]["amount"]
- redbag_data[event.group_id]["open_amount"] - redbag_data[event.group_id]["open_amount"]
) )
await return_gold(event.user_id, event.group_id, amount) await return_gold(redbag_data[event.group_id]["user_id"], event.group_id, amount)
await gold_redbag.send( await gold_redbag.send(
f'{redbag_data[event.group_id]["nickname"]}的红包过时未开完,退还{amount}金币...' f'{redbag_data[event.group_id]["nickname"]}的红包过时未开完,退还{amount}金币...'
) )
+4 -3
View File
@@ -61,7 +61,8 @@ async def generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount
async def _generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount: int, text: str): async def _generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount: int, text: str):
send_user_nickname += '的红包' send_user_nickname += '的红包'
amount = str(amount) amount = str(amount)
head = BuildImage(1000, 980, font_size=30, background=f'{IMAGE_PATH}/prts/redbag_12.png') random_redbag = random.choice(os.listdir(f"{IMAGE_PATH}/prts/redbag_1"))
head = BuildImage(1000, 980, font_size=30, background=f'{IMAGE_PATH}/prts/redbag_1/{random_redbag}')
size = BuildImage(0, 0, font_size=50).getsize(send_user_nickname) size = BuildImage(0, 0, font_size=50).getsize(send_user_nickname)
# QQ头像 # QQ头像
ava_bk = BuildImage(100 + size[0], 66, is_alpha=True, font_size=50) ava_bk = BuildImage(100 + size[0], 66, is_alpha=True, font_size=50)
@@ -70,13 +71,13 @@ async def _generate_open_redbag_pic(user_id: int, send_user_nickname: str, amoun
ava_bk.text((100, 7), send_user_nickname) ava_bk.text((100, 7), send_user_nickname)
# ava_bk.show() # ava_bk.show()
ava_bk_w, ava_bk_h = ava_bk.size ava_bk_w, ava_bk_h = ava_bk.size
head.paste(ava_bk, (int((1000 - ava_bk_w) / 2), 300)) head.paste(ava_bk, (int((1000 - ava_bk_w) / 2), 300), alpha=True)
# 金额 # 金额
size = BuildImage(0, 0, font_size=150).getsize(amount) size = BuildImage(0, 0, font_size=150).getsize(amount)
price = BuildImage(size[0], size[1], is_alpha=True, font_size=150) price = BuildImage(size[0], size[1], is_alpha=True, font_size=150)
price.text((0, 0), amount, fill=(209, 171, 108)) price.text((0, 0), amount, fill=(209, 171, 108))
# 金币中文 # 金币中文
head.paste(price, (int((1000 - size[0]) / 2) - 50, 460)) head.paste(price, (int((1000 - size[0]) / 2) - 50, 460), alpha=True)
head.text((int((1000 - size[0]) / 2 + size[0]) - 50, 500 + size[1] - 70), '金币', fill=(209, 171, 108)) head.text((int((1000 - size[0]) / 2 + size[0]) - 50, 500 + size[1] - 70), '金币', fill=(209, 171, 108))
# 剩余数量和金额 # 剩余数量和金额
head.text((350, 900), text, (198, 198, 198)) head.text((350, 900), text, (198, 198, 198))
+14 -11
View File
@@ -1,8 +1,7 @@
from nonebot import on_message, on_command from nonebot import on_message, on_command
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, ActionFailed
from nonebot.adapters.onebot.v11.permission import GROUP from nonebot.adapters.onebot.v11.permission import GROUP
from utils.utils import is_number, get_message_img, get_message_text from utils.utils import is_number, get_message_img, get_message_text
from nonebot.adapters.onebot.v11.exception import ActionFailed
from configs.path_config import DATA_PATH, TEMP_PATH from configs.path_config import DATA_PATH, TEMP_PATH
from utils.image_utils import get_img_hash from utils.image_utils import get_img_hash
from services.log import logger from services.log import logger
@@ -72,9 +71,7 @@ def save_data():
async def download_img_and_hash(url, group_id) -> str: async def download_img_and_hash(url, group_id) -> str:
if await AsyncHttpx.download_file( if await AsyncHttpx.download_file(url, TEMP_PATH / f"mute_{group_id}_img.jpg"):
url, TEMP_PATH / f"mute_{group_id}_img.jpg"
):
return str(get_img_hash(TEMP_PATH / f"mute_{group_id}_img.jpg")) return str(get_img_hash(TEMP_PATH / f"mute_{group_id}_img.jpg"))
return "" return ""
@@ -133,11 +130,19 @@ async def _(bot: Bot, event: GroupMessageEvent):
@mute_setting.handle() @mute_setting.handle()
async def _(event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()): async def _(
event: GroupMessageEvent,
cmd: Tuple[str, ...] = Command(),
arg: Message = CommandArg(),
):
global mute_data global mute_data
group_id = str(event.group_id) group_id = str(event.group_id)
if not mute_data.get(group_id): if not mute_data.get(group_id):
mute_data[group_id] = {"count": Config.get_config("mute", "MUTE_DEFAULT_COUNT"), "time": Config.get_config("mute", "MUTE_DEFAULT_TIME"), "duration": Config.get_config("mute", "MUTE_DEFAULT_DURATION")} mute_data[group_id] = {
"count": Config.get_config("mute", "MUTE_DEFAULT_COUNT"),
"time": Config.get_config("mute", "MUTE_DEFAULT_TIME"),
"duration": Config.get_config("mute", "MUTE_DEFAULT_DURATION"),
}
msg = arg.extract_plain_text().strip() msg = arg.extract_plain_text().strip()
if cmd[0] == "刷屏检测设置": if cmd[0] == "刷屏检测设置":
await mute_setting.finish( await mute_setting.finish(
@@ -157,8 +162,6 @@ async def _(event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Mes
if cmd[0] == "设置刷屏禁言时长": if cmd[0] == "设置刷屏禁言时长":
mute_data[group_id]["duration"] = int(msg) mute_data[group_id]["duration"] = int(msg)
msg += " 分钟" msg += " 分钟"
await mute_setting.send(f'刷屏检测:{cmd[0]}为 {msg}') await mute_setting.send(f"刷屏检测:{cmd[0]}为 {msg}")
logger.info( logger.info(f"USER {event.user_id} GROUP {group_id} {cmd[0]}:{msg}")
f'USER {event.user_id} GROUP {group_id} {cmd[0]}:{msg}'
)
save_data() save_data()
+1 -1
View File
@@ -7,7 +7,7 @@ from .models.open_cases_user import OpenCasesUser
from services.log import logger from services.log import logger
from utils.utils import get_bot, cn2py from utils.utils import get_bot, cn2py
from asyncio.exceptions import TimeoutError from asyncio.exceptions import TimeoutError
from nonebot.adapters.onebot.v11.exception import ActionFailed from nonebot.adapters.onebot.v11 import ActionFailed
from configs.config import Config from configs.config import Config
from utils.manager import group_manager from utils.manager import group_manager
from .config import * from .config import *
+1 -2
View File
@@ -1,10 +1,9 @@
# from nonebot import on_message # from nonebot import on_message
# from services.log import logger # from services.log import logger
# from nonebot.adapters.onebot.v11 import GroupMessageEvent # from nonebot.adapters.onebot.v11 import GroupMessageEvent, ActionFailed
# from utils.utils import get_message_json, get_local_proxy, is_number, get_message_text # from utils.utils import get_message_json, get_local_proxy, is_number, get_message_text
# from nonebot.adapters.onebot.v11.permission import GROUP # from nonebot.adapters.onebot.v11.permission import GROUP
# from utils.message_builder import image # from utils.message_builder import image
# from nonebot.adapters.onebot.v11.exception import ActionFailed
# from utils.image_utils import BuildImage # from utils.image_utils import BuildImage
# from utils.browser import get_browser # from utils.browser import get_browser
# from configs.path_config import IMAGE_PATH # from configs.path_config import IMAGE_PATH
+2 -1
View File
@@ -4,7 +4,7 @@ from asyncio.locks import Semaphore
from asyncio.exceptions import TimeoutError from asyncio.exceptions import TimeoutError
from ._model.pixiv import Pixiv from ._model.pixiv import Pixiv
from typing import List, Optional from typing import List, Optional
from utils.utils import change_pixiv_image_links from utils.utils import change_pixiv_image_links, change_img_md5
from utils.image_utils import BuildImage from utils.image_utils import BuildImage
from utils.http_utils import AsyncHttpx from utils.http_utils import AsyncHttpx
from services.log import logger from services.log import logger
@@ -238,6 +238,7 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg", "wb" TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg", "wb"
) as f: ) as f:
await f.write(response.content) await f.write(response.content)
change_img_md5(TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg")
return TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg" return TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg"
except TimeoutError: except TimeoutError:
logger.warning(f"PIX:{img_url} 图片下载超时...") logger.warning(f"PIX:{img_url} 图片下载超时...")
+11 -3
View File
@@ -20,6 +20,11 @@ usage:
pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取 pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取
pid [uid]: 通过uid获取图片 pid [uid]: 通过uid获取图片
pix pid[pid]: 查看图库中指定pid图片 pix pid[pid]: 查看图库中指定pid图片
示例:pix 萝莉 白丝
示例:pix 萝莉 白丝 10 (10为数量)
示例:pix #02 (当tag只有1个tag且为数字时,使用#标记,否则将被判定为数量)
示例:pix 34582394 (查询指定uid图片)
示例:pix pid:12323423 (查询指定pid图片)
""".strip() """.strip()
__plugin_superuser_usage__ = """ __plugin_superuser_usage__ = """
usage: usage:
@@ -88,9 +93,12 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
nsfw_tag == 2 and not Config.get_config("pix", "ALLOW_GROUP_R18") nsfw_tag == 2 and not Config.get_config("pix", "ALLOW_GROUP_R18")
): ):
await pix.finish("你不能看这些噢,这些都是是留给管理员看的...") await pix.finish("你不能看这些噢,这些都是是留给管理员看的...")
if n := len(x) == 1 and is_number(x[0]) and int(x[0]) < 100: if (n := len(x)) == 1:
num = int(x[0]) if is_number(x[0]) and int(x[0]) < 100:
keyword = "" num = int(x[0])
keyword = ""
elif x[0].startswith("#"):
keyword = x[0][1:]
elif n > 1: elif n > 1:
if is_number(x[-1]): if is_number(x[-1]):
num = int(x[-1]) num = int(x[-1])
+1 -2
View File
@@ -1,11 +1,10 @@
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message, NetworkError
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.params import CommandArg from nonebot.params import CommandArg
from nonebot import on_command from nonebot import on_command
from utils.utils import is_number from utils.utils import is_number
from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
from services.log import logger from services.log import logger
from nonebot.adapters.onebot.v11.exception import NetworkError
from asyncio.exceptions import TimeoutError from asyncio.exceptions import TimeoutError
from utils.message_builder import custom_forward_msg from utils.message_builder import custom_forward_msg
from configs.config import Config from configs.config import Config
+2
View File
@@ -1,5 +1,6 @@
from configs.path_config import IMAGE_PATH from configs.path_config import IMAGE_PATH
from utils.message_builder import image from utils.message_builder import image
from utils.utils import change_img_md5
from asyncio.exceptions import TimeoutError from asyncio.exceptions import TimeoutError
from configs.config import Config from configs.config import Config
from utils.http_utils import AsyncHttpx from utils.http_utils import AsyncHttpx
@@ -143,6 +144,7 @@ async def download_pixiv_imgs(
file, file,
timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"), timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"),
): ):
change_img_md5(file)
if forward_msg_index is not None: if forward_msg_index is not None:
result += image( result += image(
f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg", f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
+1 -1
View File
@@ -64,7 +64,7 @@ async def _poke_event(event: PokeNotifyEvent):
rand = random.random() rand = random.random()
path = random.choice(["luoli", "meitu"]) path = random.choice(["luoli", "meitu"])
if rand <= 0.3 and len(os.listdir(IMAGE_PATH / "image_management" / path)) > 0: if rand <= 0.3 and len(os.listdir(IMAGE_PATH / "image_management" / path)) > 0:
index = random.randint(0, len(os.listdir(IMAGE_PATH / "image_management" / path))) index = random.randint(0, len(os.listdir(IMAGE_PATH / "image_management" / path)) - 1)
result = f"id:{index}" + image(f"{index}.jpg", "image_management/" + path) result = f"id:{index}" + image(f"{index}.jpg", "image_management/" + path)
await poke_.send(result) await poke_.send(result)
logger.info(f"USER {event.user_id} 戳了戳我 回复: {result} {result}") logger.info(f"USER {event.user_id} 戳了戳我 回复: {result} {result}")
+15 -8
View File
@@ -1,3 +1,4 @@
from services import logger
from utils.http_utils import AsyncHttpx from utils.http_utils import AsyncHttpx
from configs.config import Config from configs.config import Config
from configs.path_config import TEMP_PATH from configs.path_config import TEMP_PATH
@@ -39,12 +40,18 @@ async def get_saucenao_image(url: str) -> Union[str, List[str]]:
): ):
msg_list.append(image(TEMP_PATH / f"saucenao_search_{index}.jpg")) msg_list.append(image(TEMP_PATH / f"saucenao_search_{index}.jpg"))
for info in data: for info in data:
similarity = info["header"]["similarity"] try:
tmp = f"相似度:{similarity}%\n" similarity = info["header"]["similarity"]
for x in info["data"].keys(): tmp = f"相似度:{similarity}%\n"
if x != "ext_urls": for x in info["data"].keys():
tmp += f"{x}:{info['data'][x]}\n" if x != "ext_urls":
if "source" not in info["data"].keys(): tmp += f"{x}:{info['data'][x]}\n"
tmp += f'source:{info["data"]["ext_urls"][0]}\n' try:
msg_list.append(tmp[:-1]) if "source" not in info["data"].keys():
tmp += f'source:{info["data"]["ext_urls"][0]}\n'
except KeyError:
tmp += f'source:{info["header"]["thumbnail"]}\n'
msg_list.append(tmp[:-1])
except Exception as e:
logger.warning(f"识图获取图片信息发生错误 {type(e)}:{e}")
return msg_list return msg_list
+1 -1
View File
@@ -13,6 +13,7 @@ from utils.utils import (
from nonebot.typing import T_State from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
ActionFailed,
MessageEvent, MessageEvent,
GroupMessageEvent, GroupMessageEvent,
PrivateMessageEvent, PrivateMessageEvent,
@@ -30,7 +31,6 @@ from .data_source import (
add_data_to_database, add_data_to_database,
get_setu_count, get_setu_count,
) )
from nonebot.adapters.onebot.v11.exception import ActionFailed
from configs.config import Config, NICKNAME from configs.config import Config, NICKNAME
from utils.manager import withdraw_message_manager from utils.manager import withdraw_message_manager
from nonebot.params import CommandArg, Command, RegexGroup from nonebot.params import CommandArg, Command, RegexGroup
@@ -2,6 +2,7 @@ from configs.path_config import IMAGE_PATH, TEMP_PATH
from utils.message_builder import image from utils.message_builder import image
from services.log import logger from services.log import logger
from utils.image_utils import get_img_hash, compressed_image from utils.image_utils import get_img_hash, compressed_image
from utils.utils import change_img_md5
from asyncpg.exceptions import UniqueViolationError from asyncpg.exceptions import UniqueViolationError
from asyncio.exceptions import TimeoutError from asyncio.exceptions import TimeoutError
from typing import List, Optional from typing import List, Optional
@@ -111,6 +112,7 @@ async def search_online_setu(
path_ / f"{index}.jpg", path_ / f"{index}.jpg",
) )
logger.info(f"下载 lolicon 图片 {url_} 成功, id:{index}") logger.info(f"下载 lolicon 图片 {url_} 成功, id:{index}")
change_img_md5(path_ / file_name)
return image(path_ / file_name), index return image(path_ / file_name), index
except TimeoutError: except TimeoutError:
pass pass
@@ -128,6 +130,7 @@ async def check_local_exists_or_download(setu_image: Setu) -> "MessageSegment, i
path_ = r18_path if setu_image.is_r18 else path path_ = r18_path if setu_image.is_r18 else path
file = IMAGE_PATH / path_ / f"{setu_image.local_id}.jpg" file = IMAGE_PATH / path_ / f"{setu_image.local_id}.jpg"
if file.exists(): if file.exists():
change_img_md5(file)
return image(f"{setu_image.local_id}.jpg", path_), 200 return image(f"{setu_image.local_id}.jpg", path_), 200
return await search_online_setu(setu_image.img_url, id_, path_) return await search_online_setu(setu_image.img_url, id_, path_)
+1 -1
View File
@@ -232,7 +232,7 @@ async def _(
result += image(b64=pic2b64(img)) result += image(b64=pic2b64(img))
if method in ["模糊效果", "6"]: if method in ["模糊效果", "6"]:
for i in range(index): for i in range(index):
img = Image.open(TEMP_PATH / f"temp/{event.user_id}_{i}_update.png").filter( img = Image.open(TEMP_PATH / f"{event.user_id}_{i}_update.png").filter(
ImageFilter.BLUR ImageFilter.BLUR
) )
result += image(b64=pic2b64(img)) result += image(b64=pic2b64(img))
+25 -15
View File
@@ -1,20 +1,30 @@
from configs.config import Config as gConfig from configs.config import Config as gConfig
from .api import * from .api import *
from .auth import * from .auth import *
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException
gConfig.add_plugin_config( from utils.manager import plugins2settings_manager
"web-ui", from nonebot.typing import T_State
"username", from nonebot.adapters.onebot.v11 import (
"admin", Bot,
name="web-ui", MessageEvent
help_="前端管理用户名"
) )
gConfig.add_plugin_config(
"web-ui", gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")
"password",
None, gConfig.add_plugin_config("web-ui", "password", None, name="web-ui", help_="前端管理密码")
name="web-ui",
help_="前端管理密码"
) # 使用webui访问api后plugins2settings中的cmd字段将从list变为str
# 暂时找不到原因
# 先使用hook修复
@run_preprocessor
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
for module in plugins2settings_manager.keys():
if isinstance(plugins2settings_manager.get_plugin_data(module).get("cmd"), str):
plugins2settings_manager.set_module_data(
module,
"cmd",
plugins2settings_manager.get_plugin_data(module).get("cmd").split(","),
)
+1 -1
View File
@@ -58,4 +58,4 @@ async def _(group: GroupResult, user: User = Depends(token_to_user)) -> Result:
group_manager.turn_on_group_bot_status(group_id) group_manager.turn_on_group_bot_status(group_id)
else: else:
group_manager.shutdown_group_bot_status(group_id) group_manager.shutdown_group_bot_status(group_id)
return Result(code=200) return Result(code=200, data="修改成功!")
+20 -4
View File
@@ -1,3 +1,5 @@
from pydantic import ValidationError
from configs.config import Config from configs.config import Config
from services.log import logger from services.log import logger
from utils.manager import (plugins2block_manager, plugins2cd_manager, from utils.manager import (plugins2block_manager, plugins2cd_manager,
@@ -85,6 +87,10 @@ def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
id_ += 1 id_ += 1
data["plugin_config"] = tmp data["plugin_config"] = tmp
plugin_list.append(Plugin(**data)) plugin_list.append(Plugin(**data))
except (AttributeError, ValidationError) as e:
logger.error(
f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}"
)
except Exception as e: except Exception as e:
logger.error( logger.error(
f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}" f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}"
@@ -108,7 +114,7 @@ def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
if str(c.value).lower() in ["true", "false"] and ( if str(c.value).lower() in ["true", "false"] and (
c.default_value is None or isinstance(c.default_value, bool) c.default_value is None or isinstance(c.default_value, bool)
): ):
c.value = True if str(c.value).lower() == "true" else False c.value = str(c.value).lower() == "true"
elif isinstance( elif isinstance(
Config.get_config(plugin.model, c.key, c.value), int Config.get_config(plugin.model, c.key, c.value), int
) or isinstance(c.default_value, int): ) or isinstance(c.default_value, int):
@@ -121,14 +127,24 @@ def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
isinstance(Config.get_config(plugin.model, c.key, c.value), list) isinstance(Config.get_config(plugin.model, c.key, c.value), list)
or isinstance(c.default_value, list) or isinstance(c.default_value, list)
): ):
default_value = Config.get_config(plugin.model, c.key, c.value)
c.value = c.value.split(",") c.value = c.value.split(",")
if default_value and isinstance(default_value[0], int):
c.value = [int(x) for x in c.value]
elif default_value and isinstance(default_value[0], float):
c.value = [float(x) for x in c.value]
elif default_value and isinstance(default_value[0], bool):
temp = []
for x in c.value:
temp.append(x.lower() == "true")
c.value = temp
Config.set_config(plugin.model, c.key, c.value) Config.set_config(plugin.model, c.key, c.value)
Config.save(None, True) Config.save(None, True)
else: else:
if plugin.plugin_settings: if plugin.plugin_settings:
for key, value in plugin.plugin_settings: for key, value in plugin.plugin_settings:
if plugin.plugin_settings.cmd: if key == "cmd":
plugin.plugin_settings.cmd = plugin.plugin_settings.cmd.split(',') value = value.split(",")
plugins2settings_manager.set_module_data(plugin.model, key, value) plugins2settings_manager.set_module_data(plugin.model, key, value)
if plugin.plugin_manager: if plugin.plugin_manager:
for key, value in plugin.plugin_manager: for key, value in plugin.plugin_manager:
@@ -141,4 +157,4 @@ def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
code=500, code=500,
data=f"WEB_UI POST /webui/plugins model:{plugin.model} 发生错误 {type(e)}:{e}", data=f"WEB_UI POST /webui/plugins model:{plugin.model} 发生错误 {type(e)}:{e}",
) )
return Result(code=200) return Result(code=200, data="修改成功!")
+1 -1
View File
@@ -34,7 +34,7 @@ async def _(parma: RequestParma, user: User = Depends(token_to_user)) -> Result:
操作请求 操作请求
:param parma: 参数 :param parma: 参数
""" """
result = "ok" result = "操作成功!"
flag = 3 flag = 3
if bot := get_bot(): if bot := get_bot():
if parma.handle == "approve": if parma.handle == "approve":
+5 -5
View File
@@ -29,7 +29,7 @@ disk_data = {"data": []}
@app.get("/webui/system") @app.get("/webui/system")
async def _(user: User = Depends(token_to_user)) -> Result: async def _() -> Result:
return await get_system_data() return await get_system_data()
@@ -74,7 +74,7 @@ async def _(user: User = Depends(token_to_user)) -> Result:
) )
async def get_system_data(): async def get_system_data(user: User = Depends(token_to_user)):
""" """
说明: 说明:
获取系统信息,资源文件大小,网络状态等 获取系统信息,资源文件大小,网络状态等
@@ -92,7 +92,7 @@ async def get_system_data():
logger.warning(f"访问Google失败... {type(e)}: {e}") logger.warning(f"访问Google失败... {type(e)}: {e}")
google = 404 google = 404
network = SystemNetwork(baidu=baidu, google=google) network = SystemNetwork(baidu=baidu, google=google)
disk = await asyncio.get_event_loop().run_in_executor(None, _get_system_disk) disk = await asyncio.get_event_loop().run_in_executor(None, _get_system_disk, None)
status = await asyncio.get_event_loop().run_in_executor(None, _get_system_status) status = await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
return Result( return Result(
code=200, code=200,
@@ -105,7 +105,7 @@ async def get_system_data():
) )
def _get_system_status() -> SystemStatus: def _get_system_status(user: User = Depends(token_to_user)) -> SystemStatus:
""" """
说明: 说明:
获取系统信息等 获取系统信息等
@@ -123,7 +123,7 @@ def _get_system_status() -> SystemStatus:
def _get_system_disk( def _get_system_disk(
type_: Optional[str], type_: Optional[str], user: User = Depends(token_to_user)
) -> Union[SystemFolderSize, Dict[str, Union[float, datetime]]]: ) -> Union[SystemFolderSize, Dict[str, Union[float, datetime]]]:
""" """
说明: 说明:
+27 -9
View File
@@ -1,4 +1,6 @@
import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
from configs.path_config import DATA_PATH
from typing import Optional from typing import Optional
from starlette import status from starlette import status
from fastapi import Depends, HTTPException from fastapi import Depends, HTTPException
@@ -8,6 +10,8 @@ from configs.config import Config
from jose import JWTError, jwt from jose import JWTError, jwt
import nonebot import nonebot
from ..config import Result
app = nonebot.get_app() app = nonebot.get_app()
@@ -18,6 +22,13 @@ ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="webui/login") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="webui/login")
token_file = DATA_PATH / "web_ui" / "token.json"
token_file.parent.mkdir(parents=True, exist_ok=True)
token_data = {"token": []}
if token_file.exists():
token_data = json.load(open(token_file, 'r', encoding='utf8'))
class User(BaseModel): class User(BaseModel):
username: str username: str
password: str password: str
@@ -62,6 +73,11 @@ async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
if not user or user.password != form_data.password: if not user or user.password != form_data.password:
raise form_exception raise form_exception
access_token = create_token(user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)) access_token = create_token(user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
token_data["token"].append(access_token)
if len(token_data["token"]) > 3:
token_data["token"] = token_data["token"][1:]
with open(token_file, 'w', encoding="utf8") as f:
json.dump(token_data, f, ensure_ascii=False, indent=4)
return {"access_token": access_token, "token_type": "bearer"} return {"access_token": access_token, "token_type": "bearer"}
@@ -72,16 +88,18 @@ credentials_exception = HTTPException(
) )
@app.post("/webui/auth")
def token_to_user(token: str = Depends(oauth2_scheme)): def token_to_user(token: str = Depends(oauth2_scheme)):
try: if token not in token_data["token"]:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) try:
username, expire = payload.get("sub"), payload.get("exp") payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user = get_user(username) username, expire = payload.get("sub"), payload.get("exp")
if user is None: user = get_user(username)
raise JWTError if user is None:
except JWTError: raise JWTError
raise credentials_exception except JWTError:
return user return Result(code=401)
return Result(code=200, data="ok")
if __name__ == '__main__': if __name__ == '__main__':
+1 -1
View File
@@ -7,7 +7,7 @@ import nonebot
app = nonebot.get_app() app = nonebot.get_app()
origins = ["http://localhost"] origins = ["*"]
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
+1 -1
View File
@@ -61,7 +61,7 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
msg_sp = msg.split("<|>") msg_sp = msg.split("<|>")
w, h = w2b.size w, h = w2b.size
add_h, font_size = init_h_font_size(h) add_h, font_size = init_h_font_size(h)
bg = BuildImage(w, h + add_h, color="black", font_size=font_size) bg = BuildImage(w, h + add_h, color="black", font_size=int(font_size))
bg.paste(w2b) bg.paste(w2b)
chinese_msg = formalization_msg(msg) chinese_msg = formalization_msg(msg)
if not bg.check_font_size(chinese_msg): if not bg.check_font_size(chinese_msg):
+6 -8
View File
@@ -1,20 +1,18 @@
import re import re
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Event
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Event
from utils.utils import get_message_img_file from utils.utils import get_message_img_file
from nonebot.typing import T_State
from .model import WordBank from .model import WordBank
async def check(bot: Bot, event: Event, state: T_State) -> bool: async def check(event: Event) -> bool:
if isinstance(event, GroupMessageEvent): if isinstance(event, GroupMessageEvent):
msg = event.raw_message msg = event.raw_message
list_img = get_message_img_file(event.json()) list_img = get_message_img_file(event.json())
if list_img: if list_img:
for img_file in list_img: for img_file in list_img:
strinfo = re.compile(f"{img_file},subType=\d*]") strinfo = re.compile(f"{img_file},.*?]")
msg = strinfo.sub(f'{img_file}]', msg) msg = strinfo.sub(f'{img_file}]', msg)
return bool( strinfo_face = re.compile(f",type=sticker]")
await WordBank.check(event.group_id, msg, event.is_tome()) msg = strinfo_face.sub(f']', msg)
) return bool(await WordBank.check(event.group_id, msg,))
return False return False
+29 -11
View File
@@ -1,9 +1,10 @@
from utils.message_builder import image, at from utils.message_builder import image, at, face
from typing import Tuple
from ._rule import check from ._rule import check
from .model import WordBank from .model import WordBank
from configs.path_config import DATA_PATH from configs.path_config import DATA_PATH
from nonebot.adapters.onebot.v11 import GroupMessageEvent from nonebot.adapters.onebot.v11 import GroupMessageEvent
from utils.utils import get_message_at, get_message_img from utils.utils import get_message_at, get_message_img, change_img_md5
from nonebot import on_message from nonebot import on_message
from models.group_member_info import GroupInfoUser from models.group_member_info import GroupInfoUser
from utils.utils import get_message_img_file, is_number from utils.utils import get_message_img_file, is_number
@@ -23,16 +24,16 @@ async def _(event: GroupMessageEvent):
list_img = get_message_img_file(event.json()) list_img = get_message_img_file(event.json())
if list_img: if list_img:
for img_file in list_img: for img_file in list_img:
strinfo = re.compile(f"{img_file},subType=\d*]") strinfo = re.compile(f"{img_file},.*?]")
msg = strinfo.sub(f'{img_file}]', msg) msg = strinfo.sub(f'{img_file}]', msg)
q = await WordBank.check( strinfo_face = re.compile(f",type=sticker]")
event.group_id, msg, event.is_tome() msg = strinfo_face.sub(f']', msg)
) q = await WordBank.check(event.group_id, msg, )
await message_handle.send(await get_one_answer(event, q.format, q.answer)) await message_handle.send(await get_one_answer(event, q.format, q.answer))
# 处理单条回答 # 处理单条回答
async def get_one_answer(event, format, _answer, all=1): async def get_one_answer(event, format: str, _answer: str, all: bool = True) -> str:
path = data_dir / f"{event.group_id}" path = data_dir / f"{event.group_id}"
placeholder_list = ( placeholder_list = (
[ [
@@ -50,12 +51,13 @@ async def get_one_answer(event, format, _answer, all=1):
else: else:
for idx, placeholder in placeholder_list: for idx, placeholder in placeholder_list:
if placeholder.endswith("jpg"): if placeholder.endswith("jpg"):
change_img_md5(path / placeholder)
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + image( answer += _a[: _a.find(f"[__placeholder_{idx}]")] + image(
path / placeholder path / placeholder
) )
else: else:
if all == 1: if all:
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + at(placeholder) answer += _a[: _a.find(f"[__placeholder_{idx}]")] + at(int(placeholder))
else: else:
q = await GroupInfoUser.get_member_info( q = await GroupInfoUser.get_member_info(
int(placeholder), event.group_id) int(placeholder), event.group_id)
@@ -65,7 +67,7 @@ async def get_one_answer(event, format, _answer, all=1):
# 处理单条问题 # 处理单条问题
async def get_one_problem(event, problem): async def get_one_problem(event, problem: str, ) -> Tuple[str, str]:
strinfo = re.compile(f",subType=\d") strinfo = re.compile(f",subType=\d")
problem = strinfo.sub('', problem) problem = strinfo.sub('', problem)
_problem = problem _problem = problem
@@ -93,7 +95,7 @@ async def get_one_problem(event, problem):
# 显示单条数据库问题 # 显示单条数据库问题
async def get_one_image_problem(event, problem): async def get_one_image_problem(event, problem: str) -> str:
path = data_dir / f"{event.group_id}" / "problem" path = data_dir / f"{event.group_id}" / "problem"
placeholder_list = [] placeholder_list = []
idx = 0 idx = 0
@@ -127,3 +129,19 @@ async def get_one_image_problem(event, problem):
_p = _p[_p.find(f"[__placeholder_{idx}]") + len(f"[__placeholder_{idx}]"):] _p = _p[_p.find(f"[__placeholder_{idx}]") + len(f"[__placeholder_{idx}]"):]
return problem + _p return problem + _p
# 替换cq码
async def replace_cq(group_id, msg: str, is_face: bool = True) -> str:
strinfo_img = re.compile(f"\[CQ:image.*?]")
msg = strinfo_img.sub('[图片]', msg)
at_list = re.findall(rf"\[CQ:at,qq=(.*?)]", msg)
if at_list:
for ats in at_list:
q = await GroupInfoUser.get_member_info(
int(ats), group_id)
msg = msg.replace(f'[CQ:at,qq={ats}]', "@" + q.user_name)
if is_face:
strinfo_face = re.compile(f"\[CQ:face,id=.*?]")
msg = strinfo_face.sub('[表情]', msg)
return msg
+22 -42
View File
@@ -1,9 +1,7 @@
from services.db_context import db from services.db_context import db
from typing import Optional, List, Union, Tuple from typing import Optional, List, Union, Tuple
from datetime import datetime from datetime import datetime
from pathlib import Path
from configs.path_config import DATA_PATH from configs.path_config import DATA_PATH
import re
import random import random
from configs.config import Config from configs.config import Config
@@ -125,58 +123,40 @@ class WordBank(db.Model):
q.sort() q.sort()
_tmp = [] _tmp = []
for problem in q: for problem in q:
if "[_to_me" in problem:
r = re.search(r"\[_to_me\|(.*?)](.*)", problem)
if r:
bot_name = r.group(1)
problem = problem.replace(f"[_to_me|{bot_name}]", bot_name)
_tmp.append(problem) _tmp.append(problem)
return list(set(_tmp)) return list(set(_tmp))
@classmethod @classmethod
async def check(cls, group_id: int, problem: str, is_tome: bool = False) -> Optional["WordBank"]: async def check(cls, group_id: int, problem: str) -> Optional["WordBank"]:
""" """
检测词条并随机返回 检测词条并随机返回
:param group_id: 群号 :param group_id: 群号
:param problem: 问题 :param problem: 问题
:param is_tome:是否at真寻
""" """
if is_tome: if problem:
FUZZY = Config.get_config("word_bank", "WORD_BANK_FUZZY")
KEY = Config.get_config("word_bank", "WORD_BANK_KEY")
q = await cls.query.where( q = await cls.query.where(
(cls.group_id == group_id) (cls.group_id == group_id) & (cls.problem == problem)
).gino.all() ).gino.all()
q = [x for x in q if "[_to_me" in x.problem] if KEY and FUZZY:
if q: q_fuzzy = await cls.query.where(
for x in q: (cls.group_id == group_id) & (cls.search_type == 2) & (
r = re.search(r"\[_to_me\|(.*?)](.*)", x.problem) cls.problem.contains(f'{problem}'))).gino.all()
if r and r.group(2) == problem: q_key = await cls.query.where((cls.group_id == group_id) & (cls.search_type == 1)).gino.all()
return x q_key = [x for x in q_key if str(x.problem) in (problem)]
return None q += q_fuzzy + q_key
elif FUZZY:
q_fuzzy = await cls.query.where(
(cls.group_id == group_id) & (cls.search_type == 2) & (
cls.problem.contains(f'{problem}'))).gino.all()
q += q_fuzzy
elif KEY:
q_key = await cls.query.where((cls.group_id == group_id) & (cls.search_type == 1)).gino.all()
q_key = [x for x in q_key if str(x.problem) in (problem)]
q += q_key
else: else:
if problem: return None
FUZZY = Config.get_config("word_bank", "WORD_BANK_FUZZY")
KEY = Config.get_config("word_bank", "WORD_BANK_KEY")
q = await cls.query.where(
(cls.group_id == group_id) & (cls.problem == problem)
).gino.all()
if KEY and FUZZY:
q_fuzzy = await cls.query.where(
(cls.group_id == group_id) & (cls.search_type == 2) & (
cls.problem.contains(f'{problem}'))).gino.all()
q_key = await cls.query.where((cls.group_id == group_id) & (cls.search_type == 1)).gino.all()
q_key = [x for x in q_key if str(x.problem) in (problem)]
q += q_fuzzy + q_key
elif FUZZY:
q_fuzzy = await cls.query.where(
(cls.group_id == group_id) & (cls.search_type == 2) & (
cls.problem.contains(f'{problem}'))).gino.all()
q += q_fuzzy
elif KEY:
q_key = await cls.query.where((cls.group_id == group_id) & (cls.search_type == 1)).gino.all()
q_key = [x for x in q_key if str(x.problem) in (problem)]
q += q_key
else:
return None
return random.choice(q) if q else None return random.choice(q) if q else None
+20 -27
View File
@@ -6,14 +6,13 @@ from utils.http_utils import AsyncHttpx
from ._data_source import WordBankBuilder from ._data_source import WordBankBuilder
from utils.message_builder import image from utils.message_builder import image
from utils.image_utils import text2image from utils.image_utils import text2image
from .message_handle import get_one_answer, get_one_problem, get_one_image_problem from .message_handle import get_one_answer, get_one_problem, get_one_image_problem, replace_cq
from .model import WordBank from .model import WordBank
from nonebot.adapters.onebot.v11 import ( from nonebot.adapters.onebot.v11 import (
Bot, Bot,
GroupMessageEvent, GroupMessageEvent,
Message Message
) )
from nonebot.typing import T_State
from nonebot import on_command from nonebot import on_command
import random import random
import os import os
@@ -69,7 +68,7 @@ show_word = on_command("显示词条", aliases={"查看词条"}, priority=5, blo
@add_word.handle() @add_word.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = CommandArg()): async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
msg = str(arg) msg = str(arg)
r = re.search(r"问(.+)\s?答([\s\S]*)", msg) r = re.search(r"问(.+)\s?答([\s\S]*)", msg)
if not r: if not r:
@@ -81,12 +80,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = C
if not answer: if not answer:
await add_word.finish("未检测到词条回答...") await add_word.finish("未检测到词条回答...")
idx = 0 idx = 0
for n in bot.config.nickname: _problem = problem
if n and problem.startswith(n):
_problem = f"[_to_me|{n}]" + problem[len(n):]
break
else:
_problem = problem
search_type = 0 search_type = 0
if re.search("^关键字|词(.*)", msg): if re.search("^关键字|词(.*)", msg):
search_type = 1 search_type = 1
@@ -94,7 +88,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = C
search_type = 2 search_type = 2
_builder = await get__builder(event, _problem, answer, idx) _builder = await get__builder(event, _problem, answer, idx)
if await _builder.save(search_type): if await _builder.save(search_type):
logger.info(f"已保存词条 问:{_builder.problem} 答:{msg}") logger.info(f"已保存词条 问:{_builder.problem} 答:{answer}")
await add_word.send("已保存词条:" + _builder.problem) await add_word.send("已保存词条:" + _builder.problem)
else: else:
await delete_word.send("保存失败,可能是回答重复") await delete_word.send("保存失败,可能是回答重复")
@@ -102,7 +96,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = C
@delete_word.handle() @delete_word.handle()
async def _(event: GroupMessageEvent, arg: Message = CommandArg()): async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
msg = str(arg).strip() msg = str(arg)
if not msg: if not msg:
await delete_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看") await delete_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
index = None index = None
@@ -124,7 +118,10 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
if answer := await WordBank.delete_problem_answer( if answer := await WordBank.delete_problem_answer(
event.user_id, event.group_id, _problem, index event.user_id, event.group_id, _problem, index
): ):
await delete_word.send("删除词条成功:" + problem + f"\n回答:\n{answer}")
await delete_word.send(Message(
"删除词条成功:\n问" + await replace_cq(event.group_id, problem, False) + f"\n回答:\n" + await replace_cq(
event.group_id, answer, False) + "\n"))
logger.info( logger.info(
f"(USER {event.user_id}, GROUP " f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})" f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
@@ -137,7 +134,7 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
@update_word.handle() @update_word.handle()
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()): async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
msg = str(arg) msg = str(arg)
if not msg: if not msg:
await update_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看") await update_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
@@ -157,12 +154,7 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
else: else:
await update_word.finish("此命令之后需要跟随修改内容") await update_word.finish("此命令之后需要跟随修改内容")
idx = 0 idx = 0
for n in bot.config.nickname: _problem = problem
if n and problem.startswith(n):
_problem = f"[_to_me|{n}]" + problem[len(n):]
break
else:
_problem = problem
_builder = await get__builder(event, _problem, new_answer, idx) _builder = await get__builder(event, _problem, new_answer, idx)
try: try:
@@ -185,8 +177,8 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
if not msg: if not msg:
_problem_list = await WordBank.get_group_all_problem(event.group_id) _problem_list = await WordBank.get_group_all_problem(event.group_id)
if not _problem_list: if not _problem_list:
await show_word.finish("该群未收录任何词条..") await show_word.finish("该群未收录任replace_cq何词条..")
_problem_list = [f"\t{i}. {x}" for i, x in enumerate(_problem_list)] _problem_list = [f"\t{i}. {await replace_cq(event.group_id, x)}" for i, x in enumerate(_problem_list)]
long_problem_list = len(_problem_list) long_problem_list = len(_problem_list)
max_line = Config.get_config("word_bank", "WORD_BANK_MIX") max_line = Config.get_config("word_bank", "WORD_BANK_MIX")
if long_problem_list > max_line: if long_problem_list > max_line:
@@ -245,10 +237,11 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
else: else:
# 解析图片和@ # 解析图片和@
_answer_img_nu_list = [await get_one_answer(event, format, answer, 0) for answer, format in _answer_list] _answer_img_nu_list = [await get_one_answer(event, format, answer, False) for answer, format in
_answer_list]
word_nu = len(_answer_img_nu_list) word_nu = len(_answer_img_nu_list)
img_nu = 0 img_nu = 0
answer = "词条" + msg + "回答:" answer = "词条" + msg + "\n回答:"
for i, x, in enumerate(_answer_img_nu_list): for i, x, in enumerate(_answer_img_nu_list):
r = re.findall(rf"\[CQ:image,file=", str(x)) r = re.findall(rf"\[CQ:image,file=", str(x))
if r: if r:
@@ -265,7 +258,7 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
# await show_word.send(f"词条 {msg} 回答:\n" + "\n".join(_answer_list)) # await show_word.send(f"词条 {msg} 回答:\n" + "\n".join(_answer_list))
async def get__builder(event, _problem, answer, idx): async def get__builder(event, _problem: str, answer: str, idx: int):
(data_dir / f"{event.group_id}").mkdir(exist_ok=True, parents=True) (data_dir / f"{event.group_id}").mkdir(exist_ok=True, parents=True)
(data_dir / f"{event.group_id}" / "problem").mkdir(exist_ok=True, parents=True) (data_dir / f"{event.group_id}" / "problem").mkdir(exist_ok=True, parents=True)
_builder = WordBankBuilder(event.user_id, event.group_id, _problem) _builder = WordBankBuilder(event.user_id, event.group_id, _problem)
@@ -293,16 +286,16 @@ async def get__builder(event, _problem, answer, idx):
if f"__placeholder_{rand}_{idx}.jpg" not in os.listdir(data_dir / f"{event.group_id}"): if f"__placeholder_{rand}_{idx}.jpg" not in os.listdir(data_dir / f"{event.group_id}"):
break break
rand = random.randint(1, 10000) + random.randint(1, 114514) rand = random.randint(1, 10000) + random.randint(1, 114514)
strinfo = re.compile(f"\[CQ:image,file={r.group(1)},url={_x_list[0]}\?{_x_list[1]},subType=\d*?]") strinfo = re.compile(f"\[CQ:image,file={r.group(1)},.*url={_x_list[0]}\?{_x_list[1]}.*?]")
answer = strinfo.sub(f"[__placeholder_{idx}]", answer) answer = strinfo.sub(f"[__placeholder_{idx}]", answer)
await AsyncHttpx.download_file( await AsyncHttpx.download_file(
img, data_dir / f"{event.group_id}" / f"__placeholder_{rand}_{idx}.jpg" img, data_dir / f"{event.group_id}" / f"__placeholder_{rand}_{idx}.jpg"
) )
_builder.set_placeholder(idx, f"__placeholder_{rand}_{idx}.jpg") _builder.set_placeholder(idx, f"__placeholder_{rand}_{idx}.jpg")
idx += 1 idx += 1
r_problem = re.search(rf"\[CQ:image,file=(.*?),url={_x}.*?]", _p) r_problem = re.search(rf"\[CQ:image,file=(.*?)(,subType=\d)?,url={_x}.*?]", _p)
if r_problem: if r_problem:
strinfo = re.compile(f",url={_x_list[0]}\?{_x_list[1]},subType=\d*?]") strinfo = re.compile(f"(,subType=\d)?,url={_x_list[0]}\?{_x_list[1]}.*?]")
_problem = strinfo.sub(f"]", _problem) _problem = strinfo.sub(f"]", _problem)
_p = strinfo.sub(f"]", _p) _p = strinfo.sub(f"]", _p)
problem += _p[: _p.find(f"[CQ:image,file={r_problem.group(1)}]")] + image(img) problem += _p[: _p.find(f"[CQ:image,file={r_problem.group(1)}]")] + image(img)
Generated
+546 -23
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 600 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 KiB

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

+4 -7
View File
@@ -1,10 +1,10 @@
import asyncio
from typing import Optional from typing import Optional
from nonebot.log import logger from nonebot.log import logger
from playwright.async_api import Browser, async_playwright from playwright.async_api import Browser, async_playwright
import nonebot import nonebot
from nonebot import Driver from nonebot import Driver
from services.log import logger from services.log import logger
import platform
driver: Driver = nonebot.get_driver() driver: Driver = nonebot.get_driver()
@@ -15,16 +15,14 @@ _browser: Optional[Browser] = None
async def init(**kwargs) -> Optional[Browser]: async def init(**kwargs) -> Optional[Browser]:
global _browser global _browser
browser = await async_playwright().start()
try: try:
browser = await async_playwright().start()
_browser = await browser.chromium.launch(**kwargs) _browser = await browser.chromium.launch(**kwargs)
return _browser return _browser
except NotImplementedError:
logger.warning("win环境下 初始化playwright失败,相关功能将被限制....")
except Exception as e: except Exception as e:
logger.warning(f"启动chromium发生错误 {type(e)}:{e}") logger.warning(f"启动chromium发生错误 {type(e)}:{e}")
if _browser: asyncio.get_event_loop().run_in_executor(None, install)
await _browser.close() _browser = await browser.chromium.launch(**kwargs)
return None return None
@@ -32,7 +30,6 @@ async def get_browser(**kwargs) -> Browser:
return _browser or await init(**kwargs) return _browser or await init(**kwargs)
# @driver.on_startup
def install(): def install():
"""自动安装、更新 Chromium""" """自动安装、更新 Chromium"""
logger.info("正在检查 Chromium 更新") logger.info("正在检查 Chromium 更新")
+2
View File
@@ -31,6 +31,8 @@ class ShopRegister(dict):
for key, value in kwargs.items(): for key, value in kwargs.items():
if key.startswith(f"{n}_"): if key.startswith(f"{n}_"):
_temp_kwargs[key.split("_", maxsplit=1)[-1]] = value _temp_kwargs[key.split("_", maxsplit=1)[-1]] = value
else:
_temp_kwargs[key] = value
self._data[n] = { self._data[n] = {
"price": p, "price": p,
"des": d, "des": d,
+6 -3
View File
@@ -30,6 +30,7 @@ class AsyncHttpx:
params: Optional[Dict[str, Any]] = None, params: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None, headers: Optional[Dict[str, str]] = None,
cookies: Optional[Dict[str, str]] = None, cookies: Optional[Dict[str, str]] = None,
verify: bool = True,
use_proxy: bool = True, use_proxy: bool = True,
proxy: Dict[str, str] = None, proxy: Dict[str, str] = None,
timeout: Optional[int] = 30, timeout: Optional[int] = 30,
@@ -50,7 +51,7 @@ class AsyncHttpx:
if not headers: if not headers:
headers = get_user_agent() headers = get_user_agent()
proxy = proxy if proxy else cls.proxy if use_proxy else None proxy = proxy if proxy else cls.proxy if use_proxy else None
async with httpx.AsyncClient(proxies=proxy) as client: async with httpx.AsyncClient(proxies=proxy, verify=verify) as client:
return await client.get( return await client.get(
url, url,
params=params, params=params,
@@ -68,6 +69,7 @@ class AsyncHttpx:
data: Optional[Dict[str, str]] = None, data: Optional[Dict[str, str]] = None,
content: Any = None, content: Any = None,
files: Any = None, files: Any = None,
verify: bool = True,
use_proxy: bool = True, use_proxy: bool = True,
proxy: Dict[str, str] = None, proxy: Dict[str, str] = None,
json: Optional[Dict[str, Union[Any]]] = None, json: Optional[Dict[str, Union[Any]]] = None,
@@ -96,7 +98,7 @@ class AsyncHttpx:
if not headers: if not headers:
headers = get_user_agent() headers = get_user_agent()
proxy = proxy if proxy else cls.proxy if use_proxy else None proxy = proxy if proxy else cls.proxy if use_proxy else None
async with httpx.AsyncClient(proxies=proxy) as client: async with httpx.AsyncClient(proxies=proxy, verify=verify) as client:
return await client.post( return await client.post(
url, url,
content=content, content=content,
@@ -117,6 +119,7 @@ class AsyncHttpx:
path: Union[str, Path], path: Union[str, Path],
*, *,
params: Optional[Dict[str, str]] = None, params: Optional[Dict[str, str]] = None,
verify: bool = True,
use_proxy: bool = True, use_proxy: bool = True,
proxy: Dict[str, str] = None, proxy: Dict[str, str] = None,
headers: Optional[Dict[str, str]] = None, headers: Optional[Dict[str, str]] = None,
@@ -169,7 +172,7 @@ class AsyncHttpx:
headers = get_user_agent() headers = get_user_agent()
proxy = proxy if proxy else cls.proxy if use_proxy else None proxy = proxy if proxy else cls.proxy if use_proxy else None
try: try:
async with httpx.AsyncClient(proxies=proxy) as client: async with httpx.AsyncClient(proxies=proxy, verify=verify) as client:
async with client.stream( async with client.stream(
"GET", "GET",
url, url,
+27 -17
View File
@@ -14,6 +14,8 @@ from imagehash import ImageHash
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from PIL import Image, ImageDraw, ImageFile, ImageFilter, ImageFont from PIL import Image, ImageDraw, ImageFile, ImageFilter, ImageFont
from services import logger
ImageFile.LOAD_TRUNCATED_IMAGES = True ImageFile.LOAD_TRUNCATED_IMAGES = True
Image.MAX_IMAGE_PIXELS = None Image.MAX_IMAGE_PIXELS = None
@@ -209,13 +211,16 @@ class BuildImage:
(self.w, self.h), Image.ANTIALIAS (self.w, self.h), Image.ANTIALIAS
) )
if is_alpha: if is_alpha:
array = self.markImg.load() try:
for i in range(w): array = self.markImg.load()
for j in range(h): for i in range(w):
pos = array[i, j] for j in range(h):
is_edit = sum([1 for x in pos[0:3] if x > 240]) == 3 pos = array[i, j]
if is_edit: is_edit = sum([1 for x in pos[0:3] if x > 240]) == 3
array[i, j] = (255, 255, 255, 0) if is_edit:
array[i, j] = (255, 255, 255, 0)
except Exception as e:
logger.warning(f"背景透明化发生错误..{type(e)}:{e}")
self.draw = ImageDraw.Draw(self.markImg) self.draw = ImageDraw.Draw(self.markImg)
self.size = self.w, self.h self.size = self.w, self.h
if plain_text: if plain_text:
@@ -681,7 +686,10 @@ class BuildImage:
right, bottom = [(value - offset) * antialias for value in ellipse_box[2:]] right, bottom = [(value - offset) * antialias for value in ellipse_box[2:]]
draw.ellipse([left, top, right, bottom], fill=fill) draw.ellipse([left, top, right, bottom], fill=fill)
mask = mask.resize(self.markImg.size, Image.LANCZOS) mask = mask.resize(self.markImg.size, Image.LANCZOS)
self.markImg.putalpha(mask) try:
self.markImg.putalpha(mask)
except ValueError:
pass
async def acircle_corner(self, radii: int = 30): async def acircle_corner(self, radii: int = 30):
""" """
@@ -1492,23 +1500,25 @@ async def text2image(
width = 0 width = 0
height = 0 height = 0
_tmp = BuildImage(0, 0, font=font, font_size=font_size) _tmp = BuildImage(0, 0, font=font, font_size=font_size)
_, h = _tmp.getsize("正")
line_height = int(font_size / 3)
image_list = []
for x in text.split("\n"): for x in text.split("\n"):
if x: w, _ = _tmp.getsize(x.strip() or "正")
w, _ = _tmp.getsize(x) height += h + line_height
_, h = _tmp.getsize("正") width = width if width > w else w
height += h + _add_height image_list.append(BuildImage(w, h, font=font, font_size=font_size, plain_text=x.strip(), color=color))
width = width if width > w else w
width += pw width += pw
height += ph height += ph
A = BuildImage( A = BuildImage(
width + left_padding, width + left_padding,
height + top_padding + 2, height + top_padding + 2,
font_size=font_size,
color=color, color=color,
font=font,
) )
await A.atext((left_padding, top_padding), text, font_color) cur_h = ph
# A.show() for img in image_list:
await A.apaste(img, (pw, cur_h), True)
cur_h += img.h + line_height
return A return A

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