//! Guild name retrieval and caching functions. use super::paths; use std::collections::HashMap; use std::fs::File; use std::sync::RwLock; use anyhow::Result; use log::{error, warn}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; static CACHE: Lazy>> = Lazy::new(|| RwLock::new(HashMap::new())); #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Guild { tag: String, name: String, } impl Guild { pub fn tag(&self) -> &str { &self.tag } pub fn name(&self) -> &str { &self.name } } /// Looks up the given guild. /// /// This checks the cache first, and if nothing was found, it will hit the API. pub fn lookup(api_id: &str) -> Option { { let cache = CACHE.read().unwrap(); if let Some(guild) = cache.get(api_id) { return Some(guild.clone()); } } let mut cache = CACHE.write().unwrap(); let url = format!("https://api.guildwars2.com/v2/guild/{}", api_id); let guild: Guild = ureq::get(&url) .call() .ok()? .into_json() .expect("Invalid JSON in API response"); cache.insert(api_id.into(), guild.clone()); Some(guild) } /// Loads the cache from the file system. pub fn prepare_cache() { let path = paths::cache_path(); if let Some(path) = path { if !path.is_file() { return; } let file = File::open(path).expect("Unable to read cache file"); let cache = serde_json::from_reader(file).expect("Cache file has invalid format"); let mut target = CACHE.write().unwrap(); *target = cache; } else { warn!("Could not determine the cache path, the persistent guild cache is disabled"); } } /// Saves the cache to the file system pub fn save_cache() { let path = paths::cache_path(); // We already warned about that earlier if let Some(path) = path { let result: Result<()> = try { let file = File::create(path)?; serde_json::to_writer(file, &*CACHE.read().unwrap())?; }; if let Err(e) = result { error!("Error saving the cache: {}", e); } } }