diff --git a/src/defaultconfig.toml b/src/defaultconfig.toml index c47ebdb..9d512e0 100644 --- a/src/defaultconfig.toml +++ b/src/defaultconfig.toml @@ -11,6 +11,9 @@ create_symlinks = true enabled = false create_symlinks = true +[uplay] +enabled = false + [legendary] enabled = false diff --git a/src/egs/epic_platform.rs b/src/egs/epic_platform.rs index 79a339e..a6bb5ab 100644 --- a/src/egs/epic_platform.rs +++ b/src/egs/epic_platform.rs @@ -37,8 +37,9 @@ impl Platform for EpicPlatform { let shortcuts_res = self.get_shortcuts(); match shortcuts_res { Ok(_) => SettingsValidity::Valid, - Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, } } - } diff --git a/src/egs/get_manifests.rs b/src/egs/get_manifests.rs index c200301..ef3a5b2 100644 --- a/src/egs/get_manifests.rs +++ b/src/egs/get_manifests.rs @@ -82,9 +82,9 @@ pub fn get_default_location() -> Option { #[cfg(target_os = "windows")] { - let path = match location_from_registry(){ + let path = match location_from_registry() { Some(path) => path, - None => guess_default_location() + None => guess_default_location(), }; if path.exists() { Some(path) diff --git a/src/egs/mod.rs b/src/egs/mod.rs index 09a9e8d..86aab01 100644 --- a/src/egs/mod.rs +++ b/src/egs/mod.rs @@ -1,10 +1,10 @@ +mod epic_platform; mod get_manifests; mod manifest_item; mod settings; -mod epic_platform; -pub(crate) use manifest_item::*; -use get_manifests::get_egs_manifests; +pub use epic_platform::*; pub use get_manifests::get_default_location; +use get_manifests::get_egs_manifests; +pub(crate) use manifest_item::*; pub use settings::EpicGamesLauncherSettings; -pub use epic_platform::*; \ No newline at end of file diff --git a/src/egs/settings.rs b/src/egs/settings.rs index 5bef498..4ef50fd 100644 --- a/src/egs/settings.rs +++ b/src/egs/settings.rs @@ -1,6 +1,6 @@ -use serde::{Serialize,Deserialize}; +use serde::{Deserialize, Serialize}; -#[derive(Debug,Serialize, Deserialize,Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct EpicGamesLauncherSettings { pub enabled: bool, pub location: Option, @@ -8,5 +8,3 @@ pub struct EpicGamesLauncherSettings { #[cfg(target_os = "linux")] pub create_symlinks: bool, } - - diff --git a/src/gog/gog_config.rs b/src/gog/gog_config.rs index df542f5..e3eb6d4 100644 --- a/src/gog/gog_config.rs +++ b/src/gog/gog_config.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; pub(crate) struct GogConfig { #[serde(alias = "installationPaths")] pub installation_paths: Option>, - + #[serde(alias = "libraryPath")] pub library_path: Option, } diff --git a/src/gog/gog_game.rs b/src/gog/gog_game.rs index 5ad08a8..55c484f 100644 --- a/src/gog/gog_game.rs +++ b/src/gog/gog_game.rs @@ -22,15 +22,14 @@ pub(crate) struct PlayTask { #[serde(alias = "type")] pub task_type: String, #[serde(alias = "workingDir")] - pub working_dir: Option, - + pub working_dir: Option, } pub(crate) struct GogShortcut { pub name: String, pub game_folder: String, pub path: String, - pub working_dir:String, + pub working_dir: String, pub game_id: String, } diff --git a/src/gog/gog_platform.rs b/src/gog/gog_platform.rs index 5b08a8e..68c4e3a 100644 --- a/src/gog/gog_platform.rs +++ b/src/gog/gog_platform.rs @@ -144,7 +144,9 @@ impl Platform for GogPlatform { let shortcuts_res = self.get_shortcuts(); match shortcuts_res { Ok(_) => SettingsValidity::Valid, - Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)}, + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, } } } diff --git a/src/gog/gog_settings.rs b/src/gog/gog_settings.rs index 59d3f17..6c0cb61 100644 --- a/src/gog/gog_settings.rs +++ b/src/gog/gog_settings.rs @@ -7,5 +7,4 @@ pub struct GogSettings { pub wine_c_drive: Option, #[cfg(target_os = "linux")] pub create_symlinks: bool, - } diff --git a/src/itch/itch_platform.rs b/src/itch/itch_platform.rs index ec17962..ea4fb7e 100644 --- a/src/itch/itch_platform.rs +++ b/src/itch/itch_platform.rs @@ -64,9 +64,10 @@ impl Platform for ItchPlatform { let shortcuts_res = self.get_shortcuts(); match shortcuts_res { Ok(_) => SettingsValidity::Valid, - Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, } - } } @@ -94,7 +95,7 @@ fn dbpath_to_game(paths: &DbPaths<'_>) -> Option { #[cfg(target_os = "linux")] pub fn get_default_location() -> String { //If we don't have a home drive we have to just die - let home = std::env::var("HOME").expect("Expected a home variable to be defined"); + let home = std::env::var("HOME").expect("Expected a home variable to be defined"); format!("{}/.config/itch/", home) } @@ -102,7 +103,11 @@ pub fn get_default_location() -> String { pub fn get_default_location() -> String { let key = "APPDATA"; let appdata = std::env::var(key).expect("Expected a APPDATA variable to be defined"); - Path::new(&appdata).join("itch").to_str().unwrap().to_string() + Path::new(&appdata) + .join("itch") + .to_str() + .unwrap() + .to_string() //C:\Users\phili\AppData\Local\itch } diff --git a/src/itch/mod.rs b/src/itch/mod.rs index fbcfe8c..2c14c02 100644 --- a/src/itch/mod.rs +++ b/src/itch/mod.rs @@ -1,9 +1,9 @@ -mod settings; +mod butler_db_parser; mod itch_game; mod itch_platform; -mod butler_db_parser; mod receipt; +mod settings; -pub use settings::*; pub use itch_game::*; -pub use itch_platform::*; \ No newline at end of file +pub use itch_platform::*; +pub use settings::*; diff --git a/src/itch/receipt.rs b/src/itch/receipt.rs index f9d1c71..029ec9b 100644 --- a/src/itch/receipt.rs +++ b/src/itch/receipt.rs @@ -1,11 +1,11 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone)] -pub(crate) struct Receipt{ - pub game:Game, +pub(crate) struct Receipt { + pub game: Game, } #[derive(Serialize, Deserialize, Debug, Clone)] -pub(crate) struct Game{ - pub title:String +pub(crate) struct Game { + pub title: String, } diff --git a/src/itch/settings.rs b/src/itch/settings.rs index afd71d2..35526f2 100644 --- a/src/itch/settings.rs +++ b/src/itch/settings.rs @@ -1,4 +1,4 @@ -use serde::{Serialize,Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ItchSettings { @@ -6,4 +6,4 @@ pub struct ItchSettings { pub location: Option, #[cfg(target_os = "linux")] pub create_symlinks: bool, -} \ No newline at end of file +} diff --git a/src/legendary/legendary_platform.rs b/src/legendary/legendary_platform.rs index b449150..afd9115 100644 --- a/src/legendary/legendary_platform.rs +++ b/src/legendary/legendary_platform.rs @@ -42,7 +42,9 @@ impl Platform> for LegendaryPlatform { let shortcuts_res = self.get_shortcuts(); match shortcuts_res { Ok(_) => SettingsValidity::Valid, - Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, } } } diff --git a/src/legendary/mod.rs b/src/legendary/mod.rs index 765f64d..9641009 100644 --- a/src/legendary/mod.rs +++ b/src/legendary/mod.rs @@ -1,8 +1,7 @@ mod legendary_game; -mod settings; mod legendary_platform; - +mod settings; pub use legendary_game::*; +pub use legendary_platform::*; pub use settings::*; -pub use legendary_platform::*; \ No newline at end of file diff --git a/src/legendary/settings.rs b/src/legendary/settings.rs index 7b14eb8..aa76e4a 100644 --- a/src/legendary/settings.rs +++ b/src/legendary/settings.rs @@ -1,7 +1,7 @@ -use serde::{Serialize,Deserialize}; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize,Clone)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct LegendarySettings { pub enabled: bool, pub executable: Option, -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 5d1712f..6446ece 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,9 +5,10 @@ mod legendary; mod origin; mod platform; mod settings; -mod sync; mod steam; mod steamgriddb; +mod sync; +mod uplay; #[cfg(feature = "ui")] mod ui; @@ -26,4 +27,3 @@ async fn main() -> Result<(), Box> { sync::run_sync(&settings).await } } - diff --git a/src/origin/mod.rs b/src/origin/mod.rs index 012912e..9d472bf 100644 --- a/src/origin/mod.rs +++ b/src/origin/mod.rs @@ -1,6 +1,6 @@ -mod settings; -mod origin_platform; mod origin_game; +mod origin_platform; +mod settings; pub use origin_platform::*; -pub use settings::*; \ No newline at end of file +pub use settings::*; diff --git a/src/origin/origin_platform.rs b/src/origin/origin_platform.rs index a967189..7c14148 100644 --- a/src/origin/origin_platform.rs +++ b/src/origin/origin_platform.rs @@ -67,13 +67,13 @@ impl Platform for OriginPlatform { } fn settings_valid(&self) -> crate::platform::SettingsValidity { - let shortcuts_res = self.get_shortcuts(); + let shortcuts_res = self.get_shortcuts(); match shortcuts_res { Ok(_) => SettingsValidity::Valid, - Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, } - - } } diff --git a/src/platform.rs b/src/platform.rs index 2ffd949..247d5b7 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -16,8 +16,7 @@ where fn create_symlinks(&self) -> bool; } - -pub enum SettingsValidity{ +pub enum SettingsValidity { Valid, - Invalid{reason:String}, + Invalid { reason: String }, } diff --git a/src/settings.rs b/src/settings.rs index ca389fb..28a0162 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,7 +1,7 @@ use crate::{ egs::EpicGamesLauncherSettings, gog::GogSettings, itch::ItchSettings, legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings, - steamgriddb::SteamGridDbSettings, + steamgriddb::SteamGridDbSettings, uplay::UplaySettings, }; use config::{Config, ConfigError, Environment, File}; @@ -18,6 +18,7 @@ pub struct Settings { pub steam: SteamSettings, pub origin: OriginSettings, pub gog: GogSettings, + pub uplay: UplaySettings, } impl Settings { diff --git a/src/steam/mod.rs b/src/steam/mod.rs index b673d5f..e27ad7c 100644 --- a/src/steam/mod.rs +++ b/src/steam/mod.rs @@ -1,5 +1,5 @@ -mod utils; mod settings; +mod utils; +pub use settings::SteamSettings; pub use utils::*; -pub use settings::SteamSettings; \ No newline at end of file diff --git a/src/steam/settings.rs b/src/steam/settings.rs index 749eed7..01efeba 100644 --- a/src/steam/settings.rs +++ b/src/steam/settings.rs @@ -1,6 +1,6 @@ -use serde::{Serialize,Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct SteamSettings{ +pub struct SteamSettings { pub location: Option, -} \ No newline at end of file +} diff --git a/src/steamgriddb/cached_search.rs b/src/steamgriddb/cached_search.rs index 61afef8..f148580 100644 --- a/src/steamgriddb/cached_search.rs +++ b/src/steamgriddb/cached_search.rs @@ -1,5 +1,5 @@ -use std::{ fs::File, io::Write, path::Path}; use dashmap::DashMap; +use std::{fs::File, io::Write, path::Path}; type SearchMap = DashMap; diff --git a/src/steamgriddb/downloader.rs b/src/steamgriddb/downloader.rs index 373fb59..a200911 100644 --- a/src/steamgriddb/downloader.rs +++ b/src/steamgriddb/downloader.rs @@ -4,8 +4,8 @@ use std::path::PathBuf; use std::{collections::HashMap, path::Path}; use futures::{stream, StreamExt}; -use steamgriddb_api::query_parameters::GridDimentions; // 0.3.1 use std::error::Error; +use steamgriddb_api::query_parameters::GridDimentions; // 0.3.1 use steam_shortcuts_util::shortcut::ShortcutOwned; use steamgriddb_api::Client; @@ -18,7 +18,11 @@ use super::CachedSearch; const CONCURRENT_REQUESTS: usize = 10; -pub async fn download_images_for_users<'b>(settings: &Settings, users: &[SteamUsersInfo], download_animated:bool) { +pub async fn download_images_for_users<'b>( + settings: &Settings, + users: &[SteamUsersInfo], + download_animated: bool, +) { let auth_key = &settings.steamgrid_db.auth_key; if let Some(auth_key) = auth_key { println!("Checking for game images"); @@ -76,7 +80,7 @@ async fn search_fo_to_download( shortcuts: &[ShortcutOwned], search: &CachedSearch<'_>, client: &Client, - download_animated:bool, + download_animated: bool, ) -> Result, Box> { let shortcuts_to_search_for = shortcuts.iter().filter(|s| { let images = vec![ @@ -110,7 +114,12 @@ async fn search_fo_to_download( for (app_id, search) in search_results_a.into_iter().flatten() { search_results.insert(app_id, search); } - let types = vec![ImageType::Logo, ImageType::Hero, ImageType::Grid, ImageType::BigPicture]; + let types = vec![ + ImageType::Logo, + ImageType::Hero, + ImageType::Grid, + ImageType::BigPicture, + ]; let mut to_download = vec![]; for image_type in types { let mut images_needed = shortcuts @@ -122,41 +131,39 @@ async fn search_fo_to_download( .filter_map(|s| search_results.get(&s.app_id)) .copied() .collect(); - use steamgriddb_api::query_parameters::QueryType::*; use steamgriddb_api::query_parameters::AnimtionType; + use steamgriddb_api::query_parameters::QueryType::*; let anymation_type = if download_animated { Some(&[AnimtionType::Animated][..]) - }else{ + } else { None }; let big_picture_dims = [GridDimentions::D920x430, GridDimentions::D460x215]; use steamgriddb_api::query_parameters::GridQueryParameters; - let big_picture_parameters = GridQueryParameters{ + let big_picture_parameters = GridQueryParameters { dimentions: Some(&big_picture_dims), types: anymation_type, ..Default::default() - }; + }; use steamgriddb_api::query_parameters::HeroQueryParameters; - let hero_parameters = HeroQueryParameters{ + let hero_parameters = HeroQueryParameters { types: anymation_type, ..Default::default() }; - let grid_parameters = GridQueryParameters{ + let grid_parameters = GridQueryParameters { types: anymation_type, ..Default::default() - }; - + }; use steamgriddb_api::query_parameters::LogoQueryParameters; - let logo_parameters = LogoQueryParameters{ + let logo_parameters = LogoQueryParameters { types: anymation_type, ..Default::default() }; - let query_type = match image_type { ImageType::Hero => Hero(Some(hero_parameters)), ImageType::BigPicture => Grid(Some(big_picture_parameters)), diff --git a/src/steamgriddb/image_type.rs b/src/steamgriddb/image_type.rs index 2256a58..a5e790a 100644 --- a/src/steamgriddb/image_type.rs +++ b/src/steamgriddb/image_type.rs @@ -1,10 +1,9 @@ - -#[derive(Debug,Clone,Copy)] +#[derive(Debug, Clone, Copy)] pub enum ImageType { Hero, Grid, Logo, - BigPicture + BigPicture, } impl ImageType { diff --git a/src/steamgriddb/mod.rs b/src/steamgriddb/mod.rs index 87acb5d..1ca32de 100644 --- a/src/steamgriddb/mod.rs +++ b/src/steamgriddb/mod.rs @@ -1,9 +1,9 @@ -mod settings; -mod image_type; mod cached_search; mod downloader; +mod image_type; +mod settings; +pub use cached_search::CachedSearch; +pub use downloader::*; pub use image_type::ImageType; pub use settings::SteamGridDbSettings; -pub use cached_search::CachedSearch; -pub use downloader::*; \ No newline at end of file diff --git a/src/steamgriddb/settings.rs b/src/steamgriddb/settings.rs index 7c775a6..ebc47df 100644 --- a/src/steamgriddb/settings.rs +++ b/src/steamgriddb/settings.rs @@ -1,8 +1,8 @@ -use serde::{Serialize,Deserialize}; +use serde::{Deserialize, Serialize}; -#[derive(Debug,Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct SteamGridDbSettings { pub enabled: bool, pub auth_key: Option, - pub prefer_animated:bool, + pub prefer_animated: bool, } diff --git a/src/sync/synchronization.rs b/src/sync/synchronization.rs index 57484e2..6345fb6 100644 --- a/src/sync/synchronization.rs +++ b/src/sync/synchronization.rs @@ -5,15 +5,16 @@ use crate::{ legendary::LegendaryPlatform, platform::Platform, settings::Settings, - steam::{get_shortcuts_for_user, get_shortcuts_paths, SteamUsersInfo, ShortcutInfo}, + steam::{get_shortcuts_for_user, get_shortcuts_paths, ShortcutInfo, SteamUsersInfo}, steamgriddb::download_images_for_users, + uplay::Uplay, }; use std::error::Error; use crate::{gog::GogPlatform, itch::ItchPlatform, origin::OriginPlatform}; use std::{fs::File, io::Write, path::Path}; -const BOILR_TAG : &str ="boilr"; +const BOILR_TAG: &str = "boilr"; pub async fn run_sync(settings: &Settings) -> Result<(), Box> { let mut userinfo_shortcuts = get_shortcuts_paths(&settings.steam)?; @@ -41,17 +42,19 @@ pub async fn run_sync(settings: &Settings) -> Result<(), Box> { if settings.steamgrid_db.enabled { if settings.steamgrid_db.prefer_animated { println!("downloading animated images"); - download_images_for_users(settings, &userinfo_shortcuts,true).await; + download_images_for_users(settings, &userinfo_shortcuts, true).await; } - download_images_for_users(settings, &userinfo_shortcuts,false).await; + download_images_for_users(settings, &userinfo_shortcuts, false).await; } Ok(()) } -fn remove_old_shortcuts(shortcut_info: &mut ShortcutInfo){ +fn remove_old_shortcuts(shortcut_info: &mut ShortcutInfo) { let boilr_tag = BOILR_TAG.to_string(); - shortcut_info.shortcuts.retain(|shortcut| !shortcut.tags.contains(&boilr_tag)); + shortcut_info + .shortcuts + .retain(|shortcut| !shortcut.tags.contains(&boilr_tag)); } fn fix_shortcut_icons(user: &SteamUsersInfo, shortcuts: &mut Vec) { @@ -77,8 +80,6 @@ fn fix_shortcut_icons(user: &SteamUsersInfo, shortcuts: &mut Vec) } } - - fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec) { update_platform_shortcuts( &EpicPlatform::new(settings.epic_games.clone()), @@ -104,6 +105,12 @@ fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec for ShortcutOwned { + fn from(game: Game) -> Self { + let launch = format!("uplay://launch/{}", game.id); + Shortcut::new(0, &game.name, &launch, "", &game.icon, "", "").to_owned() + } +} diff --git a/src/uplay/mod.rs b/src/uplay/mod.rs new file mode 100644 index 0000000..6188adb --- /dev/null +++ b/src/uplay/mod.rs @@ -0,0 +1,6 @@ +mod game; +mod platform; +mod settings; + +pub use platform::Uplay; +pub use settings::UplaySettings; diff --git a/src/uplay/platform.rs b/src/uplay/platform.rs new file mode 100644 index 0000000..7988202 --- /dev/null +++ b/src/uplay/platform.rs @@ -0,0 +1,79 @@ +use crate::platform::Platform; +use std::error::Error; + +use super::{game::Game, settings::UplaySettings}; + +pub struct Uplay { + pub settings: UplaySettings, +} + +impl Platform> for Uplay { + fn enabled(&self) -> bool { + #[cfg(target_os = "linux")] + { + false + } + #[cfg(target_os = "windows")] + { + self.settings.enabled + } + } + + fn name(&self) -> &str { + "Uplay" + } + + fn settings_valid(&self) -> crate::platform::SettingsValidity { + crate::platform::SettingsValidity::Valid + } + + fn get_shortcuts(&self) -> Result, Box> { + #[cfg(target_os = "linux")] + { + Ok(vec![]) + } + #[cfg(target_os = "windows")] + { + get_games_from_winreg() + } + } +} + +#[cfg(target_os = "windows")] +fn get_games_from_winreg() -> Result, Box> { + use std::path::Path; + + use winreg::enums::*; + use winreg::RegKey; + + let hklm = RegKey::predef(HKEY_LOCAL_MACHINE); + let mut games = vec![]; + let mut installed_ids = vec![]; + if let Ok(installs) = hklm.open_subkey("SOFTWARE\\WOW6432Node\\Ubisoft\\Launcher\\Installs") { + for i in installs.enum_keys().filter_map(|i| i.ok()) { + if let Ok(install) = installs.open_subkey(&i) { + let install_dir: Result = install.get_value("InstallDir"); + if let Ok(folder) = install_dir { + let path = Path::new(&folder); + if path.exists() { + installed_ids.push(i); + } + } + } + } + } + + for id in installed_ids { + let path = format!("SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Uplay Install {}",id); + let subkey = hklm.open_subkey(path); + if let Ok(subkey) = subkey { + let name: Result = subkey.get_value("DisplayName"); + if let Ok(name) = name { + let icon: String = subkey.get_value("DisplayName").unwrap_or_default(); + games.push(Game { name, icon, id }) + } + } + } + + Ok(games) +} diff --git a/src/uplay/settings.rs b/src/uplay/settings.rs new file mode 100644 index 0000000..4c98fb5 --- /dev/null +++ b/src/uplay/settings.rs @@ -0,0 +1,6 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct UplaySettings { + pub enabled: bool, +}