diff options
| author | EuAndreh <eu@euandre.org> | 2026-04-30 09:02:20 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2026-04-30 09:02:20 -0300 |
| commit | 8c89f3f9b83faaebe7bf356ccd086f12ef24739c (patch) | |
| tree | 76945e64cc90995416e91bc9172fdc288f68dc83 /src | |
| parent | Implement draft/metadata-2 before-connect optional behavior (diff) | |
| download | papod-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.clj | 73 |
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-> |
