mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-03-20 04:39:45 +08:00
🌱 游戏签到
This commit is contained in:
404
src/components/userScripts/tus-sign.vue
Normal file
404
src/components/userScripts/tus-sign.vue
Normal file
@@ -0,0 +1,404 @@
|
||||
<template>
|
||||
<div class="tuss-box">
|
||||
<div class="tuss-top">
|
||||
<div class="tuss-title">签到任务</div>
|
||||
<div class="tuss-acts">
|
||||
<v-btn @click="tryRefresh()" class="tuss-btn" :loading="loadState">刷新</v-btn>
|
||||
<v-btn @click="tryAuto()" class="tuss-btn" :loading="loadSign">执行</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tuss-content">
|
||||
<div
|
||||
v-for="(item, idx) in signAccounts"
|
||||
:key="idx"
|
||||
@click="item.selected = !item.selected"
|
||||
:class="{ selected: item.selected }"
|
||||
class="tuss-item"
|
||||
>
|
||||
<v-icon v-if="item.selected" color="var(--tgc-od-blue)">
|
||||
mdi-checkbox-marked-outline
|
||||
</v-icon>
|
||||
<v-icon v-else color="var(--tgc-od-white)">mdi-checkbox-blank-outline</v-icon>
|
||||
<div class="tuss-account">
|
||||
<img :src="item.info.icon" alt="icon" />
|
||||
<span>{{ item.account.gameUid }} {{ item.account.regionName }}</span>
|
||||
</div>
|
||||
<div class="tuss-stat">
|
||||
<div
|
||||
class="tuss-reward"
|
||||
v-if="item.reward"
|
||||
:title="`${item.reward.name}x${item.reward.cnt}`"
|
||||
>
|
||||
<TMiImg :src="item.reward.icon" alt="icon" :ori="true" />
|
||||
<span>{{ item.reward.cnt }}</span>
|
||||
</div>
|
||||
<v-icon v-if="item.stat?.is_sign" color="green" title="已签到">mdi-check-circle</v-icon>
|
||||
<v-icon v-else color="var(--tgc-od-white)" title="未签到">mdi-circle</v-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showGeetest from "@comp/func/geetest.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TSUserAccount from "@Sqlite/modules/userAccount.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import lunaReq from "@/web/request/lunaReq.js";
|
||||
import miscReq from "@/web/request/miscReq.js";
|
||||
import takumiReq from "@/web/request/takumiReq.js";
|
||||
|
||||
type SignGameInfo = { title: string; icon: string; gid: number };
|
||||
type SignAccount = {
|
||||
selected: boolean;
|
||||
account: TGApp.Sqlite.Account.Game;
|
||||
info: SignGameInfo;
|
||||
stat?: TGApp.BBS.Sign.InfoRes;
|
||||
reward?: TGApp.BBS.Sign.HomeAward;
|
||||
};
|
||||
|
||||
const { cookie, uid } = storeToRefs(useUserStore());
|
||||
const loadScript = defineModel<boolean>();
|
||||
const loadState = ref<boolean>(false);
|
||||
const loadSign = ref<boolean>(false);
|
||||
const signAccounts = ref<Array<SignAccount>>([]);
|
||||
const gameAccounts = shallowRef<Array<TGApp.Sqlite.Account.Game>>([]);
|
||||
|
||||
watch(
|
||||
() => uid.value,
|
||||
async () => await loadData(),
|
||||
);
|
||||
|
||||
onMounted(async () => await loadData());
|
||||
|
||||
function getGameInfo(biz: string): SignGameInfo {
|
||||
switch (biz) {
|
||||
// 崩坏2
|
||||
case "bh2_cn":
|
||||
return { title: "崩坏2", icon: "/platforms/mhy/bh2.webp", gid: 3 };
|
||||
// 崩坏3
|
||||
case "bh3_cn":
|
||||
return { title: "崩坏3", icon: "/platforms/mhy/bh3.webp", gid: 1 };
|
||||
// 原神
|
||||
case "hk4e_cn":
|
||||
return { title: "原神", icon: "/platforms/mhy/ys.webp", gid: 2 };
|
||||
// 崩坏:星穹铁道
|
||||
case "hkrpg_cn":
|
||||
return { title: "崩坏:星穹铁道", icon: "/platforms/mhy/sr.webp", gid: 6 };
|
||||
// 未定事件簿
|
||||
case "nxx_cn":
|
||||
return { title: "未定事件簿", icon: "/platforms/mhy/wd.webp", gid: 4 };
|
||||
// 绝区零
|
||||
case "nap_cn":
|
||||
return { title: "绝区零", icon: "/platforms/mhy/zzz.webp", gid: 8 };
|
||||
default:
|
||||
return { title: biz, icon: "/platforms/mhy/mys.webp", gid: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
async function loadData(): Promise<void> {
|
||||
gameAccounts.value = [];
|
||||
signAccounts.value = [];
|
||||
if (uid.value === undefined) return;
|
||||
gameAccounts.value = await TSUserAccount.game.getAccount(uid.value);
|
||||
for (const ac of gameAccounts.value) {
|
||||
const info = getGameInfo(ac.gameBiz);
|
||||
signAccounts.value.push({ selected: true, account: ac, info });
|
||||
}
|
||||
}
|
||||
|
||||
async function tryRefresh(): Promise<void> {
|
||||
if (loadScript.value) {
|
||||
showSnackbar.warn("任务正在执行中,请稍后再试");
|
||||
return;
|
||||
}
|
||||
loadScript.value = true;
|
||||
loadState.value = true;
|
||||
await TGLogger.ScriptSep("签到任务");
|
||||
await TGLogger.Script("[签到任务]刷新账户");
|
||||
if (!cookie.value) {
|
||||
await TGLogger.Script("[签到任务]未检测到Cookie");
|
||||
showSnackbar.warn("当前账户未登录,请先登录");
|
||||
await TGLogger.ScriptSep("签到任务", false);
|
||||
loadState.value = false;
|
||||
loadScript.value = false;
|
||||
return;
|
||||
}
|
||||
await refreshState(cookie.value);
|
||||
await TGLogger.Script(`[签到任务]刷新账户成功,成功获取${signAccounts.value.length}个账户`);
|
||||
await TGLogger.ScriptSep("签到任务", false);
|
||||
loadScript.value = false;
|
||||
loadState.value = false;
|
||||
}
|
||||
|
||||
async function tryAuto(): Promise<void> {
|
||||
if (loadScript.value) {
|
||||
showSnackbar.warn("任务正在执行中,请稍后再试");
|
||||
return;
|
||||
}
|
||||
loadScript.value = true;
|
||||
loadSign.value = true;
|
||||
await TGLogger.ScriptSep("签到任务");
|
||||
await TGLogger.Script("[签到任务]执行签到");
|
||||
if (!cookie.value) {
|
||||
await TGLogger.Script("[签到任务]未检测到Cookie");
|
||||
showSnackbar.warn("当前账户未登录,请先登录");
|
||||
await TGLogger.ScriptSep("签到任务", false);
|
||||
loadScript.value = false;
|
||||
loadSign.value = false;
|
||||
return;
|
||||
}
|
||||
if (signAccounts.value.length === 0 || signAccounts.value.some((i) => i.stat === undefined)) {
|
||||
await TGLogger.Script("[签到任务]未检测到游戏账户或签到状态,正在刷新");
|
||||
await refreshState(cookie.value);
|
||||
}
|
||||
const selected = signAccounts.value.filter((i) => i.selected);
|
||||
if (selected.length === 0) {
|
||||
await TGLogger.Script("[签到任务]未选择任何账户");
|
||||
showSnackbar.warn("未选择任何账户");
|
||||
await TGLogger.ScriptSep("签到任务", false);
|
||||
loadScript.value = false;
|
||||
loadSign.value = false;
|
||||
return;
|
||||
}
|
||||
await trySign(selected, cookie.value);
|
||||
await refreshState(cookie.value);
|
||||
await TGLogger.Script("[签到任务]签到任务执行完毕");
|
||||
await TGLogger.ScriptSep("签到任务", false);
|
||||
loadScript.value = false;
|
||||
loadSign.value = false;
|
||||
}
|
||||
|
||||
async function refreshState(ck: TGApp.App.Account.Cookie): Promise<void> {
|
||||
if (uid.value === undefined) return;
|
||||
await TGLogger.Script("[签到任务]刷新签到状态");
|
||||
if (signAccounts.value.length === 0) {
|
||||
await TGLogger.Script("[签到任务]未检测到游戏账户,正在获取");
|
||||
const gameResp = await takumiReq.bind.gameRoles(ck);
|
||||
if (Array.isArray(gameResp)) {
|
||||
await TGLogger.Script("[签到任务]获取游戏账户成功");
|
||||
await TSUserAccount.game.saveAccounts(uid.value, gameResp);
|
||||
gameAccounts.value = await TSUserAccount.game.getAccount(uid.value);
|
||||
for (const ac of gameAccounts.value) {
|
||||
const info = getGameInfo(ac.gameBiz);
|
||||
const find = signAccounts.value.find((i) => i.account === ac);
|
||||
if (find) continue;
|
||||
signAccounts.value.push({ selected: true, account: ac, info });
|
||||
}
|
||||
} else {
|
||||
await TGLogger.Script(`[签到任务]获取游戏账户失败:${gameResp.retcode} ${gameResp.message}`);
|
||||
showSnackbar.error(`[${gameResp.retcode}] ${gameResp.message}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const cookie = { cookie_token: ck.cookie_token, account_id: ck.account_id };
|
||||
const dayNow = new Date().getDate();
|
||||
for (const item of signAccounts.value) {
|
||||
await TGLogger.Script(
|
||||
`[签到任务]刷新${item.info.title}-${item.account.regionName}-${item.account.gameUid}`,
|
||||
);
|
||||
if (item.reward === undefined) {
|
||||
const rewardResp = await lunaReq.home(item.account, cookie);
|
||||
if ("retcode" in rewardResp) {
|
||||
await TGLogger.Script(
|
||||
`[签到任务]获取签到奖励失败:${rewardResp.retcode} ${rewardResp.message}`,
|
||||
);
|
||||
showSnackbar.error(`[${rewardResp.retcode}] ${rewardResp.message}`);
|
||||
} else item.reward = rewardResp.awards[dayNow - 1];
|
||||
}
|
||||
const statResp = await lunaReq.info(item.account, cookie);
|
||||
if ("retcode" in statResp) {
|
||||
await TGLogger.Script(`[签到任务]获取签到状态失败:${statResp.retcode} ${statResp.message}`);
|
||||
showSnackbar.error(`[${statResp.retcode}] ${statResp.message}`);
|
||||
} else item.stat = statResp;
|
||||
}
|
||||
}
|
||||
|
||||
async function trySign(ac: SignAccount[], ck: TGApp.App.Account.Cookie): Promise<void> {
|
||||
const cookie = { cookie_token: ck.cookie_token, account_id: ck.account_id };
|
||||
const ckSign = { stoken: ck.stoken, stuid: ck.stuid, mid: ck.mid };
|
||||
for (const item of ac) {
|
||||
if (item.stat?.is_sign) {
|
||||
await TGLogger.Script(
|
||||
`[签到任务]${item.info.title}-${item.account.regionName}-${item.account.gameUid}已签到`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
await TGLogger.Script(
|
||||
`[签到任务]${item.info.title}-${item.account.regionName}-${item.account.gameUid}签到`,
|
||||
);
|
||||
let check = false;
|
||||
let challenge: string | undefined = undefined;
|
||||
while (!check) {
|
||||
const signResp = await lunaReq.sign(item.account, cookie, challenge);
|
||||
if (challenge !== undefined) challenge = undefined;
|
||||
if ("retcode" in signResp) {
|
||||
if (signResp.retcode === 1034) {
|
||||
await TGLogger.Script(`[签到任务]触发验证码,正在尝试验证`);
|
||||
const challengeGet = await miscReq.challenge(ckSign);
|
||||
if (challengeGet === false) {
|
||||
await TGLogger.Script("[签到任务]验证码验证失败");
|
||||
break;
|
||||
}
|
||||
challenge = challengeGet;
|
||||
continue;
|
||||
}
|
||||
await TGLogger.Script(`[签到任务]签到失败:${signResp.retcode} ${signResp.message}`);
|
||||
showSnackbar.error(`[${signResp.retcode}] ${signResp.message}`);
|
||||
break;
|
||||
}
|
||||
if (signResp.success === 0) check = true;
|
||||
else if (signResp.is_risk) {
|
||||
await TGLogger.Script("[签到任务]触发风险验证,开始验证");
|
||||
const gtRes = await showGeetest({
|
||||
gt: signResp.gt,
|
||||
challenge: signResp.challenge,
|
||||
new_captcha: 1,
|
||||
success: 1,
|
||||
});
|
||||
if (gtRes === false) {
|
||||
await TGLogger.Script("[签到任务]验证码验证失败");
|
||||
break;
|
||||
}
|
||||
challenge = signResp.challenge;
|
||||
} else break;
|
||||
}
|
||||
if (check) {
|
||||
await TGLogger.Script(
|
||||
`[签到任务]${item.info.title}-${item.account.regionName}-${item.account.gameUid}签到成功`,
|
||||
);
|
||||
} else {
|
||||
await TGLogger.Script(
|
||||
`[签到任务]${item.info.title}-${item.account.regionName}-${item.account.gameUid}签到失败,请重试`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuss-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 12px;
|
||||
background: var(--box-bg-1);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
color: var(--box-text-1);
|
||||
}
|
||||
|
||||
.tuss-top {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tuss-title {
|
||||
font-family: var(--font-title);
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.tuss-acts {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tuss-btn {
|
||||
background: var(--tgc-btn-1);
|
||||
color: var(--btn-text);
|
||||
}
|
||||
|
||||
.tuss-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.tuss-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
column-gap: 8px;
|
||||
padding: 10px;
|
||||
background: var(--box-bg-2);
|
||||
border-radius: 4px;
|
||||
color: var(--box-text-2);
|
||||
height: 80px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background: var(--box-bg-3);
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
}
|
||||
}
|
||||
|
||||
.tuss-account {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 4px;
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.tuss-stat {
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 4px;
|
||||
}
|
||||
|
||||
.tuss-reward {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background: var(--box-bg-4);
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
}
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: fit-content;
|
||||
min-width: 48px;
|
||||
padding: 0 4px;
|
||||
border-radius: 12px;
|
||||
font-size: 8px;
|
||||
text-align: center;
|
||||
background: var(--app-page-bg);
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -56,8 +56,8 @@
|
||||
<!-- 左侧脚本列表 -->
|
||||
<div class="us-scripts">
|
||||
<div class="us-title">脚本列表</div>
|
||||
<TusMission v-model="runScript" :account="curAccount" />
|
||||
<!-- todo 签到 -->
|
||||
<TusMission v-model="runScript" />
|
||||
<TusSign v-model="runScript" />
|
||||
</div>
|
||||
<!-- 右侧脚本输出 -->
|
||||
<TusOutput />
|
||||
@@ -69,6 +69,7 @@ import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TusMission from "@comp/userScripts/tus-mission.vue";
|
||||
import TusOutput from "@comp/userScripts/tus-output.vue";
|
||||
import TusSign from "@comp/userScripts/tus-sign.vue";
|
||||
import TSUserAccount from "@Sqlite/modules/userAccount.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, shallowRef } from "vue";
|
||||
|
||||
131
src/types/BBS/Sign.d.ts
vendored
Normal file
131
src/types/BBS/Sign.d.ts
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @file types/BBS/Sign.d.ts
|
||||
* @description 米游社游戏签到模块相关类型声明
|
||||
* @since Beta v0.7.2
|
||||
*/
|
||||
|
||||
declare namespace TGApp.BBS.Sign {
|
||||
/**
|
||||
* @description 获取签到奖励信息返回
|
||||
* @interface HomeResp
|
||||
* @since Beta v0.7.2
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {HomeRes} data - 返回数据
|
||||
* @returns HomeResp
|
||||
*/
|
||||
type HomeResp = TGApp.BBS.Response.BaseWithData<HomeRes>;
|
||||
|
||||
/**
|
||||
* @description 获取签到奖励信返回数据
|
||||
* @interface HomeRes
|
||||
* @property {number} month - 月份
|
||||
* @property {Array<HomeAward>} awards - 签到奖励列表
|
||||
* @property {string} biz - 业务标识
|
||||
* @property {boolean} resign - 是否补签
|
||||
* @property {HomeAwardExtra} short_extra_award - 签到额外奖励
|
||||
* @returns HomeRes
|
||||
*/
|
||||
type HomeRes = {
|
||||
month: number;
|
||||
awards: Array<HomeAward>;
|
||||
biz: string;
|
||||
resign: boolean;
|
||||
short_extra_award: HomeAwardExtra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 签到奖励
|
||||
* @interface HomeAward
|
||||
* @property {string} icon - 奖励图标
|
||||
* @property {string} name - 奖励名称
|
||||
* @property {number} cnt - 奖励数量
|
||||
* @returns HomeAward
|
||||
*/
|
||||
type HomeAward = { icon: string; name: string; cnt: number };
|
||||
|
||||
/**
|
||||
* @description 签到额外奖励
|
||||
* @interface HomeAwardExtra
|
||||
* @property {boolean} has_extra_award - 是否有额外奖励
|
||||
* @property {string} start_time - 额外奖励开始时间
|
||||
* @property {string} end_time - 额外奖励结束时间
|
||||
* @property {Array<HomeAward>} list - 额外奖励列表
|
||||
* @property {string} start_timestamp - 额外奖励开始时间戳
|
||||
* @property {string} end_timestamp - 额外奖励结束时间戳
|
||||
* @returns HomeAwardExtra
|
||||
*/
|
||||
type HomeAwardExtra = {
|
||||
has_extra_award: boolean;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
list: Array<HomeAward>;
|
||||
start_timestamp: string;
|
||||
end_timestamp: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 获取签到信息返回
|
||||
* @interface InfoResp
|
||||
* @since Beta v0.7.2
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {InfoRes} data - 返回数据
|
||||
* @returns InfoResp
|
||||
*/
|
||||
type InfoResp = TGApp.BBS.Response.BaseWithData<InfoRes>;
|
||||
|
||||
/**
|
||||
* @description 获取签到信息返回数据
|
||||
* @interface InfoRes
|
||||
* @since Beta v0.7.2
|
||||
* @property {number} total_sign_day - 总签到天数
|
||||
* @property {string} today - 今日日期
|
||||
* @property {boolean} is_sign - 是否已签到
|
||||
* @property {boolean} is_sub - 是否已补签
|
||||
* @property {string} region - 服务器
|
||||
* @property {number} sign_cnt_missed - 未签到天数
|
||||
* @property {number} short_sign_day - 未知属性
|
||||
* @property {boolean} send_first - 是否首签
|
||||
* @return InfoRes
|
||||
*/
|
||||
type InfoRes = {
|
||||
total_sign_day: number;
|
||||
today: string;
|
||||
is_sign: boolean;
|
||||
is_sub: boolean;
|
||||
region: string;
|
||||
sign_cnt_missed: number;
|
||||
short_sign_day: number;
|
||||
send_first: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 签到返回
|
||||
* @interface SignResp
|
||||
* @since Beta v0.7.2
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {SignRes} data - 返回数据
|
||||
* @returns SignResp
|
||||
*/
|
||||
type SignResp = TGApp.BBS.Response.BaseWithData<SignRes>;
|
||||
|
||||
/**
|
||||
* @description 签到返回数据
|
||||
* @interface SignRes
|
||||
* @since Beta v0.7.2
|
||||
* @property {string} challenge - gt-challenge
|
||||
* @property {string} code - 签到状态码
|
||||
* @property {string} gt - gt
|
||||
* @property {boolean} is_risk - 是否有风险
|
||||
* @property {number} risk_code - 风险码
|
||||
* @property {number} success - 是否成功
|
||||
* @return SignRes
|
||||
*/
|
||||
type SignRes = {
|
||||
challenge: string;
|
||||
code: string;
|
||||
gt: string;
|
||||
is_risk: boolean;
|
||||
risk_code: number;
|
||||
success: number;
|
||||
};
|
||||
}
|
||||
152
src/web/request/lunaReq.ts
Normal file
152
src/web/request/lunaReq.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file web/request/lunaReq.ts
|
||||
* @description 签到模块请求
|
||||
* @since Beta v0.7.2
|
||||
*/
|
||||
import TGBbs from "@/utils/TGBbs.js";
|
||||
import TGHttp from "@/utils/TGHttp.js";
|
||||
import { getRequestHeader } from "@/web/utils/getRequestHeader.js";
|
||||
|
||||
// takumiEventLunaApiBaseUrl => telaBu
|
||||
const telaBu: Readonly<string> = "https://api-takumi.mihoyo.com/event/luna/";
|
||||
|
||||
type ReqParam = { host?: string; actId: string };
|
||||
|
||||
/**
|
||||
* @description 根据服务器获取actId跟host
|
||||
* @since Beta v0.7.2
|
||||
* @param {string} region - 服务器
|
||||
* @returns {string} actId
|
||||
*/
|
||||
function getActConf(region: string): ReqParam | false {
|
||||
switch (region) {
|
||||
// 崩坏2
|
||||
case "bh2_cn":
|
||||
return { actId: "e202203291431091" };
|
||||
// 崩坏3
|
||||
case "bh3_cn":
|
||||
return { actId: "e202306201626331" };
|
||||
// 原神
|
||||
case "hk4e_cn":
|
||||
return { actId: "e202311201442471", host: "hk4e" };
|
||||
// 崩坏:星穹铁道
|
||||
case "hkrpg_cn":
|
||||
return { actId: "e202304121516551", host: "hkrpg" };
|
||||
// 未定事件簿
|
||||
case "nxx_cn":
|
||||
return { actId: "e202202251749321" };
|
||||
// 绝区零
|
||||
case "nap_cn":
|
||||
return { actId: "e202406242138391", host: "zzz" };
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取签到奖励列表
|
||||
* @since Beta v0.7.2
|
||||
* @property {TGApp.Sqlite.Account.Game} account - 账号信息
|
||||
* @property {Record<string, string>} cookie - cookies
|
||||
* @returns {Promise<TGApp.BBS.Sign.HomeRes|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
async function getLunaHome(
|
||||
account: TGApp.Sqlite.Account.Game,
|
||||
cookie: Record<string, string>,
|
||||
): Promise<TGApp.BBS.Sign.HomeRes | TGApp.BBS.Response.Base> {
|
||||
const conf = getActConf(account.gameBiz);
|
||||
if (conf === false) {
|
||||
return <TGApp.BBS.Response.Base>{ retcode: 1, message: "未知服务器" };
|
||||
}
|
||||
const url = conf.host ? `${telaBu}${conf.host}/home` : `${telaBu}home`;
|
||||
const params = { lang: "zh-cn", act_id: conf.actId };
|
||||
const header: Record<string, string> = {
|
||||
"user-agent": TGBbs.ua,
|
||||
referer: "https://act.mihoyo.com",
|
||||
cookie: Object.keys(cookie)
|
||||
.map((key) => `${key}=${cookie[key]}`)
|
||||
.join("; "),
|
||||
};
|
||||
if (conf.host) if (conf.host) header["x-rpc-signgame"] = conf.host;
|
||||
const resp = await TGHttp<TGApp.BBS.Sign.HomeResp>(url, {
|
||||
method: "GET",
|
||||
query: params,
|
||||
headers: header,
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取签到信息
|
||||
* @since Beta v0.7.2
|
||||
* @property {TGApp.Sqlite.Account.Game} account - 账号信息
|
||||
* @property {Record<string, string>} cookie - cookies
|
||||
* @returns {Promise<TGApp.BBS.Sign.InfoRes|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
async function getLunaInfo(
|
||||
account: TGApp.Sqlite.Account.Game,
|
||||
cookie: Record<string, string>,
|
||||
): Promise<TGApp.BBS.Sign.InfoRes | TGApp.BBS.Response.Base> {
|
||||
const conf = getActConf(account.gameBiz);
|
||||
if (conf === false) {
|
||||
return <TGApp.BBS.Response.Base>{ retcode: 1, message: "未知服务器" };
|
||||
}
|
||||
const url = conf.host ? `${telaBu}${conf.host}/info` : `${telaBu}info`;
|
||||
const params = {
|
||||
lang: "zh-cn",
|
||||
act_id: conf.actId,
|
||||
region: account.region,
|
||||
uid: account.gameUid,
|
||||
};
|
||||
const header: Record<string, string> = {
|
||||
"user-agent": TGBbs.ua,
|
||||
referer: "https://act.mihoyo.com",
|
||||
cookie: Object.keys(cookie)
|
||||
.map((key) => `${key}=${cookie[key]}`)
|
||||
.join("; "),
|
||||
};
|
||||
if (conf.host) header["x-rpc-signgame"] = conf.host;
|
||||
const resp = await TGHttp<TGApp.BBS.Sign.InfoResp>(url, {
|
||||
method: "GET",
|
||||
query: params,
|
||||
headers: header,
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
async function lunaSign(
|
||||
account: TGApp.Sqlite.Account.Game,
|
||||
cookie: Record<string, string>,
|
||||
challenge?: string,
|
||||
): Promise<TGApp.BBS.Sign.SignRes | TGApp.BBS.Response.Base> {
|
||||
const conf = getActConf(account.gameBiz);
|
||||
if (conf === false) {
|
||||
return <TGApp.BBS.Response.Base>{ retcode: 1, message: "未知服务器" };
|
||||
}
|
||||
const url = conf.host ? `${telaBu}${conf.host}/sign` : `${telaBu}sign`;
|
||||
const data = {
|
||||
lang: "zh-cn",
|
||||
act_id: conf.actId,
|
||||
region: account.region,
|
||||
uid: account.gameUid,
|
||||
};
|
||||
const header: Record<string, string> = {
|
||||
...getRequestHeader(cookie, "POST", JSON.stringify(data), "X6"),
|
||||
"x-rpc-client_type": "2",
|
||||
};
|
||||
if (conf.host) header["x-rpc-signgame"] = conf.host;
|
||||
if (challenge) header["x-rpc-challenge"] = challenge;
|
||||
const resp = await TGHttp<TGApp.BBS.Sign.SignResp>(url, {
|
||||
method: "POST",
|
||||
headers: header,
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
const lunaReq = { home: getLunaHome, info: getLunaInfo, sign: lunaSign };
|
||||
|
||||
export default lunaReq;
|
||||
Reference in New Issue
Block a user