operserv: notify_exclude also mutes #channel masks, so a broad watch can skip specific channels
Some checks failed
CI / check (push) Has been cancelled
Some checks failed
CI / check (push) Has been cancelled
This commit is contained in:
parent
bbdb34aa77
commit
29bedf0358
2 changed files with 16 additions and 7 deletions
|
|
@ -187,14 +187,18 @@ impl Db {
|
||||||
/// channel: a `#`/`&` mask tests the channel name, any other tests the user's
|
/// channel: a `#`/`&` mask tests the channel name, any other tests the user's
|
||||||
/// identity. The engine tests the result for a given event's letter.
|
/// identity. The engine tests the result for a given event's letter.
|
||||||
pub fn notify_flags(&self, target: Option<&echo_api::BanTarget>, chan: Option<&str>) -> String {
|
pub fn notify_flags(&self, target: Option<&echo_api::BanTarget>, chan: Option<&str>) -> String {
|
||||||
// A user on the exclude list (e.g. a `*/*` PyLink relay client) is never
|
// Exclusions come first, same mask grammar as a watch: a `#channel` mask
|
||||||
// matched, so relayed traffic can't flood the staff feed.
|
// mutes events in that channel, any other mask mutes a user (e.g. `*/*` for
|
||||||
if let Some(t) = target {
|
// PyLink relay clients). A match means the event never reaches the feed.
|
||||||
if self.notify_exclude.iter().any(|m| {
|
let excluded = self.notify_exclude.iter().any(|m| {
|
||||||
echo_api::akick_matches(m, t) || (!m.contains(['@', '!']) && glob_match(m, t.nick))
|
if m.starts_with('#') || m.starts_with('&') {
|
||||||
}) {
|
chan.is_some_and(|c| glob_match(m, c))
|
||||||
return String::new();
|
} else {
|
||||||
|
target.is_some_and(|t| echo_api::akick_matches(m, t) || (!m.contains(['@', '!']) && glob_match(m, t.nick)))
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
if excluded {
|
||||||
|
return String::new();
|
||||||
}
|
}
|
||||||
let now = now();
|
let now = now();
|
||||||
let mut flags = String::new();
|
let mut flags = String::new();
|
||||||
|
|
|
||||||
|
|
@ -5384,6 +5384,11 @@ fn notify_flags_match_user_nick_channel_and_expiry() {
|
||||||
db.set_notify_exclude(vec!["*/*".to_string()]);
|
db.set_notify_exclude(vec!["*/*".to_string()]);
|
||||||
assert!(db.notify_flags(Some(&bt("baddie7/fun", "h.example")), None).is_empty(), "relay client excluded from every watch");
|
assert!(db.notify_flags(Some(&bt("baddie7/fun", "h.example")), None).is_empty(), "relay client excluded from every watch");
|
||||||
assert!(db.notify_flags(Some(&bt("baddie7", "h.example")), None).contains('c'), "a normal nick still matches after exclude is set");
|
assert!(db.notify_flags(Some(&bt("baddie7", "h.example")), None).contains('c'), "a normal nick still matches after exclude is set");
|
||||||
|
// A #channel in the exclude list mutes that channel while others still fire —
|
||||||
|
// e.g. watch every channel's joins but skip #staff.
|
||||||
|
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");
|
||||||
db.set_notify_exclude(vec![]);
|
db.set_notify_exclude(vec![]);
|
||||||
// DEL by mask removes just that one.
|
// DEL by mask removes just that one.
|
||||||
assert!(db.notify_del("baddie*!*@*").unwrap());
|
assert!(db.notify_del("baddie*!*@*").unwrap());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue