public static async Task MessageCreateEventHandlerAsync(KioskAppShard shard, MessageCreateEventArgs e)
        {
            if (e.Author.IsBot || e.Channel.IsPrivate)
            {
                return;
            }

            if (shard.SharedData.BlockedChannels.Contains(e.Channel.Id) || shard.SharedData.BlockedUsers.Contains(e.Author.Id))
            {
                return;
            }

            if (!e.Channel.PermissionsFor(e.Guild.CurrentMember).HasFlag(Permissions.SendMessages))
            {
                return;
            }

            if (!string.IsNullOrWhiteSpace(e.Message?.Content) && !e.Message.Content.StartsWith(shard.SharedData.GetGuildPrefix(e.Guild.Id)))
            {
                short rank = shard.SharedData.IncrementMessageCountForUser(e.Author.Id);
                if (rank != 0)
                {
                    DatabaseGuildRank rankInfo;
                    using (DatabaseContext db = shard.Database.CreateContext())
                        rankInfo = db.GuildRanks.SingleOrDefault(r => r.GuildId == e.Guild.Id && r.Rank == rank);
                    await e.Channel.EmbedAsync($"GG {e.Author.Mention}! You have advanced to level {Formatter.Bold(rank.ToString())} {(rankInfo is null ? "" : $": {Formatter.Italic(rankInfo.Name)}")} !", StaticDiscordEmoji.Medal);
                }
            }
        }
        public static async Task MessageTextReactionEventHandlerAsync(KioskAppShard shard, MessageCreateEventArgs e)
        {
            if (e.Author.IsBot || e.Channel.IsPrivate || string.IsNullOrWhiteSpace(e.Message?.Content))
            {
                return;
            }

            if (e.Message.Content.StartsWith(shard.SharedData.GetGuildPrefix(e.Guild.Id)))
            {
                return;
            }

            if (shard.SharedData.BlockedChannels.Contains(e.Channel.Id) || shard.SharedData.BlockedUsers.Contains(e.Author.Id))
            {
                return;
            }

            if (!e.Channel.PermissionsFor(e.Guild.CurrentMember).HasFlag(Permissions.SendMessages))
            {
                return;
            }

            if (!shard.SharedData.TextReactions.TryGetValue(e.Guild.Id, out ConcurrentHashSet <TextReaction> treactions))
            {
                return;
            }

            TextReaction tr = treactions?.FirstOrDefault(r => r.IsMatch(e.Message.Content));

            if (!tr?.IsCooldownActive() ?? false)
            {
                await e.Channel.SendMessageAsync(tr.Response.Replace("%user%", e.Author.Mention));
            }
        }
Exemple #3
0
 public AntispamService(KioskAppShard shard)
     : base(shard)
 {
     this.guildExempts  = new ConcurrentDictionary <ulong, ConcurrentHashSet <ExemptedEntity> >();
     this.guildSpamInfo = new ConcurrentDictionary <ulong, ConcurrentDictionary <ulong, UserSpamInfo> >();
     this.refreshTimer  = new Timer(RefreshCallback, this, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3));
     this.reason        = "_gf: Antispam";
 }
Exemple #4
0
 public RatelimitService(KioskAppShard shard)
     : base(shard)
 {
     this.guildExempts       = new ConcurrentDictionary <ulong, ConcurrentHashSet <ExemptedEntity> >();
     this.guildRatelimitInfo = new ConcurrentDictionary <ulong, ConcurrentDictionary <ulong, UserRatelimitInfo> >();
     this.refreshTimer       = new Timer(RefreshCallback, this, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(20));
     this.reason             = "_gf: Ratelimit hit";
 }
        public static void RegisterEventListeners(DiscordClient client, KioskAppShard shard)
        {
            ListenerMethods =
                from types in Assembly.GetExecutingAssembly().GetTypes()
                from methods in types.GetMethods()
                let attribute = methods.GetCustomAttribute(typeof(AsyncEventListenerAttribute), inherit: true)
                                where !(attribute is null)
                                select new ListenerMethod
            {
                Method    = methods,
                Attribute = attribute as AsyncEventListenerAttribute
            };

            foreach (ListenerMethod lm in ListenerMethods)
            {
                lm.Attribute.Register(shard, client, lm.Method);
            }
        }
        public static async Task MessageEmojiReactionEventHandlerAsync(KioskAppShard shard, MessageCreateEventArgs e)
        {
            if (e.Author.IsBot || e.Channel.IsPrivate || string.IsNullOrWhiteSpace(e.Message?.Content))
            {
                return;
            }

            if (shard.SharedData.BlockedChannels.Contains(e.Channel.Id) || shard.SharedData.BlockedUsers.Contains(e.Author.Id))
            {
                return;
            }

            if (!e.Channel.PermissionsFor(e.Guild.CurrentMember).HasFlag(Permissions.AddReactions))
            {
                return;
            }

            if (!shard.SharedData.EmojiReactions.TryGetValue(e.Guild.Id, out ConcurrentHashSet <EmojiReaction> ereactions))
            {
                return;
            }

            EmojiReaction ereaction = ereactions?
                                      .Where(er => er.IsMatch(e.Message?.Content ?? ""))
                                      .Shuffle()
                                      .FirstOrDefault();

            if (!(ereaction is null))
            {
                try
                {
                    var emoji = DiscordEmoji.FromName(shard.Client, ereaction.Response);
                    await e.Message.CreateReactionAsync(emoji);
                }
                catch (ArgumentException)
                {
                    using (DatabaseContext db = shard.Database.CreateContext())
                    {
                        db.EmojiReactions.RemoveRange(db.EmojiReactions.Where(er => er.GuildId == e.Guild.Id && er.Reaction == ereaction.Response));
                        await db.SaveChangesAsync();
                    }
                }
            }
        }
        public static async Task BulkDeleteEventHandlerAsync(KioskAppShard shard, MessageBulkDeleteEventArgs e)
        {
            if (e.Channel.IsPrivate)
            {
                return;
            }

            DiscordChannel logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Channel.Guild);

            if (logchn is null)
            {
                return;
            }

            using (DatabaseContext db = shard.Database.CreateContext())
                if (db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Channel && ee.Id == e.Channel.Id))
                {
                    return;
                }

            DiscordEmbedBuilder emb = FormEmbedBuilder(EventOrigin.Message, $"Bulk message deletion occured ({e.Messages.Count} total)", $"In channel {e.Channel.Mention}");
            await logchn.SendMessageAsync(embed : emb.Build());
        }
        public static async Task MessageCreateProtectionHandlerAsync(KioskAppShard shard, MessageCreateEventArgs e)
        {
            if (e.Author.IsBot || e.Channel.IsPrivate || string.IsNullOrWhiteSpace(e.Message?.Content))
            {
                return;
            }

            if (shard.SharedData.BlockedChannels.Contains(e.Channel.Id))
            {
                return;
            }

            CachedGuildConfig gcfg = shard.SharedData.GetGuildConfig(e.Guild.Id);

            if (gcfg.RatelimitSettings.Enabled)
            {
                await shard.CNext.Services.GetService <RatelimitService>().HandleNewMessageAsync(e, gcfg.RatelimitSettings);
            }

            if (gcfg.AntispamSettings.Enabled)
            {
                await shard.CNext.Services.GetService <AntispamService>().HandleNewMessageAsync(e, gcfg.AntispamSettings);
            }
        }
        public static async Task MessageFilterEventHandlerAsync(KioskAppShard shard, MessageCreateEventArgs e)
        {
            if (e.Author.IsBot || e.Channel.IsPrivate || string.IsNullOrWhiteSpace(e.Message?.Content))
            {
                return;
            }

            if (shard.SharedData.BlockedChannels.Contains(e.Channel.Id))
            {
                return;
            }

            CachedGuildConfig gcfg = shard.SharedData.GetGuildConfig(e.Guild.Id);

            if (gcfg.LinkfilterSettings.Enabled)
            {
                if (await shard.CNext.Services.GetService <LinkfilterService>().HandleNewMessageAsync(e, gcfg.LinkfilterSettings))
                {
                    return;
                }
            }

            if (!shard.SharedData.MessageContainsFilter(e.Guild.Id, e.Message.Content))
            {
                return;
            }

            if (!e.Channel.PermissionsFor(e.Guild.CurrentMember).HasFlag(Permissions.ManageMessages))
            {
                return;
            }

            await e.Message.DeleteAsync("_gf: Filter hit");

            await e.Channel.SendMessageAsync($"{e.Author.Mention} said: {FormatterExtensions.Spoiler(Formatter.BlockCode(Formatter.Strip(e.Message.Content)))}");
        }
Exemple #10
0
 public AntiInstantLeaveService(KioskAppShard shard)
     : base(shard)
 {
     this.guildNewMembers = new ConcurrentDictionary <ulong, ConcurrentHashSet <DiscordMember> >();
     this.reason          = "_gf: Instant leave";
 }
Exemple #11
0
        public void Register(KioskAppShard shard, DiscordClient client, MethodInfo mi)
        {
            Task OnEventWithArgs(object e)
            {
                if (!shard.IsListening)
                {
                    return(Task.CompletedTask);
                }

                _ = Task.Run(async() =>
                {
                    try
                    {
                        await(Task) mi.Invoke(null, new object[] { shard, e });
                    }
                    catch (Exception ex)
                    {
                        shard.SharedData.LogProvider.Log(LogLevel.Error, ex);
                    }
                });
                return(Task.CompletedTask);
            }

            Task OnEventVoid()
            {
                if (!shard.IsListening)
                {
                    return(Task.CompletedTask);
                }

                _ = Task.Run(async() =>
                {
                    try
                    {
                        await(Task) mi.Invoke(null, new object[] { shard });
                    }
                    catch (Exception ex)
                    {
                        shard.SharedData.LogProvider.Log(LogLevel.Error, ex);
                    }
                });
                return(Task.CompletedTask);
            }

            switch (this.Target)
            {
            case DiscordEventType.ClientErrored:
                client.ClientErrored += OnEventWithArgs;
                break;

            case DiscordEventType.SocketErrored:
                client.SocketErrored += OnEventWithArgs;
                break;

            case DiscordEventType.SocketOpened:
                client.SocketOpened += OnEventVoid;
                break;

            case DiscordEventType.SocketClosed:
                client.SocketClosed += OnEventWithArgs;
                break;

            case DiscordEventType.Ready:
                client.Ready += OnEventWithArgs;
                break;

            case DiscordEventType.Resumed:
                client.Resumed += OnEventWithArgs;
                break;

            case DiscordEventType.ChannelCreated:
                client.ChannelCreated += OnEventWithArgs;
                break;

            case DiscordEventType.DmChannelCreated:
                client.DmChannelCreated += OnEventWithArgs;
                break;

            case DiscordEventType.ChannelUpdated:
                client.ChannelUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.ChannelDeleted:
                client.ChannelDeleted += OnEventWithArgs;
                break;

            case DiscordEventType.DmChannelDeleted:
                client.DmChannelDeleted += OnEventWithArgs;
                break;

            case DiscordEventType.ChannelPinsUpdated:
                client.ChannelPinsUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildCreated:
                client.GuildCreated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildAvailable:
                client.GuildAvailable += OnEventWithArgs;
                break;

            case DiscordEventType.GuildUpdated:
                client.GuildUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildDeleted:
                client.GuildDeleted += OnEventWithArgs;
                break;

            case DiscordEventType.GuildUnavailable:
                client.GuildUnavailable += OnEventWithArgs;
                break;

            case DiscordEventType.MessageCreated:
                client.MessageCreated += OnEventWithArgs;
                break;

            case DiscordEventType.PresenceUpdated:
                client.PresenceUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildBanAdded:
                client.GuildBanAdded += OnEventWithArgs;
                break;

            case DiscordEventType.GuildBanRemoved:
                client.GuildBanRemoved += OnEventWithArgs;
                break;

            case DiscordEventType.GuildEmojisUpdated:
                client.GuildEmojisUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildIntegrationsUpdated:
                client.GuildIntegrationsUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildMemberAdded:
                client.GuildMemberAdded += OnEventWithArgs;
                break;

            case DiscordEventType.GuildMemberRemoved:
                client.GuildMemberRemoved += OnEventWithArgs;
                break;

            case DiscordEventType.GuildMemberUpdated:
                client.GuildMemberUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildRoleCreated:
                client.GuildRoleCreated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildRoleUpdated:
                client.GuildRoleUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildRoleDeleted:
                client.GuildRoleDeleted += OnEventWithArgs;
                break;

            case DiscordEventType.MessageAcknowledged:
                client.MessageAcknowledged += OnEventWithArgs;
                break;

            case DiscordEventType.MessageUpdated:
                client.MessageUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.MessageDeleted:
                client.MessageDeleted += OnEventWithArgs;
                break;

            case DiscordEventType.MessagesBulkDeleted:
                client.MessagesBulkDeleted += OnEventWithArgs;
                break;

            case DiscordEventType.TypingStarted:
                client.TypingStarted += OnEventWithArgs;
                break;

            case DiscordEventType.UserSettingsUpdated:
                client.UserSettingsUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.UserUpdated:
                client.UserUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.VoiceStateUpdated:
                client.VoiceStateUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.VoiceServerUpdated:
                client.VoiceServerUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.GuildMembersChunked:
                client.GuildMembersChunked += OnEventWithArgs;
                break;

            case DiscordEventType.UnknownEvent:
                client.UnknownEvent += OnEventWithArgs;
                break;

            case DiscordEventType.MessageReactionAdded:
                client.MessageReactionAdded += OnEventWithArgs;
                break;

            case DiscordEventType.MessageReactionRemoved:
                client.MessageReactionRemoved += OnEventWithArgs;
                break;

            case DiscordEventType.MessageReactionsCleared:
                client.MessageReactionsCleared += OnEventWithArgs;
                break;

            case DiscordEventType.WebhooksUpdated:
                client.WebhooksUpdated += OnEventWithArgs;
                break;

            case DiscordEventType.Heartbeated:
                client.Heartbeated += OnEventWithArgs;
                break;

            case DiscordEventType.CommandExecuted:
                shard.CNext.CommandExecuted += OnEventWithArgs;
                break;

            case DiscordEventType.CommandErrored:
                shard.CNext.CommandErrored += OnEventWithArgs;
                break;
            }
        }
Exemple #12
0
 public LinkfilterService(KioskAppShard shard)
     : base(shard)
 {
     this.reason = "_gf: Linkfilter";
 }
Exemple #13
0
        public static async Task MessageUpdateEventHandlerAsync(KioskAppShard shard, MessageUpdateEventArgs e)
        {
            if (e.Author is null || e.Author.IsBot || e.Channel is null || e.Channel.IsPrivate || e.Message is null)
            {
                return;
            }

            if (shard.SharedData.BlockedChannels.Contains(e.Channel.Id))
            {
                return;
            }

            if (!(e.Message.Content is null) && shard.SharedData.MessageContainsFilter(e.Guild.Id, e.Message.Content))
            {
                try
                {
                    await e.Message.DeleteAsync("_gf: Filter hit after update");

                    await e.Channel.SendMessageAsync($"{e.Author.Mention} said: {FormatterExtensions.Spoiler(Formatter.BlockCode(Formatter.Strip(e.Message.Content)))}");
                }
                catch
                {
                }
            }

            DiscordChannel logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Guild);

            if (logchn is null || !e.Message.IsEdited)
            {
                return;
            }

            DiscordMember member = await e.Guild.GetMemberAsync(e.Author.Id);

            using (DatabaseContext db = shard.Database.CreateContext())
            {
                if (db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Channel && ee.Id == e.Channel.Id))
                {
                    return;
                }
                if (db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Member && ee.Id == e.Author.Id))
                {
                    return;
                }
                if (member?.Roles.Any(r => db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Role && ee.Id == r.Id)) ?? false)
                {
                    return;
                }
            }

            string pcontent = string.IsNullOrWhiteSpace(e.MessageBefore?.Content) ? "" : e.MessageBefore.Content.Truncate(700);
            string acontent = string.IsNullOrWhiteSpace(e.Message?.Content) ? "" : e.Message.Content.Truncate(700);
            string ctime    = e.Message.CreationTimestamp == null ? _unknown : e.Message.CreationTimestamp.ToUtcTimestamp();
            string etime    = e.Message.EditedTimestamp is null ? _unknown : e.Message.EditedTimestamp.Value.ToUtcTimestamp();
            string bextra   = $"Embeds: {e.MessageBefore?.Embeds?.Count ?? 0}, Reactions: {e.MessageBefore?.Reactions?.Count ?? 0}, Attachments: {e.MessageBefore?.Attachments?.Count ?? 0}";
            string aextra   = $"Embeds: {e.Message.Embeds.Count}, Reactions: {e.Message.Reactions.Count}, Attachments: {e.Message.Attachments.Count}";

            DiscordEmbedBuilder emb = FormEmbedBuilder(EventOrigin.Message, "Message updated");

            emb.WithDescription(Formatter.MaskedUrl("Jump to message", e.Message.JumpLink));
            emb.AddField("Location", e.Channel.Mention, inline: true);
            emb.AddField("Author", e.Message.Author?.Mention ?? _unknown, inline: true);
            emb.AddField("Before update", $"Created {ctime}\n{bextra}\nContent:{Formatter.BlockCode(Formatter.Strip(pcontent))}");
            emb.AddField("After update", $"Edited {etime}\n{aextra}\nContent:{Formatter.BlockCode(Formatter.Strip(acontent))}");

            await logchn.SendMessageAsync(embed : emb.Build());
        }
Exemple #14
0
        public static async Task MessageDeleteEventHandlerAsync(KioskAppShard shard, MessageDeleteEventArgs e)
        {
            if (e.Channel.IsPrivate || e.Message is null)
            {
                return;
            }

            DiscordChannel logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Guild);

            if (logchn is null)
            {
                return;
            }

            using (DatabaseContext db = shard.Database.CreateContext())
                if (db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Channel && ee.Id == e.Channel.Id))
                {
                    return;
                }

            DiscordEmbedBuilder emb = FormEmbedBuilder(EventOrigin.Message, "Message deleted");

            emb.AddField("Location", e.Channel.Mention, inline: true);
            emb.AddField("Author", e.Message.Author?.Mention ?? _unknown, inline: true);

            DiscordAuditLogEntry entry = await e.Guild.GetLatestAuditLogEntryAsync(AuditLogActionType.MessageDelete);

            if (!(entry is null) && entry is DiscordAuditLogMessageEntry mentry)
            {
                DiscordMember member = await e.Guild.GetMemberAsync(mentry.UserResponsible.Id);

                using (DatabaseContext db = shard.Database.CreateContext())
                {
                    if (db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Member && ee.Id == mentry.UserResponsible.Id))
                    {
                        return;
                    }
                    if (member?.Roles.Any(r => db.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Role && ee.Id == r.Id)) ?? false)
                    {
                        return;
                    }
                }

                emb.AddField("User responsible", mentry.UserResponsible.Mention, inline: true);
                if (!string.IsNullOrWhiteSpace(mentry.Reason))
                {
                    emb.AddField("Reason", mentry.Reason);
                }
                emb.WithFooter(mentry.CreationTimestamp.ToUtcTimestamp(), mentry.UserResponsible.AvatarUrl);
            }

            if (!string.IsNullOrWhiteSpace(e.Message.Content))
            {
                emb.AddField("Content", $"{Formatter.BlockCode(string.IsNullOrWhiteSpace(e.Message.Content) ? "<empty content>" : Formatter.Strip(e.Message.Content.Truncate(1000)))}");
                if (shard.SharedData.MessageContainsFilter(e.Guild.Id, e.Message.Content))
                {
                    emb.WithDescription(Formatter.Italic("Message contained a filter."));
                }
            }
            if (e.Message.Embeds.Any())
            {
                emb.AddField("Embeds", e.Message.Embeds.Count.ToString(), inline: true);
            }
            if (e.Message.Reactions.Any())
            {
                emb.AddField("Reactions", string.Join(" ", e.Message.Reactions.Select(r => r.Emoji.GetDiscordName())), inline: true);
            }
            if (e.Message.Attachments.Any())
            {
                emb.AddField("Attachments", string.Join("\n", e.Message.Attachments.Select(a => a.FileName)), inline: true);
            }
            if (e.Message.CreationTimestamp != null)
            {
                emb.AddField("Message creation time", e.Message.CreationTimestamp.ToUtcTimestamp(), inline: true);
            }

            await logchn.SendMessageAsync(embed : emb.Build());
        }
Exemple #15
0
 public AntifloodService(KioskAppShard shard)
     : base(shard)
 {
     this.guildFloodUsers = new ConcurrentDictionary <ulong, ConcurrentHashSet <DiscordMember> >();
     this.reason          = "_gf: Flooding";
 }
Exemple #16
0
 protected ProtectionService(KioskAppShard shard)
 {
     this.shard = shard;
 }