diff --git a/Cargo.lock b/Cargo.lock index d2d71a9..8990a1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,6 +143,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atomic-write-file" version = "0.1.2" @@ -172,7 +178,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "http-body-util", - "hyper 1.1.0", + "hyper 1.3.1", "hyper-util", "itoa", "matchit", @@ -256,6 +262,12 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -906,6 +918,7 @@ dependencies = [ "html-escape", "mail-send", "md-5", + "reqwest 0.12.4", "sailfish", "serde", "serde-inline-default", @@ -940,15 +953,15 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.0" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d308f63daf4181410c242d34c11f928dcb3aa105852019e043c9d1f4e4368a" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http 1.0.0", "indexmap", "slab", @@ -1189,21 +1202,23 @@ dependencies = [ [[package]] name = "hyper" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.0", + "h2 0.4.5", "http 1.0.0", "http-body 1.0.0", "httparse", "httpdate", "itoa", "pin-project-lite", + "smallvec", "tokio", + "want", ] [[package]] @@ -1220,20 +1235,38 @@ dependencies = [ ] [[package]] -name = "hyper-util" -version = "0.1.2" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d8d52be92d09acc2e01dddb7fde3ad983fc6489c7db4837e605bc3fca4cb63e" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.0.0", "http-body 1.0.0", - "hyper 1.1.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", + "tower", + "tower-service", "tracing", ] @@ -1314,7 +1347,7 @@ dependencies = [ "socket2", "widestring", "windows-sys 0.48.0", - "winreg", + "winreg 0.50.0", ] [[package]] @@ -1485,7 +1518,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f5982137dccf24ca038daa022eb0ea97a31e9739477445a787a8ef77e015ebb" dependencies = [ - "base64", + "base64 0.21.5", "gethostname", "mail-auth", "mail-builder", @@ -2002,7 +2035,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -2011,7 +2044,7 @@ dependencies = [ "http 0.2.11", "http-body 0.4.6", "hyper 0.14.28", - "hyper-tls", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -2034,7 +2067,49 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.5", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.0.0", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", ] [[package]] @@ -2156,7 +2231,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.5", ] [[package]] @@ -2165,7 +2240,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" dependencies = [ - "base64", + "base64 0.21.5", "rustls-pki-types", ] @@ -2458,9 +2533,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smtp-proto" @@ -2617,7 +2692,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" dependencies = [ "atoi", - "base64", + "base64 0.21.5", "bitflags 2.4.1", "byteorder", "bytes", @@ -2659,7 +2734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" dependencies = [ "atoi", - "base64", + "base64 0.21.5", "bitflags 2.4.1", "byteorder", "crc", @@ -2842,7 +2917,7 @@ dependencies = [ "once_cell", "pin-project", "rc-box", - "reqwest", + "reqwest 0.11.23", "serde", "serde_json", "serde_with_macros", @@ -3584,6 +3659,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index 3145b28..80af66d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,12 +32,13 @@ sqlx = { version = "0.7", features = ["runtime-tokio", "tls-rustls", "any"] } teloxide = { version = "0.12", features = ["macros"], optional = true } mail-send = { version = "0.4", optional = true } tokio-rustls = { version = "0.25", optional = true } +reqwest = { version = "0.12", optional = true } # frontend sailfish = { version = "0.8", optional = true } axum-extra = { version = "0.9", optional = true } [features] -default = ["mysql", "sqlite", "postgres", "telegram", "email", "web"] # all features by default +default = ["mysql", "sqlite", "postgres", "telegram", "email", "web", "ntfy"] # all features by default # db drivers mysql = ["sqlx/mysql"] sqlite = ["sqlx/sqlite"] @@ -45,5 +46,6 @@ postgres = ["sqlx/postgres"] # notifier providers telegram = ["dep:teloxide"] email = ["dep:mail-send", "dep:tokio-rustls"] +ntfy = ["dep:reqwest"] # frontend web = ["dep:sailfish", "dep:axum-extra"] diff --git a/src/config.rs b/src/config.rs index 6ab2a98..14f8211 100644 --- a/src/config.rs +++ b/src/config.rs @@ -117,4 +117,10 @@ pub enum NotifierProvider { to: String, subject: String, }, + + #[cfg(feature = "ntfy")] + Ntfy { + server: String, + topic: String, + } } diff --git a/src/main.rs b/src/main.rs index 0ee8489..f323513 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,7 +141,12 @@ async fn launch() { &server, port, &username, &password, &from, &to, &subject ).await )); + } + #[cfg(feature = "ntfy")] + NotifierProvider::Ntfy { server, topic } => { + tracing::info!("registering ntfy provider on {}/{}", server, topic); + state.register(Box::new(notifications::ntfy::NtfyNotifier::new(server, topic))); } } } diff --git a/src/notifications/mod.rs b/src/notifications/mod.rs index ef7c05e..05e6ab0 100644 --- a/src/notifications/mod.rs +++ b/src/notifications/mod.rs @@ -5,6 +5,9 @@ pub mod telegram; #[cfg(feature = "email")] pub mod email; +#[cfg(feature = "ntfy")] +pub mod ntfy; + pub mod console; diff --git a/src/notifications/ntfy.rs b/src/notifications/ntfy.rs new file mode 100644 index 0000000..d5d0cfa --- /dev/null +++ b/src/notifications/ntfy.rs @@ -0,0 +1,39 @@ +use crate::model::Page; + +use super::NotificationProcessor; + +pub struct NtfyNotifier { + server: String, + topic: String, +} + +impl NtfyNotifier { + pub fn new(server: String, topic: String) -> Self { + NtfyNotifier { server, topic } + } +} + +#[async_trait::async_trait] +impl NotificationProcessor for NtfyNotifier { + async fn process(&self, notification: &Page) { + let author = if let Some(ref contact) = notification.contact { + format!("{} <{}>", notification.author, contact) + } else { + notification.author.clone() + }; + match reqwest::Client::new() + .post(format!("{}/{}", self.server, self.topic)) + .body(notification.body.clone()) + .header("Title", author) + .header("Tags", "computer") + .header("Priority", "low") + .send() + .await + { + Err(e) => tracing::error!("failed sending ntfy event: {e}"), + Ok(res) => if let Err(e) = res.error_for_status() { + tracing::error!("ntfy server rejected event: {e}"); + }, + } + } +}