initial upload

This commit is contained in:
bietiaop 2024-07-08 13:13:22 +08:00
commit 1c65f10e24
58 changed files with 2533 additions and 0 deletions

246
lib/mysapi.js Normal file
View file

@ -0,0 +1,246 @@
import MysApi from '../../genshin/model/mys/mysApi.js';
import md5 from 'md5';
import _ from 'lodash';
import crypto from 'crypto';
import ZZZApiTool from './mysapi/tool.js';
// const DEVICE_ID = randomString(32).toUpperCase()
const DEVICE_NAME = randomString(_.random(1, 10));
export default class MysZZZApi extends MysApi {
constructor(uid, cookie, option = {}) {
super(uid, cookie, option, true);
this.uid = uid;
this.server = this.getServer();
// this.isSr = true
// this.server = 'hkrpg_cn'
this.apiTool = new ZZZApiTool(uid, this.server);
if (typeof this.cookie != 'string' && this.cookie) {
let ck =
this.cookie[Object.keys(this.cookie).filter(k => this.cookie[k].ck)[0]];
this._device = ck?.device_id || ck?.device;
this.cookie = ck?.ck;
}
if (!this._device) {
this._device = crypto.randomUUID();
}
}
getServer() {
switch (String(this.uid).slice(0, -8)) {
case '1':
case '2':
return 'prod_gf_cn'; // 官服
case '5':
return 'prod_qd_cn'; // B服
case '6':
return 'prod_official_usa'; // 美服
case '7':
return 'prod_official_euro'; // 欧服
case '8':
case '18':
return 'prod_official_asia'; // 亚服
case '9':
return 'prod_official_cht'; // 港澳台服
}
return 'prod_gf_cn';
}
getUrl(type, data = {}) {
data.deviceId = this._device;
let urlMap = this.apiTool.getUrlMap(data);
if (!urlMap[type]) return false;
let {
url,
query = '',
body = '',
noDs = false,
dsSalt = '',
} = urlMap[type];
if (query) url += `?${query}`;
if (body) body = JSON.stringify(body);
let headers = this.getHeaders(query, body);
if (data.deviceFp) {
headers['x-rpc-device_fp'] = data.deviceFp;
// 兼容喵崽
this._device_fp = { data: { device_fp: data.deviceFp } };
}
headers.cookie = this.cookie;
if (this._device) {
headers['x-rpc-device_id'] = this._device;
}
switch (dsSalt) {
case 'web': {
headers.DS = this.getDS2();
break;
}
default:
}
if (type === 'zzzPayAuthKey') {
let extra = {
'x-rpc-app_version': '2.40.1',
'User-Agent': 'okhttp/4.8.0',
'x-rpc-client_type': '5',
Referer: 'https://app.mihoyo.com',
Origin: 'https://webstatic.mihoyo.com',
// Cookie: this.cookies,
// DS: this.getDS2(),
'x-rpc-sys_version': '12',
'x-rpc-channel': 'mihoyo',
'x-rpc-device_id': this._device,
'x-rpc-device_name': DEVICE_NAME,
'x-rpc-device_model': 'Mi 10',
Host: 'api-takumi.mihoyo.com',
};
headers = Object.assign(headers, extra);
} else {
headers.DS = this.getDs(query, body);
}
if (noDs) {
delete headers.DS;
if (this._device) {
body = JSON.parse(body);
body.device_id = this._device;
body = JSON.stringify(body);
}
}
return { url, headers, body };
}
getDs(q = '', b = '') {
let n = '';
if (['prod_gf_cn', 'prod_qd_cn'].includes(this.server)) {
n = 'xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs';
} else if (/official/.test(this.server)) {
n = 'okr4obncj8bw5a65hbnn5oo6ixjc3l9w';
}
let t = Math.round(new Date().getTime() / 1000);
let r = Math.floor(Math.random() * 900000 + 100000);
let DS = md5(`salt=${n}&t=${t}&r=${r}&b=${b}&q=${q}`);
return `${t},${r},${DS}`;
}
getDS2() {
let t = Math.round(new Date().getTime() / 1000);
let r = randomString(6);
let sign = md5(`salt=jEpJb9rRARU2rXDA9qYbZ3selxkuct9a&t=${t}&r=${r}`);
return `${t},${r},${sign}`;
}
getHeaders(query = '', body = '') {
const cn = {
app_version: '2.44.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.44.1',
client_type: '5',
Origin: 'https://webstatic.mihoyo.com',
X_Requested_With: 'com.mihoyo.hyperion',
Referer: 'https://webstatic.mihoyo.com/',
};
const os = {
app_version: '2.55.0',
User_Agent:
'Mozilla/5.0 (Linux; Android 11; J9110 Build/55.2.A.4.332; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.179 Mobile Safari/537.36 miHoYoBBSOversea/2.55.0',
client_type: '2',
Origin: 'https://act.hoyolab.com',
X_Requested_With: 'com.mihoyo.hoyolab',
Referer: 'https://act.hoyolab.com/',
};
let client;
if (/official/.test(this.server)) {
client = os;
} else {
client = cn;
}
return {
'x-rpc-app_version': client.app_version,
'x-rpc-client_type': client.client_type,
// 'x-rpc-page': '3.1.3_#/rpg',
'User-Agent': client.User_Agent,
Referer: client.Referer,
DS: this.getDs(query, body),
Origin: client.Origin,
};
}
/**
* 校验状态码
* @param e 消息e
* @param res 请求返回
* @param type 请求类型 srNote
* @param data 查询请求的数据
* @returns {Promise<*|boolean>}
*/
async checkCode(e, res, type, data = {}) {
if (!res || !e) {
this.e.reply('米游社接口请求失败,暂时无法查询');
return false;
}
this.e = e;
this.e.isSr = true;
res.retcode = Number(res.retcode);
switch (res.retcode) {
case 0:
break;
case 10035:
case 1034: {
let handler = this.e.runtime?.handler || {};
// 如果有注册的mys.req.err调用
if (handler.has('mys.req.err')) {
logger.mark(
`[米游社zzz查询失败][uid:${this.uid}][qq:${this.userId}] 遇到验证码,尝试调用 Handler mys.req.err`
);
res =
(await handler.call('mys.req.err', this.e, {
mysApi: this,
type,
res,
data,
mysInfo: this,
})) || res;
}
if (!res || res?.retcode === 1034 || res?.retcode === 10035) {
logger.mark(
`[米游社zzz查询失败][uid:${this.uid}][qq:${this.userId}] 遇到验证码`
);
this.e.reply('米游社zzz查询遇到验证码请稍后再试');
}
break;
}
default:
if (/(登录|login)/i.test(res.message)) {
logger.mark(`[ck失效][uid:${this.uid}]`);
this.e.reply(`UID:${this.uid}米游社cookie已失效`);
} else {
this.e.reply(
`米游社接口报错,暂时无法查询:${res.message || 'error'}`
);
}
break;
}
if (res.retcode !== 0) {
logger.mark(
`[米游社zzz接口报错]${JSON.stringify(res)}uid${this.uid}`
);
}
return res;
}
}
export function randomString(length) {
let randomStr = '';
for (let i = 0; i < length; i++) {
randomStr += _.sample('abcdefghijklmnopqrstuvwxyz0123456789');
}
return randomStr;
}
export function generateSeed(length = 16) {
const characters = '0123456789abcdef';
let result = '';
for (let i = 0; i < length; i++) {
result += characters[Math.floor(Math.random() * characters.length)];
}
return result;
}