| @@ -1 +1,3 @@ | |||||
| github: quinchs | |||||
| open_collective: discordnet | open_collective: discordnet | ||||
| custom: https://paypal.me/quinchs | |||||
| @@ -1,5 +1,28 @@ | |||||
| # Changelog | # Changelog | ||||
| ## [3.6.1] - 2022-04-30 | |||||
| ### Added | |||||
| - #2272 add 50080 Error code (503e720) | |||||
| ### Fixed | |||||
| - #2267 Permissions v2 Invalid Operation Exception (a8f6075) | |||||
| - #2271 null user on interaction without bot scope (f2bb55e) | |||||
| - #2274 Implement fix for Custom Id Segments NRE (0d74c5c) | |||||
| ### Misc | |||||
| - 3.6.0 (27226f0) | |||||
| ## [3.6.0] - 2022-04-28 | |||||
| ### Added | |||||
| - #2136 Passing CustomId matches into contexts (4ce1801) | |||||
| - #2222 V2 Permissions (d98b3cc) | |||||
| ### Fixed | |||||
| - #2260 Guarding against empty descriptions in `SlashCommandBuilder`/`SlashCommandOptionBuilder` (0554ac2) | |||||
| - #2248 Fix SocketGuild not returning the AudioClient (daba58c) | |||||
| - #2254 Fix browser property (275b833) | |||||
| ## [3.5.0] - 2022-04-05 | ## [3.5.0] - 2022-04-05 | ||||
| ### Added | ### Added | ||||
| @@ -1,6 +1,6 @@ | |||||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
| <PropertyGroup> | <PropertyGroup> | ||||
| <VersionPrefix>3.5.0</VersionPrefix> | |||||
| <VersionPrefix>3.6.1</VersionPrefix> | |||||
| <LangVersion>latest</LangVersion> | <LangVersion>latest</LangVersion> | ||||
| <Authors>Discord.Net Contributors</Authors> | <Authors>Discord.Net Contributors</Authors> | ||||
| <PackageTags>discord;discordapp</PackageTags> | <PackageTags>discord;discordapp</PackageTags> | ||||
| @@ -1,4 +1,3 @@ | |||||
| # Discord.Net | |||||
| <p align="center"> | <p align="center"> | ||||
| <a href="https://discordnet.dev/" title="Click to visit the documentation!"> | <a href="https://discordnet.dev/" title="Click to visit the documentation!"> | ||||
| <img src="https://raw.githubusercontent.com/discord-net/Discord.Net/dev/docs/marketing/logo/SVG/Combinationmark%20White%20Border.svg" alt="Logo"> | <img src="https://raw.githubusercontent.com/discord-net/Discord.Net/dev/docs/marketing/logo/SVG/Combinationmark%20White%20Border.svg" alt="Logo"> | ||||
| @@ -60,7 +60,7 @@ | |||||
| "overwrite": "_overwrites/**/**.md", | "overwrite": "_overwrites/**/**.md", | ||||
| "globalMetadata": { | "globalMetadata": { | ||||
| "_appTitle": "Discord.Net Documentation", | "_appTitle": "Discord.Net Documentation", | ||||
| "_appFooter": "Discord.Net (c) 2015-2022 3.5.0", | |||||
| "_appFooter": "Discord.Net (c) 2015-2022 3.6.1", | |||||
| "_enableSearch": true, | "_enableSearch": true, | ||||
| "_appLogoPath": "marketing/logo/SVG/Logomark Purple.svg", | "_appLogoPath": "marketing/logo/SVG/Logomark Purple.svg", | ||||
| "_appFaviconPath": "favicon.ico" | "_appFaviconPath": "favicon.ico" | ||||
| @@ -202,7 +202,7 @@ online in Discord. | |||||
| To create commands for your bot, you may choose from a variety of | To create commands for your bot, you may choose from a variety of | ||||
| command processors available. Throughout the guides, we will be using | command processors available. Throughout the guides, we will be using | ||||
| the one that Discord.Net ships with. @Guides.Commands.Intro will | |||||
| the one that Discord.Net ships with. @Guides.TextCommands.Intro will | |||||
| guide you through how to setup a program that is ready for | guide you through how to setup a program that is ready for | ||||
| [CommandService]. | [CommandService]. | ||||
| @@ -15,9 +15,10 @@ Slash commands can have a bunch of parameters, each their own type. Let's first | |||||
| | Integer | A number. | | | Integer | A number. | | ||||
| | Boolean | True or False. | | | Boolean | True or False. | | ||||
| | User | A user | | | User | A user | | ||||
| | Channel | A channel, this includes voice text and categories | | |||||
| | Role | A role. | | | Role | A role. | | ||||
| | Channel | A channel, this includes voice text and categories | | |||||
| | Mentionable | A role or a user. | | | Mentionable | A role or a user. | | ||||
| | File | A file | | |||||
| Each one of the parameter types has its own DNET type in the `SocketSlashCommandDataOption`'s Value field: | Each one of the parameter types has its own DNET type in the `SocketSlashCommandDataOption`'s Value field: | ||||
| | Name | C# Type | | | Name | C# Type | | ||||
| @@ -31,6 +32,7 @@ Each one of the parameter types has its own DNET type in the `SocketSlashCommand | |||||
| | Role | `SocketRole` | | | Role | `SocketRole` | | ||||
| | Channel | `SocketChannel` | | | Channel | `SocketChannel` | | ||||
| | Mentionable | `SocketUser`, `SocketGuildUser`, or `SocketRole` | | | Mentionable | `SocketUser`, `SocketGuildUser`, or `SocketRole` | | ||||
| | File | `IAttachment` | | |||||
| Let's start by making a command that takes in a user and lists their roles. | Let's start by making a command that takes in a user and lists their roles. | ||||
| @@ -158,6 +158,14 @@ Interaction service complex parameter constructors are prioritized in the follow | |||||
| 2. Constuctor tagged with `[ComplexParameterCtor]`. | 2. Constuctor tagged with `[ComplexParameterCtor]`. | ||||
| 3. Type's only public constuctor. | 3. Type's only public constuctor. | ||||
| #### DM Permissions | |||||
| You can use the [EnabledInDmAttribute] to configure whether a globally-scoped top level command should be enabled in Dms or not. Only works on top level commands. | |||||
| #### Default Member Permissions | |||||
| [DefaultMemberPermissionsAttribute] can be used when creating a command to set the permissions a user must have to use the command. Permission overwrites can be configured from the Integrations page of Guild Settings. [DefaultMemberPermissionsAttribute] cumulatively propagates down the class hierarchy until it reaches a top level command. This attribute can be only used on top level commands and will not work on commands that are nested in command groups. | |||||
| ## User Commands | ## User Commands | ||||
| A valid User Command must have the following structure: | A valid User Command must have the following structure: | ||||
| @@ -282,6 +290,8 @@ By nesting commands inside a module that is tagged with [GroupAttribute] you can | |||||
| > Although creating nested module stuctures are allowed, | > Although creating nested module stuctures are allowed, | ||||
| > you are not permitted to use more than 2 [GroupAttribute]'s in module hierarchy. | > you are not permitted to use more than 2 [GroupAttribute]'s in module hierarchy. | ||||
| [!code-csharp[Command Group Example](samples/intro/groupmodule.cs)] | |||||
| ## Executing Commands | ## Executing Commands | ||||
| Any of the following socket events can be used to execute commands: | Any of the following socket events can be used to execute commands: | ||||
| @@ -0,0 +1,59 @@ | |||||
| --- | |||||
| uid: Guides.IntFw.Perms | |||||
| title: How to handle permissions. | |||||
| --- | |||||
| # Permissions | |||||
| This page covers everything to know about setting up permissions for Slash & context commands. | |||||
| Application command (Slash, User & Message) permissions are set up at creation. | |||||
| When you add your commands to a guild or globally, the permissions will be set up from the attributes you defined. | |||||
| Commands that are added will only show up for members that meet the required permissions. | |||||
| There is no further internal handling, as Discord deals with this on its own. | |||||
| > [!WARNING] | |||||
| > Permissions can only be configured at top level commands. Not in subcommands. | |||||
| ## Disallowing commands in DM | |||||
| Commands can be blocked from being executed in DM if a guild is required to execute them in as followed: | |||||
| [!code-csharp[no-DM permission](samples/permissions/guild-only.cs)] | |||||
| > [!TIP] | |||||
| > This attribute only works on global-level commands. Commands that are registered in guilds alone do not have a need for it. | |||||
| ## Server permissions | |||||
| As previously shown, a command like ban can be blocked from being executed inside DMs, | |||||
| as there are no members to ban inside of a DM. However, for a command like this, | |||||
| we'll also want to make block it from being used by members that do not have the [permissions]. | |||||
| To do this, we can use the `DefaultMemberPermissions` attribute: | |||||
| [!code-csharp[Server permissions](samples/permissions/guild-perms.cs)] | |||||
| ### Stacking permissions | |||||
| If you want a user to have multiple [permissions] in order to execute a command, you can use the `|` operator, just like with setting up intents: | |||||
| [!code-csharp[Permission stacking](samples/permissions/perm-stacking.cs)] | |||||
| ### Nesting permissions | |||||
| Alternatively, permissions can also be nested. | |||||
| It will look for all uses of `DefaultMemberPermissions` up until the highest level class. | |||||
| The `EnabledInDm` attribute can be defined at top level as well, | |||||
| and will be set up for all of the commands & nested modules inside this class. | |||||
| [!code-csharp[Permission stacking](samples/permissions/perm-nesting.cs)] | |||||
| The amount of nesting you can do is realistically endless. | |||||
| > [!NOTE] | |||||
| > If the nested class is marked with `Group`, as required for setting up subcommands, this example will not work. | |||||
| > As mentioned before, subcommands cannot have seperate permissions from the top level command. | |||||
| [permissions]: xref:Discord.GuildPermission | |||||
| @@ -0,0 +1,21 @@ | |||||
| // You can put commands in groups | |||||
| [Group("group-name", "Group description")] | |||||
| public class CommandGroupModule : InteractionModuleBase<SocketInteractionContext> | |||||
| { | |||||
| // This command will look like | |||||
| // group-name ping | |||||
| [SlashCommand("ping", "Get a pong")] | |||||
| public async Task PongSubcommand() | |||||
| => await RespondAsync("Pong!"); | |||||
| // And even in sub-command groups | |||||
| [Group("subcommand-group-name", "Subcommand group description")] | |||||
| public class SubСommandGroupModule : InteractionModuleBase<SocketInteractionContext> | |||||
| { | |||||
| // This command will look like | |||||
| // group-name subcommand-group-name echo | |||||
| [SlashCommand("echo", "Echo an input")] | |||||
| public async Task EchoSubcommand(string input) | |||||
| => await RespondAsync(input); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,6 @@ | |||||
| [EnabledInDm(false)] | |||||
| [SlashCommand("ban", "Bans a user in this guild")] | |||||
| public async Task BanAsync(...) | |||||
| { | |||||
| ... | |||||
| } | |||||
| @@ -0,0 +1,7 @@ | |||||
| [EnabledInDm(false)] | |||||
| [DefaultMemberPermissions(GuildPermission.BanMembers)] | |||||
| [SlashCommand("ban", "Bans a user in this guild")] | |||||
| public async Task BanAsync(...) | |||||
| { | |||||
| ... | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| [EnabledInDm(true)] | |||||
| [DefaultMemberPermissions(GuildPermission.ViewChannels)] | |||||
| public class Module : InteractionModuleBase<SocketInteractionContext> | |||||
| { | |||||
| [DefaultMemberPermissions(GuildPermission.SendMessages)] | |||||
| public class NestedModule : InteractionModuleBase<SocketInteractionContext> | |||||
| { | |||||
| // While looking for more permissions, it has found 'ViewChannels' and 'SendMessages'. The result of this lookup will be: | |||||
| // ViewChannels + SendMessages + ManageMessages. | |||||
| // If these together are not found for target user, the command will not show up for them. | |||||
| [DefaultMemberPermissions(GuildPermission.ManageMessages)] | |||||
| [SlashCommand("ping", "Pong!")] | |||||
| public async Task Ping() | |||||
| => await RespondAsync("pong"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,4 @@ | |||||
| [DefaultMemberPermissions(GuildPermission.SendMessages | GuildPermission.ViewChannels)] | |||||
| [SlashCommand("ping", "Pong!")] | |||||
| public async Task Ping() | |||||
| => await RespondAsync("pong"); | |||||
| @@ -6,8 +6,8 @@ private static async Task LogAsync(LogMessage message) | |||||
| LogSeverity.Error => LogEventLevel.Error, | LogSeverity.Error => LogEventLevel.Error, | ||||
| LogSeverity.Warning => LogEventLevel.Warning, | LogSeverity.Warning => LogEventLevel.Warning, | ||||
| LogSeverity.Info => LogEventLevel.Information, | LogSeverity.Info => LogEventLevel.Information, | ||||
| LogSeverity.Verbose => LogEventLevel.Debug, | |||||
| LogSeverity.Debug => LogEventLevel.Verbose, | |||||
| LogSeverity.Verbose => LogEventLevel.Verbose, | |||||
| LogSeverity.Debug => LogEventLevel.Debug, | |||||
| _ => LogEventLevel.Information | _ => LogEventLevel.Information | ||||
| }; | }; | ||||
| Log.Write(severity, message.Exception, "[{Source}] {Message}", message.Source, message.Message); | Log.Write(severity, message.Exception, "[{Source}] {Message}", message.Source, message.Message); | ||||
| @@ -57,6 +57,8 @@ | |||||
| topicUid: Guides.IntFw.DI | topicUid: Guides.IntFw.DI | ||||
| - name: Post-execution Handling | - name: Post-execution Handling | ||||
| topicUid: Guides.IntFw.PostExecution | topicUid: Guides.IntFw.PostExecution | ||||
| - name: Permissions | |||||
| topicUid: Guides.IntFw.Perms | |||||
| - name: Slash Command Basics | - name: Slash Command Basics | ||||
| items: | items: | ||||
| - name: Introduction | - name: Introduction | ||||
| @@ -14,7 +14,7 @@ namespace InteractionFramework.Modules | |||||
| private InteractionHandler _handler; | private InteractionHandler _handler; | ||||
| // Constructor injection is also a valid way to access the dependecies | |||||
| // Constructor injection is also a valid way to access the dependencies | |||||
| public ExampleModule(InteractionHandler handler) | public ExampleModule(InteractionHandler handler) | ||||
| { | { | ||||
| _handler = handler; | _handler = handler; | ||||
| @@ -1,16 +0,0 @@ | |||||
| | |||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediatRSample", "MediatRSample\MediatRSample.csproj", "{CE066EE5-7ED1-42A0-8DB2-862D44F40EA7}" | |||||
| EndProject | |||||
| Global | |||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
| Debug|Any CPU = Debug|Any CPU | |||||
| Release|Any CPU = Release|Any CPU | |||||
| EndGlobalSection | |||||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
| {CE066EE5-7ED1-42A0-8DB2-862D44F40EA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {CE066EE5-7ED1-42A0-8DB2-862D44F40EA7}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {CE066EE5-7ED1-42A0-8DB2-862D44F40EA7}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {CE066EE5-7ED1-42A0-8DB2-862D44F40EA7}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| EndGlobalSection | |||||
| EndGlobal | |||||
| @@ -58,6 +58,7 @@ namespace Discord | |||||
| #endregion | #endregion | ||||
| #region General Actions (20XXX) | #region General Actions (20XXX) | ||||
| UnknownTag = 10087, | |||||
| BotsCannotUse = 20001, | BotsCannotUse = 20001, | ||||
| OnlyBotsCanUse = 20002, | OnlyBotsCanUse = 20002, | ||||
| CannotSendExplicitContent = 20009, | CannotSendExplicitContent = 20009, | ||||
| @@ -98,6 +99,8 @@ namespace Discord | |||||
| #region General Request Errors (40XXX) | #region General Request Errors (40XXX) | ||||
| MaximumNumberOfEditsReached = 30046, | MaximumNumberOfEditsReached = 30046, | ||||
| MaximumNumberOfPinnedThreadsInAForumChannelReached = 30047, | |||||
| MaximumNumberOfTagsInAForumChannelReached = 30048, | |||||
| TokenUnauthorized = 40001, | TokenUnauthorized = 40001, | ||||
| InvalidVerification = 40002, | InvalidVerification = 40002, | ||||
| OpeningDMTooFast = 40003, | OpeningDMTooFast = 40003, | ||||
| @@ -112,6 +115,7 @@ namespace Discord | |||||
| #region Action Preconditions/Checks (50XXX) | #region Action Preconditions/Checks (50XXX) | ||||
| InteractionHasAlreadyBeenAcknowledged = 40060, | InteractionHasAlreadyBeenAcknowledged = 40060, | ||||
| TagNamesMustBeUnique = 40061, | |||||
| MissingPermissions = 50001, | MissingPermissions = 50001, | ||||
| InvalidAccountType = 50002, | InvalidAccountType = 50002, | ||||
| CannotExecuteForDM = 50003, | CannotExecuteForDM = 50003, | ||||
| @@ -148,6 +152,7 @@ namespace Discord | |||||
| InvalidMessageType = 50068, | InvalidMessageType = 50068, | ||||
| PaymentSourceRequiredForGift = 50070, | PaymentSourceRequiredForGift = 50070, | ||||
| CannotDeleteRequiredCommunityChannel = 50074, | CannotDeleteRequiredCommunityChannel = 50074, | ||||
| CannotEditStickersWithinAMessage = 50080, | |||||
| InvalidSticker = 50081, | InvalidSticker = 50081, | ||||
| CannotExecuteOnArchivedThread = 50083, | CannotExecuteOnArchivedThread = 50083, | ||||
| InvalidThreadNotificationSettings = 50084, | InvalidThreadNotificationSettings = 50084, | ||||
| @@ -17,6 +17,16 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| public Optional<bool> IsDefaultPermission { get; set; } | public Optional<bool> IsDefaultPermission { get; set; } | ||||
| /// <summary> | |||||
| /// Gets or sets whether or not this command can be used in DMs. | |||||
| /// </summary> | |||||
| public Optional<bool> IsDMEnabled { get; set; } | |||||
| /// <summary> | |||||
| /// Gets or sets the default permissions required by a user to execute this application command. | |||||
| /// </summary> | |||||
| public Optional<GuildPermission> DefaultMemberPermissions { get; set; } | |||||
| internal ApplicationCommandProperties() { } | internal ApplicationCommandProperties() { } | ||||
| } | } | ||||
| } | } | ||||
| @@ -31,6 +31,16 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| public bool IsDefaultPermission { get; set; } = true; | public bool IsDefaultPermission { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets or sets whether or not this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsDMEnabled { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets or sets the default permission required to use this slash command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; set; } | |||||
| private string _name; | private string _name; | ||||
| /// <summary> | /// <summary> | ||||
| @@ -44,7 +54,9 @@ namespace Discord | |||||
| var props = new MessageCommandProperties | var props = new MessageCommandProperties | ||||
| { | { | ||||
| Name = Name, | Name = Name, | ||||
| IsDefaultPermission = IsDefaultPermission | |||||
| IsDefaultPermission = IsDefaultPermission, | |||||
| IsDMEnabled = IsDMEnabled, | |||||
| DefaultMemberPermissions = DefaultMemberPermissions ?? Optional<GuildPermission>.Unspecified | |||||
| }; | }; | ||||
| return props; | return props; | ||||
| @@ -73,5 +85,27 @@ namespace Discord | |||||
| IsDefaultPermission = isDefaultPermission; | IsDefaultPermission = isDefaultPermission; | ||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Sets whether or not this command can be used in dms | |||||
| /// </summary> | |||||
| /// <param name="permission"><see langword="true"/> if the command is available in dms, otherwise <see langword="false"/>.</param> | |||||
| /// <returns>The current builder.</returns> | |||||
| public MessageCommandBuilder WithDMPermission(bool permission) | |||||
| { | |||||
| IsDMEnabled = permission; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | |||||
| /// Sets the default member permissions required to use this application command. | |||||
| /// </summary> | |||||
| /// <param name="permissions">The permissions required to use this command.</param> | |||||
| /// <returns>The current builder.</returns> | |||||
| public MessageCommandBuilder WithDefaultMemberPermissions(GuildPermission? permissions) | |||||
| { | |||||
| DefaultMemberPermissions = permissions; | |||||
| return this; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -31,6 +31,16 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| public bool IsDefaultPermission { get; set; } = true; | public bool IsDefaultPermission { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets or sets whether or not this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsDMEnabled { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets or sets the default permission required to use this slash command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; set; } | |||||
| private string _name; | private string _name; | ||||
| /// <summary> | /// <summary> | ||||
| @@ -42,7 +52,9 @@ namespace Discord | |||||
| var props = new UserCommandProperties | var props = new UserCommandProperties | ||||
| { | { | ||||
| Name = Name, | Name = Name, | ||||
| IsDefaultPermission = IsDefaultPermission | |||||
| IsDefaultPermission = IsDefaultPermission, | |||||
| IsDMEnabled = IsDMEnabled, | |||||
| DefaultMemberPermissions = DefaultMemberPermissions ?? Optional<GuildPermission>.Unspecified | |||||
| }; | }; | ||||
| return props; | return props; | ||||
| @@ -71,5 +83,27 @@ namespace Discord | |||||
| IsDefaultPermission = isDefaultPermission; | IsDefaultPermission = isDefaultPermission; | ||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Sets whether or not this command can be used in dms | |||||
| /// </summary> | |||||
| /// <param name="permission"><see langword="true"/> if the command is available in dms, otherwise <see langword="false"/>.</param> | |||||
| /// <returns>The current builder.</returns> | |||||
| public UserCommandBuilder WithDMPermission(bool permission) | |||||
| { | |||||
| IsDMEnabled = permission; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | |||||
| /// Sets the default member permissions required to use this application command. | |||||
| /// </summary> | |||||
| /// <param name="permissions">The permissions required to use this command.</param> | |||||
| /// <returns>The current builder.</returns> | |||||
| public UserCommandBuilder WithDefaultMemberPermissions(GuildPermission? permissions) | |||||
| { | |||||
| DefaultMemberPermissions = permissions; | |||||
| return this; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -34,6 +34,19 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| bool IsDefaultPermission { get; } | bool IsDefaultPermission { get; } | ||||
| /// <summary> | |||||
| /// Indicates whether the command is available in DMs with the app. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// Only for globally-scoped commands. | |||||
| /// </remarks> | |||||
| bool IsEnabledInDm { get; } | |||||
| /// <summary> | |||||
| /// Set of default <see cref="GuildPermission"/> required to invoke the command. | |||||
| /// </summary> | |||||
| GuildPermissions DefaultMemberPermissions { get; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of options for this application command. | /// Gets a collection of options for this application command. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -81,6 +81,16 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| public bool IsDefaultPermission { get; set; } = true; | public bool IsDefaultPermission { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets or sets whether or not this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsDMEnabled { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets or sets the default permission required to use this slash command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; set; } | |||||
| private string _name; | private string _name; | ||||
| private string _description; | private string _description; | ||||
| private List<SlashCommandOptionBuilder> _options; | private List<SlashCommandOptionBuilder> _options; | ||||
| @@ -96,6 +106,8 @@ namespace Discord | |||||
| Name = Name, | Name = Name, | ||||
| Description = Description, | Description = Description, | ||||
| IsDefaultPermission = IsDefaultPermission, | IsDefaultPermission = IsDefaultPermission, | ||||
| IsDMEnabled = IsDMEnabled, | |||||
| DefaultMemberPermissions = DefaultMemberPermissions ?? Optional<GuildPermission>.Unspecified | |||||
| }; | }; | ||||
| if (Options != null && Options.Any()) | if (Options != null && Options.Any()) | ||||
| @@ -145,6 +157,28 @@ namespace Discord | |||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Sets whether or not this command can be used in dms | |||||
| /// </summary> | |||||
| /// <param name="permission"><see langword="true"/> if the command is available in dms, otherwise <see langword="false"/>.</param> | |||||
| /// <returns>The current builder.</returns> | |||||
| public SlashCommandBuilder WithDMPermission(bool permission) | |||||
| { | |||||
| IsDMEnabled = permission; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | |||||
| /// Sets the default member permissions required to use this application command. | |||||
| /// </summary> | |||||
| /// <param name="permissions">The permissions required to use this command.</param> | |||||
| /// <returns>The current builder.</returns> | |||||
| public SlashCommandBuilder WithDefaultMemberPermissions(GuildPermission? permissions) | |||||
| { | |||||
| DefaultMemberPermissions = permissions; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Adds an option to the current slash command. | /// Adds an option to the current slash command. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -164,21 +198,13 @@ namespace Discord | |||||
| string description, bool? isRequired = null, bool? isDefault = null, bool isAutocomplete = false, double? minValue = null, double? maxValue = null, | string description, bool? isRequired = null, bool? isDefault = null, bool isAutocomplete = false, double? minValue = null, double? maxValue = null, | ||||
| List<SlashCommandOptionBuilder> options = null, List<ChannelType> channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices) | List<SlashCommandOptionBuilder> options = null, List<ChannelType> channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices) | ||||
| { | { | ||||
| // Make sure the name matches the requirements from discord | |||||
| Preconditions.NotNullOrEmpty(name, nameof(name)); | |||||
| Preconditions.AtLeast(name.Length, 1, nameof(name)); | |||||
| Preconditions.AtMost(name.Length, MaxNameLength, nameof(name)); | |||||
| Preconditions.Options(name, description); | |||||
| // Discord updated the docs, this regex prevents special characters like @!$%( and s p a c e s.. etc, | // Discord updated the docs, this regex prevents special characters like @!$%( and s p a c e s.. etc, | ||||
| // https://discord.com/developers/docs/interactions/slash-commands#applicationcommand | // https://discord.com/developers/docs/interactions/slash-commands#applicationcommand | ||||
| if (!Regex.IsMatch(name, @"^[\w-]{1,32}$")) | if (!Regex.IsMatch(name, @"^[\w-]{1,32}$")) | ||||
| throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(name)); | throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(name)); | ||||
| // same with description | |||||
| Preconditions.NotNullOrEmpty(description, nameof(description)); | |||||
| Preconditions.AtLeast(description.Length, 1, nameof(description)); | |||||
| Preconditions.AtMost(description.Length, MaxDescriptionLength, nameof(description)); | |||||
| // make sure theres only one option with default set to true | // make sure theres only one option with default set to true | ||||
| if (isDefault == true && Options?.Any(x => x.IsDefault == true) == true) | if (isDefault == true && Options?.Any(x => x.IsDefault == true) == true) | ||||
| throw new ArgumentException("There can only be one command option with default set to true!", nameof(isDefault)); | throw new ArgumentException("There can only be one command option with default set to true!", nameof(isDefault)); | ||||
| @@ -214,6 +240,7 @@ namespace Discord | |||||
| throw new InvalidOperationException($"Cannot have more than {MaxOptionsCount} options!"); | throw new InvalidOperationException($"Cannot have more than {MaxOptionsCount} options!"); | ||||
| Preconditions.NotNull(option, nameof(option)); | Preconditions.NotNull(option, nameof(option)); | ||||
| Preconditions.Options(option.Name, option.Description); // this is a double-check when this method is called via AddOption(string name... ) | |||||
| Options.Add(option); | Options.Add(option); | ||||
| return this; | return this; | ||||
| @@ -236,6 +263,9 @@ namespace Discord | |||||
| if (Options.Count + options.Length > MaxOptionsCount) | if (Options.Count + options.Length > MaxOptionsCount) | ||||
| throw new ArgumentOutOfRangeException(nameof(options), $"Cannot have more than {MaxOptionsCount} options!"); | throw new ArgumentOutOfRangeException(nameof(options), $"Cannot have more than {MaxOptionsCount} options!"); | ||||
| foreach (var option in options) | |||||
| Preconditions.Options(option.Name, option.Description); | |||||
| Options.AddRange(options); | Options.AddRange(options); | ||||
| return this; | return this; | ||||
| } | } | ||||
| @@ -379,7 +409,7 @@ namespace Discord | |||||
| MinValue = MinValue, | MinValue = MinValue, | ||||
| MaxValue = MaxValue | MaxValue = MaxValue | ||||
| }; | }; | ||||
| } | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Adds an option to the current slash command. | /// Adds an option to the current slash command. | ||||
| @@ -400,21 +430,13 @@ namespace Discord | |||||
| string description, bool? isRequired = null, bool isDefault = false, bool isAutocomplete = false, double? minValue = null, double? maxValue = null, | string description, bool? isRequired = null, bool isDefault = false, bool isAutocomplete = false, double? minValue = null, double? maxValue = null, | ||||
| List<SlashCommandOptionBuilder> options = null, List<ChannelType> channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices) | List<SlashCommandOptionBuilder> options = null, List<ChannelType> channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices) | ||||
| { | { | ||||
| // Make sure the name matches the requirements from discord | |||||
| Preconditions.NotNullOrEmpty(name, nameof(name)); | |||||
| Preconditions.AtLeast(name.Length, 1, nameof(name)); | |||||
| Preconditions.AtMost(name.Length, SlashCommandBuilder.MaxNameLength, nameof(name)); | |||||
| Preconditions.Options(name, description); | |||||
| // Discord updated the docs, this regex prevents special characters like @!$%( and s p a c e s.. etc, | // Discord updated the docs, this regex prevents special characters like @!$%( and s p a c e s.. etc, | ||||
| // https://discord.com/developers/docs/interactions/slash-commands#applicationcommand | // https://discord.com/developers/docs/interactions/slash-commands#applicationcommand | ||||
| if (!Regex.IsMatch(name, @"^[\w-]{1,32}$")) | if (!Regex.IsMatch(name, @"^[\w-]{1,32}$")) | ||||
| throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(name)); | throw new ArgumentException("Command name cannot contain any special characters or whitespaces!", nameof(name)); | ||||
| // same with description | |||||
| Preconditions.NotNullOrEmpty(description, nameof(description)); | |||||
| Preconditions.AtLeast(description.Length, 1, nameof(description)); | |||||
| Preconditions.AtMost(description.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(description)); | |||||
| // make sure theres only one option with default set to true | // make sure theres only one option with default set to true | ||||
| if (isDefault && Options?.Any(x => x.IsDefault == true) == true) | if (isDefault && Options?.Any(x => x.IsDefault == true) == true) | ||||
| throw new ArgumentException("There can only be one command option with default set to true!", nameof(isDefault)); | throw new ArgumentException("There can only be one command option with default set to true!", nameof(isDefault)); | ||||
| @@ -449,6 +471,7 @@ namespace Discord | |||||
| throw new InvalidOperationException($"There can only be {SlashCommandBuilder.MaxOptionsCount} options per sub command group!"); | throw new InvalidOperationException($"There can only be {SlashCommandBuilder.MaxOptionsCount} options per sub command group!"); | ||||
| Preconditions.NotNull(option, nameof(option)); | Preconditions.NotNull(option, nameof(option)); | ||||
| Preconditions.Options(option.Name, option.Description); // double check again | |||||
| Options.Add(option); | Options.Add(option); | ||||
| return this; | return this; | ||||
| @@ -0,0 +1,24 @@ | |||||
| using System.Collections.Generic; | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> | |||||
| /// Represents a container for temporarily storing CustomId wild card matches of a component. | |||||
| /// </summary> | |||||
| public interface IRouteMatchContainer | |||||
| { | |||||
| /// <summary> | |||||
| /// Gets the collection of captured route segments in this container. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A collection of captured route segments. | |||||
| ///</returns> | |||||
| IEnumerable<IRouteSegmentMatch> SegmentMatches { get; } | |||||
| /// <summary> | |||||
| /// Sets the <see cref="SegmentMatches"/> property of this container. | |||||
| /// </summary> | |||||
| /// <param name="segmentMatches">The collection of captured route segments.</param> | |||||
| void SetSegmentMatches(IEnumerable<IRouteSegmentMatch> segmentMatches); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> | |||||
| /// Represents an object for storing a CustomId wild card match. | |||||
| /// </summary> | |||||
| public interface IRouteSegmentMatch | |||||
| { | |||||
| /// <summary> | |||||
| /// Gets the captured value of this wild card match. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// The value of this wild card. | |||||
| /// </returns> | |||||
| string Value { get; } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> | |||||
| /// Represents an object for storing a CustomId wild card match. | |||||
| /// </summary> | |||||
| internal record RouteSegmentMatch : IRouteSegmentMatch | |||||
| { | |||||
| /// <inheritdoc/> | |||||
| public string Value { get; } | |||||
| public RouteSegmentMatch(string value) | |||||
| { | |||||
| Value = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -297,5 +297,22 @@ namespace Discord | |||||
| } | } | ||||
| } | } | ||||
| #endregion | #endregion | ||||
| #region SlashCommandOptions | |||||
| /// <exception cref="ArgumentNullException"><paramref name="description"/> or <paramref name="name"/> is null.</exception> | |||||
| /// <exception cref="ArgumentException"><paramref name="description"/> or <paramref name="name"/> are either empty or their length exceed limits.</exception> | |||||
| public static void Options(string name, string description) | |||||
| { | |||||
| // Make sure the name matches the requirements from discord | |||||
| NotNullOrEmpty(name, nameof(name)); | |||||
| NotNullOrEmpty(description, nameof(description)); | |||||
| AtLeast(name.Length, 1, nameof(name)); | |||||
| AtMost(name.Length, SlashCommandBuilder.MaxNameLength, nameof(name)); | |||||
| AtLeast(description.Length, 1, nameof(description)); | |||||
| AtMost(description.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(description)); | |||||
| } | |||||
| #endregion | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,25 @@ | |||||
| using System; | |||||
| namespace Discord.Interactions | |||||
| { | |||||
| /// <summary> | |||||
| /// Sets the <see cref="IApplicationCommandInfo.DefaultMemberPermissions"/> of an application command or module. | |||||
| /// </summary> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |||||
| public class DefaultMemberPermissionsAttribute : Attribute | |||||
| { | |||||
| /// <summary> | |||||
| /// Gets the default permission required to use this command. | |||||
| /// </summary> | |||||
| public GuildPermission Permissions { get; } | |||||
| /// <summary> | |||||
| /// Sets the <see cref="IApplicationCommandInfo.DefaultMemberPermissions"/> of an application command or module. | |||||
| /// </summary> | |||||
| /// <param name="permissions">The default permission required to use this command.</param> | |||||
| public DefaultMemberPermissionsAttribute(GuildPermission permissions) | |||||
| { | |||||
| Permissions = permissions; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -6,6 +6,7 @@ namespace Discord.Interactions | |||||
| /// Set the "Default Permission" property of an Application Command. | /// Set the "Default Permission" property of an Application Command. | ||||
| /// </summary> | /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | ||||
| [Obsolete($"Soon to be deprecated, use Permissions-v2 attributes like {nameof(EnabledInDmAttribute)} and {nameof(DefaultMemberPermissionsAttribute)}")] | |||||
| public class DefaultPermissionAttribute : Attribute | public class DefaultPermissionAttribute : Attribute | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| @@ -0,0 +1,25 @@ | |||||
| using System; | |||||
| namespace Discord.Interactions | |||||
| { | |||||
| /// <summary> | |||||
| /// Sets the <see cref="IApplicationCommandInfo.IsEnabledInDm"/> property of an application command or module. | |||||
| /// </summary> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |||||
| public class EnabledInDmAttribute : Attribute | |||||
| { | |||||
| /// <summary> | |||||
| /// Gets whether or not this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsEnabled { get; } | |||||
| /// <summary> | |||||
| /// Sets the <see cref="IApplicationCommandInfo.IsEnabledInDm"/> property of an application command or module. | |||||
| /// </summary> | |||||
| /// <param name="isEnabled">Whether or not this command can be used in DMs.</param> | |||||
| public EnabledInDmAttribute(bool isEnabled) | |||||
| { | |||||
| IsEnabled = isEnabled; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -17,8 +17,19 @@ namespace Discord.Interactions.Builders | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the default permission of this command. | /// Gets the default permission of this command. | ||||
| /// </summary> | /// </summary> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(IsEnabledInDm)} and {nameof(DefaultMemberPermissions)} instead.")] | |||||
| public bool DefaultPermission { get; set; } = true; | public bool DefaultPermission { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets whether this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsEnabledInDm { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets the default permissions needed for executing this command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; set; } = null; | |||||
| internal ContextCommandBuilder (ModuleBuilder module) : base(module) { } | internal ContextCommandBuilder (ModuleBuilder module) : base(module) { } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -49,6 +60,7 @@ namespace Discord.Interactions.Builders | |||||
| /// <returns> | /// <returns> | ||||
| /// The builder instance. | /// The builder instance. | ||||
| /// </returns> | /// </returns> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(SetEnabledInDm)} and {nameof(WithDefaultMemberPermissions)} instead.")] | |||||
| public ContextCommandBuilder SetDefaultPermission (bool defaultPermision) | public ContextCommandBuilder SetDefaultPermission (bool defaultPermision) | ||||
| { | { | ||||
| DefaultPermission = defaultPermision; | DefaultPermission = defaultPermision; | ||||
| @@ -70,6 +82,32 @@ namespace Discord.Interactions.Builders | |||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Sets <see cref="IsEnabledInDm"/>. | |||||
| /// </summary> | |||||
| /// <param name="isEnabled">New value of the <see cref="IsEnabledInDm"/>.</param> | |||||
| /// <returns> | |||||
| /// The builder instance. | |||||
| /// </returns> | |||||
| public ContextCommandBuilder SetEnabledInDm(bool isEnabled) | |||||
| { | |||||
| IsEnabledInDm = isEnabled; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | |||||
| /// Sets <see cref="DefaultMemberPermissions"/>. | |||||
| /// </summary> | |||||
| /// <param name="permissions">New value of the <see cref="DefaultMemberPermissions"/>.</param> | |||||
| /// <returns> | |||||
| /// The builder instance. | |||||
| /// </returns> | |||||
| public ContextCommandBuilder WithDefaultMemberPermissions(GuildPermission permissions) | |||||
| { | |||||
| DefaultMemberPermissions = permissions; | |||||
| return this; | |||||
| } | |||||
| internal override ContextCommandInfo Build (ModuleInfo module, InteractionService commandService) => | internal override ContextCommandInfo Build (ModuleInfo module, InteractionService commandService) => | ||||
| ContextCommandInfo.Create(this, module, commandService); | ContextCommandInfo.Create(this, module, commandService); | ||||
| } | } | ||||
| @@ -17,8 +17,19 @@ namespace Discord.Interactions.Builders | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets and sets the default permission of this command. | /// Gets and sets the default permission of this command. | ||||
| /// </summary> | /// </summary> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(IsEnabledInDm)} and {nameof(DefaultMemberPermissions)} instead.")] | |||||
| public bool DefaultPermission { get; set; } = true; | public bool DefaultPermission { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets whether this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsEnabledInDm { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets the default permissions needed for executing this command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; set; } = null; | |||||
| internal SlashCommandBuilder (ModuleBuilder module) : base(module) { } | internal SlashCommandBuilder (ModuleBuilder module) : base(module) { } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -49,6 +60,7 @@ namespace Discord.Interactions.Builders | |||||
| /// <returns> | /// <returns> | ||||
| /// The builder instance. | /// The builder instance. | ||||
| /// </returns> | /// </returns> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(SetEnabledInDm)} and {nameof(WithDefaultMemberPermissions)} instead.")] | |||||
| public SlashCommandBuilder WithDefaultPermission (bool permission) | public SlashCommandBuilder WithDefaultPermission (bool permission) | ||||
| { | { | ||||
| DefaultPermission = permission; | DefaultPermission = permission; | ||||
| @@ -70,6 +82,32 @@ namespace Discord.Interactions.Builders | |||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Sets <see cref="IsEnabledInDm"/>. | |||||
| /// </summary> | |||||
| /// <param name="isEnabled">New value of the <see cref="IsEnabledInDm"/>.</param> | |||||
| /// <returns> | |||||
| /// The builder instance. | |||||
| /// </returns> | |||||
| public SlashCommandBuilder SetEnabledInDm(bool isEnabled) | |||||
| { | |||||
| IsEnabledInDm = isEnabled; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | |||||
| /// Sets <see cref="DefaultMemberPermissions"/>. | |||||
| /// </summary> | |||||
| /// <param name="permissions">New value of the <see cref="DefaultMemberPermissions"/>.</param> | |||||
| /// <returns> | |||||
| /// The builder instance. | |||||
| /// </returns> | |||||
| public SlashCommandBuilder WithDefaultMemberPermissions(GuildPermission permissions) | |||||
| { | |||||
| DefaultMemberPermissions = permissions; | |||||
| return this; | |||||
| } | |||||
| internal override SlashCommandInfo Build (ModuleInfo module, InteractionService commandService) => | internal override SlashCommandInfo Build (ModuleInfo module, InteractionService commandService) => | ||||
| new SlashCommandInfo(this, module, commandService); | new SlashCommandInfo(this, module, commandService); | ||||
| } | } | ||||
| @@ -51,8 +51,19 @@ namespace Discord.Interactions.Builders | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets and sets the default permission of this module. | /// Gets and sets the default permission of this module. | ||||
| /// </summary> | /// </summary> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(IsEnabledInDm)} and {nameof(DefaultMemberPermissions)} instead.")] | |||||
| public bool DefaultPermission { get; set; } = true; | public bool DefaultPermission { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets whether this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsEnabledInDm { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets the default permissions needed for executing this command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; set; } = null; | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets and sets whether this has a <see cref="DontAutoRegisterAttribute"/>. | /// Gets and sets whether this has a <see cref="DontAutoRegisterAttribute"/>. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -159,12 +170,39 @@ namespace Discord.Interactions.Builders | |||||
| /// <returns> | /// <returns> | ||||
| /// The builder instance. | /// The builder instance. | ||||
| /// </returns> | /// </returns> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(SetEnabledInDm)} and {nameof(WithDefaultMemberPermissions)} instead.")] | |||||
| public ModuleBuilder WithDefaultPermission (bool permission) | public ModuleBuilder WithDefaultPermission (bool permission) | ||||
| { | { | ||||
| DefaultPermission = permission; | DefaultPermission = permission; | ||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Sets <see cref="IsEnabledInDm"/>. | |||||
| /// </summary> | |||||
| /// <param name="isEnabled">New value of the <see cref="IsEnabledInDm"/>.</param> | |||||
| /// <returns> | |||||
| /// The builder instance. | |||||
| /// </returns> | |||||
| public ModuleBuilder SetEnabledInDm(bool isEnabled) | |||||
| { | |||||
| IsEnabledInDm = isEnabled; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | |||||
| /// Sets <see cref="DefaultMemberPermissions"/>. | |||||
| /// </summary> | |||||
| /// <param name="permissions">New value of the <see cref="DefaultMemberPermissions"/>.</param> | |||||
| /// <returns> | |||||
| /// The builder instance. | |||||
| /// </returns> | |||||
| public ModuleBuilder WithDefaultMemberPermissions(GuildPermission permissions) | |||||
| { | |||||
| DefaultMemberPermissions = permissions; | |||||
| return this; | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Adds attributes to <see cref="Attributes"/>. | /// Adds attributes to <see cref="Attributes"/>. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -85,6 +85,16 @@ namespace Discord.Interactions.Builders | |||||
| builder.DefaultPermission = defPermission.IsDefaultPermission; | builder.DefaultPermission = defPermission.IsDefaultPermission; | ||||
| } | } | ||||
| break; | break; | ||||
| case EnabledInDmAttribute enabledInDm: | |||||
| { | |||||
| builder.IsEnabledInDm = enabledInDm.IsEnabled; | |||||
| } | |||||
| break; | |||||
| case DefaultMemberPermissionsAttribute memberPermission: | |||||
| { | |||||
| builder.DefaultMemberPermissions = memberPermission.Permissions; | |||||
| } | |||||
| break; | |||||
| case PreconditionAttribute precondition: | case PreconditionAttribute precondition: | ||||
| builder.AddPreconditions(precondition); | builder.AddPreconditions(precondition); | ||||
| break; | break; | ||||
| @@ -169,6 +179,16 @@ namespace Discord.Interactions.Builders | |||||
| builder.DefaultPermission = defaultPermission.IsDefaultPermission; | builder.DefaultPermission = defaultPermission.IsDefaultPermission; | ||||
| } | } | ||||
| break; | break; | ||||
| case EnabledInDmAttribute enabledInDm: | |||||
| { | |||||
| builder.IsEnabledInDm = enabledInDm.IsEnabled; | |||||
| } | |||||
| break; | |||||
| case DefaultMemberPermissionsAttribute memberPermission: | |||||
| { | |||||
| builder.DefaultMemberPermissions = memberPermission.Permissions; | |||||
| } | |||||
| break; | |||||
| case PreconditionAttribute precondition: | case PreconditionAttribute precondition: | ||||
| builder.WithPreconditions(precondition); | builder.WithPreconditions(precondition); | ||||
| break; | break; | ||||
| @@ -211,6 +231,16 @@ namespace Discord.Interactions.Builders | |||||
| builder.DefaultPermission = defaultPermission.IsDefaultPermission; | builder.DefaultPermission = defaultPermission.IsDefaultPermission; | ||||
| } | } | ||||
| break; | break; | ||||
| case EnabledInDmAttribute enabledInDm: | |||||
| { | |||||
| builder.IsEnabledInDm = enabledInDm.IsEnabled; | |||||
| } | |||||
| break; | |||||
| case DefaultMemberPermissionsAttribute memberPermission: | |||||
| { | |||||
| builder.DefaultMemberPermissions = memberPermission.Permissions; | |||||
| } | |||||
| break; | |||||
| case PreconditionAttribute precondition: | case PreconditionAttribute precondition: | ||||
| builder.WithPreconditions(precondition); | builder.WithPreconditions(precondition); | ||||
| break; | break; | ||||
| @@ -17,6 +17,12 @@ namespace Discord.Interactions | |||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public bool DefaultPermission { get; } | public bool DefaultPermission { get; } | ||||
| /// <inheritdoc/> | |||||
| public bool IsEnabledInDm { get; } | |||||
| /// <inheritdoc/> | |||||
| public GuildPermission? DefaultMemberPermissions { get; } | |||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public override IReadOnlyCollection<CommandParameterInfo> Parameters { get; } | public override IReadOnlyCollection<CommandParameterInfo> Parameters { get; } | ||||
| @@ -31,6 +37,8 @@ namespace Discord.Interactions | |||||
| { | { | ||||
| CommandType = builder.CommandType; | CommandType = builder.CommandType; | ||||
| DefaultPermission = builder.DefaultPermission; | DefaultPermission = builder.DefaultPermission; | ||||
| IsEnabledInDm = builder.IsEnabledInDm; | |||||
| DefaultMemberPermissions = builder.DefaultMemberPermissions; | |||||
| Parameters = builder.Parameters.Select(x => x.Build(this)).ToImmutableArray(); | Parameters = builder.Parameters.Select(x => x.Build(this)).ToImmutableArray(); | ||||
| } | } | ||||
| @@ -26,6 +26,12 @@ namespace Discord.Interactions | |||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public bool DefaultPermission { get; } | public bool DefaultPermission { get; } | ||||
| /// <inheritdoc/> | |||||
| public bool IsEnabledInDm { get; } | |||||
| /// <inheritdoc/> | |||||
| public GuildPermission? DefaultMemberPermissions { get; } | |||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public override IReadOnlyCollection<SlashCommandParameterInfo> Parameters { get; } | public override IReadOnlyCollection<SlashCommandParameterInfo> Parameters { get; } | ||||
| @@ -41,6 +47,8 @@ namespace Discord.Interactions | |||||
| { | { | ||||
| Description = builder.Description; | Description = builder.Description; | ||||
| DefaultPermission = builder.DefaultPermission; | DefaultPermission = builder.DefaultPermission; | ||||
| IsEnabledInDm = builder.IsEnabledInDm; | |||||
| DefaultMemberPermissions = builder.DefaultMemberPermissions; | |||||
| Parameters = builder.Parameters.Select(x => x.Build(this)).ToImmutableArray(); | Parameters = builder.Parameters.Select(x => x.Build(this)).ToImmutableArray(); | ||||
| FlattenedParameters = FlattenParameters(Parameters).ToImmutableArray(); | FlattenedParameters = FlattenParameters(Parameters).ToImmutableArray(); | ||||
| @@ -1,3 +1,5 @@ | |||||
| using System; | |||||
| namespace Discord.Interactions | namespace Discord.Interactions | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| @@ -18,6 +20,17 @@ namespace Discord.Interactions | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the DefaultPermission of this command. | /// Gets the DefaultPermission of this command. | ||||
| /// </summary> | /// </summary> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(IsEnabledInDm)} and {nameof(DefaultMemberPermissions)} instead.")] | |||||
| bool DefaultPermission { get; } | bool DefaultPermission { get; } | ||||
| /// <summary> | |||||
| /// Gets whether this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsEnabledInDm { get; } | |||||
| /// <summary> | |||||
| /// Gets the default permissions needed for executing this command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -41,8 +41,19 @@ namespace Discord.Interactions | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the default Permission of this module. | /// Gets the default Permission of this module. | ||||
| /// </summary> | /// </summary> | ||||
| [Obsolete($"To be deprecated soon, use {nameof(IsEnabledInDm)} and {nameof(DefaultMemberPermissions)} instead.")] | |||||
| public bool DefaultPermission { get; } | public bool DefaultPermission { get; } | ||||
| /// <summary> | |||||
| /// Gets whether this command can be used in DMs. | |||||
| /// </summary> | |||||
| public bool IsEnabledInDm { get; } | |||||
| /// <summary> | |||||
| /// Gets the default permissions needed for executing this command. | |||||
| /// </summary> | |||||
| public GuildPermission? DefaultMemberPermissions { get; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the collection of Sub Modules of this module. | /// Gets the collection of Sub Modules of this module. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -110,6 +121,8 @@ namespace Discord.Interactions | |||||
| Description = builder.Description; | Description = builder.Description; | ||||
| Parent = parent; | Parent = parent; | ||||
| DefaultPermission = builder.DefaultPermission; | DefaultPermission = builder.DefaultPermission; | ||||
| IsEnabledInDm = builder.IsEnabledInDm; | |||||
| DefaultMemberPermissions = BuildDefaultMemberPermissions(builder); | |||||
| SlashCommands = BuildSlashCommands(builder).ToImmutableArray(); | SlashCommands = BuildSlashCommands(builder).ToImmutableArray(); | ||||
| ContextCommands = BuildContextCommands(builder).ToImmutableArray(); | ContextCommands = BuildContextCommands(builder).ToImmutableArray(); | ||||
| ComponentCommands = BuildComponentCommands(builder).ToImmutableArray(); | ComponentCommands = BuildComponentCommands(builder).ToImmutableArray(); | ||||
| @@ -226,5 +239,20 @@ namespace Discord.Interactions | |||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| private static GuildPermission? BuildDefaultMemberPermissions(ModuleBuilder builder) | |||||
| { | |||||
| var permissions = builder.DefaultMemberPermissions; | |||||
| var parent = builder.Parent; | |||||
| while (parent != null) | |||||
| { | |||||
| permissions = (permissions ?? 0) | (parent.DefaultMemberPermissions ?? 0); | |||||
| parent = parent.Parent; | |||||
| } | |||||
| return permissions; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,10 @@ | |||||
| using System.Collections.Generic; | |||||
| using System.Collections.Immutable; | |||||
| namespace Discord.Interactions | namespace Discord.Interactions | ||||
| { | { | ||||
| /// <inheritdoc cref="IInteractionContext"/> | /// <inheritdoc cref="IInteractionContext"/> | ||||
| public class InteractionContext : IInteractionContext | |||||
| public class InteractionContext : IInteractionContext, IRouteMatchContainer | |||||
| { | { | ||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public IDiscordClient Client { get; } | public IDiscordClient Client { get; } | ||||
| @@ -13,6 +16,8 @@ namespace Discord.Interactions | |||||
| public IUser User { get; } | public IUser User { get; } | ||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public IDiscordInteraction Interaction { get; } | public IDiscordInteraction Interaction { get; } | ||||
| /// <inheritdoc cref="IRouteMatchContainer.SegmentMatches"/> | |||||
| public IReadOnlyCollection<IRouteSegmentMatch> SegmentMatches { get; private set; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Initializes a new <see cref="SocketInteractionContext{TInteraction}"/>. | /// Initializes a new <see cref="SocketInteractionContext{TInteraction}"/>. | ||||
| @@ -30,5 +35,12 @@ namespace Discord.Interactions | |||||
| User = interaction.User; | User = interaction.User; | ||||
| Interaction = interaction; | Interaction = interaction; | ||||
| } | } | ||||
| /// <inheritdoc/> | |||||
| public void SetSegmentMatches(IEnumerable<IRouteSegmentMatch> segmentMatches) => SegmentMatches = segmentMatches.ToImmutableArray(); | |||||
| //IRouteMatchContainer | |||||
| /// <inheritdoc/> | |||||
| IEnumerable<IRouteSegmentMatch> IRouteMatchContainer.SegmentMatches => SegmentMatches; | |||||
| } | } | ||||
| } | } | ||||
| @@ -775,6 +775,9 @@ namespace Discord.Interactions | |||||
| await _componentCommandExecutedEvent.InvokeAsync(null, context, result).ConfigureAwait(false); | await _componentCommandExecutedEvent.InvokeAsync(null, context, result).ConfigureAwait(false); | ||||
| return result; | return result; | ||||
| } | } | ||||
| SetMatchesIfApplicable(context, result); | |||||
| return await result.Command.ExecuteAsync(context, services, result.RegexCaptureGroups).ConfigureAwait(false); | return await result.Command.ExecuteAsync(context, services, result.RegexCaptureGroups).ConfigureAwait(false); | ||||
| } | } | ||||
| @@ -819,9 +822,30 @@ namespace Discord.Interactions | |||||
| await _componentCommandExecutedEvent.InvokeAsync(null, context, result).ConfigureAwait(false); | await _componentCommandExecutedEvent.InvokeAsync(null, context, result).ConfigureAwait(false); | ||||
| return result; | return result; | ||||
| } | } | ||||
| SetMatchesIfApplicable(context, result); | |||||
| return await result.Command.ExecuteAsync(context, services, result.RegexCaptureGroups).ConfigureAwait(false); | return await result.Command.ExecuteAsync(context, services, result.RegexCaptureGroups).ConfigureAwait(false); | ||||
| } | } | ||||
| private static void SetMatchesIfApplicable<T>(IInteractionContext context, SearchResult<T> searchResult) | |||||
| where T : class, ICommandInfo | |||||
| { | |||||
| if (!searchResult.Command.SupportsWildCards || context is not IRouteMatchContainer matchContainer) | |||||
| return; | |||||
| if (searchResult.RegexCaptureGroups?.Length > 0) | |||||
| { | |||||
| var matches = new RouteSegmentMatch[searchResult.RegexCaptureGroups.Length]; | |||||
| for (var i = 0; i < searchResult.RegexCaptureGroups.Length; i++) | |||||
| matches[i] = new RouteSegmentMatch(searchResult.RegexCaptureGroups[i]); | |||||
| matchContainer.SetSegmentMatches(matches); | |||||
| } | |||||
| else | |||||
| matchContainer.SetSegmentMatches(Array.Empty<RouteSegmentMatch>()); | |||||
| } | |||||
| internal TypeConverter GetTypeConverter(Type type, IServiceProvider services = null) | internal TypeConverter GetTypeConverter(Type type, IServiceProvider services = null) | ||||
| => _typeConverterMap.Get(type, services); | => _typeConverterMap.Get(type, services); | ||||
| @@ -40,7 +40,8 @@ namespace Discord.Interactions | |||||
| { | { | ||||
| Name = commandInfo.Name, | Name = commandInfo.Name, | ||||
| Description = commandInfo.Description, | Description = commandInfo.Description, | ||||
| IsDefaultPermission = commandInfo.DefaultPermission, | |||||
| IsDMEnabled = commandInfo.IsEnabledInDm, | |||||
| DefaultMemberPermissions = (commandInfo.DefaultMemberPermissions ?? 0) | (commandInfo.Module.DefaultMemberPermissions ?? 0) | |||||
| }.Build(); | }.Build(); | ||||
| if (commandInfo.Parameters.Count > SlashCommandBuilder.MaxOptionsCount) | if (commandInfo.Parameters.Count > SlashCommandBuilder.MaxOptionsCount) | ||||
| @@ -64,8 +65,20 @@ namespace Discord.Interactions | |||||
| public static ApplicationCommandProperties ToApplicationCommandProps(this ContextCommandInfo commandInfo) | public static ApplicationCommandProperties ToApplicationCommandProps(this ContextCommandInfo commandInfo) | ||||
| => commandInfo.CommandType switch | => commandInfo.CommandType switch | ||||
| { | { | ||||
| ApplicationCommandType.Message => new MessageCommandBuilder { Name = commandInfo.Name, IsDefaultPermission = commandInfo.DefaultPermission}.Build(), | |||||
| ApplicationCommandType.User => new UserCommandBuilder { Name = commandInfo.Name, IsDefaultPermission=commandInfo.DefaultPermission}.Build(), | |||||
| ApplicationCommandType.Message => new MessageCommandBuilder | |||||
| { | |||||
| Name = commandInfo.Name, | |||||
| IsDefaultPermission = commandInfo.DefaultPermission, | |||||
| DefaultMemberPermissions = (commandInfo.DefaultMemberPermissions ?? 0) | (commandInfo.Module.DefaultMemberPermissions ?? 0), | |||||
| IsDMEnabled = commandInfo.IsEnabledInDm | |||||
| }.Build(), | |||||
| ApplicationCommandType.User => new UserCommandBuilder | |||||
| { | |||||
| Name = commandInfo.Name, | |||||
| IsDefaultPermission = commandInfo.DefaultPermission, | |||||
| DefaultMemberPermissions = (commandInfo.DefaultMemberPermissions ?? 0) | (commandInfo.Module.DefaultMemberPermissions ?? 0), | |||||
| IsDMEnabled = commandInfo.IsEnabledInDm | |||||
| }.Build(), | |||||
| _ => throw new InvalidOperationException($"{commandInfo.CommandType} isn't a supported command type.") | _ => throw new InvalidOperationException($"{commandInfo.CommandType} isn't a supported command type.") | ||||
| }; | }; | ||||
| #endregion | #endregion | ||||
| @@ -113,6 +126,8 @@ namespace Discord.Interactions | |||||
| Name = moduleInfo.SlashGroupName, | Name = moduleInfo.SlashGroupName, | ||||
| Description = moduleInfo.Description, | Description = moduleInfo.Description, | ||||
| IsDefaultPermission = moduleInfo.DefaultPermission, | IsDefaultPermission = moduleInfo.DefaultPermission, | ||||
| IsDMEnabled = moduleInfo.IsEnabledInDm, | |||||
| DefaultMemberPermissions = moduleInfo.DefaultMemberPermissions | |||||
| }.Build(); | }.Build(); | ||||
| if (options.Count > SlashCommandBuilder.MaxOptionsCount) | if (options.Count > SlashCommandBuilder.MaxOptionsCount) | ||||
| @@ -24,5 +24,12 @@ namespace Discord.API | |||||
| [JsonProperty("default_permission")] | [JsonProperty("default_permission")] | ||||
| public Optional<bool> DefaultPermissions { get; set; } | public Optional<bool> DefaultPermissions { get; set; } | ||||
| // V2 Permissions | |||||
| [JsonProperty("dm_permission")] | |||||
| public Optional<bool?> DmPermission { get; set; } | |||||
| [JsonProperty("default_member_permissions")] | |||||
| public Optional<GuildPermission?> DefaultMemberPermission { get; set; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -19,6 +19,12 @@ namespace Discord.API.Rest | |||||
| [JsonProperty("default_permission")] | [JsonProperty("default_permission")] | ||||
| public Optional<bool> DefaultPermission { get; set; } | public Optional<bool> DefaultPermission { get; set; } | ||||
| [JsonProperty("dm_permission")] | |||||
| public Optional<bool?> DmPermission { get; set; } | |||||
| [JsonProperty("default_member_permissions")] | |||||
| public Optional<GuildPermission?> DefaultMemberPermission { get; set; } | |||||
| public CreateApplicationCommandParams() { } | public CreateApplicationCommandParams() { } | ||||
| public CreateApplicationCommandParams(string name, string description, ApplicationCommandType type, ApplicationCommandOption[] options = null) | public CreateApplicationCommandParams(string name, string description, ApplicationCommandType type, ApplicationCommandOption[] options = null) | ||||
| { | { | ||||
| @@ -100,7 +100,12 @@ namespace Discord.Rest | |||||
| Type = arg.Type, | Type = arg.Type, | ||||
| DefaultPermission = arg.IsDefaultPermission.IsSpecified | DefaultPermission = arg.IsDefaultPermission.IsSpecified | ||||
| ? arg.IsDefaultPermission.Value | ? arg.IsDefaultPermission.Value | ||||
| : Optional<bool>.Unspecified | |||||
| : Optional<bool>.Unspecified, | |||||
| // TODO: better conversion to nullable optionals | |||||
| DefaultMemberPermission = arg.DefaultMemberPermissions.ToNullable(), | |||||
| DmPermission = arg.IsDMEnabled.ToNullable() | |||||
| }; | }; | ||||
| if (arg is SlashCommandProperties slashProps) | if (arg is SlashCommandProperties slashProps) | ||||
| @@ -134,7 +139,11 @@ namespace Discord.Rest | |||||
| Type = arg.Type, | Type = arg.Type, | ||||
| DefaultPermission = arg.IsDefaultPermission.IsSpecified | DefaultPermission = arg.IsDefaultPermission.IsSpecified | ||||
| ? arg.IsDefaultPermission.Value | ? arg.IsDefaultPermission.Value | ||||
| : Optional<bool>.Unspecified | |||||
| : Optional<bool>.Unspecified, | |||||
| // TODO: better conversion to nullable optionals | |||||
| DefaultMemberPermission = arg.DefaultMemberPermissions.ToNullable(), | |||||
| DmPermission = arg.IsDMEnabled.ToNullable() | |||||
| }; | }; | ||||
| if (arg is SlashCommandProperties slashProps) | if (arg is SlashCommandProperties slashProps) | ||||
| @@ -171,7 +180,11 @@ namespace Discord.Rest | |||||
| Type = arg.Type, | Type = arg.Type, | ||||
| DefaultPermission = arg.IsDefaultPermission.IsSpecified | DefaultPermission = arg.IsDefaultPermission.IsSpecified | ||||
| ? arg.IsDefaultPermission.Value | ? arg.IsDefaultPermission.Value | ||||
| : Optional<bool>.Unspecified | |||||
| : Optional<bool>.Unspecified, | |||||
| // TODO: better conversion to nullable optionals | |||||
| DefaultMemberPermission = arg.DefaultMemberPermissions.ToNullable(), | |||||
| DmPermission = arg.IsDMEnabled.ToNullable() | |||||
| }; | }; | ||||
| if (arg is SlashCommandProperties slashProps) | if (arg is SlashCommandProperties slashProps) | ||||
| @@ -285,7 +298,11 @@ namespace Discord.Rest | |||||
| Type = arg.Type, | Type = arg.Type, | ||||
| DefaultPermission = arg.IsDefaultPermission.IsSpecified | DefaultPermission = arg.IsDefaultPermission.IsSpecified | ||||
| ? arg.IsDefaultPermission.Value | ? arg.IsDefaultPermission.Value | ||||
| : Optional<bool>.Unspecified | |||||
| : Optional<bool>.Unspecified, | |||||
| // TODO: better conversion to nullable optionals | |||||
| DefaultMemberPermission = arg.DefaultMemberPermissions.ToNullable(), | |||||
| DmPermission = arg.IsDMEnabled.ToNullable() | |||||
| }; | }; | ||||
| if (arg is SlashCommandProperties slashProps) | if (arg is SlashCommandProperties slashProps) | ||||
| @@ -27,6 +27,12 @@ namespace Discord.Rest | |||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public bool IsDefaultPermission { get; private set; } | public bool IsDefaultPermission { get; private set; } | ||||
| /// <inheritdoc/> | |||||
| public bool IsEnabledInDm { get; private set; } | |||||
| /// <inheritdoc/> | |||||
| public GuildPermissions DefaultMemberPermissions { get; private set; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of options for this command. | /// Gets a collection of options for this command. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -57,6 +63,9 @@ namespace Discord.Rest | |||||
| Options = model.Options.IsSpecified | Options = model.Options.IsSpecified | ||||
| ? model.Options.Value.Select(RestApplicationCommandOption.Create).ToImmutableArray() | ? model.Options.Value.Select(RestApplicationCommandOption.Create).ToImmutableArray() | ||||
| : ImmutableArray.Create<RestApplicationCommandOption>(); | : ImmutableArray.Create<RestApplicationCommandOption>(); | ||||
| IsEnabledInDm = model.DmPermission.GetValueOrDefault(true).GetValueOrDefault(true); | |||||
| DefaultMemberPermissions = new GuildPermissions((ulong)model.DefaultMemberPermission.GetValueOrDefault(0).GetValueOrDefault(0)); | |||||
| } | } | ||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| @@ -1,4 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Collections.Immutable; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| namespace Discord.Rest | namespace Discord.Rest | ||||
| @@ -6,7 +8,7 @@ namespace Discord.Rest | |||||
| /// <summary> | /// <summary> | ||||
| /// Represents a Rest based context of an <see cref="IDiscordInteraction"/>. | /// Represents a Rest based context of an <see cref="IDiscordInteraction"/>. | ||||
| /// </summary> | /// </summary> | ||||
| public class RestInteractionContext<TInteraction> : IRestInteractionContext | |||||
| public class RestInteractionContext<TInteraction> : IRestInteractionContext, IRouteMatchContainer | |||||
| where TInteraction : RestInteraction | where TInteraction : RestInteraction | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| @@ -45,6 +47,9 @@ namespace Discord.Rest | |||||
| /// </remarks> | /// </remarks> | ||||
| public Func<string, Task> InteractionResponseCallback { get; set; } | public Func<string, Task> InteractionResponseCallback { get; set; } | ||||
| /// <inheritdoc cref="IRouteMatchContainer.SegmentMatches"/> | |||||
| public IReadOnlyCollection<IRouteSegmentMatch> SegmentMatches { get; private set; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Initializes a new <see cref="RestInteractionContext{TInteraction}"/>. | /// Initializes a new <see cref="RestInteractionContext{TInteraction}"/>. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -71,6 +76,13 @@ namespace Discord.Rest | |||||
| InteractionResponseCallback = interactionResponseCallback; | InteractionResponseCallback = interactionResponseCallback; | ||||
| } | } | ||||
| /// <inheritdoc/> | |||||
| public void SetSegmentMatches(IEnumerable<IRouteSegmentMatch> segmentMatches) => SegmentMatches = segmentMatches.ToImmutableArray(); | |||||
| //IRouteMatchContainer | |||||
| /// <inheritdoc/> | |||||
| IEnumerable<IRouteSegmentMatch> IRouteMatchContainer.SegmentMatches => SegmentMatches; | |||||
| // IInterationContext | // IInterationContext | ||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| IDiscordClient IInteractionContext.Client => Client; | IDiscordClient IInteractionContext.Client => Client; | ||||
| @@ -274,7 +274,7 @@ namespace Discord.API | |||||
| { | { | ||||
| ["$device"] = "Discord.Net", | ["$device"] = "Discord.Net", | ||||
| ["$os"] = Environment.OSVersion.Platform.ToString(), | ["$os"] = Environment.OSVersion.Platform.ToString(), | ||||
| [$"browser"] = "Discord.Net" | |||||
| ["$browser"] = "Discord.Net" | |||||
| }; | }; | ||||
| var msg = new IdentifyParams() | var msg = new IdentifyParams() | ||||
| { | { | ||||
| @@ -1732,7 +1732,7 @@ namespace Discord.WebSocket | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| ulong? IGuild.AFKChannelId => AFKChannelId; | ulong? IGuild.AFKChannelId => AFKChannelId; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| IAudioClient IGuild.AudioClient => null; | |||||
| IAudioClient IGuild.AudioClient => AudioClient; | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| bool IGuild.Available => true; | bool IGuild.Available => true; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -36,6 +36,12 @@ namespace Discord.WebSocket | |||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| public bool IsDefaultPermission { get; private set; } | public bool IsDefaultPermission { get; private set; } | ||||
| /// <inheritdoc/> | |||||
| public bool IsEnabledInDm { get; private set; } | |||||
| /// <inheritdoc/> | |||||
| public GuildPermissions DefaultMemberPermissions { get; private set; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of <see cref="SocketApplicationCommandOption"/>s for this command. | /// Gets a collection of <see cref="SocketApplicationCommandOption"/>s for this command. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -86,6 +92,9 @@ namespace Discord.WebSocket | |||||
| Options = model.Options.IsSpecified | Options = model.Options.IsSpecified | ||||
| ? model.Options.Value.Select(SocketApplicationCommandOption.Create).ToImmutableArray() | ? model.Options.Value.Select(SocketApplicationCommandOption.Create).ToImmutableArray() | ||||
| : ImmutableArray.Create<SocketApplicationCommandOption>(); | : ImmutableArray.Create<SocketApplicationCommandOption>(); | ||||
| IsEnabledInDm = model.DmPermission.GetValueOrDefault(true).GetValueOrDefault(true); | |||||
| DefaultMemberPermissions = new GuildPermissions((ulong)model.DefaultMemberPermission.GetValueOrDefault(0).GetValueOrDefault(0)); | |||||
| } | } | ||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| @@ -1,11 +1,13 @@ | |||||
| using Discord.WebSocket; | using Discord.WebSocket; | ||||
| using System.Collections.Generic; | |||||
| using System.Collections.Immutable; | |||||
| namespace Discord.Interactions | namespace Discord.Interactions | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Represents a Web-Socket based context of an <see cref="IDiscordInteraction"/>. | /// Represents a Web-Socket based context of an <see cref="IDiscordInteraction"/>. | ||||
| /// </summary> | /// </summary> | ||||
| public class SocketInteractionContext<TInteraction> : IInteractionContext | |||||
| public class SocketInteractionContext<TInteraction> : IInteractionContext, IRouteMatchContainer | |||||
| where TInteraction : SocketInteraction | where TInteraction : SocketInteraction | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| @@ -36,6 +38,9 @@ namespace Discord.Interactions | |||||
| /// </summary> | /// </summary> | ||||
| public TInteraction Interaction { get; } | public TInteraction Interaction { get; } | ||||
| /// <inheritdoc cref="IRouteMatchContainer.SegmentMatches"/> | |||||
| public IReadOnlyCollection<IRouteSegmentMatch> SegmentMatches { get; private set; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Initializes a new <see cref="SocketInteractionContext{TInteraction}"/>. | /// Initializes a new <see cref="SocketInteractionContext{TInteraction}"/>. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -50,6 +55,13 @@ namespace Discord.Interactions | |||||
| Interaction = interaction; | Interaction = interaction; | ||||
| } | } | ||||
| /// <inheritdoc/> | |||||
| public void SetSegmentMatches(IEnumerable<IRouteSegmentMatch> segmentMatches) => SegmentMatches = segmentMatches.ToImmutableArray(); | |||||
| //IRouteMatchContainer | |||||
| /// <inheritdoc/> | |||||
| IEnumerable<IRouteSegmentMatch> IRouteMatchContainer.SegmentMatches => SegmentMatches; | |||||
| // IInteractionContext | // IInteractionContext | ||||
| /// <inheritdoc/> | /// <inheritdoc/> | ||||
| IDiscordClient IInteractionContext.Client => Client; | IDiscordClient IInteractionContext.Client => Client; | ||||
| @@ -2,7 +2,7 @@ | |||||
| <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> | <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> | ||||
| <metadata> | <metadata> | ||||
| <id>Discord.Net</id> | <id>Discord.Net</id> | ||||
| <version>3.5.0$suffix$</version> | |||||
| <version>3.6.1$suffix$</version> | |||||
| <title>Discord.Net</title> | <title>Discord.Net</title> | ||||
| <authors>Discord.Net Contributors</authors> | <authors>Discord.Net Contributors</authors> | ||||
| <owners>foxbot</owners> | <owners>foxbot</owners> | ||||
| @@ -14,44 +14,44 @@ | |||||
| <iconUrl>https://github.com/RogueException/Discord.Net/raw/dev/docs/marketing/logo/PackageLogo.png</iconUrl> | <iconUrl>https://github.com/RogueException/Discord.Net/raw/dev/docs/marketing/logo/PackageLogo.png</iconUrl> | ||||
| <dependencies> | <dependencies> | ||||
| <group targetFramework="net6.0"> | <group targetFramework="net6.0"> | ||||
| <dependency id="Discord.Net.Core" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Core" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.6.1$suffix$" /> | |||||
| </group> | </group> | ||||
| <group targetFramework="net5.0"> | <group targetFramework="net5.0"> | ||||
| <dependency id="Discord.Net.Core" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Core" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.6.1$suffix$" /> | |||||
| </group> | </group> | ||||
| <group targetFramework="net461"> | <group targetFramework="net461"> | ||||
| <dependency id="Discord.Net.Core" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Core" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.6.1$suffix$" /> | |||||
| </group> | </group> | ||||
| <group targetFramework="netstandard2.0"> | <group targetFramework="netstandard2.0"> | ||||
| <dependency id="Discord.Net.Core" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Core" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.6.1$suffix$" /> | |||||
| </group> | </group> | ||||
| <group targetFramework="netstandard2.1"> | <group targetFramework="netstandard2.1"> | ||||
| <dependency id="Discord.Net.Core" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.5.0$suffix$" /> | |||||
| <dependency id="Discord.Net.Core" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Rest" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.WebSocket" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Commands" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Webhook" version="3.6.1$suffix$" /> | |||||
| <dependency id="Discord.Net.Interactions" version="3.6.1$suffix$" /> | |||||
| </group> | </group> | ||||
| </dependencies> | </dependencies> | ||||
| </metadata> | </metadata> | ||||