Ircbot Alt-Genesis

While attempting to press trinque's ircbot including whaack's and ben_vulpes's patches, I ran into the issue of the genesis having been created using a differing hashing algorithm than that used for whaack's patch making pressing ircbot impossible using the available patches and genesis. Here you'll find a genesis including trinque's genesis and the changes from ben_vulpes's patch and whaack's patch.

logbot-genesis.vpatch
logbot-genesis.vpatch.asc

1 diff -uNr a/ircbot/INSTALL b/ircbot/INSTALL
2 --- a/ircbot/INSTALL false
3 +++ b/ircbot/INSTALL c4c41d96ddb71db32e8cd54c22e7250abbc52d51f4b25d8092dc094b4a84100949d0a74378fc33131d2d9a5144156a738f5a91d7e949922898993eb4384b4757
4 @@ -0,0 +1,19 @@
5 +INSTALL
6 +
7 + * Install SBCL (with sb-thread) and Quicklisp.
8 +
9 + * From the SBCL REPL:
10 + (ql:quickload :cl-irc)
11 +
12 + * Use V to press `ircbot`
13 +
14 +mkdir -p ~/src/ircbot
15 +cd ~/src/ircbot
16 +
17 +mkdir .wot
18 +cd .wot && wget http://trinque.org/trinque.asc && cd ..
19 +
20 +v.pl init http://trinque.org/src/ircbot
21 +v.pl press ircbot-genesis ircbot-genesis.vpatch
22 +
23 +ln -s ~/src/ircbot/ircbot-genesis ~/quicklisp/local-projects/ircbot
24 diff -uNr a/ircbot/README b/ircbot/README
25 --- a/ircbot/README false
26 +++ b/ircbot/README 6a76028622c6bb986d68d42b7b133221d3659d56da1bd5d4e8b39f0a6075a17d8b3ee33c8e37c7d4b3ec1f108ad940777d762bab01763a63742733a1445660d4
27 @@ -0,0 +1,8 @@
28 +README
29 +
30 +`ircbot` provides a simple CLOS class, `ircbot`, which will maintain a
31 +connection to a single IRC channel via `cl-irc`. The bot will handle
32 +ping/pong and detect failed connections, and is capable of
33 +authenticating with NickServ (using ghost when necessary to
34 +reacquire nick).
35 +
36 diff -uNr a/ircbot/USAGE b/ircbot/USAGE
37 --- a/ircbot/USAGE false
38 +++ b/ircbot/USAGE 20d07e6f190f6655a2884e60c1d6a7eccdd76d019797bb165c716a6919fb5161a31b1956b9dda7927839837a924ae6ea3d0c1a833458bbbd5765f76548d637d2
39 @@ -0,0 +1,14 @@
40 +USAGE
41 +
42 +(asdf:load-system :ircbot)
43 +(defvar *bot*)
44 +(setf *bot*
45 + (ircbot:make-ircbot
46 + "chat.freenode.net" 6667 "nick" "password" "#channel"))
47 +
48 +; connect in separate thread, returning thread
49 +(ircbot:ircbot-connect-thread *bot*)
50 +
51 +; or connect using the current thread
52 +; (ircbot:ircbot-connect *bot*)
53 +
54 diff -uNr a/ircbot/ircbot.asd b/ircbot/ircbot.asd
55 --- a/ircbot/ircbot.asd false
56 +++ b/ircbot/ircbot.asd 9dfba5c2bd97e5ffc2ab071786b14c05dfda1c898ef58a5d87ea020bde042bf76c0e88b78f6d4a4fbd453aabea58e4710bf717defa023dfe410d19ac01c4e2d9
57 @@ -0,0 +1,10 @@
58 +;;;; ircbot.asd
59 +
60 +(asdf:defsystem #:ircbot
61 + :description "ircbot"
62 + :author "Michael Trinque <mike@trinque.org>"
63 + :license "http://trilema.com/2015/a-new-software-licensing-paradigm/"
64 + :depends-on (#:cl-irc)
65 + :components ((:file "package")
66 + (:file "ircbot")))
67 +
68 diff -uNr a/ircbot/ircbot.lisp b/ircbot/ircbot.lisp
69 --- a/ircbot/ircbot.lisp false
70 +++ b/ircbot/ircbot.lisp 738a2c0ca77a69fc7805cbfc668da1b61e25e512d6d9f3bdf200968e39eb201bb87be83c6ae1411c6e6a5c7dd63524a5b5ab71d99a2813ac85fc5ac4360b3b17
71 @@ -0,0 +1,143 @@
72 +(in-package #:ircbot)
73 +
74 +(defvar *max-lag* 60)
75 +(defvar *ping-freq* 30)
76 +
77 +
78 +(defclass ircbot ()
79 + ((connection :accessor ircbot-connection :initform nil)
80 + (channels :reader ircbot-channels :initarg :channels)
81 + (server :reader ircbot-server :initarg :server)
82 + (port :reader ircbot-port :initarg :port)
83 + (nick :reader ircbot-nick :initarg :nick)
84 + (password :reader ircbot-password :initarg :password)
85 + (connection-security :reader ircbot-connection-security
86 + :initarg :connection-security
87 + :initform :none)
88 + (run-thread :accessor ircbot-run-thread :initform nil)
89 + (ping-thread :accessor ircbot-ping-thread :initform nil)
90 + (lag :accessor ircbot-lag :initform nil)
91 + (lag-track :accessor ircbot-lag-track :initform nil)))
92 +
93 +(defmethod ircbot-check-nick ((bot ircbot) message)
94 + (destructuring-bind (target msgtext) (arguments message)
95 + (declare (ignore msgtext))
96 + (if (string= target (ircbot-nick bot))
97 + (ircbot-nickserv-auth bot)
98 + (ircbot-nickserv-ghost bot))))
99 +
100 +(defmethod ircbot-connect :around ((bot ircbot))
101 + (let ((conn (connect :nickname (ircbot-nick bot)
102 + :server (ircbot-server bot)
103 + :port (ircbot-port bot)
104 + :connection-security (ircbot-connection-security bot))))
105 + (setf (ircbot-connection bot) conn)
106 + (call-next-method)
107 + (read-message-loop conn)))
108 +
109 +(defmethod ircbot-connect ((bot ircbot))
110 + (let ((conn (ircbot-connection bot)))
111 + (add-hook conn 'irc-err_nicknameinuse-message (lambda (message)
112 + (declare (ignore message))
113 + (ircbot-randomize-nick bot)))
114 + (add-hook conn 'irc-kick-message (lambda (message)
115 + (declare (ignore message))
116 + (map nil
117 + (lambda (c) (join (ircbot-connection bot) c))
118 + (ircbot-channels bot))))
119 + (add-hook conn 'irc-notice-message (lambda (message)
120 + (ircbot-handle-nickserv bot message)))
121 + (add-hook conn 'irc-pong-message (lambda (message)
122 + (ircbot-handle-pong bot message)))
123 + (add-hook conn 'irc-rpl_welcome-message (lambda (message)
124 + (ircbot-start-ping-thread bot)
125 + (ircbot-check-nick bot message)))))
126 +
127 +(defmethod ircbot-connect-thread ((bot ircbot))
128 + (setf (ircbot-run-thread bot)
129 + (sb-thread:make-thread (lambda () (ircbot-connect bot))
130 + :name "ircbot-run")))
131 +
132 +(defmethod ircbot-disconnect ((bot ircbot) &optional (quit-msg "..."))
133 + (sb-sys:without-interrupts
134 + (quit (ircbot-connection bot) quit-msg)
135 + (setf (ircbot-lag-track bot) nil)
136 + (setf (ircbot-connection bot) nil)
137 + (if (not (null (ircbot-run-thread bot)))
138 + (sb-thread:terminate-thread (ircbot-run-thread bot)))
139 + (if (not (or (null (ircbot-ping-thread bot)) (equal sb-thread:*current-thread* (ircbot-ping-thread bot))))
140 + (sb-thread:terminate-thread (ircbot-ping-thread bot)))))
141 +
142 +(defmethod ircbot-reconnect ((bot ircbot) &optional (quit-msg "..."))
143 + (let ((threaded-p (not (null (ircbot-run-thread bot)))))
144 + (ircbot-disconnect bot quit-msg)
145 + (if threaded-p
146 + (ircbot-connect-thread bot)
147 + (ircbot-connect bot))))
148 +
149 +(defmethod ircbot-handle-nickserv ((bot ircbot) message)
150 + (let ((conn (ircbot-connection bot)))
151 + (if (string= (host message) "services.")
152 + (destructuring-bind (target msgtext) (arguments message)
153 + (declare (ignore target))
154 + (cond ((string= msgtext "This nickname is registered. Please choose a different nickname, or identify via /msg NickServ identify <password>.")
155 + (ircbot-nickserv-auth bot))
156 + ((string= msgtext (format nil "~A has been ghosted." (ircbot-nick bot)))
157 + (nick conn (ircbot-nick bot)))
158 + ((string= msgtext (format nil "~A is not online." (ircbot-nick bot)))
159 + (ircbot-nickserv-auth bot))
160 + ((string= msgtext (format nil "You are now identified for ~A." (ircbot-nick bot)))
161 + (map nil (lambda (c) (join conn c)) (ircbot-channels bot))))))))
162 +
163 +(defmethod ircbot-handle-pong ((bot ircbot) message)
164 + (destructuring-bind (server ping) (arguments message)
165 + (declare (ignore server))
166 + (let ((response (ignore-errors (parse-integer ping))))
167 + (when response
168 + (setf (ircbot-lag-track bot) (delete response (ircbot-lag-track bot) :test #'=))
169 + (setf (ircbot-lag bot) (- (received-time message) response))))))
170 +
171 +(defmethod ircbot-nickserv-auth ((bot ircbot))
172 + (privmsg (ircbot-connection bot) "NickServ"
173 + (format nil "identify ~A" (ircbot-password bot))))
174 +
175 +(defmethod ircbot-nickserv-ghost ((bot ircbot))
176 + (privmsg (ircbot-connection bot) "NickServ"
177 + (format nil "ghost ~A ~A" (ircbot-nick bot) (ircbot-password bot))))
178 +
179 +(defmethod ircbot-randomize-nick ((bot ircbot))
180 + (nick (ircbot-connection bot)
181 + (format nil "~A-~A" (ircbot-nick bot) (+ (random 90000) 10000))))
182 +
183 +(defmethod ircbot-send-message ((bot ircbot) target message-text)
184 + (privmsg (ircbot-connection bot) target message-text))
185 +
186 +(defmethod ircbot-start-ping-thread ((bot ircbot))
187 + (let ((conn (ircbot-connection bot)))
188 + (setf (ircbot-ping-thread bot)
189 + (sb-thread:make-thread
190 + (lambda ()
191 + (loop
192 + do (progn (sleep *ping-freq*)
193 + (let ((ct (get-universal-time)))
194 + (push ct (ircbot-lag-track bot))
195 + (ping conn (princ-to-string ct))))
196 + until (ircbot-timed-out-p bot))
197 + (ircbot-reconnect bot))
198 + :name "ircbot-ping"))))
199 +
200 +(defmethod ircbot-timed-out-p ((bot ircbot))
201 + (loop
202 + with ct = (get-universal-time)
203 + for v in (ircbot-lag-track bot)
204 + when (> (- ct v) *max-lag*)
205 + do (return t)))
206 +
207 +
208 +(defun make-ircbot (server port nick password channels)
209 + (make-instance 'ircbot
210 + :server server
211 + :port port
212 + :nick nick
213 + :password password
214 + :channels channels))
215 diff -uNr a/ircbot/manifest b/ircbot/manifest
216 --- a/ircbot/manifest false
217 +++ b/ircbot/manifest 8a535c4a26e5fba0aa52c44bfcd84176de82568ddd7e98e8fb84ab48b5dbc0bc315c09f37c8eb7201a88fb804a18712d1a876f02e06552157ebefc63a123a9c4
218 @@ -0,0 +1 @@
219 +658020 ircbot_genesis thimbronion This genesis combines trinque's genesis with ben_vulpes' multi-channel fix and whaack's reconnection fix. Theses patches were generated using differing hash algos and can not be applied by any existing v implementation and I do not see any reason that anyone would find ircbot usable without any of them.
220 diff -uNr a/ircbot/package.lisp b/ircbot/package.lisp
221 --- a/ircbot/package.lisp false
222 +++ b/ircbot/package.lisp d186f3af63443337d23a0bfbaae79246fae2b2781acb53109132b42f84cf46acabf1fe12f2aba00c452e679c721ca955daaf302e1a04a56fccb8125d95e1527c
223 @@ -0,0 +1,18 @@
224 +;;;; package.lisp
225 +
226 +(defpackage :ircbot
227 + (:use :cl
228 + :cl-irc)
229 + (:export :make-ircbot
230 + :ircbot
231 + :ircbot-connect
232 + :ircbot-connect-thread
233 + :ircbot-disconnect
234 + :ircbot-reconnect
235 + :ircbot-connection
236 + :ircbot-channels
237 + :ircbot-send-message
238 + :ircbot-server
239 + :ircbot-port
240 + :ircbot-nick
241 + :ircbot-lag))
242 /

One Response to “Ircbot Alt-Genesis”

  1. whaack says:

    Thanks for doing this. For practical use, one may want to add a handler case in the reconnect function that catches network related errors. The handler case should recall the reconnect function; this way the reconnect function keeps trying while the network is down rather than just failing once and giving up. I'll post the relevant code when I write it for my block explorer.

Leave a Reply