summaryrefslogtreecommitdiff
path: root/src/rooms.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/rooms.clj')
-rw-r--r--src/rooms.clj114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/rooms.clj b/src/rooms.clj
new file mode 100644
index 0000000..57fbf3a
--- /dev/null
+++ b/src/rooms.clj
@@ -0,0 +1,114 @@
+(ns rooms
+ (:use clojure.contrib.str-utils
+ utils))
+
+(def *run-flusher* true)
+(def *flusher-sleep* (seconds 4))
+(def *user-timeout* (seconds 15))
+
+(def rooms (ref {}))
+(def flusher (agent nil))
+
+(defn flush-inactive-users! [x]
+ (doseq [[rid room] @rooms]
+ (dosync
+ (let [users (room :users)
+ now (System/currentTimeMillis)
+ cutoff (- now *user-timeout*)
+ alive? (fn [[n u]] (> (u :last-seen) cutoff))]
+ (ref-set users
+ (into {} (filter alive? (ensure users)))))))
+ (Thread/sleep *flusher-sleep*)
+ (when *run-flusher*
+ (send *agent* #'flush-inactive-users!))
+ x)
+
+(defn start-user-flusher! []
+ (send flusher flush-inactive-users!))
+
+(def *default-room* "dumpfm")
+
+(defn default-room? [key]
+ (= (lower-case key) *default-room*))
+
+(defn lookup-room [key]
+ (@rooms (lower-case key)))
+
+(defn fetch-room [key]
+ (first (do-select ["SELECT * FROM rooms WHERE key = LOWER(?)" key])))
+
+(defn fetch-rooms []
+ (do-select ["SELECT * FROM ROOMS"]))
+
+(defn count-messages-by-room [room-id image-only]
+ (let [query (str "SELECT COUNT(*)
+ FROM messages m, users u
+ WHERE room_id = ? AND m.user_id = u.user_id"
+ (if image-only " AND m.is_image = true " ""))]
+ (do-count [query room-id])))
+
+(defn fetch-messages-by-room
+ ([room-id image-only] (fetch-messages-by-room room-id image-only 0))
+ ([room-id image-only offset]
+ (let [query (str "SELECT m.content, m.message_id, m.created_on, u.nick, u.avatar
+ FROM users u, messages m
+ WHERE room_id = ? AND m.user_id = u.user_id "
+ (if image-only "AND m.is_image = true " "")
+ "ORDER BY created_on DESC
+ LIMIT ? OFFSET ?")]
+ (do-select [query room-id *dumps-per-page* offset]))))
+
+(defn build-room-map-from-db [room-db]
+ {:admin_only (room-db :admin_only)
+ :room_id (room-db :room_id)
+ :key (room-db :key)
+ :name (room-db :name)
+ :description (room-db :description)
+ :users (ref {})
+ :messages (ref (fetch-messages-by-room (room-db :room_id) false))
+ :topic (ref nil)
+ })
+
+
+(defn load-rooms! []
+ (dosync
+ (doseq [room-db (fetch-rooms)]
+ (alter rooms assoc (lower-case (room-db :key))
+ (build-room-map-from-db room-db)))))
+
+;; Room helpers
+
+(defn login-user [user room]
+ (alter (room :users) assoc (user :nick) user))
+
+(defn add-message [msg room]
+ (alter (room :messages) (swap cons) msg))
+
+(defn create-and-add-room! [key]
+ (do-select ["INSERT INTO rooms (key, name, description)
+ VALUES (?, ?, ?) RETURNING room_id"
+ key key key])
+ (if-let [room-db (fetch-room key)]
+ (dosync
+ (alter rooms assoc (lower-case key)
+ (build-room-map-from-db room-db))
+ room-db)))
+
+(defn get-or-create-room! [key]
+ (:room_id
+ (or (first (do-select ["SELECT room_id FROM rooms WHERE lower(key) = ?"
+ (lower-case key)]))
+ (create-and-add-room!)
+ (throw (Exception. (str "Unable to create room " key))))))
+
+(defn- get-or-create-room-bot-id! [nick]
+ ((comp :user_id first)
+ (or (do-select ["SELECT user_id FROM users WHERE lower(nick) = ?"
+ (lower-case nick)])
+ (do-select ["INSERT INTO users (nick, hash, email)
+ VALUES (?, ?, ?) RETURNING user_id"
+ nick "GARBAGE" "info@dump.fm"]))))
+
+(defn get-or-create-room-bot! [key]
+ (let [nick (str key "bo†")]
+ [nick (get-or-create-room-bot-id! nick)])) \ No newline at end of file