use std::collections::HashMap; use std::future::pending; use std::path::PathBuf; use canary_magpie::protocol::*; use canary_notifications::Contents; use smol::net::unix::UnixStream; use zbus::{dbus_interface, zvariant::Value, ConnectionBuilder, SignalContext}; pub type MagpieClient = ClientMessenger; pub struct Notifications { module_path: PathBuf, magpie: MagpieClient, next_id: u32, } #[dbus_interface(name = "org.freedesktop.Notifications")] impl Notifications { fn get_capabilities(&self) -> Vec { vec!["body", "body-markup", "actions", "icon-static"] .into_iter() .map(ToString::to_string) .collect() } #[dbus_interface(out_args("name", "vendor", "version", "spec_version"))] fn get_server_information(&self) -> zbus::fdo::Result<(String, String, String, String)> { Ok(( "canary-notifications".to_string(), "Canary Development Team".to_string(), "0.1.0".to_string(), "1.2".to_string(), )) } async fn notify( &mut self, app_name: String, replaces_id: u32, app_icon: String, summary: String, body: String, actions: Vec, hints: HashMap>, timeout: i32, ) -> u32 { let contents = Contents { app_name: Some(app_name).filter(String::is_empty), summary, body: Some(body).filter(String::is_empty), timeout: Some(timeout).filter(|t| *t == 0), }; let id = self.next_id; self.next_id += 1; let msg = CreatePanel { id, protocol: "tebibyte-media.desktop.notification".to_string(), script: self.module_path.to_owned(), init_msg: serde_json::to_vec(&contents).unwrap(), }; self.magpie .send_async(&MagpieServerMsg::CreatePanel(msg)) .await .unwrap(); id } fn close_notification(&self, id: u32) {} #[dbus_interface(signal)] async fn notification_closed(ctx: &SignalContext<'_>, id: u32, reason: u32) -> zbus::Result<()>; #[dbus_interface(signal)] async fn action_invoked( ctx: &SignalContext<'_>, id: u32, action_key: String, ) -> zbus::Result<()>; } pub fn main() { let args: Vec = std::env::args().collect(); let module_path = args .get(1) .expect("Please pass a path to a Canary script!") .to_owned() .into(); smol::block_on(async { let sock_path = find_socket(); let socket = UnixStream::connect(sock_path).await.unwrap(); let magpie = MagpieClient::new(socket); let notifications = Notifications { magpie, next_id: 0, module_path, }; let _ = ConnectionBuilder::session() .unwrap() .name("org.freedesktop.Notifications") .unwrap() .serve_at("/org/freedesktop/Notifications", notifications) .unwrap() .build() .await .unwrap(); pending::<()>().await; }); }