♻️ 请求模块重构

This commit is contained in:
目棃
2024-11-19 09:34:18 +08:00
parent 9b1fa22cbe
commit c6f45f0a35
49 changed files with 660 additions and 1120 deletions

View File

@@ -1,10 +0,0 @@
/**
* @file web api BBS.ts
* @description BBS API
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
const BBS_API = "https://bbs-api.miyoushe.com/"; // 基础 API
export const BBSUserInfoApi = `${BBS_API}user/wapi/getUserFullInfo`; // 用户信息 API

View File

@@ -1,8 +0,0 @@
/**
* @file web api ENKA.ts
* @description ENKA API
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
export const ENKA_API = "https://enka.network/api/uid/"; // 基础 API

View File

@@ -1,14 +0,0 @@
/**
* @file web api Passport.ts
* @description 定义 Passport API
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
const PassportApi = "https://passport-api.mihoyo.com/"; // 基础 API
const PassportV4Api = "https://passport-api-v4.mihoyo.com/"; // 基础 API
const PassportAuthApi = `${PassportApi}account/auth/api/`; // 认证 API
export const PassportTokenApi = `${PassportAuthApi}getLTokenBySToken`; // 根据 stoken 获取 ltoken
export const PassportCookieTokenApi = `${PassportAuthApi}getCookieAccountInfoBySToken`; // 根据 Cookie 获取 Token
export const PassportVerifyApi = `${PassportV4Api}account/ma-cn-session/web/verifyLtoken`; // 验证 stoken 有效性

View File

@@ -1,58 +0,0 @@
/**
* @file web/api/TGApi.ts
* @description 应用用到的 API
* @since Beta v0.6.2
*/
import { BBSUserInfoApi } from "./BBS.js";
import { ENKA_API } from "./ENKA.js";
import { PassportTokenApi, PassportCookieTokenApi, PassportVerifyApi } from "./Passport.js";
import {
TakumiTokensApi,
TakumiRecordCardApi,
TakumiRecordCharactersApi,
TakumiRecordDailyNotesApi,
TakumiRecordIndexApi,
TakumiRecordAbyssApi,
TakumiSTokenBindingRolesApi,
TakumiCookieBindingRolesApi,
TakumiCalculateSyncAvatarListApi,
TakumiCalculateSyncAvatarDetailApi,
TakumiRecordCharacterListApi,
TakumiRecordCharacterDetailApi,
TakumiRecordCombatApi,
} from "./Takumi.js";
// 应用 API
const TGApi = {
GameEnka: ENKA_API, // 游戏 ENKA API
GameTokens: {
getTokens: TakumiTokensApi, // 根据 login_ticket 获取游戏 Token
getLToken: PassportTokenApi, // 根据 stoken 获取 ltoken
getCookieToken: PassportCookieTokenApi, // 根据 Cookie 获取 Token
verifyLToken: PassportVerifyApi, // 验证 ltoken 有效性
},
GameData: {
byCookie: {
getUserInfo: BBSUserInfoApi, // 获取用户信息
getAccounts: TakumiCookieBindingRolesApi, // 获取绑定角色
getCharacter: TakumiRecordCharactersApi, // 获取角色信息
getAvatarList: TakumiRecordCharacterListApi, // 获取角色列表
getAvatarDetail: TakumiRecordCharacterDetailApi, // 获取角色详情
},
bySToken: {
getAccounts: TakumiSTokenBindingRolesApi, // 获取绑定角色
},
calculate: {
getSyncAvatarList: TakumiCalculateSyncAvatarListApi, // 同步角色列表
getSyncAvatarDetail: TakumiCalculateSyncAvatarDetailApi, // 同步角色详情
},
getUserCard: TakumiRecordCardApi, // 获取用户卡片
getUserBase: TakumiRecordIndexApi, // 获取用户基本信息
getDailyNotes: TakumiRecordDailyNotesApi, // 获取实时便笺
getAbyss: TakumiRecordAbyssApi, // 获取深境螺旋信息
getRoleCombat: TakumiRecordCombatApi, // 获取幻想真境剧诗
},
};
export default TGApi;

View File

@@ -1,28 +0,0 @@
/**
* @file web/api/Takumi.ts
* @description 定义 Takumi API
* @since Beta v0.6.2
*/
const TakumiApi = "https://api-takumi.mihoyo.com/"; // 基础 API
const TakumiAuthApi = `${TakumiApi}auth/api/`; // 认证 API
const TakumiBindingApi = `${TakumiApi}binding/api/`; // 绑定 API
const TakumiCalculateApi = `${TakumiApi}event/e20200928calculate/`; // 计算 API
const TakumiRecordApi = "https://api-takumi-record.mihoyo.com/"; // 游戏记录 API
const TakumiRecordGenshinApi = `${TakumiRecordApi}game_record/app/genshin/api/`; // 原神游戏记录 API
export const TakumiTokensApi = `${TakumiAuthApi}getMultiTokenByLoginTicket`; // 登录票据 API
export const TakumiRecordDailyNotesApi = `${TakumiRecordGenshinApi}dailyNote`; // 游戏记录便笺 API
export const TakumiRecordCardApi = `${TakumiRecordApi}game_record/app/card/wapi/getGameRecordCard`; // 游戏记录卡片 API
export const TakumiRecordIndexApi = `${TakumiRecordGenshinApi}index`; // 原神游戏记录索引 API
export const TakumiRecordCharactersApi = `${TakumiRecordGenshinApi}character`; // 原神游戏记录角色 API
export const TakumiRecordCharacterListApi = `${TakumiRecordCharactersApi}/list`; // 原神游戏记录角色列表 API
export const TakumiRecordCharacterDetailApi = `${TakumiRecordCharactersApi}/detail`; // 原神游戏记录角色详情 API
export const TakumiRecordAbyssApi = `${TakumiRecordGenshinApi}spiralAbyss`; // 原神游戏记录深境螺旋 API
export const TakumiRecordCombatApi = `${TakumiRecordGenshinApi}role_combat`;
export const TakumiSTokenBindingRolesApi = `${TakumiBindingApi}getUserGameRolesBySToken`; // 获取绑定角色 API-根据 stoken
export const TakumiCookieBindingRolesApi = `${TakumiBindingApi}getUserGameRolesByCookie`; // 获取绑定角色 API-根据 Cookie
// 养成计算器 API
export const TakumiCalculateSyncAvatarListApi = `${TakumiCalculateApi}v1/sync/avatar/list`;
export const TakumiCalculateSyncAvatarDetailApi = `${TakumiCalculateApi}v1/sync/avatar/detail`;

View File

@@ -1,68 +0,0 @@
/**
* @file web/request/TGRequest.ts
* @description 应用用到的请求函数
* @since Beta v0.6.3
*/
import { genAuthkey, genAuthkey2 } from "./genAuthkey.js";
import { getAbyss } from "./getAbyss.js";
import { getActionTicketBySToken } from "./getActionTicket.js";
import { getAnnoContent, getAnnoList } from "./getAnno.js";
import getAuthTicket from "./getAuthTicket.js";
import { getAvatarList, getAvatarDetail, getAvatarIndex } from "./getAvatarDetail.js";
import getCode from "./getCode.js";
import { getCookieTokenByGameToken, getCookieTokenBySToken } from "./getCookieToken.js";
import { getDeviceFp } from "./getDeviceFp.js";
import { getGachaLog } from "./getGachaLog.js";
import { getGameAccountsByCookie, getGameAccountsBySToken } from "./getGameAccounts.js";
import { getGameRecord } from "./getGameRecord.js";
import { getLTokenBySToken } from "./getLToken.js";
import { getRoleCombat } from "./getRoleCombat.js";
import { getStokenByGameToken, getTokenBySToken } from "./getStoken.js";
import { getUserCollect } from "./getUserCollect.js";
import { getUserInfoByCookie } from "./getUserInfo.js";
import { verifyLToken } from "./verifyLToken.js";
const TGRequest = {
Anno: {
getList: getAnnoList,
getContent: getAnnoContent,
},
Device: {
getFp: getDeviceFp,
},
User: {
getAuthkey: genAuthkey,
getAuthkey2: genAuthkey2,
getAuthTicket,
getCollect: getUserCollect,
getGachaLog,
getRecord: getGameRecord,
verifyLToken,
byCookie: {
getAbyss,
getAccounts: getGameAccountsByCookie,
getUserInfo: getUserInfoByCookie,
getAvatarIndex,
getAvatarList,
getAvatarDetail,
getCombat: getRoleCombat,
},
bySToken: {
update: getTokenBySToken,
getAccounts: getGameAccountsBySToken,
getCookieToken: getCookieTokenBySToken,
getLToken: getLTokenBySToken,
getActionTicket: getActionTicketBySToken,
},
bgGameToken: {
getCookieToken: getCookieTokenByGameToken,
getStoken: getStokenByGameToken,
},
},
Nav: {
getCode,
},
};
export default TGRequest;

63
src/web/request/bbsReq.ts Normal file
View File

@@ -0,0 +1,63 @@
/**
* @file web/request/bbsReq.ts
* @description BBS 请求模块
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 根据 cookie 获取用户信息
* @since Beta v0.5.0
* @param {TGApp.App.Account.Cookie} cookie - 账户 cookie
* @returns {Promise<TGApp.BBS.Response.Base | TGApp.Plugins.Mys.User.Info>}
*/
async function getUserFullInfo(
cookie: TGApp.App.Account.Cookie,
): Promise<TGApp.BBS.Response.Base | TGApp.Plugins.Mys.User.Info> {
const url = "https://bbs-api.miyoushe.com/user/wapi/getUserFullInfo";
const ck = { cookie_token: cookie.cookie_token, account_id: cookie.account_id };
const params = { gids: "2" };
const header = getRequestHeader(ck, "GET", params, "common", true);
const resp = await TGHttp<TGApp.Plugins.Mys.User.HomeResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.user_info;
}
/**
* @description 获取用户收藏帖子
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie - 用户 cookie
* @param {string} uid - 用户 uid
* @param {string} offset - 偏移量
* @returns {Promise<TGApp.BBS.Collection.PostRespData|TGApp.BBS.Response.Base>} 用户收藏帖子
*/
async function userFavouritePost(
cookie: TGApp.App.Account.Cookie,
uid: string,
offset: string = "",
): Promise<TGApp.BBS.Collection.PostRespData | TGApp.BBS.Response.Base> {
const url = "https://bbs-api.miyoushe.com/post/wapi/userFavouritePost";
const ck = { cookie_token: cookie.cookie_token, account_id: cookie.account_id };
const params = { size: "20", uid, offset };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Collection.PostResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}
const BBSApi = {
userInfo: getUserFullInfo,
lovePost: userFavouritePost,
};
export default BBSApi;

View File

@@ -1,58 +0,0 @@
/**
* @file web/request/genAuthkey.ts
* @description 生成 authkey
* @since Beta v0.6.2
*/
import TGHttp from "../../utils/TGHttp.js";
import TGConstant from "../constant/TGConstant.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 生成 authkey
* @since Beta v0.6.2
* @param {TGApp.App.Account.Cookie} cookie cookie
* @param {TGApp.Sqlite.Account.Game} account 账户
* @returns {Promise<string|TGApp.BBS.Response.Base>} authkey
*/
export async function genAuthkey(
cookie: TGApp.App.Account.Cookie,
account: TGApp.Sqlite.Account.Game,
): Promise<string | TGApp.BBS.Response.Base> {
const url = "https://api-takumi.mihoyo.com/binding/api/genAuthKey";
const ck = { stoken: cookie.stoken, mid: cookie.mid };
const data = {
auth_appid: "webview_gacha",
game_biz: TGConstant.GAME_BIZ,
game_uid: account.gameUid,
region: account.region,
};
const header = getRequestHeader(ck, "POST", JSON.stringify(data), "lk2", true);
const resp = await TGHttp<TGApp.Game.Gacha.AuthkeyResponse | TGApp.BBS.Response.Base>(url, {
method: "POST",
headers: header,
body: JSON.stringify(data),
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.authkey;
}
/**
* @description 生成 authkey
* @since Beta v0.5.0
* @param {Record<string, string>} cookie cookie // stoken_v2 & mid
* @param {object} payload payload
* @returns {Promise<string|TGApp.BBS.Response.Base>} authkey
*/
export async function genAuthkey2(
cookie: Record<string, string>,
payload: Record<string, string>,
): Promise<TGApp.BBS.Response.Base> {
const url = "https://api-takumi.mihoyo.com/binding/api/genAuthKey";
const header = getRequestHeader(cookie, "POST", JSON.stringify(payload), "lk2", true);
return await TGHttp<TGApp.BBS.Response.Base>(url, {
method: "POST",
headers: header,
body: JSON.stringify(payload),
});
}

View File

@@ -1,40 +0,0 @@
/**
* @file web/request/getAbyss.ts
* @description 获取深渊信息
* @since Beta v0.6.1
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 获取深渊信息
* @since Beta v0.6.1
* @param {TGApp.App.Account.Cookie} cookie cookie
* @param {string} schedule 1: 本期, 2: 上期
* @param {TGApp.Sqlite.Account.Game} account 游戏账号
* @returns {Promise<TGApp.Game.Abyss.FullData|TGApp.BBS.Response.Base>}
*/
export async function getAbyss(
cookie: TGApp.App.Account.Cookie,
schedule: string,
account: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Abyss.FullData | TGApp.BBS.Response.Base> {
const url = TGApi.GameData.getAbyss;
const params = { role_id: account.gameUid, schedule_type: schedule, server: account.region };
const ck = {
account_id: cookie.account_id,
cookie_token: cookie.cookie_token,
ltoken: cookie.ltoken,
ltuid: cookie.ltuid,
};
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.Game.Abyss.Response | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}

View File

@@ -1,34 +0,0 @@
/**
* @file web/request/getActionTicket.ts
* @description 获取米游社动态的 ActionTicket
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 通过 stoken 获取 ActionTicket
* @since Beta v0.5.0
* @param {string} ActionType 动作类型
* @param {string} SToken stoken
* @param {string} MID 用户 MID
* @param {string} UID 用户 UID
* @returns {Promise<TGApp.BBS.Response.getActionTicketBySToken>}
*/
export async function getActionTicketBySToken(
ActionType: string,
SToken: string,
MID: string,
UID: string,
): Promise<TGApp.BBS.Response.getActionTicketBySToken> {
const url = "https://api-takumi.mihoyo.com/auth/api/getActionTicketBySToken";
const params = { action_type: ActionType, stoken: SToken, uid: UID };
const cookie = { mid: MID, stoken: SToken };
const header = getRequestHeader(cookie, "GET", params, "k2");
return await TGHttp<TGApp.BBS.Response.getActionTicketBySToken>(url, {
method: "GET",
headers: header,
query: params,
});
}

View File

@@ -1,41 +0,0 @@
/**
* @files web/request/getAuthTicket.ts
* @description 获取登录 ticket
* @since Beta v0.6.0
*/
import TGHttp from "../../utils/TGHttp.js";
/**
* @description 获取登录ticket
* @since Beta v0.6.0
* @param {TGApp.Sqlite.Account.Game} account - 账户
* @param {TGApp.App.Account.Cookie} cookie - cookie
* @returns {Promise<TGApp.BBS.Response.Base|string>}
*/
async function getAuthTicket(
account: TGApp.Sqlite.Account.Game,
cookie: TGApp.App.Account.Cookie,
): Promise<TGApp.BBS.Response.Base | string> {
const url =
"https://passport-api.mihoyo.com/account/ma-cn-verifier/app/createAuthTicketByGameBiz";
const params = {
game_biz: account.gameBiz,
stoken: cookie.stoken,
uid: account.gameUid,
mid: cookie.mid,
};
const header = {
"x-rpc-client_type": "3",
"x-rpc-app_id": "ddxf5dufpuyo",
};
const resp = await TGHttp<TGApp.BBS.Response.getAuthTicketByGameBiz>(url, {
method: "POST",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.ticket;
}
export default getAuthTicket;

View File

@@ -1,81 +0,0 @@
/**
* @file web/request/getAvatarDetail.ts
* @description 获取角色详情相关请求函数
* @since Beta v0.6.1
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 手动刷新角色数据
* @since Beta v0.6.1
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @returns {Promise<void>}
*/
export async function getAvatarIndex(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
): Promise<TGApp.BBS.Response.Base> {
const url = TGApi.GameData.getUserBase;
const params = { avatar_list_type: 1, role_id: user.gameUid, server: user.region };
const ck = { cookie_token: cookie.cookie_token, account_id: cookie.account_id };
const header = getRequestHeader(ck, "GET", params, "common");
return await TGHttp<TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
}
/**
* @description 获取角色列表
* @since Beta v0.6.1
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @return {Promise<TGApp.Game.Avatar.Avatar[]|TGApp.BBS.Response.Base>}
*/
export async function getAvatarList(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Avatar.Avatar[] | TGApp.BBS.Response.Base> {
const url = TGApi.GameData.byCookie.getAvatarList;
const data = { role_id: user.gameUid, server: user.region };
const ck = { cookie_token: cookie.cookie_token, account_id: cookie.account_id };
const header = getRequestHeader(ck, "POST", data, "common");
const resp = await TGHttp<TGApp.Game.Avatar.ListResponse | TGApp.BBS.Response.Base>(url, {
method: "POST",
body: JSON.stringify(data),
headers: header,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.list;
}
/**
* @description 获取角色详情
* @since Beta v0.6.1
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @param {string[]} avatarIds 角色 id 列表
* @return {Promise<TGApp.Game.Avatar.AvatarDetail|TGApp.BBS.Response.Base>}
*/
export async function getAvatarDetail(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
avatarIds: string[],
): Promise<TGApp.Game.Avatar.AvatarDetail | TGApp.BBS.Response.Base> {
const url = TGApi.GameData.byCookie.getAvatarDetail;
const data = { role_id: user.gameUid, server: user.region, character_ids: avatarIds };
const ck = { cookie_token: cookie.cookie_token, account_id: cookie.account_id };
const header = getRequestHeader(ck, "POST", data, "common");
const resp = await TGHttp<TGApp.Game.Avatar.DetailResponse | TGApp.BBS.Response.Base>(url, {
method: "POST",
body: JSON.stringify(data),
headers: header,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}

View File

@@ -1,28 +0,0 @@
/**
* @file web/request/getCode.ts
* @description 获取兑换码相关请求
* @since Beta v0.5.3
*/
import TGHttp from "../../utils/TGHttp.js";
/**
* @description 获取兑换码请求
* @since Beta v0.5.3
* @param {string} act_id - 活动 id
* @return {Promise<TGApp.BBS.Navigator.CodeData[]|TGApp.BBS.Response.Base>}
*/
async function getCode(
act_id: string,
): Promise<TGApp.BBS.Navigator.CodeData[] | TGApp.BBS.Response.Base> {
const url = "https://api-takumi-static.mihoyo.com/event/miyolive/refreshCode";
const header = { "x-rpc-act_id": act_id };
const res = await TGHttp<TGApp.BBS.Navigator.CodeResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
});
if (res.retcode !== 0) return <TGApp.BBS.Response.Base>res;
return res.data.code_list;
}
export default getCode;

View File

@@ -1,60 +0,0 @@
/**
* @file web/request/getCookieToken.ts
* @description 获取 Cookie Token 的请求函数
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 根据 stoken 获取 cookie_token
* @since Beta v0.5.0
* @param {string} Mid 登录用户的 mid
* @param {string} Stoken stoken_v2
* @returns {Promise<string|TGApp.BBS.Response.Base>}
*/
export async function getCookieTokenBySToken(
Mid: string,
Stoken: string,
): Promise<string | TGApp.BBS.Response.Base> {
const url = TGApi.GameTokens.getCookieToken;
const cookie = { mid: Mid, stoken: Stoken };
const params = { stoken: Stoken };
const header = getRequestHeader(cookie, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Response.getCookieTokenBySToken | TGApp.BBS.Response.Base>(
url,
{
method: "GET",
headers: header,
query: params,
},
);
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.cookie_token;
}
/**
* @description 根据 gameToken 获取 cookie_token
* @since Beta v0.5.0
* @param {string} accountId 账号 id
* @param {string} gameToken gameToken
* @returns {Promise<string|TGApp.BBS.Response.Base>}
*/
export async function getCookieTokenByGameToken(
accountId: string,
gameToken: string,
): Promise<string | TGApp.BBS.Response.Base> {
const url = "https://api-takumi.mihoyo.com/auth/api/getCookieAccountInfoByGameToken";
const data = { account_id: Number(accountId), game_token: gameToken };
const resp = await TGHttp<TGApp.BBS.Response.getCookieTokenByGameToken | TGApp.BBS.Response.Base>(
url,
{
method: "POST",
body: JSON.stringify(data),
},
);
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.cookie_token;
}

View File

@@ -1,39 +0,0 @@
/**
* @file web/request/getGachaLog.ts
* @description 获取抽卡记录请求函数
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
/**
* @description 获取抽卡记录
* @since Beta v0.5.0
* @param {string} authkey authkey
* @param {string} gachaType 抽卡类型
* @param {string} endId 结束 id默认为 0
* @returns {Promise<TGApp.Game.Gacha.GachaItem[] | TGApp.BBS.Response.Base>} 抽卡记录
*/
export async function getGachaLog(
authkey: string,
gachaType: string,
endId: string = "0",
): Promise<TGApp.Game.Gacha.GachaItem[] | TGApp.BBS.Response.Base> {
const url = "https://public-operation-hk4e.mihoyo.com/gacha_info/api/getGachaLog";
const params = {
lang: "zh-cn",
auth_appid: "webview_gacha",
authkey,
authkey_ver: "1",
sign_type: "2",
gacha_type: gachaType,
size: "20",
end_id: endId,
};
const resp = await TGHttp<TGApp.Game.Gacha.GachaLogResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.list;
}

View File

@@ -1,67 +0,0 @@
/**
* @file web/request/getGameAccounts.ts
* @description 获取游戏账号信息相关请求函数
* @since Beta v0.6.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import TGConstant from "../constant/TGConstant.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 通过 stoken 获取游戏账号
* @since Alpha v0.1.5
* @param {string} stoken stoken
* @param {string} stuid 登录用户 uid
* @returns {Promise<TGApp.BBS.Account.GameAccount[]|TGApp.BBS.Response.Base>}
*/
export async function getGameAccountsBySToken(
stoken: string,
stuid: string,
): Promise<TGApp.BBS.Account.GameAccount[] | TGApp.BBS.Response.Base> {
const url = TGApi.GameData.bySToken.getAccounts;
const cookie = { stuid, stoken };
const params = { stoken, stuid, game_biz: TGConstant.GAME_BIZ };
return await getGameAccounts(url, cookie, params);
}
/**
* @description 通过 cookie 获取游戏账号
* @since Alpha v0.1.5
* @param {string} cookie_token cookie_token
* @param {string} account_id 游戏账号 id
* @returns {Promise<TGApp.BBS.Account.GameAccount[]|TGApp.BBS.Response.Base>}
*/
export async function getGameAccountsByCookie(
cookie_token: string,
account_id: string,
): Promise<TGApp.BBS.Account.GameAccount[] | TGApp.BBS.Response.Base> {
const url = TGApi.GameData.byCookie.getAccounts;
const cookie = { account_id, cookie_token };
const params = { game_biz: TGConstant.GAME_BIZ };
return await getGameAccounts(url, cookie, params);
}
/**
* @description 获取游戏账号信息
* @since Beta v0.5.0
* @param {string} url 请求地址
* @param {Record<string, string>} cookie cookie
* @param {Record<string, string>} params 请求参数
* @returns {Promise<TGApp.BBS.Account.GameAccount[]|TGApp.BBS.Response.Base>}
*/
async function getGameAccounts(
url: string,
cookie: Record<string, string>,
params: Record<string, string>,
): Promise<TGApp.BBS.Response.Base | TGApp.BBS.Account.GameAccount[]> {
const header = getRequestHeader(cookie, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Response.getGameAccounts | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.list;
}

View File

@@ -1,34 +0,0 @@
/**
* @file core/utils/getGameRecord.ts
* @description 获取游戏数据的函数
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 获取用户游戏数据
* @since Beta v0.5.0
* @description 这边的 ck 可以是 cookie_token 和 account_id
* @description 也可以是 ltoken 和 ltuid
* @param {Record<string, string>} cookie cookie
* @param {TGApp.Sqlite.Account.Game} user 用户的基本信息
* @returns {Promise<TGApp.Game.Record.FullData|TGApp.BBS.Response.Base>} 用户基本信息
*/
export async function getGameRecord(
cookie: Record<string, string>,
user: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Record.FullData | TGApp.BBS.Response.Base> {
const url = TGApi.GameData.getUserBase;
const params = { role_id: user.gameUid, server: user.region };
const header = getRequestHeader(cookie, "GET", params, "common");
const resp = await TGHttp<TGApp.Game.Record.Response | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}

View File

@@ -1,33 +0,0 @@
/**
* @file web/request/getLToken.ts
* @description 获取 ltoken 的请求
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 根据 stoken_v2 获取 ltoken
* @since Beta v0.5.0
* @param {string} Mid 登录用户 mid
* @param {string} Stoken stoken_v2
* @returns {Promise<string|TGApp.BBS.Response.Base>}
*/
export async function getLTokenBySToken(
Mid: string,
Stoken: string,
): Promise<string | TGApp.BBS.Response.Base> {
const url = TGApi.GameTokens.getLToken;
const cookie = { mid: Mid, stoken: Stoken };
const params = { stoken: Stoken };
const header = getRequestHeader(cookie, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Response.getLTokenBySToken | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.ltoken;
}

View File

@@ -1,39 +0,0 @@
/**
* @file web/request/getRoleCombat.ts
* @description 真境剧诗
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 获取剧诗信息
* @since Beta v.0.6.3
* @param {TGApp.App.Account.Cookie} cookie
* @param {TGApp.Sqlite.Account.Game} account
* @returns {Promise<TGApp.Game.Combat.Combat[]|TGApp.BBS.Response.Base|false>}
*/
export async function getRoleCombat(
cookie: TGApp.App.Account.Cookie,
account: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Combat.Combat[] | TGApp.BBS.Response.Base | false> {
const url = TGApi.GameData.getRoleCombat;
const params = { role_id: account.gameUid, server: account.region, active: 1, need_detail: true };
const ck = {
account_id: cookie.account_id,
cookie_token: cookie.cookie_token,
ltoken: cookie.ltoken,
ltuid: cookie.ltuid,
};
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.Game.Combat.Response | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode != 0) return <TGApp.BBS.Response.Base>resp;
if (!resp.data.is_unlock) return false;
return resp.data.data;
}

View File

@@ -1,61 +0,0 @@
/**
* @file web/request/getStoken.ts
* @description 获取 stoken
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGConstant from "../constant/TGConstant.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 获取 stoken
* @since Beta v0.5.0
* @param {string} accountId 账户 ID
* @param {string} token 游戏 Token
* @param {string} isGameToken 是否为游戏 Token
* @returns {Promise<TGApp.BBS.Response.getStokenByGameTokenData | TGApp.BBS.Response.Base>}
*/
export async function getStokenByGameToken(
accountId: string,
token: string,
isGameToken: boolean,
): Promise<TGApp.BBS.Response.getStokenByGameTokenData | TGApp.BBS.Response.Base> {
let url = "https://api-takumi.mihoyo.com/account/ma-cn-session/app/getSTokenByGameToken";
if (isGameToken) {
url = "https://api-takumi.mihoyo.com/account/ma-cn-session/app/getTokenByGameToken";
}
const data = { account_id: Number(accountId), game_token: token };
const header = { "x-rpc-app_id": TGConstant.BBS.APP_ID };
const resp = await TGHttp<TGApp.BBS.Response.getStokenByGameToken | TGApp.BBS.Response.Base>(
url,
{ method: "POST", headers: header, body: JSON.stringify(data) },
);
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}
/**
* @description stoken v1 到 v2
* @since Beta v0.5.0
* @param {string} stoken 账户 ID
* @param {string} stuid 游戏 Token
* @returns {Promise<TGApp.BBS.Response.getStokenByGameTokenData | TGApp.BBS.Response.Base>}
*/
export async function getTokenBySToken(
stoken: string,
stuid: string,
): Promise<TGApp.BBS.Response.getTokenBySTokenData | TGApp.BBS.Response.Base> {
const url = "https://passport-api.mihoyo.com/account/ma-cn-session/app/getTokenBySToken";
const cookie = { stoken, stuid };
const header = {
"x-rpc-app_id": TGConstant.BBS.APP_ID,
...getRequestHeader(cookie, "POST", "", "prod"),
};
const resp = await TGHttp<TGApp.BBS.Response.getTokenBySToken | TGApp.BBS.Response.Base>(url, {
method: "POST",
headers: header,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}

View File

@@ -1,33 +0,0 @@
/**
* @file web/request/getUserCollect.ts
* @description 获取用户收藏请求模块
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 获取用户收藏帖子
* @since Beta v0.5.0
* @param {Record<string, string>} cookie - 用户 cookie
* @param {string} uid - 用户 uid
* @param {string} offset - 偏移量
* @returns {Promise<TGApp.BBS.Collection.PostRespData|TGApp.BBS.Response.Base>} 用户收藏帖子
*/
export async function getUserCollect(
cookie: Record<string, string>,
uid: string,
offset: string = "",
): Promise<TGApp.BBS.Collection.PostRespData | TGApp.BBS.Response.Base> {
const url = "https://bbs-api.miyoushe.com/post/wapi/userFavouritePost";
const params = { size: "20", uid, offset };
const header = getRequestHeader(cookie, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Collection.PostResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}

View File

@@ -1,36 +0,0 @@
/**
* @file web/request/getUserInfo.ts
* @description 获取用户信息请求
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 根据 cookie 获取用户信息
* @since Beta v0.5.0
* @param {string} cookie_token cookie token
* @param {string} account_id 用户 account_id
* @returns {Promise<TGApp.BBS.Response.Base | TGApp.Plugins.Mys.User.Info>}
*/
export async function getUserInfoByCookie(
cookie_token: string,
account_id: string,
): Promise<TGApp.BBS.Response.Base | TGApp.Plugins.Mys.User.Info> {
const cookie = {
cookie_token,
account_id,
};
const url = TGApi.GameData.byCookie.getUserInfo;
const params = { gids: "2" };
const header = getRequestHeader(cookie, "GET", params, "common", true);
const resp = await TGHttp<TGApp.Plugins.Mys.User.HomeResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.user_info;
}

View File

@@ -1,7 +1,7 @@
/**
* @file web/request/getAnnouncement.ts
* @description
* @since Beta v0.6.0
* @file web/request/hk4eReq.ts
* @description Hk4eApi
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
@@ -56,7 +56,7 @@ function getAnnoParams(
* @param {AnnoLang} lang
* @returns {Promise<TGApp.BBS.Announcement.ListData>}
*/
export async function getAnnoList(
async function getAnnoList(
region: AnnoServer = AnnoServer.CN_ISLAND,
lang: AnnoLang = "zh-cn",
): Promise<TGApp.BBS.Announcement.ListData> {
@@ -80,7 +80,7 @@ export async function getAnnoList(
* @param {AnnoLang} lang
* @returns {Promise<TGApp.BBS.Announcement.ContentItem>}
*/
export async function getAnnoContent(
async function getAnnoContent(
annId: number,
region: AnnoServer = AnnoServer.CN_ISLAND,
lang: AnnoLang = "zh-cn",
@@ -101,3 +101,45 @@ export async function getAnnoContent(
throw new Error("公告内容不存在");
}
}
/**
* @description
* @since Beta v0.5.0
* @param {string} authKey authKey
* @param {string} gachaType
* @param {string} endId id 0
* @returns {Promise<TGApp.Game.Gacha.GachaItem[] | TGApp.BBS.Response.Base>}
*/
async function getGachaLog(
authKey: string,
gachaType: string,
endId: string = "0",
): Promise<TGApp.Game.Gacha.GachaItem[] | TGApp.BBS.Response.Base> {
const url = "https://public-operation-hk4e.mihoyo.com/gacha_info/api/getGachaLog";
const params = {
lang: "zh-cn",
auth_appid: "webview_gacha",
authkey: authKey,
authkey_ver: "1",
sign_type: "2",
gacha_type: gachaType,
size: "20",
end_id: endId,
};
const resp = await TGHttp<TGApp.Game.Gacha.GachaLogResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.list;
}
const Hk4eApi = {
anno: {
list: getAnnoList,
content: getAnnoContent,
},
gacha: getGachaLog,
};
export default Hk4eApi;

View File

@@ -1,7 +1,7 @@
/**
* @file src/web/request/getDeviceFp.ts
* @description
* @since Beta v0.5.5
* @file web/request/otherReq.ts
* @description Other API
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
@@ -15,7 +15,7 @@ import TGConstant from "../constant/TGConstant.js";
* @param {TGApp.App.Device.DeviceInfo} Info -
* @returns {Promise<TGApp.App.Device.DeviceInfo>}
*/
export async function getDeviceFp(
async function getDeviceFp(
Info?: TGApp.App.Device.DeviceInfo,
): Promise<TGApp.App.Device.DeviceInfo> {
const info = Info ?? getInitDeviceInfo();
@@ -86,7 +86,7 @@ export async function getDeviceFp(
device_fp: info.device_fp,
};
const header = {
"User-Agent": `Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/${TGConstant.BBS.VERSION}`,
"User-Agent": TGConstant.BBS.UA_MOBILE,
"x-rpc-app_version": TGConstant.BBS.VERSION,
"x-rpc-client_type": "5",
"x-requested-with": "com.mihoyo.hyperion",
@@ -109,3 +109,29 @@ export async function getDeviceFp(
}
return info;
}
/**
* @description
* @since Beta v0.5.3
* @param {string} actId - id
* @return {Promise<TGApp.BBS.Navigator.CodeData[]|TGApp.BBS.Response.Base>}
*/
async function refreshCode(
actId: string,
): Promise<TGApp.BBS.Navigator.CodeData[] | TGApp.BBS.Response.Base> {
const url = "https://api-takumi-static.mihoyo.com/event/miyolive/refreshCode";
const header = { "x-rpc-act_id": actId };
const res = await TGHttp<TGApp.BBS.Navigator.CodeResponse | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
});
if (res.retcode !== 0) return <TGApp.BBS.Response.Base>res;
return res.data.code_list;
}
const OtherApi = {
code: refreshCode,
fp: getDeviceFp,
};
export default OtherApi;

View File

@@ -0,0 +1,126 @@
/**
* @file web/request/passportReq.ts
* @description Passport 相关请求
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
// PassportApiBaseUrl => pAbu
const pAbu = "https://passport-api.mihoyo.com/";
// PassportV4ApiBaseUrl => p4Abu
const p4Abu = "https://passport-api-v4.mihoyo.com/";
/**
* @description 获取登录ticket
* @since Beta v0.6.0
* @param {TGApp.Sqlite.Account.Game} account - 账户
* @param {TGApp.App.Account.Cookie} cookie - cookie
* @returns {Promise<TGApp.BBS.Response.Base|string>}
*/
async function createAuthTicketByGameBiz(
account: TGApp.Sqlite.Account.Game,
cookie: TGApp.App.Account.Cookie,
): Promise<TGApp.BBS.Response.Base | string> {
const url = `${pAbu}account/ma-cn-verifier/app/createAuthTicketByGameBiz`;
const params = {
game_biz: account.gameBiz,
stoken: cookie.stoken,
uid: account.gameUid,
mid: cookie.mid,
};
const header = {
"x-rpc-client_type": "3",
"x-rpc-app_id": "ddxf5dufpuyo",
};
const resp = await TGHttp<TGApp.BBS.Response.getAuthTicketByGameBiz>(url, {
method: "POST",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.ticket;
}
/**
* @description 根据 stoken 获取 cookie_token
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @returns {Promise<string|TGApp.BBS.Response.Base>}
*/
async function getCookieAccountInfoBySToken(
cookie: TGApp.App.Account.Cookie,
): Promise<string | TGApp.BBS.Response.Base> {
const url = `${pAbu}account/auth/api/getCookieAccountInfoBySToken`;
const ck = { stoken: cookie.stoken, mid: cookie.mid };
const params = { stoken: cookie.stoken };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Response.getCookieTokenBySToken | TGApp.BBS.Response.Base>(
url,
{
method: "GET",
headers: header,
query: params,
},
);
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.cookie_token;
}
/**
* @description 根据 stoken_v2 获取 ltoken
* @since Beta v0.5.0
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @returns {Promise<string|TGApp.BBS.Response.Base>}
*/
async function getLTokenBySToken(
cookie: TGApp.App.Account.Cookie,
): Promise<string | TGApp.BBS.Response.Base> {
const url = `${pAbu}account/auth/api/getLTokenBySToken`;
const ck = { mid: cookie.mid, stoken: cookie.stoken };
const params = { stoken: cookie.stoken };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Response.getLTokenBySToken | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.ltoken;
}
/**
* @description 验证 ltoken 有效性,返回 mid
* @since Beta v0.5.0
* @param {TGApp.App.Account.Cookie} cookie - 账户 cookie
* @returns {Promise<string | TGApp.BBS.Response.Base>}
*/
async function verifyLToken(
cookie: TGApp.App.Account.Cookie,
): Promise<string | TGApp.BBS.Response.Base> {
const url = `${p4Abu}account/ma-cn-session/web/verifyLtoken`;
const ck = { ltoken: cookie.ltoken, ltuid: cookie.ltuid };
const data = { ltoken: cookie.ltoken };
const header = getRequestHeader(ck, "POST", data, "common");
const resp = await TGHttp<TGApp.BBS.Response.verifyUserInfoBySToken | TGApp.BBS.Response.Base>(
url,
{
method: "POST",
headers: header,
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,
},
};
export default PassportApi;

View File

@@ -0,0 +1,158 @@
/**
* @file web/request/record/genshinReq.ts
* @description TakumiRecordGenshinApi 相关请求
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
// TakumiRecordGenshinApiBaseUrl => trgAbu
const trgAbu = "https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/";
/**
* @description 获取角色详情
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @param {string[]} avatarIds 角色 id 列表
* @returns {Promise<TGApp.Game.Avatar.AvatarDetail | TGApp.BBS.Response.Base>}
*/
async function characterDetail(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
avatarIds: string[],
): Promise<TGApp.Game.Avatar.AvatarDetail | TGApp.BBS.Response.Base> {
const url = `${trgAbu}character/detail`;
const ck = { account_id: cookie.account_id, cookie_token: cookie.cookie_token };
const data = { role_id: user.gameUid, server: user.region, character_ids: avatarIds };
const header = getRequestHeader(ck, "POST", data, "common");
const resp = await TGHttp<TGApp.Game.Avatar.DetailResponse | TGApp.BBS.Response.Base>(url, {
method: "POST",
body: JSON.stringify(data),
headers: header,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}
/**
* @description 获取角色列表
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @returns {Promise<TGApp.Game.Avatar.Avatar[] | TGApp.BBS.Response.Base>}
*/
async function characterList(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Avatar.Avatar[] | TGApp.BBS.Response.Base> {
const url = `${trgAbu}character/list`;
const ck = { account_id: cookie.account_id, cookie_token: cookie.cookie_token };
const data = { role_id: user.gameUid, server: user.region };
const header = getRequestHeader(ck, "POST", data, "common");
const resp = await TGHttp<TGApp.Game.Avatar.ListResponse | TGApp.BBS.Response.Base>(url, {
method: "POST",
body: JSON.stringify(data),
headers: header,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.list;
}
/**
* @description 获取首页信息
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @returns {Promise<TGApp.Game.Record.FullData | TGApp.BBS.Response.Base>}
*/
async function index(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Record.FullData | TGApp.BBS.Response.Base> {
const url = `${trgAbu}index`;
const ck = { account_id: cookie.account_id, cookie_token: cookie.cookie_token };
const params = { avatar_list_type: 1, role_id: user.gameUid, server: user.region };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.Game.Record.Response | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}
/**
* @description 获取真境剧诗数据
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @returns {Promise<TGApp.Game.Combat.Combat[] | TGApp.BBS.Response.Base|false>}
*/
async function roleCombat(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
): Promise<TGApp.Game.Combat.Combat[] | TGApp.BBS.Response.Base | false> {
const url = `${trgAbu}role_combat`;
const ck = {
account_id: cookie.account_id,
cookie_token: cookie.cookie_token,
ltoken: cookie.ltoken,
ltuid: cookie.ltuid,
};
const params = { role_id: user.gameUid, server: user.region, active: 1, need_detail: true };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.Game.Combat.Response | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
if (!resp.data.is_unlock) return false;
return resp.data.data;
}
/**
* @description 获取深渊螺旋记录
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @param {string} schedule 1: 本期, 2: 上期
* @returns {Promise<TGApp.Game.Abyss.FullData | TGApp.BBS.Response.Base>}
*/
async function spiralAbyss(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
schedule: string,
): Promise<TGApp.Game.Abyss.FullData | TGApp.BBS.Response.Base> {
const url = `${trgAbu}spiralAbyss`;
const ck = {
account_id: cookie.account_id,
cookie_token: cookie.cookie_token,
ltoken: cookie.ltoken,
ltuid: cookie.ltuid,
};
const params = { role_id: user.gameUid, schedule_type: schedule, server: user.region };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.Game.Abyss.Response | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data;
}
const TakumiRecordGenshinApi = {
index: index,
character: {
list: characterList,
detail: characterDetail,
},
roleCombat: roleCombat,
spiralAbyss: spiralAbyss,
};
export default TakumiRecordGenshinApi;

View File

@@ -0,0 +1,121 @@
/**
* @file web/request/takumiReq.ts
* @description Takumi 相关请求函数
* @since Beta v0.6.3
*/
import TGHttp from "../../utils/TGHttp.js";
import TGConstant from "../constant/TGConstant.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
// TakumiAuthApiBaseUrl => taAbu
const taAbu = "https://api-takumi.mihoyo.com/auth/api/";
// TakumiBingApiBaseUrl => tbAbu
const tbAbu = "https://api-takumi.mihoyo.com/binding/api/";
/**
* @description 根据stoken获取action_ticket
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie Cookie
* @param {TGApp.Sqlite.Account.Game} user 用户
* @param {string} actionType 动作类型
* @returns {Promise<TGApp.BBS.Response.getActionTicketBySToken>}
*/
async function getActionTicketBySToken(
cookie: TGApp.App.Account.Cookie,
user: TGApp.Sqlite.Account.Game,
actionType: string,
): Promise<TGApp.BBS.Response.getActionTicketBySToken> {
const url = `${taAbu}getActionTicketBySToken`;
const ck = { stoken: cookie.stoken, mid: cookie.mid };
const params = { action_type: actionType, stoken: cookie.stoken, uid: user.gameUid };
const header = getRequestHeader(ck, "GET", params, "k2");
return await TGHttp<TGApp.BBS.Response.getActionTicketBySToken>(url, {
method: "GET",
headers: header,
query: params,
});
}
/**
* @description 生成authkey
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie cookie
* @param {TGApp.Sqlite.Account.Game} account 账户
* @return {Promise<string|TGApp.BBS.Response.Base>} authkey
*/
async function genAuthKey(
cookie: TGApp.App.Account.Cookie,
account: TGApp.Sqlite.Account.Game,
): Promise<string | TGApp.BBS.Response.Base> {
const url = `${tbAbu}genAuthKey`;
const ck = { stoken: cookie.stoken, mid: cookie.mid };
const data = {
auth_appid: "webview_gacha",
game_biz: account.gameBiz,
game_uid: account.gameUid,
region: account.region,
};
const header = getRequestHeader(ck, "POST", JSON.stringify(data), "lk2", true);
const resp = await TGHttp<TGApp.Game.Gacha.AuthkeyResponse | TGApp.BBS.Response.Base>(url, {
method: "POST",
headers: header,
body: JSON.stringify(data),
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.authkey;
}
/**
* @description 生成authkey-v2专门用于JSBridge
* @since Beta v0.6.3
* @param {Record<string,string>} cookie cookie
* @param {Record<string,string>} payload payload
* @returns {Promise<TGApp.BBS.Response.Base>}
*/
async function genAuthKey2(
cookie: Record<string, string>,
payload: Record<string, string>,
): Promise<TGApp.BBS.Response.Base> {
const url = `${tbAbu}genAuthKey`;
const header = getRequestHeader(cookie, "POST", JSON.stringify(payload), "lk2", true);
return await TGHttp<TGApp.BBS.Response.Base>(url, {
method: "POST",
headers: header,
body: JSON.stringify(payload),
});
}
/**
* @description 通过cookie获取游戏账号
* @since Beta v0.6.3
* @param {TGApp.App.Account.Cookie} cookie cookie
* @returns {Promise<TGApp.BBS.Account.GameAccount[]|TGApp.BBS.Response.Base>}
*/
async function getUserGameRolesByCookie(
cookie: TGApp.App.Account.Cookie,
): Promise<TGApp.BBS.Account.GameAccount[] | TGApp.BBS.Response.Base> {
const url = `${tbAbu}getUserGameRolesByCookie`;
const ck = { account_id: cookie.account_id, cookie_token: cookie.cookie_token };
const params = { game_biz: TGConstant.GAME_BIZ };
const header = getRequestHeader(ck, "GET", params, "common");
const resp = await TGHttp<TGApp.BBS.Response.getGameAccounts | TGApp.BBS.Response.Base>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.list;
}
const TakumiApi = {
auth: {
actionTicket: getActionTicketBySToken,
},
bind: {
authKey: genAuthKey,
authKey2: genAuthKey2,
gameRoles: getUserGameRolesByCookie,
},
};
export default TakumiApi;

View File

@@ -1,36 +0,0 @@
/**
* @file web/request/verifyLToken.ts
* @description 验证 stoken 的请求函数
* @since Beta v0.5.0
*/
import TGHttp from "../../utils/TGHttp.js";
import TGApi from "../api/TGApi.js";
import { getRequestHeader } from "../utils/getRequestHeader.js";
/**
* @description 验证 ltoken 有效性,返回 mid
* @since Beta v0.5.0
* @param {string} ltoken ltoken
* @param {string} ltuid 登录用户 uid
* @returns {Promise<string | TGApp.BBS.Response.Base>}
*/
export async function verifyLToken(
ltoken: string,
ltuid: string,
): Promise<string | TGApp.BBS.Response.Base> {
const url = TGApi.GameTokens.verifyLToken;
const cookie = { ltoken, ltuid };
const data = { ltoken };
const header = getRequestHeader(cookie, "POST", data, "common");
const resp = await TGHttp<TGApp.BBS.Response.verifyUserInfoBySToken | TGApp.BBS.Response.Base>(
url,
{
method: "POST",
headers: header,
body: JSON.stringify(data),
},
);
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
return resp.data.user_info.mid;
}

View File

@@ -11,14 +11,16 @@ import TGConstant from "../constant/TGConstant.js";
import { transCookie, transParams } from "./tools.js";
type SaltType = "common" | "prod" | "lk2" | "k2";
/**
* @description 获取 salt
* @since Beta v0.3.3
* @since Beta v0.6.3
* @version 2.59.1
* @param {string} saltType salt 类型
* @param {SaltType} saltType salt 类型
* @returns {string} salt
*/
function getSalt(saltType: string): string {
function getSalt(saltType: SaltType): string {
switch (saltType) {
case "common":
return TGConstant.Salt.X4;
@@ -26,6 +28,8 @@ function getSalt(saltType: string): string {
return TGConstant.Salt.PROD;
case "lk2":
return TGConstant.Salt.LK2;
case "k2":
return TGConstant.Salt.K2;
default:
return TGConstant.Salt.X4;
}
@@ -48,11 +52,11 @@ function getRandomNumber(min: number, max: number): number {
* @version 2.50.1
* @param {string} method 请求方法
* @param {string} data 请求数据
* @param {string} saltType salt 类型
* @param {SaltType} saltType salt 类型
* @param {boolean} isSign 是否为签名
* @returns {string} ds
*/
function getDS(method: string, data: string, saltType: string, isSign: boolean): string {
function getDS(method: string, data: string, saltType: SaltType, isSign: boolean): string {
const salt = getSalt(saltType);
const time = Math.floor(Date.now() / 1000).toString();
let random = getRandomNumber(100000, 200000).toString();
@@ -71,7 +75,7 @@ function getDS(method: string, data: string, saltType: string, isSign: boolean):
* @param {Record<string, string>} cookie cookie
* @param {string} method 请求方法
* @param {Record<string, string|number|string[]|boolean>|string} data 请求数据
* @param {string} saltType salt 类型
* @param {SaltType} saltType salt 类型
* @param {boolean} isSign 是否为签名
* @returns {Record<string, string>} 请求头
*/
@@ -79,7 +83,7 @@ export function getRequestHeader(
cookie: Record<string, string>,
method: string,
data: Record<string, string | number | string[] | boolean> | string,
saltType: string,
saltType: SaltType,
isSign: boolean = false,
): Record<string, string> {
let ds;
@@ -104,21 +108,21 @@ export function getRequestHeader(
/**
* @description 获取 DS
* @since Beta v0.3.9
* @param {string} saltType salt 类型
* @param {SaltType} saltType salt 类型
* @param {number} dsType ds 类型
* @param {Record<string, string|number>|string} body
* @param {Record<string, string|number>|string} query
* @returns {string} DS
*/
export function getDS4JS(saltType: string, dsType: 1, body: undefined, query: undefined): string;
export function getDS4JS(saltType: SaltType, dsType: 1, body: undefined, query: undefined): string;
export function getDS4JS(
saltType: string,
saltType: SaltType,
dsType: 2,
body: Record<string, string | number> | string,
query: Record<string, string | number> | string,
): string;
export function getDS4JS(
saltType: string,
saltType: SaltType,
dsType: 1 | 2,
body?: Record<string, string | number> | string,
query?: Record<string, string | number> | string,