diff --git a/Cargo.lock b/Cargo.lock index 08a229b..0ca0962 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,43 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -209,6 +246,7 @@ dependencies = [ name = "fldsmdfr" version = "0.1.0" dependencies = [ + "clap", "tokio", "zbus", ] @@ -272,6 +310,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.2.6" @@ -281,6 +325,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hex" version = "0.4.3" @@ -316,6 +366,18 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "is-terminal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -400,7 +462,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -420,6 +482,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + [[package]] name = "parking_lot" version = "0.12.1" @@ -471,6 +539,30 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.51" @@ -658,6 +750,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "1.0.109" @@ -682,6 +780,15 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.38" @@ -833,6 +940,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index b33ff50..160309e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] +clap = { version = "4.1.8", features = ["derive"] } tokio = { version = "1", features = ["full"] } zbus = { version = "3", default-features = false, features = ["tokio"]} diff --git a/src/daemon.rs b/src/daemon.rs new file mode 100644 index 0000000..dff11ff --- /dev/null +++ b/src/daemon.rs @@ -0,0 +1,87 @@ +use crate::notification::Hints; +use std::collections::HashMap; +use std::error::Error; +use zbus::dbus_interface; +use zbus::Connection; +use crate::notification::Notification; + +pub struct NotifyManager { + next_id: u32, + pendings: HashMap, +} + +impl NotifyManager { + pub fn new() -> NotifyManager { + NotifyManager { + next_id: 1, + pendings: HashMap::new(), + } + } + + pub async fn start(self) -> Result<(), Box> { + let connection = Connection::session().await?; + + connection + .object_server() + .at("/org/freedesktop/Notifications", self) + .await?; + connection + .request_name("org.freedesktop.Notifications") + .await?; + + loop {} + } +} + +#[dbus_interface(name = "org.freedesktop.Notifications")] +impl NotifyManager { + fn notify( + &mut self, + app_name: String, + replaces_id: u32, + app_icon: String, + summary: String, + body: String, + actions: Vec, + hints: Hints, + expire_timeout: i32, + ) -> u32 { + println!("{}: {}", summary, body); + self.pendings.insert( + self.next_id, + Notification { + app_name, + app_icon, + summary, + body, + actions, + hints, + }, + ); + if replaces_id == 0 { + self.next_id += 1; + self.next_id + } else { + replaces_id + } + } + + fn get_capabilities(&self) -> Vec<&str> { + vec![ + "body", + "actions", + "body-images", + "persistence", + "icon-static", + ] + } + + fn get_server_information(&self) -> [&str; 4] { + [ + env!("CARGO_PKG_NAME"), + "zoriya", + env!("CARGO_PKG_VERSION"), + "1.2", + ] + } +} diff --git a/src/main.rs b/src/main.rs index 234966d..d04d84a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,62 +1,40 @@ +mod daemon; +mod notification; + +use clap::{Parser, Subcommand}; +use daemon::NotifyManager; use std::error::Error; -use zbus::{Connection, zvariant::{DeserializeDict, SerializeDict, Type}}; -use zbus::dbus_interface; -struct NotifManager { - next_id: u32, +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Args { + #[command(subcommand)] + command: Command, } -#[derive(DeserializeDict, SerializeDict, Type)] -#[zvariant(signature = "dict")] -struct Hints { - category: Option, - urgency: Option, -} +#[derive(Subcommand)] +enum Command { + /// Run the notification daemon. + Daemon, -#[dbus_interface(name = "org.freedesktop.Notifications")] -impl NotifManager { - fn notify( - &mut self, - app_name: &str, - replaces_id: u32, - app_icon: &str, - summary: &str, - body: &str, - actions: Vec<&str>, - hints: Hints, - expire_timeout: i32, - ) -> u32 { - self.next_id += 1; - println!("{}: {}", summary, body); - self.next_id - } + /// Listen to new notifications. + Listen { + /// Use json instead of plain-text + #[arg(short, long)] + json: bool, - fn get_capabilities(&self) -> Vec<&str> { - vec!["body", "actions", "body-images", "persistence", "icon-static"] - } - - fn get_server_information(&self) -> [&str; 4] { - [ - env!("CARGO_PKG_NAME"), - "zoriya", - env!("CARGO_PKG_VERSION"), - "1.2", - ] - } + /// Print an empty line/json object when the notification should clear. + #[arg(short, long)] + clear: bool, + }, } #[tokio::main] async fn main() -> Result<(), Box> { - let connection = Connection::session().await?; - let manager = NotifManager { next_id: 0 }; + let cli = Args::parse(); - connection - .object_server() - .at("/org/freedesktop/Notifications", manager) - .await?; - connection - .request_name("org.freedesktop.Notifications") - .await?; - - loop {} + match &cli.command { + Command::Daemon => NotifyManager::new().start().await, + Command::Listen { .. } => unimplemented!(), + } } diff --git a/src/notification.rs b/src/notification.rs new file mode 100644 index 0000000..bbdf204 --- /dev/null +++ b/src/notification.rs @@ -0,0 +1,17 @@ +use zbus::zvariant::{DeserializeDict, SerializeDict, Type}; + +pub struct Notification { + pub app_name: String, + pub app_icon: String, + pub summary: String, + pub body: String, + pub actions: Vec, + pub hints: Hints, +} + +#[derive(DeserializeDict, SerializeDict, Type)] +#[zvariant(signature = "dict")] +pub struct Hints { + category: Option, + urgency: Option, +}