Compare commits

...

2 Commits

Author SHA1 Message Date
Sebastian Crane b099d6bfe1 Release version 1.0.1
Signed-off-by: Sebastian Crane <seabass-labrax@gmx.com>
2022-04-01 15:52:51 +01:00
Sebastian Crane 6a594c5ad3 Use strings instead of keywords for game names
This commit changes the internal representation of game names in the
state data to be strings instead of keywords. This fixes a potential
memory leak relating to games that no longer have any players, since
strings, unlike keywords, are garbage collected when no longer in use.

Resolves issue LibreGaming/matchbot#2

Signed-off-by: Sebastian Crane <seabass-labrax@gmx.com>
2022-03-30 12:11:10 +01:00
5 changed files with 38 additions and 27 deletions

View File

@ -5,8 +5,17 @@
`matchbot` uses [version 2.0.0 of the Semantic Versioning](https://semver.org/spec/v2.0.0.html) scheme.
## [1.0.1] - 2022-04-01
* Fix vulnerability that causes serialised data to be deleted when it contains certain user input
* Change internal representation of game names, fixing a potential memory leak for long-running instances
* Improve reliability and code quality of the startup and shutdown sequences
## [1.0.0] - 2022-03-03
* Initial release
[1.0.1]: https://git.libregaming.org/LibreGaming/matchbot/releases/tag/1.0.1
[1.0.0]: https://git.libregaming.org/LibreGaming/matchbot/releases/tag/1.0.0

View File

@ -6,15 +6,15 @@
[game]
[irclj.core]))
(defn keywordise-game [game]
(defn lower-case-game [game]
(when (string? game)
(keyword (str/lower-case game))))
(str/lower-case game)))
(defn sort-case-insensitive [coll]
(sort #(apply compare (map str/lower-case %&)) coll))
(defn match-string [& {:keys [state game player]}]
(as-> (keywordise-game game) x
(as-> (lower-case-game game) x
(game/get-players-of-game state x)
(disj x player)
(sort-case-insensitive x)
@ -22,7 +22,7 @@
(str "Anyone ready for " game "? " x)))
(defn list-players-string [& {:keys [state game]}]
(as-> (keywordise-game game) x
(as-> (lower-case-game game) x
(game/get-players-of-game state x)
(sort-case-insensitive x)
(map #(str " _" % "_") x)
@ -46,7 +46,7 @@
(str "Games with a list of players: "
(str/join
", "
(sort-case-insensitive (map name (game/get-games state))))))
(sort-case-insensitive (game/get-games state)))))
(defn help-string [& {:keys []}]
" !list - show all the games that have a list of players
@ -59,7 +59,7 @@
(let [message-parts (str/split message #"\s")
command (if-let [x (first message-parts)] (str/lower-case x) "")
game (second message-parts)
game-keyword (keywordise-game game)]
game-keyword (lower-case-game game)]
{:command command
:game game
:game-keyword game-keyword}))

View File

@ -4,6 +4,7 @@
(ns system
(:require [irc]
[clojure.data.json :as json]
[clojure.set :as set]
[clj-yaml.core :as yaml]))
(defn setify-vals [x]
@ -13,13 +14,14 @@
{} x))
(defn process-json [x]
(update x :games setify-vals))
(-> (set/rename-keys x {"games" :games})
(update :games setify-vals)))
(defn load-state [f]
(process-json
(try
(with-open [datafile (clojure.java.io/reader f)]
(json/read datafile :key-fn keyword))
(json/read datafile))
(catch Exception e nil))))
(defn save-state [f data]

View File

@ -5,13 +5,13 @@
(:require [clojure.test :refer :all]
[bot :refer :all]))
(def test-state '{:games {:hypothetical-shooter #{"abc" "xyz" "123"}
:quasi-rts #{"abc" "123"}
:imaginary-rpg #{"xyz" "abc"}}})
(def test-state '{:games {"hypothetical-shooter" #{"abc" "xyz" "123"}
"quasi-rts" #{"abc" "123"}
"imaginary-rpg" #{"xyz" "abc"}}})
(deftest keywordise-game-test
(is (= :quasi-rts
(keywordise-game "Quasi-RTS"))))
(deftest lower-case-game-test
(is (= "quasi-rts"
(lower-case-game "Quasi-RTS"))))
(deftest sort-case-insensitive-test
(is (= ["A" "b" "C"]
@ -38,7 +38,7 @@
(list-games-string :state test-state))))
(deftest split-message-test
(is (= {:command "!match" :game "Quasi-Rts" :game-keyword :quasi-rts}
(is (= {:command "!match" :game "Quasi-Rts" :game-keyword "quasi-rts"}
(split-message "!match Quasi-Rts "))))
(deftest dispatch-command-test
@ -46,7 +46,7 @@
(is (and
(= "Added 123 to the list of players for Imaginary-RPG!"
(dispatch-command state-atom "123" "!add Imaginary-RPG"))
(= {:games {:hypothetical-shooter #{"abc" "xyz" "123"}
:quasi-rts #{"abc" "123"}
:imaginary-rpg #{"xyz" "abc" "123"}}}
(= {:games {"hypothetical-shooter" #{"abc" "xyz" "123"}
"quasi-rts" #{"abc" "123"}
"imaginary-rpg" #{"xyz" "abc" "123"}}}
@state-atom)))))

View File

@ -5,31 +5,31 @@
(:require [clojure.test :refer :all]
[game :refer :all]))
(def test-state '{:games {:hypothetical-shooter #{"player-one" "player-two" "player-three"}
:quasi-rts #{"player-two" "player-four"}
:imaginary-rpg #{"player-one" "player-three" "player-four"}}})
(def test-state '{:games {"hypothetical-shooter" #{"player-one" "player-two" "player-three"}
"quasi-rts" #{"player-two" "player-four"}
"imaginary-rpg" #{"player-one" "player-three" "player-four"}}})
(deftest get-players-of-game-test
(is (=
'#{"player-two" "player-four"}
(get-players-of-game test-state :quasi-rts))))
(get-players-of-game test-state "quasi-rts"))))
(deftest add-player-of-game-test
(is (=
'#{"player-one" "player-two" "player-four"}
(get-in (add-player-of-game test-state :quasi-rts "player-one") [:games :quasi-rts]))))
(get-in (add-player-of-game test-state "quasi-rts" "player-one") [:games "quasi-rts"]))))
(deftest remove-player-of-game-test
(is (=
'#{"player-one" "player-three"}
(get-in (remove-player-of-game test-state :imaginary-rpg "player-four") [:games :imaginary-rpg]))))
(get-in (remove-player-of-game test-state "imaginary-rpg" "player-four") [:games "imaginary-rpg"]))))
(deftest get-games-test
(is (=
'#{:hypothetical-shooter :quasi-rts :imaginary-rpg}
'#{"hypothetical-shooter" "quasi-rts" "imaginary-rpg"}
(set (get-games test-state)))))
(deftest remove-game-test
(is (=
'#{:hypothetical-shooter :imaginary-rpg}
(set (keys (:games (remove-game test-state :quasi-rts)))))))
'#{"hypothetical-shooter" "imaginary-rpg"}
(set (keys (:games (remove-game test-state "quasi-rts")))))))