summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2026-04-30 09:02:20 -0300
committerEuAndreh <eu@euandre.org>2026-04-30 09:02:20 -0300
commit8c89f3f9b83faaebe7bf356ccd086f12ef24739c (patch)
tree76945e64cc90995416e91bc9172fdc288f68dc83 /src
parentImplement draft/metadata-2 before-connect optional behavior (diff)
downloadpapod-8c89f3f9b83faaebe7bf356ccd086f12ef24739c.tar.gz
papod-8c89f3f9b83faaebe7bf356ccd086f12ef24739c.tar.xz
Honor userhost-in-names and account-tag caps end-to-end
NAMES (RPL_NAMREPLY) now appends nick!user@host when the requesting client has negotiated userhost-in-names, both on JOIN and on the explicit NAMES command. account-tag is now applied even for unauthenticated senders: per the IRCv3 spec, the value is the literal '*' when no account is known. Previously we silently dropped the tag, which made the ACK meaningless for anonymous clients.
Diffstat (limited to 'src')
-rw-r--r--src/papod.clj73
1 files changed, 38 insertions, 35 deletions
diff --git a/src/papod.clj b/src/papod.clj
index e20bec8..d5b6f20 100644
--- a/src/papod.clj
+++ b/src/papod.clj
@@ -1072,6 +1072,7 @@
(declare ban-matches?)
(declare mute-matches?)
(declare mute-except-matches?)
+(declare nuh-for-nick)
(defn- persistent-channels
"Channel handles where `nick` has stored membership."
@@ -2421,30 +2422,25 @@
(str k "=" v))
client-tag-pairs)))
sender-acct (:account @client)
- acct-tag (when sender-acct
- (str "account=" sender-acct))
+ acct-tag (str "account=" (or sender-acct "*"))
delivery-target (or raw-target target)
raw (str ":" nick " PRIVMSG "
delivery-target " " content)
tagged (tag-line-at msg-id msg-at out-tags
raw)
- tagged-acct (when acct-tag
- (tag-line-at msg-id msg-at
- (conj out-tags acct-tag)
- raw))
+ tagged-acct (tag-line-at msg-id msg-at
+ (conj out-tags acct-tag)
+ raw)
;; server-time only: msgid + time, no
;; forwarded client-only tags
time-only (tag-line-at msg-id msg-at [] raw)
- time-only-acct (when acct-tag
- (tag-line-at msg-id msg-at
- [acct-tag] raw))
+ time-only-acct (tag-line-at msg-id msg-at
+ [acct-tag] raw)
pick-line
(fn [caps]
(let [mt? (and caps (caps "message-tags"))
st? (and caps (caps "server-time"))
- at? (and acct-tag
- caps
- (caps "account-tag"))]
+ at? (and caps (caps "account-tag"))]
(cond
mt? (if at? tagged-acct tagged)
st? (if at? time-only-acct time-only)
@@ -2516,7 +2512,7 @@
(contains? (get @ops handle) nick)))
(defn- names-for
- [components handle & {:keys [multi-prefix?]}]
+ [components handle & {:keys [multi-prefix? userhost?]}]
(let [members (when (:channels components)
(get @(:channels components) handle))
ops (:ops components)
@@ -2525,19 +2521,22 @@
(string/join
" "
(map (fn [mn]
- (let [op? (and ops
- (contains?
- (get @ops handle) mn))
- voc? (and voiced
- (contains?
- (get @voiced handle)
- mn))]
+ (let [op? (and ops
+ (contains?
+ (get @ops handle) mn))
+ voc? (and voiced
+ (contains?
+ (get @voiced handle)
+ mn))
+ body (if userhost?
+ (nuh-for-nick components mn)
+ mn)]
(cond
(and op? voc? multi-prefix?)
- (str "@+" mn)
- op? (str "@" mn)
- voc? (str "+" mn)
- :else mn)))
+ (str "@+" body)
+ op? (str "@" body)
+ voc? (str "+" body)
+ :else body)))
members)))))
(defn- chan-modes-for
@@ -2885,8 +2884,11 @@
;; Build replies for the joining client
(let [mp? (contains? my-caps
"multi-prefix")
+ uh? (contains? my-caps
+ "userhost-in-names")
members (names-for components handle
- :multi-prefix? mp?)
+ :multi-prefix? mp?
+ :userhost? uh?)
sym (chan-symbol components handle)
db' (when conn (d/db conn))
ch-eid' (when db'
@@ -6013,10 +6015,9 @@
(let [base
(str ":" (client-prefix client)
" INVITE " p1 " " p2)
- acct (:account @client)
+ acct (or (:account @client) "*")
tagged-base
- (when acct
- (str "@account=" acct " " base))
+ (str "@account=" acct " " base)
inviting (numeric-reply client "341"
(str target " " handle))]
(when-let [m (and clients
@@ -6024,8 +6025,7 @@
(let [ca (:client-atom m)
caps (when ca
(or (:caps @ca) #{}))
- line (if (and tagged-base
- (caps "account-tag"))
+ line (if (caps "account-tag")
tagged-base
base)]
(deliver-to-client! (:w m) line)))
@@ -6048,8 +6048,7 @@
:when (and m
(caps "invite-notify"))]
(deliver-to-client! (:w m)
- (if (and tagged-base
- (caps "account-tag"))
+ (if (caps "account-tag")
tagged-base base)))))
;; When the channel does not exist, also
;; echo the INVITE back to the inviter
@@ -6130,9 +6129,12 @@
":End of /LIST")))
"NAMES" (let [raw-arg (first params)
chans (:channels components)
+ caps0 (or (:caps @client) #{})
mp? (contains?
- (or (:caps @client) #{})
- "multi-prefix")
+ caps0 "multi-prefix")
+ uh? (contains?
+ caps0
+ "userhost-in-names")
one-chan
(fn [ch]
(let [present?
@@ -6142,7 +6144,8 @@
(when present?
(names-for
components ch
- :multi-prefix? mp?))
+ :multi-prefix? mp?
+ :userhost? uh?))
sym (chan-symbol
components ch)]
(cond->