diff --git a/Cargo.toml b/Cargo.toml index 0b2c6a5..da69529 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,5 +9,6 @@ zbus = "4.4.0" zvariant = "4.2.0" tokio = { version = "1.40.0", features = ["full"] } futures-util = "0.3.30" +serde = "1.0.210" serde_json = "1.0.128" # rson_rs = "0.2.1" \ No newline at end of file diff --git a/src/formats/json.rs b/src/formats/json.rs index 31b5981..086777a 100644 --- a/src/formats/json.rs +++ b/src/formats/json.rs @@ -1,17 +1,54 @@ +// This module deals with converting the notification object into Json format, which might be useful for data exchange use crate::notification::Notification; -use serde_json::{json, Value}; - +use serde_json::{json, Value}; // json!() macro and Value type impl Notification { - // Json format, useful for data exchange - pub fn json(&self) { - // Actions - let actions: Value = if self.actions().is_empty() { - "None".into() + // Actions, as json + pub fn actions_json(&self) -> Value { + if self.actions().is_empty() { + json!({}) // Empty JSON object if no actions } else { - self.actions().into() - }; - json!({"actions": actions}) + serde_json::Value::Object( + // Wrap the map into a serde_json::Value + self.actions() + .iter() + .map(|(id, label)| { + (id.clone(), json!(label)) // Create key-value pairs: id -> label + }) + .collect::>(), // Collect into a serde_json::Map + ) + } } -} \ No newline at end of file + // Hints, as json + pub fn hints_json(&self) -> Value { + if self.hints().is_empty() { + json!({}) // Empty JSON object if no hints + } else { + serde_json::Value::Object( + self.hints() + .iter() + .map(|(key, value)| { + (key.clone(), json!(value.to_string())) // Convert hint value to string + }) + .collect::>(), // Collect into a serde_json::Map + ) + } + } + + // The notification as a json object + pub fn json(&self) -> Value { + json!({ + "app_name": &self.app_name(), + "replace_id": &self.replace_id(), + "icon": &self.icon(), + "summary": &self.summary(), + "body": &self.body(), + "actions": &self.actions_json(), + "hints": &self.hints_json(), + "expiration_timeout": self.expir_timeout(), + "urgency": self.urgency(), + "default_action": self.default_action().map(|actn| actn.0), + }) + } +} diff --git a/src/formats/plain.rs b/src/formats/plain.rs index 703719b..a9d663e 100644 --- a/src/formats/plain.rs +++ b/src/formats/plain.rs @@ -1,3 +1,4 @@ +// This module helps get the notification object in a plain text format, which could be printed to the console or a file use crate::notification::Notification; impl Notification { diff --git a/src/main.rs b/src/main.rs index 97a075c..f53fbcd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ pub mod formats { - pub mod plain; pub mod json; + pub mod plain; } mod notification; use notification::{to_notif, Notification}; @@ -75,7 +75,7 @@ async fn main() -> Result<()> { "GetCapabilities" => { // Client requested server capabilities. Respond with the supported capabilities let capabilities = vec!["actions", "body", "body-hyperlinks"]; // Add more LATER - connection.reply(&msg, &capabili ties).await?; + connection.reply(&msg, &capabilities).await?; println!("Request received: {member}\n\tCapabilities: {capabilities:?}"); // Remove this LATER } @@ -91,6 +91,7 @@ async fn main() -> Result<()> { let notif: Notification = to_notif(&msg_body)?; // Handle the notif println!("New notification!\n{}\n", ¬if.plain()); // Print the plain version + println!("JSON!\n{}\n", ¬if.json()); // Print the plain version } "CloseNotification" => { // Client sent a close signal. Extract notification ID of the notif to be closed from the message body diff --git a/src/notification.rs b/src/notification.rs index a8d541c..6621b1d 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -1,8 +1,10 @@ +use serde::Serialize; use std::collections::HashMap; use zbus::{message::Body, Result}; use zvariant::OwnedValue; // A notificaion object +#[derive(Serialize)] // To help with json pub struct Notification { // The application that sent the notification app_name: String,