Ircbot Alt-Genesis

November 21st, 2020

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.


1 diff -uNr a/ircbot/INSTALL b/ircbot/INSTALL
2 --- a/ircbot/INSTALL false
3 +++ b/ircbot/INSTALL c4c41d96ddb71db32e8cd54c22e7250abbc52d51f4b25d8092dc094b4a84100949d0a74378fc33131d2d9a5144156a738f5a91d7e949922898993eb4384b4757
4 @@ -0,0 +1,19 @@
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 && cd ..
19 +
20 init
21 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 @@
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 @@
41 +
42 +(asdf:load-system :ircbot)
43 +(defvar *bot*)
44 +(setf *bot*
45 + (ircbot:make-ircbot
46 + "" 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 <>"
63 + :license ""
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 /

Thoughts on WoT Search

October 25th, 2020

Here is how I am looking at WoT search right now.

The work remaining on Lekythion is

  1. Constructing a decent search query in SQL
  2. Hooking the bot up to postgres
  3. Formatting the response
  4. Publishing the lisp code I use to build the index

After publication of the code, my hope to see others build their own indexes and share them using the WoT. Index owners could share read-only access to their postgres instance, perhaps via whitelisted IPs, to others in the WoT. This is similar to the approach suggested by asciilifeform, but I can’t find a reference to his proposal at the moment.

Individuals could stand up their own bots and connect queries to whichever indexes they preferred, be they their own indexes or others’.

My indexes will eventually include at least:

  • All known former republican blogs1
  • All pages linked to in the logs
  • The logs

Perhaps at some point it will become relatively easy to quickly build an index of favorite sites/data sets and and make them available.

  1. As time goes on it may be possible for me to connect directly to blog owner indexes, rather than creating my own []

Socialist Art and Architecture of Sacramento

September 20th, 2020

All of the above images are taken from the back alley behind my apartment.

This is an outdoor olympic weightlifting gym, also in the back alley behind my apartment. I won’t report how much I can lift just yet.

I do like the industrial warehouse look of these two buildings, although both are now used for non-industrial purposes.

Disgusting, don’t you think?


This is where Newsom contemplates climate change instead of doing anything useful.

I actually liked this building until I discovered it’s a federal building.

More modern architecture.

Some train pics for the spergs.

Me and my ride.

Notes on Chinese from gregorynyssa

September 20th, 2020

In this article I attempt to condense some interesting information about Chinese I’ve learned in my recent discussions with gregorynyssa, a scholar of Chinese, Greek, and Latin, much after my own heart but far more advanced in all of these studies than myself.

Sentence Structure

According to gregorynyssa speakers of Mandarin Chinese, a language significantly lacking in grammar (such as explicit case), use these tricks with sentences to express more complicated ideas.

Since Chinese does not handle embedded clauses very elegantly, often speakers have a tendency just to avoid them.

Here are three techniques used by Mandarin speakers to express more complicated ideas.

Comma Splicing

Join two complete sentences with a comma. A result of this is there is no consistent distinction between commas and periods in Chinese writing.


Subject-periodic Construction

This involves combining sentences which share a subject.


Pivotal Construction

If the object of the first sentence is the same as the subject of the second, omit the latter and join the two sentences with a comma.


Digraphic Verbs, Improper Digraphic Verbs, and Monographic Verbs

Monographic verbs can’t serve as nouns.
Improper digraphic verbs can’t serve as nouns.
Most but not all digraphic verbs can serve as nouns.

The upshot of this is that it is necessary to learn the the noun forms for all improper digraphic verbs. For example, 睡觉 may not serve as a noun. In that case 睡眠 must be used. This partially explains why there are so many two-character words in chinese where both characters, according to the dictionary, mean exactly the same thing.

Improper digraphic verbs generally have a second syllable indicating direction or result.

Minor Grammatical Points

来 before a verb indicates the infinitive.
得 is more idiomatic when used vefore adverbs.
来到 is an improper verb meaning “come to.”
迅速 is used more often as an adverb in declarative sentences than 快, which is most often used in an imperative sense.
去 may only be used before place names, non-monographic verbs, and before terms indicating general vicinity1.

Further Reading

According to gregorynyssa, reading Disyllabic Words in Chinese and
Metrical Phonology have helped him fundamentally understand the nature 普通话(Putonghua). I haven’t yet read these papers and as of yet have no comment on them.

For a better understanding of how 普通话(apparently of relatively recent origin) differs from Ancient Chinese, read Peasant and Merchant as well as Rule of Law.

  1. Thus it is necessary to append 那边 to nouns like 超市 when expressing “going to <non-place name> []

Simple Mp-wp Article Import Script

September 20th, 2020

Below is a simple script for importing an article directly into mp-wp via the db inspired by lobbes' previous work on importing logs into mp-wp. It is a necessary step towards being able to import the entire Encyclopedia Britannica into mp-wp. I thought it might be useful for anyone wishing to automate creation of articles.


import mysql.connector
import time
import json
from pprint import pprint

def add_article(cnx, article):
        cursor = cnx.cursor()

        content = article['content'] 

        current_date = time.strftime("%Y-%m-%d %H:%M:%S",
                                                     (1910, 1, 1, 1, 3, 38, 1, 48, 0))
        current_date_gmt = current_date
        title = article['title']
        post_url_relative = '-'.join(title.split())

        query = '''INSERT INTO wpmp_posts(post_author, post_date,
                        post_date_gmt, post_content, post_title,
                        post_category, post_status, comment_status, ping_status,
                        post_name, post_modified, post_modified_gmt, post_parent,
                        guid, menu_order, post_type, comment_count,
                        post_excerpt, to_ping, pinged, post_content_filtered,
                        post_mime_type, post_password) VALUES (%s,%s,%s,%s,
                                %s,%s,%s) ; '''
                (0, current_date, current_date_gmt, content, title, 0, "publish",
                 "open", "open", post_url_relative, current_date,
                 current_date_gmt, 0, "", 0, "post", 0, "", "", "", "", "", "")


cnx = mysql.connector.connect(user='jwz', password='justwantedto',
json_file = '../data/encyclopedia.json'
with open(json_file) as json_data:
    data = json.load(json_data)
add_article(cnx, data[0]['articles'][0])

Chicken Lives Matter

September 1st, 2020

Pour one out for this chicken that was ritually sacrificed on behalf of my health sometime in the last few days by my Chinese ex-girlfriend’s1 priest/shaman somewhere in the godforsaken East.

I can already feel the chicken’s essence giving me power as its soul seeps slowly into my qi. I don’t know if this chicken will be enough for me to do the work to begin importing encyclopedia entries into mp-wp. It may take a few more chicken lives.

  1. I’ve left her on read for months but she persists []

July Search Update

July 18th, 2020

Work is progressing on the search bot.

I now have a configuration that will index the logs. The resulting index is not perfect - anything from reddit is excluded due to my ip being blocked, and many pages are not successfully indexed due to periodically going offline. There is an error when attempting to index any Bitcointalk link that I haven’t been able to resolve. Also, due to the timespan involved, many links have rotted and are lost forever. Most links provided as “shortened” links also no longer work. The results for this crawl should show up in the bot’s index about one week from now.

Work on the encyclopedia crawl progresses as well. Apify delivered a half-functional crawling script that works with their platform. At the moment I don’t have a configuration which allows the crawl to get all volumes of the encyclopedia. I am currently working with support to get this resolved.

So I'm getting divorced

June 28th, 2020

So I’m getting divorced. Not because I had the courage, like I should have had, to have broken it off years ago, but because of a condom wrapper my wife found in my back pocket on the morning of Father’s day. My wife wants to try to fix things, but I don’t, and I’ve said that. I welcome the shift from feeling anger, resentment, and fear daily to mostly sorrow and relief. She’s been very apologetic, and I should have given her the chance to respond to how I felt, like I said above, many years ago, before it was way too late. In any case I have my freedom now, like I could have had all along if I had any courage at all.


June 18th, 2020

The results for lekythion’s first crawl of are in. The index created is not of much use due to the crawler being blocked by many sites including, reddit and tardstalk for not complying with the robots.txt files.

Nevertheless I now have a comprehensive list of links from the #trilema logs. I think the index should include the logs themselves, but it might be convenient to be able to compartmentalize crawling external links into a separate task/configuration.

The Voice of Trilema

June 8th, 2020

Now that I’ve been reading Trilema (successfully or not) for about six years, I thought I’d take some time to comment on the style and voice of the English portion of the the blog.

His voice is distinctive in many ways, but some of the distinctive features that most stand out to me are mircea_popescu’s frequent use of the 2nd person and the the use of graphic sexual metaphor to illustrate many, many concepts.

Given the prominence of this person in his writing, it wouldn’t be a waste of time to think a little bit about who exactly is “you.”

Is it really me, the person reading? In many cases yes, if I go by his qualifications - those usually being something along the lines of either not having read some text or not having some particular thought on my own by my late teens. The interesting thing is, after time, if I come back and read an article again, the “you” is less and less me, and more someone else, and the article begins to feel off - because I’ve likely read the text or internalized the thought by that point.

Whoever the “you” is, mircea_popescu in this voice at least plainly holds the reader in contempt. I think this is intended as a form of rhetoric. In other words he’s using this voice to evoke particular emotions in the reader for persuasive purposes. Whoever the reader is he is in a miserable state and is absolutely responsible for being in this state and is responsible as well for his parents and grandparents sucking and so forth. There is no quarter given, without exception, except perhaps to those who realize their worthlessness and die either by their own hand or in some highly risky endeavor1. Now I have to be careful here because I know it’s impossible to know what someone else is thinking, and I certainly don’t want to appear to be making that claim. I am only speculating. In any case, I speculate that the intended effect of this use of rhetoric is to arouse a feeling of shame. Shame is painful. “You” are to be spurred on by this pain. “You” are to do whatever is necessary to deal with the pain. In my observations of some others reading Trilema, this pain turns them immediately away and they never come back. Others, such as myself, somehow either become addicted to the pain, or perhaps keep reading on to find some sort of salvation from it2.

As for the frequent use of graphic sexual metaphor mircea_popescu himself explains why he prefers this style. I suspect this rhetoric also is meant to instill pain in many readers, and perhaps levity in others. Either way it is memorable, and I can’t think of any other writer using sexual metaphor to this extent.

Another aspect of his style that I’d like to comment on is the … finality, the unforgivingness. Read any article and there is a very good chance he’ll make you aware of a mistake you’ve made that can never, ever be corrected, only regretted. It is interesting to contrast this with other writers in the Anglosphere today, where there is endless redemption to be found.

And while there is doubtless much more to be said, this is all my cup of chai will allow me to put forth today.

  1. Not that it matters but I don’t particularly disagree with this attitude []
  2. Pain itself in various forms is a major theme in Trilema articles and it makes sense that given the significance of pain’s role in mp’s thoughts on education, reading Trilema itself would be painful []