use std::fmt::{Display, Formatter}; use std::fs; use std::path::PathBuf; use dirs::home_dir; use std::io::{SeekFrom, Seek}; use reqwest::Client; use reqwest::header::CONTENT_TYPE; use crate::error::{ManifoldError, ManifoldResult}; const CACHE_VERSION: &'static str = "1"; pub trait Pump { fn pump(self) -> Result; } #[derive(Copy, Clone, Debug)] #[allow(dead_code)] pub struct FuelTank { mode: TankMode, } #[derive(Copy, Clone, Debug)] enum TankMode { Cache, } impl FuelTank { pub fn with_cache() -> Self { Self { mode: TankMode::Cache, } } } #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Tip { pub number: i32, pub tip: String, } impl Display for Tip { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "#{}: {}", self.number, self.tip) } } #[derive(Serialize, Deserialize, Debug)] pub struct Croak { pub tips: Vec, } pub async fn croak() -> ManifoldResult> { debug!("Getting new tips"); let result: Croak; let client = Client::new(); result = client.get("https://frog.tips/api/1/tips/") .header(CONTENT_TYPE, "application/json") .send().await.unwrap().json().await.unwrap(); debug!("Result: {:?}", &result); Ok(result.tips) } impl FuelTank { pub async fn next_or_fill(self) -> Result { debug!("Filling tank!"); let mut cache = { let mut path = PathBuf::new(); path.push(home_dir().ok_or(ManifoldError::from("No home dir"))?); path.push(".local"); path.push(format!("coffeebot-frog-cache-{}.json", CACHE_VERSION)); debug!("Cache path: {:?}", &path); fs::OpenOptions::new() .read(true) .write(true) .create(true) .open(path) .map_err(|e| { error!("Error creating cache file: {}", e); ManifoldError::from("CACHE ERROR") })? }; debug!("Cache: {:?}", &cache); let json: Result, serde_json::Error> = serde_json::from_reader(&mut cache); debug!("Json: {:?}", &json); let mut tips = match json { Ok(contents) => { match contents.len() { 0 => croak().await?, _ => contents, } } _ => croak().await?, }; debug!("Got tips: {:?}", &tips); let tip = tips.pop().ok_or(ManifoldError::from("FROG HAS NO TIPS FOR YOU. CROAK ERROR 12"))?; debug!("Got single tip: {:?}", &tip); cache .set_len(0) .and_then(|_| cache.seek(SeekFrom::Start(0)))?; debug!("Writing cache"); serde_json::to_writer(cache, &tips)?; Ok(tip) } }