private async Task EditFilterCmd(CommandContext ctx, BotDb db, Piracystring filter) { var(success, msg) = await EditFilterPropertiesAsync(ctx, db, filter).ConfigureAwait(false); if (success) { await db.SaveChangesAsync().ConfigureAwait(false); await msg.UpdateOrCreateMessageAsync(ctx.Channel, embed : FormatFilter(filter).WithTitle("Updated content filter")).ConfigureAwait(false); var member = ctx.Member ?? ctx.Client.GetMember(ctx.User); var reportMsg = $"{member.GetMentionWithNickname()} changed content filter: `{filter.String.Sanitize()}`"; if (!string.IsNullOrEmpty(filter.ValidatingRegex)) { reportMsg += $"\nValidation: `{filter.ValidatingRegex}`"; } await ctx.Client.ReportAsync("🆙 Content filter updated", reportMsg, null, ReportSeverity.Low).ConfigureAwait(false); ContentFilter.RebuildMatcher(); } else { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Content filter update aborted").ConfigureAwait(false); } }
public static async Task CleanupAsync(DiscordClient client) { while (!Config.Cts.IsCancellationRequested) { await using var db = new BotDb(); foreach (var invite in db.WhitelistedInvites.Where(i => i.InviteCode != null)) { try { var result = await client.GetInviteByCodeAsync(invite.InviteCode).ConfigureAwait(false); if (result?.IsRevoked == true) { invite.InviteCode = null; } } catch (NotFoundException) { invite.InviteCode = null; Config.Log.Info($"Removed invite code {invite.InviteCode} for server {invite.Name}"); } catch (Exception e) { Config.Log.Debug(e); } } await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false); await Task.Delay(TimeSpan.FromHours(1), Config.Cts.Token).ConfigureAwait(false); } }
public static async Task <bool> IsWhitelistedAsync(DiscordInvite invite) { var code = string.IsNullOrWhiteSpace(invite.Code) ? null : invite.Code; var name = string.IsNullOrWhiteSpace(invite.Guild.Name) ? null : invite.Guild.Name; await using var db = new BotDb(); var whitelistedInvite = await db.WhitelistedInvites.FirstOrDefaultAsync(i => i.GuildId == invite.Guild.Id); if (whitelistedInvite == null) { return(false); } if (name != null && name != whitelistedInvite.Name) { whitelistedInvite.Name = invite.Guild.Name; } if (string.IsNullOrEmpty(whitelistedInvite.InviteCode) && code != null) { whitelistedInvite.InviteCode = code; } await db.SaveChangesAsync().ConfigureAwait(false); return(true); }
public async Task Remove(CommandContext ctx, [Description("Filter IDs to remove, separated with spaces")] params int[] ids) { int removedFilters; var removedTriggers = new StringBuilder(); using (var db = new BotDb()) { foreach (var f in db.Piracystring.Where(ps => ids.Contains(ps.Id) && !ps.Disabled)) { f.Disabled = true; removedTriggers.Append($"\n`{f.String.Sanitize()}`"); } removedFilters = await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false); } if (removedFilters < ids.Length) { await ctx.RespondAsync("Some ids couldn't be removed.").ConfigureAwait(false); } else { await ctx.ReactWithAsync(Config.Reactions.Success, $"Trigger{StringUtils.GetSuffix(ids.Length)} successfully removed!").ConfigureAwait(false); var member = ctx.Member ?? ctx.Client.GetMember(ctx.User); var s = removedFilters == 1 ? "" : "s"; var filterList = removedTriggers.ToString(); if (removedFilters == 1) { filterList = filterList.TrimStart(); } await ctx.Client.ReportAsync($"📴 Piracy filter{s} removed", $"{member.GetMentionWithNickname()} removed {removedFilters} piracy filter{s}: {filterList}".Trim(EmbedPager.MaxDescriptionLength), null, ReportSeverity.Medium).ConfigureAwait(false); } ContentFilter.RebuildMatcher(); }
public async Task Timestamps(CommandContext ctx) { try { var @fixed = 0; using (var db = new BotDb()) { foreach (var warning in db.Warning) { if (!string.IsNullOrEmpty(warning.FullReason)) { var match = Timestamp.Match(warning.FullReason); if (match.Success && DateTime.TryParse(match.Groups["date"].Value, out var timestamp)) { warning.Timestamp = timestamp.Ticks; warning.FullReason = warning.FullReason.Substring(match.Groups["cutout"].Value.Length); @fixed++; } } } await db.SaveChangesAsync().ConfigureAwait(false); } await ctx.RespondAsync($"Fixed {@fixed} records").ConfigureAwait(false); } catch (Exception e) { Config.Log.Warn(e, "Couldn't fix warning timestamps"); await ctx.RespondAsync("Failed to fix warning timestamps").ConfigureAwait(false); } }
public async Task Channels(CommandContext ctx) { try { var @fixed = 0; using (var db = new BotDb()) { foreach (var warning in db.Warning) { var newReason = await FixChannelMentionAsync(ctx, warning.Reason).ConfigureAwait(false); if (newReason != warning.Reason) { warning.Reason = newReason; @fixed++; } } await db.SaveChangesAsync().ConfigureAwait(false); } await ctx.RespondAsync($"Fixed {@fixed} records").ConfigureAwait(false); } catch (Exception e) { Config.Log.Warn(e, "Couldn't fix channel mentions"); await ctx.RespondAsync("Failed to fix warning timestamps").ConfigureAwait(false); } }
protected async Task Update(CommandContext ctx, int id, string eventName = null) { using var db = new BotDb(); var evt = eventName == null ? db.EventSchedule.FirstOrDefault(e => e.Id == id) : db.EventSchedule.FirstOrDefault(e => e.Id == id && e.EventName == eventName); if (evt == null) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"No event with id {id}").ConfigureAwait(false); return; } var(success, msg) = await EditEventPropertiesAsync(ctx, evt, eventName).ConfigureAwait(false); if (success) { await db.SaveChangesAsync().ConfigureAwait(false); if (LimitedToSpamChannel.IsSpamChannel(ctx.Channel)) { await msg.UpdateOrCreateMessageAsync(ctx.Channel, embed : FormatEvent(evt).WithTitle("Updated event schedule entry #" + evt.Id)).ConfigureAwait(false); } else { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Updated the schedule entry").ConfigureAwait(false); } } else { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Event update aborted, changes weren't saved").ConfigureAwait(false); } }
public async Task Add(CommandContext ctx, [Description("A term to explain. Quote it if it contains spaces")] string term, [RemainingText, Description("Explanation text")] string explanation) { term = term.ToLowerInvariant().StripQuotes(); if (string.IsNullOrEmpty(explanation)) { await ctx.ReactWithAsync(Config.Reactions.Failure, "An explanation for the term must be provided").ConfigureAwait(false); } else { using (var db = new BotDb()) { if (await db.Explanation.AnyAsync(e => e.Keyword == term).ConfigureAwait(false)) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"`{term}` is already defined. Use `update` to update an existing term.").ConfigureAwait(false); } else { await db.Explanation.AddAsync(new Explanation { Keyword = term, Text = explanation }).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success, $"`{term}` was successfully added").ConfigureAwait(false); } } } }
protected async Task Add(CommandContext ctx, string eventName = null) { var evt = new EventSchedule(); var(success, msg) = await EditEventPropertiesAsync(ctx, evt, eventName).ConfigureAwait(false); if (success) { using (var db = new BotDb()) { await db.EventSchedule.AddAsync(evt).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); } await ctx.ReactWithAsync(Config.Reactions.Success).ConfigureAwait(false); if (LimitedToSpamChannel.IsSpamChannel(ctx.Channel)) { await msg.UpdateOrCreateMessageAsync(ctx.Channel, embed : FormatEvent(evt).WithTitle("Created new event schedule entry #" + evt.Id)).ConfigureAwait(false); } else { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Added a new schedule entry").ConfigureAwait(false); } } else { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Event creation aborted").ConfigureAwait(false); } }
public async Task Rename(CommandContext ctx, [Description("Filter ID to rename")] int id, [RemainingText, Description("Custom server name")] string name) { if (string.IsNullOrEmpty(name)) { await ctx.ReactWithAsync(Config.Reactions.Failure, "A name must be provided").ConfigureAwait(false); return; } await using var db = new BotDb(); var invite = await db.WhitelistedInvites.FirstOrDefaultAsync(i => i.Id == id).ConfigureAwait(false); if (invite == null) { await ctx.ReactWithAsync(Config.Reactions.Failure, "Invalid filter ID").ConfigureAwait(false); return; } invite.Name = name; await db.SaveChangesAsync().ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success).ConfigureAwait(false); await List(ctx).ConfigureAwait(false); }
public async Task Text(CommandContext ctx, [RemainingText, Description("Term to remove")] string term) { term = term.ToLowerInvariant().StripQuotes(); using (var db = new BotDb()) { var item = await db.Explanation.FirstOrDefaultAsync(e => e.Keyword == term).ConfigureAwait(false); if (item == null) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"Term `{term}` is not defined").ConfigureAwait(false); } else if (string.IsNullOrEmpty(item.Text)) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"Term `{term}` doesn't have any text").ConfigureAwait(false); } else if (string.IsNullOrEmpty(item.AttachmentFilename)) { await RemoveExplanation(ctx, term).ConfigureAwait(false); } else { item.Text = ""; await db.SaveChangesAsync().ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success, $"Removed explanation text for `{term}`").ConfigureAwait(false); } } }
public async Task Rename(CommandContext ctx, [Description("A term to rename. Remember quotes if it contains spaces")] string oldTerm, [Description("New term. Again, quotes")] string newTerm) { oldTerm = oldTerm.ToLowerInvariant().StripQuotes(); newTerm = newTerm.ToLowerInvariant().StripQuotes(); using (var db = new BotDb()) { var item = await db.Explanation.FirstOrDefaultAsync(e => e.Keyword == oldTerm).ConfigureAwait(false); if (item == null) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"Term `{oldTerm}` is not defined").ConfigureAwait(false); } else if (await db.Explanation.AnyAsync(e => e.Keyword == newTerm).ConfigureAwait(false)) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"Term `{newTerm}` already defined, can't replace it with explanation for `{oldTerm}`").ConfigureAwait(false); } else { item.Keyword = newTerm; await db.SaveChangesAsync().ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success, $"Renamed `{oldTerm}` to `{newTerm}`").ConfigureAwait(false); } } }
public async Task Add(CommandContext ctx, [RemainingText, Description("A plain string to match")] string trigger) { using (var db = new BotDb()) { Piracystring filter; if (string.IsNullOrEmpty(trigger)) { filter = new Piracystring(); } else { filter = await db.Piracystring.FirstOrDefaultAsync(ps => ps.String == trigger && ps.Disabled).ConfigureAwait(false); if (filter == null) { filter = new Piracystring { String = trigger } } ; else { filter.Disabled = false; } } var isNewFilter = filter.Id == default; if (isNewFilter) { filter.Context = FilterContext.Chat | FilterContext.Log; filter.Actions = FilterAction.RemoveContent | FilterAction.IssueWarning | FilterAction.SendMessage; } var(success, msg) = await EditFilterPropertiesAsync(ctx, db, filter).ConfigureAwait(false); if (success) { if (isNewFilter) { await db.Piracystring.AddAsync(filter).ConfigureAwait(false); } await db.SaveChangesAsync().ConfigureAwait(false); await msg.UpdateOrCreateMessageAsync(ctx.Channel, embed : FormatFilter(filter).WithTitle("Created a new content filter")).ConfigureAwait(false); var member = ctx.Member ?? ctx.Client.GetMember(ctx.User); var reportMsg = $"{member.GetMentionWithNickname()} added a new content filter: `{filter.String.Sanitize()}`"; if (!string.IsNullOrEmpty(filter.ValidatingRegex)) { reportMsg += $"\nValidation: `{filter.ValidatingRegex}`"; } await ctx.Client.ReportAsync("🆕 Content filter created", reportMsg, null, ReportSeverity.Low).ConfigureAwait(false); ContentFilter.RebuildMatcher(); } else { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Content filter creation aborted").ConfigureAwait(false); } } }
public async Task Remove(CommandContext ctx, [Description("Trigger to remove"), RemainingText] string trigger) { if (string.IsNullOrWhiteSpace(trigger)) { await ctx.ReactWithAsync(Config.Reactions.Failure, "No trigger was specified").ConfigureAwait(false); return; } using (var db = new BotDb()) { var f = await db.Piracystring.FirstOrDefaultAsync(ps => ps.String.Equals(trigger, StringComparison.InvariantCultureIgnoreCase) && !ps.Disabled).ConfigureAwait(false); if (f == null) { await ctx.ReactWithAsync(Config.Reactions.Failure, "Specified filter does not exist").ConfigureAwait(false); return; } f.Disabled = true; await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false); } await ctx.ReactWithAsync(Config.Reactions.Success, "Trigger was removed").ConfigureAwait(false); var member = ctx.Member ?? ctx.Client.GetMember(ctx.User); await ctx.Client.ReportAsync("📴 Piracy filter removed", $"{member.GetMentionWithNickname()} removed 1 piracy filter: `{trigger.Sanitize()}`", null, ReportSeverity.Medium).ConfigureAwait(false); ContentFilter.RebuildMatcher(); }
public static async Task <bool> CheckForRpcs3Updates(DiscordClient discordClient, DiscordChannel channel, string sinceCommit = null) { var info = await client.GetUpdateAsync(Config.Cts.Token, sinceCommit).ConfigureAwait(false); if (info?.ReturnCode != 1 && sinceCommit != null) { info = await client.GetUpdateAsync(Config.Cts.Token).ConfigureAwait(false); } var embed = await info.AsEmbedAsync().ConfigureAwait(false); if (info == null || embed.Color == Config.Colors.Maintenance) { embed = await CachedUpdateInfo.AsEmbedAsync().ConfigureAwait(false); } else { CachedUpdateInfo = info; } if (channel != null) { await channel.SendMessageAsync(embed : embed.Build()).ConfigureAwait(false); } var updateLinks = info?.LatestBuild?.Pr; if (!string.IsNullOrEmpty(updateLinks) && lastUpdateInfo != updateLinks && updateCheck.Wait(0)) { try { var compatChannel = await discordClient.GetChannelAsync(Config.BotChannelId).ConfigureAwait(false); await compatChannel.SendMessageAsync(embed : embed.Build()).ConfigureAwait(false); lastUpdateInfo = updateLinks; using (var db = new BotDb()) { var currentState = await db.BotState.FirstOrDefaultAsync(k => k.Key == Rpcs3UpdateStateKey).ConfigureAwait(false); if (currentState == null) { db.BotState.Add(new BotState { Key = Rpcs3UpdateStateKey, Value = updateLinks }); } else { currentState.Value = updateLinks; } await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false); return(true); } } catch (Exception e) { Config.Log.Warn(e, "Failed to check for RPCS3 update info"); } }
public async Task Add(CommandContext ctx, [Description("A term to explain. Quote it if it contains spaces")] string term, [RemainingText, Description("Explanation text. Can have attachment")] string explanation) { try { term = term.ToLowerInvariant().StripQuotes(); byte[] attachment = null; string attachmentFilename = null; if (ctx.Message.Attachments.FirstOrDefault() is DiscordAttachment att) { attachmentFilename = att.FileName; try { using (var httpClient = HttpClientFactory.Create(new CompressionMessageHandler())) attachment = await httpClient.GetByteArrayAsync(att.Url).ConfigureAwait(false); } catch (Exception e) { Config.Log.Warn(e, "Failed to download explanation attachment " + ctx); } } if (string.IsNullOrEmpty(explanation) && string.IsNullOrEmpty(attachmentFilename)) { await ctx.ReactWithAsync(Config.Reactions.Failure, "An explanation for the term must be provided").ConfigureAwait(false); } else { using (var db = new BotDb()) { if (await db.Explanation.AnyAsync(e => e.Keyword == term).ConfigureAwait(false)) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"`{term}` is already defined. Use `update` to update an existing term.").ConfigureAwait(false); } else { var entity = new Explanation { Keyword = term, Text = explanation ?? "", Attachment = attachment, AttachmentFilename = attachmentFilename }; await db.Explanation.AddAsync(entity).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success, $"`{term}` was successfully added").ConfigureAwait(false); } } } } catch (Exception e) { Config.Log.Error(e, $"Failed to add explanation for `{term}`"); } }
internal static async Task <bool> AddAsync(DiscordClient client, DiscordMessage message, ulong userId, string userName, DiscordUser issuer, string?reason, string?fullReason = null) { if (string.IsNullOrEmpty(reason)) { var interact = client.GetInteractivity(); var msg = await message.Channel.SendMessageAsync("What is the reason for this warning?").ConfigureAwait(false); var response = await interact.WaitForMessageAsync( m => m.Author == message.Author && m.Channel == message.Channel && !string.IsNullOrEmpty(m.Content) ).ConfigureAwait(false); if (string.IsNullOrEmpty(response.Result.Content)) { await msg.UpdateOrCreateMessageAsync(message.Channel, "A reason needs to be provided").ConfigureAwait(false); return(false); } await msg.DeleteAsync().ConfigureAwait(false); reason = response.Result.Content; } try { await using var db = new BotDb(); await db.Warning.AddAsync(new Warning { DiscordId = userId, IssuerId = issuer.Id, Reason = reason, FullReason = fullReason ?? "", Timestamp = DateTime.UtcNow.Ticks }).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); var threshold = DateTime.UtcNow.AddMinutes(-15).Ticks; var recentCount = db.Warning.Count(w => w.DiscordId == userId && !w.Retracted && w.Timestamp > threshold); if (recentCount > 3) { Config.Log.Debug("Suicide behavior detected, not spamming with warning responses"); return(true); } var totalCount = db.Warning.Count(w => w.DiscordId == userId && !w.Retracted); await message.Channel.SendMessageAsync($"User warning saved! User currently has {totalCount} warning{StringUtils.GetSuffix(totalCount)}!").ConfigureAwait(false); if (totalCount > 1) { await ListUserWarningsAsync(client, message, userId, userName).ConfigureAwait(false); } return(true); } catch (Exception e) { Config.Log.Error(e, "Couldn't save the warning"); return(false); } }
public static async Task <bool> AddAsync(ulong userId) { if (IsMod(userId)) { return(false); } var result = await db.Moderator.AddAsync(new Moderator { DiscordId = userId }).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); lock (mods) { if (IsMod(userId)) { return(false); } mods[userId] = result.Entity; } return(true); }
public async Task Remove(CommandContext ctx, [Description("Discord user to remove from forced nickname list.")] DiscordUser discordUser) { try { if (discordUser.IsBotSafeCheck()) { var mem = ctx.Client.GetMember(ctx.Guild.Id, discordUser); if (mem is not null) { await mem.ModifyAsync(m => m.Nickname = new(discordUser.Username)).ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success).ConfigureAwait(false); } return; } await using var db = new BotDb(); var enforcedRules = ctx.Guild == null ? await db.ForcedNicknames.Where(mem => mem.UserId == discordUser.Id).ToListAsync().ConfigureAwait(false) : await db.ForcedNicknames.Where(mem => mem.UserId == discordUser.Id && mem.GuildId == ctx.Guild.Id).ToListAsync().ConfigureAwait(false); if (enforcedRules.Count == 0) { return; } db.ForcedNicknames.RemoveRange(enforcedRules); await db.SaveChangesAsync().ConfigureAwait(false); foreach (var rule in enforcedRules) { if (ctx.Client.GetMember(rule.GuildId, discordUser) is DiscordMember discordMember) { try { //todo: change to mem.Nickname = default when the library fixes their shit await discordMember.ModifyAsync(mem => mem.Nickname = new(discordMember.Username)).ConfigureAwait(false); } catch (Exception ex) { Config.Log.Debug(ex); } } } await ctx.ReactWithAsync(Config.Reactions.Success).ConfigureAwait(false); } catch (Exception e) { Config.Log.Error(e); await ctx.ReactWithAsync(Config.Reactions.Failure, "Failed to reset user nickname").ConfigureAwait(false); } }
public static async Task <bool> AddAsync(ulong guildId) { if (IsWhitelisted(guildId)) { return(false); } await using var db = new BotDb(); await db.WhitelistedInvites.AddAsync(new WhitelistedInvite { GuildId = guildId }).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); return(true); }
public static async Task <bool> AddAsync(string trigger) { if (PiracyStrings.Contains(trigger, StringComparer.InvariantCultureIgnoreCase)) { return(false); } lock (SyncObj) { if (PiracyStrings.Contains(trigger, StringComparer.InvariantCultureIgnoreCase)) { return(false); } PiracyStrings.Add(trigger); RebuildMatcher(); } await db.Piracystring.AddAsync(new Piracystring { String = trigger }).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); return(true); }
public static async Task <bool> RemoveAsync(int id) { await using var db = new BotDb(); var dbItem = await db.WhitelistedInvites.FirstOrDefaultAsync(i => i.Id == id).ConfigureAwait(false); if (dbItem == null) { return(false); } db.WhitelistedInvites.Remove(dbItem); await db.SaveChangesAsync().ConfigureAwait(false); return(true); }
public async Task Status(CommandContext ctx, [Description("One of: None, Playing, Watching or ListeningTo")] string activity, [RemainingText] string message) { try { using (var db = new BotDb()) { var status = await db.BotState.FirstOrDefaultAsync(s => s.Key == "bot-status-activity").ConfigureAwait(false); var txt = await db.BotState.FirstOrDefaultAsync(s => s.Key == "bot-status-text").ConfigureAwait(false); if (Enum.TryParse(activity, true, out ActivityType activityType) && !string.IsNullOrEmpty(message)) { if (status == null) { await db.BotState.AddAsync(new BotState { Key = "bot-status-activity", Value = activity }).ConfigureAwait(false); } else { status.Value = activity; } if (txt == null) { await db.BotState.AddAsync(new BotState { Key = "bot-status-text", Value = message }).ConfigureAwait(false); } else { txt.Value = message; } await ctx.Client.UpdateStatusAsync(new DiscordActivity(message, activityType), UserStatus.Online).ConfigureAwait(false); } else { if (status != null) { db.BotState.Remove(status); } await ctx.Client.UpdateStatusAsync(new DiscordActivity()).ConfigureAwait(false); } await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false); } } catch (Exception e) { Config.Log.Error(e); } }
public async Task Edit(CommandContext ctx, [Description("Warning ID to edit")] int id) { var interact = ctx.Client.GetInteractivity(); await using var db = new BotDb(); var warnings = await db.Warning.Where(w => id.Equals(w.Id)).ToListAsync().ConfigureAwait(false); if (warnings.Count == 0) { await ctx.ReactWithAsync(Config.Reactions.Denied, $"{ctx.Message.Author.Mention} Warn not found", true); return; } var warningToEdit = warnings.First(); if (warningToEdit.IssuerId != ctx.User.Id) { await ctx.ReactWithAsync(Config.Reactions.Denied, $"{ctx.Message.Author.Mention} This warn wasn't issued by you :(", true); return; } var msg = await ctx.Channel.SendMessageAsync("Updated warn reason?").ConfigureAwait(false); var response = await interact.WaitForMessageAsync( m => m.Author == ctx.User && m.Channel == ctx.Channel && !string.IsNullOrEmpty(m.Content) ).ConfigureAwait(false); await msg.DeleteAsync().ConfigureAwait(false); if (string.IsNullOrEmpty(response.Result?.Content)) { await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Can't edit warning without a new reason").ConfigureAwait(false); return; } warningToEdit.Reason = response.Result.Content; await db.SaveChangesAsync().ConfigureAwait(false); await ctx.Channel.SendMessageAsync($"Warning successfully edited!").ConfigureAwait(false); }
public static async Task <bool> AddAsync(DiscordInvite invite) { if (await IsWhitelistedAsync(invite).ConfigureAwait(false)) { return(false); } var code = invite.IsRevoked || string.IsNullOrWhiteSpace(invite.Code) ? null : invite.Code; var name = string.IsNullOrWhiteSpace(invite.Guild.Name) ? null : invite.Guild.Name; await using var db = new BotDb(); await db.WhitelistedInvites.AddAsync(new WhitelistedInvite { GuildId = invite.Guild.Id, Name = name, InviteCode = code }).ConfigureAwait(false); await db.SaveChangesAsync().ConfigureAwait(false); return(true); }
public async Task Update(CommandContext ctx, [Description("A term to update. Quote it if it contains spaces")] string term, [RemainingText, Description("New explanation text")] string explanation) { term = term.ToLowerInvariant().StripQuotes(); byte[] attachment = null; string attachmentFilename = null; if (ctx.Message.Attachments.FirstOrDefault() is DiscordAttachment att) { attachmentFilename = att.FileName; try { using (var httpClient = HttpClientFactory.Create(new CompressionMessageHandler())) attachment = await httpClient.GetByteArrayAsync(att.Url).ConfigureAwait(false); } catch (Exception e) { Config.Log.Warn(e, "Failed to download explanation attachment " + ctx); } } using (var db = new BotDb()) { var item = await db.Explanation.FirstOrDefaultAsync(e => e.Keyword == term).ConfigureAwait(false); if (item == null) { await ctx.ReactWithAsync(Config.Reactions.Failure, $"Term `{term}` is not defined").ConfigureAwait(false); } else { if (!string.IsNullOrEmpty(explanation)) { item.Text = explanation; } if (attachment?.Length > 0) { item.Attachment = attachment; item.AttachmentFilename = attachmentFilename; } await db.SaveChangesAsync().ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success, "Term was updated").ConfigureAwait(false); } } }
protected async Task Clear(CommandContext ctx, int?year = null) { var currentYear = DateTime.UtcNow.Year; int removedCount; using (var db = new BotDb()) { var itemsToRemove = await db.EventSchedule.Where(e => year.HasValue ?e.Year == year : e.Year < currentYear ).ToListAsync().ConfigureAwait(false); db.EventSchedule.RemoveRange(itemsToRemove); removedCount = await db.SaveChangesAsync().ConfigureAwait(false); } await ctx.RespondAsync($"Removed {removedCount} event{(removedCount == 1 ? "" : "s")}").ConfigureAwait(false); }
public async Task Remove(CommandContext ctx, [Description("Warning IDs to remove separated with space")] params int[] ids) { int removedCount; using (var db = new BotDb()) { var warningsToRemove = await db.Warning.Where(w => ids.Contains(w.Id)).ToListAsync().ConfigureAwait(false); db.Warning.RemoveRange(warningsToRemove); removedCount = await db.SaveChangesAsync().ConfigureAwait(false); } if (removedCount == ids.Length) { await ctx.RespondAsync($"Warning{StringUtils.GetSuffix(ids.Length)} successfully removed!").ConfigureAwait(false); } else { await ctx.RespondAsync($"Removed {removedCount} items, but was asked to remove {ids.Length}").ConfigureAwait(false); } }
public async Task Clear(CommandContext ctx, [Description("User ID to clear warnings for")] ulong userId) { try { //var removed = await BotDb.Instance.Database.ExecuteSqlCommandAsync($"DELETE FROM `warning` WHERE `discord_id`={userId}").ConfigureAwait(false); int removed; using (var db = new BotDb()) { var warningsToRemove = await db.Warning.Where(w => w.DiscordId == userId).ToListAsync().ConfigureAwait(false); db.Warning.RemoveRange(warningsToRemove); removed = await db.SaveChangesAsync().ConfigureAwait(false); } await ctx.RespondAsync($"{removed} warning{StringUtils.GetSuffix(removed)} successfully removed!").ConfigureAwait(false); } catch (Exception e) { Config.Log.Error(e); } }
public async Task Revert(CommandContext ctx, [Description("Warning ID to change")] int id) { await using var db = new BotDb(); var warn = await db.Warning.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false); if (warn.Retracted) { warn.Retracted = false; warn.RetractedBy = null; warn.RetractionReason = null; warn.RetractionTimestamp = null; await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false); await ctx.ReactWithAsync(Config.Reactions.Success, "Reissued the warning", true).ConfigureAwait(false); } else { await Remove(ctx, id).ConfigureAwait(false); } }