Miao-Yunzai/plugins/genshin/model/mys/mysApi.js

242 lines
6.6 KiB
JavaScript
Raw Permalink Normal View History

2023-03-04 14:30:13 +08:00
import md5 from 'md5'
import fetch from 'node-fetch'
import cfg from '../../../../lib/config/config.js'
import apiTool from './apiTool.js'
2023-05-31 03:19:27 +08:00
2023-03-04 14:30:13 +08:00
let HttpsProxyAgent = ''
export default class MysApi {
/**
* @param uid 游戏uid
* @param cookie 米游社cookie
* @param option 其他参数
* @param option.log 是否显示日志
* @param isSr 是否星铁
* @param device 设备device_id
2023-03-04 14:30:13 +08:00
*/
2024-02-04 09:02:39 +08:00
constructor(uid, cookie, option = {}, isSr = false, device = '') {
2023-03-04 14:30:13 +08:00
this.uid = uid
this.cookie = cookie
this.isSr = isSr
2023-03-04 14:30:13 +08:00
this.server = this.getServer()
this.apiTool = new apiTool(uid, this.server, isSr)
2023-03-04 14:30:13 +08:00
/** 5分钟缓存 */
this.cacheCd = 300
2023-10-07 19:33:25 +08:00
this._device = device
2023-03-04 14:30:13 +08:00
this.option = {
log: true,
...option
}
}
2023-05-31 03:19:27 +08:00
/* eslint-disable quotes */
2024-02-04 09:02:39 +08:00
get device() {
2023-05-31 03:19:27 +08:00
if (!this._device) this._device = `Yz-${md5(this.uid).substring(0, 5)}`
return this._device
}
2024-02-04 09:02:39 +08:00
getUrl(type, data = {}) {
2023-05-31 03:19:27 +08:00
let urlMap = this.apiTool.getUrlMap({ ...data, deviceId: this.device })
2023-03-04 14:30:13 +08:00
if (!urlMap[type]) return false
let { url, query = '', body = '' } = urlMap[type]
2023-03-04 14:30:13 +08:00
if (query) url += `?${query}`
if (body) body = JSON.stringify(body)
let headers = this.getHeaders(query, body)
2023-03-04 14:30:13 +08:00
return { url, headers, body }
}
2024-02-04 09:02:39 +08:00
getServer() {
2024-02-06 07:19:34 +08:00
switch (String(this.uid).slice(0, -8)) {
2023-03-04 14:30:13 +08:00
case '1':
case '2':
return this.isSr ? 'prod_gf_cn' : 'cn_gf01' // 官服
2023-03-04 14:30:13 +08:00
case '5':
return this.isSr ? 'prod_qd_cn' : 'cn_qd01' // B服
2023-03-04 14:30:13 +08:00
case '6':
return this.isSr ? 'prod_official_usa' : 'os_usa' // 美服
2023-03-04 14:30:13 +08:00
case '7':
return this.isSr ? 'prod_official_euro' : 'os_euro' // 欧服
2023-03-04 14:30:13 +08:00
case '8':
2024-02-04 09:02:39 +08:00
case '18':
return this.isSr ? 'prod_official_asia' : 'os_asia' // 亚服
2023-03-04 14:30:13 +08:00
case '9':
return this.isSr ? 'prod_official_cht' : 'os_cht' // 港澳台服
2023-03-04 14:30:13 +08:00
}
return this.isSr ? 'prod_gf_cn' : 'cn_gf01'
2023-03-04 14:30:13 +08:00
}
2024-02-04 09:02:39 +08:00
async getData(type, data = {}, cached = false) {
2024-03-26 16:33:56 +08:00
if (!this._device_fp && !data?.Getfp && !data?.headers?.['x-rpc-device_fp']) {
this._device_fp = await this.getData('getFp', {
seed_id: this.generateSeed(16),
Getfp: true
})
}
if (type === 'getFp' && !data?.Getfp) return this._device_fp
2023-03-04 14:30:13 +08:00
let { url, headers, body } = this.getUrl(type, data)
if (!url) return false
let cacheKey = this.cacheKey(type, data)
let cahce = await redis.get(cacheKey)
if (cahce) return JSON.parse(cahce)
headers.Cookie = this.cookie
if (data.headers) {
headers = { ...headers, ...data.headers }
}
2024-03-27 06:43:13 +08:00
if (type !== 'getFp' && !headers['x-rpc-device_fp'] && this._device_fp.data?.device_fp) {
2024-03-26 16:33:56 +08:00
headers['x-rpc-device_fp'] = this._device_fp.data.device_fp
}
2023-03-04 14:30:13 +08:00
let param = {
headers,
agent: await this.getAgent(),
timeout: 10000
}
if (body) {
param.method = 'post'
param.body = body
} else {
param.method = 'get'
}
let response = {}
let start = Date.now()
try {
response = await fetch(url, param)
} catch (error) {
logger.error(error.toString())
return false
}
if (!response.ok) {
logger.error(`[米游社接口][${type}][${this.uid}] ${response.status} ${response.statusText}`)
return false
}
if (this.option.log) {
logger.mark(`[米游社接口][${type}][${this.uid}] ${Date.now() - start}ms`)
}
const res = await response.json()
if (!res) {
logger.mark('mys接口没有返回')
return false
}
res.api = type
if (cached) this.cache(res, cacheKey)
return res
}
2024-02-04 09:02:39 +08:00
getHeaders(query = '', body = '') {
2023-03-04 14:30:13 +08:00
const cn = {
app_version: '2.40.1',
User_Agent: `Mozilla/5.0 (Linux; Android 12; ${this.device}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.73 Mobile Safari/537.36 miHoYoBBS/2.40.1`,
2024-05-03 15:41:18 +08:00
client_type: '5',
2023-03-04 14:30:13 +08:00
Origin: 'https://webstatic.mihoyo.com',
X_Requested_With: 'com.mihoyo.hyperion',
Referer: 'https://webstatic.mihoyo.com/'
2023-03-04 14:30:13 +08:00
}
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',
2023-03-04 14:30:13 +08:00
client_type: '2',
Origin: 'https://act.hoyolab.com',
2023-03-04 14:30:13 +08:00
X_Requested_With: 'com.mihoyo.hoyolab',
Referer: 'https://act.hoyolab.com/'
2023-03-04 14:30:13 +08:00
}
let client
2024-05-03 15:41:18 +08:00
if (/os_|official/.test(this.server)) {
2023-03-04 14:30:13 +08:00
client = os
} else {
client = cn
}
return {
'x-rpc-app_version': client.app_version,
'x-rpc-client_type': client.client_type,
'User-Agent': client.User_Agent,
Referer: client.Referer,
DS: this.getDs(query, body)
}
}
2024-02-04 09:02:39 +08:00
getDs(q = '', b = '') {
2023-03-04 14:30:13 +08:00
let n = ''
2023-05-31 03:19:27 +08:00
if (['cn_gf01', 'cn_qd01', 'prod_gf_cn', 'prod_qd_cn'].includes(this.server)) {
2023-03-04 14:30:13 +08:00
n = 'xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs'
} else if (/os_|official/.test(this.server)) {
2023-03-04 14:30:13 +08:00
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}`
}
2024-02-04 09:02:39 +08:00
getGuid() {
function S4() {
2023-03-04 14:30:13 +08:00
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
}
return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
}
2024-02-04 09:02:39 +08:00
cacheKey(type, data) {
2023-03-04 14:30:13 +08:00
return 'Yz:genshin:mys:cache:' + md5(this.uid + type + JSON.stringify(data))
}
2024-02-04 09:02:39 +08:00
async cache(res, cacheKey) {
2023-03-04 14:30:13 +08:00
if (!res || res.retcode !== 0) return
redis.setEx(cacheKey, this.cacheCd, JSON.stringify(res))
}
2024-02-04 09:02:39 +08:00
async getAgent() {
2023-03-04 14:30:13 +08:00
let proxyAddress = cfg.bot.proxyAddress
if (!proxyAddress) return null
if (proxyAddress === 'http://0.0.0.0:0') return null
2024-05-03 15:41:18 +08:00
if (!/os_|official/.test(this.server)) return null
2023-03-04 14:30:13 +08:00
if (HttpsProxyAgent === '') {
HttpsProxyAgent = await import('https-proxy-agent').catch((err) => {
logger.error(err)
})
HttpsProxyAgent = HttpsProxyAgent ? HttpsProxyAgent.HttpsProxyAgent : undefined
2023-03-04 14:30:13 +08:00
}
if (HttpsProxyAgent) {
return new HttpsProxyAgent(proxyAddress)
}
return null
}
2023-10-07 19:33:25 +08:00
2024-02-04 09:02:39 +08:00
generateSeed(length = 16) {
2023-10-07 19:33:25 +08:00
const characters = '0123456789abcdef'
let result = ''
for (let i = 0; i < length; i++) {
result += characters[Math.floor(Math.random() * characters.length)]
}
return result
}
2024-05-25 00:58:51 +08:00
}
export function randomRange() {
let randomStr = ''
let charStr = 'abcdef0123456789'
for (let i = 0; i < 64; i++) {
let index = Math.round(Math.random() * (charStr.length - 1))
randomStr += charStr.substring(index, index + 1)
}
return randomStr
2024-05-03 15:41:18 +08:00
}