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
(AbstractIRCBackend
), and the
interface for the bot itself (AbstractBot
). 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
(plugin_name, capability, arg=None, failure_callback=None, success_callback=None)¶ Tell Sopel to request a capability when it starts.
- Parameters
plugin_name (str) – the plugin 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 plugin requires a capability, and another prohibits it, this function will raise an exception in whichever plugin loads second. An exception will also be raised if the plugin 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 plugin 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 plugins, a plugin 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 plugins have requested for that capability, it is considered a conflict.
-
change_current_nick
(new_nick)¶ Change the current nick without configuration modification.
- Parameters
new_nick (str) – new nick to be used by the bot
-
property
config
¶ The
sopel.config.Config
for the current Sopel instance.
-
connection_registered
¶ Flag stating whether the IRC Connection is 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 an operator in the specified channel for this to work.
New in version 7.0.
-
log_raw
(line, prefix)¶ Log a raw line to the raw log.
- Parameters
The
prefix
is usually either>>
for an outgoingline
or<<
for a received one.
-
property
name
¶ Sopel’s “real name”, as used for WHOIS responses.
-
property
nick
¶ Sopel’s current nick.
Changing this while Sopel is running is unsupported and can result in undefined behavior.
-
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.
-
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 a nickname.
- 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, truncation='', trailing='')¶ Send a PRIVMSG to a user or channel.
- Parameters
text (str) – the text to send
recipient (str) – the message recipient
max_messages (int) – split
text
into at most this many messages if it is too long to fit in one (optional)truncation (str) – string to append if
text
is too long to fit in a single message, or into the last message ifmax_messages
is greater than 1 (optional)trailing (str) – string to append after
text
and (if used)truncation
(optional)
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. The split is made at the last space character before the “safe length” (which is calculated based on the bot’s nickname and hostmask), or exactly at the “safe length” if no such space character 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. You can specifytruncation
to tell Sopel how it should indicate that the remainingtext
was cut off. Note that thetruncation
parameter must include leading whitespace if you desire any between it and the truncated text.The
trailing
parameter is always appended totext
, after the point wheretruncation
would be inserted if necessary. It’s useful for making sure e.g. a link is always included, even if the summary your plugin fetches is too long to fit.Here are some examples of how the
truncation
andtrailing
parameters work, using an artificially low maximum line length:# bot.say() outputs <text> + <truncation?> + <trailing> # always if needed always bot.say( '"This is a short quote.', truncation=' […]', trailing='"') # Sopel says: "This is a short quote." bot.say( '"This quote is very long and will not fit on a line.', truncation=' […]', trailing='"') # Sopel says: "This quote is very long […]" bot.say( # note the " included at the end this time '"This quote is very long and will not fit on a line."', truncation=' […]') # Sopel says: "This quote is very long […] # The ending " goes missing
New in version 7.1: The
truncation
andtrailing
parameters.
-
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.
-
on_irc_error
(pretrigger)¶ Action to perform when the server sends an error event.
- Parameters
pretrigger (
sopel.trigger.PreTrigger
) – PreTrigger object with the error event
On IRC error, if
bot.hasquit
is set, the backend should close the connection so the bot can quit or reconnect as required.
-
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_interval=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_interval (int) – ping interval in seconds
The
server_timeout
option defaults to120
seconds if not provided.The
ping_interval
defaults toserver_timeout * 0.45
if not specified.-
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 connection must be 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.
This method is an override of
asyncore.dispatcher.handle_error()
, theasynchat.async_chat
being a subclass ofasyncore.dispatcher
.
-
initiate_connect
(host, port, source_address)¶ Initiate IRC connection.
-
irc_send
(data)¶ Send an IRC line as raw
data
to the socket connection.- Parameters
data (bytes) – raw line to send
This uses
asyncore.dispatcher.send()
method to senddata
directly. This method is thread-safe.
-
on_irc_error
(pretrigger)¶ Action to perform when the server sends an error event.
- Parameters
pretrigger (
sopel.trigger.PreTrigger
) – PreTrigger object with the error event
On IRC error, if
bot.hasquit
is set, the backend should close the connection so the bot can quit or reconnect as required.
-
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.
-
register_timeout_jobs
(handlers)¶ Register the timeout handlers for the timeout scheduler.
-
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.This exposes information about 4 types of channel modes:
>>> isupport.CHANMODES { 'A': 'b', 'B': 'k', 'C': 'l', 'D': 'imnpst', }
The values are empty if the server does not provide this information.
-
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, } >>> isupport['TARGMAX'] # internal representation (('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
.The internal representation of
TARGMAX
is a tuple of 2-value tuples as seen above.
-
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, plugin, failure=None, arg=None, success=None)¶ Represents a pending CAP REQ request.
- Parameters
prefix (str) – either
=
(must be enabled),-
(must not be enabled), or empty string (desired but optional)plugin (str) – the requesting plugin’s 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.
- Parameters
string (str) – input text to process
- Returns
the string without newlines
- Return type
- Raises
TypeError – when
string
isNone
This function removes newlines from a string and always returns a unicode string (as in
str
on Python 3 andunicode
on Python 2), but doesn’t strip or alter it in any other way:>>> safe('some text\r\n') 'some text'
This is useful to ensure a string can be used in a IRC message.
Changed in version 7.1: This function now raises a
TypeError
instead of an unpredictable behaviour when givenNone
.