diff --git a/README.md b/README.md
index 844e7a916..326a1a530 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,9 @@
## 声明
此项目仅用于学习交流,请勿用于非法用途
+## Gitee同步
+# [Gitee](https://gitee.com/two_Dimension/zhenxun_bot)
+
## 未完成的文档
# [传送门](https://hibikier.github.io/zhenxun_bot/)
@@ -67,6 +70,8 @@
- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
- [x] 原神便笺查询
- [x] 原神玩家查询
+- [x] 原神树脂提醒
+- [x] 原神签到/自动签到
- [x] 金币红包
- [x] 微博热搜
- [x] B站主播/UP/番剧订阅
@@ -147,6 +152,7 @@
- [x] 清理临时数据
- [x] 增删群认证
- [x] 同意/拒绝好友/群聊请求
+- [x] 配置重载
#### 超级用户的被动技能
- [x] 邀请入群提醒(别人邀请真寻入群)
@@ -171,6 +177,7 @@
- [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
- [x] 群权限系统
- [x] 定时更新权限
+- [x] 自动配置重载
## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
@@ -226,6 +233,24 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
## 更新
+### 2021/2/11
+
+* 修复pix不使用反代无法下载图片
+
+### 2021/2/10 \[v0.1.1]
+
+* 修复购买道具出错
+
+### 2021/2/9 \[v0.1]
+
+* 新增原神自动签到和手动签到
+* 新增原神树脂提醒
+* 新增手动重载Config.yaml命令以及重载配置定时任务(极少部分帮助或配置可能需要重启
+* 修改了发送本地图库的matcher,改为on_message
+* register_use可以通过返回值发送消息
+* 修复修改商品时限制时间出错
+* 修复超时商品依旧可以被购买
+
### 2021/1/16 \[v0.0.9.0]
* Ai提供文本敏感词过滤器
@@ -316,5 +341,5 @@ __..... 更多更新信息请查看文档__
[H-K-Y / Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot) :原神bot,这是一个基于nonebot和HoshinoBot的原神娱乐及信息查询插件
[NothAmor / nonebot2_luxun_says](https://github.com/NothAmor/nonebot2_luxun_says) :基于nonebot2机器人框架的鲁迅说插件
[Kyomotoi / AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus) :一个~~特二刺螈~~(文爱)的适用于任何bot的词库
-[Ailitonia / omega-miya](https://github.com/Ailitonia/omega-miya) :基于nonebot2的qq机器人
+[Ailitonia / omega-miya](https://github.com/Ailitonia/omega-miya) :基于nonebot2的qq机器人
[KimigaiiWuyi / GenshinUID]("https://github.com/KimigaiiWuyi/GenshinUID") :一个基于HoshinoBot/NoneBot2的原神UID查询插件
diff --git a/__version__ b/__version__
index 0facde816..38a0893e7 100644
--- a/__version__
+++ b/__version__
@@ -1 +1 @@
-__version__: v0.0.9.0
+__version__: v0.1.1
\ No newline at end of file
diff --git a/basic_plugins/init_plugin_config/__init__.py b/basic_plugins/init_plugin_config/__init__.py
index f2b6f9636..65156ada6 100755
--- a/basic_plugins/init_plugin_config/__init__.py
+++ b/basic_plugins/init_plugin_config/__init__.py
@@ -11,7 +11,6 @@
)
from .init import init
from .check_plugin_status import check_plugin_status
-from utils.manager import admin_manager
from nonebot.adapters.cqhttp import Bot
from configs.path_config import DATA_PATH
from services.log import logger
diff --git a/basic_plugins/scripts.py b/basic_plugins/scripts.py
index 8272239df..b45569c67 100755
--- a/basic_plugins/scripts.py
+++ b/basic_plugins/scripts.py
@@ -93,6 +93,18 @@ async def _():
"ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
"bag_users",
), # bag_users 新增字段 property 替代 props
+ (
+ "ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
+ "genshin"
+ ), # 新增原神自动签到字段
+ (
+ "ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
+ "genshin"
+ ), # 新增原神自动签到字段
+ (
+ "ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
+ "genshin"
+ ), # 新增原神自动签到字段
]
for sql in sql_str:
try:
diff --git a/basic_plugins/shop/buy.py b/basic_plugins/shop/buy.py
index 374464dc3..430a0fa67 100644
--- a/basic_plugins/shop/buy.py
+++ b/basic_plugins/shop/buy.py
@@ -7,6 +7,7 @@
from services.db_context import db
from nonebot.adapters.cqhttp.permission import GROUP
from models.goods_info import GoodsInfo
+import time
__zx_plugin_name__ = "商店 - 购买道具"
@@ -20,7 +21,7 @@
""".strip()
__plugin_des__ = "商店 - 购买道具"
__plugin_cmd__ = ["购买 [序号或名称] ?[数量=1]"]
-__plugin_type__ = ('商店',)
+__plugin_type__ = ("商店",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
@@ -29,9 +30,7 @@
"limit_superuser": False,
"cmd": ["商店", "购买道具"],
}
-__plugin_cd_limit__ = {
- "cd": 3
-}
+__plugin_cd_limit__ = {"cd": 3}
buy = on_command("购买", aliases={"购买道具"}, priority=5, block=True, permission=GROUP)
@@ -42,8 +41,15 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
goods = None
if get_message_text(event.json()) in ["神秘药水"]:
await buy.finish("你们看看就好啦,这是不可能卖给你们的~", at_sender=True)
- goods_lst = await GoodsInfo.get_all_goods()
- goods_name_lst = [x.goods_name for x in goods_lst]
+ goods_list = [
+ x
+ for x in await GoodsInfo.get_all_goods()
+ if x.goods_limit_time > time.time() or x.goods_limit_time == 0
+ ]
+ goods_name_list = [
+ x.goods_name
+ for x in goods_list
+ ]
msg = get_message_text(event.json()).split()
num = 1
if len(msg) > 1:
@@ -51,17 +57,16 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
num = int(msg[1])
else:
await buy.finish("购买的数量要是数字且大于0!", at_sender=True)
- # print(msg, num)
if is_number(msg[0]):
msg = int(msg[0])
- if msg > len(goods_lst) or msg < 1:
+ if msg > len(goods_name_list) or msg < 1:
await buy.finish("请输入正确的商品id!", at_sender=True)
- goods = goods_lst[msg - 1]
+ goods = goods_list[msg - 1]
else:
- if msg[0] in goods_name_lst:
- for i in range(len(goods_name_lst)):
- if msg[0] == goods_name_lst[i]:
- goods = goods_lst[i]
+ if msg[0] in goods_name_list:
+ for i in range(len(goods_name_list)):
+ if msg[0] == goods_name_list[i]:
+ goods = goods_list[i]
break
else:
await buy.finish("请输入正确的商品名称!")
diff --git a/basic_plugins/shop/shop_handle/data_source.py b/basic_plugins/shop/shop_handle/data_source.py
index 2c4973ef3..822f55a1f 100644
--- a/basic_plugins/shop/shop_handle/data_source.py
+++ b/basic_plugins/shop/shop_handle/data_source.py
@@ -217,11 +217,12 @@ async def update_goods(**kwargs) -> "str, str, int":
tmp += f'折扣:{discount} --> {kwargs["discount"]}\n'
discount = kwargs["discount"]
if kwargs.get("limit_time"):
+ kwargs["limit_time"] = float(kwargs["limit_time"])
new_time = time.strftime(
"%Y-%m-%d %H:%M:%S",
- time.localtime(time.time() + int(kwargs["limit_time"] * 60 * 60)),
+ time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
)
- tmp += f"折扣至: {new_time}\n"
+ tmp += f"限时至: {new_time}\n"
limit_time = kwargs["limit_time"]
return (
await GoodsInfo.update_goods(
@@ -249,7 +250,6 @@ def parse_goods_info(msg: str) -> Union[dict, str]:
sp = x.split(":", maxsplit=1)
if str(sp[1]).strip():
sp[1] = sp[1].strip()
- print(sp)
if sp[0] == "name":
data["name"] = sp[1]
elif sp[0] == "price":
diff --git a/basic_plugins/shop/use/__init__.py b/basic_plugins/shop/use/__init__.py
index 408dc6d81..0b85ce419 100644
--- a/basic_plugins/shop/use/__init__.py
+++ b/basic_plugins/shop/use/__init__.py
@@ -66,9 +66,11 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await use_props.finish(f"该道具单次只能使用 {n} 个!")
if await BagUser.delete_property(
event.user_id, event.group_id, name, num
- ) and await effect(bot, event, name, num):
+ ):
if func_manager.check_send_success_message(name):
await use_props.send(f"使用道具 {name} {num} 次成功!", at_sender=True)
+ if msg := await effect(bot, event, name, num):
+ await use_props.send(msg, at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次成功"
)
diff --git a/basic_plugins/shop/use/data_source.py b/basic_plugins/shop/use/data_source.py
index d1fc82bc1..bab56b756 100644
--- a/basic_plugins/shop/use/data_source.py
+++ b/basic_plugins/shop/use/data_source.py
@@ -1,6 +1,7 @@
-from nonebot.adapters.cqhttp import GroupMessageEvent
+from nonebot.adapters.cqhttp import GroupMessageEvent, MessageSegment
from services.log import logger
from nonebot.adapters.cqhttp import Bot
+from typing import Optional, Union
import asyncio
@@ -32,7 +33,7 @@ def get_max_num_limit(self, goods_name: str) -> int:
return self._data[goods_name]["kwargs"]["_max_num_limit"]
return 1
- async def use(self, **kwargs):
+ async def use(self, **kwargs) -> Optional[Union[str, MessageSegment]]:
"""
使用道具
:param kwargs: kwargs
@@ -40,11 +41,11 @@ async def use(self, **kwargs):
goods_name = kwargs.get("goods_name")
if self.exists(goods_name):
if asyncio.iscoroutinefunction(self._data[goods_name]["func"]):
- await self._data[goods_name]["func"](
+ return await self._data[goods_name]["func"](
**kwargs,
)
else:
- self._data[goods_name]["func"](
+ return self._data[goods_name]["func"](
**kwargs,
)
@@ -70,7 +71,9 @@ def get_kwargs(self, goods_name: str) -> dict:
func_manager = GoodsUseFuncManager()
-async def effect(bot: Bot, event: GroupMessageEvent, goods_name: str, num: int) -> bool:
+async def effect(
+ bot: Bot, event: GroupMessageEvent, goods_name: str, num: int
+) -> Optional[Union[str, MessageSegment]]:
"""
商品生效
:param bot: Bot
@@ -83,7 +86,7 @@ async def effect(bot: Bot, event: GroupMessageEvent, goods_name: str, num: int)
try:
if func_manager.exists(goods_name):
_kwargs = func_manager.get_kwargs(goods_name)
- await func_manager.use(
+ return await func_manager.use(
**{
**_kwargs,
"_bot": bot,
@@ -94,10 +97,9 @@ async def effect(bot: Bot, event: GroupMessageEvent, goods_name: str, num: int)
"goods_name": goods_name,
}
)
- return True
except Exception as e:
logger.error(f"use 商品生效函数effect 发生错误 {type(e)}:{e}")
- return False
+ return None
def register_use(goods_name: str, func, **kwargs):
diff --git a/basic_plugins/super_cmd/reload_setting.py b/basic_plugins/super_cmd/reload_setting.py
index fd92db2d6..aab55d0c1 100755
--- a/basic_plugins/super_cmd/reload_setting.py
+++ b/basic_plugins/super_cmd/reload_setting.py
@@ -8,7 +8,10 @@
group_manager,
)
from nonebot.typing import T_State
+from configs.config import Config
+from services.log import logger
from nonebot.adapters.cqhttp import Bot, MessageEvent
+from utils.utils import scheduler
__zx_plugin_name__ = "重载插件配置 [Superuser]"
@@ -28,6 +31,18 @@
]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
+__plugin_configs__ = {
+ "AUTO_RELOAD": {
+ "value": False,
+ "help": "自动重载配置文件",
+ "default_value": False
+ },
+ "AUTO_RELOAD_TIME": {
+ "value": 180,
+ "help": "控制自动重载配置文件时长",
+ "default_value": 180
+ }
+}
reload_plugins_manager = on_command(
@@ -41,4 +56,19 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
plugins2cd_manager.reload()
plugins2block_manager.reload()
group_manager.reload()
+ Config.reload()
await reload_plugins_manager.send("重载完成...")
+
+
+@scheduler.scheduled_job(
+ 'interval',
+ seconds=Config.get_config("reload_setting", "AUTO_RELOAD_TIME", 180),
+)
+async def _():
+ if Config.get_config("reload_setting", "AUTO_RELOAD"):
+ plugins2settings_manager.reload()
+ plugins2cd_manager.reload()
+ plugins2block_manager.reload()
+ group_manager.reload()
+ Config.reload()
+ logger.debug("已自动重载所有配置文件...")
diff --git a/models/group_member_info.py b/models/group_member_info.py
index 54c4ac117..aec123092 100755
--- a/models/group_member_info.py
+++ b/models/group_member_info.py
@@ -131,8 +131,10 @@ async def set_group_member_nickname(
@classmethod
async def get_user_all_group(cls, user_qq: int) -> List[int]:
"""
- 获取该用户所在的所有群聊
- :param user_qq: 用户qq
+ 说明:
+ 获取该用户所在的所有群聊
+ 参数:
+ :param user_qq: 用户qq
"""
query = await cls.query.where(cls.user_qq == user_qq).gino.all()
if query:
diff --git a/plugins/bilibili_sub/data_source.py b/plugins/bilibili_sub/data_source.py
index 338dc54c2..affdb5371 100755
--- a/plugins/bilibili_sub/data_source.py
+++ b/plugins/bilibili_sub/data_source.py
@@ -193,7 +193,6 @@ async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
获取订阅状态
:param id_: 订阅 id
:param sub_type: 订阅类型
- :return:
"""
try:
if sub_type == "live":
@@ -203,7 +202,7 @@ async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
elif sub_type == "season":
return await _get_season_status(id_)
except ResponseCodeException:
- return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
+ return f"Id:{id_} 获取信息失败...请检查订阅Id是否存在或稍后再试..."
# except Exception as e:
# logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
diff --git a/plugins/draw_card/genshin_handle.py b/plugins/draw_card/genshin_handle.py
index 1d766ac40..e13533471 100755
--- a/plugins/draw_card/genshin_handle.py
+++ b/plugins/draw_card/genshin_handle.py
@@ -109,18 +109,6 @@ async def update_genshin_info():
data, code = await update_info(
url,
"genshin_arms",
- [
- "头像",
- "名称",
- "类型",
- "稀有度.alt",
- "获取途径",
- "初始基础属性1",
- "初始基础属性2",
- "攻击力(MAX)",
- "副属性(MAX)",
- "技能",
- ],
)
if code == 200:
ALL_ARMS = init_game_pool("genshin_arms", data, GenshinChar)
@@ -177,7 +165,6 @@ def _get_genshin_card(mode: int = 1, pool_name: str = "", add: float = 0.0):
if flag and star > 3 and pool_name:
# 获取up角色列表
up_char_lst = [x.operators for x in data_lst if x.star == star][0]
- print(up_char_lst)
# 成功获取up角色
if random.random() < 0.5:
up_char_name = random.choice(up_char_lst)
diff --git a/plugins/draw_card/update_game_info.py b/plugins/draw_card/update_game_info.py
index f3289e7b9..1246dc69f 100755
--- a/plugins/draw_card/update_game_info.py
+++ b/plugins/draw_card/update_game_info.py
@@ -179,6 +179,9 @@ async def _last_check(data: dict, game_name: str):
# 对抓取每行数据是否需要额外处理?
def intermediate_check(member_dict: dict, key: str, game_name: str, td: bs4.element.Tag):
+ if game_name == "genshin_arms":
+ if key == "稀有度":
+ member_dict["稀有度"] = td.find("img")["alt"].split('.')[0]
if game_name == 'prts':
if key == '获取途径':
msg = re.search('
([\\s\\S]*)', str(td)).group(1).strip()
diff --git a/plugins/draw_card/update_game_simple_info.py b/plugins/draw_card/update_game_simple_info.py
index e8c2a919c..60abc324e 100755
--- a/plugins/draw_card/update_game_simple_info.py
+++ b/plugins/draw_card/update_game_simple_info.py
@@ -131,8 +131,9 @@ async def retrieve_char_data(char: bs4.element.Tag, game_name: str, data: dict,
'名称': remove_prohibited_str(char.find('a')['title']),
'星级': 3 - index}
if game_name == 'azur':
- char = char.find('div').find('div').find('div').find('div')
+ char = char.find('div').find('div').find('div')
avatar_img = char.find('a').find('img')
+ char = char.find('div')
try:
member_dict['名称'] = remove_prohibited_str(char.find('a')['title'])
except TypeError:
diff --git a/plugins/epic/data_source.py b/plugins/epic/data_source.py
index 074a01c87..b54c38568 100755
--- a/plugins/epic/data_source.py
+++ b/plugins/epic/data_source.py
@@ -13,6 +13,8 @@
# 方法参考:RSSHub /epicgames 路由
# https://github.com/DIYgod/RSSHub/blob/master/lib/routes/epicgames/index.js
async def get_epic_game():
+ # 现在没用 graphql 辣
+ """ prv_graphql Code
epic_url = "https://www.epicgames.com/store/backend/graphql-proxy"
headers = {
"Referer": "https://www.epicgames.com/store/zh-CN/",
@@ -31,10 +33,18 @@ async def get_epic_game():
"withPrice": True,
"withPromotions": True,
},
+ }
+ """
+
+ epic_url = "https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale=zh-CN&country=CN&allowCountries=CN"
+ headers = {
+ "Referer": "https://www.epicgames.com/store/zh-CN/",
+ "Content-Type": "application/json; charset=utf-8",
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"
}
async with AsyncClient(headers=headers) as client:
try:
- res = await client.post(epic_url, json=data, timeout=10.0)
+ res = await client.get(epic_url, timeout=10.0)
res_json = res.json()
games = res_json["data"]["Catalog"]["searchStore"]["elements"]
return games
diff --git a/plugins/fudu.py b/plugins/fudu.py
index 3555ccc3a..a150ecb9c 100755
--- a/plugins/fudu.py
+++ b/plugins/fudu.py
@@ -90,12 +90,12 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if get_message_text(event.json()):
if get_message_text(event.json()).find("@可爱的小真寻") != -1:
await fudu.finish("复制粘贴的虚空艾特?", at_sender=True)
- imgs = get_message_img(event.json())
+ img = get_message_img(event.json())
msg = get_message_text(event.json())
- if not imgs and not msg:
+ if not img and not msg:
return
- if imgs:
- img_hash = await get_fudu_img_hash(imgs[0], event.group_id)
+ if img:
+ img_hash = await get_fudu_img_hash(img[0], event.group_id)
else:
img_hash = ""
add_msg = msg + "|-|" + img_hash
@@ -113,15 +113,17 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if random.random() < 0.2:
await fudu.finish("打断施法!")
_fudu_list.set_repeater(event.group_id)
- if imgs and msg:
+ if img and msg:
rst = msg + image(f"compare_{event.group_id}_img.jpg", "temp")
- elif imgs:
+ elif img:
rst = image(f"compare_{event.group_id}_img.jpg", "temp")
elif msg:
rst = msg
else:
rst = ""
if rst:
+ if rst.endswith("打断施法!"):
+ rst = "打断" + rst
await fudu.send(rst)
diff --git a/plugins/genshin/query_resource_points/__init__.py b/plugins/genshin/query_resource_points/__init__.py
index 1339d0596..20c919e0e 100755
--- a/plugins/genshin/query_resource_points/__init__.py
+++ b/plugins/genshin/query_resource_points/__init__.py
@@ -40,6 +40,9 @@
"limit_superuser": False,
"cmd": ["原神资源查询", "原神资源列表"],
}
+__plugin_block_limit__ = {
+ "rst": "您有资源正在查询!"
+}
qr = on_command("原神资源查询", aliases={"原神资源查找"}, priority=5, block=True)
qr_lst = on_command("原神资源列表", priority=5, block=True)
diff --git a/plugins/genshin/query_user/__init__.py b/plugins/genshin/query_user/__init__.py
index 0ac73fe19..8751dd7fc 100644
--- a/plugins/genshin/query_user/__init__.py
+++ b/plugins/genshin/query_user/__init__.py
@@ -14,6 +14,12 @@
"xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs"
)
+Config.add_plugin_config(
+ "genshin",
+ "n",
+ "h8w582wxwgqvahcdkpvdhbh2w9casgfl"
+)
+
Config.add_plugin_config(
"genshin",
"client_type",
@@ -24,3 +30,4 @@
+
diff --git a/plugins/genshin/query_user/bind/__init__.py b/plugins/genshin/query_user/bind/__init__.py
index 355553c56..272305962 100644
--- a/plugins/genshin/query_user/bind/__init__.py
+++ b/plugins/genshin/query_user/bind/__init__.py
@@ -70,9 +70,9 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
uid = await Genshin.get_user_uid(event.user_id)
if not uid:
await bind.finish("请先绑定原神uid..")
- if msg.startswith('"'):
+ if msg.startswith('"') or msg.startswith("'"):
msg = msg[1:]
- if msg.endswith('"'):
+ if msg.endswith('"') or msg.endswith("'"):
msg = msg[:-1]
await Genshin.set_cookie(uid, msg)
_x = f"已成功为uid:{uid} 设置cookie"
diff --git a/plugins/genshin/query_user/genshin_sign/__init__.py b/plugins/genshin/query_user/genshin_sign/__init__.py
new file mode 100644
index 000000000..61af62cd9
--- /dev/null
+++ b/plugins/genshin/query_user/genshin_sign/__init__.py
@@ -0,0 +1,101 @@
+from .data_source import get_sign_reward_list, genshin_sign
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from nonebot import on_command
+from nonebot.typing import T_State
+from services.log import logger
+from .init_task import add_job, scheduler, _sign
+from apscheduler.jobstores.base import JobLookupError
+from ..models import Genshin
+
+
+__zx_plugin_name__ = "原神自动签到"
+__plugin_usage__ = """
+usage:
+ 米游社原神签到,需要uid以及cookie
+ 且在第二天自动排序签到时间
+ # 不听,就要手动签到!(使用命令 “原神我硬签 or 米游社我硬签”
+ 指令:
+ 开/关原神自动签到
+ 原神我硬签
+""".strip()
+__plugin_des__ = "原神懒人签到"
+__plugin_cmd__ = ["开/关原神自动签到", "原神我硬签"]
+__plugin_type__ = ("原神相关",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["原神签到"],
+}
+
+
+genshin_matcher = on_command(
+ "开原神自动签到", aliases={"关原神自动签到", "原神我硬签"}, priority=5, block=True
+)
+
+
+@genshin_matcher.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ uid = await Genshin.get_user_uid(event.user_id)
+ if not uid or not await Genshin.get_user_cookie(uid, True):
+ await genshin_matcher.finish("请先绑定uid和cookie!")
+ if "account_id" not in await Genshin.get_user_cookie(uid, True):
+ await genshin_matcher.finish("请更新cookie!")
+ if state["_prefix"]["raw_command"] == "原神我硬签":
+ try:
+ msg = await genshin_sign(uid)
+ logger.info(
+ f"(USER {event.user_id}, "
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{uid} 原神签到"
+ )
+ # 硬签,移除定时任务
+ try:
+ for i in range(3):
+ scheduler.remove_job(f"genshin_auto_sign_{uid}_{event.user_id}_{i}",)
+ except JobLookupError:
+ pass
+ u = await Genshin.get_user_by_uid(uid)
+ if u and u.auto_sign:
+ await u.clear_sign_time(uid)
+ next_date = await Genshin.random_sign_time(uid)
+ add_job(event.user_id, uid, next_date)
+ msg += f"因开启自动签到\n下一次签到时间为:{next_date.replace(microsecond=0)}"
+ except Exception as e:
+ msg = "原神签到失败..请尝试检查cookie或报告至管理员!"
+ logger.info(
+ f"(USER {event.user_id}, "
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{uid} 原神签到发生错误 "
+ f"{type(e)}:{e}"
+ )
+ msg = msg or "请检查cookie是否更新!"
+ await genshin_matcher.send(msg, at_sender=True)
+ else:
+ for i in range(3):
+ try:
+ scheduler.remove_job(f"genshin_auto_sign_{uid}_{event.user_id}_{i}")
+ except JobLookupError:
+ pass
+ if state["_prefix"]["raw_command"][0] == "开":
+ await Genshin.set_auto_sign(uid, True)
+ next_date = await Genshin.random_sign_time(uid)
+ add_job(event.user_id, uid, next_date)
+ await genshin_matcher.send(
+ f"已开启原神自动签到!\n下一次签到时间为:{next_date.replace(microsecond=0)}",
+ at_sender=True,
+ )
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 开启原神自动签到"
+ )
+ else:
+ await Genshin.set_auto_sign(uid, False)
+ await Genshin.clear_sign_time(uid)
+ await genshin_matcher.send(f"已关闭原神自动签到!", at_sender=True)
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 关闭原神自动签到"
+ )
diff --git a/plugins/genshin/query_user/genshin_sign/data_source.py b/plugins/genshin/query_user/genshin_sign/data_source.py
new file mode 100644
index 000000000..66c58fe55
--- /dev/null
+++ b/plugins/genshin/query_user/genshin_sign/data_source.py
@@ -0,0 +1,104 @@
+from utils.http_utils import AsyncHttpx
+from configs.config import Config
+from services.log import logger
+from ..utils import random_hex, get_old_ds
+from ..models import Genshin
+from typing import Optional, Dict
+
+
+async def genshin_sign(uid: int) -> Optional[str]:
+ """
+ 原神签到信息
+ :param uid: uid
+ """
+ data = await _sign(uid)
+ if not data:
+ return "签到失败..."
+ status = data["message"]
+ if status == "OK":
+ sign_info = await _get_sign_info(uid)
+ if sign_info:
+ sign_info = sign_info["data"]
+ sign_list = await get_sign_reward_list()
+ get_reward = sign_list["data"]["awards"][
+ int(sign_info["total_sign_day"]) - 1
+ ]["name"]
+ reward_num = sign_list["data"]["awards"][
+ int(sign_info["total_sign_day"]) - 1
+ ]["cnt"]
+ get_im = f"本次签到获得:{get_reward}x{reward_num}"
+ if status == "OK" and sign_info["is_sign"]:
+ return f"\n原神签到成功!\n{get_im}\n本月漏签次数:{sign_info['sign_cnt_missed']}"
+ else:
+ return status
+ return None
+
+
+async def _sign(uid: int, server_id: str = "cn_gf01") -> Optional[Dict[str, str]]:
+ """
+ 米游社签到
+ :param uid: uid
+ :param server_id: 服务器id
+ """
+ if str(uid)[0] == "5":
+ server_id = "cn_qd01"
+ try:
+ req = await AsyncHttpx.post(
+ url="https://api-takumi.mihoyo.com/event/bbs_sign_reward/sign",
+ headers={
+ "User_Agent": "Mozilla/5.0 (Linux; Android 10; MIX 2 Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36 miHoYoBBS/2.3.0",
+ "Cookie": await Genshin.get_user_cookie(int(uid), True),
+ "x-rpc-device_id": random_hex(32),
+ "Origin": "https://webstatic.mihoyo.com",
+ "X_Requested_With": "com.mihoyo.hyperion",
+ "DS": get_old_ds(),
+ "x-rpc-client_type": "5",
+ "Referer": "https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true&act_id=e202009291139501&utm_source=bbs&utm_medium=mys&utm_campaign=icon",
+ "x-rpc-app_version": "2.3.0",
+ },
+ json={"act_id": "e202009291139501", "uid": uid, "region": server_id},
+ )
+ return req.json()
+ except Exception as e:
+ logger.error(f"米游社签到发生错误 UID:{uid} {type(e)}:{e}")
+ return None
+
+
+async def get_sign_reward_list():
+ """
+ 获取签到奖励列表
+ """
+ try:
+ req = await AsyncHttpx.get(
+ url="https://api-takumi.mihoyo.com/event/bbs_sign_reward/home?act_id=e202009291139501",
+ headers={
+ "x-rpc-app_version": str(Config.get_config("genshin", "mhyVersion")),
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
+ "x-rpc-client_type": str(Config.get_config("genshin", "client_type")),
+ "Referer": "https://webstatic.mihoyo.com/",
+ },
+ )
+ return req.json()
+ except Exception as e:
+ logger.error(f"获取签到奖励列表发生错误 {type(e)}:{e}")
+ return None
+
+
+async def _get_sign_info(uid: int, server_id: str = "cn_gf01"):
+ if str(uid)[0] == "5":
+ server_id = "cn_qd01"
+ try:
+ req = await AsyncHttpx.get(
+ url=f"https://api-takumi.mihoyo.com/event/bbs_sign_reward/info?act_id=e202009291139501®ion={server_id}&uid={uid}",
+ headers={
+ "x-rpc-app_version": str(Config.get_config("genshin", "mhyVersion")),
+ "Cookie": await Genshin.get_user_cookie(int(uid), True),
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
+ "x-rpc-client_type": str(Config.get_config("genshin", "client_type")),
+ "Referer": "https://webstatic.mihoyo.com/",
+ },
+ )
+ return req.json()
+ except Exception as e:
+ logger.error(f"获取签到信息发生错误 UID:{uid} {type(e)}:{e}")
+ return None
diff --git a/plugins/genshin/query_user/genshin_sign/init_task.py b/plugins/genshin/query_user/genshin_sign/init_task.py
new file mode 100644
index 000000000..5371764a2
--- /dev/null
+++ b/plugins/genshin/query_user/genshin_sign/init_task.py
@@ -0,0 +1,110 @@
+from .data_source import genshin_sign
+from models.group_member_info import GroupInfoUser
+from utils.message_builder import at
+from services.log import logger
+from utils.utils import scheduler, get_bot
+from apscheduler.jobstores.base import ConflictingIdError
+from ..models import Genshin
+from datetime import datetime, timedelta
+from nonebot import Driver
+import nonebot
+import random
+import pytz
+
+
+driver: Driver = nonebot.get_driver()
+
+
+@driver.on_startup
+async def _():
+ """
+ 启动时分配定时任务
+ """
+ g_list = await Genshin.get_all_auto_sign_user()
+ for u in g_list:
+ if u.auto_sign_time:
+ date = await Genshin.random_sign_time(u.uid)
+ scheduler.add_job(
+ _sign,
+ "date",
+ run_date=date.replace(microsecond=0),
+ id=f"genshin_auto_sign_{u.uid}_{u.user_qq}_0",
+ args=[u.user_qq, u.uid, 0],
+ )
+ logger.info(
+ f"genshin_sign add_job:USER:{u.user_qq} UID:{u.uid} " f"{date} 原神自动签到"
+ )
+
+
+def add_job(user_id: int, uid: int, date: datetime):
+ try:
+ scheduler.add_job(
+ _sign,
+ "date",
+ run_date=date.replace(microsecond=0),
+ id=f"genshin_auto_sign_{uid}_{user_id}_0",
+ args=[user_id, uid, 0],
+ )
+ logger.debug(f"genshin_sign add_job:{date.replace(microsecond=0)} 原神自动签到")
+ except ConflictingIdError:
+ pass
+
+
+async def _sign(user_id: int, uid: int, count: int):
+ """
+ 执行签到任务
+ :param user_id: 用户id
+ :param uid: uid
+ :param count: 执行次数
+ """
+ if count < 3:
+ try:
+ msg = await genshin_sign(uid)
+ next_time = await Genshin.random_sign_time(uid)
+ msg += f"\n下一次签到时间为:{next_time.replace(microsecond=0)}"
+ logger.info(f"USER:{user_id} UID:{uid} 原神自动签到任务发生成功...")
+ try:
+ scheduler.add_job(
+ _sign,
+ "date",
+ run_date=next_time.replace(microsecond=0),
+ id=f"genshin_auto_sign_{uid}_{user_id}_0",
+ args=[user_id, uid, 0],
+ )
+ except ConflictingIdError:
+ msg += "\n定时任务设定失败..."
+ except Exception as e:
+ logger.error(f"USER:{user_id} UID:{uid} 原神自动签到任务发生错误 {type(e)}:{e}")
+ msg = None
+ if not msg:
+ now = datetime.now(pytz.timezone("Asia/Shanghai"))
+ if now.hour < 23:
+ random_hours = random.randint(1, 23 - now.hour)
+ next_time = now + timedelta(hours=random_hours)
+ scheduler.add_job(
+ _sign,
+ "date",
+ run_date=next_time.replace(microsecond=0),
+ id=f"genshin_auto_sign_{uid}_{user_id}_{count}",
+ args=[user_id, uid, count + 1],
+ )
+ msg = (
+ f"{now.replace(microsecond=0)} 原神"
+ f"签到失败,将在 {next_time.replace(microsecond=0)} 时重试!"
+ )
+ else:
+ msg = "今日原神签到失败,请手动签到..."
+ logger.debug(f"USER:{user_id} UID:{uid} 原神今日签到失败...")
+ else:
+ msg = "今日原神自动签到重试次数已达到3次,请手动签到。"
+ logger.debug(f"USER:{user_id} UID:{uid} 原神今日签到失败次数打到 3 次...")
+ bot = get_bot()
+ if bot:
+ if user_id in [x["user_id"] for x in await bot.get_friend_list()]:
+ await bot.send_private_msg(user_id=user_id, message=msg)
+ else:
+ group_list = await GroupInfoUser.get_user_all_group(user_id)
+ if group_list:
+ await bot.send_group_msg(
+ group_id=group_list[0], message=at(user_id) + msg
+ )
diff --git a/plugins/genshin/query_user/models/__init__.py b/plugins/genshin/query_user/models/__init__.py
index 5b54ba1bc..04add021f 100644
--- a/plugins/genshin/query_user/models/__init__.py
+++ b/plugins/genshin/query_user/models/__init__.py
@@ -1,5 +1,8 @@
from services.db_context import db
-from typing import Optional, Union
+from typing import Optional, Union, List
+from datetime import datetime, timedelta
+import random
+import pytz
class Genshin(db.Model):
@@ -11,7 +14,10 @@ class Genshin(db.Model):
mys_id = db.Column(db.BigInteger())
cookie = db.Column(db.String(), default="")
today_query_uid = db.Column(db.String(), default="") # 该cookie今日查询的uid
- auto_sign = db.Column(db.Boolean(), default=False) # 自动签到
+ auto_sign = db.Column(db.Boolean(), default=False)
+ auto_sign_time = db.Column(db.DateTime(timezone=True))
+ resin_remind = db.Column(db.Boolean(), default=False) # 树脂提醒
+ resin_recovery_time = db.Column(db.DateTime(timezone=True)) # 满树脂提醒日期
_idx1 = db.Index("genshin_uid_idx1", "user_qq", "uid", unique=True)
@@ -66,11 +72,75 @@ async def set_cookie(cls, uid: int, cookie: str) -> bool:
return True
return False
+ @classmethod
+ async def set_resin_remind(cls, uid: int, flag: bool) -> bool:
+ """
+ 说明:
+ 设置体力提醒
+ 参数:
+ :param uid: 原神uid
+ :param flag: 开关状态
+ """
+ query = cls.query.where(cls.uid == uid).with_for_update()
+ user = await query.gino.first()
+ if user:
+ await user.update(resin_remind=flag).apply()
+ return True
+ return False
+
+ @classmethod
+ async def set_user_resin_recovery_time(cls, uid: int, date: datetime):
+ """
+ 说明:
+ 设置体力完成时间
+ 参数:
+ :param uid: uid
+ :param date: 提醒日期
+ """
+ u = await cls.query.where(cls.uid == uid).gino.first()
+ if u:
+ await u.update(resin_recovery_time=date).apply()
+
+ @classmethod
+ async def get_user_resin_recovery_time(cls, uid: int) -> Optional[datetime]:
+ """
+ 说明:
+ 获取体力完成时间
+ 参数:
+ :param uid: uid
+ """
+ u = await cls.query.where(cls.uid == uid).gino.first()
+ if u:
+ return u.resin_recovery_time.astimezone(pytz.timezone("Asia/Shanghai"))
+ return None
+
+ @classmethod
+ async def get_all_resin_remind_user(cls) -> List["Genshin"]:
+ """
+ 说明:
+ 获取所有开启体力提醒的用户
+ """
+ return await cls.query.where(cls.resin_remind == True).gino.all()
+
+ @classmethod
+ async def clear_resin_remind_time(cls, uid: int) -> bool:
+ """
+ 说明:
+ 清空提醒日期
+ 参数:
+ :param uid: uid
+ """
+ user = await cls.query.where(cls.uid == uid).gino.first()
+ if user:
+ await user.update(resin_recovery_time=None).apply()
+ return True
+ return False
+
@classmethod
async def set_auto_sign(cls, uid: int, flag: bool) -> bool:
"""
说明:
- 设置米游社自动签到
+ 设置米游社/原神自动签到
参数:
:param uid: 原神uid
:param flag: 开关状态
@@ -82,6 +152,66 @@ async def set_auto_sign(cls, uid: int, flag: bool) -> bool:
return True
return False
+ @classmethod
+ async def get_all_auto_sign_user(cls) -> List["Genshin"]:
+ """
+ 说明:
+ 获取所有开启自动签到的用户
+ """
+ return await cls.query.where(cls.auto_sign == True).gino.all()
+
+ @classmethod
+ async def get_all_sign_user(cls) -> List["Genshin"]:
+ """
+ 说明:
+ 获取 原神 所有今日签到用户
+ """
+ return await cls.query.where(cls.auto_sign_time != None).gino.all()
+
+ @classmethod
+ async def clear_sign_time(cls, uid: int) -> bool:
+ """
+ 说明:
+ 清空签到日期
+ 参数:
+ :param uid: uid
+ """
+ user = await cls.query.where(cls.uid == uid).gino.first()
+ if user:
+ await user.update(auto_sign_time=None).apply()
+ return True
+ return False
+
+ @classmethod
+ async def random_sign_time(cls, uid: int) -> Optional[datetime]:
+ """
+ 说明:
+ 随机签到时间
+ 说明:
+ :param uid: uid
+ """
+ query = cls.query.where(cls.uid == uid).with_for_update()
+ user = await query.gino.first()
+ if user and user.cookie:
+ if user.auto_sign_time and user.auto_sign_time.astimezone(
+ pytz.timezone("Asia/Shanghai")
+ ) - timedelta(seconds=2) >= datetime.now(pytz.timezone("Asia/Shanghai")):
+ return user.auto_sign_time.astimezone(pytz.timezone("Asia/Shanghai"))
+ hours = int(str(datetime.now()).split()[1].split(":")[0])
+ minutes = int(str(datetime.now()).split()[1].split(":")[1])
+ date = (
+ datetime.now()
+ + timedelta(days=1)
+ - timedelta(hours=hours)
+ - timedelta(minutes=minutes - 1)
+ )
+ random_hours = random.randint(0, 22)
+ random_minutes = random.randint(1, 59)
+ date += timedelta(hours=random_hours) + timedelta(minutes=random_minutes)
+ await user.update(auto_sign_time=date).apply()
+ return date
+ return None
+
@classmethod
async def get_query_cookie(cls, uid: int) -> Optional[str]:
"""
@@ -95,7 +225,9 @@ async def get_query_cookie(cls, uid: int) -> Optional[str]:
x = await query.gino.first()
if x:
return x.cookie
- for u in [x for x in await cls.query.order_by(db.func.random()).gino.all() if x.cookie]:
+ for u in [
+ x for x in await cls.query.order_by(db.func.random()).gino.all() if x.cookie
+ ]:
if not u.today_query_uid or len(u.today_query_uid[:-1].split()) < 30:
await cls._add_query_uid(uid, u.uid)
return u.cookie
@@ -115,6 +247,26 @@ async def get_user_cookie(cls, uid: int, flag: bool = False) -> Optional[str]:
cookie = await cls.get_query_cookie(uid)
return cookie
+ @classmethod
+ async def get_user_by_qq(cls, user_qq: int) -> Optional["Genshin"]:
+ """
+ 说明:
+ 通过qq获取用户对象
+ 参数:
+ :param user_qq: qq
+ """
+ return await cls.query.where(cls.user_qq == user_qq).gino.first()
+
+ @classmethod
+ async def get_user_by_uid(cls, uid: int) -> Optional["Genshin"]:
+ """
+ 说明:
+ 通过uid获取用户对象
+ 参数:
+ :param uid: qq
+ """
+ return await cls.query.where(cls.uid == uid).gino.first()
+
@classmethod
async def get_user_uid(cls, user_qq: int) -> Optional[int]:
"""
@@ -178,7 +330,7 @@ async def _add_query_uid(cls, uid: int, cookie_uid: int):
@classmethod
async def _get_user_data(
- cls, user_qq: Optional[int], uid: Optional[int], type_: str
+ cls, user_qq: Optional[int], uid: Optional[int], type_: str
) -> Optional[Union[int, str]]:
"""
说明:
@@ -198,11 +350,10 @@ async def _get_user_data(
return user.mys_id
elif type_ == "cookie":
return user.cookie
+ return None
@classmethod
async def reset_today_query_uid(cls):
for u in await cls.query.with_for_update().gino.all():
if u.today_query_uid:
- await u.update(
- today_query_uid=""
- ).apply()
+ await u.update(today_query_uid="").apply()
diff --git a/plugins/genshin/query_user/query_memo/__init__.py b/plugins/genshin/query_user/query_memo/__init__.py
index 13d1fad0d..410d7cb2b 100644
--- a/plugins/genshin/query_user/query_memo/__init__.py
+++ b/plugins/genshin/query_user/query_memo/__init__.py
@@ -2,8 +2,9 @@
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from services.log import logger
-from .data_source import get_user_memo
+from .data_source import get_user_memo, get_memo
from ..models import Genshin
+from nonebot.plugin import export
__zx_plugin_name__ = "原神便笺查询"
@@ -25,6 +26,12 @@
"limit_superuser": False,
"cmd": ["原神便笺查询"],
}
+__plugin_block_limit__ = {}
+
+
+export = export()
+
+export.get_memo = get_memo
query_memo_matcher = on_command("原神便签查询", aliases={"原神便笺查询", "yss"}, priority=5, block=True)
@@ -43,7 +50,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
await query_memo_matcher.send(data)
logger.info(
f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 使用原神便笺查询 uid:{uid}"
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
+ f"使用原神便笺查询 uid:{uid}"
)
else:
await query_memo_matcher.send("未查询到数据...")
@@ -51,3 +59,4 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
+
diff --git a/plugins/genshin/query_user/query_memo/data_source.py b/plugins/genshin/query_user/query_memo/data_source.py
index 229f006d1..45a3f402b 100644
--- a/plugins/genshin/query_user/query_memo/data_source.py
+++ b/plugins/genshin/query_user/query_memo/data_source.py
@@ -43,7 +43,7 @@ async def _():
async def get_user_memo(user_id: int, uid: int, uname: str) -> Optional[Union[str, MessageSegment]]:
uid = str(uid)
- if uid[0] == "1" or uid[0] == "2":
+ if uid[0] in ["1", "2"]:
server_id = "cn_gf01"
elif uid[0] == "5":
server_id = "cn_qd01"
@@ -72,7 +72,7 @@ async def get_memo(uid: str, server_id: str) -> "Union[str, dict], int":
except TimeoutError:
return "访问超时,请稍后再试", 997
except Exception as e:
- logger.info(f"便签查询获取失败未知错误 {e}:{e}")
+ logger.error(f"便签查询获取失败未知错误 {e}:{e}")
return "发生了一些错误,请稍后再试", 998
diff --git a/plugins/genshin/query_user/query_role/__init__.py b/plugins/genshin/query_user/query_role/__init__.py
index d28775b0a..48155ce58 100644
--- a/plugins/genshin/query_user/query_role/__init__.py
+++ b/plugins/genshin/query_user/query_role/__init__.py
@@ -26,6 +26,7 @@
"limit_superuser": False,
"cmd": ["原神玩家查询"],
}
+__plugin_block_limit__ = {}
query_role_info_matcher = on_command("原神玩家查询", aliases={"原神玩家查找", "ys"}, priority=5, block=True)
diff --git a/plugins/genshin/query_user/resin_remind/__init__.py b/plugins/genshin/query_user/resin_remind/__init__.py
new file mode 100644
index 000000000..4cf2f9271
--- /dev/null
+++ b/plugins/genshin/query_user/resin_remind/__init__.py
@@ -0,0 +1,83 @@
+from nonebot import on_command
+from nonebot.typing import T_State
+from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
+from apscheduler.jobstores.base import JobLookupError
+from services.log import logger
+from .init_task import scheduler, add_job
+from ..models import Genshin
+from datetime import datetime
+import random
+import asyncio
+import pytz
+
+
+__zx_plugin_name__ = "原神树脂提醒"
+__plugin_usage__ = """
+usage:
+ 即将满树脂的提醒
+ 指令:
+ 开原神树脂提醒
+ 关原神树脂提醒
+""".strip()
+__plugin_des__ = "时时刻刻警醒你!"
+__plugin_cmd__ = ["开原神树脂提醒", "关原神树脂提醒"]
+__plugin_type__ = ("原神相关",)
+__plugin_version__ = 0.1
+__plugin_author__ = "HibiKier"
+__plugin_settings__ = {
+ "level": 5,
+ "default_status": True,
+ "limit_superuser": False,
+ "cmd": ["原神树脂提醒", "关原神树脂提醒", "开原神树脂提醒"],
+}
+
+resin_remind = on_command("开原神树脂提醒", aliases={"关原神树脂提醒"}, priority=5, block=True)
+
+
+@resin_remind.handle()
+async def _(bot: Bot, event: MessageEvent, state: T_State):
+ uid = await Genshin.get_user_uid(event.user_id)
+ if not uid or not await Genshin.get_user_cookie(uid, True):
+ await resin_remind.finish("请先绑定uid和cookie!")
+ try:
+ scheduler.remove_job(f"genshin_resin_remind_{uid}_{event.user_id}")
+ except JobLookupError:
+ pass
+ if state["_prefix"]["raw_command"][0] == "开":
+ await Genshin.set_resin_remind(uid, True)
+ add_job(event.user_id, uid)
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 开启原神体力提醒"
+ )
+ await resin_remind.send("开启原神树脂提醒成功!", at_sender=True)
+ else:
+ await Genshin.set_resin_remind(uid, False)
+ await Genshin.clear_resin_remind_time(uid)
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 关闭原神体力提醒"
+ )
+ await resin_remind.send("已关闭原神树脂提醒..", at_sender=True)
+
+
+@scheduler.scheduled_job(
+ "interval",
+ minutes=30,
+)
+async def _():
+ for u in await Genshin.get_all_resin_remind_user():
+ if u.resin_recovery_time:
+ if await Genshin.get_user_resin_recovery_time(u.uid) < datetime.now(
+ pytz.timezone("Asia/Shanghai")
+ ):
+ await Genshin.clear_resin_remind_time(u.uid)
+ elif (
+ await Genshin.get_user_resin_recovery_time(u.uid)
+ - datetime.now(pytz.timezone("Asia/Shanghai"))
+ ).seconds > 360:
+ continue
+ add_job(u.user_qq, u.uid)
+ await asyncio.sleep(random.randint(10, 30))
diff --git a/plugins/genshin/query_user/resin_remind/init_task.py b/plugins/genshin/query_user/resin_remind/init_task.py
new file mode 100644
index 000000000..844804b28
--- /dev/null
+++ b/plugins/genshin/query_user/resin_remind/init_task.py
@@ -0,0 +1,123 @@
+from utils.utils import get_bot, scheduler
+from utils.message_builder import at
+from models.group_member_info import GroupInfoUser
+from apscheduler.jobstores.base import ConflictingIdError
+from nonebot import Driver
+from ..models import Genshin
+from datetime import datetime, timedelta
+from services.log import logger
+from nonebot.plugin import require
+import time
+import nonebot
+import pytz
+
+
+driver: Driver = nonebot.get_driver()
+
+
+get_memo = require('query_memo').get_memo
+
+
+class UserManager:
+
+ def __init__(self):
+ self._data = []
+
+ def append(self, o: str):
+ if o not in self._data:
+ self._data.append(o)
+
+ def remove(self, o: str):
+ if o in self._data:
+ self._data.remove(o)
+
+ def exists(self, o: str):
+ return o in self._data
+
+
+user_manager = UserManager()
+
+
+@driver.on_startup
+async def _():
+ """
+ 启动时分配定时任务
+ """
+ g_list = await Genshin.get_all_resin_remind_user()
+ for u in g_list:
+ if u.resin_recovery_time and await Genshin.get_user_resin_recovery_time(
+ u.uid
+ ) > datetime.now(pytz.timezone("Asia/Shanghai")):
+ date = await Genshin.get_user_resin_recovery_time(u.uid)
+ scheduler.add_job(
+ _remind,
+ "date",
+ run_date=date.replace(microsecond=0),
+ id=f"genshin_resin_remind_{u.uid}_{u.user_qq}",
+ args=[u.user_qq, u.uid],
+ )
+ logger.info(
+ f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid} "
+ f"{date} 原神树脂提醒"
+ )
+
+
+def add_job(user_id: int, uid: int):
+ date = datetime.now(pytz.timezone("Asia/Shanghai")) + timedelta(seconds=30)
+ try:
+ scheduler.add_job(
+ _remind,
+ "date",
+ run_date=date.replace(microsecond=0),
+ id=f"genshin_resin_remind_{uid}_{user_id}",
+ args=[user_id, uid],
+ )
+ except ConflictingIdError:
+ pass
+
+
+async def _remind(user_id: int, uid: str):
+ uid = str(uid)
+ if uid[0] in ["1", "2"]:
+ server_id = "cn_gf01"
+ elif uid[0] == "5":
+ server_id = "cn_qd01"
+ else:
+ return
+ data, code = await get_memo(uid, server_id)
+ if code == 200:
+ current_resin = data["current_resin"] # 当前树脂
+ max_resin = data["max_resin"] # 最大树脂
+ resin_recovery_time = data["resin_recovery_time"] # 树脂全部回复时间
+ if max_resin - current_resin > 5:
+ user_manager.remove(uid)
+ next_time = datetime.strptime(time.strftime(
+ "%Y-%m-%d %H:%M:%S", time.localtime(time.time() + float(resin_recovery_time))
+ ), "%Y-%m-%d %H:%M:%S")
+ await Genshin.set_user_resin_recovery_time(int(uid), next_time)
+ scheduler.add_job(
+ _remind,
+ "date",
+ run_date=next_time,
+ id=f"genshin_resin_remind_{uid}_{user_id}",
+ args=[user_id, uid],
+ )
+ logger.info(f"genshin_resin_remind add_job:{next_time.replace(microsecond=0)} 原神树脂提醒")
+ else:
+ if not user_manager.exists(uid):
+ user_manager.append(uid)
+ bot = get_bot()
+ if bot:
+ if user_id in [x["user_id"] for x in await bot.get_friend_list()]:
+ await bot.send_private_msg(
+ user_id=user_id,
+ message=f"树脂已经 {current_resin} 个啦" f",马上就要溢出了!快快刷掉刷掉!",
+ )
+ else:
+ group_list = await GroupInfoUser.get_user_all_group(user_id)
+ if group_list:
+ await bot.send_group_msg(
+ group_id=group_list[0],
+ message=at(user_id) + f"树脂已经 {current_resin} 个啦"
+ f",马上就要溢出了!快快刷掉刷掉!",
+ )
diff --git a/plugins/genshin/query_user/utils/__init__.py b/plugins/genshin/query_user/utils/__init__.py
index 7cbd9deda..10fa36f89 100644
--- a/plugins/genshin/query_user/utils/__init__.py
+++ b/plugins/genshin/query_user/utils/__init__.py
@@ -3,6 +3,7 @@
import time
import random
import hashlib
+import string
def _md5(text):
@@ -11,7 +12,15 @@ def _md5(text):
return md5.hexdigest()
-def get_ds(q: str = "", b: dict = None):
+def get_old_ds() -> str:
+ n = Config.get_config("genshin", "n")
+ i = str(int(time.time()))
+ r = ''.join(random.sample(string.ascii_lowercase + string.digits, 6))
+ c = _md5("salt=" + n + "&t=" + i + "&r=" + r)
+ return i + "," + r + "," + c
+
+
+def get_ds(q: str = "", b: dict = None) -> str:
if b:
br = json.dumps(b)
else:
@@ -23,6 +32,13 @@ def get_ds(q: str = "", b: dict = None):
return t + "," + r + "," + c
+def random_hex(length: int) -> str:
+ result = hex(random.randint(0, 16 ** length)).replace("0x", "").upper()
+ if len(result) < length:
+ result = "0" * (length - len(result)) + result
+ return result
+
+
element_mastery = {
"anemo": "风",
"pyro": "火",
diff --git a/plugins/gold_redbag/__init__.py b/plugins/gold_redbag/__init__.py
index 74f629ed5..40211762b 100755
--- a/plugins/gold_redbag/__init__.py
+++ b/plugins/gold_redbag/__init__.py
@@ -323,7 +323,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
scheduler.add_job(
end_festive_redbag,
"date",
- run_date=str(datetime.now() + timedelta(hours=24)).split(".")[0],
+ run_date=(datetime.now() + timedelta(hours=24)).replace(microsecond=0),
id=f"festive_redbag_{g}",
args=[bot, g],
)
diff --git a/plugins/image_management/send_image/__init__.py b/plugins/image_management/send_image/__init__.py
index 99db0d08e..7fb617d7c 100755
--- a/plugins/image_management/send_image/__init__.py
+++ b/plugins/image_management/send_image/__init__.py
@@ -1,4 +1,4 @@
-from nonebot import on_command, on_keyword, on_regex
+from nonebot import on_message, on_keyword, on_regex
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from utils.utils import get_message_text, is_number
@@ -9,6 +9,7 @@
from pathlib import Path
from configs.config import Config
from utils.manager import group_manager, withdraw_message_manager
+from .rule import rule
import random
import os
@@ -50,9 +51,8 @@
_flmt = FreqLimiter(1)
-cmd = set(Config.get_config("image_management", "IMAGE_DIR_LIST"))
-send_img = on_command("img", aliases=cmd, priority=5, block=True)
+send_img = on_message(priority=5, rule=rule, block=True)
pa = on_keyword({"丢人爬", "爪巴"}, priority=5, block=True)
pa_reg = on_regex("^爬$", priority=5, block=True)
@@ -62,18 +62,24 @@
@send_img.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
- img_id = get_message_text(event.json())
- path = _path / cn2py(state["_prefix"]["raw_command"])
- if state["_prefix"]["raw_command"] in Config.get_config(
+ msg = get_message_text(event.json()).split()
+ gallery = msg[0]
+ if gallery not in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ return
+ img_id = None
+ if len(msg) > 1:
+ img_id = msg[1]
+ path = _path / cn2py(gallery)
+ if gallery in Config.get_config(
"image_management", "IMAGE_DIR_LIST"
):
- if not path.exists() and (path.parent.parent / cn2py(state["_prefix"]["raw_command"])).exists():
- path = Path(IMAGE_PATH) / cn2py(state["_prefix"]["raw_command"])
+ if not path.exists() and (path.parent.parent / cn2py(gallery)).exists():
+ path = Path(IMAGE_PATH) / cn2py(gallery)
else:
path.mkdir(parents=True, exist_ok=True)
length = len(os.listdir(path))
if length == 0:
- logger.warning(f'图库 {cn2py(state["_prefix"]["raw_command"])} 为空,调用取消!')
+ logger.warning(f'图库 {cn2py(gallery)} 为空,调用取消!')
await send_img.finish("该图库中没有图片噢")
index = img_id if img_id else str(random.randint(0, length - 1))
if not is_number(index):
@@ -85,7 +91,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
- f"发送{cn2py(state['_prefix']['raw_command'])}:"
+ f"发送{cn2py(gallery)}:"
+ result
)
msg_id = await send_img.send(
@@ -102,7 +108,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
- f"发送 {cn2py(state['_prefix']['raw_command'])} 失败"
+ f"发送 {cn2py(gallery)} 失败"
)
await send_img.finish(f"不想给你看Ov|")
@@ -135,4 +141,4 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
return
if _flmt.check(event.user_id):
_flmt.start_cd(event.user_id)
- await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
+ await pa_reg.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), "pa"))
diff --git a/plugins/image_management/send_image/rule.py b/plugins/image_management/send_image/rule.py
new file mode 100644
index 000000000..981376f10
--- /dev/null
+++ b/plugins/image_management/send_image/rule.py
@@ -0,0 +1,18 @@
+from nonebot.adapters.cqhttp import Bot, Event
+from nonebot.typing import T_State
+from utils.utils import get_message_text
+from configs.config import Config
+
+
+def rule(bot: Bot, event: Event, state: T_State) -> bool:
+ """
+ 检测文本是否是关闭功能命令
+ :param bot: pass
+ :param event: pass
+ :param state: pass
+ """
+ msg = get_message_text(event.json())
+ for x in Config.get_config("image_management", "IMAGE_DIR_LIST"):
+ if msg.startswith(x):
+ return True
+ return False
diff --git a/plugins/pix_gallery/data_source.py b/plugins/pix_gallery/data_source.py
index d6116799e..8cccbf225 100755
--- a/plugins/pix_gallery/data_source.py
+++ b/plugins/pix_gallery/data_source.py
@@ -230,7 +230,7 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
)
for _ in range(3):
try:
- response = await AsyncHttpx.get(img_url, timeout=Config.get_config("pix", "TIMEOUT"),)
+ response = await AsyncHttpx.get(img_url, headers=headers, timeout=Config.get_config("pix", "TIMEOUT"),)
if response.status_code == 404:
img_url = old_img_url
continue
@@ -240,6 +240,7 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
await f.write(response.content)
return f"pix_{user_id}_{img_url[-10:-4]}.jpg"
except TimeoutError:
+ logger.warning(f"PIX:{img_url} 图片下载超时...")
pass
return None
diff --git a/utils/image_utils.py b/utils/image_utils.py
index 55482f688..17581bc8f 100755
--- a/utils/image_utils.py
+++ b/utils/image_utils.py
@@ -248,13 +248,13 @@ async def text2image(
for e in placeholder[2].split():
if e.startswith("font="):
_font = e.split("=")[-1]
- if e.startswith("font_size="):
+ if e.startswith("font_size=") or e.startswith("fs="):
_font_size = int(e.split("=")[-1])
if _font_size > 1000:
_font_size = 1000
if _font_size < 1:
_font_size = 1
- if e.startswith("font_color"):
+ if e.startswith("font_color") or e.startswith("fc="):
_font_color = e.split("=")[-1]
text_img = BuildImage(
0,