Пример #1
0
        public async Task CheckMessage(IMessage message, ICommandContext context = null)
        {
            if (message.Author.IsBot || message.Channel is not IGuildChannel chnl || message is not IUserMessage userMessage || string.IsNullOrWhiteSpace(message.Content))
            {
                return; //Makes sure it's not logging a message from a bot and that it's in a discord server
            }
            context ??= new SocketCommandContext((DiscordSocketClient)client, (SocketUserMessage)message);
            var gUser = message.Author as IGuildUser;

            if (gUser?.Guild == null || gUser.HasAdmin())
            {
                return;
            }
            IGuild guild = chnl.Guild;

            try
            {
                var            modSettings    = guild.LoadFromFile <ModerationSettings>();
                var            filterSettings = guild.LoadFromFile <FilterSettings>();
                List <BadWord> badWords       = guild.LoadFromFile <BadWordList>()?.badWords;

                string msgContent = message.Content;
                if (modSettings != null && filterSettings != null)
                {
                    if (filterSettings.channelsWithoutAutoMod != null && filterSettings.channelsWithoutAutoMod.Contains(chnl.Id) || //If channel has filter disabled
                        filterSettings.filterIgnored != null && filterSettings.filterIgnored.Intersect(gUser.RoleIds).Any()) //If user has filter ignored role
                    {
                        return;
                    }

                    //Checks if a message contains too many "newlines"
                    if (filterSettings.maxNewLines != null)
                    {
                        //Gets number of "newlines"
                        int newLines = context.Message.Content.Count(c => c == '\n');
                        if (newLines > filterSettings.maxNewLines.Value)
                        {
                            await context.FilterPunish("too many newlines", modSettings, filterSettings, null, warnSize : (newLines - filterSettings.maxNewLines.Value) * 0.5f);

                            return;
                        }
                    }

                    //Checks if a message contains an invite
                    if (!filterSettings.invitesAllowed)
                    {
                        MatchCollection matches = Regex.Matches(message.Content, inviteRegex, regexOptions);
                        foreach (Match match in matches)
                        {
                            var invite = await client.GetInviteAsync(match.Value);

                            if (invite?.GuildId != null && !filterSettings.whitelistedForInvite.Contains(invite.GuildId.Value))
                            {
                                await context.FilterPunish("Posted Invite", modSettings, filterSettings, match.Value, match.Index);

                                return;
                            }
                        }
                    }

                    //Checks if a message contains ugly, unwanted text t̨̠̱̭͓̠ͪ̈́͌ͪͮ̐͒h̲̱̯̀͂̔̆̌͊ͅà̸̻͌̍̍ͅt͕̖̦͂̎͂̂ͮ͜ ̲͈̥͒ͣ͗̚l̬͚̺͚͎̆͜ͅo͔̯̖͙ͩõ̲̗̎͆͜k̦̭̮̺ͮ͆̀ ͙̍̂͘l̡̮̱̤͍̜̲͙̓̌̐͐͂̓i͙̬ͫ̀̒͑̔͐k̯͇̀ͭe̎͋̓́ ̥͖̼̬ͪ̆ṫ͏͕̳̞̯h̛̼͔ͩ̑̿͑i͍̲̽ͮͪsͦ͋ͦ̌͗ͭ̋
                    //Props to Mathias Bynens for the regex string
                    const string zalgoRegex = @"([\0-\u02FF\u0370-\u1AAF\u1B00-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uE000-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])([\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)";
                    if (filterSettings.zalgoAllowed == false)
                    {
                        MatchCollection matches = Regex.Matches(message.Content, zalgoRegex, regexOptions);
                        if (matches.Any())
                        {
                            await context.FilterPunish("zalgo usage", modSettings, filterSettings, null);

                            return;
                        }
                    }

                    //Check for links if setting enabled and user is not allowed to link
                    if (filterSettings.allowedLinks?.Count is not null and not 0 && (filterSettings.allowedToLink == null || !gUser.RoleIds.Intersect(filterSettings.allowedToLink).Any()))
                    {
                        const string    linkRegex   = @"((?:https?|steam):\/\/[^\s<]+[^<.,:;" + "\"\'\\]\\s])";
                        MatchCollection linkMatches = Regex.Matches(message.Content, linkRegex, regexOptions);
                        //if (matches != null && matches.Count > 0) await new LogMessage(LogSeverity.Info, "Filter", "Link detected").Log();
                        foreach (Match match in linkMatches)
                        {
                            if (msgContent.Equals(match.Value, StringComparison.InvariantCultureIgnoreCase))
                            {
                                return;
                            }
                            msgContent = msgContent.Replace(match.Value, "", StringComparison.InvariantCultureIgnoreCase);
                            //Checks for links

                            if (!filterSettings.allowedLinks.Any(s => match.Value.Contains(s, StringComparison.InvariantCultureIgnoreCase)))
                            {
                                await context.FilterPunish("Using unauthorized links", modSettings, filterSettings, match.Value, match.Index, warnSize : 1);

                                return;
                            }
                        }
                    }

                    //Check for emojis
                    if (filterSettings.badUEmojis?.Count is not null and not 0 && filterSettings.badUEmojis.Any(s => message.Content.Contains(s)))
                    {
                        await context.FilterPunish("Bad emoji used", modSettings, filterSettings, null, warnSize : 0.8f);

                        return;
                    }

                    if (filterSettings.allowedCaps > 0 && message.Content.Length > 5)
                    {
                        uint amountCaps = 0;
                        foreach (char c in message.Content)
                        {
                            if (char.IsUpper(c))
                            {
                                amountCaps++;
                            }
                        }
                        if (((amountCaps / (float)message.Content.Length) * 100) >= filterSettings.allowedCaps)
                        {
                            await context.FilterPunish("Excessive caps", modSettings, filterSettings, null, warnSize : 0.3f);

                            return;
                        }
                    }
                } //End of stuff from mod settings
                var result          = msgContent.CheckForBadWords(badWords?.ToArray());
                var detectedBadWord = result.word;
                if (detectedBadWord != null)
                {
                    if (!string.IsNullOrEmpty(detectedBadWord.Euphemism))
                    {
                        await context.FilterPunish($"Bad word used ({detectedBadWord.Euphemism})", modSettings, filterSettings, detectedBadWord.Word, result.pos, detectedBadWord.Size);

                        return;
                    }
                    else
                    {
                        await context.FilterPunish("Bad word used", modSettings, filterSettings, detectedBadWord.Word, result.pos, detectedBadWord.Size);

                        return;
                    }
                }
            }
            catch (Exception e)
            {
#if DEBUG
                throw;
#else
                await e.LogFilterError("message", guild);
#endif
            }
        }