feat: notify: link to new comment

This commit is contained in:
Pascal Engélibert 2022-12-04 14:51:18 +01:00
parent aec876233d
commit 17e61b8a67
Signed by: tuxmain
GPG key ID: 3504BC6D362F7DCA
5 changed files with 48 additions and 9 deletions

1
Cargo.lock generated
View file

@ -3359,6 +3359,7 @@ dependencies = [
"intl-memoizer", "intl-memoizer",
"log", "log",
"matrix-sdk", "matrix-sdk",
"percent-encoding",
"petname", "petname",
"rand 0.8.5", "rand 0.8.5",
"rand_core 0.6.4", "rand_core 0.6.4",

View file

@ -18,6 +18,7 @@ fluent-langneg = "0.13.0"
intl-memoizer = "0.5.1" intl-memoizer = "0.5.1"
log = "0.4.17" log = "0.4.17"
matrix-sdk = { version = "0.6.2", default-features = false, features = ["rustls-tls"] } matrix-sdk = { version = "0.6.2", default-features = false, features = ["rustls-tls"] }
percent-encoding = "2.2.0"
petname = { version = "1.1.3", optional = true, default-features = false, features = ["std_rng", "default_dictionary"] } petname = { version = "1.1.3", optional = true, default-features = false, features = ["std_rng", "default_dictionary"] }
rand = "0.8.5" rand = "0.8.5"
rand_core = { version = "0.6.4", features = ["std"] } rand_core = { version = "0.6.4", features = ["std"] }

View file

@ -55,10 +55,17 @@ pub struct Config {
pub matrix_server: String, pub matrix_server: String,
#[serde(default = "Config::default_matrix_user")] #[serde(default = "Config::default_matrix_user")]
pub matrix_user: String, pub matrix_user: String,
/// Our address, with protocol and hostname but without path or trailing `/`
/// It is used to make hyperlinks that should be clickable from anywhere.
#[serde(default = "Config::default_public_address")]
pub public_address: String,
/// Are we behind a reverse proxy? /// Are we behind a reverse proxy?
/// Determines whether we assume client address is in a Forwarded header or socket address. /// Determines whether we assume client address is in a Forwarded header or socket address.
#[serde(default = "Config::default_reverse_proxy")] #[serde(default = "Config::default_reverse_proxy")]
pub reverse_proxy: bool, pub reverse_proxy: bool,
/// Our root url path (without protocol and hostname)
/// Useful when used behind a reverse proxy in a pseudo-subdirectory.
/// Should start and end with `/`.
#[serde(default = "Config::default_root_url")] #[serde(default = "Config::default_root_url")]
pub root_url: String, pub root_url: String,
/// Templates directory. May be absolute or relative to config/data directory. /// Templates directory. May be absolute or relative to config/data directory.
@ -127,6 +134,9 @@ impl Config {
fn default_matrix_user() -> String { fn default_matrix_user() -> String {
"@tuxmain:matrix.txmn.tk".into() "@tuxmain:matrix.txmn.tk".into()
} }
fn default_public_address() -> String {
"http://127.0.0.1:31720".into()
}
fn default_reverse_proxy() -> bool { fn default_reverse_proxy() -> bool {
false false
} }
@ -161,6 +171,7 @@ impl Default for Config {
matrix_room: Self::default_matrix_room(), matrix_room: Self::default_matrix_room(),
matrix_server: Self::default_matrix_server(), matrix_server: Self::default_matrix_server(),
matrix_user: Self::default_matrix_user(), matrix_user: Self::default_matrix_user(),
public_address: Self::default_public_address(),
reverse_proxy: Self::default_reverse_proxy(), reverse_proxy: Self::default_reverse_proxy(),
root_url: Self::default_root_url(), root_url: Self::default_root_url(),
templates_dir: Self::default_templates_dir(), templates_dir: Self::default_templates_dir(),

View file

@ -5,6 +5,10 @@ use log::error;
use matrix_sdk::ruma; use matrix_sdk::ruma;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
pub struct Notification {
pub topic: String,
}
enum OptionSince<T> { enum OptionSince<T> {
Some(T), Some(T),
NoneSince(SystemTime), NoneSince(SystemTime),
@ -48,14 +52,30 @@ impl Notifier {
} }
} }
async fn notify(&mut self, config: &Config) { async fn notify(&mut self, config: &Config, notification: Notification) {
match &self.matrix { match &self.matrix {
None => {} None => {}
Some(OptionSince::Some((_client, room))) => { Some(OptionSince::Some((_client, room))) => {
let decoded_topic = tera::escape_html(
&percent_encoding::percent_decode_str(&notification.topic).decode_utf8_lossy(),
);
if let Err(e) = room if let Err(e) = room
.send( .send(
ruma::events::room::message::RoomMessageEventContent::text_plain( ruma::events::room::message::RoomMessageEventContent::text_html(
"New comment.", format!(
"New comment on topic \"{}\": {}{}t/{}",
decoded_topic,
config.public_address,
config.root_url,
notification.topic,
),
format!(
"<a href=\"{}{}t/{}\">New comment on topic \"<em>{}</em>\".</a>",
config.public_address,
config.root_url,
notification.topic,
decoded_topic,
),
), ),
None, None,
) )
@ -77,10 +97,10 @@ impl Notifier {
} }
} }
pub async fn run_notifier(config: &Config, recv: Receiver<()>) { pub async fn run_notifier(config: &Config, recv: Receiver<Notification>) {
let mut notifier = Notifier::new(config).await; let mut notifier = Notifier::new(config).await;
for () in recv { for notification in recv {
notifier.notify(config).await; notifier.notify(config, notification).await;
} }
} }

View file

@ -1,6 +1,8 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use crate::{config::*, db::*, helpers, locales::*, queries::*, templates::*}; use crate::{
config::*, db::*, helpers, locales::*, notify::Notification, queries::*, templates::*,
};
use argon2::{Argon2, PasswordHash, PasswordVerifier}; use argon2::{Argon2, PasswordHash, PasswordVerifier};
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
@ -247,7 +249,7 @@ async fn handle_post_comments(
templates: &Templates, templates: &Templates,
dbs: Dbs, dbs: Dbs,
locales: &Locales, locales: &Locales,
notify_send: Sender<()>, notify_send: Sender<Notification>,
) -> tide::Result<tide::Response> { ) -> tide::Result<tide::Response> {
let admin = req.cookie("admin").map_or(false, |psw| { let admin = req.cookie("admin").map_or(false, |psw| {
check_admin_password_hash(config, &String::from(psw.value())) check_admin_password_hash(config, &String::from(psw.value()))
@ -339,7 +341,11 @@ async fn handle_post_comments(
helpers::new_pending_comment(&comment, &dbs) helpers::new_pending_comment(&comment, &dbs)
.map_err(|e| error!("Adding pending comment: {:?}", e)) .map_err(|e| error!("Adding pending comment: {:?}", e))
.ok(); .ok();
notify_send.send(()).ok(); notify_send
.send(Notification {
topic: topic.to_string(),
})
.ok();
} else { } else {
context.insert("new_comment_author", &query.comment.author); context.insert("new_comment_author", &query.comment.author);
context.insert("new_comment_email", &query.comment.email); context.insert("new_comment_email", &query.comment.email);