summaryrefslogtreecommitdiff
path: root/src/client/connector.rs
blob: 32c9caead6cd3af4977e91caa87511e1bb575db8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
pub mod httpconnector;

use std::{
    fmt::{Debug, Display},
    net::IpAddr,
    result,
};

use crate::client::Client;
use remote_control_rs::{
    executor::Executor,
    tasks::{
        IntoTaskErr,
        client::{NETWORK_T, Task},
    },
};

pub type Result<T: Display, E: Debug> = result::Result<T, E>;

// TODO: adapter to convert the types to strings so normal http server work too
pub trait Connection {
    type Ok: std::fmt::Display + AsRef<str> = String;
    type Err: std::fmt::Debug;

    // should use channel to notify update
    fn update(&self) -> Result<Self::Ok, Self::Err>; // 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<IpAddr>;

    fn force_network(&mut self) {
        _ = Executor::new(NETWORK_T.as_ref(), ["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() as result::Result<Task, IntoTaskErr>).unwrap().as_ref(), it, ()).unwrap().run().as_ref().unwrap().clone()).unwrap();
            }
            Result::Err(e) => {
                #[cfg(debug_assertions)]
                std::eprintln!("[{}:{}:{}] {} = {:#?}", std::file!(), std::line!(), std::column!(), std::stringify!(e), &&e as &dyn std::fmt::Debug,);
            }
        }
    }
}