From 728a7697d03afb30f36c12254855c9cefd44005e Mon Sep 17 00:00:00 2001 From: tee Date: Tue, 11 Aug 2026 16:53:52 -0400 Subject: [PATCH] chore(release): v5.61.0 Bundle the changes merged since v5.60.0: - #128 offline 'easycord try' CLI - #129 plugin ergonomics helpers (config mixin, decorator stacks, task/timer managers) - #130 discord_errors() middleware + server_stats store.mutate migration - #131 slash_mod_command moderate_members permission fix Bump version across pyproject/__init__/README/docs and add the CHANGELOG entry. Gates: metadata drift check, ruff (E9,F63,F7,F82), plugin-test floor, and full suite (1865) all pass. --- CHANGELOG.md | 23 +++++++++++++++++++++++ README.md | 6 +++--- docs/getting-started.md | 2 +- easycord/__init__.py | 2 +- pyproject.toml | 6 +++--- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3a7ec..b035e46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ All notable changes to EasyCord are documented here. See [Semantic Versioning](https://semver.org) for version numbering. +## EasyCord v5.61.0 — 2026-08-11 + +### Added + +- **`easycord try ` CLI** — run a registered slash command offline (no token, no network) through the existing `testing.invoke()` harness. Supports `--set key=value` argument coercion, context flags (`--user` / `--guild` / `--dm` / `--no-admin`), and `--json` output. Exits non-zero on an unknown command (listing available names) or when the command raises, so it doubles as a scriptable smoke check (#128) +- **Plugin ergonomics helpers** — opt-in modules for common plugin patterns: `PluginConfigHelper` (a mixin providing atomic `config_get/set/update/delete/mutate/clear`, each routed through `ServerConfigStore.mutate` so writes share the store's single per-guild lock domain); pre-composed decorator stacks (`slash_admin_command`, `slash_management_command`, `slash_mod_command`, `slash_user_command`, `slash_with_confirm`); and `TaskManager` / `TimerManager` lifecycle helpers for tracking and cancelling background tasks and timers (#129) +- **`discord_errors()` middleware** — a central, type-aware complement to `catch_errors()`: catches `discord.Forbidden`, `NotFound`, and `HTTPException` and replies with localized, type-specific ephemeral messages. Register it after `catch_errors()` so it handles Discord errors first while `catch_errors()` remains the generic fallback; non-Discord errors propagate untouched (#130) + +### Changed + +- **`server_stats` config writes** now route through `ServerConfigStore.mutate` instead of a plugin-owned `GuildLockManager` + manual `load`/`save`, consolidating on the store's single lock domain (behavior-preserving) (#130) + +### Fixed + +- **`slash_mod_command` permission name** — required `moderate_members` (the real discord.py timeout permission) instead of the nonexistent `timeout_members`. Because permissions are enforced via `getattr(guild_permissions, name, False)`, the old entry was silently always-false, breaking the intended gate for any command built on the stack (#131) +- **`TaskManager.track` cleanup race** — a task that finished after a replacement was registered under the same name could evict the replacement, leaving it untracked and uncancellable; the done-callback now removes a task only if it is still the one registered under that name (#129) +- **Removed three unused imports** in `_decorator_stacks.py` (`cooldown`, `require_permissions`, `describe`) flagged by CodeQL (#131) + +### Release metadata + +- Wheel: `easycord-5.61.0-py3-none-any.whl` +- Source: `easycord-5.61.0.tar.gz` — `releases/download/v5.61.0/easycord-5.61.0.tar.gz` + ## EasyCord v5.60.0 — 2026-07-25 ### Changed diff --git a/README.md b/README.md index ee55696..611a996 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # EasyCord -![Version](https://img.shields.io/badge/v-5.60.0-blue) +![Version](https://img.shields.io/badge/v-5.61.0-blue) ![Python](https://img.shields.io/badge/python-3.10%2B-blue) ![License](https://img.shields.io/badge/license-MIT-green) ![Tests](https://img.shields.io/badge/tests-1777%2B-brightgreen) @@ -25,7 +25,7 @@ ## Quick Start ```bash -pip install "https://github.com/rolling-codes/EasyCord/releases/download/v5.60.0/easycord-5.60.0-py3-none-any.whl" +pip install "https://github.com/rolling-codes/EasyCord/releases/download/v5.61.0/easycord-5.61.0-py3-none-any.whl" ``` Or scaffold a full project: @@ -304,4 +304,4 @@ Copyright (c) 2026 Rolling Codes. **Docs:** [Getting Started](docs/getting-started.md) · [Built-in Plugins](docs/builtin-plugins.md) · [AI Features](docs/conversation-memory.md) · [All guides →](docs/README.md) -Release: [v5.60.0](https://github.com/rolling-codes/EasyCord/releases/tag/v5.60.0) · [Changelog](CHANGELOG.md) · [GitHub](https://github.com/rolling-codes/EasyCord) +Release: [v5.61.0](https://github.com/rolling-codes/EasyCord/releases/tag/v5.61.0) · [Changelog](CHANGELOG.md) · [GitHub](https://github.com/rolling-codes/EasyCord) diff --git a/docs/getting-started.md b/docs/getting-started.md index 3ae7c82..7312458 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -3,7 +3,7 @@ ## Install ```bash -pip install "https://github.com/rolling-codes/EasyCord/releases/download/v5.60.0/easycord-5.60.0-py3-none-any.whl" +pip install "https://github.com/rolling-codes/EasyCord/releases/download/v5.61.0/easycord-5.61.0-py3-none-any.whl" ``` Or clone and install locally: diff --git a/easycord/__init__.py b/easycord/__init__.py index 1499014..9a001d4 100644 --- a/easycord/__init__.py +++ b/easycord/__init__.py @@ -16,7 +16,7 @@ async def ping(ctx): bot.run("YOUR_TOKEN") """ -__version__ = "5.60.0" +__version__ = "5.61.0" from .audit import AuditLog from .bot import Bot diff --git a/pyproject.toml b/pyproject.toml index 1f3e4ef..de20407 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "easycord" -version = "5.60.0" +version = "5.61.0" description = "Production-grade Discord bot framework with AI orchestration, multi-provider LLMs, and permission-gated tool execution" readme = "README.md" license = "MIT" @@ -48,8 +48,8 @@ Homepage = "https://github.com/rolling-codes/EasyCord" Repository = "https://github.com/rolling-codes/EasyCord" Issues = "https://github.com/rolling-codes/EasyCord/issues" Documentation = "https://github.com/rolling-codes/EasyCord/blob/main/docs/README.md" -Download = "https://github.com/rolling-codes/EasyCord/releases/download/v5.60.0/easycord-5.60.0-py3-none-any.whl" -Release = "https://github.com/rolling-codes/EasyCord/releases/tag/v5.60.0" +Download = "https://github.com/rolling-codes/EasyCord/releases/download/v5.61.0/easycord-5.61.0-py3-none-any.whl" +Release = "https://github.com/rolling-codes/EasyCord/releases/tag/v5.61.0" Changelog = "https://github.com/rolling-codes/EasyCord/blob/main/CHANGELOG.md" "Getting Started" = "https://github.com/rolling-codes/EasyCord/blob/main/docs/getting-started.md" "Task Scheduling" = "https://github.com/rolling-codes/EasyCord/blob/main/docs/task-scheduling.md"