use std::path::PathBuf; use owl::{Deserialize, Serialize}; use sheepd::{DeviceList, LoginParam}; use super::args::{ListDevicesCommand, LoginCommand}; use crate::api::domain; pub fn api_call Deserialize<'a>, I: Serialize>( server: &str, path: &str, data: I, ) -> crate::api::Result { let url = format!("{}/{path}", domain(server)); let mut res = ureq::post(url).send_json(data).unwrap(); let res: crate::api::Result = res.body_mut().read_json().unwrap(); res } pub fn api_call_get Deserialize<'a>>( server: &str, path: &str, token: &str, ) -> crate::api::Result { let url = format!("{}/{path}", domain(server)); let mut res = ureq::get(url) .header("Authorization", format!("Bearer {token}")) .force_send_body() .send_empty() .unwrap(); let res: crate::api::Result = res.body_mut().read_json().unwrap(); res } fn get_config_path() -> Option { directories::ProjectDirs::from("de", "Hydrar", "sheepd") .map(|proj_dirs| proj_dirs.config_dir().join("config.toml")) } #[derive(Debug, Serialize, Deserialize)] pub struct CtlConfig { pub home: String, pub token: String, } impl CtlConfig { pub fn load() -> Option { let c = std::fs::read_to_string(get_config_path()?).ok()?; toml::from_str(&c).ok() } pub fn save(&self) { let s = toml::to_string(self).unwrap(); let config = get_config_path().unwrap(); let _ = std::fs::create_dir_all(config.parent().unwrap()); std::fs::write(get_config_path().unwrap(), s).unwrap(); } } pub fn list_devices(arg: ListDevicesCommand) { let conf = CtlConfig::load().unwrap(); if let Ok(devices) = api_call_get::(&conf.home, "devices", &conf.token).as_result() { println!("Hosts:"); for d in devices.devices { println!( "- {} [{}]{}", d.hostname, d.id, if d.online { " [ONLINE]" } else { "" } ); } } } pub fn login(arg: LoginCommand) { if let Some(conf) = CtlConfig::load() { println!("You are already logged in to {}", conf.home); std::process::exit(1); } let password = inquire::prompt_secret("Password: ").unwrap(); // login request if let Result::Ok(token) = api_call::( &arg.home, "login", LoginParam { username: arg.username, password: password, }, ) .as_result() { // save token to config CtlConfig { home: arg.home, token, } .save(); } else { println!("Login failed"); } }