mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Initial Origin Support
This commit is contained in:
@@ -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 },
|
||||
}
|
||||
Reference in New Issue
Block a user