game-scanner 1.0.0

Game Scanner for any launcher and OS
Documentation
use std::fs;
use std::path::Path;

use serde::{Deserialize, Serialize};

use crate::error::{Error, ErrorKind, Result};
use crate::prelude::{Game, GameCommands, GameState, GameType};

#[derive(Serialize, Deserialize, Debug)]
struct Manifest {
    #[serde(rename(deserialize = "bIsIncompleteInstall"))]
    is_incomplete_install: bool,
    #[serde(rename(deserialize = "AppName"))]
    app_name: String,
    #[serde(rename(deserialize = "DisplayName"))]
    display_name: String,
    #[serde(rename(deserialize = "InstallLocation"))]
    install_location: String,
    #[serde(rename(deserialize = "LaunchExecutable"))]
    launch_executable: String,
}

pub fn read(file: &Path, launcher_executable: &Path) -> Result<Game> {
    let manifest_data = fs::read_to_string(&file)
        .map_err(|error| {
            Error::new(
                ErrorKind::InvalidManifest,
                format!(
                    "Invalid Epic Games manifest: {} {}",
                    file.display().to_string(),
                    error.to_string()
                ),
            )
        })
        .unwrap();

    let manifest = serde_json::from_str::<Manifest>(manifest_data.as_str())
        .map_err(|error| {
            Error::new(
                ErrorKind::InvalidManifest,
                format!(
                    "Error on read the Epic Games manifest: {} {}",
                    file.display().to_string(),
                    error.to_string()
                ),
            )
        })
        .unwrap();

    if manifest.display_name.contains("Unreal Engine") {
        return Err(Error::new(
            ErrorKind::IgnoredApp,
            format!(
                "({}) {} is an invalid game",
                &manifest.app_name, &manifest.display_name
            ),
        ));
    }

    return Ok(Game {
        _type: GameType::EpicGames.to_string(),
        id: manifest.app_name.clone(),
        name: manifest.display_name.clone(),
        path: manifest.install_location.clone(),
        commands: GameCommands {
            install: None,
            launch: vec![
                launcher_executable.display().to_string(),
                format!(
                    "com.epicgames.launcher://apps/{}?action=launch&silent=true",
                    &manifest.app_name
                ),
            ],
            uninstall: None,
        },
        state: GameState {
            installed: !manifest.is_incomplete_install,
            needs_update: false,
            downloading: false,
            total_bytes: None,
            received_bytes: None,
        },
    });
}