mirror of
https://github.com/ZZZure/ZZZ-Plugin.git
synced 2025-12-15 12:47:48 +00:00
242 lines
6.8 KiB
JavaScript
242 lines
6.8 KiB
JavaScript
import md5 from 'md5';
|
||
import _ from 'lodash';
|
||
import crypto from 'crypto';
|
||
import ZZZApiTool from './mysapi/tool.js';
|
||
import MysApi from '../../genshin/model/mys/mysApi.js';
|
||
|
||
// const DEVICE_ID = randomString(32).toUpperCase()
|
||
const DEVICE_NAME = randomString(_.random(1, 10));
|
||
const game_region = [
|
||
'prod_gf_cn',
|
||
'prod_gf_cn',
|
||
'prod_gf_us',
|
||
'prod_gf_eu',
|
||
'prod_gf_jp',
|
||
'prod_gf_sg',
|
||
];
|
||
export default class MysZZZApi extends MysApi {
|
||
constructor(uid, cookie, option = {}) {
|
||
super(uid, cookie, option, true);
|
||
this.uid = uid;
|
||
this.server = this.getServer();
|
||
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() {
|
||
const _uid = this.uid.toString();
|
||
if (_uid.length < 10) {
|
||
return game_region[0]; // 官服
|
||
}
|
||
switch (_uid.slice(0, -8)) {
|
||
case '10':
|
||
return game_region[2]; // 美服
|
||
case '15':
|
||
return game_region[3]; // 欧服
|
||
case '13':
|
||
return game_region[4]; // 亚服
|
||
case '17':
|
||
return game_region[5]; // 港澳台服
|
||
}
|
||
}
|
||
|
||
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 === 'zzzAuthKey') {
|
||
let extra = {
|
||
DS: this.getDS2(),
|
||
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 (/prod_gf_/.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=BIPaooxbWZW02fGHZL1If26mYCljPgst&t=${t}&r=${r}`);
|
||
return `${t},${r},${sign}`;
|
||
}
|
||
|
||
getHeaders(query = '', body = '') {
|
||
const cn = {
|
||
app_version: '2.63.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.63.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,
|
||
'User-Agent': 'okhttp/4.8.0',
|
||
'x-rpc-sys_version': '12',
|
||
'x-rpc-client_type': '2',
|
||
'x-rpc-channel': 'mihoyo',
|
||
'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;
|
||
}
|