diff --git a/Documentation/docfx.json b/Documentation/docfx.json index 60c5f1033..23d7d1d45 100644 --- a/Documentation/docfx.json +++ b/Documentation/docfx.json @@ -22,25 +22,25 @@ }, "content": [ { - "files": ["docs/**.yml", "docs/index.md"] + "files": [ "docs/**.yml", "docs/index.md" ] }, { - "files": ["guides/**.md", "guides/**/toc.yml", "toc.yml", "index.md"] + "files": [ "guides/**.md", "guides/**/toc.yml", "toc.yml", "index.md" ] } ], "resource": [ { - "files": ["images/**", "favicon.ico", "logo.svg", "robots.txt"] + "files": [ "images/**", "favicon.ico", "logo.svg", "robots.txt" ] } ], "overwrite": [ { - "files": ["apidoc/**.md"], - "exclude": ["obj/**", "_site/**"] + "files": [ "apidoc/**.md" ], + "exclude": [ "obj/**", "_site/**" ] } ], "dest": "_site", - "template": ["default", "templates/NetCord"], + "template": [ "default", "templates/NetCord" ], "markdownEngineName": "markdig", "globalMetadata": { "_appDescription": "NetCord – the modern and fully customizable C# Discord library", @@ -58,6 +58,6 @@ "!docs/**": false } }, - "xrefService": "https://xref.docs.microsoft.com/query?uid={uid}" + "xref": [ "https://learn.microsoft.com/en-us/dotnet/.xrefmap.json" ] } } diff --git a/Documentation/guides/services/component-interactions/Parameters/ExampleModule.cs b/Documentation/guides/services/component-interactions/Parameters/ExampleModule.cs new file mode 100644 index 000000000..49b402314 --- /dev/null +++ b/Documentation/guides/services/component-interactions/Parameters/ExampleModule.cs @@ -0,0 +1,44 @@ +using NetCord; +using NetCord.Rest; +using NetCord.Services.ComponentInteractions; + +namespace MyBot; + +public class ExampleModule : ComponentInteractionModule +{ + [ComponentInteraction("publish")] + public static InteractionMessageProperties Publish(string content) + { + return new InteractionMessageProperties() + .AddEmbeds(new EmbedProperties().WithTitle("Publication") + .WithDescription(content) + .WithColor(new Color(0x7777FF))); + } + + [ComponentInteraction("delete")] + public async Task DeleteAsync(params ulong[] messageIds) + { + await Context.Channel.DeleteMessagesAsync(messageIds); + + return "The messages have been deleted successfully."; + } + + [ComponentInteraction("unban")] + public async Task UnbanAsync(ulong userId, string reason = "No reason provided.") + { + await Context.Guild!.UnbanUserAsync(userId, new RestRequestProperties().WithAuditLogReason(reason)); + + return $"The user has been unbanned successfully."; + } + + [ComponentInteraction("bug report")] + public static InteractionMessageProperties BugReport(string title, string body = "No body provided.", string category = "None") + { + return new InteractionMessageProperties() + .AddEmbeds(new EmbedProperties() + .WithColor(new(0xFF0000)) + .WithTitle(title) + .WithDescription(body) + .WithFooter(new EmbedFooterProperties().WithText($"Category: {category}"))); + } +} diff --git a/Documentation/guides/services/component-interactions/Parameters/Parameters.csproj b/Documentation/guides/services/component-interactions/Parameters/Parameters.csproj new file mode 100644 index 000000000..9a0b94917 --- /dev/null +++ b/Documentation/guides/services/component-interactions/Parameters/Parameters.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + latest + enable + MyBot + MyBot + + + + + + + + diff --git a/Documentation/guides/services/component-interactions/parameters.md b/Documentation/guides/services/component-interactions/parameters.md index 966ebb691..2d513968e 100644 --- a/Documentation/guides/services/component-interactions/parameters.md +++ b/Documentation/guides/services/component-interactions/parameters.md @@ -1,12 +1,83 @@ # Parameters -You can specify parameters by separating them with a separator (default: `:`) in `customId`, for example `unban:userId`. +Component interaction parameters allow you to pass data to components during their creation. For example, you can pass a user ID to ban or the content of a message to send. By default, parameters are separated by a colon (`:`), but this behavior can be customized by setting @NetCord.Services.ComponentInteractions.ComponentInteractionServiceConfiguration`1.ParameterSeparator in the configuration. This guide assumes the default separator is used. + +## Type Readers + +NetCord uses type readers to convert parameters to their respective types. The following table lists the default type readers and the types they read. + +
+Expand to see the full list of built-in type readers. + +| Type Reader | Type Read | +|--------------------------------------------------------------------------------------|------------------------------------------------| +| @NetCord.Services.ComponentInteractions.TypeReaders.BigIntegerTypeReader`1 | @System.Numerics.BigInteger | +| @NetCord.Services.ComponentInteractions.TypeReaders.BooleanTypeReader`1 | @System.Boolean | +| @NetCord.Services.ComponentInteractions.TypeReaders.ByteTypeReader`1 | @System.Byte | +| @NetCord.Services.ComponentInteractions.TypeReaders.CharTypeReader`1 | @System.Char | +| @NetCord.Services.ComponentInteractions.TypeReaders.CodeBlockTypeReader`1 | @NetCord.CodeBlock | +| @NetCord.Services.ComponentInteractions.TypeReaders.DateOnlyTypeReader`1 | @System.DateOnly | +| @NetCord.Services.ComponentInteractions.TypeReaders.DateTimeOffsetTypeReader`1 | @System.DateTimeOffset | +| @NetCord.Services.ComponentInteractions.TypeReaders.DateTimeTypeReader`1 | @System.DateTime | +| @NetCord.Services.ComponentInteractions.TypeReaders.DecimalTypeReader`1 | @System.Decimal | +| @NetCord.Services.ComponentInteractions.TypeReaders.DoubleTypeReader`1 | @System.Double | +| @NetCord.Services.ComponentInteractions.TypeReaders.EnumTypeReader`1 | @System.Enum | +| @NetCord.Services.ComponentInteractions.TypeReaders.GuildUserTypeReader`1 | @NetCord.GuildUser | +| @NetCord.Services.ComponentInteractions.TypeReaders.HalfTypeReader`1 | @System.Half | +| @NetCord.Services.ComponentInteractions.TypeReaders.Int128TypeReader`1 | @System.Int128 | +| @NetCord.Services.ComponentInteractions.TypeReaders.Int16TypeReader`1 | @System.Int16 | +| @NetCord.Services.ComponentInteractions.TypeReaders.Int32TypeReader`1 | @System.Int32 | +| @NetCord.Services.ComponentInteractions.TypeReaders.Int64TypeReader`1 | @System.Int64 | +| @NetCord.Services.ComponentInteractions.TypeReaders.IntPtrTypeReader`1 | @System.IntPtr | +| @NetCord.Services.ComponentInteractions.TypeReaders.ReadOnlyMemoryOfCharTypeReader`1 | @"System.ReadOnlyMemory`1?text=ReadOnlyMemory" | +| @NetCord.Services.ComponentInteractions.TypeReaders.SByteTypeReader`1 | @System.SByte | +| @NetCord.Services.ComponentInteractions.TypeReaders.SingleTypeReader`1 | @System.Single | +| @NetCord.Services.ComponentInteractions.TypeReaders.StringTypeReader`1 | @System.String | +| @NetCord.Services.ComponentInteractions.TypeReaders.TimeOnlyTypeReader`1 | @System.TimeOnly | +| @NetCord.Services.ComponentInteractions.TypeReaders.TimeSpanTypeReader`1 | @System.TimeSpan | +| @NetCord.Services.ComponentInteractions.TypeReaders.TimestampTypeReader`1 | @NetCord.Timestamp | +| @NetCord.Services.ComponentInteractions.TypeReaders.UInt128TypeReader`1 | @System.UInt128 | +| @NetCord.Services.ComponentInteractions.TypeReaders.UInt16TypeReader`1 | @System.UInt16 | +| @NetCord.Services.ComponentInteractions.TypeReaders.UInt32TypeReader`1 | @System.UInt32 | +| @NetCord.Services.ComponentInteractions.TypeReaders.UInt64TypeReader`1 | @System.UInt64 | +| @NetCord.Services.ComponentInteractions.TypeReaders.UIntPtrTypeReader`1 | @System.UIntPtr | +| @NetCord.Services.ComponentInteractions.TypeReaders.UriTypeReader`1 | @System.Uri | +| @NetCord.Services.ComponentInteractions.TypeReaders.UserIdTypeReader`1 | @NetCord.Services.UserId | + +
+ +
## Remainder -Last parameter always accepts rest of an input. -## Variable number of parameters -You can use `params` keyword to accept a variable number of parameters. +The last parameter is always considered a remainder. This means that it can contain any number of colons. This is useful when you want to pass a string that may contain colons. + +For example, using a custom ID like `publish:testing 1 2 3` would send an embed with the content `testing 1 2 3`. + +[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L9-L16)] + +## Variable Number of Parameters + +You can use the `params` keyword to accept a variable number of parameters. + +For example, a custom ID like `delete:931274046312701962:963913427661766717` would delete messages with the IDs `931274046312701962` and `963913427661766717`. + +[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L18-L24)] + +## Optional Parameters + +To mark parameters as optional, assign them a default value. + +For example, the following custom IDs can be used: +- `unban:735048387178659854:` (note the trailing `:` to indicate the omission of the `reason` parameter) to unban the user without specifying a reason. +- `unban:735048387178659854:proof of innocence` to unban the user and provide a reason. + +[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L26-L32)] + +In another example, with two optional parameters, you can use these custom IDs: +- `bug report:troll::` (note the two consecutive colons `::` at the end to indicate the omission of both `body` and `category` parameters) to create a bug report titled `troll` without a body or category. +- `bug report:Channel Disappeared:I can no longer find the general channel:` (note the trailing colon `:` to indicate the omission of the `category` parameter) to create a bug report with a title and body, but no category. +- `bug report:Bot Bug::Bot` (note the two consecutive colons `::` in the middle to indicate the omission of the `body` parameter) to create a bug report with a title and category but no body. +- `bug report:Wrong Channel Permissions:I am able to send messages in the announcements channel:Permissions` to create a bug report with all parameters specified. -## Optional parameters -To mark parameters as optional, give them a default value. +[!code-cs[ExampleModule.cs](Parameters/ExampleModule.cs#L34-L43)] diff --git a/NetCord.sln b/NetCord.sln index 3a9dc6ea6..6f6149f56 100644 --- a/NetCord.sln +++ b/NetCord.sln @@ -141,7 +141,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RestClientMethodAliasesGene EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocalizationsHosting", "Documentation\guides\services\application-commands\LocalizationsHosting\LocalizationsHosting.csproj", "{9E6C8288-7762-4F98-85B1-A3ED29EE0DFF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoiceEncryptionTest", "Tests\VoiceEncryptionTest\VoiceEncryptionTest.csproj", "{98A70693-9EC7-4965-BC8F-A5646723DAA2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoiceEncryptionTest", "Tests\VoiceEncryptionTest\VoiceEncryptionTest.csproj", "{98A70693-9EC7-4965-BC8F-A5646723DAA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Parameters", "Documentation\guides\services\component-interactions\Parameters\Parameters.csproj", "{C99E04D0-96EE-4671-980E-5183D2D6A72A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -353,6 +355,10 @@ Global {98A70693-9EC7-4965-BC8F-A5646723DAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {98A70693-9EC7-4965-BC8F-A5646723DAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {98A70693-9EC7-4965-BC8F-A5646723DAA2}.Release|Any CPU.Build.0 = Release|Any CPU + {C99E04D0-96EE-4671-980E-5183D2D6A72A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C99E04D0-96EE-4671-980E-5183D2D6A72A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C99E04D0-96EE-4671-980E-5183D2D6A72A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C99E04D0-96EE-4671-980E-5183D2D6A72A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -418,6 +424,7 @@ Global {941F7A6C-313B-481E-9EBC-2B82972F8649} = {0A9D75D2-B760-43E3-8A18-1BF2F629D0FB} {9E6C8288-7762-4F98-85B1-A3ED29EE0DFF} = {46E6F97B-83C3-4B66-8B0F-226D02DEC5A0} {98A70693-9EC7-4965-BC8F-A5646723DAA2} = {5E156987-5CC6-4873-B774-F41CBD7D3F3D} + {C99E04D0-96EE-4671-980E-5183D2D6A72A} = {5631D9FD-493B-40C6-85CC-D8742DF012CB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {945CA52C-0E28-4020-A241-BDE73D8384AA} diff --git a/Tests/NetCord.Test/Commands/StrangeCommands.cs b/Tests/NetCord.Test/Commands/StrangeCommands.cs index 7d25d7efc..b786906b5 100644 --- a/Tests/NetCord.Test/Commands/StrangeCommands.cs +++ b/Tests/NetCord.Test/Commands/StrangeCommands.cs @@ -295,7 +295,7 @@ public static Task StaticAsync(string x, params string[] s) } [Command("button")] - public Task ButtonAsync(string customId) + public Task ButtonAsync([CommandParameter(Remainder = true)] string customId) { return SendAsync(new() {