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)); } }
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"; }
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)))}"); }
public AntiInstantLeaveService(KioskAppShard shard) : base(shard) { this.guildNewMembers = new ConcurrentDictionary <ulong, ConcurrentHashSet <DiscordMember> >(); this.reason = "_gf: Instant leave"; }
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; } }
public LinkfilterService(KioskAppShard shard) : base(shard) { this.reason = "_gf: Linkfilter"; }
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()); }
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()); }
public AntifloodService(KioskAppShard shard) : base(shard) { this.guildFloodUsers = new ConcurrentDictionary <ulong, ConcurrentHashSet <DiscordMember> >(); this.reason = "_gf: Flooding"; }
protected ProtectionService(KioskAppShard shard) { this.shard = shard; }