diff --git a/src/defaultconfig.toml b/src/defaultconfig.toml index 9d512e0..74d4c5e 100644 --- a/src/defaultconfig.toml +++ b/src/defaultconfig.toml @@ -26,3 +26,6 @@ create_symlinks = true [steamgrid_db] enabled = true prefer_animated = false + +[lutris] +enabled = true diff --git a/src/lutris/game_list_parser.rs b/src/lutris/game_list_parser.rs new file mode 100644 index 0000000..d063abb --- /dev/null +++ b/src/lutris/game_list_parser.rs @@ -0,0 +1,78 @@ +use super::lutris_game::LutrisGame; + +pub fn parse_lutris_games<'a>(input: &'a str) -> Vec { + input + .split("\n") + .into_iter() + .filter(|s| !s.is_empty()) + .filter_map(parse_line) + .collect() +} + +fn parse_line<'a>(input: &'a str) -> Option { + let mut sections = input.split("|"); + if sections.clone().count() < 4 { + return None; + } + let index = sections.next().unwrap().trim(); + let name = sections.next().unwrap().trim(); + let id = sections.next().unwrap().trim(); + let platform = sections.next().unwrap().trim(); + + Some(LutrisGame { + id:id.to_string(), + index:index.to_string(), + name:name.to_string(), + platform:platform.to_string(), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_parse_output() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(19, games.len()); + } + + #[test] + fn reads_index() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[0].index, "7"); + } + + #[test] + fn reads_name() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[1].name, "Cave Story+"); + } + + #[test] + fn reads_id() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[3].id, "dicey-dungeons"); + } + + #[test] + fn reads_platform() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[18].platform, "steam"); + } +} diff --git a/src/lutris/lutris_game.rs b/src/lutris/lutris_game.rs new file mode 100644 index 0000000..89ab7ee --- /dev/null +++ b/src/lutris/lutris_game.rs @@ -0,0 +1,25 @@ +use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut}; + +#[derive(Clone)] +pub struct LutrisGame { + pub index: String, + pub name: String, + pub id: String, + pub platform: String, +} + +impl From for ShortcutOwned { + fn from(game: LutrisGame) -> Self { + let options = format!("lutris:rungame/{}", game.id); + Shortcut::new( + 0, + game.name.as_str(), + "lutris", + "", + "", + "", + &options.as_str(), + ) + .to_owned() + } +} diff --git a/src/lutris/lutris_platform.rs b/src/lutris/lutris_platform.rs new file mode 100644 index 0000000..4d94db2 --- /dev/null +++ b/src/lutris/lutris_platform.rs @@ -0,0 +1,51 @@ +use super::game_list_parser::parse_lutris_games; +use super::lutris_game::LutrisGame; +use super::settings::LutrisSettings; +use crate::platform::{Platform, SettingsValidity}; +use std::error::Error; +use std::process::Command; + +pub struct LutrisPlatform { + pub settings: LutrisSettings, +} + + +impl Platform> for LutrisPlatform { + fn enabled(&self) -> bool { + self.settings.enabled + } + + fn name(&self) -> &str { + "Lutris" + } + + fn get_shortcuts(&self) -> Result, Box> { + let default_lutris_exe = "lutris".to_string(); + let lutris_executable = self.settings.executable.as_ref().unwrap_or(&default_lutris_exe); + let lutris_command = Command::new(lutris_executable).arg("-lo").output()?; + let output = String::from_utf8_lossy(&lutris_command.stdout).to_string(); + let games = parse_lutris_games(output.as_str()); + let mut res = vec![]; + for game in games { + if game.platform != "steam" { + res.push(game); + } + } + Ok(res) + } + + #[cfg(target_family = "unix")] + fn create_symlinks(&self) -> bool { + false + } + + fn settings_valid(&self) -> crate::platform::SettingsValidity { + let shortcuts_res = self.get_shortcuts(); + match shortcuts_res { + Ok(_) => SettingsValidity::Valid, + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, + } + } +} diff --git a/src/lutris/mod.rs b/src/lutris/mod.rs new file mode 100644 index 0000000..eacdc4f --- /dev/null +++ b/src/lutris/mod.rs @@ -0,0 +1,4 @@ +pub mod game_list_parser; +pub mod lutris_game; +pub mod lutris_platform; +pub mod settings; diff --git a/src/lutris/settings.rs b/src/lutris/settings.rs new file mode 100644 index 0000000..810a6f6 --- /dev/null +++ b/src/lutris/settings.rs @@ -0,0 +1,7 @@ +use serde::{Serialize,Deserialize}; + +#[derive(Debug, Deserialize, Serialize,Clone)] +pub struct LutrisSettings { + pub enabled: bool, + pub executable: Option, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6446ece..01aa197 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod egs; mod gog; mod itch; +mod lutris; mod legendary; mod origin; mod platform; diff --git a/src/settings.rs b/src/settings.rs index 28a0162..f84863d 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,7 +1,13 @@ use crate::{ - egs::EpicGamesLauncherSettings, gog::GogSettings, itch::ItchSettings, - legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings, - steamgriddb::SteamGridDbSettings, uplay::UplaySettings, + egs::EpicGamesLauncherSettings, + gog::GogSettings, + itch::ItchSettings, + legendary::LegendarySettings, + origin::OriginSettings, + steam::SteamSettings, + steamgriddb::SteamGridDbSettings, + uplay::UplaySettings, + lutris::settings::LutrisSettings, }; use config::{Config, ConfigError, Environment, File}; @@ -19,6 +25,7 @@ pub struct Settings { pub origin: OriginSettings, pub gog: GogSettings, pub uplay: UplaySettings, + pub lutris: LutrisSettings, } impl Settings { diff --git a/src/sync/synchronization.rs b/src/sync/synchronization.rs index 6345fb6..6da64b3 100644 --- a/src/sync/synchronization.rs +++ b/src/sync/synchronization.rs @@ -3,6 +3,7 @@ use steam_shortcuts_util::{shortcut::ShortcutOwned, shortcuts_to_bytes}; use crate::{ egs::EpicPlatform, legendary::LegendaryPlatform, + lutris::lutris_platform::LutrisPlatform, platform::Platform, settings::Settings, steam::{get_shortcuts_for_user, get_shortcuts_paths, ShortcutInfo, SteamUsersInfo}, @@ -111,6 +112,13 @@ fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec