diff options
-rw-r--r-- | README.md | 29 | ||||
-rw-r--r-- | src/actions/ntfy.rs | 85 |
2 files changed, 96 insertions, 18 deletions
@@ -136,31 +136,38 @@ accounts for some reason). This is the best straightforward way to get push notifications on a smartphone. 1. Install the android/iOS app following the relevant links in https://ntfy.sh -2. If you don't run your own ntfy self-hosted server, create an account at - ntfy.sh -3. Open the app, give it the needed permissions and configure your account - credentials -4. Click on the `+` button and create a "topic", preferably named `sentrum` - since that's what will be used by default. +2. Open the app, give it the needed permissions Then you just need to add the relevant configuration: ```toml [[actions]] type = "ntfy" -# Credentials (required if you use a public server like the default one) -credentials.username = "<YOUR USERNAME HERE>" -credentials.password = "<YOUR PASSWORD HERE>" +# +# EVERYTHING BELOW IS OPTIONAL +# +# Credentials (optional, relevant for self-hosted instances or paid reserved topics) +#credentials.username = "<YOUR USERNAME HERE>" +#credentials.password = "<YOUR PASSWORD HERE>" # ntfy server (optional) #url = "https://ntfy.sh" -# notification channel name (optional) -#topic = "sentrum" +# notification channel name (optional, defaults to random string for security) +#topic = "<RANDOM TOPIC NAME>" # Proxy used to connect (optional, defaults to None) #proxy = "socks5://127.0.0.1:9050" # Priority ("max", "high", "default", "low", "min") (optional) #priority = "default" ``` +If you don't set a `topic = `, `sentrum` will auto-generate one for you randomly +(since topic names are kind of like a password for the public default ntfy.sh +server). When you later run `sentrum`, it will print out the topic name it's +using. + +Open the ntfy app, click on the `+` button, create a "topic" and set the same +equal to the one should be the `sentrum` logs. + + ### nostr Get notified by a nostr [NIP04 encrypted diff --git a/src/actions/ntfy.rs b/src/actions/ntfy.rs index badee70..98b630a 100644 --- a/src/actions/ntfy.rs +++ b/src/actions/ntfy.rs @@ -1,15 +1,76 @@ -use super::Action; -use crate::message::MessageConfig; -use crate::message::MessageFormat; -use crate::message::MessageParams; +use std::fs::File; +use std::io::BufReader; +use std::io::Write; +use std::path::PathBuf; + +use anyhow::Context; use anyhow::Result; use async_trait::async_trait; +use log::info; use ntfy::Auth; use ntfy::Dispatcher; use ntfy::Payload; use ntfy::Priority; use ntfy::Url; +use rand::distributions::Alphanumeric; +use rand::thread_rng; +use rand::Rng; use serde::Deserialize; +use serde::Serialize; +use serde_json::from_reader; +use serde_json::to_string; + +use super::Action; +use crate::message::MessageConfig; +use crate::message::MessageFormat; +use crate::message::MessageParams; + +#[derive(Debug, Clone, Deserialize, Serialize)] +struct NtfyData { + topic: String, +} + +fn get_random_topic() -> String { + thread_rng() + .sample_iter(&Alphanumeric) + .take(16) + .map(char::from) + .collect() +} + +impl Default for NtfyData { + fn default() -> Self { + NtfyData { + topic: get_random_topic(), + } + } +} + +fn get_ntfy_data_filepath() -> PathBuf { + dirs::cache_dir() + .unwrap_or(PathBuf::from("cache")) + .join(env!("CARGO_PKG_NAME")) + .join("ntfy.json") +} + +fn get_ntfy_topic() -> Result<String> { + let path = get_ntfy_data_filepath(); + Ok(match File::open(&path) { + Ok(file) => { + let reader = BufReader::new(file); + from_reader(reader) + .with_context(|| format!("cannot read ntfy data from '{}'", path.display())) + } + Err(_) => { + let ntfy_data = NtfyData::default(); + let mut file = File::create(&path)?; + file.write_all(to_string(&ntfy_data)?.as_bytes()) + .with_context(|| format!("could not write ntfy data to '{}'", path.display()))?; + Ok(ntfy_data) + } + }? + .topic) +} #[derive(Deserialize, Debug)] #[serde(remote = "Priority")] @@ -49,8 +110,8 @@ impl NtfyConfig { self.url.as_deref().unwrap_or("https://ntfy.sh") } - pub fn topic(&self) -> &str { - self.topic.as_deref().unwrap_or(env!("CARGO_PKG_NAME")) + pub fn topic(&self) -> Option<&str> { + self.topic.as_deref() } } @@ -71,7 +132,17 @@ impl<'a> NtfyAction<'a> { dispatcher_builder = dispatcher_builder.proxy(proxy); } - let mut payload = Payload::new(ntfy_config.topic()) + let topic = ntfy_config + .topic() + .unwrap_or(&get_ntfy_topic()?) + .to_string(); + info!( + "[ntfy] using topic '{}', connect to {}/{}", + topic, + ntfy_config.url(), + topic + ); + let mut payload = Payload::new(&topic) .markdown(match message_config.format() { MessageFormat::Plain => false, MessageFormat::Markdown => true, |