From 1a0477d6b9b9120c10f9a25cb87b24b4c9a5e601 Mon Sep 17 00:00:00 2001 From: Purp1e <47248616+Purple-CSGO@users.noreply.github.com> Date: Sun, 23 Mar 2025 22:41:19 +0800 Subject: [PATCH] [fix] steam id32 + avatar --- src-tauri/Cargo.lock | 174 ++++++++++++++++++++++++++--- src-tauri/Cargo.toml | 9 +- src-tauri/src/vdf/preset.rs | 89 +++++++++------ src/components/cstb/SteamUsers.tsx | 14 +-- src/components/window/Header.tsx | 6 +- src/components/window/SideBar.tsx | 10 +- 6 files changed, 238 insertions(+), 64 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fb71319..7a7b3ff 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -10,6 +10,7 @@ dependencies = [ "base64 0.22.1", "log", "regex", + "reqwest", "serde", "serde_json", "tauri", @@ -698,7 +699,7 @@ dependencies = [ "cocoa-foundation", "core-foundation 0.10.0", "core-graphics 0.24.0", - "foreign-types", + "foreign-types 0.5.0", "libc", "objc", ] @@ -826,7 +827,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", "core-graphics-types 0.1.3", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -839,7 +840,7 @@ dependencies = [ "bitflags 2.9.0", "core-foundation 0.10.0", "core-graphics-types 0.2.0", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -1422,6 +1423,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -1429,7 +1439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -1443,6 +1453,12 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -2091,6 +2107,22 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.10" @@ -2748,6 +2780,23 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk" version = "0.9.0" @@ -3204,6 +3253,50 @@ dependencies = [ "pathdiff", ] +[[package]] +name = "openssl" +version = "0.10.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -3965,6 +4058,7 @@ dependencies = [ "cookie", "cookie_store", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2", @@ -3973,11 +4067,13 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -3991,6 +4087,7 @@ dependencies = [ "sync_wrapper", "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -4179,6 +4276,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "schemars" version = "0.8.22" @@ -4212,6 +4318,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "selectors" version = "0.22.0" @@ -4498,7 +4627,7 @@ dependencies = [ "bytemuck", "cfg_aliases 0.2.1", "core-graphics 0.24.0", - "foreign-types", + "foreign-types 0.5.0", "js-sys", "log", "objc2 0.5.2", @@ -5151,9 +5280,9 @@ dependencies = [ [[package]] name = "tauri-plugin-valtio" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "920125988ca715c48bf74091e2fb4da951fac392f445b1d96df67a3a72c28877" +checksum = "a0b4f506590b0ce053703e225e780adc8dfae67cdb6e7a60141d4c25e23be0a0" dependencies = [ "serde", "tauri", @@ -5211,14 +5340,13 @@ dependencies = [ [[package]] name = "tauri-store" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82e807a25b2fa63ef204d61c44092c4b6262bb534c766f13e1b2f68cd07e568" +checksum = "d5640a5e33ce596c70b6b7a6b40b2021a011311f91b2a90e3267779062041dd2" dependencies = [ "dashmap", "futures", "itertools", - "semver", "serde", "serde_json", "tauri", @@ -5231,9 +5359,9 @@ dependencies = [ [[package]] name = "tauri-store-macros" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0a53dbd50f92ca25e352530aa80026a6b221fa04453df0c2bf2b198d3c71fa" +checksum = "87cd54d307240ecd1fd823468fd00f5aabf27e1945f621ba1392b915c0471f0a" dependencies = [ "proc-macro2", "quote", @@ -5242,12 +5370,12 @@ dependencies = [ [[package]] name = "tauri-store-utils" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48256653b57a054a65c5d650c998cabd8956522ade275641095c9a49e7506b9d" +checksum = "72f973009b5017f3b9289b37d34a91a78ba1458ab7734574728bd36fe946a28d" dependencies = [ "bon", - "futures", + "semver", "serde", "serde_json", "tauri", @@ -5500,6 +5628,16 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.2" @@ -5839,6 +5977,12 @@ dependencies = [ "serde", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bcddecd..87067d0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -29,8 +29,9 @@ log = "0.4.26" base64 = "0.22.1" walkdir = "2.5.0" serde_json = "1.0.140" -serde = { version = "1.0.219", features = ["derive"] } regex = "1.11.1" +serde = { version = "1.0.219", features = ["derive"] } +reqwest = { version = "0.12.15", features = ["blocking"] } tauri = { version = "2.4.0", features = [ "macos-private-api", "tray-icon" ] } @@ -43,12 +44,12 @@ tauri-plugin-clipboard-manager = "2.2.2" tauri-plugin-shell = "2.2.0" tauri-plugin-http = "2.4.2" tauri-plugin-notification = "2.2.2" -tauri-plugin-valtio = "2.0.0" +tauri-plugin-valtio = "2.1.0" tauri-plugin-store = "2.2.0" tauri-plugin-system-info = "2.0.9" tauri-plugin-theme = "2.1.3" -tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] } -tauri-plugin-deep-link = "2.0.0" +tauri-plugin-single-instance = { version = "2.2.2", features = ["deep-link"] } +tauri-plugin-deep-link = "2.2.0" anyhow = "1.0.97" [target.'cfg(windows)'.dependencies] # Windows Only winreg = "0.55.0" diff --git a/src-tauri/src/vdf/preset.rs b/src-tauri/src/vdf/preset.rs index 7600eda..37e9932 100644 --- a/src-tauri/src/vdf/preset.rs +++ b/src-tauri/src/vdf/preset.rs @@ -6,6 +6,7 @@ use serde_json::Value; use std::collections::HashMap; use std::fs; use std::path::Path; +use tauri_plugin_http::reqwest::blocking::get; use walkdir::WalkDir; use crate::steam; @@ -189,51 +190,32 @@ pub fn parse_local_users(steam_dir: &str) -> Result> { Ok(local_users) } -fn read_avatar(steam_dir: &str, steam_id64: &str) -> Option { - let t_path = Path::new(steam_dir).join(format!("avatarcache/{}.png", steam_id64)); - if !t_path.exists() { - return None; - } - - if let Ok(img) = fs::read(t_path) { - Some(STANDARD.encode(img)) - } else { - None - } -} - -pub fn get_users(steam_dir: &str) -> Result> { - let login_users = parse_login_users(steam_dir)?; - let local_users = parse_local_users(steam_dir)?; - let users = merge_users(login_users, local_users); - - Ok(users) -} - pub fn merge_users(login: Vec, local: Vec) -> Vec { let mut users = Vec::new(); for i in login { - let mut id32: u32 = 0; - let mut avatar = i.avatar; + let avatar: String; let mut avatar_key = String::new(); + // 匹配获取 avatar_key 在线获取头像使用 let t_usr: Vec<&LocalUser> = local .iter() - .filter(|j| i.persona_name == j.persona_name) + .filter(|j| i.steam_id32 == j.steam_id32) .collect(); - if t_usr.len() > 1 { - id32 = steam::id::id64_to_32(i.steam_id64); - } else if t_usr.len() == 1 { - avatar_key = t_usr[0].avatar_key.clone(); + + if let Some(usr) = t_usr.first() { + avatar_key = usr.avatar_key.clone(); } - if avatar.is_empty() && !avatar_key.is_empty() { + // 获取头像的base64 本地头像文件不存在时使用在线api获取 + if i.avatar.is_empty() && !avatar_key.is_empty() { avatar = download_avatar(&avatar_key).unwrap_or_default(); + } else { + avatar = i.avatar; } users.push(User { steam_id64: i.steam_id64, - steam_id32: id32, + steam_id32: i.steam_id32, account_name: i.account_name, persona_name: i.persona_name, recent: i.most_recent.parse().unwrap_or(0), @@ -253,7 +235,48 @@ pub fn merge_users(login: Vec, local: Vec) -> Vec { users } -fn download_avatar(avatar_key: &str) -> Result { - // Implement avatar download logic here - Ok(String::new()) +pub fn get_users(steam_dir: &str) -> Result> { + let login_users = parse_login_users(steam_dir)?; + let local_users = parse_local_users(steam_dir)?; + let users = merge_users(login_users, local_users); + + Ok(users) +} + +fn download_avatar(avatar_key: &str) -> Result { + // 下载并转换成Base64 "https://avatars.cloudflare.steamstatic.com/" + avatarKey + "_full.jpg" + let url = format!( + "https://avatars.cloudflare.steamstatic.com/{}_full.jpg", + avatar_key + ); + if let Ok(resp) = get(&url) { + if let Ok(bytes) = resp.bytes() { + return Ok(STANDARD.encode(bytes)); + } + } + return Err(anyhow::anyhow!("Failed to download avatar")); +} + +fn read_avatar(steam_dir: &str, steam_id64: &str) -> Option { + let t_path = Path::new(steam_dir).join(format!("config\\avatarcache\\{}.png", steam_id64)); + if !t_path.exists() { + return None; + } + + if let Ok(img) = fs::read(t_path) { + Some(STANDARD.encode(img)) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_users() { + let users = get_users("D:\\Programs\\Steam").unwrap(); + println!("{:?}", users); + } } diff --git a/src/components/cstb/SteamUsers.tsx b/src/components/cstb/SteamUsers.tsx index 2a244ef..4075e18 100644 --- a/src/components/cstb/SteamUsers.tsx +++ b/src/components/cstb/SteamUsers.tsx @@ -40,7 +40,7 @@ const SteamUsers = ({ className }: { className?: string }) => { className="flex gap-2 transition rounded-lg bg-zinc-50 dark:bg-zinc-900" > avatar @@ -56,13 +56,11 @@ const SteamUsers = ({ className }: { className?: string }) => { {user.steam_id64?.toString()} - - {user.recent} - - - - {user.avatar} - + {user.recent > 0 && ( + + 最近登录 + + )}
diff --git a/src/components/window/Header.tsx b/src/components/window/Header.tsx index 45b4e7a..cd2c294 100644 --- a/src/components/window/Header.tsx +++ b/src/components/window/Header.tsx @@ -1,14 +1,16 @@ import { useSteamStore } from "@/store/steam" +import { useRouter } from "next/navigation" const Header = () => { const steam = useSteamStore() + const router = useRouter() return (
-

+

router.push('/users')}> {steam.currentUser()?.persona_name || 'CS工具箱'}

-

+

router.push('/users')}> {steam.currentUser()?.account_name || '本周使用CS工具箱 114 小时'}

diff --git a/src/components/window/SideBar.tsx b/src/components/window/SideBar.tsx index d6c0382..bb7f568 100644 --- a/src/components/window/SideBar.tsx +++ b/src/components/window/SideBar.tsx @@ -1,5 +1,5 @@ "use client" -import { cn } from "@heroui/react" +import { cn, user } from "@heroui/react" import { Home, MonitorOne, Movie, Setting, Terminal, Toolkit } from "@icon-park/react" import { usePathname, useRouter } from "next/navigation" import type { ReactNode } from "react" @@ -7,6 +7,7 @@ import { getVersion } from "@tauri-apps/api/app" // import { platform } from "@tauri-apps/plugin-os" import { useAppStore } from "@/store/app" +import { useSteamStore } from "@/store/steam" interface SideButtonProps { route: string @@ -46,12 +47,17 @@ const SideButton = ({ } const Avatar = () => { + const steam = useSteamStore() const router = useRouter() const path = usePathname() return (