diff options
| author | EuAndreh <eu@euandre.org> | 2026-04-26 20:38:06 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2026-04-26 20:38:06 -0300 |
| commit | 5a9f800c604b5d59bf71bd077be1c5434cee1715 (patch) | |
| tree | 3073c43e9418c5658836074c777b967af501f8d6 /src/papod.clj | |
| parent | Reject non-UTF-8 messages with FAIL INVALID_UTF8 (diff) | |
| download | papod-5a9f800c604b5d59bf71bd077be1c5434cee1715.tar.gz papod-5a9f800c604b5d59bf71bd077be1c5434cee1715.tar.xz | |
Implement +b channel ban mode with glob mask matching
- Track per-channel ban masks in :chan-bans atom
- MODE +b <mask> adds, -b removes (case-insensitive)
- MODE +b without mask returns RPL_BANLIST + RPL_ENDOFBANLIST
- JOIN checks ban list and returns ERR_BANNEDFROMCHAN (474)
- Update CHANMODES isupport to b,k,l,nt
Diffstat (limited to 'src/papod.clj')
| -rw-r--r-- | src/papod.clj | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/src/papod.clj b/src/papod.clj index 316b65a..8e1851c 100644 --- a/src/papod.clj +++ b/src/papod.clj @@ -1064,7 +1064,7 @@ (numeric-reply client "005" (str "AWAYLEN=200 CASEMAPPING=ascii" " CHANLIMIT=#:100" - " CHANMODES=,,l,nt" + " CHANMODES=b,k,l,nt" " CHANNELLEN=64 CHANTYPES=#" " ELIST= HOSTLEN=64" " KICKLEN=300 MAXLIST=b:50" @@ -2236,6 +2236,34 @@ (get @(:chan-modes components) handle)) "+nt")) +(defn- glob-pattern + [^String mask] + (re-pattern + (str "^" + (->> mask + (map (fn [c] + (case c + \* ".*" + \? "." + (java.util.regex.Pattern/quote + (str c))))) + (apply str)) + "$"))) + +(defn- nuh-mask + [nick] + (str nick "!" nick "@localhost")) + +(defn- ban-matches? + [bans nick] + (let [nuh (nuh-mask nick)] + (some (fn [mask] + (boolean + (re-matches (glob-pattern + (string/lower-case mask)) + (string/lower-case nuh)))) + bans))) + (defn- chan-symbol [components handle] (let [m (chan-modes-for components handle)] @@ -2304,6 +2332,16 @@ (str handle " :Cannot join channel (+l)"))] + ;; +b: banned + (and existing? + (not (contains? (get @channels handle) nick)) + (let [bans-atom (:chan-bans components) + bans (when bans-atom + (get @bans-atom handle #{}))] + (and (seq bans) (ban-matches? bans nick)))) + [(numeric-reply client "474" + (str handle " :Cannot join channel (+b)"))] + :else (let [db (when conn (d/db conn)) channel-eid (when db (resolve-channel db handle)) @@ -3811,10 +3849,41 @@ (:w m) line))) []))) + ;; +b/-b with mask: add/remove ban + (and (= \b mode-char) mode-arg) + (let [bans-atom (:chan-bans components) + mask mode-arg + mask-key (string/lower-case mask) + line (str ":" nick " MODE " target + " " mode-str " " mask)] + (when bans-atom + (if adding? + (swap! bans-atom update target + (fnil conj #{}) mask-key) + (swap! bans-atom update target + (fnil disj #{}) mask-key))) + (when (and clients channels) + (doseq [mn (get @channels target) + :let [m (get @clients mn)] + :when m] + (deliver-to-client! (:w m) line))) + []) + ;; +b: ban list query (and (= \b mode-char) (nil? mode-arg)) - [(numeric-reply client "368" - (str target " :End of channel ban list"))] + (let [bans-atom (:chan-bans components) + cur-bans (when bans-atom + (get @bans-atom target #{}))] + (concat + (mapv (fn [mask] + (numeric-reply client "367" + (str target " " mask " " nick + " " (quot + (System/currentTimeMillis) + 1000)))) + (sort cur-bans)) + [(numeric-reply client "368" + (str target " :End of channel ban list"))])) :else [])))) @@ -4495,6 +4564,7 @@ :chan-modes (atom {}) :chan-keys (atom {}) :chan-limits (atom {}) + :chan-bans (atom {}) :invites (atom {}) :whowas (atom []) :max-users (atom 0) |
