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); } }
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 static Task OnMessageCreated(MessageCreateEventArgs args) { var message = args.Message; if (message.Author.IsBotSafeCheck()) { return(Task.CompletedTask); } if (!string.IsNullOrEmpty(message.Content) && (message.Content.StartsWith(Config.CommandPrefix) || message.Content.StartsWith(Config.AutoRemoveCommandPrefix))) { return(Task.CompletedTask); } var checkExternalLinks = "help".Equals(args.Channel.Name, StringComparison.InvariantCultureIgnoreCase) || LimitedToSpamChannel.IsSpamChannel(args.Channel); OnNewLog(args.Client, args.Channel, args.Message, checkExternalLinks: checkExternalLinks); return(Task.CompletedTask); }
public static async Task OnMessageCreated(MessageCreateEventArgs args) { if (DefaultHandlerFilter.IsFluff(args.Message)) { return; } if (args.Message.Channel.IsPrivate) { return; } #if DEBUG if (args.Message.Content == "emoji test") { var badEmojis = new List <DiscordEmoji>(SadReactions.Concat(ThankYouReactions)); var posted = 0; var line = 1; var msg = await args.Channel.SendMessageAsync("Line " + line).ConfigureAwait(false); for (var i = 0; i < 5; i++) { var tmp = new List <DiscordEmoji>(); foreach (var emoji in badEmojis) { try { await msg.CreateReactionAsync(emoji).ConfigureAwait(false); if (++posted == 15) { line++; posted = 0; msg = await args.Channel.SendMessageAsync("Line " + line).ConfigureAwait(false); } } catch (Exception e) { Config.Log.Debug(e); tmp.Add(emoji); } } badEmojis = tmp; if (badEmojis.Any()) { await Task.Delay(1000).ConfigureAwait(false); } } if (badEmojis.Any()) { await args.Channel.SendMessageAsync("Bad emojis: " + string.Concat(badEmojis)).ConfigureAwait(false); } else { await args.Channel.SendMessageAsync("Everything looks fine").ConfigureAwait(false); } return; } #endif var(needToSilence, needToThank) = NeedToSilence(args.Message); if (!(needToSilence || needToThank)) { return; } if (needToThank) { DiscordEmoji emoji; string thankYouMessage; lock (theDoor) { emoji = ThankYouReactions[rng.Next(ThankYouReactions.Length)]; thankYouMessage = LimitedToSpamChannel.IsSpamChannel(args.Channel) ? ThankYouMessages[rng.Next(ThankYouMessages.Length)] : null; } await args.Message.ReactWithAsync(emoji, thankYouMessage).ConfigureAwait(false); } if (needToSilence) { DiscordEmoji emoji; string sadMessage; lock (theDoor) { emoji = SadReactions[rng.Next(SadReactions.Length)]; sadMessage = SadMessages[rng.Next(SadMessages.Length)]; } await args.Message.ReactWithAsync(emoji, sadMessage).ConfigureAwait(false); if (args.Author.IsSmartlisted(args.Client, args.Message.Channel.Guild)) { var botMember = args.Guild?.CurrentMember ?? args.Client.GetMember(args.Client.CurrentUser); if (args.Channel.PermissionsFor(botMember).HasPermission(Permissions.ReadMessageHistory)) { var lastBotMessages = await args.Channel.GetMessagesBeforeAsync(args.Message.Id, 20, DateTime.UtcNow.Add(-Config.ShutupTimeLimit)).ConfigureAwait(false); if (lastBotMessages.OrderByDescending(m => m.CreationTimestamp).FirstOrDefault(m => m.Author.IsCurrent) is DiscordMessage msg) { await msg.DeleteAsync("asked to shut up").ConfigureAwait(false); } } else { await args.Message.ReactWithAsync(DiscordEmoji.FromUnicode("🙅"), @"No can do, boss ¯\\_(ツ)\_/¯").ConfigureAwait(false); } } } }
public static async void EnqueueLogProcessing(DiscordClient client, DiscordChannel channel, DiscordMessage message, DiscordMember requester = null, bool checkExternalLinks = false) { try { if (!QueueLimiter.Wait(0)) { await channel.SendMessageAsync("Log processing is rate limited, try again a bit later").ConfigureAwait(false); return; } bool parsedLog = false; var startTime = Stopwatch.StartNew(); DiscordMessage botMsg = null; try { var possibleHandlers = sourceHandlers.Select(h => h.FindHandlerAsync(message, archiveHandlers).ConfigureAwait(false).GetAwaiter().GetResult()).ToList(); var source = possibleHandlers.FirstOrDefault(h => h.source != null).source; var fail = possibleHandlers.FirstOrDefault(h => !string.IsNullOrEmpty(h.failReason)).failReason; if (source != null) { Config.Log.Debug($">>>>>>> {message.Id % 100} Parsing log '{source.FileName}' from {message.Author.Username}#{message.Author.Discriminator} ({message.Author.Id}) using {source.GetType().Name} ({source.SourceFileSize} bytes)..."); var analyzingProgressEmbed = GetAnalyzingMsgEmbed(client); botMsg = await channel.SendMessageAsync(embed : analyzingProgressEmbed.AddAuthor(client, message, source)).ConfigureAwait(false); parsedLog = true; LogParseState result = null; using (var timeout = new CancellationTokenSource(Config.LogParsingTimeout)) { using var combinedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, Config.Cts.Token); var tries = 0; do { result = await ParseLogAsync( source, async() => botMsg = await botMsg.UpdateOrCreateMessageAsync(channel, embed : analyzingProgressEmbed.AddAuthor(client, message, source)).ConfigureAwait(false), combinedTokenSource.Token ).ConfigureAwait(false); tries++; } while (result == null && !combinedTokenSource.IsCancellationRequested && tries < 3); } if (result == null) { botMsg = await botMsg.UpdateOrCreateMessageAsync(channel, embed : new DiscordEmbedBuilder { Description = "Log analysis failed, most likely cause is a truncated/invalid log.\n" + "Please run the game again and re-upload a new copy.", Color = Config.Colors.LogResultFailed, } .AddAuthor(client, message, source) .Build() ).ConfigureAwait(false); } else { result.ParsingTime = startTime.Elapsed; try { if (result.Error == LogParseState.ErrorCode.PiracyDetected) { var yarr = client.GetEmoji(":piratethink:", "☠"); result.ReadBytes = 0; if (message.Author.IsWhitelisted(client, channel.Guild)) { var piracyWarning = await result.AsEmbedAsync(client, message, source).ConfigureAwait(false); piracyWarning = piracyWarning.WithDescription("Please remove the log and issue warning to the original author of the log"); botMsg = await botMsg.UpdateOrCreateMessageAsync(channel, embed : piracyWarning).ConfigureAwait(false); await client.ReportAsync(yarr + " Pirated Release (whitelisted by role)", message, result.SelectedFilter?.String, result.SelectedFilterContext, ReportSeverity.Low).ConfigureAwait(false); } else { var severity = ReportSeverity.Low; try { await message.DeleteAsync("Piracy detected in log").ConfigureAwait(false); } catch (Exception e) { severity = ReportSeverity.High; Config.Log.Warn(e, $"Unable to delete message in {channel.Name}"); } try { /* * botMsg = await botMsg.UpdateOrCreateMessageAsync(channel, * $"{message.Author.Mention}, please read carefully:", * embed: await result.AsEmbedAsync(client, message, source).ConfigureAwait(false) * ).ConfigureAwait(false); */ botMsg = await botMsg.UpdateOrCreateMessageAsync(channel, $"{message.Author.Mention}, please read carefully:\n" + "🏴☠️ **Pirated content detected** 🏴☠️\n" + "__You are being denied further support until you legally dump the game__.\n" + "Please note that the RPCS3 community and its developers do not support piracy.\n" + "Most of the issues with pirated dumps occur due to them being modified in some way " + "that prevent them from working on RPCS3.\n" + "If you need help obtaining valid working dump of the game you own, please read the quickstart guide at <https://rpcs3.net/quickstart>" ).ConfigureAwait(false); } catch (Exception e) { Config.Log.Error(e, "Failed to send piracy warning"); } try { await client.ReportAsync(yarr + " Pirated Release", message, result.SelectedFilter?.String, result.SelectedFilterContext, severity).ConfigureAwait(false); } catch (Exception e) { Config.Log.Error(e, "Failed to send piracy report"); } if (!(message.Channel.IsPrivate || (message.Channel.Name?.Contains("spam") ?? true))) { await Warnings.AddAsync(client, message, message.Author.Id, message.Author.Username, client.CurrentUser, "Pirated Release", $"{result.SelectedFilter?.String} - {result.SelectedFilterContext?.Sanitize()}"); } } } else { if (result.SelectedFilter != null) { await ContentFilter.PerformFilterActions(client, message, result.SelectedFilter, FilterAction.IssueWarning | FilterAction.SendMessage, result.SelectedFilterContext).ConfigureAwait(false); } botMsg = await botMsg.UpdateOrCreateMessageAsync(channel, requester == null?null : $"Analyzed log from {client.GetMember(channel.Guild, message.Author)?.GetUsernameWithNickname()} by request from {requester.Mention}:", embed : await result.AsEmbedAsync(client, message, source).ConfigureAwait(false) ).ConfigureAwait(false); } } catch (Exception e) { Config.Log.Error(e, "Sending log results failed"); } } return; } else if (!string.IsNullOrEmpty(fail) && ("help".Equals(channel.Name, StringComparison.InvariantCultureIgnoreCase) || LimitedToSpamChannel.IsSpamChannel(channel))) { await channel.SendMessageAsync($"{message.Author.Mention} {fail}").ConfigureAwait(false); return; } if (!"help".Equals(channel.Name, StringComparison.InvariantCultureIgnoreCase)) { return; } var potentialLogExtension = message.Attachments.Select(a => Path.GetExtension(a.FileName).ToUpperInvariant().TrimStart('.')).FirstOrDefault(); switch (potentialLogExtension) { case "TXT": { await channel.SendMessageAsync($"{message.Author.Mention} Please upload the full RPCS3.log.gz (or RPCS3.log with a zip/rar icon) file after closing the emulator instead of copying the logs from RPCS3's interface, as it doesn't contain all the required information.").ConfigureAwait(false); return; } } if (string.IsNullOrEmpty(message.Content)) { return; } var linkStart = message.Content.IndexOf("http"); if (linkStart > -1) { var link = message.Content[linkStart..].Split(linkSeparator, 2)[0]; if (link.Contains(".log", StringComparison.InvariantCultureIgnoreCase) || link.Contains("rpcs3.zip", StringComparison.CurrentCultureIgnoreCase)) { await channel.SendMessageAsync("If you intended to upload a log file please re-upload it directly to discord").ConfigureAwait(false); } }
public static Task <DiscordChannel> GetChannelForSpamAsync(this CommandContext ctx) { return(LimitedToSpamChannel.IsSpamChannel(ctx.Channel) ? Task.FromResult(ctx.Channel) : ctx.CreateDmAsync()); }
public static async Task OnMessageCreated(DiscordClient c, MessageCreateEventArgs args) { if (DefaultHandlerFilter.IsFluff(args.Message)) { return; } if (args.Message.Channel.IsPrivate) { return; } #if DEBUG if (args.Message.Content == "emoji test") { var badEmojis = new List <DiscordEmoji>(SadReactions.Concat(ThankYouReactions)); var posted = 0; var line = 1; var msg = await args.Channel.SendMessageAsync("Line " + line).ConfigureAwait(false); for (var i = 0; i < 5; i++) { var tmp = new List <DiscordEmoji>(); foreach (var emoji in badEmojis) { try { await msg.CreateReactionAsync(emoji).ConfigureAwait(false); if (++posted == 15) { line++; posted = 0; msg = await args.Channel.SendMessageAsync("Line " + line).ConfigureAwait(false); } } catch (Exception e) { Config.Log.Debug(e); tmp.Add(emoji); } } badEmojis = tmp; if (badEmojis.Any()) { await Task.Delay(1000).ConfigureAwait(false); } } if (badEmojis.Any()) { await args.Channel.SendMessageAsync("Bad emojis: " + string.Concat(badEmojis)).ConfigureAwait(false); } else { await args.Channel.SendMessageAsync("Everything looks fine").ConfigureAwait(false); } return; } #endif if (!string.IsNullOrEmpty(args.Message.Content) && Paws.Matches(args.Message.Content) is MatchCollection mc) { using var db = new BotDb(); var matchedGroups = (from m in mc from Group g in m.Groups where g.Success && !string.IsNullOrEmpty(g.Value) select g.Name ).Distinct() .ToArray(); if (matchedGroups.Contains("kot")) { if (!db.Kot.Any(k => k.UserId == args.Author.Id)) { db.Kot.Add(new Kot { UserId = args.Author.Id }); await db.SaveChangesAsync().ConfigureAwait(false); } } if (matchedGroups.Contains("doggo")) { if (!db.Doggo.Any(d => d.UserId == args.Author.Id)) { db.Doggo.Add(new Doggo { UserId = args.Author.Id }); await db.SaveChangesAsync().ConfigureAwait(false); } } } var(needToSilence, needToThank) = NeedToSilence(args.Message); if (!(needToSilence || needToThank)) { return; } if (needToThank) { DiscordEmoji emoji; string thankYouMessage; lock (theDoor) { emoji = ThankYouReactions[rng.Next(ThankYouReactions.Length)]; thankYouMessage = LimitedToSpamChannel.IsSpamChannel(args.Channel) || LimitedToOfftopicChannel.IsOfftopicChannel(args.Channel) ? ThankYouMessages[rng.Next(ThankYouMessages.Length)] : null; } await args.Message.ReactWithAsync(emoji, thankYouMessage).ConfigureAwait(false); } if (needToSilence) { DiscordEmoji emoji; string sadMessage; lock (theDoor) { emoji = SadReactions[rng.Next(SadReactions.Length)]; sadMessage = SadMessages[rng.Next(SadMessages.Length)]; } await args.Message.ReactWithAsync(emoji, sadMessage).ConfigureAwait(false); if (args.Author.IsSmartlisted(c, args.Message.Channel.Guild)) { var botMember = args.Guild?.CurrentMember ?? c.GetMember(c.CurrentUser); if (args.Channel.PermissionsFor(botMember).HasPermission(Permissions.ReadMessageHistory)) { var lastBotMessages = await args.Channel.GetMessagesBeforeAsync(args.Message.Id, 20, DateTime.UtcNow.Add(-Config.ShutupTimeLimitInMin)).ConfigureAwait(false); if (lastBotMessages.OrderByDescending(m => m.CreationTimestamp).FirstOrDefault(m => m.Author.IsCurrent) is DiscordMessage msg) { await msg.DeleteAsync("asked to shut up").ConfigureAwait(false); } } else { await args.Message.ReactWithAsync(DiscordEmoji.FromUnicode("🙅"), @"No can do, boss ¯\\_(ツ)\_/¯").ConfigureAwait(false); } } } }
public async Task ShowExplanation(CommandContext ctx, [RemainingText, Description("Term to explain")] string term) { await ctx.TriggerTypingAsync().ConfigureAwait(false); string inSpecificLocation = null; if (!LimitedToSpamChannel.IsSpamChannel(ctx.Channel)) { var spamChannel = await ctx.Client.GetChannelAsync(Config.BotSpamId).ConfigureAwait(false); inSpecificLocation = $" in {spamChannel.Mention} or bot DMs"; } if (string.IsNullOrEmpty(term)) { await ctx.RespondAsync($"You may want to look at available terms by using `{Config.CommandPrefix}explain list`{inSpecificLocation}").ConfigureAwait(false); return; } term = term.ToLowerInvariant(); using (var db = new BotDb()) { var explanation = await db.Explanation.FirstOrDefaultAsync(e => e.Keyword == term).ConfigureAwait(false); if (explanation != null) { await ctx.RespondAsync(explanation.Text).ConfigureAwait(false); return; } } term = term.StripQuotes(); var idx = term.LastIndexOf(" to "); if (idx > 0) { var potentialUserId = term.Substring(idx + 4).Trim(); bool hasMention = false; try { var lookup = await new DiscordUserConverter().ConvertAsync(potentialUserId, ctx).ConfigureAwait(false); hasMention = lookup.HasValue; } catch { } if (hasMention) { term = term.Substring(0, idx).TrimEnd(); using (var db = new BotDb()) { var explanation = await db.Explanation.FirstOrDefaultAsync(e => e.Keyword == term).ConfigureAwait(false); if (explanation != null) { await ctx.RespondAsync(explanation.Text).ConfigureAwait(false); return; } } } } var msg = $"Unknown term `{term.Sanitize()}`. Use `{Config.CommandPrefix}explain list` to look at defined terms{inSpecificLocation}"; await ctx.RespondAsync(msg).ConfigureAwait(false); }
public async Task ShowExplanation(CommandContext ctx, [RemainingText, Description("Term to explain")] string term) { var sourceTerm = term; if (string.IsNullOrEmpty(term)) { var lastBotMessages = await ctx.Channel.GetMessagesBeforeAsync(ctx.Message.Id, 10).ConfigureAwait(false); var showList = true; foreach (var pastMsg in lastBotMessages) { if (pastMsg.Embeds.FirstOrDefault() is DiscordEmbed pastEmbed && pastEmbed.Title == TermListTitle || BotReactionsHandler.NeedToSilence(pastMsg).needToChill) { showList = false; break; } } if (showList) { await List(ctx).ConfigureAwait(false); } var botMsg = await ctx.RespondAsync("Please tell what term to explain:").ConfigureAwait(false); var interact = ctx.Client.GetInteractivity(); var newMessage = await interact.WaitForMessageAsync(m => m.Author == ctx.User && m.Channel == ctx.Channel && !string.IsNullOrEmpty(m.Content)).ConfigureAwait(false); await botMsg.DeleteAsync().ConfigureAwait(false); if (string.IsNullOrEmpty(newMessage.Result?.Content) || newMessage.Result.Content.StartsWith(Config.CommandPrefix)) { await ctx.ReactWithAsync(Config.Reactions.Failure).ConfigureAwait(false); return; } sourceTerm = term = newMessage.Result.Content; } if (!await DiscordInviteFilter.CheckMessageForInvitesAsync(ctx.Client, ctx.Message).ConfigureAwait(false)) { return; } if (!await ContentFilter.IsClean(ctx.Client, ctx.Message).ConfigureAwait(false)) { return; } term = term.ToLowerInvariant(); var result = await LookupTerm(term).ConfigureAwait(false); if (result.explanation == null || !string.IsNullOrEmpty(result.fuzzyMatch)) { term = term.StripQuotes(); var idx = term.LastIndexOf(" to "); if (idx > 0) { var potentialUserId = term.Substring(idx + 4).Trim(); bool hasMention = false; try { var lookup = await((IArgumentConverter <DiscordUser>) new DiscordUserConverter()).ConvertAsync(potentialUserId, ctx).ConfigureAwait(false); hasMention = lookup.HasValue; } catch {} if (hasMention) { term = term.Substring(0, idx).TrimEnd(); var mentionResult = await LookupTerm(term).ConfigureAwait(false); if (mentionResult.score > result.score) { result = mentionResult; } } } } try { if (result.explanation != null && result.score > 0.5) { if (!string.IsNullOrEmpty(result.fuzzyMatch)) { var fuzzyNotice = $"Showing explanation for `{result.fuzzyMatch}`:"; #if DEBUG fuzzyNotice = $"Showing explanation for `{result.fuzzyMatch}` ({result.score:0.######}):"; #endif await ctx.RespondAsync(fuzzyNotice).ConfigureAwait(false); } var explain = result.explanation; StatsStorage.ExplainStatCache.TryGetValue(explain.Keyword, out int stat); StatsStorage.ExplainStatCache.Set(explain.Keyword, ++stat, StatsStorage.CacheTime); await ctx.Channel.SendMessageAsync(explain.Text, explain.Attachment, explain.AttachmentFilename).ConfigureAwait(false); return; } } catch (Exception e) { Config.Log.Error(e, "Failed to explain " + sourceTerm); return; } string inSpecificLocation = null; if (!LimitedToSpamChannel.IsSpamChannel(ctx.Channel)) { var spamChannel = await ctx.Client.GetChannelAsync(Config.BotSpamId).ConfigureAwait(false); inSpecificLocation = $" in {spamChannel.Mention} or bot DMs"; } var msg = $"Unknown term `{term.Sanitize(replaceBackTicks: true)}`. Use `{ctx.Prefix}explain list` to look at defined terms{inSpecificLocation}"; await ctx.RespondAsync(msg).ConfigureAwait(false); }