tree checksum vpatch file split hunks

all signers:

antecedents:

press order:

logbot-genesis

patch:

-
+ AE93B514E6A6BA3861C1099BB3FA536525F47F19E7CDC0B411A0EAA6159B1D75A522CA0611BE5559EC63B1BFDC90E9C2A4D6872D741DF0D768CD48BE7ECDEABF
logbot/INSTALL
(0 . 0)(1 . 26)
5 INSTALL
6
7 * Install `ircbot`.
8
9 * From the SBCL REPL:
10 (ql:quickload :cl-irc)
11 (ql:quickload :cl-postgres)
12 (ql:quickload :postmodern)
13
14 * Use V to press `logbot`
15
16 mkdir -p ~/src/logbot
17 cd ~/src/logbot
18
19 mkdir .wot
20 cd .wot && wget http://trinque.org/trinque.asc && cd ..
21
22 v.pl init http://trinque.org/src/logbot
23 v.pl press logbot-genesis logbot-genesis.vpatch
24
25 ln -s ~/src/logbot/logbot-genesis ~/quicklisp/local-projects/logbot
26
27 * Create a PostgreSQL database with UTF-8 encoding, then load logbot.sql
28 into that database:
29
30 psql -f logbot.sql mydb
-
+ 9D7CA23668DF545B7ED07857CC8965FB65AB980FD540CEBC2CDD96C2F556D5FB65EB149233DC777AF7BE1BA8243CA607BD6A68D8EA991D4A2666BE617447682D
logbot/README
(0 . 0)(1 . 7)
35 README
36
37 `logbot` extends `ircbot` to provide an interface to a single IRC
38 channel from PostgreSQL, writing all messages to a `log` table and
39 reading messages to be sent from `outbox` in a specified database. By
40 listening to pg_notify channels, services connected to PostgreSQL can
41 react when new log lines are inserted.
-
+ EB195D717F53AC62D3BA4CABF2960B87BD30184A128F42DCC856F1757FFFA2EF4E74D5C8976DFC0F76809286609749B150FF90B47D325549F7ADF9971F05FF00
logbot/USAGE
(0 . 0)(1 . 14)
46 USAGE
47
48 (asdf:load-system :logbot)
49 (defvar *bot*)
50 (setf *bot*
51 (logbot:make-logbot
52 "chat.freenode.net" 6667 "nick" "password" "#channel"
53 '("db-name" "db-user" "db-password" "db-host")))
54
55 ; connect in separate thread, returning thread
56 (logbot:ircbot-connect-thread *bot*)
57
58 ; or connect using the current thread
59 ; (logbot:ircbot-connect *bot*)
-
+ 17258C61CC8878A2AC72FCCA188892E35B1FF69A069B93B4FB633DA9E39447DA66DC50D6AD2AF53259700F78B187970E9BB75C0BACA03318C65246A29A2D5FE5
logbot/logbot.asd
(0 . 0)(1 . 13)
64 ;;;; logbot.asd
65
66 (asdf:defsystem #:logbot
67 :description "logbot"
68 :author "Michael Trinque <mike@trinque.org>"
69 :license "http://trilema.com/2015/a-new-software-licensing-paradigm/"
70 :depends-on (#:cl-irc
71 #:cl-postgres
72 #:ircbot
73 #:postmodern)
74 :components ((:file "package")
75 (:file "logbot")))
76
-
+ 34C09AAE0020F81B9DD9A9120DAE84C0E996B578041E837785E814409F69D0D587A21C0C1454C6E39039C8CA3FD135092D4EFD006F39F0E47AC87F0314F6F92D
logbot/logbot.lisp
(0 . 0)(1 . 93)
82 (in-package #:logbot)
83
84
85 (defun get-and-purge-outbox-messages (db)
86 (postmodern:with-connection db
87 (postmodern:query
88 "with deleted as (
89 delete from outbox
90 returning target, message, queued_at
91 )
92 select target,
93 message
94 from deleted
95 order by queued_at"
96 :rows)))
97
98 (defun make-log-entry (db target message host source user)
99 (postmodern:with-connection db
100 (postmodern:execute
101 "insert into log (target, message, host, source, \"user\")
102 values ($1, $2, $3, $4, $5)"
103 target
104 message
105 (if (string= "" host) :null host)
106 source
107 (if (null user) :null user))))
108
109
110 (defclass logbot (ircbot)
111 ((pg-thread :accessor logbot-pg-thread :initform nil)
112 (db :reader logbot-db :initarg :db)))
113
114 (defmethod ircbot-connect :after ((bot logbot))
115 (let ((conn (ircbot-connection bot)))
116 (add-hook conn 'irc-mode-message (lambda (message)
117 (logbot-check-mode bot message)))
118 (add-hook conn 'irc-privmsg-message (lambda (message)
119 (destructuring-bind (target message-text) (arguments message)
120 (make-log-entry (logbot-db bot)
121 target
122 message-text
123 (host message)
124 (source message)
125 (user message)))))))
126
127 (defmethod ircbot-send-message :after ((bot logbot) target message-text)
128 (let* ((b-connection (ircbot-connection bot))
129 (b-user (user b-connection)))
130 (make-log-entry (logbot-db bot)
131 target
132 message-text
133 (hostname b-user)
134 (nickname b-user)
135 (username b-user))))
136
137 (defmethod logbot-check-mode ((bot logbot) message)
138 (if (= 3 (length (arguments message)))
139 (destructuring-bind (channel mode nick) (arguments message)
140 (when (and (string= (host message) "services.")
141 (string= channel (ircbot-channel bot))
142 (or (string= mode "+o") (string= mode "+v"))
143 (string= nick (ircbot-nick bot)))
144
145 (when (null (logbot-pg-thread bot))
146 (logbot-start-pg-thread bot)
147 (logbot-send-outbox bot))))))
148
149 (defmethod logbot-send-outbox ((bot logbot))
150 (loop
151 for (target message)
152 in (get-and-purge-outbox-messages (logbot-db bot))
153 do (ircbot-send-message bot target message)))
154
155 (defmethod logbot-start-pg-thread ((bot logbot))
156 (setf (logbot-pg-thread bot)
157 (sb-thread:make-thread
158 (lambda ()
159 (postmodern:with-connection (logbot-db bot)
160 (postmodern:execute "listen outbox_new_message")
161 (loop
162 (if (string= (cl-postgres:wait-for-notification postmodern:*database*)
163 "outbox_new_message")
164 (logbot-send-outbox bot)))))
165 :name "logbot-pg")))
166
167 (defun make-logbot (server port nick password channel db)
168 (make-instance 'logbot
169 :server server
170 :port port
171 :nick nick
172 :password password
173 :channel channel
174 :db db))
-
+ DBC265A63C34C6B682694C8776AA4640C83BA92DCA5400F0BD393F6A9EB5D3672011C234C3D04A7AD074F3FCE560D71D78201F4BBCB506C12ED6CC90D3C59017
logbot/logbot.sql
(0 . 0)(1 . 48)
179 set search_path = public;
180
181 create extension if not exists plpgsql;
182 create extension if not exists pgcrypto;
183 create extension if not exists "uuid-ossp";
184
185 create table log (
186 id uuid primary key default gen_random_uuid(),
187 target text not null,
188 message text not null,
189 host text,
190 source text not null,
191 "user" text,
192 received_at timestamp without time zone not null default (now() at time zone 'utc')
193 );
194
195 create index log_received_at on log (received_at);
196 create index log_target on log (target);
197 create index log_source on log (source);
198
199 create or replace function log_insert_notify () returns trigger as $$
200 begin
201 perform pg_notify('log_new_message', NEW.id::text);
202 return NEW;
203 end;
204 $$ language plpgsql;
205
206 create trigger log_insert_notify_trigger
207 after insert on log
208 for each row execute procedure log_insert_notify ();
209
210 create table outbox (
211 id serial primary key,
212 target text not null,
213 message text not null,
214 queued_at timestamp without time zone not null default (now() at time zone 'utc')
215 );
216
217 create or replace function outbox_insert_notify () returns trigger as $$
218 begin
219 perform pg_notify('outbox_new_message', NEW.id::text);
220 return NEW;
221 end;
222 $$ language plpgsql;
223
224 create trigger outbox_insert_notify_trigger
225 after insert on outbox
226 for each row execute procedure outbox_insert_notify ();
-
+ 29A3142E5A5A5B814921B49C16571B2D0359CDCA2DFDC9CA4463734F066B1E087A4ECECB6341F1667EF26F6A97B0B8CE326CEDAF2539D2CFD64CA4C3FB6551DF
logbot/package.lisp
(0 . 0)(1 . 20)
231 ;;;; package.lisp
232
233 (defpackage :logbot
234 (:use :cl
235 :cl-irc
236 :ircbot)
237 (:export :make-logbot
238 :logbot
239 :ircbot-connect
240 :ircbot-connect-thread
241 :ircbot-disconnect
242 :ircbot-reconnect
243 :ircbot-connection
244 :ircbot-channel
245 :ircbot-send-message
246 :ircbot-server
247 :ircbot-port
248 :ircbot-nick
249 :ircbot-lag))
250