ifttt_webhook/
lib.rs

1#[macro_use]
2extern crate lazy_static;
3
4mod error;
5mod http;
6
7use error::IftttWebhookError;
8use http::HTTP_CLIENT;
9
10use std::collections::HashMap;
11use std::error::Error;
12
13#[derive(Debug, Clone)]
14pub struct IftttWebhook {
15    pub event: String,
16    pub key: String,
17}
18
19pub fn build_hook_url(key: &str, event: &str) -> String {
20    format!(
21        "https://maker.ifttt.com/trigger/{event}/with/key/{key}",
22        event = event,
23        key = key,
24    )
25}
26
27pub async fn trigger_webhook(key: &str, event: &str, body: Option<&HashMap<&str, &str>>) -> Result<(), impl Error> {
28    let req = if let Some(body) = body {
29        HTTP_CLIENT.post(&build_hook_url(key, event)).json(body)
30    } else {
31        HTTP_CLIENT.get(&build_hook_url(key, event))
32    };
33    let res = req.send().await?;
34    if res.status() != 200 {
35        Err(IftttWebhookError::new(format!(
36            "Invalid status {}.\n{:?}",
37            res.status(),
38            res
39        )))
40    } else {
41        Ok(())
42    }
43}
44
45impl IftttWebhook {
46    pub fn url(&self) -> String {
47        build_hook_url(&self.event,&self.key)
48    }
49
50    pub async fn trigger(&self, body: Option<&HashMap<&str, &str>>) -> Result<(), impl Error> {
51        trigger_webhook(&self.key, &self.event, body).await
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::IftttWebhook;
58    use std::collections::HashMap;
59    use std::env;
60
61    lazy_static! {
62        // The Client holds a connection pool internally, so it is advised that you create one and reuse it.
63        pub static ref KEY: String = env::var("IFTTT_KEY").unwrap();
64    }
65
66    #[tokio::test]
67    async fn test_post() {
68        // webhook https://maker.ifttt.com/trigger/test/with/key/{key}
69        let mut values = HashMap::new();
70        values.insert("value1", "value_1_test_value");
71        values.insert("value2", "value_2_test_value");
72        values.insert("value3", "value_3_test_value");
73        let webhook = IftttWebhook {
74            key: KEY.clone(),
75            event: "test".into(),
76        };
77        let result = webhook.trigger(Some(&values)).await;
78        assert_eq!(result.is_ok(), true);
79    }
80
81    #[tokio::test]
82    async fn test_get() {
83        // webhook https://maker.ifttt.com/trigger/test/with/key/{key}
84        let webhook = IftttWebhook {
85            key: KEY.clone(),
86            event: "test".into(),
87        };
88        let result = webhook.trigger(None).await;
89        assert_eq!(result.is_ok(), true);
90    }
91
92    #[tokio::test]
93    async fn test_post_error_unauthorized() {
94        // webhook https://maker.ifttt.com/trigger/test/with/key/{key}
95        let mut values = HashMap::new();
96        values.insert("value1", "value_1_test_value");
97        values.insert("value2", "value_2_test_value");
98        values.insert("value3", "value_3_test_value");
99        let webhook = IftttWebhook {
100            key: "wrong_key".into(),
101            event: "test".into(),
102        };
103        let result = webhook.trigger(Some(&values)).await;
104        assert_eq!(result.is_err(), true);
105    }
106
107    #[tokio::test]
108    async fn test_get_error_unauthorized() {
109        // webhook https://maker.ifttt.com/trigger/test/with/key/{key}
110        let webhook = IftttWebhook {
111            key: "wrong_key".into(),
112            event: "test".into(),
113        };
114        let result = webhook.trigger(None).await;
115        assert_eq!(result.is_err(), true);
116    }
117}