mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
🌱 完善 jsBridge
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
//! @file src/client.rs
|
||||
//! @desc 客户端模块,负责操作米游社客户端
|
||||
//! @since Beta v0.3.3
|
||||
//! @since Beta v0.3.4
|
||||
|
||||
use tauri::{AppHandle, Manager, WindowBuilder, WindowUrl};
|
||||
use url::Url;
|
||||
@@ -25,6 +25,7 @@ pub async fn create_mhy_client(handle: AppHandle, func: String) {
|
||||
mhy_window_config.url = get_mhy_client_url(func.clone());
|
||||
let has_mhy_client = handle.get_window("mhy_client").is_some();
|
||||
if has_mhy_client {
|
||||
dbg!("mhy_client exists");
|
||||
return;
|
||||
}
|
||||
let js_bridge = r#"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! @file src/main.rs
|
||||
//! @desc 主模块,用于启动应用
|
||||
//! @since Beta v0.3.3
|
||||
//! @since Beta v0.3.4
|
||||
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
@@ -48,6 +48,7 @@ async fn register_deep_link(app_handle: tauri::AppHandle) {
|
||||
#[tauri::command]
|
||||
async fn execute_js(app_handle: tauri::AppHandle, label: String, js: String) {
|
||||
let window = app_handle.get_window(&label).unwrap();
|
||||
dbg!(&js);
|
||||
window.eval(&js).ok().unwrap();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@ async function getGC(): Promise<void> {
|
||||
}
|
||||
|
||||
async function tryNewWindow(): Promise<void> {
|
||||
await mhyClient.open("game_record");
|
||||
await mhyClient.open("sign_in");
|
||||
// await mhyClient.open("game_record");
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
import { event, invoke } from "@tauri-apps/api";
|
||||
import type { Event } from "@tauri-apps/api/event";
|
||||
import { WebviewWindow } from "@tauri-apps/api/window";
|
||||
import Md5 from "js-md5";
|
||||
|
||||
import TGSqlite from "../plugins/Sqlite";
|
||||
import { useUserStore } from "../store/modules/user";
|
||||
import TGConstant from "../web/constant/TGConstant";
|
||||
import TGRequest from "../web/request/TGRequest";
|
||||
import TGUtils from "../web/utils/TGUtils";
|
||||
|
||||
// 正常 arg 参数
|
||||
interface NormalArg {
|
||||
@@ -72,6 +76,18 @@ class TGClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @func hideSideBar
|
||||
* @since Beta v0.3.4
|
||||
* @desc 隐藏侧边栏
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async hideSideBar(): Promise<void> {
|
||||
const executeJS =
|
||||
"javascript:(function() {let st = document.createElement('style');st.innerHTML = '::-webkit-scrollbar{display:none}';document.querySelector('body').appendChild(st);})();";
|
||||
await invoke("execute_js", { label: "mhy_client", js: executeJS });
|
||||
}
|
||||
|
||||
/**
|
||||
* @func open
|
||||
* @since Beta v0.3.4
|
||||
@@ -86,6 +102,7 @@ class TGClient {
|
||||
await invoke<InvokeArg>("create_mhy_client", { func });
|
||||
this.window = WebviewWindow.getByLabel("mhy_client");
|
||||
await this.window?.show();
|
||||
await this.hideSideBar();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,14 +115,33 @@ class TGClient {
|
||||
async handleCallback(arg: Event<string>): Promise<any> {
|
||||
console.log(`[${arg.windowLabel}] ${arg.payload}`);
|
||||
const { method, payload, callback } = <NormalArg>JSON.parse(arg.payload);
|
||||
console.log(method, payload, callback);
|
||||
switch (method) {
|
||||
case "getStatusBarHeight":
|
||||
this.getStatusBarHeight(callback);
|
||||
await this.getStatusBarHeight(callback);
|
||||
break;
|
||||
case "getCookieInfo":
|
||||
await this.getCookieInfo(callback);
|
||||
break;
|
||||
case "getActionTicket":
|
||||
await this.getActionTicket(payload, callback);
|
||||
break;
|
||||
case "getHTTPRequestHeaders":
|
||||
await this.getHTTPRequestHeaders(callback);
|
||||
break;
|
||||
case "getDS":
|
||||
await this.getDS(callback);
|
||||
break;
|
||||
case "getDS2":
|
||||
await this.getDS2(payload, callback);
|
||||
break;
|
||||
case "getUserInfo":
|
||||
await this.getUserInfo(callback);
|
||||
break;
|
||||
case "configure_share":
|
||||
await this.callback(callback ?? "");
|
||||
break;
|
||||
default:
|
||||
console.warn(`[${arg.windowLabel}] ${arg.payload}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +154,9 @@ class TGClient {
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async callback(callback: string, payload?: string): Promise<void> {
|
||||
const js = `javascript:mhyWebBridge("${callback}", ${payload ?? ""})`;
|
||||
await invoke("create_mhy_client");
|
||||
const js = `javascript:mhyWebBridge("${callback}", ${payload ?? ""});`;
|
||||
console.log(js);
|
||||
await invoke("create_mhy_client", { func: "execute_js" });
|
||||
await invoke("execute_js", { label: "mhy_client", js });
|
||||
}
|
||||
|
||||
@@ -130,9 +167,11 @@ class TGClient {
|
||||
* @param {string} callback - 回调函数名
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
getStatusBarHeight(callback: string): void {
|
||||
console.log("getStatusBarHeight");
|
||||
console.log(callback);
|
||||
async getStatusBarHeight(callback: string): Promise<void> {
|
||||
const data = {
|
||||
statusBarHeight: 0,
|
||||
};
|
||||
await this.callback(callback, JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,10 +182,134 @@ class TGClient {
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async getCookieInfo(callback: string): Promise<void> {
|
||||
console.log("getCookieInfo");
|
||||
const cookie = await TGSqlite.getCookie();
|
||||
const user = useUserStore();
|
||||
// todo:这边还不清楚返回结构
|
||||
const cookie = {
|
||||
data: {
|
||||
ltuid: user.cookie.ltuid,
|
||||
ltoken: user.cookie.ltoken,
|
||||
stuid: user.cookie.stuid,
|
||||
stoken: user.cookie.stoken,
|
||||
mid: user.cookie.mid,
|
||||
},
|
||||
};
|
||||
await this.callback(callback, JSON.stringify(cookie));
|
||||
}
|
||||
|
||||
/**
|
||||
* @func getActionTicket
|
||||
* @since Beta v0.3.4
|
||||
* @desc 获取米游社客户端的 action_ticket\
|
||||
* @param {unknown} payload - 请求参数
|
||||
* @param {string} callback - 回调函数名
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async getActionTicket(payload: any, callback: string): Promise<void> {
|
||||
const actionType = payload.action_type;
|
||||
const user = useUserStore();
|
||||
const uid = user.getCurAccount().gameUid;
|
||||
const mid = user.cookie.mid;
|
||||
const stoken = user.cookie.stoken;
|
||||
const actionTicket = await TGRequest.User.bySToken.getActionTicket(
|
||||
actionType,
|
||||
stoken,
|
||||
mid,
|
||||
uid,
|
||||
);
|
||||
await this.callback(callback, JSON.stringify(actionTicket));
|
||||
}
|
||||
|
||||
/**
|
||||
* @func getHTTPRequestHeaders
|
||||
* @since Beta v0.3.4
|
||||
* @desc 获取米游社客户端的 HTTP 请求头
|
||||
* @param {string} callback - 回调函数名
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async getHTTPRequestHeaders(callback: string): Promise<void> {
|
||||
console.log("getHTTPRequestHeaders");
|
||||
const header = {
|
||||
"x-rpc-client_type": "5",
|
||||
"x-rpc-device_id": localStorage.getItem("device_id") ?? "",
|
||||
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
||||
};
|
||||
const data = {
|
||||
headers: header,
|
||||
};
|
||||
await this.callback(callback, JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @func getDS
|
||||
* @since Beta v0.3.4
|
||||
* @desc 获取米游社客户端的 DS 参数
|
||||
* @param {string} callback - 回调函数名
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async getDS(callback: string): Promise<void> {
|
||||
console.log("getDS");
|
||||
const salt = TGConstant.Salt.LK2;
|
||||
const time = Math.floor(Date.now() / 1000).toString();
|
||||
const random = TGUtils.Tools.getRandomString(6);
|
||||
const ds = Md5.md5.update(`salt=${salt}&t=${time}&r=${random}`).hex();
|
||||
const data = {
|
||||
data: {
|
||||
DS: `${time},${random},${ds}`,
|
||||
},
|
||||
};
|
||||
await this.callback(callback, JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @func getDS2
|
||||
* @since Beta v0.3.4
|
||||
* @desc 获取米游社客户端的 DS 参数
|
||||
* @param {unknown} payload - 请求参数
|
||||
* @param {string} callback - 回调函数名
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async getDS2(payload: any, callback: string): Promise<void> {
|
||||
const { query, body } = payload;
|
||||
const salt = TGConstant.Salt.LK2;
|
||||
const time = Math.floor(Date.now() / 1000).toString();
|
||||
const random = TGUtils.Tools.getRandomNumber(100000, 200000).toString();
|
||||
const dataB = TGUtils.Tools.transParams(body);
|
||||
const dataQ = TGUtils.Tools.transParams(query);
|
||||
const ds = Md5.md5.update(`salt=${salt}&t=${time}&r=${random}&b=${dataB}&q=${dataQ}`).hex();
|
||||
const data = {
|
||||
data: {
|
||||
DS: `${time},${random},${ds}`,
|
||||
},
|
||||
};
|
||||
console.log(data);
|
||||
await this.callback(callback, JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @func getUserInfo
|
||||
* @since Beta v0.3.4
|
||||
* @desc 获取米游社客户端的用户信息
|
||||
* @param {string} callback - 回调函数名
|
||||
* @returns {void} - 无返回值
|
||||
*/
|
||||
async getUserInfo(callback: string): Promise<void> {
|
||||
const user = useUserStore();
|
||||
const cookieToken = user.cookie.cookie_token;
|
||||
const accountId = user.cookie.account_id;
|
||||
const userInfo = await TGRequest.User.byCookie.getUserInfo(cookieToken, accountId, true);
|
||||
if ("retcode" in userInfo) {
|
||||
console.error(`[${callback}] ${userInfo.message}`);
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
id: userInfo.uid,
|
||||
gender: userInfo.gender,
|
||||
nickname: userInfo.nickname,
|
||||
introduce: userInfo.introduce,
|
||||
avatar_url: userInfo.avatar_url,
|
||||
};
|
||||
await this.callback(callback, JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
|
||||
const mhyClient = new TGClient();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* @file web request TGRequest.ts
|
||||
* @description 应用用到的请求函数
|
||||
* @author BTMuli <bt-muli@outlook.com>
|
||||
* @since Beta v0.3.0
|
||||
* @since Beta v0.3.4
|
||||
*/
|
||||
|
||||
import { genAuthkey } from "./genAuthkey";
|
||||
import { getAbyss } from "./getAbyss";
|
||||
import { getActionTicketBySToken } from "./getActionTicket";
|
||||
import { getAnnoContent, getAnnoList } from "./getAnno";
|
||||
import { getCookieTokenByGameToken, getCookieTokenBySToken } from "./getCookieToken";
|
||||
// import * from "./getEnkaData.ts";
|
||||
@@ -48,6 +48,7 @@ const TGRequest = {
|
||||
getAccounts: getGameAccountsBySToken,
|
||||
getCookieToken: getCookieTokenBySToken,
|
||||
getLToken: getLTokenBySToken,
|
||||
getActionTicket: getActionTicketBySToken,
|
||||
},
|
||||
bgGameToken: {
|
||||
getCookieToken: getCookieTokenByGameToken,
|
||||
|
||||
@@ -15,7 +15,7 @@ import TGUtils from "../utils/TGUtils";
|
||||
* @param {Record<string, string>} cookie cookie
|
||||
* @param {string} schedule_type 1: 本期, 2: 上期
|
||||
* @param {TGApp.Sqlite.Account.Game} account 游戏账号
|
||||
* @returns {Promise<TGApp.Game.Abyss.FullData|TGApp.App.Base.Response>}
|
||||
* @returns {Promise<TGApp.Game.Abyss.FullData|TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getAbyss(
|
||||
cookie: Record<string, string>,
|
||||
|
||||
47
src/web/request/getActionTicket.ts
Normal file
47
src/web/request/getActionTicket.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file web/request/getActionTicket.ts
|
||||
* @description 获取米游社动态的 ActionTicket
|
||||
* @since Beta v0.3.4
|
||||
*/
|
||||
|
||||
import { http } from "@tauri-apps/api";
|
||||
|
||||
import TGUtils from "../utils/TGUtils";
|
||||
|
||||
/**
|
||||
* @description 通过 stoken 获取 ActionTicket
|
||||
* @since Beta v0.3.4
|
||||
* @todo 类型完善
|
||||
* @param {string} ActionType 动作类型
|
||||
* @param {string} SToken stoken
|
||||
* @param {string} MID 用户 MID
|
||||
* @param {string} UID 用户 UID
|
||||
* @returns {Promise<TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getActionTicketBySToken(
|
||||
ActionType: string,
|
||||
SToken: string,
|
||||
MID: string,
|
||||
UID: string,
|
||||
): Promise<TGApp.BBS.Response.Base> {
|
||||
const url = "https://api-takumi.mihoyo.com/auth/api/getActionTicketBySToken";
|
||||
const params = {
|
||||
action_type: ActionType,
|
||||
stoken: SToken,
|
||||
uid: UID,
|
||||
};
|
||||
const cookie = {
|
||||
mid: MID,
|
||||
stoken: SToken,
|
||||
};
|
||||
const header = TGUtils.User.getHeader(cookie, "GET", params, "k2");
|
||||
return await http
|
||||
.fetch<TGApp.BBS.Response.Base>(url, {
|
||||
method: "GET",
|
||||
headers: header,
|
||||
query: params,
|
||||
})
|
||||
.then((res) => {
|
||||
return res.data;
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file web request getUserInfo.ts
|
||||
* @description 获取用户信息请求
|
||||
* @since Beta v0.3.3
|
||||
* @since Beta v0.3.4
|
||||
*/
|
||||
|
||||
import { http } from "@tauri-apps/api";
|
||||
@@ -11,15 +11,28 @@ import TGUtils from "../utils/TGUtils";
|
||||
|
||||
/**
|
||||
* @description 根据 cookie 获取用户信息
|
||||
* @since Beta v0.3.3
|
||||
* @since Beta v0.3.4
|
||||
* @todo 完善
|
||||
* @param {string} cookie_token cookie token
|
||||
* @param {string} account_id 用户 account_id
|
||||
* @returns {Promise<TGApp.App.Account.BriefInfo | TGApp.BBS.Response.Base>}
|
||||
* @param {boolean} return_full 是否返回完整信息
|
||||
* @returns {Promise<TGApp.App.Account.BriefInfo | TGApp.Plugins.Mys.User.Info>}
|
||||
*/
|
||||
export async function getUserInfoByCookie(
|
||||
cookie_token: string,
|
||||
account_id: string,
|
||||
): Promise<TGApp.App.Account.BriefInfo | TGApp.BBS.Response.Base> {
|
||||
return_full: false,
|
||||
): Promise<TGApp.App.Account.BriefInfo | TGApp.BBS.Response.Base>;
|
||||
export async function getUserInfoByCookie(
|
||||
cookie_token: string,
|
||||
account_id: string,
|
||||
return_full: true,
|
||||
): Promise<TGApp.Plugins.Mys.User.Info | TGApp.BBS.Response.Base>;
|
||||
export async function getUserInfoByCookie(
|
||||
cookie_token: string,
|
||||
account_id: string,
|
||||
return_full: boolean = false,
|
||||
): Promise<TGApp.App.Account.BriefInfo | TGApp.BBS.Response.Base | TGApp.Plugins.Mys.User.Info> {
|
||||
const cookie = {
|
||||
cookie_token,
|
||||
account_id,
|
||||
@@ -36,6 +49,7 @@ export async function getUserInfoByCookie(
|
||||
.then((res) => {
|
||||
if (res.data.retcode !== 0) return res.data;
|
||||
const info = res.data.data.user_info;
|
||||
if (return_full === undefined || return_full) return info;
|
||||
return {
|
||||
nickname: info.nickname,
|
||||
uid: info.uid,
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/**
|
||||
* @file web utils TGUtils.ts
|
||||
* @description 应用用到的工具函数
|
||||
* @author BTMuli <bt-muli@outlook.com>
|
||||
* @since Beta v0.3.0
|
||||
* @since Beta v0.3.4
|
||||
*/
|
||||
|
||||
import { getAnnoCard } from "./getAnnoCard";
|
||||
import { getRequestHeader } from "./getRequestHeader";
|
||||
import { getRequestHeader, getRandomString, getRandomNumber } from "./getRequestHeader";
|
||||
import { parseAnnoContent } from "./parseAnno";
|
||||
import { getServerByUid, transCookie } from "./tools";
|
||||
import { getServerByUid, transCookie, transParams } from "./tools";
|
||||
|
||||
const TGUtils = {
|
||||
Anno: {
|
||||
@@ -21,6 +20,9 @@ const TGUtils = {
|
||||
Tools: {
|
||||
getServerByUid,
|
||||
transCookie,
|
||||
getRandomString,
|
||||
getRandomNumber,
|
||||
transParams,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ function getSalt(saltType: string): string {
|
||||
* @param {number} max 最大值
|
||||
* @returns {number} 随机数
|
||||
*/
|
||||
function getRandomNumber(min: number, max: number): number {
|
||||
export function getRandomNumber(min: number, max: number): number {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user