game_scanner/steam/
acf.rs1use 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}