pusher_beam_rust/
lib.rs

1use anyhow::{anyhow, Result};
2use reqwest::header::{HeaderMap, ACCEPT, CONTENT_TYPE, AUTHORIZATION};
3use serde::{ Serialize};
4use serde_json::{Value, json};
5
6const SDK_VERSION: &'static str = env!("CARGO_PKG_VERSION");
7
8pub struct PusherBeam {
9    instance_id: String,
10    secret_key: String,
11}
12
13#[derive(Debug, Serialize)]
14pub struct Payload {
15    pub interests: Vec<String>,
16    #[serde(skip_serializing_if = "Value::is_null")]
17    pub web: Value,
18    #[serde(skip_serializing_if = "Value::is_null")]
19    pub fcm: Value,
20    #[serde(skip_serializing_if = "Value::is_null")]
21    pub apns: Value,
22}
23
24impl PusherBeam {
25    pub fn new(instance_id: &str, secret_key: &str) -> Self {
26        Self {
27            instance_id: instance_id.to_owned(),
28            secret_key: secret_key.to_owned(),
29        }
30    }
31
32    pub async fn publish(&self, payload: &Payload) -> Result<()>  {
33        let client = self.build_client();
34        let resp =  client.json(&json!(payload)).send().await?;
35        if resp.status() == 200 {
36            Ok(())
37        } else {
38            Err(anyhow!("Failed to publish the request: {}. Error: {}", serde_json::to_string(&payload).unwrap(), resp.text().await?))
39        }
40
41    }
42
43    // private function
44    fn build_client(&self) -> reqwest::RequestBuilder {
45        let client = reqwest::Client::new();
46        let url = format!("https://{}.pushnotifications.pusher.com/publish_api/v1/instances/{}/publishes", self.instance_id, self.instance_id);
47        let mut headers = HeaderMap::new();
48        headers.insert(ACCEPT, "application/json".parse().unwrap());
49        headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
50        headers.insert(AUTHORIZATION, format!("Bearer {}", self.secret_key).parse().unwrap());
51        headers.insert("X-Pusher-Library", format!("pusher-push-notifications-node {}", SDK_VERSION).parse().unwrap());
52
53        client.post(&url).headers(headers)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use std::env;
60    use super::*;
61    #[tokio::test]
62    async fn it_works() -> Result<()> {
63        // To run this test, you need to provide pusher settings in envar with below names.
64        let instance_id = env::var("PUSHER_BEAM_INSTANCE_ID").unwrap();
65        let secret = env::var("PUSHER_BEAM_SECRET").unwrap();
66        let pusher = PusherBeam::new(&instance_id, &secret);
67        let request = r#"
68        {"web":{"notification":{"title":"Hello","body":"Hello, world!"}}}
69        "#;
70        let payload = Payload {
71            interests: vec!["hello".to_owned(), "hi".to_owned()],
72            web: serde_json::from_str(request)?,
73            fcm: Value::Null,
74            apns: Value::Null,
75        };
76        pusher.publish(&payload).await.unwrap();
77        Ok(())
78    }
79}