From b52a3f7caf5a82edc0524850cb782761ca227ad2 Mon Sep 17 00:00:00 2001 From: Philip Kristoffersen Date: Sun, 11 Jun 2023 22:36:34 +0200 Subject: [PATCH] Fix finding more game pass games (#353) --- Cargo.lock | 18 ++++++- Cargo.toml | 3 +- src/platforms/gamepass/platform.rs | 86 +++++++++++++++++++++--------- 3 files changed, 80 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 594a4f5..5e04a09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,7 +399,7 @@ dependencies = [ [[package]] name = "boilr" -version = "1.9.0" +version = "1.9.1" dependencies = [ "base64 0.21.0", "color-eyre", @@ -417,6 +417,7 @@ dependencies = [ "nom", "openssl", "reqwest", + "roxmltree", "rusty-leveldb", "serde", "serde_json", @@ -2613,6 +2614,15 @@ dependencies = [ "serde", ] +[[package]] +name = "roxmltree" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f595a457b6b8c6cda66a48503e92ee8d19342f905948f29c383200ec9eb1d8" +dependencies = [ + "xmlparser", +] + [[package]] name = "rust-ini" version = "0.18.0" @@ -3970,6 +3980,12 @@ version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" +[[package]] +name = "xmlparser" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index 4c07201..0f30246 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = "2021" name = "boilr" -version = "1.9.0" +version = "1.9.1" [dependencies] base64 = "^0.21.0" @@ -64,6 +64,7 @@ winres = "^0.1.12" [target."cfg(windows)".dependencies] winreg = "^0.50.0" sqlite = "^0.30.3" +roxmltree = "^0.18.0" [features] # This feature is enabled when building for a flatpak environment diff --git a/src/platforms/gamepass/platform.rs b/src/platforms/gamepass/platform.rs index 703ca61..99132d5 100644 --- a/src/platforms/gamepass/platform.rs +++ b/src/platforms/gamepass/platform.rs @@ -14,12 +14,11 @@ pub struct GamePassPlatForm { settings: GamePassSettings, } -#[derive(Serialize,Deserialize, Default, Clone)] +#[derive(Serialize, Deserialize, Default, Clone)] pub struct GamePassSettings { enabled: bool, } - impl GamesPlatform for GamePassPlatForm { fn name(&self) -> &str { "Game Pass" @@ -37,39 +36,44 @@ impl GamesPlatform for GamePassPlatForm { let command = include_str!("./game_pass_games.ps1"); let res = run_powershell_command(command)?; let apps: Vec = serde_json::from_str(&res)?; - let expanded_search = false; - let windows_dir = std::env::var("WinDir").unwrap_or("C:\\Windows".to_string()); let explorer = Path::new(&windows_dir) .join("explorer.exe") .to_string_lossy() .to_string(); + + let name_getters: [fn(&AppInfo) -> eyre::Result; 3] = + [get_name_from_game, get_name_from_config, get_name_from_xml]; + let games_iter = apps .iter() .filter(|app| { - app.kind.is_game() - || (expanded_search - && (app.display_name.contains("DisplayName") - || app.display_name.contains("ms-resource"))) + !(app.display_name.contains("DisplayName") + || app.display_name.contains("ms-resource")) }) - .filter(|game| game.microsoft_game_path().exists() || game.appx_manifest().exists()) - .map(|game| { + .filter_map(|game| { let launch_url = format!("shell:AppsFolder\\{}", game.aum_id()); - let shortcut = Shortcut::new( - "0", - &game.display_name, - &explorer, - &windows_dir, - "", - "", - &launch_url, - ); - ShortcutToImport { - shortcut: shortcut.to_owned(), - needs_proton: false, - needs_symlinks: false, - } + name_getters + .iter() + .find_map(|&f| f(game).ok()) + .map(|game_name| { + let shortcut = Shortcut::new( + "0", + &game_name, + &explorer, + &windows_dir, + "", + "", + &launch_url, + ); + ShortcutToImport { + shortcut: shortcut.to_owned(), + needs_proton: false, + needs_symlinks: false, + } + }) }); + Ok(games_iter.collect()) } @@ -83,6 +87,38 @@ impl GamesPlatform for GamePassPlatForm { } } +fn get_name_from_xml(app_info: &AppInfo) -> eyre::Result { + use roxmltree::Document; + let path_to_config = app_info.appx_manifest(); + let xml = std::fs::read_to_string(path_to_config)?; + let doc = Document::parse(&xml)?; + doc.descendants() + .find(|n| n.has_tag_name("uap::VisualElements")) + .and_then(|n| n.attribute("DisplayName")) + .map(|n| n.to_string()) + .ok_or(eyre::format_err!("Name not found")) +} + +fn get_name_from_game(app_info: &AppInfo) -> eyre::Result { + if !app_info.kind.is_game() { + Err(eyre::format_err!("Not a game type")) + } else { + Ok(app_info.display_name.to_owned()) + } +} + +fn get_name_from_config(app_info: &AppInfo) -> eyre::Result { + use roxmltree::Document; + let path_to_config = app_info.microsoft_game_path(); + let xml = std::fs::read_to_string(path_to_config)?; + let doc = Document::parse(&xml)?; + doc.descendants() + .find(|n| n.has_tag_name("ShellVisuals")) + .and_then(|n| n.attribute("DefaultDisplayName")) + .map(|n| n.to_string()) + .ok_or(eyre::format_err!("Name not found")) +} + #[derive(Deserialize, Debug)] struct AppInfo { kind: Kind, @@ -105,7 +141,7 @@ impl AppInfo { } fn microsoft_game_path(&self) -> PathBuf { - Path::new(&self.install_location).join("MicrosoftGames.config") + Path::new(&self.install_location).join("MicrosoftGame.config") } fn appx_manifest(&self) -> PathBuf {