Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Changelog uses v5.61.0 📘 Rule violation ⚙ Maintainability

The new CHANGELOG heading uses v5.61.0, while pyproject.toml and easycord/__init__.py use
5.61.0, so the version string is not exactly consistent across all three locations. This may break
tooling that expects an exact match when parsing release versions.
Agent Prompt
## Issue description
`CHANGELOG.md` uses a `v`-prefixed version (`v5.61.0`) while the canonical version in `pyproject.toml` and `easycord/__init__.py` is `5.61.0`. The compliance rule requires the exact same version string in all three places.

## Issue Context
Current sources:
- `pyproject.toml`: `version = "5.61.0"`
- `easycord/__init__.py`: `__version__ = "5.61.0"`
- `CHANGELOG.md`: `## EasyCord v5.61.0 — 2026-08-11`

## Fix Focus Areas
- CHANGELOG.md[5-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


### Added

- **`easycord try <target> <command>` 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
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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:
Expand Down Expand Up @@ -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)
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion easycord/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
Loading