The bot and its state#
- class sopel.bot.Sopel(config, daemon=False)#
Bases:
AbstractBot- 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.
- add_plugin(
- plugin: AbstractPluginHandler,
- callables: Sequence[Callable],
- jobs: Sequence[Callable],
- shutdowns: Sequence[Callable],
- urls: Sequence[Callable],
Add a loaded plugin to the bot’s registry.
- Parameters:
plugin – loaded plugin to add
callables – an iterable of callables from the
pluginjobs – an iterable of functions from the
pluginthat are periodically invokedshutdowns – an iterable of functions from the
pluginthat should be called on shutdownurls – an iterable of functions from the
pluginto call when matched against a URL
- backend: AbstractIRCBackend#
IRC Connection Backend.
- call(
- func: Any,
- sopel: SopelWrapper,
- trigger: Trigger,
Call a function, applying any rate limits or other restrictions.
- Parameters:
func (function) – the function to call
sopel (
SopelWrapper) – a SopelWrapper instancetrigger (Trigger) – the Trigger object for the line from the server that triggered this call
- 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.
- channels#
A map of the channels that Sopel is in.
The keys are
Identifiers of the channel names, and map toChannelobjects which contain the users in the channel and their permissions.
- property command_groups: dict[str, list]#
A mapping of plugin names to lists of their commands.
Changed in version 7.1: This attribute is now generated on the fly from the registered list of commands and nickname commands.
- property config: Config#
The
sopel.config.Configfor 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.
- db#
The bot’s database, as a
sopel.db.SopelDBinstance.
- dispatch(pretrigger: PreTrigger) None#
Dispatch a parsed message to any registered callables.
- Parameters:
pretrigger (
PreTrigger) – a parsed message from the server
The
pretrigger(a parsed message) is used to find matching rules; it will retrieve them by order of priority, and execute them. It runs triggered rules in separate threads, unless they are marked otherwise.However, it won’t run triggered blockable rules at all when they can’t be executed for blocked nickname or hostname.
See also
The pattern matching is done by the
Rules Manager.
- property doc: dict[str, tuple]#
A dictionary of command names to their documentation.
Each command is mapped to its docstring and any available examples, if declared in the plugin’s code.
Changed in version 3.2: Use the first item in each callable’s commands list as the key, instead of the function name as declared in the source code.
Changed in version 7.1: This attribute is now generated on the fly from the registered list of commands and nickname commands.
- 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.capabilitiesand its various methods and attributes:use
bot.capabilities.is_enabled()to check if a capability is enableduse
bot.capabilities.enabledfor a list of enabled capabilities
Will be removed in Sopel 9.
- error(
- trigger: Trigger | None = None,
- exception: BaseException | None = None,
Called internally when a plugin causes an error.
- Parameters:
trigger – the IRC line that caused the error (if available)
exception – the exception raised by the error (if available)
- get_irc_backend( ) AbstractIRCBackend#
Set up the IRC backend based on the bot’s settings.
- Returns:
the initialized IRC backend object
- get_plugin_meta(name: str) dict#
Get info about a registered plugin by its name.
- Parameters:
name (str) – name of the plugin about which to get info
- Returns:
the plugin’s metadata (see
get_meta_description())- Return type:
- Raises:
plugins.exceptions.PluginNotRegistered – when there is no
nameplugin registered
- has_channel_privilege(channel: str, privilege: int) bool#
Tell if the bot has a
privilegelevel or above in achannel.- Parameters:
channel – a channel the bot is in
privilege – privilege level to check
- Raises:
ValueError – when the channel is unknown
This method checks the bot’s privilege level in a channel, i.e. if it has this level or higher privileges:
>>> bot.channels['#chan'].privileges[bot.nick] = plugin.OP >>> bot.has_channel_privilege('#chan', plugin.VOICE) True
The
channelargument can be either astror anIdentifier, as long as Sopel joined said channel. If the channel is unknown, aValueErrorwill be raised.
- property hostmask: str | None#
The current hostmask for the bot
User.- Returns:
the bot’s current hostmask if the bot is connected and in a least one channel;
Noneotherwise
- join(channel: str, password: str | None = None) None#
Join a
channel.- Parameters:
channel – the channel to join
password – an optional channel password
If
channelcontains a space, and nopasswordis given, the space is assumed to split the argument into the channel to join and its password.channelshould not contain a space ifpasswordis given.
- kick(nick: str, channel: str, text: str | None = None) None#
Kick a
nickfrom achannel.- Parameters:
nick – nick to kick out of the
channelchannel – channel to kick
nickfromtext – 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
prefixis usually either>>for an outgoinglineor<<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 theSopelIdentifierMemorywill cast its keys toIdentifiers that are compatible with what the bot tracks internally and sends withTriggers 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.memoriesmodule describes how to useSopelIdentifierMemoryand its siblings.
- memory#
A thread-safe dict for storage of runtime data to be shared between plugins. See
sopel.tools.memories.SopelMemory.
- modeparser#
A mode parser used to parse
MODEmessages and modestrings.
- 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_job_error(
- scheduler: Scheduler,
- job: Job,
- exc: BaseException,
Called when a job from the Job Scheduler fails.
- Parameters:
scheduler – the job scheduler responsible for the errored
jobjob – the Job that errored
exc – the raised exception
See also
- 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.
- on_scheduler_error(
- scheduler: Scheduler,
- exc: BaseException,
Called when the Job Scheduler fails.
- Parameters:
scheduler – the job scheduler that errored
exc – the raised exception
See also
- 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
- property plugins: Mapping[str, plugins.handlers.AbstractPluginHandler]#
A dict of the bot’s currently loaded plugins.
- Returns:
an immutable map of plugin name to plugin object
- post_setup() None#
Perform post-setup actions.
This method handles everything that should happen after all the plugins are loaded, and before the bot can connect to the IRC server.
At the moment, this method checks for undefined configuration options, and starts the job scheduler.
New in version 7.1.
- 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
Identifierthat represents the bot’s nick, e.g. after ISUPPORT info is received.New in version 8.0.
- register_url_callback(pattern, callback)#
Register a
callbackfor URLs matching the regexpattern.- Parameters:
pattern (re.Pattern) – compiled regex pattern to register
callback (function) – callable object to handle matching URLs
New in version 7.0: This method replaces manual management of
url_callbacksin Sopel’s plugins, so instead of doing this insetup():if 'url_callbacks' not in bot.memory: bot.memory['url_callbacks'] = tools.SopelMemory() regex = re.compile(r'http://example.com/path/.*') bot.memory['url_callbacks'][regex] = callback
use this much more concise pattern:
regex = re.compile(r'http://example.com/path/.*') bot.register_url_callback(regex, callback)
It’s recommended you completely avoid manual management of URL callbacks through the use of
sopel.plugin.url().Deprecated since version 7.1: Made obsolete by fixes to the behavior of
sopel.plugin.url(). Will be removed in Sopel 9.Changed in version 8.0: Stores registered callbacks in an internal property instead of
bot.memory['url_callbacks'].
- reload_plugin(name: str) None#
Reload a plugin.
- Parameters:
name – name of the plugin to reload
- Raises:
plugins.exceptions.PluginNotRegistered – when there is no
nameplugin registered
This function runs the plugin’s shutdown routine and unregisters the plugin from the bot. Then this function reloads the plugin, runs its setup routines, and registers it again.
- reload_plugins() None#
Reload all registered plugins.
First, this function runs all plugin shutdown routines and unregisters all plugins. Then it reloads all plugins, runs their setup routines, and registers them again.
- remove_plugin(
- plugin: AbstractPluginHandler,
- callables: Sequence[Callable],
- jobs: Sequence[Callable],
- shutdowns: Sequence[Callable],
- urls: Sequence[Callable],
Remove a loaded plugin from the bot’s registry.
- Parameters:
plugin – loaded plugin to remove
callables – an iterable of callables from the
pluginjobs – an iterable of functions from the
pluginthat are periodically invokedshutdowns – an iterable of functions from the
pluginthat should be called on shutdownurls – an iterable of functions from the
pluginto call when matched against a URL
- reply(text: str, dest: str, reply_to: str, notice: bool = False) 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
NOTICEor not, defaults toFalse
If
noticeisTrue, send aNOTICErather than aPRIVMSG.The same loop detection and length restrictions apply as with
say(), though automatic message splitting is not available.
- request_capabilities() bool#
Request available capabilities and return if negotiation is on.
- Returns:
tell if the negotiation is active or not
This takes the available capabilities and asks the request manager to request only these that are available.
If none is available or if none is requested, the negotiation is not active and this returns
False. It is the responsibility of the caller to make sure it signals the IRC server to end the negotiation with aCAP ENDcommand.
- 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!”)
- resume_capability_negotiation( ) None#
Resume capability negotiation and close when necessary.
- Parameters:
cap_req – a capability request
plugin_name – plugin that requested the capability and wants to resume capability negotiation
This will resume a capability request through the bot’s
capability requests manager, and if the negotiation wasn’t completed before and is now complete, it will send aCAP ENDcommand.This method must be used by plugins that declare a capability request with a handler that returns
sopel.plugin.CapabilityNegotiation.CONTINUEon acknowledgement in order for the bot to resume and eventually close negotiation.For example, this is useful for SASL auth which happens while negotiating capabilities.
- 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
- property running_triggers: list#
Current active threads for triggers.
- Returns:
the running thread(s) currently processing trigger(s)
- Return type:
This is for testing and debugging purposes only.
- 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
PRIVMSGorNOTICEby 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
PRIVMSGto a user or channel.- Parameters:
text – the text to send
recipient – the message recipient
max_messages – split
textinto at most this many messages if it is too long to fit in one (optional)truncation – string to append if
textis too long to fit in a single message, or into the last message ifmax_messagesis greater than 1 (optional)trailing – string to append after
textand (if used)truncation(optional)
By default, this will attempt to send the entire
textin one message. If the text is too long for the server, it may be truncated.If
max_messagesis given, thetextwill 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
textis 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 specifytruncationto tell Sopel how it should indicate that the remainingtextwas cut off. Note that thetruncationparameter must include leading whitespace if you desire any between it and the truncated text.The
trailingparameter is always appended totext, after the point wheretruncationwould 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
truncationandtrailingparameters 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
truncationandtrailingparameters.
- property scheduler: Scheduler#
Job Scheduler. See
sopel.plugin.interval().
- search_url_callbacks(url)#
Yield callbacks whose regex pattern matches the
url.- Parameters:
url (str) – URL found in a trigger
- Returns:
yield 2-value tuples of
(callback, match)
For each pattern that matches the
urlparameter, it yields a 2-value tuple of(callable, match)for that pattern.The
callableis the one registered withregister_url_callback(), and thematchis the result of the regex pattern’ssearchmethod.New in version 7.0.
Changed in version 8.0: Searches for registered callbacks in an internal property instead of
bot.memory['url_callbacks'].Deprecated since version 8.0: Made obsolete by fixes to the behavior of
sopel.plugin.url(). Will be removed in Sopel 9.See also
The Python documentation for the re.search function and the match object.
- 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 haveNoneas 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.capabilitiesand its various methods and attributes:use
bot.capabilities.is_available()to check if a capability is availableuse
bot.capabilities.availablefor a list of available capabilities and their parameters
Will be removed in Sopel 9.
- settings#
The bot’s settings.
New in version 7.0.
- setup() None#
Set up Sopel bot before it can run.
The setup phase is in charge of:
setting up logging (configure Python’s built-in
logging)setting up the bot’s plugins (load, setup, and register)
starting the job scheduler
- shutdown_methods#
List of methods to call on shutdown.
- unregister_url_callback(pattern, callback)#
Unregister the callback for URLs matching the regex
pattern.- Parameters:
pattern (re.Pattern) – compiled regex pattern to unregister callback
callback (function) – callable object to remove
New in version 7.0: This method replaces manual management of
url_callbacksin Sopel’s plugins, so instead of doing this inshutdown():regex = re.compile(r'http://example.com/path/.*') try: del bot.memory['url_callbacks'][regex] except KeyError: pass
use this much more concise pattern:
regex = re.compile(r'http://example.com/path/.*') bot.unregister_url_callback(regex, callback)
It’s recommended you completely avoid manual management of URL callbacks through the use of
sopel.plugin.url().Deprecated since version 7.1: Made obsolete by fixes to the behavior of
sopel.plugin.url(). Will be removed in Sopel 9.Changed in version 8.0: Deletes registered callbacks from an internal property instead of
bot.memory['url_callbacks'].
- users#
A map of the users that Sopel is aware of.
The keys are
Identifiers of the nicknames, and map toUserinstances. In order for Sopel to be aware of a user, it must share at least one mutual channel.
- 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
argsis an iterable of strings, which are joined by spaces.textis 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.
- class sopel.bot.SopelWrapper(sopel, trigger, output_prefix='')#
Bases:
objectWrapper around a Sopel instance and a Trigger.
- Parameters:
This wrapper will be used to call Sopel’s triggered commands and rules as their
botargument. It acts as a proxy, providing thetrigger’ssender(source channel or private message) as the defaultdestinationargument for overridden methods.Deprecated since version 8.0:
SopelWrapperwill be replaced with acontextvarsbased alternative. For more information, see #2460.- action(message, destination=None)#
Override
Sopel.actionto use trigger source by default.- Parameters:
message (str) – action message
destination (str) – channel or nickname; defaults to
trigger.sender
The
destinationwill default to the channel in which the trigger happened (or nickname, if received in a private message).See also
- property default_destination: str | None#
Default say/reply destination for the associated Trigger.
- Returns:
the channel (with status prefix) or nick to send messages to
This property returns the
strversion of the destination that will be used by default by these methods:For a channel, it also ensures that the status-specific prefix is added to the result, so the bot replies with the same status.
- kick(nick, channel=None, message=None)#
Override
Sopel.kickto kick in a channel- Parameters:
The
channelwill default to the channel in which the call was triggered. If triggered from a private message,channelis required.See also
- notice(message, destination=None)#
Override
Sopel.noticeto use trigger source by default.- Parameters:
message (str) – notice message
destination (str) – channel or nickname; defaults to
trigger.sender
The
destinationwill default to the channel in which the trigger happened (or nickname, if received in a private message).See also
- reply(message, destination=None, reply_to=None, notice=False)#
Override
Sopel.replytoreply_tosender by default.- Parameters:
message (str) – reply message
destination (str) – channel or nickname; defaults to
trigger.senderreply_to (str) – person to reply to; defaults to
trigger.nicknotice (bool) – reply as an IRC notice or with a simple message
The
destinationwill default to the channel in which the trigger happened (or nickname, if received in a private message).reply_towill default to the nickname who sent the trigger.See also
- say(
- message,
- destination=None,
- max_messages=1,
- truncation='',
- trailing='',
Override
Sopel.sayto use trigger source by default.- Parameters:
message (str) – message to say
destination (str) – channel or nickname; defaults to
trigger.sendermax_messages (int) – split
messageinto at most this many messages if it is too long to fit into one line (optional)truncation (str) – string to indicate that the
messagewas truncated (optional)trailing (str) – string that should always appear at the end of
message(optional)
The
destinationwill default to the channel in which the trigger happened (or nickname, if received in a private message).See also
For more details about the optional arguments to this wrapper method, consult the documentation for
sopel.bot.Sopel.say().