IRC Core Implementation#
Operation of the sopel.irc
core is supported by these utility submodules:
sopel.irc#
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
).
Warning
This is all internal code, not intended for direct use by plugins. It is subject to change between versions, even patch releases, without any advance warning.
Please use the public APIs on bot
.
Important
When working on core IRC protocol related features, consult protocol documentation at https://modern.ircdocs.horse/
- class sopel.irc.AbstractBot(settings: Config)#
Abstract definition of Sopel’s interface.
- action(text: str, dest: str) None #
Send a CTCP ACTION PRIVMSG to a user or channel.
- Parameters:
text – the text to send in the CTCP ACTION
dest – 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: AbstractIRCBackend#
IRC Connection Backend.
- property capabilities: Capabilities#
Capabilities negotiated with the server.
New in version 8.0.
- change_current_nick(new_nick: str) None #
Change the current nick without configuration modification.
- Parameters:
new_nick – new nick to be used by the bot
New in version 7.1.
- property config: Config#
The
sopel.config.Config
for the current Sopel instance.
- property connection_registered: bool#
Whether the IRC connection is registered.
This is a property so it can accurately reflect not only the socket state (connection to IRC server), but also whether the connection is ready to accept “normal” IRC commands.
Before registration is completed, only a very limited set of commands are allowed to be used. Sopel itself takes care of these, so plugins will be more concerned with whether they are allowed to use methods like
say()
yet.
- abstract dispatch(pretrigger: PreTrigger) None #
Handle running the appropriate callables for an incoming message.
- Parameters:
pretrigger – Sopel PreTrigger object
Important
This method MUST be implemented by concrete subclasses.
- property enabled_capabilities: set[str]#
A set containing the IRCv3 capabilities that the bot has enabled.
Deprecated since version 8.0: Enabled server capabilities are now managed by
bot.capabilities
and its various methods and attributes:use
bot.capabilities.is_enabled()
to check if a capability is enableduse
bot.capabilities.enabled
for a list of enabled capabilities
Will be removed in Sopel 9.
- get_irc_backend( ) AbstractIRCBackend #
Set up the IRC backend based on the bot’s settings.
- Returns:
the initialized IRC backend object
- join(channel: str, password: str | None = None) None #
Join a
channel
.- Parameters:
channel – the channel to join
password – an optional channel password
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: str, channel: str, text: str | None = None) None #
Kick a
nick
from achannel
.- Parameters:
nick – nick to kick out of the
channel
channel – channel to kick
nick
fromtext – optional text for the kick
The bot must be an operator in the specified channel for this to work.
New in version 7.0.
- log_raw(line: str, prefix: str) None #
Log raw line to the raw log.
- Parameters:
line – the raw line
prefix – additional information to prepend to the log line
The
prefix
is usually either>>
for an outgoingline
or<<
for a received one.
- make_identifier(name: str) Identifier #
Instantiate an Identifier using the bot’s context.
New in version 8.0.
- make_identifier_memory() SopelIdentifierMemory #
Instantiate a SopelIdentifierMemory using the bot’s context.
This is a shortcut for
SopelIdentifierMemory
’s most common use case, which requires remembering to pass thebot
’s ownmake_identifier()
method so theSopelIdentifierMemory
will cast its keys toIdentifier
s that are compatible with what the bot tracks internally and sends withTrigger
s when a plugin callable runs.Calling this method is equivalent to the following:
from sopel.tools import memories memories.SopelIdentifierMemory( identifier_factory=bot.make_identifier, )
New in version 8.0.
See also
The
tools.memories
module describes how to useSopelIdentifierMemory
and its siblings.
- property nick: Identifier#
Sopel’s current nick.
Changing this while Sopel is running is unsupported and can result in undefined behavior.
- notice(text: str, dest: str) None #
Send an IRC NOTICE to a user or channel (
dest
).- Parameters:
text – the text to send in the NOTICE
dest – the destination of the NOTICE
- on_message(message: str) None #
Handle an incoming IRC message.
- Parameters:
message – the received raw IRC message
- on_message_sent(raw: str) None #
Handle any message sent through the connection.
- Parameters:
raw – 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: str, msg: str | None = None) None #
Leave a channel.
- Parameters:
channel – the channel to leave
msg – the message to display when leaving a channel
- quit(message: str | None = None) None #
Disconnect from IRC and close the bot.
- Parameters:
message – optional QUIT message to send (e.g. “Bye!”)
- rebuild_nick() None #
Rebuild nick as a new identifier.
This method exists to update the casemapping rules for the
Identifier
that represents the bot’s nick, e.g. after ISUPPORT info is received.New in version 8.0.
- reply( ) None #
Send a PRIVMSG to a user or channel, prepended with
reply_to
.- Parameters:
text – the text of the reply
dest – the destination of the reply
reply_to – the nickname that the reply will be prepended with
notice – whether to send the reply as a
NOTICE
or not, defaults toFalse
If
notice
isTrue
, send aNOTICE
rather than aPRIVMSG
.The same loop detection and length restrictions apply as with
say()
, though automatic message splitting is not available.
- restart(message: str | None = None) None #
Disconnect from IRC and restart the bot.
- Parameters:
message – optional QUIT message to send (e.g. “Be right back!”)
- run(host: str, port: int = 6667) None #
Connect to IRC server and run the bot forever.
- Parameters:
host – the IRC server hostname
port – the IRC server port
- safe_text_length(recipient: str) int #
Estimate a safe text length for an IRC message.
- Returns:
the maximum possible length of a message to
recipient
When the bot sends a message to a recipient (channel or nick), it has 512 bytes minus the command, arguments, various separators and trailing CRLF for its text. However, this is not what other users will see from the server; the message forwarded to other clients will be sent using this format:
:nick!~user@hostname PRIVMSG #channel :text
Which takes more bytes, reducing the maximum length available for a single line of text. This method computes a safe length of text that can be sent using
PRIVMSG
orNOTICE
by subtracting the size required by the server to convey the bot’s message.New in version 8.0.
See also
This method is useful when sending a message using
say()
, and can be used withsopel.tools.get_sendable_message()
.
- say( ) None #
Send a
PRIVMSG
to a user or channel.- Parameters:
text – the text to send
recipient – the message recipient
max_messages – split
text
into at most this many messages if it is too long to fit in one (optional)truncation – 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 – 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.
- property server_capabilities: dict[str, str | None]#
A dict mapping supported IRCv3 capabilities to their options.
For example, if the server specifies the capability
sasl=EXTERNAL
, it will be here as{"sasl": "EXTERNAL"}
. Capabilities specified without any options will haveNone
as the value.For servers that do not support IRCv3, this will be an empty set.
Deprecated since version 8.0: Enabled server capabilities are now managed by
bot.capabilities
and its various methods and attributes:use
bot.capabilities.is_available()
to check if a capability is availableuse
bot.capabilities.available
for a list of available capabilities and their parameters
Will be removed in Sopel 9.
- settings#
The bot’s settings.
New in version 7.0.
- write(args: Iterable[str], text: str | None = None) None #
Send a command to the server.
- Parameters:
args – an iterable of strings, which will be joined by spaces
text – 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 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.