Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
612f005
feat(core): add MessageFlags.IsComponentsV2
M1tsumi May 13, 2026
a911a5a
feat(core): add missing permission flags
M1tsumi May 13, 2026
d395601
feat(gateway): add GuildVoiceChannelStatusUpdates intent
M1tsumi May 13, 2026
6e05567
feat(api): add Poll, Attachments, and Status to API models
M1tsumi May 13, 2026
b60faa4
feat(api): implement voice channel status REST endpoints
M1tsumi May 13, 2026
429d539
feat(interactions): add deferred response builder support
M1tsumi May 13, 2026
a41619c
feat(gateway): add voice channel status update support
M1tsumi May 13, 2026
0f94455
fix: improve error handling and logging across modules
M1tsumi May 13, 2026
39ea6cf
fix: resolve critical async, logging, and contract compliance issues
M1tsumi May 14, 2026
ea7bf05
fix: add ConfigureAwait(false) to all Gateway async paths
M1tsumi May 14, 2026
65d53f3
chore: remove temporary fix script
M1tsumi May 14, 2026
a17e03a
fix: add ConfigureAwait(false) to REST, Commands, Interactivity, and …
M1tsumi May 14, 2026
15d1fb3
fix(gateway): remove duplicate OnVoiceChannelStatusUpdate method defi…
M1tsumi May 15, 2026
0ea794a
fix(dave): complete DAVE E2EE implementation for DM/GroupDM voice calls
M1tsumi Jun 15, 2026
233a199
docs: update changelog with DAVE E2EE fix notes in 1.1.0-alpha.3
M1tsumi Jun 15, 2026
d440425
Release 1.1.0-alpha.3 — audit fixes, IDiscordClient interface, assemb…
M1tsumi Jun 15, 2026
368f66e
fix: add GatewayIntents.None and sync version to 1.1.0-alpha.3 across…
M1tsumi Jun 15, 2026
9306586
fix: move InternalsVisibleTo from PropertyGroup to ItemGroup in Voice…
M1tsumi Jun 15, 2026
cac7120
fix: correct GetCurrentUserAsync return type in IDiscordClient and re…
M1tsumi Jun 15, 2026
6145b3c
Fix remaining CI errors: static logger ref, missing using, GetMlsStat…
M1tsumi Jun 15, 2026
efa9132
Fix Build_WithoutToken test message wildcard
M1tsumi Jun 15, 2026
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
100 changes: 100 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,106 @@ All notable changes to PawSharp are documented here.

---

## [1.1.0-alpha.3] - 2026-06-15

### New Features

- **IDiscordClient interface** (`PawSharp.Client`)
- New `IDiscordClient` interface with 130+ methods, 8 properties, 2 events, and 74 gateway event subscriptions.
- `DiscordClient` now implements `IDiscordClient` — all existing code continues to work.
- `PawSharpClientBuilder.Build()` returns `IDiscordClient`.
- DI registration registers both `IDiscordClient` and `DiscordClient` for backward compatibility.
- Enables full mocking via Moq for unit tests.

- **Connection state tracking** (`PawSharp.Client`)
- Added `ClientConnectionState` enum (`Disconnected`, `Connecting`, `Connected`, `Disconnecting`).
- `DiscordClient.ConnectionState` property and `ConnectionStateChanged` event.
- `DiscordClient.IsConnected` helper property.
- `DiscordClient.ReconnectAsync()` for graceful disconnect-reconnect cycles.
- State transitions are tracked during `ConnectAsync()` and `DisconnectAsync()`.

- **Global exception handler infrastructure** (`PawSharp.Client`)
- Added `DiscordClient.SetupGlobalExceptionHandlers()` static method.
- Wires `AppDomain.CurrentDomain.UnhandledException` and `TaskScheduler.UnobservedTaskException`.
- Optional logger and custom callback parameters.

- **Command module auto-discovery** (`PawSharp.Commands`)
- `CommandsExtension.RegisterModulesInAssembly()` — discovers and registers all `BaseCommandModule` subclasses in an assembly.
- `CommandsExtension.RegisterSlashModulesInAssemblyAsync()` — same, but as slash commands.
- `UseCommandsWithAutoDiscovery()` extension method for one-liner setup.
- Modules are resolved via service provider when available, falling back to `Activator.CreateInstance`.

- **Convenience methods on DiscordClient** (`PawSharp.Client`)
- `SendDirectMessageAsync(ulong userId, string content)` — creates DM channel and sends message.
- `TrySendMessageAsync(ulong channelId, string content)` — returns null on failure instead of throwing.
- `TryReplyAsync(MessageCreateEvent, string)` — non-throwing reply helper.
- `SendEmbedAsync(ulong channelId, Embed embed)` — shorthand for sending a single embed.
- `GetOrCreateThreadAsync(ulong channelId, string threadName, ...)` — find or create a thread.

- **Builder validation** (`PawSharp.Client`)
- `PawSharpClientBuilder.Build()` now validates token (not null/empty), intents (not `None`), API version (in supported range).
- All validation errors include actionable messages.
- Added `PawSharpClientBuilder.Create()` static factory method.

- **XML documentation with code examples** (across all projects)
- Added `<example>` blocks to 30+ methods across `DiscordClient`, `PawSharpClientBuilder`, `InteractionHandler`, `CommandsExtension`, `IDiscordRestClient`, `IEntityCache`, `IGatewayClient`.
- Examples compile, use realistic patterns, and include error handling.

### Changes

- **Exception hierarchy consolidated** (`PawSharp.Core` / `PawSharp.API`)
- `PawSharp.Core.Exceptions.DiscordApiException` now inherits from `PawSharp.API.Exceptions.DiscordApiException` instead of being a separate class — eliminates catch ambiguity. [Breaking if you caught the Core version by full type name]
- `PawSharp.Cache.Exceptions.CacheException` now inherits from `DiscordException` instead of `Exception` — all library exceptions are now in the same hierarchy.

- **Error handling hardened** (all modules)
- Gateway `UpdatePresenceAsync`, `RequestGuildMembersAsync`, `RequestSoundboardSoundsAsync` now re-throw exceptions after logging (previously silent).
- `GatewaySendAsync` rate-limit release uses `CancellationToken.None` to prevent semaphore leak on cancellation.
- `EventDispatchQueue.Dispose()` stores disposal task and exposes `WaitForDrainAsync()`.
- `WebSocketConnection.Dispose()` stores disposal task and exposes `WaitForDisposeAsync()`.
- 15 empty `catch {}` blocks replaced with `catch (Exception)` across CacheSwapper, ChannelExtensions, WebhookVerifier, InteractionExtensions.
- `CacheManager.HandleGuildMemberUpdate` null-guards `e.User`.
- `InteractivityValidation` now uses `ValidationException` from Core instead of `ArgumentException`.

- **Log sanitization and security** (`PawSharp.API` / `PawSharp.Interactions`)
- `PawSharpClientBuilder` now enforces TLS 1.2+ on the HttpClient via `SslOptions`.
- `WebhookVerifier` XML docs updated with clear warning about non-constant-time BigInteger implementation.
- Token security warning added to `PawSharpOptions.Token` XML docs.
- `ConnectAsync()` XML docs recommend setting up global exception handlers.

### Documentation

- Created `docs/MIGRATION.md` — migration guide covering all breaking changes from 0.x through 1.1.0-alpha versions.
- Rewrote README.md — comprehensive, human-written, with clear getting-started paths, package reference, and real code examples.
- Updated all .NET version references from 8.0 to 10.0 across 4 documentation files.
- Re-reconciled `docs/VOICE_GUIDE.md` and `src/PawSharp.Voice/README.md` — Voice README now accurately describes built-in MLS DAVE E2EE implementation.
- Fixed `src/PawSharp.Gateway/README.md` — event examples now use correct `On<T>("EVENT_NAME", handler)` API.
- Fixed formatting issues in `docs/PATTERNS_GUIDE.md` and `docs/GATEWAY_GUIDE.md`.
- Updated `docs/DEVELOPERS_GUIDE.md`, `docs/TROUBLESHOOTING.md`, `docs/VOICE_GUIDE.md` version and framework references.
- Updated `docs/INDEX.md` to reflect new features and fix version numbers.

### Example Bots

- **ModerationBot** — all 22 `_client.API.*` calls changed to `_client.Rest.*` (property didn't exist).
- **MusicBot** — `AddPawSharpCommands()` → `AddCommands()`, `CommandModule` → `BaseCommandModule`, `MusicService` now DI-injected (no duplicate creation), removed non-existent attributes.
- **DashboardBot** — rewritten to use `InteractionHandler` instead of non-existent `InteractionService`.
- All example bots updated to use `IDiscordClient` instead of `DiscordClient`.

### Bug Fixes

- **Voice — DAVE E2EE fixes** (`PawSharp.Voice`)
- Fixed DM/GroupDM voice calls crashing on connect: `VoiceClient.ConnectAsync` now accepts DM/GroupDM channel types with `guildId = 0`, and `OnVoiceServerUpdate` matches DM connections by channel type when the gateway sends `guild_id = 0`.
- Fixed inbound DAVE frames being silently dropped: `UdpReceiveLoopAsync` now checks `_dave?.IsActive` before attempting transport decryption on received audio packets.
- Fixed keep-alive (NAT timeout) never running: `KeepAliveLoopAsync` is now started during `ConnectInternalAsync` instead of being left as dead code.
- Fixed forward secrecy gap: external sender packages (op 31) are now stored in `MLSGroupState` and bound as the HKDF salt during commit epoch advances, so future commits benefit from the sender's entropy.

- **Example bot compilation** — fixed `client.API` → `client.Rest` in ModerationBot, fixed `AddPawSharpCommands` → `AddCommands` in MusicBot, removed references to non-existent `InteractionService`, `CommandModule`, `[CommandModule]`, and `Color` enum in example projects.

### Internal / Tooling

- Exposed `DAVEProtocol.MlsState` as internal for test access and added `InternalsVisibleTo` for `PawSharp.Voice.Tests`.
- Created `DAVETestData` helper that generates structurally valid MLS Welcome/Commit messages using real HPKE, HKDF, and AES-GCM primitives.
- Unskipped all 16 previously-skipped DAVE tests — they now run against real cryptographically-generated test data.

## [1.1.0-alpha.2] - 2026-05-03

### New Features
Expand Down
163 changes: 92 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,38 @@

---

PawSharp is a Discord library for C# developers who want clean building blocks instead of one giant monolith.
PawSharp is a Discord API wrapper for C#. Instead of one big library you have to accept on its own terms, it's split into independent packages — grab the full client if you're building a bot, or pick just the pieces you need.

If you want a high-level client, use `PawSharp.Client`.
If you only need specific pieces (REST, Gateway, Interactions, Voice), install just those packages.
Current release: `1.1.0-alpha.3`. Things are moving fast, but the API is stabilizing. See the [versioning policy][versioning] for what to expect, and [MIGRATION.md][migration] if you're upgrading from an earlier alpha.

Current release status: `1.1.0-alpha.1`.
## Where to start

This is a public alpha. The library is already usable, but some APIs can still evolve. See [versioning policy][versioning].
**You want a bot up and running in five minutes.** Start with the quickstart below using `PawSharpClientBuilder`, then read the [DEVELOPERS_GUIDE.md][dev-guide] when you're ready to go deeper.

## What You Get
**You want to understand how the pieces fit together.** Read the [INDEX.md][docs-index] — it maps out every module, every guide, and links to code examples.

- REST coverage for about 140+ Discord endpoints
- Gateway connection lifecycle, heartbeat, reconnect, and session resume
- Prefix commands with preconditions and cooldowns
- Slash commands, components, and modals
- Interactivity helpers for reactions/buttons/select menus
- In-memory caching and route-aware rate limiting
- Voice support with Opus, RTP, and Discord DAVE E2EE
**You're migrating from a previous alpha.** Check [MIGRATION.md][migration] for breaking changes.

## Installation
**You ran into a problem.** The [TROUBLESHOOTING.md][troubleshooting] guide covers the most common issues.

Most bots should start with the full client package:
---

## Quickstart

### 1. Install the packages

```bash
dotnet add package PawSharp.Client --version 1.1.0-alpha.2
dotnet add package PawSharp.Commands --version 1.1.0-alpha.2
dotnet add package PawSharp.Interactions --version 1.1.0-alpha.2
dotnet add package PawSharp.Interactivity --version 1.1.0-alpha.2
dotnet add package PawSharp.Voice --version 1.1.0-alpha.2
dotnet add package PawSharp.Client --version 1.1.0-alpha.3
```

## Quick Start
### 2. Write a minimal bot

```csharp
using PawSharp.Client;
using PawSharp.Core.Enums;

var token = Environment.GetEnvironmentVariable("DISCORD_TOKEN")
?? throw new InvalidOperationException("Set DISCORD_TOKEN before starting the bot.");
string token = Environment.GetEnvironmentVariable("DISCORD_TOKEN")
?? throw new InvalidOperationException("Set DISCORD_TOKEN before running.");

var client = new PawSharpClientBuilder()
.WithToken(token)
Expand All @@ -65,80 +58,103 @@ var client = new PawSharpClientBuilder()

client.OnMessageCreated(async evt =>
{
if (evt.Author?.Bot == true)
{
return;
}

if (evt.Author?.IsBot == true) return;
if (evt.Content == "!ping")
{
await client.SendMessageAsync(evt.ChannelId, "Pong!");
}
});

await client.ConnectAsync();
await Task.Delay(Timeout.Infinite);
```

## Package Guide
That's it. The builder wires up the REST client, gateway, cache, and logging with sensible defaults.

- `PawSharp.Client`: recommended entry point (`DiscordClient` and fluent builder)
- `PawSharp.Core`: entities, enums, exceptions, validation, utility builders
- `PawSharp.API`: raw REST layer with advanced rate-limit handling
- `PawSharp.Gateway`: gateway connection and event dispatcher
- `PawSharp.Commands`: attribute-based prefix command framework
- `PawSharp.Interactions`: slash commands and interaction routing
- `PawSharp.Interactivity`: wait helpers for reactions/components and polls
- `PawSharp.Voice`: voice transport, Opus codec integration, DAVE E2EE support
### 3. Run it

## Dependency Injection Setup
```bash
export DISCORD_TOKEN="your-bot-token-here"
dotnet run
```

For `Microsoft.Extensions.DependencyInjection`, use the one-call setup entrypoint:
---

```csharp
using PawSharp.Client.Extensions;
using PawSharp.Core.Enums;
using PawSharp.Core.Models;
## Packages

services.SetupPawSharp(new PawSharpOptions
{
Token = token,
Intents = GatewayIntents.AllNonPrivileged | GatewayIntents.MessageContent
});
PawSharp is modular by design. Install only what you need.

services.AddPawSharpCommands();
services.AddPawSharpInteractions();
```
| Package | Purpose | Depends on |
|---------|---------|-----------|
| `PawSharp.Client` | Top-level `DiscordClient` — fluent builder, DI, connection state tracking, 130+ convenience methods | Core, API, Gateway, Cache |
| `PawSharp.Core` | Shared entities (`Guild`, `Channel`, `Message`, `User`, `Role`), enums, builders (`EmbedBuilder`, `ComponentBuilder`), validation, serialization | — |
| `PawSharp.API` | Raw REST client with 140+ Discord endpoints, automatic rate limiting, telemetry | Core |
| `PawSharp.Gateway` | WebSocket connection, heartbeat, resume, reconnection, sharding, 40+ typed events | Core, API, Cache |
| `PawSharp.Commands` | Prefix commands via `[Command]` attributes, preconditions (`[RequireOwner]`, `[RequirePermissions]`, `[Cooldown]`), type conversion, middleware pipeline | Core, API, Client |
| `PawSharp.Interactions` | Slash commands, message components (buttons, select menus), modals, autocomplete, context menus, webhook verification | Core, API, Gateway |
| `PawSharp.Interactivity` | Pagination (reactions + buttons), wait-for-input helpers, polls, confirmation dialogs | Core, Client |
| `PawSharp.Voice` | Voice gateway, UDP audio transport, Opus encode/decode, DAVE end-to-end encryption (MLS / RFC 9420) | Core, API, Gateway, Client |
| `PawSharp.Cache` | In-memory and Redis caching with per-entity TTL, LRU eviction, health checks, telemetry, dynamic provider swapping | Core |

---

## What you can do

**REST API** — 140+ endpoints covered. Messages, channels, guilds, members, roles, webhooks, threads, reactions, slash commands, audit logs, auto-moderation, scheduled events, stage instances, stickers, soundboard, polls, entitlements, onboarding — all with typed request/response models. Rate limiting is handled automatically with configurable retry logic and telemetry events.

**Gateway** — WebSocket connection lifecycle with automatic resume, heartbeat monitoring, and exponential-backoff reconnection. Over 40 typed events (`OnMessageCreated`, `OnGuildMemberJoined`, etc.) with an event-interest filtering system that tells you which intents you're missing. Sharding is built in, including auto-rebalancing for large bots.

## Alpha.2 Highlights
**Commands** — Attribute-based prefix commands with a full middleware pipeline, type conversion (14 built-in converters plus custom), preconditions for permissions, ownership, roles, cooldowns, guild/DM/NSFW scoping. Modules can be registered manually or auto-discovered with assembly scanning.

- `SetupPawSharp(options)` for simpler DI setup
- Connect-time intent validation modes (`Off`, `Warn`, `Strict`)
- Message forwarding support using Discord message reference forwarding
- Structured rate-limit telemetry from the REST client (`RateLimitObserved`)
- `EmbedTemplates` helpers for common success/error/info/warning responses
**Interactions** — Slash command registration, button and select menu handling, modals, autocomplete, user/message context menus. The `InteractionHandler` routes incoming interactions to the right handler with built-in error recovery that tells the user something went wrong instead of silently timing out.

## Still In Progress
**Interactivity** — High-level helpers that remove the boilerplate from common patterns: paginated messages (reactions or buttons), confirmation dialogs, input prompts, poll creation and voting. All with configurable timeouts.

- Slash command attribute auto-registration scanner (manual registration works today)
- Dedicated Redis cache package publication (provider implementation exists)
**Voice** — Full Discord Voice Protocol v8 with UDP audio transport, Opus encoding/decoding (via Concentus, pure .NET — no native DLLs), and DAVE end-to-end encryption using MLS (RFC 9420) with X25519 key exchange, Ed25519 signatures, and AES-128-GCM frame encryption. Multiple simultaneous voice connections supported.

## Documentation And Examples
**Caching** — Pluggable cache layer with in-memory (`MemoryCacheProvider`) and Redis (`RedisCacheProvider`) implementations. Per-entity TTL, LRU eviction, health checks, cache telemetry (hits, misses, operation durations), and dynamic provider swapping with circuit breaker fallback.

- Start here: [docs/INDEX.md][docs-index]
- REST guide: [docs/REST_API_GUIDE.md][rest-guide]
- Gateway guide: [docs/GATEWAY_GUIDE.md][gateway-guide]
- Voice guide: [docs/VOICE_GUIDE.md][voice-guide]
- Troubleshooting: [docs/TROUBLESHOOTING.md][troubleshooting]
- Working sample bots: [examples][examples]
---

## Going further

- **[DEVELOPERS_GUIDE.md][dev-guide]** — Installation, first bot, configuration, core concepts, best practices
- **[REST_API_GUIDE.md][rest-guide]** — Full REST endpoint reference with code examples
- **[GATEWAY_GUIDE.md][gateway-guide]** — Events, connection lifecycle, sharding, middleware
- **[CACHING_GUIDE.md][caching-guide]** — In-memory cache, Redis, strategies, monitoring
- **[PATTERNS_GUIDE.md][patterns-guide]** — Real-world patterns: moderation, logging, pagination
- **[VOICE_GUIDE.md][voice-guide]** — Voice connections, Opus, DAVE E2EE deep dive
- **[ERROR_HANDLING.md][error-handling]** — Exception hierarchy, common errors, recovery strategies
- **[MIGRATION.md][migration]** — Breaking changes between alpha versions
- **[TROUBLESHOOTING.md][troubleshooting]** — Common issues and solutions

---

## Example bots

The [examples/][examples] directory has three working bots that show different patterns:

- **ModerationBot** — Gateway events, REST operations, moderation logic. Uses the low-level API directly.
- **MusicBot** — DI setup, commands with `[Command]` attributes, voice integration. Shows the module pattern.
- **DashboardBot** — ASP.NET integration, interaction handlers, webhook verification. Shows HTTP interaction mode.

Each example has its own README with setup instructions.

---

## Versioning

PawSharp follows [Semantic Versioning](https://semver.org/). Until 1.0.0, minor version bumps may include breaking changes. See [VERSIONING_POLICY.md][versioning] for the full policy.

---

## Contributing

Contributions are welcome. Please read [CONTRIBUTING.md][contributing] before opening a pull request.
Pull requests are welcome. Read [CONTRIBUTING.md][contributing] first — it covers code style, testing, documentation, and the release process.

---

## License

PawSharp is distributed under the [MIT License][license].
MIT. See [LICENSE][license].

---

Expand All @@ -155,9 +171,14 @@ PawSharp is distributed under the [MIT License][license].
[build]: https://github.com/M1tsumi/PawSharp/actions/workflows/ci.yml
[docs]: https://github.com/M1tsumi/PawSharp/tree/main/docs
[docs-index]: docs/INDEX.md
[dev-guide]: docs/DEVELOPERS_GUIDE.md
[rest-guide]: docs/REST_API_GUIDE.md
[gateway-guide]: docs/GATEWAY_GUIDE.md
[caching-guide]: docs/CACHING_GUIDE.md
[patterns-guide]: docs/PATTERNS_GUIDE.md
[voice-guide]: docs/VOICE_GUIDE.md
[error-handling]: docs/ERROR_HANDLING.md
[migration]: docs/MIGRATION.md
[troubleshooting]: docs/TROUBLESHOOTING.md
[changelog]: CHANGELOG.md
[examples]: examples/
Expand Down
2 changes: 1 addition & 1 deletion docs/DEVELOPERS_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PawSharp Developer Documentation

Welcome to PawSharp! This documentation will guide you through building Discord bots with .NET 8.0+.
Welcome to PawSharp! This documentation will guide you through building Discord bots with .NET 10.0+.

## Table of Contents

Expand Down
3 changes: 1 addition & 2 deletions docs/GATEWAY_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ dispatcher.Use(async (eventName, eventData) =>
await _auditLog.RecordBotMessageAsync(msg);
}
});
```

### Best practices for event handlers

Expand Down Expand Up @@ -244,8 +245,6 @@ sub.Dispose();

- Be mindful of intents: handlers that rely on message content require `GatewayIntents.MessageContent`.

```

---

## Connection Management
Expand Down
Loading
Loading