@@ -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>(); | |||