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(?)" 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]
(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)]))
|