Version 8.0.0
Highlights
Detailed coverage of the major changes can be found in the dedicated Sopel 8 upgrade guide.
For users:
- Python 3.8+ is now required
- IRC connections are made with TLS on port 6697 if not configured
- SASL EXTERNAL authentication is now supported
- Plugins in
~/.sopel/modulesare no longer loaded by default- Use the
core.extrasetting to add this directory back if needed
- Use the
- Database options can be configured all at once in new
db_urlsetting (useful for managed cloud hosting such as Heroku) .blockscommand accepts “nick” and “host” types now, and no longer lies about supporting “hostmasks” (further improvements to come)- Sopel no longer supports loading (very!) old Phenny/Jenni plugins
- Several built-in plugins have been converted to external packages, to simplify maintenance and release-management going forward
For developers:
Identifierwas moved tosopel.tools.identifiersand now supports dynamic casemapping; an optionalcasemappingoridentifier_factorykwarg has been added to many object types to help manage this at runtime- You can usually just pass
bot.make_identifieras the factory function and things will Just Work™ - Feel free to use
bot.make_identifier()yourself to get anIdentifierrepresenting any nick or channel name you get, e.g. as input to a command
- You can usually just pass
- The
core.nicksetting value is now returned as astr, not anIdentifier - Capability negotiation is a first-class plugin API feature (see
plugin.capabilityand the related documentation chapter) trigger.senderattribute as passed to plugin callables is nowNonein cases where its value is meaningless (events with no channel/query context)- Numerous deprecated API features were removed:
bot.privileges(usebot.channels)bot.msg()(usebot.say())sopel.websubmodule (usesopel.tools.web)
- Messages from other bots are ignored by default on supported networks, but
plugins can opt back in with the
@plugin.allow_botsdecorator STATUSMSGprefix is removed fromtrigger.senderif present and stored in a separatetrigger.status_prefixattribute- See documentation for
bot.SopelWrapper.default_destination
- See documentation for
bot.connection_registeredis now the way to check whether the bot is connected to IRC, registered with the network, and ready for your plugin to send commands
Plugin changes
- admin:
- Added
.rawcommand to make Sopel send a raw IRC line [#2104]
- Added
- adminchannel:
- bugzilla:
- Extracted to its own package [#2481]
- calc:
- clock:
- Added
unsetcommands for user & channel time zone/format [#2181]
- Added
- coretasks:
- currency:
- dice:
- Refactoring, bugfixes, and improved test coverage [#2532]
- emoticons:
- find:
- help:
- Now updatable independently from its own package, but still installs with Sopel as a dependency [#2332]
- ip:
- Miscellaneous code-style improvements [#2393]
- Extracted to its own package [#2523]
- meetbot:
- Extracted to its own package [#2477]
- pronouns:
- Accept abbreviated pronoun sets [#2070]
- Added
.clearpronounscommand [#2154] - Fetch pronoun list dynamically at startup [#2130]
- Support configurable pronoun backend [#2437, #2438]
- The old backend at
pronoun.iswent down and never came back, so now you can use our replacement or host your own
- The old backend at
- py:
- Extracted to its own package [#2411, #2415]
- reddit:
- Newer
prawlibrary allowed [#2319] - Added configuration setting to turn off inline slash-references [#2418]
- Extracted to its own package [#2444]
- Newer
- reload:
- remind:
- Avoid trying to use IRC connection if it’s not ready [#2351, #2374]
- Extracted to its own package [#2478]
- safety:
- search:
- seen:
- tell:
- Fixed edge cases in cleanup of tellee argument [#2584]
- translate:
- Improved help output [#2453]
- unicode_info:
- url:
- Improved interaction between
.titlecommand and link handlers [#2282] - Removed traceback from debug log when URL fetch fails [#2280]
- Made channel-privilege-based access to
.urlexcludecommand and friends configurable [#2352] - Cleaned up code [#2304, #2307, #2433]
- Added better error handling for DNS lookups [#2428]
- Ignore invalid hostnames [#2472]
- Improved interaction between
- version:
- Support retrieving plugin versions with
.version pluginname[#2133]
- Support retrieving plugin versions with
- wikipedia:
- Commands are now
.wp,.wikipedia; old commands (.w,.wik, &.wiki) were removed [#1966] - Remove deprecated
lang_per_channelsetting [#2142] - Work around excessive whitespace in math formulas [#2286]
- Don’t ping the user who posted a URL that fails to load [#2315]
- Output image description if URL has an image viewer fragment [#2388]
- Handle query strings in article links [#2414]
- Fail gracefully on
Special:namespace links [#2575]
- Commands are now
- xkcd:
Core changes
- Removed support for EOL Python versions (2.7, 3.3, 3.4, 3.5, 3.6, & 3.7), added testing on newer Python versions (up to 3.12), and modernized coding standards [#2062, #2073, #2123, #2124, #2134, #2136, #2138, #2205, #2213, #2227, #2298, #2326, #2327, #2342, #2384, #2464, #2500, #2516]
- Modified default settings:
- IRC backend refactored to use
asyncio[#2256]- Just in time, too: The
asynchatmodule was removed in Python 3.12
- Just in time, too: The
- Improved IRC connection error handling [#2430, #2431]
SopelDBadapted to SQLAlchemy 2.x style [#2243]- Database can be configured all at once with a new
db_urlsetting [#2087] - Replaced
pkg_resourceswithimportlib.metadata[#2261, #2268] - Added support for several new IRC features and IRCv3 specifications:
- Improved SASL handling when auth fails [#2187, #2191]
- Added automatic
CASEMAPPINGhandling based onRPL_ISUPPORT[#2231] - Plugins in
~/.sopel/modulesare no longer loaded by default [#2119] - Removed support for Phenny/Jenni plugin style [#2126]
- Ignore
bot-tagged messages by default [#2089, #2272] - Privilege tracking (MODE event handling) refactored [#2131]
- Maintain ordering of
ISupport.PREFIXproperty [#2200] - Added
__slots__toChannelandUserobjects [#2233] - Improved handling of the bot’s nick getting changed [#2240]
- Improved tracking and enforcement of rate limits [#2297]
- Prevent infinite loop on connection failure [#2306]
- Added
ssl_ciphersandssl_minimum_versionsettings [#2246, #2306] - Added
antiloop_repeat_text,antiloop_silent_after,antiloop_threshold, andantiloop_windowsettings to control command-loop prevention [#2320] - Using
,inListAttributevalues logs a warning [#2252]- Write lists with newlines instead; Sopel 9 will remove splitting on
,
- Write lists with newlines instead; Sopel 9 will remove splitting on
- IRC connections use TLS on port 6697 by default [#2277]
- Potentially a breaking change, but the configuration wizard has long written these settings to the final config file even if they were left at the default values
- Fixed
UHNAMESrace condition caused by joining channels too soon [#2321] - Removed hunting for CA root store [#2278, #2303]
- Sopel will simply use the system TLS library’s default trust store unless
the
ca_certssetting is specified
- Sopel will simply use the system TLS library’s default trust store unless
the
- Improved truncation/splitting of over-length messages in e.g.
bot.say()[#2310, #2450] - Gracefully handle missing
userhost-in-namesdata, e.g. with ZNC [#2312]- See ZNC issue #1224
- Override
get_version()method forEntryPointPlugin[#2313] - Take advantage of
LINELENtoken if advertised in ISUPPORT [#2346] - Unescape ISUPPORT parameter values [#2429]
- Keep track of user realnames via WHO/WHOX [#2383, #2396]
- Raise error on receiving non-UTF-8 data if server advertises
UTF8ONLY[#2365, #2369, #2372] - Make all arguments
safe()when preparing IRC commands [#2368] - Ignore disabling
coretaskshandlers in per-channel settings [#2400] - Add guardrails to channel logging [#2419]
- Default is now always WARNING, regardless of file logging level
- DEBUG level is no longer available for channel logs; it is far too noisy
- Handle
core.modessetting beingNone[#2510] - Handle broken symlinks to plugin files [#2545]
- Fixed auto-saving changes to Sopel’s ignore list with
.blocks[#2550]
API changes
- Importing
sopel.modulenow emits a deprecation warning [#2170] - Removed support for Phenny/Jenni plugin style [#2126]
- Stopped searching
bot.memory['url_callbacks']for link handlers [#2121] - Deprecated
bot.search_url_callbacks()[#2121, #2156, #2581] - Deprecated
db.execute()[#2243] - Cleaned up parts of
sopel.toolsnamespace- Deprecated
tools.web.entity()and itsr_entityconstant, to be removed in Sopel 9.0 [#2205] - Deprecated the
iteritems,iterkeys,itervalues, andraw_input2to3-style shims, to be removed in Sopel 8.1 [#2228] - Moved
Identifierto its own submodule,tools.identifiers[#2231]tools.Identifierremains for now as a compatibility shortcut
- Moved
check_pid()andstderr()functions tocli.utils[#2385] - Deprecated
tools.OutputRedirectclass left over from the days before modern logging, to be removed in Sopel 8.1 [#2385]
- Deprecated
- Moved channel privilege constants into their own
sopel.privilegessubmodule [#2179, #2352, #2540]- The new
sopel.privileges.AccessLeveltype encapsulates all levels in a single object, which can support dynamic features in the future - The original, individual constants in
sopel.pluginare still available for now, mapped to their correspondingAccessLevelvalues
- The new
- Sopel’s API now uses enumerated types where suitable:
bot-tagged messages are ignored by default [#2089]trigger.timeis offset-aware [#2099]tools.timeimprovements & changes:- Added
plugin.allow_botsdecorator [#2244] - Added more rate-limit controls [#2290, #2434]
- New
messagekeyword-only argument toplugin.ratedecorator, an optional string sent via NOTICE when a command is rate-limited - New
plugin.rate_user,plugin.rate_channel, andplugin.rate_globaldecorators provide simpler control over a single rate-limit type, with therateandmessage(optional) as positional parameters - Messages support various placeholders that will be replaced with runtime
data about the triggering user, the rate limit in effect, and the
plugin/command that was limited; see
plugin.ratedecorator documentation for details
- New
- Added
bot.safe_text_length()method [#2136] - Added
RPL_WHOISBOTtotools.eventslist [#2145] - Added
bot.pluginsproperty [#2199] - Added
db.forget_channel()anddb.forget_plugin()methods [#2224] - Renamed
db.delete_nick_group()todb.forget_nick_group()[#2224] - Added CASEMAPPING support to
Identifier[#2231]- Static
Identifier._lower()method now obeys RFC 1459 casing rules Identifierconstructor now takes optionalcasemappingandchantypeskwargs; see documentation for details, or use thebot.make_identifier()helper method to automatically use the bot’s knowledge about the current server’s configuration
- Static
- Added CHANTYPES support to
Identifier[#2236] - Added
bot.make_identifier_memory()helper to easily take advantage of the bot’s CASEMAPPING and CHANTYPES knowledge [#2552] - Changed reading
core.nickfrom the bot’s settings to return astrinstead ofIdentifier[#2231]- Depending on what your plugin does, you might need to use the result of
bot.make_identifier(bot.settings.core.nick)instead of the raw value
- Depending on what your plugin does, you might need to use the result of
- Moved memory classes to
sopel.tools.memories[#2237] - Moved
deprecated()fromsopel.toolstosopel.lifecycle[#2232] db.get_nick_id()no longer creates a new nick ID by default [#2234]- Standardized on
ctcpinstead ofintent[#2253]- The old
module.intent()decorator was deprecated in Sopel 7.1; use theplugin.ctcp()decorator instead - Sopel 8.0 removes
intentfromtrigger.tags; usetrigger.ctcpinstead
- The old
- Updated invite-related event names in
tools.events[#2270] - Fixed checking if
Noneexists in aSopelIdentifierMemory[#2306] - Fixed and tested
SopelIdentifierMemoryinteractions with plainer-vanilla dictionary types [#2525] - Reworked capability negotiation [#2341]
- See Managing Capability Negotiation documentation chapter
- This replaces the
irc.utils.CapReqinterface, which is now deprecated
- Changed
trigger.senderproperty to beNonefor events not associated with a channel or query [#2359] - Fixed
trigger.texterroneously containing command name for events with emptyargs[#2360] - Removed
STATUSMSGprefix fromtrigger.sender[#2370, #2441]- Status prefix is now stored in a new
trigger.status_prefixattribute - The
botpassed to plugin callables will use thestatus_prefixandsenderattributes to build itsdefault_destination, meaning no change to plugins’ most common usages ofbot.say(),bot.reply(), etc.
- Status prefix is now stored in a new
- Fixed
formatting.colorresult when passing0asfgorbg[[#2366][]] config.types.FilenameAttributestrips quotes from its value [#2371]- Made
bot.connection_registeredmore robust [#2375, #2406, #2410] - The bot initializes with an
UninitializedBackendinstead ofNone, to intercept actions that don’t work prior to connecting [#2394]- Prohibited actions raise
RuntimeErrorinstead of falling through to a more esoteric error type or—worse—silently failing
- Prohibited actions raise
- Added
realname&is_botfields toUserobjects [#2383, #2448] - Use of
plugin.require_privilege()orplugin.require_bot_privilege()decorators now impliesrequire_chanmsg()[#2405, #2580] - Fixed an inconsistency between behavior and documentation for
tools.calculation.pow_complexity()[#2543] - Soft-deprecated
SopelWrappertype [#2521]- Long-term, we will phase out this subclass in favor of using
contextvars; see #2460 for the full timeline
- Long-term, we will phase out this subclass in favor of using
- Moved
sopel.pluginstosopel.builtins[#2504]- We don’t technically consider these to be part of the API, but if this isn’t mentioned we just know someone will complain that the move broke some custom plugin code
- Removed previously-deprecated API features [#2128, #2129, #2141, #2144, #2146, #2147, #2148, #2150, #2329]
Housekeeping changes
- Many, many additions & improvements to documentation [#1990, #2169, #2178, #2182, #2226, #2238, #2239, #2257, #2275, #2276, #2323, #2379, #2386, #2409, #2424, #2426, #2442, #2489, #2494, #2495, #2496, #2533, #2539, #2543, #2550, #2558, #2574, #2600, #2606]
- Switched from Travis CI to GitHub Actions and incrementally improved tests [#2075, #2078, #2123, #2188, #2262, #2335, #2342, #2381, #2452, #2453, #2458, #2505, #2519, #2543]
- Improved tooling for contributors, e.g.
Makefiletargets [#2502] - Modernized packaging [#2328]
- Cleanup on aisle
contrib/[#2085, #2520] - Cleanup of deprecated feature usage in core & built-in plugins [#2117, #2464, #2468, #2470]
- Import reorganization [#2179]
- Various code smell/style issues fixed [#2186, #2220, #2231, #2382, #2393, #2514]
- Various logging improvements [#2309, #2354, #2473, #2569]
- Deprecation warnings for the corresponding stable release now begin to emit logs in prerelease versions [#2522]
- Removed legacy CLI run mode [#2118]
- Removed obsolete, nonfunctional CLI argument
--quiet[#2404] - Removed old
sopel.test_tools[#2139, #2177] - Raw logs improved both output and decode failure handling [#2095]
- Started our journey into the wonderful world of type checking [#2185,
#2462, #2471, #2480, #2491, #2535, #2555]
- Many many PRs added or updated type hints in the course of adding/fixing something else, so we won’t also list all of them here