summaryrefslogtreecommitdiff
path: root/src/rooms.clj
blob: 32239d28f3eb36a374241f9d9d72f577dedd62fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
(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(?) AND active" key])))

(defn fetch-rooms []
  (do-select ["SELECT * FROM ROOMS WHERE active"]))

(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]
  (println "Creating 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! key)
       (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
         (do-select ["INSERT INTO users (nick, hash, email)
                    VALUES (?, ?, ?) RETURNING user_id"
                     nick "GARBAGE" "info@dump.fm"])
         (println "Creating bot  " nick)))))

(defn get-or-create-room-bot! [key]
  (let [nick  (str "~" key)]
    [nick (get-or-create-room-bot-id! nick)]))