IRC-OC
An IRC client library for OpenComputers.
Quickstart
First, create a builder instance:
local irc = require("irc")
local builder = irc.builder()
Then run builder:connection
to set connection options, and builder:auth
to
set the nickname, username, and realname:
builder:connection {
host = "irc.esper.net:6667",
}
builder:auth {
nickname = "my-bot",
username = "my-bot",
realname = "My OpenComputers bot",
}
Subscribe to the needed events:
builder:subscribe(irc.events.irc.message, irc.events.priority.normal,
function(self, client, evt)
print(evt.rawLine)
evt:reply("Hello!")
end)
And start the bot:
builder:buildAndRun()
Now the bot should connect to the IRC server. Alternatively, you can chain the calls:
local irc = require("irc")
local client = irc.builder()
:connection {
host = "irc.esper.net:6667",
}
:auth {
nickname = "my-bot",
username = "my-bot",
realname = "My OpenComputers bot",
}
:subscribe(irc.events.irc.message, irc.events.priority.normal,
function(self, client, evt)
print(evt.rawLine)
evt:reply("Hello!")
end)
:buildAndRun()
Settings
Connection settings
Configured by calling builder:connection
.
-
host
: an address of the IRC server, with the port -
timeout
: a connection establishment timeout, in seconds; 10 by default -
bufferSize
: the maximum length of the read buffer, in bytes; 1024 by default -
throttling
: a table of throttling options that limit the rate at which messages are sent:-
maxDelay
: the maximal imposed delay between two consecutive messages, in seconds, 0 by default -
maxThroughput
: the number of messages sent in the lastmaxDelay
seconds when the maximal delay is imposed,math.huge
by default -
delayFunction
: a function that maps the rate (number of messages in the lastmaxDelay
seconds divided bymaxThroughput
), from 0 to 1, to a coefficient, a value between 0 and 1, which is multiplied bymaxDelay
to get the delay between a consecutive message,x^2
by default
-
-
splitter
: afunction(message, size)
that splits themessage
into multiple lines, each of which must be less thansize
, in bytes -
maxLineLength
: the maximal line length
Registration settings
Configured by calling builder:auth
.
-
nickname
: the bot's nickname -
username
: the bot's username -
realname
: the bot's realname
Account settings
Configured by calling builder:account
.
-
nickname
: the name of an account -
password
: the password
If these options are set, the bot sends
PRIVMSG :IDENTIFY <nickname> <password>
after it connects to the server.
Bot settings
Configured by calling builder:bot
.
-
channels
: a list of channels to join automatically. If a channel requires a key to join, set it as the value of the key that is the channel name (channels["#test"] = "mykey"
). -
tracking
: a table of tracking options:-
users
: configures user tracking: iftrue
, automatically populates the bot's user registry, enables channel member list tracking. -
modes
: iftrue
, enables mode tracking. Ifbot.tracking.users
is also enabled, tracks member prefixes. -
userInfo
: iftrue
, sends aWHO
command to the server for each joined channel to track user information -
account
: iftrue
, enables user account tracking
-
Execution settings
Configured by calling builder:execution
.
-
threaded
: iftrue
, the bot is started in a thread, which is default; otherwise, it registers an event listener usingevent.listen
-
reconnect
: iftrue
, the bot reconnects automatically if it disconnects, which is default; note that you should probably capture theirc.commands.error
event or enableexecution.catchErrors
as well -
catchErrors
: iftrue
, the bot catches errors in user-defined event handlers and pushes anclient.error
event (you'd still need to set yourclient.error
handler to process the event and cancel the event);false
by default
Client methods and properties
-
client:isChannel(target)
: returnstrue
iftarget
is a channel name -
client:lowerCase(identifier)
: returns the lower-case version of theidentifier
according to theCASEMAPPING
ISUPPORT
token and RFC1459 -
client:areEqual(id1, id2)
: returnstrue
if the two identifiers are equal -
client:getChannel(name, create)
: looks up a channel in the bot registry. If it is not found andcreate
istrue
, puts a new entry to the registory and returns it. -
client:getUser(source, create)
: looks up a user in the bot registry. If the user is not found andcreate
istrue
, puts a new entry to the registry and returns it.source
can be a user mask, aSource
instance, or a nickname. -
client:highestPrefix(prefixes...)
: returns the prefix that gives the most privileges. If none of the given prefixes are recognized, returnstrue
. -
client:subscribe(event, priority, callback)
: call thecallback
(a callable or a coroutine) when theevent
is pushed- Alternative syntax:
client:subscribe({event1, priority1}, {event2, priority2}..., callback)
to handle multiple events. - Returns self so that call can be chained, and the handler object.
- Alternative syntax:
-
client:isConnected()
: returnstrue
if the client is connected to the server -
client:run()
: start the client -
client:stop(reason)
: stop the client; if the client is connected to the server, aQUIT
command will be sent with thereason
-
client:msg(target, message)
: send aPRIVMSG
totarget
-
client:notice(target, message)
: send aNOTICE
totarget
-
client:send(command, parameters...)
: send a command to the server-
Alternative syntax:
client:send(options)
. Recognized options are:-
options.tags
: a table of message tags ({"tag1", tag2 = true, tag3 = "value"}
) -
options.command
: the command name; if not set,options[1]
is used instead -
options.throttle
: iftrue
, an additional delay will be imposed upon the command (see theconnection.throttling
option above) -
options.split
: iftrue
, the last parameter of the command will be split over multiple commands if it exceedsconnection.maxLineLength
- indexed values (
options[1]
,options[2]
and so forth) are the parameters of the command, unlessoptions.command
is not set, in which case indexing starts at 2 (options[2]
,options[3]
and so on)
-
-
You can call
client.send[command]
to send most recognized commands (e.g.client.send:topic(channel)
). These are listed in the source code.The arguments are passed to
client:send
. Some options are set automatically, such as the command name.
-
-
client:requestCapabilitiy(capability)
: sends aCAP REQ
message. Use this method instead of callingclient.send:cap
directly: it waits for the reply during capability negotiation. -
client:whox(mask, format)
: send an extendedWHO
command. Use this method instead of callingclient.send:who
directory so that the client can parse the reply. -
client.thread
: ifexecution.threaded
is enabled, this is the thread where the client is run -
client.bus
: the client's event bus -
client.settings
: the client's settings -
client.features
: a list of parsed ISUPPORT parameters -
client.botUser
: the bot user instance. The value isnil
until the bot registers on the server. -
client.channels
: the bot's channel registry -
client.users
: the bot's user registry -
client.capabilities
: a hash set of enabled capabilities: if acapability
is negotiated,client.capabilities[capability]
istrue
Events
Defined in irc.events
.
Client events
-
client.disconnected
: the client has been disconnected -
client.connected
: the client has established the connection -
client.registered
: the client has registered on the server -
client.authenticated
: the client has authenticated; the bot can send messages after this event -
client.unknownCommand
: the client has received an unknown command; the events has the same parameters asirc.command
-
client.stopping
: the client is stopping (the connection has already been closed when this event is pushed) -
client.error
: the client has caught an error in a used-defined callback. Unless this event is canceled, the client will crash. Only sent when theexecution.catchErrors
option is set totrue
.
IRC events
irc.send
Pushed each time a command is about to be queued for sending. Event handlers can modify the parameters to alter the command.
Parameters
-
evt.tags
: message tags -
evt.command
: the command name -
evt.parameters
: a list of parameters
Methods
-
evt:getLine()
: compile the raw line
irc.write
A line is about to be written to the socket. If the event is canceled, the line will not be sent.
Parameters
-
evt.line
: the line
irc.command
A command is received from the server.
For convenience, in addition to this, an irc.commands[name]
event is pushed
if the command is known. Otherwise, a client.unknownClient
event is fired.
Parameters
-
evt.tags
: message tags -
evt.source
: the source of the message (an instance ofSource
)-
evt.source.nickname
: the nickname -
evt.source.username
: the username (may benil
) -
evt.source.host
: the hostname (may benil
) -
evt.source.source
: the raw source (e.g.nick!user@host.name
)
-
-
evt.command
: the command name -
evt.rawLine
: the raw line, as received from the server (\r\n
at the end are not included)
The event can be indexed: evt[i]
returns the i
th parameter.
irc.commands
events
Specific command events are grouped here. The library exports an irc.commands
enumeration, which maps known commands (PRIVMSG
, 003
, etc.) to their names
(PRIVMSG
, RPL_CREATED
, respectively).
There is an event for every known command, defined at irc.commands[name]
.
The names are converted to camelCase. Examples:
irc.commands.privmsg
irc.commands.errErroneusnickname
irc.commands.rplIsupport
The events have the same parameters as the irc.command
event.
irc.commands.rplWhospcrpl
A reply to an extended WHO
request. The client parses the fields and adds
additional parameters to the event if they were requested:
queryType
channelName
username
ip
hostname
server
nickname
away
oper
prefix
hopCount
idle
account
operRank
realname
irc.message
A PRIVMSG
command that is not a CTCP request.
Parameters
-
evt.originalEvent
: the originalirc.commands.privmsg
event -
evt.tags
: message tags -
evt.source
: the source of the message -
evt.target
: the target the message was sent to (a channel name or a nickname).- Bear in mind that the channel name may have a prefix (
+#channel
).
- Bear in mind that the channel name may have a prefix (
-
evt.message
: the message
Methods
-
evt:reply(msg)
: reply to the message; prefixes the reply with the nickname of the original message author, e.g.test-user: Hello
.
irc.notice
A NOTICE
command that is not a CTCP reply.
It has the same parameters as irc.message
.
irc.ctcpRequest
A CTCP request.
Parameters
All the parameters of irc.message
, and:
-
evt.ctcpCommand
: the CTCP command (uppercased) -
evt.ctcpParams
: the CTCP parameters. Note that this is a string, and the parameters are not parsed.
Methods
-
evt:reply(msg)
: reply with a CTCP response
irc.ctcpResponse
A CTCP response.
It has the same parameters as irc.ctcpRequest
.
Capability events
capability.new
A capability has been advertised in a CAP LS
or CAP NEW
command.
Parameters
-
evt.capability
: the name of the capabilty advertised -
evt.value
: the extended information about the capability (true
if not provided)
capability.removed
A capability has been removed.
Parameters
-
evt.capability
: the capability name
capability.acknowledged
A capability request has been acknowledged by the server.
Parameters
-
evt.capability
: the capability name
capability.notAcknowledged
A capability request has been denied by the server.
Parameters
-
evt.capability
: the capability name
capability.negotiated
The initial capability negotation has finished.
Event priorities
The table of event handler priorities is exported as irc.events.priority
. It
has the following fields, in descending order:
top
high
normal
low
bottom
Event methods and properties
-
evt:cancel()
: cancel the event. If there are multiple handlers for the event, the rest of them are not run. -
evt:get()
: get the table of event parameters -
evt.client
: a reference to the client -
evt.__class
: a reference to the event class
Handlers
The handlers are registered with client:subscribe
. The callback can either be
a function (or table with the __call
metamethod) or a coroutine.
Function-based callbacks
Such a callback is called with 3 arguments every time:
-
self
: the handler object -
client
: the client reference -
evt
: the event object
The reassign the handler to other events by returning a non-nil value. To reassign the handler to one event, return its class and the priority:
return irc.events.irc.commands.privmsg, irc.events.priority.normal
To reassign the handler to multiple events, group each event-priority pair in a table:
return {irc.events.client.connected, irc.events.priority.top},
{irc.events.client.disconnected, irc.events.priority.bottom}
If the callback returns nil
, the handler is reassigned to the events it was
originally registered for.
Example:
client:subscribe(irc.events.irc.message, irc.events.priority.normal,
function(self, client, evt)
print(evt.message)
if evt.__class == irc.events.irc.message then
return irc.events.irc.notice, irc.events.priority.normal
end
end)
Coroutine-based callbacks
The first time the handler with a coroutine callback is executed, the coroutine is started with 3 arguments, same as for function-based callbacks.
To reassign the handler to other events, call self:await
inside the coroutine.
If the coroutine returns, it is removed.
client:subscribe(irc.events.irc.message, irc.events.priority.normal,
coroutine.create(function(self, client, evt)
while true do
print(evt.message)
print(self:await(irc.events.irc.notice,
irc.events.priority.normal).message)
evt = self:await()
end
end))
Handler methods
-
handler:remove()
: remove the handler from the event bus -
handler:await(event, priority)
: yield the coroutine and reassign the handler to theevent
with the givenpriority
. When the coroutine is resumed, returns the receivied event.-
Alternative syntax:
handler:await({event1, priority1}, {event2, priority2}...)
to wait for multiple events. -
handler:await()
reattaches the handler to the events it was originally registered for.
-
ISUPPORT features
This section lists recognized ISUPPORT
parameters. The values are stored in
the client.features
table under the specified keys.
If a feature is not advertised, it will have a nil
value.
Look here for additional information about these parameters.
-
ACCEPT
:maxAcceptCount
-
AWAYLEN
:maxAwayLength
-
CALLERID
:calledId
-
CASEMAPPING
:caseMapping
-
CHANLIMIT
:channelLimit
. The value is a table that maps prefixes to the limit, e.g.client.features.channelLimit["#"]
. -
CHANMODES
:channelModes
. The values is a table with the following keys:-
channelModes.server
: the type A modes -
channelModes.always
: the type B modes -
channelModes.onlySet
: the type C modes -
channelModes.never
: the type D modes
The meaning of these categories is defined here.
The value under each key is a hash set: if a
mode
(e.g."m"
) belongs to agroup
(e.g.channelModes.never
),group[mode]
istrue
.In addition,
channelModes.modes
is defined: it is a table that maps a mode to the group name. For example, ifmode
is a type A mode,channelModes.modes[mode]
is set to"server"
. -
-
CHANNELLEN
:maxChannelLength
-
CHANTYPES
:channelTypes
. The value is a hash set: if achar
is a channel type prefix,channelTypes[char]
istrue
. -
CNOTICE
:cnotice
-
CPRIVMSG
:cprivmsg
-
DEAF
:deaf
-
ELIST
:elist
. The value is a table with the following keys, each having a value oftrue
orfalse
:channelCreationTime
mask
inverseMask
-
topicSetTime
, userCount
-
EXCEPTS
:banExemptions
-
EXTBAN
:extendedBans
. The value is a hash set: if achar
is an extended ban letter,extendedBans[char]
istrue
. Additionally,extendedBans.prefix
is set; if there is no prefix, it is set to""
. -
INVEX
:inviteExceptions
-
KEYLEN
:maxKeyLength
-
KICKLEN
:maxKickLength
-
KNOCK
:knock
-
MAXLIST
:maxListLength
. The value is a table that maps a channel type prefix to the limit (e.g.client.features.maxListLength["#"]
). -
METADATA
:maxMetadataCount
-
MODES
:maxVarModesInCommand
-
MONITOR
:maxMonitorCount
-
NETWORK
:networkName
-
NICKLEN
:maxNickLength
-
PREFIX
:membershipPrefixes
. The value is a table with 2 keys:-
modes
: a sequence of modes; also maps modes to prefixes -
prefixes
: a sequence of prefixes; also maps prefixes to modes
-
-
SAFELIST
:safeList
-
SILENCE
:maxSilenceCount
-
STATUSMSG
:statusMessage
. The value is a hash set: if aprefix
is an accepted target prefix,statusMessage[prefix]
istrue
. -
TARGMAX
:maxTargetCount
. The value is a table that maps a command name to the limit. -
TOPICLEN
:maxTopicLength
-
USERIP
:userIp
-
USERLEN
:maxUsernameLength
-
WHOX
:extendedWho
Default supported capabilities
account-notify
extended-join
message-tags
cap-notify
userhost-in-names
multi-prefix
User
instance
An object that encompasses all information stored about a user.
Comparison
The __eq metamethod is overriden to use client:areEqual
for comparison.
Properties
Note that most properties can be set to nil
, which means the value is unknown.
-
user.client
: the reference to the client -
user.nickname
: the nickname -
user.username
: the username -
user.hostname
: the hostname -
user.realname
: the realname -
user.server
: the server the user is connected to -
user.oper
: whether the user is an operator -
user.hopCount
: the number of hops to the user -
user.ip
: the user's IP address -
user.account
: the user's account name -
user.operRank
: the user's operator rank level -
user.channels
: ifbot.tracking.users
is enabled, this is a table of channels the users has joined. The keys areChannel
instances, and the values aretrue
, ifbot.tracking.modes
is disabled, or instances ofPrefix
otherwise. -
user.modes
: ifbot.tracking.modes
is enabled, this is aModes
instance that stores the user modes. This is only meaningful for the bot user: the bot has no way to get the modes of other users.
Channel
instance
An object that stores information about a channel.
Comparison
The __eq metamethod is overriden to use client:areEqual
for comparison.
Properties
Note that most properties can be set to nil
, which means the value is unknown.
-
channel.client
: the reference to the client -
channel.name
: the name of the channel -
channel.users
: ifbot.tracking.users
is enabled, this is a table of channel members. The keys areUser
instances, and the values aretrue
, ifbot.tracking.modes
is disabled, or instances ofPrefix
otherwise. -
channel.topic
: the channel topic -
channel.joined
: iftrue
, the bot has joined the channel -
channel.modes
: ifbot.tracking.modes
is enabled, this is aModes
instance that stores the channel modes.
Modes
instance
An object that stores user or channel modes.
If a mode
is:
-
a type A mode:
modes[mode]
is a hash set: if the mode list contains avalue
,modes[mode][value]
istrue
-
a type B mode:
modes[mode]
is set to the mode value; if themode
is not set,modes[mode]
isnil
-
a type C mode: same as type B
-
a type D mode: if the
mode
is set,modes[mode]
istrue
; otherwise,modes[mode]
isnil
Prefix
instance
An object that stores a user's membership prefixes.
tostring
tostring(prefix)
returns the effective prefix (the one that gives the most
privileges).
Comparison
The __eq, __lt, __le metamethods are overriden to compare prefixes:
prefix1 < prefix2
is true
if prefix2
gives more privileges than prefix1
.