⚗️ 测试

This commit is contained in:
KimigaiiWuyi 2023-10-26 05:34:34 +08:00
parent ebf10976d4
commit 6ac4f8a66a
4 changed files with 125 additions and 150 deletions

View File

@ -15,7 +15,9 @@ class GsClient:
self = GsClient() self = GsClient()
cls.ws_url = f'ws://{IP}:{PORT}/ws/Nonebot' cls.ws_url = f'ws://{IP}:{PORT}/ws/Nonebot'
print(f'连接至WS链接{self.ws_url}...') print(f'连接至WS链接{self.ws_url}...')
cls.ws = await websockets.client.connect(cls.ws_url, max_size=2**25) cls.ws = await websockets.client.connect(
cls.ws_url, max_size=2**25, open_timeout=30
)
print('已成功链接!') print('已成功链接!')
return self return self
@ -24,7 +26,10 @@ class GsClient:
async for message in self.ws: async for message in self.ws:
print(msgjson.decode(message, type=MessageSend)) print(msgjson.decode(message, type=MessageSend))
except ConnectionClosedError: except ConnectionClosedError:
print('断开链接...') print('断开连接...等待5秒尝试重连中...')
await asyncio.sleep(5)
client = await self.async_connect()
await client.start()
async def _input(self): async def _input(self):
return await asyncio.get_event_loop().run_in_executor( return await asyncio.get_event_loop().run_in_executor(
@ -45,9 +50,9 @@ class GsClient:
content = [Message(type='text', data=intent)] content = [Message(type='text', data=intent)]
msg = MessageReceive( msg = MessageReceive(
bot_id='Nonebot222', bot_id='Nonebot222',
user_type='group', user_type='direct',
user_pm=1, user_pm=1,
group_id='9999', group_id=None,
user_id='511', user_id='511',
content=content, content=content,
) )

View File

@ -136,5 +136,7 @@ RECEIVE_URL = f'{DRAW_BASE_URL}/post_my_draw'
BS_INDEX_URL = f'{DRAW_BASE_URL}/index' BS_INDEX_URL = f'{DRAW_BASE_URL}/index'
GET_FP_URL = 'https://public-data-api.mihoyo.com/device-fp/api/getFp' GET_FP_URL = 'https://public-data-api.mihoyo.com/device-fp/api/getFp'
DEVICE_LOGIN = f'{NEW_BBS_URL}/apihub/api/deviceLogin'
SAVE_DEVICE = f'{NEW_BBS_URL}/apihub/api/saveDevice'
_API = locals() _API = locals()

View File

@ -15,7 +15,6 @@ from aiohttp import TCPConnector, ClientSession, ContentTypeError
from gsuid_core.logger import logger from gsuid_core.logger import logger
from gsuid_core.utils.database.api import DBSqla from gsuid_core.utils.database.api import DBSqla
from gsuid_core.utils.database.models import GsUser
from gsuid_core.utils.plugins_config.gs_config import core_plugins_config from gsuid_core.utils.plugins_config.gs_config import core_plugins_config
from .api import _API from .api import _API
@ -75,12 +74,14 @@ class BaseMysApi:
_HEADER = { _HEADER = {
'x-rpc-app_version': mysVersion, 'x-rpc-app_version': mysVersion,
'User-Agent': ( 'User-Agent': (
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) ' 'Mozilla/5.0 (Linux; Android 13; PHK110 Build/SKQ1.221119.001; wv)'
f'AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/{mysVersion}' 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/'
f'118.0.0.0 Mobile Safari/537.36 miHoYoBBS/{mysVersion}'
), ),
'x-rpc-client_type': '5', 'x-rpc-client_type': '5',
'Referer': 'https://webstatic.mihoyo.com/', 'Referer': 'https://webstatic.mihoyo.com/',
'Origin': 'https://webstatic.mihoyo.com', # 'Origin': 'https://webstatic.mihoyo.com/',
# 'X-Requested-With': 'com.mihoyo.hyperion',
} }
_HEADER_OS = { _HEADER_OS = {
'x-rpc-app_version': '1.5.0', 'x-rpc-app_version': '1.5.0',
@ -122,34 +123,45 @@ class BaseMysApi:
... ...
def get_device_id(self) -> str: def get_device_id(self) -> str:
device_id = str(uuid.uuid4()).upper() device_id = str(uuid.uuid4())
return device_id return device_id
def generate_fp(self, length: int = 13) -> str:
char = digits + "abcdef"
return ''.join(random.choices(char, k=length))
def generate_seed(self, length: int): def generate_seed(self, length: int):
characters = '0123456789abcdef' characters = '0123456789abcdef'
result = ''.join(random.choices(characters, k=length)) result = ''.join(random.choices(characters, k=length))
return result return result
async def generate_fp_by_uid(self, uid: str) -> str: def generate_ID(self, length: int = 64):
seed_id = self.generate_seed(16) characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
seed_time = str(int(time.time() * 1000)) result = ''.join(random.choices(characters, k=length))
ext_fields = f'{{"userAgent":"{self._HEADER["User-Agent"]}",\ return result
"browserScreenSize":281520,"maxTouchPoints":5,\
"isTouchSupported":true,"browserLanguage":"zh-CN","browserPlat":"iPhone",\ def generate_model_name(self):
"browserTimeZone":"Asia/Shanghai","webGlRender":"Apple GPU",\ return self.generate_ID(6)
"webGlVendor":"Apple Inc.",\
"numOfPlugins":0,"listOfPlugins":"unknown","screenRatio":3,"deviceMemory":"unknown",\ def get_seed(self):
"hardwareConcurrency":"4","cpuClass":"unknown","ifNotTrack":"unknown","ifAdBlock":0,\ return self.get_device_id(), str(int(time.time() * 1000))
"hasLiedResolution":1,"hasLiedOs":0,"hasLiedBrowser":0}}'
async def generate_fp_by_uid(
self, uid: str, seed_id: str, seed_time: str, model_name: str
) -> str:
device_id = await self.get_user_device_id(uid)
ext_fields = f'''{{\"cpuType\":\"arm64-v8a\",\"romCapacity\":\"512\",\"productName\":\"{model_name}\",\"romRemain\":\"422\",\"manufacturer\":\"XiaoMi\",\"appMemory\":\"512\",\"hostname\":\"dg02-pool03-kvm87\",\"screenSize\":\"1240x2662\",\"osVersion\":\"13\",\"aaid\":\"{self.generate_ID()}\",\"vendor\":\"中国联通\",\"accelerometer\":\"1.4883357x7.1712894x6.2847486\",\"buildTags\":\"release-keys\",\"model\":\"{model_name}\",\"brand\":\"XiaoMi\",\"oaid\":\"6C47BC55BBC443F49B603129AFCD621E6f70bfc8a663a364e224fe59c248b471\",\"hardware\":\"qcom\",\"deviceType\":\"OP5913L1\",\"devId\":\"REL\",\"serialNumber\":\"unknown\",\"buildTime\":\"1687848011000\",\"buildUser\":\"root\",\"ramCapacity\":\"469679\",\"magnetometer\":\"20.081251x-27.487501x2.1937501\",\"display\":\"{model_name}_13.1.0.181(CN01)\",\"ramRemain\":\"215344\",\"deviceInfo\":\"XiaoMi\\\/{model_name}\\\/OP5913L1:13\\\/SKQ1.221119.001\\\/T.118e6c7-5aa23-73911:user\\\/release-keys\",\"gyroscope\":\"0.030226856x0.014647375x0.010652636\",\"vaid\":\"{self.generate_ID()}\",\"buildType\":\"user\",\"sdkVersion\":\"33\",\"board\":\"taro\"}}''' # noqa
body = { body = {
'seed_id': seed_id, 'device_id': self.generate_seed(16),
'device_id': await self.get_user_device_id(uid), 'seed_id': seed_id, # uuid4
'platform': '5', 'platform': '2',
'seed_time': seed_time, 'seed_time': seed_time,
'ext_fields': ext_fields, 'ext_fields': ext_fields,
'app_name': 'account_cn', 'app_name': 'bbs_cn',
'device_fp': '38d7ee834d1e9', 'bbs_device_id': device_id,
'device_fp': self.generate_fp(),
} }
print(body)
HEADER = copy.deepcopy(self._HEADER) HEADER = copy.deepcopy(self._HEADER)
res = await self._mys_request( res = await self._mys_request(
url=self.MAPI['GET_FP_URL'], url=self.MAPI['GET_FP_URL'],
@ -166,6 +178,40 @@ class BaseMysApi:
else: else:
return res["data"]["device_fp"] return res["data"]["device_fp"]
async def device_login_and_save(
self, device_id: str, device_fp: str, model_name: str, cookie: str
):
body = {
"app_version": self.mysVersion,
"device_id": device_id,
"device_name": f"XiaoMi{model_name}",
"os_version": "33",
"platform": "Android",
"registration_id": self.generate_seed(19),
}
HEADER = copy.deepcopy(self._HEADER)
HEADER['x-rpc-device_id'] = device_id
HEADER['x-rpc-device_fp'] = device_fp
HEADER['x-rpc-device_name'] = f"XiaoMi{model_name}"
HEADER['x-rpc-device_model'] = model_name
HEADER['DS'] = generate_passport_ds('', body)
HEADER['cookie'] = cookie
await self._mys_request(
url=self.MAPI['DEVICE_LOGIN'],
method='POST',
header=HEADER,
data=body,
)
await self._mys_request(
url=self.MAPI['SAVE_DEVICE'],
method='POST',
header=HEADER,
data=body,
)
async def simple_mys_req( async def simple_mys_req(
self, self,
URL: str, URL: str,
@ -260,9 +306,12 @@ class BaseMysApi:
uid = None uid = None
if params and 'role_id' in params: if params and 'role_id' in params:
uid = params['role_id'] uid = params['role_id']
header['x-rpc-device_id'] = await self.get_user_device_id(uid) device_id = await self.get_user_device_id(uid)
header['x-rpc-device_fp'] = await self.get_user_fp(uid) header['x-rpc-device_fp'] = await self.get_user_fp(uid)
if device_id is not None:
header['x-rpc-device_id'] = device_id
print(header)
for _ in range(2): for _ in range(2):
async with client.request( async with client.request(
method, method,
@ -278,7 +327,9 @@ class BaseMysApi:
except ContentTypeError: except ContentTypeError:
_raw_data = await resp.text() _raw_data = await resp.text()
raw_data = {'retcode': -999, 'data': _raw_data} raw_data = {'retcode': -999, 'data': _raw_data}
logger.debug(raw_data) logger.debug(raw_data)
# 判断retcode # 判断retcode
if 'retcode' in raw_data: if 'retcode' in raw_data:
retcode: int = raw_data['retcode'] retcode: int = raw_data['retcode']
@ -289,44 +340,55 @@ class BaseMysApi:
# 针对1034做特殊处理 # 针对1034做特殊处理
if retcode == 1034: if retcode == 1034:
if ( if uid:
not core_plugins_config.get_config('MysPass').data '''
or _ == 1 ck = header['Cookie']
): if 'DEVICEFP_SEED_ID' not in ck:
if uid and self.is_sr: header['Cookie'] = (
new_fp = await self.generate_fp_by_uid(uid) 'mi18nLang=zh-cn;_MHYUUID='
await GsUser.update_data_by_uid_without_bot_id( 'b6261233-05a8-45fc-b7a1-55e152b52ae4'
uid, fp=new_fp f'DEVICEFP_SEED_ID={seed_id};'
f'DEVICEFP_SEED_TIME={seed_time};'
f'{ck};DEVICE_FP={new_fp}'
) )
header['x-rpc-device_fp'] = new_fp '''
return retcode
else:
header['x-rpc-challenge_game'] = ( header['x-rpc-challenge_game'] = (
'6' if self.is_sr else '2' '6' if self.is_sr else '2'
) )
header['x-rpc-page'] = ( header['x-rpc-page'] = (
'3.1.3_#/rpg' if self.is_sr else '3.1.3_#/ys' 'v1.4.1-rpg_#/rpg'
if self.is_sr
else 'v4.1.5-ys_#ys'
) )
header['x-rpc-tool-verison'] = (
'v1.4.1-rpg' if self.is_sr else 'v4.1.5-ys'
)
if core_plugins_config.get_config('MysPass').data:
pass_header = copy.deepcopy(header) pass_header = copy.deepcopy(header)
ch = await self._upass(pass_header) ch = await self._upass(pass_header)
if ch == '': if ch == '':
return 114514 return 114514
else: else:
header['x-rpc-challenge'] = ch header['x-rpc-challenge'] = ch
if 'DS' in header:
if isinstance(params, Dict): if 'DS' in header:
q = '&'.join( if isinstance(params, Dict):
[ q = '&'.join(
f'{k}={v}' [
for k, v in sorted( f'{k}={v}'
params.items(), for k, v in sorted(
key=lambda x: x[0], params.items(),
) key=lambda x: x[0],
] )
) ]
else: )
q = '' else:
header['DS'] = get_ds_token(q, data) q = ''
header['DS'] = get_ds_token(q, data)
logger.debug(header)
elif retcode != 0: elif retcode != 0:
return retcode return retcode
else: else:
@ -334,103 +396,6 @@ class BaseMysApi:
else: else:
return -999 return -999
'''
async def _mys_request(
self,
url: str,
method: Literal['GET', 'POST'] = 'GET',
header: Dict[str, Any] = _HEADER,
params: Optional[Dict[str, Any]] = None,
data: Optional[Dict[str, Any]] = None,
use_proxy: Optional[bool] = False,
) -> Union[Dict, int]:
import types
import inspect
async with ClientSession(
connector=TCPConnector(verify_ssl=ssl_verify)
) as client:
if 'Cookie' in header:
if header['Cookie'] in self.chs:
header['x-rpc-challenge'] = self.chs.pop(header["Cookie"])
async with client.request(
method,
url=url,
headers=header,
params=params,
json=data,
proxy=self.proxy_url if use_proxy else None,
timeout=300,
) as resp:
try:
raw_data = await resp.json()
except ContentTypeError:
_raw_data = await resp.text()
raw_data = {'retcode': -999, 'data': _raw_data}
logger.debug(raw_data)
# 判断retcode
if 'retcode' in raw_data:
retcode: int = raw_data['retcode']
elif 'code' in raw_data:
retcode: int = raw_data['code']
else:
retcode = 0
# 针对1034做特殊处理
if retcode == 1034:
try:
# 获取ch
ch = await self._upass(header)
# 记录ck -> ch的对照表
if "Cookie" in header:
self.chs[header["Cookie"]] = ch
# 获取当前的栈帧
curframe = inspect.currentframe()
# 确保栈帧存在
assert curframe
# 获取调用者的栈帧
calframe = curframe.f_back
# 确保调用者的栈帧存在
assert calframe
# 获取调用者的函数名
caller_name = calframe.f_code.co_name
# 获取调用者函数的局部变量字典
caller_args = inspect.getargvalues(calframe).locals
# 获取调用者的参数列表
caller_args2 = inspect.getargvalues(calframe).args
# # 生成一个字典键为调用者的参数名值为对应的局部变量值如果不存在则为None
caller_args3 = {
k: caller_args.get(k, None) for k in caller_args2
}
if caller_name != '_mys_req_get':
return await types.FunctionType(
calframe.f_code, globals()
)(**caller_args3)
else:
curframe = calframe
calframe = curframe.f_back
assert calframe
caller_name = calframe.f_code.co_name
caller_args = inspect.getargvalues(calframe).locals
caller_args2 = inspect.getargvalues(calframe).args
caller_args3 = {
k: caller_args.get(k, None)
for k in caller_args2
}
return await types.FunctionType(
calframe.f_code, globals()
)(**caller_args3)
except Exception as e:
logger.error(e)
traceback.print_exc()
return -999
elif retcode != 0:
return retcode
return raw_data
'''
class MysApi(BaseMysApi): class MysApi(BaseMysApi):
async def _pass( async def _pass(

View File

@ -234,7 +234,10 @@ async def _deal_ck(bot_id: str, mes: str, user_id: str) -> str:
uid = '0' uid = '0'
device_id = mys_api.get_device_id() device_id = mys_api.get_device_id()
fp = await mys_api.generate_fp_by_uid(uid) seed_id, seed_time = mys_api.get_seed()
model_name = mys_api.generate_model_name()
fp = await mys_api.generate_fp_by_uid(uid, seed_id, seed_time, model_name)
await mys_api.device_login_and_save(device_id, fp, model_name, app_cookie)
# 往数据库添加内容 # 往数据库添加内容
if uid_bind and await GsUser.user_exists(uid_bind): if uid_bind and await GsUser.user_exists(uid_bind):