Abstract
The extensions communication protocol, allows third party programs to receive and send messages to and from IRCTk, with the idea of writing extensions to integrate IRCTk with the surrounding system. Different type of messages are provided, and the extensions, running as external programs, can request which specific messages to receive from IRCTk.
1. Introduction
This document describe the extensions communication protocol as a simple, line-oriented, stream of bytes. Such stream is bi-directional, meaning, IRCTk and an extension can exchange messages between each other.
The protocol can be kept simple due to the fact that the IRC protocol as described in RFC1459, is itself a line-oriented protocol, thus there is no need to handle bytes sequences in a, somehow, "structured" fashion.
The protocol described herein can be used to write client-side bots, or to integrate IRCTk with the surrounding system (think about opening URLs in a browser), leveraging the capabilities built into the systems running the application.
2. Requirements Language (RFC 2119)
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC2119
3. Message format
This specification documents the version 1.0 of the extensions protocol.
A message, exchanged between IRCTk and an extension program, is a UTF-8 CSV-like encoded line, terminated by the sequence <CR><LF>.
A message line contains a series of fields, separated by a tab ('<HT>' or '\t', ASCII code 9) character. The number of fields varies depending on the message type. An example of a basic message might be the following:
34563\tirc\t1234\tfoo\tmention\tfalse\taway\tLibera\t#openbsd\ttime=2023-08-03T19:47:05.231Z\tPRIVMSG\tHello, World!<CR><LF>
In this example, the fields are:
- 34563: The message id.
- irc: The message type, in this case an "irc command".
- 1681676304: The message timestamp.
- 1234: The channel id the message is coming from.
- foo: The user that sent the message.
- mention: Message level.
- false: The application window is not in focus.
- away: The client user current status (he is away, in this moment).
- Libera: The network name.
- #openbsd: The channel name.
- time=2023-08-03T19:47:05.231Z: IRCv3 message tags.
- PRIVMSG: IRC command.
- Hello, world! The command arguments.
- <CR><LF>: Termination sequence.
All the message types sent by either IRCTk or an extension, MUST follow the aforementioned format.
4. Message types
The extensions protocol supports six message types:
- Handshake: messages for the initial communication between IRCTk the extensions.
- Ack: acknowledge of a request.
- Nack: Request denied.
- Filter: messages sent by an extension to allow an extension tell the application to only relay specific type of messages.
- Irc: IRC commands received by IRCTk from the server.
- Plumb: Generic text data sent to the extensions.
If a field on a message type definition is marked as "EMPTY", it means that the field itself MUST be present in the message, with a length of zero bytes. An empty field is defined by two consecutive tab characters ('\t\t') or, if the final field of a message can be empty, by a tab character and the termination sequence ('\t<CR><LF>').
Unless explicitly marked as "EMPTY", Every message MUST have an "id" as first field. This is required to keep track of messages that must receive an acknowledge from either the application or an extension. The ID might be numeric, or a random generated string, and it can be reused once a previous exchange, using that id, is completed. However, it is RECOMMENDED that both IRCTk and the loaded extensions, use a unique message id for every exchange whenever possible.
4.1 Handshake
ACK/NACK: yes
The handshake messages are exchanged between IRCTk and an extension when the latter is first loaded.
An handshake message have the following fields:
- Id: The message id.
- Type: The message type, "handshake" in this case.
- Version: The protocol version.
- Name: Application, or extension name.
- AppVersion: Application or extension version.
- Capabilities: Space-separated list of capabilities (EMPTY).
The means of this message type, is to establish if the loaded extension is compatible with the version of IRCTk and it's extension protocol that loaded it.
Additionally, combined with proper filters, extensions MAY be able to handle particular IRCv3 capabilities, that will be requested by IRCTk to the server on behalf of an extension.
4.2 ACK
ACK/NACK: no
The ACK is a generic acknowledge message that might be sent by the application, or by an extension, in response to a request in order to say that it was accepted. It has the following fields:
- Id: The id of the message the ack refers to.
- Type: Message type, "ack" in this case.
- Comment: A string, commenting the ACK (EMPTY).
4.3 NACK
ACK/NACK: no
See "ACK", but in this case, the request or message is denied. The fields are:
- Id: The id of the message the ack refers to.
- Type: Message type, "nack" in this case.
- Comment: A string, commenting the NACK (EMPTY).
4.4 Filter
ACK/NACK: yes
A "filter" message, is used by an extension, to inform IRCTk to only send messages of the type specified in the filter or a specific command specified in the filter. More than one filter message may be sent by an extension in order to specify additional types or commands to receive.
By default all the messages processed by IRCTk will be forwarded to an extension.
A filter message has the following fields:
- Id: The message ID.
- Type: The message type, "filter" in this case.
- type/command: The message type or command to filter for.
Silent change in behaviour by IRCTk without acknowledge is not allowed. An extension MUST NOT change it's working behaviour until an ACK for the sent request is received.
An extension wanting to receive messages only for specific commands of a specific type, MUST first request a filter for the message type first, and then send a filter requests for the specific command. For example, an extension asking to send messages of type "irc" only, with no further command filtering requests, will cause IRCTk to send all the messages of type irc it receives, to the extension.
Refer to the Communication example section for additional details.
4.5 IRC
ACK/NACK: no
A message of type "irc" is, essentially, an IRC command received by IRCTk from a server, or a command coming from the IRCTk user's GUI itself. All those commands, unless filters are in place, are relayed to an extension. On the other hand, an extension can send an irc message to IRCTk, to show specific information, or to relay a message to a specific channel (client-side bot). The fields are:
- Id: Message Id (EMPTY).
- Type: The message type, "irc" in this case.
- Timestamp: Timestamp of the message, in seconds, from the epoch (EMPTY).
- Cid: The id of the channel in IRCTk (EMPTY).
- Nick: The nick of the user that sent the message (EMPTY).
- Level: Message level, from "info", to "mention" (EMPTY).
- Focus: true or false. Define if the application window is on focus (EMPTY).
- Status: Client user's status. Might be "away" or not (EMPTY).
- Network: The network name.
- Channel: The channel name.
- Tags: A list of IRCv3 tags (EMPTY).
- Command: The IRC command.
- Args: The command arguments.
An example of this message (received by an extension), is the one written in the introduction section.
Suggestions for extensions implementers will be provided in a separate document.
In this revision of the specification, the "id" field for the IRC message type can be empty, but it MAY become mandatory it in a future version of the spec.
The "Tags" field, is a string representing a list of tags as defined in the IRCv3 message tags spec. This spec extends on that by adding an additional escape sequences for the the tabulation character ('t'). The escape sequence will appear, literally, in a tag value to represent a tabulation character, as the tabulation is among the permitted characters in a tag value. This is needed, as the tab character is used as a separation character for a the various message fields. An example might be:
firsttag=myvalue;secondtag=new\tvalue
4.6 Plumb
ACK/NACK: no
A plumb, is a generic message sent by IRCTk to an extension with just some text data. It's up to the extension to decide what to do with this type of message. An extension MUST NOT send messages of this type and IRCTk MUST ignore such messages.
Fields are as follow:
- Id: Message Id (EMPTY).
- Type: The message type, "plumb" in this case.
- Cid: The Id of the channel where the plumb happened (EMPTY).
- Network: The network name (EMPTY).
- Channel: The channel name (EMPTY).
- Data The text string.
5. Communication example
When IRCTk first starts an extension, a small handshake sequence takes place, where just some messages are exchanged. IRCTk will, initially, send the following message:
1234\thandshake\t1.0\tirctk\t1.0\t<CR><LF>
To which, the extension will answer with an ACK if everything is fine:
1234\tack\tok<CR><LF>
or with an NACK, if something is wrong:
1234\tnack\tko<CR><LF>
If everything is ok, the extension will send it's details, with a capability to request in this example:
5678\thandshake\t1.0\textension-name\t0.1\tserver-time<CR><LF>
If everything is fine, IRCTk will acknowledge that the extension is compatible:
5678\tack\tok<CR><LF>
Or deny running the extension if something is wrong (the comment is an example):
5678\tnack\textension not supported<CR><LF>
If everything is ok, the extension is finally "ready" and the flow of other type of messages can start. As an example, an extension may ask to receive messages of type irc, only for the privmsg command:
55354\tfilter\tirc<CR><LF>
45634\tfilter\tprivmsg<CR><LF>
The application ACKs the requests:
55354<HT>ack<HT>ok<CR><LF>
45634<HT>ack<HT>ok<CR><LF>
The application then sends messages of type IRC and for the privmsg command to the extensions. An extension may send an irc message, that will be posted in the corresponding channel. The following is an example of a minimum valid IRC message coming from an extension:
\tirc\t\t\t\t\t\t\tLibera\t#irctk\tPRIVMSG\tHello, world!<CR><LF>
The message will be posted, by IRCTk, to the channel #irctk on the configured Libera network.