pub mod httpconnector; use std::{ fmt::{Debug, Display}, net::IpAddr, result, }; use crate::{client::Client, executor::Executor}; use remote_control_rs::tasks::NETWORK_T; pub type Result = result::Result; pub trait Connection { type Ok: std::fmt::Display + AsRef = String; type Err: std::fmt::Debug; // should use channel to notify update fn update(&self) -> Result; // None if no update(content is same) // TODO: queue failed ntfy // TODO: impl type of data fn ntfy(&self, data: String) -> std::result::Result<(), Self::Err>; fn is_prev(&mut self, str: &Self::Ok) -> bool; fn get_ip(&self) -> Option; fn force_network(&mut self) { _ = Executor::new(&NETWORK_T, ["true"]); } fn init<'a>(&self, c: &Client<'a, Self>) -> std::result::Result<(), Self::Err> where Self: std::marker::Sized, { self.ntfy(format!( r#"New client: {c} "#, )) } fn reinit(&mut self) { self.force_network(); } fn tick(&mut self) { // tradeoff: if I put this at the ened of the loop, then the continue would just // skip it, and continue doing update() until with no waiting, this wastes lot // of cpu/IO however, of course we can add a manual sleep before it // continue and put this in the end, but that's code duplication // the cons of the current approch is that the first time we've entered, it // would start sleeping self.reinit(); match self.update() { Result::Ok(s) => { if self.is_prev(&s) { return; } let mut it = s.as_ref().split_whitespace(); let task = match it.next() { Some(t) => t, None => return, }; // FIXME: handle the errors... peak prod code self.ntfy(Executor::new(task.try_into().unwrap(), it).unwrap().run().unwrap().clone().unwrap()).unwrap(); } Result::Err(e) => { #[cfg(debug_assertions)] std::eprintln!("[{}:{}:{}] {} = {:#?}", std::file!(), std::line!(), std::column!(), std::stringify!(e), &&e as &dyn std::fmt::Debug,); } } } }