ntfy_types/
lib.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize)]
4pub struct NtfyMsg {
5    pub topic: String,
6    #[serde(skip_serializing_if = "Option::is_none")]
7    pub message: Option<String>,
8    #[serde(skip_serializing_if = "Option::is_none")]
9    pub title: Option<String>,
10    #[serde(skip_serializing_if = "Option::is_none")]
11    pub tags: Option<Vec<String>>,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub priority: Option<NtfyPriority>,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub attach: Option<String>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub filename: Option<String>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub click: Option<String>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub actions: Option<Vec<NtfyAction>>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub delay: Option<String>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub email: Option<String>,
26}
27
28impl NtfyMsg {
29    pub fn new(topic: &str) -> NtfyMsg {
30        NtfyMsg {
31            topic: String::from(topic),
32            ..Default::default()
33        }
34    }
35
36    pub fn builder(topic: &str) -> NtfyMsgBuilder {
37        NtfyMsgBuilder::new(topic)
38    }
39}
40
41pub struct NtfyMsgBuilder {
42    msg: NtfyMsg,
43}
44
45impl NtfyMsgBuilder {
46    pub fn new(topic: &str) -> NtfyMsgBuilder {
47        NtfyMsgBuilder {
48            msg: NtfyMsg::new(topic),
49        }
50    }
51
52    pub fn topic(mut self, topic: &str) -> NtfyMsgBuilder {
53        self.msg.topic = String::from(topic);
54        self
55    }
56
57    pub fn message(mut self, message: &str) -> NtfyMsgBuilder {
58        self.msg.message = Some(String::from(message));
59        self
60    }
61
62    pub fn title(mut self, title: &str) -> NtfyMsgBuilder {
63        self.msg.title = Some(String::from(title));
64        self
65    }
66
67    pub fn tags(mut self, tags: Vec<String>) -> NtfyMsgBuilder {
68        self.msg.tags = Some(tags);
69        self
70    }
71
72    pub fn add_tag(mut self, tag: &str) -> NtfyMsgBuilder {
73        if self.msg.tags.is_none() {
74            self.msg.tags = Some(vec![String::from(tag)]);
75        } else {
76            self.msg.tags.as_mut().unwrap().push(String::from(tag));
77        }
78        self
79    }
80
81    pub fn priority(mut self, priority: NtfyPriority) -> NtfyMsgBuilder {
82        self.msg.priority = Some(priority);
83        self
84    }
85
86    pub fn attach(mut self, attach: &str) -> NtfyMsgBuilder {
87        self.msg.attach = Some(String::from(attach));
88        self
89    }
90
91    pub fn filename(mut self, filename: &str) -> NtfyMsgBuilder {
92        self.msg.filename = Some(String::from(filename));
93        self
94    }
95
96    pub fn click(mut self, click: &str) -> NtfyMsgBuilder {
97        self.msg.click = Some(String::from(click));
98        self
99    }
100
101    pub fn actions(mut self, actions: Vec<NtfyAction>) -> NtfyMsgBuilder {
102        self.msg.actions = Some(actions);
103        self
104    }
105
106    pub fn add_action(mut self, action: NtfyAction) -> NtfyMsgBuilder {
107        if self.msg.actions.is_none() {
108            self.msg.actions = Some(vec![action]);
109        } else {
110            self.msg.actions.as_mut().unwrap().push(action);
111        }
112        self
113    }
114
115    pub fn delay(mut self, delay: &str) -> NtfyMsgBuilder {
116        self.msg.delay = Some(String::from(delay));
117        self
118    }
119
120    pub fn email(mut self, email: &str) -> NtfyMsgBuilder {
121        self.msg.email = Some(String::from(email));
122        self
123    }
124
125    pub fn build(self) -> NtfyMsg {
126        self.msg
127    }
128}
129
130#[derive(Debug, Clone, Default, Serialize, Deserialize)]
131pub struct NtfyAction {
132    pub action: NtfyActionType,
133    pub label: String,
134    pub url: String,
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub clear: Option<bool>,
137}
138
139impl NtfyAction {
140    pub fn new(label: String, url: String) -> NtfyAction {
141        NtfyAction {
142            action: NtfyActionType::View,
143            label,
144            url,
145            clear: None,
146        }
147    }
148}
149
150#[repr(u8)]
151#[non_exhaustive]
152#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
153#[serde(from = "u8")]
154#[serde(into = "u8")]
155pub enum NtfyPriority {
156    Minimum,
157    Low,
158    Default,
159    High,
160    Maximum,
161}
162
163impl Default for NtfyPriority {
164    fn default() -> Self {
165        NtfyPriority::Default
166    }
167}
168
169impl From<NtfyPriority> for u8 {
170    fn from(priority: NtfyPriority) -> Self {
171        match priority {
172            NtfyPriority::Minimum => 1,
173            NtfyPriority::Low => 2,
174            NtfyPriority::Default => 3,
175            NtfyPriority::High => 4,
176            NtfyPriority::Maximum => 5,
177        }
178    }
179}
180
181impl From<u8> for NtfyPriority {
182    fn from(value: u8) -> Self {
183        match value {
184            1 => NtfyPriority::Minimum,
185            2 => NtfyPriority::Low,
186            4 => NtfyPriority::High,
187            5 => NtfyPriority::Maximum,
188            _ => NtfyPriority::Default,
189        }
190    }
191}
192
193#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
194#[serde(rename_all = "lowercase")]
195pub enum NtfyActionType {
196    View,
197    Broadcast,
198    Http,
199}
200
201impl NtfyActionType {
202    pub fn value(&self) -> &'static str {
203        match self {
204            Self::View => "view",
205            Self::Broadcast => "broadcast",
206            Self::Http => "http",
207        }
208    }
209}
210
211impl Default for NtfyActionType {
212    fn default() -> Self {
213        NtfyActionType::View
214    }
215}
216
217// Responses
218
219#[derive(Debug, Clone, Default, Serialize, Deserialize)]
220pub struct NtfyResponse {
221    pub id: String,
222    pub time: u64,
223    pub event: String,
224    pub topic: String,
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub message: Option<String>,
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub title: Option<String>,
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub tags: Option<Vec<String>>,
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub priority: Option<NtfyPriority>,
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub click: Option<String>,
235    #[serde(skip_serializing_if = "Option::is_none")]
236    pub action: Option<Vec<NtfyAction>>,
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub attachment: Option<NtfyAttachment>,
239}
240
241#[derive(Debug, Clone, Default, Serialize, Deserialize)]
242pub struct NtfyAttachment {
243    pub name: String,
244    pub url: String,
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub r#type: Option<String>,
247    #[serde(skip_serializing_if = "Option::is_none")]
248    pub size: Option<u64>,
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub expires: Option<u64>,
251}
252
253#[derive(Debug, Clone, Default, Serialize, Deserialize)]
254pub struct NtfyErrorResponse {
255    pub code: u64,
256    pub http: u16,
257    pub error: String,
258    pub link: String,
259}