sxmotify 0.1.1

Create, modify, and delete sxmo notifications
Documentation
use crate::{clear_notification, notification_directory, set_notification};
use std::{fs, io, path};

/// A namespace for sxmo notifications. The namespace is associated with a prefix provided during
/// construction. Any notification additionally has an ID, which has to be unique within the
/// namespace. The nofications are created as files in the form $prefix-$id, so keep both the
/// variables filename-friendly (e.g. by escaping or hashing potentially unsafe IDs), or bad
/// things can happen.
pub struct Namespace {
    prefix: String,
}

impl Namespace {
    /// Create a notification namespace using the provided prefix.
    pub fn new(prefix: String) -> Self {
        Namespace { prefix }
    }

    fn namespaced(&self, id: String) -> String {
        format!("{}-{}", self.prefix, id)
    }

    /// Set the notification with the provided ID. This will override any previous notifications
    /// with that ID.
    pub fn set_notification(
        &self,
        id: String,
        text: String,
        command: String,
        watched_file: Option<&path::Path>,
    ) -> io::Result<()> {
        set_notification(self.namespaced(id), text, command, watched_file)
    }

    /// Clear the notification with a given ID. If successful, it guarantees no notification with
    /// this ID exists anymore.
    pub fn clear_notification(&self, id: String) -> io::Result<()> {
        clear_notification(self.namespaced(id))
    }

    /// Clean up the namespace, removing all notifications within it. Will attempt to remove all
    /// notifications it is able to locate, disregarding errors. Returns only the last error
    /// encountered, sorry.
    pub fn cleanup(self) -> io::Result<()> {
        let Self { prefix } = self;
        fs::read_dir(notification_directory())?
            .filter_map(|f| Some(f.ok()?.path()))
            .filter_map(|f| {
                if f.file_name()?.to_str()?.starts_with(&prefix) {
                    Some(f)
                } else {
                    None
                }
            })
            .fold(Ok(()), |e, f| {
                fs::remove_file(f)?;
                e
            })
    }
}