| @@ -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<PreconditionResult> 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}")); | |||
| } | |||
| } | |||
| } | |||
| @@ -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<PreconditionResult> 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()); | |||
| @@ -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)); | |||
| /// <summary> Gets a blank ChannelPermissions that grants no permissions. </summary> | |||
| 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<ChannelPermission> ToList() | |||
| { | |||
| var perms = new List<ChannelPermission>(); | |||
| @@ -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<GuildPermission> ToList() | |||
| { | |||
| var perms = new List<GuildPermission>(); | |||