Compare commits

..
36 Commits
Author SHA1 Message Date
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
HibiKier 38501cebf1 Update data_source.py 2022-05-29 20:56:03 +08:00
HibiKier ee45d0217e Update __init__.py 2022-05-29 20:55:32 +08:00
HibiKier 558f362919 update v0.1.5.8 2022-05-29 20:47:18 +08:00
HibiKier fb9db2f50c fix 2022-05-29 19:57:57 +08:00
github-actions[bot] 374b7b7261 Auto generate poetry.lock 2022-05-25 23:42:48 +00:00
70 changed files with 175 additions and 81 deletions
+28 -2
View File
@@ -243,10 +243,36 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
## 更新 ## 更新
### 2022/5/29 \[v0.1.5.7] ### 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
* 修复了webUI插件相关API问题
* 插件仓库在已安装插件边上会提示\[已安装]
* 修复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]
* 修复错误的resource路径会删除IMAGE_PATH等重要文件夹
* 提供了真寻适配仓库的插件 安装/卸载 操作 * 提供了真寻适配仓库的插件 安装/卸载 操作
* 暂时关闭了插件资源清空
* 通过指令安装插件时会在插件目录下生成plugin_info.json记录当前插件信息
### 2022/5/28 ### 2022/5/28
+1 -1
View File
@@ -1 +1 @@
__version__: v0.1.5.6 __version__: v0.1.5.9
@@ -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"
@@ -40,7 +40,7 @@ def init_none_plugin_count_manager():
plugins2block_manager.save() plugins2block_manager.save()
plugins_manager.delete(module) plugins_manager.delete(module)
plugins_manager.save() plugins_manager.save()
resources_manager.remove_resource(module) # resources_manager.remove_resource(module)
none_plugin_count_manager.delete(module) none_plugin_count_manager.delete(module)
logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...") logger.info(f"{module}:{plugin_name} 插件疑似已删除,清除对应插件数据...")
except Exception as e: except Exception as e:
+13 -2
View File
@@ -1,6 +1,6 @@
from nonebot import on_command, on_regex from nonebot import on_command, on_regex
from .data_source import show_plugin_repo, install_plugin, uninstall_plugin from .data_source import show_plugin_repo, install_plugin, uninstall_plugin, download_json
from services.log import logger from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.params import CommandArg from nonebot.params import CommandArg
@@ -15,7 +15,8 @@ usage:
下载安装插件 下载安装插件
指令: 指令:
查看插件仓库 查看插件仓库
安装插件 [name/id] 更新插件仓库
安装插件 [name/id] (重新安装等同于更新)
卸载插件 [name/id] 卸载插件 [name/id]
""".strip() """.strip()
__plugin_des__ = "从真寻适配仓库中下载插件" __plugin_des__ = "从真寻适配仓库中下载插件"
@@ -25,6 +26,8 @@ __plugin_author__ = "HibiKier"
show_repo = on_regex("^查看插件仓库$", priority=1, block=True, permission=SUPERUSER) show_repo = on_regex("^查看插件仓库$", priority=1, block=True, permission=SUPERUSER)
update_repo = on_regex("^更新插件仓库$", priority=1, block=True, permission=SUPERUSER)
install_plugin_matcher = on_command("安装插件", priority=1, block=True, permission=SUPERUSER) install_plugin_matcher = on_command("安装插件", priority=1, block=True, permission=SUPERUSER)
uninstall_plugin_matcher = on_command("卸载插件", priority=1, block=True, permission=SUPERUSER) uninstall_plugin_matcher = on_command("卸载插件", priority=1, block=True, permission=SUPERUSER)
@@ -44,6 +47,14 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
await install_plugin_matcher.send(msg) await install_plugin_matcher.send(msg)
@update_repo.handle()
async def _(bot: Bot, event: MessageEvent):
code = await download_json()
if code == 200:
await update_repo.finish("更新插件仓库信息成功!")
await update_repo.send("更新插件仓库信息失败!")
@show_repo.handle() @show_repo.handle()
async def _(bot: Bot, event: MessageEvent): async def _(bot: Bot, event: MessageEvent):
msg = await show_plugin_repo() msg = await show_plugin_repo()
+15 -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,6 +72,13 @@ 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()}"
) )
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)
logger.debug("移动插件文件夹完成...") logger.debug("移动插件文件夹完成...")
logger.info(f"成功安装插件 {name} 成功!\n{tmp}") logger.info(f"成功安装插件 {name} 成功!\n{tmp}")
return f"成功安装插件 {name},请重启bot!" return f"成功安装插件 {name},请重启bot!"
@@ -108,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
@@ -122,8 +131,9 @@ async def show_plugin_repo() -> Union[int, str]:
"github_url": plugin_info[key]["github_url"], "github_url": plugin_info[key]["github_url"],
} }
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{"<f font_color=#1a7e30>[已安装]</f>" if key in load_plugin_list else ""}\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"]}\n'
f'简介:{plugin_info[key]["introduction"]}\n' f'简介:{plugin_info[key]["introduction"]}\n'
@@ -133,10 +143,10 @@ async def show_plugin_repo() -> Union[int, str]:
w = w if w > img.w else img.w w = w if w > img.w else img.w
h += img.h + line_height h += img.h + line_height
image_list.append(img) image_list.append(img)
A = BuildImage(w + 100, h + 100, color="#f9f6f2") A = BuildImage(w + 50, h + 50, color="#f9f6f2")
cur_h = 50 cur_h = 25
for img in image_list: for img in image_list:
await A.apaste(img, (50, cur_h)) await A.apaste(img, (25, cur_h))
cur_h += img.h + line_height cur_h += img.h + line_height
return A.pic2bs4() return A.pic2bs4()
+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("已清空所有好友/群聊请求..")
+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
@@ -27,7 +27,7 @@ __plugin_author__ = "HibiKier"
__plugin_configs__ = { __plugin_configs__ = {
"UPDATE_REMIND": { "UPDATE_REMIND": {
"value": True, "value": True,
"help": "真寻是否自动检查更新", "help": "真寻是否检测版本状态",
"default": True, "default": True,
}, },
"AUTO_UPDATE_ZHENXUN": { "AUTO_UPDATE_ZHENXUN": {
@@ -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,16 +142,18 @@ 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 - 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) next_time = now + timedelta(minutes=(max_resin - 20 - current_resin + 1) * 8, seconds=10)
elif current_resin < max_resin: elif max_resin - 20 < current_resin < max_resin:
next_time = now + timedelta(minutes=(max_resin - current_resin) * 8, seconds=10) next_time = now + timedelta(minutes=(max_resin - current_resin) * 8, seconds=10)
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")
@@ -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} 原神树脂提醒"
)
+1 -1
View File
@@ -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))
@@ -36,7 +36,7 @@ __plugin_settings__ = {
"limit_superuser": False, "limit_superuser": False,
"cmd": ["发送图片"] + Config.get_config("image_management", "IMAGE_DIR_LIST"), "cmd": ["发送图片"] + Config.get_config("image_management", "IMAGE_DIR_LIST"),
} }
__plugin_resources__ = {"pa": IMAGE_PATH} __plugin_resources__ = {"pa": IMAGE_PATH / "pa"}
Config.add_plugin_config( Config.add_plugin_config(
"_task", "_task",
+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}")
+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="修改成功!")
+12 -4
View File
@@ -108,7 +108,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 +121,22 @@ 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:
plugin.plugin_settings.cmd = plugin.plugin_settings.cmd.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 +149,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]]]:
""" """
说明: 说明:
+25 -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,9 @@ 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:]
return {"access_token": access_token, "token_type": "bearer"} return {"access_token": access_token, "token_type": "bearer"}
@@ -72,16 +86,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,
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

+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,
+12 -10
View File
@@ -178,7 +178,7 @@ class BuildImage:
self.paste_image_height = int(paste_image_height) self.paste_image_height = int(paste_image_height)
self.current_w = 0 self.current_w = 0
self.current_h = 0 self.current_h = 0
self.font = ImageFont.truetype(str(FONT_PATH / font), int(font_size)) self.font = ImageFont.truetype(str(FONT_PATH / font), font_size)
if not plain_text and not color: if not plain_text and not color:
color = (255, 255, 255) color = (255, 255, 255)
self.background = background self.background = background
@@ -1492,23 +1492,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()))
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
+1 -1
View File
@@ -158,7 +158,7 @@ class RequestManager(StaticData):
) )
ava.circle() ava.circle()
age_bk = BuildImage( age_bk = BuildImage(
len(str(age)) * 10 - 5, len(str(age)) * 6 + 6,
15, 15,
color="#04CAF7" if sex == "male" else "#F983C1", color="#04CAF7" if sex == "male" else "#F983C1",
) )