use reqwest::Client; use steam::App; pub mod steam; #[cfg(test)] mod test; pub mod util; #[derive(Debug)] pub struct Game { pub app_id: u32, pub name: String, pub achievements: Vec, } #[derive(Debug)] pub struct Achievement { pub name: String, pub description: Option, pub achieved: bool, pub hidden: bool, pub icon: String, pub icongray: String, pub current_progress: u32, pub max_progress: u32, pub unlock_time: u32, } pub struct Context { pub api_key: String, pub game_name_cache_path: String, pub json_cache_path: String, pub icon_cache_path: String, pub game_name_list: Vec, pub dirs: Vec, } pub async fn get_achievement_data(client: &Client, app_id: u32, context: &Context) -> Option { let mut game = Game { name: steam::get_game_name( client, &context.game_name_cache_path, &context.game_name_list, app_id, ) .await .unwrap(), app_id, achievements: Vec::new(), }; let game_data = steam::get_steam_data(client, &context.api_key, app_id, "en", &context.json_cache_path).await; let ini_data = steam::get_achievement_data_all_ini(&context.dirs); let ini_game = ini_data.iter().find(|m| m.id == app_id)?; for json_achievement in &game_data.game.available_game_stats.achievements { let mut achievement = Achievement { achieved: false, max_progress: 0, current_progress: 0, unlock_time: 0, description: json_achievement.description.clone(), name: json_achievement.display_name.clone(), hidden: if json_achievement.hidden == 1 { true } else if json_achievement.hidden == 0 { false } else { panic!("Unexpected hidden value") }, icon: json_achievement.icon.clone(), icongray: json_achievement.icongray.clone(), }; for ini_achievement in &ini_game.achievements { if json_achievement.name == ini_achievement.name { achievement.achieved = ini_achievement.achieved; achievement.max_progress = ini_achievement.max_progress; achievement.current_progress = ini_achievement.current_progress; achievement.unlock_time = ini_achievement.unlock_time; } } game.achievements.push(achievement); } Some(game) } pub async fn get_achievement_data_all(client: &Client, context: &Context) -> Vec { let mut games: Vec = Vec::new(); let ini_games = steam::get_achievement_data_all_ini(&context.dirs); for ini_game in ini_games { let mut game = Game { app_id: ini_game.id, achievements: Vec::new(), name: steam::get_game_name( client, &context.game_name_cache_path, &context.game_name_list, ini_game.id, ) .await .unwrap(), }; let game_data = steam::get_steam_data(client, &context.api_key, ini_game.id, "en", &context.json_cache_path).await; for json_achievement in &game_data.game.available_game_stats.achievements { let mut found_in_ini = false; for ini_achievement in &ini_game.achievements { if json_achievement.name == ini_achievement.name { game.achievements.push(Achievement { achieved: ini_achievement.achieved, max_progress: ini_achievement.max_progress, current_progress: ini_achievement.current_progress, description: json_achievement.description.clone(), name: json_achievement.display_name.clone(), hidden: if json_achievement.hidden == 1 { true } else if json_achievement.hidden == 0 { false } else { panic!("Unexpected hidden value") }, icon: json_achievement.icon.clone(), icongray: json_achievement.icongray.clone(), unlock_time: ini_achievement.unlock_time, }); found_in_ini = true; } } if !found_in_ini { game.achievements.push(Achievement { achieved: false, max_progress: 0, current_progress: 0, unlock_time: 0, description: json_achievement.description.clone(), name: json_achievement.display_name.clone(), hidden: if json_achievement.hidden == 1 { true } else if json_achievement.hidden == 0 { false } else { panic!("Unexpected hidden value") }, icon: json_achievement.icon.clone(), icongray: json_achievement.icongray.clone(), }); } } games.push(game); } games }