diff --git a/Cargo.lock b/Cargo.lock index 88c3214..4c3a36c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1749,6 +1749,7 @@ dependencies = [ "serde_json", "surf", "tide", + "urlencoding", ] [[package]] @@ -2591,6 +2592,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8parse" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index e1a5214..e3926c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ futures-util = "0.3.12" lettre = "0.11.7" anyhow = "1.0.86" clap = { version = "4.5.9", features = ["derive"] } +urlencoding = "2.1.3" [dependencies.async-std] version = "*" # Use whatever tide uses. diff --git a/src/mail.rs b/src/mail.rs index 039698c..c1995b8 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -6,6 +6,9 @@ use lettre::message::Mailbox; use lettre::transport::smtp::authentication::Credentials; use lettre::{Message, SmtpTransport, Transport}; use std::env; +use urlencoding::encode; + +use crate::CONFIG; pub fn send_notification( recipient: &str, @@ -25,6 +28,12 @@ pub fn send_notification( body += "This is the last update you will get for this pr.\n\ Thx for using this service\n\ Goodbye"; + } else { + body += &format!( + "Unsubscribe from this PR", + &CONFIG.url, + encode(recipient) + ); } let sending_address = env::var("PR_TRACKER_MAIL_ADDRESS")?; let sending_user = match env::var("PR_TRACKER_MAIL_USER") { diff --git a/src/main.rs b/src/main.rs index 81b8896..ea3c0bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod systemd; mod tree; use std::collections::HashSet; -use std::fs::{remove_dir_all, File}; +use std::fs::{remove_dir_all, remove_file, File}; use std::io::BufReader; use std::path::PathBuf; use std::{ffi::OsString, fs::read_dir}; @@ -40,7 +40,7 @@ use tree::Tree; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] -struct Config { +pub struct Config { #[arg(long)] path: PathBuf, @@ -61,9 +61,12 @@ struct Config { #[arg(long)] email_white_list: Option, + + #[arg(long)] + url: String, } -static CONFIG: Lazy = Lazy::new(Config::parse); +pub static CONFIG: Lazy = Lazy::new(Config::parse); static WHITE_LIST: Lazy> = Lazy::new(|| { use std::io::{BufRead, BufReader}; @@ -225,6 +228,31 @@ async fn update_subscribers(_request: Request) -> http_types::Result(request: Request) -> http_types::Result { + let pr_number = request.query::()?.pr; + let email = request.query::()?.email; + + if let Some(email) = email { + for f in read_dir(CONFIG.data_folder.clone())? { + let dir_path = f?.path(); + let dir_name = dir_path.file_name().and_then(|x| x.to_str()).unwrap(); + if dir_path.is_dir() + && (pr_number.is_none() || pr_number.as_ref().is_some_and(|x| x == dir_name)) + { + match remove_file(dir_path.join(&email)) { + Ok(_) => {} + Err(_) => {} + } + } + } + } + + Ok(Response::builder(200) + .content_type(mime::HTML) + .body("") + .build()) +} + async fn handle_request(request: Request) -> http_types::Result { let mut status = 200; let mut page = PageTemplate { @@ -290,6 +318,7 @@ async fn main() { root.at("/").get(handle_request); root.at("update").get(update_subscribers); + root.at("unsubscribe").get(unsubscribe); let fd_count = handle_error(listen_fds(true), 71, "sd_listen_fds"); diff --git a/templates/page.html b/templates/page.html index feab091..08212e1 100644 --- a/templates/page.html +++ b/templates/page.html @@ -172,17 +172,17 @@ {%- if subscribed -%}
You will be notified be by mail when this PR reaches a new branch
{%- endif -%} + Back to home
+ {{- pr_number -}}" readonly=readonly {%- else -%} " + {%- endmatch -%}> {% match pr_number %} {%- when Some with (pr_number) -%}
- +