IRC Backends¶
sopel.irc
is the core IRC module for Sopel.
This sub-package contains everything that is related to the IRC protocol (connection, commands, abstract client, etc.) and that can be used to implement the Sopel bot.
In particular, it defines the interface for the
IRC backend
, and the
interface for the bot itself
. This is all
internal code that isn’t supposed to be used directly by a plugin developer,
who should worry about sopel.bot.Sopel
only.
Important
When working on core IRC protocol related features, consult protocol documentation at https://www.irchelp.org/protocol/rfc/
Bot Interface¶
-
class
sopel.irc.
AbstractBot
(settings)¶ Bases:
object
Abstract definition of Sopel’s interface.
-
action
(text, dest)¶ Send a CTCP ACTION PRIVMSG to a user or channel.
- Parameters
The same loop detection and length restrictions apply as with
say()
, though automatic message splitting is not available.
-
backend
¶ IRC Connection Backend.
-
cap_req
(module_name, capability, arg=None, failure_callback=None, success_callback=None)¶ Tell Sopel to request a capability when it starts.
- Parameters
module_name (str) – the module requesting the capability
capability (str) – the capability requested, optionally prefixed with
-
or=
arg (str) – arguments for the capability request
failure_callback (function) – a function that will be called if the capability request fails
success_callback (function) – a function that will be called if the capability is successfully requested
By prefixing the capability with
-
, it will be ensured that the capability is not enabled. Similarly, by prefixing the capability with=
, it will be ensured that the capability is enabled. Requiring and disabling is “first come, first served”; if one module requires a capability, and another prohibits it, this function will raise an exception in whichever module loads second. An exception will also be raised if the module is being loaded after the bot has already started, and the request would change the set of enabled capabilities.If the capability is not prefixed, and no other module prohibits it, it will be requested. Otherwise, it will not be requested. Since capability requests that are not mandatory may be rejected by the server, as well as by other modules, a module which makes such a request should account for that possibility.
The actual capability request to the server is handled after the completion of this function. In the event that the server denies a request, the
failure_callback
function will be called, if provided. The arguments will be aSopel
object, and the capability which was rejected. This can be used to disable callables which rely on the capability. It will be be called either if the server NAKs the request, or if the server enabled it and later DELs it.The
success_callback
function will be called upon acknowledgment of the capability from the server, whether during the initial capability negotiation, or later.If
arg
is given, and does not exactly match what the server provides or what other modules have requested for that capability, it is considered a conflict.
-
property
config
¶ The
sopel.config.Config
for the current Sopel instance.
-
connection_registered
¶ Is the IRC Connection registered yet?
-
dispatch
(pretrigger)¶ Handle running the appropriate callables for an incoming message.
- Parameters
pretrigger (
sopel.trigger.PreTrigger
) – Sopel PreTrigger object- Raises
NotImplementedError – if the subclass does not implement this required method
Important
This method MUST be implemented by concrete subclasses.
-
enabled_capabilities
¶ A set containing the IRCv3 capabilities that the bot has enabled.
-
get_irc_backend
()¶ Set up the IRC backend based on the bot’s settings.
- Returns
the initialized IRC backend object
- Return type
an object implementing the interface of
AbstractIRCBackend
-
join
(channel, password=None)¶ Join a
channel
.If
channel
contains a space, and nopassword
is given, the space is assumed to split the argument into the channel to join and its password.channel
should not contain a space ifpassword
is given.
-
kick
(nick, channel, text=None)¶ Kick a
nick
from achannel
.- Parameters
The bot must be operator in the specified channel for this to work.
New in version 7.0.
-
log_raw
(line, prefix)¶ Log raw line to the raw log.
-
property
name
¶ Sopel’s “real name”, to be displayed in WHOIS responses.
-
property
nick
¶ Sopel’s current
Identifier
.
-
notice
(text, dest)¶ Send an IRC NOTICE to a user or channel (
dest
).
-
on_close
()¶ Call shutdown methods.
-
on_connect
()¶ Handle successful establishment of IRC connection.
-
on_error
()¶ Handle any uncaptured error in the bot itself.
This method is an override of
asyncore.dispatcher.handle_error()
, theasynchat.async_chat
being a subclass ofasyncore.dispatcher
.
-
on_message
(message)¶ Handle an incoming IRC message.
- Parameters
message (str) – the received raw IRC message
-
on_message_sent
(raw)¶ Handle any message sent through the connection.
- Parameters
raw (str) – raw text message sent through the connection
When a message is sent through the IRC connection, the bot will log the raw message. If necessary, it will also simulate the echo-message feature of IRCv3.
-
part
(channel, msg=None)¶ Leave a channel.
-
quit
(message)¶ Disconnect from IRC and close the bot.
-
reply
(text, dest, reply_to, notice=False)¶ Send a PRIVMSG to a user or channel, prepended with
reply_to
.- Parameters
If
notice
isTrue
, send a NOTICE rather than a PRIVMSG.The same loop detection and length restrictions apply as with
say()
, though automatic message splitting is not available.
-
run
(host, port=6667)¶ Connect to IRC server and run the bot forever.
-
say
(text, recipient, max_messages=1)¶ Send a PRIVMSG to a user or channel.
- Parameters
By default, this will attempt to send the entire
text
in one message. If the text is too long for the server, it may be truncated.If
max_messages
is given, thetext
will be split into at most that many messages, each no more than 400 bytes. The split is made at the last space character before the 400th byte, or at the 400th byte if no such space exists.If the
text
is too long to fit into the specified number of messages using the above splitting, the final message will contain the entire remainder, which may be truncated by the server.
-
settings
¶ Bot settings.
-
property
user
¶ Sopel’s user/ident.
-
write
(args, text=None)¶ Send a command to the server.
- Parameters
args
is an iterable of strings, which are joined by spaces.text
is treated as though it were the final item inargs
, but is preceded by a:
. This is a special case which means thattext
, unlike the items inargs
, may contain spaces (though this constraint is not checked bywrite
).In other words, both
sopel.write(('PRIVMSG',), 'Hello, world!')
andsopel.write(('PRIVMSG', ':Hello, world!'))
will sendPRIVMSG :Hello, world!
to the server.Newlines and carriage returns (
'\n'
and'\r'
) are removed before sending. Additionally, if the message (after joining) is longer than than 510 characters, any remaining characters will not be sent.See also
The connection backend is responsible for formatting and sending the message through the IRC connection. See the
sopel.irc.abstract_backends.AbstractIRCBackend.send_command()
method for more information.
-
Backend Interface¶
-
class
sopel.irc.abstract_backends.
AbstractIRCBackend
(bot)¶ Abstract class defining the interface and basic logic of an IRC backend.
- Parameters
bot (
sopel.bot.Sopel
) – a Sopel instance
Some methods of this class MUST be overridden by a subclass, or the backend implementation will not function correctly.
-
prepare_command
(*args, **kwargs)¶ Prepare an IRC command from
args
and optionaltext
.- Parameters
- Returns
the raw message to send through the connection
- Return type
From RFC 2812 Internet Relay Chat: Client Protocol, Section 2.3:
IRC messages are always lines of characters terminated with a CR-LF (Carriage Return - Line Feed) pair, and these messages SHALL NOT exceed 512 characters in length, counting all characters including the trailing CR-LF. Thus, there are 510 characters maximum allowed for the command and its parameters. There is no provision for continuation of message lines.
The length in the RFC refers to the length in bytes, which can be bigger than the length of the Unicode string. This method cuts the message until its length fits within this limit of 510 bytes.
The returned message contains the CR-LF pair required at the end, and can be sent as-is.
-
send_command
(*args, **kwargs)¶ Send a command through the IRC connection.
- Parameters
args – IRC command to send with its argument(s)
text (str) – the text to send (optional keyword argument)
Example:
# send the INFO command backend.send_command('INFO') # send the NICK command with the argument 'Sopel' backend.send_command('NICK', 'Sopel') # send the PRIVMSG command to channel #sopel with some text backend.send_command('PRIVMSG', '#sopel', text='Hello world!')
Note
This will call the
sopel.bot.Sopel.on_message_sent()
callback on the bot instance with the raw message sent.
-
send_join
(channel, password=None)¶ Send a
JOIN
command tochannel
with optionalpassword
.
-
send_kick
(channel, nick, reason=None)¶ Send a
KICK
command fornick
inchannel
.
-
send_notice
(dest, text)¶ Send a
NOTICE
command todest
withtext
.
-
send_part
(channel, reason=None)¶ Send a
PART
command tochannel
.
-
send_pass
(password)¶ Send a
PASS
command with apassword
.- Parameters
password (str) – password for authentication
-
send_ping
(host)¶ Send a
PING
command to the server.- Parameters
host (str) – IRC server host
A
PING
command should be sent at a regular interval to make sure the server knows the IRC connection is still active.
-
send_pong
(host)¶ Send a
PONG
command to the server.- Parameters
host (str) – IRC server host
A
PONG
command must be sent each time the server sends aPING
command to the client.
-
send_privmsg
(dest, text)¶ Send a
PRIVMSG
command todest
withtext
.
Backends¶
-
class
sopel.irc.backends.
AsynchatBackend
(bot, server_timeout=None, ping_timeout=None, **kwargs)¶ Bases:
sopel.irc.abstract_backends.AbstractIRCBackend
,asynchat.async_chat
IRC backend implementation using
asynchat
(asyncore
).- Parameters
bot (
sopel.bot.Sopel
) – a Sopel instanceserver_timeout (int) – connection timeout in seconds
ping_timeout (int) – ping timeout in seconds
-
collect_incoming_data
(data)¶ Try to make sense of incoming data as Unicode.
- Parameters
data (bytes) – the incoming raw bytes
The incoming line is discarded (and thus ignored) if guessing the text encoding and decoding it fails.
-
found_terminator
()¶ Handle the end of an incoming message.
-
handle_close
()¶ Called when the socket is closed.
-
handle_connect
()¶ Called when the active opener’s socket actually makes a connection.
-
handle_error
()¶ Called when an exception is raised and not otherwise handled.
-
initiate_connect
(host, port, source_address)¶ Initiate IRC connection.
-
on_job_error
(scheduler, job, exc)¶ Called when a job from the Job Scheduler fails.
-
on_scheduler_error
(scheduler, exc)¶ Called when the Job Scheduler fails.
-
run_forever
()¶ Run forever.
-
class
sopel.irc.backends.
SSLAsynchatBackend
(bot, verify_ssl=True, ca_certs=None, **kwargs)¶ Bases:
sopel.irc.backends.AsynchatBackend
SSL-aware extension of
AsynchatBackend
.- Parameters
bot (
sopel.bot.Sopel
) – a Sopel instanceverify_ssl (bool) – whether to validate the IRC server’s certificate (default
True
, for good reason)ca_certs (str) – filesystem path to a CA Certs file containing trusted root certificates
-
handle_connect
()¶ Handle potential TLS connection.
-
recv
(buffer_size)¶ SSL-aware override for
recv()
.From a (now deleted) blog post by Evan “K7FOS” Fosmark: https://k7fos.com/2010/09/ssl-support-in-asynchatasync_chat
ISUPPORT¶
IRC Tools for ISUPPORT management.
When a server wants to advertise its features and settings, it can use the
RPL_ISUPPORT
command (005
numeric) with a list of arguments.
-
class
sopel.irc.isupport.
ISupport
(**kwargs)¶ Storage class for IRC’s
ISUPPORT
feature.An instance of
ISupport
can be used as a read-only dict, to store features advertised by the IRC server:>>> isupport = ISupport(chanlimit=(('&', None), ('#', 70))) >>> isupport['CHANLIMIT'] (('&', None) ('#', 70)) >>> isupport.CHANLIMIT # some parameters are also properties { '&': None, '#': 70, } >>> 'chanlimit' in isupport # case-insensitive True >>> 'chanmode' in isupport False >>> isupport.CHANMODE # not advertised by the server! Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'ISupport' object has no attribute 'CHANMODE'
The list of possible parameters can be found at modern.ircdocs.horse’s RPL_ISUPPORT Parameters.
-
property
CHANLIMIT
¶ Expose
CHANLIMIT
as a dict, if advertised by the server.This exposes information about the maximum number of channels that the bot can join for each prefix:
>>> isupport.CHANLIMIT { '#': 70, '&': None, }
In that example, the bot may join 70
#
channels and any number of&
channels.This attribute is not available if the server does not provide the right information, and accessing it will raise an
AttributeError
.
-
property
CHANMODES
¶ Expose
CHANMODES
as a dict, if advertised by the server.This exposes information about 4 types of channel modes:
>>> isupport.CHANMODES { 'A': 'b', 'B': 'k', 'C': 'l', 'D': 'imnpst', }
This attribute is not available if the server does not provide the right information, and accessing it will raise an
AttributeError
.
-
property
MAXLIST
¶ Expose
MAXLIST
as a dict, if advertised by the server.This exposes information about maximums for combinations of modes:
>>> isupport.MAXLIST { 'beI': 100, 'q': 50, 'b': 50, }
This attribute is not available if the server does not provide the right information, and accessing it will raise an
AttributeError
.
-
property
PREFIX
¶ Expose
PREFIX
as a dict, if advertised by the server.This exposes information about the modes and nick prefixes used for user privileges in channels:
>>> isupport.PREFIX { 'q': '~', 'a': '&', 'o': '@', 'h': '%', 'v': '+', }
This attribute is not available if the server does not provide the right information, and accessing it will raise an
AttributeError
.
-
property
TARGMAX
¶ Expose
TARGMAX
as a dict, if advertised by the server.This exposes information about the maximum number of arguments for each command:
>>> isupport.TARGMAX { 'JOIN': None, 'PRIVMSG': 3, 'WHOIS': 1, }
This attribute is not available if the server does not provide the right information, and accessing it will raise an
AttributeError
.
-
apply
(**kwargs)¶ Build a new instance of
ISupport
.- Returns
a new instance, updated with the latest advertised features
- Return type
This method applies the latest advertised features from the server: the result contains the new and updated parameters, and doesn’t contain the removed parameters (marked by
-{PARAMNAME}
):>>> updated = {'-AWAYLEN': None, 'NICKLEN': 25, 'CHANNELLEN': 10} >>> new = isupport.apply(**updated) >>> 'CHANNELLEN' in new True >>> 'AWAYLEN' in new False
-
property
Utility¶
-
class
sopel.irc.utils.
CapReq
(prefix, module, failure=None, arg=None, success=None)¶ Represents a pending CAP REQ request.
- Parameters
prefix (str) – either
=
(must be enabled) or-
(must not be enabled)module (str) – the requesting package/module name
failure (function) – function to call if this capability request fails
arg (str) – optional capability value; the request will fail if the server’s value is different
success (function) – function to call if this capability request succeeds
The
success
andfailure
callbacks must accept two arguments:bot
(aSopel
instance) andcap
(the name of the requested capability, as a string).See also
For more information on how capability requests work, see the documentation for
sopel.irc.AbstractBot.cap_req()
.
-
class
sopel.irc.utils.
MyInfo
(client, servername, version)¶ Store client, servername, and version from
RPL_MYINFO
events.
-
sopel.irc.utils.
get_cnames
(domain)¶ Determine the CNAMEs for a given domain.
- Parameters
domain (str) – domain to check
- Returns
list (of str)
-
sopel.irc.utils.
safe
(string)¶ Remove newlines from a string.