DisCatSharp.Analyzer
1.0.3
Prefix Reserved
dotnet add package DisCatSharp.Analyzer --version 1.0.3
NuGet\Install-Package DisCatSharp.Analyzer -Version 1.0.3
<PackageReference Include="DisCatSharp.Analyzer" Version="1.0.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="DisCatSharp.Analyzer" Version="1.0.3" />
<PackageReference Include="DisCatSharp.Analyzer"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add DisCatSharp.Analyzer --version 1.0.3
#r "nuget: DisCatSharp.Analyzer, 1.0.3"
#:package DisCatSharp.Analyzer@1.0.3
#addin nuget:?package=DisCatSharp.Analyzer&version=1.0.3
#tool nuget:?package=DisCatSharp.Analyzer&version=1.0.3
DisCatSharp
A Discord App Library written in C# for .NET
News
New
- Nothing here yet
Breaking
- Nothing here yet
About
Why DisCatSharp?
If you:
- want a library where you get kind and efficient help
- would like to have and use the most recent features of the Discord API
- are ready to build great things
Then this is the right place for you!
What Happened With The History
We've squashed the history of DisCatSharp due to it's clone size and cluttered history. The original history can be seen in the releases / tags and at https://github.com/Aiko-IT-Systems/DisCatSharp.Backup (Archived version before the squash).
Installing
You can install the library from the following sources:
Documentation
The documentation is available at docs.dcs.aitsys.dev.
Alternative hosts for our docs are:
- Backup Host backup-docs.dcs.aitsys.dev
Bugs or Feature requests?
Either join our official support guild at https://discord.gg/RXA6u3jxdU, open an issue or write us an email at bugs@aitsys.dev.
Tutorials / Examples
Visual Studio Tools
NuGet Packages
Main
| Package | LTS | Latest |
|---|---|---|
| DisCatSharp | ||
| DisCatSharp.ApplicationCommands | ||
| DisCatSharp.CommandsNext | ||
| DisCatSharp.Interactivity |
Voice
| Package | LTS | Latest |
|---|---|---|
| DisCatSharp.Lavalink | ||
| DisCatSharp.Voice | ||
| DisCatSharp.Voice.Natives |
Hosting
| Package | LTS | Latest |
|---|---|---|
| DisCatSharp.Configuration | ||
| DisCatSharp.Hosting | ||
| DisCatSharp.Hosting.DependencyInjection |
Templates
| Package | LTS | Latest |
|---|---|---|
| DisCatSharp.ProjectTemplates |
Development / Commons
| Package | LTS | Latest |
|---|---|---|
| DisCatSharp.Attributes | ||
| DisCatSharp.Common | ||
| DisCatSharp.Analyzer |
Extensions
| Package | LTS | Latest |
|---|---|---|
| DisCatSharp.Extensions.TwoFactorCommands | ||
| DisCatSharp.Extensions.OAuth2Web | ||
| DisCatSharp.Extensions.SimpleMusicCommands |
Sponsors (Current & Past)
Thanks
Big thanks goes to the following people who helped us without being part of the core team ♥️
Special Thanks
The special thanks goes to Nagisa. Make sure to check out her Instagram ♥️♥️
The second special thanks goes to Sentry (GitHub) for sponsoring us with a business account on Sentry for error tracking. You guys are the best 💕⭐
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
DisCatSharp Release Notes
- Fixed `RingBuffer<T>.CopyTo` to respect the `index` parameter and validate that enough free slots exist before copying, preventing silent data corruption.
- Hardened gateway dispatch: all `GuildsInternal` indexer accesses now use `TryGetValue` guards to prevent `KeyNotFoundException` on late-arriving or missing guild payloads.
- Synchronized session state during reconnect under `_sessionStateLock` to close a TOCTOU race where `OnHelloAsync` could read a partially-cleared session ID and produce a malformed RESUME payload.
- Fixed heartbeat skipped-beat counter reset from a no-op `Interlocked.CompareExchange` to `Volatile.Write`, and cancels the old heartbeat loop before starting a new one to prevent task leaks across reconnects.
- Null-guarded `GetSocketLock` to return `null` instead of throwing before the WebSocket is fully initialized.
- Made `ReadyGuildIds` thread-safe via a dedicated lock and an atomic `SetReadyGuildIds()` mutator; dispatch now calls the mutator instead of writing directly to the backing set.
- Narrowed broad `catch (Exception)` blocks to specific exception types (`JsonReaderException`, `ArgumentOutOfRangeException`) in all seven Discord exception wrapper types and `Utilities`.
- Replaced `Stream.Read` with `Stream.ReadExactly` in `MediaTool` to prevent silent partial reads.
- Eliminated a redundant `DateTimeOffset` → `DateTime` → `DateTimeOffset` round-trip in `Formatter`, preserving UTC offset fidelity.
- Added a defensive copy on `AttachmentsInternal` in `DiscordMessage.Attachments` to prevent external callers from mutating cached message state.
- Capped REST `retry_after` to 3 600 s to guard against adversarially large values from misbehaving proxies or rogue buckets.
- Linearized concurrent bucket enumeration in `RestClient` with a `.ToList()` snapshot before iteration to prevent `InvalidOperationException` under concurrent request pressure.
- Fixed `SocketLock.ContinueWith` calls to use `CancellationToken.None` and `TaskScheduler.Default`, preventing ambient sync-context capture and potential deadlocks in UI/ASP.NET contexts.
- Added `DiscordConfiguration.Validate()`, called from `ConnectAsync` before any network I/O, which throws `InvalidOperationException` when `ShardId ≥ ShardCount`.
- Clamped `LargeThreshold` to the Discord-specified bot range (50–250) in `DiscordConfiguration`; values outside the range are silently clamped on assignment.
- Added non-negative validation for `ShardId` and positive validation for `ShardCount` in `DiscordConfiguration` property setters.
- Audited `NullValueHandling` across 51 serialized properties in 19 entity files: corrected 25 from `Include` to `Ignore` on fields Discord never reads as explicit `null`; preserved `Include` on 26 fields where `null` carries a distinct semantic (ungrouping channels, disconnecting from voice, clearing timeout/gradient/incident restrictions, null-as-boolean role tags, and unicode-vs-custom emoji disambiguation).
- Fixed `DiscordMember.BanAsync` and `UnbanAsync` to route through `ApiClient` directly, consistent with all other member REST operations.
- Renamed `deleteMessageDays` to `deleteMessageSeconds` on `DiscordMember.BanAsync` and all `DiscordGuild.BanMemberAsync` overloads; removed the legacy days-to-seconds compatibility shim — the API has always accepted seconds. **Note:** positional callers passing day values must be updated manually; named-argument callers are handled by `DCS1102`.
- Padded log-level labels to eight characters in `DefaultLogger` for consistent column alignment across log lines.
- Fixed `DiscordEventArgs` scoped service scope to be properly disposed after event dispatch, preventing scoped service leaks on high-volume bots.
- Overhauled presence caching and added follow-up regression coverage around gateway cache behavior.
- Added Discord parity updates for store, entitlement, SKU, guild powerup / applied boost, application, audit-log, automod, message-type, and OAuth scope surfaces.
- Fixed interaction response posting, soundboard cache refresh/list behavior, duplicate application-command execution logging, and several gateway/store dispatch follow-ups.
- Removed .NET 8 support and aligned the core package with the current target framework matrix.
- Reworked built-in Sentry telemetry around a per-client diagnostics sink with breadcrumbs, structured tags, better grouping, scrubbed file payload attachments, release/PDB upload support, and package-root stack frame rewriting for code mappings.
- Added package-level diagnostics participation for built-in extensions and hosting paths, including origin tagging for upstream Lavalink failures.
- Added gateway telemetry for unknown opcodes, disconnect/session lifecycle, and suppressed dispatch exceptions, plus follow-up fixes for wrapped exception filtering, preserved route-specific grouping, and shard-specific sink metadata.
- Adjusted Sentry environment tagging so local stable source builds report as `dev` while CI stable builds continue reporting as `production`.
- Removed the separate `ReportMissingFields` telemetry switch so schema-drift diagnostics now follow `EnableSentry` directly.
- Prevented the temporary sharded gateway-info client from reusing the parent telemetry sink and emitting spurious session-ended events.
- Made `DiscordApplicationCommandLocalization.ValidLocales` a static `FrozenSet<string>` for O(1) lookup and zero per-instance allocation.
DisCatSharp.Attributes Release Notes
- No major API additions.
- Package metadata and target framework alignment were updated alongside the wider .NET 8 removal work.
DisCatSharp.ApplicationCommands Release Notes
- Added dedicated `SlashCommandChecksFailed` and `ContextMenuChecksFailed` events with new event args for modern checks-failed handling.
- Updated command error flow to use dedicated checks-failed events instead of the older errored-event-only pattern.
- Included follow-up fixes and regression coverage around application-command checks-failed behavior and execution logging.
- Added diagnostics-sink reporting for application-command execution, registration, and autocomplete failure paths.
- Fixed command equality change detection: defensive copies for both source and target, type-based matching for entry points and context menus, and explicit `Optional` clearing for unchanged option fields.
- Fixed entry point (launch) command registration so it flows through normal create/overwrite/unchanged detection instead of being unconditionally re-created on every startup.
- Strip built-in localizations from the entry point command when `EnableLocalization` is disabled.
- Added `RegisterEntryPointCommand()` on `ApplicationCommandsExtension` so consumers can configure entry point properties (description, handler type, contexts, integration types) without hardcoding them.
- Replaced three wasteful `new ServiceCollection().BuildServiceProvider()` allocations with a shared `EmptyServiceProvider.Instance` singleton.
- Hardened `ChoiceProvider.Services` with a backing field and `InvalidOperationException` guard when accessed before initialization.
- Fixed bare `catch` blocks to use filtered `catch (Exception ex)` for proper debugger break behavior.
- Fixed unsafe `int`/`ulong` casts to use `Convert.ToInt32`/`Convert.ToUInt64` for safe numeric conversion.
- Normalized `ToLower()` calls to `ToLowerInvariant()` for culture-independent command name handling (including `SlashCommandGroupAttribute`).
- Improved choice value comparison with numeric normalization (`AreChoiceValuesEqual`) to avoid false change detection between `int`/`long`/`double` representations from JSON.
- Rewrote `DeepEqualOptions` to collect all option mismatches with per-field diagnostic messages instead of returning on the first difference.
- Added thread-safe snapshots for public collection properties (`GlobalCommands`, `GuildCommands`).
- Isolated `resultCommands` from the input `updateList` to prevent mutation of caller-provided data.
DisCatSharp.CommandsNext Release Notes
- No notable feature changes.
- Package alignment was updated as part of the .NET 8 removal and current framework support refresh.
- Added diagnostics-sink reporting for command execution failures.
DisCatSharp.Interactivity Release Notes
- Fixed `ComponentCollectRequest.Collected` never being initialized, which caused `NullReferenceException` on any component collect operation.
- Replaced non-thread-safe `Dictionary` in `ComponentPaginator` with `ConcurrentDictionary` to prevent race condition corruption during concurrent pagination.
- Added try-catch blocks around all fire-and-forget `Task.Run` calls in `Paginator` and `Poller` to prevent silent exception swallowing.
- Fixed `CancellationTokenSource` leak in `GetCancellationToken` by registering a self-disposal callback on the token.
- Fixed `InteractionPaginationRequest.GetPageAsync` so navigation buttons are properly disabled for single-page pagination and boundary conditions.
- Removed broken followup-without-ACK path in `ComponentEventWaiter.Handle` that caused Discord API 400 errors on non-matching interactions.
- Eliminated shared mutable `_builder` field in `ComponentPaginator`; each pagination response now uses a local builder to prevent concurrent corruption.
- Aligned `PaginationButtons` default custom IDs with their declared constants so custom ID matching works correctly.
- Removed spam followup messages in `ModalEventWaiter.Handle` for every non-matching interaction event.
- Fixed dispose-race in `Paginator` and `Poller` where `_client` was set to null before pending `Task.Run` could complete, causing `NullReferenceException`.
- Replaced reflection-based event lookup in `EventWaiter<T>` with explicit subscribe/unsubscribe delegates for the three known event types; reflection kept only as fallback for the dynamic `WaitForEventArgsAsync<T>` / `CollectEventArgsAsync<T>` public API.
- Replaced reflection-based event lookup in `ReactionCollector` with direct `+=` / `-=` event subscription matching the pattern `Paginator` and `Poller` already use.
- Added `lock()` guards around non-atomic read-modify-write operations on `ConcurrentHashSet` in `ReactionCollector` and `PollRequest` to prevent race conditions losing reactions or votes.
- Fixed multiple enumeration of `IEnumerable<Page>` in `SendPaginatedMessageAsync` / `SendPaginatedResponseAsync` by coercing to `IList<Page>` upfront.
- Added empty-pages guard (`ArgumentException`) in pagination methods instead of letting `pages.First()` throw an unhelpful exception.
- Removed dead code `HandleInvalidInteraction` method and unused `_componentInteractionWaiter` / `_modalInteractionWaiter` fields along with their suppressions.
- `IPaginator` now extends `IDisposable` so paginators held via the interface can be properly disposed.
- `InteractivityExtension` now implements `IDisposable` with a `_disposed` guard that disposes all nine internal components (waiters, paginators, poller, collector).
- Added double-dispose guards with `_disposed` flags to `ComponentPaginator`, `PaginationRequest`, `PollRequest`, `ReactionCollectRequest`, `Paginator`, and `Poller`.
- Replaced unnecessary `await Task.Yield()` calls in `PaginationRequest` with `Task.FromResult` / `Task.CompletedTask`.
- Renamed confusing `_behaviorBehavior` field to `_buttonBehavior`.
- `InteractivityHelpers.Recalculate` now throws if all pages lack embeds and preserves content-only pages in the output.
- Stored `CancellationTokenRegistration` in `ComponentMatchRequest` and `ModalMatchRequest` for proper lifecycle tracking.
- Added diagnostics-sink reporting for waiter, paginator, poller, and collector exception paths.
DisCatSharp.Common Release Notes
- No dedicated end-user feature changes.
- Shared framework/package alignment was updated with the rest of the solution.
DisCatSharp.Lavalink Release Notes
- Fixed a regression affecting player updates when switching the bot's voice channel while using Lavalink.
- Included follow-up Lavalink session/internal cleanup and removed obsolete archived Lavalink v1 sources from the maintained tree.
- Added diagnostics-sink reporting for Lavalink REST, websocket, and connection failures with upstream-origin tagging to distinguish Lavalink server issues from library faults.
DisCatSharp.Voice Release Notes
- Fixed voice/lavalink integration regressions around channel switching.
- Voice native packaging/build settings were refreshed with the wider framework alignment changes.
- Added diagnostics-sink reporting across voice sender, receiver, keepalive, disconnect, and native-loading failure paths.
DisCatSharp.Experimental Release Notes
- Stabilized autocomplete interaction value handling.
- Added documentation/supporting work around newer experimental search-related behavior.
DisCatSharp.Configuration Release Notes
- No standalone package-specific API additions.
- Configuration-related framework alignment was refreshed with the rest of the solution.
DisCatSharp.Hosting Release Notes
- Added diagnostics-sink reporting for hosted-service startup and extension-initialization failures.
- Hosting package alignment was updated as part of the current framework support refresh.
DisCatSharp.Hosting.DependencyInjection Release Notes
- No notable feature changes.
- Dependency injection/hosting package alignment was updated as part of the current framework support refresh.
DisCatSharp.Analyzer Release Notes
- Reworked the analyzer/tooling stack into a NuGet-first workflow with real xUnit/Roslyn regression coverage.
- Added `DCS2101` as a application-command migration analyzer/code fix with rewrite, split, and manual migration modes..
- Added `DCS2101` to an error because leaving legacy checks-failed logic on errored events can break consumers.
- Added `DCS1101`, a presence migration analyzer/code fix for moving supported manual `DiscordClient.Presences` filtering and direct lookup shapes to `DiscordClient.GetPresences(userId)`.
- Improved `DCS0201` so the override fixer can update `DiscordConfiguration` across project documents.
- Updated analyzer packaging so `DisCatSharp.Attributes.dll` is bundled with the analyzer package for Roslyn runtime loading.
- Added analyzer authoring documentation, diagnostic family guidance, release tracking files, and release workflow support for publishing `DisCatSharp.Analyzer`.
- Added `DCS1102`, a ban-parameter migration analyzer/code fix: detects `deleteMessageDays:` named arguments on `BanAsync`/`BanMemberAsync` and renames them to `deleteMessageSeconds:`, multiplying integer literals by 86400 automatically.