diff --git a/src/Discord.Net.Interactions/Attributes/Preconditions/RequireAppPermissionAttribute.cs b/src/Discord.Net.Interactions/Attributes/Preconditions/RequireAppPermissionAttribute.cs new file mode 100644 index 0000000000..b1f65c81ca --- /dev/null +++ b/src/Discord.Net.Interactions/Attributes/Preconditions/RequireAppPermissionAttribute.cs @@ -0,0 +1,77 @@ +using System.Threading.Tasks; +using System; + +namespace Discord.Interactions; + +/// +/// Requires the bot to have a specific permission in the channel a command is invoked in. +/// +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] +public class RequireAppPermissionAttribute : PreconditionAttribute +{ + /// + /// Gets the specified of the precondition. + /// + public GuildPermission? GuildPermission { get; } + + /// + /// Gets the specified of the precondition. + /// + public ChannelPermission? ChannelPermission { get; } + + /// + /// Gets or sets the error message if the precondition + /// fails due to being run outside of a Guild channel. + /// + public string NotAGuildErrorMessage { get; set; } + + /// + /// Requires the bot account to have a specific . + /// + /// + /// This precondition will always fail if the command is being invoked in a . + /// + /// + /// The that the bot must have. Multiple permissions can be specified + /// by ORing the permissions together. + /// + public RequireAppPermissionAttribute(GuildPermission permission) + { + GuildPermission = permission; + ChannelPermission = null; + } + /// + /// Requires that the bot account to have a specific . + /// + /// + /// The that the bot must have. Multiple permissions can be + /// specified by ORing the permissions together. + /// + public RequireAppPermissionAttribute(ChannelPermission permission) + { + ChannelPermission = permission; + GuildPermission = null; + } + + /// + public override Task CheckRequirementsAsync(IInteractionContext context, ICommandInfo command, IServiceProvider services) + { + if (GuildPermission.HasValue) + { + if (context.Interaction.GuildId is null) + return Task.FromResult(PreconditionResult.FromError(NotAGuildErrorMessage ?? "Command must be used in a guild channel.")); + if (context.Interaction.Permissions.Has(GuildPermission.Value)) + return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"Bot requires guild permission {GuildPermission.Value}.")); + } + + if (ChannelPermission.HasValue) + { + var channelPerms = new ChannelPermissions(context.Interaction.Permissions.RawValue); + if (!channelPerms.Has(ChannelPermission.Value)) + return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"Bot requires channel permission {ChannelPermission.Value}.")); + } + + return Task.FromResult(PreconditionResult.FromSuccess()); + } + +} diff --git a/src/Discord.Net.Interactions/Attributes/Preconditions/RequireBotPermissionAttribute.cs b/src/Discord.Net.Interactions/Attributes/Preconditions/RequireBotPermissionAttribute.cs index 1dd3092ffc..f6d58685bf 100644 --- a/src/Discord.Net.Interactions/Attributes/Preconditions/RequireBotPermissionAttribute.cs +++ b/src/Discord.Net.Interactions/Attributes/Preconditions/RequireBotPermissionAttribute.cs @@ -7,6 +7,7 @@ namespace Discord.Interactions /// Requires the bot to have a specific permission in the channel a command is invoked in. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + [Obsolete("This attribute does not support user app interactions. Consider switching to 'RequireAppPermissionAttribute'", false)] public class RequireBotPermissionAttribute : PreconditionAttribute { /// diff --git a/src/Discord.Net.Rest/Entities/Messages/CustomSticker.cs b/src/Discord.Net.Rest/Entities/Messages/CustomSticker.cs index 6fd0f7700a..9626a8c741 100644 --- a/src/Discord.Net.Rest/Entities/Messages/CustomSticker.cs +++ b/src/Discord.Net.Rest/Entities/Messages/CustomSticker.cs @@ -34,6 +34,7 @@ internal CustomSticker(BaseDiscordClient client, ulong id, RestGuild guild, ulon { AuthorId = authorId; Guild = guild; + GuildId = guild.Id; } internal CustomSticker(BaseDiscordClient client, ulong id, ulong guildId, ulong? authorId = null) : base(client, id)