some minor restructuring and wip errors
This commit is contained in:
@@ -22,4 +22,5 @@ reqwest = "0.12.12"
|
||||
rust-ini = "0.21.1"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.137"
|
||||
thiserror = "2.0.11"
|
||||
tokio = { version = "1.43.0", default-features = false, features = ["rt-multi-thread", "macros"] }
|
||||
|
||||
95
src/lib.rs
95
src/lib.rs
@@ -1,10 +1,13 @@
|
||||
use crate::steam::SteamApp;
|
||||
use reqwest::Client;
|
||||
use steam::App;
|
||||
use std::path::Path;
|
||||
|
||||
pub mod steam;
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
pub mod ui;
|
||||
pub mod util;
|
||||
pub mod watch;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Game {
|
||||
@@ -28,10 +31,10 @@ pub struct Achievement {
|
||||
|
||||
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<App>,
|
||||
pub game_name_cache_path: Box<Path>,
|
||||
pub json_cache_path: Box<Path>,
|
||||
pub icon_cache_path: Box<Path>,
|
||||
pub game_name_list: Vec<SteamApp>,
|
||||
pub dirs: Vec<String>,
|
||||
}
|
||||
|
||||
@@ -48,7 +51,14 @@ pub async fn get_achievement_data(client: &Client, app_id: u32, context: &Contex
|
||||
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 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 {
|
||||
@@ -75,7 +85,8 @@ pub async fn get_achievement_data(client: &Client, app_id: u32, context: &Contex
|
||||
achievement.max_progress = ini_achievement.max_progress;
|
||||
achievement.current_progress = ini_achievement.current_progress;
|
||||
achievement.unlock_time = ini_achievement.unlock_time;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
game.achievements.push(achievement);
|
||||
}
|
||||
@@ -98,50 +109,42 @@ pub async fn get_achievement_data_all(client: &Client, context: &Context) -> Vec
|
||||
.await
|
||||
.unwrap(),
|
||||
};
|
||||
let game_data = steam::get_steam_data(client, &context.api_key, ini_game.id, "en", &context.json_cache_path).await;
|
||||
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;
|
||||
let mut achievement = Achievement {
|
||||
achieved: false,
|
||||
unlock_time: 0,
|
||||
max_progress: 0,
|
||||
current_progress: 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 {
|
||||
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;
|
||||
achievement.achieved = ini_achievement.achieved;
|
||||
achievement.unlock_time = ini_achievement.unlock_time;
|
||||
achievement.max_progress = ini_achievement.max_progress;
|
||||
achievement.current_progress = ini_achievement.current_progress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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(),
|
||||
});
|
||||
}
|
||||
game.achievements.push(achievement);
|
||||
}
|
||||
games.push(game);
|
||||
}
|
||||
|
||||
122
src/main.rs
122
src/main.rs
@@ -1,23 +1,19 @@
|
||||
use achievement_watcher::{Context, Game};
|
||||
use achievement_watcher::{ui, util, watch};
|
||||
use reqwest::Client;
|
||||
use std::{env, fs};
|
||||
|
||||
mod ui;
|
||||
mod watch;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let client = Client::new();
|
||||
let context = match setup() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
eprintln!("ERROR: was not able to create context");
|
||||
let context = match util::setup() {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let mut games = achievement_watcher::get_achievement_data_all(&client, &context).await;
|
||||
|
||||
cache_icons(&context, &games).await;
|
||||
util::cache_icons(&context, &games).await;
|
||||
|
||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||
if args.is_empty() {
|
||||
@@ -34,109 +30,3 @@ async fn main() {
|
||||
panic!("wrong arg count");
|
||||
}
|
||||
}
|
||||
|
||||
fn setup() -> Option<Context> {
|
||||
let config_dir = dirs::config_dir()?.to_str()?.to_owned() + "/achievement-watcher";
|
||||
let cache_dir = dirs::cache_dir()?.to_str()?.to_owned() + "/achievement-watcher";
|
||||
match std::fs::exists(&config_dir) {
|
||||
Ok(false) => std::fs::create_dir(&config_dir).ok()?,
|
||||
Err(e) => eprintln!("error in setup: config dir: {e}"),
|
||||
Ok(true) => (),
|
||||
}
|
||||
match std::fs::exists(&cache_dir) {
|
||||
Ok(false) => std::fs::create_dir(&cache_dir).ok()?,
|
||||
Err(e) => eprintln!("error in setup: cache dir: {e}"),
|
||||
Ok(true) => (),
|
||||
}
|
||||
let game_name_cache_path = format!("{cache_dir}/game_names.txt");
|
||||
let json_cache_path = format!("{cache_dir}/json");
|
||||
let icon_cache_path = format!("{cache_dir}/icon");
|
||||
let game_name_list = achievement_watcher::util::get_game_name_file_cache(&game_name_cache_path);
|
||||
let api_key_path = format!("{config_dir}/api-key.txt");
|
||||
let api_key = match fs::read_to_string(&api_key_path) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to read api key: {e} from: {api_key_path}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let api_key = api_key.trim();
|
||||
let wine_dir = env::var("WINEPREFIX").unwrap_or(env::var("HOME").ok()? + ".wine");
|
||||
let dirs = vec![
|
||||
wine_dir.clone() + "/drive_c/users/Public/Documents/Steam/CODEX",
|
||||
wine_dir.clone() + "/drive_c/users/Public/Documents/Steam/RUNE",
|
||||
];
|
||||
Some(Context {
|
||||
api_key: api_key.to_owned(),
|
||||
dirs,
|
||||
game_name_list,
|
||||
game_name_cache_path,
|
||||
json_cache_path,
|
||||
icon_cache_path,
|
||||
})
|
||||
}
|
||||
|
||||
async fn cache_icons(context: &Context, games: &Vec<Game>) {
|
||||
let client = Client::new();
|
||||
let mut futures = Vec::new();
|
||||
for game in games {
|
||||
let header = client
|
||||
.get(format!(
|
||||
"https://cdn.cloudflare.steamstatic.com/steam/apps/{}/header.jpg",
|
||||
game.app_id
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
fs::write(
|
||||
&format!("{}/{}/header.jpg", context.icon_cache_path, game.name),
|
||||
header,
|
||||
)
|
||||
.unwrap();
|
||||
for achievement in &game.achievements {
|
||||
let client = &client;
|
||||
let future = async move {
|
||||
let icon_dir = &format!("{}/{}", &context.icon_cache_path, game.name);
|
||||
if !std::path::Path::new(icon_dir).exists() {
|
||||
std::fs::create_dir(icon_dir).unwrap();
|
||||
}
|
||||
let icon_path = format!(
|
||||
"{}/{}/{}.png",
|
||||
&context.icon_cache_path, game.name, achievement.name,
|
||||
);
|
||||
if !std::path::Path::new(&icon_path).exists() {
|
||||
let data = client
|
||||
.get(&achievement.icon)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
std::fs::write(&icon_path, &data).unwrap();
|
||||
}
|
||||
|
||||
let icon_path = format!(
|
||||
"{}/{}/{}gray.png",
|
||||
context.icon_cache_path, game.name, achievement.name,
|
||||
);
|
||||
if !std::path::Path::new(&icon_path).exists() {
|
||||
let data = client
|
||||
.get(&achievement.icongray)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
std::fs::write(&icon_path, &data).unwrap();
|
||||
}
|
||||
};
|
||||
futures.push(future);
|
||||
}
|
||||
}
|
||||
futures::future::join_all(futures).await;
|
||||
}
|
||||
|
||||
21
src/steam.rs
21
src/steam.rs
@@ -2,7 +2,9 @@ use ini::Ini;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -60,12 +62,12 @@ pub struct AppList {
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Apps {
|
||||
pub apps: Vec<App>,
|
||||
pub apps: Vec<SteamApp>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct App {
|
||||
pub struct SteamApp {
|
||||
pub name: String,
|
||||
pub appid: u32,
|
||||
}
|
||||
@@ -96,10 +98,11 @@ pub async fn get_steam_data(
|
||||
key: &str,
|
||||
appid: u32,
|
||||
lang: &str,
|
||||
json_cache_path: &str,
|
||||
json_cache_path: &Path,
|
||||
) -> JsonGame {
|
||||
let json_file_path = format!("{json_cache_path}/{appid}.json");
|
||||
if Path::new(&json_file_path).exists() {
|
||||
let mut json_file_path: PathBuf = json_cache_path.to_path_buf();
|
||||
json_file_path.push(format!("{appid}.json"));
|
||||
if json_file_path.exists() {
|
||||
let json = fs::read_to_string(json_file_path).unwrap();
|
||||
return serde_json::from_str(&json).unwrap();
|
||||
}
|
||||
@@ -111,12 +114,10 @@ pub async fn get_steam_data(
|
||||
|
||||
pub async fn get_game_name(
|
||||
client: &Client,
|
||||
path: &str,
|
||||
game_name_list: &Vec<App>,
|
||||
path: &Path,
|
||||
game_name_list: &Vec<SteamApp>,
|
||||
appid: u32,
|
||||
) -> Option<String> {
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::prelude::*;
|
||||
for app in game_name_list {
|
||||
if app.appid == appid {
|
||||
return Some(app.name.clone());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use achievement_watcher::{Context, Game};
|
||||
use crate::{Context, Game};
|
||||
use eframe::egui;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -30,7 +30,8 @@ pub fn ui(context: Context, games: Vec<Game>) -> eframe::Result {
|
||||
ui.add(
|
||||
egui::Image::new(format!(
|
||||
"file://{}/{}/header.jpg",
|
||||
context.icon_cache_path, game.name
|
||||
context.icon_cache_path.to_str().unwrap(),
|
||||
game.name
|
||||
))
|
||||
.fit_to_original_size(1.),
|
||||
);
|
||||
@@ -51,7 +52,7 @@ pub fn ui(context: Context, games: Vec<Game>) -> eframe::Result {
|
||||
}
|
||||
let icon_path = format!(
|
||||
"{}/{}/{}{}.png",
|
||||
context.icon_cache_path,
|
||||
context.icon_cache_path.to_str().unwrap(),
|
||||
game.name,
|
||||
achievement.name,
|
||||
if achievement.achieved { "" } else { "gray" }
|
||||
|
||||
159
src/util.rs
159
src/util.rs
@@ -1,12 +1,40 @@
|
||||
use crate::steam::App;
|
||||
use std::path::PathBuf;
|
||||
use crate::{steam::SteamApp, Context, Game};
|
||||
use thiserror::Error;
|
||||
use reqwest::Client;
|
||||
use std::{env, fs};
|
||||
|
||||
pub fn get_game_name_file_cache(path: &str) -> Vec<App> {
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SetupError {
|
||||
#[error("failed to get configuration directory")]
|
||||
GetConfigDir,
|
||||
#[error("failed to create configuration directory: \"{0}\"")]
|
||||
CreateConfigDir(std::io::Error, PathBuf),
|
||||
#[error("failed to get cache directory")]
|
||||
GetCacheDir,
|
||||
#[error("failed to create cache directory: \"{1}\", with err: \"{0}\"")]
|
||||
CreateCacheDir(std::io::Error, PathBuf),
|
||||
|
||||
#[error("failed to create cache file: \"{1}\", with err: \"{0}\"")]
|
||||
CreateCacheFile(std::io::Error, PathBuf),
|
||||
|
||||
#[error("api key does not exist: \"{0}\"")]
|
||||
NoApiKey(PathBuf),
|
||||
|
||||
#[error("failed to read api key from path: \"{1}\", with err: \"{0}\"")]
|
||||
ReadApiKey(std::io::Error, PathBuf),
|
||||
|
||||
#[error("no home dir found: \"{0}\"")]
|
||||
NoHomeDir(std::env::VarError),
|
||||
}
|
||||
|
||||
pub fn get_game_name_file_cache(path: &PathBuf) -> Vec<SteamApp> {
|
||||
std::fs::read_to_string(path)
|
||||
.unwrap()
|
||||
.lines()
|
||||
.map(|m| {
|
||||
let a = m.split_once(":").unwrap();
|
||||
App {
|
||||
SteamApp {
|
||||
appid: a.0.parse().unwrap(),
|
||||
name: a.1.to_owned(),
|
||||
}
|
||||
@@ -34,3 +62,128 @@ pub fn send_notification(
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
||||
pub fn setup() -> Result<Context, SetupError> {
|
||||
let mut config_dir = dirs::config_dir().ok_or(SetupError::GetConfigDir)?;
|
||||
config_dir.push("achievement-watcher");
|
||||
if !config_dir.exists() {
|
||||
fs::create_dir(&config_dir)
|
||||
.map_err(|e| SetupError::CreateConfigDir(e, config_dir.clone()))?;
|
||||
}
|
||||
|
||||
let mut cache_dir = dirs::cache_dir().ok_or(SetupError::GetCacheDir)?;
|
||||
cache_dir.push("achievement-watcher");
|
||||
if !cache_dir.exists() {
|
||||
fs::create_dir(&cache_dir).map_err(|e| SetupError::CreateCacheDir(e, cache_dir.clone()))?;
|
||||
}
|
||||
|
||||
let mut json_cache_path = cache_dir.clone();
|
||||
json_cache_path.push("json");
|
||||
if !json_cache_path.exists() {
|
||||
fs::create_dir(&json_cache_path)
|
||||
.map_err(|e| SetupError::CreateCacheDir(e, json_cache_path.clone()))?;
|
||||
}
|
||||
|
||||
let mut icon_cache_path = cache_dir.clone();
|
||||
icon_cache_path.push("icon");
|
||||
if !icon_cache_path.exists() {
|
||||
fs::create_dir(&icon_cache_path)
|
||||
.map_err(|e| SetupError::CreateCacheDir(e, icon_cache_path.clone()))?;
|
||||
}
|
||||
|
||||
let mut game_name_cache_path = cache_dir.clone();
|
||||
game_name_cache_path.push("game_names.txt");
|
||||
if !game_name_cache_path.exists() {
|
||||
fs::write(&game_name_cache_path, "")
|
||||
.map_err(|e| SetupError::CreateCacheFile(e, game_name_cache_path.clone()))?;
|
||||
}
|
||||
|
||||
let game_name_list = crate::util::get_game_name_file_cache(&game_name_cache_path);
|
||||
|
||||
let mut api_key_path = config_dir.clone();
|
||||
api_key_path.push("api-key.txt");
|
||||
if !api_key_path.exists() {
|
||||
return Err(SetupError::NoApiKey(api_key_path.clone()));
|
||||
}
|
||||
|
||||
let api_key = std::fs::read_to_string(&api_key_path)
|
||||
.map_err(|e| SetupError::ReadApiKey(e, api_key_path))?;
|
||||
let api_key = api_key.trim();
|
||||
|
||||
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",
|
||||
];
|
||||
Ok(Context {
|
||||
api_key: api_key.to_owned(),
|
||||
dirs,
|
||||
game_name_list,
|
||||
game_name_cache_path: game_name_cache_path.into(),
|
||||
json_cache_path: json_cache_path.into(),
|
||||
icon_cache_path: icon_cache_path.into(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn cache_icons(context: &Context, games: &Vec<Game>) {
|
||||
let client = Client::new();
|
||||
let mut futures = Vec::new();
|
||||
for game in games {
|
||||
let mut icon_dir: PathBuf = context.icon_cache_path.to_path_buf();
|
||||
icon_dir.push(&game.name);
|
||||
if !icon_dir.exists() {
|
||||
std::fs::create_dir(&icon_dir).unwrap();
|
||||
}
|
||||
let header = client
|
||||
.get(format!(
|
||||
"https://cdn.cloudflare.steamstatic.com/steam/apps/{}/header.jpg",
|
||||
game.app_id
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
let mut header_path = icon_dir.clone();
|
||||
header_path.push("header.jpg");
|
||||
fs::write(header_path, header).unwrap();
|
||||
for achievement in &game.achievements {
|
||||
let client = &client;
|
||||
let mut icon_path = icon_dir.clone();
|
||||
let mut icon_path_gray = icon_dir.clone();
|
||||
let future = async move {
|
||||
icon_path.push(format!("{}.png", achievement.name));
|
||||
if !icon_path.exists() {
|
||||
let data = client
|
||||
.get(&achievement.icon)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
std::fs::write(&icon_path, &data).unwrap();
|
||||
}
|
||||
drop(icon_path);
|
||||
|
||||
icon_path_gray.push(format!("{}gray.png", achievement.name));
|
||||
if !icon_path_gray.exists() {
|
||||
let data = client
|
||||
.get(&achievement.icongray)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
std::fs::write(&icon_path_gray, &data).unwrap();
|
||||
}
|
||||
};
|
||||
futures.push(future);
|
||||
}
|
||||
}
|
||||
futures::future::join_all(futures).await;
|
||||
}
|
||||
|
||||
25
src/watch.rs
25
src/watch.rs
@@ -1,10 +1,11 @@
|
||||
use achievement_watcher::{util, Achievement, Context, Game};
|
||||
use crate::{Achievement, Context, Game};
|
||||
use crate::util;
|
||||
use notify::{event::AccessKind, Event, EventKind, RecursiveMode, Result, Watcher};
|
||||
use reqwest::Client;
|
||||
use std::path::Path;
|
||||
use std::sync::mpsc;
|
||||
|
||||
pub async fn watch_files(context: &Context, games: &mut Vec<Game>) -> Result<()> {
|
||||
pub async fn watch_files(context: &Context, games: &mut [Game]) -> Result<()> {
|
||||
let (tx, rx) = mpsc::channel::<Result<Event>>();
|
||||
let mut watcher = notify::recommended_watcher(tx)?;
|
||||
let client = Client::new();
|
||||
@@ -43,11 +44,11 @@ pub async fn watch_files(context: &Context, games: &mut Vec<Game>) -> Result<()>
|
||||
|
||||
async fn check_for_new_achievement(
|
||||
client: &Client,
|
||||
games: &mut Vec<Game>,
|
||||
games: &mut [Game],
|
||||
app_id: u32,
|
||||
context: &Context,
|
||||
) {
|
||||
let new = achievement_watcher::get_achievement_data(&client, app_id, context)
|
||||
let new = crate::get_achievement_data(client, app_id, context)
|
||||
.await
|
||||
.unwrap();
|
||||
let old = games.iter().find(|m| m.app_id == app_id);
|
||||
@@ -57,8 +58,11 @@ async fn check_for_new_achievement(
|
||||
let new_count = new.achievements.iter().filter(|m| m.achieved).count();
|
||||
let old_count = old.achievements.iter().filter(|m| m.achieved).count();
|
||||
if new_count <= old_count {
|
||||
if new_count < old_count {
|
||||
println!("WATCHER: new count: {}, old count: {}, not updating.", new_count, old_count);
|
||||
if new_count < old_count {
|
||||
println!(
|
||||
"WATCHER: new count: {}, old count: {}, not updating.",
|
||||
new_count, old_count
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -71,7 +75,9 @@ async fn check_for_new_achievement(
|
||||
let new_achievement = &new.achievements[i];
|
||||
let icon_path = format!(
|
||||
"{}/{}/{}.png",
|
||||
context.icon_cache_path, old.name, new_achievement.name
|
||||
context.icon_cache_path.to_str().unwrap(),
|
||||
old.name,
|
||||
new_achievement.name
|
||||
);
|
||||
let icon_path = Path::new(&icon_path);
|
||||
|
||||
@@ -103,12 +109,11 @@ async fn check_for_new_achievement(
|
||||
*old = new;
|
||||
}
|
||||
|
||||
fn compare_achievements(new: &Vec<Achievement>, old: &Vec<Achievement>) -> Vec<usize> {
|
||||
fn compare_achievements(new: &[Achievement], old: &[Achievement]) -> Vec<usize> {
|
||||
new.iter()
|
||||
.map(|n| {
|
||||
.filter_map(|n| {
|
||||
old.iter()
|
||||
.position(|o| !o.achieved && n.achieved && o.name == n.name)
|
||||
})
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user