Add uplay syncrhonization

This commit is contained in:
Philip
2022-01-02 10:37:12 +01:00
parent f60a591180
commit dd21e56fd6
36 changed files with 225 additions and 97 deletions
+3
View File
@@ -11,6 +11,9 @@ create_symlinks = true
enabled = false enabled = false
create_symlinks = true create_symlinks = true
[uplay]
enabled = false
[legendary] [legendary]
enabled = false enabled = false
+3 -2
View File
@@ -37,8 +37,9 @@ impl Platform<ManifestItem, EpicGamesManifestsError> for EpicPlatform {
let shortcuts_res = self.get_shortcuts(); let shortcuts_res = self.get_shortcuts();
match shortcuts_res { match shortcuts_res {
Ok(_) => SettingsValidity::Valid, Ok(_) => SettingsValidity::Valid,
Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} Err(err) => SettingsValidity::Invalid {
reason: format!("{}", err),
},
} }
} }
} }
+1 -1
View File
@@ -84,7 +84,7 @@ pub fn get_default_location() -> Option<PathBuf> {
{ {
let path = match location_from_registry() { let path = match location_from_registry() {
Some(path) => path, Some(path) => path,
None => guess_default_location() None => guess_default_location(),
}; };
if path.exists() { if path.exists() {
Some(path) Some(path)
+5 -5
View File
@@ -1,10 +1,10 @@
mod epic_platform;
mod get_manifests; mod get_manifests;
mod manifest_item; mod manifest_item;
mod settings; mod settings;
mod epic_platform;
pub(crate) use manifest_item::*;
use get_manifests::get_egs_manifests;
pub use get_manifests::get_default_location;
pub use settings::EpicGamesLauncherSettings;
pub use epic_platform::*; 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;
+1 -3
View File
@@ -1,4 +1,4 @@
use serde::{Serialize,Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct EpicGamesLauncherSettings { pub struct EpicGamesLauncherSettings {
@@ -8,5 +8,3 @@ pub struct EpicGamesLauncherSettings {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub create_symlinks: bool, pub create_symlinks: bool,
} }
-1
View File
@@ -23,7 +23,6 @@ pub(crate) struct PlayTask {
pub task_type: String, pub task_type: String,
#[serde(alias = "workingDir")] #[serde(alias = "workingDir")]
pub working_dir: Option<String>, pub working_dir: Option<String>,
} }
pub(crate) struct GogShortcut { pub(crate) struct GogShortcut {
+3 -1
View File
@@ -144,7 +144,9 @@ impl Platform<GogShortcut, GogErrors> for GogPlatform {
let shortcuts_res = self.get_shortcuts(); let shortcuts_res = self.get_shortcuts();
match shortcuts_res { match shortcuts_res {
Ok(_) => SettingsValidity::Valid, Ok(_) => SettingsValidity::Valid,
Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)}, Err(err) => SettingsValidity::Invalid {
reason: format!("{}", err),
},
} }
} }
} }
-1
View File
@@ -7,5 +7,4 @@ pub struct GogSettings {
pub wine_c_drive: Option<String>, pub wine_c_drive: Option<String>,
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub create_symlinks: bool, pub create_symlinks: bool,
} }
+8 -3
View File
@@ -64,9 +64,10 @@ impl Platform<ItchGame, ItchErrors> for ItchPlatform {
let shortcuts_res = self.get_shortcuts(); let shortcuts_res = self.get_shortcuts();
match shortcuts_res { match shortcuts_res {
Ok(_) => SettingsValidity::Valid, Ok(_) => SettingsValidity::Valid,
Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} Err(err) => SettingsValidity::Invalid {
reason: format!("{}", err),
},
} }
} }
} }
@@ -102,7 +103,11 @@ pub fn get_default_location() -> String {
pub fn get_default_location() -> String { pub fn get_default_location() -> String {
let key = "APPDATA"; let key = "APPDATA";
let appdata = std::env::var(key).expect("Expected a APPDATA variable to be defined"); 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 //C:\Users\phili\AppData\Local\itch
} }
+3 -3
View File
@@ -1,9 +1,9 @@
mod settings; mod butler_db_parser;
mod itch_game; mod itch_game;
mod itch_platform; mod itch_platform;
mod butler_db_parser;
mod receipt; mod receipt;
mod settings;
pub use settings::*;
pub use itch_game::*; pub use itch_game::*;
pub use itch_platform::*; pub use itch_platform::*;
pub use settings::*;
+1 -1
View File
@@ -7,5 +7,5 @@ pub(crate) struct Receipt{
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub(crate) struct Game { pub(crate) struct Game {
pub title:String pub title: String,
} }
+1 -1
View File
@@ -1,4 +1,4 @@
use serde::{Serialize,Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ItchSettings { pub struct ItchSettings {
+3 -1
View File
@@ -42,7 +42,9 @@ impl Platform<LegendaryGame, Box<dyn Error>> for LegendaryPlatform {
let shortcuts_res = self.get_shortcuts(); let shortcuts_res = self.get_shortcuts();
match shortcuts_res { match shortcuts_res {
Ok(_) => SettingsValidity::Valid, Ok(_) => SettingsValidity::Valid,
Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} Err(err) => SettingsValidity::Invalid {
reason: format!("{}", err),
},
} }
} }
} }
+2 -3
View File
@@ -1,8 +1,7 @@
mod legendary_game; mod legendary_game;
mod settings;
mod legendary_platform; mod legendary_platform;
mod settings;
pub use legendary_game::*; pub use legendary_game::*;
pub use settings::*;
pub use legendary_platform::*; pub use legendary_platform::*;
pub use settings::*;
+1 -1
View File
@@ -1,4 +1,4 @@
use serde::{Serialize,Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone)] #[derive(Debug, Deserialize, Serialize, Clone)]
pub struct LegendarySettings { pub struct LegendarySettings {
+2 -2
View File
@@ -5,9 +5,10 @@ mod legendary;
mod origin; mod origin;
mod platform; mod platform;
mod settings; mod settings;
mod sync;
mod steam; mod steam;
mod steamgriddb; mod steamgriddb;
mod sync;
mod uplay;
#[cfg(feature = "ui")] #[cfg(feature = "ui")]
mod ui; mod ui;
@@ -26,4 +27,3 @@ async fn main() -> Result<(), Box<dyn Error>> {
sync::run_sync(&settings).await sync::run_sync(&settings).await
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
mod settings;
mod origin_platform;
mod origin_game; mod origin_game;
mod origin_platform;
mod settings;
pub use origin_platform::*; pub use origin_platform::*;
pub use settings::*; pub use settings::*;
+3 -3
View File
@@ -70,10 +70,10 @@ impl Platform<OriginGame, OriginErrors> for OriginPlatform {
let shortcuts_res = self.get_shortcuts(); let shortcuts_res = self.get_shortcuts();
match shortcuts_res { match shortcuts_res {
Ok(_) => SettingsValidity::Valid, Ok(_) => SettingsValidity::Valid,
Err(err) => SettingsValidity::Invalid{reason:format!("{}",err)} Err(err) => SettingsValidity::Invalid {
reason: format!("{}", err),
},
} }
} }
} }
-1
View File
@@ -16,7 +16,6 @@ where
fn create_symlinks(&self) -> bool; fn create_symlinks(&self) -> bool;
} }
pub enum SettingsValidity { pub enum SettingsValidity {
Valid, Valid,
Invalid { reason: String }, Invalid { reason: String },
+2 -1
View File
@@ -1,7 +1,7 @@
use crate::{ use crate::{
egs::EpicGamesLauncherSettings, gog::GogSettings, itch::ItchSettings, egs::EpicGamesLauncherSettings, gog::GogSettings, itch::ItchSettings,
legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings, legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings,
steamgriddb::SteamGridDbSettings, steamgriddb::SteamGridDbSettings, uplay::UplaySettings,
}; };
use config::{Config, ConfigError, Environment, File}; use config::{Config, ConfigError, Environment, File};
@@ -18,6 +18,7 @@ pub struct Settings {
pub steam: SteamSettings, pub steam: SteamSettings,
pub origin: OriginSettings, pub origin: OriginSettings,
pub gog: GogSettings, pub gog: GogSettings,
pub uplay: UplaySettings,
} }
impl Settings { impl Settings {
+2 -2
View File
@@ -1,5 +1,5 @@
mod utils;
mod settings; mod settings;
mod utils;
pub use utils::*;
pub use settings::SteamSettings; pub use settings::SteamSettings;
pub use utils::*;
+1 -1
View File
@@ -1,4 +1,4 @@
use serde::{Serialize,Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SteamSettings { pub struct SteamSettings {
+1 -1
View File
@@ -1,5 +1,5 @@
use std::{ fs::File, io::Write, path::Path};
use dashmap::DashMap; use dashmap::DashMap;
use std::{fs::File, io::Write, path::Path};
type SearchMap = DashMap<u32, (String, usize)>; type SearchMap = DashMap<u32, (String, usize)>;
+13 -6
View File
@@ -4,8 +4,8 @@ use std::path::PathBuf;
use std::{collections::HashMap, path::Path}; use std::{collections::HashMap, path::Path};
use futures::{stream, StreamExt}; use futures::{stream, StreamExt};
use steamgriddb_api::query_parameters::GridDimentions; // 0.3.1
use std::error::Error; use std::error::Error;
use steamgriddb_api::query_parameters::GridDimentions; // 0.3.1
use steam_shortcuts_util::shortcut::ShortcutOwned; use steam_shortcuts_util::shortcut::ShortcutOwned;
use steamgriddb_api::Client; use steamgriddb_api::Client;
@@ -18,7 +18,11 @@ use super::CachedSearch;
const CONCURRENT_REQUESTS: usize = 10; 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; let auth_key = &settings.steamgrid_db.auth_key;
if let Some(auth_key) = auth_key { if let Some(auth_key) = auth_key {
println!("Checking for game images"); println!("Checking for game images");
@@ -110,7 +114,12 @@ async fn search_fo_to_download(
for (app_id, search) in search_results_a.into_iter().flatten() { for (app_id, search) in search_results_a.into_iter().flatten() {
search_results.insert(app_id, search); 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![]; let mut to_download = vec![];
for image_type in types { for image_type in types {
let mut images_needed = shortcuts let mut images_needed = shortcuts
@@ -122,8 +131,8 @@ async fn search_fo_to_download(
.filter_map(|s| search_results.get(&s.app_id)) .filter_map(|s| search_results.get(&s.app_id))
.copied() .copied()
.collect(); .collect();
use steamgriddb_api::query_parameters::QueryType::*;
use steamgriddb_api::query_parameters::AnimtionType; use steamgriddb_api::query_parameters::AnimtionType;
use steamgriddb_api::query_parameters::QueryType::*;
let anymation_type = if download_animated { let anymation_type = if download_animated {
Some(&[AnimtionType::Animated][..]) Some(&[AnimtionType::Animated][..])
} else { } else {
@@ -149,14 +158,12 @@ async fn search_fo_to_download(
..Default::default() ..Default::default()
}; };
use steamgriddb_api::query_parameters::LogoQueryParameters; use steamgriddb_api::query_parameters::LogoQueryParameters;
let logo_parameters = LogoQueryParameters { let logo_parameters = LogoQueryParameters {
types: anymation_type, types: anymation_type,
..Default::default() ..Default::default()
}; };
let query_type = match image_type { let query_type = match image_type {
ImageType::Hero => Hero(Some(hero_parameters)), ImageType::Hero => Hero(Some(hero_parameters)),
ImageType::BigPicture => Grid(Some(big_picture_parameters)), ImageType::BigPicture => Grid(Some(big_picture_parameters)),
+1 -2
View File
@@ -1,10 +1,9 @@
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum ImageType { pub enum ImageType {
Hero, Hero,
Grid, Grid,
Logo, Logo,
BigPicture BigPicture,
} }
impl ImageType { impl ImageType {
+4 -4
View File
@@ -1,9 +1,9 @@
mod settings;
mod image_type;
mod cached_search; mod cached_search;
mod downloader; mod downloader;
mod image_type;
mod settings;
pub use image_type::ImageType;
pub use settings::SteamGridDbSettings;
pub use cached_search::CachedSearch; pub use cached_search::CachedSearch;
pub use downloader::*; pub use downloader::*;
pub use image_type::ImageType;
pub use settings::SteamGridDbSettings;
+1 -1
View File
@@ -1,4 +1,4 @@
use serde::{Serialize,Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct SteamGridDbSettings { pub struct SteamGridDbSettings {
+16 -5
View File
@@ -5,8 +5,9 @@ use crate::{
legendary::LegendaryPlatform, legendary::LegendaryPlatform,
platform::Platform, platform::Platform,
settings::Settings, 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, steamgriddb::download_images_for_users,
uplay::Uplay,
}; };
use std::error::Error; use std::error::Error;
@@ -51,7 +52,9 @@ pub async fn run_sync(settings: &Settings) -> Result<(), Box<dyn Error>> {
fn remove_old_shortcuts(shortcut_info: &mut ShortcutInfo) { fn remove_old_shortcuts(shortcut_info: &mut ShortcutInfo) {
let boilr_tag = BOILR_TAG.to_string(); 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<ShortcutOwned>) { fn fix_shortcut_icons(user: &SteamUsersInfo, shortcuts: &mut Vec<ShortcutOwned>) {
@@ -77,8 +80,6 @@ fn fix_shortcut_icons(user: &SteamUsersInfo, shortcuts: &mut Vec<ShortcutOwned>)
} }
} }
fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec<ShortcutOwned>) { fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec<ShortcutOwned>) {
update_platform_shortcuts( update_platform_shortcuts(
&EpicPlatform::new(settings.epic_games.clone()), &EpicPlatform::new(settings.epic_games.clone()),
@@ -104,6 +105,12 @@ fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec<ShortcutOw
}, },
new_user_shortcuts, new_user_shortcuts,
); );
update_platform_shortcuts(
&Uplay {
settings: settings.uplay.clone(),
},
new_user_shortcuts,
);
} }
fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) { fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) {
@@ -141,7 +148,11 @@ where
{ {
if platform.enabled() { if platform.enabled() {
if let crate::platform::SettingsValidity::Invalid { reason } = platform.settings_valid() { if let crate::platform::SettingsValidity::Invalid { reason } = platform.settings_valid() {
eprintln!("Setting for platform {} are invalid, reason: {}",platform.name(),reason); eprintln!(
"Setting for platform {} are invalid, reason: {}",
platform.name(),
reason
);
return; return;
} }
+2 -3
View File
@@ -1,6 +1,5 @@
mod ui;
mod mainview; mod mainview;
mod ui;
pub use ui::run_ui;
pub(crate) use mainview::UserInterface; pub(crate) use mainview::UserInterface;
pub use ui::run_ui;
-1
View File
@@ -76,7 +76,6 @@ fn update_settings_with_ui_values(settings: &mut Settings, ui: &UserInterface) {
settings.gog.wine_c_drive = empty_or_whitespace(ui.gog_winedrive_input.value()); settings.gog.wine_c_drive = empty_or_whitespace(ui.gog_winedrive_input.value());
} }
fn save_settings_to_file(settings: &Settings) { fn save_settings_to_file(settings: &Settings) {
let toml = toml::to_string(&settings).unwrap(); let toml = toml::to_string(&settings).unwrap();
std::fs::write("config.toml", toml).unwrap(); std::fs::write("config.toml", toml).unwrap();
+14
View File
@@ -0,0 +1,14 @@
use steam_shortcuts_util::shortcut::{Shortcut, ShortcutOwned};
pub(crate) struct Game {
pub(crate) name: String,
pub(crate) icon: String,
pub(crate) id: String,
}
impl From<Game> for ShortcutOwned {
fn from(game: Game) -> Self {
let launch = format!("uplay://launch/{}", game.id);
Shortcut::new(0, &game.name, &launch, "", &game.icon, "", "").to_owned()
}
}
+6
View File
@@ -0,0 +1,6 @@
mod game;
mod platform;
mod settings;
pub use platform::Uplay;
pub use settings::UplaySettings;
+79
View File
@@ -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<Game, Box<dyn Error>> 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<Vec<Game>, Box<dyn Error>> {
#[cfg(target_os = "linux")]
{
Ok(vec![])
}
#[cfg(target_os = "windows")]
{
get_games_from_winreg()
}
}
}
#[cfg(target_os = "windows")]
fn get_games_from_winreg() -> Result<Vec<Game>, Box<dyn Error>> {
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<String, _> = 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<String, _> = 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)
}
+6
View File
@@ -0,0 +1,6 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct UplaySettings {
pub enabled: bool,
}