Add feedbot-iii draft
authorLucian Mogosanu <lucian@mogosanu.ro>
Thu, 25 Apr 2019 09:39:29 +0000 (12:39 +0300)
committerLucian Mogosanu <lucian@mogosanu.ro>
Thu, 25 Apr 2019 09:39:29 +0000 (12:39 +0300)
drafts/000-feedbot-iii.markdown [new file with mode: 0644]

diff --git a/drafts/000-feedbot-iii.markdown b/drafts/000-feedbot-iii.markdown
new file mode 100644 (file)
index 0000000..e75ab2f
--- /dev/null
@@ -0,0 +1,173 @@
+---
+postid: 000
+title: Feedbot [iii]: the IRC bot
+date: April 25, 2019
+author: Lucian MogoČ™anu
+tags: tech, tmsr
+---
+
+All the basic building blocks pertaining to RSS functionality --
+i.e. the [checker][feedbot-i] and the [announcer][feedbot-ii] -- being
+in place, we conclude the [Feedbot][feedbot] series with:
+
+* The [V patch][feedbot-irc.vpatch]; and
+* my [seal][feedbot-irc.vpatch.spyked.sig].
+
+The patch in this episode introduces the following changes:
+
+* Some methods are removed, due to their retrospective uselessness;
+  some methods are added, due to them being found useful for both IRC
+  implementation and maintenance operations.
+* Auxiliary functions are provided in order to handle IRC operation
+  and Feedbot command argument parsing.
+* Most importantly, functionality is added to: manage the bot state;
+  glue to Ircbot and adapt the announcer to IRC; and implement
+  [Trilemabot][trilemabot] commands.
+
+The remainder of this post will detail the last bullet above. The
+reader is however encouraged to read the [V patch][feedbot-irc.vpatch]
+in its entirety, to get a broader image of the changes.
+
+**VII. State management**
+
+Feedbot state is a list of the form:
+
+~~~~ {.commonlisp}
+(feed-db msg-queue)
+~~~~
+
+where `feed-db` is a feed db and `msg-queue` is a message queue.
+
+Feedbot state is kept persistent using principally the feedbot
+`save-state` and `load-state` methods:
+
+~~~~ {.commonlisp}
+(defmethod feedbot-save-state ((bot feedbot) &optional (path "state.sexp"))
+  "Save bot state to disk location given by `path'."
+  (let ((feed-db (with-feed-db (feed-db) bot feed-db))
+        (msg-queue (with-msg-queue (msg-queue) bot msg-queue)))
+    (with-open-file (out path
+                         :direction :output
+                         :if-does-not-exist :create
+                         :if-exists :supersede)
+      (write (list feed-db msg-queue) :stream out)
+      nil)))
+
+(defmethod feedbot-load-state ((bot feedbot) &optional (path "state.sexp"))
+  "Load bot state from disk location given by `path'.
+
+This method throws an error condition if the bot contains pre-existing
+state, i.e. `feed-db' and `msg-queue' are non-NIL."
+  (with-slots (feed-db msg-queue) bot
+    (assert (not feed-db))
+    (assert (not msg-queue)))
+  (feedbot-reload-state bot path))
+~~~~
+
+**VIII. Ircbot glue**
+
+IRC glue:
+
+**a\.** implements [entry announcer][announcer] functionality:
+
+~~~~ {.commonlisp}
+(defun announce-irc! (bot msg)
+  (announce-stdout! msg)
+  (let ((rcpt (get-msg-to! msg))
+        (entry (get-msg-entry! msg)))
+    (ircbot-send-message bot rcpt
+                         (format nil "~a << ~a -- ~a~%"
+                                 (get-entry-link entry)
+                                 (get-msg-feed-title! msg)
+                                 (get-entry-title entry)))))
+~~~~
+
+**b\.** starts the checker and announcer threads on rpl_welcome:
+
+~~~~ {.commonlisp}
+(defun feedbot-rpl_welcome (bot message)
+  (declare (ignore message))
+  (feedbot-start-checker-thread bot)
+  (feedbot-start-announcer-thread bot))
+~~~~
+
+**c\.** sends messages to online nicks on rpl_ison
+
+~~~~ {.commonlisp}
+(defun feedbot-rpl_ison (bot message)
+  ;; Only when our reply contains some nicks...
+  (when (cdr (arguments message))
+    (let ((nicks (parse-ison (cadr (arguments message)))))
+      ;; Process messages...
+      (feedbot-process-msg-queue
+       bot #'(lambda (msg)
+               ;; Only when msg not send and :to is online...
+               (when (and (not (get-msg-sent! msg))
+                          (member (get-msg-to! msg) nicks
+                                  :test #'string=))
+                ;; Wait a bit
+                (sleep *announce-delay*)
+                 ;; Announce and mark as sent.
+                 (announce-irc! bot msg)
+                 (set-msg-sent! msg)))))))
+~~~~
+
+**d\.** implements ircbot-{connect,disconnect} routines
+
+~~~~ {.commonlisp}
+(defmethod ircbot-connect :after ((bot feedbot))
+  (feedbot-load-state bot)
+  (let ((conn (ircbot-connection bot)))
+    (add-hook conn 'irc-rpl_welcome-message
+              #'(lambda (message)
+                  (feedbot-rpl_welcome bot message)))
+    (add-hook conn 'irc-rpl_ison-message
+              #'(lambda (message)
+                  (feedbot-rpl_ison bot message)))))
+
+(defmethod ircbot-disconnect :after ((bot feedbot)
+                                     &optional (quit-msg "feedbot out"))
+  (declare (ignore quit-msg))
+  (with-slots (db-mutex queue-mutex checker-thread announcer-thread) bot
+    (ignore-errors
+      (release-mutex db-mutex :if-not-owner :force)
+      (release-mutex queue-mutex :if-not-owner :force)
+      (terminate-thread checker-thread)
+      (terminate-thread announcer-thread))
+    (setf checker-thread nil
+          announcer-thread nil)
+    (feedbot-flush-state bot)))
+~~~~
+
+**IX. Trilemabot commands**
+
+Consult [the feedbot manual][feedbot-manual] for more details.
+
+~~~~ {.commonlisp}
+(trilemabot-define-cmd (:help bot message target arguments)
+  (declare (ignore arguments))
+  (ircbot-send-message bot (response-rcpt bot message target)
+          "http://thetarpit.org/posts/y05/081-feedbot-manual.html"))
+~~~~
+
+**Post codex:** In total, Feedbot weighs circa nine hundred lines of
+code, of which almost a hundred comprise auxiliary functionality
+(parsing, sanitization and low-level IRC code), the rest being mostly
+Feedbot mechanism. Of these, about 23% are comments and another 7% are
+inline function documentation strings.
+
+The mechanism is, as far as I'm concerned, done. There are some
+operator-side bits missing (e.g. bulk adding/removal of feeds), but
+then again, some of them can be easily scripted, while others are more
+indicative of brain-fixing rather than any imagined code-fixing.
+
+Bug fixes and other comments are, as usual, more than welcome.
+
+[feedbot-i]: /posts/y05/08a-feedbot-i.html
+[feedbot-ii]: /posts/y05/08b-feedbot-ii.html
+[feedbot]: http://btcbase.org/log-search?q=feedbot
+[feedbot-irc.vpatch]: TODO
+[feedbot-irc.vpatch.spyked.sig]
+[trilemabot]: /posts/y05/078-trilemabot-ii.html
+[announcer]: /posts/y05/08b-feedbot-ii.html#selection-249.0-252.0
+[feedbot-manual]: /posts/y05/081-feedbot-manual.html