some more error handling and logging

This commit is contained in:
2025-01-28 20:29:54 +01:00
parent 7a99a03b67
commit cc0c86a970
3 changed files with 79 additions and 24 deletions

View File

@@ -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,

View File

@@ -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)
}

View File

@@ -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(),