mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-04-03 06:55:06 +08:00
♻️ 请求重构
This commit is contained in:
@@ -1,12 +1,32 @@
|
||||
/**
|
||||
* @file web/request/bbsReq.ts
|
||||
* @description BBS 请求模块
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.7.2
|
||||
*/
|
||||
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
import { getRequestHeader } from "@/web/utils/getRequestHeader.js";
|
||||
|
||||
/**
|
||||
* @description 获取表情包列表
|
||||
* @since Beta v0.7.2
|
||||
* @return {Promise<Record<string,string>|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
async function getEmoticonSet(): Promise<Record<string, string> | TGApp.BBS.Response.Base> {
|
||||
const resp = await TGHttp<TGApp.BBS.Emoji.Resp>(
|
||||
"https://bbs-api-static.miyoushe.com/misc/api/emoticon_set",
|
||||
{ method: "GET" },
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
const emojis: Record<string, string> = {};
|
||||
for (const series of resp.data.list) {
|
||||
for (const emoji of series.list) {
|
||||
emojis[emoji.name] = emoji.icon;
|
||||
}
|
||||
}
|
||||
return emojis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 根据 cookie 获取用户信息
|
||||
* @since Beta v0.5.0
|
||||
@@ -46,6 +66,10 @@ async function getOtherUserInfo(
|
||||
return resp.data.user_info;
|
||||
}
|
||||
|
||||
const BBSApi = { userInfo: getUserFullInfo, otherUserInfo: getOtherUserInfo };
|
||||
const BBSApi = {
|
||||
emojis: getEmoticonSet,
|
||||
userInfo: getUserFullInfo,
|
||||
otherUserInfo: getOtherUserInfo,
|
||||
};
|
||||
|
||||
export default BBSApi;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file web/request/otherReq.ts
|
||||
* @description Other API
|
||||
* @since Beta v0.6.8
|
||||
* @since Beta v0.7.2
|
||||
*/
|
||||
|
||||
import TGBbs from "@/utils/TGBbs.js";
|
||||
@@ -11,7 +11,7 @@ import { getInitDeviceInfo } from "@/utils/toolFunc.js";
|
||||
|
||||
/**
|
||||
* @description 获取设备指纹
|
||||
* @since Beta v0.5.5
|
||||
* @since Beta v0.7.2
|
||||
* @param {TGApp.App.Device.DeviceInfo} Info - 设备信息
|
||||
* @returns {Promise<TGApp.App.Device.DeviceInfo>} 设备指纹
|
||||
*/
|
||||
@@ -91,8 +91,9 @@ async function getDeviceFp(
|
||||
"x-requested-with": "com.mihoyo.hyperion",
|
||||
Referer: "https://webstatic.mihoyo.com/",
|
||||
};
|
||||
type ResType = { device_fp: string; code: number; msg: string };
|
||||
try {
|
||||
const resp = await TGHttp<DeviceFpResp>(
|
||||
const resp = await TGHttp<TGApp.BBS.Response.BaseWithData<ResType>>(
|
||||
"https://public-data-api.mihoyo.com/device-fp/api/getFp",
|
||||
{ method: "POST", body: JSON.stringify(data), headers: header },
|
||||
);
|
||||
@@ -125,8 +126,3 @@ async function refreshCode(
|
||||
const OtherApi = { code: refreshCode, fp: getDeviceFp };
|
||||
|
||||
export default OtherApi;
|
||||
|
||||
/// 一些类型 ///
|
||||
type DeviceFpResp = TGApp.BBS.Response.BaseWithData & {
|
||||
data: { device_fp: string; code: number; msg: string };
|
||||
};
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/**
|
||||
* @file web/request/passportReq.ts
|
||||
* @description Passport 相关请求
|
||||
* @since Beta v0.6.8
|
||||
* @since Beta v0.7.2
|
||||
*/
|
||||
import { JSEncrypt } from "jsencrypt";
|
||||
|
||||
import TGBbs from "@/utils/TGBbs.js";
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
import { getDeviceInfo } from "@/utils/toolFunc.js";
|
||||
import { getRequestHeader } from "@/web/utils/getRequestHeader.js";
|
||||
@@ -13,6 +16,26 @@ const pAbu: Readonly<string> = "https://passport-api.mihoyo.com/";
|
||||
const p4Abu: Readonly<string> = "https://passport-api-v4.mihoyo.com/";
|
||||
// HoyoLauncherVersion
|
||||
const hlv: Readonly<string> = "1.3.3.182";
|
||||
// 加密密钥
|
||||
const PUB_KEY_STR: Readonly<string> = `-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7cI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs
|
||||
9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q
|
||||
CgGs52bFoYMtyi+xEQIDAQAB
|
||||
-----END PUBLIC KEY-----`;
|
||||
const encrypt = new JSEncrypt();
|
||||
encrypt.setPublicKey(PUB_KEY_STR);
|
||||
|
||||
/**
|
||||
* @description rsa 加密
|
||||
* @since Beta v0.5.1
|
||||
* @param {string} data - 待加密数据
|
||||
* @returns {string} 加密后数据
|
||||
*/
|
||||
function rsaEncrypt(data: string): string {
|
||||
const res = encrypt.encrypt(data.toString());
|
||||
if (res === false) return "";
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录ticket
|
||||
@@ -35,7 +58,8 @@ async function createAuthTicketByGameBiz(
|
||||
"x-rpc-client_type": "3",
|
||||
"x-rpc-app_id": "ddxf5dufpuyo",
|
||||
};
|
||||
const resp = await TGHttp<AuthTicketByGameBizResp>(
|
||||
type ResType = { ticket: string };
|
||||
const resp = await TGHttp<TGApp.BBS.Response.BaseWithData<ResType>>(
|
||||
`${pAbu}account/ma-cn-verifier/app/createAuthTicketByGameBiz`,
|
||||
{ method: "POST", headers: headers, query: params },
|
||||
);
|
||||
@@ -43,6 +67,48 @@ async function createAuthTicketByGameBiz(
|
||||
return resp.data.ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取短信验证码
|
||||
* @since Beta v0.7.2
|
||||
* @param {string} phone - 手机号
|
||||
* @param {string} [aigis] - 验证数据
|
||||
* @returns {Promise<TGApp.BBS.CaptchaLogin.CaptchaRes | TGApp.BBS.Response.BaseWithData<string>>}
|
||||
*/
|
||||
async function createLoginCaptcha(
|
||||
phone: string,
|
||||
aigis?: string,
|
||||
): Promise<TGApp.BBS.CaptchaLogin.CaptchaRes | TGApp.BBS.Response.BaseWithData<string>> {
|
||||
const body = { area_code: rsaEncrypt("+86"), mobile: rsaEncrypt(phone) };
|
||||
const header: Record<string, string> = {
|
||||
"x-rpc-aigis": aigis || "",
|
||||
"x-rpc-app_version": TGBbs.version,
|
||||
"x-rpc-client_type": "2",
|
||||
"x-rpc-app_id": "bll8iq97cem8",
|
||||
"x-rpc-device_fp": getDeviceInfo("device_fp"),
|
||||
"x-rpc-device_name": getDeviceInfo("device_name"),
|
||||
"x-rpc-device_id": getDeviceInfo("device_id"),
|
||||
"x-rpc-device_model": getDeviceInfo("product"),
|
||||
"user-agent": TGBbs.ua,
|
||||
"content-type": "application/json",
|
||||
referer: "https://user.miyoushe.com/",
|
||||
"x-rpc-game_biz": "hk4e_cn",
|
||||
};
|
||||
const resp = await TGHttp<TGApp.BBS.CaptchaLogin.CaptchaResp>(
|
||||
`${pAbu}account/ma-cn-verifier/verifier/createLoginCaptcha`,
|
||||
{ method: "POST", headers: header, body: JSON.stringify(body) },
|
||||
true,
|
||||
);
|
||||
const data = await resp.data;
|
||||
if (data.retcode !== 0) {
|
||||
return <TGApp.BBS.Response.BaseWithData<string>>{
|
||||
retcode: data.retcode,
|
||||
message: data.message,
|
||||
data: resp.resp.headers.get("x-rpc-aigis"),
|
||||
};
|
||||
}
|
||||
return <TGApp.BBS.CaptchaLogin.CaptchaRes>data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建登录二维码
|
||||
* @since Beta v0.6.8
|
||||
@@ -78,7 +144,8 @@ async function getCookieAccountInfoBySToken(
|
||||
): Promise<string | TGApp.BBS.Response.Base> {
|
||||
const ck = { stoken: cookie.stoken, mid: cookie.mid };
|
||||
const params = { stoken: cookie.stoken };
|
||||
const resp = await TGHttp<GetCookieTokenBySTokenResp | TGApp.BBS.Response.Base>(
|
||||
type ResType = { uid: string; cookie_token: string };
|
||||
const resp = await TGHttp<TGApp.BBS.Response.BaseWithData<ResType>>(
|
||||
`${pAbu}account/auth/api/getCookieAccountInfoBySToken`,
|
||||
{ method: "GET", headers: getRequestHeader(ck, "GET", params), query: params },
|
||||
);
|
||||
@@ -97,7 +164,8 @@ async function getLTokenBySToken(
|
||||
): Promise<string | TGApp.BBS.Response.Base> {
|
||||
const ck = { mid: cookie.mid, stoken: cookie.stoken };
|
||||
const params = { stoken: cookie.stoken };
|
||||
const resp = await TGHttp<GetLTokenBySTokenResp | TGApp.BBS.Response.Base>(
|
||||
type ResType = { ltoken: string };
|
||||
const resp = await TGHttp<TGApp.BBS.Response.BaseWithData<ResType>>(
|
||||
`${pAbu}account/auth/api/getLTokenBySToken`,
|
||||
{ method: "GET", headers: getRequestHeader(ck, "GET", params), query: params },
|
||||
);
|
||||
@@ -105,6 +173,46 @@ async function getLTokenBySToken(
|
||||
return resp.data.ltoken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 通过短信验证码登录
|
||||
* @since Beta v0.5.1
|
||||
* @param {string} phone - 手机号
|
||||
* @param {string} captcha - 验证码
|
||||
* @param {string} action_type - 操作类型
|
||||
* @param {string} [aigis] - 验证数据
|
||||
* @returns {Promise<TGApp.BBS.CaptchaLogin.LoginRes | TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
async function loginByMobileCaptcha(
|
||||
phone: string,
|
||||
captcha: string,
|
||||
action_type: string,
|
||||
aigis?: string,
|
||||
): Promise<TGApp.BBS.CaptchaLogin.LoginRes | TGApp.BBS.Response.Base> {
|
||||
const body = {
|
||||
area_code: rsaEncrypt("+86"),
|
||||
mobile: rsaEncrypt(phone),
|
||||
action_type,
|
||||
captcha,
|
||||
};
|
||||
const header = {
|
||||
"x-rpc-aigis": aigis || "",
|
||||
"x-rpc-app_version": TGBbs.version,
|
||||
"x-rpc-client_type": "2",
|
||||
"x-rpc-app_id": "bll8iq97cem8",
|
||||
"x-rpc-device_fp": getDeviceInfo("device_fp"),
|
||||
"x-rpc-device_name": getDeviceInfo("device_name"),
|
||||
"x-rpc-device_id": getDeviceInfo("device_id"),
|
||||
"x-rpc-device_model": getDeviceInfo("product"),
|
||||
"user-agent": TGBbs.ua,
|
||||
};
|
||||
const resp = await TGHttp<TGApp.BBS.CaptchaLogin.LoginResp>(
|
||||
`${pAbu}account/ma-cn-passport/app/loginByMobileCaptcha`,
|
||||
{ method: "POST", headers: header, body: JSON.stringify(body) },
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取登录状态
|
||||
* @since Beta v0.6.8
|
||||
@@ -142,35 +250,7 @@ async function verifyLToken(
|
||||
): Promise<string | TGApp.BBS.Response.Base> {
|
||||
const ck = { ltoken: cookie.ltoken, ltuid: cookie.ltuid };
|
||||
const data = { ltoken: cookie.ltoken };
|
||||
const resp = await TGHttp<VerifyLtokenResp>(`${p4Abu}account/ma-cn-session/web/verifyLtoken`, {
|
||||
method: "POST",
|
||||
headers: getRequestHeader(ck, "POST", data),
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data.user_info.mid;
|
||||
}
|
||||
|
||||
const PassportApi = {
|
||||
authTicket: createAuthTicketByGameBiz,
|
||||
cookieToken: getCookieAccountInfoBySToken,
|
||||
lToken: { get: getLTokenBySToken, verify: verifyLToken },
|
||||
qrLogin: { create: createQrLogin, query: queryLoginStatus },
|
||||
};
|
||||
|
||||
export default PassportApi;
|
||||
|
||||
/// 一些类型 ///
|
||||
type AuthTicketByGameBizResp = TGApp.BBS.Response.BaseWithData & { data: { ticket: string } };
|
||||
|
||||
type GetCookieTokenBySTokenResp = TGApp.BBS.Response.BaseWithData & {
|
||||
data: { uid: string; cookie_token: string };
|
||||
};
|
||||
|
||||
type GetLTokenBySTokenResp = TGApp.BBS.Response.BaseWithData & { data: { ltoken: string } };
|
||||
|
||||
type VerifyLtokenResp = TGApp.BBS.Response.BaseWithData & {
|
||||
data: {
|
||||
type ResType = {
|
||||
realname_info: unknown;
|
||||
need_realperson: boolean;
|
||||
user_info: {
|
||||
@@ -189,4 +269,24 @@ type VerifyLtokenResp = TGApp.BBS.Response.BaseWithData & {
|
||||
links: Array<unknown>;
|
||||
};
|
||||
};
|
||||
const resp = await TGHttp<TGApp.BBS.Response.BaseWithData<ResType>>(
|
||||
`${p4Abu}account/ma-cn-session/web/verifyLtoken`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: getRequestHeader(ck, "POST", data),
|
||||
body: JSON.stringify(data),
|
||||
},
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data.user_info.mid;
|
||||
}
|
||||
|
||||
const PassportApi = {
|
||||
authTicket: createAuthTicketByGameBiz,
|
||||
cookieToken: getCookieAccountInfoBySToken,
|
||||
lToken: { get: getLTokenBySToken, verify: verifyLToken },
|
||||
qrLogin: { create: createQrLogin, query: queryLoginStatus },
|
||||
captcha: { create: createLoginCaptcha, login: loginByMobileCaptcha },
|
||||
};
|
||||
|
||||
export default PassportApi;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file web/request/takumiReq.ts
|
||||
* @description Takumi 相关请求函数
|
||||
* @since Beta v0.7.0
|
||||
* @since Beta v0.7.2
|
||||
*/
|
||||
import TGBbs from "@/utils/TGBbs.js";
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
@@ -57,20 +57,20 @@ async function getSTokenByGameToken(
|
||||
|
||||
/**
|
||||
* @description 根据stoken获取action_ticket
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.7.2
|
||||
* @param {TGApp.App.Account.Cookie} cookie Cookie
|
||||
* @param {TGApp.Sqlite.Account.Game} user 用户
|
||||
* @param {string} actionType 动作类型
|
||||
* @returns {Promise<ActionTicketByStokenResp>}
|
||||
* @returns {Promise<TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
async function getActionTicketBySToken(
|
||||
cookie: TGApp.App.Account.Cookie,
|
||||
user: TGApp.Sqlite.Account.Game,
|
||||
actionType: string,
|
||||
): Promise<ActionTicketByStokenResp> {
|
||||
): Promise<TGApp.BBS.Response.Base> {
|
||||
const ck = { stoken: cookie.stoken, mid: cookie.mid };
|
||||
const params = { action_type: actionType, stoken: cookie.stoken, uid: user.gameUid };
|
||||
return await TGHttp<ActionTicketByStokenResp>(`${taBu}auth/api/getActionTicketBySToken`, {
|
||||
return await TGHttp<TGApp.BBS.Response.Base>(`${taBu}auth/api/getActionTicketBySToken`, {
|
||||
method: "GET",
|
||||
headers: getRequestHeader(ck, "GET", params, "K2"),
|
||||
query: params,
|
||||
@@ -127,7 +127,7 @@ async function genAuthKey2(
|
||||
|
||||
/**
|
||||
* @description 通过cookie获取游戏账号
|
||||
* @since Beta v0.6.5
|
||||
* @since Beta v0.7.2
|
||||
* @param {TGApp.App.Account.Cookie} cookie cookie
|
||||
* @returns {Promise<TGApp.BBS.Account.GameAccount[]|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
@@ -136,58 +136,76 @@ async function getUserGameRolesByCookie(
|
||||
): Promise<TGApp.BBS.Account.GameAccount[] | TGApp.BBS.Response.Base> {
|
||||
const ck = { account_id: cookie.account_id, cookie_token: cookie.cookie_token };
|
||||
const params = { game_biz: "hk4e_cn" };
|
||||
const resp = await TGHttp<GameAccountsResp>(`${taBu}binding/api/getUserGameRolesByCookie`, {
|
||||
method: "GET",
|
||||
headers: getRequestHeader(ck, "GET", params),
|
||||
query: params,
|
||||
});
|
||||
type ResType = { list: Array<TGApp.BBS.Account.GameAccount> };
|
||||
const resp = await TGHttp<TGApp.BBS.Response.BaseWithData<ResType>>(
|
||||
`${taBu}binding/api/getUserGameRolesByCookie`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: getRequestHeader(ck, "GET", params),
|
||||
query: params,
|
||||
},
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data.list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取卡池信息
|
||||
* @since Beta v0.7.2
|
||||
* @return {Promise<Array<TGApp.BBS.Obc.GachaItem>>}
|
||||
*/
|
||||
async function getObcGachaPool(): Promise<Array<TGApp.BBS.Obc.GachaItem>> {
|
||||
const resp = await TGHttp<TGApp.BBS.Obc.GachaResp>(
|
||||
`${taBu}common/blackboard/ys_obc/v1/gacha_pool`,
|
||||
{
|
||||
method: "GET",
|
||||
query: { app_sn: "ys_obc" },
|
||||
headers: { "Content-Type": "application/json" },
|
||||
},
|
||||
);
|
||||
return resp.data.list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 深度优先遍历
|
||||
* @since Beta v0.7.2
|
||||
* @param {Array<TGApp.BBS.Obc.ObcItem<TGApp.BBS.Obc.PositionItem>>} list 列表
|
||||
* @returns {Array<TGApp.BBS.Obc.PositionItem>} 返回列表
|
||||
*/
|
||||
function DfsObc(
|
||||
list: Array<TGApp.BBS.Obc.ObcItem<TGApp.BBS.Obc.PositionItem>>,
|
||||
): Array<TGApp.BBS.Obc.PositionItem> {
|
||||
const res: Array<TGApp.BBS.Obc.PositionItem> = [];
|
||||
for (const item of list) {
|
||||
if (item.name === "近期活动") res.push(...item.list);
|
||||
if (item.children) res.push(...DfsObc(item.children));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取热点追踪信息
|
||||
* @since Beta v0.7.2
|
||||
* @return {Promise<Array<TGApp.BBS.Obc.PositionItem>>}
|
||||
*/
|
||||
async function getObcHomePosition(): Promise<Array<TGApp.BBS.Obc.PositionItem>> {
|
||||
const resp = await TGHttp<TGApp.BBS.Obc.PositionResp>(
|
||||
`${taBu}common/blackboard/ys_obc/v1/home/position`,
|
||||
{
|
||||
method: "GET",
|
||||
query: { app_sn: "ys_obc" },
|
||||
headers: { "Content-Type": "application/json" },
|
||||
},
|
||||
);
|
||||
const data = resp.data.list;
|
||||
return DfsObc(data);
|
||||
}
|
||||
|
||||
const TakumiApi = {
|
||||
auth: { actionTicket: getActionTicketBySToken },
|
||||
bind: { authKey: genAuthKey, authKey2: genAuthKey2, gameRoles: getUserGameRolesByCookie },
|
||||
game: { stoken: getSTokenByGameToken },
|
||||
obc: { gacha: getObcGachaPool, position: getObcHomePosition },
|
||||
};
|
||||
|
||||
export default TakumiApi;
|
||||
|
||||
/// 一些类型 ///
|
||||
type ActionTicketByStokenResp = TGApp.BBS.Response.BaseWithData & {
|
||||
data: {
|
||||
ticket: string;
|
||||
is_verified: boolean;
|
||||
account_info: {
|
||||
is_realname: boolean;
|
||||
mobile: string;
|
||||
safe_mobile: string;
|
||||
account_id: string;
|
||||
account_name: string;
|
||||
email: string;
|
||||
is_email_verify: boolean;
|
||||
area_code: string;
|
||||
safe_area_code: string;
|
||||
real_name: string;
|
||||
identity_code: string;
|
||||
create_time: string;
|
||||
create_ip: string;
|
||||
change_pwd_time: string;
|
||||
nickname: string;
|
||||
user_icon_id: number;
|
||||
safe_level: number;
|
||||
black_endtime: string;
|
||||
black_note: string;
|
||||
gender: number;
|
||||
real_stat: number;
|
||||
apple_name: string;
|
||||
sony_name: string;
|
||||
tap_name: string;
|
||||
reactivate_ticket: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type GameAccountsResp = TGApp.BBS.Response.BaseWithData & {
|
||||
data: { list: Array<TGApp.BBS.Account.GameAccount> };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user