Additional API features¶
Sopel includes a number of additional functions that are useful for various common IRC tasks.
Note that sopel.web
was deprecated in 6.2.0, and is not included in this
documentation; it will be removed completely in Sopel 8. Plugins should use
requests directly.
Contents
sopel.tools¶
Useful miscellaneous tools and shortcuts for Sopel plugins
Availability: 3+
-
class
sopel.tools.
Ddict
(default=None)¶ A default dict implementation available for Python 2.x support.
It was used to make multi-dimensional
dict
s easy to use when the bot worked with Python version < 2.5.Deprecated since version 7.0: Use
collections.defaultdict
instead.
-
class
sopel.tools.
Identifier
(identifier)¶ A unicode subclass which acts appropriately for IRC identifiers.
When used as normal unicode objects, case will be preserved. However, when comparing two Identifier objects, or comparing a Identifier object with a unicode object, the comparison will be case insensitive. This case insensitivity includes the case convention conventions regarding
[]
,{}
,|
,\
,^
and~
described in RFC 2812.-
is_nick
()¶ Check if the Identifier is a nickname (i.e. not a channel)
- Returns
True
if thisIdentifier
is a nickname;False
if it appears to be a channel
>>> from sopel import tools >>> ident = tools.Identifier('Sopel') >>> ident.is_nick() True >>> ident = tools.Identifier('#sopel') >>> ident.is_nick() False
-
lower
()¶ Get the RFC 2812-compliant lowercase version of this identifier.
- Returns
RFC 2812-compliant lowercase version of the
Identifier
instance- Return type
-
-
class
sopel.tools.
OutputRedirect
(logpath, stderr=False, quiet=False)¶ Redirect the output to the terminal and a log file.
A simplified object used to write to both the terminal and a log file.
-
flush
()¶ Flush the file writing buffer.
-
-
class
sopel.tools.
SopelIdentifierMemory
(*args)¶ Special Sopel memory that stores
Identifier
as key.This is a convenient subclass of
SopelMemory
that always casts its keys as instances ofIdentifier
:>>> from sopel import tools >>> memory = tools.SopelIdentifierMemory() >>> memory['Exirel'] = 'king' >>> list(memory.items()) [(Identifier('Exirel'), 'king')] >>> tools.Identifier('exirel') in memory True >>> 'exirel' in memory True
As seen in the example above, it is possible to perform various operations with both
Identifier
andstr
objects, taking advantage of the case-insensitive behavior ofIdentifier
.Note
Internally, it will try to do
key = tools.Identifier(key)
, which will raise an exception if it cannot instantiate the key properly:>>> memory[1] = 'error' AttributeError: 'int' object has no attribute 'lower'
New in version 7.1.
-
class
sopel.tools.
SopelMemory
(*args)¶ A simple thread-safe
dict
implementation.In order to prevent exceptions when iterating over the values and changing them at the same time from different threads, we use a blocking lock in
__setitem__
andcontains
.New in version 3.1: As
Willie.WillieMemory
Changed in version 4.0: Moved to
tools.WillieMemory
Changed in version 6.0: Renamed from
WillieMemory
toSopelMemory
-
class
sopel.tools.
SopelMemoryWithDefault
(*args)¶ Same as SopelMemory, but subclasses from collections.defaultdict.
New in version 4.3: As
WillieMemoryWithDefault
Changed in version 6.0: Renamed to
SopelMemoryWithDefault
-
sopel.tools.
chain_loaders
(*lazy_loaders)¶ Chain lazy loaders into one.
- Parameters
lazy_loaders (function) – one or more lazy loader functions
- Returns
a lazy loader that combines all of the given ones
- Return type
This function takes any number of lazy loaders as arguments and merges them together into one. It’s primarily a helper for lazy rule decorators such as
sopel.plugin.url_lazy()
.Important
This function doesn’t check the uniqueness of regexes generated by all the loaders.
-
sopel.tools.
check_pid
(pid)¶ Check if a process is running with the given
PID
.- Parameters
pid (int) – PID to check
- Return bool
True
if the given PID is running,False
otherwise
Availability: POSIX systems only.
Note
Matching the
os.kill()
behavior this function needs on Windows was rejected in Python issue #14480, socheck_pid()
cannot be used on Windows systems.
-
sopel.tools.
compile_rule
(nick, pattern, alias_nicks)¶ Compile a rule regex and fill in nickname placeholders.
- Parameters
- Returns
the compiled regex
pattern
, with placeholders for$nick
and$nickname
filled in- Return type
Will not recompile an already compiled pattern.
Deprecated since version 7.1: Rule regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
deprecated
(reason=None, version=None, removed_in=None, warning_in=None, stack_frame=- 1, func=None)¶ Decorator to mark deprecated functions in Sopel’s API
- Parameters
reason (str) – optional text added to the deprecation warning
version (str) – optional version number when the decorated function is deprecated
removed_in (str) – optional version number when the deprecated function will be removed
warning_in (str) – optional version number when the decorated function should start emitting a warning when called
stack_frame (int) – optional stack frame to output; defaults to
-1
; should almost always be negativefunc (callable) – deprecated function
- Returns
a callable that depends on how the decorator is called; either the decorated function, or a decorator with the appropriate parameters
Any time the decorated
func
is called, a deprecation warning will be printed tosys.stderr
, with the last frame of the traceback. The optionalwarning_in
argument suppresses the warning on Sopel versions older than that, allowing for multi-stage deprecation timelines.The decorator can be used with or without arguments:
from sopel import tools @tools.deprecated def func1(): print('func 1') @tools.deprecated() def func2(): print('func 2') @tools.deprecated(reason='obsolete', version='7.0', removed_in='8.0') def func3(): print('func 3')
which will output the following in a console:
>>> func1() Deprecated: func1 File "<stdin>", line 1, in <module> func 1 >>> func2() Deprecated: func2 File "<stdin>", line 1, in <module> func 2 >>> func3() Deprecated since 7.0, will be removed in 8.0: obsolete File "<stdin>", line 1, in <module> func 3
The
stack_frame
argument can be used to choose which stack frame is printed along with the message text. By default, this decorator prints the most recent stack frame (the last entry in the list,-1
), corresponding to where the decorated function itself was called. However, in certain cases such as deprecating conditional behavior within an object constructor, it can be useful to show a less recent stack frame instead.Note
There is nothing that prevents this decorator to be used on a class’s method, or on any existing callable.
New in version 7.0: Parameters
reason
,version
, andremoved_in
.New in version 7.1: The
warning_in
andstack_frame
parameters.
-
sopel.tools.
get_action_command_pattern
(command)¶ Get the uncompiled regex pattern for action commands.
- Parameters
command (str) – the command name
- Returns
a regex pattern that will match the given command
- Return type
Deprecated since version 7.1: Command regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
get_action_command_regexp
(command)¶ Get a compiled regexp object that implements the command.
- Parameters
command (str) – the name of the command
- Returns
a compiled regexp object that implements the command
- Return type
Deprecated since version 7.1: Command regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
get_command_pattern
(prefix, command)¶ Get the uncompiled regex pattern for standard commands.
- Parameters
- Returns
a regex pattern that will match the given command
- Return type
Deprecated since version 7.1: Command regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
get_command_regexp
(prefix, command)¶ Get a compiled regexp object that implements the command.
- Parameters
- Returns
a compiled regexp object that implements the command
- Return type
Deprecated since version 7.1: Command regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
get_hostmask_regex
(mask)¶ Get a compiled regex pattern for an IRC hostmask
- Parameters
mask (str) – the hostmask that the pattern should match
- Returns
a compiled regex pattern matching the given
mask
- Return type
-
sopel.tools.
get_input
(prompt)¶ Get decoded input from the terminal (equivalent to Python 3’s
input
).- Parameters
prompt (str) – what to display as a prompt on the terminal
- Returns
the user’s input
- Return type
Deprecated since version 7.1: Use of this function will become a warning when Python 2 support is dropped in Sopel 8.0. The function will be removed in Sopel 8.1.
-
sopel.tools.
get_logger
(plugin_name)¶ Return a logger for a plugin.
- Parameters
plugin_name (str) – name of the plugin
- Returns
the logger for the given plugin
This:
from sopel import tools LOGGER = tools.get_logger('my_custom_plugin')
is equivalent to this:
import logging LOGGER = logging.getLogger('sopel.externals.my_custom_plugin')
Internally, Sopel configures logging for the
sopel
namespace, so external plugins can’t benefit from it withlogging.getLogger(__name__)
as they won’t be in the same namespace. This function uses theplugin_name
with a prefix inside this namespace.New in version 7.0.
-
sopel.tools.
get_nickname_command_pattern
(command)¶ Get the uncompiled regex pattern for a nickname command.
- Parameters
command (str) – the command name
- Returns
a regex pattern that will match the given nickname command
- Return type
Deprecated since version 7.1: Command regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
get_nickname_command_regexp
(nick, command, alias_nicks)¶ Get a compiled regexp object that implements the nickname command.
- Parameters
- Returns
a compiled regex pattern that implements the given nickname command
- Return type
Deprecated since version 7.1: Command regexp tools are now part of the internal machinery. This function is deprecated and will be removed in Sopel 8.
-
sopel.tools.
get_raising_file_and_line
(tb=None)¶ Get the file and line number where an exception happened.
- Parameters
tb – the traceback (uses the most recent exception if not given)
- Returns
a tuple of the filename and line number
- Return type
Deprecated since version 7.0: Use Python’s built-in logging system, with the
logger.exception
method. This method makes sure to log the exception with the traceback and the relevant information (filename, line number, etc.).
-
sopel.tools.
get_sendable_message
(text, max_length=400)¶ Get a sendable
text
message, with its excess when needed.- Parameters
- Returns
a tuple of two values, the sendable text and its excess text
- Return type
We’re arbitrarily saying that the max is 400 bytes of text when messages will be split. Otherwise, we’d have to account for the bot’s hostmask, which is hard.
The
max_length
is the max length of text in bytes, but we take care of Unicode 2-byte characters by working on the Unicode string, then making sure the bytes version is smaller than the max length.New in version 6.6.2.
-
sopel.tools.
iteritems
()¶ D.items() -> a set-like object providing a view on D’s items
-
sopel.tools.
iterkeys
()¶ D.keys() -> a set-like object providing a view on D’s keys
-
sopel.tools.
itervalues
()¶ D.values() -> an object providing a view on D’s values
sopel.tools.web¶
The tools.web
package contains utility functions for interaction with web
applications, APIs, or websites in your plugins.
New in version 7.0.
Note
Some parts of this module will remain accessible through sopel.web
as
well until its final removal in Sopel 8. This is for backward
compatibility only; please update old code as soon as possible.
-
sopel.tools.web.
r_entity
= re.compile('&([^;\\s]+);')¶ Regular expression to match HTML entities.
-
sopel.tools.web.
DEFAULT_HEADERS
= {'User-Agent': 'Sopel/7.1.9 (https://sopel.chat)'}¶ Default header dict for use with
requests
methods.Use it like this:
import requests from sopel.tools import web result = requests.get( 'https://some.site/api/endpoint', headers=web.DEFAULT_HEADERS )
Important
You should never modify this directly in your plugin code. Make a copy and use
update()
if you need to add or change headers:from sopel.tools import web default_headers = web.DEFAULT_HEADERS.copy() custom_headers = {'Accept': 'text/*'} default_headers.update(custom_headers)
-
sopel.tools.web.
USER_AGENT
= 'Sopel/7.1.9 (https://sopel.chat)'¶ User agent string to be sent with HTTP requests.
Meant to be passed like so:
import requests from sopel.tools import web result = requests.get( 'https://some.site/api/endpoint', user_agent=web.USER_AGENT )
-
sopel.tools.web.
decode
(html)¶ Decode HTML entities into Unicode text.
- Parameters
html (str) – the HTML page or snippet to process
- Return str
html
with all entity references replaced
-
sopel.tools.web.
entity
(match)¶ Convert an entity reference to the appropriate character.
-
sopel.tools.web.
iri_to_uri
(iri)¶ Decodes an internationalized domain name (IDN).
-
sopel.tools.web.
quote
(string, safe='/')¶ Safely encodes a string for use in a URL.
- Parameters
- Return str
the
string
with special characters URL-encoded
Note
This is a shim to make writing cross-compatible plugins for both Python 2 and Python 3 easier.
-
sopel.tools.web.
quote_query
(string)¶ Safely encodes a URL’s query parameters.
- Parameters
string (str) – a URL containing query parameters
- Return str
the input URL with query parameter values URL-encoded
-
sopel.tools.web.
search_urls
(text, exclusion_char=None, clean=False, schemes=None)¶ Extracts all URLs in
text
.- Parameters
text (str) – the text to search for URLs
exclusion_char (str) – optional character that, if placed before a URL in the
text
, will exclude it from being extractedclean (bool) – if
True
, all found URLs are passed throughtrim_url()
before being returned; defaultFalse
schemes (list) – optional list of URL schemes to look for; defaults to
['http', 'https', 'ftp']
- Returns
generator iterator of all URLs found in
text
To get the URLs as a plain list, use e.g.:
list(search_urls(text))
-
sopel.tools.web.
trim_url
(url)¶ Removes extra punctuation from URLs found in text.
- Parameters
url (str) – the raw URL match
- Return str
the cleaned URL
This function removes trailing punctuation that looks like it was not intended to be part of the URL:
trailing sentence- or clause-ending marks like
.
,;
, etc.unmatched trailing brackets/braces like
}
,)
, etc.
It is intended for use with the output of
search_urls()
, which may include trailing punctuation when used on input from chat.
-
sopel.tools.web.
unquote
(string)¶ Decodes a URL-encoded string.
- Parameters
string (str) – the string to decode
- Return str
the decoded
string
Note
This is a shim to make writing cross-compatible plugins for both Python 2 and Python 3 easier.
-
sopel.tools.web.
urlencode
(query, doseq=False, safe='', encoding=None, errors=None, quote_via=<function quote_plus>)¶ Encode a dict or sequence of two-element tuples into a URL query string.
If any values in the query arg are sequences and doseq is true, each sequence element is converted to a separate parameter.
If the query arg is a sequence of two-element tuples, the order of the parameters in the output will match the order of parameters in the input.
The components of a query arg may each be either a string or a bytes type.
The safe, encoding, and errors parameters are passed down to the function specified by quote_via (encoding and errors only if a component is a str).
-
sopel.tools.web.
urlencode_non_ascii
(b)¶ Safely encodes non-ASCII characters in a URL.
sopel.tools.time¶
Tools for getting and displaying the time.
-
sopel.tools.time.
format_time
(db=None, config=None, zone=None, nick=None, channel=None, time=None)¶ Return a formatted string of the given time in the given zone.
- Parameters
db (
SopelDB
) – bot database object (optional)config (
Config
) – bot config object (optional)zone (str) – name of timezone to use (optional)
nick (str) – nick whose time format to use, if set (optional)
channel (str) – channel whose time format to use, if set (optional)
time (
datetime
) – the time value to format (optional)
time
, if given, should be a naivedatetime.datetime
object and will be treated as being in the UTC timezone. If it is not given, the current time will be used. Ifzone
is given it must be present in the IANA Time Zone Database;get_timezone
can be helpful for this. Ifzone
is not given, UTC will be assumed.The format for the string is chosen in the following order:
The format for the nick
nick
indb
, if one is set and valid.The format for the channel
channel
indb
, if one is set and valid.The default format in
config
, if one is set and valid.ISO-8601
If
db
is not given or is not set up, steps 1 and 2 are skipped. Ifconfig
is not given, step 3 will be skipped.
-
sopel.tools.time.
get_channel_timezone
(db, channel)¶ Get a channel’s timezone from database.
- Parameters
db (
SopelDB
) – Bot’s database handler (usuallybot.db
)channel (
Identifier
) – IRC channel name
- Returns
the timezone associated with the
channel
If a timezone cannot be found for
channel
, or if it is invalid,None
will be returned.
-
sopel.tools.time.
get_nick_timezone
(db, nick)¶ Get a nick’s timezone from database.
- Parameters
db (
SopelDB
) – Bot’s database handler (usuallybot.db
)nick (
Identifier
) – IRC nickname
- Returns
the timezone associated with the
nick
If a timezone cannot be found for
nick
, or if it is invalid,None
will be returned.
-
sopel.tools.time.
get_time_unit
(years=0, months=0, days=0, hours=0, minutes=0, seconds=0)¶ Map a time in (y, m, d, h, min, s) to its labels.
- Parameters
- Returns
a tuple of 2-value tuples, each for a time amount and its label
- Return type
This helper function get a time split in years, months, days, hours, minutes, and seconds to return a tuple with the correct label for each unit. The label is pluralized and account for zéro, one, and more than one value per unit:
>>> get_time_unit(days=1, hours=15, minutes=54, seconds=19) ( (0, 'years'), (0, 'months'), (1, 'day'), (15, 'hours'), (54, 'minutes'), (19, 'seconds'), )
This function can be used with
seconds_to_split()
:>>> get_time_unit(*seconds_to_split(143659)) # ... same result as the example above
Note
This function always returns a tuple with all time units, even when their amount is 0 (which is their default value).
-
sopel.tools.time.
get_timezone
(db=None, config=None, zone=None, nick=None, channel=None)¶ Find, and return, the appropriate timezone.
- Parameters
Timezone is pulled in the following priority:
zone
, if it is validThe timezone for the channel or nick
zone
indb
if one is set and valid.The timezone for the nick
nick
indb
, if one is set and valid.The timezone for the channel
channel
indb
, if one is set and valid.The default timezone in
config
, if one is set and valid.
If
db
is not given, or given but not set up, steps 2 and 3 will be skipped. Ifconfig
is not given, step 4 will be skipped. If no step yields a valid timezone,None
is returned.Valid timezones are those present in the IANA Time Zone Database.
See also
The
validate_timezone()
function handles the validation and formatting of the timezone.
-
sopel.tools.time.
seconds_to_human
(secs, granularity=2)¶ Format
timedelta
as a human-readable relative time.- Parameters
Inspiration for function structure from: https://gist.github.com/Highstaker/280a09591df4a5fb1363b0bbaf858f0d
Examples:
>>> seconds_to_human(65707200) '2 years, 1 month ago' >>> seconds_to_human(-17100) # negative amount 'in 4 hours, 45 minutes' >>> seconds_to_human(-709200) 'in 8 days, 5 hours' >>> seconds_to_human(39441600, 1) # 1 year + 3 months '1 year ago'
This function can be used with a
timedelta
:>>> from datetime import timedelta >>> seconds_to_human(timedelta(days=42, seconds=278)) '1 month, 11 days ago'
The
granularity
argument controls how detailed the result is:>>> seconds_to_human(3672) # 2 by default '1 hour, 1 minute ago' >>> seconds_to_human(3672, granularity=3) '1 hour, 1 minute, 12 seconds ago' >>> seconds_to_human(3672, granularity=1) '1 hour ago'
-
sopel.tools.time.
seconds_to_split
(seconds)¶ Split an amount of
seconds
into years, months, days, etc.- Parameters
seconds (int) – amount of time in seconds
- Returns
the time split into a tuple of years, months, days, hours, minutes, and seconds
- Return type
Examples:
>>> seconds_to_split(7800) (0, 0, 0, 2, 10, 0) >>> seconds_to_split(143659) (0, 0, 1, 15, 54, 19)
-
sopel.tools.time.
validate_format
(tformat)¶ Validate a time format string.
- Parameters
tformat (str) – the format string to validate
- Returns
the format string, if valid
- Raises
ValueError – when
tformat
is not a valid time format string
-
sopel.tools.time.
validate_timezone
(zone)¶ Return an IETF timezone from the given IETF zone or common abbreviation.
- Parameters
zone (str) – in a strict or a human-friendly format
- Returns
the valid IETF timezone properly formatted
- Raises
ValueError – when
zone
is not a valid timezone
Prior to checking timezones, two transformations are made to make the zone names more human-friendly:
the string is split on
', '
, the pieces reversed, and then joined with/
(“New York, America” becomes “America/New York”)Remaining spaces are replaced with
_
This means
new york, america
becomesAmerica/New_York
, andutc
becomesUTC
. In the majority of user-facing interactions, such case-insensitivity will be expected.If the zone is not valid,
ValueError
will be raised.
sopel.tools.calculation¶
Tools to help safely do calculations from user input
-
sopel.tools.calculation.
eval_equation
= <sopel.tools.calculation.EquationEvaluator object>¶ Evaluates a Python equation expression and returns the result.
- Parameters
Supports addition (+), subtraction (-), multiplication (*), division (/), power (**) and modulo (%).
sopel.tools.target¶
-
class
sopel.tools.target.
Channel
(name)¶ A representation of a channel Sopel is in.
- Parameters
name (
Identifier
) – the channel name
-
add_user
(user, privs=0)¶ Add
user
to this channel.- Parameters
user (
User
) – the new user to addprivs (int) – privilege bitmask (see constants in
sopel.plugin
)
Called when a new user JOINs the channel.
-
clear_user
(nick)¶ Remove
nick
from this channel.- Parameters
nick (
Identifier
) – the nickname of the user to remove
Called after a user leaves the channel via PART, KICK, QUIT, etc.
-
has_privilege
(nick, privilege)¶ Tell if a user has a
privilege
level or above in this channel.- Parameters
- Return type
This method checks the user’s privilege level in this channel, i.e. if it has this level or higher privileges:
>>> channel.add_user(some_user, plugin.OP) >>> channel.has_privilege(some_user.nick, plugin.VOICE) True
The
nick
argument can be either astr
or asopel.tools.Identifier
. If the user is not in this channel, it will be considered as not having any privilege.See also
There are other methods to check the exact privilege level of a user, such as
is_oper()
,is_owner()
,is_admin()
,is_op()
,is_halfop()
, andis_voiced()
.Important
Not all IRC networks support all privilege levels. If you intend for your plugin to run on any network, it is safest to rely only on the presence of standard modes:
+v
(voice) and+o
(op).
-
is_admin
(nick)¶ Tell if a user has the ADMIN privilege level.
Unlike
has_privilege()
, this method checks if the user has been explicitly granted the ADMIN privilege level:>>> channel.add_user(some_user, plugin.ADMIN) >>> channel.is_admin(some_user.nick) True >>> channel.is_voiced(some_user.nick) False
Note that you can always have more than one privilege level:
>>> channel.add_user(some_user, plugin.ADMIN | plugin.VOICE) >>> channel.is_admin(some_user.nick) True >>> channel.is_voiced(some_user.nick) True
Important
Not all IRC networks support this privilege mode. If you are writing a plugin for public distribution, ensure your code behaves sensibly if only
+v
(voice) and+o
(op) modes exist.
-
is_halfop
(nick)¶ Tell if a user has the HALFOP privilege level.
Unlike
has_privilege()
, this method checks if the user has been explicitly granted the HALFOP privilege level:>>> channel.add_user(some_user, plugin.HALFOP) >>> channel.is_halfop(some_user.nick) True >>> channel.is_voiced(some_user.nick) False
Note that you can always have more than one privilege level:
>>> channel.add_user(some_user, plugin.HALFOP | plugin.VOICE) >>> channel.is_halfop(some_user.nick) True >>> channel.is_voiced(some_user.nick) True
Important
Not all IRC networks support this privilege mode. If you are writing a plugin for public distribution, ensure your code behaves sensibly if only
+v
(voice) and+o
(op) modes exist.
-
is_op
(nick)¶ Tell if a user has the OP privilege level.
Unlike
has_privilege()
, this method checks if the user has been explicitly granted the OP privilege level:>>> channel.add_user(some_user, plugin.OP) >>> channel.is_op(some_user.nick) True >>> channel.is_voiced(some_user.nick) False
Note that you can always have more than one privilege level:
>>> channel.add_user(some_user, plugin.OP | plugin.VOICE) >>> channel.is_op(some_user.nick) True >>> channel.is_voiced(some_user.nick) True
-
is_oper
(nick)¶ Tell if a user has the OPER (operator) privilege level.
Unlike
has_privilege()
, this method checks if the user has been explicitly granted the OPER privilege level:>>> channel.add_user(some_user, plugin.OPER) >>> channel.is_oper(some_user.nick) True >>> channel.is_voiced(some_user.nick) False
Note that you can always have more than one privilege level:
>>> channel.add_user(some_user, plugin.OPER | plugin.VOICE) >>> channel.is_oper(some_user.nick) True >>> channel.is_voiced(some_user.nick) True
Important
Not all IRC networks support this privilege mode. If you are writing a plugin for public distribution, ensure your code behaves sensibly if only
+v
(voice) and+o
(op) modes exist.
-
is_owner
(nick)¶ Tell if a user has the OWNER privilege level.
Unlike
has_privilege()
, this method checks if the user has been explicitly granted the OWNER privilege level:>>> channel.add_user(some_user, plugin.OWNER) >>> channel.is_owner(some_user.nick) True >>> channel.is_voiced(some_user.nick) False
Note that you can always have more than one privilege level:
>>> channel.add_user(some_user, plugin.OWNER | plugin.VOICE) >>> channel.is_owner(some_user.nick) True >>> channel.is_voiced(some_user.nick) True
Important
Not all IRC networks support this privilege mode. If you are writing a plugin for public distribution, ensure your code behaves sensibly if only
+v
(voice) and+o
(op) modes exist.
-
is_voiced
(nick)¶ Tell if a user has the VOICE privilege level.
Unlike
has_privilege()
, this method checks if the user has been explicitly granted the VOICE privilege level:>>> channel.add_user(some_user, plugin.VOICE) >>> channel.is_voiced(some_user.nick) True >>> channel.add_user(some_user, plugin.OP) >>> channel.is_voiced(some_user.nick) False
Note that you can always have more than one privilege level:
>>> channel.add_user(some_user, plugin.VOICE | plugin.OP) >>> channel.is_voiced(some_user.nick) True >>> channel.is_op(some_user.nick) True
-
last_who
¶ The last time a WHO was requested for the channel.
-
modes
¶ The channel’s modes.
For type A modes (nick/address list), the value is a set. For type B (parameter) or C (parameter when setting), the value is a string. For type D, the value is
True
.Note
Type A modes may only contain changes the bot has observed. Sopel does not automatically populate all modes and lists.
-
name
¶ The name of the channel.
-
privileges
¶ The permissions of the users in the channel.
This maps nickname
Identifier
s to bitwise integer values. This can be compared to appropriate constants fromsopel.plugin
.
-
rename_user
(old, new)¶ Rename a user.
- Parameters
old (
Identifier
) – the user’s old nicknamenew (
Identifier
) – the user’s new nickname
Called on NICK events.
-
topic
¶ The topic of the channel.
-
users
¶ The users in the channel.
This maps nickname
Identifier
s toUser
objects.
-
class
sopel.tools.target.
User
(nick, user, host)¶ A representation of a user Sopel is aware of.
- Parameters
nick (
Identifier
) – the user’s nicknameuser (str) – the user’s local username (“user” in user@host.name)
host (str) – the user’s hostname (“host.name” in user@host.name)
-
account
¶ The IRC services account of the user.
This relies on IRCv3 account tracking being enabled.
-
away
¶ Whether the user is marked as away.
-
channels
¶ The channels the user is in.
This maps channel name
Identifier
s toChannel
objects.
-
host
¶ The user’s hostname.
-
property
hostmask
¶ The user’s full hostmask.
-
nick
¶ The user’s nickname.
-
user
¶ The user’s local username.
sopel.tools.events¶
-
class
sopel.tools.
events
¶ An enumeration of all the standardized and notable IRC numeric events
This allows you to do, for example,
@plugin.event(events.RPL_WELCOME)
rather than@plugin.event('001')
-
ERR_ALREADYREGISTERED
= '462'¶
-
ERR_ALREADYREGISTRED
= '462'¶
-
ERR_BADCHANMASK
= '476'¶
-
ERR_BADCHANNELKEY
= '475'¶
-
ERR_BADMASK
= '415'¶
-
ERR_BANLISTFULL
= '478'¶
-
ERR_BANNEDFROMCHAN
= '474'¶
-
ERR_CANNOTSENDTOCHAN
= '404'¶
-
ERR_CANTKILLSERVER
= '483'¶
-
ERR_CHANNELISFULL
= '471'¶
-
ERR_CHANOPRIVSNEEDED
= '482'¶
-
ERR_ERRONEUSNICKNAME
= '432'¶
-
ERR_FILEERROR
= '424'¶
-
ERR_INVALIDCAPCMD
= '410'¶
-
ERR_INVITEONLYCHAN
= '473'¶
-
ERR_KEYINVALID
= '767'¶
-
ERR_KEYNOPERMISSION
= '769'¶
-
ERR_KEYNOTSET
= '768'¶
-
ERR_KEYSET
= '467'¶
-
ERR_METADATALIMIT
= '764'¶
-
ERR_MONLISTFULL
= '734'¶
-
ERR_NEEDMOREPARAMS
= '461'¶
-
ERR_NICKCOLLISION
= '436'¶
-
ERR_NICKLOCKED
= '902'¶
-
ERR_NICKNAMEINUSE
= '433'¶
-
ERR_NOADMININFO
= '423'¶
-
ERR_NOCHANMODES
= '477'¶
-
ERR_NOLOGIN
= '444'¶
-
ERR_NOMATCHINGKEY
= '766'¶
-
ERR_NOMOTD
= '422'¶
-
ERR_NONICKNAMEGIVEN
= '431'¶
-
ERR_NOOPERHOST
= '491'¶
-
ERR_NOORIGIN
= '409'¶
-
ERR_NOPERMFORHOST
= '463'¶
-
ERR_NOPRIVILEGES
= '481'¶
-
ERR_NORECIPIENT
= '411'¶
-
ERR_NOSUCHCHANNEL
= '403'¶
-
ERR_NOSUCHNICK
= '401'¶
-
ERR_NOSUCHSERVER
= '402'¶
-
ERR_NOSUCHSERVICE
= '408'¶
-
ERR_NOTEXTTOSEND
= '412'¶
-
ERR_NOTONCHANNEL
= '442'¶
-
ERR_NOTOPLEVEL
= '413'¶
-
ERR_NOTREGISTERED
= '451'¶
-
ERR_PASSWDMISMATCH
= '464'¶
-
ERR_RESTRICTED
= '484'¶
-
ERR_SASLABORTED
= '906'¶
-
ERR_SASLALREADY
= '907'¶
-
ERR_SASLFAIL
= '904'¶
-
ERR_SASLTOOLONG
= '905'¶
-
ERR_STARTTLS
= '691'¶
-
ERR_SUMMONDISABLED
= '445'¶
-
ERR_TARGETINVALID
= '765'¶
-
ERR_TOOMANYCHANNELS
= '405'¶
-
ERR_TOOMANYTARGETS
= '407'¶
-
ERR_UMODEUNKNOWNFLAG
= '501'¶
-
ERR_UNAVAILRESOURCE
= '437'¶
-
ERR_UNIQOPPRIVSNEEDED
= '485'¶
-
ERR_UNKNOWNCOMMAND
= '421'¶
-
ERR_UNKNOWNMODE
= '472'¶
-
ERR_USERNOTINCHANNEL
= '441'¶
-
ERR_USERONCHANNEL
= '443'¶
-
ERR_USERSDISABLED
= '446'¶
-
ERR_USERSDONTMATCH
= '502'¶
-
ERR_WASNOSUCHNICK
= '406'¶
-
ERR_WILDTOPLEVEL
= '414'¶
-
ERR_YOUREBANNEDCREEP
= '465'¶
-
ERR_YOUWILLBEBANNED
= '466'¶
-
RPL_ADMINEMAIL
= '259'¶
-
RPL_ADMINLOC1
= '257'¶
-
RPL_ADMINLOC2
= '258'¶
-
RPL_ADMINME
= '256'¶
-
RPL_AWAY
= '301'¶
-
RPL_BANLIST
= '367'¶
-
RPL_BOUNCE
= '005'¶
-
RPL_CHANNELMODEIS
= '324'¶
-
RPL_CREATED
= '003'¶
-
RPL_ENDOFBANLIST
= '368'¶
-
RPL_ENDOFEXCEPTLIST
= '349'¶
-
RPL_ENDOFINFO
= '374'¶
-
RPL_ENDOFINVITELIST
= '347'¶
-
RPL_ENDOFLINKS
= '365'¶
-
RPL_ENDOFMONLIST
= '733'¶
-
RPL_ENDOFMOTD
= '376'¶
-
RPL_ENDOFNAMES
= '366'¶
-
RPL_ENDOFSTATS
= '219'¶
-
RPL_ENDOFUSERS
= '394'¶
-
RPL_ENDOFWHO
= '315'¶
-
RPL_ENDOFWHOIS
= '318'¶
-
RPL_ENDOFWHOWAS
= '369'¶
-
RPL_EXCEPTLIST
= '348'¶
-
RPL_INFO
= '371'¶
-
RPL_INVITELIST
= '346'¶
-
RPL_INVITING
= '341'¶
-
RPL_ISON
= '303'¶
-
RPL_ISUPPORT
= '005'¶
-
RPL_KEYVALUE
= '761'¶
-
RPL_LINKS
= '364'¶
-
RPL_LIST
= '322'¶
-
RPL_LISTEND
= '323'¶
-
RPL_LISTSTART
= '321'¶
-
RPL_LOGGEDIN
= '900'¶
-
RPL_LOGGEDOUT
= '901'¶
-
RPL_LUSERCHANNELS
= '254'¶
-
RPL_LUSERCLIENT
= '251'¶
-
RPL_LUSERME
= '255'¶
-
RPL_LUSEROP
= '252'¶
-
RPL_LUSERUNKNOWN
= '253'¶
-
RPL_METADATAEND
= '762'¶
-
RPL_MONLIST
= '732'¶
-
RPL_MONOFFLINE
= '731'¶
-
RPL_MONONLINE
= '730'¶
-
RPL_MOTD
= '372'¶
-
RPL_MOTDSTART
= '375'¶
-
RPL_MYINFO
= '004'¶
-
RPL_NAMREPLY
= '353'¶
-
RPL_NONE
= '300'¶
-
RPL_NOTOPIC
= '331'¶
-
RPL_NOUSERS
= '395'¶
-
RPL_NOWAWAY
= '306'¶
-
RPL_REHASHING
= '382'¶
-
RPL_SASLMECHS
= '908'¶
-
RPL_SASLSUCCESS
= '903'¶
-
RPL_SERVLIST
= '234'¶
-
RPL_SERVLISTEND
= '235'¶
-
RPL_STARTTLS
= '670'¶
-
RPL_STATSCLINE
= '213'¶
-
RPL_STATSCOMMANDS
= '212'¶
-
RPL_STATSHLINE
= '244'¶
-
RPL_STATSILINE
= '215'¶
-
RPL_STATSKLINE
= '216'¶
-
RPL_STATSLINKINFO
= '211'¶
-
RPL_STATSLLINE
= '241'¶
-
RPL_STATSNLINE
= '214'¶
-
RPL_STATSOLINE
= '243'¶
-
RPL_STATSUPTIME
= '242'¶
-
RPL_STATSYLINE
= '218'¶
-
RPL_SUMMONING
= '342'¶
-
RPL_TIME
= '391'¶
-
RPL_TOPIC
= '332'¶
-
RPL_TRACECLASS
= '209'¶
-
RPL_TRACECONNECTING
= '201'¶
-
RPL_TRACEEND
= '262'¶
-
RPL_TRACEHANDSHAKE
= '202'¶
-
RPL_TRACELINK
= '200'¶
-
RPL_TRACELOG
= '261'¶
-
RPL_TRACENEWTYPE
= '208'¶
-
RPL_TRACEOPERATOR
= '204'¶
-
RPL_TRACERECONNECT
= '210'¶
-
RPL_TRACESERVER
= '206'¶
-
RPL_TRACESERVICE
= '207'¶
-
RPL_TRACEUNKNOWN
= '203'¶
-
RPL_TRACEUSER
= '205'¶
-
RPL_TRYAGAIN
= '263'¶
-
RPL_UMODEIS
= '221'¶
-
RPL_UNAWAY
= '305'¶
-
RPL_UNIQOPIS
= '325'¶
-
RPL_USERHOST
= '302'¶
-
RPL_USERS
= '393'¶
-
RPL_USERSSTART
= '392'¶
-
RPL_VERSION
= '351'¶
-
RPL_WELCOME
= '001'¶
-
RPL_WHOISCHANNELS
= '319'¶
-
RPL_WHOISIDLE
= '317'¶
-
RPL_WHOISKEYVALUE
= '760'¶
-
RPL_WHOISOPERATOR
= '313'¶
-
RPL_WHOISSERVER
= '312'¶
-
RPL_WHOISUSER
= '311'¶
-
RPL_WHOREPLY
= '352'¶
-
RPL_WHOSPCRPL
= '354'¶
-
RPL_WHOWASUSER
= '314'¶
-
RPL_YOUREOPER
= '381'¶
-
RPL_YOURESERVICE
= '383'¶
-
RPL_YOURHOST
= '002'¶
-
sopel.tools.jobs¶
Sopel’s Job Scheduler: internal tool for job management.
Important
As of Sopel 5.3, this is an internal tool used by Sopel to manage internal jobs and should not be used by plugin authors. Its usage and documentation is for Sopel core development and advanced developers. It is subject to rapid changes between versions without much (or any) warning.
-
class
sopel.tools.jobs.
Job
(intervals, plugin=None, label=None, handler=None, threaded=True, doc=None)¶ Holds information about when a function should be called next.
- Parameters
intervals (iterable) – set of intervals; each is a number of seconds between calls to
handler
plugin (str) – optional plugin name to which the job belongs
label (str) – optional label (name) for the job
handler (function) – function to be called when the job is ready to execute
doc (str) – optional documentation for the job
Job is a simple structure that holds information about when a function should be called next. They are best used with a
Scheduler
that will manage job execution when they are ready.The function to execute is the
handler
, which must be a callable with this signature:def handler(manager): # perform action periodically # return is optional
The
manager
parameter can be any kind of object; usually it’s an instance ofsopel.bot.Sopel
.When a job is ready, you can execute it by calling its
execute()
method (providing the appropriatemanager
argument):if job.is_ready_to_run(time.time()): job.execute(manager) # marked as running # "next times" have been updated; the job is not running
In that case,
execute
takes care of the running state of the job.Alternatively, you can use a
with
statement to perform action before and/or after executing the job; in that case, thewith
statement takes precedence, and theexecute()
method won’t interfere:with job: # the job is now running, you can perform pre-execute action job.execute() # execute the job's action, no state modification # the job is still marked as "running" # you can perform post-execute action # outside of the with statement, the job is not running anymore
See also
The
sopel.plugins.jobs.Scheduler
class is specifically designed for plugins’ jobs, expecting an instance ofsopel.bot.Sopel
as a manager, and should be used to manipulate plugin jobs.In all other case, the
sopel.tools.jobs.Scheduler
class is a generic job scheduler.-
execute
(manager)¶ Execute the job’s handler and return its result.
- Parameters
manager (object) – used as argument to the job’s handler
- Returns
the return value from the handler’s execution
This method executes the job’s handler. It doesn’t change its running state, as this must be done by the caller:
with job: # mark as running # before execution job.execute(manager) # after execution
-
classmethod
from_callable
(settings, handler)¶ Instantiate a Job from the bot’s
settings
and ahandler
.- Parameters
settings (
sopel.config.Config
) – bot’s settingshandler (function) – callable used to instantiate a new job
-
get_doc
()¶ Get the job’s documentation.
- Return type
A job’s documentation is a short text that can be displayed to a user.
-
get_job_label
()¶ Get the job’s label.
- Return type
A job can have a label, which can identify the job by string, the same way rules can be. This label can be used to manipulate or display the job’s information in a more human-readable way. Note that the label has no effect on the job’s execution.
-
get_plugin_name
()¶ Get the job’s plugin name.
- Return type
The job’s plugin name will be used in various places to select, register, unregister, and manipulate the job based on its plugin, which is referenced by its name.
-
intervals
¶ Set of intervals at which to execute the job.
-
is_ready_to_run
(at_time)¶ Check if this job is (or will be) ready to run at the given time.
-
is_running
¶ Running flag: it tells if the job is running or not.
This flag is set and cleared automatically by the
execute()
method. It is also set and cleared when the job is used with thewith
statement:with job: # you do something before executing the job # this ensures that the job is marked as "running"
Note
When set manually or with the
with
statement, theexecute()
method won’t clear this attribute itself.
-
is_threaded
()¶ Tell if the job’s execution should be in a thread.
- Returns
True
if the execution should be in a thread,False
otherwise- Return type
-
classmethod
kwargs_from_callable
(handler)¶ Generate the keyword arguments to create a new instance.
- Parameters
handler (function) – callable used to generate keyword arguments
- Returns
a map of keyword arguments
- Return type
This classmethod takes the
handler
’s attributes to generate a map of keyword arguments for the class. This can be used by thefrom_callable()
classmethod to instantiate a new rule object.The expected attributes are the ones set by decorators from the
sopel.plugin
module.
-
next
(current_time)¶ Update
next_times
, assuming it executed atcurrent_time
.- Parameters
current_time (int) – timestamp of the current time
- Returns
a modified job object
-
next_times
¶ Tracking of when to execute the job next time.
-
class
sopel.tools.jobs.
Scheduler
(manager)¶ Generic Job Scheduler.
- Parameters
manager (object) – manager passed to jobs as argument
Scheduler is a
thread
that keeps track ofJobs
and periodically checks which ones are ready to execute. When ready, theirexecute()
method is called, either in a separate thread or in the scheduler’s thread (it depends on the job’sis_threaded()
method).It can be started as any other thread:
# on bot's startup scheduler = jobs.Scheduler(bot) scheduler.start() # run the thread forever
Then it runs forever until the
stop()
method is called, usually when the bot shuts down.Note
Thread safety is ensured with threading’s
Lock
andEvent
when:a job is
registered
orremoved
the scheduler gets jobs that are ready for execution
These actions can be performed while the scheduler is running.
Important
This is an internal tool used by Sopel to manage internal jobs and should not be used by plugin authors. Its usage and documentation is for Sopel core development and advanced developers. It is subject to rapid changes between versions without much (or any) warning.
-
clear_jobs
()¶ Clear current Job queue and start fresh.
This method is thread safe. However, it won’t cancel or stop any currently running jobs.
-
manager
¶ Job manager, used as argument for jobs.
-
register
(job)¶ Register a Job to the current job queue.
- Parameters
job (
sopel.tools.jobs.Job
) – job to register
This method is thread safe.
-
remove_callable_job
(callable)¶ Remove
callable
from the job queue.- Parameters
callable (function) – the callable to remove
This method is thread safe. However, it won’t cancel or stop any currently running jobs.
-
run
()¶ Run forever until
stop()
is called.This method waits at most a second between each iteration. At each step it retrieves the jobs that are ready for execution, and executes them. See the
Job.execute()
method for more information.Internally, it loops forever until its
stopping
event is set.Note
This should not be called directly, as it will be done by the
threading.Thread.start()
method.
-
stop
()¶ Ask the job scheduler to stop.
The scheduler thread will stop its loop over jobs to process, but it won’t join the thread, or clear its queue—this has to be done separately by the calling thread:
scheduler.stop() # ask the scheduler to stop scheduler.join() # wait for the scheduler to actually stop
Note that this won’t cancel or stop any currently running jobs.
sopel.formatting¶
The formatting module includes functions to apply IRC formatting to text.
Availability: 4.5+
-
sopel.formatting.
CONTROL_BOLD
= '\x02'¶ The control code to start or end bold formatting.
-
sopel.formatting.
CONTROL_COLOR
= '\x03'¶ The control code to start or end color formatting.
-
sopel.formatting.
CONTROL_HEX_COLOR
= '\x04'¶ The control code to start or end hexadecimal color formatting.
-
sopel.formatting.
CONTROL_ITALIC
= '\x1d'¶ The control code to start or end italic formatting.
-
sopel.formatting.
CONTROL_MONOSPACE
= '\x11'¶ The control code to start or end monospace formatting.
-
sopel.formatting.
CONTROL_NORMAL
= '\x0f'¶ The control code to reset formatting.
-
sopel.formatting.
CONTROL_REVERSE
= '\x16'¶ The control code to start or end reverse-color formatting.
-
sopel.formatting.
CONTROL_STRIKETHROUGH
= '\x1e'¶ The control code to start or end strikethrough formatting.
-
sopel.formatting.
CONTROL_UNDERLINE
= '\x1f'¶ The control code to start or end underlining.
-
sopel.formatting.
bold
(text)¶ Return the text, with bold IRC formatting.
- Parameters
text (str) – the text to format
-
sopel.formatting.
color
(text, fg=None, bg=None)¶ Return the text, with the given colors applied in IRC formatting.
- Parameters
text (str) – the text to format
fg (mixed) – the foreground color
bg (mixed) – the background color
The color can be a string of the color name, or an integer in the range 0-99. The known color names can be found in the
colors
class of this module.
-
class
sopel.formatting.
colors
¶ -
BLACK
= '01'¶
-
BLUE
= '02'¶
-
BROWN
= '05'¶
-
CYAN
= '11'¶
-
FUCHSIA
= '13'¶
-
GRAY
= '14'¶
-
GREEN
= '03'¶
-
GREY
= '14'¶
-
LIGHT_BLUE
= '12'¶
-
LIGHT_CYAN
= '11'¶
-
LIGHT_GRAY
= '15'¶
-
LIGHT_GREEN
= '09'¶
-
LIGHT_GREY
= '15'¶
-
LIGHT_PURPLE
= '13'¶
-
LIME
= '09'¶
-
MAROON
= '05'¶
-
NAVY
= '02'¶
-
OLIVE
= '07'¶
-
ORANGE
= '07'¶
-
PINK
= '13'¶
-
PURPLE
= '06'¶
-
RED
= '04'¶
-
ROYAL
= '12'¶
-
SILVER
= '15'¶
-
TEAL
= '10'¶
-
WHITE
= '00'¶
-
YELLOW
= '08'¶
-
-
sopel.formatting.
hex_color
(text, fg=None, bg=None)¶ Return the text, with the given colors applied in IRC formatting.
- Parameters
The color can be provided with a string of either 3 or 6 hexadecimal digits. As in CSS, 3-digit colors will be interpreted as if they were 6-digit colors with each digit repeated (e.g. color
c90
is identical tocc9900
). Do not include the leading#
symbol.Note
This is a relatively new IRC formatting convention. Use only when you can afford to have its meaning lost, as not many clients support it yet.
-
sopel.formatting.
italic
(text)¶ Return the text, with italic IRC formatting.
- Parameters
text (str) – the text to format
-
sopel.formatting.
monospace
(text)¶ Return the text, with monospace IRC formatting.
- Parameters
text (str) – the text to format
Note
This is a relatively new IRC formatting convention. Use only when you can afford to have its meaning lost, as not many clients support it yet.
-
sopel.formatting.
plain
(text)¶ Return the text without any IRC formatting.
-
sopel.formatting.
reverse
(text)¶ Return the text, with reverse-color IRC formatting.
- Parameters
text (str) – the text to format
Note
This code isn’t super well supported, and its behavior even in clients that understand it (e.g. mIRC) can be unpredictable. Use it carefully.
sopel.logger¶
-
class
sopel.logger.
ChannelOutputFormatter
(fmt='[%(filename)s] %(message)s', datefmt=None)¶ Output formatter for log messages destined for an IRC channel.
- Parameters
fmt (format string) – log line format
datefmt (format string) – date format
Implementation of a
logging.Formatter
.-
formatException
(exc_info)¶ Format the exception info as a string for output.
- Parameters
exc_info (tuple) – standard exception information returned by
exc_info()
-
class
sopel.logger.
IrcLoggingHandler
(bot, level)¶ Logging handler for output to an IRC channel.
- Parameters
bot (
sopel.bot.Sopel
) – a Sopel instancelevel (logging level) – minimum level of log messages to report through this handler
Implementation of a
logging.Handler
.-
emit
(record)¶ Emit a log
record
to the IRC channel.- Parameters
record (
logging.LogRecord
) – the log record to output
-
sopel.logger.
get_logger
(name=None)¶ Return a logger for a module, if the name is given.
Deprecated since version 7.0: Sopel’s own code should use
logging.getLogger(__name__)
instead, and external plugins should usesopel.tools.get_logger()
.This will emit a deprecation warning in Sopel 8.0, and it will be removed in Sopel 9.0.
-
sopel.logger.
setup_logging
(settings)¶ Set up logging based on the bot’s configuration
settings
.- Parameters
settings (
sopel.config.Config
) – configuration settings object