♻️ 迁移hutaoReq

This commit is contained in:
BTMuli
2026-04-15 14:10:14 +08:00
parent 96d63e8e8c
commit f370953d43
16 changed files with 767 additions and 587 deletions

View File

@@ -73,6 +73,8 @@ import TOverlay from "@comp/app/t-overlay.vue";
import showSnackbar from "@comp/func/snackbar.js";
import hutao from "@Hutao/index.js";
import useHutaoStore from "@store/hutao.js";
import TGHttps from "@utils/TGHttps.js";
import TGLogger from "@utils/TGLogger.js";
import { validEmail } from "@utils/toolFunc.js";
import { storeToRefs } from "pinia";
import { onUnmounted, ref, shallowRef, useTemplateRef } from "vue";
@@ -113,11 +115,20 @@ async function tryGetCode(): Promise<void> {
const check = await usernameRef.value.validate();
if (check.length > 0) return;
codeLoad.value = true;
const resp = await hutao.Account.verify.pwd(username.value!);
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
} else {
showSnackbar.success(`${resp.message}`);
try {
const resp = await hutao.Account.verify.pwd(username.value!);
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
await TGLogger.Warn(
`[tco-hutaoVerify][tryGetCode] 获取验证码失败:${resp.retcode} ${resp.message}`,
);
} else {
showSnackbar.success(`${resp.message}`);
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`获取验证码失败:${errMsg}`);
await TGLogger.Error(`[tco-hutaoVerify][tryGetCode] 获取验证码异常:${errMsg}`);
}
codeLoad.value = false;
codeDisabled.value = true;
@@ -146,17 +157,28 @@ async function onSubmit(): Promise<void> {
if (!check.valid) return;
formDisabled.value = true;
formLoad.value = true;
const resp = await hutao.Account.reset.pwd(username.value!, verifyCode.value!, pwd.value!);
formLoad.value = false;
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
try {
const resp = await hutao.Account.reset.pwd(username.value!, verifyCode.value!, pwd.value!);
formLoad.value = false;
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
await TGLogger.Warn(
`[tco-hutaoVerify][onSubmit] 重置密码失败:${resp.retcode} ${resp.message}`,
);
formDisabled.value = false;
return;
}
showSnackbar.success(`${resp.message}`);
await hutaoStore.autoLogin(username.value!, pwd.value!);
formDisabled.value = false;
visible.value = false;
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
formLoad.value = false;
showSnackbar.error(`重置密码失败:${errMsg}`);
await TGLogger.Error(`[tco-hutaoVerify][onSubmit] 重置密码异常:${errMsg}`);
formDisabled.value = false;
return;
}
showSnackbar.success(`${resp.message}`);
await hutaoStore.autoLogin(username.value!, pwd.value!);
formDisabled.value = false;
visible.value = false;
}
onUnmounted(() => {

View File

@@ -37,6 +37,8 @@ import showSnackbar from "@comp/func/snackbar.js";
import hutao from "@Hutao/index.js";
import TSUserGacha from "@Sqlm/userGacha.js";
import useHutaoStore from "@store/hutao.js";
import TGHttps from "@utils/TGHttps.js";
import TGLogger from "@utils/TGLogger.js";
import { storeToRefs } from "pinia";
import { computed, ref, shallowRef, watch } from "vue";
@@ -103,13 +105,23 @@ async function loadDownload(): Promise<void> {
if (!accessToken.value) return;
try {
const info = await hutao.Gacha.entry(accessToken.value);
if ("retcode" in info) {
if (info.retcode !== 0) {
showSnackbar.warn(`[${info.retcode}] ${info.message}`);
await TGLogger.Warn(
`[ugo-hutao-du][loadDownload] 获取入口数据失败:${info.retcode} ${info.message}`,
);
return;
}
uidList.value = info.map((i) => ({ uid: i.Uid, cnt: i.ItemCount }));
if (!info.data) {
showSnackbar.warn("获取入口数据返回为空");
await TGLogger.Warn(`[ugo-hutao-du][loadDownload] 获取入口数据返回为空`);
return;
}
uidList.value = info.data.map((i) => ({ uid: i.Uid, cnt: i.ItemCount }));
} catch (e) {
console.error(e);
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`获取入口数据失败:${errMsg}`);
await TGLogger.Error(`[ugo-hutao-du][loadDownload] 获取入口数据异常:${errMsg}`);
}
}

View File

@@ -340,7 +340,7 @@ async function tryReadAbyss(): Promise<void> {
showSnackbar.warn("文件数据格式错误");
return;
}
if (!Hutao.raw.valid.abyss(fileData)) {
if (!Hutao.valid.abyss(fileData)) {
await showLoading.end();
showSnackbar.warn("深渊数据验证失败,请检查数据格式");
return;
@@ -355,7 +355,6 @@ async function tryReadAbyss(): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
window.location.reload();
} catch (e) {
console.error(e);
await TGLogger.Error(`[UserAbyss][tryReadAbyss] 导入深渊数据失败: ${e}`);
await showLoading.end();
showSnackbar.error("导入深渊数据失败,请检查文件格式是否正确");
@@ -390,7 +389,6 @@ async function uploadAbyss(): Promise<void> {
return;
}
const gcFind = await TSUserAccount.game.getAccountByGid(uidCur.value!.toString());
console.log(uidCur.value, gcFind);
if (!gcFind) {
showSnackbar.warn(`未找到 ${uidCur.value} 对应 UID无法刷新角色数据进行上传`);
return;
@@ -400,42 +398,58 @@ async function uploadAbyss(): Promise<void> {
showSnackbar.warn(`未找到 ${uidCur.value} 对应 CK无法刷新角色数据进行上传`);
return;
}
await showLoading.start(`正在上传 ${gcFind.gameUid} 的深渊数据`, `期数:${abyssData.id}`);
const transAbyss = Hutao.Abyss.utils.transData(abyssData);
if (userName.value) transAbyss.ReservedUserName = userName.value;
const check = await refreshAvatars(acFind.cookie!, gcFind);
if (!check) {
await showLoading.end();
return;
}
let roles: Array<TGApp.Sqlite.Character.TableTrans> | undefined;
try {
await showLoading.start(`正在上传 ${gcFind.gameUid} 的深渊数据`, `期数:${abyssData.id}`);
const transAbyss = Hutao.Abyss.utils.transData(abyssData);
if (userName.value) transAbyss.ReservedUserName = userName.value;
const check = await refreshAvatars(acFind.cookie!, gcFind);
if (!check) return;
const roles = await TSUserAvatar.getAvatars(Number(gcFind.gameUid));
roles = await TSUserAvatar.getAvatars(Number(gcFind.gameUid));
if (!roles) {
await showLoading.end();
showSnackbar.warn("未找到角色数据");
return;
}
await showLoading.update("正在转换角色数据");
transAbyss.Avatars = Hutao.Abyss.utils.transAvatars(roles);
await showLoading.update("正在上传深渊数据");
console.log("uploadAbyss", transAbyss);
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.end();
showSnackbar.error(`获取角色数据失败:${errMsg}`);
await TGLogger.Error(`[Abyss][uploadAbyss] 获取角色数据异常:${errMsg}`);
return;
}
await showLoading.update("正在转换角色数据");
transAbyss.Avatars = Hutao.Abyss.utils.transAvatars(roles);
await showLoading.update("正在上传深渊数据");
try {
const res = await Hutao.Abyss.upload(transAbyss);
if (res.retcode !== 0) {
showSnackbar.error(`[${res.retcode}]${res.message}`);
await TGLogger.Warn("[Abyss][uploadAbyss] 上传深渊数据失败");
await TGLogger.Warn(`[Abyss][uploadAbyss] ${res.retcode} ${res.message}`);
await showLoading.end();
showSnackbar.warn(`[${res.retcode}]${res.message}`);
await TGLogger.Warn(`[Abyss][uploadAbyss] 上传深渊数据失败:${res.retcode} ${res.message}`);
return;
}
showSnackbar.success(res.message ?? "上传深渊数据成功,即将刷新祈愿时长");
await TGLogger.Info("[Abyss][uploadAbyss] 上传深渊数据成功");
await TGLogger.Info(`[${res.retcode}] ${res.message}`);
// 等待5s刷新时长
await showLoading.update("正在刷新胡桃云数据");
await new Promise<void>((resolve) => setTimeout(resolve, 5000));
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.end();
showSnackbar.error(`上传深渊数据失败:${errMsg}`);
await TGLogger.Error(`[Abyss][uploadAbyss] 上传深渊数据异常:${errMsg}`);
return;
}
await showLoading.update("正在刷新胡桃云数据");
await new Promise<void>((resolve) => setTimeout(resolve, 5000));
try {
await hutaoStore.tryRefreshInfo();
} catch (e) {
if (e instanceof Error) {
showSnackbar.error(e.message);
await TGLogger.Error("[Abyss][uploadAbyss] 上传深渊数据失败");
await TGLogger.Error(`[Abyss][uploadAbyss] ${e.message}`);
}
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`刷新胡桃云数据失败:${errMsg}`);
await TGLogger.Error(`[Abyss][uploadAbyss] 刷新胡桃云数据异常:${errMsg}`);
}
await showLoading.end();
}

View File

@@ -394,7 +394,7 @@ async function tryReadChallenge(): Promise<void> {
showSnackbar.warn("文件数据格式错误");
return;
}
if (!Hutao.raw.valid.challenge(fileData)) {
if (!Hutao.valid.challenge(fileData)) {
await showLoading.end();
showSnackbar.warn("危战数据验证失败,请检查数据格式");
return;

View File

@@ -241,13 +241,20 @@ async function hideAllOverlay(): Promise<void> {
async function loadWiki(): Promise<void> {
await showLoading.start("正在加载统计数据");
const res = await Hutao.Combat.data();
if (res === undefined) showSnackbar.error("未获取到剧诗数据");
else if ("retcode" in res) {
showSnackbar.warn(`[${res.retcode}] ${res.message}`);
await TGLogger.Warn(`[Combat][loadWiki] ${JSON.stringify(res)}`);
} else cloudCombat.value = res;
showSnackbar.success("成功获取统计数据");
try {
const res = await Hutao.Combat.data();
if (res.retcode !== 0) {
showSnackbar.warn(`[${res.retcode}] ${res.message}`);
await TGLogger.Warn(`[Combat][loadWiki] ${res.retcode} ${res.message}`);
} else {
cloudCombat.value = res.data;
showSnackbar.success("成功获取统计数据");
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`获取统计数据失败:${errMsg}`);
await TGLogger.Error(`[Combat][loadWiki] 获取统计数据异常:${errMsg}`);
}
await hideAllOverlay();
await showLoading.end();
showStat.value = true;
@@ -474,16 +481,15 @@ async function uploadCombat(): Promise<void> {
showSnackbar.success(res.message ?? "上传剧诗数据成功");
await TGLogger.Info("[UserCombat][uploadCombat] 上传剧诗数据成功");
} else {
showSnackbar.error(`[${res.retcode}]${res.message}`);
await TGLogger.Error("[UserCombat][uploadCombat] 上传剧诗数据失败");
await TGLogger.Error(`[UserCombat][uploadCombat] ${res.retcode} ${res.message}`);
showSnackbar.warn(`[${res.retcode}]${res.message}`);
await TGLogger.Warn(
`[UserCombat][uploadCombat] 上传剧诗数据失败:${res.retcode} ${res.message}`,
);
}
} catch (e) {
if (e instanceof Error) {
showSnackbar.error(e.message);
await TGLogger.Error("[UserCombat][uploadCombat] 上传剧诗数据失败");
await TGLogger.Error(`[UserCombat][uploadCombat] ${e.message}`);
}
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`上传剧诗数据失败:${errMsg}`);
await TGLogger.Error(`[UserCombat][uploadCombat] 上传剧诗数据异常:${errMsg}`);
}
await showLoading.end();
}
@@ -521,7 +527,7 @@ async function tryReadCombat(): Promise<void> {
showSnackbar.warn("文件数据格式错误");
return;
}
if (!Hutao.raw.valid.combat(fileData)) {
if (!Hutao.valid.combat(fileData)) {
await showLoading.end();
showSnackbar.warn("剧诗数据验证失败,请检查数据格式");
return;
@@ -536,7 +542,6 @@ async function tryReadCombat(): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
window.location.reload();
} catch (e) {
console.error(e);
await TGLogger.Error(`[UserCombat][tryReadCombat] 导入剧诗数据失败: ${e}`);
await showLoading.end();
showSnackbar.error("导入剧诗数据失败,请检查文件格式是否正确");

View File

@@ -284,10 +284,21 @@ async function handleHutaoUpload(uids: Array<string>): Promise<void> {
"302": 0,
"500": 0,
};
const endIdResp = await hutao.Gacha.endIds(accessToken.value!, u);
if ("retcode" in endIdResp) {
showSnackbar.warn(`[${endIdResp.retcode}] ${endIdResp.message}`);
} else endIdRes = endIdResp;
try {
const endIdResp = await hutao.Gacha.endIds(accessToken.value!, u);
if (endIdResp.retcode !== 0) {
showSnackbar.warn(`[${endIdResp.retcode}] ${endIdResp.message}`);
await TGLogger.Warn(
`[Gacha][handleHutaoUpload] 获取EndId失败${endIdResp.retcode} ${endIdResp.message}`,
);
} else if (endIdResp.data) {
endIdRes = endIdResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`获取EndId失败${errMsg}`);
await TGLogger.Error(`[Gacha][handleHutaoUpload] 获取EndId异常${errMsg}`);
}
const dataRaw: Array<TGApp.Sqlite.Gacha.Gacha> = [];
for (const [k, v] of Object.entries(endIdRes)) {
const gachaRead = await TSUserGacha.record.endId(u, k, v.toString());
@@ -304,11 +315,18 @@ async function handleHutaoUpload(uids: Array<string>): Promise<void> {
Id: i.id.toString(),
})),
};
const resp = await hutao.Gacha.upload(accessToken.value!, data);
if (resp.retcode === 0) {
showSnackbar.success(`成功上传祈愿数据:${resp.message}`);
} else {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
try {
const resp = await hutao.Gacha.upload(accessToken.value!, data);
if (resp.retcode === 0) {
showSnackbar.success(`成功上传祈愿数据:${resp.message}`);
} else {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
await TGLogger.Warn(`[Gacha][handleHutaoUpload] 上传失败:${resp.retcode} ${resp.message}`);
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`上传祈愿数据失败:${errMsg}`);
await TGLogger.Error(`[Gacha][handleHutaoUpload] 上传异常:${errMsg}`);
}
}
await showLoading.end();
@@ -333,67 +351,102 @@ async function handleHutaoDownload(uids: Array<string>): Promise<void> {
await showLoading.start("正在下载胡桃云祈愿记录...", "正在刷新Token");
for (const u of uids) {
await showLoading.start(`正在下载UID:${u}的祈愿记录`, "正在获取EndIds");
const endIdResp = await hutao.Gacha.endIds(accessToken.value!, u);
if ("retcode" in endIdResp) {
showSnackbar.warn(`[${endIdResp.retcode}] ${endIdResp.message}`);
continue;
}
for (const [p, i] of Object.entries(endIdResp)) {
if (i === 0) continue;
let endId: string | undefined = undefined;
let flag = true;
const pageSize = 200;
await showLoading.start(`正在下载卡池 ${p}`);
const uigfList: Array<TGApp.Plugins.UIGF.GachaItem> = [];
while (flag) {
await showLoading.update(`EndId:${endId ?? "无"}`);
await hutaoStore.tryRefreshToken();
const gachaResp = await hutao.Gacha.logs(accessToken.value!, u, Number(p), pageSize, endId);
if (gachaResp.retcode !== 0) {
showSnackbar.warn(`[${gachaResp.retcode}] ${gachaResp.message}`);
break;
}
const data: TGApp.Plugins.Hutao.Gacha.GachaLogRes = gachaResp.data ?? [];
if (data.length === pageSize) {
endId = data[data.length - 1].Id.toString();
} else flag = false;
for (const item of data) {
const tempItem: TGApp.Plugins.UIGF.GachaItem = {
gacha_type: item.GachaType.toString(),
item_id: item.ItemId.toString(),
count: "1",
time: item.Time,
name: "",
item_type: "",
rank_type: "",
id: BigInt(item.Id).toString(),
uigf_gacha_type: item.QueryType.toString(),
};
const find = AppCalendarData.find((i) => i.id.toString() === item.ItemId.toString());
if (find) {
tempItem.name = find.name;
tempItem.item_type = find.itemType;
tempItem.rank_type = find.star.toString();
} else {
if (yattaData.value.length === 0) {
await showLoading.update(`未查找到 ${tempItem.item_id} 的 信息,正在获取 Yatta 数据`);
await loadYatta();
}
const findH = yattaData.value.find((i) => i.id.toString() === item.ItemId.toString());
if (findH) {
tempItem.name = findH.name;
tempItem.item_type = findH.type;
tempItem.rank_type = findH.star.toString();
} else {
showSnackbar.warn(`无法搜索到 ${item.ItemId} 的信息,请等待元数据更新`);
continue;
}
}
uigfList.push(tempItem);
}
try {
const endIdResp = await hutao.Gacha.endIds(accessToken.value!, u);
if (endIdResp.retcode !== 0) {
showSnackbar.warn(`[${endIdResp.retcode}] ${endIdResp.message}`);
await TGLogger.Warn(
`[Gacha][handleHutaoDownload] 获取EndIds失败${endIdResp.retcode} ${endIdResp.message}`,
);
continue;
}
await showLoading.start(`正在写入卡池 ${p}-${uigfList.length}`);
await TSUserGacha.mergeUIGF(u, uigfList, true);
if (!endIdResp.data) {
showSnackbar.warn("获取EndIds返回数据为空");
await TGLogger.Warn(`[Gacha][handleHutaoDownload] 获取EndIds返回数据为空`);
continue;
}
const endIdRes = endIdResp.data;
for (const [p, i] of Object.entries(endIdRes)) {
if (i === 0) continue;
let endId: string | undefined = undefined;
let flag = true;
const pageSize = 200;
await showLoading.start(`正在下载卡池 ${p}`);
const uigfList: Array<TGApp.Plugins.UIGF.GachaItem> = [];
while (flag) {
await showLoading.update(`EndId:${endId ?? "无"}`);
await hutaoStore.tryRefreshToken();
try {
const gachaResp = await hutao.Gacha.logs(
accessToken.value!,
u,
Number(p),
pageSize,
endId,
);
if (gachaResp.retcode !== 0) {
showSnackbar.warn(`[${gachaResp.retcode}] ${gachaResp.message}`);
await TGLogger.Warn(
`[Gacha][handleHutaoDownload] 获取记录失败:${gachaResp.retcode} ${gachaResp.message}`,
);
break;
}
const data: TGApp.Plugins.Hutao.Gacha.GachaLogRes = gachaResp.data ?? [];
if (data.length === pageSize) {
endId = data[data.length - 1].Id.toString();
} else flag = false;
for (const item of data) {
const tempItem: TGApp.Plugins.UIGF.GachaItem = {
gacha_type: item.GachaType.toString(),
item_id: item.ItemId.toString(),
count: "1",
time: item.Time,
name: "",
item_type: "",
rank_type: "",
id: BigInt(item.Id).toString(),
uigf_gacha_type: item.QueryType.toString(),
};
const find = AppCalendarData.find((i) => i.id.toString() === item.ItemId.toString());
if (find) {
tempItem.name = find.name;
tempItem.item_type = find.itemType;
tempItem.rank_type = find.star.toString();
} else {
if (yattaData.value.length === 0) {
await showLoading.update(
`未查找到 ${tempItem.item_id} 的 信息,正在获取 Yatta 数据`,
);
await loadYatta();
}
const findH = yattaData.value.find(
(i) => i.id.toString() === item.ItemId.toString(),
);
if (findH) {
tempItem.name = findH.name;
tempItem.item_type = findH.type;
tempItem.rank_type = findH.star.toString();
} else {
showSnackbar.warn(`无法搜索到 ${item.ItemId} 的信息,请等待元数据更新`);
continue;
}
}
uigfList.push(tempItem);
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`获取祈愿记录失败:${errMsg}`);
await TGLogger.Error(`[Gacha][handleHutaoDownload] 获取记录异常:${errMsg}`);
break;
}
}
await showLoading.start(`正在写入卡池 ${p}-${uigfList.length}`);
await TSUserGacha.mergeUIGF(u, uigfList, true);
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`下载祈愿记录失败:${errMsg}`);
await TGLogger.Error(`[Gacha][handleHutaoDownload] 下载异常:${errMsg}`);
}
}
await showLoading.end();
@@ -423,11 +476,20 @@ async function handleHutaoDelete(uids: Array<string>): Promise<void> {
await showLoading.start("正在删除胡桃云祈愿记录");
for (const u of uids) {
await showLoading.update(`UID:${u}`);
const deleteResp = await hutao.Gacha.delete(accessToken.value!, u);
if (deleteResp.retcode === 0) {
showSnackbar.success(`删除记录成功:${deleteResp.message}`);
} else {
showSnackbar.warn(`[${deleteResp.retcode}] ${deleteResp.message}`);
try {
const deleteResp = await hutao.Gacha.delete(accessToken.value!, u);
if (deleteResp.retcode === 0) {
showSnackbar.success(`删除记录成功:${deleteResp.message}`);
} else {
showSnackbar.warn(`[${deleteResp.retcode}] ${deleteResp.message}`);
await TGLogger.Warn(
`[Gacha][handleHutaoDelete] 删除失败:${deleteResp.retcode} ${deleteResp.message}`,
);
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`删除记录失败:${errMsg}`);
await TGLogger.Error(`[Gacha][handleHutaoDelete] 删除异常:${errMsg}`);
}
}
await showLoading.end();
@@ -465,7 +527,6 @@ async function confirmRefresh(force: boolean): Promise<void> {
}
} else {
const gcFind = await TSUserAccount.game.getAccountByGid(uidCur.value.toString());
console.log(uidCur.value, gcFind);
if (!gcFind) {
const check = await showDialog.check(
`确定刷新?`,

View File

@@ -53,6 +53,8 @@ import HtaTabTeam from "@comp/hutaoAbyss/hta-tab-team.vue";
import HtaTabUp from "@comp/hutaoAbyss/hta-tab-up.vue";
import HtaTabUse from "@comp/hutaoAbyss/hta-tab-use.vue";
import hutao from "@Hutao/index.js";
import TGHttps from "@utils/TGHttps.js";
import TGLogger from "@utils/TGLogger.js";
import { timestampToDate } from "@utils/toolFunc.js";
import { onMounted, reactive, ref, type ShallowRef, shallowRef, watch } from "vue";
@@ -120,17 +122,35 @@ async function getOverview(): Promise<void> {
await showLoading.start("正在获取深渊概览");
let cur: TGApp.Plugins.Hutao.Abyss.OverviewData | undefined = undefined;
let last: TGApp.Plugins.Hutao.Abyss.OverviewData | undefined = undefined;
const curResp = await hutao.Abyss.overview();
if ("retcode" in curResp) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
} else {
cur = curResp;
try {
const curResp = await hutao.Abyss.overview();
if (curResp.retcode !== 0) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getOverview] 获取本期概览失败:${curResp.retcode} ${curResp.message}`,
);
} else {
cur = curResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取本期概览失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getOverview] 获取本期概览异常:${errMsg}`);
}
const lastResp = await hutao.Abyss.overview(true);
if ("retcode" in lastResp) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
} else {
last = lastResp;
try {
const lastResp = await hutao.Abyss.overview(true);
if (lastResp.retcode !== 0) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getOverview] 获取上期概览失败:${lastResp.retcode} ${lastResp.message}`,
);
} else {
last = lastResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取上期概览失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getOverview] 获取上期概览异常:${errMsg}`);
}
if (cur && last) overview.value = { cur, last };
else overview.value = undefined;
@@ -140,17 +160,35 @@ async function getUseData(): Promise<void> {
await showLoading.start("正在获取角色使用率数据");
let cur: Array<TGApp.Plugins.Hutao.Abyss.AvatarUse> = [];
let last: Array<TGApp.Plugins.Hutao.Abyss.AvatarUse> = [];
const curResp = await hutao.Abyss.avatar.use();
if (!Array.isArray(curResp)) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
} else {
cur = curResp;
try {
const curResp = await hutao.Abyss.avatar.use();
if (curResp.retcode !== 0) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getUseData] 获取本期使用率失败:${curResp.retcode} ${curResp.message}`,
);
} else if (curResp.data) {
cur = curResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取本期使用率失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getUseData] 获取本期使用率异常:${errMsg}`);
}
const lastResp = await hutao.Abyss.avatar.use(true);
if (!Array.isArray(lastResp)) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
} else {
last = lastResp;
try {
const lastResp = await hutao.Abyss.avatar.use(true);
if (lastResp.retcode !== 0) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getUseData] 获取上期使用率失败:${lastResp.retcode} ${lastResp.message}`,
);
} else if (lastResp.data) {
last = lastResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取上期使用率失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getUseData] 获取上期使用率异常:${errMsg}`);
}
abyssData.use = { cur, last };
}
@@ -159,28 +197,55 @@ async function getUpData(): Promise<void> {
await showLoading.start("正在获取角色出场率数据");
let cur: Array<TGApp.Plugins.Hutao.Abyss.AvatarUp> = [];
let last: Array<TGApp.Plugins.Hutao.Abyss.AvatarUp> = [];
const curResp = await hutao.Abyss.avatar.up();
if (!Array.isArray(curResp)) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
} else {
cur = curResp;
try {
const curResp = await hutao.Abyss.avatar.up();
if (curResp.retcode !== 0) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getUpData] 获取本期出场率失败:${curResp.retcode} ${curResp.message}`,
);
} else if (curResp.data) {
cur = curResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取本期出场率失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getUpData] 获取本期出场率异常:${errMsg}`);
}
const lastResp = await hutao.Abyss.avatar.use(true);
if (!Array.isArray(lastResp)) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
} else {
last = lastResp;
try {
const lastResp = await hutao.Abyss.avatar.up(true);
if (lastResp.retcode !== 0) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getUpData] 获取上期出场率失败:${lastResp.retcode} ${lastResp.message}`,
);
} else if (lastResp.data) {
last = lastResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取上期出场率失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getUpData] 获取上期出场率异常:${errMsg}`);
}
abyssData.up = { cur, last };
}
async function getTeamData(): Promise<void> {
await showLoading.start("正在获取队伍出场数据");
const teamResp = await hutao.Abyss.team();
if ("retcode" in teamResp) {
await showLoading.update(`[${teamResp.retcode}] ${teamResp.message}`);
} else {
abyssData.team = teamResp;
try {
const teamResp = await hutao.Abyss.team();
if (teamResp.retcode !== 0) {
await showLoading.update(`[${teamResp.retcode}] ${teamResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getTeamData] 获取队伍数据失败:${teamResp.retcode} ${teamResp.message}`,
);
} else if (teamResp.data) {
abyssData.team = teamResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取队伍数据失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getTeamData] 获取队伍数据异常:${errMsg}`);
}
}
@@ -188,17 +253,35 @@ async function getHoldData(): Promise<void> {
await showLoading.start("正在获取角色持有数据");
let cur: Array<TGApp.Plugins.Hutao.Abyss.AvatarHold> = [];
let last: Array<TGApp.Plugins.Hutao.Abyss.AvatarHold> = [];
const curResp = await hutao.Abyss.avatar.hold();
if (!Array.isArray(curResp)) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
} else {
cur = curResp;
try {
const curResp = await hutao.Abyss.avatar.hold();
if (curResp.retcode !== 0) {
await showLoading.update(`[${curResp.retcode}] ${curResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getHoldData] 获取本期持有率失败:${curResp.retcode} ${curResp.message}`,
);
} else if (curResp.data) {
cur = curResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取本期持有率失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getHoldData] 获取本期持有率异常:${errMsg}`);
}
const lastResp = await hutao.Abyss.avatar.hold(true);
if (!Array.isArray(lastResp)) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
} else {
last = lastResp;
try {
const lastResp = await hutao.Abyss.avatar.hold(true);
if (lastResp.retcode !== 0) {
await showLoading.update(`[${lastResp.retcode}] ${lastResp.message}`);
await TGLogger.Warn(
`[WIKI/Abyss][getHoldData] 获取上期持有率失败:${lastResp.retcode} ${lastResp.message}`,
);
} else if (lastResp.data) {
last = lastResp.data;
}
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
await showLoading.update(`获取上期持有率失败:${errMsg}`);
await TGLogger.Error(`[WIKI/Abyss][getHoldData] 获取上期持有率异常:${errMsg}`);
}
abyssData.hold = { cur, last };
}

View File

@@ -1,90 +1,27 @@
/**
* Hutao 插件入口
* @since Beta v0.9.1
* @since Beta v0.10.1
*/
import {
getAbyssOverview,
getAvatarCollect,
getAvatarHoldRate,
getAvatarUpRate,
getAvatarUseRate,
getTeamCollect,
uploadAbyssData,
} from "./request/abyssReq.js";
import {
getResetPwdCode,
getUserInfo,
loginPassport,
refreshToken,
resetPwd,
} from "./request/accountReq.js";
import { getCombatStatistic, uploadCombatData } from "./request/combatReq.js";
import {
deleteGachaLogs,
getEndIds,
getEntries,
getGachaLogs,
uploadGachaLogs,
} from "./request/gachaReq.js";
import { transAbyssAvatars, transAbyssLocal } from "./utils/abyssUtil.js";
import { transCombatLocal } from "./utils/combatUtil.js";
import { RawValidator } from "./utils/RawValidator.js";
import AbyssReq from "./request/abyssReq.js";
import AccountReq from "./request/accountReq.js";
import CombatReq from "./request/combatReq.js";
import GachaReq from "./request/gachaReq.js";
import HutaoValid from "./utils/RawValidator.js";
const _ = "Not Implemented";
const Hutao = {
Abyss: {
avatar: {
collect: getAvatarCollect,
hold: getAvatarHoldRate,
up: getAvatarUpRate,
use: getAvatarUseRate,
},
overview: getAbyssOverview,
team: getTeamCollect,
upload: uploadAbyssData,
utils: {
transData: transAbyssLocal,
transAvatars: transAbyssAvatars,
},
},
Combat: {
upload: uploadCombatData,
data: getCombatStatistic,
trans: transCombatLocal,
},
Account: {
register: _,
login: loginPassport,
verify: {
username: _,
usernameNew: _,
pwd: getResetPwdCode,
cancel: _,
},
cancel: _,
reset: {
username: _,
pwd: resetPwd,
},
info: getUserInfo,
},
Abyss: AbyssReq,
Combat: CombatReq,
Account: AccountReq,
Token: {
refresh: refreshToken,
refresh: AccountReq.refresh,
revoke: _,
revokeAll: _,
},
Gacha: {
entry: getEntries,
endIds: getEndIds,
logs: getGachaLogs,
upload: uploadGachaLogs,
delete: deleteGachaLogs,
},
raw: {
valid: RawValidator,
},
Gacha: GachaReq,
valid: HutaoValid,
};
export default Hutao;

View File

@@ -1,133 +1,246 @@
/**
* 深渊相关请求
* @since Beta v0.9.1
* @since Beta v0.10.1
*/
import TGHttp from "@utils/TGHttp.js";
import TGHttps from "@utils/TGHttps.js";
const AbyssUrl: Readonly<string> = `https://homa.gentle.house/Statistics/`;
/**
* 获取深渊概览数据
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 深渊概览数据
* @returns 深渊概览响应
*/
export async function getAbyssOverview(
async function getOverview(
isLast: boolean = false,
): Promise<TGApp.Plugins.Hutao.Abyss.OverviewData | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Abyss.OverviewResp> {
const url = `${AbyssUrl}Overview`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Abyss.OverviewResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Abyss.OverviewResp>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 获取角色搭配数据
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 角色搭配数据
* @returns 角色搭配响应
*/
export async function getAvatarCollect(
async function getAvatarCollect(
isLast: boolean = false,
): Promise<Array<TGApp.Plugins.Hutao.Abyss.AvatarCollocation> | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Abyss.AvatarCollectResp> {
const url = `${AbyssUrl}Avatar/AvatarCollocation`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Abyss.AvatarCollectResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Abyss.AvatarCollectResp>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 获取角色持有率数据
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 角色持有率数据
* @returns 角色持有率响应
*/
export async function getAvatarHoldRate(
async function getAvatarHoldRate(
isLast: boolean = false,
): Promise<Array<TGApp.Plugins.Hutao.Abyss.AvatarHold> | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Abyss.AvatarHoldResp> {
const url = `${AbyssUrl}Avatar/HoldingRate`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Abyss.AvatarHoldResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Abyss.AvatarHoldResp>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 获取角色上场率数据
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 角色上场率数据
* @returns 角色上场率响应
*/
export async function getAvatarUpRate(
async function getAvatarUpRate(
isLast: boolean = false,
): Promise<Array<TGApp.Plugins.Hutao.Abyss.AvatarUp> | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Abyss.AvatarUpResp> {
const url = `${AbyssUrl}Avatar/AttendanceRate`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Abyss.AvatarUpResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Abyss.AvatarUpResp>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 获取角色使用率
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 角色使用率
* @returns 角色使用率响应
*/
export async function getAvatarUseRate(
async function getAvatarUseRate(
isLast: boolean = false,
): Promise<Array<TGApp.Plugins.Hutao.Abyss.AvatarUse> | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Abyss.AvatarUseResp> {
const url = `${AbyssUrl}Avatar/UtilizationRate`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Abyss.AvatarUseResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Abyss.AvatarUseResp>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 获取队伍搭配数据
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 队伍搭配数据
* @returns 队伍搭配响应
*/
export async function getTeamCollect(
async function getTeamCollect(
isLast: boolean = false,
): Promise<Array<TGApp.Plugins.Hutao.Abyss.TeamCombination> | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Abyss.TeamCombineResp> {
const url = `${AbyssUrl}Team/Combination`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Abyss.TeamCombineResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Abyss.TeamCombineResp>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 上传用户数据
* @since Beta v0.5.0
* @since Beta v0.10.1
* @param data - 用户数据
* @returns 上传结果
*/
export async function uploadAbyssData(
async function uploadData(
data: TGApp.Plugins.Hutao.Abyss.RecordUpload,
): Promise<TGApp.Plugins.Hutao.Abyss.UploadResp> {
const url = "https://homa.gentle.house/Record/Upload";
return await TGHttp<TGApp.Plugins.Hutao.Abyss.UploadResp>(url, {
method: "POST",
body: JSON.stringify(data),
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Abyss.UploadResp>(url, {
body: data,
query: { returningRank: false },
headers: { "Content-Type": "application/json" },
});
return resp.data;
}
/**
* 将本地数据转为上传用的数据
* @since Beta v0.6.3
* @param data - 本地数据
* @returns 上传用的数据
*/
function transData(data: TGApp.Sqlite.Abyss.TableTrans): TGApp.Plugins.Hutao.Abyss.RecordUpload {
return {
Uid: data.uid,
Identity: "TeyvatGuide",
SpiralAbyss: transAbyssData(data),
Avatars: [],
ReservedUserName: "",
};
}
/**
* 转换深渊数据
* @since Beta v0.6.3
* @param data - 本地数据
* @returns 上传用的数据
*/
function transAbyssData(data: TGApp.Sqlite.Abyss.TableTrans): TGApp.Plugins.Hutao.Abyss.RecordData {
return {
ScheduleId: data.id,
TotalBattleTimes: data.totalBattleTimes,
TotalWinTimes: data.totalWinTimes,
Defeat: {
AvatarId: data.defeatRank[0].id,
Value: data.defeatRank[0].value,
},
EnergySkill: {
AvatarId: data.energySkillRank[0].id,
Value: data.energySkillRank[0].value,
},
NormalSkill: {
AvatarId: data.normalSkillRank[0].id,
Value: data.normalSkillRank[0].value,
},
Damage: {
AvatarId: data.damageRank[0].id,
Value: data.damageRank[0].value,
},
TakeDamage: {
AvatarId: data.takeDamageRank[0].id,
Value: data.takeDamageRank[0].value,
},
Floors: data.floors.map((floor: TGApp.Sqlite.Abyss.Floor) => transFloor(floor)),
};
}
/**
* 转换层数数据
* @since Alpha v0.2.1
* @param data - 本地数据
* @returns 上传用的数据
*/
function transFloor(data: TGApp.Sqlite.Abyss.Floor): TGApp.Plugins.Hutao.Abyss.Floor {
return {
Index: data.id,
Star: data.winStar,
Levels: data.levels.map((level) => transLevel(level)),
};
}
/**
* 转换层-关卡数据
* @since Alpha v0.2.1
* @param data - 本地数据
* @returns 上传用的数据
*/
function transLevel(data: TGApp.Sqlite.Abyss.Level): TGApp.Plugins.Hutao.Abyss.Level {
const battles: Array<{ Index: number; Avatars: Array<number> }> = [];
battles.push({
Index: 1,
Avatars: data.upBattle!.characters.map((character) => character.id),
});
battles.push({
Index: 2,
Avatars: data.downBattle!.characters.map((character) => character.id),
});
return {
Index: data.id,
Star: data.winStar,
Battles: battles,
};
}
/**
* 转换角色数据
* @since Beta v0.5.5
* @param avatars - 角色数据
* @returns 上传用的数据
*/
function transAvatars(
avatars: Array<TGApp.Sqlite.Character.TableTrans>,
): Array<TGApp.Plugins.Hutao.Abyss.Avatar> {
return avatars.map((avatar) => {
return {
AvatarId: avatar.avatar.id,
WeaponId: avatar.weapon.id,
ReliquarySetIds: avatar.relics.map((relic) => relic.set.id),
ActivedConstellationNumber: avatar.avatar.actived_constellation_num,
};
});
}
const AbyssReq = {
avatar: {
collect: getAvatarCollect,
hold: getAvatarHoldRate,
up: getAvatarUpRate,
use: getAvatarUseRate,
},
overview: getOverview,
team: getTeamCollect,
upload: uploadData,
utils: {
transData,
transAvatars,
},
};
export default AbyssReq;

View File

@@ -1,9 +1,9 @@
/**
* 账号相关请求
* @since Beta v0.9.1
* @since Beta v0.10.1
*/
import TGHttp from "@utils/TGHttp.js";
import TGHttps from "@utils/TGHttps.js";
import { getReqHeader, rsaEncrypt } from "../utils/authUtils.js";
@@ -11,73 +11,67 @@ const PassportUrl = "https://homa.gentle.house/Passport/v2/";
/**
* 登录
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param username - 用户名(邮箱)
* @param password - 密码
* @returns 登录返回
* @returns 登录响应
*/
export async function loginPassport(
async function login(
username: string,
password: string,
): Promise<TGApp.Plugins.Hutao.Account.LoginRes | TGApp.Plugins.Hutao.Base.Resp> {
): Promise<TGApp.Plugins.Hutao.Account.LoginResp> {
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",
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Account.LoginResp>(url, {
headers: header,
body: JSON.stringify(data),
body: data,
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Account.LoginRes>resp.data;
return resp.data;
}
/**
* 刷新访问令牌
* @since Beta v0.9.1
* @returns 令牌返回
* @since Beta v0.10.1
* @param token - 刷新令牌
* @returns 令牌响应
*/
export async function refreshToken(token: string) {
async function refresh(token: string): Promise<TGApp.Plugins.Hutao.Account.RefreshTokenResp> {
const url = `${PassportUrl}RefreshToken`;
const header = await getReqHeader();
const data = { RefreshToken: rsaEncrypt(token) };
const resp = await TGHttp<TGApp.Plugins.Hutao.Account.RefreshTokenResp>(url, {
method: "POST",
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Account.RefreshTokenResp>(url, {
headers: header,
body: JSON.stringify(data),
body: data,
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Account.RefreshTokenRes>resp.data;
return resp.data;
}
/**
* 获取用户信息
* @since Beta v0.9.1
* @returns 用户信息返回
* @since Beta v0.10.1
* @param token - 访问令牌
* @returns 用户信息响应
*/
export async function getUserInfo(
token: string,
): Promise<TGApp.Plugins.Hutao.Account.InfoRes | TGApp.Plugins.Hutao.Base.Resp> {
async function info(token: string): Promise<TGApp.Plugins.Hutao.Account.InfoResp> {
const url = `${PassportUrl}UserInfo`;
const header = await getReqHeader(token);
const resp = await TGHttp<TGApp.Plugins.Hutao.Account.InfoResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Account.InfoResp>(url, {
headers: header,
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Account.InfoRes>resp.data;
return resp.data;
}
/**
* 获取充值密码验证码
* @since Beta v0.9.1
* @param username - 用户
* @returns 验证码返回
* 获取重置密码验证码
* @since Beta v0.10.1
* @param username - 用户
* @returns 验证码响应
*/
export async function getResetPwdCode(username: string): Promise<TGApp.Plugins.Hutao.Base.Resp> {
async function verifyPwd(username: string): Promise<TGApp.Plugins.Hutao.Base.Resp> {
const url = `${PassportUrl}Verify`;
const header = await getReqHeader();
const data: TGApp.Plugins.Hutao.Account.ResetPwdCodeParam = {
@@ -87,24 +81,22 @@ export async function getResetPwdCode(username: string): Promise<TGApp.Plugins.H
IsResetUserName: false,
IsResetUserNameNew: false,
};
const resp = await TGHttp<TGApp.Plugins.Hutao.Base.Resp>(url, {
method: "POST",
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Base.Resp>(url, {
headers: header,
body: JSON.stringify(data),
body: data,
});
console.log(resp);
return resp;
return resp.data;
}
/**
* 重置密码
* @since Beta v0.9.1
* @param username - 用户
* @since Beta v0.10.1
* @param username - 用户
* @param code - 验证码
* @param pwd - 密码
* @returns 重置密码返回
* @param pwd - 密码
* @returns 重置密码响应
*/
export async function resetPwd(
async function resetPwd(
username: string,
code: string,
pwd: string,
@@ -120,11 +112,31 @@ export async function resetPwd(
IsResetUserName: false,
IsResetUserNameNew: false,
};
const resp = await TGHttp<TGApp.Plugins.Hutao.Base.Resp>(url, {
method: "POST",
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Base.Resp>(url, {
headers: header,
body: JSON.stringify(data),
body: data,
});
console.log(resp);
return resp;
return resp.data;
}
const _ = "Not Implemented";
const AccountReq = {
register: _,
login,
refresh,
verify: {
username: _,
usernameNew: _,
pwd: verifyPwd,
cancel: _,
},
cancel: _,
reset: {
username: _,
pwd: resetPwd,
},
info,
};
export default AccountReq;

View File

@@ -1,42 +1,62 @@
/**
* 幻想真境剧诗相关请求
* @since Beta v0.9.1
* @since Beta v0.10.1
*/
import TGHttp from "@utils/TGHttp.js";
import TGHttps from "@utils/TGHttps.js";
const CombatUrl: Readonly<string> = "https://homa.gentle.house/RoleCombat/";
/**
* 获取数据
* @since Beta v0.9.1
* 获取剧诗统计数据
* @since Beta v0.10.1
* @param isLast - 是否获取上期数据
* @returns 剧诗数据
* @returns 剧诗响应
*/
export async function getCombatStatistic(
isLast: boolean = false,
): Promise<TGApp.Plugins.Hutao.Combat.Data | TGApp.Plugins.Hutao.Base.Resp> {
async function data(isLast: boolean = false): Promise<TGApp.Plugins.Hutao.Combat.Response> {
const url = `${CombatUrl}Statistics`;
const resp = await TGHttp<TGApp.Plugins.Hutao.Combat.Response>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Combat.Response>(url, {
query: { Last: isLast },
});
if (resp.data) return resp.data;
return { retcode: resp.retcode, message: resp.message };
return resp.data;
}
/**
* 上传数据
* @since Beta v0.6.3
* @param data - 数据
* @returns 上传返回
* 上传剧诗数据
* @since Beta v0.10.1
* @param uploadData - 上传数据
* @returns 上传响应
*/
export async function uploadCombatData(
data: TGApp.Plugins.Hutao.Combat.UploadData,
async function upload(
uploadData: TGApp.Plugins.Hutao.Combat.UploadData,
): Promise<TGApp.Plugins.Hutao.Combat.UploadResp> {
const url = `${CombatUrl}Upload`;
return await TGHttp<TGApp.Plugins.Hutao.Combat.UploadResp>(url, {
method: "POST",
body: JSON.stringify(data),
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Combat.UploadResp>(url, {
body: uploadData,
headers: { "Content-Type": "application/json" },
});
return resp.data;
}
/**
* 将本地数据转为上传用的数据
* @since Beta v0.6.3
* @param data - 本地数据
* @returns 上传用的数据
*/
function trans(data: TGApp.Sqlite.Combat.TableTrans): TGApp.Plugins.Hutao.Combat.UploadData {
return {
Version: 1,
Uid: data.uid,
Identity: "TeyvatGuide",
BackupAvatars: data.detail.backup_avatars.map((i) => i.avatar_id),
ScheduleId: data.id,
};
}
const CombatReq = {
data,
upload,
trans,
};
export default CombatReq;

View File

@@ -1,8 +1,8 @@
/**
* 祈愿相关请求
* @since Beta v0.10.0
* @since Beta v0.10.1
*/
import TGHttp from "@utils/TGHttp.js";
import TGHttps from "@utils/TGHttps.js";
import { getReqHeader } from "../utils/authUtils.js";
@@ -10,54 +10,47 @@ const HUTAO_GACHA_API = "https://homa.gentle.house/GachaLog/";
/**
* 获取抽卡入口
* @since Beta v0.10.1
* @param tk - token
* @returns 抽卡记录概况
* @returns 抽卡记录概况响应
*/
export async function getEntries(
tk: string,
): Promise<TGApp.Plugins.Hutao.Gacha.EntryRes | TGApp.Plugins.Hutao.Base.Resp> {
async function entry(tk: string): Promise<TGApp.Plugins.Hutao.Gacha.EntryResp> {
const url = `${HUTAO_GACHA_API}Entries`;
const header = await getReqHeader(tk);
const resp = await TGHttp<TGApp.Plugins.Hutao.Gacha.EntryResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Gacha.EntryResp>(url, {
headers: header,
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Gacha.EntryRes>resp.data;
return resp.data;
}
/**
* 获取抽卡EndId
* @since Beta v0.10.0
* @since Beta v0.10.1
* @param tk - token
* @param uid - 记录UID
* @returns EndId
* @returns EndId响应
*/
export async function getEndIds(
tk: string,
uid: string,
): Promise<TGApp.Plugins.Hutao.Gacha.EndIdRes | TGApp.Plugins.Hutao.Base.Resp> {
async function endIds(tk: string, uid: string): Promise<TGApp.Plugins.Hutao.Gacha.EndIdResp> {
const url = `${HUTAO_GACHA_API}EndIds`;
const header = await getReqHeader(tk);
const resp = await TGHttp<TGApp.Plugins.Hutao.Gacha.EndIdResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Gacha.EndIdResp>(url, {
headers: header,
query: { Uid: uid },
});
if (resp.retcode !== 0) return <TGApp.Plugins.Hutao.Base.Resp>resp;
return <TGApp.Plugins.Hutao.Gacha.EndIdRes>resp.data;
return resp.data;
}
/**
* 获取抽卡记录
* @since Beta v0.10.0
* @since Beta v0.10.1
* @param tk - token
* @param uid - 记录UID
* @param gType - 祈愿类型按照EndId来
* @param gType - 祈愿类型
* @param count - 数量
* @param endId - endId
* @param count - 尺寸
* @returns 抽卡记录响应
*/
export async function getGachaLogs(
async function logs(
tk: string,
uid: string,
gType: number,
@@ -72,49 +65,56 @@ export async function getGachaLogs(
count: count,
};
if (endId) params.endId = endId;
return await TGHttp<TGApp.Plugins.Hutao.Gacha.GachaLogResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Gacha.GachaLogResp>(url, {
headers: header,
query: params,
});
return resp.data;
}
/**
* 上传抽卡记录
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param tk - token
* @param data - 上传数据
* @returns 上传结果
*/
export async function uploadGachaLogs(
async function upload(
tk: string,
data: TGApp.Plugins.Hutao.Gacha.UploadData,
): Promise<TGApp.Plugins.Hutao.Gacha.UploadResp> {
const url = `${HUTAO_GACHA_API}Upload`;
const header = await getReqHeader(tk);
return await TGHttp<TGApp.Plugins.Hutao.Gacha.UploadResp>(url, {
method: "POST",
const resp = await TGHttps.post<TGApp.Plugins.Hutao.Gacha.UploadResp>(url, {
headers: header,
body: JSON.stringify(data),
body: data,
});
return resp.data;
}
/**
* 删除祈愿记录
* @since Beta v0.9.1
* @since Beta v0.10.1
* @param tk - token
* @param uid - uid
* @returns 删除结果
*/
export async function deleteGachaLogs(
tk: string,
uid: string,
): Promise<TGApp.Plugins.Hutao.Gacha.DeleteResp> {
async function deleteLogs(tk: string, uid: string): Promise<TGApp.Plugins.Hutao.Gacha.DeleteResp> {
const url = `${HUTAO_GACHA_API}Delete`;
const header = await getReqHeader(tk);
return await TGHttp<TGApp.Plugins.Hutao.Gacha.DeleteResp>(url, {
method: "GET",
const resp = await TGHttps.get<TGApp.Plugins.Hutao.Gacha.DeleteResp>(url, {
headers: header,
query: { Uid: uid },
});
return resp.data;
}
const GachaReq = {
entry,
endIds,
logs,
upload,
delete: deleteLogs,
};
export default GachaReq;

View File

@@ -1,6 +1,6 @@
/**
* 胡桃原始数据验证器
* @since Beta v0.9.9
* @since Beta v0.10.1
*/
import showSnackbar from "@comp/func/snackbar.js";
@@ -108,11 +108,7 @@ function verifyCombatArray(data: unknown): data is Array<TGApp.Plugins.Hutao.Com
return data.every(validateCombat);
}
/**
* 原始数据验证器
* @since Beta v0.9.9
*/
export const RawValidator = {
const HutaoValid = {
/** 深渊数据验证 */
abyss: verifyAbyssArray,
/** 危战数据验证 */
@@ -120,3 +116,5 @@ export const RawValidator = {
/** 剧诗数据验证 */
combat: verifyCombatArray,
};
export default HutaoValid;

View File

@@ -1,113 +0,0 @@
/**
* 将本地数据转为上传用的数据
* @since Beta v0.6.3
*/
/**
* 将本地数据转为上传用的数据
* @since Beta v0.6.3
* @param data - 本地数据
* @returns 上传用的数据
*/
export function transAbyssLocal(
data: TGApp.Sqlite.Abyss.TableTrans,
): TGApp.Plugins.Hutao.Abyss.RecordUpload {
return {
Uid: data.uid,
Identity: "TeyvatGuide",
SpiralAbyss: transAbyssData(data),
Avatars: [],
ReservedUserName: "",
};
}
/**
* 转换深渊数据
* @since Beta v0.6.3
* @param data - 本地数据
* @returns 上传用的数据
*/
function transAbyssData(data: TGApp.Sqlite.Abyss.TableTrans): TGApp.Plugins.Hutao.Abyss.RecordData {
return {
ScheduleId: data.id,
TotalBattleTimes: data.totalBattleTimes,
TotalWinTimes: data.totalWinTimes,
Defeat: {
AvatarId: data.defeatRank[0].id,
Value: data.defeatRank[0].value,
},
EnergySkill: {
AvatarId: data.energySkillRank[0].id,
Value: data.energySkillRank[0].value,
},
NormalSkill: {
AvatarId: data.normalSkillRank[0].id,
Value: data.normalSkillRank[0].value,
},
Damage: {
AvatarId: data.damageRank[0].id,
Value: data.damageRank[0].value,
},
TakeDamage: {
AvatarId: data.takeDamageRank[0].id,
Value: data.takeDamageRank[0].value,
},
Floors: data.floors.map((floor: TGApp.Sqlite.Abyss.Floor) => transFloor(floor)),
};
}
/**
* 转换层数数据
* @since Alpha v0.2.1
* @param data - 本地数据
* @returns 上传用的数据
*/
function transFloor(data: TGApp.Sqlite.Abyss.Floor): TGApp.Plugins.Hutao.Abyss.Floor {
return {
Index: data.id,
Star: data.winStar,
Levels: data.levels.map((level) => transLevel(level)),
};
}
/**
* 转换层-关卡数据
* @since Alpha v0.2.1
* @param data - 本地数据
* @returns 上传用的数据
*/
function transLevel(data: TGApp.Sqlite.Abyss.Level): TGApp.Plugins.Hutao.Abyss.Level {
const battles: Array<{ Index: number; Avatars: Array<number> }> = [];
battles.push({
Index: 1,
Avatars: data.upBattle!.characters.map((character) => character.id),
});
battles.push({
Index: 2,
Avatars: data.downBattle!.characters.map((character) => character.id),
});
return {
Index: data.id,
Star: data.winStar,
Battles: battles,
};
}
/**
* 转换角色数据
* @since Beta v0.5.5
* @param avatars - 角色数据
* @returns 上传用的数据
*/
export function transAbyssAvatars(
avatars: Array<TGApp.Sqlite.Character.TableTrans>,
): Array<TGApp.Plugins.Hutao.Abyss.Avatar> {
return avatars.map((avatar) => {
return {
AvatarId: avatar.avatar.id,
WeaponId: avatar.weapon.id,
ReliquarySetIds: avatar.relics.map((relic) => relic.set.id),
ActivedConstellationNumber: avatar.avatar.actived_constellation_num,
};
});
}

View File

@@ -1,22 +0,0 @@
/**
* 将本地数据转为上传用的数据
* @since Beta v0.6.3
*/
/**
* 将本地数据转为上传用的数据
* @since Beta v0.6.3
* @param data - 数据
* @returns 上传用的数据
*/
export function transCombatLocal(
data: TGApp.Sqlite.Combat.TableTrans,
): TGApp.Plugins.Hutao.Combat.UploadData {
return {
Version: 1,
Uid: data.uid,
Identity: "TeyvatGuide",
BackupAvatars: data.detail.backup_avatars.map((i) => i.avatar_id),
ScheduleId: data.id,
};
}

View File

@@ -1,12 +1,14 @@
/**
* 胡桃账号
* @since Beta v0.9.1
* @since Beta v0.10.1
*/
import showDialog from "@comp/func/dialog.js";
import showLoading from "@comp/func/loading.js";
import showSnackbar from "@comp/func/snackbar.js";
import hutao from "@Hutao/index.js";
import TGHttps from "@utils/TGHttps.js";
import TGLogger from "@utils/TGLogger.js";
import { validEmail } from "@utils/toolFunc.js";
import { defineStore } from "pinia";
import { ref } from "vue";
@@ -55,21 +57,28 @@ const useHutaoStore = defineStore(
await showLoading.start("正在登录胡桃云", inputN);
try {
const resp = await hutao.Account.login(inputN, inputP);
if ("retcode" in resp) {
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
console.error(resp);
await TGLogger.Warn(`[HutaoStore][tryLogin] 登录失败:${resp.retcode} ${resp.message}`);
await showLoading.end();
return;
}
if (!resp.data) {
showSnackbar.error("登录返回数据为空");
await TGLogger.Error(`[HutaoStore][tryLogin] 登录返回数据为空`);
await showLoading.end();
return;
}
isLogin.value = true;
userName.value = inputN;
accessToken.value = resp.AccessToken;
refreshToken.value = resp.RefreshToken;
accessExpire.value = Date.now() + resp.ExpiresIn * 1000;
accessToken.value = resp.data.AccessToken;
refreshToken.value = resp.data.RefreshToken;
accessExpire.value = Date.now() + resp.data.ExpiresIn * 1000;
showSnackbar.success("成功登录胡桃云");
} catch (err) {
console.error(err);
showSnackbar.error("登录胡桃云失败");
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`登录胡桃云失败${errMsg}`);
await TGLogger.Error(`[HutaoStore][tryLogin] 登录异常:${errMsg}`);
} finally {
await showLoading.end();
}
@@ -82,21 +91,28 @@ const useHutaoStore = defineStore(
await showLoading.start("正在登录胡桃云", username);
try {
const resp = await hutao.Account.login(username, pwd);
if ("retcode" in resp) {
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
console.error(resp);
await TGLogger.Warn(`[HutaoStore][autoLogin] 登录失败:${resp.retcode} ${resp.message}`);
await showLoading.end();
return;
}
if (!resp.data) {
showSnackbar.error("登录返回数据为空");
await TGLogger.Error(`[HutaoStore][autoLogin] 登录返回数据为空`);
await showLoading.end();
return;
}
isLogin.value = true;
userName.value = username;
accessToken.value = resp.AccessToken;
refreshToken.value = resp.RefreshToken;
accessExpire.value = Date.now() + resp.ExpiresIn * 1000;
accessToken.value = resp.data.AccessToken;
refreshToken.value = resp.data.RefreshToken;
accessExpire.value = Date.now() + resp.data.ExpiresIn * 1000;
showSnackbar.success("成功登录胡桃云");
} catch (err) {
console.error(err);
showSnackbar.error("登录胡桃云失败");
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`登录胡桃云失败${errMsg}`);
await TGLogger.Error(`[HutaoStore][autoLogin] 登录异常:${errMsg}`);
} finally {
await showLoading.end();
}
@@ -107,13 +123,27 @@ const useHutaoStore = defineStore(
async function tryRefreshInfo(): Promise<void> {
await tryRefreshToken();
const resp = await hutao.Account.info(accessToken.value!);
if ("retcode" in resp) {
showSnackbar.warn(`刷新用户信息失败:${resp.retcode}-${resp.message}`);
return;
try {
const resp = await hutao.Account.info(accessToken.value!);
if (resp.retcode !== 0) {
showSnackbar.warn(`刷新用户信息失败:${resp.retcode}-${resp.message}`);
await TGLogger.Warn(
`[HutaoStore][tryRefreshInfo] 刷新用户信息失败:${resp.retcode} ${resp.message}`,
);
return;
}
if (!resp.data) {
showSnackbar.error("刷新用户信息返回数据为空");
await TGLogger.Error(`[HutaoStore][tryRefreshInfo] 刷新用户信息返回数据为空`);
return;
}
userInfo.value = resp.data;
showSnackbar.success("成功刷新用户信息");
} catch (e) {
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`刷新用户信息失败:${errMsg}`);
await TGLogger.Error(`[HutaoStore][tryRefreshInfo] 刷新用户信息异常:${errMsg}`);
}
userInfo.value = resp;
showSnackbar.success("成功刷新用户信息");
}
async function tryRefreshToken(): Promise<void> {
@@ -124,18 +154,26 @@ const useHutaoStore = defineStore(
if (checkIsValid()) return;
try {
const resp = await hutao.Token.refresh(refreshToken.value);
if ("retcode" in resp) {
if (resp.retcode !== 0) {
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
console.error(resp);
await TGLogger.Warn(
`[HutaoStore][tryRefreshToken] 刷新Token失败${resp.retcode} ${resp.message}`,
);
return;
}
accessToken.value = resp.AccessToken;
refreshToken.value = resp.RefreshToken;
accessExpire.value = Date.now() + resp.ExpiresIn * 1000;
if (!resp.data) {
showSnackbar.error("刷新Token返回数据为空");
await TGLogger.Error(`[HutaoStore][tryRefreshToken] 刷新Token返回数据为空`);
return;
}
accessToken.value = resp.data.AccessToken;
refreshToken.value = resp.data.RefreshToken;
accessExpire.value = Date.now() + resp.data.ExpiresIn * 1000;
showSnackbar.success("成功刷新胡桃云Token");
} catch (e) {
console.error(e);
showSnackbar.error("刷新胡桃云Token失败");
const errMsg = TGHttps.getErrMsg(e);
showSnackbar.error(`刷新胡桃云Token失败${errMsg}`);
await TGLogger.Error(`[HutaoStore][tryRefreshToken] 刷新Token异常${errMsg}`);
}
}