Skip to content

EasyCord v5.61.1

Latest

Choose a tag to compare

@rolling-codes rolling-codes released this 13 Aug 04:29
· 6 commits to main since this release

EasyCord v5.61.1 is a patch release focused on making the v5.61 developer experience match the documented API, especially around lifecycle hooks, grouped plugins, built-in plugin reliability, and docs accuracy.

What was fixed

Lifecycle hooks now work in real bots

The docs described bot.hooks, before_command, after_command, on_plugin_load, and on_plugin_unload, but the main Bot object did not actually initialize a HookRegistry, and the command/plugin paths did not fire those hooks. This made the documented hook examples fail or silently do nothing.

Fixed by:

  • Creating bot.hooks during Bot initialization.
  • Firing before_command and after_command around slash command callback execution.
  • Firing on_plugin_load and on_plugin_unload during plugin load, late-load, unload, and reload flows.
  • Adding regression tests for command hook order and plugin unload hooks.

SlashGroup plugins behave like normal plugins

Several grouped-plugin paths were incomplete compared with regular Plugin loading. This affected developers building command groups as plugins.

Fixed by:

  • Allowing Bot.load_builtin_plugins() and Bot.add_plugin() to register SlashGroup instances through add_group().
  • Enforcing requires dependencies for grouped plugins and raising PluginDependencyError when dependencies are missing.
  • Firing lifecycle hooks for late-loaded groups.
  • Cleaning cooldown registry entries for nested group commands on unload so hot reloads do not leave stale callbacks or plugin state behind.

Mixin-decorated plugin commands are discovered again

Plain Python mixins with decorated methods were not reliably discovered during plugin scanning. That broke a useful composition pattern for sharing commands, events, components, modals, and subscriptions across plugins.

Fixed by walking the plugin class MRO in source-definition order while skipping only object, then registering decorated methods from mixins as expected.

Plugin @slash(...) matches the direct bot API more closely

The plugin decorator accepted fewer options than Bot.slash(...), so moving a command into a plugin could silently drop metadata.

Fixed by adding support for:

  • nsfw
  • allowed_contexts
  • allowed_installs

Those values now propagate through the existing command metadata scanner.

Built-in plugin reliability fixes

Fixed several concrete runtime bugs in bundled plugins:

  • TagsPlugin now registers as the documented /tag slash-command group.
  • Tag responses disable mentions with discord.AllowedMentions.none(), preventing stored tag content from pinging users, roles, @everyone, or @here.
  • TicketsPlugin.ticket_open() no longer crashes if the ticket panel message cannot be sent. It now skips persistent view registration when no message ID exists.
  • LevelsPlugin invalidates its config cache after rank and role-reward config changes, so updates apply immediately instead of waiting for the cache TTL.
  • ConfigHelpers.update_atomic() now routes through ServerConfigStore.mutate() instead of a separate load/save sequence, avoiding lost concurrent writes.
  • Optional JuiceWRLD external-service imports are treated as optional by Pyright rather than blocking release type checks.

Documentation and examples now match the shipped API

The docs sweep corrected user-facing examples that pointed developers at APIs or command names that did not exist in v5.61.

Fixed docs/examples include:

  • README version, release links, install URL, and test count.
  • Built-in plugin command names such as /tag set, /ticket_open, /ticket_close, /rep, /rep_check, /giveaway, /giveaway_end, /filter_add, /autorole_add, and related commands.
  • AI examples now construct providers/orchestrators using the current constructors.
  • database= replaces stale db= snippets where appropriate.
  • Default database docs now describe the current local SQLite default instead of saying the default is memory-only.
  • Event bus docs now state that callbacks run sequentially in registration order, matching implementation.
  • Command sync examples now use plan_command_sync(...) and sync_commands(dry_run=True, ...) instead of the nonexistent preview_sync_commands() helper.
  • Hook unregister examples now use public HookRegistry.unregister() instead of mutating private callback lists.
  • Troubleshooting no longer recommends a nonexistent bot.cache attribute.
  • Type-checking docs import SENDABLE_CHANNEL_TYPES from the supported top-level export.
  • Broken or stale internal doc links were corrected.

Agent review coverage

This release was prepared from multiple read-only agent sweeps plus local integration work:

  • Docs agents checked README, docs, examples, command names, AI snippets, database configuration, hook docs, event bus behavior, and links.
  • DX/runtime agents checked hook wiring, grouped plugin behavior, decorator parity, mixin discovery, built-in plugin ergonomics, and unfinished public API promises.
  • Package/release agents checked version metadata, release asset names, changelog shape, plugin test coverage gates, build output, and release readiness.

Several larger DX ideas from the sweep remain candidates for future releases rather than patch material, including Composer parity for more Bot(...) options, a real remote-fetching sync preview helper, and broader built-in plugin persistence configuration.

Verification

  • python -m pytest -q -> 1871 passed
  • python scripts/check_release_metadata.py -> passed
  • python scripts/verify_plugin_tests.py -> passed
  • ruff check easycord tests --select E9,F63,F7,F82 -> passed
  • pyright easycord/ tests/ -> 0 errors
  • python -m build --no-isolation -> built wheel and sdist
  • python -m twine check dist\* -> passed

Artifacts

  • easycord-5.61.1-py3-none-any.whl
  • easycord-5.61.1.tar.gz

PyPI status

GitHub release publishing succeeded. PyPI upload was attempted, but this machine does not have a Twine API token configured, so the upload stopped with:

ERROR NonInteractive: Credential not found for API token.