use std::collections::HashMap; use std::fmt; use dbus::blocking::{Connection, Message, MessageType, Sender}; use dbus::message::{MatchRule, MessageType::MethodCall}; use dbus::prelude::*; // Structure of a notification struct Notif { app_name: String, replace_id: Option, ico: String, summary: String, body: String, actions: Vec<(String, String)>, hints: HashMap, expir_timeout: Option, } // Function to print the contents of the notification impl fmt::Display for Notif { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "AppName: {}", &self.app_name)?; match self.replace_id { Some(notif_id) => writeln!(f, "ReplaceId: {notif_id}")?, None => writeln!(f, "None")?, } write!( f, "Icon: {}\nSummary: {}\nBody: {}\nActions:\n", &self.ico, &self.summary, &self.body )?; for (key, label) in &self.actions { writeln!(f, "\t{key}: {label}")?; } writeln!(f, "Hints:")?; for (key, value) in &self.hints { writeln!(f, "\t{key}: {value}")?; } match self.expir_timeout { Some(millisec) => writeln!(f, "Expiration Timeout: {millisec}")?, None => writeln!(f, "None")?, } Ok(()) // Return Ok to indicate success } } // Summary should be generally <= 40 chars, as per the specification. fn truncate_summary(notif: &mut Notif) { if notif.summary.len() > 40 { notif.summary.truncate(39); notif.summary.push('…'); } } // Callback function fn handle_notification_added(message: Message) { if message.get_type() == MessageType::Signal { let signal_name = message.get_signature().unwrap(); if signal_name == "notification_added" { let (id, app_name, icon, summary, body, actions, hints, timeout) = message.get_arguments::<(u32, String, String, String, String, Vec, HashMap, i32)>().unwrap(); let notif = Notif { app_name, replace_id: Some(id), // Assuming you want to use the ID for replacement ico: icon, summary, body, actions: actions.iter().map(|(key, value)| (key.clone(), value.clone())).collect(), hints: hints.iter().map(|(key, value)| (key.clone(), value.to_string())).collect(), expir_timeout: if timeout < 0 { None } else { Some(timeout as u32) }, }; // Print or process the notification object println!("{notification}"); } } } fn main() -> Result<(), dbus::Error> { /* // Example notif let mut not = Notif { app_name: "snot".to_string(), replace_id: Some(0), ico: "alert.png".to_string(), summary: "This is a very long suuummmaaarrryyy! Don't you believe me????".to_string(), body: "short body(hehe)".to_string(), actions: vec![ ("reply".to_string(), "Reply".to_string()), ("close".to_string(), "Close".to_string()), ], hints: HashMap::new(), // Create an empty HashMap for hints, add the hints later expir_timeout: Some(0), }; not.hints .insert("urgency".to_string(), "critical".to_string()); not.hints .insert("category".to_string(), "network.error".to_string()); // End of eg. notif truncate_summary(&mut not); //Limit the summary length */ // Connect to the system bus let conn = Connection::new_session()?; // Get the object path of the notification service let object_path = "/org/freedesktop/Notifications"; // Get the interface name of the notification service let interface_name = "org.freedesktop.Notifications"; // Subscribe to the "handle_notification_added" signal let match_rule = MatchRule::new_for_signal(object_path, interface_name, "handle_notification_added"); conn.add_match(match_rule)?; // Create a sender to send messages let sender = conn.sender(object_path, interface_name)?; // Add the callback to the connection conn.add_signal_handler(handle_notification_added)?; // Wait for signals conn.process_incoming(None)?; //println!("{not}"); Ok(()) }