This file is used to auto-generate the "Changelog" section of Sopel's website. When adding new entries, follow the style guide in NEWS.spec.md to avoid causing problems with the site build. Changes between 7.1.9 and 8.0.0 =============================== Highlights ---------- **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/modules` are no longer loaded by default * Use the `core.extra` setting to add this directory back if needed * Database options can be configured all at once in new `db_url` setting (useful for managed cloud hosting such as Heroku) * `.blocks` command 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:** * `Identifier` was moved to `sopel.tools.identifiers` and now supports dynamic casemapping; an optional `casemapping` or `identifier_factory` kwarg has been added to many object types to help manage this at runtime * You can usually just pass `bot.make_identifier` as the factory function and things will Just Work™ * Feel free to use `bot.make_identifier()` yourself to get an `Identifier` representing any nick or channel name you get, e.g. as input to a command * The `core.nick` setting value is now returned as a `str`, not an `Identifier` * Capability negotiation is a first-class plugin API feature (see `plugin.capability` and the [related documentation chapter][cap-mgmt-8]) * `trigger.sender` attribute as passed to plugin callables is now `None` in cases where its value is meaningless (events with no channel/query context) * Numerous deprecated API features were removed: * `bot.privileges` (use `bot.channels`) * `bot.msg()` (use `bot.say()`) * `sopel.web` submodule (use `sopel.tools.web`) * Messages from other bots are ignored by default on supported networks, but plugins can opt back in with the `@plugin.allow_bots` decorator * `STATUSMSG` prefix is removed from `trigger.sender` if present and stored in a separate `trigger.status_prefix` attribute * See documentation for `bot.SopelWrapper.default_destination` * `bot.connection_registered` is 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 `.raw` command to make Sopel send a raw IRC line [[#2104][]] * adminchannel: * Refactored hostmask handling & added code comments/tests [[#2222][]] * Improved result of trying to kick the bot with `.kick` [[#2240][]] * Unified topic-mask management under `.tmask` with subcommands [[#2601][]] * bugzilla: * Extracted to [its own package][sopel-bugzilla] [[#2481][]] * calc: * Improved error handling [[#2507][]] * Improved help output & test coverage [[#2530][]] * clock: * Added `unset` commands for user & channel time zone/format [[#2181][]] * coretasks: * Replaced "hostmask" type with "host" in `.blocks` command [[#2344][]] * Real "hostmask" support is planned; see [#1355][] * Improved help output for `.blocks` [[#2345][]] * currency: * Added `.currencies` command to list known currency symbols [[#2439][]] * `fiat_provider` setting takes precedence over the existence of a `fixer_io_key` value [[#2330][]] * Switched from `exchangerate.host` to `open.er-api.com` [[#2512][]] * dice: * Refactoring, bugfixes, and improved test coverage [[#2532][]] * emoticons: * Added `.tback` alias for `.unflip` command [[#2287][]] * Made `.unflip` table more closely match the `.tflip` one [[#2287][]] * find: * Fixed use of flags when `|` is used as input separator [[#2447][]] * Code cleanup [[#2267][]] * help: * Now updatable independently from [its own package][sopel-help], but still installs with Sopel as a dependency [[#2332][]] * ip: * Miscellaneous code-style improvements [[#2393][]] * Extracted to [its own package][sopel-iplookup] [[#2523][]] * meetbot: * Extracted to [its own package][sopel-meetbot] [[#2477][]] * pronouns: * Accept abbreviated pronoun sets [[#2070][]] * Added `.clearpronouns` command [[#2154][]] * Fetch pronoun list dynamically at startup [[#2130][]] * Support configurable pronoun backend [[#2437][], [#2438][]] * The old backend at `pronoun.is` went down and never came back, so now you can use [our replacement][pronoun-ours] or [host your own][pronoun-base] * py: * Extracted to [its own package][sopel-py] [[#2411][], [#2415][]] * reddit: * Newer `praw` library allowed [[#2319][]] * Added configuration setting to turn off inline slash-references [[#2418][]] * Extracted to [its own package][sopel-reddit] [[#2444][]] * reload: * Remove unsupported `.update` command [[#2416][]] * Improve plugin help strings [[#2417][]] * remind: * Avoid trying to use IRC connection if it's not ready [[#2351][], [#2374][]] * Extracted to [its own package][sopel-remind] [[#2478][]] * safety: * Comprehensive rework improving caching, output, etc. [[#2279][]] * Ignore invalid hostnames [[#2472][]] * search: * Fix `.suggest` when there is only one result [[#2513][]] * Code style and dependency updates [[#2260][], [#2334][], [#2420][]] * seen: * Adapted to aware `trigger.time` [[#2265][]] * Prevent error spam if database is temporarily inaccessible [[#2338][]] * tell: * Fixed edge cases in cleanup of tellee argument [[#2584][]] * translate: * Improved help output [[#2453][]] * unicode_info: * Uses `unicodedata2` if available [[#2349][], [#2361][]] * url: * Improved interaction between `.title` command and link handlers [[#2282][]] * Removed traceback from debug log when URL fetch fails [[#2280][]] * Made channel-privilege-based access to `.urlexclude` command and friends configurable [[#2352][]] * Cleaned up code [[#2304][], [#2307][], [#2433][]] * Added better error handling for DNS lookups [[#2428][]] * Ignore invalid hostnames [[#2472][]] * version: * Support retrieving plugin versions with `.version pluginname` [[#2133][]] * wikipedia: * Commands are now `.wp`, `.wikipedia`; old commands (`.w`, `.wik`, & `.wiki`) were removed [[#1966][]] * Remove deprecated `lang_per_channel` setting [[#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][]] * xkcd: * Switched keyword-search backend [[#2376][], [#2377][]] 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: * Removed default `B` mode from `core.modes` [[#2448][]] * Added space before timezone in `default_time_format` [[#2531][]] * IRC backend refactored to use `asyncio` [[#2256][]] * Just in time, too: The `asynchat` module was removed in Python 3.12 * Improved IRC connection error handling [[#2430][], [#2431][]] * `SopelDB` adapted to SQLAlchemy 2.x style [[#2243][]] * Database can be configured all at once with a new `db_url` setting [[#2087][]] * Replaced `pkg_resources` with `importlib.metadata` [[#2261][], [#2268][]] * Added support for several new IRC features and IRCv3 specifications: * SASL EXTERNAL client certificate authentication [[#2100][], [#2561][]] * Sopel uses [the Bot Mode specification][bot-mode-spec] to mark itself as a bot and track other users that are flagged as bots [[#2088][], [#2448][]] * `userhost-in-names` capability and the legacy `UHNAMES` feature [[#2102][]] * `chghost` capability [[#2116][]] * Improved SASL handling when auth fails [[#2187][], [#2191][]] * Added automatic `CASEMAPPING` handling based on `RPL_ISUPPORT` [[#2231][]] * Plugins in `~/.sopel/modules` are 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.PREFIX` property [[#2200][]] * Added `__slots__` to `Channel` and `User` objects [[#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_ciphers` and `ssl_minimum_version` settings [[#2246][], [#2306][]] * Added `antiloop_repeat_text`, `antiloop_silent_after`, `antiloop_threshold`, and `antiloop_window` settings to control command-loop prevention [[#2320][]] * Using `,` in `ListAttribute` values logs a warning [[#2252][]] * 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 `UHNAMES` race 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_certs` setting is specified * Improved truncation/splitting of over-length messages in e.g. `bot.say()` [[#2310][], [#2450][]] * Gracefully handle missing `userhost-in-names` data, e.g. with ZNC [[#2312][]] * See [ZNC issue #1224][znc/znc#1224] * Override `get_version()` method for `EntryPointPlugin` [[#2313][]] * Take advantage of `LINELEN` token 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 `coretasks` handlers 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.modes` setting being `None` [[#2510][]] * Handle broken symlinks to plugin files [[#2545][]] * Fixed auto-saving changes to Sopel's ignore list with `.blocks` [[#2550][]] API changes ----------- * Importing `sopel.module` now 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.tools` namespace * Deprecated `tools.web.entity()` and its `r_entity` constant, to be removed in Sopel 9.0 [[#2205][]] * Deprecated the `iteritems`, `iterkeys`, `itervalues`, and `raw_input` 2to3-style shims, to be removed in Sopel 8.1 [[#2228][]] * Moved `Identifier` to its own submodule, `tools.identifiers` [[#2231][]] * `tools.Identifier` remains for now as a compatibility shortcut * Moved `check_pid()` and `stderr()` functions to `cli.utils` [[#2385][]] * Deprecated `tools.OutputRedirect` class left over from the days before modern logging, to be removed in Sopel 8.1 [[#2385][]] * Moved channel privilege constants into their own `sopel.privileges` submodule [[#2179][], [#2352][], [#2540][]] * The new `sopel.privileges.AccessLevel` type encapsulates all levels in a single object, which can support dynamic features in the future * The original, individual constants in `sopel.plugin` are still available for now, mapped to their corresponding `AccessLevel` values * Sopel's API now uses enumerated types where suitable: * `formatting.colors` [[#2122][]] * `privileges.AccessLevel` [[#2540][]] * `tools.events` [[#2127][]] * `bot`-tagged messages are ignored by default [[#2089][]] * `trigger.time` is offset-aware [[#2099][]] * `tools.time` improvements & changes: * `format_time()` accepts offset-aware `datetime` values [[#2132][]] * `seconds_to_split()` returns a `Duration` named tuple [[#2446][]] * `validate_timezone()` now raises `ValueError` for `None` [[#2446][]] * Added `plugin.allow_bots` decorator [[#2244][]] * Added more rate-limit controls [[#2290][], [#2434][]] * New `message` keyword-only argument to `plugin.rate` decorator, an optional string sent via NOTICE when a command is rate-limited * New `plugin.rate_user`, `plugin.rate_channel`, and `plugin.rate_global` decorators provide simpler control over a single rate-limit type, with the `rate` and `message` (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.rate`][rate-decorator] decorator documentation for details * Added `bot.safe_text_length()` method [[#2136][]] * Added `RPL_WHOISBOT` to `tools.events` list [[#2145][]] * Added `bot.plugins` property [[#2199][]] * Added `db.forget_channel()` and `db.forget_plugin()` methods [[#2224][]] * Renamed `db.delete_nick_group()` to `db.forget_nick_group()` [[#2224][]] * Added CASEMAPPING support to `Identifier` [[#2231][]] * Static `Identifier._lower()` method now obeys RFC 1459 casing rules * `Identifier` constructor now takes optional `casemapping` and `chantypes` kwargs; see documentation for details, or use the `bot.make_identifier()` helper method to automatically use the bot's knowledge about the current server's configuration * 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.nick` from the bot's settings to return a `str` instead of `Identifier` [[#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 * Moved memory classes to `sopel.tools.memories` [[#2237][]] * Moved `deprecated()` from `sopel.tools` to `sopel.lifecycle` [[#2232][]] * `db.get_nick_id()` no longer creates a new nick ID by default [[#2234][]] * Standardized on `ctcp` instead of `intent` [[#2253][]] * The old `module.intent()` decorator was deprecated in Sopel 7.1; use the `plugin.ctcp()` decorator instead * Sopel 8.0 removes `intent` from `trigger.tags`; use `trigger.ctcp` instead * Updated invite-related event names in `tools.events` [[#2270][]] * Fixed checking if `None` exists in a `SopelIdentifierMemory` [[#2306][]] * Fixed and tested `SopelIdentifierMemory` interactions with plainer-vanilla dictionary types [[#2525][]] * Reworked capability negotiation [[#2341][]] * See [Managing Capability Negotiation][cap-mgmt-8] documentation chapter * This replaces the `irc.utils.CapReq` interface, which is now deprecated * Changed `trigger.sender` property to be `None` for events not associated with a channel or query [[#2359][]] * Fixed `trigger.text` erroneously containing command name for events with empty `args` [[#2360][]] * Removed `STATUSMSG` prefix from `trigger.sender` [[#2370][], [#2441][]] * Status prefix is now stored in a new `trigger.status_prefix` attribute * The `bot` passed to plugin callables will use the `status_prefix` and `sender` attributes to build its `default_destination`, meaning no change to plugins' most common usages of `bot.say()`, `bot.reply()`, etc. * Fixed `formatting.color` result when passing `0` as `fg` or `bg` [[#2366][]] * `config.types.FilenameAttribute` strips quotes from its value [[#2371][]] * Made `bot.connection_registered` more robust [[#2375][], [#2406][], [#2410][]] * The bot initializes with an `UninitializedBackend` instead of `None`, to intercept actions that don't work prior to connecting [[#2394][]] * Prohibited actions raise `RuntimeError` instead of falling through to a more esoteric error type or—worse—silently failing * Added `realname` & `is_bot` fields to `User` objects [[#2383][], [#2448][]] * Use of `plugin.require_privilege()` or `plugin.require_bot_privilege()` decorators now implies `require_chanmsg()` [[#2405][], [#2580][]] * Fixed an inconsistency between behavior and documentation for `tools.calculation.pow_complexity()` [[#2543][]] * Soft-deprecated `SopelWrapper` type [[#2521]] * Long-term, we will phase out this subclass in favor of using `contextvars`; see [#2460][] for the full timeline * Moved `sopel.plugins` to `sopel.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][]] * 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. `Makefile` targets [[#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 [bot-mode-spec]: https://ircv3.net/specs/extensions/bot-mode [cap-mgmt-8]: https://sopel.chat/docs/plugin/advanced#managing-capability-negotiation [pronoun-base]: https://github.com/lucasew/svelte-pronounisland [pronoun-ours]: https://github.com/sopel-irc/pronoun-service [rate-decorator]: https://sopel.chat/docs/plugin/decorators#sopel.plugin.rate [sopel-bugzilla]: https://pypi.org/project/sopel-bugzilla/ [sopel-help]: https://pypi.org/project/sopel-help/ [sopel-iplookup]: https://pypi.org/project/sopel-iplookup/ [sopel-meetbot]: https://pypi.org/project/sopel-meetbot/ [sopel-py]: https://pypi.org/project/sopel-py/ [sopel-reddit]: https://pypi.org/project/sopel-reddit/ [sopel-remind]: https://pypi.org/project/sopel-remind/ [znc/znc#1224]: https://github.com/znc/znc/issues/1224 [#1355]: https://github.com/sopel-irc/sopel/issues/1355 [#1966]: https://github.com/sopel-irc/sopel/pull/1966 [#1990]: https://github.com/sopel-irc/sopel/pull/1990 [#2062]: https://github.com/sopel-irc/sopel/pull/2062 [#2070]: https://github.com/sopel-irc/sopel/pull/2070 [#2073]: https://github.com/sopel-irc/sopel/pull/2073 [#2075]: https://github.com/sopel-irc/sopel/pull/2075 [#2078]: https://github.com/sopel-irc/sopel/pull/2078 [#2085]: https://github.com/sopel-irc/sopel/pull/2085 [#2087]: https://github.com/sopel-irc/sopel/pull/2087 [#2088]: https://github.com/sopel-irc/sopel/pull/2088 [#2089]: https://github.com/sopel-irc/sopel/pull/2089 [#2095]: https://github.com/sopel-irc/sopel/pull/2095 [#2099]: https://github.com/sopel-irc/sopel/pull/2099 [#2100]: https://github.com/sopel-irc/sopel/pull/2100 [#2102]: https://github.com/sopel-irc/sopel/pull/2102 [#2104]: https://github.com/sopel-irc/sopel/pull/2104 [#2116]: https://github.com/sopel-irc/sopel/pull/2116 [#2117]: https://github.com/sopel-irc/sopel/pull/2117 [#2118]: https://github.com/sopel-irc/sopel/pull/2118 [#2119]: https://github.com/sopel-irc/sopel/pull/2119 [#2121]: https://github.com/sopel-irc/sopel/pull/2121 [#2122]: https://github.com/sopel-irc/sopel/pull/2122 [#2123]: https://github.com/sopel-irc/sopel/pull/2123 [#2124]: https://github.com/sopel-irc/sopel/pull/2124 [#2126]: https://github.com/sopel-irc/sopel/pull/2126 [#2127]: https://github.com/sopel-irc/sopel/pull/2127 [#2128]: https://github.com/sopel-irc/sopel/pull/2128 [#2129]: https://github.com/sopel-irc/sopel/pull/2129 [#2130]: https://github.com/sopel-irc/sopel/pull/2130 [#2131]: https://github.com/sopel-irc/sopel/pull/2131 [#2132]: https://github.com/sopel-irc/sopel/pull/2132 [#2133]: https://github.com/sopel-irc/sopel/pull/2133 [#2134]: https://github.com/sopel-irc/sopel/pull/2134 [#2136]: https://github.com/sopel-irc/sopel/pull/2136 [#2138]: https://github.com/sopel-irc/sopel/pull/2138 [#2139]: https://github.com/sopel-irc/sopel/pull/2139 [#2141]: https://github.com/sopel-irc/sopel/pull/2141 [#2142]: https://github.com/sopel-irc/sopel/pull/2142 [#2144]: https://github.com/sopel-irc/sopel/pull/2144 [#2145]: https://github.com/sopel-irc/sopel/pull/2145 [#2146]: https://github.com/sopel-irc/sopel/pull/2146 [#2147]: https://github.com/sopel-irc/sopel/pull/2147 [#2148]: https://github.com/sopel-irc/sopel/pull/2148 [#2150]: https://github.com/sopel-irc/sopel/pull/2150 [#2154]: https://github.com/sopel-irc/sopel/pull/2154 [#2156]: https://github.com/sopel-irc/sopel/pull/2156 [#2169]: https://github.com/sopel-irc/sopel/pull/2169 [#2170]: https://github.com/sopel-irc/sopel/pull/2170 [#2177]: https://github.com/sopel-irc/sopel/pull/2177 [#2178]: https://github.com/sopel-irc/sopel/pull/2178 [#2179]: https://github.com/sopel-irc/sopel/pull/2179 [#2181]: https://github.com/sopel-irc/sopel/pull/2181 [#2182]: https://github.com/sopel-irc/sopel/pull/2182 [#2185]: https://github.com/sopel-irc/sopel/pull/2185 [#2186]: https://github.com/sopel-irc/sopel/pull/2186 [#2187]: https://github.com/sopel-irc/sopel/pull/2187 [#2188]: https://github.com/sopel-irc/sopel/pull/2188 [#2191]: https://github.com/sopel-irc/sopel/pull/2191 [#2199]: https://github.com/sopel-irc/sopel/pull/2199 [#2200]: https://github.com/sopel-irc/sopel/pull/2200 [#2205]: https://github.com/sopel-irc/sopel/pull/2205 [#2213]: https://github.com/sopel-irc/sopel/pull/2213 [#2220]: https://github.com/sopel-irc/sopel/pull/2220 [#2222]: https://github.com/sopel-irc/sopel/pull/2222 [#2224]: https://github.com/sopel-irc/sopel/pull/2224 [#2226]: https://github.com/sopel-irc/sopel/pull/2226 [#2227]: https://github.com/sopel-irc/sopel/pull/2227 [#2228]: https://github.com/sopel-irc/sopel/pull/2228 [#2231]: https://github.com/sopel-irc/sopel/pull/2231 [#2232]: https://github.com/sopel-irc/sopel/pull/2232 [#2233]: https://github.com/sopel-irc/sopel/pull/2233 [#2234]: https://github.com/sopel-irc/sopel/pull/2234 [#2236]: https://github.com/sopel-irc/sopel/pull/2236 [#2237]: https://github.com/sopel-irc/sopel/pull/2237 [#2238]: https://github.com/sopel-irc/sopel/pull/2238 [#2239]: https://github.com/sopel-irc/sopel/pull/2239 [#2240]: https://github.com/sopel-irc/sopel/pull/2240 [#2243]: https://github.com/sopel-irc/sopel/pull/2243 [#2244]: https://github.com/sopel-irc/sopel/pull/2244 [#2246]: https://github.com/sopel-irc/sopel/pull/2246 [#2252]: https://github.com/sopel-irc/sopel/pull/2252 [#2253]: https://github.com/sopel-irc/sopel/pull/2253 [#2256]: https://github.com/sopel-irc/sopel/pull/2256 [#2257]: https://github.com/sopel-irc/sopel/pull/2257 [#2260]: https://github.com/sopel-irc/sopel/pull/2260 [#2261]: https://github.com/sopel-irc/sopel/pull/2261 [#2262]: https://github.com/sopel-irc/sopel/pull/2262 [#2265]: https://github.com/sopel-irc/sopel/pull/2265 [#2267]: https://github.com/sopel-irc/sopel/pull/2267 [#2268]: https://github.com/sopel-irc/sopel/pull/2268 [#2270]: https://github.com/sopel-irc/sopel/pull/2270 [#2272]: https://github.com/sopel-irc/sopel/pull/2272 [#2275]: https://github.com/sopel-irc/sopel/pull/2275 [#2276]: https://github.com/sopel-irc/sopel/pull/2276 [#2277]: https://github.com/sopel-irc/sopel/pull/2277 [#2278]: https://github.com/sopel-irc/sopel/pull/2278 [#2279]: https://github.com/sopel-irc/sopel/pull/2279 [#2280]: https://github.com/sopel-irc/sopel/pull/2280 [#2282]: https://github.com/sopel-irc/sopel/pull/2282 [#2286]: https://github.com/sopel-irc/sopel/pull/2286 [#2287]: https://github.com/sopel-irc/sopel/pull/2287 [#2290]: https://github.com/sopel-irc/sopel/pull/2290 [#2297]: https://github.com/sopel-irc/sopel/pull/2297 [#2298]: https://github.com/sopel-irc/sopel/pull/2298 [#2303]: https://github.com/sopel-irc/sopel/pull/2303 [#2304]: https://github.com/sopel-irc/sopel/pull/2304 [#2306]: https://github.com/sopel-irc/sopel/pull/2306 [#2307]: https://github.com/sopel-irc/sopel/pull/2307 [#2309]: https://github.com/sopel-irc/sopel/pull/2309 [#2310]: https://github.com/sopel-irc/sopel/pull/2310 [#2312]: https://github.com/sopel-irc/sopel/pull/2312 [#2313]: https://github.com/sopel-irc/sopel/pull/2313 [#2315]: https://github.com/sopel-irc/sopel/pull/2315 [#2319]: https://github.com/sopel-irc/sopel/pull/2319 [#2320]: https://github.com/sopel-irc/sopel/pull/2320 [#2321]: https://github.com/sopel-irc/sopel/pull/2321 [#2323]: https://github.com/sopel-irc/sopel/pull/2323 [#2326]: https://github.com/sopel-irc/sopel/pull/2326 [#2327]: https://github.com/sopel-irc/sopel/pull/2327 [#2328]: https://github.com/sopel-irc/sopel/pull/2328 [#2329]: https://github.com/sopel-irc/sopel/pull/2329 [#2330]: https://github.com/sopel-irc/sopel/pull/2330 [#2332]: https://github.com/sopel-irc/sopel/pull/2332 [#2334]: https://github.com/sopel-irc/sopel/pull/2334 [#2335]: https://github.com/sopel-irc/sopel/pull/2335 [#2338]: https://github.com/sopel-irc/sopel/pull/2338 [#2341]: https://github.com/sopel-irc/sopel/pull/2341 [#2342]: https://github.com/sopel-irc/sopel/pull/2342 [#2344]: https://github.com/sopel-irc/sopel/pull/2344 [#2345]: https://github.com/sopel-irc/sopel/pull/2345 [#2346]: https://github.com/sopel-irc/sopel/pull/2346 [#2349]: https://github.com/sopel-irc/sopel/pull/2349 [#2351]: https://github.com/sopel-irc/sopel/pull/2351 [#2352]: https://github.com/sopel-irc/sopel/pull/2352 [#2354]: https://github.com/sopel-irc/sopel/pull/2354 [#2359]: https://github.com/sopel-irc/sopel/pull/2359 [#2360]: https://github.com/sopel-irc/sopel/pull/2360 [#2361]: https://github.com/sopel-irc/sopel/pull/2361 [#2365]: https://github.com/sopel-irc/sopel/pull/2365 [#2368]: https://github.com/sopel-irc/sopel/pull/2368 [#2369]: https://github.com/sopel-irc/sopel/pull/2369 [#2370]: https://github.com/sopel-irc/sopel/pull/2370 [#2371]: https://github.com/sopel-irc/sopel/pull/2371 [#2372]: https://github.com/sopel-irc/sopel/pull/2372 [#2374]: https://github.com/sopel-irc/sopel/pull/2374 [#2375]: https://github.com/sopel-irc/sopel/pull/2375 [#2376]: https://github.com/sopel-irc/sopel/pull/2376 [#2377]: https://github.com/sopel-irc/sopel/pull/2377 [#2379]: https://github.com/sopel-irc/sopel/pull/2379 [#2381]: https://github.com/sopel-irc/sopel/pull/2381 [#2382]: https://github.com/sopel-irc/sopel/pull/2382 [#2383]: https://github.com/sopel-irc/sopel/pull/2383 [#2384]: https://github.com/sopel-irc/sopel/pull/2384 [#2385]: https://github.com/sopel-irc/sopel/pull/2385 [#2386]: https://github.com/sopel-irc/sopel/pull/2386 [#2388]: https://github.com/sopel-irc/sopel/pull/2388 [#2393]: https://github.com/sopel-irc/sopel/pull/2393 [#2394]: https://github.com/sopel-irc/sopel/pull/2394 [#2396]: https://github.com/sopel-irc/sopel/pull/2396 [#2400]: https://github.com/sopel-irc/sopel/pull/2400 [#2404]: https://github.com/sopel-irc/sopel/pull/2404 [#2405]: https://github.com/sopel-irc/sopel/pull/2405 [#2406]: https://github.com/sopel-irc/sopel/pull/2406 [#2409]: https://github.com/sopel-irc/sopel/pull/2409 [#2410]: https://github.com/sopel-irc/sopel/pull/2410 [#2411]: https://github.com/sopel-irc/sopel/pull/2411 [#2414]: https://github.com/sopel-irc/sopel/pull/2414 [#2415]: https://github.com/sopel-irc/sopel/pull/2415 [#2416]: https://github.com/sopel-irc/sopel/pull/2416 [#2417]: https://github.com/sopel-irc/sopel/pull/2417 [#2418]: https://github.com/sopel-irc/sopel/pull/2418 [#2419]: https://github.com/sopel-irc/sopel/pull/2419 [#2420]: https://github.com/sopel-irc/sopel/pull/2420 [#2424]: https://github.com/sopel-irc/sopel/pull/2424 [#2426]: https://github.com/sopel-irc/sopel/pull/2426 [#2428]: https://github.com/sopel-irc/sopel/pull/2428 [#2429]: https://github.com/sopel-irc/sopel/pull/2429 [#2430]: https://github.com/sopel-irc/sopel/pull/2430 [#2431]: https://github.com/sopel-irc/sopel/pull/2431 [#2433]: https://github.com/sopel-irc/sopel/pull/2433 [#2434]: https://github.com/sopel-irc/sopel/pull/2434 [#2437]: https://github.com/sopel-irc/sopel/pull/2437 [#2438]: https://github.com/sopel-irc/sopel/pull/2438 [#2439]: https://github.com/sopel-irc/sopel/pull/2439 [#2441]: https://github.com/sopel-irc/sopel/pull/2441 [#2442]: https://github.com/sopel-irc/sopel/pull/2442 [#2444]: https://github.com/sopel-irc/sopel/pull/2444 [#2446]: https://github.com/sopel-irc/sopel/pull/2446 [#2447]: https://github.com/sopel-irc/sopel/pull/2447 [#2448]: https://github.com/sopel-irc/sopel/pull/2448 [#2450]: https://github.com/sopel-irc/sopel/pull/2450 [#2452]: https://github.com/sopel-irc/sopel/pull/2452 [#2453]: https://github.com/sopel-irc/sopel/pull/2453 [#2455]: https://github.com/sopel-irc/sopel/pull/2455 [#2458]: https://github.com/sopel-irc/sopel/pull/2458 [#2460]: https://github.com/sopel-irc/sopel/issues/2460 [#2462]: https://github.com/sopel-irc/sopel/pull/2462 [#2464]: https://github.com/sopel-irc/sopel/pull/2464 [#2468]: https://github.com/sopel-irc/sopel/pull/2468 [#2470]: https://github.com/sopel-irc/sopel/pull/2470 [#2471]: https://github.com/sopel-irc/sopel/pull/2471 [#2472]: https://github.com/sopel-irc/sopel/pull/2472 [#2473]: https://github.com/sopel-irc/sopel/pull/2473 [#2477]: https://github.com/sopel-irc/sopel/pull/2477 [#2478]: https://github.com/sopel-irc/sopel/pull/2478 [#2480]: https://github.com/sopel-irc/sopel/pull/2480 [#2481]: https://github.com/sopel-irc/sopel/pull/2481 [#2489]: https://github.com/sopel-irc/sopel/pull/2489 [#2491]: https://github.com/sopel-irc/sopel/pull/2491 [#2494]: https://github.com/sopel-irc/sopel/pull/2494 [#2495]: https://github.com/sopel-irc/sopel/pull/2495 [#2496]: https://github.com/sopel-irc/sopel/pull/2496 [#2500]: https://github.com/sopel-irc/sopel/pull/2500 [#2502]: https://github.com/sopel-irc/sopel/pull/2502 [#2504]: https://github.com/sopel-irc/sopel/pull/2504 [#2505]: https://github.com/sopel-irc/sopel/pull/2505 [#2507]: https://github.com/sopel-irc/sopel/pull/2507 [#2510]: https://github.com/sopel-irc/sopel/pull/2510 [#2512]: https://github.com/sopel-irc/sopel/pull/2512 [#2513]: https://github.com/sopel-irc/sopel/pull/2513 [#2514]: https://github.com/sopel-irc/sopel/pull/2514 [#2516]: https://github.com/sopel-irc/sopel/pull/2516 [#2519]: https://github.com/sopel-irc/sopel/pull/2519 [#2520]: https://github.com/sopel-irc/sopel/pull/2520 [#2521]: https://github.com/sopel-irc/sopel/pull/2521 [#2522]: https://github.com/sopel-irc/sopel/pull/2522 [#2523]: https://github.com/sopel-irc/sopel/pull/2523 [#2525]: https://github.com/sopel-irc/sopel/pull/2525 [#2530]: https://github.com/sopel-irc/sopel/pull/2530 [#2531]: https://github.com/sopel-irc/sopel/pull/2531 [#2532]: https://github.com/sopel-irc/sopel/pull/2532 [#2533]: https://github.com/sopel-irc/sopel/pull/2533 [#2535]: https://github.com/sopel-irc/sopel/pull/2535 [#2539]: https://github.com/sopel-irc/sopel/pull/2539 [#2540]: https://github.com/sopel-irc/sopel/pull/2540 [#2543]: https://github.com/sopel-irc/sopel/pull/2543 [#2545]: https://github.com/sopel-irc/sopel/pull/2545 [#2550]: https://github.com/sopel-irc/sopel/pull/2550 [#2552]: https://github.com/sopel-irc/sopel/pull/2552 [#2555]: https://github.com/sopel-irc/sopel/pull/2555 [#2558]: https://github.com/sopel-irc/sopel/pull/2558 [#2561]: https://github.com/sopel-irc/sopel/pull/2561 [#2569]: https://github.com/sopel-irc/sopel/pull/2569 [#2574]: https://github.com/sopel-irc/sopel/pull/2574 [#2575]: https://github.com/sopel-irc/sopel/pull/2575 [#2580]: https://github.com/sopel-irc/sopel/pull/2580 [#2581]: https://github.com/sopel-irc/sopel/pull/2581 [#2584]: https://github.com/sopel-irc/sopel/pull/2584 [#2600]: https://github.com/sopel-irc/sopel/pull/2600 [#2601]: https://github.com/sopel-irc/sopel/pull/2601 Changes between 7.1.8 and 7.1.9 =============================== Plugin changes -------------- * search: replace deprecated git.io link in messaging [[#2271][]] * tell: fix exception when message is missing [[#2264][]] [#2264]: https://github.com/sopel-irc/sopel/pull/2264 [#2271]: https://github.com/sopel-irc/sopel/pull/2271 Changes between 7.1.7 and 7.1.8 =============================== Plugin changes -------------- * isup: ensure compatibility with newer `requests` versions [[#2235][]] * reddit: handle image preview links [[#2245][]] * search: per tests of both back-ends, warn more consistently about multiple `site:` operators [[#2254][]] * translate: fix accepting language hints for Chinese [[#2242][]] * url: * bump user-agent [[#2218][]] * tweak logging levels to better reflect severity [[#2249][]] * wikipedia: refine handling of sections with "hatnote" templates [[#2225][]] * xkcd: improve reliability of comic search [[#2247][]] Core changes ------------ * Formatting tweaks in IRC logging output [[#2250][]] * Requirement tweaks to make sure installing on Python 3.4 still works (but if you're still using that, *please* update your Python) API changes ----------- * Fix/improve more documentation [[#2251][]] [#2218]: https://github.com/sopel-irc/sopel/pull/2218 [#2225]: https://github.com/sopel-irc/sopel/pull/2225 [#2235]: https://github.com/sopel-irc/sopel/pull/2235 [#2242]: https://github.com/sopel-irc/sopel/pull/2242 [#2245]: https://github.com/sopel-irc/sopel/pull/2245 [#2247]: https://github.com/sopel-irc/sopel/pull/2247 [#2249]: https://github.com/sopel-irc/sopel/pull/2249 [#2250]: https://github.com/sopel-irc/sopel/pull/2250 [#2251]: https://github.com/sopel-irc/sopel/pull/2251 [#2254]: https://github.com/sopel-irc/sopel/pull/2254 Changes between 7.1.6 and 7.1.7 =============================== Plugin changes -------------- * adminchannel: fix a very old bug in NUH (hostmask) handling [[#2221][]] * reddit: * add flair text to submission output [[#2209][]] * further improve link matching [[#2208][], [#2216][]] * wiktionary: correctly handle multi-paragraph etymologies [[#2214][]] Core changes ------------ * Added an alert if the IRC server registers the bot as a client using a different nickname than what's set in `core.nick` [[#2215][]] [#2208]: https://github.com/sopel-irc/sopel/pull/2208 [#2209]: https://github.com/sopel-irc/sopel/pull/2209 [#2214]: https://github.com/sopel-irc/sopel/pull/2214 [#2215]: https://github.com/sopel-irc/sopel/pull/2215 [#2216]: https://github.com/sopel-irc/sopel/pull/2216 [#2221]: https://github.com/sopel-irc/sopel/pull/2221 Changes between 7.1.5 and 7.1.6 =============================== Plugin changes -------------- * reddit: fix regression in shortlink (`redd.it/`) handling [[#2201][]] * url: fix tripping on HTML character entities like `'` if running on Python 3.4+ [[#2204][]] * wikipedia: add mobile links to URL handling [[#2201][]] Core changes ------------ * Detect UTF-8 locale on Windows [[#2174][]] API changes ----------- * `web.decode()`: use Python's built-in HTML character entity decoder if available [[#2204][]] * Fix minor documentation error [[#2196][]] [#2174]: https://github.com/sopel-irc/sopel/pull/2174 [#2196]: https://github.com/sopel-irc/sopel/pull/2196 [#2201]: https://github.com/sopel-irc/sopel/pull/2201 [#2202]: https://github.com/sopel-irc/sopel/pull/2202 [#2204]: https://github.com/sopel-irc/sopel/pull/2204 Changes between 7.1.4 and 7.1.5 =============================== Since 7.1.4 was released, an [expiring TLS root certificate][le-expiration] caused us some problems in the old CI system we're still using for Sopel 7.1.x to run tests against EOL versions of Python. Our workaround in [#2192][] (basically "Workaround 1" from [this OpenSSL blog post][openssl-102-fixes]) might be of use to anyone still running Sopel on an old system. Core changes ------------ * Fixed incorrect behavior during unrecognized SASL authentication [[#2190][]] * Ignore case when checking config sections for "defined" settings [[#2193][]] [#2190]: https://github.com/sopel-irc/sopel/pull/2190 [#2192]: https://github.com/sopel-irc/sopel/pull/2192 [#2193]: https://github.com/sopel-irc/sopel/pull/2193 [le-expiration]: https://letsencrypt.org/2021/10/01/cert-chaining-help.html [openssl-102-fixes]: https://www.openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire/ Changes between 7.1.3 and 7.1.4 =============================== Plugin changes -------------- * reddit: prevent comment links from also displaying post info [[#2176][]] [#2176]: https://github.com/sopel-irc/sopel/pull/2176 Changes between 7.1.2 and 7.1.3 =============================== Plugin changes -------------- * announce: fix Python 3 compatibility [[#2166][]] * reddit: fix handling post links with parameters, e.g. sorting [[#2163][]] * reddit: silence PRAW update notices [[#2171][]] * tell: don't strip IRC formatting at message start [[#2162][]] * translate: better error handling in `.mangle` [[#2160][]] * wikipedia: skip messagebox template contents for cleaner snippets [[#2159][]] * wikipedia: improve handling of links to transcluded sections [[#2168][]] Core changes ------------ * Fixed showing plugin information in `sopel-plugins` CLI tool even if loading the plugin fails [[#2135][]] * Stop warning about `parse == bool` configuration settings in 7.x [[#2164][]] * This warning will return in Sopel 8.0, a major release which will be a more natural time for plugin maintainers to release compatibility updates. * Fixed `requests` requirement on Python 3.3 [[#2172][]] [#2135]: https://github.com/sopel-irc/sopel/pull/2135 [#2159]: https://github.com/sopel-irc/sopel/pull/2159 [#2160]: https://github.com/sopel-irc/sopel/pull/2160 [#2162]: https://github.com/sopel-irc/sopel/pull/2162 [#2163]: https://github.com/sopel-irc/sopel/pull/2163 [#2164]: https://github.com/sopel-irc/sopel/pull/2164 [#2166]: https://github.com/sopel-irc/sopel/pull/2166 [#2168]: https://github.com/sopel-irc/sopel/pull/2168 [#2171]: https://github.com/sopel-irc/sopel/pull/2171 [#2172]: https://github.com/sopel-irc/sopel/pull/2172 Changes between 7.1.1 and 7.1.2 =============================== Plugin changes -------------- * invite: handle invalid arguments better [[#2151][]] * translate: handle failed API requests better [[#2153][]] * wikipedia: warn if deprecated `lang_per_channel` setting is used [[#2143][]] Core changes ------------ * Clarified documentation about `owner` and `owner_account` settings in core config section [[#2112][], [#2125][]] [#2112]: https://github.com/sopel-irc/sopel/pull/2112 [#2125]: https://github.com/sopel-irc/sopel/pull/2125 [#2143]: https://github.com/sopel-irc/sopel/pull/2143 [#2151]: https://github.com/sopel-irc/sopel/pull/2151 [#2153]: https://github.com/sopel-irc/sopel/pull/2153 Changes between 7.1.0 and 7.1.1 =============================== Plugin changes -------------- * safety: fixed loading bad-domains list on py2 [[#2103][]] * tell: fixed hard-coded verb when trying to `.ask` the bot [[#2106][]] * tld: fixed `.tldcache clear` command corrupting internal state [[#2077][]] Core changes ------------ * Fixed `BooleanAttribute` with `default=True` [[#2084][]] * Ignore invalid URLs when triggering URL callbacks [[#2086][]] * Fixed infinite loop in WHO tracking on certain networks [[#2091][]] * Ignore problematic environment variables in tests [[#2094][]] * Improved MODE tracking even more [[#2097][], [#2098][]] * Updated, clarified, and expanded even more documentation [[#2090][], [#2096][], [#2105][], [#2108][]] [#2077]: https://github.com/sopel-irc/sopel/pull/2077 [#2084]: https://github.com/sopel-irc/sopel/pull/2084 [#2086]: https://github.com/sopel-irc/sopel/pull/2086 [#2090]: https://github.com/sopel-irc/sopel/pull/2090 [#2091]: https://github.com/sopel-irc/sopel/pull/2091 [#2094]: https://github.com/sopel-irc/sopel/pull/2094 [#2096]: https://github.com/sopel-irc/sopel/pull/2096 [#2097]: https://github.com/sopel-irc/sopel/pull/2097 [#2098]: https://github.com/sopel-irc/sopel/pull/2098 [#2103]: https://github.com/sopel-irc/sopel/pull/2103 [#2105]: https://github.com/sopel-irc/sopel/pull/2105 [#2106]: https://github.com/sopel-irc/sopel/pull/2106 [#2108]: https://github.com/sopel-irc/sopel/pull/2108 Changes between 7.0.7 and 7.1.0 =============================== Admittedly a few _months_ later than originally intended, Sopel 7.1.0 is ready to go. We've focused on polish this time around, both in documentation and features. Lots of little fixes add up to make something good—over 140 pull requests were merged for this release. We will now begin work on Sopel 8.0, focusing primarily on modernization—dropping the end-of-life Python versions that 7.x still supports—and on unbundling the core plugins so they can be updated separately. None of these plans are new, but we figured a reminder was in order as it's been some months since they last came up in Sopel 7.0's release notes! As always, you can keep up with development and give us feedback on [GitHub][sopel-github], [IRC][sopel-irc], or [Twitter][sopel-twitter]. **Important note:** Sopel's IRC channel has moved from freenode to Libera Chat ([#2072][]). You will find us in `#sopel` as always, but at a new network address: `irc.libera.chat`. At least some of the old guard will remain on freenode for the foreseeable future, to guide anyone running an older Sopel version to the new channel (and encourage them to update Sopel, too). Plugin changes -------------- * Removed `instagram` plugin, as it was not possible to fix after changes to the site [[#2000][]] * Merged `etymology` plugin functionality into `wiktionary` plugin [[#1178][], [#2064][]] * admin: * reply on save [[#1913][]] * add `.chanlist` command to show Sopel's channel memberships [[#1961][]] * adminchannel: * use `TOPICLEN` if server advertises it [[#1956][]] * allow non-op `.topic` in channels without mode `+t` [[#1981][]] * announce: speed up by sending to multiple channels if the server supports it [[#1859][], [#2048][]] * choose: safely handle formatted choices [[#1965][]] * currency: * added thousands separator & better handling of small numbers [[#1988][]] * improved error handling [[#2053][]] * updated API endpoints [[#1988][], [#2060][], [#2074][]] * emoticons: added `.smirk` command & action responses [[#1899][]] * find: accept either `/` or `|` as delimiter, and format replacement text as **bold** so it's easier to see the correction [[#1993][], [#2014][], [#2066][]] * find_updates: * prepare to handle unstable releases again [[#1955][]] * improve error handling [[#2052][], [#2056][]] * ip: querying by nickname is no longer case-sensitive [[#1915][]] * isup: be more specific about what's wrong if the site looks down [[#1940][], [#1950][], [#2063][]] * meetbot: tweaked handling of path settings [[#1959][]] * ping: added `.ping` command [[#1875][]] * pronouns: now understands two-word aliases for the full pronoun groups [[#2069][]] * reddit: * added handling for `r/all` and `r/popular` [[#1763][]] * fixed incorrect behavior in `r/` and `u/` handling [[#1889][]] * added basic handling for gallery view [[#1914][]] * fixed a floating-point issue [[#1987][]] * fixed grammar [[#2025][]] * remind: added commands to count/forget reminders [[#2007][]] * safety: switched away from obsolete list source [[#2012][]] * tell: strip `@` from the start of nicknames [[#1994][]] * tld: rewritten to be more robust [[#1939][], [#1949][], [#1968][], [#1970][], [#1985][], [#2076][]] * url: * tweaked to improve reliability of title fetching [[#1871][]] * added a setting to control automatic titles [[#1897][]] * adapted to upstream dependency changes [[#1989][]] * add `.urlexclude`/`.urlallow` commands [[#2028][]] * auto-title now ignores URLs in _any_ other command [[#2028][]] * fixed showing an error when appropriate [[#2029][]] * wikipedia: * can now fetch section snippets [[#1163][]] * language preferences per-channel and per-nick are now stored in the database, and manageable with commands [[#1916][]] * xkcd: show latest comic when base URL is linked [[#1858][]] * Built-in plugins' output formats were checked for consistency [[#1937][]] * Improved plugin documentation/help [[#1878][], [#1952][], [#1954][], [#2002][], [#2035][]] * Updated some plugins to use new API features [[#1879][], [#1892][], [#1894][], [#1995][]] * Minor code style fixes and cleanup [[#1856][], [#1880][], [#1910][], [#1953][], [#1960][]] Core changes ------------ * Sopel's outbound flooding protection is now configurable [[#1929][]] * `core.modes` setting now only assumes `+` if no sign is included in its value [[#1941][]] * Improved documentation of core configuration settings [[#1861][], [#1866][], [#2006][]] * Documented use of environment variables to override parts of Sopel's configuration [[#1901][]] * Also fixed some broken functionality related to this feature [[#1882][], [#1900][]] * Improved command-line error messages [[#2047][]] * Unexpected settings in config files will now generate warnings [[#1973][]] * Improved SASL handling [[#1928][], [#1971][], [#1976][], [#1977][]] * Change/recover in-use nick; fix `USER` syntax [[#1930][]] * Improved channel mode tracking [[#1980][]] * Improved channel member tracking [[#1997][]] * Reduced log spam from core `MODE` handling logic [[#1951][]] * Refactored the Rule system [[#1873][], [#1894][], [#1904][], [#2011][]] * Reworked IRC connection timeout management [[#2041][]] * Fixed loading callables that should be ignored from plugins [[#1936][]] * Streamlined how the bot generates help text for plugin commands [[#2071][]] * Fixed signal handling (e.g. `^C`) if bot is not connected [[#1893][]] * Fixed crash if a plugin tries to `sys.exit()` [[#1943][]] * Fixed crash if IRC backend is uninitialized and logging to a channel is enabled [[#2020][]] * Improved scheduled job handling [[#1891][], [#1927][]] * Improved test coverage [[#1983][], [#1984][]] * Improved test infrastructure [[#1905][]] * Minor code style fixes and refactoring [[#1864][], [#1890][], [#1933][], [#1942][], [#1969][], [#1998][], [#2005][], [#2023][]] API changes ----------- * Moved plugin decorators to `sopel.plugin`; `sopel.module` is now deprecated [[#1898][], [#1906][], [#1924][], [#1967][]] * Decorators that are new in Sopel 7.1 or later will appear only in `sopel.plugin`; `sopel.module` contains only a snapshot of what was available in Sopel 7.0 and will not be updated * The old `sopel.module` imports will be removed in Sopel 9.0 * The `intent` decorator is replaced by `ctcp`, and `trigger` objects now have a `ctcp` property [[#1975][]] * "Intents" were an IRCv3 spec idea that never took off, and the draft specs for them are now long abandoned * See [#1683][] for the full deprecation and removal plan * `sopel.tools` functions related to command patterns/regex are now deprecated [[#1944][], [#2027][], [#2034][]] * `tools.get_input` is now deprecated [[#1872][]] * `bot.(un)register_url_callback` functions are deprecated [[#2049][]] * These are simply no longer necessary after the Rule system rewrite * `test_tools` submodule is now deprecated [[#2003][]] * Sopel now provides a `pytest` plugin; use that instead * The use of whitespace after `$nick` placeholders in plugin rules is now less confusing [[#1920][]] * Sopel now explicitly supports running plugins' event handlers before/after core has processed the event [[#2018][]] * Added more tools related to `tools.time.seconds_to_human` [[#2026][]] * Added a warning when plugins use `bot.memory['url_callbacks']` [[#2033][]] * Added `SopelIdentifierMemory` class to `tools` [[#1938][]] * This offers a less error-prone alternative to using a plain `SopelMemory`, which often requires manually casting user input to the `Identifier` type * New `plugin.require_bot_privilege` decorator and `bot.has_channel_privilege` method [[#1982][]] * Added `plugin.find` and `plugin.search` decorators [[#1881][]] * Added `plugin.rule_lazy`, `plugin.find_lazy`, and `plugin.search_lazy` decorators [[#2037][]] * These are for plugins to define rules that depend on the contents of Sopel's settings object (`bot.config`) * `bot.say` now allows even more control over variable-length content via optional `truncation` and `trailing` parameters [[#1958][], [#2050][]] * `bot.trigger` now has a `plain` attribute, containing the received line with formatting stripped [[#1918][]] * `Channel` objects now contain information about channel modes [[#1980][]] * Added a `BooleanAttribute` setting type [[#2044][], [#2059][]] * Use of `ValidatedAttribute` with `parse=bool` is now considered deprecated so we can remove the monkey-patching in a future release, and will raise a warning if used * Added a `SecretAttribute` setting type, and `is_secret` parameter to `ValidatedAttribute` [[#1879][]] * `plugin.example` now supports running plugin tests with [VCR.py][pypi-vcrpy] support [[#1853][]] * `bot.isupport` will return an empty `CHANMODES` if unadvertised [[#2015][]] * Make `tools.time` and `tools.web` submodules available with just `from sopel import tools` [[#1948][]] * Added new optional `warning_in` and `stack_frame` parameters to the `tools.deprecated` decorator, which now outputs its warning via logging [[#1872][], [#2046][], [#2058][]] * `MockIRCServer` methods now block by default [[#2065][]] * Improved documentation for writing & testing plugins [[#1923][], [#1964][], [#2013][], [#2067][]] * Improved documentation of various Sopel components: * `bot` [[#1857][]] * `cli` [[#1922][]] * `coretasks` [[#2001][]] * `loader` [[#2004][]] * `plugins` [[#1902][]] * Tweaked documentation styles for easier readability [[#1932][]] * Note: We plan to change the documentation theme entirely for Sopel 8, to something much more modern [#1163]: https://github.com/sopel-irc/sopel/pull/1163 [#1178]: https://github.com/sopel-irc/sopel/pull/1178 [#1763]: https://github.com/sopel-irc/sopel/pull/1763 [#1853]: https://github.com/sopel-irc/sopel/pull/1853 [#1856]: https://github.com/sopel-irc/sopel/pull/1856 [#1857]: https://github.com/sopel-irc/sopel/pull/1857 [#1858]: https://github.com/sopel-irc/sopel/pull/1858 [#1859]: https://github.com/sopel-irc/sopel/pull/1859 [#1861]: https://github.com/sopel-irc/sopel/pull/1861 [#1864]: https://github.com/sopel-irc/sopel/pull/1864 [#1866]: https://github.com/sopel-irc/sopel/pull/1866 [#1871]: https://github.com/sopel-irc/sopel/pull/1871 [#1872]: https://github.com/sopel-irc/sopel/pull/1872 [#1873]: https://github.com/sopel-irc/sopel/pull/1873 [#1875]: https://github.com/sopel-irc/sopel/pull/1875 [#1878]: https://github.com/sopel-irc/sopel/pull/1878 [#1879]: https://github.com/sopel-irc/sopel/pull/1879 [#1880]: https://github.com/sopel-irc/sopel/pull/1880 [#1881]: https://github.com/sopel-irc/sopel/pull/1881 [#1882]: https://github.com/sopel-irc/sopel/pull/1882 [#1889]: https://github.com/sopel-irc/sopel/pull/1889 [#1890]: https://github.com/sopel-irc/sopel/pull/1890 [#1891]: https://github.com/sopel-irc/sopel/pull/1891 [#1892]: https://github.com/sopel-irc/sopel/pull/1892 [#1893]: https://github.com/sopel-irc/sopel/pull/1893 [#1894]: https://github.com/sopel-irc/sopel/pull/1894 [#1897]: https://github.com/sopel-irc/sopel/pull/1897 [#1898]: https://github.com/sopel-irc/sopel/pull/1898 [#1899]: https://github.com/sopel-irc/sopel/pull/1899 [#1900]: https://github.com/sopel-irc/sopel/pull/1900 [#1901]: https://github.com/sopel-irc/sopel/pull/1901 [#1902]: https://github.com/sopel-irc/sopel/pull/1902 [#1904]: https://github.com/sopel-irc/sopel/pull/1904 [#1905]: https://github.com/sopel-irc/sopel/pull/1905 [#1906]: https://github.com/sopel-irc/sopel/pull/1906 [#1910]: https://github.com/sopel-irc/sopel/pull/1910 [#1913]: https://github.com/sopel-irc/sopel/pull/1913 [#1914]: https://github.com/sopel-irc/sopel/pull/1914 [#1915]: https://github.com/sopel-irc/sopel/pull/1915 [#1916]: https://github.com/sopel-irc/sopel/pull/1916 [#1918]: https://github.com/sopel-irc/sopel/pull/1918 [#1920]: https://github.com/sopel-irc/sopel/pull/1920 [#1922]: https://github.com/sopel-irc/sopel/pull/1922 [#1923]: https://github.com/sopel-irc/sopel/pull/1923 [#1924]: https://github.com/sopel-irc/sopel/pull/1924 [#1927]: https://github.com/sopel-irc/sopel/pull/1927 [#1928]: https://github.com/sopel-irc/sopel/pull/1928 [#1929]: https://github.com/sopel-irc/sopel/pull/1929 [#1930]: https://github.com/sopel-irc/sopel/pull/1930 [#1932]: https://github.com/sopel-irc/sopel/pull/1932 [#1933]: https://github.com/sopel-irc/sopel/pull/1933 [#1936]: https://github.com/sopel-irc/sopel/pull/1936 [#1937]: https://github.com/sopel-irc/sopel/pull/1937 [#1938]: https://github.com/sopel-irc/sopel/pull/1938 [#1939]: https://github.com/sopel-irc/sopel/pull/1939 [#1940]: https://github.com/sopel-irc/sopel/pull/1940 [#1941]: https://github.com/sopel-irc/sopel/pull/1941 [#1942]: https://github.com/sopel-irc/sopel/pull/1942 [#1943]: https://github.com/sopel-irc/sopel/pull/1943 [#1944]: https://github.com/sopel-irc/sopel/pull/1944 [#1948]: https://github.com/sopel-irc/sopel/pull/1948 [#1949]: https://github.com/sopel-irc/sopel/pull/1949 [#1950]: https://github.com/sopel-irc/sopel/pull/1950 [#1951]: https://github.com/sopel-irc/sopel/pull/1951 [#1952]: https://github.com/sopel-irc/sopel/pull/1952 [#1953]: https://github.com/sopel-irc/sopel/pull/1953 [#1954]: https://github.com/sopel-irc/sopel/pull/1954 [#1955]: https://github.com/sopel-irc/sopel/pull/1955 [#1956]: https://github.com/sopel-irc/sopel/pull/1956 [#1958]: https://github.com/sopel-irc/sopel/pull/1958 [#1959]: https://github.com/sopel-irc/sopel/pull/1959 [#1960]: https://github.com/sopel-irc/sopel/pull/1960 [#1961]: https://github.com/sopel-irc/sopel/pull/1961 [#1964]: https://github.com/sopel-irc/sopel/pull/1964 [#1965]: https://github.com/sopel-irc/sopel/pull/1965 [#1967]: https://github.com/sopel-irc/sopel/pull/1967 [#1968]: https://github.com/sopel-irc/sopel/pull/1968 [#1969]: https://github.com/sopel-irc/sopel/pull/1969 [#1970]: https://github.com/sopel-irc/sopel/pull/1970 [#1971]: https://github.com/sopel-irc/sopel/pull/1971 [#1973]: https://github.com/sopel-irc/sopel/pull/1973 [#1975]: https://github.com/sopel-irc/sopel/pull/1975 [#1976]: https://github.com/sopel-irc/sopel/pull/1976 [#1977]: https://github.com/sopel-irc/sopel/pull/1977 [#1980]: https://github.com/sopel-irc/sopel/pull/1980 [#1981]: https://github.com/sopel-irc/sopel/pull/1981 [#1982]: https://github.com/sopel-irc/sopel/pull/1982 [#1983]: https://github.com/sopel-irc/sopel/pull/1983 [#1984]: https://github.com/sopel-irc/sopel/pull/1984 [#1985]: https://github.com/sopel-irc/sopel/pull/1985 [#1987]: https://github.com/sopel-irc/sopel/pull/1987 [#1988]: https://github.com/sopel-irc/sopel/pull/1988 [#1989]: https://github.com/sopel-irc/sopel/pull/1989 [#1993]: https://github.com/sopel-irc/sopel/pull/1993 [#1994]: https://github.com/sopel-irc/sopel/pull/1994 [#1995]: https://github.com/sopel-irc/sopel/pull/1995 [#1997]: https://github.com/sopel-irc/sopel/pull/1997 [#1998]: https://github.com/sopel-irc/sopel/pull/1998 [#2000]: https://github.com/sopel-irc/sopel/pull/2000 [#2001]: https://github.com/sopel-irc/sopel/pull/2001 [#2002]: https://github.com/sopel-irc/sopel/pull/2002 [#2003]: https://github.com/sopel-irc/sopel/pull/2003 [#2004]: https://github.com/sopel-irc/sopel/pull/2004 [#2005]: https://github.com/sopel-irc/sopel/pull/2005 [#2006]: https://github.com/sopel-irc/sopel/pull/2006 [#2007]: https://github.com/sopel-irc/sopel/pull/2007 [#2011]: https://github.com/sopel-irc/sopel/pull/2011 [#2012]: https://github.com/sopel-irc/sopel/pull/2012 [#2013]: https://github.com/sopel-irc/sopel/pull/2013 [#2014]: https://github.com/sopel-irc/sopel/pull/2014 [#2015]: https://github.com/sopel-irc/sopel/pull/2015 [#2018]: https://github.com/sopel-irc/sopel/pull/2018 [#2020]: https://github.com/sopel-irc/sopel/pull/2020 [#2023]: https://github.com/sopel-irc/sopel/pull/2023 [#2025]: https://github.com/sopel-irc/sopel/pull/2025 [#2026]: https://github.com/sopel-irc/sopel/pull/2026 [#2027]: https://github.com/sopel-irc/sopel/pull/2027 [#2028]: https://github.com/sopel-irc/sopel/pull/2028 [#2029]: https://github.com/sopel-irc/sopel/pull/2029 [#2033]: https://github.com/sopel-irc/sopel/pull/2033 [#2034]: https://github.com/sopel-irc/sopel/pull/2034 [#2035]: https://github.com/sopel-irc/sopel/pull/2035 [#2037]: https://github.com/sopel-irc/sopel/pull/2037 [#2041]: https://github.com/sopel-irc/sopel/pull/2041 [#2044]: https://github.com/sopel-irc/sopel/pull/2044 [#2046]: https://github.com/sopel-irc/sopel/pull/2046 [#2047]: https://github.com/sopel-irc/sopel/pull/2047 [#2048]: https://github.com/sopel-irc/sopel/pull/2048 [#2049]: https://github.com/sopel-irc/sopel/pull/2049 [#2050]: https://github.com/sopel-irc/sopel/pull/2050 [#2052]: https://github.com/sopel-irc/sopel/pull/2052 [#2053]: https://github.com/sopel-irc/sopel/pull/2053 [#2056]: https://github.com/sopel-irc/sopel/pull/2056 [#2058]: https://github.com/sopel-irc/sopel/pull/2058 [#2059]: https://github.com/sopel-irc/sopel/pull/2059 [#2060]: https://github.com/sopel-irc/sopel/pull/2060 [#2063]: https://github.com/sopel-irc/sopel/pull/2063 [#2064]: https://github.com/sopel-irc/sopel/pull/2064 [#2065]: https://github.com/sopel-irc/sopel/pull/2065 [#2066]: https://github.com/sopel-irc/sopel/pull/2066 [#2067]: https://github.com/sopel-irc/sopel/pull/2067 [#2069]: https://github.com/sopel-irc/sopel/pull/2069 [#2071]: https://github.com/sopel-irc/sopel/pull/2071 [#2072]: https://github.com/sopel-irc/sopel/pull/2072 [#2074]: https://github.com/sopel-irc/sopel/pull/2074 [#2076]: https://github.com/sopel-irc/sopel/pull/2076 [#1683]: https://github.com/sopel-irc/sopel/issues/1683 [pypi-vcrpy]: https://pypi.org/project/vcrpy/ [sopel-github]: https://github.com/sopel-irc/sopel [sopel-irc]: ircs://irc.libera.chat/sopel [sopel-twitter]: https://twitter.com/SopelIRC Changes between 7.0.6 and 7.0.7 =============================== Core changes ------------ * Make sure Sopel continues to install smoothly on all of its supported Python versions after November 2020 changes in `urllib3` 1.26 * Updated a few spots in tests and documentation to keep our 7.0.x maintenance branch in tip-top shape Changes between 7.0.5 and 7.0.6 =============================== Core changes ------------ * Tweak `reddit` plugin's requirements to mitigate install problems on older versions of Python [[#1919][]] [#1919]: https://github.com/sopel-irc/sopel/pull/1919 Changes between 7.0.4 and 7.0.5 =============================== Core changes ------------ * Update `ip` plugin's requirements to prevent install problems on older versions of Python [[#1909][]] * Also includes a tweak to one of DuckDuckGo's tests in the `search` plugin, and a backported update to the `ip` plugin's tests. [#1909]: https://github.com/sopel-irc/sopel/pull/1909 Changes between 7.0.3 and 7.0.4 =============================== Plugin changes -------------- * Relax DuckDuckGo test in `search` plugin that was causing CI issues Core changes ------------ * Fix plugin name in bot's internal command-group tracking [[#1863][]] [#1863]: https://github.com/sopel-irc/sopel/pull/1863 Changes between 7.0.2 and 7.0.3 =============================== Plugin changes -------------- * Tweak Bing result matching in `search` plugin again [[#1854][]] Core changes ------------ * Fix URL callbacks missing required attributes [[#1855][]] [#1854]: https://github.com/sopel-irc/sopel/pull/1854 [#1855]: https://github.com/sopel-irc/sopel/pull/1855 Changes between 7.0.1 and 7.0.2 =============================== Plugin changes -------------- * Fix version comparison in `find_updates` plugin [[#1832][]] * Suppress link when `xkcd` plugin is triggered by a URL [[#1848][]] * Fix `reddit` grammar when post/comment only has 1 point [[#1849][]] * Handle missing data when `safety` plugin uses VirusTotal [[#1851][]] * Update `search` plugin for changed Bing SERPs [[#1852][]] * Also fixes `xkcd` plugin's find-comic-by-keywords functionality Core changes ------------ * Fixed that per-channel configuration didn't work as documented for some plugin types [[#1840][]] * Show how to use channel key (password) in configuration examples [[#1844][]] * Fixed URL callbacks bypassing user/channel restrictions [[#1845][]] * Capped `urllib3` (transitive dependency from `requests`) version on Python 3.3 to avoid a recent release breaking things * Meta: Fixed incorrect links in changelog entry for 7.0.1 API changes ----------- * Handle 0 seconds properly in `tools.time.seconds_to_human()` [[#1843][]] [#1832]: https://github.com/sopel-irc/sopel/pull/1832 [#1840]: https://github.com/sopel-irc/sopel/pull/1840 [#1843]: https://github.com/sopel-irc/sopel/pull/1843 [#1844]: https://github.com/sopel-irc/sopel/pull/1844 [#1845]: https://github.com/sopel-irc/sopel/pull/1845 [#1848]: https://github.com/sopel-irc/sopel/pull/1848 [#1849]: https://github.com/sopel-irc/sopel/pull/1849 [#1851]: https://github.com/sopel-irc/sopel/pull/1851 [#1852]: https://github.com/sopel-irc/sopel/pull/1852 Changes between 7.0.0 and 7.0.1 =============================== Sopel 7.0.1 contains small fixes and tweaks for core code, core plugins, and documentation. As this is a maintenance release, there are no new API features or deprecations to report—but stay tuned for a few new things in version 7.1.0. Plugin changes -------------- * The `reddit` plugin now displays when a redditor is an admin [[#1764][]] * When triggered by a native media link, `reddit` plugin output will include a link to the submission page (comments view) [[#1814][]] * Fixed `reddit` plugin not matching links with encoded characters [[#1827][]] * `clock` plugin's `.setchanneltz` command now emits an error message if an unprivileged user attempts to use it [[#1828][]] * Fixed the `units` plugin's handling of 16 ounces / 1 pound [[#1829][]] * Fixed loading `remind` database with reminder(s) containing certain IRC formatting characters [[#1831][]] Core changes ------------ * Hotfixed a crash that could occur if the connection was lost [[#1820][]] * Sopel now prints the used config file path at startup [[#1822][]] [#1764]: https://github.com/sopel-irc/sopel/pull/1764 [#1814]: https://github.com/sopel-irc/sopel/pull/1814 [#1820]: https://github.com/sopel-irc/sopel/pull/1820 [#1822]: https://github.com/sopel-irc/sopel/pull/1822 [#1827]: https://github.com/sopel-irc/sopel/pull/1827 [#1828]: https://github.com/sopel-irc/sopel/pull/1828 [#1829]: https://github.com/sopel-irc/sopel/pull/1829 [#1831]: https://github.com/sopel-irc/sopel/pull/1831 Changes between 6.6.9 and 7.0.0 =============================== Sopel 7.0 contains numerous fixes, tweaks, new features, and internal improvements. While we maintain no official statistics on such things, it's probably the biggest release the project has ever seen. The full, detailed list of changes is below, but you can just read the [migration guide][sopel-7-migration] if all you care about is the really important stuff. All breaking changes (including those planned for the *next* release) are explained there. Plugin changes -------------- * The `spellcheck` plugin has been removed to simplify dependencies [[#1675][]] * An updated version with added features and tweaks, based on `aspell`, is installable separately [from PyPI][spellcheck-pypi] [[#1164][], [#1545][]] * See [#1142][] & [#1642][] for background on why we decided to separate `spellcheck` into a separate package (tl;dr: dependency hell) * Similarly, the `ipython` plugin is now an external package, eliminating from Sopel itself a dependency which most users will never need [[#1684][]] * Find the new `sopel-ipython` package [on PyPI][ipython-pypi] * The `.choose`/`.choice` command has been moved from `dice` into a standalone plugin, aptly named `choose` [[#1679][]] * Moved `.py` into its own plugin, named `py` [[#1710][], [#1711][], [#1712][]] * In case of issues with our "official" instance, there's now a setting to configure the address of your own [Oblique][oblique] service * The `currency` plugin changed data sources to support more currencies, and can optionally use Fixer.io for even *more* [[#1430][], [#1627][], [#1629][]] * Fixer.io requires a free API key, which gives plenty of calls per month (the plugin caches exchange rates for 24 hours) * Choose any of five pastebin services for `help` output [[#1451][], [#1651][]] * This is intended mostly for resilience (so one pastebin service going down, as ptpb did during the 6.6.x life-cycle, won't force a new Sopel release), but it's also just good to have choices * Optionally hide IRC server name/address in `help` command listing [[#1459][]] * New `help` plugin setting, `reply_method` [[#1700][]] * `wiktionary` now supports many more parts of speech [[#1443][]] * Definitions can be retrieved for things like proper nouns, prepositional phrases, and punctuation marks—things that were unsupported in Sopel 6.x * This means that the `wiktionary` plugin is now somewhat case-sensitive, to account for common and proper nouns that differ only in capitalization * `url` will now ignore "private" addresses by default [[#1439][], [#1624][]] * New config settings for the `url` plugin allow overriding the checks, in cases where loading previews of e.g. LAN servers is safe * The default is off, so users don't unwittingly open themselves to attackers fishing for running HTTP services on the local machine or network * `url` now correctly ignores invalid URLs (e.g. `http://*\.com`) [[#1788][]] * Various improvements to the `clock` functions [[#1592][]] * Improved guessing in `.t`/`.time` command, which no longer falls back all the way to the bot's default timezone if given an unrecognized argument * New `.tz` command, to explicitly get time for a timezone name (in case of conflict between a known nick and a timezone name) * The `tell` & `remind` plugins' ".db" files have changed names [[#1699][]] * Both will attempt automatic migration of existing files, if they exist, and output debugging information if the migration fails * The `.at` command (in `remind`) understands dates now [[#1590][], [#1736][]] * Finally, it's possible to set a reminder more than 24 hours ahead without first converting the future date/time to a duration for use with `.in`! * A new `tell` plugin setting allows delivering messages privately [[#1694][]] * The `reddit` plugin now also handles short `redd.it` links, direct links to comments, inline `u/` and `r/` references, & reddit-hosted image/video links [[#1503][], [#1720][], [#1722][], [#1734][], [#1760][], [#1773][]] * Spoilers & NSFW are now separate concepts in the `reddit` plugin [[#1620][]] * Reddit implemented spoilers as a distinct post flag some time ago. Sopel's plugin supports independently setting channels as "SFW" or "spoiler-free". * Rolling `.dice` now officially supports trailing `# comments` [[#1577][]] * Python version is now included in `.version` command output [[#1462][]] * The `.version` command's output format is improved [[#1633][]] * Using the `.reload` command shows the specific file reloaded [[#1762][]] * The `.seen` command's output now uses relative time [[#1661][]] * Readability of `.choose` command output is significantly improved [[#1425][]] * Added `.invite` command [[#1497][]] * Both Sopel and the inviting user must have privileges in the target channel * A `.restart` command is added [[#1333][]] * Usable by admins only, just like `.quit` * The `.msg` command is now known as `.say` [[#1606][]] * `.msg` will continue to work for now, likely until being removed in Sopel 8 * The `admin` plugin auto-saves channels when using `.join`/`.part`, and added `.tmpjoin`/`.tmppart` commands to bypass this behavior [[#1492][]] * Added command to `.unset` config values in the `admin` plugin [[#1556][]] * Restored commands in `adminchannel` plugin for managing op/voice [[#1498][]] * These were removed some time ago, seemingly without reason, by the project's previous maintainers * Since there was some desire from users to have them back, we restored them * Fixed/tweaked hostmask handling in `adminchannel` ban functions [[#1791][]] * `find` also collects Sopel's own messages now, so users can "correct" the bot if they wish to be extra cheeky [[#1470][]] * Fixed that the `url` plugin had to be enabled or some link-handling functions wouldn't work [[#1510][]] * Tweaked `.ddg` command output so it's less likely to mangle URLs [[#1713][]] * `remind` commands now "reply" with error messages [[#1715][]] * Fixed `etymology` plugin error with empty argument [[#1677][]] * Fixed an uncaught exception in `instagram` plugin [[#1702][]] * Handle JSON fetch/parse errors in `find_updates` plugin [[#1779][]] * Removed nonsensical uses of the `core.verify_ssl` setting [[#1706][]] * Unused `clock` plugin settings have been removed [[#1696][]] * Updated MaxMind database handling in `ip` plugin [[#1797][]] * Reworked `safety` plugin's cache management [[#1753][], [#1802][]] * General code cleanup and tweaks all around [[#1402][], [#1486][], [#1505][], [#1569][], [#1573][], [#1578][], [#1579][], [#1581][], [#1592][], [#1606][], [#1607][], [#1609][], [#1678][], [#1681][], [#1696][], [#1717][], [#1721][], [#1725][], [#1735][], [#1741][], [#1754][]] Core changes ------------ * Brought back support for non-SQLite databases by switching to SQLAlchemy [[#1446][], [#1652][], [#1729][], [#1755][], [#1774][], [#1777][], [#1783][]] * For details on using non-SQLite databases, see the [README][readme-db] or [configuration instructions][db-config-docs] * You will probably need to install additional dependencies if you wish to use something other than SQLite * Migrating an existing database from SQLite to your chosen option is probably easy, but we do not offer instructions for doing so * Be aware that plugins written for older versions of Sopel might not work properly with non-SQLite databases * The `db_filename` config setting (for SQLite) is now interpreted as relative to the config's `homedir` setting [[#1574][]] * `homedir` itself has a default value that will be used if not set * Added separate server & nickname authentication options [[#1513][]] * See [authentication configuration docs][auth-config-docs] * Added `commands_on_connect` setting to send a list of commands automatically when Sopel's IRC connection is successfully established [[#1528][]] * Log files have become *much* more configurable [[#1678][], [#1714][]] * Logs are named based on the config name * Many, many new settings added to customize logging * The default log format includes timestamp, source package, & level (which will make logs *much* more useful when reporting bugs) * Logs now have information about which plugin file was reloaded [[#1762][]] * This is helpful for owners of Sopel instances with multiple versions of a plugin available for testing or development purposes * Sopel's own rate-limiting & flood protection parameters are now configurable, and can even be turned off entirely if Sopel is behind a bouncer or other IRC proxy that handles flood protection itself [[#1518][], [#1638][]] * Added more control over JOIN throttling [[#1751][]] * Includes a new `throttle_wait` setting instead of a hard-coded time value * Log timestamp and log line formats are now configurable [[#1512][]] * See details in [the logging configuration docs][logging-config-docs] * Log filenames now include the config name, to help keep track of logs from multiple Sopel instances [[#1547][]] * Home directory is no longer assumed to be `~/.sopel` on first run [[#1404][]] * Restarting Sopel via CLI is added [[#1333][]] * Sopel's CLI is restructured [[#1493][], [#1509][], [#1718][]] * New subcommands (`start`, `stop`, `restart`, and `configure`) replace many of the old `--option`s, cleaning up the syntax * The legacy `--option`s will continue to work for the life of Sopel 7.x, and will be removed in Sopel 8 * New `--config-dir` common option [[#1598][]] * Added a new `sopel-config` command for working with config files [[#1507][]] * Currently supports `list` (existing files), `init` (new config file), and `get` (config value) actions * The old `--list` argument to `sopel` is considered deprecated, and will be removed in Sopel 8 * See detailed usage in your terminal with `sopel-config --help`, or review [the online CLI docs][docs-cli-config] at our website * Added a new `sopel-plugins` command for managing plugins [[#1588][]] * Currently supports `list` (available plugins), `show` (plugin details & status), `enable` & `disable` (edits config on the user's behalf) * See detailed usage in your terminal with `sopel-plugins --help`, or review [the online CLI docs][docs-cli-plugins] at our website * Sopel now also looks for plugins in `$HOMEDIR/plugins` [[#1747][]] * This is part of a longer-term plan to reduce confusion over the term "module", which Sopel has been using in conflicting ways; see [[#1738][]] * The config file Sopel should use can be specified via the `SOPEL_CONFIG` environment variable [[#1473][]] * List values in config can be separated by newlines [[#1628][], [#1690][]] * Newline-separated values support commas within each value * Comma-separated value support will end someday, but likely not till Sopel 9 * Find more details in [the `ListAttribute` documentation][docs-listattr] * Config options can be set/overridden via environment variables [[#1096][]] * Variable naming format: `SOPEL_SECTION_OPTION` * Underscores in `SECTION` and `OPTION` names are preserved, e.g. `SOPEL_CORE_AUTH_PASSWORD` * Example multi-instance systemd template is now available [[#1059][]] * Example systemd unit files wait until networking is connected before starting Sopel [[#1511][]] * Running Sopel on an unknown OS platform will output a warning encouraging the user to report any issues (because test coverage on an unrecognized platform name is likely to be nil) [[#1487][]] * Cleaned up or refactored a bunch of places [[#1424][], [#1429][], [#1456][], [#1458][], [#1472][], [#1479][], [#1510][], [#1522][], [#1527][], [#1542][], [#1557][], [#1561][], [#1567][], [#1579][], [#1580][], [#1583][], [#1597][], [#1610][], [#1635][], [#1685][], [#1697][], [#1708][], [#1716][], [#1723][], [#1724][], [#1728][], [#1730][], [#1731][], [#1732][], [#1735][], [#1739][], [#1740][], [#1741][], [#1742][], [#1743][], [#1754][], [#1759][], [#1787][]] * Sopel 7 will emit warnings when run under Python 2, as Python 2.7 support officially ended on January 1, 2020 [[#1488][], [#1795][], [#1800][]] * Sopel's warnings are set to become more dire around the time when Python's maintainers plan to release the final version of 2.7 * While Sopel 7 is intended to remain compatible with Python 2, future compatibility is not guaranteed, and users should plan for Sopel 8 to officially drop Python 2 support (see [upgrade notes][sopel-7-migration]) * Added support for IRCv3 `echo-message` capability, which Sopel will now request upon connecting to an IRC server [[#1470][], [#1672][], [#1674][]] * Added support for disabling commands (or entire plugins) on a per-channel basis [[#1235][]] * See how it works: [Per-channel configuration][per-channel-conf] * Fixed tracking user `away` state [[#1663][], [#1664][], [#1666][], [#1703][]] * User information is now periodically updated [[#1664][]] * Fixed a case in which MODE tracking could break [[#1737][]] * Handle non-standard `+y`/`+Y` OPER modes [[#1671][]] * A new `OPER` constant in `sopel.module` now exists for these channel modes, which (at least on InspIRCd) use the privilege prefix `!` * This is a stopgap for one specific case; we are working on further changes to support dynamic parsing of privilege modes/prefixes at connect time * Stopped sending TOPIC command on JOIN [[#1749][]] * IRC servers should send the topic on join without being asked, per spec * Greatly improved the warning printed when a deprecated function is used, adding detail and removing unnecessary traceback lines [[#1568][], [#1613][]] * Typical length of output for each deprecated function call reduced from roughly 15 lines to 3 (warning, file/line, and offending code snippet) * Added optional `@deprecated` decorator arguments: * `reason`: why this item was deprecated * `version`: the version in which the deprecation happened * `removed_in`: the version in which the deprecated item will be removed * The end-of-life warning for users on Python 2.x is now date-aware [[#1756][]] * Made sure ignored users cannot trigger URL handlers [[#1806][]] * Tightened up some more dependency version specifiers [[#1807][]] API changes ----------- * [API documentation][api-docs] has been almost entirely overhauled [[#1563][], [#1566][], [#1646][], [#1668][], [#1669][], [#1680][], [#1719][], [#1727][], [#1735][], [#1750][], [#1766][], [#1770][], [#1771][], [#1772][], [#1775][], [#1776][], [#1778][], [#1782][], [#1813][]] * Nearly every file, both for the public API and Sopel's internals, was reviewed in its entirety to make these improvements globally: * More consistent style * Better use of Sphinx features (e.g. parameter definitions, return value notes, & version annotations) * General cleanup and copy-editing * Add more detail and examples to help new bot users and plugin authors * Remove or correct outdated information left over from previous versions * Most of Sopel's submodules now define `__all__`, limiting namespace pollution from using `*` in imports [[#1582][], [#1727][]] * Plugins can register themselves via `setuptools` entry points [[#1585][]] * This feature is an evolution of the previous mechanism to install plugins via PyPI packages, which required a specific directory structure and package name format (`sopel_modules.plugin_name`) * See [the entry point plugin documentation][entry-point-plugin] for more * Logging has been reworked [[#1678][]] * The `sopel.logger.get_logger()` function is deprecated in favor of a new `sopel.tools.get_logger()` utility with plugin-specific behavior * `sopel.logger.get_logger()` will begin emitting deprecation warnings in version 8.0, and will be removed in 9.0 * Testing tools have been overhauled [[#1731][], [#1732][], [#1781][]] * The old "Mock" classes in `sopel.test_tools` are now deprecated: * `MockConfig` * `MockSopel` * `MockSopelWrapper` * New pytest fixtures make the real objects usable in tests directly * The bot keeps track of running triggered threads, so tests can be sure that processing has finished before evaluating results * Sopel also now exports a `pytest` plugin, for convenience * `module.event()` decorator no longer requires a rule [[#1693][], [#1709][]] * Since 99% (unscientific guesstimate) of event decorators were paired with `@module.rule('.*')`, that's now implied if no rule decorator is present * Added `sopel.tools.web` (replaces `sopel.web`) [[#1616][], [#1670][]] * Both old and new import locations will work until Sopel 7 end-of-life * The `sopel.web` package will be removed completely in Sopel 8 * Functions marked as deprecated in the old location (e.g. `web.get()`) do *not* carry forward to the new package namespace; they remain deprecated * Added `tools.web.unquote()`, the reverse of `tools.web.quote()` [[#1681][]] * Note: This is not available in the `sopel.web` compatibility layer * Added a set of methods in the `bot` object to manipulate URL callbacks: `bot.register_url_callback`, `bot.unregister_url_callback`, and `bot.search_url_callbacks` [[#1508][], [#1808][]] * Modules should switch to using these new API methods instead of directly accessing `bot.memory['url_callbacks']` * There are no definite plans to remove `bot.memory['url_callbacks']`, but it should be considered deprecated * Added `kick()` method to `bot` object [[#1539][]] * `bot.kick(nick, channel, optional_message)` is shorthand for the pattern `bot.write(['KICK', channel, nick], optional_message)`, used by a number of both core and third-party plugins * Added `bot.myinfo`, containing the server's RPL_MYINFO (004) data [[#1769][]] * More information in [the MYINFO documentation][docs-myinfo] * Added `bot.isupport`, exposing network-specific settings and properties from the server's RPL_ISUPPORT (005) data [[#1758][]] * This includes useful things like the network's maximum nickname length (`NICKLEN`), maximum topic length (`TOPICLEN`), number of targets allowed per command (`TARGMAX`), and channel-privilege mappings (`PREFIX`) * More information in [the ISUPPORT documentation][docs-isupport] * Added `session()` method to `bot.db` [[#1811][]] * `db.connect()` now logs a message when used with a non-SQLite database connected, as raw connection behavior for different DB types varies * Added `delete_{nick,channel}_value` methods in `bot.db` [[#1526][]] * Added "plugin value" API to `bot.db` [[#1621][]] * Functionally identical to "nick" and "channel" values, but in a separate namespace intended for plugins' use to store key-value data that isn't associated with a nick or channel and doesn't belong in the config file * Added optional `default` kwarg to `db.get_*_value()` functions [[#1673][]] * This allows streamlining some uses of values fetched from the database * New `sopel.module.output_prefix` decorator [[#1701][]] * Defines a prefix for all output sent from the decorated callable via `bot.say` or `bot.notice` (`bot.action` & `bot.reply` don't fit the use cases this feature is intended to address) * New `sopel.module.require_account` decorator [[#1733][]] * This is useful to require services login on networks where Sopel can track users' authentication status, but will block *all* use of the decorated callable on networks without the necessary features * `sopel.module` decorators work much more consistently [[#1632][]] * All relevant decorators accept multiple arguments at once, and will work properly if used multiple times on the same function * Added `reply` option to `module.require_*` decorators [[#1456][], [#1500][]] * Passing `reply=True` will send the error message as if via `bot.reply()`, prefixing it with the name of the calling user to get their attention * Passing `reply=False` (or omitting the argument) will behave exactly as before, with the error message sent as if via `bot.say()` * Fixed the `@module.url` decorator to work always, regardless of whether any core plugins are enabled [[#1510][], [#1576][]] * Added `bot.hostmask` property (read-only) [[#1537][]] * This property is a shortcut for `bot.users.get(bot.nick).hostmask`, so it will throw an error if the bot is not connected to a network **and** joined to at least one channel. Basically, don't try to use it in plugin `setup()` or `shutdown()` methods. * Added `bot.get_plugin_meta()` method to fetch plugin information [[#1762][]] * Added `module.echo` decorator [[#1470][]] * Decorated callables will receive messages that Sopel itself sends, regardless of whether the IRC server actually supports `echo-message` * Don't send output from `@echo`-decorated callables; this will cause loops * Added `module.action_commands` decorator [[#1660][]] * This presently conflicts with other command/trigger decorators because of internal implementation details, but fixing that is on our to-do list * If you want both `action_commands` and another command type (`commands`, `nickname_commands`, etc.), use `@action_commands('foo')` to decorate a wrapper function that simply calls the main one * Officially deprecated the methods `SopelMemory.contains()` and `SopelMemoryWithDefault.contains()`, to be removed in Sopel 8 [[#1563][]] * Use the `in` operator instead * Officially deprecated the `bot.msg()` method [[#1606][]] * Adds a warning to Sopel's output for any third-party code that is still using `bot.msg()` (which was declared deprecated and removed from the API docs in 6.0) instead of `bot.say()` * Added a new `user_help` kwarg to `@module.example` decorator [[#1403][]] * This allows multiple help examples per command, as requested in [#1200][] * See the [Sopel 7 migration guide][sopel-7-migration] for details on using this new parameter, and about backwards compatibility * Added a new `online` kwarg to `@module.example` decorator [[#1555][]] * Example tests that require an Internet connection may be marked with `online=True` to indicate this fact (the default is `False`) * This facilitates running only offline-safe plugin tests, by passing `--offline` to pytest, if an Internet connection is unavailable * Outside of the test suite, this parameter has no effect * Corrected case-mapping in `tools.Identifier` class [[#1744][]] * See [the Sopel 7 migration guide][sopel-7-migration] for details, particularly if your plugin interacts with the database and/or user/channel identifiers in their lowercase form * Added more utilities to `tools.time`: * `tools.time.seconds_to_human()`, for generating human-readable fuzzy relative timestamps from `timedelta` or raw number of seconds [[#1560][]] * `tools.time.get_nick_timezone()` and `tools.time.get_channel_timezone()`, for cases where the fallback behavior(s) of `tools.time.get_timezone()` would be undesired [[#1592][]] * Made `tools.time.validate_timezone()` more robust [[#1707][]] * Added alias for 462 numeric in `tools.events` [[#1665][]] * [RFC 2812][] defined an incorrect spelling, `ERR_ALREADYREGISTRED`, and Sopel copied it verbatim * The spelling `ERR_ALREADYREGISTERED` can be used now, too * Fixed invalid raw lines in generated `@example` tests [[#1499][]] * Fixed `PreTrigger` objects missing the `text` attribute sometimes [[#1782][]] [#1059]: https://github.com/sopel-irc/sopel/pull/1059 [#1096]: https://github.com/sopel-irc/sopel/pull/1096 [#1142]: https://github.com/sopel-irc/sopel/issues/1142 [#1164]: https://github.com/sopel-irc/sopel/pull/1164 [#1200]: https://github.com/sopel-irc/sopel/issues/1200 [#1235]: https://github.com/sopel-irc/sopel/pull/1235 [#1333]: https://github.com/sopel-irc/sopel/pull/1333 [#1402]: https://github.com/sopel-irc/sopel/pull/1402 [#1403]: https://github.com/sopel-irc/sopel/pull/1403 [#1404]: https://github.com/sopel-irc/sopel/pull/1404 [#1424]: https://github.com/sopel-irc/sopel/pull/1424 [#1425]: https://github.com/sopel-irc/sopel/pull/1425 [#1429]: https://github.com/sopel-irc/sopel/pull/1429 [#1430]: https://github.com/sopel-irc/sopel/pull/1430 [#1439]: https://github.com/sopel-irc/sopel/pull/1439 [#1443]: https://github.com/sopel-irc/sopel/pull/1443 [#1446]: https://github.com/sopel-irc/sopel/pull/1446 [#1451]: https://github.com/sopel-irc/sopel/pull/1451 [#1456]: https://github.com/sopel-irc/sopel/pull/1456 [#1458]: https://github.com/sopel-irc/sopel/pull/1458 [#1459]: https://github.com/sopel-irc/sopel/pull/1459 [#1462]: https://github.com/sopel-irc/sopel/pull/1462 [#1470]: https://github.com/sopel-irc/sopel/pull/1470 [#1472]: https://github.com/sopel-irc/sopel/pull/1472 [#1473]: https://github.com/sopel-irc/sopel/pull/1473 [#1479]: https://github.com/sopel-irc/sopel/pull/1479 [#1486]: https://github.com/sopel-irc/sopel/pull/1486 [#1487]: https://github.com/sopel-irc/sopel/pull/1487 [#1488]: https://github.com/sopel-irc/sopel/pull/1488 [#1492]: https://github.com/sopel-irc/sopel/pull/1492 [#1493]: https://github.com/sopel-irc/sopel/pull/1493 [#1497]: https://github.com/sopel-irc/sopel/pull/1497 [#1498]: https://github.com/sopel-irc/sopel/pull/1498 [#1499]: https://github.com/sopel-irc/sopel/pull/1499 [#1500]: https://github.com/sopel-irc/sopel/pull/1500 [#1503]: https://github.com/sopel-irc/sopel/pull/1503 [#1505]: https://github.com/sopel-irc/sopel/pull/1505 [#1507]: https://github.com/sopel-irc/sopel/pull/1507 [#1508]: https://github.com/sopel-irc/sopel/pull/1508 [#1509]: https://github.com/sopel-irc/sopel/pull/1509 [#1510]: https://github.com/sopel-irc/sopel/pull/1510 [#1511]: https://github.com/sopel-irc/sopel/pull/1511 [#1512]: https://github.com/sopel-irc/sopel/pull/1512 [#1513]: https://github.com/sopel-irc/sopel/pull/1513 [#1518]: https://github.com/sopel-irc/sopel/pull/1518 [#1522]: https://github.com/sopel-irc/sopel/pull/1522 [#1526]: https://github.com/sopel-irc/sopel/pull/1526 [#1527]: https://github.com/sopel-irc/sopel/pull/1527 [#1528]: https://github.com/sopel-irc/sopel/pull/1528 [#1537]: https://github.com/sopel-irc/sopel/pull/1537 [#1539]: https://github.com/sopel-irc/sopel/pull/1539 [#1542]: https://github.com/sopel-irc/sopel/pull/1542 [#1545]: https://github.com/sopel-irc/sopel/pull/1545 [#1547]: https://github.com/sopel-irc/sopel/pull/1547 [#1555]: https://github.com/sopel-irc/sopel/pull/1555 [#1556]: https://github.com/sopel-irc/sopel/pull/1556 [#1557]: https://github.com/sopel-irc/sopel/pull/1557 [#1560]: https://github.com/sopel-irc/sopel/pull/1560 [#1561]: https://github.com/sopel-irc/sopel/pull/1561 [#1563]: https://github.com/sopel-irc/sopel/pull/1563 [#1566]: https://github.com/sopel-irc/sopel/pull/1566 [#1567]: https://github.com/sopel-irc/sopel/pull/1567 [#1568]: https://github.com/sopel-irc/sopel/pull/1568 [#1569]: https://github.com/sopel-irc/sopel/pull/1569 [#1573]: https://github.com/sopel-irc/sopel/pull/1573 [#1574]: https://github.com/sopel-irc/sopel/pull/1574 [#1576]: https://github.com/sopel-irc/sopel/pull/1576 [#1577]: https://github.com/sopel-irc/sopel/pull/1577 [#1578]: https://github.com/sopel-irc/sopel/pull/1578 [#1579]: https://github.com/sopel-irc/sopel/pull/1579 [#1580]: https://github.com/sopel-irc/sopel/pull/1580 [#1581]: https://github.com/sopel-irc/sopel/pull/1581 [#1582]: https://github.com/sopel-irc/sopel/pull/1582 [#1583]: https://github.com/sopel-irc/sopel/pull/1583 [#1585]: https://github.com/sopel-irc/sopel/pull/1585 [#1588]: https://github.com/sopel-irc/sopel/pull/1588 [#1590]: https://github.com/sopel-irc/sopel/pull/1590 [#1592]: https://github.com/sopel-irc/sopel/pull/1592 [#1597]: https://github.com/sopel-irc/sopel/pull/1597 [#1598]: https://github.com/sopel-irc/sopel/pull/1598 [#1606]: https://github.com/sopel-irc/sopel/pull/1606 [#1607]: https://github.com/sopel-irc/sopel/pull/1607 [#1609]: https://github.com/sopel-irc/sopel/pull/1609 [#1610]: https://github.com/sopel-irc/sopel/pull/1610 [#1613]: https://github.com/sopel-irc/sopel/pull/1613 [#1616]: https://github.com/sopel-irc/sopel/pull/1616 [#1620]: https://github.com/sopel-irc/sopel/pull/1620 [#1621]: https://github.com/sopel-irc/sopel/pull/1621 [#1624]: https://github.com/sopel-irc/sopel/pull/1624 [#1627]: https://github.com/sopel-irc/sopel/pull/1627 [#1628]: https://github.com/sopel-irc/sopel/pull/1628 [#1629]: https://github.com/sopel-irc/sopel/pull/1629 [#1632]: https://github.com/sopel-irc/sopel/pull/1632 [#1633]: https://github.com/sopel-irc/sopel/pull/1633 [#1635]: https://github.com/sopel-irc/sopel/pull/1635 [#1638]: https://github.com/sopel-irc/sopel/pull/1638 [#1642]: https://github.com/sopel-irc/sopel/issues/1642 [#1646]: https://github.com/sopel-irc/sopel/pull/1646 [#1651]: https://github.com/sopel-irc/sopel/pull/1651 [#1652]: https://github.com/sopel-irc/sopel/pull/1652 [#1660]: https://github.com/sopel-irc/sopel/pull/1660 [#1661]: https://github.com/sopel-irc/sopel/pull/1661 [#1663]: https://github.com/sopel-irc/sopel/pull/1663 [#1664]: https://github.com/sopel-irc/sopel/pull/1664 [#1665]: https://github.com/sopel-irc/sopel/pull/1665 [#1666]: https://github.com/sopel-irc/sopel/pull/1666 [#1668]: https://github.com/sopel-irc/sopel/pull/1668 [#1669]: https://github.com/sopel-irc/sopel/pull/1669 [#1670]: https://github.com/sopel-irc/sopel/pull/1670 [#1671]: https://github.com/sopel-irc/sopel/pull/1671 [#1672]: https://github.com/sopel-irc/sopel/pull/1672 [#1673]: https://github.com/sopel-irc/sopel/pull/1673 [#1674]: https://github.com/sopel-irc/sopel/pull/1674 [#1675]: https://github.com/sopel-irc/sopel/pull/1675 [#1677]: https://github.com/sopel-irc/sopel/pull/1677 [#1678]: https://github.com/sopel-irc/sopel/pull/1678 [#1679]: https://github.com/sopel-irc/sopel/pull/1679 [#1680]: https://github.com/sopel-irc/sopel/pull/1680 [#1681]: https://github.com/sopel-irc/sopel/pull/1681 [#1684]: https://github.com/sopel-irc/sopel/pull/1684 [#1685]: https://github.com/sopel-irc/sopel/pull/1685 [#1690]: https://github.com/sopel-irc/sopel/pull/1690 [#1693]: https://github.com/sopel-irc/sopel/pull/1693 [#1694]: https://github.com/sopel-irc/sopel/pull/1694 [#1696]: https://github.com/sopel-irc/sopel/pull/1696 [#1697]: https://github.com/sopel-irc/sopel/pull/1697 [#1699]: https://github.com/sopel-irc/sopel/pull/1699 [#1700]: https://github.com/sopel-irc/sopel/pull/1700 [#1701]: https://github.com/sopel-irc/sopel/pull/1701 [#1702]: https://github.com/sopel-irc/sopel/pull/1702 [#1703]: https://github.com/sopel-irc/sopel/pull/1703 [#1706]: https://github.com/sopel-irc/sopel/pull/1706 [#1707]: https://github.com/sopel-irc/sopel/pull/1707 [#1708]: https://github.com/sopel-irc/sopel/pull/1708 [#1709]: https://github.com/sopel-irc/sopel/pull/1709 [#1710]: https://github.com/sopel-irc/sopel/pull/1710 [#1711]: https://github.com/sopel-irc/sopel/pull/1711 [#1712]: https://github.com/sopel-irc/sopel/pull/1712 [#1713]: https://github.com/sopel-irc/sopel/pull/1713 [#1714]: https://github.com/sopel-irc/sopel/pull/1714 [#1715]: https://github.com/sopel-irc/sopel/pull/1715 [#1716]: https://github.com/sopel-irc/sopel/pull/1716 [#1717]: https://github.com/sopel-irc/sopel/pull/1717 [#1718]: https://github.com/sopel-irc/sopel/pull/1718 [#1719]: https://github.com/sopel-irc/sopel/pull/1719 [#1720]: https://github.com/sopel-irc/sopel/pull/1720 [#1721]: https://github.com/sopel-irc/sopel/pull/1721 [#1722]: https://github.com/sopel-irc/sopel/pull/1722 [#1723]: https://github.com/sopel-irc/sopel/pull/1723 [#1724]: https://github.com/sopel-irc/sopel/pull/1724 [#1725]: https://github.com/sopel-irc/sopel/pull/1725 [#1727]: https://github.com/sopel-irc/sopel/pull/1727 [#1728]: https://github.com/sopel-irc/sopel/pull/1728 [#1729]: https://github.com/sopel-irc/sopel/pull/1729 [#1730]: https://github.com/sopel-irc/sopel/pull/1730 [#1731]: https://github.com/sopel-irc/sopel/pull/1731 [#1732]: https://github.com/sopel-irc/sopel/pull/1732 [#1733]: https://github.com/sopel-irc/sopel/pull/1733 [#1734]: https://github.com/sopel-irc/sopel/pull/1734 [#1735]: https://github.com/sopel-irc/sopel/pull/1735 [#1736]: https://github.com/sopel-irc/sopel/pull/1736 [#1737]: https://github.com/sopel-irc/sopel/pull/1737 [#1738]: https://github.com/sopel-irc/sopel/issues/1738 [#1739]: https://github.com/sopel-irc/sopel/pull/1739 [#1740]: https://github.com/sopel-irc/sopel/pull/1740 [#1741]: https://github.com/sopel-irc/sopel/pull/1741 [#1742]: https://github.com/sopel-irc/sopel/pull/1742 [#1743]: https://github.com/sopel-irc/sopel/pull/1743 [#1744]: https://github.com/sopel-irc/sopel/pull/1744 [#1747]: https://github.com/sopel-irc/sopel/pull/1747 [#1749]: https://github.com/sopel-irc/sopel/pull/1749 [#1750]: https://github.com/sopel-irc/sopel/pull/1750 [#1751]: https://github.com/sopel-irc/sopel/pull/1751 [#1753]: https://github.com/sopel-irc/sopel/pull/1753 [#1754]: https://github.com/sopel-irc/sopel/pull/1754 [#1755]: https://github.com/sopel-irc/sopel/pull/1755 [#1756]: https://github.com/sopel-irc/sopel/pull/1756 [#1758]: https://github.com/sopel-irc/sopel/pull/1758 [#1759]: https://github.com/sopel-irc/sopel/pull/1759 [#1760]: https://github.com/sopel-irc/sopel/pull/1760 [#1762]: https://github.com/sopel-irc/sopel/pull/1762 [#1766]: https://github.com/sopel-irc/sopel/pull/1766 [#1769]: https://github.com/sopel-irc/sopel/pull/1769 [#1770]: https://github.com/sopel-irc/sopel/pull/1770 [#1771]: https://github.com/sopel-irc/sopel/pull/1771 [#1772]: https://github.com/sopel-irc/sopel/pull/1772 [#1773]: https://github.com/sopel-irc/sopel/pull/1773 [#1774]: https://github.com/sopel-irc/sopel/pull/1774 [#1775]: https://github.com/sopel-irc/sopel/pull/1775 [#1776]: https://github.com/sopel-irc/sopel/pull/1776 [#1777]: https://github.com/sopel-irc/sopel/pull/1777 [#1778]: https://github.com/sopel-irc/sopel/pull/1778 [#1779]: https://github.com/sopel-irc/sopel/pull/1779 [#1781]: https://github.com/sopel-irc/sopel/pull/1781 [#1782]: https://github.com/sopel-irc/sopel/pull/1782 [#1783]: https://github.com/sopel-irc/sopel/pull/1783 [#1787]: https://github.com/sopel-irc/sopel/pull/1787 [#1788]: https://github.com/sopel-irc/sopel/pull/1788 [#1791]: https://github.com/sopel-irc/sopel/pull/1791 [#1795]: https://github.com/sopel-irc/sopel/pull/1795 [#1797]: https://github.com/sopel-irc/sopel/pull/1797 [#1800]: https://github.com/sopel-irc/sopel/pull/1800 [#1802]: https://github.com/sopel-irc/sopel/pull/1802 [#1806]: https://github.com/sopel-irc/sopel/pull/1806 [#1807]: https://github.com/sopel-irc/sopel/pull/1807 [#1808]: https://github.com/sopel-irc/sopel/pull/1808 [#1811]: https://github.com/sopel-irc/sopel/pull/1811 [#1813]: https://github.com/sopel-irc/sopel/pull/1813 [api-docs]: https://sopel.chat/docs/ [auth-config-docs]: https://sopel.chat/docs/configure.html#authentication [db-config-docs]: https://sopel.chat/docs/configuration.html#database [docs-cli-config]: https://sopel.chat/docs/cli.html#the-sopel-config-command [docs-cli-plugins]: https://sopel.chat/docs/cli.html#the-sopel-plugins-command [docs-isupport]: https://sopel.chat/docs/irc.html#module-sopel.irc.isupport [docs-listattr]: https://sopel.chat/docs/config.html#sopel.config.types.ListAttribute [docs-myinfo]: https://sopel.chat/docs/irc.html#sopel.irc.utils.MyInfo [entry-point-plugin]: https://sopel.chat/docs/plugin.html#sopel.plugins.handlers.EntryPointPlugin [logging-config-docs]: https://sopel.chat/docs/configure.html#logging [per-channel-conf]: https://sopel.chat/usage/per-channel-configuration/ [readme-db]: https://github.com/sopel-irc/sopel/blob/v7.0.0/README.rst#database-support [sopel-7-migration]: https://sopel.chat/usage/installing/upgrading-to-sopel-7/ [oblique]: https://github.com/sopel-irc/oblique [ipython-pypi]: https://pypi.org/project/sopel-ipython/ [spellcheck-pypi]: https://pypi.org/project/sopel-spellcheck/ [RFC 2812]: https://tools.ietf.org/html/rfc2812 Changes between 6.6.8 and 6.6.9 =============================== Module changes -------------- * Also block changing `core.owner_account` setting in `admin` plugin [[#1599][]] * Fixed `instagram` parsing after changes to the website [[#1608][]] * `tld` plugin decodes HTML entities before output [[#1612][]] * Handle an error condition when querying `ip` module using nickname [[#1631][]] Core changes ------------ * Fixed populating `user` & `host` in the bot's user database when `NAMES` reply arrives first [[#1630][]] [#1599]: https://github.com/sopel-irc/sopel/pull/1599 [#1608]: https://github.com/sopel-irc/sopel/pull/1608 [#1612]: https://github.com/sopel-irc/sopel/pull/1612 [#1630]: https://github.com/sopel-irc/sopel/pull/1630 [#1631]: https://github.com/sopel-irc/sopel/pull/1631 Changes between 6.6.7 and 6.6.8 =============================== Module changes -------------- * `admin` module no longer allows setting `core.owner` value [[#1587][]] * Allowing any bot admin to change the owner opened Sopel to a privilege-escalation attack * Even with this patch, you still should add only users you really trust to the `admins` list, for obvious reasons API changes ----------- * Fixed some content & formatting errors in documentation [[#1589][]] [#1587]: https://github.com/sopel-irc/sopel/pull/1587 [#1589]: https://github.com/sopel-irc/sopel/pull/1589 Changes between 6.6.6 and 6.6.7 =============================== Fixing this bug, which was discovered after the previous release, serves to exorcise the curse brought upon us by version 6.6.6. Core changes ------------ * Fixed incorrect `MODE` message parsing that could lead to Sopel thinking some users had higher channel privileges than they did [[#1575][]] [#1575]: https://github.com/sopel-irc/sopel/pull/1575 Changes between 6.6.5 and 6.6.6 =============================== This slightly cursed version of Sopel is brought to you by the following happy coincidences. When this release cycle began: * 6.6.6 was the next patch version number * Tax Day (in the U.S.) was just a few weeks off — the perfect release date As it happens, the [v6.6.6 GitHub milestone][ms-666] ended up with 13 closed issues/PRs in total. We *definitely* didn't try to *plan* any of this. Promise. [ms-666]: https://github.com/sopel-irc/sopel/milestone/21?closed=1 Module changes -------------- * Potential denial-of-service via repeated long output in the `.py` and `.calc` commands was mitigated [[#1552][]] * `admin` module's `.set` command no longer throws an exception if missing arguments [[#1520][]] * Fixed `admin` module's `.mode` command sending invalid raw line [[#1549][]] * Tweaked output-formatting code in the `meetbot` & `reddit` modules [[#1516][]] * The most visible effect of this is that moderators' names will now appear green in `reddit`'s output, like on the site, instead of the old brown/purple * Updated example/test output for `.ip` command [[#1523][]] Core changes ------------ * Flood protection delay is now capped at 2 seconds [[#1552][]] * The flood delay penalty is calculated using the message length before truncation. Very long command output could thus "hang" the bot for many minutes at a time, meaning some modules could be used to DoS the bot. * Sopel 7 will add configuration for flood protection and perhaps reorganize the logic to reduce silly bugs like this. (See: [#1518][], [#1559][]) * Fixed a few cases where keyboard interrupt (Control + C) wasn't handled correctly [[#1534][], [#1558][]] * Fixed invalid `MODE` command sent during connection phase [[#1544][]] API changes ----------- * Fixed a regression in testing modules by running them directly [[#1529][]] * Fixed that `bot` output methods (`say`, `reply`, etc.) would cause errors during tests if passed certain keyword arguments [[#1538][]] [#1516]: https://github.com/sopel-irc/sopel/pull/1516 [#1518]: https://github.com/sopel-irc/sopel/pull/1518 [#1520]: https://github.com/sopel-irc/sopel/pull/1520 [#1523]: https://github.com/sopel-irc/sopel/pull/1523 [#1529]: https://github.com/sopel-irc/sopel/pull/1529 [#1534]: https://github.com/sopel-irc/sopel/pull/1534 [#1538]: https://github.com/sopel-irc/sopel/pull/1538 [#1544]: https://github.com/sopel-irc/sopel/pull/1544 [#1549]: https://github.com/sopel-irc/sopel/pull/1549 [#1552]: https://github.com/sopel-irc/sopel/pull/1552 [#1558]: https://github.com/sopel-irc/sopel/pull/1558 [#1559]: https://github.com/sopel-irc/sopel/issues/1559 Changes between 6.6.4 and 6.6.5 =============================== Module changes -------------- * Fixed url module not cleaning punctuation when auto-titling [[#1515][]] * Fixed url module's punctuation-cleaning on Python 2 [[#1517][]] * Fixed `.redditor` command with newer `praw` versions (4.0+) [[#1506][]] * Reloading modules now runs their `shutdown()` routines [[#1412][]] [#1412]: https://github.com/sopel-irc/sopel/pull/1412 [#1506]: https://github.com/sopel-irc/sopel/pull/1506 [#1515]: https://github.com/sopel-irc/sopel/pull/1515 [#1517]: https://github.com/sopel-irc/sopel/pull/1517 Changes between 6.6.3 and 6.6.4 =============================== Module changes -------------- * Replaced `help` pastebin with `clbin.com` * `ptpb.pw` shut down due to abuse — see [ptpb/pb#246]( https://github.com/ptpb/pb/issues/246) for more * More news on this front (reducing Sopel's dependence on specific pastebins) in a future release. Several ideas are under consideration. * Cleaned up code in `instagram` and `unicode` modules * Core modules now use `bot.channels` instead of deprecated `bot.privileges` Core changes ------------ * Privilege tracking now always updates both `bot.channels` & `bot.privileges`, where before some handlers only updated one or the other * This *should* have zero effect on behavior, but do report any observed. Changes between 6.6.2 and 6.6.3 =============================== Module changes -------------- * Fixed loading etymology module on Python 3.3 * Added Unicode support to calc module's `.py` output * Correctly quote URL parameters in etymology and search modules Core changes ------------ * Added docstrings to the privilege level constants in `sopel.module` Changes between 6.6.1 and 6.6.2 =============================== Module changes -------------- * wiktionary tries harder to get a valid result before erroring out Core changes ------------ * Fixed an inconsistency between interpretations of the `--config` option in normal operation vs. wizard mode * Requirement specifiers tightened up to reduce/prevent `pip` trying to install incompatible dependency versions (`IPython`, `dnspython`) * SASL token is now split when required according to spec * Multi-byte Unicode characters are now handled correctly when splitting lines Changes between 6.6.0 and 6.6.1 =============================== Module changes -------------- * spellcheck's `pyenchant` dependency is no longer required for py3.7+ * This should alleviate a lot of installation problems due to `pyenchant` being unmaintained. If use of the spellcheck module is desired, the necessary libraries may be installed manually. Changes between 6.5.3 and 6.6.0 =============================== Sopel 6.6.0 has been a long time coming, but it contains a metric ton of fixes and enhancements. The big stuff is yet to come in Sopel 7, though; stay tuned! (You can get some hints by browsing the [GitHub milestones][].) View and contribute toward Sopel's budgetary needs by visiting the project's new [Open Collective page](https://opencollective.com/sopel). Now that Sopel 6.6.0 is released, the focus will shift from preparing the new release to migrating the website and documentation off of Embolalia's personal infrastructure. Once this migration is complete, Sopel's [documentation][docs] will be updated to reflect the changes/additions listed below. Questions about the new (and old) API methods are welcome in [#sopel][] on Libera Chat, of course, as always. Thank you for bearing with this transitional period! Importantly, a couple of broken modules have been removed in this release. For easy reference, they and their PyPI-installable replacements are listed near the top of the "[Module changes](#module-changes)" section. Because this is the last release planned before Sopel 7, it's important to note some upcoming changes. They're mostly for module developers, or for bot owners who run unmaintained third-party modules (which might need manual updating). But first, a user-facing change. Sopel is drifting toward a more streamlined release model, which will see most of the core module library split out into separate packages. Moving modules to their own packages will enable faster fixes when APIs change, and easier module adoption by members of the community. Further process details will appear in future changelogs as modules are moved out of core, but the plan is to have Sopel "require" modules it used to include for a release or two after their removal. Existing installations should thereby have a smooth transition, as long as they get updated reasonably often. To discuss this plan, visit issue [#1291][]. And now, for the developer stuff. There will be some attention given to how `Identifier` objects work in Sopel 7. In particular, the way lowercase works appears to have been wrong for some time. Subscribe to issue [#1389][] for updates, or to join the discussion on the best plan for addressing this. Also in Sopel 7, the following deprecated functions in `sopel.web` will be removed: `get()`, `head()`, `post()`, `get_urllib_object()`. Module authors should replace these with equivalent code using `requests`. If you don't know what that is, you're in for a treat: Remaining `sopel.web` functions might also move in a future major release. See [#1318][] and comment your opinion if you are a module developer. There is still plenty of time to give feedback; nothing will happen before Sopel 8 at the earliest. Support for multiple help examples on each module command is planned for Sopel 7 and will allow for clearer command and argument documentation. The current help system uses a deterministic but unintuitive method to choose a single example to output. The current plan is to make the new multi-example behavior opt-in, so only help for modules that are explicitly updated to support it will change. Follow this initiative in [#1200][]. Bot owners and admins might appreciate the new ignore system proposal, which would (among other things) make "hostmask" blocks actually block hostmasks! See [#1355][] to participate in the design process; this change is tentatively planned for Sopel 7 but may be pushed back. And finally, for users who hate SQLite with a passion: Work on bringing back alternate DB support has begun! It's unclear how soon this will be ready, but users who want to switch off SQLite to another database engine might be able to do so as early as Sopel 7. Follow the ups and downs of this long-awaited journey at [#1446][] for the time being. [docs]: https://sopel.chat/docs/ [#sopel]: irc://irc.libera.chat/sopel [GitHub milestones]: https://github.com/sopel-irc/sopel/milestones [#1200]: https://github.com/sopel-irc/sopel/issues/1200 [#1291]: https://github.com/sopel-irc/sopel/issues/1291 [#1318]: https://github.com/sopel-irc/sopel/issues/1318 [#1355]: https://github.com/sopel-irc/sopel/issues/1355 [#1389]: https://github.com/sopel-irc/sopel/issues/1389 [#1446]: https://github.com/sopel-irc/sopel/pull/1446 ---- Module changes -------------- * Added emoticons module: includes `.shrug`, `.tableflip`, `.lenny`, and other common kaomoji * Added instagram module: displays information about Instagram links in chat * Removed movie: The OMDb API went private some time ago (Q2 2017) * See [`sopel-modules.imdb`][pypi-imdb] on PyPI for a functional replacement * Removed weather: Yahoo deprecated its weather service, the last known keyless weather API * See [`sopel-modules.weather`][pypi-weather] on PyPI for a functional replacement that also adds the forecast command originally planned to launch with Sopel 6.6.0. * admin module's `.set` command handles spaces properly now * bugzilla no longer spits out an error on shutdown if its domain list is empty * dice module's `.roll`/`.dice`/`.d` command gives friendlier errors, and its `.choice`/`.choose`/`.ch` command has cleaner output (will be further improved in a later release) * etymology module updated to work with etymonline.com's changes * ip module can now look up nicknames (user's hostname) & IPv6 addresses * ip module switched from deprecated GeoIP database to GeoIP2 * isup module can be forced to ignore untrusted/broken HTTPS with a new command alias, `.isupinsecure` * lmgtfy module gained improved output URLs (HTTPS, encoded query) and help examples * reddit module now picks up links under all commonly used subdomains * reload's habit of duplicating packaged modules' command output has been significantly curtailed * There are still some edge cases (like reloading a module with a removed function) that might still cause problems, but the majority of module updates should be OK now. * This feature will continue to improve over the next few releases. * search module should behave better when encountering Unicode in URLs on py2 * search now warns `.ddg`/`.g` users of a bug affecting multiple "site:" operators in a single query * This is a bug in DuckDuckGo's plain-HTML SERP, and they have ignored all attempts to report it. Sopel's DuckDuckGo code might be rewritten to use an unaffected interface in the future. * tld module gracefully handles missing arguments now * translate now handles API failures gracefully * url module can now create a short URL for convenience when fetching title * only URLs longer than configured minimum length * off by default * url module will say an error if `.title` command fails * url module's URL finder will ignore suspicious trailing punctuation, making the auto-title feature more reliable when links are included in sentences * version module no longer prints "wat" to the console/log when answering CTCP `VERSION` requests * wiktionary module now decodes HTML entities in its output before sending, and it should also now give correct results for affixes & definitions containing reference tags * xkcd fetching by comic title should work again (switched back-end search provider) * Many modules updated to use HTTPS in both API calls and output [pypi-imdb]: https://pypi.org/project/sopel-modules.imdb/ [pypi-weather]: https://pypi.org/project/sopel-modules.weather/ Core changes ------------ * Added `userserv` option for `auth_method` * Added default value of `'UTC'` to `default_timezone` * Added `alias_nicks` option * Lets Sopel respond to (a) nickname(s) other than the name it uses for its IRC nick * Made handling `CNAME`'d TLS hostnames more forgiving * Raw logging is no longer enabled by default * Comparisons between Identifiers and other types were improved * Sopel no longer sends the sticky modifier for capabilities * Database tables are now created using "IF NOT EXISTS" to reduce error potential * Deprecated `sopel.web` calls in various modules updated to use `requests` instead * Intents/CTCP handling fixed * Fixed more cases where module shutdown routines weren't running API changes ----------- * New formatting methods: `italic`, `strikethrough`, `monospace`, `hex_color`, `reverse` (inverted video) * With the exception of italics, these are all "niche" formatting codes that have relatively limited client support, but they are included for completeness. * `sopel.db.get_uri()` was returning an incorrectly formatted result, now fixed * Fixed populating `bot.channels` privileges dicts on connect * Fixed updating `User` objects when receiving `NICK` events from the server * Documentation added/corrected in several places * Command prefix in examples is now assumed to match the default regex pattern (currently `\.`) * This fixes some issues with incorrect help output, but might cause new problems in modules that use non-standard prefixes in their examples. * Sopel's maintenance team regrets not providing advance warning of this change, but the potential impact is limited to perhaps a few misplaced characters in help output, at most—same as the bug itself, but likely with a much lower incidence. Changes between 6.5.2 and 6.5.3 =============================== Module changes -------------- * tell module takes nicknames up to 30 characters long now (previously 20) * reddit module (and Sopel, by extension) once again accepts any installed version of PRAW Core changes ------------ * Specified which `IPython` versions pip should give Sopel depending on Python version in use * Fixed trying to use `pytest` stuff in production * Various testing tweaks Changes between 6.5.1 and 6.5.2 =============================== Larger than the usual "patch" release because it's been so long since the last version and a number of bugs crept in. New maintainer (dgw) says hi. To reduce the "dependency hell" of installing things that Sopel doesn't need unless specific modules are used, the `spellcheck` and `ipython` modules will likely be removed from core and published separately in a future release (tentatively, Sopel 7). ---- Module changes -------------- * Added (restored) `.bing` command to search module, and fixed Bing results * Updated DDG ad filtering, and converted query URLs in search module to HTTPS * Fixed search module `.suggest` command using Google suggestions API * Fixed reddit and updated PRAW version requirement * reload module no longer tries to reload nonexistent modules when passed the name of a system package (e.g. "time" or "re") * remind module will now give the reminder time in the correct timezone when using `.at` * wikipedia module ignores `File:` namespace links, and output from other Sopel bots' wikipedia modules * Fixed retrieving xkcd comics by number * Fixed currency module (updated API URLs) * Tweaked url module's title finder to reduce garbage from Gawker/Kinja sites * help module now filters out duplicate commands from its command list * Fixed wikipedia module's handling of special characters like `&` * Prevent wikipedia module spewing an error if someone posts a link to an article that doesn't exist * help module now sends the command list to ptpb.pw, as GitHub removed their anonymous Gist API * Switched calc module to use new backend service for `.py` command, to reduce outages * Added physical temperature limit to units module * Tweaked argument handling in pronouns module Core changes ------------ * Logger bug squashed * Shutdown method handling fixed * Added documentation in a few places * Made finding the system SSL/TLS certificate trust store more robust * Modules with example tests no longer need to hack around `pytest` running their `setup()` routines * Corrected `IPython` dependency for ipython module (now installs with Sopel automatically) * Widened acceptable `requests` version range API changes ----------- * Module `shutdown()` methods should fire correctly now * `ListAttribute` config values now return `[]` (empty list) when blank instead of `[""]` (empty string in list) * Updated documentation for (still deprecated) `sopel.web` (the documentation for `post()` included a nonexistent kwarg, `headers`) Changes between 6.5.0 and 6.5.1 =============================== Module changes -------------- * A module to track users' pronouns is added * A few bug and regression fixes Changes between 6.4.0 and 6.5.0 =============================== Module changes -------------- * xkcd module can now recognize xkcd.com urls * SSL is verified for HTTP requests when not turned off in the config * The command list is placed in a gist, to prevent flooding * Title finding uses a custom user-agent, to prevent issues with some sites Core changes ------------ * Intent handling is improved API changes ----------- * A `@url` decorator is added to simplify URL handling Changes between 6.3.1 and 6.4.0 =============================== Module changes -------------- * For some subreddits where NSFW is used to mark spoilers, an appropriate tag is shown. * `.ddg` avoids giving ad results. * `.wa` is fully removed * See [`sopel-modules.wolfram`][pypi-wolfram] on PyPI for a replacement [pypi-wolfram]: https://pypi.org/project/sopel-modules.wolfram/ Core changes ------------ * Support for authenticating with Quakenet's Q is added. * Errors from empty PID files are fixed. * Issues with errors not being logged to the logging channel are fixed. * Topic tracking is improved * `extended-join` is supported properly * Error messages being reported to the triggering channel/user can be disabled. API changes ----------- * Channel privileges are no longer checked in private messages. * Rate limiting can now be done by channel and globally, not just per user. Changes between 6.3.0 and 6.3.1 =============================== Module changes -------------- * The xkcd module is working again * Fix an issue causing Unicode errors to show for some URLs when using Python 2 (but you should really switch to 3!) Core changes ------------ * Fix a bug in QUIT message parsing which caused certain users to be flooded with PMs if their nick matched the first word of a user's QUIT message (such as "disconnected" or "ping") * Fix a rare Python 3 incompatibility bug when quitting due to too many core errors * We no longer show a warning when detecting a non-Unicode system locale if you're still using Python 2 Changes between 6.2.0 and 6.3.0 =============================== Module changes -------------- * Many modules ported to use `requests` package for stability and security * Weather location lookup is fixed * Confusing and unnecessary commands like .op were removed * Splitting of options in `.choice` is now more intuitive * Some edge cases in reddit post information were fixed Core changes ------------ * A check is added to warn about an obscure environment issue that can cause strange errors * Regex characters in the bot's nick no longer cause issues when a rule has the nickname added * Rate limiting is tweaked slightly, which should reduce the severity of the `.commands` flood bug until a proper solution is found API changes ----------- * The current topic of a channel is now available as the `Channel` object's `topic` attribute * `sopel.web` has been reworked as a wrapper around requests; it remains deprecated Changes between 6.1.1 and 6.2.0 =============================== Module changes -------------- * An error in excluding URLs from title display is fixed * Case sensitivity issues in currency and dice commands are fixed * Guards to require channel or private message are added to a number of commands, to avoid confusing errors * A calculation bug in the countdown command is fixed * Misc. minor bugfixes and improvements Core changes ------------ * An occasional error with SSL connections on Python 3 is fixed * On servers which support IRCv3 account extensions, the services account name can be used to authenticate the owner * Numerous additional IRCv3 features are supported API changes ----------- * `bot.privileges` is now deprecated in favor of `bot.channels` * `bot.channels` contains more information about the channels the bot is in * `bot.users` is now available with information about the users Sopel is aware of * `sopel.web` is now deprecated in favor of the third-party `requests` library * `trigger.time` is added with the current time, or server-time if the server supports it * `sopel.tools.events` is now available as an enum of IRC numeric replies Changes between 6.1.0 and 6.1.1 =============================== If you are updating from a pre-6.0 version (i.e. Willie), there are backwards- incompatible changes which you should be aware of. See for more information. ---- Core changes ------------ * A regression which caused the config wizard to be unusable is fixed Changes between 6.0.0 and 6.1.0 =============================== If you are updating from a pre-6.0 version (i.e. Willie), there are backwards- incompatible changes which you should be aware of. See for more information. ---- Module changes -------------- * A regression which prevented the URL safety detection from working is fixed. * Issues with some special characters in DuckDuckGo searches are fixed * `lxml` is no longer required by any modules, greatly simplifying the install process * Misc. minor bugfixes and improvements Core changes ------------ * A regression which disabled blocking functionality is fixed * Examples are no longer mangled by the `.help` command, and show the correct prefix * The listing from `.commands` is now separated by module * Issues with reloading folder modules are fixed API changes ----------- * `ListAttribute` configs can be set to a list or set, with the same effect * The configure method of validated config attributes now takes the parent config and section name Changes between 5.5.1 and 6.0.0 =============================== This release contains backwards-incompatible changes. See for more information. This is the first release in which the bot will have a new name. Current tentative name is Sopel. ---- Module changes -------------- * chanlogs, rss, github, and radio modules are removed * Default in admin module is now to join on invite from anyone; the old default of only joining on invite from admins can be configured * Wikipedia module's per-channel default language configuration is deprecated; a database-backed option will be added in a future version * `.seen` replies on action messages now display action messages differently * `.kick` no longer truncates the message, and `.kickban` works properly Core changes ------------ * Deprecated login configs have been removed in favor of the new `auth_*` values * Module reloading has been redone to enable modules to be installed from PyPI * IRCv3 capability negotiation is updated for v3.2 API changes ----------- * Configuration has been entirely reworked. Old wizard functions and the `get_list()` function are removed, but most other uses of the config should continue to work. * The reorganization of `willie.tools` introduced in 5.3.0 is finalized; the old import locations no longer work. * `bot.msg` is deprecated in favor of `bot.say`, which can now be used in un-triggered contexts with an additional `recipient` argument Changes between 5.5.0 and 5.5.1 =============================== This release continues preparations for Willie 6. See ---- Module changes -------------- * The URL safety module correctly checks URLs * The URL for the service used for `.py` and `.wa` is updated Changes between 5.4.1 and 5.5.0 =============================== This release starts preparations for Willie 6. See ---- API changes ----------- * The ability to import from the `sopel` package, rather than `willie`, is added to enable forward compatibility with the rename in 6.0 * A `version_info` tuple, similar to Python's own `sys.version_info`, is added * An error when setting a validated config attribute to `None` is fixed Changes between 5.4.0 and 5.4.1 =============================== This release starts preparations for Willie 6. See ---- Core changes ------------ * Regression which prevented SSL verification from being disabled is fixed Changes between 5.3.0 and 5.4.0 =============================== This release starts preparations for Willie 6. See ---- Module changes -------------- * Dropping the lowest results from `.dice` rolls works properly * `.blocks` listing is now on one line * HTML entities in reddit post titles are now displayed correctly Core changes ------------ * DB nick group merging now works properly * A few combinations of authentication configuration that were broken are fixed API changes ----------- * The core config section now uses a 6.0-style config definition. Deprecated attributes will give a warning. * Accessing core config values directly from the `config` object itself (rather than `config.core`) now appropriately prints a warning * `@require_chanmsg` now works properly Changes between 5.2.0 and 5.3.0 =============================== Module changes -------------- * The YouTube module is removed due to breakage of its API by Google * Fixes for Unicode in channel logging * `.py` hits an updated service running Python 2.7, rather than 2.5 * Multiple new features are added in the reddit module * Wind direction arrows in weather now point the right way API changes ----------- * Time and calculation tools are split out into multiple modules. The moved things will also be available in `tools` itself until 6.0, whereupon they will only be available in their new locations. * Functions and classes used internally for scheduling jobs are moved. They are still available in their old location, but are no longer documented and will not be considered part of the public API in 6.0. Changes between 5.1.1 and 5.2.0 =============================== Module changes -------------- * An exception that failed the chanlogs module from loading is fixed * Meetbot meeting subjects no longer fail with Unicode Core changes ------------ * The various ways of authenticating the bot are now configured using the same set of attributes. The old settings will be used as fallback until 6.0.0. API changes ----------- * Privilege decorators no longer cause an error when no message is given * A new `@intent` decorator is added as a shortcut for triggering on a message with an intent Changes between 5.0.0 and 5.1.1 =============================== Module changes -------------- * Fixed a regression that caused getting weather for a nick to fail * Bugs related to channel log filenames are fixed * Channel logs can now use the bot's preferred time zone * Getter and setter methods for timezone and format are more consistently named * `.seen` persists across bot restarts * `.seen` no longer shows message or channel unless used within the same channel * Special characters in Wikipedia URLs are handled correctly Core changes ------------ * `help_prefix` can now be given in `[core]` to change the command prefix used in help API changes ----------- * The `Trigger` object is now immutable, as expected * New decorators for checking privileges on callables are added Changes between 4.6.2 and 5.0.0 =============================== This release contains backwards-incompatible changes. See for more information. ---- Module changes -------------- * YouTube no longer shows bizarre lengths when the bot is running under Python 3 * When Wikipedia links are posted, a snippet of the article is shown Core changes ------------ * `WillieDB` is entirely rewritten, meaning migration will be needed to access old data * Logging output to the debug channel is improved * The name of the NickServ user can be configured with `nickserv_name` in `[core]` * SSL is disabled on Python 2.7 when `backports.ssl_match_hostname` is not installed API changes ----------- * Deprecated `WillieDB` functions are removed * CTCP actions are stripped prior to matching, and added to the `'intent'` key of `trigger.tags` * Deprecated `Trigger` functions are removed * `bot.debug` is removed, in favor of standard Python logging * `tools.Nick` is removed, in favor of the `tools.Identifier` introduced in 4.6.0 Changes between 4.6.1 and 4.6.2 =============================== This release starts preparations for Willie 5. See for more information. ---- Module changes -------------- * Due to API deprecation and instability, `.g` now uses DuckDuckGo instead of Google Core changes ------------ * Fix remaining regression in db update function Changes between 4.6.0 and 4.6.1 =============================== This release starts preparations for Willie 5. See for more information. ---- Module changes -------------- * Fix regression in table creations and erroneously changed column names Core changes ------------ * Fix regression in db update function API changes ----------- * Correctly print out deprecation warnings Changes between 4.5.1 and 4.6.0 =============================== This release starts preparations for Willie 5. See for more information. ---- Module changes -------------- * The `^` operator in `.calc` is now equivalent to `**` * `.dice`, `.tr`, and `.addtrace` give meaningful errors when no argument is given * A number of database issues were fixed (more will be fixed in Willie 5) * A number of Python 3-related issues were fixed. * Malicious URLs are now detected with VirusTotal and malwaredomains * `.weather` no longer shows pressure Core changes ------------ * The config wizard no longer configures the database, instead automatically creating a SQLite DB * MySQL and Postgres databases are deprecated; only SQLite will be supported in Willie 5 * Logging channel and level can be configured with `logging_channel` and `logging_level` in the config * A `--version` switch was added to the `willie` command, to show the version in use * Corrupt PID files will no longer prevent the bot from starting * Non-ASCII values no longer crash the config wizard API changes ----------- * Numerous functions were added to the db to ease the transition to Willie 5 * `tools.Nick` has been renamed to `tools.Identifier`. `Nick` will be removed in Willie 5 * `willie.web` functions now specify a meaningful default user agent * `web.post` now supports dicts as the payload, and can optionally return headers * `config.get` was added as an alias to `config.parser.get` * Callables can now handle more than one event by stacking decorators Changes between 4.5.0 and 4.5.1 =============================== Module changes -------------- * Version checking module no longer causes an error at startup * URL handling modules no longer repeat themselves after being reloaded * `.isup` now adds a `.com` TLD if none is used * IPython integration now works with older versions of IPython Changes between 4.4.1 and 4.5.0 =============================== Module changes -------------- * Willie will now alert the owner at startup, and every 24 hours, when a new version is available * `.calc` will now time out on excessively long calculations, and is less likely to error out * `.help` now works properly for command aliases * `.help` will now output multi-line help in multiple messages, rather than all at once * A new `.uptime` command tells how long the bot has been running * `.length` can now handle astronomical units * Absolute vote counts are no longer shown in reddit output * Using `.setlocation` without a location will no longer set your location to Italy * Time units for `.in` are now case-insensitive * `.duck` no longer gives a long, unrelated URL Core changes ------------ * Scheduled tasks now work properly under Python 3 * Willie no longer accepts partial matches for admin status API changes ----------- * Setting attributes on the bot object now works as expected * The status code is now returned from `web.get` as `_http_status` in the headers * `web.get` now attempts to decode based on headers, rather than assuming utf-8 * `web.iri_to_uri` is now available to decode internationalized domain names * A `willie.formatting` module is now available to simplify IRC bold, underline and color formatting Changes between 4.4.0 and 4.4.1 =============================== Module changes -------------- * RSS no longer checks for malformed XML * Starting RSS manually after bot restart is no longer needed * Youtube video search properly handles spaces * The `.at` command defaults to UTC if user's timezone is not set Core changes ------------ * Ping timeout handling is working again * `bind_host` configuration option is working again Changes between 4.3.0 and 4.4.0 =============================== Module changes -------------- * `.cur` behaves better when bad arguments are given * Fixed numerous Unicode errors * Added a command to open an IPython console within the module context * Added mass units and millimeters to .cur * GitHub pull requests now get extended URL info * `.weather` now displays wind in m/s instead of kts * A security issue involving improperly named channel logs was fixed * Misc. bugfixes Core changes ------------ * Channel joins at bot startup can be rate limited with the `throttle_joins` option in the `[core]` config section to work around server limits * Added the ability for SASL login where the nickname and username are different * Improved loop protection and rate limiting * Fixed multiple Python 3 errors * Enable logging the bot in to Authserv at startup * Added support for Postgres as the database backend * SSL cert location detection now works on Debian-based systems * Misc. bugfixes API changes ----------- * Unicode in command decorators now works properly * `web.get` now decodes the result from UTF-8, with a `dont_decode` argument to disable Changes between 4.2.0 and 4.3.0 =============================== Module changes -------------- * A new channel logging module is added * Misc. bugfixes, especially when running with Python 3 Core changes ------------ * Fixed a regression that caused numerous errors in `willie.web` * Misc. bugfixes API changes ----------- * Nick instances now have an `is_nick` attribute, which is `True` when the value is a valid nickname (as opposed to a channel) Changes between 4.1.0 and 4.2.0 =============================== Module changes -------------- * A new `.cur` command can convert a number of currencies, including Bitcoin * `.c` can now understand a comma used as a radix point (rather than a period) * `.w` can now look in the Wikipedia for a specified (or configurable default) language * Timezones are now more user-friendly, and used more consistently across modules * Misc. bugfixes Core changes ------------ * `willie.web` now verifies HTTPS connections properly * The SQLite database file respects use of `~` in the configured filename * Willie can now run in Python 3 * Willie now depends on `python-backports.ssl_match_hostname` (see README.rst for installation instructions) * Misc. bugfixes API changes ----------- * `trigger.is_privmsg` is added for an easy way to see if a trigger was created in a private or channel message * `get_timezone` and `format_time` are added to `tools` to make displaying time according to user/channel format easier * Added `bot.notice` and an optional notice parameter for `bot.reply` for easier sending of IRC `NOTICE` messages Changes between 4.0.1 and 4.1.0 =============================== Module changes -------------- * Admin-only `.set` command can now set non-existent config values * The meetbot `.endmeeting` command now works properly * Significant improvements made to RSS module * The database structure for storing RSS feeds has been modified. The module will attempt to migrate old data. * Command syntax has changed in multiple ways * `.rss` help is now available with more detailed information on usage. * Module is overall better-behaved and less buggy * Traceback can now be attached to a GitHub issue from Willie's logs * GitHub module no longer puts "IRC" tag on issues it creates * A `.listactions` command is added to allow actions to be listed before the end of a meeting * Dice now limits itself to 1000 dice, and output is cleaned up * Willie now joins channels when invited * Reddit module no longer gives an error if the submitter's account has been deleted * A new `.comments` feature allows optional comments on meetings, e.g. from those muted in the channel * `.xkcd` is more robust, and can now access the nth-latest comic * calc module now uses an internal calculator, rather than the discontinued iGoogle calculator Core changes ------------ * Memory lock and unlock no longer cause errors * Debugging target no longer needs to be a channel * Whitespace can now be used in the command prefix * Line numbers are given when modules fail to load * Error messages are more consistent across core and modules * Willie now retries joining channels if it fails initially * SQLite is now the default and recommended database type * MySQL remains supported; support may be dropped in a later version * `MySQLdb` is no longer listed as a recommended dependency * IRCv3 is now largely supported * Willie can now authenticate with SASL API changes ----------- * Modules can now provide a `shutdown()` function to clean up when the bot is quitting or the module is reloading * `web.get` and `web.post` can be told to limit how much they read from a URL, to prevent malicious use * A new `@unblockable` decorator allows callables to be run even when triggered by otherwise blocked users * Willie can now connect over IPv6 * If the channel given to `bot.join` contains a space, the part after the space will be used as the password * IRCv3 is now largely supported * Modules can now request capabilities from the server. * Message tags, if enabled, can be read from `trigger.tags` Changes between 4.0.0 and 4.0.1 =============================== Core changes ------------ * Setup script once again works properly * Message splitting now works properly * Bug fixes in handling of nick and hostmask blocks Changes between 3.2.0 and 4.0.0 =============================== Module changes -------------- * The following modules have been moved to the willie-extras repository: * ai * bucket * fuckingweather * nws * roulette * twit * slap * oblique * The information of the last URL seen in a channel can now be replayed with `.title` * The YouTube module was reworked to use the YouTube JSON API * The IP module is now independent of 3rd party services, and requires a local copy of the (free) GeoLite database. If such database is not installed, Willie will download it automatically. * `.commands` now gives better output (no more truncated output due to message length limit) * Added a unit conversion module * Better handling for non-Unicode page titles in the URL titler * Removed bing support from search * Various minor improvements and bugfixes across all modules Core changes ------------ * Module discovery was reworked. Willie will now try to load additional modules from `~/.willie/modules` by default, if installed. * The home directory, usually `~/.willie`, can now be configured by adding `homedir` under `[core]` * The location of PID files can now be configured by adding `pid_dir` under `[core]` * Willie can now be run as a systemd service * Case sensitivity in nick blocking is fixed * Better handling of ping timeouts (connection problems) * Major code cleanup API changes ----------- * Improved Unicode UTF-8 support across all codepaths * Triggers, and the appropriate attributes thereof, are now `unicode` objects * Decorators were introduced for setting attributes on callables, available in `willie.module` * The `NOLIMIT` return value was moved from the `Willie` class to `willie.module` * Callables with the same name in different modules no longer override each other * `willie.channels` is now properly maintained * trigger.isvoice can now be used to determine if a user has voice privileges * Added the max_messages parameter for `willie.msg()` and `willie.say()`. See documentation for details. * Added interval callable support (see documentation for details) * Numerous minor features, and stability and usability fixes Changes between 3.1.2 and 3.2.0 =============================== * `tools.Nick` class added for RFC-compliant nickname comparison and storage * Returning `willie.NOLIMIT` from a callable ignores the rate limit for that call * `get_list()` added to `ConfigSection`. Will reliably return a list from a config attribute. * A number of bugs regarding admin and operator lists were fixed * Unusual mode changes no longer cause errors * Times shown by `.t`, `.in`, etc. all now use formats set by `.settimeformat` * sed feature can use backslashed slashes in substitutions * Weather module was rewritten, and now uses Yahoo! Weather * Numerous stability and usability fixes