/
clojurebot.clj
170 lines (142 loc) · 5.22 KB
/
clojurebot.clj
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
(ns hiredman.clojurebot
(:import (org.jibble.pircbot PircBot)))
;; dictionaries for storing relationships
;; 'are' dict is not used right now.
(def dict-is (ref {}))
(def dict-are (ref {}))
;; responses that can be randomly selected from
(def response
{:input-accepted ["Ok." "Roger." "You don't have to tell me twice."]
:befuddled ["Excuse me?" "Huh?" "I don't understand."]})
(defn random-response
"select a random response of the correct type"
[type]
((response type) (rand-int (count (response type)))))
(defn ok []
(random-response :input-accepted))
(defn befuddled []
(random-response :befuddled))
(defn doc-lookup?
"is this a well formed doc-string lookup?"
[msg]
(re-find #"^\(doc " msg))
(defn d?op
"if string ends in a question mark return
the string without the question mark"
[x]
(if (= \? (.charAt x (dec (count x))))
(subs x 0 (dec (count x)))
x))
(defn symbol-to-var-doc
"this returns the doc metadata from a var in the
clojure ns or a befuddled response"
[symb]
(let [x (:doc (meta (find-var (symbol "clojure.core" symb))))]
(if x
x
(befuddled))))
(defmacro async
"just do this, I don't care"
[& x]
`(send-off (agent nil) (fn [& _#] ~@x )))
(defn sendMsg
"send a message to a recv, a recv is a channel name or a nick"
[this recv msg]
(async (.sendMessage this recv (.replace msg \newline \ ))))
(defn who
"am I talking to someonein a privmsg, or in a channel?"
[pojo]
(if (:channel pojo)
(:channel pojo)
(:sender pojo)))
(defn addressed?
"is this message prefixed with clojurebot: "
[pojo]
(when (or (re-find #"^clojurebot:" (:message pojo)) (nil? (:channel pojo)))
pojo))
(defn dispatch
"this function does dispatch for responder"
[pojo]
(cond
(doc-lookup? (:message pojo))
(do (prn :foo) :doc-lookup)
(and (addressed? pojo) (re-find #"svn" (:message pojo)))
:svn
(and (addressed? pojo) (re-find #" is " (:message pojo)))
:define-is
(addressed? pojo)
:lookup
:else
nil))
(defmulti responder dispatch)
(defmethod responder :doc-lookup [pojo]
(sendMsg (:this pojo)
(who pojo)
(symbol-to-var-doc (subs (:message pojo) 5 (dec (count (:message pojo)))))))
(defmethod responder :svn [pojo]
(sendMsg (:this pojo)
(who pojo)
"svn co https://clojure.svn.sourceforge.net/svnroot/clojure clojure"))
(defmethod responder :define-is [pojo]
(let [a (.trim (.replaceFirst (:message pojo) "^clojurebot:" " "))
[term defi] (.split a " is ")]
(dosync
(alter dict-is
(fn [dict]
(let [r (assoc dict (.trim term) (.trim defi))]
(when r
(sendMsg (:this pojo) (who pojo) (ok)))
r))))))
(defmethod responder :lookup [pojo]
(let [msg (d?op (.trim (.replaceFirst (:message pojo) "^clojurebot:" "")))]
(cond
((deref dict-is) msg)
(sendMsg (:this pojo)
(who pojo)
(if (re-find #"^<reply>" ((deref dict-is) msg))
(.replaceFirst (str ((deref dict-is) msg)) "^<reply>" "")
(str msg " is " ((deref dict-is) msg))))
:else
(sendMsg (:this pojo) (who pojo) (befuddled)))))
(defstruct junks :this :channel :sender :login :hostname :message)
(defn handleMessage [this channel sender login hostname message]
(prn :hdlmsg)
(responder {:this this :channel channel :sender sender :login login :hostname hostname :message message}))
(defn handlePrivateMessage [this sender login hostname message]
(prn :privmsg)
(handleMessage this nil sender login hostname message))
(defn pircbot []
(proxy [PircBot] []
(onMessage [channel sender login hostname message]
(handleMessage this channel sender login hostname message))
(onPrivateMessage [sender login hostname message]
(handlePrivateMessage this sender login hostname message))))
(update-proxy bot {'onMessage handleMessage
'onPrivateMessage handlePrivateMessage})
(defn dumpdicts []
(map (fn [[rel rels]]
(binding [*out* (-> (str "clojurebot." rel)
java.io.File.
java.io.FileWriter.)]
(prn @rels)))
[["is" dict-is] ["are" dict-are]]))
;;(.start (Thread. (fn []
;; (loop []
;; (dumpdicts)
;; (.sleep Thread 600000)
;; (recur)))))
;;
;; (.connect bot "chat.freenode.org")
;; (.changeNick bot "clojurebot")
(dosync
(ref-set dict-is
(eval (binding [*in* (-> "clojurebot.is"
java.io.File.
java.io.FileReader.
java.io.PushbackReader.)]
(read))))
)
(def bot (pircbot))
(.connect bot "chat.freenode.org")
(.changeNick "clojurebot")
(.joinChannel "#clojure")