Add basic IRC command parser

This commit is contained in:
2023-09-10 17:10:01 +02:00
parent f936f115b7
commit 7ed6ff30b9
2 changed files with 60 additions and 0 deletions

View File

@ -34,3 +34,27 @@
trailing-param (last params)]
(apply str (map #(str " " %) (conj first-params (str ":" trailing-param)))))))
(.write writer "\r\n"))
(defn send-command [client command]
(write-command (:writer client) command)
(.flush (:writer client)))
(defn send-commands [client commands]
(for [command commands]
(write-command (:writer client) command))
(.flush (:writer client)))
(def line-re
#"^(?:@([^ ]+) )?(?::([^ ]+) )?([^ ]+)(?: (.*?))??(?: :(.*))?$")
(defn parse-command [line]
(let [[_ tags source cmd params trailing] (re-matches line-re line)]
{:tags tags
:source source
:cmd cmd
:params (let [params (if (empty? params)
[]
(str/split params #" "))]
(if trailing
(conj params trailing)
params))}))

View File

@ -23,3 +23,39 @@
(write-command buf {:cmd "KICK" :params ["#chan" "badperson" "bye bye"]})
(is (= (.toString buf) "KICK #chan badperson :bye bye\r\n")))))
(deftest parse-command-test
(testing "parsing a command with no param"
(is (= (parse-command "AWAY")
{:tags nil :source nil :cmd "AWAY" :params []})))
(testing "parsing a command with one param"
(is (= (parse-command "AWAY reason")
{:tags nil :source nil :cmd "AWAY" :params ["reason"]})))
(testing "parsing a command with one trailing param"
(is (= (parse-command "AWAY :the reason")
{:tags nil :source nil :cmd "AWAY" :params ["the reason"]})))
(testing "parsing a command with two params"
(is (= (parse-command "PRIVMSG #chan :hi")
{:tags nil :source nil :cmd "PRIVMSG" :params ["#chan" "hi"]})))
(testing "parsing a command with one normal param and one trailing param"
(is (= (parse-command "PRIVMSG #chan :hi there")
{:tags nil :source nil :cmd "PRIVMSG" :params ["#chan" "hi there"]})))
(testing "parsing a command with source"
(is (= (parse-command ":nick!user@host AWAY")
{:tags nil :source "nick!user@host" :cmd "AWAY" :params []})))
(testing "parsing a command with tags"
(is (= (parse-command "@label=abc ACK")
{:tags "label=abc" :source nil :cmd "ACK" :params []})))
(testing "parsing a command with source and tags"
(is (= (parse-command "@label=abc :nick!user@host AWAY")
{:tags "label=abc" :source "nick!user@host" :cmd "AWAY" :params []})))
(testing "parsing a command with all fields"
(is (= (parse-command "@k1=v1;k2=v2 :server. KICK #chan badperson :reason")
{:tags "k1=v1;k2=v2" :source "server." :cmd "KICK" :params ["#chan" "badperson" "reason"]}))))