From 0f5f3bad2ca0e5ddff1ac74a27c348d0cfca6be5 Mon Sep 17 00:00:00 2001 From: Philip Kristoffersen Date: Tue, 19 Apr 2022 21:24:17 +0200 Subject: [PATCH] Amazon Games for Windows (#91) --- Cargo.lock | 31 ++++++++++++++ Cargo.toml | 1 + Readme.md | 1 + src/amazon/amazon_game.rs | 25 ++++++++++++ src/amazon/amazon_platform.rs | 77 +++++++++++++++++++++++++++++++++++ src/amazon/amazon_settings.rs | 6 +++ src/amazon/mod.rs | 8 ++++ src/defaultconfig.toml | 3 ++ src/main.rs | 1 + src/settings.rs | 3 +- src/sync/synchronization.rs | 7 ++++ src/ui/uiapp.rs | 11 +++++ 12 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/amazon/amazon_game.rs create mode 100644 src/amazon/amazon_platform.rs create mode 100644 src/amazon/amazon_settings.rs create mode 100644 src/amazon/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 01ce228..35b0ce8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,6 +245,7 @@ dependencies = [ "rusty-leveldb", "serde 1.0.136", "serde_json", + "sqlite", "steam_shortcuts_util", "steamgriddb_api", "sysinfo", @@ -2695,6 +2696,36 @@ dependencies = [ "lock_api", ] +[[package]] +name = "sqlite" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1a534c07ec276fbbe0e55a1c00814d8563da3a2f4d9d9d4c802bd1278db6a" +dependencies = [ + "libc", + "sqlite3-sys", +] + +[[package]] +name = "sqlite3-src" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a260b07ce75a0644c6f5891f34f46db9869e731838e95293469ab17999abcfa3" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "sqlite3-sys" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d2f028faeb14352df7934b4771806f60d61ce61be1928ec92396d7492e2e54" +dependencies = [ + "libc", + "sqlite3-src", +] + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8666575..7f624a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ egui = { version = "0.17.0" } image = { version = "0.24.1", features = ["png"] } toml = { version = "^0.5.8" } sysinfo = "0.23.10" +sqlite = "0.26.0" [target.'cfg(windows)'.dependencies] winreg = "0.10.1" diff --git a/Readme.md b/Readme.md index d9a9b0a..48e359c 100644 --- a/Readme.md +++ b/Readme.md @@ -50,6 +50,7 @@ Optionally you can set BoilR up to automatically download artwork from [SteamGri - [x] [Legendary](https://github.com/derrod/legendary) - [x] [Rare](https://github.com/Dummerle/Rare/releases) - [x] [Heroic Launcher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) (Linux Only) +- [x] [Amazon Games](https://gaming.amazon.com) (Windows Only) - [ ] XBox/Microsoft Store integration diff --git a/src/amazon/amazon_game.rs b/src/amazon/amazon_game.rs new file mode 100644 index 0000000..11a59c0 --- /dev/null +++ b/src/amazon/amazon_game.rs @@ -0,0 +1,25 @@ +use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut}; + +#[derive(Debug, Clone)] +pub struct AmazonGame{ + pub title : String, + pub id : String +} + + + +impl From for ShortcutOwned { + fn from(game: AmazonGame) -> Self { + let launch = format!("amazon-games://play/{}", game.id); + Shortcut::new( + "0", + game.title.as_str(), + launch.as_str(), + "", + "", + "", + "", + ) + .to_owned() + } +} diff --git a/src/amazon/amazon_platform.rs b/src/amazon/amazon_platform.rs new file mode 100644 index 0000000..161905c --- /dev/null +++ b/src/amazon/amazon_platform.rs @@ -0,0 +1,77 @@ +use std::{error::Error, path::{PathBuf, Path}}; + +use sqlite::State; + +use crate::platform::Platform; + +use super::{AmazonSettings, AmazonGame}; + + +pub struct AmazonPlatform{ + pub settings:AmazonSettings +} + +impl Platform> for AmazonPlatform{ + #[cfg(windows)] + fn enabled(&self) -> bool { + self.settings.enabled + } + + #[cfg(target_family="unix")] + fn enabled(&self) -> bool { + false + } + + fn name(&self) -> &str { + "Amazon" + } + + fn get_shortcuts(&self) -> Result, Box> { + let sqllite_path = get_sqlite_path().expect("This should enver get called if settings are invalid"); + let mut result = vec![]; + let connection = sqlite::open(sqllite_path)?; + let mut statement = connection.prepare("SELECT Id, ProductTitle FROM DbSet WHERE Installed = 1")?; + while let State::Row = statement.next().unwrap() { + let id = statement.read::(0); + let title = statement.read::(1); + if let (Ok(id),Ok(title)) = (id,title){ + result.push(AmazonGame { title, id }); + } + } + Ok(result) + } + + fn settings_valid(&self) -> crate::platform::SettingsValidity { + let path = get_sqlite_path(); + if path.is_some(){ + crate::platform::SettingsValidity::Valid + }else{ + crate::platform::SettingsValidity::Invalid { reason: format!("Could not find Amazon Games installation")} + } + + } + + #[cfg(target_family ="unix")] + fn create_symlinks(&self) -> bool { + false + } + + fn needs_proton(&self, _input: &AmazonGame) -> bool { + false + } +} + + +fn get_sqlite_path() -> Option { + match std::env::var("LOCALAPPDATA") { + Ok(localdata) => { + let path = Path::new(&localdata).join("Amazon Games").join("Data").join("Games").join("Sql").join("GameInstallInfo.sqlite"); + if path.exists() { + Some(path) + }else{ + None + } + } + Err(_e) => None, + } +} \ No newline at end of file diff --git a/src/amazon/amazon_settings.rs b/src/amazon/amazon_settings.rs new file mode 100644 index 0000000..a7a7563 --- /dev/null +++ b/src/amazon/amazon_settings.rs @@ -0,0 +1,6 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct AmazonSettings{ + pub enabled:bool +} \ No newline at end of file diff --git a/src/amazon/mod.rs b/src/amazon/mod.rs new file mode 100644 index 0000000..8795361 --- /dev/null +++ b/src/amazon/mod.rs @@ -0,0 +1,8 @@ +pub mod amazon_platform; +pub use amazon_platform::*; + +pub mod amazon_game; +pub use amazon_game::*; + +pub mod amazon_settings; +pub use amazon_settings::*; \ No newline at end of file diff --git a/src/defaultconfig.toml b/src/defaultconfig.toml index ac698d8..8309d40 100644 --- a/src/defaultconfig.toml +++ b/src/defaultconfig.toml @@ -34,6 +34,9 @@ enabled = false [heroic] enabled = true +[amazon] +enabled = true + [steam] create_collections = false optimize_for_big_picture = false diff --git a/src/main.rs b/src/main.rs index 6fe5711..3a3cbf7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ mod steamgriddb; mod sync; mod uplay; mod ui; +mod amazon; use std::error::Error; fn main() -> Result<(), Box> { diff --git a/src/settings.rs b/src/settings.rs index 0e64dc1..19c61d8 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,7 +1,7 @@ use crate::{ egs::EpicGamesLauncherSettings, gog::GogSettings, itch::ItchSettings, legendary::LegendarySettings, lutris::settings::LutrisSettings, origin::OriginSettings, - steam::SteamSettings, steamgriddb::SteamGridDbSettings, uplay::UplaySettings, heroic::HeroicSettings, + steam::SteamSettings, steamgriddb::SteamGridDbSettings, uplay::UplaySettings, heroic::HeroicSettings, amazon::AmazonSettings, }; use config::{Config, ConfigError, Environment, File}; @@ -22,6 +22,7 @@ pub struct Settings { pub uplay: UplaySettings, pub lutris: LutrisSettings, pub heroic: HeroicSettings, + pub amazon: AmazonSettings, } impl Settings { diff --git a/src/sync/synchronization.rs b/src/sync/synchronization.rs index 35829dd..7a996d1 100644 --- a/src/sync/synchronization.rs +++ b/src/sync/synchronization.rs @@ -194,6 +194,13 @@ pub fn get_platform_shortcuts(settings: &Settings) -> Vec<(String, Vec