public void HasPermissionReturnsTrueForExistingVoicePermission()
        {
            var permissions = new DiscordPermissionSet(BigInteger.One);
            var permission  = DiscordVoicePermission.CreateInstantInvite;

            Assert.True(permissions.HasPermission(permission));
        }
        public void HasPermissionReturnsFalseForNonExistentVoicePermission()
        {
            var permissions = new DiscordPermissionSet(BigInteger.One);
            var permission  = DiscordVoicePermission.ManageChannels;

            Assert.False(permissions.HasPermission(permission));
        }
Beispiel #3
0
        public void CanComputeMemberWithRolePermissions()
        {
            var memberID = new Snowflake(0);

            var everyonePermissions = new DiscordPermissionSet(DiscordTextPermission.SendMessages);
            var everyoneRoleMock    = new Mock <IRole>();

            everyoneRoleMock.SetupGet(r => r.ID).Returns(new Snowflake(1));
            everyoneRoleMock.SetupGet(r => r.Permissions).Returns(everyonePermissions);

            var everyoneRole = everyoneRoleMock.Object;

            var rolePermissions = new DiscordPermissionSet(DiscordTextPermission.MentionEveryone);
            var roleMock        = new Mock <IRole>();

            roleMock.SetupGet(r => r.ID).Returns(new Snowflake(2));
            roleMock.SetupGet(r => r.Permissions).Returns(rolePermissions);

            var role = roleMock.Object;

            var actual = DiscordPermissionSet.ComputePermissions(memberID, everyoneRole, new[] { role });

            var expected = new DiscordPermissionSet
                           (
                DiscordTextPermission.SendMessages,
                DiscordTextPermission.MentionEveryone
                           );

            Assert.Equal(expected, actual);
        }
        public void HasPermissionReturnsFalseForNonExistentPermissionInAnotherByte()
        {
            var permissions = new DiscordPermissionSet(BigInteger.One);
            var permission  = DiscordPermission.MoveMembers;

            Assert.False(permissions.HasPermission(permission));
        }
Beispiel #5
0
        public void CanComputeMemberPermissionsWithMemberDenyOverwrites()
        {
            var memberID = new Snowflake(0);

            var everyonePermissions = new DiscordPermissionSet(DiscordTextPermission.SendMessages);
            var everyoneRoleMock    = new Mock <IRole>();

            everyoneRoleMock.SetupGet(r => r.ID).Returns(new Snowflake(1));
            everyoneRoleMock.SetupGet(r => r.Permissions).Returns(everyonePermissions);

            var everyoneRole = everyoneRoleMock.Object;

            var memberDeny          = new DiscordPermissionSet(DiscordTextPermission.SendMessages);
            var memberOverwriteMock = new Mock <IPermissionOverwrite>();

            memberOverwriteMock.SetupGet(o => o.ID).Returns(memberID);
            memberOverwriteMock.SetupGet(o => o.Allow).Returns(new DiscordPermissionSet(BigInteger.Zero));
            memberOverwriteMock.SetupGet(o => o.Deny).Returns(memberDeny);

            var memberOverwrite = memberOverwriteMock.Object;

            var actual = DiscordPermissionSet.ComputePermissions
                         (
                memberID,
                everyoneRole,
                Array.Empty <IRole>(),
                new[] { memberOverwrite }
                         );

            var expected = new DiscordPermissionSet(BigInteger.Zero);

            Assert.Equal(expected, actual);
        }
    public async Task <Result> RespondAsync(IMessageReactionAdd ev, CancellationToken ct = default)
    {
        if (ev.ChannelID.Value != _discordSettings.FeedbackChannelId ||
            !ev.GuildID.HasValue ||
            !ev.Member.HasValue ||
            ev.Member.Value.User.HasValue && ev.Member.Value.User.Value.IsBot.HasValue &&
            ev.Member.Value.User.Value.IsBot.Value ||
            !ev.Emoji.Name.HasValue ||
            ev.Emoji.Name.Value is null ||
            !_protectedEmojis.Contains(ev.Emoji.Name.Value)
            )
        {
            return(Result.FromSuccess());
        }

        var getChannelResult = await _channelApi.GetChannelAsync(ev.ChannelID, ct);

        if (!getChannelResult.IsSuccess)
        {
            return(Result.FromError(getChannelResult));
        }

        var getGuildRolesResult = await _guildApi.GetGuildRolesAsync(ev.GuildID.Value, ct);

        if (!getGuildRolesResult.IsSuccess)
        {
            return(Result.FromError(getGuildRolesResult));
        }

        var channel      = getChannelResult.Entity;
        var guildRoles   = getGuildRolesResult.Entity;
        var everyoneRole = guildRoles.FirstOrDefault(r => r.ID == ev.GuildID.Value);

        if (everyoneRole is null)
        {
            return(new NotFoundError("No @everyone role found."));
        }

        var memberRoles         = guildRoles.Where(r => ev.Member.Value.Roles.Contains(r.ID)).ToList();
        var computedPermissions = channel.PermissionOverwrites.HasValue
            ? DiscordPermissionSet.ComputePermissions(ev.UserID, everyoneRole, memberRoles,
                                                      channel.PermissionOverwrites.Value)
            : DiscordPermissionSet.ComputePermissions(ev.UserID, everyoneRole, memberRoles);

        return(computedPermissions.HasPermission(DiscordPermission.Administrator) ||
               computedPermissions.HasPermission(DiscordPermission.BanMembers)
            ? Result.FromSuccess()
            : await _channelApi.DeleteUserReactionAsync(ev.ChannelID, ev.MessageID, ev.Emoji.Name.Value, ev.UserID,
                                                        ct));
    }
Beispiel #7
0
        public void CanComputeMemberPermissionsWithRoleAllowOverwrites()
        {
            var memberID = new Snowflake(0);

            var everyonePermissions = new DiscordPermissionSet(DiscordTextPermission.SendMessages);
            var everyoneMock        = new Mock <IRole>();

            everyoneMock.SetupGet(r => r.ID).Returns(new Snowflake(1));
            everyoneMock.SetupGet(r => r.Permissions).Returns(everyonePermissions);

            var everyoneRole = everyoneMock.Object;

            var rolePermissions = new DiscordPermissionSet(DiscordTextPermission.MentionEveryone);
            var roleMock        = new Mock <IRole>();

            roleMock.SetupGet(r => r.ID).Returns(new Snowflake(2));
            roleMock.SetupGet(r => r.Permissions).Returns(rolePermissions);

            var role = roleMock.Object;

            var roleAllow         = new DiscordPermissionSet(DiscordTextPermission.AddReactions);
            var roleOverwriteMock = new Mock <IPermissionOverwrite>();

            roleOverwriteMock.SetupGet(o => o.ID).Returns(role.ID);
            roleOverwriteMock.SetupGet(o => o.Allow).Returns(roleAllow);
            roleOverwriteMock.SetupGet(o => o.Deny).Returns(new DiscordPermissionSet(BigInteger.Zero));

            var roleOverwrite = roleOverwriteMock.Object;

            var actual = DiscordPermissionSet.ComputePermissions
                         (
                memberID,
                everyoneRole,
                new[] { role },
                new[] { roleOverwrite }
                         );

            var expected = new DiscordPermissionSet
                           (
                DiscordTextPermission.SendMessages,
                DiscordTextPermission.MentionEveryone,
                DiscordTextPermission.AddReactions
                           );

            Assert.Equal(expected, actual);
        }
Beispiel #8
0
        public void CanComputeMemberPermissions()
        {
            var memberID = new Snowflake(0);

            var everyonePermissions = new DiscordPermissionSet(DiscordTextPermission.SendMessages);
            var everyoneRoleMock    = new Mock <IRole>();

            everyoneRoleMock.SetupGet(r => r.ID).Returns(new Snowflake(1));
            everyoneRoleMock.SetupGet(r => r.Permissions).Returns(everyonePermissions);

            var everyoneRole = everyoneRoleMock.Object;

            var actual = DiscordPermissionSet.ComputePermissions
                         (
                memberID,
                everyoneRole,
                Array.Empty <IRole>()
                         );

            var expected = new DiscordPermissionSet(DiscordTextPermission.SendMessages);

            Assert.Equal(expected, actual);
        }
        public async Task <Result <FeedbackMessage> > SetCharacterRoleAsync
        (
            [RequireEntityOwner]
            [AutocompleteProvider("character::owned")]
            Character character,
            IRole discordRole
        )
        {
            var getRoleResult = await _characterRoles.GetCharacterRoleAsync
                                (
                _context.GuildID.Value,
                discordRole.ID,
                this.CancellationToken
                                );

            if (!getRoleResult.IsSuccess)
            {
                return(Result <FeedbackMessage> .FromError(getRoleResult));
            }

            // Get a bunch of stuff for permission checking...
            var getMember = await _guildAPI.GetGuildMemberAsync
                            (
                _context.GuildID.Value,
                _context.User.ID,
                this.CancellationToken
                            );

            if (!getMember.IsSuccess)
            {
                return(Result <FeedbackMessage> .FromError(getMember));
            }

            var member = getMember.Entity;

            var getGuildRoles = await _guildAPI.GetGuildRolesAsync(_context.GuildID.Value, this.CancellationToken);

            if (!getGuildRoles.IsSuccess)
            {
                return(Result <FeedbackMessage> .FromError(getGuildRoles));
            }

            var guildRoles   = getGuildRoles.Entity;
            var everyoneRole = guildRoles.First(r => r.ID == _context.GuildID.Value);
            var memberRoles  = guildRoles.Where(r => member.Roles.Contains(r.ID)).ToList();

            // We ignore channel overrides here; the user should have it on a guild level
            var computedPermissions = DiscordPermissionSet.ComputePermissions
                                      (
                _context.User.ID,
                everyoneRole,
                memberRoles
                                      );

            var characterRole = getRoleResult.Entity;

            if (characterRole.Access == RoleAccess.Restricted)
            {
                if (!computedPermissions.HasPermission(DiscordPermission.ManageRoles))
                {
                    return(new UserError
                           (
                               "That role is restricted, and you must be able to manage roles to use it."
                           ));
                }
            }

            var setRoleResult = await _characterRoles.SetCharacterRoleAsync
                                (
                _context.GuildID.Value,
                _context.User.ID,
                character,
                characterRole,
                this.CancellationToken
                                );

            return(!setRoleResult.IsSuccess
                ? Result <FeedbackMessage> .FromError(setRoleResult)
                : new FeedbackMessage("Character role set.", _feedback.Theme.Secondary));
        }
    /// <summary>
    /// Posts a notification that a message was deleted.
    /// </summary>
    /// <param name="message">The deleted message.</param>
    /// <param name="guildID">The ID of the guild in which the message was.</param>
    /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
    public async Task <Result> NotifyMessageDeletedAsync(IMessage message, Snowflake guildID)
    {
        // We don't care about bot messages
        var isNonFeedbackMessage = (message.Author.IsBot.IsDefined(out var isBot) && isBot) ||
                                   (message.Author.IsSystem.IsDefined(out var isSystem) && isSystem);

        if (isNonFeedbackMessage)
        {
            return(Result.FromSuccess());
        }

        var getChannel = await GetMonitoringChannelAsync(guildID);

        if (!getChannel.IsSuccess)
        {
            return(Result.FromError(getChannel));
        }

        var getSelf = await _userAPI.GetCurrentUserAsync();

        if (!getSelf.IsSuccess)
        {
            return(Result.FromError(getSelf));
        }

        var self    = getSelf.Entity;
        var channel = getChannel.Entity;

        var eb = new Embed
        {
            Colour = _feedback.Theme.Warning,
            Title  = "Message Deleted"
        };

        var getGuildRoles = await _guildAPI.GetGuildRolesAsync(guildID);

        if (!getGuildRoles.IsSuccess)
        {
            return(Result.FromError(getGuildRoles));
        }

        var guildRoles   = getGuildRoles.Entity;
        var everyoneRole = guildRoles.First(r => r.ID == guildID);

        var getGuildMember = await _guildAPI.GetGuildMemberAsync(guildID, self.ID);

        if (!getGuildMember.IsSuccess)
        {
            return(Result.FromError(getGuildMember));
        }

        var botGuildMember = getGuildMember.Entity;
        var botRoles       = guildRoles.Where(r => botGuildMember.Roles.Contains(r.ID)).ToList();

        var botPermissions = DiscordPermissionSet.ComputePermissions
                             (
            self.ID,
            everyoneRole,
            botRoles
                             );

        var extra = string.Empty;

        if (botPermissions.HasPermission(DiscordPermission.ViewAuditLog))
        {
            var getMostProbableDeleter = await FindMostProbableDeleterAsync(message, guildID);

            if (!getMostProbableDeleter.IsSuccess)
            {
                return(Result.FromError(getMostProbableDeleter));
            }

            var userID  = getMostProbableDeleter.Entity;
            var getUser = await _userAPI.GetUserAsync(userID);

            if (!getUser.IsSuccess)
            {
                return(Result.FromError(getUser));
            }

            var mostProbableDeleter = getUser.Entity;

            var isNonUserDeleter = (mostProbableDeleter.IsBot.IsDefined(out var isDeleterBot) && isDeleterBot) ||
                                   (mostProbableDeleter.IsSystem.IsDefined(out var isDeleterSystem) && isDeleterSystem);

            // We don't care about bot deletions
            if (!isNonUserDeleter)
            {
                extra = $" (probably) by <@{mostProbableDeleter.ID}>";
            }
        }

        eb = eb with
        {
            Description = $"A message was deleted from <#{message.ChannelID}>{extra}."
        };

        var quote = QuoteService.CreateMessageQuote(message, self.ID);

        var sendResult = await _feedback.SendEmbedAsync(channel, eb);

        if (!sendResult.IsSuccess)
        {
            return(Result.FromError(sendResult));
        }

        sendResult = await _feedback.SendEmbedAsync(channel, quote);

        return(sendResult.IsSuccess
            ? Result.FromSuccess()
            : Result.FromError(sendResult));
    }
Beispiel #11
0
        /// <inheritdoc />
        public async ValueTask <Result> CheckHasRequiredPermission(
            DiscordPermission permission,
            Snowflake channelId,
            IUser userToCheck,
            CancellationToken ct = default
            )
        {
            var getChannel = await _channelApi.GetChannelAsync(channelId, ct);

            if (!getChannel.IsSuccess)
            {
                return(Result.FromError(getChannel));
            }

            var channel = getChannel.Entity;

            if (!channel.GuildID.HasValue)
            {
                return(new ConditionNotSatisfiedError(
                           "Command requires a guild permission but was executed outside of a guild."));
            }

            var guildId = channel.GuildID.Value;

            var getGuildMember = await _guildApi.GetGuildMemberAsync(guildId, userToCheck.ID, ct);

            if (!getGuildMember.IsSuccess)
            {
                return(Result.FromError(getGuildMember));
            }

            var getGuildRoles = await _guildApi.GetGuildRolesAsync(guildId, ct);

            if (!getGuildRoles.IsSuccess)
            {
                return(Result.FromError(getGuildRoles));
            }

            var guildRoles   = getGuildRoles.Entity;
            var everyoneRole = guildRoles.FirstOrDefault(r => r.Name.Equals("@everyone"));

            if (everyoneRole is null)
            {
                return(new NotFoundError("No @everyone role found."));
            }

            var user = getGuildMember.Entity;

            if (user is null)
            {
                return(new NotFoundError("Executing user not found"));
            }

            var getGuild = await _guildApi.GetGuildAsync(guildId, ct : ct);

            if (!getGuild.IsSuccess)
            {
                return(Result.FromError(getGuild));
            }

            var guildOwnerId = getGuild.Entity.OwnerID;

            // succeed if the user is the Owner of the guild
            if (guildOwnerId.Equals(userToCheck.ID))
            {
                return(Result.FromSuccess());
            }

            var memberRoles = guildRoles.Where(r => user.Roles.Contains(r.ID)).ToList();
            IDiscordPermissionSet computedPermissions;

            if (channel.PermissionOverwrites.HasValue)
            {
                computedPermissions = DiscordPermissionSet.ComputePermissions(
                    userToCheck.ID,
                    everyoneRole,
                    memberRoles,
                    channel.PermissionOverwrites.Value
                    );
            }
            else
            {
                computedPermissions = DiscordPermissionSet.ComputePermissions(
                    userToCheck.ID,
                    everyoneRole,
                    memberRoles
                    );
            }

            // succeed if the user is an Administrator of the guild
            if (computedPermissions.HasPermission(DiscordPermission.Administrator))
            {
                return(Result.FromSuccess());
            }

            var hasPermission = computedPermissions.HasPermission(permission);

            return(!hasPermission
                ? new ConditionNotSatisfiedError(
                       $"Guild User requesting the command does not have the required {permission.ToString()} permission")
                : Result.FromSuccess());
        }