From 77f996c591cc7a889e7b245af26aa6963e39682a Mon Sep 17 00:00:00 2001 From: rzuasti Date: Fri, 23 Jan 2026 10:25:45 -0500 Subject: [PATCH] Added pushover notification sending --- oott.toml | 7 ++++ sample_oott.toml | 7 ++++ src/events.rs | 72 ++++++++++++++++++++++++++++++++---------- src/events/pushover.rs | 27 ++++++++++++++++ src/main.rs | 4 +-- src/settings.rs | 13 ++++++++ 6 files changed, 111 insertions(+), 19 deletions(-) create mode 100644 src/events/pushover.rs diff --git a/oott.toml b/oott.toml index e73bd01..697eedd 100644 --- a/oott.toml +++ b/oott.toml @@ -4,3 +4,10 @@ level = "info" # off, error, warn, info, debug, trace [timings] arp_sender_timeout="30" arp_scan_duration="60" + +[notifications] +method="pushover" # For now just pushover + +[notifications.pushover] +token="acxa8ouwj5iraswe8pupnpp12kmsm7" # Your pushover token goes here, just copy&paste from their website after creating the app +user_key="u872udy8xc8ceys9ee6iur229xs3fj" # User key goes here, this is the account wide code for pushover diff --git a/sample_oott.toml b/sample_oott.toml index e73bd01..b10c8a4 100644 --- a/sample_oott.toml +++ b/sample_oott.toml @@ -4,3 +4,10 @@ level = "info" # off, error, warn, info, debug, trace [timings] arp_sender_timeout="30" arp_scan_duration="60" + +[notifications] +method="pushover" # For now just pushover, you can set this to "none" to avoid sending notifications (it will just log) + +[notifications.pushover] +token="" # Your pushover token goes here, just copy&paste from their website after creating the app +user_key="" # User key goes here, this is the account wide code for pushover diff --git a/src/events.rs b/src/events.rs index de68e20..078a36f 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,21 +1,59 @@ -use crate::device_finders::Device; -use log::info; +mod pushover; -pub fn trigger_new_device(device: Device) { - info!("Trigger - New device found: {}.", device); +use crate::{device_finders::Device, settings::CONFIG}; +use log::{debug, info, warn}; + +// Private helper function to deliver messages +fn send_message(body: String) -> Result<(), String> { + debug!("About to send notification ({body})."); + + match CONFIG.notifications.method.as_str() { + "pushover" => { + pushover::send_message(body)?; + } + other => { + warn!("Notification method set to '{other}'. Set logs to 'info' to see notifications."); + info!("Notification: {body}"); + } + }; + + Ok(()) } -pub fn trigger_existing_device(existing_device: Device, new_device: Device) { - if existing_device.ipv4_address != new_device.ipv4_address { - info!( - "Trigger - Device with MAC {} changed IPv4 address from {} to {}.", - existing_device.mac_address, existing_device.ipv4_address, new_device.ipv4_address - ); - } - if existing_device.vendor != new_device.vendor { - info!( - "Trigger - Device with MAC {} changed vendor from {} to {}.", - existing_device.mac_address, existing_device.vendor, new_device.vendor - ); - } +pub fn trigger_new_device(device: Device) -> Result<(), String> { + send_message(format!("New device found in your network: {device}"))?; + Ok(()) +} + +pub fn trigger_existing_device(existing_device: Device, new_device: Device) -> Result<(), String> { + if (existing_device.ipv4_address != new_device.ipv4_address) + && (existing_device.vendor != new_device.vendor) + { + send_message(format!( + "Device with MAC {} changed IP address from {} to {} and vendor from {} to {}.", + existing_device.mac_address, + existing_device.ipv4_address, + new_device.ipv4_address, + existing_device.vendor, + new_device.vendor + ))?; + } else if existing_device.ipv4_address != new_device.ipv4_address { + send_message(format!( + "Device with MAC {} ({}) changed IP address from {} to {}.", + existing_device.mac_address, + new_device.vendor, + existing_device.ipv4_address, + new_device.ipv4_address + ))?; + } else if existing_device.vendor != new_device.vendor { + send_message(format!( + "Device with MAC {} ({}) changed vendor from {} to {}.", + existing_device.mac_address, + existing_device.ipv4_address, + existing_device.vendor, + new_device.vendor + ))?; + }; + + Ok(()) } diff --git a/src/events/pushover.rs b/src/events/pushover.rs new file mode 100644 index 0000000..3562ad6 --- /dev/null +++ b/src/events/pushover.rs @@ -0,0 +1,27 @@ +use log::{debug, error}; +use pushover::API; +use pushover::requests::message::SendMessage; + +use crate::settings::CONFIG; + +pub fn send_message(body: String) -> Result<(), String> { + debug!("About to send message via pushover ({body})"); + let api = API::new(); + + let msg = SendMessage::new( + CONFIG.notifications.pushover.token.as_str(), + CONFIG.notifications.pushover.user_key.as_str(), + body, + ); + + match api.send(&msg) { + Ok(_) => { + debug!("Message sent successfully"); + Ok(()) + } + Err(error) => { + error!("Error sending message via pushover: {error}"); + Err(format!("Error sending message via pushover: {error}")) + } + } +} diff --git a/src/main.rs b/src/main.rs index 6ce439c..11a640f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,7 @@ async fn main() -> Result<(), String> { recorded_device, device ); db::devices::update(db_conn_clone.lock().unwrap(), device.clone())?; - events::trigger_existing_device(recorded_device, device.clone()); + events::trigger_existing_device(recorded_device, device.clone()).ok(); // Ignoring errors here, do not stop loop if notification delivery fails } None => { // If it doesn't exist insert it @@ -69,7 +69,7 @@ async fn main() -> Result<(), String> { ); db::devices::insert(db_conn_clone.lock().unwrap(), device.clone())?; - events::trigger_new_device(device.clone()); + events::trigger_new_device(device.clone()).ok(); // Ignoring errors here, do not stop loop if notification delivery fails } }; } diff --git a/src/settings.rs b/src/settings.rs index e41f976..71a90e3 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -16,10 +16,23 @@ pub struct Timings { pub arp_scan_duration: u64, } +#[derive(Debug, Deserialize, Clone)] +pub struct Pushover { + pub token: String, + pub user_key: String, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct Notifications { + pub method: String, + pub pushover: Pushover, +} + #[derive(Debug, Deserialize, Clone)] pub struct Settings { pub log: Log, pub timings: Timings, + pub notifications: Notifications, } // End configuration structure // -----------------------------------------------------------