game_scanner/steam/
acf.rs

1use std::path::{Path, PathBuf};
2
3use crate::{
4    error::{Error, ErrorKind, Result},
5    prelude::Game,
6    steam::types::{SteamAppState, SteamUpdateResult},
7    utils::string::remove_quotes,
8};
9
10pub fn read(file: &Path, launcher_executable: &Path, library_path: &Path) -> Result<Game> {
11    let manifest_data = std::fs::read_to_string(&file).map_err(|error| {
12        Error::new(
13            ErrorKind::InvalidManifest,
14            format!(
15                "Error on read the Steam manifest: {} {}",
16                file.display().to_string(),
17                error.to_string()
18            ),
19        )
20    })?;
21
22    let manifest = manifest_data.split("\n").collect::<Vec<&str>>();
23
24    let mut game = Game::default();
25    game._type = String::from("steam");
26
27    for file_line in manifest {
28        let line = file_line
29            .split("\t")
30            .filter(|str| !str.trim().is_empty())
31            .collect::<Vec<&str>>();
32
33        if line.len() != 2 {
34            continue;
35        }
36
37        let attr = remove_quotes(line.get(0).unwrap());
38        let value = remove_quotes(line.get(1).unwrap());
39
40        match attr.as_str() {
41            "appid" => game.id = value,
42            "name" => game.name = value,
43            "StateFlags" => {
44                let state = value.parse::<i64>().unwrap();
45
46                game.state.installed = has_app_state(state, SteamAppState::FullyInstalled);
47
48                game.state.needs_update = has_app_state(state, SteamAppState::UpdateRequired);
49
50                game.state.downloading = has_app_state(state, SteamAppState::Downloading);
51            }
52            "UpdateResult" => {
53                let state = value.parse::<i64>().unwrap();
54
55                if game.state.needs_update && !game.state.downloading {
56                    game.state.downloading =
57                        has_update_result(state, SteamUpdateResult::Downloading);
58                }
59            }
60            "BytesToDownload" => game.state.total_bytes = value.parse::<u64>().ok(),
61            "BytesDownloaded" => game.state.received_bytes = value.parse::<u64>().ok(),
62            "installdir" => {
63                game.path = Some(PathBuf::from(library_path).join("common").join(value))
64            }
65            _ => {}
66        }
67    }
68
69    if game.id == "228980" {
70        return Err(Error::new(
71            ErrorKind::IgnoredApp,
72            format!("({}) {} is an invalid game", &game.id, &game.name),
73        ));
74    }
75
76    game.commands.install = Some(vec![
77        launcher_executable.display().to_string(),
78        String::from("-silent"),
79        format!("steam://install/{}", &game.id),
80    ]);
81
82    game.commands.launch = Some(vec![
83        launcher_executable.display().to_string(),
84        String::from("-silent"),
85        format!("steam://run/{}", &game.id),
86    ]);
87
88    game.commands.uninstall = Some(vec![
89        launcher_executable.display().to_string(),
90        String::from("-silent"),
91        format!("steam://uninstall/{}", &game.id),
92    ]);
93
94    return Ok(game);
95}
96
97fn has_app_state(state: i64, flag: SteamAppState) -> bool {
98    if flag == SteamAppState::Invalid {
99        return state == 0;
100    }
101
102    if flag == SteamAppState::Uninstalled {
103        return state == 1;
104    }
105
106    (state & flag.get_code()) == flag.get_code()
107}
108
109fn has_update_result(state: i64, flag: SteamUpdateResult) -> bool {
110    if flag == SteamUpdateResult::Downloading {
111        return state == 0;
112    }
113
114    (state & flag.get_code()) == flag.get_code()
115}