use clap::Parser; use log::{debug, error, warn}; use reqwest::blocking::Client; use serde::{Deserialize, Serialize}; use std::process::Command; fn main() -> Result<(), Box> { let args = CliArgs::parse(); if args.debug { let _ = simplelog::SimpleLogger::init( simplelog::LevelFilter::Debug, simplelog::Config::default(), ); } else { let _ = simplelog::SimpleLogger::init( simplelog::LevelFilter::Info, simplelog::Config::default(), ); } debug!("Opening Config file: {}", args.config_file); debug!( "Config file exists: {}", std::fs::metadata(&args.config_file).is_ok() ); let file_contents = match std::fs::read_to_string(&args.config_file) { Ok(val) => val, Err(e) => { error!("Could not read config file: {e}"); panic!("{e}"); } }; let cfg: Config = match toml::from_str(&file_contents) { Ok(val) => val, Err(e) => { error!("Could not parse config file: {e}"); panic!("{e}"); } }; let mut body_content: String = format!( "*Last Updated:* {} \n", chrono::Local::now().format("%D - %H:%M:%S") ); let mut drives: Vec = vec![]; match std::fs::read_dir("/dev/") { Ok(paths) => { for path in paths.flatten() { let tmp = path.path().to_string_lossy().to_string(); if tmp.starts_with("/dev/sd") && tmp.len() == 8 { drives.push(tmp); } } } Err(e) => { error!("Error opening /dev/: {e}"); panic!("{e}"); } }; { let mut drive_temps: Vec = vec![]; for drive in drives { let output = match Command::new(&args.hddtemp_executable) .arg("--unit=F") .arg(&drive) .output() { Ok(val) => String::from_utf8_lossy(&val.stdout).into_owned(), Err(e) => { warn!("Error running hddtemp: {e}"); warn!("Drive was: '{drive}'"); "".to_string() } }; if !output.contains("sensor") { drive_temps.push(output.replace('\n', "")); } else { drive_temps.push(output[0..9].to_string() + " No Sensor"); } } body_content.push_str("## Hard Drive Temps\n"); body_content.push_str(&drive_temps.join("\n")); } Client::new() .put(format!( "https://{}/index.php/apps/notes/api/v1/notes/{}", &cfg.server_url, &cfg.note_id )) .header("Accept", "application/json") .header("Content-Type", "application/json") .basic_auth(&cfg.user, Some(&cfg.pswd)) .body( serde_json::to_string(&NoteUpdate { content: body_content, }) .unwrap(), ) .send()?; Ok(()) } #[derive(Serialize, Deserialize, Debug)] struct Note { id: usize, etag: String, readonly: bool, modified: u64, title: String, category: String, content: String, favorite: bool, } #[derive(Serialize, Deserialize, Debug)] struct NoteUpdate { content: String, } #[derive(Serialize, Deserialize, Default)] struct Config { user: String, pswd: String, note_id: String, server_url: String, } #[derive(Parser, Debug)] #[command(author, version, about, long_about=None)] struct CliArgs { /// Path to config .toml file #[arg(short, long)] config_file: String, #[arg(short, long)] hddtemp_executable: String, #[arg(short, long)] debug: bool, }