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, but is still in use in many modules. It’s highly recommended that you switch to requests instead.

sopel.tools

Useful miscellaneous tools and shortcuts for Sopel modules

Availability: 3+

class sopel.tools.Ddict(default=None)

Class for multi-dimensional dict.

A simple helper class to ease the creation of multi-dimensional dicts.

class sopel.tools.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()

Returns True if the Identifier is a nickname (as opposed to channel)

lower()

Return the identifier converted to lower-case per RFC 2812.

class sopel.tools.OutputRedirect(logpath, stderr=False, quiet=False)

Redirect te output to the terminal and a log file.

A simplified object used to write to both the terminal and a log file.

write(string)

Write the given string to the logfile and terminal.

class sopel.tools.SopelMemory(*args)

A simple thread-safe dict implementation.

Availability: 4.0; available as ``Sopel.SopelMemory`` in 3.1.0 - 3.2.0

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 on __setitem__ and contains.

contains(key)

Backwards compatability with 3.x, use in operator instead.

class sopel.tools.SopelMemoryWithDefault(*args)

Same as SopelMemory, but subclasses from collections.defaultdict.

contains(key)

Backwards compatability with 3.x, use in operator instead.

sopel.tools.check_pid(pid)

Check if a process is running with the given PID.

Availability: Only on POSIX systems

Return True if there is a process running with the given PID.

sopel.tools.get_command_regexp(prefix, command)

Return a compiled regexp object that implements the command.

sopel.tools.get_hostmask_regex(mask)

Return a compiled re.RegexObject for an IRC hostmask

sopel.tools.get_input(prompt)

Get decoded input from the terminal (equivalent to python 3’s input).

sopel.tools.get_raising_file_and_line(tb=None)

Return the file and line number of the statement that raised the tb.

Returns: (filename, lineno) tuple

sopel.tools.stderr(string)

Print the given string to stderr.

This is equivalent to print >> sys.stderr, string

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.

time, if given, should be a naive datetime.datetime object and will be treated as being in the UTC timezone. If it is not given, the current time will be used. If zone is given and pytz is available, zone must be present in the IANA Time Zone Database; get_timezone can be helpful for this. If zone is not given or pytz is not available, UTC will be assumed.

The format for the string is chosen in the following order:

  1. The format for the nick nick in db, if one is set and valid.
  2. The format for the channel channel in db, if one is set and valid.
  3. The default format in config, if one is set and valid.
  4. ISO-8601

If db is not given or is not set up, steps 1 and 2 are skipped. If config is not given, step 3 will be skipped.

sopel.tools.time.get_timezone(db=None, config=None, zone=None, nick=None, channel=None)

Find, and return, the approriate timezone

Time zone is pulled in the following priority: 1. zone, if it is valid 2. The timezone for the channel or nick zone in db if one is set and valid. 3. The timezone for the nick nick in db, if one is set and valid. 4. The timezone for the channel channel in db, if one is set and valid. 5. 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. If config is not given, step 4 will be skipped. If no step yeilds a valid timezone, None is returned.

Valid timezones are those present in the IANA Time Zone Database. Prior to checking timezones, two translations are made to make the zone names more human-friendly. First, the string is split on ‘, ‘, the pieces reversed, and then joined with ‘/’. Next, remaining spaces are replaced with ‘_’. Finally, strings longer than 4 characters are made title-case, and those 4 characters and shorter are made upper-case. This means “new york, america” becomes “America/New_York”, and “utc” becomes “UTC”.

This function relies on pytz being available. If it is not available, None will always be returned.

sopel.tools.time.validate_format(tformat)

Returns the format, if valid, else None

sopel.tools.time.validate_timezone(zone)

Return an IETF timezone from the given IETF zone or common abbreviation.

If the length of the zone is 4 or less, it will be upper-cased before being looked up; otherwise it will be title-cased. This is the expected case-insensitivity behavior in the majority of cases. For example, 'edt' and 'america/new_york' will both return 'America/New_York'.

If the zone is not valid, ValueError will be raised. If pytz is not available, and the given zone is anything other than 'UTC', 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 instance>

Evaluates a Python equation expression and returns the result.

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.

name = None

The name of the channel.

privileges = None

The permissions of the users in the channel.

This maps username Identifier``s to bitwise integer values. This can be compared to appropriate constants from ``sopel.module.

topic = None

The topic of the channel.

users = None

The users in the channel.

This maps username Identifiers to channel objects.

class sopel.tools.target.User(nick, user, host)

A representation of a user Sopel is aware of.

account = None

The IRC services account of the user.

This relies on IRCv3 account tracking being enabled.

away = None

Whether the user is marked as away.

channels = None

The channels the user is in.

This maps channel name Identifiers to Channel objects.

host = None

The user’s hostname.

hostmask

The user’s full hostmask.

nick = None

The user’s nickname.

user = None

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, @module.event(events.RPL_WELCOME) rather than @module.event(‘001’)

ERR_ALREADYREGISTRED = u'462'
ERR_BADCHANMASK = u'476'
ERR_BADCHANNELKEY = u'475'
ERR_BADMASK = u'415'
ERR_BANLISTFULL = u'478'
ERR_BANNEDFROMCHAN = u'474'
ERR_CANNOTSENDTOCHAN = u'404'
ERR_CANTKILLSERVER = u'483'
ERR_CHANNELISFULL = u'471'
ERR_CHANOPRIVSNEEDED = u'482'
ERR_ERRONEUSNICKNAME = u'432'
ERR_FILEERROR = u'424'
ERR_INVALIDCAPCMD = u'410'
ERR_INVITEONLYCHAN = u'473'
ERR_KEYINVALID = u'767'
ERR_KEYNOPERMISSION = u'769'
ERR_KEYNOTSET = u'768'
ERR_KEYSET = u'467'
ERR_METADATALIMIT = u'764'
ERR_MONLISTFULL = u'734'
ERR_NEEDMOREPARAMS = u'461'
ERR_NICKCOLLISION = u'436'
ERR_NICKLOCKED = u'902'
ERR_NICKNAMEINUSE = u'433'
ERR_NOADMININFO = u'423'
ERR_NOCHANMODES = u'477'
ERR_NOLOGIN = u'444'
ERR_NOMATCHINGKEY = u'766'
ERR_NOMOTD = u'422'
ERR_NONICKNAMEGIVEN = u'431'
ERR_NOOPERHOST = u'491'
ERR_NOORIGIN = u'409'
ERR_NOPERMFORHOST = u'463'
ERR_NOPRIVILEGES = u'481'
ERR_NORECIPIENT = u'411'
ERR_NOSUCHCHANNEL = u'403'
ERR_NOSUCHNICK = u'401'
ERR_NOSUCHSERVER = u'402'
ERR_NOSUCHSERVICE = u'408'
ERR_NOTEXTTOSEND = u'412'
ERR_NOTONCHANNEL = u'442'
ERR_NOTOPLEVEL = u'413'
ERR_NOTREGISTERED = u'451'
ERR_PASSWDMISMATCH = u'464'
ERR_RESTRICTED = u'484'
ERR_SASLABORTED = u'906'
ERR_SASLALREADY = u'907'
ERR_SASLFAIL = u'904'
ERR_SASLTOOLONG = u'905'
ERR_STARTTLS = u'691'
ERR_SUMMONDISABLED = u'445'
ERR_TARGETINVALID = u'765'
ERR_TOOMANYCHANNELS = u'405'
ERR_TOOMANYTARGETS = u'407'
ERR_UMODEUNKNOWNFLAG = u'501'
ERR_UNAVAILRESOURCE = u'437'
ERR_UNIQOPPRIVSNEEDED = u'485'
ERR_UNKNOWNCOMMAND = u'421'
ERR_UNKNOWNMODE = u'472'
ERR_USERNOTINCHANNEL = u'441'
ERR_USERONCHANNEL = u'443'
ERR_USERSDISABLED = u'446'
ERR_USERSDONTMATCH = u'502'
ERR_WASNOSUCHNICK = u'406'
ERR_WILDTOPLEVEL = u'414'
ERR_YOUREBANNEDCREEP = u'465'
ERR_YOUWILLBEBANNED = u'466'
RPL_ADMINEMAIL = u'259'
RPL_ADMINLOC1 = u'257'
RPL_ADMINLOC2 = u'258'
RPL_ADMINME = u'256'
RPL_AWAY = u'301'
RPL_BANLIST = u'367'
RPL_BOUNCE = u'005'
RPL_CHANNELMODEIS = u'324'
RPL_CREATED = u'003'
RPL_ENDOFBANLIST = u'368'
RPL_ENDOFEXCEPTLIST = u'349'
RPL_ENDOFINFO = u'374'
RPL_ENDOFINVITELIST = u'347'
RPL_ENDOFMONLIST = u'733'
RPL_ENDOFMOTD = u'376'
RPL_ENDOFNAMES = u'366'
RPL_ENDOFSTATS = u'219'
RPL_ENDOFUSERS = u'394'
RPL_ENDOFWHO = u'315'
RPL_ENDOFWHOIS = u'318'
RPL_ENDOFWHOWAS = u'369'
RPL_EXCEPTLIST = u'348'
RPL_INFO = u'371'
RPL_INVITELIST = u'346'
RPL_INVITING = u'341'
RPL_ISON = u'303'
RPL_ISUPPORT = u'005'
RPL_KEYVALUE = u'761'
RPL_LIST = u'322'
RPL_LISTEND = u'323'
RPL_LISTSTART = u'321'
RPL_LOGGEDIN = u'900'
RPL_LOGGEDOUT = u'901'
RPL_LUSERCHANNELS = u'254'
RPL_LUSERCLIENT = u'251'
RPL_LUSERME = u'255'
RPL_LUSEROP = u'252'
RPL_LUSERUNKNOWN = u'253'
RPL_METADATAEND = u'762'
RPL_MONLIST = u'732'
RPL_MONOFFLINE = u'731'
RPL_MONONLINE = u'730'
RPL_MOTD = u'372'
RPL_MOTDSTART = u'375'
RPL_MYINFO = u'004'
RPL_NAMREPLY = u'353'
RPL_NONE = u'300'
RPL_NOTOPIC = u'331'
RPL_NOUSERS = u'395'
RPL_NOWAWAY = u'306'
RPL_REHASHING = u'382'
RPL_SASLMECHS = u'908'
RPL_SASLSUCCESS = u'903'
RPL_SERVLIST = u'234'
RPL_SERVLISTEND = u'235'
RPL_STARTTLS = u'670'
RPL_STATSCLINE = u'213'
RPL_STATSCOMMANDS = u'212'
RPL_STATSHLINE = u'244'
RPL_STATSILINE = u'215'
RPL_STATSKLINE = u'216'
RPL_STATSLINKINFO = u'211'
RPL_STATSLLINE = u'241'
RPL_STATSNLINE = u'214'
RPL_STATSOLINE = u'243'
RPL_STATSUPTIME = u'242'
RPL_STATSYLINE = u'218'
RPL_SUMMONING = u'342'
RPL_TIME = u'391'
RPL_TOPIC = u'332'
RPL_TRACECLASS = u'209'
RPL_TRACECONNECTING = u'201'
RPL_TRACEEND = u'262'
RPL_TRACEHANDSHAKE = u'202'
RPL_TRACELOG = u'261'
RPL_TRACENEWTYPE = u'208'
RPL_TRACEOPERATOR = u'204'
RPL_TRACERECONNECT = u'210'
RPL_TRACESERVER = u'206'
RPL_TRACESERVICE = u'207'
RPL_TRACEUNKNOWN = u'203'
RPL_TRACEUSER = u'205'
RPL_TRYAGAIN = u'263'
RPL_UMODEIS = u'221'
RPL_UNAWAY = u'305'
RPL_UNIQOPIS = u'325'
RPL_USERHOST = u'302'
RPL_USERS = u'393'
RPL_USERSSTART = u'392'
RPL_VERSION = u'351'
RPL_WELCOME = u'001'
RPL_WHOISCHANNELS = u'319'
RPL_WHOISIDLE = u'317'
RPL_WHOISKEYVALUE = u'760'
RPL_WHOISOPERATOR = u'313'
RPL_WHOISSERVER = u'312'
RPL_WHOISUSER = u'311'
RPL_WHOREPLY = u'352'
RPL_WHOSPCRPL = u'354'
RPL_WHOWASUSER = u'314'
RPL_YOUREOPER = u'381'
RPL_YOURESERVICE = u'383'
RPL_YOURHOST = u'002'

sopel.formatting

The formatting module includes functions to apply IRC formatting to text.

Availability: 4.5+

sopel.formatting.CONTROL_BOLD = u'\x02'

The control code to start or end bold formatting

sopel.formatting.CONTROL_COLOR = u'\x03'

The control code to start or end color formatting

sopel.formatting.CONTROL_NORMAL = u'\x0f'

The control code to reset formatting

sopel.formatting.CONTROL_UNDERLINE = u'\x1f'

The control code to start or end underlining

sopel.formatting.bold(text)

Return the text, with bold IRC formatting.

sopel.formatting.color(text, fg=None, bg=None)

Return the text, with the given colors applied in IRC formatting.

The color can be a string of the color name, or an integer between 0 and 99. The known color names can be found in the colors class of this module.

class sopel.formatting.colors
BLACK = u'01'
BLUE = u'02'
BROWN = u'05'
CYAN = u'11'
FUCHSIA = u'13'
GRAY = u'14'
GREEN = u'03'
GREY = u'14'
LIGHT_BLUE = u'12'
LIGHT_CYAN = u'11'
LIGHT_GRAY = u'15'
LIGHT_GREEN = u'09'
LIGHT_GREY = u'15'
LIGHT_PURPLE = u'13'
LIME = u'09'
MAROON = u'05'
NAVY = u'02'
OLIVE = u'07'
ORANGE = u'07'
PINK = u'13'
PURPLE = u'06'
RED = u'04'
ROYAL = u'12'
SILVER = u'15'
TEAL = u'10'
WHITE = u'00'
YELLOW = u'08'
sopel.formatting.underline(text)

Return the text, with underline IRC formatting.