diff --git a/src/Discord.Net.Commands/Attributes/Preconditions/RequireContextAttribute.cs b/src/Discord.Net.Commands/Attributes/Preconditions/RequireContextAttribute.cs index da9391fad..41f4e4a97 100644 --- a/src/Discord.Net.Commands/Attributes/Preconditions/RequireContextAttribute.cs +++ b/src/Discord.Net.Commands/Attributes/Preconditions/RequireContextAttribute.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; namespace Discord.Commands @@ -8,35 +6,36 @@ namespace Discord.Commands [Flags] public enum ContextType { - Guild = 1, // 01 - DM = 2 // 10 + Guild = 0x01, + DM = 0x02, + Group = 0x04 } - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class RequireContextAttribute : PreconditionAttribute { - public ContextType Context { get; set; } + public ContextType Contexts { get; } - public RequireContextAttribute(ContextType context) + public RequireContextAttribute(ContextType contexts) { - Context = context; + Contexts = contexts; } public override Task CheckPermissions(IMessage context, Command executingCommand, object moduleInstance) { - var validContext = false; - - if (Context.HasFlag(ContextType.Guild)) - validContext = validContext || context.Channel is IGuildChannel; + bool isValid = false; - if (Context.HasFlag(ContextType.DM)) - validContext = validContext || context.Channel is IDMChannel; + if ((Contexts & ContextType.Guild) != 0) + isValid = isValid || context.Channel is IGuildChannel; + if ((Contexts & ContextType.DM) != 0) + isValid = isValid || context.Channel is IDMChannel; + if ((Contexts & ContextType.Group) != 0) + isValid = isValid || context.Channel is IGroupChannel; - if (validContext) + if (isValid) return Task.FromResult(PreconditionResult.FromSuccess()); else - return Task.FromResult(PreconditionResult.FromError($"Invalid context for command; accepted contexts: {Context}")); + return Task.FromResult(PreconditionResult.FromError($"Invalid context for command; accepted contexts: {Contexts}")); } } } diff --git a/src/Discord.Net.Commands/Attributes/Preconditions/RequirePermission.cs b/src/Discord.Net.Commands/Attributes/Preconditions/RequirePermission.cs index a970685f5..bb624a2ae 100644 --- a/src/Discord.Net.Commands/Attributes/Preconditions/RequirePermission.cs +++ b/src/Discord.Net.Commands/Attributes/Preconditions/RequirePermission.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; namespace Discord.Commands.Attributes.Preconditions @@ -8,42 +6,44 @@ namespace Discord.Commands.Attributes.Preconditions [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class RequirePermission : PreconditionAttribute { - public GuildPermission? GuildPermission { get; set; } - public ChannelPermission? ChannelPermission { get; set; } + public GuildPermission? GuildPermission { get; } + public ChannelPermission? ChannelPermission { get; } public RequirePermission(GuildPermission permission) { GuildPermission = permission; ChannelPermission = null; } - public RequirePermission(ChannelPermission permission) { ChannelPermission = permission; GuildPermission = null; } - + public override Task CheckPermissions(IMessage context, Command executingCommand, object moduleInstance) { - if (!(context.Channel is IGuildChannel)) - return Task.FromResult(PreconditionResult.FromError("Command must be used in a guild channel")); - - var author = context.Author as IGuildUser; + var guildUser = context.Author as IGuildUser; if (GuildPermission.HasValue) { - var guildPerms = author.GuildPermissions.ToList(); - if (!guildPerms.Contains(GuildPermission.Value)) - return Task.FromResult(PreconditionResult.FromError($"User is missing guild permission {GuildPermission.Value}")); + if (guildUser == null) + return Task.FromResult(PreconditionResult.FromError("Command must be used in a guild channel")); + if (!guildUser.GuildPermissions.Has(GuildPermission.Value)) + return Task.FromResult(PreconditionResult.FromError($"Command requires guild permission {GuildPermission.Value}")); } if (ChannelPermission.HasValue) { - var channel = context.Channel as IGuildChannel; - var channelPerms = author.GetPermissions(channel).ToList(); + var guildChannel = context.Channel as IGuildChannel; + + ChannelPermissions perms; + if (guildChannel != null) + perms = guildUser.GetPermissions(guildChannel); + else + perms = ChannelPermissions.All(guildChannel); - if (!channelPerms.Contains(ChannelPermission.Value)) - return Task.FromResult(PreconditionResult.FromError($"User is missing channel permission {ChannelPermission.Value}")); + if (!perms.Has(ChannelPermission.Value)) + return Task.FromResult(PreconditionResult.FromError($"Command requires channel permission {ChannelPermission.Value}")); } return Task.FromResult(PreconditionResult.FromSuccess()); diff --git a/src/Discord.Net/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net/Entities/Permissions/ChannelPermissions.cs index 74938f509..8051eed1f 100644 --- a/src/Discord.Net/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net/Entities/Permissions/ChannelPermissions.cs @@ -8,9 +8,10 @@ namespace Discord public struct ChannelPermissions { //TODO: C#7 Candidate for binary literals - private static ChannelPermissions _allDM { get; } = new ChannelPermissions(Convert.ToUInt64("00010000000000111111110000011001", 2)); private static ChannelPermissions _allText { get; } = new ChannelPermissions(Convert.ToUInt64("00000000000000011100110000000000", 2)); private static ChannelPermissions _allVoice { get; } = new ChannelPermissions(Convert.ToUInt64("00010011111100000000000000011001", 2)); + private static ChannelPermissions _allDM { get; } = new ChannelPermissions(Convert.ToUInt64("00010000000000111111110000011001", 2)); + private static ChannelPermissions _allGroup { get; } = new ChannelPermissions(Convert.ToUInt64("00010000000000111111110000011001", 2)); /// Gets a blank ChannelPermissions that grants no permissions. public static ChannelPermissions None { get; } = new ChannelPermissions(); @@ -21,6 +22,7 @@ namespace Discord if (channel is ITextChannel) return _allText; if (channel is IVoiceChannel) return _allVoice; if (channel is IDMChannel) return _allDM; + if (channel is IGroupChannel) return _allGroup; throw new ArgumentException("Unknown channel type", nameof(channel)); } @@ -118,6 +120,8 @@ namespace Discord embedLinks, attachFiles, readMessageHistory, mentionEveryone, connect, speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, managePermissions); + public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission); + public List ToList() { var perms = new List(); diff --git a/src/Discord.Net/Entities/Permissions/GuildPermissions.cs b/src/Discord.Net/Entities/Permissions/GuildPermissions.cs index 32aadb603..141f979f9 100644 --- a/src/Discord.Net/Entities/Permissions/GuildPermissions.cs +++ b/src/Discord.Net/Entities/Permissions/GuildPermissions.cs @@ -129,7 +129,9 @@ namespace Discord => new GuildPermissions(RawValue, createInstantInvite, manageRoles, kickMembers, banMembers, manageChannels, manageGuild, readMessages, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, mentionEveryone, connect, speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, changeNickname, manageNicknames, manageRoles); - + + public bool Has(GuildPermission permission) => Permissions.GetValue(RawValue, permission); + public List ToList() { var perms = new List();