Adding IRCv3 Compatibility to an IRC bot

IRCv3.2 is the latest stable version of the IRC (Internet Relay Chat) protocol and after a few hours, I have attempted to find an implementation for every new capability added to the list. So far, I currently support all the 3.2 capabilities marked done on my TODO list and have provided an example.

Since I’m finally done with this, I’m going to further document what I’ve done and what obstacles I overcame writing this section of my project (there are many, so enjoy the article).

Adding tags to the bot

The first major component that I took when adding compatibility with IRCv3 was tags; in the process, I learned a few things about how to properly handle parsing code using Lua as well. To start off with, what I used to do was to check each individual character and set a state based off of it; the parser also used a concatenation method, which took more memory than it’s current form. The finished parser is here.

Understanding block message processing

Attempting to pass control of who managed the incoming messages was a much harder task than my new format; what I’ve done instead, to understand processing in which execution is blocked, is to add in a new “hooks” system. A hook’s state is declared outside of the hook function and then changed inside of the hook — it is also possible to use a state for multiple hooks (such as via 0697126). What I did for the CAP command was I checked if any hooks responded to ‘CAP_LS’ and, if so, stopped blocking and waited until the hook that had started the messages block had its state reach zero, then finish the block by sending ‘CAP END’.

Adding in support for echo-message

Honestly, adding in support for this was one of the easiest things I’ve ever done; all I had to do was add a check for if the `echo-message’ capability existed and, if it did not, print out the message it was sending.

Supporting extended-join

This simply required an “if/else” case; if the capability existed, then the data stored in the user’s table (or hash table, dict, whatever you call them) is updated; if not, only the JOIN to the channel is recorded.

multi-prefix support

This one proved to be slightly tougher in that I had to add an escaped regex to capture all characters that matched the set listed in either the PREFIX 005 capability or “@+”, then store the fully captured string in the table

Including away-notify

This was yet another one of the easier ones; all that had to be done was to update a table value when a message was sent. It was no more than about five lines code-wise.

Support for account-notify

This was — yet again — a fairly simple addition to updating a value when a message was received.

Support for invite-notify

This is getting repetitive, but that’s what you get for reading this document. Yet another simple addition, but this time printing out. I’m not sure why this is really important but apparently it is.

Originally supporting cap-notify

Just parse the output of CAP NEW and trigger hooks if needed (something along the lines of NEW_CAP_invite-notify).

Adding account-tag

The technical implementation just meant to add in some way to know the account name directly off the tag; this was technically implemented by passing a `tags’ table to each function.

Supporting chghost

Yet another field update

Support for userhost-in-names

If/else statement and a string match

Supporting server-time

Adding in a `parse-time’ function to the IRC class and the tag passed to it gave users the ability to parse the server time. This could be useful for things such as a time-based spam ban system.

Closing Up

This is basically a summary of everything that I added to my bot between the release v0.1.0 and v0.2.0 — I don’t expect many to enjoy reading this but if you did, tell me. I’ll be sure to make more.

Show your support

Clapping shows how much you appreciated Ryan Rion’s story.