| @@ -1,6 +1,4 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| @@ -8,35 +6,36 @@ namespace Discord.Commands | |||||
| [Flags] | [Flags] | ||||
| public enum ContextType | public enum ContextType | ||||
| { | { | ||||
| Guild = 1, // 01 | |||||
| DM = 2 // 10 | |||||
| Guild = 0x01, | |||||
| DM = 0x02, | |||||
| Group = 0x04 | |||||
| } | } | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | ||||
| public class RequireContextAttribute : PreconditionAttribute | 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) | 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()); | return Task.FromResult(PreconditionResult.FromSuccess()); | ||||
| else | 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; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| namespace Discord.Commands.Attributes.Preconditions | namespace Discord.Commands.Attributes.Preconditions | ||||
| @@ -8,42 +6,44 @@ namespace Discord.Commands.Attributes.Preconditions | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
| public class RequirePermission : PreconditionAttribute | 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) | public RequirePermission(GuildPermission permission) | ||||
| { | { | ||||
| GuildPermission = permission; | GuildPermission = permission; | ||||
| ChannelPermission = null; | ChannelPermission = null; | ||||
| } | } | ||||
| public RequirePermission(ChannelPermission permission) | public RequirePermission(ChannelPermission permission) | ||||
| { | { | ||||
| ChannelPermission = permission; | ChannelPermission = permission; | ||||
| GuildPermission = null; | GuildPermission = null; | ||||
| } | } | ||||
| public override Task<PreconditionResult> CheckPermissions(IMessage context, Command executingCommand, object moduleInstance) | 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) | 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) | 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()); | return Task.FromResult(PreconditionResult.FromSuccess()); | ||||
| @@ -8,9 +8,10 @@ namespace Discord | |||||
| public struct ChannelPermissions | public struct ChannelPermissions | ||||
| { | { | ||||
| //TODO: C#7 Candidate for binary literals | //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 _allText { get; } = new ChannelPermissions(Convert.ToUInt64("00000000000000011100110000000000", 2)); | ||||
| private static ChannelPermissions _allVoice { get; } = new ChannelPermissions(Convert.ToUInt64("00010011111100000000000000011001", 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> | /// <summary> Gets a blank ChannelPermissions that grants no permissions. </summary> | ||||
| public static ChannelPermissions None { get; } = new ChannelPermissions(); | public static ChannelPermissions None { get; } = new ChannelPermissions(); | ||||
| @@ -21,6 +22,7 @@ namespace Discord | |||||
| if (channel is ITextChannel) return _allText; | if (channel is ITextChannel) return _allText; | ||||
| if (channel is IVoiceChannel) return _allVoice; | if (channel is IVoiceChannel) return _allVoice; | ||||
| if (channel is IDMChannel) return _allDM; | if (channel is IDMChannel) return _allDM; | ||||
| if (channel is IGroupChannel) return _allGroup; | |||||
| throw new ArgumentException("Unknown channel type", nameof(channel)); | throw new ArgumentException("Unknown channel type", nameof(channel)); | ||||
| } | } | ||||
| @@ -118,6 +120,8 @@ namespace Discord | |||||
| embedLinks, attachFiles, readMessageHistory, mentionEveryone, connect, speak, muteMembers, deafenMembers, | embedLinks, attachFiles, readMessageHistory, mentionEveryone, connect, speak, muteMembers, deafenMembers, | ||||
| moveMembers, useVoiceActivation, managePermissions); | moveMembers, useVoiceActivation, managePermissions); | ||||
| public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission); | |||||
| public List<ChannelPermission> ToList() | public List<ChannelPermission> ToList() | ||||
| { | { | ||||
| var perms = new List<ChannelPermission>(); | var perms = new List<ChannelPermission>(); | ||||
| @@ -129,7 +129,9 @@ namespace Discord | |||||
| => new GuildPermissions(RawValue, createInstantInvite, manageRoles, kickMembers, banMembers, manageChannels, manageGuild, readMessages, | => new GuildPermissions(RawValue, createInstantInvite, manageRoles, kickMembers, banMembers, manageChannels, manageGuild, readMessages, | ||||
| sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, mentionEveryone, connect, speak, muteMembers, deafenMembers, | sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, mentionEveryone, connect, speak, muteMembers, deafenMembers, | ||||
| moveMembers, useVoiceActivation, changeNickname, manageNicknames, manageRoles); | moveMembers, useVoiceActivation, changeNickname, manageNicknames, manageRoles); | ||||
| public bool Has(GuildPermission permission) => Permissions.GetValue(RawValue, permission); | |||||
| public List<GuildPermission> ToList() | public List<GuildPermission> ToList() | ||||
| { | { | ||||
| var perms = new List<GuildPermission>(); | var perms = new List<GuildPermission>(); | ||||