Example #1
0
        /// <summary>
        /// Posts a notification that a message was deleted.
        /// </summary>
        /// <param name="message">The deleted message.</param>
        /// <param name="messageChannel">The channel the message was deleted from.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task <OperationResult> NotifyMessageDeletedAsync(IMessage message, ISocketMessageChannel messageChannel)
        {
            if (!(messageChannel is ITextChannel textChannel))
            {
                return(OperationResult.FromError("The channel was not a text channel."));
            }

            // We don't care about bot messages
            if (message.Author.IsBot | message.Author.IsWebhook)
            {
                return(OperationResult.FromSuccess());
            }

            var getChannel = await GetMonitoringChannelAsync(textChannel.Guild);

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

            var channel = getChannel.Entity;

            var eb = _feedback.CreateEmbedBase();

            eb.WithTitle("Message Deleted");
            eb.WithColor(Color.Orange);

            var extra = string.Empty;

            if ((await textChannel.Guild.GetUserAsync(_client.CurrentUser.Id)).GuildPermissions.ViewAuditLog)
            {
                var mostProbableDeleter = await FindMostProbableDeleterAsync(message, textChannel);

                // We don't care about bot deletions
                if (!(mostProbableDeleter.IsBot || mostProbableDeleter.IsWebhook))
                {
                    extra = $"by {mostProbableDeleter.Mention}.";
                }
            }

            eb.WithDescription
            (
                $"A message was deleted from {MentionUtils.MentionChannel(textChannel.Id)} {extra}"
            );

            var quote = _quotes.CreateMessageQuote(message, _client.CurrentUser);

            await _feedback.SendEmbedAsync(channel, eb.Build());

            await _feedback.SendEmbedAsync(channel, quote.Build());

            return(OperationResult.FromSuccess());
        }
    /// <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));
    }
Example #3
0
        /// <inheritdoc />
        protected override async Task <OperationResult> MessageReceivedAsync(SocketMessage arg)
        {
            if (!(arg is SocketUserMessage message))
            {
                return(OperationResult.FromError("The message was not a user message."));
            }

            if (!(message.Author is SocketGuildUser guildUser))
            {
                return(OperationResult.FromError("The author was not a guild user."));
            }

            if (arg.Author.IsBot || arg.Author.IsWebhook)
            {
                return(OperationResult.FromSuccess());
            }

            var discard = 0;

            if (message.HasCharPrefix('!', ref discard))
            {
                return(OperationResult.FromSuccess());
            }

            if (message.HasMentionPrefix(this.Client.CurrentUser, ref discard))
            {
                return(OperationResult.FromSuccess());
            }

            if (IsQuote(message))
            {
                return(OperationResult.FromSuccess());
            }

            var matches = Pattern.Matches(message.Content);

            if (matches.Count == 0)
            {
                return(OperationResult.FromSuccess());
            }

            foreach (Match?match in matches)
            {
                if (match is null)
                {
                    continue;
                }

                if (!ulong.TryParse(match.Groups["GuildId"].Value, out _) ||
                    !ulong.TryParse(match.Groups["ChannelId"].Value, out var channelId) ||
                    !ulong.TryParse(match.Groups["MessageId"].Value, out var messageId))
                {
                    continue;
                }

                var quotedChannel = this.Client.GetChannel(channelId);

                if (!(quotedChannel is IGuildChannel) ||
                    !(quotedChannel is ISocketMessageChannel quotedMessageChannel))
                {
                    continue;
                }

                var quotedMessage = await quotedMessageChannel.GetMessageAsync(messageId);

                if (quotedMessage == null || IsQuote(quotedMessage))
                {
                    return(OperationResult.FromSuccess());
                }

                var embed = _quotes.CreateMessageQuote(quotedMessage, guildUser);
                embed.WithTimestamp(quotedMessage.Timestamp);

                try
                {
                    await message.Channel.SendMessageAsync(string.Empty, embed : embed.Build());
                }
                catch (HttpException hex)
                {
                    if (!hex.WasCausedByMissingPermission())
                    {
                        throw;
                    }
                }
            }

            if (!(message.Channel is IGuildChannel messageGuildChannel))
            {
                return(OperationResult.FromSuccess());
            }

            var guildBotUser = await messageGuildChannel.Guild.GetUserAsync(this.Client.CurrentUser.Id);

            var messageCharacterCount = message.Content.Select(c => !char.IsWhiteSpace(c)).Count();
            var matchesCharacterCount = matches.Sum(m => m.Length);

            // If the message consists of just links (i.e, no other text outside of the links, not counting
            // whitespace), we'll delete it
            if (messageCharacterCount == matchesCharacterCount && guildBotUser.GuildPermissions.ManageMessages)
            {
                await message.DeleteAsync();
            }

            return(OperationResult.FromSuccess());
        }
Example #4
0
        /// <inheritdoc />
        protected override async Task MessageReceived(SocketMessage arg)
        {
            if (!(arg is SocketUserMessage message))
            {
                return;
            }

            if (!(message.Author is SocketGuildUser guildUser))
            {
                return;
            }

            if ((arg.Author.IsBot && !arg.Author.IsMe(this.Client)) || arg.Author.IsWebhook)
            {
                return;
            }

            var discard = 0;

            if (message.HasCharPrefix('!', ref discard))
            {
                return;
            }

            if (message.HasMentionPrefix(this.Client.CurrentUser, ref discard))
            {
                return;
            }

            foreach (Match?match in Pattern.Matches(message.Content))
            {
                if (match is null)
                {
                    continue;
                }

                if (!ulong.TryParse(match.Groups["GuildId"].Value, out _) ||
                    !ulong.TryParse(match.Groups["ChannelId"].Value, out var channelId) ||
                    !ulong.TryParse(match.Groups["MessageId"].Value, out var messageId))
                {
                    continue;
                }

                var quotedChannel = this.Client.GetChannel(channelId);

                if (!(quotedChannel is IGuildChannel) ||
                    !(quotedChannel is ISocketMessageChannel quotedMessageChannel))
                {
                    continue;
                }

                var quotedMessage = await quotedMessageChannel.GetMessageAsync(messageId);

                if (quotedMessage == null || IsQuote(quotedMessage))
                {
                    return;
                }

                if (message.Channel is IGuildChannel messageGuildChannel)
                {
                    var guildBotUser = await messageGuildChannel.Guild.GetUserAsync(this.Client.CurrentUser.Id);

                    // It's just a single quote link, so we'll delete it
                    if (message.Content == match.Value && guildBotUser.GuildPermissions.ManageMessages)
                    {
                        await message.DeleteAsync();
                    }
                }

                var embed = _quotes.CreateMessageQuote(quotedMessage, guildUser);
                embed.WithTimestamp(quotedMessage.Timestamp);

                try
                {
                    await message.Channel.SendMessageAsync(string.Empty, embed : embed.Build());
                }
                catch (HttpException hex)
                {
                    if (!hex.WasCausedByMissingPermission())
                    {
                        throw;
                    }
                }
            }
        }