mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-03-30 06:19:45 +08:00
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Hutao 插件入口
|
||||
* @since Beta v0.6.3
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
|
||||
import {
|
||||
@@ -12,10 +12,13 @@ import {
|
||||
getTeamCollect,
|
||||
uploadAbyssData,
|
||||
} from "./request/abyssReq.js";
|
||||
import { loginPassport } from "./request/accountReq.js";
|
||||
import { getCombatStatistic, uploadCombatData } from "./request/combatReq.js";
|
||||
import { transAbyssAvatars, transAbyssLocal } from "./utils/abyssUtil.js";
|
||||
import { transCombatLocal } from "./utils/combatUtil.js";
|
||||
|
||||
const _ = "Not Implemented";
|
||||
|
||||
const Hutao = {
|
||||
Abyss: {
|
||||
avatar: {
|
||||
@@ -37,6 +40,27 @@ const Hutao = {
|
||||
data: getCombatStatistic,
|
||||
trans: transCombatLocal,
|
||||
},
|
||||
Account: {
|
||||
register: _,
|
||||
login: loginPassport,
|
||||
verify: _,
|
||||
cancel: _,
|
||||
reset: {
|
||||
username: _,
|
||||
password: _,
|
||||
},
|
||||
token: {
|
||||
refresh: _,
|
||||
revoke: _,
|
||||
revokeAll: _,
|
||||
},
|
||||
info: _,
|
||||
},
|
||||
Gacha: {
|
||||
log: _,
|
||||
upload: _,
|
||||
delete: _,
|
||||
},
|
||||
};
|
||||
|
||||
export default Hutao;
|
||||
|
||||
66
src/plugins/Hutao/request/accountReq.ts
Normal file
66
src/plugins/Hutao/request/accountReq.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 账号相关请求
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
* @param username - 用户名(邮箱)
|
||||
* @param password - 密码
|
||||
* @returns
|
||||
*/
|
||||
export async function loginPassport(
|
||||
username: string,
|
||||
password: string,
|
||||
): Promise<TGApp.Plugins.Hutao.Account.LoginRes | TGApp.Plugins.Hutao.Base.Resp> {
|
||||
const url = `${PassportUrl}Login`;
|
||||
const data = {
|
||||
UserName: rsaEncrypt(username),
|
||||
Password: rsaEncrypt(password),
|
||||
};
|
||||
const header = await getReqHeader();
|
||||
const resp = await TGHttp<TGApp.Plugins.Hutao.Account.LoginResp>(url, {
|
||||
method: "POST",
|
||||
headers: header,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
|
||||
return resp.data;
|
||||
}
|
||||
58
src/plugins/Hutao/types/Account.d.ts
vendored
Normal file
58
src/plugins/Hutao/types/Account.d.ts
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 账号请求相关类型
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
|
||||
declare namespace TGApp.Plugins.Hutao.Account {
|
||||
/**
|
||||
* Passport 请求参数
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
type PassportReqParams = {
|
||||
/** 设备ID */
|
||||
DeviceId: string;
|
||||
/** 邮箱 */
|
||||
UserName: string | null;
|
||||
/**
|
||||
* 新邮箱
|
||||
* @remarks 用于账号迁移
|
||||
*/
|
||||
NewUserName: string | null;
|
||||
/** 密码 */
|
||||
Password: string | null;
|
||||
/** 邮箱验证码 */
|
||||
VerifyCode: string | null;
|
||||
/**
|
||||
* 新邮箱验证码
|
||||
* @remarks 用于账号迁移
|
||||
*/
|
||||
NewVerifyCode: string | null;
|
||||
/** 重置密码Flag */
|
||||
IsResetPassword: boolean;
|
||||
/** 校验邮箱Flag */
|
||||
IsResetUserName: boolean;
|
||||
/** 校验新邮箱Flag */
|
||||
IsResetNewUserName: boolean;
|
||||
/** 注销账号Flag */
|
||||
IsCancelRegistration: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 登录请求响应
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
type LoginResp = TGApp.Plugins.Hutao.Base.Resp<LoginRes>;
|
||||
|
||||
/**
|
||||
* 登录请求返回
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
type LoginRes = {
|
||||
/** token */
|
||||
AccessToken: string;
|
||||
/** expire */
|
||||
ExpiresIn: number;
|
||||
/** refresh */
|
||||
RefreshToken: string;
|
||||
};
|
||||
}
|
||||
27
src/plugins/Hutao/utils/authUtils.ts
Normal file
27
src/plugins/Hutao/utils/authUtils.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 账号认证相关方法
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
import { commands } from "@skipperndt/plugin-machine-uid";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
|
||||
let DEVICE_ID: string | null = null;
|
||||
|
||||
/**
|
||||
* 获取请求头
|
||||
* @since Beta v0.9.1
|
||||
*/
|
||||
export async function getReqHeader(tk?: string): Promise<Record<string, string>> {
|
||||
const version = await getVersion();
|
||||
if (DEVICE_ID === null) {
|
||||
const deviceRes = await commands.getMachineUid();
|
||||
if (deviceRes.status === "ok") DEVICE_ID = deviceRes.data.id;
|
||||
}
|
||||
const device = DEVICE_ID ?? "";
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
"x-hutao-device-id": device,
|
||||
Authorization: tk ? `Bearer ${tk}` : "",
|
||||
"User-Agent": `TeyvatGuide/${version}`,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user