summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2026-04-26 09:41:03 -0300
committerEuAndreh <eu@euandre.org>2026-04-26 09:41:03 -0300
commit89d992d23218553e84361cbb2d0b0ff18063c675 (patch)
tree109ab78414916d0b8b9bb174e9356cd07064be36 /src
parentAdd PAPOD_PASSWORD authentication via PASS (diff)
downloadpapod-89d992d23218553e84361cbb2d0b0ff18063c675.tar.gz
papod-89d992d23218553e84361cbb2d0b0ff18063c675.tar.xz
Add WHOX support and WHOWAS wildcard masks
WHOX: parse %fields[,token] in WHO command second arg, emit RPL_WHOSPCRPL (354) with fields in canonical order (tcuihsnfdlaor). Add WHOX to ISUPPORT. WHOWAS: support wildcards (* and ?) in target. End-of-WHOWAS reply now uses the matched nick instead of the original mask, matching common IRC server behavior.
Diffstat (limited to 'src')
-rw-r--r--src/papod.clj62
1 files changed, 53 insertions, 9 deletions
diff --git a/src/papod.clj b/src/papod.clj
index 33296eb..82bd7ce 100644
--- a/src/papod.clj
+++ b/src/papod.clj
@@ -994,7 +994,7 @@
" STATUSMSG=@+"
" TARGMAX=KICK:1,LIST:,WHOIS:1,PRIVMSG:4,NAMES:"
" TOPICLEN=390 USERLEN=18"
- " UTF8ONLY"
+ " UTF8ONLY WHOX"
" :are supported by this server"))
(numeric-reply client "422"
":MOTD File is missing")]
@@ -3241,6 +3241,12 @@
mp? (contains?
(or (:caps @client) #{})
"multi-prefix")
+ whox (when-let [arg (second params)]
+ (when (and (string? arg)
+ (string/starts-with? arg "%"))
+ (let [body (subs arg 1)
+ [fs t] (string/split body #"," 2)]
+ {:fields (set fs) :token t})))
who-reply
(fn [chan-name mn m]
(let [ca (:client-atom m)
@@ -3265,11 +3271,33 @@
voc? "+"))
uname (or (:username (:user st)) mn)
rname (or (:realname (:user st)) mn)]
- (numeric-reply client "352"
- (str chan-name " " uname
- " localhost " +server-name+
- " " mn " " flag
- " :0 " rname))))]
+ (if whox
+ (let [fs (:fields whox)
+ parts (cond-> []
+ (fs \t) (conj (or (:token whox) "0"))
+ (fs \c) (conj (or chan-name "*"))
+ (fs \u) (conj uname)
+ (fs \i) (conj "255.255.255.255")
+ (fs \h) (conj "localhost")
+ (fs \s) (conj +server-name+)
+ (fs \n) (conj mn)
+ (fs \f) (conj flag)
+ (fs \d) (conj "0")
+ (fs \l) (conj "0")
+ (fs \a) (conj "0")
+ (fs \o) (conj "0"))
+ base (string/join " " parts)]
+ (numeric-reply client "354"
+ (if (fs \r)
+ (if (seq parts)
+ (str base " :" rname)
+ (str ":" rname))
+ base)))
+ (numeric-reply client "352"
+ (str chan-name " " uname
+ " localhost " +server-name+
+ " " mn " " flag
+ " :0 " rname)))))]
(cond
(nil? target)
[(numeric-reply client "315"
@@ -3407,10 +3435,26 @@
t-lower (string/lower-case target)
hist (when (:whowas components)
@(:whowas components))
+ wild? (some #{\* \?} target)
+ pat (when wild?
+ (re-pattern
+ (str "^"
+ (->> t-lower
+ (map (fn [c]
+ (case c
+ \* ".*"
+ \? "."
+ (java.util.regex.Pattern/quote
+ (str c)))))
+ (apply str))
+ "$")))
matches0 (when hist
(filter
- #(= (string/lower-case (:nick %))
- t-lower)
+ (fn [e]
+ (let [nl (string/lower-case (:nick e))]
+ (if pat
+ (boolean (re-matches pat nl))
+ (= nl t-lower))))
hist))
matches (cond
(or (nil? limit) (zero? limit))
@@ -3433,7 +3477,7 @@
" :papod"))])
matches))
(conj (numeric-reply client "369"
- (str target
+ (str (:nick (first matches))
" :End of WHOWAS"))))
[(numeric-reply client "406"
(str target " :There was no such nickname"))