operserv: notify_exclude gains server:<glob> to mute a whole relay server from the feed
All checks were successful
CI / check (push) Successful in 4m1s

This commit is contained in:
Jean Chevronnet 2026-07-18 17:35:04 +00:00
parent 4d327c3f47
commit 4247df8844
No known key found for this signature in database
4 changed files with 24 additions and 11 deletions

View file

@ -191,7 +191,11 @@ impl Db {
// mutes events in that channel, any other mask mutes a user (e.g. `*/*` for
// PyLink relay clients). A match means the event never reaches the feed.
let excluded = self.notify_exclude.iter().any(|m| {
if m.starts_with('#') || m.starts_with('&') {
if let Some(srv) = m.strip_prefix("server:").or_else(|| m.strip_prefix("via:")) {
// `server:<glob>` mutes everyone on a matching server — the only handle
// on a relay whose users carry clean nicks (no /network suffix).
target.is_some_and(|t| glob_match(&srv.to_ascii_lowercase(), &t.server.to_ascii_lowercase()))
} else if m.starts_with('#') || m.starts_with('&') {
chan.is_some_and(|c| glob_match(m, c))
} else {
target.is_some_and(|t| echo_api::akick_matches(m, t) || (!m.contains(['@', '!']) && glob_match(m, t.nick)))

View file

@ -5389,6 +5389,12 @@ fn notify_flags_match_user_nick_channel_and_expiry() {
db.set_notify_exclude(vec!["#staff".to_string()]);
assert!(db.notify_flags(Some(&bt("nice", "h.example")), Some("#staff")).is_empty(), "excluded channel is muted");
assert!(db.notify_flags(Some(&bt("nice", "h.example")), Some("#warez7")).contains('j'), "other channels still watched");
// `server:<glob>` mutes everyone on a matching server — a relay whose users have
// clean nicks. bt() puts users on server "s.net".
db.set_notify_exclude(vec!["server:s.net".to_string()]);
assert!(db.notify_flags(Some(&bt("relayed", "h.example")), Some("#warez7")).is_empty(), "user on the excluded server is muted");
db.set_notify_exclude(vec!["via:other.net".to_string()]);
assert!(db.notify_flags(Some(&bt("relayed", "h.example")), Some("#warez7")).contains('j'), "user on a different server still watched");
db.set_notify_exclude(vec![]);
// DEL by mask removes just that one.
assert!(db.notify_del("baddie*!*@*").unwrap());