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
  • text (str) – the text to send in the CTCP ACTION

  • dest (str) – the destination of the CTCP ACTION

The same loop detection and length restrictions apply as with say(), though automatic message splitting is not available.

backend = None

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 a Sopel 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 = None

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 = None

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

property isupport

Features advertised by the server.

Type

ISupport instance

join(channel, password=None)

Join a channel.

Parameters
  • channel (str) – the channel to join

  • password (str) – an optional channel password

If channel contains a space, and no password is given, the space is assumed to split the argument into the channel to join and its password. channel should not contain a space if password is given.

kick(nick, channel, text=None)

Kick a nick from a channel.

Parameters
  • nick (str) – nick to kick out of the channel

  • channel (str) – channel to kick nick from

  • text (str) – optional text for the kick

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.

Parameters
  • line (str) – the raw line

  • prefix (str) – additional information to prepend to the log line

property myinfo

Server/network information.

Type

MyInfo instance

New in version 7.0.

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).

Parameters
  • text (str) – the text to send in the NOTICE

  • dest (str) – the destination of the NOTICE

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(), the asynchat.async_chat being a subclass of asyncore.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.

Parameters
  • channel (str) – the channel to leave

  • msg (str) – the message to display when leaving 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
  • text (str) – the text of the reply

  • dest (str) – the destination of the reply

  • reply_to (str) – the nickname that the reply will be prepended with

  • notice (bool) – whether to send the reply as a NOTICE or not, defaults to False

If notice is True, 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.

Parameters
  • host (str) – the IRC server hostname

  • port (int) – the IRC server port

say(text, recipient, max_messages=1)

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)

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, the text 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 = None

Bot settings.

property user

Sopel’s user/ident.

write(args, text=None)

Send a command to the server.

Parameters
  • args (iterable) – an iterable of strings, which will be joined by spaces

  • text (str) – a string that will be prepended with a : and added to the end of the command

args is an iterable of strings, which are joined by spaces. text is treated as though it were the final item in args, but is preceded by a :. This is a special case which means that text, unlike the items in args, may contain spaces (though this constraint is not checked by write).

In other words, both sopel.write(('PRIVMSG',), 'Hello, world!') and sopel.write(('PRIVMSG', ':Hello, world!')) will send PRIVMSG :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 optional text.

Parameters
  • args (list) – list of text, arguments of the IRC command to send

  • text (str) – optional text to send with the IRC command

Returns

the raw message to send through the connection

Return type

str

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 to channel with optional password.

Parameters
  • channel (str) – channel to join

  • password (str) – optional password for protected channels

send_kick(channel, nick, reason=None)

Send a KICK command for nick in channel .

Parameters
  • channel (str) – the channel from which to kick nick

  • nick (str) – nickname to kick from the channel

  • reason (str) – optional reason for the kick

send_nick(nick)

Send a NICK command with a nick.

Parameters

nick (str) – nickname to take

send_notice(dest, text)

Send a NOTICE command to dest with text.

Parameters
  • dest (str) – nickname or channel name

  • text (str) – the text to send

send_part(channel, reason=None)

Send a PART command to channel.

Parameters
  • channel (str) – the channel to part

  • text (str) – optional text for leaving the channel

send_pass(password)

Send a PASS command with a password.

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 a PING command to the client.

send_privmsg(dest, text)

Send a PRIVMSG command to dest with text.

Parameters
  • dest (str) – nickname or channel name

  • text (str) – the text to send

send_quit(reason=None)

Send a QUIT command.

Parameters

reason (str) – optional text for leaving the server

This won’t send anything if the backend isn’t connected.

send_user(user, mode, nick, name)

Send a USER command with a user.

Parameters
  • user (str) – IRC username

  • mode (str) – mode(s) to send for the user

  • nick (str) – nickname associated with this user

  • name (str) – “real name” for the user

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 instance

  • server_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.

Parameters
  • host (str) – IRC server hostname

  • port (int) – IRC server port

  • source_address (str) – the source address from which to initiate the connection attempt

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 instance

  • verify_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

send(data)

SSL-aware override for send().

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

ISupport

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

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 and failure callbacks must accept two arguments: bot (a Sopel instance) and cap (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

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.