unraid_notification/
notifier.rs

1use std::{ffi::OsStr, fmt::Display, path::Path, process::Command};
2
3use crate::{
4    notificationlevel::NotificationLevel, unraidnotifiererror::UnraidNotifierError,
5    verifypath::VerifyPath,
6};
7
8// Function to send anything to the wegGui.
9pub fn send<S, M, N>(
10    message: M,
11    level: NotificationLevel,
12    sender: N,
13    path: &S,
14) -> Result<(), UnraidNotifierError>
15where
16    S: AsRef<OsStr> + VerifyPath,
17    M: Display,
18    N: Display,
19{
20    let icon = level.icon();
21    path.verify_path()?;
22
23    if let Err(err) = Command::new(path)
24        .arg("-e")
25        .arg(sender.to_string())
26        .arg("-s")
27        .arg(level.to_levelname())
28        .arg("-d")
29        .arg(message.to_string())
30        .arg("-i")
31        .arg(icon)
32        .spawn()
33    {
34        Err(UnraidNotifierError::IOError(err))
35    } else {
36        Ok(())
37    }
38}
39
40// Used as an interface to implement
41pub trait Notifier<M: Display> {
42    fn send(&self, message: M, level: NotificationLevel) -> Result<(), UnraidNotifierError>;
43}
44
45/// The 'UnraidNotifier' struct is responsible for sending notifications.
46///
47/// The sender is the name displayed as by the unraid webgui.
48#[derive(Debug, Clone)]
49pub struct UnraidNotifier<S, M>
50where
51    S: AsRef<OsStr> + VerifyPath,
52    M: Display,
53{
54    notify_cmd_path: S,
55    sender: M,
56}
57
58impl<S, M> UnraidNotifier<S, M>
59where
60    S: AsRef<OsStr> + VerifyPath,
61    M: Display,
62{
63    /// Creates a new UnraidNotifier with the specified path and sender.
64    ///
65    /// # Arguments
66    ///    
67    /// - `notify_cmd_path`: The path to the notification command.
68    /// - `sender`: The sender of the notification.
69    ///
70    /// # Errors
71    ///
72    /// Returns an 'UnraidNotifierError' if the path verification fails.
73    pub fn new(notify_cmd_path: S, sender: M) -> Result<Self, UnraidNotifierError> {
74        notify_cmd_path.verify_path()?;
75
76        Ok(Self {
77            notify_cmd_path,
78            sender,
79        })
80    }
81    /// Consumes the notifier, and returns one with a new path.
82    pub fn with_path<A: Into<S>>(self, path: A) -> Self {
83        Self {
84            notify_cmd_path: path.into(),
85            ..self
86        }
87    }
88    /// Consumes the notifier, and returns one with a new sender.
89    pub fn with_sender<A: Into<M>>(self, sender: A) -> Self {
90        Self {
91            sender: sender.into(),
92            ..self
93        }
94    }
95    /// Modifies the path of notifier.
96    ///
97    /// # Errors
98    ///
99    /// Returns an 'UnraidNotifierError' if the path verification fails.
100    pub fn modify_path<A: Into<S>>(&mut self, path: A) -> Result<(), UnraidNotifierError> {
101        let path = path.into();
102        path.verify_path()?;
103        self.notify_cmd_path = path;
104        Ok(())
105    }
106    /// Modifies the sender of the notifier.
107    pub fn modify_sender<A: Into<M>>(&mut self, sender: A) {
108        let sender = sender.into();
109        self.sender = sender;
110    }
111}
112
113impl<S, M> Notifier<M> for UnraidNotifier<S, M>
114where
115    S: AsRef<OsStr> + VerifyPath,
116    M: Display,
117{
118    fn send(&self, message: M, level: NotificationLevel) -> Result<(), UnraidNotifierError> {
119        send(message, level, &self.sender, &self.notify_cmd_path)
120    }
121}
122
123static DEFAULT_CMD_PATH: &str = "/usr/local/emhttp/webGui/scripts/notify";
124
125// Implement Default for UnraidNotifier<PathBuf, String>
126impl Default for UnraidNotifier<&Path, String> {
127    fn default() -> Self {
128        Self {
129            sender: "rust-unraid-notifier".into(),
130            notify_cmd_path: Path::new(DEFAULT_CMD_PATH),
131        }
132    }
133}
134
135// Implement Default for UnraidNotifier<PathBuf, &str>
136impl Default for UnraidNotifier<&Path, &str> {
137    fn default() -> Self {
138        Self {
139            sender: "rust-unraid-notifier",
140            notify_cmd_path: Path::new(DEFAULT_CMD_PATH),
141        }
142    }
143}