2
0
mirror of https://github.com/ctrlcvs/xiaoyao-cvs-plugin.git synced 2024-12-23 11:40:51 +08:00
xiaoyao-cvs-plugin/model/mys/mihoyoApi.js
2023-01-14 07:27:26 +08:00

541 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import utils from './utils.js';
import md5 from 'md5';
import _ from 'lodash';
import fs from "fs";
import YAML from 'yaml'
import {
Data
} from "../../components/index.js";
import gsCfg from '../gsCfg.js'
import {
isV3
} from '../../components/Changelog.js';
import fetch from "node-fetch"
import mys from "./mysTool.js"
import crypto from "crypto";
const _path = process.cwd();
const DEVICE_ID = utils.randomString(32).toUpperCase();
const DEVICE_NAME = utils.randomString(_.random(1, 10));
const yamlDataUrl = `${_path}/plugins/xiaoyao-cvs-plugin/data/yaml`;
let HttpsProxyAgent = ''
// 米游社的版块
export default class miHoYoApi {
constructor(e) {
if (e) {
this.e = e
this.cookie = e.cookie
this.userId = String(e.user_id)
this.yuntoken = e.yuntoken
this.devId = e.devId
this.isOs = false;
if (this.e?.uid) {
this.isOs = this.e?.uid[0] * 1 > 5
}
this.apiMap = {
apiWeb: mys.web_api,
saltweb: mys.saltWeb,
saltSign: mys.salt
}
if (this.isOs) {
this.apiMap = {
apiWeb: mys.os_web_api,
saltweb: mys.saltWeb, //os websalt待定中
saltSign: mys.salt
}
}
// //初始化配置文件
let data = this.getStoken(this.e.user_id);
if (data) {
this.cookies = `stuid=${data.stuid};stoken=${data.stoken};ltoken=${data.ltoken};`;
if (data?.mid) {
this.cookies = `stuid=${data.stuid};stoken=${data.stoken};mid=${data.mid};`;
}
this.e.cookies = this.cookies
}
}
Data.createDir("", yamlDataUrl, false);
}
getBody(name) {
for (let item in mys.boards) {
if (mys.boards[item].name === name) {
return mys.boards[item]
}
}
}
async getData(type, data = {}) {
let gameBody = this.getBody(data.name);
let {
url,
headers,
body
} = this.getUrl(type, gameBody, data)
if (!url) return false
if (data.headers) {
headers = {
...headers,
...data.headers
}
delete data.headers
}
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) {
Bot.logger.error(`[接口][${type}][${this.e.uid}] ${response.status} ${response.statusText}`)
return false
}
let res = await response.text();
// Bot.logger.mark(`[接口][${type}][${this.e.uid}] ${Date.now() - start}ms\n${res}`)
if (res.startsWith('(')) {
res = JSON.parse((res).replace(/\(|\)/g, ""))
} else {
res = JSON.parse(res)
}
if (!res) {
Bot.logger.mark('mys接口没有返回')
return false
}
if (res.retcode !== 0) {
Bot.logger.debug(`[米游社接口][请求参数] ${url} ${JSON.stringify(param)}`)
}
res.api = type
if (type == "loginByPassword") {
res.aigis_data = JSON.parse(response.headers.get("x-rpc-aigis"))
}
return res
}
getUrl(type, board, data) {
let urlMap = {
userGameInfo: { //通用查询
url: `${this.apiMap.apiWeb}/binding/api/getUserGameRolesByCookie`,
query: `game_biz=${this.isOs ? board?.osbiz : board?.biz}`,
types: 'sign'
},
isSign: board?.signUrl(data, "isSign", this.apiMap.apiWeb) || {},
sign: board?.signUrl(data, "sign", this.apiMap.apiWeb) || {},
home: board?.signUrl(data, "home", this.apiMap.apiWeb) || {},
//bbs接口 hoyolab那边不是很需要 这边不进行优化处理
bbsisSign: { //bbs 签到 (状态查询 米游币查询)
url: `${mys.bbs_api}/apihub/sapi/getUserMissionsState`,
types: 'bbs'
},
bbsSign: { //bbs讨论区签到
url: `${mys.bbs_api}/apihub/app/api/signIn`,
body: {
gids: data.forumId * 1
},
sign: true,
types: 'bbs'
},
bbsGetCaptcha: {
url: `${mys.bbs_api}/misc/api/createVerification`,
query: `is_high=false`,
types: 'bbs'
},
bbsValidate: {
url: `https://apiv6.geetest.com/ajax.php`,
query: `gt=${data.gt}&challenge=${data.challenge}&lang=zh-cn&pt=3&client_type=web_mobile`,
},
bbsCaptchaVerify: {
url: `${mys.bbs_api}/misc/api/verifyVerification`,
body: {
"geetest_challenge": data.challenge, //challenge,
"geetest_validate": data.validate,
"geetest_seccode": `${data.validate}|jordan`
},
types: 'bbs'
},
geeType: {
url: `https://api.geetest.com/gettype.php`,
query: `gt=${data.gt}`
},
//待定接口 用于获取用户米游社顶部的模块栏
bbs_Businesses_url: {
url: `${mys.bbs_api}/user/api/getUserBusinesses`,
query: `uid={}` //????
},
bbsPostList: { //bbs讨论区签到
url: `${mys.bbs_api}/post/api/getForumPostList`,
query: `forum_id=${data.forumId}&is_good=false&is_hot=false&page_size=20&sort_type=1`,
types: 'bbs'
},
bbsPostFull: { //bbs讨论区签到
url: `${mys.bbs_api}/post/api/getPostFull`,
query: `post_id=${data.postId}`,
types: 'bbs'
},
bbsShareConf: { //bbs讨论区签到
url: `${mys.bbs_api}/apihub/api/getShareConf`,
query: `entity_id=${data.postId}&entity_type=1`,
types: 'bbs'
},
bbsVotePost: { //bbs讨论区签到
url: `${mys.bbs_api}/apihub/sapi/upvotePost`,
body: {
"post_id": data.postId,
"is_cancel": false
},
types: 'bbs'
},
bbsGetCookie: {
url: `${this.apiMap.apiWeb}/auth/api/getCookieAccountInfoBySToken`,
query: `game_biz=hk4e_cn&${data.cookies}`,
types: ''
},
bbsStoken: {
url: `${this.apiMap.apiWeb}/auth/api/getMultiTokenByLoginTicket`,
query: `login_ticket=${data.loginTicket}&token_types=3&uid=${data.loginUid}`,
types: 'stoken'
},
//接口来源于外网扒来的 接口目前暂时免费后续看token是否收费祝你生活愉快
validate: {
url: `http://api.fuckmys.tk/geetest`,
query: `token=fuckmys&gt=${data.gt}&challenge=${data.challenge}`
},
cloudLogin: {
url: `${mys.cloud_api}/hk4e_cg_cn/gamer/api/login`,
types: 'cloud'
},
cloudReward: {
url: `${mys.cloud_api}/hk4e_cg_cn/gamer/api/listNotifications`,
query: `status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true`,
types: 'cloud'
},
cloudGamer: {
url: `${mys.cloud_api}/hk4e_cg_cn/gamer/api/ackNotification`,
body: {
id: data.reward_id
},
types: 'cloud'
},
cloudGet: {
url: `${mys.cloud_api}/hk4e_cg_cn/wallet/wallet/get`,
types: 'cloud'
},
authKey: {
///account/auth/api/genAuthKey
url: `${this.apiMap.apiWeb}/binding/api/genAuthKey`,
body: {
'auth_appid': 'webview_gacha',
'game_biz': this.isOs ? 'hk4e_global' : 'hk4e_cn',
'game_uid': this.e.uid * 1,
'region': this.e.region,
},
types: 'authKey'
},
getLtoken: {
url: `${mys.pass_api}/account/auth/api/getLTokenBySToken`,
query: `${data.cookies}`,
},
//用于手动过验证码,账号密码登录需要
microgg: {
url: `https://s.microgg.cn/gt/https://validate.microgg.cn/`,
query: `gt=${data.gt}&challenge=${data.challenge}`
},
microggVl: {
url: `https://validate.microgg.cn/`,
query: `callback=${data.challenge}`
},
loginByPassword: {
url: "https://passport-api.mihoyo.com/account/ma-cn-passport/app/loginByPassword",
body: {
account: this.encrypt_data(data.account),
password: this.encrypt_data(data.password)
},
types: 'pass'
},
qrCodeLogin: {
url: `https://hk4e-sdk.mihoyo.com/hk4e_cn/combo/panda/qrcode/fetch`,
body: {
app_id: mys.app_id,
device: data.device
}
},
qrCodeQuery: {
url: `https://hk4e-sdk.mihoyo.com/hk4e_cn/combo/panda/qrcode/query`,
body: {
app_id: mys.app_id,
device: data.device,
ticket: data.ticket
}
},
getTokenByGameToken: {
url: `https://passport-api.mihoyo.com/account/ma-cn-session/app/getTokenByGameToken`,
body: {
account_id: data.uid * 1,
game_token: data.token
},
types: 'pass'
},
getCookieAccountInfoByGameToken: {
url: `https://api-takumi.mihoyo.com/auth/api/getCookieAccountInfoByGameToken`,
query: `account_id=${data.uid}&game_token=${data.token}`
},
GetCode:{
url:``,
query:``
},
goodsList:{
url:``,
query:``
},
checkOrder:{
url:``,
body:{}
}
}
if (!urlMap[type]) return false
let {
url,
query = '',
body = '',
types = '',
sign = ''
} = urlMap[type]
if (query) url += `?${query}`
if (body) body = JSON.stringify(body)
let headers = this.getHeaders(board, types, sign, body, query)
return {
url,
headers,
body
}
}
// 签到的 headers
getHeaders(board, type = "bbs", sign, body = {}, query = '') {
let header = {};
switch (type) {
case "bbs":
header = {
'Cookie': this.cookies,
"x-rpc-channel": "miyousheluodi",
"x-rpc-auto_test": true,
'x-rpc-device_id': DEVICE_ID,
'x-rpc-app_version': mys.APP_VERSION,
"x-rpc-device_model": "Mi 10",
'x-rpc-device_name': DEVICE_NAME,
'x-rpc-client_type': '2', // 1 - iOS, 2 - Android, 4 - Web
'DS': (sign ? this.getDs2("", JSON.stringify({
gids: board.forumid * 1
}), mys.salt2) : this.getDs(mys.salt)),
"Referer": "https://app.mihoyo.com",
"x-rpc-sys_version": "12",
"Host": "bbs-api.mihoyo.com",
"User-Agent": "okhttp/4.8.0",
}
break;
case "sign":
header = {
'accept-language': 'zh-CN,zh;q=0.9,ja-JP;q=0.8,ja;q=0.7,en-US;q=0.6,en;q=0.5',
'x-rpc-device_id': DEVICE_ID,
'User-Agent': `Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/${mys.APP_VERSION}`,
Referer: board.getReferer(),
Host: 'api-takumi.mihoyo.com',
'x-rpc-channel': 'appstore',
'x-rpc-app_version': mys.APP_VERSION,
'x-requested-with': 'com.mihoyo.hyperion',
'x-rpc-client_type': '5',
'Content-Type': 'application/json;charset=UTF-8',
DS: this.getDs(),
'Cookie': this.cookie
}
if (this.isOs) {
let os_Header = {
app_version: '2.9.0',
User_Agent: `Mozilla/5.0 (Linux; Android 9.0; SAMSUNG SM-F900U Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.73 Mobile Safari/537.36 miHoYoBBSOversea/2.9.0`,
client_type: '2',
'x-rpc-app_version': '2.9.0',
Origin: 'https://webstatic-sea.hoyolab.com',
X_Requested_With: 'com.mihoyo.hoyolab',
Referer: 'https://webstatic-sea.hoyolab.com',
DS: this.getDs(),
'Cookie': this.cookie
}
header = os_Header
}
break;
case "cloud":
header = {
// "x-rpc-combo_token": this.yuntoken, //云原神签到ck
// "x-rpc-client_type": "2",
// "x-rpc-app_version": "1.3.0",
// "x-rpc-sys_version": "11",
// "x-rpc-channel": "mihoyo",
// "x-rpc-device_id": this.devId, //设备Id
// "x-rpc-device_name": "Xiaomi Mi 10 Pro",
// "x-rpc-device_model": "Mi 10 Pro",
// "x-rpc-app_id": "1953439974",
// "Referer": "https://app.mihoyo.com",
// "Content-Length": "0",
// "Host": "api-cloudgame.mihoyo.com",
// "Connection": "Keep-Alive",
// "Accept-Encoding": "gzip",
'Host': 'api-cloudgame.mihoyo.com',
'Accept': '*/*',
'Referer': 'https://app.mihoyo.com',
'x-rpc-combo_token': this.yuntoken,
'Accept-Encoding': 'gzip, deflate',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 HBPC/12.1.1.301',
"User-Agent": "okhttp/3.14.9"
}
break;
case "authKey":
header = {
'x-rpc-app_version': mys.APP_VERSION,
'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.getDs(this.isOs ? mys.osSalt : mys.saltWeb),
'x-rpc-sys_version': '12',
'x-rpc-channel': 'mihoyo',
'x-rpc-device_id': DEVICE_ID,
'x-rpc-device_name': DEVICE_NAME,
'x-rpc-device_model': 'Mi 10',
Host: 'api-takumi.mihoyo.com'
}
if (this.isOs) {
let os_Header = {
'x-rpc-app_version': '2.18.1',
app_version: '2.18.1',
client_type: '2',
'x-rpc-client_type': '2',
Origin: 'https://app.hoyolab.com',
X_Requested_With: 'com.mihoyo.hoyolab',
Referer: 'https://app.hoyolab.com',
Host: 'api-os-takumi.mihoyo.com',
'x-rpc-channel': 'hoyolab'
}
header = Object.assign({}, header, os_Header)
}
break;
case "stoken":
header = {
"x-rpc-device_id": "zxcvbnmasadfghjk123456",
"Content-Type": "application/json;charset=UTF-8",
"x-rpc-client_type": "",
"x-rpc-app_version": "",
"DS": "",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/%s",
"Referer": "cors",
"Accept-Encoding": "gzip, deflate, br",
"x-rpc-channel": "appstore",
}
break;
case "pass":
header = {
'x-rpc-device_id': DEVICE_ID,
'x-rpc-app_id': "bll8iq97cem8",
'x-rpc-device_name': DEVICE_NAME,
"x-rpc-device_fp": utils.randomString(13),
"x-rpc-device_model": utils.randomString(16),
'x-rpc-app_version': mys.APP_VERSION,
'x-rpc-game_biz': 'bbs_cn',
"x-rpc-aigis": '',
"Content-Type": "application/json;",
"x-rpc-client_type": "2",
"DS": this.getDs2('', body, mys.passSalt),
"x-rpc-sdk_version": '1.3.1.2',
"User-Agent": "okhttp/4.9.3",
"Referer": "cors",
'Host': 'passport-api.mihoyo.com',
"Connection": 'Keep-Alive',
"Accept-Encoding": "gzip, deflate, br",
"x-rpc-channel": "appstore",
Cookie: this.cookies,
}
break;
default:
header = {}
break;
}
return header;
}
getStoken(userId) {
let file = `${yamlDataUrl}/${userId}.yaml`
try {
let ck = fs.readFileSync(file, 'utf-8')
ck = YAML.parse(ck)
if (ck?.uid) {
let datalist = {};
ck.userId = this.e.user_id
datalist[ck.uid] = ck;
ck = datalist
gsCfg.saveBingStoken(this.e.user_id, datalist)
}
return ck[this.e.uid] || {}
} catch (error) {
return {}
}
}
encrypt_data(data) {
if (!data) return '';
return crypto.publicEncrypt({
key: mys.publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING
}, data).toString("base64")
}
//社区签到ds
getDs2(q = "", b, salt) {
let i = Math.floor(Date.now() / 1000)
let r = _.random(100001, 200000)
let add = `&b=${b}&q=${q}`
let c = md5("salt=" + salt + "&t=" + i + "&r=" + r + add)
return `${i},${r},${c}`
}
getDs(salt = mys.saltWeb) {
const randomStr = utils.randomString(6);
const timestamp = Math.floor(Date.now() / 1000)
let sign = md5(`salt=${salt}&t=${timestamp}&r=${randomStr}`);
return `${timestamp},${randomStr},${sign}`
}
async getAgent() {
if (isV3) {
let cfg = await import(`file://${_path}/lib/config/config.js`);
let proxyAddress = cfg.default.bot.proxyAddress
if (!proxyAddress) return null
if (proxyAddress === 'http://0.0.0.0:0') return null
if (!this.isOs) return null
if (HttpsProxyAgent === '') {
HttpsProxyAgent = await import('https-proxy-agent').catch((err) => {
logger.error(err)
})
HttpsProxyAgent = HttpsProxyAgent ? HttpsProxyAgent.default : undefined
}
if (HttpsProxyAgent) {
return new HttpsProxyAgent(proxyAddress)
}
}
return null
}
}