🌱 初步完成实时便笺获取,但未处理 1034

This commit is contained in:
BTMuli
2023-07-29 20:32:38 +08:00
parent ca6bbccd89
commit 7ab9898f97
9 changed files with 457 additions and 7 deletions

View File

@@ -32,7 +32,8 @@
"https://passport-api-v4.mihoyo.com/*",
"https://act-webstatic.mihoyo.com/*",
"https://sdk-webstatic.mihoyo.com/*",
"https://homa.snapgenshin.com/*"
"https://homa.snapgenshin.com/*",
"https://help.tencentbot.top/geetest2/*"
]
},
"shell": {

View File

@@ -90,9 +90,6 @@ function onCancel(): void {
function onConfirm(): void {
visible.value = false;
emits("confirm");
if (props.isInput) {
inputVal.value = "";
}
}
</script>

View File

@@ -0,0 +1,307 @@
<template>
<ToLoading v-model="loading" :title="loadingTitle" :subtitle="loadingSub" />
<div class="tud-box">
<div class="tud-top">
<div class="tud-bt-quote">*数据刷新可能存在一定延迟请以当前游戏实际数据为准</div>
<div class="tud-bt-icon" @click="getDailyNotes">
<v-icon>mdi-refresh</v-icon>
</div>
</div>
<div class="tud-bottom">
<div v-if="notes.max_resin" class="tud-bl-list">
<TudTopList>
<template #icon>
<img src="/icon/material/106.webp" alt="resin" class="tud-bl-icon" />
</template>
<template #title>原粹树脂</template>
<template #subtitle>将于 {{ notes.resin_recovery_time }} 后全部恢复</template>
<template #rcontent> {{ notes.current_resin }}/{{ notes.max_resin }} </template>
</TudTopList>
<TudTopList>
<template #icon>
<img src="/icon/material/204.webp" alt="coin" class="tud-bl-icon" />
</template>
<template #title>洞天财瓮-洞天宝钱</template>
<template #subtitle>将于 {{ notes.home_coin_recovery_time }} 后全部恢复</template>
<template #rcontent> {{ notes.current_home_coin }}/{{ notes.max_home_coin }} </template>
</TudTopList>
<TudTopList>
<template #icon>
<img src="/icon/material/102.webp" alt="task" class="tud-bl-icon" />
</template>
<template #title>每日委托任务</template>
<template #subtitle>
{{
notes.is_extra_reward_received ? "『每日委托』奖励已领取" : "『每日委托』奖励未领取"
}}
</template>
<template #rcontent> {{ notes.finished_task_num }}/{{ notes.total_task_num }} </template>
</TudTopList>
<TudTopList>
<template #icon>
<img src="/icon/material/113021.webp" alt="boss" class="tud-bl-icon" />
</template>
<template #title>值得铭记的强敌</template>
<template #subtitle>本周剩余消耗减半次数</template>
<template #rcontent>
{{ notes.remain_resin_discount_num }}/{{ notes.resin_discount_num_limit }}
</template>
</TudTopList>
<TudTopList>
<template #icon>
<img src="/icon/material/220021.webp" alt="transform" class="tud-bl-icon" />
</template>
<template #title>参量质变仪</template>
<template #subtitle>
{{ notes.transformer.obtained ? "已准备完成" : "" }}
</template>
<template #rcontent>
{{ notes.transformer.obtained ? "可使用" : "" }}
</template>
</TudTopList>
</div>
<div v-if="notes.max_resin" class="tud-bottom-list">
<div class="tud-bt-title">
<span>探索派遣限制</span>
<span>{{ notes.current_expedition_num }}/{{ notes.max_expedition_num }}</span>
<span></span>
</div>
<div
v-for="avatar in notes.expeditions"
:key="avatar.remained_time"
class="tud-expedition-item"
>
<div
class="tud-avatar"
:style="{
borderRadius: '50%',
border: avatar.status === 'finished' ? '3px solid #4caf50' : '3px solid #f44336',
}"
>
<img :src="avatar.avatar_side_icon" alt="avatar" />
</div>
<div class="tud-ei-text">剩余探索时间{{ avatar.remained_time }}</div>
</div>
</div>
</div>
</div>
<ToConfirm
v-model="confirmShow"
v-model:model-input="confirmInput"
:title="confirmTitle"
subtitle="请输入返回结果"
:is-input="true"
@confirm="inputGeetest"
/>
<v-snackbar v-model="snackbar" timeout="1500" :color="snackbarColor">
{{ snackbarText }}
</v-snackbar>
</template>
<script lang="ts" setup>
// vue
import { onMounted, ref } from "vue";
import ToLoading from "../overlay/to-loading.vue";
import ToConfirm from "../overlay/to-confirm.vue";
import TudTopList from "./tud-top-list.vue";
// store
import { useUserStore } from "../../store/modules/user";
// utils
import TGRequest from "../../web/request/TGRequest";
import { createTGWindow } from "../../utils/TGWindow";
// loading
const loading = ref<boolean>(true);
const loadingTitle = ref<string>("正在获取数据...");
const loadingSub = ref<string>("");
// confirm
const confirmShow = ref<boolean>(false);
const confirmTitle = ref<string>();
const confirmInput = ref<string>("");
// snackbar
const snackbar = ref<boolean>(false);
const snackbarColor = ref<string>("success");
const snackbarText = ref<string>();
// store
const userStore = useUserStore();
// data
const user = ref<TGApp.Sqlite.Account.Game>(<TGApp.Sqlite.Account.Game>{});
const notes = ref<TGApp.Game.DailyNotes.FullInfo>(<TGApp.Game.DailyNotes.FullInfo>{});
const geetest = ref<TGApp.BBS.Geetest.postData>({
challenge: "",
validate: "",
});
onMounted(() => {
loadingTitle.value = "正在获取数据...";
loadingSub.value = "";
loading.value = true;
user.value = userStore.getCurAccount();
loading.value = false;
});
async function getDailyNotes(): Promise<void> {
loadingTitle.value = "正在获取数据...";
loadingSub.value = "";
loading.value = true;
const cookieGet = userStore.getCookieGroup4();
const cookie = {
account_id: cookieGet.account_id,
cookie_token: cookieGet.cookie_token,
ltoken: cookieGet.ltoken,
ltuid: cookieGet.ltuid,
};
const res = await TGRequest.User.dailyNote.widget(cookie, user.value);
if ("retcode" in res) {
if (res.retcode === 1034) {
loadingTitle.value = "检测到 1034 错误,需要进行极验验证";
await doGeetest();
} else {
console.error(`[${res.retcode}] ${res.message}`);
snackbarColor.value = "error";
snackbarText.value = `[${res.retcode}] ${res.message}`;
snackbar.value = true;
}
} else {
snackbarColor.value = "success";
snackbarText.value = "刷新成功";
snackbar.value = true;
notes.value = res;
}
}
function openTest(res: TGApp.BBS.Geetest.getData): void {
const url = `https://help.tencentbot.top/geetest2/?gt=${res.gt}&challenge=${res.challenge}`;
createTGWindow(url, "geetest", "极验验证-完成验证后请复制结果并关闭窗口", 800, 600, true);
}
async function doGeetest(): Promise<void> {
loadingTitle.value = "正在获取极验数据...";
const cookieGet = userStore.getCookieGroup3();
const cookie = {
ltoken: cookieGet.ltoken,
ltuid: cookieGet.ltuid,
};
const res = await TGRequest.User.dailyNote.getTest(cookie);
if ("retcode" in res) {
loading.value = false;
console.error(`[${res.retcode}] ${res.message}`);
snackbarColor.value = "error";
snackbarText.value = `[${res.retcode}] ${res.message}`;
snackbar.value = true;
} else {
geetest.value.challenge = res.challenge;
loadingTitle.value = "成功获取极验数据";
loadingSub.value = "请在新页面完成验证";
setTimeout(() => {
loading.value = false;
openTest(res);
confirmTitle.value = "请输入极验验证结果";
confirmInput.value = "";
confirmShow.value = true;
}, 1000);
}
}
async function inputGeetest(): Promise<void> {
geetest.value.validate = confirmInput.value;
const cookieGet = userStore.getCookieGroup4();
const cookie = {
ltoken: cookieGet.ltoken,
ltuid: cookieGet.ltuid,
};
const res = await TGRequest.User.dailyNote.postRes(cookie, geetest.value);
console.log(res);
}
</script>
<style lang="css" scoped>
.tud-box {
display: flex;
width: 600px;
height: auto;
flex-wrap: wrap;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px var(--common-shadow-4);
gap: 10px;
}
.tud-top {
display: flex;
width: 100%;
height: 20px;
align-items: center;
justify-content: space-between;
}
.tud-bt-quote {
height: 100%;
color: var(--common-text-quote);
font-size: 12px;
}
.tud-bt-icon {
width: 20px;
height: 20px;
margin-right: 5px;
color: var(--common-text-title);
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.tud-bt-icon:hover {
animation: fresh-bt-icon 0.3s linear;
}
@keyframes fresh-bt-icon {
0% {
transform: rotate(0deg) scale(0.9);
}
50% {
transform: rotate(180deg) scale(0.9);
}
100% {
transform: rotate(360deg) scale(0.9);
}
}
.tud-bottom {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
}
.tud-bl-list {
display: flex;
flex-wrap: wrap;
background: transparent;
gap: 5px;
}
.tud-bl-icon {
width: 30px;
height: 30px;
}
.tud-avatar {
display: flex;
width: 40px;
height: 40px;
justify-content: center;
border: 6px solid;
}
.tud-avatar img {
width: 130%;
height: 130%;
border-radius: 50%;
transform: translateY(-10px);
}
</style>

View File

@@ -0,0 +1,28 @@
<template>
<div class="tud-tl-box">
<div class="tud-tl-icon">
<slot name="icon"></slot>
</div>
<div class="tud-tl-lcontent">
<div class="tud-tl-title">
<slot name="title"></slot>
</div>
<div class="tud-tl-subtitle">
<slot name="subtitle"></slot>
</div>
</div>
<div class="tud-tl-rcontent">
<slot name="rcontent"></slot>
</div>
</div>
</template>
<style lang="css" scoped>
.tud-tl-box {
display: flex;
width: 100%;
height: 20px;
align-items: center;
justify-content: space-between;
border: 1px inset var(--common-color-grey);
}
</style>

View File

@@ -1,3 +1,7 @@
<template>
<h1>测试页</h1>
<TUserDailyNotes />
</template>
<script lang="ts" setup>
import TUserDailyNotes from "../../components/user/t-user-dailyNotes.vue";
</script>

View File

@@ -24,13 +24,13 @@ import {
/**
* @description 初始化应用表数据
* @since Alpha v0.2.0
* @since Alpha v0.2.2
* @returns {Promise<string[]>} sql
*/
async function initAppData(): Promise<string[]> {
const sqlRes: string[] = [];
const appVersion = await app.getVersion();
const buildTime = getBuildTime();
const buildTime: string = getBuildTime();
// 初始化应用版本
sqlRes.push(`
INSERT INTO AppData (key, value, updated)

50
src/types/BBS/Geetest.d.ts vendored Normal file
View File

@@ -0,0 +1,50 @@
/**
* @file types BBS Geetest.d.ts
* @description BBS 极验相关类型定义文件
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.2.2
*/
declare namespace TGApp.BBS.Geetest {
/**
* @description 获取极验验证的响应数据
* @since Alpha v0.2.2
* @extends TGApp.BBS.Response.Base
* @interface getResponse
* @property {getData} data - 极验验证的响应数据
* @return getGeetest
*/
export interface getResponse extends TGApp.BBS.Response.Base {
data: getData;
}
/**
* @description 极验验证的响应数据
* @since Alpha v0.2.2
* @interface getData
* @property {string} gt - 极验验证 gt
* @property {string} challenge - 极验验证 challenge
* @property {number} new_captcha - 极验验证 new_captcha
* @property {number} success - 极验验证 success
* @return getData
*/
export interface getData {
gt: string;
challenge: string;
new_captcha: number;
success: number;
}
/**
* @description 极验验证的请求数据
* @since Alpha v0.2.2
* @interface postData
* @property {string} challenge - 极验验证 challenge
* @property {string} validate - 极验验证 validate
* @return postData
*/
export interface postData {
challenge: string;
validate: string;
}
}

View File

@@ -2,12 +2,13 @@
* @file web request TGRequest.ts
* @description 应用用到的请求函数
* @author BTMuli <bt-muli@outlook.com>
* @since Alpha v0.2.1
* @since Alpha v0.2.2
*/
import { getAbyss } from "./getAbyss";
import { getAnnoList, getAnnoContent } from "./getAnno";
import { getCookieTokenBySToken } from "./getCookieToken";
import { getDailyNotes, getGeeTest, postGeeTest } from "./getDailyNotes";
// import * from "./getEnkaData.ts";
import { getGameAccountsBySToken, getGameAccountsByCookie } from "./getGameAccounts";
import { getGameRecord } from "./getGameRecord";
@@ -51,6 +52,11 @@ const TGRequest = {
getSyncAvatarListAll,
getSyncAvatarDetail,
},
dailyNote: {
widget: getDailyNotes,
getTest: getGeeTest,
postRes: postGeeTest,
},
},
};

View File

@@ -38,3 +38,60 @@ export async function getDailyNotes(
return res.data.data;
});
}
/**
* @description 获取极验验证码
* @since Alpha v0.2.2
* @param {Record<string, string>} cookie cookie
* @returns {Promise<TGApp.App.Base.Response|TGApp.BBS.Geetest.getData>}
*/
export async function getGeeTest(
cookie: Record<string, string>,
): Promise<TGApp.BBS.Response.Base | TGApp.BBS.Geetest.getData> {
const url = "https://api-takumi-record.mihoyo.com/game_record/app/card/wapi/createVerification";
const params = { is_high: "true" };
const header = getRequestHeader(cookie, "GET", params, "common");
return await http
.fetch<TGApp.BBS.Geetest.getResponse>(url, {
method: "GET",
headers: header,
query: params,
})
.then((res) => {
if (res.data.retcode !== 0) return res.data;
return res.data.data;
});
}
/**
* @description 发送极验验证码
* @since Alpha v0.2.2
* @param {Record<string, string>} cookie cookie
* @param {TGApp.BBS.Geetest.postData} geetest 极验验证的请求数据
* @returns {Promise<TGApp.BBS.Response.Base>}
*/
export async function postGeeTest(
cookie: Record<string, string>,
geetest: TGApp.BBS.Geetest.postData,
): Promise<TGApp.BBS.Response.Base> {
const url = "https://api-takumi-record.mihoyo.com/game_record/app/card/wapi/verifyVerification";
const data = {
geetest_challenge: geetest.challenge,
geetest_seccode: `${geetest.validate}|jordan`,
geetest_validate: geetest.validate,
};
const header = getRequestHeader(cookie, "POST", data, "common");
console.log(header);
console.log(cookie);
console.log(data);
return await http
.fetch<TGApp.BBS.Response.Base>(url, {
headers: header,
method: "POST",
body: http.Body.json(data),
})
.then((res) => {
if (res.data.retcode !== 0) return res.data;
return res.data.data;
});
}