Initial Origin Support

This commit is contained in:
Philip
2021-10-01 22:26:29 +02:00
parent 272e198e85
commit d7deae57ad
8 changed files with 175 additions and 9 deletions
+5
View File
@@ -1,8 +1,13 @@
debug= false debug= false
[origin]
enabled = false
[epic_games] [epic_games]
enabled = false
[legendary] [legendary]
enabled = false
[steam] [steam]
+1 -1
View File
@@ -3,7 +3,7 @@ mod manifest_item;
mod settings; mod settings;
mod epic_platform; mod epic_platform;
pub use manifest_item::*; pub(crate) use manifest_item::*;
use get_manifests::get_egs_manifests; use get_manifests::get_egs_manifests;
pub use settings::EpicGamesLauncherSettings; pub use settings::EpicGamesLauncherSettings;
pub use epic_platform::*; pub use epic_platform::*;
+9
View File
@@ -1,11 +1,13 @@
use crate::{ use crate::{
itch::ItchPlatform, itch::ItchPlatform,
origin::OriginPlatform,
steamgriddb::{download_images, CachedSearch}, steamgriddb::{download_images, CachedSearch},
}; };
use std::{fs::File, io::Write, path::Path}; use std::{fs::File, io::Write, path::Path};
mod egs; mod egs;
mod itch; mod itch;
mod legendary; mod legendary;
mod origin;
mod platform; mod platform;
mod settings; mod settings;
mod steam; mod steam;
@@ -93,6 +95,13 @@ async fn run_sync() -> Result<(), Box<dyn Error>> {
&mut new_user_shortcuts, &mut new_user_shortcuts,
); );
update_platform_shortcuts(
&OriginPlatform {
settings: settings.origin.clone(),
},
&mut new_user_shortcuts,
);
let shortcuts = new_user_shortcuts.iter().map(|f| f.borrow()).collect(); let shortcuts = new_user_shortcuts.iter().map(|f| f.borrow()).collect();
save_shortcuts(&shortcuts, Path::new(&shortcut_info.path)); save_shortcuts(&shortcuts, Path::new(&shortcut_info.path));
+6
View File
@@ -0,0 +1,6 @@
mod settings;
mod origin_platform;
mod origin_game;
pub use origin_platform::*;
pub use settings::*;
+18
View File
@@ -0,0 +1,18 @@
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
pub struct OriginGame {
pub id: String,
pub title: String,
}
impl From<OriginGame> for ShortcutOwned {
fn from(game: OriginGame) -> Self {
let launch = format!("origin2://game/launch?offerIds={}&autoDownload=1", game.id);
let shortcut = Shortcut::new(0, game.title.as_str(), launch.as_str(), "", "", "", "");
let mut owned_shortcut = shortcut.to_owned();
owned_shortcut.tags.push("Origin".to_owned());
owned_shortcut.tags.push("Ready TO Play".to_owned());
owned_shortcut.tags.push("Installed".to_owned());
owned_shortcut
}
}
+125
View File
@@ -0,0 +1,125 @@
use crate::platform::Platform;
use failure::*;
use nom::bytes::complete::take_until;
use std::{
fs::DirEntry,
path::{Path, PathBuf},
};
use super::{origin_game::OriginGame, OriginSettings};
pub struct OriginPlatform {
pub settings: OriginSettings,
}
impl Platform<OriginGame, OriginErrors> for OriginPlatform {
fn enabled(&self) -> bool {
self.settings.enabled
}
fn name(&self) -> &str {
"Origin"
}
fn get_shortcuts(&self) -> Result<Vec<OriginGame>, OriginErrors> {
let origin_folder = Path::new(
&self
.settings
.path
.clone()
.unwrap_or_else(|| get_default_location()),
)
.join("LocalContent");
if !origin_folder.exists() {
return Err(OriginErrors::PathNotFound {
path: origin_folder.to_str().unwrap().to_string(),
});
}
let game_folders =
origin_folder
.read_dir()
.map_err(|e| OriginErrors::CouldNotReadGameDir {
path: origin_folder,
error: format!("{:?}", e),
})?;
let games = game_folders
.filter_map(|folder| folder.ok())
.filter_map(|game_folder| {
let game_title = game_folder.file_name().to_string_lossy().to_string();
let mfst_content = get_folder_mfst_file_content(&game_folder.path());
let id = match mfst_content {
Some(c) => parse_id_from_file(c.as_str())
.ok()
.map(|(_, id_str)| String::from(id_str)),
None => None,
};
id.map(|id| OriginGame {
id: id.to_string(),
title: game_title,
})
});
Ok(games.collect())
}
}
fn get_folder_mfst_file_content(game_folder_path: &Path) -> Option<String> {
let game_folder_files = game_folder_path.read_dir();
if let Ok(game_folder_files) = game_folder_files {
let mfst_file = game_folder_files
.filter_map(|file| file.ok())
.filter(is_mfst_file)
.next()
.map(|file| std::fs::read_to_string(&file.path()));
return match mfst_file {
Some(mfst_file) => mfst_file.ok(),
None => None,
};
}
None
}
fn is_mfst_file(file: &DirEntry) -> bool {
file.path()
.extension()
.map(|ex| ex.to_str().unwrap_or("") == "mfst")
.unwrap_or(false)
}
fn parse_id_from_file(i: &str) -> nom::IResult<&str, &str> {
let (i, _) = take_until("&id=")(i)?;
let (i, _) = nom::bytes::complete::tag("&id=")(i)?;
take_until("&")(i)
}
#[cfg(target_os = "linux")]
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");
format!("{}/.origin/", home)
}
#[cfg(target_os = "windows")]
fn get_default_location() -> String {
let key = "PROGRAMDATA";
let program_data = std::env::var(key).expect("Expected a APPDATA variable to be defined");
Path::new(&program_data)
.join("Origin")
.to_str()
.unwrap()
.to_string()
}
#[derive(Debug, Fail)]
pub enum OriginErrors {
#[fail(
display = "Origin path: {} could not be found. Try to specify a different path for Origin.",
path
)]
PathNotFound { path: String },
#[fail(
display = "Could not read Origin directory: {:?}. Error: {}",
path, error
)]
CouldNotReadGameDir { path: PathBuf, error: String },
}
+8
View File
@@ -0,0 +1,8 @@
use serde::Deserialize;
#[derive(Debug, Deserialize,Clone)]
pub struct OriginSettings {
pub enabled: bool,
pub path: Option<String>,
}
+3 -8
View File
@@ -1,4 +1,4 @@
use crate::{egs::EpicGamesLauncherSettings, itch::ItchSettings, legendary::LegendarySettings, steam::SteamSettings, steamgriddb::SteamGridDbSettings}; use crate::{egs::EpicGamesLauncherSettings, itch::ItchSettings, legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings, steamgriddb::SteamGridDbSettings};
use config::{Config, ConfigError, Environment, File}; use config::{Config, ConfigError, Environment, File};
use serde::Deserialize; use serde::Deserialize;
@@ -11,11 +11,10 @@ pub struct Settings {
pub legendary: LegendarySettings, pub legendary: LegendarySettings,
pub itch: ItchSettings, pub itch: ItchSettings,
pub steamgrid_db: SteamGridDbSettings, pub steamgrid_db: SteamGridDbSettings,
pub steam: SteamSettings pub steam: SteamSettings,
pub origin: OriginSettings,
} }
//https://github.com/JosefNemec/Playnite/tree/master/source/Plugins/OriginLibrary
//https://github.com/JosefNemec/Playnite/blob/master/source/Plugins/OriginLibrary/Origin.cs#L109
impl Settings { impl Settings {
pub fn new() -> Result<Self, ConfigError> { pub fn new() -> Result<Self, ConfigError> {
let mut s = Config::new(); let mut s = Config::new();
@@ -33,10 +32,6 @@ impl Settings {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let enable_epic = true; let enable_epic = true;
s.set_default("legendary.enabled", enable_legendary)?;
s.set_default("epic_games.enabled", enable_epic)?;
// Start off by merging in the "default" configuration file // Start off by merging in the "default" configuration file
s.merge(File::with_name("config.toml").required(false))?; s.merge(File::with_name("config.toml").required(false))?;