🌱 祈愿相关接口&类型

#202
This commit is contained in:
BTMuli
2026-01-04 05:15:31 +08:00
parent f0c78a3b03
commit 2c451c3c01
7 changed files with 209 additions and 39 deletions

View File

@@ -31,7 +31,7 @@ async function test() {
if (!hutaoStore.checkIsValid()) {
await hutaoStore.tryRefreshToken();
}
const resp = await hutao.Account.info(accessToken.value!);
const resp = await hutao.Gacha.entry(accessToken.value!);
if ("retcode" in resp) {
showSnackbar.warn(`${resp.retcode}-${resp.message}`);
return;

View File

@@ -14,6 +14,7 @@ import {
} from "./request/abyssReq.js";
import { getUserInfo, loginPassport, refreshToken } from "./request/accountReq.js";
import { getCombatStatistic, uploadCombatData } from "./request/combatReq.js";
import { getEndIds, getEntries, getGachaLogs } from "./request/gachaReq.js";
import { transAbyssAvatars, transAbyssLocal } from "./utils/abyssUtil.js";
import { transCombatLocal } from "./utils/combatUtil.js";
@@ -49,15 +50,17 @@ const Hutao = {
username: _,
password: _,
},
token: {
refresh: refreshToken,
revoke: _,
revokeAll: _,
},
info: getUserInfo,
},
Token: {
refresh: refreshToken,
revoke: _,
revokeAll: _,
},
Gacha: {
log: _,
entry: getEntries,
endIds: getEndIds,
logs: getGachaLogs,
upload: _,
delete: _,
},

View File

@@ -4,41 +4,11 @@
*/
import TGHttp from "@utils/TGHttp.js";
import { importPublicKey, sha1 } from "rsa-oaep-encryption";
import { getReqHeader } from "../utils/authUtils.js";
/** 加密公钥 */
const HUTAO_PUB_KEY: Readonly<string> = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5W2SEyZSlP2zBI1Sn8Gd
TwbZoXlUGNKyoVrY8SVYu9GMefdGZCrUQNkCG/Np8pWPmSSEFGd5oeug/oIMtCZQ
NOn0drlR+pul/XZ1KQhKmj/arWjN1XNok2qXF7uxhqD0JyNT/Fxy6QvzqIpBsM9S
7ajm8/BOGlPG1SInDPaqTdTRTT30AuN+IhWEEFwT3Ctv1SmDupHs2Oan5qM7Y3uw
b6K1rbnk5YokiV2FzHajGUymmSKXqtG1USZzwPqImpYb4Z0M/StPFWdsKqexBqMM
mkXckI5O98GdlszEmQ0Ejv5Fx9fR2rXRwM76S4iZTfabYpiMbb4bM42mHMauupj6
9QIDAQAB
-----END PUBLIC KEY-----`;
const encrypt = importPublicKey(HUTAO_PUB_KEY);
import { getReqHeader, rsaEncrypt } from "../utils/authUtils.js";
const PassportUrl = "https://homa.gentle.house/Passport/v2/";
/**
* rsa 加密
* @since Beta v0.9.1
* @param data - 待加密数据
* @returns 加密后数据
*/
function rsaEncrypt(data: string): string {
const res = encrypt.encrypt(data, sha1.create());
const bytes = new Uint8Array(res);
let binary = "";
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
/**
* 登录
* @since Beta v0.9.1

View File

@@ -0,0 +1,80 @@
/**
* 祈愿相关请求
* @since Beta v0.9.1
*/
import { getReqHeader } from "@Hutao/utils/authUtils.js";
import TGHttp from "@utils/TGHttp.js";
const GachaUrl = "https://homa.gentle.house/GachaLog/";
/**
* 获取抽卡入口
* @param tk - token
* @returns 抽卡记录概况
*/
export async function getEntries(
tk: string,
): Promise<TGApp.Plugins.Hutao.Gacha.EntryRes | TGApp.Plugins.Hutao.Base.Resp> {
const url = `${GachaUrl}Entries`;
const header = await getReqHeader(tk);
const resp = await TGHttp<TGApp.Plugins.Hutao.Gacha.EntryResp>(url, {
method: "GET",
headers: header,
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Gacha.EntryRes>resp.data;
}
/**
* 获取抽卡EndId
* @param tk - token
* @param uid - 记录UID
* @returns EndId
*/
export async function getEndIds(
tk: string,
uid: string,
): Promise<TGApp.Plugins.Hutao.Gacha.EndIdRes | TGApp.Plugins.Hutao.Base.Resp> {
const url = `${GachaUrl}EndIds`;
const header = await getReqHeader(tk);
const resp = await TGHttp<TGApp.Plugins.Hutao.Gacha.EndIdResp>(url, {
method: "GET",
headers: header,
query: { Uid: uid },
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Gacha.EndIdRes>resp.data;
}
/**
* 获取抽卡记录
* @since Beta v0.9.1
* @param tk - token
* @param uid - 记录UID
* @param gType - 祈愿类型按照EndId来
* @param endId - endId
* @param count - 尺寸
*/
export async function getGachaLogs(
tk: string,
uid: string,
gType: number,
endId: number,
count: number,
): Promise<TGApp.Plugins.Hutao.Gacha.GachaLogRes | TGApp.Plugins.Hutao.Base.Resp> {
const url = `${GachaUrl}LimitedRetrieve`;
const header = await getReqHeader(tk);
const params = {
uid: uid,
configType: gType,
endId: endId,
count: count,
};
const resp = await TGHttp<TGApp.Plugins.Hutao.Gacha.GachaLogResp>(url, {
method: "GET",
headers: header,
query: params,
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Gacha.GachaLogRes>resp.data;
}

88
src/plugins/Hutao/types/Gacha.d.ts vendored Normal file
View File

@@ -0,0 +1,88 @@
/**
* 祈愿相关
* @since Beta v0.9.1
*/
declare namespace TGApp.Plugins.Hutao.Gacha {
/**
* EntriesResp
* @since Beta v0.9.1
*/
type EntryResp = TGApp.Plugins.Hutao.Base.Resp<EntryRes>;
/**
* EntriesRes
* @since Beta v0.9.1
*/
type EntryRes = Array<EntryItem>;
/**
* EntryItem
* @since Beta v0.9.1
*/
type EntryItem = {
/** UID */
Uid: string;
/** cnt */
ItemCount: number;
/**
* excluded
* @remarks 未知用途
*/
Excluded: boolean;
};
/**
* 获取EndId列表响应
* @since Beta v0.9.1
*/
type EndIdResp = TGApp.Plugins.Hutao.Base.Resp<EndIdRes>;
/**
* EndId返回
* @since Beta v0.9.1
*/
type EndIdRes = {
/** 新手 */
"100": number;
/** 常驻 */
"200": number;
/** 角色活动 */
"301": number;
/** 武器活动 */
"302": number;
/** 集录 */
"500": number;
};
/**
* 祈愿记录返回响应
* @since Beta v0.9.1
*/
type GachaLogResp = TGApp.Plugins.Hutao.Base.Resp<GachaLogRes>;
/**
* 祈愿记录返回
* @since Beta v0.9.1
*/
type GachaLogRes = Array<GachaLog>;
/**
* 祈愿记录
* @since Beta v0.9.1
*/
type GachaLog = {
/** 卡池类型 */
GachaType: number;
/** 卡池类型(UIGF) */
QueryType: number;
/** 物品ID */
ItemId: number;
/**
* 时间
* @example 2023-05-24T02:33:23+00:00
*/
Time: string;
/** Id */
Id: number;
};
}

View File

@@ -4,8 +4,37 @@
*/
import { commands } from "@skipperndt/plugin-machine-uid";
import { getVersion } from "@tauri-apps/api/app";
import { importPublicKey, sha1 } from "rsa-oaep-encryption";
let DEVICE_ID: string | null = null;
/** 加密公钥 */
const HUTAO_PUB_KEY: Readonly<string> = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5W2SEyZSlP2zBI1Sn8Gd
TwbZoXlUGNKyoVrY8SVYu9GMefdGZCrUQNkCG/Np8pWPmSSEFGd5oeug/oIMtCZQ
NOn0drlR+pul/XZ1KQhKmj/arWjN1XNok2qXF7uxhqD0JyNT/Fxy6QvzqIpBsM9S
7ajm8/BOGlPG1SInDPaqTdTRTT30AuN+IhWEEFwT3Ctv1SmDupHs2Oan5qM7Y3uw
b6K1rbnk5YokiV2FzHajGUymmSKXqtG1USZzwPqImpYb4Z0M/StPFWdsKqexBqMM
mkXckI5O98GdlszEmQ0Ejv5Fx9fR2rXRwM76S4iZTfabYpiMbb4bM42mHMauupj6
9QIDAQAB
-----END PUBLIC KEY-----`;
const encrypt = importPublicKey(HUTAO_PUB_KEY);
/**
* rsa 加密
* @since Beta v0.9.1
* @param data - 待加密数据
* @returns 加密后数据
*/
export function rsaEncrypt(data: string): string {
const res = encrypt.encrypt(data, sha1.create());
const bytes = new Uint8Array(res);
let binary = "";
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
/**
* 获取请求头

View File

@@ -78,7 +78,7 @@ const useHutaoStore = defineStore(
return;
}
try {
const resp = await hutao.Account.token.refresh(refreshToken.value);
const resp = await hutao.Token.refresh(refreshToken.value);
if ("retcode" in resp) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
console.error(resp);