some more error handling and logging
This commit is contained in:
26
src/lib.rs
26
src/lib.rs
@@ -1,6 +1,6 @@
|
||||
use crate::steam::{IniAchievement, JsonAchievement, SteamApp};
|
||||
use reqwest::Client;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod steam;
|
||||
#[cfg(test)]
|
||||
@@ -31,11 +31,11 @@ pub struct Achievement {
|
||||
|
||||
pub struct Context {
|
||||
pub api_key: String,
|
||||
pub game_name_cache_path: Box<Path>,
|
||||
pub json_cache_path: Box<Path>,
|
||||
pub icon_cache_path: Box<Path>,
|
||||
pub game_name_cache_path: PathBuf,
|
||||
pub json_cache_path: PathBuf,
|
||||
pub icon_cache_path: PathBuf,
|
||||
pub game_name_list: Vec<SteamApp>,
|
||||
pub dirs: Vec<String>,
|
||||
pub dirs: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Achievement {
|
||||
@@ -81,7 +81,13 @@ pub async fn get_achievement_data(client: &Client, app_id: u32, context: &Contex
|
||||
&context.json_cache_path,
|
||||
)
|
||||
.await;
|
||||
let ini_data = steam::get_achievement_data_all_ini(&context.dirs);
|
||||
let ini_data = match steam::get_achievement_data_all_ini(&context.dirs) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let ini_game = ini_data.iter().find(|m| m.id == app_id)?;
|
||||
for json_achievement in game_data.game.available_game_stats.achievements {
|
||||
if let Some(ini_achievement) = ini_game
|
||||
@@ -101,7 +107,13 @@ pub async fn get_achievement_data(client: &Client, app_id: u32, context: &Contex
|
||||
|
||||
pub async fn get_achievement_data_all(client: &Client, context: &Context) -> Vec<Game> {
|
||||
let mut games: Vec<Game> = Vec::new();
|
||||
let ini_games = steam::get_achievement_data_all_ini(&context.dirs);
|
||||
let ini_games = match steam::get_achievement_data_all_ini(&context.dirs) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
for ini_game in ini_games {
|
||||
let mut game = Game {
|
||||
app_id: ini_game.id,
|
||||
|
||||
73
src/steam.rs
73
src/steam.rs
@@ -1,10 +1,10 @@
|
||||
use ini::Ini;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, fs::OpenOptions};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -143,12 +143,32 @@ pub async fn get_game_name(
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_achievement_data_all_ini(dirs: &Vec<String>) -> Vec<IniGame> {
|
||||
#[derive(Error, Debug)]
|
||||
pub enum IniError {
|
||||
#[error("failed to read dir: {1}, with err: {0}")]
|
||||
FailedToReadDir(std::io::Error, PathBuf),
|
||||
#[error("failed to get dir entry from dir: {1}, with err: {0}")]
|
||||
FailedToGetDirEntry(std::io::Error, PathBuf),
|
||||
#[error("failed to parse achieved value: {0} in ini file: {1}")]
|
||||
ParseAchieved(std::num::ParseIntError, PathBuf),
|
||||
#[error("failed to parse current progress value: {0} in ini file: {1}")]
|
||||
ParseCurrentProgress(std::num::ParseIntError, PathBuf),
|
||||
#[error("failed to parse max progress value: {0} in ini file: {1}")]
|
||||
ParseMaxProgress(std::num::ParseIntError, PathBuf),
|
||||
#[error("failed to parse unlock time value: {0} in ini file: {1}")]
|
||||
ParseUnlockTime(std::num::ParseIntError, PathBuf),
|
||||
#[error("found unexpected achievement stat: {0}, in file: {1}")]
|
||||
UnexpectedAchievementStat(String, PathBuf),
|
||||
}
|
||||
|
||||
pub fn get_achievement_data_all_ini(dirs: &Vec<PathBuf>) -> Result<Vec<IniGame>, IniError> {
|
||||
let mut ini_games = Vec::new();
|
||||
for dir in dirs {
|
||||
let game_dirs = fs::read_dir(dir).unwrap();
|
||||
let game_dirs: fs::ReadDir =
|
||||
fs::read_dir(dir).map_err(|e| IniError::FailedToReadDir(e, dir.to_path_buf()))?;
|
||||
for game_dir in game_dirs {
|
||||
let game_dir = game_dir.unwrap();
|
||||
let game_dir =
|
||||
game_dir.map_err(|e| IniError::FailedToGetDirEntry(e, dir.to_path_buf()))?;
|
||||
let app_id = game_dir
|
||||
.file_name()
|
||||
.to_str()
|
||||
@@ -156,15 +176,16 @@ pub fn get_achievement_data_all_ini(dirs: &Vec<String>) -> Vec<IniGame> {
|
||||
.to_owned()
|
||||
.parse()
|
||||
.unwrap();
|
||||
let game_dir_path = game_dir.path().to_str().unwrap().to_owned();
|
||||
let ini_game = parse_ini_file(&format!("{game_dir_path}/achievements.ini"), app_id);
|
||||
let mut game_dir_path = game_dir.path();
|
||||
game_dir_path.push("achievements.ini");
|
||||
let ini_game = parse_ini_file(&game_dir_path, app_id)?;
|
||||
ini_games.push(ini_game);
|
||||
}
|
||||
}
|
||||
ini_games
|
||||
Ok(ini_games)
|
||||
}
|
||||
|
||||
pub fn parse_ini_file(path: &str, app_id: u32) -> IniGame {
|
||||
pub fn parse_ini_file(path: &Path, app_id: u32) -> Result<IniGame, IniError> {
|
||||
let mut ini_game = IniGame::new(app_id);
|
||||
let ini = Ini::load_from_file(path).unwrap();
|
||||
for (sec, prop) in ini.iter() {
|
||||
@@ -175,15 +196,37 @@ pub fn parse_ini_file(path: &str, app_id: u32) -> IniGame {
|
||||
let mut ini_achievement = IniAchievement::new(section.to_owned());
|
||||
for (k, v) in prop.iter() {
|
||||
match k {
|
||||
"Achieved" => ini_achievement.achieved = v.parse::<u32>().unwrap() == 1,
|
||||
"CurProgress" => ini_achievement.current_progress = v.parse().unwrap(),
|
||||
"MaxProgress" => ini_achievement.max_progress = v.parse().unwrap(),
|
||||
"UnlockTime" => ini_achievement.unlock_time = v.parse().unwrap(),
|
||||
s => panic!("unexpected achievement stat {s}"),
|
||||
"Achieved" => {
|
||||
ini_achievement.achieved = v
|
||||
.parse::<u32>()
|
||||
.map_err(|e| IniError::ParseAchieved(e, path.to_path_buf()))?
|
||||
== 1
|
||||
}
|
||||
"CurProgress" => {
|
||||
ini_achievement.current_progress = v
|
||||
.parse()
|
||||
.map_err(|e| IniError::ParseCurrentProgress(e, path.to_path_buf()))?
|
||||
}
|
||||
"MaxProgress" => {
|
||||
ini_achievement.max_progress = v
|
||||
.parse()
|
||||
.map_err(|e| IniError::ParseMaxProgress(e, path.to_path_buf()))?
|
||||
}
|
||||
"UnlockTime" => {
|
||||
ini_achievement.unlock_time = v
|
||||
.parse()
|
||||
.map_err(|e| IniError::ParseUnlockTime(e, path.to_path_buf()))?
|
||||
}
|
||||
s => {
|
||||
return Err(IniError::UnexpectedAchievementStat(
|
||||
s.to_owned(),
|
||||
path.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
ini_game.achievements.push(ini_achievement);
|
||||
}
|
||||
}
|
||||
ini_game
|
||||
Ok(ini_game)
|
||||
}
|
||||
|
||||
@@ -114,8 +114,8 @@ pub fn setup() -> Result<Context, SetupError> {
|
||||
let wine_dir = env::var("WINEPREFIX")
|
||||
.unwrap_or(env::var("HOME").map_err(SetupError::NoHomeDir)? + ".wine");
|
||||
let dirs = vec![
|
||||
wine_dir.clone() + "/drive_c/users/Public/Documents/Steam/CODEX",
|
||||
wine_dir.clone() + "/drive_c/users/Public/Documents/Steam/RUNE",
|
||||
PathBuf::from(wine_dir.clone() + "/drive_c/users/Public/Documents/Steam/CODEX"),
|
||||
PathBuf::from(wine_dir.clone() + "/drive_c/users/Public/Documents/Steam/RUNE"),
|
||||
];
|
||||
Ok(Context {
|
||||
api_key: api_key.to_owned(),
|
||||
|
||||
Reference in New Issue
Block a user