From 9409fca9a89ad80b36d1566fda410085f577e347 Mon Sep 17 00:00:00 2001 From: CMHopeSunshine <277073121@qq.com> Date: Sat, 16 Apr 2022 11:55:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=B1=B3=E6=B8=B8=E7=A4=BE?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E7=AD=BE=E5=88=B0=E3=80=81=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- hoshino/modules/Genshin_Paimon/config.py | 12 +++ .../Genshin_Paimon/daily_note/__init__.py | 41 ++++++--- hoshino/modules/Genshin_Paimon/db_util.py | 48 ++++++++++- .../modules/Genshin_Paimon/gacha/__init__.py | 5 +- hoshino/modules/Genshin_Paimon/get_data.py | 77 ++++++++++++++++- .../Genshin_Paimon/monthinfo/__init__.py | 1 - .../Genshin_Paimon/mys_bbs_sign/__init__.py | 86 +++++++++++++++++++ hoshino/modules/Genshin_Paimon/util.py | 31 +++++++ 9 files changed, 283 insertions(+), 21 deletions(-) create mode 100644 hoshino/modules/Genshin_Paimon/config.py create mode 100644 hoshino/modules/Genshin_Paimon/mys_bbs_sign/__init__.py diff --git a/README.md b/README.md index 68adf6b..2488c0f 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ javascript:(function(){prompt(document.domain,document.cookie)})(); - 4.11 改用数据库进行数据存储,优化代码 - 4.14 新增每日天赋突破材料表查询 - 4.15 新增实时便签树脂提醒功能 +- 4.16 新增米游社原神自动签到功能 ## ToDo🕛 @@ -125,7 +126,7 @@ javascript:(function(){prompt(document.domain,document.cookie)})(); - [ ] ocr圣遗物评分和角色面板记录 - [ ] 角色、武器和圣遗物wiki - [ ] 派蒙AI闲聊 -- [ ] 米游社自动签到 +- [x] 米游社自动签到 - [x] 今日可刷材料 - [ ] 角色练度统计 - [ ] 派蒙戳一戳集卡 diff --git a/hoshino/modules/Genshin_Paimon/config.py b/hoshino/modules/Genshin_Paimon/config.py new file mode 100644 index 0000000..4b1dbd8 --- /dev/null +++ b/hoshino/modules/Genshin_Paimon/config.py @@ -0,0 +1,12 @@ +# 树脂提醒免打扰时间段,0和8即0点到8点不提醒 +remind_time_start = 0 +remind_time_end = 8 + +# 树脂提醒检查时间,8即为每八分钟检查一次 +remind_check_time = 8 + +# 自动签到执行开始时间,0即为每天0点执行 +auto_sign_time = 0 + +# 模拟抽卡的冷却时间,单位秒 +gacha_cooldown = 30 diff --git a/hoshino/modules/Genshin_Paimon/daily_note/__init__.py b/hoshino/modules/Genshin_Paimon/daily_note/__init__.py index cfc69f0..1f1772e 100644 --- a/hoshino/modules/Genshin_Paimon/daily_note/__init__.py +++ b/hoshino/modules/Genshin_Paimon/daily_note/__init__.py @@ -7,6 +7,7 @@ from ..db_util import update_note_remind2, update_note_remind, get_note_remind, from hoshino import get_bot, logger from datetime import datetime, timedelta from asyncio import sleep +from ..config import remind_time_start, remind_time_end, remind_check_time help_msg=''' [ssbq/实时便签 (uid)]查询当前树脂、洞天宝钱、派遣状况等 @@ -17,19 +18,26 @@ sv = Service('派蒙实时便签', bundle='派蒙', help_=help_msg) @sv.on_prefix(('ssbq','实时便笺','实时便签')) async def main(bot,ev): + if ev.message_type == 'group': + gid = str(ev.group_id) + else: + gid = str(ev.user_id) uid, msg, user_id, use_cache = await get_uid_in_msg(ev) - find_remind_enable = re.search(r'(?P开启提醒|关闭提醒|删除提醒)((?P\d{1,3})|(?:.*))', msg) + find_remind_enable = re.search(r'(?P开启提醒|关闭提醒|删除提醒)(.*)((?P\d{1,3})|(?:.*))', msg) if find_remind_enable: + if ev.message_type == 'guild': + await bot.send(ev, '实时便签提醒功能暂时无法在频道内使用哦') + return if find_remind_enable.group('action') == '开启提醒': if find_remind_enable.group('num'): - await update_note_remind2(user_id, uid, str(ev.group_id), True, find_remind_enable.group('num')) - await bot.send(ev, f'开启提醒成功,派蒙会在你的树脂达到{find_remind_enable.group("num")}时在群里提醒你的', at_sender=True) + await update_note_remind2(user_id, uid, gid, 1, find_remind_enable.group('num')) + await bot.send(ev, f'开启提醒成功,派蒙会在你的树脂达到{find_remind_enable.group("num")}时提醒你的', at_sender=True) else: - await update_note_remind2(user_id, uid, str(ev.group_id), True) + await update_note_remind2(user_id, uid, gid, 1) await bot.send(ev, '开启提醒成功', at_sender=True) elif find_remind_enable.group('action') == '关闭提醒': await bot.send(ev, '关闭提醒成功', at_sender=True) - await update_note_remind2(user_id, uid, str(ev.group_id), False) + await update_note_remind2(user_id, uid, gid, 0) elif find_remind_enable.group('action') == '删除提醒': await bot.send(ev, '删除提醒成功', at_sender=True) await delete_note_remind(user_id, uid) @@ -44,11 +52,15 @@ async def main(bot,ev): except Exception as e: await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True) -@sv.scheduled_job('cron', minute='*/8') +@sv.scheduled_job('cron', minute=f'*/{remind_check_time}') async def check_note(): + now_time = datetime.now() + start_time = datetime(now_time.year, now_time.month, now_time.day, remind_time_start, 0, 0) + end_time = datetime(now_time.year, now_time.month, now_time.day, remind_time_end, 0, 0) + if start_time < now_time < end_time: + return data = await get_note_remind() if data: - now_time = datetime.now() logger.info('---派蒙开始检查实时便签树脂提醒---') for user_id, uid, count, remind_group, enable, last_remind_time, today_remind_count in data: if last_remind_time: @@ -62,8 +74,12 @@ async def check_note(): if enable and ((today_remind_count and today_remind_count < 3) or not today_remind_count) and time_e: now_data = await get_daily_note_data(uid) if isinstance(now_data, str): - try: - await get_bot().send_group_msg(group_id=remind_group, message=f'[CQ:at,qq={user_id}]你的cookie失效了哦,派蒙没办法帮你检查树脂,先帮你删除了,请重新添加ck后再叫派蒙开启提醒') + try: + await delete_note_remind(user_id, uid) + if user_id == remind_group: + await get_bot().send_private_msg(user_id=user_id, message=f'[CQ:at,qq={user_id}]你的cookie失效了哦,派蒙没办法帮你检查树脂,请重新添加ck后再叫派蒙开启提醒') + else: + await get_bot().send_group_msg(group_id=remind_group, message=f'[CQ:at,qq={user_id}]你的cookie失效了哦,派蒙没办法帮你检查树脂,请重新添加ck后再叫派蒙开启提醒') except Exception as e: logger.error(f'---派蒙发送树脂提醒失败:{e}---') else: @@ -76,10 +92,13 @@ async def check_note(): now_time_str = now_time.strftime('%Y%m%d %H:%M:%S') try: await update_note_remind(user_id, uid, count, remind_group, enable, now_time_str, today_remind_count) - await get_bot().send_group_msg(group_id=remind_group, message=f'[CQ:at,qq={user_id}]⚠️你的树脂已经达到了{now_data["data"]["current_resin"]},派蒙30分钟后还会帮你检查⚠️') + if user_id == remind_group: + await get_bot().send_private_msg(user_id=user_id, message=f'[CQ:at,qq={user_id}]⚠️你的树脂已经达到了{now_data["data"]["current_resin"]},记得清理哦!⚠️') + else: + await get_bot().send_group_msg(group_id=remind_group, message=f'[CQ:at,qq={user_id}]⚠️你的树脂已经达到了{now_data["data"]["current_resin"]},记得清理哦!⚠️') except Exception as e: logger.error(f'---派蒙发送树脂提醒失败:{e}---') - await sleep(2) + await sleep(3) @sv.scheduled_job('cron', hour='0') async def delete_day_limit(): diff --git a/hoshino/modules/Genshin_Paimon/db_util.py b/hoshino/modules/Genshin_Paimon/db_util.py index 9165716..bcf6b51 100644 --- a/hoshino/modules/Genshin_Paimon/db_util.py +++ b/hoshino/modules/Genshin_Paimon/db_util.py @@ -258,7 +258,7 @@ async def get_note_remind(): uid TEXT NOT NULL, count INTEGER, remind_group TEXT, - enable bool, + enable boolean, last_remind_time datetime, today_remind_count INTEGER, PRIMARY KEY (user_id, uid) @@ -317,7 +317,7 @@ async def update_day_remind_count(): uid TEXT NOT NULL, count INTEGER, remind_group TEXT, - enable bool, + enable boolean, last_remind_time datetime, today_remind_count INTEGER, PRIMARY KEY (user_id, uid) @@ -336,7 +336,7 @@ async def delete_note_remind(user_id, uid): uid TEXT NOT NULL, count INTEGER, remind_group TEXT, - enable bool, + enable boolean, last_remind_time datetime, today_remind_count INTEGER, PRIMARY KEY (user_id, uid) @@ -345,6 +345,48 @@ async def delete_note_remind(user_id, uid): conn.commit() conn.close() +async def get_auto_sign(): + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + cursor.execute('''CREATE TABLE IF NOT EXISTS bbs_sign + ( + user_id TEXT NOT NULL, + uid TEXT NOT NULL, + group_id TEXT, + PRIMARY KEY (user_id, uid) + );''') + cursor.execute('SELECT * FROM bbs_sign;') + res = cursor.fetchall() + conn.close() + return res + +async def add_auto_sign(user_id, uid, group_id): + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + cursor.execute('''CREATE TABLE IF NOT EXISTS bbs_sign + ( + user_id TEXT NOT NULL, + uid TEXT NOT NULL, + group_id TEXT, + PRIMARY KEY (user_id, uid) + );''') + cursor.execute('REPLACE INTO bbs_sign VALUES (?, ?, ?);', (user_id, uid, group_id)) + conn.commit() + conn.close() + +async def delete_auto_sign(user_id, uid): + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + cursor.execute('''CREATE TABLE IF NOT EXISTS bbs_sign + ( + user_id TEXT NOT NULL, + uid TEXT NOT NULL, + group_id TEXT, + PRIMARY KEY (user_id, uid) + );''') + cursor.execute('DELETE FROM bbs_sign WHERE user_id=? AND uid=?;', (user_id, uid)) + conn.commit() + conn.close() init_db() diff --git a/hoshino/modules/Genshin_Paimon/gacha/__init__.py b/hoshino/modules/Genshin_Paimon/gacha/__init__.py index d0faf1b..b17ecbb 100644 --- a/hoshino/modules/Genshin_Paimon/gacha/__init__.py +++ b/hoshino/modules/Genshin_Paimon/gacha/__init__.py @@ -5,8 +5,9 @@ from hoshino.util import PriFreqLimiter from ..util import Dict from .gacha_role import * from .gacha_wish import more_ten +from ..config import gacha_cooldown -lmt = PriFreqLimiter(30) +lmt = PriFreqLimiter(gacha_cooldown) help_msg=''' 1.[抽n十连xx池]抽n次xx池的十连,最多同时5次 *池子和官方同步,有角色1|角色2|武器|常驻,默认为角色1 @@ -52,7 +53,7 @@ async def gacha(bot, ev): if not lmt.check(gid,uid): await bot.finish(ev, f'模拟抽卡冷却中(剩余{int(lmt.left_time(gid,uid)) + 1}秒)', at_sender=True) return - lmt.start_cd(gid, uid, 30) + lmt.start_cd(gid, uid, gacha_cooldown) if num >= 3: await bot.send(ev, '抽卡图正在生成中,请稍候') if isinstance(gacha_type,int): diff --git a/hoshino/modules/Genshin_Paimon/get_data.py b/hoshino/modules/Genshin_Paimon/get_data.py index 2f5263a..c3ddf74 100644 --- a/hoshino/modules/Genshin_Paimon/get_data.py +++ b/hoshino/modules/Genshin_Paimon/get_data.py @@ -1,5 +1,5 @@ from hoshino import aiorequests -from .util import get_headers, cache, get_use_cookie, get_own_cookie, check_retcode +from .util import get_headers, get_sign_headers, cache, get_use_cookie, get_own_cookie, check_retcode from .db_util import update_cookie_cache import datetime import re @@ -37,7 +37,11 @@ async def get_daily_note_data(uid): "role_id": uid } res = await aiorequests.get(url=url, headers=headers, params=params) - return await res.json() + data = await res.json() + if await check_retcode(data, cookie, uid): + return data + else: + return f'你的uid{uid}的cookie已过期,需要重新绑定哦!' @cache(ttl=datetime.timedelta(hours=1)) async def get_player_card_data(user_id, uid, use_cache=True): @@ -113,11 +117,15 @@ async def get_monthinfo_data(uid, month, use_cache=True): data = await res.json() if await check_retcode(data, cookie, uid): return data + else: + return f'你的uid{uid}的cookie已过期,需要重新绑定哦!' async def get_bind_game(cookie): finduid = re.search(r'account_id=(\d{6,12})', cookie) if not finduid: - return None + finduid = re.search(r'ltuid=(\d{6,12})', cookie) + if not finduid: + return None, None uid = finduid.group(1) url = 'https://api-takumi.mihoyo.com/game_record/card/wapi/getGameRecordCard' headers = get_headers(q=f'uid={uid}', cookie = cookie) @@ -127,6 +135,69 @@ async def get_bind_game(cookie): res = await aiorequests.get(url=url, headers=headers, params=params) return (await res.json()), uid +# 获取今日签到信息 +async def get_sign_info(uid): + server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01" + url = 'https://api-takumi.mihoyo.com/event/bbs_sign_reward/info' + cookie = await get_own_cookie(uid, action='查询米游社签到') + if not cookie: + return f'你的uid{uid}没有绑定对应的cookie,使用ysb绑定才能用米游社签到哦!' + headers = { + 'x-rpc-app_version': '2.11.1', + 'x-rpc-client_type': '5', + 'Origin': 'https://webstatic.mihoyo.com', + 'Referer': 'https://webstatic.mihoyo.com/', + 'Cookie': cookie['cookie'], + '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', + + } + params = { + 'act_id': 'e202009291139501', + 'region': server_id, + 'uid': uid + } + res = await aiorequests.get(url=url, headers=headers, params=params) + data = await res.json() + if await check_retcode(data, cookie, uid): + return data + +# 执行签到操作 +async def sign(uid): + server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01" + url = 'https://api-takumi.mihoyo.com/event/bbs_sign_reward/sign' + cookie = await get_own_cookie(uid, action='米游社签到') + if not cookie: + return f'你的uid{uid}没有绑定对应的cookie,使用ysb绑定才能用米游社签到哦!' + headers = get_sign_headers(cookie['cookie']) + json_data = { + 'act_id': 'e202009291139501', + 'uid': uid, + 'region': server_id + } + res = await aiorequests.post(url=url, headers=headers, json=json_data) + data = await res.json() + print(res) + if await check_retcode(data, cookie, uid): + return data + else: + return f'你的uid{uid}的cookie已过期,需要重新绑定哦!' + +# 获取签到奖励列表 +async def get_sign_list(): + url = 'https://api-takumi.mihoyo.com/event/bbs_sign_reward/home' + headers = { + 'x-rpc-app_version': '2.11.1', + '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': '5', + 'Referer' : 'https://webstatic.mihoyo.com/' + } + params = { + 'act_id': 'e202009291139501' + } + res = await aiorequests.get(url=url, headers=headers, params=params) + return await res.json() \ No newline at end of file diff --git a/hoshino/modules/Genshin_Paimon/monthinfo/__init__.py b/hoshino/modules/Genshin_Paimon/monthinfo/__init__.py index bc6be83..d269f31 100644 --- a/hoshino/modules/Genshin_Paimon/monthinfo/__init__.py +++ b/hoshino/modules/Genshin_Paimon/monthinfo/__init__.py @@ -1,6 +1,5 @@ import json,os,re,datetime from hoshino import R,MessageSegment,logger, Service -from hoshino.typing import CQEvent, Message from hoshino.util import filt_message from ..util import get_uid_in_msg from ..get_data import get_monthinfo_data diff --git a/hoshino/modules/Genshin_Paimon/mys_bbs_sign/__init__.py b/hoshino/modules/Genshin_Paimon/mys_bbs_sign/__init__.py new file mode 100644 index 0000000..d8acb5a --- /dev/null +++ b/hoshino/modules/Genshin_Paimon/mys_bbs_sign/__init__.py @@ -0,0 +1,86 @@ +from hoshino import Service, get_bot, logger +from ..util import get_uid_in_msg +from ..db_util import get_auto_sign, add_auto_sign, delete_auto_sign +from ..get_data import get_sign_info, sign, get_sign_list +from ..config import auto_sign_time +from datetime import datetime +from asyncio import sleep +import random +from collections import defaultdict +import re + +sv = Service('派蒙米游社自动签到', bundle='派蒙') + + +@sv.on_prefix(('mys签到', 'mys-sign')) +async def bbs_ys_sign(bot, ev): + uid, msg, user_id, use_cache = await get_uid_in_msg(ev) + sign_list = await get_sign_list() + sign_info = await get_sign_info(uid) + if isinstance(sign_info, str): + await bot.send(ev, sign_info, at_sender=True) + elif sign_info['data']['is_sign']: + sign_day = sign_info['data']['total_sign_day'] - 1 + await bot.send(ev, f'你今天已经签过到了哦,获得的奖励为:\n{sign_list["data"]["awards"][sign_day]["name"]} * {sign_list["data"]["awards"][sign_day]["cnt"]}', at_sender=True) + else: + sign_day = sign_info['data']['total_sign_day'] + sign_action = await sign(uid) + if isinstance(sign_action, str): + await bot.send(ev, sign_action, at_sender=True) + else: + await bot.send(ev, f'签到成功,获得的奖励为:\n{sign_list["data"]["awards"][sign_day]["name"]} * {sign_list["data"]["awards"][sign_day]["cnt"]}', at_sender=True) + +@sv.on_prefix(('mys自动签到', '米游社自动签到', 'mys-auto-sign')) +async def bbs_auto_sign(bot, ev): + if ev.message_type != 'group': + await bot.send(ev, '自动签到功能暂时只限Q群内使用哦') + return + msg = ev.message.extract_plain_text().strip() + find_uid = re.search(r'(?P(1|2|5)\d{8})', msg) + if not find_uid: + await bot.send(ev, '请把正确的需要帮忙签到的uid给派蒙哦!', at_sender=True) + else: + uid = find_uid.group('uid') + find_action = re.search(r'(?P开启|启用|打开|关闭|禁用)', msg) + if find_action: + if find_action.group('action') in ['开启', '启用', '打开']: + await add_auto_sign(str(ev.user_id), uid, str(ev.group_id)) + await bot.send(ev, '开启米游社自动签到成功,派蒙会在每日0点帮你签到', at_sender=True) + elif find_action.group('action') in ['关闭', '禁用']: + await delete_auto_sign(str(ev.user_id), uid) + await bot.send(ev, '关闭米游社自动签到成功', at_sender=True) + else: + await add_auto_sign(str(ev.user_id), uid, str(ev.group_id)) + await bot.send(ev, '开启米游社自动签到成功,派蒙会在每日0点帮你签到', at_sender=True) + + +@sv.scheduled_job('cron', hour=auto_sign_time) +async def auto_sign(): + data = await get_auto_sign() + if data: + ann = defaultdict(lambda: defaultdict(list)) + logger.info('---派蒙开始执行米游社自动签到---') + sign_list = await get_sign_list() + for user_id, uid, group_id in data: + await sleep(random.randint(3,8)) + sign_result = await sign(uid) + if not isinstance(sign_result, str): + sign_info = await get_sign_info(uid) + sign_day = sign_info['data']['total_sign_day'] - 1 + ann[group_id]['成功'].append(f'.UID{uid}-{sign_list["data"]["awards"][sign_day]["name"]}*{sign_list["data"]["awards"][sign_day]["cnt"]}') + else: + await delete_auto_sign(user_id, uid) + ann[group_id]['失败'].append(f'.UID{uid}') + for group_id, content in ann.items(): + group_str = '米游社自动签到结果:\n' + for type, ann_list in content.items(): + if ann_list: + group_str += f'签到{type}:\n' + for u in ann_list: + group_str += str(ann_list.index(u) + 1) + u + '\n' + try: + await get_bot().send_group_msg(group_id=group_id, message=group_str) + await sleep(random.randint(3,8)) + except Exception as e: + logger.error(f'米游社签到结果发送失败:{e}') + diff --git a/hoshino/modules/Genshin_Paimon/util.py b/hoshino/modules/Genshin_Paimon/util.py index dcb761e..637c73d 100644 --- a/hoshino/modules/Genshin_Paimon/util.py +++ b/hoshino/modules/Genshin_Paimon/util.py @@ -4,6 +4,7 @@ import hashlib import re import random import time +import string from hoshino import logger, aiorequests from io import BytesIO import base64 @@ -154,6 +155,12 @@ def md5(text: str) -> str: md5.update(text.encode()) return md5.hexdigest() +def random_hex(length): + result = hex(random.randint(0, 16 ** length)).replace('0x', '').upper() + if len(result) < length: + result = '0' * (length - len(result)) + result + return result + # 米游社headers的ds_token,对应版本2.11.1 def get_ds(q="", b=None) -> str: if b: @@ -180,6 +187,30 @@ def get_headers(cookie, q='',b=None): } return headers +def get_old_version_ds() -> str: + s = 'h8w582wxwgqvahcdkpvdhbh2w9casgfl' + t = str(int(time.time())) + r = ''.join(random.sample(string.ascii_lowercase + string.digits, 6)) + c = md5("salt=" + s + "&t=" + t + "&r=" + r) + return f"{t},{r},{c}" + +def get_sign_headers(cookie): + 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': cookie, + 'x-rpc-device_id': random_hex(32), + 'Origin': 'https://webstatic.mihoyo.com', + 'X_Requested_With': 'com.mihoyo.hyperion', + 'DS': get_old_version_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' + } + return headers + # 检查cookie是否有效,通过查看个人主页来判断 async def check_cookie(cookie): url = 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2'