tree checksum vpatch file split hunks
all signers: spyked
antecedents:
press order:
trilemabot-voicer | spyked |
patch:
(0 . 0)(1 . 22)
5 INSTALL
6
7 * Install and load cl-irc and its dependencies
8
9 * Install ircbot
10
11 * Use V to press `trilemabot`
12
13 mkdir -p ~/src/trilemabot
14 cd ~/src/trilemabot
15
16 mkdir .wot
17 cd .wot && wget http://lucian.mogosanu.ro/spyked.asc && cd ..
18
19 v.pl init http://lucian.mogosanu.ro/src/trilemabot/
20 v.pl press trilemabot-voicer trilemabot-voicer.vpatch
21
22 * Load `trilemabot` via Quicklisp or directly using ASDF:
23
24 (dolist (path '("/path/to/ircbot/" "~/src/trilemabot/trilemabot-voicer/"))
25 (pushnew path asdf:*central-registry* :test #'string=))
26 (asdf:load-system :trilemabot)
-(0 . 0)(1 . 12)
31 README
32
33 `trilemabot` extends `ircbot` with #trilema-specific functionality. See the
34 following for more details:
35
36 * http://trilema.com/2016/how-to-participate-in-the-affairs-of-the-most-serene-republic/
37 * http://trilema.com/2016/trilema-bot-spec/
38 * http://thetarpit.org/posts/y04/072-trilemabot-i.html
39
40 Currently the following functionalities are implemented:
41
42 * self-voicing with deedbot, using a list of pre-provided OTPs
-(0 . 0)(1 . 37)
47 USAGE
48
49 (asdf:load-system :trilemabot)
50 (defvar *bot*)
51 (setq *bot*
52 (trlb:make-trilemabot
53 "chat.freenode.net" 6667 "nick" "password" '("#trilema")))
54
55 ;; connect in separate thread, returning thread
56 (ircbot:ircbot-connect-thread *bot*)
57
58 ;;;; 1. Self-voicing
59
60 ;; ask for n !!up OTPs from deedbot
61 (loop for i from 1 to n do
62 (trlb:trilemabot-send-up *bot*)
63 (sleep 0.5))
64
65 ;; get messages received from deedbot
66 (trlb:trilemabot-inbox *bot*)
67
68 ;; add decrypted !!up OTPs
69 (trlb:trilemabot-add-voice-otps *bot*
70 "decrypted-otp-1" "decrypted-otp2" ... "decrypted-otpn")
71
72 ;; get the list of !!up OTPs
73 (trlb:trilemabot-voice-otp-stash *bot*)
74
75 ;; save !!up OTPs to disk
76 (trlb:trilemabot-save-voice-otp-stash *bot* "voice-otps.sexp")
77
78 ;; self-voice
79 (trlb:trilemabot-voice *bot*)
80
81 ;; if `voice-otp-stash' is not empty, the bot will automatically
82 ;; self-voice on reconnect
83 (ircbot:ircbot-reconnect *bot*)
-(0 . 0)(1 . 19)
88 ;;;; package.lisp
89
90 (in-package #:cl-user)
91
92 (defpackage #:trilemabot
93 (:use #:cl #:cl-irc #:ircbot)
94 (:nicknames #:trlb)
95 (:export #:trilemabot
96 #:trilemabot-voice-otp-stash
97 #:trilemabot-inbox
98 #:trilemabot-join-channel
99 #:trilemabot-part-channel
100 #:trilemabot-handle-privmsg
101 #:trilemabot-check-mode
102 #:trilemabot-voice
103 #:trilemabot-add-voice-otps
104 #:trilemabot-send-up
105 #:trilemabot-send-otp
106 #:trilemabot-save-voice-otp-stash))
-(0 . 0)(1 . 10)
111 ;;;; trilemabot.asd
112
113 (asdf:defsystem #:trilemabot
114 :description "trilemabot"
115 :author "Lucian Mogosanu <lucian@mogosanu.ro>"
116 :license "http://trilema.com/2015/a-new-software-licensing-paradigm/"
117 :depends-on (#:cl-irc
118 #:ircbot)
119 :components ((:file "package")
120 (:file "trilemabot")))
-(0 . 0)(1 . 120)
125 ;;;; trilemabot.lisp
126
127 (in-package #:trilemabot)
128
129 ;; These are used to check that we're joining #trilema; make sure that
130 ;; your bot is configured accordingly if you want to use
131 ;; #trilema-specific functionality.
132 (defparameter *trilema-server* ".freenode.net")
133 (defparameter *trilema-channel* "#trilema")
134 (defparameter *trilema-deedbot-nick* "deedbot")
135
136 (defclass trilemabot (ircbot)
137 ((in-chan :accessor trilemabot-in-chan :initform nil)
138 (voiced :accessor trilemabot-voiced :initform nil)
139 (voice-otp-stash :accessor trilemabot-voice-otp-stash
140 :initarg :voice-otp-stash
141 :initform nil)
142 (inbox :accessor trilemabot-inbox
143 :initform nil)))
144
145 (defmethod ircbot-connect :after ((bot trilemabot))
146 (with-slots (connection) bot
147 (add-hook connection 'irc-join-message
148 #'(lambda (message) (trilemabot-join-channel bot message)))
149 (add-hook connection 'irc-part-message
150 #'(lambda (message) (trilemabot-part-channel bot message)))
151 (add-hook connection 'irc-privmsg-message
152 #'(lambda (message) (trilemabot-handle-privmsg bot message)))
153 (add-hook connection 'irc-mode-message
154 #'(lambda (message) (trilemabot-check-mode bot message)))))
155
156 (defmethod ircbot-disconnect :after ((bot trilemabot) &optional (quit-msg ""))
157 (declare (ignore quit-msg))
158 (with-slots (in-chan voiced) bot
159 (setf in-chan nil
160 voiced nil)))
161
162 (defmethod trilemabot-join-channel ((bot trilemabot) message)
163 (destructuring-bind (channel) (arguments message)
164 (when (and (string= (source message) (ircbot-nick bot))
165 (string= channel *trilema-channel*)
166 (search *trilema-server* (ircbot-server bot)))
167 (setf (trilemabot-in-chan bot) t)
168 (trilemabot-voice bot))))
169
170 (defmethod trilemabot-part-channel ((bot trilemabot) message)
171 (let ((channel (car (arguments message))))
172 (when (and (string= (source message) (ircbot-nick bot))
173 (string= channel *trilema-channel*)
174 (search *trilema-server* (ircbot-server bot)))
175 (setf (trilemabot-in-chan bot) nil
176 (trilemabot-voiced bot) nil))))
177
178 (defmethod trilemabot-handle-privmsg ((bot trilemabot) message)
179 (destructuring-bind (target message-text) (arguments message)
180 (when (and (string= (source message) *trilema-deedbot-nick*)
181 (string= target (ircbot-nick bot)))
182 (format *standard-output* "<~a>: ~a~%"
183 (source message) message-text)
184 (push (list :from (source message)
185 :time (received-time message)
186 :message message-text)
187 (trilemabot-inbox bot)))))
188
189 (defmethod trilemabot-check-mode ((bot trilemabot) message)
190 (when (= 3 (length (arguments message))) ; mode change for user in chan
191 (destructuring-bind (channel mode nick) (arguments message)
192 (when (and (string= channel *trilema-channel*)
193 (string= nick (ircbot-nick bot)))
194 (cond
195 ((or (string= mode "+o")
196 (string= mode "+v")) (setf (trilemabot-voiced bot) t))
197 ((or (string= mode "-o")
198 (string= mode "-v")) (setf (trilemabot-voiced bot) nil)))))))
199
200 (defmethod trilemabot-add-voice-otps ((bot trilemabot) &rest otps)
201 (with-slots (voice-otp-stash) bot
202 (setf voice-otp-stash (nconc voice-otp-stash otps))))
203
204 (defmethod trilemabot-voice ((bot trilemabot))
205 (with-slots (voice-otp-stash) bot
206 (if voice-otp-stash
207 (trilemabot-send-otp bot (pop voice-otp-stash))
208 (format *standard-output* "[trilemabot ~a@~a] No OTPs available.~%"
209 (ircbot-nick bot) (ircbot-server bot)))))
210
211 (defmethod trilemabot-send-up ((bot trilemabot) &optional nick)
212 (ircbot-send-message bot *trilema-deedbot-nick*
213 (make-bot-command "!!up"
214 (or nick (ircbot-nick bot)))))
215
216 (defmethod trilemabot-send-otp ((bot trilemabot) otp)
217 (ircbot-send-message bot *trilema-deedbot-nick*
218 (make-bot-command "!!v" otp)))
219
220 (defun make-bot-command (command &rest arguments)
221 "Make raw bot command string consisting of `command' and
222 space-separated `arguments'."
223 (with-output-to-string (out)
224 (write-string command out)
225 (dolist (arg arguments)
226 (write-string " " out)
227 (write-string arg out))))
228
229 (defmethod trilemabot-save-voice-otp-stash ((bot trilemabot) filespec)
230 (with-open-file (out filespec
231 :direction :output
232 :if-exists :supersede
233 :if-does-not-exist :create)
234 (print (trlb:trilemabot-voice-otp-stash bot) out)
235 (finish-output out)))
236
237 (defun make-trilemabot (server port nick password channels &optional voice-otps)
238 (make-instance 'trilemabot
239 :server server
240 :port port
241 :nick nick
242 :password password
243 :channels channels
244 :voice-otp-stash voice-otps))