Send ntfy notifications
This commit is contained in:
parent
77a72329a8
commit
bdcc0def42
10 changed files with 289 additions and 44 deletions
2
src/notifications/mod.rs
Normal file
2
src/notifications/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod notification;
|
||||
pub mod ntfy;
|
||||
31
src/notifications/notification.rs
Normal file
31
src/notifications/notification.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use crate::actions::action::ProcessedMagnets;
|
||||
use async_trait::async_trait;
|
||||
use color_eyre::eyre::Result;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Trait for notification services
|
||||
#[async_trait]
|
||||
pub trait Notification {
|
||||
/// Return the name of the notification service
|
||||
fn name(&self) -> &str;
|
||||
|
||||
/// Send a notification about the processing results
|
||||
async fn send_notification(
|
||||
&self,
|
||||
action_results: &HashMap<String, ProcessedMagnets>,
|
||||
total_new_links: usize,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Determine if a notification should be sent based on the results
|
||||
fn should_notify(
|
||||
&self,
|
||||
action_results: &HashMap<String, ProcessedMagnets>,
|
||||
total_new_links: usize,
|
||||
) -> bool {
|
||||
// Don't send notification if everything was successful but 0 links were grabbed and processed
|
||||
if total_new_links == 0 && action_results.values().all(|pm| pm.failed.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
23
src/notifications/ntfy/config.rs
Normal file
23
src/notifications/ntfy/config.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Configuration for the ntfy notification service
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct NtfyConfig {
|
||||
/// Whether to enable the ntfy notification service
|
||||
#[serde(default)]
|
||||
pub enable: bool,
|
||||
|
||||
/// The host URL of the ntfy server
|
||||
pub host: String,
|
||||
|
||||
/// The username for authentication (optional)
|
||||
#[serde(default)]
|
||||
pub username: Option<String>,
|
||||
|
||||
/// The password for authentication (optional)
|
||||
#[serde(default)]
|
||||
pub password: Option<String>,
|
||||
|
||||
/// The topic to publish notifications to
|
||||
pub topic: String,
|
||||
}
|
||||
5
src/notifications/ntfy/mod.rs
Normal file
5
src/notifications/ntfy/mod.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
pub mod config;
|
||||
pub mod notification;
|
||||
|
||||
pub use config::NtfyConfig;
|
||||
pub use notification::NtfyNotification;
|
||||
68
src/notifications/ntfy/notification.rs
Normal file
68
src/notifications/ntfy/notification.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
use crate::actions::action::ProcessedMagnets;
|
||||
use crate::notifications::notification::Notification;
|
||||
use crate::notifications::ntfy::config::NtfyConfig;
|
||||
use crate::report;
|
||||
use async_trait::async_trait;
|
||||
use color_eyre::eyre::Result;
|
||||
use log::{debug, info};
|
||||
use ntfy::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Notification service using ntfy
|
||||
pub struct NtfyNotification {
|
||||
config: NtfyConfig,
|
||||
client: Dispatcher<Async>,
|
||||
}
|
||||
|
||||
impl NtfyNotification {
|
||||
/// Create a new NtfyNotification instance
|
||||
pub fn new(config: NtfyConfig) -> Result<Self> {
|
||||
let mut builder = dispatcher::builder(config.host.clone());
|
||||
|
||||
// Add authentication if provided
|
||||
if let (Some(username), Some(password)) = (&config.username, &config.password) {
|
||||
builder = builder.credentials(Auth::credentials(username, password))
|
||||
}
|
||||
|
||||
let client = builder.build_async()?;
|
||||
|
||||
Ok(NtfyNotification { config, client })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Notification for NtfyNotification {
|
||||
fn name(&self) -> &str {
|
||||
"Ntfy"
|
||||
}
|
||||
|
||||
async fn send_notification(
|
||||
&self,
|
||||
action_results: &HashMap<String, ProcessedMagnets>,
|
||||
total_new_links: usize,
|
||||
) -> Result<()> {
|
||||
if !self.should_notify(action_results, total_new_links) {
|
||||
debug!("Skipping notification as there's nothing to report");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let priority = if action_results.values().any(|pm| !pm.failed.is_empty()) {
|
||||
Priority::High
|
||||
} else {
|
||||
Priority::Default
|
||||
};
|
||||
|
||||
let payload = Payload::new(&self.config.topic)
|
||||
.message(report::generate_report(
|
||||
action_results,
|
||||
total_new_links,
|
||||
false,
|
||||
))
|
||||
.priority(priority);
|
||||
|
||||
self.client.send(&payload).await?;
|
||||
|
||||
info!("Sent notification to ntfy topic: {}", self.config.topic);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue