sxmotify/
namespace.rs

1use crate::{clear_notification, notification_directory, set_notification};
2use std::{fs, io, path};
3
4/// A namespace for sxmo notifications. The namespace is associated with a prefix provided during
5/// construction. Any notification additionally has an ID, which has to be unique within the
6/// namespace. The nofications are created as files in the form $prefix-$id, so keep both the
7/// variables filename-friendly (e.g. by escaping or hashing potentially unsafe IDs), or bad
8/// things can happen.
9pub struct Namespace {
10    prefix: String,
11}
12
13impl Namespace {
14    /// Create a notification namespace using the provided prefix.
15    pub fn new(prefix: String) -> Self {
16        Namespace { prefix }
17    }
18
19    fn namespaced(&self, id: String) -> String {
20        format!("{}-{}", self.prefix, id)
21    }
22
23    /// Set the notification with the provided ID. This will override any previous notifications
24    /// with that ID.
25    pub fn set_notification(
26        &self,
27        id: String,
28        text: String,
29        command: String,
30        watched_file: Option<&path::Path>,
31    ) -> io::Result<()> {
32        set_notification(self.namespaced(id), text, command, watched_file)
33    }
34
35    /// Clear the notification with a given ID. If successful, it guarantees no notification with
36    /// this ID exists anymore.
37    pub fn clear_notification(&self, id: String) -> io::Result<()> {
38        clear_notification(self.namespaced(id))
39    }
40
41    /// Clean up the namespace, removing all notifications within it. Will attempt to remove all
42    /// notifications it is able to locate, disregarding errors. Returns only the last error
43    /// encountered, sorry.
44    pub fn cleanup(self) -> io::Result<()> {
45        let Self { prefix } = self;
46        fs::read_dir(notification_directory())?
47            .filter_map(|f| Some(f.ok()?.path()))
48            .filter_map(|f| {
49                if f.file_name()?.to_str()?.starts_with(&prefix) {
50                    Some(f)
51                } else {
52                    None
53                }
54            })
55            .fold(Ok(()), |e, f| {
56                fs::remove_file(f)?;
57                e
58            })
59    }
60}