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 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 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}