mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-14 09:38:13 +08:00
@@ -10,17 +10,21 @@
|
||||
<template #actions>
|
||||
<v-spacer />
|
||||
<v-btn variant="outlined" @click="scan = true" icon="mdi-qrcode-scan" />
|
||||
<v-btn variant="outlined" @click="toWebLogin" icon="mdi-web" />
|
||||
<v-btn variant="outlined" @click="confirmRefreshUser" icon="mdi-refresh" :loading="loading" />
|
||||
</template>
|
||||
</v-card>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { event, window as windowTauri } from "@tauri-apps/api";
|
||||
import type { UnlistenFn } from "@tauri-apps/api/helpers/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
|
||||
import TGSqlite from "../../plugins/Sqlite";
|
||||
import { useAppStore } from "../../store/modules/app";
|
||||
import { useUserStore } from "../../store/modules/user";
|
||||
import TGClient from "../../utils/TGClient";
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import { getDeviceFp } from "../../web/request/getDeviceFp";
|
||||
import TGRequest from "../../web/request/TGRequest";
|
||||
@@ -46,12 +50,175 @@ const userInfo = ref<TGApp.App.Account.BriefInfo>({
|
||||
avatar: "/source/UI/lumine.webp",
|
||||
});
|
||||
|
||||
let signListener: UnlistenFn;
|
||||
|
||||
onMounted(() => {
|
||||
if (userStore.briefInfo.value && userStore.briefInfo.value.nickname) {
|
||||
userInfo.value = userStore.briefInfo.value;
|
||||
}
|
||||
});
|
||||
|
||||
async function toWebLogin(): Promise<void> {
|
||||
const confirm = await showConfirm({
|
||||
title: "请在子窗口中完成登录操作",
|
||||
text: "请操作完成后点击子窗口的“用户登录”菜单",
|
||||
});
|
||||
if (!confirm) {
|
||||
showSnackbar({
|
||||
color: "cancel",
|
||||
text: "已取消登录",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await TGClient.open("config_sign_in", "https://user.mihoyo.com");
|
||||
signListener = await event.listen("config_user_sign", async (e) => {
|
||||
if (typeof e.payload !== "string") {
|
||||
showSnackbar({
|
||||
color: "error",
|
||||
text: "登录失败!",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await getTokenWeb(e.payload);
|
||||
});
|
||||
}
|
||||
|
||||
async function getTokenWeb(cookie: string): Promise<void> {
|
||||
await windowTauri.appWindow.setFocus();
|
||||
emits("loadOuter", { show: true, title: "正在解析 cookie" });
|
||||
const ck = cookie.split(";").reduce(
|
||||
(prev, curr) => {
|
||||
const [key, value] = curr.split("=");
|
||||
prev[key.trim()] = value.trim();
|
||||
return prev;
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
if (!("login_ticket" in ck) || !("login_uid" in ck)) {
|
||||
emits("loadOuter", { show: false });
|
||||
showSnackbar({
|
||||
text: "未检测到 login_ticket, 请确认是否登录成功!",
|
||||
color: "error",
|
||||
});
|
||||
try {
|
||||
setTimeout(() => {
|
||||
windowTauri.WebviewWindow.getByLabel("mhy_client")?.setFocus();
|
||||
}, 2000);
|
||||
} catch (e) {
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 无法获取子窗口");
|
||||
await TGClient.open("config_sign_in", "https://user.mihoyo.com/");
|
||||
}
|
||||
return;
|
||||
}
|
||||
emits("loadOuter", { show: true, title: "正在获取 token" });
|
||||
let cookieUser: TGApp.User.Account.Cookie = {
|
||||
account_id: "",
|
||||
ltuid: "",
|
||||
stuid: "",
|
||||
mid: "",
|
||||
cookie_token: "",
|
||||
stoken: "",
|
||||
ltoken: "",
|
||||
};
|
||||
cookieUser.account_id = ck["login_uid"];
|
||||
cookieUser.ltuid = ck["login_uid"];
|
||||
cookieUser.stuid = ck["login_uid"];
|
||||
const tokenRes = await TGRequest.User.byLoginTicket.getTokens(
|
||||
ck["login_ticket"],
|
||||
ck["login_uid"],
|
||||
);
|
||||
if ("retcode" in tokenRes) {
|
||||
emits("loadOuter", { show: false });
|
||||
showSnackbar({
|
||||
text: "获取 token 失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 获取 token 失败");
|
||||
await TGLogger.Error(`[tc-userBadge][getTokenWeb] ${tokenRes.retcode}: ${tokenRes.message}`);
|
||||
return;
|
||||
}
|
||||
tokenRes.map((i) => {
|
||||
if (i.name === "ltoken") return (cookieUser.ltoken = i.token);
|
||||
if (i.name === "stoken") return (cookieUser.stoken = i.token);
|
||||
});
|
||||
if (cookieUser.ltoken === "" || cookieUser.stoken === "") {
|
||||
emits("loadOuter", { show: false });
|
||||
showSnackbar({
|
||||
text: "获取 ltoken 或者 stoken 失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 获取 ltoken 或者 stoken 失败");
|
||||
return;
|
||||
}
|
||||
const ltokenRes = await TGRequest.User.byLToken.verify(cookieUser.ltoken, cookieUser.ltuid);
|
||||
if (typeof ltokenRes !== "string") {
|
||||
showSnackbar({
|
||||
text: "ltoken 验证失败!",
|
||||
color: "error",
|
||||
});
|
||||
} else {
|
||||
cookieUser.mid = ltokenRes;
|
||||
}
|
||||
if (!cookieUser.stoken.startsWith("v2")) {
|
||||
const stokenRes = await TGRequest.User.bySToken.update(cookieUser.stoken, cookieUser.stuid);
|
||||
if ("retcode" in stokenRes) {
|
||||
showSnackbar({
|
||||
text: "stoken 更新失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] stoken 更新失败");
|
||||
await TGLogger.Error(
|
||||
`[tc-userBadge][getTokenWeb] ${stokenRes.retcode}: ${stokenRes.message}`,
|
||||
);
|
||||
} else {
|
||||
cookieUser.stoken = stokenRes.token.token;
|
||||
if (cookieUser.mid === "" && stokenRes.user_info.mid !== "")
|
||||
cookieUser.mid = stokenRes.user_info.mid;
|
||||
}
|
||||
}
|
||||
const cookieTokenRes = await TGRequest.User.bySToken.getCookieToken(
|
||||
cookieUser.mid,
|
||||
cookieUser.stoken,
|
||||
);
|
||||
if (typeof cookieTokenRes !== "string") {
|
||||
showSnackbar({
|
||||
text: "cookie_token 获取失败!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] cookie_token 获取失败");
|
||||
await TGLogger.Error(
|
||||
`[tc-userBadge][getTokenWeb] ${cookieTokenRes.retcode}: ${cookieTokenRes.message}`,
|
||||
);
|
||||
} else {
|
||||
cookieUser.cookie_token = cookieTokenRes;
|
||||
}
|
||||
userStore.cookie.value = cookieUser;
|
||||
try {
|
||||
await windowTauri.WebviewWindow.getByLabel("mhy_client")?.close();
|
||||
} catch (e) {
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 无法获取子窗口");
|
||||
showSnackbar({
|
||||
text: "请手动关闭子窗口!",
|
||||
color: "error",
|
||||
});
|
||||
}
|
||||
signListener();
|
||||
emits("loadOuter", { show: false });
|
||||
// 检测cookie是否每项都有
|
||||
if (Object.values(cookieUser).some((i) => i === "")) {
|
||||
showSnackbar({
|
||||
text: "获取 cookie 失败!部分项为空!",
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error("[tc-userBadge][getTokenWeb] 获取 cookie 失败");
|
||||
return;
|
||||
}
|
||||
showSnackbar({
|
||||
text: "登录成功!",
|
||||
color: "success",
|
||||
});
|
||||
}
|
||||
|
||||
async function refreshUser() {
|
||||
const ck = userStore.cookie.value;
|
||||
if (ck === undefined || JSON.stringify(ck) === "{}") {
|
||||
@@ -194,6 +361,10 @@ async function confirmRefreshUser(): Promise<void> {
|
||||
}
|
||||
await refreshUser();
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (signListener) signListener();
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tcu-box {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<TOverlay v-model="visible" hide blur-val="20px" :to-click="onCancel">
|
||||
<div class="tog-box">
|
||||
<div class="tog-top">
|
||||
<div class="tog-title">请使用米游社APP进行扫码操作</div>
|
||||
<div class="tog-subtitle">所需米游社版本 >= 2.57.1</div>
|
||||
<div class="tog-title">请使用原神进行扫码操作</div>
|
||||
<div class="tog-subtitle">仅支持官服,渠道服请使用网页登录</div>
|
||||
</div>
|
||||
<div class="tog-mid">
|
||||
<qrcode-vue
|
||||
@@ -24,6 +24,7 @@ import { computed, onUnmounted, reactive, ref, watch } from "vue";
|
||||
|
||||
import Mys from "../../plugins/Mys";
|
||||
import { useUserStore } from "../../store/modules/user";
|
||||
import TGLogger from "../../utils/TGLogger";
|
||||
import TGRequest from "../../web/request/TGRequest";
|
||||
import showSnackbar from "../func/snackbar";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
@@ -58,7 +59,6 @@ const cookie = reactive<TGApp.User.Account.Cookie>({
|
||||
ltuid: "",
|
||||
stuid: "",
|
||||
mid: "",
|
||||
game_token: "",
|
||||
cookie_token: "",
|
||||
stoken: "",
|
||||
ltoken: "",
|
||||
@@ -113,11 +113,10 @@ async function cycleGetData() {
|
||||
color: "error",
|
||||
});
|
||||
if (res.retcode === -106) {
|
||||
// 二维码过期
|
||||
await freshQr();
|
||||
} else {
|
||||
// 取消轮询
|
||||
if (cycleTimer) clearInterval(cycleTimer);
|
||||
clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
visible.value = false;
|
||||
}
|
||||
return;
|
||||
@@ -126,14 +125,22 @@ async function cycleGetData() {
|
||||
return;
|
||||
}
|
||||
if (res.stat === "Confirmed") {
|
||||
// 取消轮询
|
||||
if (cycleTimer) clearInterval(cycleTimer);
|
||||
clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
if (res.payload.proto !== "OpenToken") {
|
||||
await TGLogger.Warn(`[to-gameLogin] 检测到非Combo协议:${res.payload.proto}`);
|
||||
showSnackbar({
|
||||
text: "请使用原神进行扫码操作",
|
||||
color: "error",
|
||||
});
|
||||
visible.value = false;
|
||||
return;
|
||||
}
|
||||
const data: TGApp.Plugins.Mys.GameLogin.StatusPayloadRaw = JSON.parse(res.payload.raw);
|
||||
cookie.account_id = data.uid;
|
||||
cookie.ltuid = data.uid;
|
||||
cookie.stuid = data.uid;
|
||||
cookie.game_token = data.token;
|
||||
await getTokens();
|
||||
await getTokens(data.open_token);
|
||||
showSnackbar({
|
||||
text: "登录成功",
|
||||
color: "success",
|
||||
@@ -145,27 +152,29 @@ async function cycleGetData() {
|
||||
}
|
||||
}
|
||||
|
||||
async function getTokens(): Promise<void> {
|
||||
const stokenRes = await TGRequest.User.bgGameToken.getStoken(
|
||||
cookie.account_id,
|
||||
cookie.game_token,
|
||||
);
|
||||
async function getTokens(game_token: string): Promise<void> {
|
||||
const stokenRes = await TGRequest.User.bgGameToken.getStoken(cookie.account_id, game_token);
|
||||
if (!("retcode" in stokenRes)) {
|
||||
cookie.stoken = stokenRes.token.token;
|
||||
cookie.mid = stokenRes.user_info.mid;
|
||||
} else {
|
||||
await TGLogger.Error("[to-gameLogin] 获取stoken失败");
|
||||
}
|
||||
const cookieTokenRes = await TGRequest.User.bgGameToken.getCookieToken(
|
||||
cookie.account_id,
|
||||
cookie.game_token,
|
||||
game_token,
|
||||
);
|
||||
if (typeof cookieTokenRes === "string") cookie.cookie_token = cookieTokenRes;
|
||||
else await TGLogger.Error("[to-gameLogin] 获取cookieToken失败");
|
||||
const ltokenRes = await TGRequest.User.bySToken.getLToken(cookie.mid, cookie.stoken);
|
||||
if (typeof ltokenRes === "string") cookie.ltoken = ltokenRes;
|
||||
else await TGLogger.Error("[to-gameLogin] 获取ltoken失败");
|
||||
userStore.cookie.value = cookie;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cycleTimer) clearInterval(cycleTimer);
|
||||
if (cycleTimer !== null) clearInterval(cycleTimer);
|
||||
cycleTimer = null;
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
|
||||
Reference in New Issue
Block a user