2023-02-18 18:46:54 +08:00
|
|
|
|
import random
|
|
|
|
|
|
from datetime import datetime, timedelta
|
2022-05-21 13:15:53 +08:00
|
|
|
|
|
2023-02-18 18:46:54 +08:00
|
|
|
|
import nonebot
|
|
|
|
|
|
import pytz
|
|
|
|
|
|
from apscheduler.jobstores.base import ConflictingIdError, JobLookupError
|
2022-02-09 20:05:49 +08:00
|
|
|
|
from nonebot import Driver
|
2023-02-18 18:46:54 +08:00
|
|
|
|
from nonebot.adapters.onebot.v11 import ActionFailed
|
2022-02-09 20:05:49 +08:00
|
|
|
|
from nonebot.plugin import require
|
2023-02-18 18:46:54 +08:00
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
from configs.config import Config
|
2023-02-18 18:46:54 +08:00
|
|
|
|
from models.group_member_info import GroupInfoUser
|
|
|
|
|
|
from services.log import logger
|
|
|
|
|
|
from utils.message_builder import at
|
|
|
|
|
|
from utils.utils import get_bot, scheduler
|
2022-02-09 20:05:49 +08:00
|
|
|
|
|
2023-02-18 18:46:54 +08:00
|
|
|
|
from .._models import Genshin
|
2022-02-09 20:05:49 +08:00
|
|
|
|
|
|
|
|
|
|
driver: Driver = nonebot.get_driver()
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-15 19:49:53 +08:00
|
|
|
|
require("query_memo")
|
|
|
|
|
|
|
|
|
|
|
|
from ..query_memo import get_memo
|
2022-02-09 20:05:49 +08:00
|
|
|
|
|
2022-04-26 14:45:04 +08:00
|
|
|
|
global_map = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-09 20:05:49 +08:00
|
|
|
|
class UserManager:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
def __init__(self, max_error_count: int = 3):
|
2022-02-09 20:05:49 +08:00
|
|
|
|
self._data = []
|
2022-02-19 18:20:19 +08:00
|
|
|
|
self._overflow_data = []
|
|
|
|
|
|
self._error_count = {}
|
|
|
|
|
|
self.max_error_count = max_error_count
|
2022-02-09 20:05:49 +08:00
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
def add_error_count(self, uid: str):
|
|
|
|
|
|
if uid in self._error_count.keys():
|
|
|
|
|
|
self._error_count[uid] += 1
|
|
|
|
|
|
else:
|
|
|
|
|
|
self._error_count[uid] = 1
|
|
|
|
|
|
|
|
|
|
|
|
def check(self, uid: str) -> bool:
|
|
|
|
|
|
if uid in self._error_count.keys():
|
|
|
|
|
|
return self._error_count[uid] == self.max_error_count
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def remove_error_count(self, uid):
|
|
|
|
|
|
if uid in self._error_count.keys():
|
|
|
|
|
|
del self._error_count[uid]
|
|
|
|
|
|
|
|
|
|
|
|
def add_overflow(self, uid: str):
|
|
|
|
|
|
if uid not in self._overflow_data:
|
|
|
|
|
|
self._overflow_data.append(uid)
|
|
|
|
|
|
|
|
|
|
|
|
def remove_overflow(self, uid: str):
|
|
|
|
|
|
if uid in self._overflow_data:
|
|
|
|
|
|
self._overflow_data.remove(uid)
|
|
|
|
|
|
|
|
|
|
|
|
def is_overflow(self, uid: str) -> bool:
|
|
|
|
|
|
return uid in self._overflow_data
|
|
|
|
|
|
|
2022-02-09 20:05:49 +08:00
|
|
|
|
|
|
|
|
|
|
user_manager = UserManager()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@driver.on_startup
|
|
|
|
|
|
async def _():
|
|
|
|
|
|
"""
|
|
|
|
|
|
启动时分配定时任务
|
|
|
|
|
|
"""
|
2023-02-18 18:46:54 +08:00
|
|
|
|
g_list = await Genshin.filter(resin_remind=True).all()
|
|
|
|
|
|
update_list = []
|
2022-02-19 18:20:19 +08:00
|
|
|
|
date = datetime.now(pytz.timezone("Asia/Shanghai")) + timedelta(seconds=30)
|
2022-02-09 20:05:49 +08:00
|
|
|
|
for u in g_list:
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if u.resin_remind:
|
|
|
|
|
|
if u.resin_recovery_time:
|
2023-02-18 18:46:54 +08:00
|
|
|
|
if u.resin_recovery_time and u.resin_recovery_time > datetime.now(
|
2022-02-19 18:20:19 +08:00
|
|
|
|
pytz.timezone("Asia/Shanghai")
|
|
|
|
|
|
):
|
2022-06-03 11:52:40 +08:00
|
|
|
|
# date = await Genshin.get_user_resin_recovery_time(u.uid) # 不能要,因为可能在这期间用户使用了树脂
|
|
|
|
|
|
add_job(u.user_qq, 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],
|
|
|
|
|
|
# )
|
2022-02-19 18:20:19 +08:00
|
|
|
|
logger.info(
|
2022-06-03 11:52:40 +08:00
|
|
|
|
f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
|
2022-02-19 18:20:19 +08:00
|
|
|
|
)
|
|
|
|
|
|
else:
|
2023-03-04 17:51:18 +08:00
|
|
|
|
u.resin_recovery_time = None # type: ignore
|
2023-02-18 18:46:54 +08:00
|
|
|
|
update_list.append(u)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
add_job(u.user_qq, u.uid)
|
|
|
|
|
|
logger.info(
|
2022-06-03 11:52:40 +08:00
|
|
|
|
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
|
2022-02-19 18:20:19 +08:00
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
add_job(u.user_qq, u.uid)
|
|
|
|
|
|
logger.info(
|
2022-06-03 11:52:40 +08:00
|
|
|
|
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
|
2022-02-19 18:20:19 +08:00
|
|
|
|
)
|
2023-02-18 18:46:54 +08:00
|
|
|
|
if update_list:
|
|
|
|
|
|
await Genshin.bulk_update(update_list, ["resin_recovery_time"])
|
2022-02-09 20:05:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_job(user_id: int, uid: int):
|
2022-03-03 00:18:59 +08:00
|
|
|
|
# 移除
|
|
|
|
|
|
try:
|
|
|
|
|
|
scheduler.remove_job(f"genshin_resin_remind_{uid}_{user_id}")
|
|
|
|
|
|
except JobLookupError:
|
|
|
|
|
|
pass
|
2022-02-09 20:05:49 +08:00
|
|
|
|
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):
|
2023-02-18 18:46:54 +08:00
|
|
|
|
user = await Genshin.get_or_none(user_qq=user_id, uid=int(uid))
|
2022-02-09 20:05:49 +08:00
|
|
|
|
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)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
now = datetime.now(pytz.timezone("Asia/Shanghai"))
|
|
|
|
|
|
next_time = None
|
2022-02-09 20:05:49 +08:00
|
|
|
|
if code == 200:
|
2022-06-02 08:55:24 +08:00
|
|
|
|
current_resin = int(data["current_resin"]) # 当前树脂
|
|
|
|
|
|
max_resin = int(data["max_resin"]) # 最大树脂
|
2022-02-19 18:20:19 +08:00
|
|
|
|
msg = f"你的已经存了 {current_resin} 个树脂了!不要忘记刷掉!"
|
|
|
|
|
|
# resin_recovery_time = data["resin_recovery_time"] # 树脂全部回复时间
|
|
|
|
|
|
if current_resin < max_resin:
|
2022-02-09 20:05:49 +08:00
|
|
|
|
user_manager.remove(uid)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
user_manager.remove_overflow(uid)
|
2022-06-18 09:15:19 +08:00
|
|
|
|
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)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
elif current_resin == max_resin:
|
2023-02-18 18:46:54 +08:00
|
|
|
|
custom_overflow_resin = Config.get_config(
|
|
|
|
|
|
"resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND"
|
|
|
|
|
|
)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if user_manager.is_overflow(uid) and custom_overflow_resin:
|
|
|
|
|
|
next_time = now + timedelta(minutes=custom_overflow_resin * 8)
|
|
|
|
|
|
user_manager.add_overflow(uid)
|
|
|
|
|
|
user_manager.remove(uid)
|
|
|
|
|
|
msg = f"你的树脂都溢出 {custom_overflow_resin} 个了!浪费可耻!"
|
|
|
|
|
|
else:
|
|
|
|
|
|
next_time = now + timedelta(minutes=40 * 8 + random.randint(5, 50))
|
2022-06-03 11:52:40 +08:00
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if not user_manager.exists(uid) and current_resin >= max_resin - 40:
|
|
|
|
|
|
if current_resin == max_resin:
|
2022-02-09 20:05:49 +08:00
|
|
|
|
user_manager.append(uid)
|
2022-02-19 18:20:19 +08:00
|
|
|
|
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:
|
2023-02-18 18:46:54 +08:00
|
|
|
|
if user:
|
|
|
|
|
|
group_id = user.bind_group
|
|
|
|
|
|
if not group_id:
|
|
|
|
|
|
if group_list := await GroupInfoUser.get_user_all_group(
|
|
|
|
|
|
user_id
|
|
|
|
|
|
):
|
|
|
|
|
|
group_id = group_list[0]
|
|
|
|
|
|
try:
|
|
|
|
|
|
await bot.send_group_msg(
|
|
|
|
|
|
group_id=group_id, message=at(user_id) + msg
|
|
|
|
|
|
)
|
|
|
|
|
|
except ActionFailed as e:
|
|
|
|
|
|
logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}")
|
2022-06-03 11:52:40 +08:00
|
|
|
|
|
2022-02-19 18:20:19 +08:00
|
|
|
|
if not next_time:
|
2023-02-18 18:46:54 +08:00
|
|
|
|
if user_manager.check(uid) and Config.get_config(
|
|
|
|
|
|
"resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"
|
|
|
|
|
|
):
|
|
|
|
|
|
if user:
|
|
|
|
|
|
user.resin_remind = False
|
|
|
|
|
|
user.resin_recovery_time = None
|
|
|
|
|
|
await user.save(update_fields=["resin_recovery_time", "resin_remind"])
|
2022-02-19 18:20:19 +08:00
|
|
|
|
next_time = now + timedelta(minutes=(20 + random.randint(5, 20)) * 8)
|
|
|
|
|
|
user_manager.add_error_count(uid)
|
|
|
|
|
|
else:
|
|
|
|
|
|
user_manager.remove_error_count(uid)
|
2023-02-18 18:46:54 +08:00
|
|
|
|
if user:
|
|
|
|
|
|
user.resin_recovery_time = next_time
|
|
|
|
|
|
await user.save(update_fields=["resin_recovery_time", "resin_remind"])
|
2022-02-19 18:20:19 +08:00
|
|
|
|
scheduler.add_job(
|
|
|
|
|
|
_remind,
|
|
|
|
|
|
"date",
|
|
|
|
|
|
run_date=next_time,
|
|
|
|
|
|
id=f"genshin_resin_remind_{uid}_{user_id}",
|
|
|
|
|
|
args=[user_id, uid],
|
|
|
|
|
|
)
|
2022-06-03 11:52:40 +08:00
|
|
|
|
logger.info(
|
2023-02-18 18:46:54 +08:00
|
|
|
|
f"genshin_resin_remind add_job:USER:{user_id} UID:{uid} " f"{next_time} 原神树脂提醒"
|
|
|
|
|
|
)
|