Browse code
Reformat whitespace
Ed Langley authored on 04/02/2019 07:07:44
Showing 5 changed files
Showing 5 changed files
... | ... |
@@ -4,28 +4,26 @@ |
4 | 4 |
:description "Describe hhgbot here" |
5 | 5 |
:author "Your Name <your.name@example.com>" |
6 | 6 |
:license "Specify license here" |
7 |
- :depends-on ( |
|
8 |
- #:alexandria |
|
9 |
- #:blackbird |
|
10 |
- #:carrier |
|
11 |
- #:chanl |
|
12 |
- #:cl+ssl |
|
13 |
- #:cl-js |
|
14 |
- #:drakma |
|
15 |
- #:fast-http |
|
16 |
- #:flexi-streams |
|
17 |
- #:fwoar.lisputils |
|
18 |
- #:hunchensocket |
|
19 |
- #:positional-lambda |
|
20 |
- #:plump |
|
21 |
- #:puri |
|
22 |
- #:serapeum |
|
23 |
- #:ubiquitous |
|
24 |
- #:vecto |
|
25 |
- #:websocket-driver |
|
26 |
- #:yason |
|
27 |
- #:vecto |
|
28 |
- ) |
|
7 |
+ :depends-on (#:alexandria |
|
8 |
+ #:blackbird |
|
9 |
+ #:carrier |
|
10 |
+ #:chanl |
|
11 |
+ #:cl+ssl |
|
12 |
+ #:cl-js |
|
13 |
+ #:drakma |
|
14 |
+ #:fast-http |
|
15 |
+ #:flexi-streams |
|
16 |
+ #:fwoar-lisputils |
|
17 |
+ #:hunchensocket |
|
18 |
+ #:positional-lambda |
|
19 |
+ #:plump |
|
20 |
+ #:puri |
|
21 |
+ #:serapeum |
|
22 |
+ #:ubiquitous |
|
23 |
+ #:vecto |
|
24 |
+ #:websocket-driver |
|
25 |
+ #:yason |
|
26 |
+ #:vecto) |
|
29 | 27 |
:serial t |
30 | 28 |
:components ((:file "package") |
31 | 29 |
(:file "event-pump") |
... | ... |
@@ -9,20 +9,20 @@ |
9 | 9 |
(with-accessors ((work-queue work-queue)) executor |
10 | 10 |
(let ((promise (blackbird-base:make-promise :name "js-execution"))) |
11 | 11 |
(chanl:send work-queue |
12 |
- (list promise js)) |
|
12 |
+ (list promise js)) |
|
13 | 13 |
promise))) |
14 | 14 |
|
15 | 15 |
(defmethod slacker:start-module ((event-pump event-pump) (exe js-executor)) |
16 | 16 |
(declare (ignorable event-pump)) |
17 | 17 |
(values exe |
18 |
- (bt:make-thread |
|
19 |
- (lambda () |
|
20 |
- (loop |
|
21 |
- (multiple-value-bind (message message-p) (chanl:recv (work-queue exe)) |
|
22 |
- (when message-p |
|
23 |
- (destructuring-bind (promise script) message |
|
24 |
- (handler-case |
|
25 |
- (blackbird-base:finish promise (cl-js:run-js script)) |
|
26 |
- (t (c) (blackbird:signal-error promise c))))) |
|
27 |
- (sleep 0.4)))) |
|
28 |
- :name "js-executor"))) |
|
18 |
+ (bt:make-thread |
|
19 |
+ (lambda () |
|
20 |
+ (loop |
|
21 |
+ (multiple-value-bind (message message-p) (chanl:recv (work-queue exe)) |
|
22 |
+ (when message-p |
|
23 |
+ (destructuring-bind (promise script) message |
|
24 |
+ (handler-case |
|
25 |
+ (blackbird-base:finish promise (cl-js:run-js script)) |
|
26 |
+ (t (c) (blackbird:signal-error promise c))))) |
|
27 |
+ (sleep 0.4)))) |
|
28 |
+ :name "js-executor"))) |
... | ... |
@@ -2,13 +2,13 @@ |
2 | 2 |
(defpackage :slacker |
3 | 3 |
(:use :cl :alexandria :serapeum :fw.lu) |
4 | 4 |
(:export #:coordinate-threads #:define-command #:start-module |
5 |
- #:event-pump #:attach-module #:*api-token* #:send-message |
|
6 |
- #:get-event-nonblocking #:get-event #:event-loop #:quote-output |
|
7 |
- #:in-wq #:aconsf #:queue-message #:command-error #:unsupported-args |
|
8 |
- #:define-command #:edit-message #:with-output-to-message |
|
9 |
- #:help #:make-message #:modules #:latest-id #:work-queue #:result-queue |
|
10 |
- #:ws-client #:waiting-pings #:ts #:channel :get-module |
|
11 |
- #:keep-in-thread #:ensure-thread #:handle-message)) |
|
5 |
+ #:event-pump #:attach-module #:*api-token* #:send-message |
|
6 |
+ #:get-event-nonblocking #:get-event #:event-loop #:quote-output |
|
7 |
+ #:in-wq #:aconsf #:queue-message #:command-error #:unsupported-args |
|
8 |
+ #:define-command #:edit-message #:with-output-to-message |
|
9 |
+ #:help #:make-message #:modules #:latest-id #:work-queue #:result-queue |
|
10 |
+ #:ws-client #:waiting-pings #:ts #:channel :get-module |
|
11 |
+ #:keep-in-thread #:ensure-thread #:handle-message)) |
|
12 | 12 |
|
13 | 13 |
(defpackage slacker.api |
14 | 14 |
(:use)) |
... | ... |
@@ -2,48 +2,48 @@ |
2 | 2 |
|
3 | 3 |
(defmethod attach-module ((event-pump event-pump) module &rest args &key) |
4 | 4 |
(setf (gethash (make-keyword module) |
5 |
- (modules event-pump)) |
|
6 |
- (apply #'make-instance |
|
7 |
- module |
|
8 |
- args))) |
|
5 |
+ (modules event-pump)) |
|
6 |
+ (apply #'make-instance |
|
7 |
+ module |
|
8 |
+ args))) |
|
9 | 9 |
|
10 | 10 |
(defgeneric get-module (module event-pump) |
11 | 11 |
(:documentation "Get one of the activated modules") |
12 | 12 |
(:method (module (event-pump event-pump)) |
13 | 13 |
(gethash (make-keyword module) |
14 |
- (modules event-pump)))) |
|
14 |
+ (modules event-pump)))) |
|
15 | 15 |
|
16 | 16 |
(defvar *api-token*) |
17 | 17 |
|
18 | 18 |
(defun make-client (event-pump) |
19 | 19 |
(flet ((get-ws-url (slack-response) |
20 |
- (gethash "url" slack-response))) |
|
20 |
+ (gethash "url" slack-response))) |
|
21 | 21 |
(fw.lu:let-each (:be slack-data) |
22 | 22 |
(format nil "https://slack.com/api/rtm.start?token=~a" *api-token*) |
23 | 23 |
(drakma:http-request slack-data :want-stream t) |
24 | 24 |
(yason:parse slack-data) |
25 | 25 |
|
26 | 26 |
(let* ((url (get-ws-url slack-data)) |
27 |
- (client (wsd:make-client url))) |
|
28 |
- (setf (ws-client event-pump) |
|
29 |
- client) |
|
30 |
- (wsd:on :message client |
|
31 |
- (lambda (message) |
|
32 |
- #+null |
|
33 |
- (format t "~&Got a message ~a~%" message) |
|
34 |
- (chanl:send (result-queue event-pump) |
|
35 |
- message))) |
|
36 |
- client)))) |
|
27 |
+ (client (wsd:make-client url))) |
|
28 |
+ (setf (ws-client event-pump) |
|
29 |
+ client) |
|
30 |
+ (wsd:on :message client |
|
31 |
+ (lambda (message) |
|
32 |
+ #+null |
|
33 |
+ (format t "~&Got a message ~a~%" message) |
|
34 |
+ (chanl:send (result-queue event-pump) |
|
35 |
+ message))) |
|
36 |
+ client)))) |
|
37 | 37 |
|
38 | 38 |
(defgeneric send-message (client type &key) |
39 | 39 |
(:documentation "Send a slack message") |
40 | 40 |
(:method :around ((client event-pump) _type &key) |
41 | 41 |
(declare (ignorable client _type)) |
42 | 42 |
(let ((result (call-next-method))) |
43 |
- (values result |
|
44 |
- (wsd:send (ws-client client) |
|
45 |
- (with-output-to-string (s) |
|
46 |
- (yason:encode result s))))))) |
|
43 |
+ (values result |
|
44 |
+ (wsd:send (ws-client client) |
|
45 |
+ (with-output-to-string (s) |
|
46 |
+ (yason:encode result s))))))) |
|
47 | 47 |
|
48 | 48 |
(defmethod send-message ((client event-pump) (type (eql :ping)) &key data) |
49 | 49 |
(let* ((id (incf (latest-id client))) |
... | ... |
@@ -60,15 +60,15 @@ |
60 | 60 |
|
61 | 61 |
(defmethod send-message ((client event-pump) (type (eql :message)) &key channel data thread) |
62 | 62 |
(let* ((id (incf (latest-id client))) |
63 |
- (message `(("id" . ,id) |
|
64 |
- ("type" . "message") |
|
65 |
- ("channel" . ,channel) |
|
66 |
- ("text" . ,data) |
|
67 |
- ,@(unsplice |
|
68 |
- (when thread |
|
69 |
- `("thread_ts" . ,thread)))))) |
|
63 |
+ (message `(("id" . ,id) |
|
64 |
+ ("type" . "message") |
|
65 |
+ ("channel" . ,channel) |
|
66 |
+ ("text" . ,data) |
|
67 |
+ ,@(unsplice |
|
68 |
+ (when thread |
|
69 |
+ `("thread_ts" . ,thread)))))) |
|
70 | 70 |
(alist-hash-table message |
71 |
- :test 'equal))) |
|
71 |
+ :test 'equal))) |
|
72 | 72 |
|
73 | 73 |
|
74 | 74 |
(defgeneric start-module (client module) |
... | ... |
@@ -90,11 +90,11 @@ |
90 | 90 |
(defun handle-work-queue (event-pump) |
91 | 91 |
(multiple-value-bind (message message-p) |
92 | 92 |
(chanl:recv (work-queue event-pump) |
93 |
- :blockp nil) |
|
93 |
+ :blockp nil) |
|
94 | 94 |
(when message-p |
95 | 95 |
(format t "Got a message") |
96 | 96 |
(funcall message |
97 |
- event-pump)))) |
|
97 |
+ event-pump)))) |
|
98 | 98 |
|
99 | 99 |
(defun send-pings (event-pump client) |
100 | 100 |
"Ping slack for connectivity, error if we have too many waiting pings." |
... | ... |
@@ -107,54 +107,54 @@ |
107 | 107 |
(defun network-loop (event-pump client-factory modules) |
108 | 108 |
(declare (optimize (debug 3))) |
109 | 109 |
(loop for (module . args) in modules |
110 |
- do (start-module event-pump |
|
111 |
- (apply #'attach-module |
|
112 |
- event-pump module args))) |
|
110 |
+ do (start-module event-pump |
|
111 |
+ (apply #'attach-module |
|
112 |
+ event-pump module args))) |
|
113 | 113 |
(let ((client (funcall client-factory)) |
114 |
- (connected nil)) |
|
114 |
+ (connected nil)) |
|
115 | 115 |
(as:with-event-loop () |
116 | 116 |
(websocket-driver:start-connection client) |
117 | 117 |
(setf connected t) |
118 | 118 |
(as:with-interval (15) |
119 |
- (when connected |
|
120 |
- (restart-case (send-pings event-pump client) |
|
121 |
- (restart-server () |
|
122 |
- (websocket-driver:close-connection client) |
|
123 |
- (setf connected nil) |
|
124 |
- (clear-waiting-pings event-pump) |
|
125 |
- (as:with-delay (10) |
|
119 |
+ (when connected |
|
120 |
+ (restart-case (send-pings event-pump client) |
|
121 |
+ (restart-server () |
|
122 |
+ (websocket-driver:close-connection client) |
|
123 |
+ (setf connected nil) |
|
124 |
+ (clear-waiting-pings event-pump) |
|
125 |
+ (as:with-delay (10) |
|
126 | 126 |
(cl+ssl:reset-library) |
127 | 127 |
(websocket-driver:start-connection |
128 | 128 |
(setf client (funcall client-factory))) |
129 |
- (setf connected t)))))) |
|
129 |
+ (setf connected t)))))) |
|
130 | 130 |
(as:with-interval (0.01) |
131 |
- (when connected |
|
132 |
- (handle-work-queue event-pump)) |
|
133 |
- :event-cb (lambda (ev) |
|
134 |
- (format t "~&EVENT: ~a~%" ev)))))) |
|
131 |
+ (when connected |
|
132 |
+ (handle-work-queue event-pump)) |
|
133 |
+ :event-cb (lambda (ev) |
|
134 |
+ (format t "~&EVENT: ~a~%" ev)))))) |
|
135 | 135 |
|
136 | 136 |
(defun start-client (&key (queue-pair (make-instance 'queue-pair)) modules) |
137 | 137 |
(let* ((event-pump (make-instance 'event-pump :queue-pair queue-pair)) |
138 |
- (client-factory (op (make-client event-pump)))) |
|
138 |
+ (client-factory (op (make-client event-pump)))) |
|
139 | 139 |
(values event-pump |
140 |
- (bt:make-thread (lambda () |
|
140 |
+ (bt:make-thread (lambda () |
|
141 | 141 |
(network-loop event-pump |
142 | 142 |
client-factory |
143 | 143 |
modules)) |
144 |
- :name "Event Server" |
|
145 |
- :initial-bindings `((*api-token* . ,*api-token*)))))) |
|
144 |
+ :name "Event Server" |
|
145 |
+ :initial-bindings `((*api-token* . ,*api-token*)))))) |
|
146 | 146 |
|
147 | 147 |
(defmethod get-event-nonblocking ((event-pump event-pump) &key (object-as :hash-table)) |
148 | 148 |
(multiple-value-bind (message message-p) (chanl:recv (result-queue event-pump) :blockp nil) |
149 | 149 |
(values (when message-p |
150 |
- (yason:parse message :object-as object-as)) |
|
151 |
- message-p))) |
|
150 |
+ (yason:parse message :object-as object-as)) |
|
151 |
+ message-p))) |
|
152 | 152 |
|
153 | 153 |
(defmethod get-event ((queue-pair queue-pair) &key (object-as :hash-table)) |
154 | 154 |
(multiple-value-bind (message message-p) (chanl:recv (result-queue queue-pair)) |
155 | 155 |
(values (when message-p |
156 |
- (yason:parse message :object-as object-as)) |
|
157 |
- message-p))) |
|
156 |
+ (yason:parse message :object-as object-as)) |
|
157 |
+ message-p))) |
|
158 | 158 |
|
159 | 159 |
(defparameter *ignored-messages* '(:pong)) |
160 | 160 |
(defgeneric handle-message (type event-pump ts channel message) |
... | ... |
@@ -172,38 +172,38 @@ |
172 | 172 |
(format t "~&Was waiting on ~a pings," (waiting-pings event-pump)) |
173 | 173 |
(decf (waiting-pings event-pump)) |
174 | 174 |
(format t "after pong received for ~a, now waiting on ~a~%" |
175 |
- (gethash "reply_to" message) |
|
176 |
- (waiting-pings event-pump)))) |
|
175 |
+ (gethash "reply_to" message) |
|
176 |
+ (waiting-pings event-pump)))) |
|
177 | 177 |
|
178 | 178 |
(defmethod handle-message ((type (eql :message)) (event-pump event-pump) ts channel message) |
179 | 179 |
(format t "~&Received message ~s~%" message) |
180 | 180 |
(when-let* ((msg (gethash "text" message)) |
181 |
- (parsed-message (tokens msg))) |
|
181 |
+ (parsed-message (tokens msg))) |
|
182 | 182 |
(when (eql #\; (elt msg 0)) |
183 | 183 |
(handle-command event-pump message channel |
184 | 184 |
(plump:decode-entities |
185 | 185 |
(car parsed-message)) |
186 |
- (cdr parsed-message))))) |
|
186 |
+ (cdr parsed-message))))) |
|
187 | 187 |
|
188 | 188 |
(defun event-loop (event-pump) |
189 | 189 |
(loop with message with message-p |
190 |
- do (multiple-value-setq (message message-p) (get-event (queue-pair event-pump))) |
|
191 |
- when message-p do |
|
192 |
- (let ((type (gethash "type" message)) |
|
193 |
- (reply (gethash "reply_to" message)) |
|
194 |
- (ts (gethash "ts" message)) |
|
195 |
- (channel (gethash "channel" message))) |
|
196 |
- (cond (type |
|
197 |
- (handle-message (make-keyword (string-upcase type)) |
|
198 |
- event-pump ts channel message)) |
|
199 |
- (reply ))) |
|
200 |
- do (sleep 0.01))) |
|
190 |
+ do (multiple-value-setq (message message-p) (get-event (queue-pair event-pump))) |
|
191 |
+ when message-p do |
|
192 |
+ (let ((type (gethash "type" message)) |
|
193 |
+ (reply (gethash "reply_to" message)) |
|
194 |
+ (ts (gethash "ts" message)) |
|
195 |
+ (channel (gethash "channel" message))) |
|
196 |
+ (cond (type |
|
197 |
+ (handle-message (make-keyword (string-upcase type)) |
|
198 |
+ event-pump ts channel message)) |
|
199 |
+ (reply ))) |
|
200 |
+ do (sleep 0.01))) |
|
201 | 201 |
|
202 | 202 |
(defun coordinate-threads (&optional queue-pair) |
203 | 203 |
(let* ((event-pump (start-client :queue-pair queue-pair |
204 | 204 |
:modules '((hhgbot-augmented-assistant::js-executor))))) |
205 |
- (bt:make-thread (lambda () (event-loop event-pump)) |
|
206 |
- :name "Event Loop") |
|
205 |
+ (bt:make-thread (lambda () (event-loop event-pump)) |
|
206 |
+ :name "Event Loop") |
|
207 | 207 |
event-pump)) |
208 | 208 |
|
209 | 209 |
(defparameter *command-table* (make-hash-table :test 'equal)) |
... | ... |
@@ -215,21 +215,21 @@ |
215 | 215 |
(defmacro in-wq ((client-sym) &body body) |
216 | 216 |
`(let ((promise (blackbird-base:make-promise))) |
217 | 217 |
(values promise |
218 |
- (chanl:send (work-queue ,client-sym) |
|
219 |
- (lambda (,client-sym) |
|
220 |
- (declare (ignorable ,client-sym)) |
|
221 |
- (let ((result (progn ,@body))) |
|
222 |
- (blackbird-base:finish promise result) |
|
223 |
- result)))))) |
|
218 |
+ (chanl:send (work-queue ,client-sym) |
|
219 |
+ (lambda (,client-sym) |
|
220 |
+ (declare (ignorable ,client-sym)) |
|
221 |
+ (let ((result (progn ,@body))) |
|
222 |
+ (blackbird-base:finish promise result) |
|
223 |
+ result)))))) |
|
224 | 224 |
|
225 | 225 |
(defun queue-message (event-pump channel message &key quote thread) |
226 | 226 |
(let ((message (if quote (quote-output message) |
227 |
- message))) |
|
227 |
+ message))) |
|
228 | 228 |
(in-wq (event-pump) |
229 | 229 |
(send-message event-pump :message |
230 |
- :channel channel |
|
231 |
- :data message |
|
232 |
- :thread thread)))) |
|
230 |
+ :channel channel |
|
231 |
+ :data message |
|
232 |
+ :thread thread)))) |
|
233 | 233 |
|
234 | 234 |
(define-condition command-error () ()) |
235 | 235 |
(define-condition unsupported-args (command-error) ()) |
... | ... |
@@ -237,15 +237,15 @@ |
237 | 237 |
(defgeneric add-command ()) |
238 | 238 |
(defmacro define-command (name (event-pump ts channel &rest args) &body body) |
239 | 239 |
(let* ((command-sym (intern (string-upcase name))) |
240 |
- (has-rest (position '&rest args)) |
|
241 |
- (rest-sym (gensym "rest")) |
|
242 |
- (args (if has-rest |
|
243 |
- args |
|
244 |
- (append args `(&rest ,rest-sym))))) |
|
240 |
+ (has-rest (position '&rest args)) |
|
241 |
+ (rest-sym (gensym "rest")) |
|
242 |
+ (args (if has-rest |
|
243 |
+ args |
|
244 |
+ (append args `(&rest ,rest-sym))))) |
|
245 | 245 |
`(progn |
246 | 246 |
(defun ,command-sym (,event-pump ,ts ,channel ,@args) |
247 |
- (declare (ignorable ,event-pump ,ts ,@(when (not has-rest) `(,rest-sym)))) |
|
248 |
- ,@body) |
|
247 |
+ (declare (ignorable ,event-pump ,ts ,@(when (not has-rest) `(,rest-sym)))) |
|
248 |
+ ,@body) |
|
249 | 249 |
(setf (gethash ,name *command-table*) ',command-sym)))) |
250 | 250 |
|
251 | 251 |
(defun safe-apply (func event-pump message channel args) |
... | ... |
@@ -255,12 +255,12 @@ |
255 | 255 |
(defun handle-command (event-pump message channel command args) |
256 | 256 |
(declare (ignorable args)) |
257 | 257 |
(let* ((command (subseq command 1)) |
258 |
- (handler (gethash command *command-table*))) |
|
258 |
+ (handler (gethash command *command-table*))) |
|
259 | 259 |
(print (hash-table-alist *command-table*)) |
260 | 260 |
(terpri) |
261 | 261 |
(print command) |
262 | 262 |
(if handler |
263 |
- (safe-apply handler event-pump message channel args) |
|
263 |
+ (safe-apply handler event-pump message channel args) |
|
264 | 264 |
(queue-message event-pump channel |
265 | 265 |
(concat "I don't understand the command `" command "`.") |
266 | 266 |
:thread (ensure-thread message))))) |
... | ... |
@@ -270,19 +270,19 @@ |
270 | 270 |
(bt:make-thread |
271 | 271 |
(lambda () |
272 | 272 |
(handler-case |
273 |
- (let ((api-result (yason:parse |
|
274 |
- (babel:octets-to-string |
|
275 |
- (drakma:http-request (concat "https://slack.com/api/" method "?token=" *api-token*) |
|
276 |
- :method :post |
|
277 |
- :content (quri:url-encode-params |
|
278 |
- (loop for (key value) on args by #'cddr |
|
279 |
- collect (cons (string-downcase key) value))) |
|
280 |
- ))))) |
|
281 |
- ;todo error handling . . . |
|
282 |
- (resolve api-result)) |
|
283 |
- (t (c) |
|
284 |
- (format t "~&Received condition ~s~%" c) |
|
285 |
- (reject c))))))) |
|
273 |
+ (let ((api-result (yason:parse |
|
274 |
+ (babel:octets-to-string |
|
275 |
+ (drakma:http-request (concat "https://slack.com/api/" method "?token=" *api-token*) |
|
276 |
+ :method :post |
|
277 |
+ :content (quri:url-encode-params |
|
278 |
+ (loop for (key value) on args by #'cddr |
|
279 |
+ collect (cons (string-downcase key) value))) |
|
280 |
+ ))))) |
|
281 |
+ ;todo error handling . . . |
|
282 |
+ (resolve api-result)) |
|
283 |
+ (t (c) |
|
284 |
+ (format t "~&Received condition ~s~%" c) |
|
285 |
+ (reject c))))))) |
|
286 | 286 |
|
287 | 287 |
;; (defgeneric api-call (name args) |
288 | 288 |
;; (:method ((name symbol) (args list)) |
... | ... |
@@ -290,49 +290,49 @@ |
290 | 290 |
|
291 | 291 |
(defmacro define-api-wrapper (name required-args &rest args) |
292 | 292 |
(flet ((name-case (string) |
293 |
- (let ((parts (split-sequence #\- (string-downcase string)))) |
|
294 |
- (apply #'concatenate 'string |
|
295 |
- (car parts) |
|
296 |
- (mapcar #'string-capitalize (cdr parts)))))) |
|
293 |
+ (let ((parts (split-sequence #\- (string-downcase string)))) |
|
294 |
+ (apply #'concatenate 'string |
|
295 |
+ (car parts) |
|
296 |
+ (mapcar #'string-capitalize (cdr parts)))))) |
|
297 | 297 |
(let* ((api-method-name (name-case name))) |
298 | 298 |
`(progn (defun ,name (,@required-args &rest r &key ,@args) |
299 |
- (apply #'slack-api-call ,api-method-name |
|
300 |
- ,@(loop for req-arg in required-args |
|
301 |
- append (list (make-keyword req-arg) req-arg)) |
|
302 |
- r)) |
|
303 |
- (eval-when (:compile-toplevel :load-toplevel :execute) |
|
304 |
- (let ((*package* (find-package 'slacker.api))) |
|
305 |
- (import ',name) |
|
306 |
- (export ',name))))))) |
|
299 |
+ (apply #'slack-api-call ,api-method-name |
|
300 |
+ ,@(loop for req-arg in required-args |
|
301 |
+ append (list (make-keyword req-arg) req-arg)) |
|
302 |
+ r)) |
|
303 |
+ (eval-when (:compile-toplevel :load-toplevel :execute) |
|
304 |
+ (let ((*package* (find-package 'slacker.api))) |
|
305 |
+ (import ',name) |
|
306 |
+ (export ',name))))))) |
|
307 | 307 |
|
308 | 308 |
|
309 | 309 |
(defmacro define-api-wrappers (&body body) |
310 | 310 |
`(progn ,@(loop for (name required-args . rest) in body |
311 |
- collect `(define-api-wrapper ,name ,required-args ,@rest)))) |
|
311 |
+ collect `(define-api-wrapper ,name ,required-args ,@rest)))) |
|
312 | 312 |
|
313 | 313 |
(defun edit-message (ts channel text) |
314 | 314 |
(babel:octets-to-string |
315 | 315 |
(drakma:http-request "https://slack.com/api/chat.update" |
316 |
- :method :post |
|
317 |
- :content (concat "token=" *api-token* |
|
318 |
- "&channel=" channel |
|
319 |
- "&ts=" ts |
|
320 |
- "&text=" text)))) |
|
316 |
+ :method :post |
|
317 |
+ :content (concat "token=" *api-token* |
|
318 |
+ "&channel=" channel |
|
319 |
+ "&ts=" ts |
|
320 |
+ "&text=" text)))) |
|
321 | 321 |
|
322 | 322 |
(defmacro with-output-to-message ((stream event-pump channel &key quote thread) &body body) |
323 | 323 |
(once-only (event-pump channel quote) |
324 | 324 |
`(queue-message ,event-pump ,channel |
325 |
- (with-output-to-string (,stream) |
|
326 |
- ,@body) |
|
327 |
- :quote ,quote |
|
328 |
- :thread ,thread))) |
|
325 |
+ (with-output-to-string (,stream) |
|
326 |
+ ,@body) |
|
327 |
+ :quote ,quote |
|
328 |
+ :thread ,thread))) |
|
329 | 329 |
|
330 | 330 |
(defmacro with-thread-info ((ts thread-ts in-thread is-reply) message &body body) |
331 | 331 |
(once-only (message) |
332 | 332 |
`(let* ((,ts (gethash "ts" ,message)) |
333 |
- (,thread-ts (gethash "thread_ts" ,message)) |
|
334 |
- (,in-thread (not (null ,thread-ts))) |
|
335 |
- (,is-reply (and ,in-thread (string/= ,ts ,thread-ts)))) |
|
333 |
+ (,thread-ts (gethash "thread_ts" ,message)) |
|
334 |
+ (,in-thread (not (null ,thread-ts))) |
|
335 |
+ (,is-reply (and ,in-thread (string/= ,ts ,thread-ts)))) |
|
336 | 336 |
,@body))) |
337 | 337 |
|
338 | 338 |
(defun ensure-thread (message) |
... | ... |
@@ -349,13 +349,13 @@ |
349 | 349 |
|
350 | 350 |
(define-command "help" (event-pump message channel) |
351 | 351 |
(let ((*print-right-margin* (max (or *print-right-margin* 0) |
352 |
- 80))) |
|
352 |
+ 80))) |
|
353 | 353 |
(with-thread-info (ts thread-ts in-thread is-reply) message |
354 | 354 |
(format t "~&THREAD INFO: (ts ~s) (thread-ts ~s) (in-thread ~s) (is-reply ~s)~%" ts thread-ts in-thread is-reply) |
355 | 355 |
(with-output-to-message (s event-pump channel :thread (ensure-thread message)) |
356 |
- (format s "I understand these commands:~%~{`~a`~^ ~}" |
|
357 |
- (hash-table-keys *command-table*)) |
|
358 |
- :quote t)))) |
|
356 |
+ (format s "I understand these commands:~%~{`~a`~^ ~}" |
|
357 |
+ (hash-table-keys *command-table*)) |
|
358 |
+ :quote t)))) |
|
359 | 359 |
|
360 | 360 |
|
361 | 361 |
(defparameter *id* 0) |
... | ... |
@@ -365,9 +365,9 @@ |
365 | 365 |
(yason:encode |
366 | 366 |
(alist-hash-table |
367 | 367 |
`(("id" . ,*id*) |
368 |
- ("type" . "message") |
|
369 |
- ("channel" . ,channel) |
|
370 |
- ("text" . ,data))) |
|
368 |
+ ("type" . "message") |
|
369 |
+ ("channel" . ,channel) |
|
370 |
+ ("text" . ,data))) |
|
371 | 371 |
s))) |
372 | 372 |
|
373 | 373 |
|