mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-10 08:58:15 +08:00
🌱 初步完成实时便笺获取,但未处理 1034
This commit is contained in:
@@ -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": {
|
||||
|
||||
@@ -90,9 +90,6 @@ function onCancel(): void {
|
||||
function onConfirm(): void {
|
||||
visible.value = false;
|
||||
emits("confirm");
|
||||
if (props.isInput) {
|
||||
inputVal.value = "";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
307
src/components/user/t-user-dailyNotes.vue
Normal file
307
src/components/user/t-user-dailyNotes.vue
Normal 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>
|
||||
28
src/components/user/tud-top-list.vue
Normal file
28
src/components/user/tud-top-list.vue
Normal 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>
|
||||
@@ -1,3 +1,7 @@
|
||||
<template>
|
||||
<h1>测试页</h1>
|
||||
<TUserDailyNotes />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TUserDailyNotes from "../../components/user/t-user-dailyNotes.vue";
|
||||
</script>
|
||||
|
||||
@@ -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
50
src/types/BBS/Geetest.d.ts
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user