mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-09-30 09:10:01 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
216d32cf21 | ||
|
|
248fae4fe6 | ||
|
|
b479b6839d | ||
|
|
1a4e1e9515 | ||
|
|
e5160a4ee8 | ||
|
|
56ea3964a7 | ||
|
|
ad73778286 | ||
|
|
3e548f48c8 | ||
|
|
ae466931fa | ||
|
|
68052b526f | ||
|
|
903b5b88a7 | ||
|
|
007823d6b2 | ||
|
|
db5c4fb349 | ||
|
|
c37901290a | ||
|
|
da67f1f6f8 | ||
|
|
5172fa69e5 | ||
|
|
dd7280cd0d | ||
|
|
0d0f522c88 | ||
|
|
5429e6ed5c | ||
|
|
9db69fa05b | ||
|
|
3b8d52bcb5 | ||
|
|
807f39a336 | ||
|
|
fea2f30461 | ||
|
|
5d97e3f95f | ||
|
|
63e6ca3e99 | ||
|
|
b11590ec3c | ||
|
|
3a43ed6919 | ||
|
|
15ce9c91fb | ||
|
|
0e8d7537d4 | ||
|
|
1fca0787be | ||
|
|
af30285c00 | ||
|
|
a84cab7afd | ||
|
|
593573ddfb | ||
|
|
e9e9f81bdb | ||
|
|
61f624841b | ||
|
|
4bb38a2730 | ||
|
|
d4ec0df00c | ||
|
|
c8a7d855f8 | ||
|
|
73a126dcd5 | ||
|
|
0736533389 | ||
|
|
2695d658ab | ||
|
|
947166e793 | ||
|
|
80c49a7cf5 | ||
|
|
55bfa8f669 | ||
|
|
74ade14f5e | ||
|
|
c9b5218ebc | ||
|
|
b324b2bd65 | ||
|
|
35c038efa2 | ||
|
|
caa404d58d | ||
|
|
830103b9d5 | ||
|
|
6e18379597 | ||
|
|
6effbacb28 | ||
|
|
a20a1a0234 | ||
|
|
3667724061 | ||
|
|
785179e4a7 | ||
|
|
715338f821 | ||
|
|
7d5a82ab6d | ||
|
|
e764cfcc1c | ||
|
|
363acf37bc | ||
|
|
5fd687c1e4 | ||
|
|
dbedcbb93d | ||
|
|
9e9611f11f | ||
|
|
44002838da | ||
|
|
4daab8459f | ||
|
|
5a002f75cc | ||
|
|
a2180a1365 | ||
|
|
7b836acf36 | ||
|
|
a112a561cc | ||
|
|
6dcc2a69f4 |
@@ -140,6 +140,7 @@ cython_debug/
|
||||
|
||||
test.py
|
||||
server_ip.py
|
||||
game_utils.py
|
||||
member_activity_handle.py
|
||||
Yu-Gi-Oh/
|
||||
csgo/
|
||||
|
||||
@@ -243,6 +243,50 @@ __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
|
||||
@@ -252,7 +296,6 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
|
||||
|
||||
### 2022/6/3
|
||||
|
||||
* 修复了webUI插件相关API问题
|
||||
* 插件仓库在已安装插件边上会提示\[已安装]
|
||||
* 修复ShopRegister kwargs某些字段无效
|
||||
* 调整了一下查看所有请求中的年龄绘制 [@pull/745](https://github.com/HibiKier/zhenxun_bot/pull/745)
|
||||
@@ -284,7 +327,6 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
|
||||
* 新增自动更新插件```UPDATE_REMIND```:新版本提醒,原配置项```AUTO_UPDATE_ZHENXUN```改为自动更新升级
|
||||
* black_word新增当群权限为-1时不再检测该群
|
||||
* 修复非超级用户绑定原神cookie会被black_word阻拦
|
||||
* 修复webui中plugins2setting修改时会改变plugins2setting.cmd为字符串
|
||||
* 修复微博热搜报错,发红包小bug [@pull/688](https://github.com/HibiKier/zhenxun_bot/pull/688)
|
||||
* 更多的中文提示
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
__version__: v0.1.5.9
|
||||
__version__: v0.1.6.0
|
||||
|
||||
@@ -4,7 +4,7 @@ from nonebot import on_message
|
||||
from services.log import logger
|
||||
from models.group_info import GroupInfo
|
||||
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 utils.manager import group_manager
|
||||
from pathlib import Path
|
||||
@@ -107,6 +107,7 @@ async def _():
|
||||
group_info["group_name"],
|
||||
group_info["max_member_count"],
|
||||
group_info["member_count"],
|
||||
1
|
||||
)
|
||||
logger.info(f"自动更新群组 {g} 信息成功")
|
||||
except Exception as e:
|
||||
|
||||
@@ -7,10 +7,10 @@ from datetime import datetime
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
GroupIncreaseNoticeEvent,
|
||||
GroupDecreaseNoticeEvent,
|
||||
)
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from utils.manager import group_manager, plugins2settings_manager, requests_manager
|
||||
from configs.config import NICKNAME
|
||||
from models.group_info import GroupInfo
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from nonebot.matcher import Matcher
|
||||
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.group_member_info import GroupInfoUser
|
||||
from models.bag_user import BagUser
|
||||
@@ -23,6 +22,7 @@ from nonebot.typing import T_State
|
||||
from typing import Optional
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
MessageEvent,
|
||||
GroupMessageEvent,
|
||||
PokeNotifyEvent,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_preprocessor, IgnoredException
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
Event,
|
||||
MessageEvent,
|
||||
ActionFailed,
|
||||
PokeNotifyEvent,
|
||||
GroupMessageEvent,
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_preprocessor, IgnoredException
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
MessageEvent,
|
||||
GroupMessageEvent,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from nonebot import on_request, on_message
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
FriendRequestEvent,
|
||||
GroupRequestEvent,
|
||||
MessageEvent,
|
||||
@@ -8,7 +9,6 @@ from nonebot.adapters.onebot.v11 import (
|
||||
from models.friend_user import FriendUser
|
||||
from datetime import datetime
|
||||
from configs.config import NICKNAME, Config
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from utils.manager import requests_manager
|
||||
from models.group_info import GroupInfo
|
||||
from utils.utils import scheduler
|
||||
|
||||
@@ -22,6 +22,12 @@ __plugin_des__ = "区区昵称,才不想叫呢!"
|
||||
__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["昵称", "昵称系统"],
|
||||
}
|
||||
__plugin_configs__ = {
|
||||
"BLACK_WORD": {
|
||||
"value": ["爸", "爹", "爷", "父亲"],
|
||||
@@ -57,8 +63,9 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
|
||||
await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
|
||||
_tmp = ""
|
||||
black_word = Config.get_config("nickname", "BLACK_WORD")
|
||||
for x in msg:
|
||||
_tmp += "*" if x in black_word else x
|
||||
if black_word:
|
||||
for x in msg:
|
||||
_tmp += "*" if x in black_word else x
|
||||
msg = _tmp
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
if await GroupInfoUser.set_group_member_nickname(
|
||||
|
||||
@@ -20,7 +20,7 @@ usage:
|
||||
卸载插件 [name/id]
|
||||
""".strip()
|
||||
__plugin_des__ = "从真寻适配仓库中下载插件"
|
||||
__plugin_cmd__ = [""]
|
||||
__plugin_cmd__ = ["查看插件仓库", "更新插件仓库", "安装插件 [name/id]", "卸载插件 [name/id]"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ async def install_plugin(name: str) -> str:
|
||||
json.dump(data[name], f, ensure_ascii=False, indent=4)
|
||||
logger.debug("移动插件文件夹完成...")
|
||||
logger.info(f"成功安装插件 {name} 成功!\n{tmp}")
|
||||
return f"成功安装插件 {name},请重启bot!"
|
||||
return f"成功安装插件 {name},请重启真寻!"
|
||||
except Exception as e:
|
||||
logger.error(f"安装插件 {name} 失败 {type(e)}:{e}")
|
||||
return f"安装插件 {name} 失败 {type(e)}:{e}"
|
||||
@@ -130,12 +130,17 @@ async def show_plugin_repo() -> Union[int, str]:
|
||||
"download_url": plugin_info[key]["download_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 = (
|
||||
f'id:{i+1}\n名称:{plugin_info[key]["plugin_name"]}'
|
||||
f' \t\t{"<f font_color=#1a7e30>[已安装]</f>" if key in load_plugin_list else ""}\n'
|
||||
f' \t\t{status}\n'
|
||||
f"模块:{key}\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"-------------------"
|
||||
)
|
||||
|
||||
@@ -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.permission import SUPERUSER
|
||||
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 services.log import logger
|
||||
from configs.config import NICKNAME
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from nonebot.params import Command, CommandArg
|
||||
from typing import Tuple
|
||||
|
||||
@@ -137,9 +143,7 @@ async def _():
|
||||
async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
|
||||
cmd = cmd[0]
|
||||
msg = arg.extract_plain_text().strip().split()
|
||||
all_group = [
|
||||
g["group_id"] for g in await bot.get_group_list()
|
||||
]
|
||||
all_group = [g["group_id"] for g in await bot.get_group_list()]
|
||||
group_list = []
|
||||
for group in msg:
|
||||
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:
|
||||
group_manager.delete_group_white_list(group)
|
||||
group_list = [str(x) for x in group_list]
|
||||
await manager_group_whitelist.send(
|
||||
"已成功将 " + "\n".join(group_list) + " " + cmd
|
||||
)
|
||||
await manager_group_whitelist.send("已成功将 " + "\n".join(group_list) + " " + cmd)
|
||||
else:
|
||||
await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
|
||||
|
||||
@@ -199,6 +201,4 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
|
||||
else:
|
||||
if await GroupInfo.get_group_info(group_id):
|
||||
await GroupInfo.set_group_flag(group_id, 0)
|
||||
await group_auth.send(
|
||||
f'已为 {group_id} {cmd[:2]}群认证..'
|
||||
)
|
||||
await group_auth.send(f"已为 {group_id} {cmd[:2]}群认证..")
|
||||
|
||||
@@ -94,12 +94,13 @@ class ConfigsManager:
|
||||
del self._data[module]
|
||||
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 key: 配置名称
|
||||
:param value: 值
|
||||
:param save_simple_data: 同时保存至config.yaml
|
||||
"""
|
||||
if module in self._data.keys():
|
||||
if (
|
||||
@@ -108,7 +109,7 @@ class ConfigsManager:
|
||||
):
|
||||
self._data[module][key]["value"] = 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):
|
||||
"""
|
||||
@@ -122,7 +123,7 @@ class ConfigsManager:
|
||||
self._data[module][key]["help"] = help_
|
||||
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: 模块名
|
||||
|
||||
@@ -228,12 +228,14 @@ async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
|
||||
:param sub: BilibiliSub
|
||||
:param bot: Bot
|
||||
"""
|
||||
temp_group = []
|
||||
if rst:
|
||||
for x in sub.sub_users.split(",")[:-1]:
|
||||
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(
|
||||
group_id=int(x.split(":")[1]), message=Message(rst)
|
||||
group_id=int(x.split(":")[1]), message=Message(rst)
|
||||
)
|
||||
else:
|
||||
await bot.send_private_msg(user_id=int(x), message=Message(rst))
|
||||
|
||||
@@ -6,7 +6,7 @@ from configs.config import Config
|
||||
from pathlib import Path
|
||||
from services.log import logger
|
||||
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 utils.http_utils import AsyncHttpx
|
||||
import random
|
||||
|
||||
@@ -9,7 +9,7 @@ import platform
|
||||
# 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):
|
||||
|
||||
@@ -5,7 +5,7 @@ from .data_source import check_update, get_latest_version_data
|
||||
from services.log import logger
|
||||
from utils.utils import scheduler, get_bot
|
||||
from pathlib import Path
|
||||
from configs.config import Config
|
||||
from configs.config import NICKNAME, Config
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.params import ArgStr
|
||||
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="确定是否重启真寻?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)")
|
||||
@restart.got("flag", prompt=f"确定是否重启{NICKNAME}?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)")
|
||||
async def _(flag: str = ArgStr("flag")):
|
||||
if flag.lower() in ["true", "是", "好", "确定", "确定是"]:
|
||||
await restart.send("开始重启真寻..请稍等...")
|
||||
await restart.send(f"开始重启{NICKNAME}..请稍等...")
|
||||
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:
|
||||
await restart.send("已取消操作...")
|
||||
|
||||
@@ -126,5 +126,5 @@ async def _():
|
||||
if code == 200:
|
||||
await bot.send_private_msg(
|
||||
user_id=int(list(bot.config.superusers)[0]),
|
||||
message=f"更新完毕,请重启真寻....",
|
||||
message=f"更新完毕,请重启{NICKNAME}....",
|
||||
)
|
||||
|
||||
@@ -162,7 +162,7 @@ def _file_handle(latest_version: str) -> str:
|
||||
if backup_file.exists():
|
||||
backup_file.unlink()
|
||||
if file not in [config_file, config_path_file]:
|
||||
os.rename(file.absolute(), backup_file.absolute())
|
||||
shutil.move(file.absolute(), backup_file.absolute())
|
||||
else:
|
||||
with open(file, "r", encoding="utf8") as rf:
|
||||
data = rf.read()
|
||||
@@ -174,7 +174,7 @@ def _file_handle(latest_version: str) -> str:
|
||||
old_file = Path() / file
|
||||
if old_file not in [config_file, config_path_file] and file != "configs":
|
||||
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}")
|
||||
# except Exception as e:
|
||||
# error = f'{type(e)}:{e}'
|
||||
|
||||
@@ -149,12 +149,12 @@ async def _remind(user_id: int, uid: str):
|
||||
if current_resin < max_resin:
|
||||
user_manager.remove(uid)
|
||||
user_manager.remove_overflow(uid)
|
||||
if current_resin <= max_resin - 40:
|
||||
next_time = now + timedelta(minutes=(max_resin - 40 - current_resin + 1) * 8, seconds=10)
|
||||
elif max_resin - 40 < current_resin <= max_resin - 20:
|
||||
next_time = now + timedelta(minutes=(max_resin - 20 - current_resin + 1) * 8, seconds=10)
|
||||
elif max_resin - 20 < current_resin < max_resin:
|
||||
next_time = now + timedelta(minutes=(max_resin - current_resin) * 8, seconds=10)
|
||||
if current_resin < max_resin - 40:
|
||||
next_time = now + timedelta(minutes=(max_resin - 40 - current_resin) * 8)
|
||||
elif max_resin - 40 <= current_resin < max_resin - 20:
|
||||
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:
|
||||
custom_overflow_resin = Config.get_config("resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND")
|
||||
if user_manager.is_overflow(uid) and custom_overflow_resin:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from nonebot import on_command, on_notice
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
GroupMessageEvent,
|
||||
PokeNotifyEvent,
|
||||
Message
|
||||
@@ -24,7 +25,6 @@ from nonebot.rule import to_me
|
||||
from datetime import datetime, timedelta
|
||||
from configs.config import NICKNAME
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from nonebot.params import CommandArg
|
||||
import random
|
||||
import time
|
||||
|
||||
+14
-11
@@ -1,8 +1,7 @@
|
||||
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 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 utils.image_utils import get_img_hash
|
||||
from services.log import logger
|
||||
@@ -72,9 +71,7 @@ def save_data():
|
||||
|
||||
|
||||
async def download_img_and_hash(url, group_id) -> str:
|
||||
if await AsyncHttpx.download_file(
|
||||
url, TEMP_PATH / f"mute_{group_id}_img.jpg"
|
||||
):
|
||||
if await AsyncHttpx.download_file(url, TEMP_PATH / f"mute_{group_id}_img.jpg"):
|
||||
return str(get_img_hash(TEMP_PATH / f"mute_{group_id}_img.jpg"))
|
||||
return ""
|
||||
|
||||
@@ -133,11 +130,19 @@ async def _(bot: Bot, event: GroupMessageEvent):
|
||||
|
||||
|
||||
@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
|
||||
group_id = str(event.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()
|
||||
if cmd[0] == "刷屏检测设置":
|
||||
await mute_setting.finish(
|
||||
@@ -157,8 +162,6 @@ async def _(event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Mes
|
||||
if cmd[0] == "设置刷屏禁言时长":
|
||||
mute_data[group_id]["duration"] = int(msg)
|
||||
msg += " 分钟"
|
||||
await mute_setting.send(f'刷屏检测:{cmd[0]}为 {msg}')
|
||||
logger.info(
|
||||
f'USER {event.user_id} GROUP {group_id} {cmd[0]}:{msg}'
|
||||
)
|
||||
await mute_setting.send(f"刷屏检测:{cmd[0]}为 {msg}")
|
||||
logger.info(f"USER {event.user_id} GROUP {group_id} {cmd[0]}:{msg}")
|
||||
save_data()
|
||||
|
||||
@@ -7,7 +7,7 @@ from .models.open_cases_user import OpenCasesUser
|
||||
from services.log import logger
|
||||
from utils.utils import get_bot, cn2py
|
||||
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 utils.manager import group_manager
|
||||
from .config import *
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# from nonebot import on_message
|
||||
# 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 nonebot.adapters.onebot.v11.permission import GROUP
|
||||
# from utils.message_builder import image
|
||||
# from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
# from utils.image_utils import BuildImage
|
||||
# from utils.browser import get_browser
|
||||
# from configs.path_config import IMAGE_PATH
|
||||
|
||||
@@ -4,7 +4,7 @@ from asyncio.locks import Semaphore
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from ._model.pixiv import Pixiv
|
||||
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.http_utils import AsyncHttpx
|
||||
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"
|
||||
) as f:
|
||||
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"
|
||||
except TimeoutError:
|
||||
logger.warning(f"PIX:{img_url} 图片下载超时...")
|
||||
|
||||
@@ -20,6 +20,11 @@ usage:
|
||||
pix ?*[tags]: 通过 tag 获取相似图片,不含tag时随机抽取
|
||||
pid [uid]: 通过uid获取图片
|
||||
pix pid[pid]: 查看图库中指定pid图片
|
||||
示例:pix 萝莉 白丝
|
||||
示例:pix 萝莉 白丝 10 (10为数量)
|
||||
示例:pix #02 (当tag只有1个tag且为数字时,使用#标记,否则将被判定为数量)
|
||||
示例:pix 34582394 (查询指定uid图片)
|
||||
示例:pix pid:12323423 (查询指定pid图片)
|
||||
""".strip()
|
||||
__plugin_superuser_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")
|
||||
):
|
||||
await pix.finish("你不能看这些噢,这些都是是留给管理员看的...")
|
||||
if n := len(x) == 1 and is_number(x[0]) and int(x[0]) < 100:
|
||||
num = int(x[0])
|
||||
keyword = ""
|
||||
if (n := len(x)) == 1:
|
||||
if is_number(x[0]) and int(x[0]) < 100:
|
||||
num = int(x[0])
|
||||
keyword = ""
|
||||
elif x[0].startswith("#"):
|
||||
keyword = x[0][1:]
|
||||
elif n > 1:
|
||||
if is_number(x[-1]):
|
||||
num = int(x[-1])
|
||||
|
||||
@@ -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.params import CommandArg
|
||||
from nonebot import on_command
|
||||
from utils.utils import is_number
|
||||
from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
|
||||
from services.log import logger
|
||||
from nonebot.adapters.onebot.v11.exception import NetworkError
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from utils.message_builder import custom_forward_msg
|
||||
from configs.config import Config
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.message_builder import image
|
||||
from utils.utils import change_img_md5
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from configs.config import Config
|
||||
from utils.http_utils import AsyncHttpx
|
||||
@@ -143,6 +144,7 @@ async def download_pixiv_imgs(
|
||||
file,
|
||||
timeout=Config.get_config("pixiv_rank_search", "TIMEOUT"),
|
||||
):
|
||||
change_img_md5(file)
|
||||
if forward_msg_index is not None:
|
||||
result += image(
|
||||
f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from services import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from configs.config import Config
|
||||
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"))
|
||||
for info in data:
|
||||
similarity = info["header"]["similarity"]
|
||||
tmp = f"相似度:{similarity}%\n"
|
||||
for x in info["data"].keys():
|
||||
if x != "ext_urls":
|
||||
tmp += f"{x}:{info['data'][x]}\n"
|
||||
if "source" not in info["data"].keys():
|
||||
tmp += f'source:{info["data"]["ext_urls"][0]}\n'
|
||||
msg_list.append(tmp[:-1])
|
||||
try:
|
||||
similarity = info["header"]["similarity"]
|
||||
tmp = f"相似度:{similarity}%\n"
|
||||
for x in info["data"].keys():
|
||||
if x != "ext_urls":
|
||||
tmp += f"{x}:{info['data'][x]}\n"
|
||||
try:
|
||||
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
|
||||
|
||||
@@ -13,6 +13,7 @@ from utils.utils import (
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
ActionFailed,
|
||||
MessageEvent,
|
||||
GroupMessageEvent,
|
||||
PrivateMessageEvent,
|
||||
@@ -30,7 +31,6 @@ from .data_source import (
|
||||
add_data_to_database,
|
||||
get_setu_count,
|
||||
)
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from configs.config import Config, NICKNAME
|
||||
from utils.manager import withdraw_message_manager
|
||||
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 services.log import logger
|
||||
from utils.image_utils import get_img_hash, compressed_image
|
||||
from utils.utils import change_img_md5
|
||||
from asyncpg.exceptions import UniqueViolationError
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from typing import List, Optional
|
||||
@@ -111,6 +112,7 @@ async def search_online_setu(
|
||||
path_ / f"{index}.jpg",
|
||||
)
|
||||
logger.info(f"下载 lolicon 图片 {url_} 成功, id:{index}")
|
||||
change_img_md5(path_ / file_name)
|
||||
return image(path_ / file_name), index
|
||||
except TimeoutError:
|
||||
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
|
||||
file = IMAGE_PATH / path_ / f"{setu_image.local_id}.jpg"
|
||||
if file.exists():
|
||||
change_img_md5(file)
|
||||
return image(f"{setu_image.local_id}.jpg", path_), 200
|
||||
return await search_online_setu(setu_image.img_url, id_, path_)
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ async def _(
|
||||
result += image(b64=pic2b64(img))
|
||||
if method in ["模糊效果", "6"]:
|
||||
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
|
||||
)
|
||||
result += image(b64=pic2b64(img))
|
||||
|
||||
+25
-15
@@ -1,20 +1,30 @@
|
||||
from configs.config import Config as gConfig
|
||||
from .api import *
|
||||
from .auth import *
|
||||
|
||||
|
||||
gConfig.add_plugin_config(
|
||||
"web-ui",
|
||||
"username",
|
||||
"admin",
|
||||
name="web-ui",
|
||||
help_="前端管理用户名"
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_preprocessor, IgnoredException
|
||||
from utils.manager import plugins2settings_manager
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
MessageEvent
|
||||
)
|
||||
|
||||
gConfig.add_plugin_config(
|
||||
"web-ui",
|
||||
"password",
|
||||
None,
|
||||
name="web-ui",
|
||||
help_="前端管理密码"
|
||||
)
|
||||
|
||||
gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")
|
||||
|
||||
gConfig.add_plugin_config("web-ui", "password", None, 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,3 +1,5 @@
|
||||
from pydantic import ValidationError
|
||||
|
||||
from configs.config import Config
|
||||
from services.log import logger
|
||||
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
|
||||
data["plugin_config"] = tmp
|
||||
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:
|
||||
logger.error(
|
||||
f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}"
|
||||
@@ -137,6 +143,8 @@ def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
|
||||
else:
|
||||
if plugin.plugin_settings:
|
||||
for key, value in plugin.plugin_settings:
|
||||
if key == "cmd":
|
||||
value = value.split(",")
|
||||
plugins2settings_manager.set_module_data(plugin.model, key, value)
|
||||
if plugin.plugin_manager:
|
||||
for key, value in plugin.plugin_manager:
|
||||
|
||||
@@ -76,6 +76,8 @@ async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
|
||||
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"}
|
||||
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
|
||||
msg_sp = msg.split("<|>")
|
||||
w, h = w2b.size
|
||||
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)
|
||||
chinese_msg = formalization_msg(msg)
|
||||
if not bg.check_font_size(chinese_msg):
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import re
|
||||
|
||||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Event
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Event
|
||||
from utils.utils import get_message_img_file
|
||||
from nonebot.typing import T_State
|
||||
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):
|
||||
msg = event.raw_message
|
||||
list_img = get_message_img_file(event.json())
|
||||
if 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)
|
||||
return bool(
|
||||
await WordBank.check(event.group_id, msg, event.is_tome())
|
||||
)
|
||||
strinfo_face = re.compile(f",type=sticker]")
|
||||
msg = strinfo_face.sub(f']', msg)
|
||||
return bool(await WordBank.check(event.group_id, msg,))
|
||||
return False
|
||||
|
||||
@@ -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 .model import WordBank
|
||||
from configs.path_config import DATA_PATH
|
||||
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 models.group_member_info import GroupInfoUser
|
||||
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())
|
||||
if 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)
|
||||
q = await WordBank.check(
|
||||
event.group_id, msg, event.is_tome()
|
||||
)
|
||||
strinfo_face = re.compile(f",type=sticker]")
|
||||
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))
|
||||
|
||||
|
||||
# 处理单条回答
|
||||
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}"
|
||||
placeholder_list = (
|
||||
[
|
||||
@@ -50,12 +51,13 @@ async def get_one_answer(event, format, _answer, all=1):
|
||||
else:
|
||||
for idx, placeholder in placeholder_list:
|
||||
if placeholder.endswith("jpg"):
|
||||
change_img_md5(path / placeholder)
|
||||
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + image(
|
||||
path / placeholder
|
||||
)
|
||||
else:
|
||||
if all == 1:
|
||||
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + at(placeholder)
|
||||
if all:
|
||||
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + at(int(placeholder))
|
||||
else:
|
||||
q = await GroupInfoUser.get_member_info(
|
||||
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")
|
||||
problem = strinfo.sub('', 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"
|
||||
placeholder_list = []
|
||||
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}]"):]
|
||||
|
||||
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
@@ -1,9 +1,7 @@
|
||||
from services.db_context import db
|
||||
from typing import Optional, List, Union, Tuple
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from configs.path_config import DATA_PATH
|
||||
import re
|
||||
import random
|
||||
from configs.config import Config
|
||||
|
||||
@@ -125,58 +123,40 @@ class WordBank(db.Model):
|
||||
q.sort()
|
||||
_tmp = []
|
||||
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)
|
||||
return list(set(_tmp))
|
||||
|
||||
@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 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(
|
||||
(cls.group_id == group_id)
|
||||
(cls.group_id == group_id) & (cls.problem == problem)
|
||||
).gino.all()
|
||||
q = [x for x in q if "[_to_me" in x.problem]
|
||||
if q:
|
||||
for x in q:
|
||||
r = re.search(r"\[_to_me\|(.*?)](.*)", x.problem)
|
||||
if r and r.group(2) == problem:
|
||||
return x
|
||||
return None
|
||||
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:
|
||||
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(
|
||||
(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 None
|
||||
|
||||
return random.choice(q) if q else None
|
||||
|
||||
|
||||
@@ -6,14 +6,13 @@ from utils.http_utils import AsyncHttpx
|
||||
from ._data_source import WordBankBuilder
|
||||
from utils.message_builder import image
|
||||
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 nonebot.adapters.onebot.v11 import (
|
||||
Bot,
|
||||
GroupMessageEvent,
|
||||
Message
|
||||
)
|
||||
from nonebot.typing import T_State
|
||||
from nonebot import on_command
|
||||
import random
|
||||
import os
|
||||
@@ -69,7 +68,7 @@ show_word = on_command("显示词条", aliases={"查看词条"}, priority=5, blo
|
||||
|
||||
|
||||
@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)
|
||||
r = re.search(r"问(.+)\s?答([\s\S]*)", msg)
|
||||
if not r:
|
||||
@@ -81,12 +80,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = C
|
||||
if not answer:
|
||||
await add_word.finish("未检测到词条回答...")
|
||||
idx = 0
|
||||
for n in bot.config.nickname:
|
||||
if n and problem.startswith(n):
|
||||
_problem = f"[_to_me|{n}]" + problem[len(n):]
|
||||
break
|
||||
else:
|
||||
_problem = problem
|
||||
_problem = problem
|
||||
search_type = 0
|
||||
if re.search("^关键字|词(.*)", msg):
|
||||
search_type = 1
|
||||
@@ -94,7 +88,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = C
|
||||
search_type = 2
|
||||
_builder = await get__builder(event, _problem, answer, idx)
|
||||
if await _builder.save(search_type):
|
||||
logger.info(f"已保存词条 问:{_builder.problem} 答:{msg}")
|
||||
logger.info(f"已保存词条 问:{_builder.problem} 答:{answer}")
|
||||
await add_word.send("已保存词条:" + _builder.problem)
|
||||
else:
|
||||
await delete_word.send("保存失败,可能是回答重复")
|
||||
@@ -102,7 +96,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State, arg: Message = C
|
||||
|
||||
@delete_word.handle()
|
||||
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
msg = str(arg).strip()
|
||||
msg = str(arg)
|
||||
if not msg:
|
||||
await delete_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
|
||||
index = None
|
||||
@@ -124,7 +118,10 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
if answer := await WordBank.delete_problem_answer(
|
||||
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(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
@@ -137,7 +134,7 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
|
||||
|
||||
@update_word.handle()
|
||||
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
msg = str(arg)
|
||||
if not msg:
|
||||
await update_word.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
|
||||
@@ -157,12 +154,7 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
else:
|
||||
await update_word.finish("此命令之后需要跟随修改内容")
|
||||
idx = 0
|
||||
for n in bot.config.nickname:
|
||||
if n and problem.startswith(n):
|
||||
_problem = f"[_to_me|{n}]" + problem[len(n):]
|
||||
break
|
||||
else:
|
||||
_problem = problem
|
||||
_problem = problem
|
||||
_builder = await get__builder(event, _problem, new_answer, idx)
|
||||
|
||||
try:
|
||||
@@ -185,8 +177,8 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
if not msg:
|
||||
_problem_list = await WordBank.get_group_all_problem(event.group_id)
|
||||
if not _problem_list:
|
||||
await show_word.finish("该群未收录任何词条..")
|
||||
_problem_list = [f"\t{i}. {x}" for i, x in enumerate(_problem_list)]
|
||||
await show_word.finish("该群未收录任replace_cq何词条..")
|
||||
_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)
|
||||
max_line = Config.get_config("word_bank", "WORD_BANK_MIX")
|
||||
if long_problem_list > max_line:
|
||||
@@ -245,10 +237,11 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
|
||||
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)
|
||||
img_nu = 0
|
||||
answer = "词条" + msg + "回答:"
|
||||
answer = "词条" + msg + "\n回答:"
|
||||
for i, x, in enumerate(_answer_img_nu_list):
|
||||
r = re.findall(rf"\[CQ:image,file=", str(x))
|
||||
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))
|
||||
|
||||
|
||||
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}" / "problem").mkdir(exist_ok=True, parents=True)
|
||||
_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}"):
|
||||
break
|
||||
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)
|
||||
await AsyncHttpx.download_file(
|
||||
img, data_dir / f"{event.group_id}" / f"__placeholder_{rand}_{idx}.jpg"
|
||||
)
|
||||
_builder.set_placeholder(idx, f"__placeholder_{rand}_{idx}.jpg")
|
||||
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:
|
||||
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)
|
||||
_p = strinfo.sub(f"]", _p)
|
||||
problem += _p[: _p.find(f"[CQ:image,file={r_problem.group(1)}]")] + image(img)
|
||||
|
||||
Generated
+546
-23
File diff suppressed because it is too large
Load Diff
+4
-7
@@ -1,10 +1,10 @@
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
from nonebot.log import logger
|
||||
from playwright.async_api import Browser, async_playwright
|
||||
import nonebot
|
||||
from nonebot import Driver
|
||||
from services.log import logger
|
||||
import platform
|
||||
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
@@ -15,16 +15,14 @@ _browser: Optional[Browser] = None
|
||||
|
||||
async def init(**kwargs) -> Optional[Browser]:
|
||||
global _browser
|
||||
browser = await async_playwright().start()
|
||||
try:
|
||||
browser = await async_playwright().start()
|
||||
_browser = await browser.chromium.launch(**kwargs)
|
||||
return _browser
|
||||
except NotImplementedError:
|
||||
logger.warning("win环境下 初始化playwright失败,相关功能将被限制....")
|
||||
except Exception as e:
|
||||
logger.warning(f"启动chromium发生错误 {type(e)}:{e}")
|
||||
if _browser:
|
||||
await _browser.close()
|
||||
asyncio.get_event_loop().run_in_executor(None, install)
|
||||
_browser = await browser.chromium.launch(**kwargs)
|
||||
return None
|
||||
|
||||
|
||||
@@ -32,7 +30,6 @@ async def get_browser(**kwargs) -> Browser:
|
||||
return _browser or await init(**kwargs)
|
||||
|
||||
|
||||
# @driver.on_startup
|
||||
def install():
|
||||
"""自动安装、更新 Chromium"""
|
||||
logger.info("正在检查 Chromium 更新")
|
||||
|
||||
+6
-3
@@ -30,6 +30,7 @@ class AsyncHttpx:
|
||||
params: Optional[Dict[str, Any]] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
cookies: Optional[Dict[str, str]] = None,
|
||||
verify: bool = True,
|
||||
use_proxy: bool = True,
|
||||
proxy: Dict[str, str] = None,
|
||||
timeout: Optional[int] = 30,
|
||||
@@ -50,7 +51,7 @@ class AsyncHttpx:
|
||||
if not headers:
|
||||
headers = get_user_agent()
|
||||
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(
|
||||
url,
|
||||
params=params,
|
||||
@@ -68,6 +69,7 @@ class AsyncHttpx:
|
||||
data: Optional[Dict[str, str]] = None,
|
||||
content: Any = None,
|
||||
files: Any = None,
|
||||
verify: bool = True,
|
||||
use_proxy: bool = True,
|
||||
proxy: Dict[str, str] = None,
|
||||
json: Optional[Dict[str, Union[Any]]] = None,
|
||||
@@ -96,7 +98,7 @@ class AsyncHttpx:
|
||||
if not headers:
|
||||
headers = get_user_agent()
|
||||
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(
|
||||
url,
|
||||
content=content,
|
||||
@@ -117,6 +119,7 @@ class AsyncHttpx:
|
||||
path: Union[str, Path],
|
||||
*,
|
||||
params: Optional[Dict[str, str]] = None,
|
||||
verify: bool = True,
|
||||
use_proxy: bool = True,
|
||||
proxy: Dict[str, str] = None,
|
||||
headers: Optional[Dict[str, str]] = None,
|
||||
@@ -169,7 +172,7 @@ class AsyncHttpx:
|
||||
headers = get_user_agent()
|
||||
proxy = proxy if proxy else cls.proxy if use_proxy else None
|
||||
try:
|
||||
async with httpx.AsyncClient(proxies=proxy) as client:
|
||||
async with httpx.AsyncClient(proxies=proxy, verify=verify) as client:
|
||||
async with client.stream(
|
||||
"GET",
|
||||
url,
|
||||
|
||||
+18
-10
@@ -14,6 +14,8 @@ from imagehash import ImageHash
|
||||
from matplotlib import pyplot as plt
|
||||
from PIL import Image, ImageDraw, ImageFile, ImageFilter, ImageFont
|
||||
|
||||
from services import logger
|
||||
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
Image.MAX_IMAGE_PIXELS = None
|
||||
|
||||
@@ -178,7 +180,7 @@ class BuildImage:
|
||||
self.paste_image_height = int(paste_image_height)
|
||||
self.current_w = 0
|
||||
self.current_h = 0
|
||||
self.font = ImageFont.truetype(str(FONT_PATH / font), font_size)
|
||||
self.font = ImageFont.truetype(str(FONT_PATH / font), int(font_size))
|
||||
if not plain_text and not color:
|
||||
color = (255, 255, 255)
|
||||
self.background = background
|
||||
@@ -209,13 +211,16 @@ class BuildImage:
|
||||
(self.w, self.h), Image.ANTIALIAS
|
||||
)
|
||||
if is_alpha:
|
||||
array = self.markImg.load()
|
||||
for i in range(w):
|
||||
for j in range(h):
|
||||
pos = array[i, j]
|
||||
is_edit = sum([1 for x in pos[0:3] if x > 240]) == 3
|
||||
if is_edit:
|
||||
array[i, j] = (255, 255, 255, 0)
|
||||
try:
|
||||
array = self.markImg.load()
|
||||
for i in range(w):
|
||||
for j in range(h):
|
||||
pos = array[i, j]
|
||||
is_edit = sum([1 for x in pos[0:3] if x > 240]) == 3
|
||||
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.size = self.w, self.h
|
||||
if plain_text:
|
||||
@@ -681,7 +686,10 @@ class BuildImage:
|
||||
right, bottom = [(value - offset) * antialias for value in ellipse_box[2:]]
|
||||
draw.ellipse([left, top, right, bottom], fill=fill)
|
||||
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):
|
||||
"""
|
||||
@@ -1499,7 +1507,7 @@ async def text2image(
|
||||
w, _ = _tmp.getsize(x.strip() or "正")
|
||||
height += h + line_height
|
||||
width = width if width > w else w
|
||||
image_list.append(BuildImage(w, h, font=font, font_size=font_size, plain_text=x.strip()))
|
||||
image_list.append(BuildImage(w, h, font=font, font_size=font_size, plain_text=x.strip(), color=color))
|
||||
width += pw
|
||||
height += ph
|
||||
A = BuildImage(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from utils.manager.data_class import StaticData
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from nonebot.adapters.onebot.v11.exception import ActionFailed
|
||||
from nonebot.adapters.onebot.v11 import Bot, ActionFailed
|
||||
from services.log import logger
|
||||
from typing import Optional, Literal
|
||||
from utils.image_utils import BuildImage
|
||||
|
||||
@@ -5,6 +5,8 @@ from configs.config import SYSTEM_PROXY, Config
|
||||
from typing import List, Union, Optional, Type, Any
|
||||
from nonebot.adapters.onebot.v11 import Bot, Message
|
||||
from nonebot.matcher import matchers, Matcher
|
||||
from services.log import logger
|
||||
from pathlib import Path
|
||||
import httpx
|
||||
import nonebot
|
||||
import pytz
|
||||
@@ -398,3 +400,19 @@ def change_pixiv_image_links(
|
||||
.replace("_webp", "")
|
||||
)
|
||||
return url
|
||||
|
||||
|
||||
def change_img_md5(path_file: Union[str, Path]) -> bool:
|
||||
"""
|
||||
说明:
|
||||
改变图片MD5
|
||||
参数:
|
||||
:param path_file: 图片路径
|
||||
"""
|
||||
try:
|
||||
with open(path_file, "a") as f:
|
||||
f.write(str(int(time.time() * 1000)))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"改变图片MD5发生错误 {type(e)}:{e} Path:{path_file}")
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user