| @@ -0,0 +1,75 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord.Commands | |||||
| { | |||||
| /// <summary> | |||||
| /// This attribute requires that the bot has a speicifed permission in the channel a command is invoked in. | |||||
| /// </summary> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |||||
| public class RequireBotPermissionAttribute : PreconditionAttribute | |||||
| { | |||||
| public GuildPermission? GuildPermission { get; } | |||||
| public ChannelPermission? ChannelPermission { get; } | |||||
| /// <summary> | |||||
| /// Require that the bot account has a specified GuildPermission | |||||
| /// </summary> | |||||
| /// <remarks>This precondition will always fail if the command is being invoked in a private channel.</remarks> | |||||
| /// <param name="permission">The GuildPermission that the bot must have. Multiple permissions can be specified by ORing or ANDing the permissions together.</param> | |||||
| public RequireBotPermissionAttribute(GuildPermission permission) | |||||
| { | |||||
| GuildPermission = permission; | |||||
| ChannelPermission = null; | |||||
| } | |||||
| /// <summary> | |||||
| /// Require that the bot account has a specified ChannelPermission. | |||||
| /// </summary> | |||||
| /// <param name="permission">The ChannelPermission that the bot must have. Multiple permissions can be specified by ORing or ANDing the permissions together.</param> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// [Command("permission")] | |||||
| /// [RequireBotPermission(ChannelPermission.ManageMessages)] | |||||
| /// public async Task Purge() | |||||
| /// { | |||||
| /// } | |||||
| /// </code> | |||||
| /// </example> | |||||
| public RequireBotPermissionAttribute(ChannelPermission permission) | |||||
| { | |||||
| ChannelPermission = permission; | |||||
| GuildPermission = null; | |||||
| } | |||||
| public override async Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map) | |||||
| { | |||||
| var guildUser = await context.Guild.GetCurrentUserAsync(); | |||||
| if (GuildPermission.HasValue) | |||||
| { | |||||
| if (guildUser == null) | |||||
| return PreconditionResult.FromError("Command must be used in a guild channel"); | |||||
| if (!guildUser.GuildPermissions.Has(GuildPermission.Value)) | |||||
| return PreconditionResult.FromError($"Command requires guild permission {GuildPermission.Value}"); | |||||
| } | |||||
| if (ChannelPermission.HasValue) | |||||
| { | |||||
| var guildChannel = context.Channel as IGuildChannel; | |||||
| ChannelPermissions perms; | |||||
| if (guildChannel != null) | |||||
| perms = guildUser.GetPermissions(guildChannel); | |||||
| else | |||||
| perms = ChannelPermissions.All(guildChannel); | |||||
| if (!perms.Has(ChannelPermission.Value)) | |||||
| return PreconditionResult.FromError($"Command requires channel permission {ChannelPermission.Value}"); | |||||
| } | |||||
| return PreconditionResult.FromSuccess(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -11,11 +11,27 @@ namespace Discord.Commands | |||||
| Group = 0x04 | Group = 0x04 | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Require that the command be invoked in a specified context. | |||||
| /// </summary> | |||||
| [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 Contexts { get; } | public ContextType Contexts { get; } | ||||
| /// <summary> | |||||
| /// Require that the command be invoked in a specified context. | |||||
| /// </summary> | |||||
| /// <param name="contexts">The type of context the command can be invoked in. Multiple contexts can be speicifed by ORing the contexts together.</param> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// [Command("private_only")] | |||||
| /// [RequireContext(ContextType.DM | ContextType.Group)] | |||||
| /// public async Task PrivateOnly() | |||||
| /// { | |||||
| /// } | |||||
| /// </code> | |||||
| /// </example> | |||||
| public RequireContextAttribute(ContextType contexts) | public RequireContextAttribute(ContextType contexts) | ||||
| { | { | ||||
| Contexts = contexts; | Contexts = contexts; | ||||
| @@ -0,0 +1,23 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| using Discord; | |||||
| namespace Discord.Commands | |||||
| { | |||||
| /// <summary> | |||||
| /// Require that the command is invoked by the owner of the bot. | |||||
| /// </summary> | |||||
| /// <remarks>This precondition will only work if the bot is a bot account.</remarks> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |||||
| public class RequireOwnerAttribute : PreconditionAttribute | |||||
| { | |||||
| public override async Task<PreconditionResult> CheckPermissions(CommandContext context, CommandInfo command, IDependencyMap map) | |||||
| { | |||||
| var application = await context.Client.GetApplicationInfoAsync(); | |||||
| if (context.User.Id == application.Owner.Id) return PreconditionResult.FromSuccess(); | |||||
| return PreconditionResult.FromError("Command can only be run by the owner of the bot"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -3,18 +3,40 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| /// <summary> | |||||
| /// This attribute requires that the user invoking the command has a specified permission. | |||||
| /// </summary> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
| public class RequirePermissionAttribute : PreconditionAttribute | |||||
| public class RequireUserPermissionAttribute : PreconditionAttribute | |||||
| { | { | ||||
| public GuildPermission? GuildPermission { get; } | public GuildPermission? GuildPermission { get; } | ||||
| public ChannelPermission? ChannelPermission { get; } | public ChannelPermission? ChannelPermission { get; } | ||||
| public RequirePermissionAttribute(GuildPermission permission) | |||||
| /// <summary> | |||||
| /// Require that the user invoking the command has a specified GuildPermission | |||||
| /// </summary> | |||||
| /// <remarks>This precondition will always fail if the command is being invoked in a private channel.</remarks> | |||||
| /// <param name="permission">The GuildPermission that the user must have. Multiple permissions can be specified by ORing or ANDing the permissions together.</param> | |||||
| public RequireUserPermissionAttribute(GuildPermission permission) | |||||
| { | { | ||||
| GuildPermission = permission; | GuildPermission = permission; | ||||
| ChannelPermission = null; | ChannelPermission = null; | ||||
| } | } | ||||
| public RequirePermissionAttribute(ChannelPermission permission) | |||||
| /// <summary> | |||||
| /// Require that the user invoking the command has a specified ChannelPermission. | |||||
| /// </summary> | |||||
| /// <param name="permission">The ChannelPermission that the user must have. Multiple permissions can be specified by ORing or ANDing the permissions together.</param> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// [Command("permission")] | |||||
| /// [RequireUserPermission(ChannelPermission.ReadMessageHistory & ChannelPermission.ReadMessages)] | |||||
| /// public async Task HasPermission() | |||||
| /// { | |||||
| /// await ReplyAsync("You can read messages and the message history!"); | |||||
| /// } | |||||
| /// </code> | |||||
| /// </example> | |||||
| public RequireUserPermissionAttribute(ChannelPermission permission) | |||||
| { | { | ||||
| ChannelPermission = permission; | ChannelPermission = permission; | ||||
| GuildPermission = null; | GuildPermission = null; | ||||
| @@ -38,6 +38,7 @@ namespace Discord.WebSocket | |||||
| private int _nextAudioId; | private int _nextAudioId; | ||||
| private bool _canReconnect; | private bool _canReconnect; | ||||
| private DateTimeOffset? _statusSince; | private DateTimeOffset? _statusSince; | ||||
| private RestApplication _application; | |||||
| /// <summary> Gets the shard of of this client. </summary> | /// <summary> Gets the shard of of this client. </summary> | ||||
| public int ShardId { get; } | public int ShardId { get; } | ||||
| @@ -333,8 +334,10 @@ namespace Discord.WebSocket | |||||
| } | } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public Task<RestApplication> GetApplicationInfoAsync() | |||||
| => ClientHelper.GetApplicationInfoAsync(this); | |||||
| public async Task<RestApplication> GetApplicationInfoAsync() | |||||
| { | |||||
| return _application ?? (_application = await ClientHelper.GetApplicationInfoAsync(this)); | |||||
| } | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public SocketGuild GetGuild(ulong id) | public SocketGuild GetGuild(ulong id) | ||||