feat: allow unsubscribing
This commit is contained in:
parent
af7f2b3f55
commit
e7125bb7b2
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -1749,6 +1749,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"surf",
|
"surf",
|
||||||
"tide",
|
"tide",
|
||||||
|
"urlencoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2591,6 +2592,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urlencoding"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|
|
@ -24,6 +24,7 @@ futures-util = "0.3.12"
|
||||||
lettre = "0.11.7"
|
lettre = "0.11.7"
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.86"
|
||||||
clap = { version = "4.5.9", features = ["derive"] }
|
clap = { version = "4.5.9", features = ["derive"] }
|
||||||
|
urlencoding = "2.1.3"
|
||||||
|
|
||||||
[dependencies.async-std]
|
[dependencies.async-std]
|
||||||
version = "*" # Use whatever tide uses.
|
version = "*" # Use whatever tide uses.
|
||||||
|
|
|
@ -6,6 +6,9 @@ use lettre::message::Mailbox;
|
||||||
use lettre::transport::smtp::authentication::Credentials;
|
use lettre::transport::smtp::authentication::Credentials;
|
||||||
use lettre::{Message, SmtpTransport, Transport};
|
use lettre::{Message, SmtpTransport, Transport};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use urlencoding::encode;
|
||||||
|
|
||||||
|
use crate::CONFIG;
|
||||||
|
|
||||||
pub fn send_notification(
|
pub fn send_notification(
|
||||||
recipient: &str,
|
recipient: &str,
|
||||||
|
@ -25,6 +28,12 @@ pub fn send_notification(
|
||||||
body += "This is the last update you will get for this pr.\n\
|
body += "This is the last update you will get for this pr.\n\
|
||||||
Thx for using this service\n\
|
Thx for using this service\n\
|
||||||
Goodbye";
|
Goodbye";
|
||||||
|
} else {
|
||||||
|
body += &format!(
|
||||||
|
"<a href=\"{}/unsubscribe?pr={pr_number}&email={}\">Unsubscribe from this PR</a>",
|
||||||
|
&CONFIG.url,
|
||||||
|
encode(recipient)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let sending_address = env::var("PR_TRACKER_MAIL_ADDRESS")?;
|
let sending_address = env::var("PR_TRACKER_MAIL_ADDRESS")?;
|
||||||
let sending_user = match env::var("PR_TRACKER_MAIL_USER") {
|
let sending_user = match env::var("PR_TRACKER_MAIL_USER") {
|
||||||
|
|
35
src/main.rs
35
src/main.rs
|
@ -10,7 +10,7 @@ mod systemd;
|
||||||
mod tree;
|
mod tree;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
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::io::BufReader;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{ffi::OsString, fs::read_dir};
|
use std::{ffi::OsString, fs::read_dir};
|
||||||
|
@ -40,7 +40,7 @@ use tree::Tree;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
struct Config {
|
pub struct Config {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
|
||||||
|
@ -61,9 +61,12 @@ struct Config {
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
email_white_list: Option<PathBuf>,
|
email_white_list: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
static CONFIG: Lazy<Config> = Lazy::new(Config::parse);
|
pub static CONFIG: Lazy<Config> = Lazy::new(Config::parse);
|
||||||
|
|
||||||
static WHITE_LIST: Lazy<HashSet<String>> = Lazy::new(|| {
|
static WHITE_LIST: Lazy<HashSet<String>> = Lazy::new(|| {
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
|
@ -225,6 +228,31 @@ async fn update_subscribers<S>(_request: Request<S>) -> http_types::Result<Respo
|
||||||
.build())
|
.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn unsubscribe<S>(request: Request<S>) -> http_types::Result<Response> {
|
||||||
|
let pr_number = request.query::<Query>()?.pr;
|
||||||
|
let email = request.query::<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<S>(request: Request<S>) -> http_types::Result<Response> {
|
async fn handle_request<S>(request: Request<S>) -> http_types::Result<Response> {
|
||||||
let mut status = 200;
|
let mut status = 200;
|
||||||
let mut page = PageTemplate {
|
let mut page = PageTemplate {
|
||||||
|
@ -290,6 +318,7 @@ async fn main() {
|
||||||
|
|
||||||
root.at("/").get(handle_request);
|
root.at("/").get(handle_request);
|
||||||
root.at("update").get(update_subscribers);
|
root.at("update").get(update_subscribers);
|
||||||
|
root.at("unsubscribe").get(unsubscribe);
|
||||||
|
|
||||||
let fd_count = handle_error(listen_fds(true), 71, "sd_listen_fds");
|
let fd_count = handle_error(listen_fds(true), 71, "sd_listen_fds");
|
||||||
|
|
||||||
|
|
|
@ -172,13 +172,13 @@
|
||||||
{%- if subscribed -%}
|
{%- if subscribed -%}
|
||||||
<div class="state-subscribed">You will be notified be by mail when this PR reaches a new branch</div>
|
<div class="state-subscribed">You will be notified be by mail when this PR reaches a new branch</div>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
<a href="/">Back to home</a>
|
||||||
<form>
|
<form>
|
||||||
<label for="pr">PR number: </label>
|
<label for="pr">PR number: </label>
|
||||||
<input id="pr" name="pr" type="text" pattern="[1-9][0-9]*" value="{%- match pr_number -%}
|
<input id="pr" name="pr" type="text" pattern="[1-9][0-9]*" value="{%- match pr_number -%}
|
||||||
{%- when Some with (pr_number) -%}
|
{%- when Some with (pr_number) -%}
|
||||||
{{- pr_number -}}
|
{{- pr_number -}}" readonly=readonly {%- else -%} "
|
||||||
{%- else -%}
|
{%- endmatch -%}>
|
||||||
{%- endmatch -%}">
|
|
||||||
{% match pr_number %}
|
{% match pr_number %}
|
||||||
{%- when Some with (pr_number) -%}
|
{%- when Some with (pr_number) -%}
|
||||||
<br>
|
<br>
|
||||||
|
|
Loading…
Reference in a new issue