### Example Module Structure Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/intro.md This is a basic example of a module that can be loaded by the Command Service. Ensure your module inherits from ModuleBase. ```csharp using Discord.Commands; public class ExampleModule : ModuleBase { [Command("ping")] public async Task PingAsync() { await ReplyAsync("Pong!"); } } ``` -------------------------------- ### Install Discord.Net.BuildOverrides Package Source: https://github.com/discord-net/discord.net/blob/dev/docs/faq/build_overrides/what-are-they.md Install the build override package using the Package Manager Console. ```powershell PM> Install-Package Discord.Net.BuildOverrides ``` -------------------------------- ### Annotated Example of Bot Structure Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/getting_started/first-bot.md This C# code provides an annotated example of a basic bot structure, useful for understanding initialization and command handling setup. ```csharp // This is an example of a basic bot structure. // It is not intended to be run directly. // using Discord; // using Discord.WebSocket; // using Discord.Commands; // using System.Threading.Tasks; // namespace MyBot // { // public class Program // { // private DiscordSocketClient _client; // private CommandService _commands; // public static Task Main(string[] args) => new Program().MainAsync(); // public async Task MainAsync() // { // _client = new DiscordSocketClient(); // _commands = new CommandService(); // _client.Log += LogAsync; // // Add other event handlers here // // Replace with your bot's token // await _client.LoginAsync(TokenType.Bot, "YOUR_BOT_TOKEN"); // await _client.StartAsync(); // // You can add your own custom commands here. // // Block the main method from exiting. // await Task.Delay(-1); // } // private Task LogAsync(LogMessage log) // { // Console.WriteLine(log); // return Task.CompletedTask; // } // } // } ``` -------------------------------- ### Prefilled Select Menus Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/modals.md Example of implementing user, role, mentionable, and channel selects in a modal. These attributes can be used on properties of specific interface types or arrays of those types. ```csharp using Discord; using Discord.Interactions; public class PrefilledSelectsModal : IModal { public string Title => "Prefilled Selects Modal"; [ModalUserSelect("user-select")] public IUser User { get; set; } [ModalRoleSelect("role-select")] public IRole Role { get; set; } [ModalMentionableSelect("mentionable-select")] public IMentionable Mentionable { get; set; } [ModalChannelSelect("channel-select")] public IChannel Channel { get; set; } [ModalChannelSelect("text-channel-select", ChannelType.Text)] public ITextChannel TextChannel { get; set; } public async Task RespondAsync(PrefilledSelectsModal modal) { await RespondAsync($"User: {modal.User} Role: {modal.Role} Mentionable: {modal.Mentionable} Channel: {modal.Channel} Text Channel: {modal.TextChannel}"); return ModalResponse.None; } } ``` -------------------------------- ### Registering User Install Commands Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md This C# snippet demonstrates how to register a user install command for a Discord application. Ensure the command is correctly defined within your interaction modules. ```csharp using Discord.Interactions; namespace Discord.Bot.Modules; public class UserAppModule : InteractionModuleBase { [UserCommand("Echo")] public async Task EchoAsync(IUser user) { await RespondAsync($"Hello {user.Username}!"); } } ``` -------------------------------- ### Example - Using a Precondition Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/preconditions.md Apply a precondition attribute directly to a command method to enforce specific conditions before execution. ```csharp using Discord.Commands; public class MyModule : ModuleBase { [Command("ping")] [RequireUserPermission(GuildPermission.Administrator)] public async Task PingAsync() { await ReplyAsync("Pong!"); } } ``` -------------------------------- ### Empty Module Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Commands/ICommandContext.Inclusion.md An example of an empty module, serving as a basic structure for command organization. ```csharp using Discord.Commands; namespace SampleModule { public class EmptyModule : ModuleBase { } } ``` -------------------------------- ### Basic Command Handler Setup Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/intro.md This is the bare minimum required to set up a command handler for your bot. Ensure you have the necessary intents enabled. ```csharp using Discord; using Discord.Commands; public class CommandHandler { private readonly DiscordSocketClient _client; private readonly CommandService _commands; public CommandHandler(DiscordSocketClient client, CommandService commands) { _client = client; _commands = commands; } public async Task InstallCommandsAsync() { // Hook the CommandExecuted event _commands.CommandExecuted += CommandExecuted; // Hook the MessageReceived event _client.MessageReceived += HandleMessageAsync; // Here we discover all of the commands in the assembly that contains this class await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), null); } private async Task HandleMessageAsync(SocketMessage messageParam) { // Don't process the command if it was a system message var message = messageParam as SocketUserMessage; if (message == null) return; // Ignore self, and we also want to ignore messages that aren't from a user if (message.Author.IsBot) return; // Create a number to track where the prefix ends int argPos = 0; // Identify the command prefix and verify the message has one if (!message.HasCharPrefix('!', ref argPos) && !message.HasMentionPrefix(_client.CurrentUser, ref argPos)) return; // Create a Command Context var context = new SocketCommandContext(_client, message); // Perform the search, and/or execute the command await _commands.ExecuteAsync(context, argPos, null); } private async Task CommandExecuted(Optional command, ICommandContext context, IResult result) { // command is Optional because maybe the command was not found // To get help with the command, check the documentation if (!command.IsSpecified) await context.Channel.SendMessageAsync($"Command failed: {result}"); // the command was successful, so no further action is required } } ``` -------------------------------- ### Command Handler Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Commands/ICommandContext.Inclusion.md A sample command handler that processes incoming messages and executes commands. ```csharp using Discord; using Discord.Commands; using Discord.WebSocket; using System.Threading.Tasks; public class CommandHandler { private readonly DiscordSocketClient _client; private readonly CommandService _commands; public CommandHandler(DiscordSocketClient client) { _client = client; _commands = new CommandService(); _client.MessageReceived += HandleCommandAsync; } private async Task HandleCommandAsync(SocketMessage messageParam) { var message = messageParam as SocketUserMessage; if (message == null) return; int argPos = 0; if (!message.HasCharPrefix('!', ref argPos) || message.Author.IsBot) return; var context = new SocketCommandContext(_client, message); var result = await _commands.ExecuteAsync( context: context, argPos: argPos, services: null); if (!result.IsSuccess) await context.Channel.SendMessageAsync($"Something went wrong: {result.ErrorReason}"); } } ``` -------------------------------- ### Property Injection Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/faq/int_framework/framework.md Demonstrates how to correctly set up properties for injection within command modules. Ensure properties are publicly accessible and settable. ```csharp using Discord.Interactions; public class MyModule : InteractionModuleBase { // Properties must be public and settable for injection to work. public IDependency MyDependency { get; set; } [SlashCommand("mycommand", "A command that uses injected dependencies.")] public async Task MyCommandAsync() { // Use the injected dependency here. await RespondAsync($"Injected dependency value: {MyDependency.GetValue()}"); } } ``` -------------------------------- ### Service and Dependency Injection Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/faq/basics/dependency-injection.md Demonstrates how to implement a service for persistent data and inject it into a module. Ensure you understand Microsoft's DI implementation before using this. ```csharp using Discord; using Discord.Commands; using Microsoft.Extensions.DependencyInjection; public class MyService { public int Counter { get; set; } } public class MyModule : ModuleBase { private readonly MyService _myService; // Inject your service here public MyModule(MyService myService) { _myService = myService; } [Command("increment")] public async Task IncrementCommand() { _myService.Counter++; await ReplyAsync($"Counter is now: {_myService.Counter}"); } } public class Program { public static async Task Main(string[] args) { var services = new ServiceCollection() .AddSingleton() // Add your service here .BuildServiceProvider(); // ... rest of your bot setup using services.GetRequiredService() } } ``` -------------------------------- ### Groups and Submodules Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/intro.md Demonstrates how to create command groups and submodules. Commands within a group can be prefixed, and submodules allow for nested command structures. ```csharp using Discord.Commands; [Group("math")] public class MathModule : ModuleBase { [Command("add")] public async Task AddAsync(int a, int b) { await ReplyAsync($"{a} + {b} = {a + b}"); } [Group("subtract")] public class SubtractModule : ModuleBase { [Command] public async Task SubtractAsync(int a, int b) { await ReplyAsync($"{a} - {b} = {a - b}"); } } } ``` -------------------------------- ### Interaction Context Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md This example demonstrates accessing interaction-specific information within different interaction context types. It shows how to use the generic variant of InteractionModuleBase to access specific context types. ```csharp public class ContextModule : InteractionModuleBase> { [UserCommand("User Info")] public async Task UserInfoAsync() { // Accessing SocketUserCommand specific properties var targetUser = Context.TargetUser; await RespondAsync($"You right-clicked on {targetUser.Username}."); } } ``` -------------------------------- ### Create a Settings Command with Subcommands Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_basics/application-commands/slash-commands/subcommands.md This C# code defines a complex slash command named 'settings' with subcommand groups for 'field-a', 'field-b', and 'field-c'. Each group contains 'set' and 'get' subcommands to modify or retrieve values. Ensure you have the necessary Discord.Net libraries installed. ```csharp public string FieldA { get; set; } = "test"; public int FieldB { get; set; } = 10; public bool FieldC { get; set; } = true; public async Task Client_Ready() { ulong guildId = 848176216011046962; var guildCommand = new SlashCommandBuilder() .WithName("settings") .WithDescription("Changes some settings within the bot.") .AddOption(new SlashCommandOptionBuilder() .WithName("field-a") .WithDescription("Gets or sets the field A") .WithType(ApplicationCommandOptionType.SubCommandGroup) .AddOption(new SlashCommandOptionBuilder() .WithName("set") .WithDescription("Sets the field A") .WithType(ApplicationCommandOptionType.SubCommand) .AddOption("value", ApplicationCommandOptionType.String, "the value to set the field", isRequired: true) ).AddOption(new SlashCommandOptionBuilder() .WithName("get") .WithDescription("Gets the value of field A.") .WithType(ApplicationCommandOptionType.SubCommand) ) ).AddOption(new SlashCommandOptionBuilder() .WithName("field-b") .WithDescription("Gets or sets the field B") .WithType(ApplicationCommandOptionType.SubCommandGroup) .AddOption(new SlashCommandOptionBuilder() .WithName("set") .WithDescription("Sets the field B") .WithType(ApplicationCommandOptionType.SubCommand) .AddOption("value", ApplicationCommandOptionType.Integer, "the value to set the fie to.", isRequired: true) ).AddOption(new SlashCommandOptionBuilder() .WithName("get") .WithDescription("Gets the value of field B.") .WithType(ApplicationCommandOptionType.SubCommand) ) ).AddOption(new SlashCommandOptionBuilder() .WithName("field-c") .WithDescription("Gets or sets the field C") .WithType(ApplicationCommandOptionType.SubCommandGroup) .AddOption(new SlashCommandOptionBuilder() .WithName("set") .WithDescription("Sets the field C") .WithType(ApplicationCommandOptionType.SubCommand) .AddOption("value", ApplicationCommandOptionType.Boolean, "the value to set the fie to.", isRequired: true) ).AddOption(new SlashCommandOptionBuilder() .WithName("get") .WithDescription("Gets the value of field C.") .WithType(ApplicationCommandOptionType.SubCommand) ) ); try { await client.Rest.CreateGuildCommand(guildCommand.Build(), guildId); } catch(ApplicationCommandException exception) { var json = JsonConvert.SerializeObject(exception.Error, Formatting.Indented); Console.WriteLine(json); } } ``` -------------------------------- ### Configure Serilog Logger Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/other_libs/serilog.md Set up the Serilog logger in your async Main method. Ensure you have installed the Serilog.Extensions.Logging and Serilog.Sinks.Console NuGet packages. ```csharp await new DiscordSocketClient().LoginAsync("bot", "..."); await new DiscordSocketClient().StartAsync(); Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .CreateLogger(); await Task.Delay(-1); ``` -------------------------------- ### Example - ORing Preconditions Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/preconditions.md Use the 'Group' property on precondition attributes to allow a command to execute if any of the grouped preconditions are met. ```csharp using Discord.Commands; public class MyModule : ModuleBase { [Command("test")] [RequireUserPermission(GuildPermission.Administrator, Group = "AdminOrOwner")] [RequireOwner(Group = "AdminOrOwner")] public async Task TestAsync() { await ReplyAsync("You are either an admin or the owner."); } } ``` -------------------------------- ### Basic Command Handler Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/post-execution.md This snippet demonstrates a fundamental post-execution handler by storing and printing the result of ExecuteAsync to the chat. ```csharp var result = await Commands.ExecuteAsync(context, services); if (!result.IsSuccess) { await context.Channel.SendMessageAsync($"Error: {result.ErrorReason}"); } ``` -------------------------------- ### JsonLocalizationManager Structure Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md Illustrates the expected JSON structure for localizing command names, descriptions, and parameter details when using JsonLocalizationManager. ```json { "command_1":{ "name": "localized_name", "description": "localized_description", "parameter_1":{ "name": "localized_name", "description": "localized_description" } }, "group_1":{ "name": "localized_name", "description": "localized_description", "command_1":{ "name": "localized_name", "description": "localized_description", "parameter_1":{ "name": "localized_name", "description": "localized_description" }, "parameter_2":{ "name": "localized_name", "description": "localized_description" } } } } ``` -------------------------------- ### Register and Start the Event Listener Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/other_libs/mediatr.md Register the DiscordEventListener in your DI container and retrieve an instance in your main method to start listening for events. ```csharp using Microsoft.Extensions.DependencyInjection; // ... var services = new ServiceCollection(); // ... configure other services and MediatR ... services.AddSingleton(); var serviceProvider = services.BuildServiceProvider(); var listener = serviceProvider.GetRequiredService(); listener.StartAsync(); // ... rest of your bot startup code ... ``` -------------------------------- ### Command Group Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md Demonstrates how to create nested command groups using the GroupAttribute in discord.net. ```csharp using Discord; using Discord.Interactions; public class MyModule : InteractionModuleBase { [Group("mygroup")] public class MyNestedModule : InteractionModuleBase { [SlashCommand("hello", "Says hello!")] public async Task SayHelloAsync() { await RespondAsync("Hello!"); } } } ``` -------------------------------- ### Create Global and Guild Context Menu Commands Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_basics/application-commands/context-menu-commands/creating-context-menu-commands.md This example demonstrates how to create both guild and global user and message context menu commands. It hooks into the client's Ready event to register these commands. Ensure you have the necessary guild ID. ```cs client.Ready += Client_Ready; ... public async Task Client_Ready() { var guild = client.GetGuild(guildId); var guildUserCommand = new UserCommandBuilder(); var guildMessageCommand = new MessageCommandBuilder(); guildUserCommand.WithName("Guild User Command"); guildMessageCommand.WithName("Guild Message Command"); var globalUserCommand = new UserCommandBuilder(); globalUserCommand.WithName("Global User Command"); var globalMessageCommand = new MessageCommandBuilder(); globalMessageCommand.WithName("Global Message Command"); try { await guild.BulkOverwriteApplicationCommandAsync(new ApplicationCommandProperties[] { guildUserCommand.Build(), guildMessageCommand.Build() }); await client.BulkOverwriteGlobalApplicationCommandsAsync(new ApplicationCommandProperties[] { globalUserCommand.Build(), globalMessageCommand.Build() }); } catch(ApplicationCommandException exception) { var json = JsonConvert.SerializeObject(exception.Error, Formatting.Indented); Console.WriteLine(json); } } ``` -------------------------------- ### Stacking Gateway Intents Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/breakings/v2_to_v3_guide.md This example demonstrates how to combine multiple Gateway Intents using the bitwise OR operator, which is a common practice when specific intents are required. ```cs GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | .. ``` -------------------------------- ### Publishing for Framework-Dependent Deployment Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/deployment/deployment.md Use this command to publish your application for framework-dependent deployment. The target machine requires the .NET runtime to be installed. ```bash dotnet publish -c Release ``` -------------------------------- ### CommandExecuted Event Demo Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/post-execution.md This example shows how to use the CommandExecuted event to streamline post-execution logic, avoiding drawbacks associated with RunMode.Async. ```csharp private Task OnCommandExecutedAsync(Optional command, Discord.IUser user, CommandResult result) { // Do your post-execution logic here. // You can check result.ErrorReason, result.Error, etc. return Task.CompletedTask; } // In your constructor: Commands.CommandExecuted += OnCommandExecutedAsync; ``` -------------------------------- ### Example - Creating a Custom Precondition Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/preconditions.md Create a custom precondition by inheriting from PreconditionAttribute and overriding CheckPermissionsAsync. Return PreconditionResult.FromSuccess if conditions are met, otherwise return PreconditionResult.FromError. ```csharp using System; using System.Threading.Tasks; using Discord; using Discord.Commands; public class RequireRoleAttribute : PreconditionAttribute { private readonly GuildPermission _permission; public RequireRoleAttribute(GuildPermission permission) { _permission = permission; } public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services) { if (context.User is IGuildUser guildUser) { if (guildUser.GuildPermissions.Has(_permission)) { return PreconditionResult.FromSuccess(); } else { return PreconditionResult.FromError($"User does not have the required permission: {_permission}"); } } else { return PreconditionResult.FromError("This command can only be used in a guild."); } } } public class MyModule : ModuleBase { [Command("secret")] [RequireRole(GuildPermission.ManageMessages)] public async Task SecretAsync() { await ReplyAsync("You have the required role!"); } } ``` -------------------------------- ### Property Injection Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/injection.md Inject services through public properties. Be aware that missing services in property injection will cause an error and will not fall back to a constructor. ```csharp using Discord.WebSocket; namespace MyBot.Services { public class MyService { public DiscordSocketClient Client { get; set; } } } ``` -------------------------------- ### Create and Connect Discord Bot Client Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/getting_started/first-bot.md This C# code snippet demonstrates how to create a DiscordSocketClient, hook up a log handler, log in with a bot token, and start the client. Ensure your token is kept secure and not hardcoded in production. ```csharp await using var client = new DiscordSocketClient(); client.Log += LogAsync; // Replace with your bot's token await client.LoginAsync(TokenType.Bot, "YOUR_BOT_TOKEN"); await client.StartAsync(); // Block the main method from exiting await Task.Delay(-1); ``` -------------------------------- ### Configure Gateway Intents in DiscordSocketConfig Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/breakings/v2_to_v3_guide.md When upgrading to Discord.NET v3, GatewayIntents must be specified in the DiscordSocketConfig. This example shows how to set the intents during client initialization. ```cs var config = new DiscordSocketConfig() { .. // Other config options can be presented here. GatewayIntents = GatewayIntents.All } _client = new DiscordSocketClient(config); ``` -------------------------------- ### Markdown Link Syntax Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/CONTRIBUTING.md Use the long syntax for creating links in Markdown documentation, especially when referencing API documentation. ```markdown Please consult the [API Documentation] for more information. [API Documentation]: xref:System.String ``` -------------------------------- ### XML Docstring Summary Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/CONTRIBUTING.md Use concise verbs for the `` tag in XML documentation. Keep the summary under 3 lines; use `` for longer explanations. ```csharp /// Gets or sets the guild user in this object. public IGuildUser GuildUser { get; set; } ``` -------------------------------- ### Modal Command Implementation Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md A modal command requires its last parameter to be an implementation of IModal. This example shows a basic modal structure. ```csharp public class ModalCommand : InteractionModuleBase { [SlashCommand("modal", "description")] public async Task ModalCommandAsync(MyModal modal) { await RespondAsync("Thanks for submitting the modal!", components: modal.Build()); } } public class MyModal : Modal { public MyModal() { Title = "My Modal"; } [ModalTextInput("input_id", TextInputStyle.Short, "Enter text", maxLength: 100)] public string MyTextInput { get; set; } } ``` -------------------------------- ### Constructor Injection Example Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/injection.md Inject services via the constructor for automatic readonly field assignment. Ensure both the service and the target class are registered with the IServiceProvider. ```csharp using Discord.WebSocket; namespace MyBot.Services { public class MyService { private readonly DiscordSocketClient _client; public MyService(DiscordSocketClient client) { _client = client; } } } ``` -------------------------------- ### Handle Slash Command Interaction Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_basics/application-commands/slash-commands/parameters.md Processes incoming slash command interactions. This example demonstrates how to route commands to specific handler methods and extract parameters, such as a 'SocketGuildUser', from the command data to perform actions. ```csharp private async Task SlashCommandHandler(SocketSlashCommand command) { // Let's add a switch statement for the command name so we can handle multiple commands in one event. switch(command.Data.Name) { case "list-roles": await HandleListRoleCommand(command); break; } } private async Task HandleListRoleCommand(SocketSlashCommand command) { // We need to extract the user parameter from the command. since we only have one option and it's required, we can just use the first option. var guildUser = (SocketGuildUser)command.Data.Options.First().Value; // We remove the everyone role and select the mention of each role. var roleList = string.Join(",\n", guildUser.Roles.Where(x => !x.IsEveryone).Select(x => x.Mention)); var embedBuiler = new EmbedBuilder() .WithAuthor(guildUser.ToString(), guildUser.GetAvatarUrl() ?? guildUser.GetDefaultAvatarUrl()) .WithTitle("Roles") .WithDescription(roleList) .WithColor(Color.Green) .WithCurrentTimestamp(); // Now, Let's respond with the embed. await command.RespondAsync(embed: embedBuiler.Build()); } ``` -------------------------------- ### Executing the Service Activator Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/scaling.md Call the ActivateAsync method on the service activator to start all registered services that implement the IService interface. This method iterates through and initializes each service. ```csharp await activator.ActivateAsync(); ``` -------------------------------- ### Handle Command Execution Errors with CommandException Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Commands/CommandException.Overwrite.md Log command execution errors by checking if the exception is a CommandException. This example shows how to extract details about the failed command, its context, and the user who invoked it. ```csharp public Task LogHandlerAsync(LogMessage logMessage) { // Note that this casting method requires C#7 and up. if (logMessage?.Exception is CommandException cmdEx) { Console.WriteLine($"{cmdEx.GetBaseException().GetType()} was thrown while executing {cmdEx.Command.Aliases.First()} in {cmdEx.Context.Channel} by {cmdEx.Context.User}."); } return Task.CompletedTask; } ``` -------------------------------- ### Build Documentation with DocFX Source: https://github.com/discord-net/discord.net/blob/dev/docs/README.md Use this command to build the documentation. Add `--serve` to preview locally. ```bash docfx docs/docfx.json ``` ```bash docfx docs/docfx.json --serve ``` -------------------------------- ### Example Enum TypeConverter Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/typeconverters.md This code snippet provides an example implementation of a TypeConverter for enum types, demonstrating how to handle parsing and configuration for enums. ```csharp using Discord.Interactions; using System; namespace Samples.TypeConverters; public class EnumConverter : TypeConverter where T : Enum { public override ApplicationCommandOptionType GetDiscordType() => ApplicationCommandOptionType.String; public override Task ReadAsync(IInteractionContext context, ApplicationCommandParameterInfo parameter, CancellationToken cancellationToken) { if (Enum.TryParse(parameter.Value.ToString(), out var value)) return Task.FromResult(TypeConverterResult.FromSuccess(value)); return Task.FromResult(TypeConverterResult.FromError(InteractionCommandResult.BadArgument, "Could not convert to enum.")); } public override string ToString(object value) => value.ToString(); } ``` -------------------------------- ### Building the Program with DI Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/basics.md This snippet shows the basic structure for a .NET application that utilizes dependency injection. It sets up the necessary services and builds a service provider. ```csharp using Discord.WebSocket; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var host = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { // Register your services here services.AddSingleton(); services.AddSingleton(); }) .Build(); var client = host.Services.GetRequiredService(); await client.LoginAsync(TokenType.Bot, "YOUR_BOT_TOKEN"); await client.StartAsync(); // Keep the console alive await Task.Delay(-1); ``` -------------------------------- ### Create Global and Guild Slash Commands Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_basics/application-commands/slash-commands/creating-slash-commands.md Use the Ready event to create global and guild slash commands. Guild commands are created using `guild.CreateApplicationCommandAsync`, while global commands use `client.CreateGlobalApplicationCommandAsync`. Note that global commands can take up to an hour to register. ```cs client.Ready += Client_Ready; ... public async Task Client_Ready() { // Let's build a guild command! We're going to need a guild so lets just put that in a variable. var guild = client.GetGuild(guildId); // Next, lets create our slash command builder. This is like the embed builder but for slash commands. var guildCommand = new SlashCommandBuilder(); // Note: Names have to be all lowercase and match the regular expression ^[\w-]{3,32}$ guildCommand.WithName("first-command"); // Descriptions can have a max length of 100. guildCommand.WithDescription("This is my first guild slash command!"); // Let's do our global command var globalCommand = new SlashCommandBuilder(); globalCommand.WithName("first-global-command"); globalCommand.WithDescription("This is my first global slash command"); try { // Now that we have our builder, we can call the CreateApplicationCommandAsync method to make our slash command. await guild.CreateApplicationCommandAsync(guildCommand.Build()); // With global commands we don't need the guild. await client.CreateGlobalApplicationCommandAsync(globalCommand.Build()); // Using the ready event is a simple implementation for the sake of the example. Suitable for testing and development. // For a production bot, it is recommended to only run the CreateGlobalApplicationCommandAsync() once for each command. } catch(HttpException exception) { // If our command was invalid, we should catch an HttpException. This exception contains the Discord error code, the request object that was sent, the reason of the exception and a list of of errors to explain what went wrong with the request. You can serialize the Error field in the exception to get a visual of where your error is. var json = JsonConvert.SerializeObject(exception.Errors, Formatting.Indented); // You can send this error somewhere or just print it to the console, for this example we're just going to print it. Console.WriteLine(json); } } ``` -------------------------------- ### UserComparer Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/DiscordComparers.Overwrites.md Gets an IEqualityComparer to be used to compare users. ```APIDOC ## UserComparer ### Description Gets an [IEqualityComparer](xref:System.Collections.Generic.IEqualityComparer`1)<> to be used to compare users. ### Method GET ### Endpoint N/A (This is a static property/method, not an HTTP endpoint) ### Parameters None ### Request Example None ### Response #### Success Response (200) An instance of IEqualityComparer`1 for IUser. #### Response Example None ``` -------------------------------- ### Building the Service Collection Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/basics.md Demonstrates how to configure and build the service collection, which is essential for managing your application's dependencies. It shows registering the DiscordSocketConfig before the client. ```csharp var collection = new ServiceCollection(); // Register Discord.Net services collection.AddSingleton(new DiscordSocketConfig() { // Add your configuration here LogLevel = LogSeverity.Verbose }); collection.AddSingleton(); var provider = collection.BuildServiceProvider(); ``` -------------------------------- ### RoleComparer Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/DiscordComparers.Overwrites.md Gets an IEqualityComparer to be used to compare roles. ```APIDOC ## RoleComparer ### Description Gets an [IEqualityComparer](xref:System.Collections.Generic.IEqualityComparer`1)<> to be used to compare roles. ### Method GET ### Endpoint N/A (This is a static property/method, not an HTTP endpoint) ### Parameters None ### Request Example None ### Response #### Success Response (200) An instance of IEqualityComparer`1 for IRole. #### Response Example None ``` -------------------------------- ### MessageComparer Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/DiscordComparers.Overwrites.md Gets an IEqualityComparer to be used to compare messages. ```APIDOC ## MessageComparer ### Description Gets an [IEqualityComparer](xref:System.Collections.Generic.IEqualityComparer`1)<> to be used to compare messages. ### Method GET ### Endpoint N/A (This is a static property/method, not an HTTP endpoint) ### Parameters None ### Request Example None ### Response #### Success Response (200) An instance of IEqualityComparer`1 for IMessage. #### Response Example None ``` -------------------------------- ### GuildComparer Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/DiscordComparers.Overwrites.md Gets an IEqualityComparer to be used to compare guilds. ```APIDOC ## GuildComparer ### Description Gets an [IEqualityComparer](xref:System.Collections.Generic.IEqualityComparer`1)<> to be used to compare guilds. ### Method GET ### Endpoint N/A (This is a static property/method, not an HTTP endpoint) ### Parameters None ### Request Example None ### Response #### Success Response (200) An instance of IEqualityComparer`1 for IGuild. #### Response Example None ``` -------------------------------- ### ChannelComparer Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/DiscordComparers.Overwrites.md Gets an IEqualityComparer to be used to compare channels. ```APIDOC ## ChannelComparer ### Description Gets an [IEqualityComparer](xref:System.Collections.Generic.IEqualityComparer`1)<> to be used to compare channels. ### Method GET ### Endpoint N/A (This is a static property/method, not an HTTP endpoint) ### Parameters None ### Request Example None ### Response #### Success Response (200) An instance of IEqualityComparer`1 for IChannel. #### Response Example None ``` -------------------------------- ### Get Guild Events Async Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/guild_events/intro.md Retrieve all events within a guild asynchronously. This method is available on a guild object. ```csharp var guildEvents = await guild.GetEventsAsync(); ``` -------------------------------- ### Creating Singleton Services Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/services.md Create singleton services to maintain state across multiple command or interaction executions. This is recommended because modules are transient and reinstantiate on each request. ```csharp public class MySingletonService { public int Counter { get; private set; } = 0; public void DoSomething() { Counter++; Console.WriteLine($"Singleton service called {Counter} times."); } } public class MyTransientService { public void DoSomethingElse() { Console.WriteLine("Transient service called."); } } ``` -------------------------------- ### Get Current User's Connections Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/bearer_token/bearer_token_guide.md Retrieve the current user's connections to other platforms. This requires the 'connections' scope. ```csharp var connections = await client.GetConnectionsAsync(); Console.WriteLine($"Connections: {string.Join(", ", connections.Select(c => c.Type))}"); ``` -------------------------------- ### Create FFmpeg Process for Audio Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/voice/sending-voice.md Initiate an FFmpeg process to stream audio. Ensure FFmpeg is in your system's PATH or alongside your bot's executable. The process must output PCM audio at 48000hz. ```csharp var ffmpeg = Process.Start(new ProcessStartInfo { FileName = "ffmpeg", Arguments = "-i pipe:0 -f s16le -ar 48000 -ac 2 pipe:1", UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true }); ``` -------------------------------- ### CommandService Log Event for Exceptions Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/text_commands/post-execution.md This example demonstrates how to use the CommandService.Log event to catch and handle exceptions thrown during command execution. ```csharp private Task OnLogAsync(LogMessage msg) { if (msg.Exception is CommandException cmdEx) { // Do something with the exception Console.WriteLine($"Command exception: {cmdEx.Message} - {cmdEx.InnerException?.Message}"); } else { // Log other messages Console.WriteLine(msg.Message); } return Task.CompletedTask; } // In your constructor: Commands.Log += OnLogAsync; ``` -------------------------------- ### Basic EmbedBuilder Usage Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/EmbedBuilder.Overwrites.md Demonstrates how to create and populate an EmbedBuilder with various properties like title, description, author, footer, color, and timestamp. The embed is built and then sent. ```csharp var embed = new EmbedBuilder { // Embed property can be set within object initializer Title = "Hello world!", Description = "I am a description set by initializer." }; // Or with methods embed.AddField("Field title", "Field value. I also support [hyperlink markdown](https://example.com)!") .WithAuthor(Context.Client.CurrentUser) .WithFooter(footer => footer.Text = "I am a footer.") .WithColor(Color.Blue) .WithTitle("I overwrote \"Hello world!\"") .WithDescription("I am a description.") .WithUrl("https://example.com") .WithCurrentTimestamp(); //Your embed needs to be built before it is able to be sent await ReplyAsync(embed: embed.Build()); ``` -------------------------------- ### Registering Services for DI Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/services.md Register your services with the IServiceProvider to make them available for injection into your modules. The DiscordSocketClient and IConfiguration are automatically acknowledged if registered. ```csharp await client.UseInteractionServiceAsync(new InteractionService(client.Rest, discordConfig)); // Register your services services.AddSingleton(); services.AddTransient(); // Build the service provider var provider = services.BuildServiceProvider(); // Add the service provider to the client client.AddDependencyInjection(provider); ``` -------------------------------- ### Applying DI in RunAsync Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/dependency_injection/basics.md Illustrates how to retrieve registered services, such as the DiscordSocketClient, from the service provider within your application's main execution flow. ```csharp public async Task RunAsync() { // Get the DiscordSocketClient from the service provider var client = _provider.GetRequiredService(); client.Log += LogAsync; // Replace with your bot token await client.LoginAsync(TokenType.Bot, "YOUR_BOT_TOKEN"); await client.StartAsync(); // Here we sample aПосле того, как вы построили свой провайдер в конструкторе класса Program, провайдер теперь доступен внутри экземпляра, который вы активно используете. Через провайдера мы можем запросить DiscordSocketClient, который мы зарегистрировали ранее. // Keep the console alive await Task.Delay(Timeout.Infinite); } ``` -------------------------------- ### Slash Command with Choice Attribute Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md Add predefined choices to a slash command parameter using the ChoiceAttribute. This example demonstrates string choices. ```csharp using Discord.Interactions; public class IntroModule : InteractionModuleBase { [SlashCommand("choose", "Chooses an option.")] public async Task ChooseCommand( [Choice("Option 1", "one")] [Choice("Option 2", "two")] [Summary("The option to choose.")] string choice) { await RespondAsync($"You chose: {choice}"); } } ``` -------------------------------- ### Override IUser TypeReader Source: https://github.com/discord-net/discord.net/blob/dev/docs/_overwrites/Common/OverrideTypeReaderAttribute.Overwrites.md Use this attribute to specify a custom TypeReader for a command parameter. This example overrides the default IUser TypeReader to MyUserTypeReader. ```csharp public async Task PrintUserAsync( [OverrideTypeReader(typeof(MyUserTypeReader))] IUser user) { //... } ``` -------------------------------- ### Get All Guild Event Users Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/guild_events/getting-event-users.md Retrieve all users interested in an event and flatten the results into a single collection. This method returns an async enumerable. ```csharp // get all users and flatten the result into one collection. var users = await event.GetUsersAsync().FlattenAsync(); ``` -------------------------------- ### Slash Command with ChannelTypes Attribute Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md Restrict the allowed channel types for an IChannel parameter using the ChannelTypesAttribute. This example allows only Stage and Text channels. ```csharp using Discord.Interactions; using Discord.WebSocket; public class IntroModule : InteractionModuleBase { [SlashCommand("channel-test", "Tests channel type restriction.")] public async Task ChannelTestCommand( [ChannelTypes(ChannelType.Stage, ChannelType.Text)] [Summary("A text or stage channel.")] IChannel channel) { await RespondAsync($"You provided channel: {channel.Name}"); } } ``` -------------------------------- ### Component Container Generation Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/components_v2/advanced.md This C# code demonstrates how to generate the main component container using Components V2. ```csharp using Discord.WebSocket; using Discord.Interactions; public class ComponentBuilderV2Sample { public static MessageComponent BuildComponent() => new ComponentBuilder() .WithButton("Click Me", "my_button_id") .Build(); } ``` -------------------------------- ### Define an Example Modal Class Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/modals.md Define a modal by creating a class that inherits from IModal and implements the Title property. This is the recommended way to create modals. ```csharp public class ExampleModal : IModal { public string Title => "Example Modal"; [ModalTextInput("input_id", "Short answer", 100)] public string ShortAnswer { get; set; } [ModalTextInput("paragraph_id", "Paragraph", 1000, TextInputStyle.Paragraph)] public string Paragraph { get; set; } } ``` -------------------------------- ### Initialize Interaction Service Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/intro.md Instantiates the InteractionService, optionally configuring its behavior. The DiscordSocketClient's REST client is passed as a dependency. ```csharp var _interactionService = new InteractionService(_client.Rest); ``` -------------------------------- ### Implement an AutocompleteHandler Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/autocompletion.md Inherit from AutocompleteHandler and implement GenerateSuggestionsAsync to provide autocompletion options. Use AutocompletionResult.FromSuccess with a list of AutocompleteResult for suggestions, or AutocompletionResult.FromSuccess() for no matches. AutocompletionResult.FromError() should be used for error handling. ```csharp using Discord; using Discord.Interactions; public class MyAutocompleteHandler : AutocompleteHandler { public override async Task GenerateSuggestionsAsync(IInteractionContext context, IParameterInfo parameter, AutocompleteParameter value, CancellationToken cancellationToken) { // Example: Filter options based on user input var options = new List { new AutocompleteResult("Option 1", "option1"), new AutocompleteResult("Option 2", "option2"), new AutocompleteResult("Option 3", "option3") }; var filteredOptions = options.Where(x => x.Name.Contains(value.RawValue, StringComparison.OrdinalIgnoreCase)); if (!filteredOptions.Any()) { return AutocompletionResult.FromSuccess(); // No options match } return AutocompletionResult.FromSuccess(filteredOptions); } } ``` -------------------------------- ### C# Logging Sample in Discord.Net Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/concepts/logging.md This sample demonstrates how to hook into the Discord client's `Log` event to receive and process log messages. It's recommended to use an established function for handling logs, as many addons require a reference to a logging function. ```csharp using Discord; using Discord.Commands; using Microsoft.Extensions.DependencyInjection; using System; using System.Threading.Tasks; public class Logging { private readonly IServiceProvider _provider; public Logging(IServiceProvider provider) { _provider = provider; } public async Task OnLogAsync(LogMessage message) { // Optionally, you can use the logging service to log messages // var loggingService = _provider.GetService(); // await loggingService.OnLogAsync(message); // Log to console Console.WriteLine(message.ToString()); // Handle specific log levels or message types if needed switch (message.Severity) { case LogSeverity.Critical: case LogSeverity.Error: // Handle critical or error logs break; case LogSeverity.Warning: // Handle warning logs break; case LogSeverity.Info: // Handle informational logs break; case LogSeverity.Verbose: case LogSeverity.Debug: // Handle verbose or debug logs break; } // If the log message is related to a CommandException, you can access command context if (message.Exception is CommandException cmdException) { // Example: Log the command that failed and the user who invoked it Console.WriteLine($"Command failed: {cmdException.Command.Name} invoked by {cmdException.Context.User}"); } } // Example of how to register the handler with a DiscordSocketClient public void RegisterClientLogging(DiscordSocketClient client) { client.Log += OnLogAsync; } // Example of how to register the handler with a CommandService public void RegisterCommandServiceLogging(CommandService commandService) { commandService.Log += OnLogAsync; } } // Example of a simple LoggingService (optional) public class LoggingService { public Task OnLogAsync(LogMessage message) { // Implement your custom logging logic here, e.g., writing to a file, database, or external service Console.WriteLine($"[LoggingService] {message.Severity}: {message.Message}"); if (message.Exception != null) { Console.WriteLine($"[LoggingService] Exception: {message.Exception}"); } return Task.CompletedTask; } } ``` -------------------------------- ### Respond with Select Menu Component Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_basics/message-components/advanced.md Responds to a command with an ephemeral message containing a select menu. The select menu is configured with options and a placeholder. Ensure the `SelectMenuBuilder` and `ComponentBuilder` are correctly instantiated and populated. ```csharp var menu = new SelectMenuBuilder() { CustomId = "select-1", Placeholder = "Select Somthing!", MaxValues = 1, MinValues = 1, }; menu.AddOption("Meh", "1", "Its not gaming.") .AddOption("Ish", "2", "Some would say that this is gaming.") .AddOption("Moderate", "3", "It could pass as gaming") .AddOption("Confirmed", "4", "We are gaming") .AddOption("Excellent", "5", "It is renowned as gaming nation wide", new Emoji("🔥")); var components = new ComponentBuilder() .WithSelectMenu(menu); await arg.RespondAsync("On a scale of one to five, how gaming is this?", component: components.Build(), ephemeral: true); break; ``` -------------------------------- ### Define a Command to Spawn Components Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_basics/message-components/intro.md This C# code defines a command that will later be used to send a message with components. Ensure you have the necessary Discord.Net command framework set up. ```csharp using Discord.Commands; public class MyModule : ModuleBase { [Command("spawner")] public async Task Spawn() { // Reply with some components } } ``` -------------------------------- ### Get Current User Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/bearer_token/bearer_token_guide.md Fetch the current user's information after logging in. The user object is available in the CurrentUser property. Use GetCurrentUserAsync() to refresh. ```csharp var user = await client.GetCurrentUserAsync(); Console.WriteLine($"User: {user.Username}"); ``` -------------------------------- ### Setting Command RunMode with CommandAttribute Source: https://github.com/discord-net/discord.net/blob/dev/docs/faq/text_commands/general.md Illustrates how to set the execution mode for a specific command using the `CommandAttribute`. Use `RunMode.Async` to prevent long-running commands from blocking the gateway thread. ```csharp using Discord.Commands; [Command("longcommand", RunMode = RunMode.Async)] public async Task LongCommandAsync() { // Command logic here await Task.Delay(5000); // Simulate a long-running operation await ReplyAsync("Command finished."); } ``` -------------------------------- ### Configuring Enum Options for Select Menus Source: https://github.com/discord-net/discord.net/blob/dev/docs/guides/int_framework/modals.md Demonstrates how to use attributes like `EnumOption`, `ChoiceDisplay`, and `Hide` to configure options for enum properties used in select menus, checkbox groups, or radio groups. This allows for custom descriptions, default values, emotes, and conditional hiding of options. ```csharp public enum ModalEnum { [EnumOption(Description = "Some description 1")] Value1 = 1 << 0, [EnumOption(Description = "Some description 2", IsDefault = true)] Value2 = 1 << 1, [EnumOption(Description = "Some description 3", Emote = "🦫")] Value3 = 1 << 2, [EnumOption(Description = "Some description 69")] [ChoiceDisplay("Value 42")] Value69 = 1 << 3, [Hide] SuperSecretOption = 1 << 31, } ```