diff --git a/.env.prod b/.env.prod
index 82e48b65..4c6e8d82 100644
--- a/.env.prod
+++ b/.env.prod
@@ -5,3 +5,6 @@ SUPERUSERS=["123456"] # 超级用户
NICKNAME=["派蒙", "bot"] # 机器人的昵称
COMMAND_START=[""] # 命令前缀,根据需要自行修改
COMMAND_SEP=[""] # 命令分隔符
+CAPTCHA_ENABLED=true#启用打码平台
+CAPTCHA_API_KEY="YOUR-API-KEY"#验证码打码平台api key
+CAPTCHA_API_ENDPOINT="YOUR-API-PLATFORM"#验证码打码平台api调用网址
\ No newline at end of file
diff --git a/LittlePaimon/plugins/Paimon_Autobbs/draw.py b/LittlePaimon/plugins/Paimon_Autobbs/draw.py
index 26ce5020..eff9a947 100644
--- a/LittlePaimon/plugins/Paimon_Autobbs/draw.py
+++ b/LittlePaimon/plugins/Paimon_Autobbs/draw.py
@@ -11,12 +11,13 @@ class SignResult(IntEnum):
SUCCESS = auto()
DONE = auto()
FAIL = auto()
+ INVALID = auto()
async def draw_result(group_id: int, data: list):
img = PMImage(await load_image(RESOURCE_BASE_PATH / 'player_card' / 'white_bg.png'))
success_list = [d for d in data if d['result'] in [SignResult.SUCCESS, SignResult.DONE]]
- fail_list = [d['uid'] for d in data if d['result'] == SignResult.FAIL]
+ fail_list = [d['uid'] for d in data if d['result'] == SignResult.FAIL or d['uid'] for d in data if d['result'] == SignResult.INVALID]
same_reward = defaultdict(list)
for s in success_list:
same_reward[s['reward']].append(s['uid'])
diff --git a/LittlePaimon/plugins/Paimon_Autobbs/sign_handle.py b/LittlePaimon/plugins/Paimon_Autobbs/sign_handle.py
index 0451cbc4..a1253496 100644
--- a/LittlePaimon/plugins/Paimon_Autobbs/sign_handle.py
+++ b/LittlePaimon/plugins/Paimon_Autobbs/sign_handle.py
@@ -5,6 +5,7 @@
from collections import defaultdict
from typing import Tuple, Union
+import nonebot
from nonebot import get_bot
from LittlePaimon.config import config
@@ -15,12 +16,12 @@
from .draw import SignResult, draw_result
SIGN_ACTION_API = 'https://api-takumi.mihoyo.com/event/bbs_sign_reward/sign'
-GEETEST_HEADER = {"Accept": "*/*",
+GEETEST_HEADER = {"Accept": "*/*",
"X-Requested-With": "com.mihoyo.hyperion",
- "User-Agent": 'Mozilla/5.0 (Linux; Android 12; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) '
- 'Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36 miHoYoBBS/2.35.2',
- "Referer": "https://webstatic.mihoyo.com/",
- "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
+ "User-Agent": 'Mozilla/5.0 (Linux; Android 12; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) '
+ 'Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36 miHoYoBBS/2.35.2',
+ "Referer": "https://webstatic.mihoyo.com/",
+ "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
}
sign_reward_list: dict = {}
@@ -31,7 +32,7 @@ async def sign_action(user_id: str, uid: str) -> Union[dict, str]:
resp = await aiorequests.post(SIGN_ACTION_API, headers=mihoyo_sign_headers(cookie_info.cookie),
json={
'act_id': 'e202009291139501',
- 'uid': uid,
+ 'uid': uid,
'region': server_id
})
data = resp.json()
@@ -54,7 +55,7 @@ async def mhy_bbs_sign(user_id: str, uid: str) -> Tuple[SignResult, str]:
if isinstance(sign_info, str):
logger.info('米游社原神签到', '➤', {'用户': user_id, 'UID': uid}, '未绑定私人cookie或已失效', False)
await MihoyoBBSSub.filter(user_id=user_id, uid=uid).delete()
- return SignResult.FAIL, sign_info
+ return SignResult.INVALID, sign_info
elif sign_info['data']['is_sign']:
signed_days = sign_info['data']['total_sign_day'] - 1
logger.info('米游社原神签到', '➤', {'用户': user_id, 'UID': uid}, '今天已经签过了', True)
@@ -62,6 +63,7 @@ async def mhy_bbs_sign(user_id: str, uid: str) -> Tuple[SignResult, str]:
return SignResult.DONE, f'UID{uid}今天已经签过了,获得的奖励为\n{sign_reward_list[signed_days]["name"]}*{sign_reward_list[signed_days]["cnt"]}'
else:
return SignResult.DONE, f'UID{uid}今天已经签过了'
+ message = None
for i in range(3):
sign_data = await sign_action(user_id, uid)
if isinstance(sign_data, str):
@@ -87,13 +89,84 @@ async def mhy_bbs_sign(user_id: str, uid: str) -> Tuple[SignResult, str]:
else:
return SignResult.SUCCESS, '签到成功'
else:
- wait_time = random.randint(90, 120)
- logger.info('米游社原神签到', '➤', {'用户': user_id, 'UID': uid}, f'出现验证码,等待{wait_time}秒后进行第{i + 1}次尝试绕过', False)
- await asyncio.sleep(wait_time)
- logger.info('米游社原神签到', '➤', {'用户': user_id, 'UID': uid}, '尝试3次签到失败,无法绕过验证码', False)
- return SignResult.FAIL, f'{uid}签到失败,无法绕过验证码'
+ result, message = await geetest_verify(user_id=user_id, uid=uid, sign_data=sign_data)
+ if result == SignResult.INVALID:
+ return SignResult.INVALID, f'{uid}签到失败,你的UID{uid}的cookie疑似失效了'
+ elif result == SignResult.FAIL:
+ logger.warning('米游社原神签到', '➤', f'{uid}第{i}次签到失败,正在重试,报错信息:{message}')
+ elif result == SignResult.SUCCESS:
+ return SignResult.SUCCESS, '签到成功'
+ else:
+ logger.warning('米游社原神签到', '➤', f'{uid}第{i}次签到失败,正在重试,报错信息:{message}')
+ return SignResult.FAIL, f'{uid}签到失败,报错信息{message}'
+async def sign_action_after_geetest(user_id: str,
+ uid: str,
+ geetest_challenge: str,
+ geetest_validate: str,
+ geetest_seccode: str):
+ server_id = 'cn_qd01' if uid[0] == '5' else 'cn_gf01'
+ cookie_info = await PrivateCookie.get_or_none(user_id=user_id, uid=uid)
+ headers = mihoyo_sign_headers(cookie_info.cookie)
+ headers["x-rpc-validate"] = geetest_validate
+ headers["x-rpc-challenge"] = geetest_challenge
+ headers["x-rpc-seccode"] = geetest_seccode
+ resp = await aiorequests.post(url=SIGN_ACTION_API, headers=headers,
+ json={
+ 'act_id': 'e202009291139501',
+ 'uid': uid,
+ 'region': server_id
+ })
+ data = resp.json()
+ if await check_retcode(data, cookie_info, user_id, uid):
+ return data
+ else:
+ return f'你的UID{uid}的cookie疑似失效了'
+
+
+async def geetest_verify(user_id: str, uid: str, sign_data: dict):
+ global_config = nonebot.get_driver().config
+ captcha_enable = global_config.captcha_enabled
+ superuser = global_config.superusers
+ if not captcha_enable:
+ logger.info('米游社原神签到➤',
+ '未开启验证码绕过,请添加captcha_api_key并根据需求修改geetest_verify(), sign_action_after_geetest(), '
+ 'geetest_handle_init(), 以及geetest_handle_finish()函数')
+ if user_id not in superuser:
+ return SignResult.FAIL, f'{uid}签到失败,请联系管理员检查后台日志并开启验证码绕过'
+ else:
+ return SignResult.FAIL, f'{uid}签到失败,请检查后台日志开启验证码绕过'
+ api_key = global_config.captcha_api_key
+ api_endpoint = global_config.captcha_api_endpoint
+ gt = sign_data['data']['gt']
+ challenge = sign_data['data']['challenge']
+ page_url = f'https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true&act_id' \
+ f'=e202009291139501<uid={uid}'
+ token, err_message = await geetest_handle_init(api_key=api_key, gt=gt, challenge=challenge,
+ page_url=page_url, api_endpoint=api_endpoint)
+ if err_message == "":
+ sign_result = await sign_action_after_geetest(user_id=user_id,
+ uid=uid,
+ geetest_challenge=token['challenge'],
+ geetest_seccode=token['seccode'],
+ geetest_validate=token['validate'])
+ if sign_result == f'你的UID{uid}的cookie疑似失效了':
+ return SignResult.INVALID, f'你的UID{uid}的cookie疑似失效了'
+ else:
+ return SignResult.SUCCESS, '签到成功'
+ else:
+ return SignResult.FAIL, f'{uid}平台返回错误{err_message}'
+
+
+async def geetest_handle_init(api_key: str,
+ api_endpoint: str,
+ gt: str,
+ challenge: str,
+ page_url: str):
+ # TODO: Please modify this function according to the captcha resolver you are using
+ raise NotImplementedError
+
@scheduler.scheduled_job('cron', hour=config.auto_sign_hour, minute=config.auto_sign_minute,
misfire_grace_time=10)
async def _():
@@ -111,7 +184,8 @@ async def bbs_auto_sign():
if not subs:
# 如果没有米游社原神签到订阅,则不执行签到任务
return
- logger.info('米游社原神签到', f'开始执行米游社自动签到,共{len(subs)}个任务,预计花费{len(subs) * 2}分钟')
+ logger.info('米游社原神签到',
+ f'开始执行米游社自动签到,共{len(subs)}个任务,预计花费{len(subs) * 2}分钟')
sign_result_group = defaultdict(list)
sign_result_private = defaultdict(list)
for sub in subs:
@@ -120,13 +194,13 @@ async def bbs_auto_sign():
if sub.user_id != sub.group_id:
sign_result_group[sub.group_id].append({
'user_id': sub.user_id,
- 'uid': sub.uid,
- 'result': result,
- 'reward': msg.split('\n')[-1] if result in [SignResult.SUCCESS, SignResult.DONE] else ''
+ 'uid': sub.uid,
+ 'result': result,
+ 'reward': msg.split('\n')[-1] if result in [SignResult.SUCCESS, SignResult.DONE] else ''
})
else:
sign_result_private[sub.user_id].append({
- 'uid': sub.uid,
+ 'uid': sub.uid,
'result': result,
'reward': msg.split('\n')[-1] if result in [SignResult.SUCCESS, SignResult.DONE] else ''
})
diff --git a/LittlePaimon/plugins/Paimon_DailyNote/handler.py b/LittlePaimon/plugins/Paimon_DailyNote/handler.py
index 9fef91fc..e7d727b2 100644
--- a/LittlePaimon/plugins/Paimon_DailyNote/handler.py
+++ b/LittlePaimon/plugins/Paimon_DailyNote/handler.py
@@ -4,16 +4,19 @@
import re
import time
+import nonebot
import pytz
from nonebot import get_bot
from nonebot.adapters.onebot.v11 import Message
from nonebot.params import CommandArg, Depends
from LittlePaimon.config import config
-from LittlePaimon.database import DailyNoteSub, Player, LastQuery
+from LittlePaimon.database import DailyNoteSub, Player, LastQuery, PrivateCookie
from LittlePaimon.utils import logger, scheduler
-from LittlePaimon.utils.api import get_mihoyo_private_data
+from LittlePaimon.utils.api import get_mihoyo_private_data, mihoyo_headers, get_cookie, DAILY_NOTE_API, \
+ mihoyo_sign_headers, mihoyo_verify_verification_headers
from .draw import draw_daily_note_card
+from ...utils.requests import aiorequests
def SubList() -> dict:
@@ -45,6 +48,75 @@ async def get_subs(**kwargs) -> str:
return f'会在{result.strip(",")}时向你发送提醒' if result else '当前没有订阅'
+async def geetest_verify_verification(api: str, cookie: str, validate: dict):
+ geetest_challenge = validate['challenge']
+ geetest_seccode = validate['seccode']
+ geetest_validate = validate['validate']
+ body = {
+ "geetest_challenge": geetest_challenge,
+ "geetest_seccode": geetest_seccode,
+ "geetest_validate": geetest_validate
+ }
+ header = mihoyo_verify_verification_headers(cookie=cookie, request_body=body)
+ url = api + "/game_record/app/card/wapi/verifyVerification"
+ resp = await aiorequests.post(url=url, headers=header, json=body)
+ return resp.json()
+
+
+async def geetest_create_verification(api: str, cookie: str):
+ url = api + "/game_record/app/card/wapi/createVerification?is_high=true"
+ header = mihoyo_headers(cookie=cookie, q="is_high=true")
+ result = await aiorequests.get(url=url, headers=header)
+ return result.json()
+
+
+async def geetest_handle_init(api_key: str,
+ api_endpoint: str,
+ gt: str,
+ challenge: str,
+ page_url: str):
+ # TODO: Please modify this function according to the captcha resolver you are using
+ raise NotImplementedError
+
+
+async def geetest_handle(user_id: str, uid: str, ssbq_data: dict):
+ global_config = nonebot.get_driver().config
+ captcha_enable = global_config.captcha_enabled
+ superuser = global_config.superusers
+ if not captcha_enable:
+ if user_id not in superuser:
+ logger.warning('原神实时便签', '➤', '非特权用户试图绕过验证码失败:未开启验证码绕过')
+ return 1, f'服务器返回1034,疑似验证码。请联系管理员开启验证码绕过程序。'
+ else:
+ logger.warning('原神实时便签', '➤', '特权用户试图绕过验证码失败:未开启验证码绕过')
+ return 1, f'服务器返回1034,疑似验证码,请配置验证码绕过程序。'
+ cookie_info = await get_cookie(user_id=user_id, uid=uid, check=True)
+ if not cookie_info:
+ logger.warning('原神实时便签', '➤', '用户试图绕过验证码失败:cookie失效')
+ return 1, f'当前uid{uid}cookie已失效,请使用[原神扫码绑定]/[ysb]绑定私人cookie/联系管理员添加私人cookie或公共cookie'
+ api_endpoint = 'https://api-takumi-record.mihoyo.com'
+ geetest_create = await geetest_create_verification(api=api_endpoint, cookie=cookie_info.cookie)
+ captcha_api_endpoint = ""
+ captcha_api_key = global_config.captcha_api_key
+ gt = geetest_create['data']['gt']
+ challenge = geetest_create['data']['challenge']
+ page_url = "https://webstatic.mihoyo.com/app/community-game-records/"
+ token, err_message = await geetest_handle_init(api_key=captcha_api_key,
+ api_endpoint=captcha_api_endpoint,
+ gt=gt,
+ challenge=challenge,
+ page_url=page_url)
+ if err_message != "":
+ logger.warning('原神实时便签', '➤', f'用户试图绕过验证码失败:打码平台返回错误{err_message}')
+ return 1, f'{uid}查询实时便签失败,米哈游服务器返回1034疑似验证码,绕过验证码失败:{err_message}'
+ geetest_verify = await geetest_verify_verification(api=api_endpoint, validate=token, cookie=cookie_info.cookie)
+ if geetest_verify['retcode'] != 0:
+ logger.warning('原神实时便签', '➤',
+ f'用户试图绕过验证码失败:米哈游服务器返回验证码结果{geetest_verify["message"]}')
+ return 1, f'{uid}查询实时便签失败,米哈游服务器返回1034疑似验证码,绕过验证码失败:米哈游服务器返回验证码结果{geetest_verify["message"]}'
+ return 0, challenge
+
+
async def handle_ssbq(player: Player):
await LastQuery.update_last_query(player.user_id, player.uid)
data = await get_mihoyo_private_data(player.uid, player.user_id, 'daily_note')
@@ -54,7 +126,21 @@ async def handle_ssbq(player: Player):
elif data['retcode'] == 1034:
logger.info('原神实时便签', '➤', {'用户': player.user_id, 'UID': player.uid},
'获取数据失败,状态码为1034,疑似验证码', False)
- return f'{player.uid}遇验证码阻拦,需手动前往米游社进行验证后才能继续使用\n'
+ status, result = await geetest_handle(user_id=player.user_id, uid=player.uid, ssbq_data=data)
+ if status == 0:
+ data = await get_mihoyo_private_data(uid=player.uid, user_id=player.user_id, mode='daily_note',
+ geetest_challenge=result)
+ logger.info('原神实时便签', '➤', {'用户': player.user_id, 'UID': player.uid}, '获取数据成功', True)
+ try:
+ img = await draw_daily_note_card(data['data'], player.uid)
+ logger.info('原神实时便签', '➤➤', {'用户': player.user_id, 'UID': player.uid}, '绘制图片成功', True)
+ return img
+ except Exception as e:
+ logger.info('原神实时便签', '➤➤', {'用户': player.user_id, 'UID': player.uid}, f'绘制图片失败,{e}',
+ False)
+ return f'{player.uid}绘制图片失败,{e}\n'
+ else:
+ return result
elif data['retcode'] != 0:
logger.info('原神实时便签', '➤', {'用户': player.user_id, 'UID': player.uid},
f'获取数据失败,code为{data["retcode"]}, msg为{data["message"]}', False)
@@ -84,7 +170,8 @@ async def check_note():
if not (subs := await DailyNoteSub.all()):
return
time_now = time.time()
- logger.info('原神实时便签', f'开始执行定时检查,共{len(subs)}个任务,预计花费{round(6 * len(subs) / 60, 2)}分钟')
+ logger.info('原神实时便签',
+ f'开始执行定时检查,共{len(subs)}个任务,预计花费{round(6 * len(subs) / 60, 2)}分钟')
for sub in subs:
limit_num = 5 if sub.resin_num and sub.coin_num else 3
if sub.today_remind_num <= limit_num and (
@@ -93,11 +180,13 @@ async def check_note():
tzinfo=pytz.timezone('Asia/Shanghai'))))):
data = await get_mihoyo_private_data(sub.uid, str(sub.user_id), 'daily_note')
if isinstance(data, str):
- logger.info('原神实时便签', '➤', {'用户': sub.user_id, 'UID': sub.uid}, 'Cookie未绑定或已失效,删除任务', False)
+ logger.info('原神实时便签', '➤', {'用户': sub.user_id, 'UID': sub.uid}, 'Cookie未绑定或已失效,删除任务',
+ False)
try:
if sub.remind_type == 'group':
await get_bot().send_group_msg(group_id=sub.group_id,
- message=f'[CQ:at,qq={sub.user_id}]你的UID{sub.uid}️未绑定Cookie或已失效,无法继续为你检查实时便签')
+ message=f'[CQ:at,qq={sub.user_id}]你的UID{sub.uid}️未绑定Cookie'
+ f'或已失效,无法继续为你检查实时便签')
else:
await get_bot().send_private_msg(user_id=sub.user_id,
message=f'你的UID{sub.uid}未绑定Cookie或已失效,无法继续为你检查实时便签')
@@ -119,9 +208,11 @@ async def check_note():
result += f'银币达到了{str(data["data"]["current_home_coin"])},'
result_log += '银币'
if result_log:
- logger.info('原神实时便签', '➤', {'用户': sub.user_id, 'UID': sub.uid}, f'{result_log}达到了阈值,发送提醒', True)
+ logger.info('原神实时便签', '➤', {'用户': sub.user_id, 'UID': sub.uid},
+ f'{result_log}达到了阈值,发送提醒', True)
else:
- logger.info('原神实时便签', '➤➤', {'用户': sub.user_id, 'UID': sub.uid}, '检查完成,未达到阈值', True)
+ logger.info('原神实时便签', '➤➤', {'用户': sub.user_id, 'UID': sub.uid}, '检查完成,未达到阈值',
+ True)
if result:
sub.last_remind_time = datetime.datetime.now()
sub.today_remind_num += 1
@@ -134,7 +225,8 @@ async def check_note():
await get_bot().send_private_msg(user_id=sub.user_id,
message=f'⚠️你的UID{sub.uid}{result}记得清理哦⚠️')
except Exception as e:
- logger.info('原神实时便签', '➤➤', {'用户': sub.user_id, 'UID': sub.uid}, f'发送提醒失败,{e}', False)
+ logger.info('原神实时便签', '➤➤', {'用户': sub.user_id, 'UID': sub.uid}, f'发送提醒失败,{e}',
+ False)
# 等待一会再检查下一个,防止检查过快
await asyncio.sleep(random.randint(4, 8))
logger.info('原神实时便签', f'树脂检查完成,共花费{round((time.time() - time_now) / 60, 2)}分钟')
diff --git a/LittlePaimon/utils/api.py b/LittlePaimon/utils/api.py
index adf7c35b..fdce1127 100644
--- a/LittlePaimon/utils/api.py
+++ b/LittlePaimon/utils/api.py
@@ -65,7 +65,7 @@ def random_hex(length: int) -> str:
:param length: 长度
:return: 随机字符串
"""
- result = hex(random.randint(0, 16**length)).replace('0x', '').upper()
+ result = hex(random.randint(0, 16 ** length)).replace('0x', '').upper()
if len(result) < length:
result = '0' * (length - len(result)) + result
return result
@@ -104,6 +104,7 @@ def get_ds(q: str = '', b: dict = None, mhy_bbs_sign: bool = False) -> str:
def get_old_version_ds(mhy_bbs: bool = False) -> str:
"""
生成米游社旧版本headers的ds_token
+ salt对应的版本为2.35.2
"""
if mhy_bbs:
s = 'N50pqm7FSy2AkFz2B3TqtuZMJ5TOl3Ep'
@@ -129,12 +130,34 @@ def mihoyo_headers(cookie, q='', b=None) -> dict:
'Cookie': cookie,
'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) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1',
'x-rpc-client_type': '5',
'Referer': 'https://webstatic.mihoyo.com/',
}
+def mihoyo_verify_verification_headers(cookie: str, request_body: dict):
+ """
+ 生成米游社实时便签验证码headers
+ :param cookie: cookie
+ :param request_body: post请求体
+ :return headers
+ """
+ header = {
+ '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',
+ 'Cookie': cookie,
+ 'x-rpc-device_id': random_hex(32),
+ 'Origin': 'https://webstatic.mihoyo.com',
+ 'DS': get_ds(q="", b=request_body),
+ 'x-rpc-client_type': '5',
+ 'Referer': 'https://webstatic.mihoyo.com',
+ 'x-rpc-app_version': '2.11.1',
+ 'x-rpc-challenge_path': 'https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/dailyNote'
+ }
+ return header
+
+
def mihoyo_sign_headers(cookie: str, extra_headers: Optional[dict] = None) -> dict:
"""
生成米游社签到headers
@@ -144,7 +167,7 @@ def mihoyo_sign_headers(cookie: str, extra_headers: Optional[dict] = None) -> di
"""
header = {
'User_Agent': 'Mozilla/5.0 (Linux; Android 12; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) '
- 'Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36 miHoYoBBS/2.35.2',
+ 'Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36 miHoYoBBS/2.35.2',
'Cookie': cookie,
'x-rpc-device_id': random_hex(32),
'Origin': 'https://webstatic.mihoyo.com',
@@ -152,7 +175,7 @@ def mihoyo_sign_headers(cookie: str, extra_headers: Optional[dict] = None) -> di
'DS': get_old_version_ds(mhy_bbs=True),
'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',
+ '=e202009291139501&utm_source=bbs&utm_medium=mys&utm_campaign=icon',
'x-rpc-app_version': '2.35.2',
}
if extra_headers:
@@ -222,7 +245,7 @@ async def check_retcode(data: dict, cookie_info, user_id: str, uid: str) -> bool
async def get_cookie(
- user_id: str, uid: str, check: bool = True, own: bool = False
+ user_id: str, uid: str, check: bool = True, own: bool = False
) -> Union[None, PrivateCookie, PublicCookie, CookieCache]:
"""
获取可用的cookie
@@ -233,14 +256,14 @@ async def get_cookie(
"""
query = Q(status=1) | Q(status=0) if check else Q(status=1)
if private_cookie := await PrivateCookie.filter(
- Q(Q(query) & Q(user_id=user_id) & Q(uid=uid))
+ Q(Q(query) & Q(user_id=user_id) & Q(uid=uid))
).first():
return private_cookie
elif not own:
if cache_cookie := await CookieCache.get_or_none(uid=uid):
return cache_cookie
elif private_cookie := await PrivateCookie.filter(
- Q(Q(query) & Q(user_id=user_id))
+ Q(Q(query) & Q(user_id=user_id))
).first():
return private_cookie
else:
@@ -270,10 +293,10 @@ async def get_bind_game_info(cookie: str, mys_id: str):
async def get_mihoyo_public_data(
- uid: str,
- user_id: Optional[str],
- mode: Literal['abyss', 'player_card', 'role_detail'],
- schedule_type: Optional[str] = '1',
+ uid: str,
+ user_id: Optional[str],
+ mode: Literal['abyss', 'player_card', 'role_detail'],
+ schedule_type: Optional[str] = '1',
):
server_id = 'cn_qd01' if uid[0] == '5' else 'cn_gf01'
check = True
@@ -319,18 +342,19 @@ async def get_mihoyo_public_data(
async def get_mihoyo_private_data(
- uid: str,
- user_id: Optional[str],
- mode: Literal['role_skill', 'month_info', 'daily_note', 'sign_info', 'sign_action'],
- role_id: Optional[str] = None,
- month: Optional[str] = None,
+ uid: str,
+ user_id: Optional[str],
+ mode: Literal['role_skill', 'month_info', 'daily_note', 'sign_info', 'sign_action'],
+ role_id: Optional[str] = None,
+ month: Optional[str] = None,
+ geetest_challenge: str = None
):
server_id = 'cn_qd01' if uid[0] == '5' else 'cn_gf01'
cookie_info = await get_cookie(user_id, uid, True, True)
if not cookie_info:
return (
- '未绑定私人cookie,绑定方法二选一:\n1.通过米游社扫码绑定:\n请发送指令[原神扫码绑定]\n2.获取cookie的教程:\ndocs.qq.com/doc/DQ3JLWk1vQVllZ2Z1\n获取后,使用[ysb cookie]指令绑定'
- + (f'或前往{config.CookieWeb_url}网页添加绑定' if config.CookieWeb_enable else '')
+ '未绑定私人cookie,绑定方法二选一:\n1.通过米游社扫码绑定:\n请发送指令[原神扫码绑定]\n2.获取cookie的教程:\ndocs.qq.com/doc/DQ3JLWk1vQVllZ2Z1\n获取后,使用[ysb cookie]指令绑定'
+ + (f'或前往{config.CookieWeb_url}网页添加绑定' if config.CookieWeb_enable else '')
)
if mode == 'role_skill':
data = await aiorequests.get(
@@ -351,11 +375,12 @@ async def get_mihoyo_private_data(
params={"month": month, "bind_uid": uid, "bind_region": server_id},
)
elif mode == 'daily_note':
+ headers = mihoyo_headers(q=f'role_id={uid}&server={server_id}', cookie=cookie_info.cookie)
+ if geetest_challenge is not None:
+ headers["x-rpc-challenge"] = geetest_challenge
data = await aiorequests.get(
url=DAILY_NOTE_API,
- headers=mihoyo_headers(
- q=f'role_id={uid}&server={server_id}', cookie=cookie_info.cookie
- ),
+ headers=headers,
params={"server": server_id, "role_id": uid},
)
elif mode == 'sign_info':
@@ -368,7 +393,7 @@ async def get_mihoyo_private_data(
'Referer': 'https://webstatic.mihoyo.com/',
'Cookie': cookie_info.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',
+ 'X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1',
},
params={'act_id': 'e202009291139501', 'region': server_id, 'uid': uid},
)
@@ -392,7 +417,7 @@ async def get_sign_reward_list() -> dict:
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',
+ 'KHTML, like Gecko) miHoYoBBS/2.11.1',
'x-rpc-client_type': '5',
'Referer': 'https://webstatic.mihoyo.com/',
}
@@ -442,7 +467,7 @@ async def get_cookie_token_by_stoken(stoken: str, mys_id: str) -> Optional[str]:
async def get_authkey_by_stoken(
- user_id: str, uid: str
+ user_id: str, uid: str
) -> Tuple[Optional[str], bool, Optional[PrivateCookie]]:
"""
根据stoken获取authkey