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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
use crate::request::notification::{NotificationBuilder, NotificationOptions};
use crate::request::payload::{APSAlert, APSSound, Payload, APS};
use std::collections::BTreeMap;
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct WebPushAlert<'a> {
pub title: &'a str,
pub body: &'a str,
pub action: &'a str,
}
/// A builder to create a simple APNs notification payload.
///
/// # Example
///
/// ```rust
/// # use a2::request::notification::{NotificationBuilder, WebNotificationBuilder, WebPushAlert};
/// # use a2::request::payload::PayloadLike;
/// # fn main() {
/// let mut builder = WebNotificationBuilder::new(WebPushAlert {title: "Hello", body: "World", action: "View"}, &["arg1"]);
/// builder.set_sound("prööt");
/// let payload = builder.build("device_id", Default::default())
/// .to_json_string().unwrap();
/// # }
/// ```
pub struct WebNotificationBuilder<'a> {
alert: WebPushAlert<'a>,
sound: Option<&'a str>,
url_args: &'a [&'a str],
}
impl<'a> WebNotificationBuilder<'a> {
/// Creates a new builder with the minimum amount of content.
///
/// ```rust
/// # use a2::request::notification::{WebNotificationBuilder, NotificationBuilder, WebPushAlert};
/// # use a2::request::payload::PayloadLike;
/// # fn main() {
/// let mut builder = WebNotificationBuilder::new(WebPushAlert {title: "Hello", body: "World", action: "View"}, &["arg1"]);
/// let payload = builder.build("token", Default::default());
///
/// assert_eq!(
/// "{\"aps\":{\"alert\":{\"title\":\"Hello\",\"body\":\"World\",\"action\":\"View\"},\"url-args\":[\"arg1\"]}}",
/// &payload.to_json_string().unwrap()
/// );
/// # }
/// ```
pub fn new(alert: WebPushAlert<'a>, url_args: &'a [&'a str]) -> WebNotificationBuilder<'a> {
WebNotificationBuilder {
alert,
sound: None,
url_args,
}
}
/// File name of the custom sound to play when receiving the notification.
///
/// ```rust
/// # use a2::request::notification::{WebNotificationBuilder, NotificationBuilder, WebPushAlert};
/// # use a2::request::payload::PayloadLike;
/// # fn main() {
/// let mut builder = WebNotificationBuilder::new(WebPushAlert {title: "Hello", body: "World", action: "View"}, &["arg1"]);
/// builder.set_sound("meow");
/// let payload = builder.build("token", Default::default());
///
/// assert_eq!(
/// "{\"aps\":{\"alert\":{\"title\":\"Hello\",\"body\":\"World\",\"action\":\"View\"},\"sound\":\"meow\",\"url-args\":[\"arg1\"]}}",
/// &payload.to_json_string().unwrap()
/// );
/// # }
/// ```
pub fn set_sound(&mut self, sound: &'a str) -> &mut Self {
self.sound = Some(sound);
self
}
}
impl<'a> NotificationBuilder<'a> for WebNotificationBuilder<'a> {
fn build(self, device_token: &'a str, options: NotificationOptions<'a>) -> Payload<'a> {
Payload {
aps: APS {
alert: Some(APSAlert::WebPush(self.alert)),
badge: None,
sound: self.sound.map(APSSound::Sound),
content_available: None,
category: None,
mutable_content: None,
url_args: Some(self.url_args),
},
device_token,
options,
data: BTreeMap::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::request::payload::PayloadLike;
use serde_json::Value;
#[test]
fn test_webpush_notification() {
let payload = WebNotificationBuilder::new(
WebPushAlert {
action: "View",
title: "Hello",
body: "world",
},
&["arg1"],
)
.build("device-token", Default::default())
.to_json_string()
.unwrap();
let expected_payload = json!({
"aps": {
"alert": {
"title": "Hello",
"body": "world",
"action": "View",
},
"url-args": ["arg1"]
}
});
assert_eq!(expected_payload, serde_json::from_str::<Value>(&payload).unwrap());
}
}