public static async Task MessageTextReactionEventHandlerAsync(FreudShard 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 var treactions)) { return; } var 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 static async Task MessageCreateEventHandlerAsync(FreudShard 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 (var dc = shard.Database.CreateContext()) rankInfo = dc.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 MessageFilterEventHandlerAsync(FreudShard 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; } var gcfg = shard.SharedData.GetGuildConfiguration(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("bot: Filter hit"); await e.Channel.SendMessageAsync($"{e.Author.Mention} said: {FormatterExtensions.Spoiler(Formatter.BlockCode(FormatterExtensions.StripMarkdown(e.Message.Content)))}"); }
public AntispamService(FreudShard 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 = "bot: Antispam"; }
public RatelimitService(FreudShard 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 = "bot: Ratelimit hit"; }
public static async Task MessageUpdateEventHandlerAsync(FreudShard 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.Author == e.Client.CurrentUser && shard.SharedData.IsEventRunningInChannel(e.Channel.Id)) { return; } if (!(e.Message.Content is null) && shard.SharedData.MessageContainsFilter(e.Guild.Id, e.Message.Content)) { try { await e.Message.DeleteAsync("bot: Filter hit after update"); await e.Channel.SendMessageAsync($"{e.Author.Mention} said: {FormatterExtensions.Spoiler(Formatter.BlockCode(FormatterExtensions.StripMarkdown(e.Message.Content)))}"); } catch { // swallow } } var logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Guild); if (logchn is null || !e.Message.IsEdited || e.Channel.IsExempted(shard)) { return; } var member = await e.Guild.GetMemberAsync(e.Author.Id); if (member.IsExempted(shard)) { 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}"; var 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(FormatterExtensions.StripMarkdown(pcontent))}"); emb.AddField("After update", $"Edited {etime}\n{aextra}\nContent:{Formatter.BlockCode(FormatterExtensions.StripMarkdown(acontent))}"); await logchn.SendMessageAsync(embed : emb.Build()); }
public static Task CommandExecutionEventHandler(FreudShard shard, CommandExecutionEventArgs e) { shard.LogMany(LogLevel.Info, $"Executed: {e.Command?.QualifiedName ?? "<unknown command>"}", $"{e.Context.User.ToString()}", $"{e.Context.Guild.ToString()}; {e.Context.Channel.ToString()}"); return(Task.CompletedTask); }
public static Task GuildAvailableEventHandlerAsync(FreudShard shard, GuildCreateEventArgs e) { shard.Log(LogLevel.Debug, $"Guild available: {e.Guild.ToString()}"); if (shard.SharedData.GuildConfigurations.ContainsKey(e.Guild.Id)) { return(Task.CompletedTask); } return(RegisterGuildAsync(shard.SharedData, shard.Database, e.Guild.Id)); }
public static bool IsExempted(this DiscordChannel channel, FreudShard shard) { using (var dc = shard.Database.CreateContext()) { if (dc.LoggingExempts.Any(ee => ee.GuildId == channel.GuildId && ee.Type == ExemptedEntityType.Channel && (ee.Id == channel.Id || ee.Id == channel.Parent.Id))) { return(true); } } return(false); }
public Task DeleteAsync(CommandContext ctx, [RemainingText, Description("Command to remove")] string command) { Command cmd = ctx.CommandsNext.FindCommand(command, out _); if (cmd is null) { throw new CommandFailedException("Cannot find that command."); } ctx.CommandsNext.UnregisterCommands(cmd); FreudShard.UpdateCommandList(ctx.CommandsNext); return(this.InformAsync(ctx, $"Removed command {Formatter.Bold(cmd.QualifiedName)}.", important: false)); }
public static async Task MemberJoinEventHandlerAsync(FreudShard shard, GuildMemberAddEventArgs e) { var gcfg = e.Guild.GetGuildSettings(shard.Database); await Task.Delay(TimeSpan.FromSeconds(gcfg.AntiInstantLeaveSettings.Cooldown + 1)); if (e.Member.Guild is null) { return; } var whcn = e.Guild.GetChannel(gcfg.WelcomeChannelId); if (!(whcn is null)) { if (string.IsNullOrWhiteSpace(gcfg.WelcomeMessage)) { await whcn.EmbedAsync($"Welcome to {Formatter.Bold(e.Guild.Name)}, {e.Member.Mention}!", StaticDiscordEmoji.Wave); } else { await whcn.EmbedAsync(gcfg.WelcomeMessage.Replace("%user%", e.Member.Mention), StaticDiscordEmoji.Wave); } } try { using (var dc = shard.Database.CreateContext()) { var rids = dc.AutoAssignableRoles.Where(dbr => dbr.GuildId == e.Guild.Id).Select(dbr => dbr.RoleId); foreach (ulong rid in rids.ToList()) { try { var role = e.Guild.GetRole(rid); if (!(role is null)) { await e.Member.GrantRoleAsync(role); } else { dc.AutoAssignableRoles.Remove(dc.AutoAssignableRoles.Single(r => r.GuildId == e.Guild.Id && r.RoleId == rid)); } } catch (Exception exc) { shard.Log(LogLevel.Debug, $"| Failed to assign an automatic role to a new member!\n" + $"| {e.Guild.ToString()}\n" + $"| Exception: {exc.GetType()}" + $"| Message: {exc.Message}" ); } }
public static async Task ChannelCreateEventHandlerAsync(FreudShard shard, ChannelCreateEventArgs e) { var logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Guild); if (logchn is null) { return; } var emb = FormEmbedBuilder(EventOrigin.Channel, "Channel created", e.Channel.ToString()); var entry = await e.Guild.GetLatestAuditLogEntryAsync(AuditLogActionType.ChannelCreate); if (entry is null || !(entry is DiscordAuditLogChannelEntry centry)) { emb.AddField("Error", "Failed to read audit log information. Please check my permissions"); }
public static async Task BulkDeleteEventHandlerAsync(FreudShard shard, MessageBulkDeleteEventArgs e) { if (e.Channel.IsPrivate) { return; } var logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Channel.Guild); if (logchn is null || e.Channel.IsExempted(shard)) { return; } var emb = FormEmbedBuilder(EventOrigin.Message, $"Bulk message deletiong occured ({e.Messages.Count} total)", $"In channel {e.Channel.Mention}"); await logchn.SendMessageAsync(embed : emb.Build()); }
public static async Task GuildBanEventHandlerAsync(FreudShard shard, GuildBanAddEventArgs e) { var logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Guild); if (logchn is null) { return; } var emb = FormEmbedBuilder(EventOrigin.KickOrBan, "User BANNED"); var entry = await e.Guild.GetLatestAuditLogEntryAsync(AuditLogActionType.Ban); if (entry is null || !(entry is DiscordAuditLogBanEntry bentry)) { emb.WithDescription(e.Member?.ToString() ?? _unknown); emb.AddField("Error", "Failed to read audit log information. Please check my permissions"); }
public static void RegisterEventListeners(DiscordClient client, FreudShard 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 GuildCreatedEventhandlerAsync(FreudShard shard, GuildCreateEventArgs e) { shard.Log(LogLevel.Info, $"Joined guild: {e.Guild.ToString()}"); await RegisterGuildAsync(shard.SharedData, shard.Database, e.Guild.Id); var defChannel = e.Guild.GetDefaultChannel(); if (!defChannel.PermissionsFor(e.Guild.CurrentMember).HasPermission(Permissions.SendMessages)) { return; } await defChannel.EmbedAsync( $"{Formatter.Bold("Thank you for adding me to your discord!")}\n\n" + $"{StaticDiscordEmoji.SmallBlueDiamond} The default prefix for my command is {Formatter.Bold(shard.SharedData.BotConfiguration.DefaultPrefix)}, but it can be changed using {Formatter.Bold("prefix")} command.\n" + $"{StaticDiscordEmoji.SmallBlueDiamond} I advise you to run the configuration wizard for this guild in order to quickly configure functions like logging and notifications. The wizard can be invoked using {Formatter.Bold("guild configuration setup")} command.\n" + $"{StaticDiscordEmoji.SmallBlueDiamond} You can use the {Formatter.Bold("help")} command as a guide, though it is recommended to read the command list provided in the source \n" + $"{StaticDiscordEmoji.SmallBlueDiamond} If you have any questions or issues, use the {Formatter.Bold("report")} command in order to send a message to the bot owner ({e.Client.CurrentApplication.Team}#{e.Client.CurrentApplication.Description})." + StaticDiscordEmoji.Wave ); }
public static bool IsExempted(this DiscordMember member, FreudShard shard) { if (member is null) { return(false); } using (var dc = shard.Database.CreateContext()) { if (dc.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Member && ee.Id == member.Id)) { return(true); } if (member.Roles.Any(r => dc.LoggingExempts.Any(ee => ee.Type == ExemptedEntityType.Role && ee.Id == r.Id))) { return(true); } } return(false); }
public static async Task MessageCreateProtectionHandlerAsync(FreudShard 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; } var gcfg = shard.SharedData.GetGuildConfiguration(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 MessageEmojiReactionEventHandlerAsync(FreudShard 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 var ereactions)) { return; } var 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 { using (var dc = shard.Database.CreateContext()) { dc.EmojiReactions.RemoveRange(dc.EmojiReactions.Where(er => er.GuildId == e.Guild.Id && er.Reaction == ereaction.Response)); await dc.SaveChangesAsync(); } } } }
public static Task ClientErrorEventHandlerAsync(FreudShard shard, ClientErrorEventArgs e) { var ex = e.Exception; while (ex is AggregateException) { ex = ex.InnerException; } if (ex.InnerException is null) { shard.LogMany(LogLevel.Critical, $"Client errored with exception: {ex.GetType()}", $"Message: {ex.Message}"); } else { shard.LogMany(LogLevel.Critical, $"Client errored with exception: {ex.GetType()}", $"Message: {ex.Message}", $"Inner exception: {ex.InnerException.GetType()}", $"Inner exception message: {ex.InnerException.Message}"); }; return(Task.CompletedTask); }
protected ProtectionService(FreudShard shard) { this.shard = shard; }
public static Task GuildDownloadCompletedEventHandlerAsync(FreudShard shard, GuildDownloadCompletedEventArgs e) { shard.Log(LogLevel.Info, $"All guilds are now available."); return(Task.CompletedTask); }
public static async Task CommandErrorEventHandlerAsync(FreudShard shard, CommandErrorEventArgs e) { if (e.Exception is null) { return; } var ex = e.Exception; while (ex is AggregateException) { ex = ex.InnerException; } if (ex is ChecksFailedException chke && chke.FailedChecks.Any(c => c is NotBlockedAttribute)) { await e.Context.Message.CreateReactionAsync(StaticDiscordEmoji.X); return; } shard.LogMany(LogLevel.Info, $"Tried executing: {e.Command?.QualifiedName ?? "<unknown command>"}", $"{e.Context.User.ToString()}", $"{e.Context.Guild.ToString()}; {e.Context.Channel.ToString()}", $"Exception: {ex.GetType()}", $"Message: {ex.Message ?? "<no message provided>"}", ex.InnerException is null ? "" : $"Inner exception: {ex.InnerException.GetType()}", ex.InnerException is null ? "" : $"Inner exception message: {ex.InnerException.Message}"); var emb = new DiscordEmbedBuilder { Color = DiscordColor.Red }; var sb = new StringBuilder(StaticDiscordEmoji.NoEntry).Append(" "); switch (ex) { case CommandNotFoundException cne: if (!shard.SharedData.GetGuildConfiguration(e.Context.Guild.Id).SuggestionsEnabled) { await e.Context.Message.CreateReactionAsync(StaticDiscordEmoji.Question); return; } sb.Clear(); sb.AppendLine(Formatter.Bold($"Command {Formatter.InlineCode(cne.CommandName)} not found. Did you mean...")); var ordered = FreudShard.Commands .OrderBy(tup => cne.CommandName.LevenshteinDistance(tup.Name)).Take(3); foreach ((string alias, var cmd) in ordered) { emb.AddField($"{alias} ({cmd.QualifiedName})", cmd.Description); } break; case InvalidCommandUsageException _: sb.Append("Invalid command usage! "); sb.AppendLine(ex.Message); emb.WithFooter($"Type \"{shard.SharedData.GetGuildPrefix(e.Context.Guild.Id)}help {e.Command.QualifiedName}\" for a command manual."); break; case ArgumentException _: string fcmdStr = $"help {e.Command.QualifiedName}"; var command = shard.CNext.FindCommand(fcmdStr, out string args); var fctx = shard.CNext.CreateFakeContext(e.Context.User, e.Context.Channel, fcmdStr, e.Context.Prefix, command, args); await shard.CNext.ExecuteCommandAsync(fctx); return; case BadRequestException brex: sb.Append($"Bad request! Details: {brex.JsonMessage}"); break; case NotFoundException nfe: sb.Append($"404: Not found! Details: {nfe.JsonMessage}"); break; case CommandFailedException _: sb.Append($"{ex.Message} {ex.InnerException?.Message}"); break; case NpgsqlException dbex: sb.Append($"Database operation failed. Details: {dbex.Message}"); shard.SharedData.LogProvider.Log(LogLevel.Error, ex); break; case ChecksFailedException cfex: switch (cfex.FailedChecks.First()) { case CooldownAttribute _: return; case UsageInteractivityAttribute _: sb.Append($"I am waiting for your answer and you cannot execute commands until you either answer, or the timeout is reached."); break; default: sb.AppendLine($"Command {Formatter.Bold(e.Command.QualifiedName)} cannot be executed because:").AppendLine(); foreach (var attr in cfex.FailedChecks) { switch (attr) { case RequirePermissionsAttribute perms: sb.AppendLine($"- One of us does not have the required permissions ({perms.Permissions.ToPermissionString()})!"); break; case RequireUserPermissionsAttribute uperms: sb.AppendLine($"- You do not have sufficient permissions ({uperms.Permissions.ToPermissionString()})!"); break; case RequireOwnerOrPermissionsAttribute operms: sb.AppendLine($"- You do not have sufficient permissions ({operms.Permissions.ToPermissionString()})!"); break; case RequireBotPermissionsAttribute bperms: sb.AppendLine($"- I do not have sufficient permissions ({bperms.Permissions.ToPermissionString()})!"); break; case RequirePrivilegedUserAttribute _: sb.AppendLine($"- That command is reserved for my owner and privileged users!"); break; case RequireOwnerAttribute _: sb.AppendLine($"- That command is reserved only for my owner!"); break; case RequireNsfwAttribute _: sb.AppendLine($"- That command is allowed only in the NSFW channels!"); break; case RequirePrefixesAttribute pattr: sb.AppendLine($"- That command can only be invoked only with the following prefixes: {string.Join(" ", pattr.Prefixes)}!"); break; default: sb.AppendLine($"{attr} was not met! (this should not happen, please report this)"); break; } } break; } break; case ConcurrentOperationException _: sb.Append($"A concurrency error occured - please report this. Details: {ex.Message}"); shard.SharedData.LogProvider.Log(LogLevel.Error, ex); break; case UnauthorizedException _: sb.Append("I am unauthorized to do that"); break; case DbUpdateException _: sb.Append("A database update error has occured, possibly due to large amount of update request. Please try again later."); shard.SharedData.LogProvider.Log(LogLevel.Error, ex); break; case TargetInvocationException _: sb.Append($"{ex.InnerException?.Message ?? "Target invocation error occured. Please check the arguments provided and try again."}"); break; case TaskCanceledException _: return; default: sb.AppendLine($"Command {Formatter.Bold(e.Command.QualifiedName)} errored!").AppendLine(); sb.AppendLine($"Exception: {Formatter.InlineCode(ex.GetType().ToString())}"); sb.AppendLine($"Details: {Formatter.Italic(ex.Message)}"); if (!(ex.InnerException is null)) { sb.AppendLine($"Inner exception: {Formatter.InlineCode(ex.InnerException.GetType().ToString())}"); sb.AppendLine($"Details: {Formatter.Italic(ex.InnerException.Message ?? "No details provided")}"); } shard.SharedData.LogProvider.Log(LogLevel.Error, ex); break; } emb.Description = sb.ToString(); await e.Context.RespondAsync(embed : emb.Build()); }
public void Register(FreudShard shard, DiscordClient client, MethodInfo info) { Task OnEventWithArgs(object e) { if (!shard.IsListening) { return(Task.CompletedTask); } _ = Task.Run(async() => { try { await(Task) info.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) info.Invoke(null, new object[] { shard }); } catch (Exception ex) { shard.SharedData.LogProvider.Log(LogLevel.Error, ex); } }); return(Task.CompletedTask); } #region START_SWITCH_STATEMENT 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; #endregion START_SWITCH_STATEMENT } }
public Task AddAsync(CommandContext ctx, [RemainingText, Description("Code to evaluate.")] string code) { if (string.IsNullOrWhiteSpace(code)) { throw new InvalidCommandUsageException("Code missing."); } int cs1 = code.IndexOf("```") + 3; int cs2 = code.LastIndexOf("```"); if (cs1 == -1 || cs2 == -1) { throw new InvalidCommandUsageException("You need to wrap the code into a code block."); } code = $@" [ModuleLifespan(ModuleLifespan.Transient)] public sealed class DynamicCommands : FreudModule {{ public Dynamic Commands(SharedData shared, DatabaseContextBuilder dcb) : base(shard, dcb) {{ this.ModuleColor = DiscordColor.NotQuiteBlack; }} {code.Substring(cs1, cs2 - cs1)} }}"; string type = $"DynamicCommands{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; Type moduleType = null; try { var refs = AppDomain.CurrentDomain.GetAssemblies() .Where(xa => !xa.IsDynamic && !string.IsNullOrWhiteSpace(xa.Location)) .Select(x => MetadataReference.CreateFromFile(x.Location)); var ast = SyntaxFactory.ParseSyntaxTree(code, new CSharpParseOptions().WithKind(SourceCodeKind.Script).WithLanguageVersion(LanguageVersion.Latest)); var opts = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, scriptClassName: type, usings: new[] { "System", "System.Collections.Generic", "System.Linq", "System.Text", "System.Threading.Tasks", "DSharpPlus", "DSharpPlus.Entities", "DSharpPlus.CommandsNext", "DSharpPlus.CommandsNext.Attributes", "DSharpPlus.Interactivity" }, optimizationLevel: OptimizationLevel.Release, allowUnsafe: true, platform: Platform.X64); var compilation = CSharpCompilation.CreateScriptCompilation(type, ast, refs, opts, returnType: typeof(object)); Assembly assembly = null; using (var ms = new MemoryStream()) { var result = compilation.Emit(ms); ms.Position = 0; assembly = Assembly.Load(ms.ToArray()); } var outType = assembly.ExportedTypes.FirstOrDefault(x => x.Name == type); moduleType = outType.GetNestedTypes().FirstOrDefault(x => x.BaseType == typeof(BaseCommandModule)); ctx.CommandsNext.RegisterCommands(moduleType); FreudShard.UpdateCommandList(ctx.CommandsNext); return(this.InformAsync(ctx, StaticDiscordEmoji.Information, "Compilation successful! Command(s) successfully added!", important: false)); } catch (Exception ex) { return(this.InformOfFailureAsync(ctx, $"Compilation failed!\n\n{Formatter.Bold(ex.GetType().ToString())}: {ex.Message}")); } }
public LinkfilterService(FreudShard shard) : base(shard) { this.reason = "bot: Linkfilter"; }
public static async Task MessageDeleteEventHandlerAsync(FreudShard shard, MessageDeleteEventArgs e) { if (e.Channel.IsPrivate || e.Message is null) { return; } var logchn = shard.SharedData.GetLogChannelForGuild(shard.Client, e.Guild); if (logchn is null || e.Channel.IsExempted(shard)) { return; } if (e.Message.Author == e.Client.CurrentUser && shard.SharedData.IsEventRunningInChannel(e.Channel.Id)) { return; } var emb = FormEmbedBuilder(EventOrigin.Message, "Message deleted"); emb.AddField("Location", e.Channel.Mention, inline: true); emb.AddField("Author", e.Message.Author?.Mention ?? _unknown, inline: true); var entry = await e.Guild.GetLatestAuditLogEntryAsync(AuditLogActionType.MessageDelete); if (!(entry is null) && entry is DiscordAuditLogMessageEntry mentry) { var member = await e.Guild.GetMemberAsync(mentry.UserResponsible.Id); if (member.IsExempted(shard)) { 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>" : FormatterExtensions.StripMarkdown(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(FreudShard shard) : base(shard) { this.guildFloodUsers = new ConcurrentDictionary <ulong, ConcurrentHashSet <DiscordMember> >(); this.reason = "bot: Flooding"; }
public AntiInstantLeaveService(FreudShard shard) : base(shard) { this.newGuildMembers = new ConcurrentDictionary <ulong, ConcurrentHashSet <DiscordMember> >(); this.reason = "bot: Instant leave"; }