Files
BoilR/src/platforms/itch/itch_platform.rs
T
Philip KristoffersenandGitHub 0410ceffff Clippy fixes for windows specific code (#319)
* Clippy fixes for windows specific code

* Remove unwraps in windows code

* Fix compile error on unix
2023-01-08 14:02:40 +01:00

158 lines
4.9 KiB
Rust

use super::butler_db_parser::*;
use super::itch_game::ItchGame;
use super::receipt::Receipt;
use super::ItchSettings;
use crate::platforms::{
load_settings, to_shortcuts, FromSettingsString, GamesPlatform, ShortcutToImport,
};
use flate2::read::GzDecoder;
use is_executable::IsExecutable;
use std::collections::HashSet;
use std::io::prelude::*;
use std::path::Path;
#[derive(Clone)]
pub struct ItchPlatform {
pub settings: ItchSettings,
}
impl ItchPlatform {
fn get_itch_games(&self) -> eyre::Result<Vec<ItchGame>> {
let itch_location = self.settings.location.clone();
let itch_location = itch_location.unwrap_or_else(get_default_location);
let itch_db_location = Path::new(&itch_location).join("db").join("butler.db-wal");
if !itch_db_location.exists() {
return Err(eyre::format_err!(
"Path not found: {:?}",
itch_db_location.to_str()
));
}
let shortcut_bytes = std::fs::read(&itch_db_location)?;
let paths = match parse_butler_db(&shortcut_bytes) {
Ok((_, shortcuts)) => Ok(shortcuts),
Err(e) => Err(eyre::format_err!(
"Could not parse path: {:?} , error: {:?}",
itch_db_location.to_str(),
e
)),
}?;
//This is done to paths dedupe
let paths: HashSet<&DbPaths> = paths.iter().collect();
let res = paths.iter().filter_map(|e| dbpath_to_game(e)).collect();
Ok(res)
}
}
fn dbpath_to_game(paths: &DbPaths) -> Option<ItchGame> {
let recipt = Path::new(paths.base_path.as_str())
.join(".itch")
.join("receipt.json.gz");
if !&recipt.exists() {
return None;
}
paths
.paths
.iter()
.filter(|p| Path::new(&paths.base_path).join(p).is_executable())
.find_map(|executable| {
if let Ok(gz_bytes) = std::fs::read(&recipt) {
let mut d = GzDecoder::new(gz_bytes.as_slice());
let mut s = String::new();
if d.read_to_string(&mut s).is_ok() {
let receipt_op: Option<Receipt> = serde_json::from_str(&s).ok();
return receipt_op.map(|re| ItchGame {
install_path: paths.base_path.to_owned(),
executable: executable.to_owned(),
title: re.game.title,
});
}
}
None
})
}
#[cfg(target_family = "unix")]
pub 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!("{}/.config/itch/", home)
}
#[cfg(target_os = "windows")]
pub fn get_default_location() -> String {
let key = "APPDATA";
std::env::var(key)
.map(|appdata| {
Path::new(&appdata)
.join("itch")
.to_string_lossy()
.to_string()
})
.unwrap_or_default()
//C:\Users\phili\AppData\Local\itch
}
impl FromSettingsString for ItchPlatform {
fn from_settings_string<S: AsRef<str>>(s: S) -> Self {
ItchPlatform {
settings: load_settings(s),
}
}
}
impl GamesPlatform for ItchPlatform {
fn name(&self) -> &str {
"Itch"
}
fn enabled(&self) -> bool {
self.settings.enabled
}
fn get_shortcut_info(&self) -> eyre::Result<Vec<ShortcutToImport>> {
to_shortcuts(self, self.get_itch_games())
}
fn render_ui(&mut self, ui: &mut egui::Ui) {
ui.heading("Itch.io");
ui.checkbox(&mut self.settings.enabled, "Import from Itch.io");
if self.settings.enabled {
ui.horizontal(|ui| {
let mut empty_string = "".to_string();
let itch_location = self.settings.location.as_mut().unwrap_or(&mut empty_string);
ui.label("Itch.io Folder: ");
if ui.text_edit_singleline(itch_location).changed() {
self.settings.location = if itch_location.is_empty() {
None
} else {
Some(itch_location.to_string())
};
} else if !itch_location.is_empty()
&& ui
.button("Reset")
.on_hover_text("Reset the itch path, let BoilR guess again")
.clicked()
{
self.settings.location = None;
}
});
#[cfg(target_family = "unix")]
{
ui.checkbox(&mut self.settings.create_symlinks, "Create symlinks");
}
}
}
fn get_settings_serilizable(&self) -> String {
toml::to_string(&self.settings).unwrap_or_default()
}
fn code_name(&self) -> &str {
"itch"
}
}