diff options
Diffstat (limited to 'src/actions.rs')
-rw-r--r-- | src/actions.rs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/actions.rs b/src/actions.rs new file mode 100644 index 0000000..bf78414 --- /dev/null +++ b/src/actions.rs @@ -0,0 +1,121 @@ +use std::fmt; + +use anyhow::Result; +use async_trait::async_trait; +use log::{debug, info, warn}; +use serde::Deserialize; + +use crate::message::MessageConfig; +use crate::message::MessageParams; + +mod command; +#[cfg(feature = "desktop")] +mod desktop_notification; +#[cfg(feature = "email")] +mod email; +#[cfg(feature = "nostr")] +mod nostr; +#[cfg(feature = "ntfy")] +mod ntfy; +#[cfg(feature = "telegram")] +mod telegram; +mod terminal_print; + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "type")] +pub enum AnyActionConfig { + TerminalPrint, + Command(self::command::CommandConfig), + #[cfg(feature = "desktop")] + DesktopNotification, + #[cfg(feature = "ntfy")] + Ntfy(self::ntfy::NtfyConfig), + #[cfg(feature = "email")] + Email(self::email::EmailConfig), + #[cfg(feature = "telegram")] + Telegram(self::telegram::TelegramConfig), + #[cfg(feature = "nostr")] + Nostr(self::nostr::NostrConfig), +} + +impl fmt::Display for AnyActionConfig { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + AnyActionConfig::TerminalPrint => write!(f, "terminal_print"), + AnyActionConfig::Command(_) => write!(f, "command"), + #[cfg(feature = "desktop")] + AnyActionConfig::DesktopNotification => write!(f, "desktop_notification"), + #[cfg(feature = "ntfy")] + AnyActionConfig::Ntfy(_) => write!(f, "ntfy"), + #[cfg(feature = "email")] + AnyActionConfig::Email(_) => write!(f, "email"), + #[cfg(feature = "telegram")] + AnyActionConfig::Telegram(_) => write!(f, "telegram"), + #[cfg(feature = "nostr")] + AnyActionConfig::Nostr(_) => write!(f, "nostr"), + } + } +} + +#[async_trait] +pub trait Action<'a> { + async fn run(&self, params: Option<&MessageParams<'_, '_>>) -> Result<()>; +} + +pub async fn get_action<'a>( + message_config: &'a MessageConfig, + action_config: &'a AnyActionConfig, +) -> Result<Box<dyn Action<'a> + 'a + Sync>> { + Ok(match action_config { + AnyActionConfig::TerminalPrint => Box::new(self::terminal_print::TerminalPrintAction::new( + message_config, + )), + AnyActionConfig::Command(config) => { + Box::new(self::command::CommandAction::new(message_config, config)?) + } + #[cfg(feature = "desktop")] + AnyActionConfig::DesktopNotification => Box::new( + self::desktop_notification::DesktopNotificationAction::new(message_config), + ), + #[cfg(feature = "ntfy")] + AnyActionConfig::Ntfy(config) => { + Box::new(self::ntfy::NtfyAction::new(message_config, config)?) + } + #[cfg(feature = "email")] + AnyActionConfig::Email(config) => { + Box::new(self::email::EmailAction::new(message_config, config)?) + } + #[cfg(feature = "telegram")] + AnyActionConfig::Telegram(config) => { + Box::new(self::telegram::TelegramAction::new(message_config, config)?) + } + #[cfg(feature = "nostr")] + AnyActionConfig::Nostr(config) => { + Box::new(self::nostr::NostrAction::new(message_config, config).await?) + } + }) +} + +pub async fn get_actions<'a>( + message_config: &'a MessageConfig, + actions_config: &'a [AnyActionConfig], +) -> Vec<Box<dyn Action<'a> + 'a + Sync>> { + let mut result: Vec<Box<dyn Action + Sync>> = Default::default(); + + // TODO: parallelize this. It's hard because the result vector needs to be shared. + for action_config in actions_config { + debug!("registering action '{}'", action_config); + match get_action(message_config, action_config).await { + Ok(action) => { + info!("registered action '{}'", action_config); + result.push(action); + } + Err(e) => { + warn!("could not register action '{}': {}", action_config, e); + } + } + } + + result +} |