summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/papod.clj177
1 files changed, 121 insertions, 56 deletions
diff --git a/src/papod.clj b/src/papod.clj
index f68c430..a63e5b5 100644
--- a/src/papod.clj
+++ b/src/papod.clj
@@ -3212,13 +3212,24 @@
:else
(let [nick (client-target client)
mode-str (second params)
- mode-arg (nth params 2 nil)
+ raw-arg (nth params 2 nil)
+ mode-arg (when raw-arg
+ (cond-> raw-arg
+ (string/starts-with?
+ raw-arg ":")
+ (subs 1)))
adding? (or (string/starts-with?
mode-str "+")
(not (string/starts-with?
mode-str "-")))
mode-char (last mode-str)]
(cond
+ ;; Channel must exist
+ (and channels
+ (empty? (get @channels target)))
+ [(numeric-reply client "403"
+ (str target " :No such channel"))]
+
;; Need op for mode changes
(and channels
(not (is-op? components target nick)))
@@ -3228,9 +3239,23 @@
;; +o/-o: operator mode
(= \o mode-char)
- (if-not mode-arg
+ (cond
+ (not mode-arg)
[(numeric-reply client "461"
"MODE :Not enough parameters")]
+ (and clients
+ (not (get @clients mode-arg)))
+ [(numeric-reply client "401"
+ (str mode-arg
+ " :No such nick/channel"))]
+ (and channels
+ (not (contains?
+ (get @channels target)
+ mode-arg)))
+ [(numeric-reply client "441"
+ (str mode-arg " " target
+ " :They aren't on that channel"))]
+ :else
(let [line (str ":" nick " MODE " target
" " mode-str " " mode-arg)]
(if adding?
@@ -3280,35 +3305,58 @@
;; +l/-l: limit
(= \l mode-char)
- (let [cur (or (get @(:chan-modes components)
- target)
- "+nt")
- flag "l"
- new (if adding?
- (if (string/includes? cur flag)
- cur
- (str cur flag))
- (string/replace cur flag ""))
- line (str ":" nick " MODE " target
- " " mode-str
- (when (and adding? mode-arg)
- (str " " mode-arg)))]
- (when (:chan-modes components)
- (swap! (:chan-modes components)
- assoc target new))
- (when-let [limits (:chan-limits components)]
- (if (and adding? mode-arg)
- (try
- (swap! limits assoc target
- (Integer/parseInt mode-arg))
- (catch NumberFormatException _ nil))
- (swap! limits dissoc target)))
- (when (and clients channels)
- (doseq [mn (get @channels target)
- :let [m (get @clients mn)]
- :when m]
- (deliver-to-client! (:w m) line)))
- [])
+ (let [parsed (when (and adding? mode-arg)
+ (try
+ (Integer/parseInt
+ (string/trim mode-arg))
+ (catch NumberFormatException _
+ nil)))
+ valid? (or (not adding?)
+ (and parsed (pos? parsed)))]
+ (cond
+ (and adding? (not mode-arg))
+ [(numeric-reply client "461"
+ "MODE :Not enough parameters")]
+ (not valid?)
+ (let [shown (if (and mode-arg
+ (seq mode-arg))
+ mode-arg
+ "*")]
+ [(numeric-reply client "696"
+ target "l" shown
+ ":Invalid limit value")])
+ :else
+ (let [cur (or (get @(:chan-modes
+ components)
+ target)
+ "+nt")
+ flag "l"
+ new (if adding?
+ (if (string/includes?
+ cur flag)
+ cur
+ (str cur flag))
+ (string/replace cur flag ""))
+ line (str ":" nick " MODE " target
+ " " mode-str
+ (when (and adding?
+ mode-arg)
+ (str " " mode-arg)))]
+ (when (:chan-modes components)
+ (swap! (:chan-modes components)
+ assoc target new))
+ (when-let [limits
+ (:chan-limits components)]
+ (if adding?
+ (swap! limits assoc target parsed)
+ (swap! limits dissoc target)))
+ (when (and clients channels)
+ (doseq [mn (get @channels target)
+ :let [m (get @clients mn)]
+ :when m]
+ (deliver-to-client!
+ (:w m) line)))
+ [])))
;; Simple flag modes (n/t/m/i/s/p/c)
;; Iterate every char in the mode-str so
@@ -3346,32 +3394,49 @@
;; +k/-k: channel key
(= \k mode-char)
- (let [cur (or (get @(:chan-modes components)
+ (let [valid-key?
+ (and adding?
+ mode-arg
+ (seq mode-arg)
+ (not (string/includes? mode-arg
+ " ")))]
+ (cond
+ (and adding? (not valid-key?))
+ [(numeric-reply client "696"
+ target "k" "*"
+ ":Invalid key value")]
+ :else
+ (let [cur (or (get
+ @(:chan-modes components)
target)
- "+nt")
- flag "k"
- new (if adding?
- (if (string/includes? cur flag)
- cur
- (str cur flag))
- (string/replace cur flag ""))
- line (str ":" nick " MODE " target
- " " mode-str
- (when (and adding? mode-arg)
- (str " " mode-arg)))]
- (when (:chan-modes components)
- (swap! (:chan-modes components)
- assoc target new))
- (when-let [keys (:chan-keys components)]
- (if (and adding? mode-arg)
- (swap! keys assoc target mode-arg)
- (swap! keys dissoc target)))
- (when (and clients channels)
- (doseq [mn (get @channels target)
- :let [m (get @clients mn)]
- :when m]
- (deliver-to-client! (:w m) line)))
- [])
+ "+nt")
+ flag "k"
+ new (if adding?
+ (if (string/includes?
+ cur flag)
+ cur
+ (str cur flag))
+ (string/replace cur flag ""))
+ line (str ":" nick " MODE " target
+ " " mode-str
+ (when (and adding?
+ mode-arg)
+ (str " " mode-arg)))]
+ (when (:chan-modes components)
+ (swap! (:chan-modes components)
+ assoc target new))
+ (when-let [keys
+ (:chan-keys components)]
+ (if adding?
+ (swap! keys assoc target mode-arg)
+ (swap! keys dissoc target)))
+ (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))