Skip to main content

pushover_rs/pushover/data/
attachment_message_builder.rs

1use std::io::Error;
2use std::io::ErrorKind;
3use crate::pushover::constants;
4
5use super::PushoverSound;
6use super::AttachmentMessage;
7
8// TODO: Fix DRY principle with message_builder.rs
9
10/**
11Helps build a correct Pushover request, with attachment.
12 */
13pub struct AttachmentMessageBuilder {
14    build: AttachmentMessage,
15}
16
17impl AttachmentMessageBuilder {
18    /// Creates a new MessageBuilder instance with the required minimal informations (User key, App token & Message)
19    pub fn new(user_key: &str, application_token: &str, message: &str) -> Self {
20        let mut build = AttachmentMessage::default();
21        
22        build.user_key = user_key.to_owned();
23        build.app_token = application_token.to_owned();
24        build.message = message.to_owned();
25
26        AttachmentMessageBuilder {
27            build,
28        }
29    }
30
31    /// Modifies the existing message.
32    pub fn modify_message(mut self, message: &str) -> AttachmentMessageBuilder {
33        if message.trim().len() == 0 {
34            return self;
35        }
36
37        self.build.message = message.to_owned();
38        self
39    }
40
41    /// Sets a title to your message
42    pub fn set_title(mut self, title: &str) -> AttachmentMessageBuilder {
43        if title.trim().len() == 0 {
44            self.build.title = None;
45        }
46
47        self.build.title = Some(title.to_owned());
48        self
49    }
50
51    /// Adds a title to your message
52    #[deprecated(since="0.3.12", note="Please use set_title instead.")]
53    pub fn add_title(mut self, title: &str) -> AttachmentMessageBuilder {
54        if title.trim().len() == 0 {
55            self.build.title = None;
56        }
57
58        self.build.title = Some(title.to_owned());
59        self
60    }
61
62    /// Removes the title. The title will be defaulted to your application name.
63    pub fn remove_title(mut self) -> AttachmentMessageBuilder {
64        self.build.title = None;
65        self
66    }
67
68    /// Sets an url (and optionally, an url title) to send along with your message.
69    ///
70    /// If set, the URL title will be shown, otherwise the URL will be shown.
71    pub fn set_url(mut self, url: &str, url_title: Option<&str>) -> AttachmentMessageBuilder {
72        if url.trim().len() == 0 {
73            self.build.url = None;
74            self.build.url_title = None;
75            return self;
76        }
77
78        self.build.url = Some(url.to_owned());
79
80        if url_title.is_some() {
81            self.build.url_title = Some(url_title.unwrap().to_owned());
82        }
83
84        self
85    }
86
87    /// Adds an url (and optionally, an url title) to send along with your message.
88    /// 
89    /// If set, the URL title will be shown, otherwise the URL will be shown.
90    #[deprecated(since="0.3.12", note="Please use set_url instead.")]
91    pub fn add_url(mut self, url: &str, url_title: Option<&str>) -> AttachmentMessageBuilder {
92        if url.trim().len() == 0 {
93            self.build.url = None;
94            self.build.url_title = None;
95            return self;
96        }
97
98        self.build.url = Some(url.to_owned());
99
100        if url_title.is_some() {
101            self.build.url_title = Some(url_title.unwrap().to_owned());
102        }
103
104        self
105    }
106
107    /// Removes both the url and url title from your message
108    pub fn remove_url(mut self) -> AttachmentMessageBuilder {
109        self.build.url = None;
110        self.build.url_title = None;
111        self
112    }
113
114    /// Send as -2 to generate no notification/alert, -1 to always send as a quiet notification, 1 to display as high-priority and bypass the user's quiet hours, or 2 to also require confirmation from the user.
115    pub fn set_priority(mut self, priority: i8) -> AttachmentMessageBuilder {
116        if priority < -2 || priority > 2 {
117            self.build.priority = Some("0".into());
118            return self;
119        }
120
121        self.build.priority = Some(priority.to_string());
122        self
123    }
124
125    /// Resets the priority to default (0, normal)
126    pub fn remove_priority(mut self) -> AttachmentMessageBuilder {
127        self.build.priority = Some("0".into());
128        self.build.retry = None;
129        self.build.expire = None;
130        self
131    }
132
133    /// When the priority is set to 2, sets the amount of seconds between each retries. Must be at least 30 seconds.
134    pub fn set_retry(mut self, retry_secs: i32) -> AttachmentMessageBuilder {
135        if self.build.priority != Some("2".into()) {
136            // Retry only makes sense if priority is 2
137            return self;
138        }
139
140        if retry_secs < 30 {
141            self.build.retry = Some("30".into());
142            return self;
143        }
144
145        self.build.retry = Some(retry_secs.to_string());
146        self
147    }
148
149    /// When the priority is set to 2, sets the amount of seconds before the notification is expired. The maximum value is 10800 (3 hours). Must be between 60 and 10800.
150    pub fn set_expire(mut self, expire_secs: i32) -> AttachmentMessageBuilder {
151        if self.build.priority != Some("2".into()) {
152            // Expire only makes sense if priority is 2
153            return self;
154        }
155
156        if expire_secs < 60 {
157            self.build.expire = Some("60".into());
158            return self;
159        }
160        else if expire_secs > 10800 {
161            self.build.expire = Some("10800".into());
162            return self;
163        }
164
165        self.build.expire = Some(expire_secs.to_string());
166        self
167    }
168
169    /// Sets the sound to be used to notify the user.
170    /// 
171    /// See this list of available sounds: https://pushover.net/api#sounds
172    pub fn set_sound(mut self, sound: PushoverSound) -> AttachmentMessageBuilder {
173        self.build.sound = Some(sound.to_string());
174        self
175    }
176
177    /// Removes the custom sound and reverts to the default sound.
178    pub fn remove_sound(mut self) -> AttachmentMessageBuilder {
179        self.build.sound = None;
180        self
181    }
182
183    /// Sets an Unix timestamp of your message's date and time to display to the user, rather than the time your message is received by our API
184    pub fn set_timestamp(mut self, unix_timestamp: u64) -> AttachmentMessageBuilder {
185        self.build.timestamp = Some(unix_timestamp.to_string());
186        self
187    }
188
189    /// Resets the custom unix timestamp
190    pub fn remove_timestamp(mut self) -> AttachmentMessageBuilder {
191        self.build.timestamp = None;
192        self
193    }
194
195    /// Add a device name to send the notification to.
196    ///
197    /// Overrides the current device if a new device name is set.
198    pub fn set_device(mut self, device_name: &str) -> AttachmentMessageBuilder {
199        self.build.device = Some(device_name.to_string());
200        self
201    }
202
203    /// Clears the device if set.
204    pub fn remove_device(mut self) -> AttachmentMessageBuilder {
205        self.build.device = None;
206        self
207    }
208
209    /// Set the TTL (Time to Live), in seconds
210    pub fn set_ttl(mut self, ttl_secs: u32) -> AttachmentMessageBuilder {
211        if ttl_secs <= 0 {
212            self.build.ttl = None;
213        }
214        else {
215            self.build.ttl = Some(ttl_secs);
216        }
217        self
218    }
219
220    /// Add attachment to the message.
221    /// 
222    /// Attachments cannot be larger than 2.5MB.
223    /// 
224    /// Adding an attachment will make the API call blocking.
225    pub fn set_attachment(mut self, attachment_path: String) -> AttachmentMessageBuilder {
226        if attachment_path.trim().len() == 0 {
227            return self;
228        }
229
230        self.build.attachment = attachment_path;
231        self
232    }
233
234    /// Transforms the MessageBuilder into a useable Message
235    pub fn build(mut self) -> Result<AttachmentMessage, Box<dyn std::error::Error>> {
236        if self.build.priority == Some("2".into()) {
237            if self.build.retry.is_none() {
238                self.build.retry = Some("30".into());
239            }
240            if self.build.expire.is_none() {
241                self.build.expire = Some("10800".into());
242            }
243        }
244
245        if self.build.app_token.is_empty() {
246            return Err(Box::new(Error::new(ErrorKind::InvalidInput, "Application token is empty")));
247        }
248
249        if self.build.user_key.is_empty() {
250            return Err(Box::new(Error::new(ErrorKind::InvalidInput, "User key is empty")));
251        }
252
253        if self.build.message.is_empty() {
254            return Err(Box::new(Error::new(ErrorKind::InvalidInput, "Message is empty")));
255        }
256
257        if self.build.attachment.is_empty() {
258            return Err(Box::new(Error::new(ErrorKind::InvalidInput, "Attachment is empty")));
259        }
260
261        // Check if the attachment file path exists
262        if !std::path::Path::new(&self.build.attachment).exists() {
263            return Err(Box::new(Error::new(ErrorKind::InvalidInput, "Attachment file doesn't exist.")));
264        }
265
266        // Check if the attachment file size is less or equal to 2621440 bytes
267        let file_size = std::fs::metadata(&self.build.attachment).unwrap().len();
268        if file_size > constants::PUSHOVER_API_ATTACHMENT_MAX_SIZE_BYTES {
269            return Err(Box::new(Error::new(ErrorKind::InvalidInput, "Attachment file is too large. (> 2621440 bytes)")));
270        }
271
272        Ok(self.build.clone())
273    }
274}