summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/papod.clj109
-rw-r--r--tests/unit.clj5
2 files changed, 92 insertions, 22 deletions
diff --git a/src/papod.clj b/src/papod.clj
index 5e81533..4055e8a 100644
--- a/src/papod.clj
+++ b/src/papod.clj
@@ -664,13 +664,13 @@
index 0]
(if (or (= index (count s))
(= +separator+ (nth s index)))
- [(apply str chars) (count chars)]
- (let [c (nth s index)]
- (if-not (letter? c)
- [nil nil {:message "Bad char for non-numerical command"
- :data {:c c}}]
- (recur (conj chars c)
- (inc index)))))))
+ (if (zero? (count chars))
+ [nil nil {:message "Empty command"
+ :type :empty-command
+ :data {}}]
+ [(apply str chars) (count chars)])
+ (recur (conj chars (nth s index))
+ (inc index)))))
(defconst- params-re
(java.util.regex.Pattern/compile (str +separator+)))
@@ -2063,10 +2063,12 @@
(get @clients target))]
(deliver! m)))
;; Build reply vector
- (let [echo? (contains?
- (or (:caps @client) #{})
- "echo-message")
- echo (when echo? [tagged])
+ (let [my-caps (or (:caps @client) #{})
+ echo? (contains? my-caps "echo-message")
+ tags? (or (my-caps "message-tags")
+ (my-caps "server-time"))
+ echo (when echo?
+ [(if tags? tagged raw)])
away (when-not chan?
(let [m (when clients
(get @clients target))
@@ -2578,7 +2580,8 @@
handle (first params)
reply-id-str (get tags "+reply")
react-emoji (get tags "+draft/react")
- unreact-emoji (get tags "+draft/unreact")]
+ unreact-emoji (get tags "+draft/unreact")
+ chan? (channel-handle? handle)]
(cond
(empty? params)
[(numeric-reply client "461" "TAGMSG :Not enough parameters")]
@@ -2658,7 +2661,54 @@
(deliver-to-client! (:w m) line)))
[])
- :else [])))
+ ;; Generic TAGMSG: forward client tags
+ :else
+ (let [user-tags (->> tags
+ (filter (fn [[k _]]
+ (string/starts-with? k "+")))
+ (map (fn [[k v]] (str k "=" v))))
+ base-line (str ":" nick " TAGMSG " handle)
+ recip-line (if (seq user-tags)
+ (str "@" (string/join ";" user-tags)
+ " " base-line)
+ base-line)
+ my-caps (or (:caps @client) #{})
+ tags-cap? (contains? my-caps "message-tags")
+ recipient-exists?
+ (cond
+ chan? (and channels
+ (seq (get @channels handle)))
+ :else (and clients
+ (get @clients handle)))]
+ (cond
+ (and (not chan?) (not recipient-exists?))
+ [(numeric-reply client "401"
+ (str handle " :No such nick/channel"))]
+
+ (and chan? (not recipient-exists?))
+ [(numeric-reply client "403"
+ (str handle " :No such channel"))]
+
+ :else
+ (do
+ (when tags-cap?
+ (if chan?
+ (doseq [mn (get @channels handle)
+ :when (not= mn nick)
+ :let [m (get @clients mn)
+ ca (when m (:client-atom m))
+ caps (when ca (or (:caps @ca) #{}))]
+ :when (and m (caps "message-tags"))]
+ (deliver-to-client! (:w m) recip-line))
+ (when-let [m (get @clients handle)]
+ (let [ca (:client-atom m)
+ caps (when ca (or (:caps @ca) #{}))]
+ (when (caps "message-tags")
+ (deliver-to-client! (:w m) recip-line))))))
+ (if (and (contains? my-caps "echo-message")
+ tags-cap?)
+ [recip-line]
+ [])))))))
(defn- handle-markread
[params client components]
@@ -2921,6 +2971,7 @@
"NICK" (handle-nick params client components)
"USER" (handle-user params client components)
"PING" (handle-ping params client)
+ "PONG" []
"CAP" (handle-cap params client components)
"AUTHENTICATE" (handle-authenticate params client components)
(cond
@@ -3755,6 +3806,24 @@
(.write w bytes 0 (count bytes))))
(.flush w))
+(defn- add-label-tag
+ [line label]
+ (if (string/starts-with? line "@")
+ (let [sp (.indexOf line " ")]
+ (str "@label=" label ";"
+ (subs line 1 sp)
+ (subs line sp)))
+ (str "@label=" label " " line)))
+
+(defn- add-batch-tag
+ [line batch-id]
+ (if (string/starts-with? line "@")
+ (let [sp (.indexOf line " ")]
+ (str "@batch=" batch-id ";"
+ (subs line 1 sp)
+ (subs line sp)))
+ (str "@batch=" batch-id " " line)))
+
(defn- handle-message!
[message w client components]
(let [label (get (:tags message) "label")
@@ -3767,16 +3836,16 @@
(not has-lr?)
(send-replies! replies w)
- ;; Single reply — add label tag directly
- (= 1 (count replies))
+ ;; No replies — send ACK with label
+ (empty? replies)
(send-replies!
- [(str "@label=" label " " (first replies))]
+ [(str "@label=" label " ACK")]
w)
- ;; No replies — send ACK with label
- (empty? replies)
+ ;; Single reply — add label tag directly
+ (= 1 (count replies))
(send-replies!
- [(str "@label=" label " :" +server-name+ " ACK")]
+ [(add-label-tag (first replies) label)]
w)
;; Multiple replies — wrap in BATCH
@@ -3788,7 +3857,7 @@
" labeled-response")]
(concat
(map (fn [r]
- (str "@batch=" batch-id " " r))
+ (add-batch-tag r batch-id))
replies)
[(str "BATCH -" batch-id)]))
w)))))
diff --git a/tests/unit.clj b/tests/unit.clj
index 1345501..c398350 100644
--- a/tests/unit.clj
+++ b/tests/unit.clj
@@ -1689,8 +1689,9 @@
(let [replies (handle-privmsg ["#test" ":no-echo"]
alice components)]
(is (empty? replies)))
- ;; With echo-message: reply includes the message
- (swap! alice assoc :caps #{"echo-message"})
+ ;; With echo-message + message-tags: reply has @msgid=
+ (swap! alice assoc :caps
+ #{"echo-message" "message-tags"})
(let [replies (handle-privmsg ["#test" ":with-echo"]
alice components)]
(is (= 1 (count replies)))