From b21d7bfab79497bdc8d908ed3f0456790a11d201 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 24 Nov 2020 21:23:22 +0100 Subject: [PATCH 001/149] Log to datadog --- src/Core/Core.csproj | 6 +- .../LoggingAdapter/NpgsqlLoggingAdapter.cs | 19 +-- src/Core/Logger/GeekbotLogger.cs | 14 +- src/Core/Logger/IGeekbotLogger.cs | 2 +- src/Core/Logger/LoggerFactory.cs | 128 ++++++++++++------ src/Core/RunParameters.cs | 7 +- src/Web/Logging/AspLogger.cs | 18 +-- 7 files changed, 119 insertions(+), 75 deletions(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 780d0e2..c05d75c 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -23,11 +23,11 @@ - - + + + - diff --git a/src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs b/src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs index 8a46c0d..29acb93 100644 --- a/src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs +++ b/src/Core/Database/LoggingAdapter/NpgsqlLoggingAdapter.cs @@ -1,7 +1,8 @@ using System; using Geekbot.Core.Logger; +using Microsoft.Extensions.Logging; using Npgsql.Logging; -using LogLevel = NLog.LogLevel; +using Serilog.Events; namespace Geekbot.Core.Database.LoggingAdapter { @@ -21,7 +22,7 @@ namespace Geekbot.Core.Database.LoggingAdapter public override bool IsEnabled(NpgsqlLogLevel level) { - return (_runParameters.DbLogging && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(level))); + return (_runParameters.DbLogging && _geekbotLogger.GetLogger().IsEnabled(ToGeekbotLogLevel(level))); } public override void Log(NpgsqlLogLevel level, int connectorId, string msg, Exception exception = null) @@ -51,16 +52,16 @@ namespace Geekbot.Core.Database.LoggingAdapter } } - private static LogLevel ToGeekbotLogLevel(NpgsqlLogLevel level) + private static LogEventLevel ToGeekbotLogLevel(NpgsqlLogLevel level) { return level switch { - NpgsqlLogLevel.Trace => LogLevel.Trace, - NpgsqlLogLevel.Debug => LogLevel.Debug, - NpgsqlLogLevel.Info => LogLevel.Info, - NpgsqlLogLevel.Warn => LogLevel.Warn, - NpgsqlLogLevel.Error => LogLevel.Error, - NpgsqlLogLevel.Fatal => LogLevel.Fatal, + NpgsqlLogLevel.Trace => LogEventLevel.Verbose, + NpgsqlLogLevel.Debug => LogEventLevel.Debug, + NpgsqlLogLevel.Info => LogEventLevel.Information, + NpgsqlLogLevel.Warn => LogEventLevel.Warning, + NpgsqlLogLevel.Error => LogEventLevel.Error, + NpgsqlLogLevel.Fatal => LogEventLevel.Fatal, _ => throw new ArgumentOutOfRangeException(nameof(level)) }; } diff --git a/src/Core/Logger/GeekbotLogger.cs b/src/Core/Logger/GeekbotLogger.cs index 652faef..d9b7752 100644 --- a/src/Core/Logger/GeekbotLogger.cs +++ b/src/Core/Logger/GeekbotLogger.cs @@ -6,13 +6,13 @@ namespace Geekbot.Core.Logger public class GeekbotLogger : IGeekbotLogger { private readonly bool _logAsJson; - private readonly NLog.Logger _logger; + private readonly Serilog.ILogger _logger; private readonly JsonSerializerSettings _serializerSettings; public GeekbotLogger(RunParameters runParameters) { - _logAsJson = !string.IsNullOrEmpty(runParameters.SumologicEndpoint) || runParameters.LogJson; - _logger = LoggerFactory.CreateNLog(runParameters); + _logAsJson = !string.IsNullOrEmpty(runParameters.DatadogApiKey) || runParameters.LogJson; + _logger = LoggerFactory.CreateLogger(runParameters); _serializerSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize, @@ -22,21 +22,21 @@ namespace Geekbot.Core.Logger } public void Trace(LogSource source, string message, object extra = null) - => _logger.Trace(CreateLogString("Trace", source, message, null, extra)); + => _logger.Verbose(CreateLogString("Trace", source, message, null, extra)); public void Debug(LogSource source, string message, object extra = null) => _logger.Debug(CreateLogString("Debug", source, message, null, extra)); public void Information(LogSource source, string message, object extra = null) - => _logger.Info(CreateLogString("Information", source, message, null, extra)); + => _logger.Information(CreateLogString("Information", source, message, null, extra)); public void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null) - => _logger.Warn(CreateLogString("Warning", source, message, stackTrace, extra)); + => _logger.Warning(CreateLogString("Warning", source, message, stackTrace, extra)); public void Error(LogSource source, string message, Exception stackTrace, object extra = null) => _logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra)); - public NLog.Logger GetNLogger() => _logger; + public Serilog.ILogger GetLogger() => _logger; public bool LogAsJson() => _logAsJson; diff --git a/src/Core/Logger/IGeekbotLogger.cs b/src/Core/Logger/IGeekbotLogger.cs index 1363629..3359d10 100644 --- a/src/Core/Logger/IGeekbotLogger.cs +++ b/src/Core/Logger/IGeekbotLogger.cs @@ -9,7 +9,7 @@ namespace Geekbot.Core.Logger void Information(LogSource source, string message, object extra = null); void Warning(LogSource source, string message, Exception stackTrace = null, object extra = null); void Error(LogSource source, string message, Exception stackTrace, object extra = null); - NLog.Logger GetNLogger(); + Serilog.ILogger GetLogger(); bool LogAsJson(); } } \ No newline at end of file diff --git a/src/Core/Logger/LoggerFactory.cs b/src/Core/Logger/LoggerFactory.cs index bf3d926..d44c331 100644 --- a/src/Core/Logger/LoggerFactory.cs +++ b/src/Core/Logger/LoggerFactory.cs @@ -1,64 +1,104 @@ using System; -using System.Text; -using NLog; -using NLog.Config; -using NLog.Targets; -using SumoLogic.Logging.NLog; +using Serilog; +using Serilog.Events; +using Serilog.Sinks.Datadog.Logs; namespace Geekbot.Core.Logger { public class LoggerFactory { - public static NLog.Logger CreateNLog(RunParameters runParameters) + public static ILogger CreateLogger(RunParameters runParameters) { - var config = new LoggingConfiguration(); - var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; - - if (!string.IsNullOrEmpty(runParameters.SumologicEndpoint)) + var logger = new LoggerConfiguration(); + var minLevel = runParameters.Verbose ? LogEventLevel.Verbose : LogEventLevel.Information; + if (!string.IsNullOrEmpty(runParameters.DatadogApiKey)) { - Console.WriteLine("Logging Geekbot Logs to Sumologic"); - config.LoggingRules.Add( - new LoggingRule("*", minLevel, LogLevel.Fatal, - new SumoLogicTarget() - { - Url = runParameters.SumologicEndpoint, - SourceName = "GeekbotLogger", - Layout = "${message}", - UseConsoleLog = false, - OptimizeBufferReuse = true, - Name = "Geekbot" - }) + // 2nd error logger + var errorLogger = new LoggerConfiguration().WriteTo.Console().CreateLogger(); + errorLogger.Information("Enabling Datadog Logger"); + + logger.WriteTo.DatadogLogs( + apiKey: runParameters.DatadogApiKey, + source: "GeekbotLogger", + service: "Geekbot", + host: Environment.MachineName, + configuration: new DatadogConfiguration() + { + Url = "https://http-intake.logs.datadoghq.eu", + Port = 443, + UseSSL = true, + UseTCP = false + }, + logLevel: minLevel, + exceptionHandler: exception => + { + var cannotSendLogEventException = exception as CannotSendLogEventException; + errorLogger.Error(cannotSendLogEventException, "Datadog Error"); + } ); } else if (runParameters.LogJson) { - config.LoggingRules.Add( - new LoggingRule("*", minLevel, LogLevel.Fatal, - new ConsoleTarget - { - Name = "Console", - Encoding = Encoding.UTF8, - Layout = "${message}" - } - ) - ); + logger.WriteTo.Console(restrictedToMinimumLevel: minLevel, outputTemplate: "{Message:lj}{NewLine}"); } else { - config.LoggingRules.Add( - new LoggingRule("*", minLevel, LogLevel.Fatal, - new ColoredConsoleTarget - { - Name = "Console", - Encoding = Encoding.UTF8, - Layout = "[${longdate} ${level:format=FirstCharacter}] ${message} ${exception:format=toString}" - } - ) - ); + logger.WriteTo.Console(restrictedToMinimumLevel: minLevel); } - var loggerConfig = new LogFactory {Configuration = config}; - return loggerConfig.GetCurrentClassLogger(); + return logger.CreateLogger(); } + + // public static NLog.Logger CreateNLog(RunParameters runParameters) + // { + // var config = new LoggingConfiguration(); + // var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info; + // + // if (!string.IsNullOrEmpty(runParameters.SumologicEndpoint)) + // { + // Console.WriteLine("Logging Geekbot Logs to Sumologic"); + // config.LoggingRules.Add( + // new LoggingRule("*", minLevel, LogLevel.Fatal, + // new SumoLogicTarget() + // { + // Url = runParameters.SumologicEndpoint, + // SourceName = "GeekbotLogger", + // Layout = "${message}", + // UseConsoleLog = false, + // OptimizeBufferReuse = true, + // Name = "Geekbot" + // }) + // ); + // } + // else if (runParameters.LogJson) + // { + // config.LoggingRules.Add( + // new LoggingRule("*", minLevel, LogLevel.Fatal, + // new ConsoleTarget + // { + // Name = "Console", + // Encoding = Encoding.UTF8, + // Layout = "${message}" + // } + // ) + // ); + // } + // else + // { + // config.LoggingRules.Add( + // new LoggingRule("*", minLevel, LogLevel.Fatal, + // new ColoredConsoleTarget + // { + // Name = "Console", + // Encoding = Encoding.UTF8, + // Layout = "[${longdate} ${level:format=FirstCharacter}] ${message} ${exception:format=toString}" + // } + // ) + // ); + // } + // + // var loggerConfig = new LogFactory {Configuration = config}; + // return loggerConfig.GetCurrentClassLogger(); + // } } } \ No newline at end of file diff --git a/src/Core/RunParameters.cs b/src/Core/RunParameters.cs index 3210587..00ff5f2 100644 --- a/src/Core/RunParameters.cs +++ b/src/Core/RunParameters.cs @@ -74,12 +74,15 @@ namespace Geekbot.Core * Intergrations * ************************************/ - [Option("sumologic", HelpText = "Sumologic endpoint for logging (default: null) (env: SUMOLOGIC)")] - public string SumologicEndpoint { get; set; } = ParamFallback("SUMOLOGIC"); + // [Option("sumologic", HelpText = "Sumologic endpoint for logging (default: null) (env: SUMOLOGIC)")] + // public string SumologicEndpoint { get; set; } = ParamFallback("SUMOLOGIC"); [Option("sentry", HelpText = "Sentry endpoint for error reporting (default: null) (env: SENTRY)")] public string SentryEndpoint { get; set; } = ParamFallback("SENTRY"); + [Option("datadog-api-key", HelpText = "Datadog API Key (default: null) (env: DATADOG_API_KEY)")] + public string DatadogApiKey { get; set; } = ParamFallback("DATADOG_API_KEY"); + /************************************ * Helper Functions * ************************************/ diff --git a/src/Web/Logging/AspLogger.cs b/src/Web/Logging/AspLogger.cs index c18a7f3..ad6fe15 100644 --- a/src/Web/Logging/AspLogger.cs +++ b/src/Web/Logging/AspLogger.cs @@ -1,6 +1,7 @@ using System; using Geekbot.Core.Logger; using Microsoft.Extensions.Logging; +using Serilog.Events; namespace Geekbot.Web.Logging { @@ -45,7 +46,7 @@ namespace Geekbot.Web.Logging public bool IsEnabled(LogLevel logLevel) { - return !_geekbotLogger.LogAsJson() && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(logLevel)); + return !_geekbotLogger.LogAsJson() && _geekbotLogger.GetLogger().IsEnabled(ToGeekbotLogLevel(logLevel)); } public IDisposable BeginScope(TState state) @@ -53,17 +54,16 @@ namespace Geekbot.Web.Logging return null; } - private static NLog.LogLevel ToGeekbotLogLevel(LogLevel level) + private static LogEventLevel ToGeekbotLogLevel(LogLevel level) { return level switch { - LogLevel.Trace => NLog.LogLevel.Trace, - LogLevel.Debug => NLog.LogLevel.Debug, - LogLevel.Information => NLog.LogLevel.Info, - LogLevel.Warning => NLog.LogLevel.Warn, - LogLevel.Error => NLog.LogLevel.Error, - LogLevel.Critical => NLog.LogLevel.Fatal, - LogLevel.None => NLog.LogLevel.Off, + LogLevel.Trace => LogEventLevel.Verbose, + LogLevel.Debug => LogEventLevel.Debug, + LogLevel.Information => LogEventLevel.Information, + LogLevel.Warning => LogEventLevel.Warning, + LogLevel.Error => LogEventLevel.Error, + LogLevel.Critical => LogEventLevel.Fatal, _ => throw new ArgumentOutOfRangeException(nameof(level)) }; } From 09dbeb97667d12adcfd9fab69fc14b2811a6abdb Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 24 Nov 2020 21:40:33 +0100 Subject: [PATCH 002/149] Fix a stupid bug with the !avatar command --- src/Bot/Commands/Utils/AvatarGetter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Utils/AvatarGetter.cs b/src/Bot/Commands/Utils/AvatarGetter.cs index 6585a75..2aa6b07 100644 --- a/src/Bot/Commands/Utils/AvatarGetter.cs +++ b/src/Bot/Commands/Utils/AvatarGetter.cs @@ -21,8 +21,8 @@ namespace Geekbot.Bot.Commands.Utils { try { - if (user == null) user = Context.User; - var url = user.GetAvatarUrl().Replace("128", "1024"); + user ??= Context.User; + var url = user.GetAvatarUrl(ImageFormat.Auto, 1024); await ReplyAsync(url); } catch (Exception e) From baf09e2f3807c9aa3fbd652f344399fee835eb89 Mon Sep 17 00:00:00 2001 From: runebaas Date: Wed, 25 Nov 2020 15:21:55 +0100 Subject: [PATCH 003/149] Remove the ability to create quotes from message ids --- src/Bot/Commands/Utils/Quote/Quote.cs | 35 ++------------------------ src/Bot/Localization/Quote.Designer.cs | 9 ------- src/Bot/Localization/Quote.de-ch.resx | 3 --- src/Bot/Localization/Quote.resx | 3 --- 4 files changed, 2 insertions(+), 48 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 0b197cd..a5f2e3c 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -74,22 +74,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote { await QuoteFromMention(user, false); } - - [Command("add")] - [Alias("save")] - [Summary("Add a quote from a message id")] - public async Task AddQuote([Summary("message-ID")] ulong messageId) - { - await QuoteFromMessageId(messageId, true); - } - - [Command("make")] - [Alias("preview")] - [Summary("Preview a quote from a message id")] - public async Task ReturnSpecifiedQuote([Summary("message-ID")] ulong messageId) - { - await QuoteFromMessageId(messageId, false); - } [Command("add")] [Alias("save")] @@ -208,21 +192,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } - private async Task QuoteFromMessageId(ulong messageId, bool saveToDb) - { - try - { - var message = await Context.Channel.GetMessageAsync(messageId); - - await ProcessQuote(message, saveToDb, true); - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context, "I couldn't find a message with that id :disappointed:"); - } - } - - private async Task QuoteFromMessageLink(string messageLink, bool saveToDb) + private async Task QuoteFromMessageLink(string messageLink, bool saveToDb) { try { @@ -253,7 +223,7 @@ namespace Geekbot.Bot.Commands.Utils.Quote } } - private async Task ProcessQuote(IMessage message, bool saveToDb, bool showMessageIdWarning = false) + private async Task ProcessQuote(IMessage message, bool saveToDb) { if (message.Author.Id == Context.Message.Author.Id && saveToDb && !_isDev) { @@ -278,7 +248,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote var sb = new StringBuilder(); if (saveToDb) sb.AppendLine(Localization.Quote.QuoteAdded); - if (showMessageIdWarning) sb.AppendLine(Localization.Quote.MessageIdDeprecation); await ReplyAsync(sb.ToString(), false, embed.Build()); } diff --git a/src/Bot/Localization/Quote.Designer.cs b/src/Bot/Localization/Quote.Designer.cs index d0926ae..342c181 100644 --- a/src/Bot/Localization/Quote.Designer.cs +++ b/src/Bot/Localization/Quote.Designer.cs @@ -78,15 +78,6 @@ namespace Geekbot.Bot.Localization { } } - /// - /// Looks up a localized string similar to :warning: Creating quotes by message ID is deprecated in favour of message links and will be removed on 1 December 2020. - /// - internal static string MessageIdDeprecation { - get { - return ResourceManager.GetString("MessageIdDeprecation", resourceCulture); - } - } - /// /// Looks up a localized string similar to Most quoted person. /// diff --git a/src/Bot/Localization/Quote.de-ch.resx b/src/Bot/Localization/Quote.de-ch.resx index c7e3b8b..99fd959 100644 --- a/src/Bot/Localization/Quote.de-ch.resx +++ b/src/Bot/Localization/Quote.de-ch.resx @@ -44,7 +44,4 @@ Du chasch numme nachrichte vom gliche server quote - - :warning: Es mache vo quotes mit message-IDs isch zgunste vo message-links veraltet und wird am 1. dezember 2020 entfernt - \ No newline at end of file diff --git a/src/Bot/Localization/Quote.resx b/src/Bot/Localization/Quote.resx index 215f0ea..b51d79c 100644 --- a/src/Bot/Localization/Quote.resx +++ b/src/Bot/Localization/Quote.resx @@ -51,7 +51,4 @@ You can only quote messages from the same server - - :warning: Creating quotes by message ID is deprecated in favour of message links and will be removed on 1 December 2020 - \ No newline at end of file From 714b0008bc480ebb1ac56f9f397d5591dc066df9 Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 11 Dec 2020 22:38:43 +0100 Subject: [PATCH 004/149] Allow a die to have 145 sides --- src/Core/DiceParser/SingleDie.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/DiceParser/SingleDie.cs b/src/Core/DiceParser/SingleDie.cs index 4e0f474..7c1ae41 100644 --- a/src/Core/DiceParser/SingleDie.cs +++ b/src/Core/DiceParser/SingleDie.cs @@ -63,9 +63,9 @@ namespace Geekbot.Core.DiceParser throw new DiceException("Die must have at least 2 sides") { DiceName = DiceName }; } - if (Sides > 144) + if (Sides > 145) { - throw new DiceException("Die can not have more than 144 sides") { DiceName = DiceName }; + throw new DiceException("Die can not have more than 145 sides") { DiceName = DiceName }; } } } From 7e792bd7821ada737086c3b8a5171cc82ffc55b4 Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 29 Dec 2020 17:12:03 +0100 Subject: [PATCH 005/149] Fallback to user repo when retrieving a user via the discord gateway fails or times out --- src/Bot/Commands/Utils/Quote/Quote.cs | 16 ++++++++++++++-- src/Core/Polyfills/UserPolyfillDto.cs | 3 ++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index a5f2e3c..47986a0 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -13,6 +13,7 @@ using Geekbot.Core.Extensions; using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; +using Geekbot.Core.UserRepository; namespace Geekbot.Bot.Commands.Utils.Quote { @@ -22,13 +23,15 @@ namespace Geekbot.Bot.Commands.Utils.Quote { private readonly DatabaseContext _database; private readonly IRandomNumberGenerator _randomNumberGenerator; + private readonly IUserRepository _userRepository; private readonly bool _isDev; - public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager) + public Quote(IErrorHandler errorHandler, DatabaseContext database, IRandomNumberGenerator randomNumberGenerator, IGuildSettingsManager guildSettingsManager, IUserRepository userRepository) : base(errorHandler, guildSettingsManager) { _database = database; _randomNumberGenerator = randomNumberGenerator; + _userRepository = userRepository; // to remove restrictions when developing _isDev = Constants.BotVersion() == "0.0.0-DEV"; } @@ -254,7 +257,16 @@ namespace Geekbot.Bot.Commands.Utils.Quote private EmbedBuilder QuoteBuilder(QuoteModel quote) { - var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result ?? new UserPolyfillDto { Username = "Unknown User" }; + var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result; + if (user == null) + { + var fallbackUserFromRepo = _userRepository.Get(quote.UserId.AsUlong()); + user = new UserPolyfillDto() + { + Username = fallbackUserFromRepo?.Username ?? "Unknown User", + AvatarUrl = fallbackUserFromRepo?.AvatarUrl + }; + } var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); if (quote.InternalId == 0) diff --git a/src/Core/Polyfills/UserPolyfillDto.cs b/src/Core/Polyfills/UserPolyfillDto.cs index 3a8f43f..1d3a54b 100644 --- a/src/Core/Polyfills/UserPolyfillDto.cs +++ b/src/Core/Polyfills/UserPolyfillDto.cs @@ -14,6 +14,7 @@ namespace Geekbot.Core.Polyfills public UserStatus Status { get; set; } public IImmutableSet ActiveClients { get; } public string AvatarId { get; set; } + public string AvatarUrl { get; set; } public string Discriminator { get; set; } public ushort DiscriminatorValue { get; set; } public bool IsBot { get; set; } @@ -22,7 +23,7 @@ namespace Geekbot.Core.Polyfills public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) { - return "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; + return AvatarUrl ?? "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; } public string GetDefaultAvatarUrl() From 29c0def713fb668cdbd1d3bc7a74d94e0738a23c Mon Sep 17 00:00:00 2001 From: runebaas Date: Tue, 29 Dec 2020 22:33:19 +0100 Subject: [PATCH 006/149] Start counting messages per quarter starting 1 january 2021 --- src/Bot/Handlers/StatsHandler.cs | 88 +++++++++++++++---- src/Core/Database/DatabaseContext.cs | 1 + .../Database/Models/MessageSeasonsModel.cs | 21 +++++ 3 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 src/Core/Database/Models/MessageSeasonsModel.cs diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 197bbb8..e5962a9 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,5 +1,7 @@ using System; +using System.Globalization; using System.Threading.Tasks; +using System.Timers; using Discord.WebSocket; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -13,11 +15,28 @@ namespace Geekbot.Bot.Handlers { private readonly IGeekbotLogger _logger; private readonly DatabaseContext _database; + private string _season; + // ToDo: Clean up in 2021 + private bool _seasonsStarted; public StatsHandler(IGeekbotLogger logger, DatabaseContext database) { _logger = logger; _database = database; + _season = GetSeason(); + _seasonsStarted = DateTime.Now.Year == 2021; + + var timer = new Timer() + { + Enabled = true, + AutoReset = true, + Interval = TimeSpan.FromHours(1).TotalMilliseconds + }; + timer.Elapsed += (sender, args) => + { + _season = GetSeason(); + _seasonsStarted = DateTime.Now.Year == 2021; + }; } public async Task UpdateStats(SocketMessage message) @@ -32,23 +51,12 @@ namespace Geekbot.Bot.Handlers } var channel = (SocketGuildChannel) message.Channel; - - var rowId = await _database.Database.ExecuteSqlRawAsync( - "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", - channel.Guild.Id.AsLong(), - message.Author.Id.AsLong() - ); - - if (rowId == 0) + await UpdateTotalTable(message, channel); + if (_seasonsStarted) { - await _database.Messages.AddAsync(new MessagesModel - { - UserId = message.Author.Id.AsLong(), - GuildId = channel.Guild.Id.AsLong(), - MessageCount = 1 - }); - await _database.SaveChangesAsync(); + await UpdateSeasonsTable(message, channel); } + if (message.Author.IsBot) return; _logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message)); @@ -58,5 +66,55 @@ namespace Geekbot.Bot.Handlers _logger.Error(LogSource.Message, "Could not process message stats", e); } } + + private async Task UpdateTotalTable(SocketMessage message, SocketGuildChannel channel) + { + var rowId = await _database.Database.ExecuteSqlRawAsync( + "UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}", + channel.Guild.Id.AsLong(), + message.Author.Id.AsLong() + ); + + if (rowId == 0) + { + await _database.Messages.AddAsync(new MessagesModel + { + UserId = message.Author.Id.AsLong(), + GuildId = channel.Guild.Id.AsLong(), + MessageCount = 1 + }); + await _database.SaveChangesAsync(); + } + } + + private async Task UpdateSeasonsTable(SocketMessage message, SocketGuildChannel channel) + { + var rowId = await _database.Database.ExecuteSqlRawAsync( + "UPDATE \"MessagesSeasons\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1} AND \"Season\" = {2}", + channel.Guild.Id.AsLong(), + message.Author.Id.AsLong(), + _season + ); + + if (rowId == 0) + { + await _database.MessagesSeasons.AddAsync(new MessageSeasonsModel() + { + UserId = message.Author.Id.AsLong(), + GuildId = channel.Guild.Id.AsLong(), + Season = _season, + MessageCount = 1 + }); + await _database.SaveChangesAsync(); + } + } + + private static string GetSeason() + { + var now = DateTime.Now; + var year = (now.Year - 2000).ToString(CultureInfo.InvariantCulture); + var quarter = Math.Ceiling(now.Month / 3.0).ToString(CultureInfo.InvariantCulture); + return $"{year}Q{quarter}"; + } } } \ No newline at end of file diff --git a/src/Core/Database/DatabaseContext.cs b/src/Core/Database/DatabaseContext.cs index 93d46d3..14a1275 100644 --- a/src/Core/Database/DatabaseContext.cs +++ b/src/Core/Database/DatabaseContext.cs @@ -11,6 +11,7 @@ namespace Geekbot.Core.Database public DbSet Karma { get; set; } public DbSet Ships { get; set; } public DbSet Rolls { get; set; } + public DbSet MessagesSeasons { get; set; } public DbSet Messages { get; set; } public DbSet Slaps { get; set; } public DbSet Globals { get; set; } diff --git a/src/Core/Database/Models/MessageSeasonsModel.cs b/src/Core/Database/Models/MessageSeasonsModel.cs new file mode 100644 index 0000000..5a4252c --- /dev/null +++ b/src/Core/Database/Models/MessageSeasonsModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace Geekbot.Core.Database.Models +{ + public class MessageSeasonsModel + { + [Key] + public int Id { get; set; } + + [Required] + public long GuildId { get; set; } + + [Required] + public long UserId { get; set; } + + [Required] + public string Season { get; set; } + + public int MessageCount { get; set; } + } +} \ No newline at end of file From 29bb8035fe14f4f9a2b34c60f91548433fd82535 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:17:00 +0100 Subject: [PATCH 007/149] add !rank seasons to the rank command --- src/Bot/Commands/User/Ranking/Rank.cs | 22 ++++++++++++++++++---- src/Bot/Handlers/StatsHandler.cs | 16 +++++----------- src/Core/Highscores/HighscoreManager.cs | 16 +++++++++++++++- src/Core/Highscores/HighscoreTypes.cs | 3 ++- src/Core/Highscores/IHighscoreManager.cs | 3 ++- src/Core/Highscores/SeasonsUtils.cs | 16 ++++++++++++++++ 6 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 src/Core/Highscores/SeasonsUtils.cs diff --git a/src/Bot/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs index 20749a8..14a7650 100644 --- a/src/Bot/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -30,9 +30,12 @@ namespace Geekbot.Bot.Commands.User.Ranking } [Command("rank", RunMode = RunMode.Async)] - [Summary("get user top 10 in messages or karma")] + [Summary("Get the highscore for various stats like message count, karma, correctly guessed roles, etc...")] [DisableInDirectMessage] - public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10) + public async Task RankCmd( + [Summary("type")] string typeUnformated = "messages", + [Summary("amount")] int amount = 10, + [Summary("season")] string season = null) { try { @@ -59,7 +62,7 @@ namespace Geekbot.Bot.Commands.User.Ranking Dictionary highscoreUsers; try { - highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount); + highscoreUsers = _highscoreManager.GetHighscoresWithUserData(type, guildId, amount, season); } catch (HighscoreListEmptyException) { @@ -80,7 +83,18 @@ namespace Geekbot.Bot.Commands.User.Ranking if (failedToRetrieveUser) replyBuilder.AppendLine(Localization.Rank.FailedToResolveAllUsernames).AppendLine(); - replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name)); + if (type == HighscoreTypes.seasons) + { + if (string.IsNullOrEmpty(season)) + { + season = SeasonsUtils.GetCurrentSeason(); + } + replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, $"{type.ToString().CapitalizeFirst()} ({season})", Context.Guild.Name)); + } + else + { + replyBuilder.AppendLine(string.Format(Localization.Rank.HighscoresFor, type.ToString().CapitalizeFirst(), Context.Guild.Name)); + } var highscorePlace = 1; foreach (var (user, value) in highscoreUsers) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index e5962a9..669be0f 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,11 +1,11 @@ using System; -using System.Globalization; using System.Threading.Tasks; using System.Timers; using Discord.WebSocket; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.Extensions; +using Geekbot.Core.Highscores; using Geekbot.Core.Logger; using Microsoft.EntityFrameworkCore; @@ -23,7 +23,7 @@ namespace Geekbot.Bot.Handlers { _logger = logger; _database = database; - _season = GetSeason(); + _season = SeasonsUtils.GetCurrentSeason(); _seasonsStarted = DateTime.Now.Year == 2021; var timer = new Timer() @@ -34,7 +34,9 @@ namespace Geekbot.Bot.Handlers }; timer.Elapsed += (sender, args) => { - _season = GetSeason(); + var current = SeasonsUtils.GetCurrentSeason(); + if (current == _season) return; + _season = SeasonsUtils.GetCurrentSeason(); _seasonsStarted = DateTime.Now.Year == 2021; }; } @@ -108,13 +110,5 @@ namespace Geekbot.Bot.Handlers await _database.SaveChangesAsync(); } } - - private static string GetSeason() - { - var now = DateTime.Now; - var year = (now.Year - 2000).ToString(CultureInfo.InvariantCulture); - var quarter = Math.Ceiling(now.Month / 3.0).ToString(CultureInfo.InvariantCulture); - return $"{year}Q{quarter}"; - } } } \ No newline at end of file diff --git a/src/Core/Highscores/HighscoreManager.cs b/src/Core/Highscores/HighscoreManager.cs index ac8580b..7379e5e 100644 --- a/src/Core/Highscores/HighscoreManager.cs +++ b/src/Core/Highscores/HighscoreManager.cs @@ -18,7 +18,7 @@ namespace Geekbot.Core.Highscores } - public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount) + public Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount, string season = null) { var list = type switch { @@ -26,6 +26,7 @@ namespace Geekbot.Core.Highscores HighscoreTypes.karma => GetKarmaList(guildId, amount), HighscoreTypes.rolls => GetRollsList(guildId, amount), HighscoreTypes.cookies => GetCookiesList(guildId, amount), + HighscoreTypes.seasons => GetMessageSeasonList(guildId, amount, season), _ => new Dictionary() }; @@ -75,6 +76,19 @@ namespace Geekbot.Core.Highscores .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); } + public Dictionary GetMessageSeasonList(ulong guildId, int amount, string season) + { + if (string.IsNullOrEmpty(season)) + { + season = SeasonsUtils.GetCurrentSeason(); + } + return _database.MessagesSeasons + .Where(k => k.GuildId.Equals(guildId.AsLong()) && k.Season.Equals(season)) + .OrderByDescending(o => o.MessageCount) + .Take(amount) + .ToDictionary(key => key.UserId.AsUlong(), key => key.MessageCount); + } + public Dictionary GetKarmaList(ulong guildId, int amount) { return _database.Karma diff --git a/src/Core/Highscores/HighscoreTypes.cs b/src/Core/Highscores/HighscoreTypes.cs index b577642..9901c98 100644 --- a/src/Core/Highscores/HighscoreTypes.cs +++ b/src/Core/Highscores/HighscoreTypes.cs @@ -5,6 +5,7 @@ messages, karma, rolls, - cookies + cookies, + seasons } } \ No newline at end of file diff --git a/src/Core/Highscores/IHighscoreManager.cs b/src/Core/Highscores/IHighscoreManager.cs index 83ba2da..9c2d6f0 100644 --- a/src/Core/Highscores/IHighscoreManager.cs +++ b/src/Core/Highscores/IHighscoreManager.cs @@ -4,8 +4,9 @@ namespace Geekbot.Core.Highscores { public interface IHighscoreManager { - Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount); + Dictionary GetHighscoresWithUserData(HighscoreTypes type, ulong guildId, int amount, string season = null); Dictionary GetMessageList(ulong guildId, int amount); + Dictionary GetMessageSeasonList(ulong guildId, int amount, string season); Dictionary GetKarmaList(ulong guildId, int amount); Dictionary GetRollsList(ulong guildId, int amount); } diff --git a/src/Core/Highscores/SeasonsUtils.cs b/src/Core/Highscores/SeasonsUtils.cs new file mode 100644 index 0000000..d2a8e3e --- /dev/null +++ b/src/Core/Highscores/SeasonsUtils.cs @@ -0,0 +1,16 @@ +using System; +using System.Globalization; + +namespace Geekbot.Core.Highscores +{ + public class SeasonsUtils + { + public static string GetCurrentSeason() + { + var now = DateTime.Now; + var year = (now.Year - 2000).ToString(CultureInfo.InvariantCulture); + var quarter = Math.Ceiling(now.Month / 3.0).ToString(CultureInfo.InvariantCulture); + return $"{year}Q{quarter}"; + } + } +} \ No newline at end of file From 01f0d2f43b613d07b9a5be365c6274f2f9dbd983 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:19:15 +0100 Subject: [PATCH 008/149] Check every 5 minutes if it's 2021 instead of every hour in the stats handler --- src/Bot/Handlers/StatsHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 669be0f..137842c 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -30,7 +30,7 @@ namespace Geekbot.Bot.Handlers { Enabled = true, AutoReset = true, - Interval = TimeSpan.FromHours(1).TotalMilliseconds + Interval = TimeSpan.FromMinutes(5).TotalMilliseconds }; timer.Elapsed += (sender, args) => { From 17f62d76079f48c49e9943a6f11f73adb15970ca Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:23:40 +0100 Subject: [PATCH 009/149] Ignore the discord bots server when updating stats --- src/Bot/Handlers/StatsHandler.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 137842c..5ee7871 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using System.Timers; using Discord.WebSocket; @@ -25,7 +26,7 @@ namespace Geekbot.Bot.Handlers _database = database; _season = SeasonsUtils.GetCurrentSeason(); _seasonsStarted = DateTime.Now.Year == 2021; - + var timer = new Timer() { Enabled = true, @@ -53,6 +54,14 @@ namespace Geekbot.Bot.Handlers } var channel = (SocketGuildChannel) message.Channel; + + // ignore the discord bots server + // ToDo: create a clean solution for this... + if (channel.Guild.Id == 110373943822540800) + { + return; + } + await UpdateTotalTable(message, channel); if (_seasonsStarted) { From 8bdf2e96818c2ef2ad5acb6906ca8200e7851e77 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:31:15 +0100 Subject: [PATCH 010/149] Add support for !rank quote --- src/Bot/Commands/Utils/Quote/Quote.cs | 4 ++-- src/Core/Highscores/HighscoreManager.cs | 12 ++++++++++++ src/Core/Highscores/HighscoreTypes.cs | 3 ++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 47986a0..6a94309 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -147,8 +147,8 @@ namespace Geekbot.Bot.Commands.Utils.Quote .Where(row => row.GuildId == Context.Guild.Id.AsLong()) .GroupBy(row => row.UserId) .Select(row => new { userId = row.Key, amount = row.Count()}) - .OrderBy(row => row.amount) - .Last(); + .OrderByDescending(row => row.amount) + .First(); var mostQuotedPersonUser = Context.Client.GetUserAsync(mostQuotedPerson.userId.AsUlong()).Result ?? new UserPolyfillDto {Username = "Unknown User"}; var quotesByYear = _database.Quotes diff --git a/src/Core/Highscores/HighscoreManager.cs b/src/Core/Highscores/HighscoreManager.cs index 7379e5e..c839b39 100644 --- a/src/Core/Highscores/HighscoreManager.cs +++ b/src/Core/Highscores/HighscoreManager.cs @@ -27,6 +27,7 @@ namespace Geekbot.Core.Highscores HighscoreTypes.rolls => GetRollsList(guildId, amount), HighscoreTypes.cookies => GetCookiesList(guildId, amount), HighscoreTypes.seasons => GetMessageSeasonList(guildId, amount, season), + HighscoreTypes.quotes => GetQuotesList(guildId, amount), _ => new Dictionary() }; @@ -115,5 +116,16 @@ namespace Geekbot.Core.Highscores .Take(amount) .ToDictionary(key => key.UserId.AsUlong(), key => key.Cookies); } + + private Dictionary GetQuotesList(ulong guildId, int amount) + { + return _database.Quotes + .Where(row => row.GuildId == guildId.AsLong()) + .GroupBy(row => row.UserId) + .Select(row => new { userId = row.Key, amount = row.Count()}) + .OrderByDescending(row => row.amount) + .Take(amount) + .ToDictionary(key => key.userId.AsUlong(), key => key.amount); + } } } \ No newline at end of file diff --git a/src/Core/Highscores/HighscoreTypes.cs b/src/Core/Highscores/HighscoreTypes.cs index 9901c98..3aa396e 100644 --- a/src/Core/Highscores/HighscoreTypes.cs +++ b/src/Core/Highscores/HighscoreTypes.cs @@ -6,6 +6,7 @@ karma, rolls, cookies, - seasons + seasons, + quotes } } \ No newline at end of file From d477a4b056e209c4462fc369e311ec7044afb3e7 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 30 Dec 2020 23:33:27 +0100 Subject: [PATCH 011/149] Update the translations for !rank with the new rank types --- src/Bot/Localization/Rank.Designer.cs | 2 +- src/Bot/Localization/Rank.de-ch.resx | 2 +- src/Bot/Localization/Rank.resx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bot/Localization/Rank.Designer.cs b/src/Bot/Localization/Rank.Designer.cs index 23f5e16..6d54030 100644 --- a/src/Bot/Localization/Rank.Designer.cs +++ b/src/Bot/Localization/Rank.Designer.cs @@ -79,7 +79,7 @@ namespace Geekbot.Bot.Localization { } /// - /// Looks up a localized string similar to Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`'. + /// Looks up a localized string similar to Valid types are '`messages`' '`karma`', '`rolls`', '`cookies`', '`seasons`' and '`quotes`'. /// internal static string InvalidType { get { diff --git a/src/Bot/Localization/Rank.de-ch.resx b/src/Bot/Localization/Rank.de-ch.resx index 0b22fe4..743b8cd 100644 --- a/src/Bot/Localization/Rank.de-ch.resx +++ b/src/Bot/Localization/Rank.de-ch.resx @@ -24,6 +24,6 @@ :bar_chart: **{0} Highscore für {1}** - Gültigi paramenter sind '`messages`' '`karma`', '`rolls`' und '`cookies` + Gültigi paramenter sind '`messages`' '`karma`', '`rolls`', '`cookies`', '`seasons`' und '`quotes`' \ No newline at end of file diff --git a/src/Bot/Localization/Rank.resx b/src/Bot/Localization/Rank.resx index 9598cf8..606a34e 100644 --- a/src/Bot/Localization/Rank.resx +++ b/src/Bot/Localization/Rank.resx @@ -19,7 +19,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Valid types are '`messages`' '`karma`', '`rolls`' and '`cookies`' + Valid types are '`messages`' '`karma`', '`rolls`', '`cookies`', '`seasons`' and '`quotes`' :warning: Limiting to 20 From e495e2df17178bf0f444fe5a9bc0c73ad19dc920 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 1 Jan 2021 02:48:28 +0100 Subject: [PATCH 012/149] Use the correct unit when listing messages in a season --- src/Bot/Commands/User/Ranking/Rank.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Bot/Commands/User/Ranking/Rank.cs b/src/Bot/Commands/User/Ranking/Rank.cs index 14a7650..2f5f841 100644 --- a/src/Bot/Commands/User/Ranking/Rank.cs +++ b/src/Bot/Commands/User/Ranking/Rank.cs @@ -106,10 +106,13 @@ namespace Geekbot.Bot.Commands.User.Ranking replyBuilder.Append(user.Username != null ? $"**{user.Username}#{user.Discriminator}**" : $"**{user.Id}**"); - - replyBuilder.Append(type == HighscoreTypes.messages - ? $" - {value} {type} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n" - : $" - {value} {type}\n"); + + replyBuilder.Append(type switch + { + HighscoreTypes.messages => $" - {value} {HighscoreTypes.messages} - {Math.Round((double) (100 * value) / guildMessages, 2)}%\n", + HighscoreTypes.seasons => $" - {value} {HighscoreTypes.messages}\n", + _ => $" - {value} {type}\n" + }); highscorePlace++; } From 21303bfca81015af03e02d3a92f15e86f98d00ba Mon Sep 17 00:00:00 2001 From: runebaas Date: Fri, 1 Jan 2021 18:06:40 +0100 Subject: [PATCH 013/149] Remove code in the stats handler that checks if 2021 has started --- src/Bot/Handlers/StatsHandler.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index 5ee7871..d1384cd 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -17,15 +17,12 @@ namespace Geekbot.Bot.Handlers private readonly IGeekbotLogger _logger; private readonly DatabaseContext _database; private string _season; - // ToDo: Clean up in 2021 - private bool _seasonsStarted; public StatsHandler(IGeekbotLogger logger, DatabaseContext database) { _logger = logger; _database = database; _season = SeasonsUtils.GetCurrentSeason(); - _seasonsStarted = DateTime.Now.Year == 2021; var timer = new Timer() { @@ -38,7 +35,6 @@ namespace Geekbot.Bot.Handlers var current = SeasonsUtils.GetCurrentSeason(); if (current == _season) return; _season = SeasonsUtils.GetCurrentSeason(); - _seasonsStarted = DateTime.Now.Year == 2021; }; } @@ -62,11 +58,8 @@ namespace Geekbot.Bot.Handlers return; } - await UpdateTotalTable(message, channel); - if (_seasonsStarted) - { - await UpdateSeasonsTable(message, channel); - } + await UpdateTotalTable(message, channel); + await UpdateSeasonsTable(message, channel); if (message.Author.IsBot) return; From 04343352395a6f015e2acf919f64e5de2f5aca92 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 24 Jan 2021 22:15:15 +0100 Subject: [PATCH 014/149] Fix !corona by changing data source to covid19-api.org, added a country code parameter as well --- .../Corona/CoronaApiCountryResponseDto.cs | 19 +++++ src/Bot/Commands/Utils/Corona/CoronaStats.cs | 72 +++++++++++++++---- .../Commands/Utils/Corona/CoronaSummaryDto.cs | 9 --- .../Commands/Utils/Corona/CoronaTotalDto.cs | 9 +++ 4 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs delete mode 100644 src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs create mode 100644 src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs diff --git a/src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs b/src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs new file mode 100644 index 0000000..84da7f0 --- /dev/null +++ b/src/Bot/Commands/Utils/Corona/CoronaApiCountryResponseDto.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace Geekbot.Bot.Commands.Utils.Corona +{ + public record CoronaApiCountryResponseDto + { + [JsonProperty("country")] + public string Country { get; init; } + + [JsonProperty("cases")] + public decimal Cases { get; init; } + + [JsonProperty("deaths")] + public decimal Deaths { get; init; } + + [JsonProperty("recovered")] + public decimal Recovered { get; init; } + } +} \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs index 3f9f3ea..5880030 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; @@ -11,7 +13,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona public class CoronaStats : ModuleBase { private readonly IErrorHandler _errorHandler; - + public CoronaStats(IErrorHandler errorHandler) { _errorHandler = errorHandler; @@ -19,24 +21,30 @@ namespace Geekbot.Bot.Commands.Utils.Corona [Command("corona", RunMode = RunMode.Async)] [Summary("Get the latest worldwide corona statistics")] - public async Task Summary() + public async Task Summary([Summary("CountryCode")] string countryCode = null) { try { - var summary = await HttpAbstractions.Get(new Uri("https://api.covid19api.com/world/total")); - var activeCases = summary.TotalConfirmed - (summary.TotalRecovered + summary.TotalDeaths); + var summary = await GetCoronaInfo(countryCode); + if (summary == null) + { + await Context.Channel.SendMessageAsync($"`{countryCode}` is not a valid country code"); + return; + } + + var activeCases = summary.Cases - (summary.Recovered + summary.Deaths); - string CalculatePercentage(decimal i) => (i / summary.TotalConfirmed).ToString("#0.##%"); + string CalculatePercentage(decimal i) => (i / summary.Cases).ToString("#0.##%"); var activePercent = CalculatePercentage(activeCases); - var recoveredPercentage = CalculatePercentage(summary.TotalRecovered); - var deathsPercentage = CalculatePercentage(summary.TotalDeaths); + var recoveredPercentage = CalculatePercentage(summary.Recovered); + var deathsPercentage = CalculatePercentage(summary.Deaths); var numberFormat = "#,#"; - var totalFormatted = summary.TotalConfirmed.ToString(numberFormat); + var totalFormatted = summary.Cases.ToString(numberFormat); var activeFormatted = activeCases.ToString(numberFormat); - var recoveredFormatted = summary.TotalRecovered.ToString(numberFormat); - var deathsFormatted = summary.TotalDeaths.ToString(numberFormat); - + var recoveredFormatted = summary.Recovered.ToString(numberFormat); + var deathsFormatted = summary.Deaths.ToString(numberFormat); + var eb = new EmbedBuilder { Author = new EmbedAuthorBuilder @@ -46,7 +54,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona }, Footer = new EmbedFooterBuilder { - Text = "Source: covid19api.com", + Text = "Source: covid19-api.org", }, Color = Color.Red }; @@ -54,7 +62,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona eb.AddInlineField("Active", $"{activeFormatted} ({activePercent})"); eb.AddInlineField("Recovered", $"{recoveredFormatted} ({recoveredPercentage})"); eb.AddInlineField("Deaths", $"{deathsFormatted} ({deathsPercentage})"); - + await Context.Channel.SendMessageAsync(String.Empty, false, eb.Build()); } catch (Exception e) @@ -62,5 +70,43 @@ namespace Geekbot.Bot.Commands.Utils.Corona await _errorHandler.HandleCommandException(e, Context); } } + + private async Task GetCoronaInfo(string countryCode = null) + { + var allCountries = await HttpAbstractions.Get>(new Uri("https://covid19-api.org/api/status")); + + if (string.IsNullOrEmpty(countryCode)) + { + return allCountries.Aggregate( + new CoronaTotalDto(), + (accumulate, source) => + { + accumulate.Cases += source.Cases; + accumulate.Deaths += source.Deaths; + accumulate.Recovered += source.Recovered; + return accumulate; + } + ); + } + + if (countryCode.Length != 2) + { + return null; + } + + var upcasedCountryCode = countryCode.ToUpper(); + var countryStats = allCountries.Find(x => x.Country == upcasedCountryCode); + if (countryStats == null) + { + return null; + } + + return new CoronaTotalDto() + { + Cases = countryStats.Cases, + Deaths = countryStats.Deaths, + Recovered = countryStats.Recovered, + }; + } } } \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs b/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs deleted file mode 100644 index 3f6a820..0000000 --- a/src/Bot/Commands/Utils/Corona/CoronaSummaryDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Geekbot.Bot.Commands.Utils.Corona -{ - public class CoronaSummaryDto - { - public decimal TotalConfirmed { get; set; } - public decimal TotalDeaths { get; set; } - public decimal TotalRecovered { get; set; } - } -} \ No newline at end of file diff --git a/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs new file mode 100644 index 0000000..c135927 --- /dev/null +++ b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Bot.Commands.Utils.Corona +{ + public record CoronaTotalDto + { + public decimal Cases { get; set; } + public decimal Deaths { get; set; } + public decimal Recovered { get; set; } + } +} \ No newline at end of file From 4fd62e9184145db1f76f33ebc3762c782e7fcde5 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 24 Jan 2021 22:20:59 +0100 Subject: [PATCH 015/149] Make sure that the build version suffix is not a number --- .gitlab-ci.yml | 4 ++-- src/Bot/Bot.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c4d8b15..20b1c84 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ stages: - ops variables: - VERSION: 4.3.0-$CI_COMMIT_SHORT_SHA + VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG Build: @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix $VERSION -r linux-x64 -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 4cd5b39..ec32e8f 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -7,7 +7,7 @@ $(VersionSuffix) Geekbot.Bot Geekbot - $(VersionSuffix) + $(VersionSuffix) 0.0.0-DEV Pizza and Coffee Studios Pizza and Coffee Studios From bbb9b894227f6f136bddfa1f8b418166d623d82d Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 25 Jan 2021 00:48:42 +0100 Subject: [PATCH 016/149] Add Support for emoji flags in the emoji converter --- src/Core/Converters/EmojiConverter.cs | 166 ++++++++++++++++--------- src/Core/Converters/IEmojiConverter.cs | 1 + 2 files changed, 107 insertions(+), 60 deletions(-) diff --git a/src/Core/Converters/EmojiConverter.cs b/src/Core/Converters/EmojiConverter.cs index 327aab8..7527321 100644 --- a/src/Core/Converters/EmojiConverter.cs +++ b/src/Core/Converters/EmojiConverter.cs @@ -1,90 +1,136 @@ using System.Collections; +using System.Net.NetworkInformation; using System.Text; namespace Geekbot.Core.Converters { public class EmojiConverter : IEmojiConverter { + private readonly string[] NumberEmojiMap = + { + ":zero:", + ":one:", + ":two:", + ":three:", + ":four:", + ":five:", + ":six:", + ":seven:", + ":eight:", + ":nine:" + }; + public string NumberToEmoji(int number) { if (number == 10) { return "🔟"; } - var emojiMap = new[] - { - ":zero:", - ":one:", - ":two:", - ":three:", - ":four:", - ":five:", - ":six:", - ":seven:", - ":eight:", - ":nine:" - }; + var numbers = number.ToString().ToCharArray(); var returnString = new StringBuilder(); foreach (var n in numbers) { - returnString.Append(emojiMap[int.Parse(n.ToString())]); + returnString.Append(NumberEmojiMap[int.Parse(n.ToString())]); } return returnString.ToString(); } + private readonly Hashtable TextEmojiMap = new Hashtable + { + ['A'] = ":regional_indicator_a: ", + ['B'] = ":b: ", + ['C'] = ":regional_indicator_c: ", + ['D'] = ":regional_indicator_d: ", + ['E'] = ":regional_indicator_e: ", + ['F'] = ":regional_indicator_f: ", + ['G'] = ":regional_indicator_g: ", + ['H'] = ":regional_indicator_h: ", + ['I'] = ":regional_indicator_i: ", + ['J'] = ":regional_indicator_j: ", + ['K'] = ":regional_indicator_k: ", + ['L'] = ":regional_indicator_l: ", + ['M'] = ":regional_indicator_m: ", + ['N'] = ":regional_indicator_n: ", + ['O'] = ":regional_indicator_o: ", + ['P'] = ":regional_indicator_p: ", + ['Q'] = ":regional_indicator_q: ", + ['R'] = ":regional_indicator_r: ", + ['S'] = ":regional_indicator_s: ", + ['T'] = ":regional_indicator_t: ", + ['U'] = ":regional_indicator_u: ", + ['V'] = ":regional_indicator_v: ", + ['W'] = ":regional_indicator_w: ", + ['X'] = ":regional_indicator_x: ", + ['Y'] = ":regional_indicator_y: ", + ['Z'] = ":regional_indicator_z: ", + ['!'] = ":exclamation: ", + ['?'] = ":question: ", + ['#'] = ":hash: ", + ['*'] = ":star2: ", + ['+'] = ":heavy_plus_sign: ", + ['0'] = ":zero: ", + ['1'] = ":one: ", + ['2'] = ":two: ", + ['3'] = ":three: ", + ['4'] = ":four: ", + ['5'] = ":five: ", + ['6'] = ":six: ", + ['7'] = ":seven: ", + ['8'] = ":eight: ", + ['9'] = ":nine: ", + [' '] = " " + }; + public string TextToEmoji(string text) { - var emojiMap = new Hashtable - { - ['A'] = ":regional_indicator_a: ", - ['B'] = ":b: ", - ['C'] = ":regional_indicator_c: ", - ['D'] = ":regional_indicator_d: ", - ['E'] = ":regional_indicator_e: ", - ['F'] = ":regional_indicator_f: ", - ['G'] = ":regional_indicator_g: ", - ['H'] = ":regional_indicator_h: ", - ['I'] = ":regional_indicator_i: ", - ['J'] = ":regional_indicator_j: ", - ['K'] = ":regional_indicator_k: ", - ['L'] = ":regional_indicator_l: ", - ['M'] = ":regional_indicator_m: ", - ['N'] = ":regional_indicator_n: ", - ['O'] = ":regional_indicator_o: ", - ['P'] = ":regional_indicator_p: ", - ['Q'] = ":regional_indicator_q: ", - ['R'] = ":regional_indicator_r: ", - ['S'] = ":regional_indicator_s: ", - ['T'] = ":regional_indicator_t: ", - ['U'] = ":regional_indicator_u: ", - ['V'] = ":regional_indicator_v: ", - ['W'] = ":regional_indicator_w: ", - ['X'] = ":regional_indicator_x: ", - ['Y'] = ":regional_indicator_y: ", - ['Z'] = ":regional_indicator_z: ", - ['!'] = ":exclamation: ", - ['?'] = ":question: ", - ['#'] = ":hash: ", - ['*'] = ":star2: ", - ['+'] = ":heavy_plus_sign: ", - ['0'] = ":zero: ", - ['1'] = ":one: ", - ['2'] = ":two: ", - ['3'] = ":three: ", - ['4'] = ":four: ", - ['5'] = ":five: ", - ['6'] = ":six: ", - ['7'] = ":seven: ", - ['8'] = ":eight: ", - ['9'] = ":nine: ", - [' '] = " " - }; var letters = text.ToUpper().ToCharArray(); var returnString = new StringBuilder(); foreach (var n in letters) { - var emoji = emojiMap[n] ?? n; + var emoji = TextEmojiMap[n] ?? n; + returnString.Append(emoji); + } + return returnString.ToString(); + } + + private readonly Hashtable RegionalIndicatorMap = new Hashtable() + { + ['A'] = new Rune(0x1F1E6), + ['B'] = new Rune(0x1F1E7), + ['C'] = new Rune(0x1F1E8), + ['D'] = new Rune(0x1F1E9), + ['E'] = new Rune(0x1F1EA), + ['F'] = new Rune(0x1F1EB), + ['G'] = new Rune(0x1F1EC), + ['H'] = new Rune(0x1F1ED), + ['I'] = new Rune(0x1F1EE), + ['J'] = new Rune(0x1F1EF), + ['K'] = new Rune(0x1F1F0), + ['L'] = new Rune(0x1F1F1), + ['M'] = new Rune(0x1F1F2), + ['N'] = new Rune(0x1F1F3), + ['O'] = new Rune(0x1F1F4), + ['P'] = new Rune(0x1F1F5), + ['Q'] = new Rune(0x1F1F6), + ['R'] = new Rune(0x1F1F7), + ['S'] = new Rune(0x1F1F8), + ['T'] = new Rune(0x1F1F9), + ['U'] = new Rune(0x1F1FA), + ['V'] = new Rune(0x1F1FB), + ['W'] = new Rune(0x1F1FC), + ['X'] = new Rune(0x1F1FD), + ['Y'] = new Rune(0x1F1FE), + ['Z'] = new Rune(0x1F1FF) + }; + + public string CountryCodeToEmoji(string countryCode) + { + var letters = countryCode.ToUpper().ToCharArray(); + var returnString = new StringBuilder(); + foreach (var n in letters) + { + var emoji = RegionalIndicatorMap[n]; returnString.Append(emoji); } return returnString.ToString(); diff --git a/src/Core/Converters/IEmojiConverter.cs b/src/Core/Converters/IEmojiConverter.cs index 79ca0a7..0c364ea 100644 --- a/src/Core/Converters/IEmojiConverter.cs +++ b/src/Core/Converters/IEmojiConverter.cs @@ -4,5 +4,6 @@ { string NumberToEmoji(int number); string TextToEmoji(string text); + string CountryCodeToEmoji(string countryCode); } } \ No newline at end of file From 644d877e29adda6752be60578281572ca648138b Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 25 Jan 2021 00:49:18 +0100 Subject: [PATCH 017/149] Show country flag when !corona has a country code parameter --- src/Bot/Commands/Utils/Corona/CoronaStats.cs | 17 +++++++++++++++-- src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs index 5880030..15431d2 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; using Geekbot.Core; +using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -13,10 +15,12 @@ namespace Geekbot.Bot.Commands.Utils.Corona public class CoronaStats : ModuleBase { private readonly IErrorHandler _errorHandler; + private readonly IEmojiConverter _emojiConverter; - public CoronaStats(IErrorHandler errorHandler) + public CoronaStats(IErrorHandler errorHandler, IEmojiConverter emojiConverter) { _errorHandler = errorHandler; + _emojiConverter = emojiConverter; } [Command("corona", RunMode = RunMode.Async)] @@ -45,11 +49,19 @@ namespace Geekbot.Bot.Commands.Utils.Corona var recoveredFormatted = summary.Recovered.ToString(numberFormat); var deathsFormatted = summary.Deaths.ToString(numberFormat); + var embedTitleBuilder = new StringBuilder(); + embedTitleBuilder.Append("Confirmed Corona Cases"); + if (!string.IsNullOrEmpty(summary.Country)) + { + embedTitleBuilder.Append(" - "); + embedTitleBuilder.Append(_emojiConverter.CountryCodeToEmoji(summary.Country)); + } + var eb = new EmbedBuilder { Author = new EmbedAuthorBuilder { - Name = "Confirmed Corona Cases", + Name = embedTitleBuilder.ToString(), IconUrl = "https://www.redcross.org/content/dam/icons/disasters/virus/Virus-1000x1000-R-Pl.png" }, Footer = new EmbedFooterBuilder @@ -103,6 +115,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona return new CoronaTotalDto() { + Country = upcasedCountryCode, Cases = countryStats.Cases, Deaths = countryStats.Deaths, Recovered = countryStats.Recovered, diff --git a/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs index c135927..58e5ac9 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaTotalDto.cs @@ -2,6 +2,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona { public record CoronaTotalDto { + public string Country { get; set; } public decimal Cases { get; set; } public decimal Deaths { get; set; } public decimal Recovered { get; set; } From eddd005d34159ab7890c2795707157d4bef5d6c4 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 25 Jan 2021 01:40:51 +0100 Subject: [PATCH 018/149] Add translations for !corona --- src/Bot/Bot.csproj | 9 ++ src/Bot/Commands/Utils/Corona/CoronaStats.cs | 21 ++-- src/Bot/Localization/Corona.Designer.cs | 117 +++++++++++++++++++ src/Bot/Localization/Corona.de-ch.resx | 32 +++++ src/Bot/Localization/Corona.resx | 39 +++++++ 5 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 src/Bot/Localization/Corona.Designer.cs create mode 100644 src/Bot/Localization/Corona.de-ch.resx create mode 100644 src/Bot/Localization/Corona.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index ec32e8f..6c6f56f 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -84,6 +84,10 @@ ResXFileCodeGenerator Stats.Designer.cs + + ResXFileCodeGenerator + Corona.Designer.cs + @@ -144,5 +148,10 @@ True Stats.resx + + True + True + Corona.resx + diff --git a/src/Bot/Commands/Utils/Corona/CoronaStats.cs b/src/Bot/Commands/Utils/Corona/CoronaStats.cs index 15431d2..e39be0a 100644 --- a/src/Bot/Commands/Utils/Corona/CoronaStats.cs +++ b/src/Bot/Commands/Utils/Corona/CoronaStats.cs @@ -9,17 +9,16 @@ using Geekbot.Core; using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Bot.Commands.Utils.Corona { - public class CoronaStats : ModuleBase + public class CoronaStats : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; private readonly IEmojiConverter _emojiConverter; - public CoronaStats(IErrorHandler errorHandler, IEmojiConverter emojiConverter) + public CoronaStats(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager, IEmojiConverter emojiConverter) : base(errorHandler, guildSettingsManager) { - _errorHandler = errorHandler; _emojiConverter = emojiConverter; } @@ -50,7 +49,7 @@ namespace Geekbot.Bot.Commands.Utils.Corona var deathsFormatted = summary.Deaths.ToString(numberFormat); var embedTitleBuilder = new StringBuilder(); - embedTitleBuilder.Append("Confirmed Corona Cases"); + embedTitleBuilder.Append(Localization.Corona.ConfirmedCases); if (!string.IsNullOrEmpty(summary.Country)) { embedTitleBuilder.Append(" - "); @@ -66,20 +65,20 @@ namespace Geekbot.Bot.Commands.Utils.Corona }, Footer = new EmbedFooterBuilder { - Text = "Source: covid19-api.org", + Text = $"{Localization.Corona.Source}: covid19-api.org", }, Color = Color.Red }; - eb.AddField("Total", totalFormatted); - eb.AddInlineField("Active", $"{activeFormatted} ({activePercent})"); - eb.AddInlineField("Recovered", $"{recoveredFormatted} ({recoveredPercentage})"); - eb.AddInlineField("Deaths", $"{deathsFormatted} ({deathsPercentage})"); + eb.AddField(Localization.Corona.Total, totalFormatted); + eb.AddInlineField(Localization.Corona.Active, $"{activeFormatted} ({activePercent})"); + eb.AddInlineField(Localization.Corona.Recovered, $"{recoveredFormatted} ({recoveredPercentage})"); + eb.AddInlineField(Localization.Corona.Deaths, $"{deathsFormatted} ({deathsPercentage})"); await Context.Channel.SendMessageAsync(String.Empty, false, eb.Build()); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } diff --git a/src/Bot/Localization/Corona.Designer.cs b/src/Bot/Localization/Corona.Designer.cs new file mode 100644 index 0000000..b243bfc --- /dev/null +++ b/src/Bot/Localization/Corona.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Corona { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Corona() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Corona", typeof(Corona).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Active. + /// + internal static string Active { + get { + return ResourceManager.GetString("Active", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirmed Corona Cases. + /// + internal static string ConfirmedCases { + get { + return ResourceManager.GetString("ConfirmedCases", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Deaths. + /// + internal static string Deaths { + get { + return ResourceManager.GetString("Deaths", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Recovered. + /// + internal static string Recovered { + get { + return ResourceManager.GetString("Recovered", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Source. + /// + internal static string Source { + get { + return ResourceManager.GetString("Source", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Total. + /// + internal static string Total { + get { + return ResourceManager.GetString("Total", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Corona.de-ch.resx b/src/Bot/Localization/Corona.de-ch.resx new file mode 100644 index 0000000..3c4180c --- /dev/null +++ b/src/Bot/Localization/Corona.de-ch.resx @@ -0,0 +1,32 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bstätigti Corona Fallzahle + + + Total + + + Aktiv + + + Erholt + + + Gstorbe + + + Quelle + + \ No newline at end of file diff --git a/src/Bot/Localization/Corona.resx b/src/Bot/Localization/Corona.resx new file mode 100644 index 0000000..44bf85e --- /dev/null +++ b/src/Bot/Localization/Corona.resx @@ -0,0 +1,39 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Confirmed Corona Cases + + + Total + + + Active + + + Recovered + + + Deaths + + + Source + + \ No newline at end of file From c1b8394e1b092d9d7b459f2969cad5ebb21e1b24 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 12:06:41 +0100 Subject: [PATCH 019/149] Add a !neutral command for karma, it does nothing. --- src/Bot/Commands/User/Karma.cs | 41 ++++++++++++++++++++++++++ src/Bot/Localization/Karma.Designer.cs | 9 ++++++ src/Bot/Localization/Karma.de-ch.resx | 3 ++ src/Bot/Localization/Karma.resx | 3 ++ 4 files changed, 56 insertions(+) diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs index 4778bce..3ba8650 100644 --- a/src/Bot/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -115,6 +115,47 @@ namespace Geekbot.Bot.Commands.User await ErrorHandler.HandleCommandException(e, Context); } } + + [Command("neutral", RunMode = RunMode.Async)] + [Summary("Do nothing to someones karma")] + public async Task Neutral([Summary("@someone")] IUser user) + { + try + { + var actor = await GetUser(Context.User.Id); + if (user.Id == Context.User.Id) + { + await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); + return; + } + + if (TimeoutFinished(actor.TimeOut)) + { + var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); + return; + } + + var target = await GetUser(user.Id); + + var eb = new EmbedBuilder(); + eb.WithAuthor(new EmbedAuthorBuilder() + .WithIconUrl(user.GetAvatarUrl()) + .WithName(user.Username)); + + eb.WithColor(new Color(138, 219, 146)); + eb.Title = Localization.Karma.Neutral; + eb.AddInlineField(Localization.Karma.By, Context.User.Username); + eb.AddInlineField(Localization.Karma.Amount, "0"); + eb.AddInlineField(Localization.Karma.Current, target.Karma); + await ReplyAsync("", false, eb.Build()); + + } + catch (Exception e) + { + await ErrorHandler.HandleCommandException(e, Context); + } + } private bool TimeoutFinished(DateTimeOffset lastKarma) { diff --git a/src/Bot/Localization/Karma.Designer.cs b/src/Bot/Localization/Karma.Designer.cs index 4191fa2..71cab3b 100644 --- a/src/Bot/Localization/Karma.Designer.cs +++ b/src/Bot/Localization/Karma.Designer.cs @@ -123,6 +123,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Neutral Karma. + /// + internal static string Neutral { + get { + return ResourceManager.GetString("Neutral", resourceCulture); + } + } + /// /// Looks up a localized string similar to Sorry {0}, but you have to wait {1} before you can give karma again.... /// diff --git a/src/Bot/Localization/Karma.de-ch.resx b/src/Bot/Localization/Karma.de-ch.resx index 5605f8b..7b739b7 100644 --- a/src/Bot/Localization/Karma.de-ch.resx +++ b/src/Bot/Localization/Karma.de-ch.resx @@ -35,4 +35,7 @@ Karma gsenkt + + Neutral Karma + \ No newline at end of file diff --git a/src/Bot/Localization/Karma.resx b/src/Bot/Localization/Karma.resx index 3a8fe5a..2ebea1d 100644 --- a/src/Bot/Localization/Karma.resx +++ b/src/Bot/Localization/Karma.resx @@ -42,4 +42,7 @@ Karma lowered + + Neutral Karma + \ No newline at end of file From 6c142f41d3b16582cd5bcaa4dd871ca522b43698 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 12:23:18 +0100 Subject: [PATCH 020/149] Upgrade discord.net --- src/Core/Core.csproj | 2 +- src/Core/Polyfills/UserPolyfillDto.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 780d0e2..0a4e989 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Core/Polyfills/UserPolyfillDto.cs b/src/Core/Polyfills/UserPolyfillDto.cs index 1d3a54b..385a30d 100644 --- a/src/Core/Polyfills/UserPolyfillDto.cs +++ b/src/Core/Polyfills/UserPolyfillDto.cs @@ -13,6 +13,7 @@ namespace Geekbot.Core.Polyfills public IActivity Activity { get; } public UserStatus Status { get; set; } public IImmutableSet ActiveClients { get; } + public IImmutableList Activities { get; } public string AvatarId { get; set; } public string AvatarUrl { get; set; } public string Discriminator { get; set; } @@ -20,7 +21,8 @@ namespace Geekbot.Core.Polyfills public bool IsBot { get; set; } public bool IsWebhook { get; set; } public string Username { get; set; } - + public UserProperties? PublicFlags { get; } + public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) { return AvatarUrl ?? "https://discordapp.com/assets/6debd47ed13483642cf09e832ed0bc1b.png"; From c77b501b6c6d6fd3492a881686fca4c801311921 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 12:27:26 +0100 Subject: [PATCH 021/149] Fix message sent when user is trying give themselves !neutral karma --- src/Bot/Commands/User/Karma.cs | 2 +- src/Bot/Localization/Karma.Designer.cs | 9 +++++++++ src/Bot/Localization/Karma.de-ch.resx | 3 +++ src/Bot/Localization/Karma.resx | 3 +++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs index 3ba8650..61e381e 100644 --- a/src/Bot/Commands/User/Karma.cs +++ b/src/Bot/Commands/User/Karma.cs @@ -125,7 +125,7 @@ namespace Geekbot.Bot.Commands.User var actor = await GetUser(Context.User.Id); if (user.Id == Context.User.Id) { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); + await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnSame, Context.User.Username)); return; } diff --git a/src/Bot/Localization/Karma.Designer.cs b/src/Bot/Localization/Karma.Designer.cs index 71cab3b..041fec4 100644 --- a/src/Bot/Localization/Karma.Designer.cs +++ b/src/Bot/Localization/Karma.Designer.cs @@ -87,6 +87,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Sorry {0}, but you can't give yourself neutral karma. + /// + internal static string CannotChangeOwnSame { + get { + return ResourceManager.GetString("CannotChangeOwnSame", resourceCulture); + } + } + /// /// Looks up a localized string similar to Sorry {0}, but you can't give yourself karma. /// diff --git a/src/Bot/Localization/Karma.de-ch.resx b/src/Bot/Localization/Karma.de-ch.resx index 7b739b7..5805a27 100644 --- a/src/Bot/Localization/Karma.de-ch.resx +++ b/src/Bot/Localization/Karma.de-ch.resx @@ -38,4 +38,7 @@ Neutral Karma + + Sorry {0}, aber du chasch dr selber kei neutrals karma geh + \ No newline at end of file diff --git a/src/Bot/Localization/Karma.resx b/src/Bot/Localization/Karma.resx index 2ebea1d..a16e14a 100644 --- a/src/Bot/Localization/Karma.resx +++ b/src/Bot/Localization/Karma.resx @@ -45,4 +45,7 @@ Neutral Karma + + Sorry {0}, but you can't give yourself neutral karma + \ No newline at end of file From d1d57ba7144e497c9fcf7991060e7bfcee6d5d6c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Thu, 18 Mar 2021 23:53:56 +0100 Subject: [PATCH 022/149] Refactor karma commands --- src/Bot/Commands/User/Karma.cs | 190 --------------------- src/Bot/Commands/User/Karma/Karma.cs | 137 +++++++++++++++ src/Bot/Commands/User/Karma/KarmaChange.cs | 9 + 3 files changed, 146 insertions(+), 190 deletions(-) delete mode 100644 src/Bot/Commands/User/Karma.cs create mode 100644 src/Bot/Commands/User/Karma/Karma.cs create mode 100644 src/Bot/Commands/User/Karma/KarmaChange.cs diff --git a/src/Bot/Commands/User/Karma.cs b/src/Bot/Commands/User/Karma.cs deleted file mode 100644 index 61e381e..0000000 --- a/src/Bot/Commands/User/Karma.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.Bot.Utils; -using Geekbot.Core; -using Geekbot.Core.CommandPreconditions; -using Geekbot.Core.Database; -using Geekbot.Core.Database.Models; -using Geekbot.Core.ErrorHandling; -using Geekbot.Core.Extensions; -using Geekbot.Core.GuildSettingsManager; - -namespace Geekbot.Bot.Commands.User -{ - [DisableInDirectMessage] - public class Karma : GeekbotCommandBase - { - private readonly DatabaseContext _database; - - public Karma(DatabaseContext database, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) - { - _database = database; - } - - [Command("good", RunMode = RunMode.Async)] - [Summary("Increase Someones Karma")] - public async Task Good([Summary("@someone")] IUser user) - { - try - { - var actor = await GetUser(Context.User.Id); - if (user.Id == Context.User.Id) - { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnUp, Context.User.Username)); - } - else if (TimeoutFinished(actor.TimeOut)) - { - var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); - } - else - { - var target = await GetUser(user.Id); - target.Karma += 1; - SetUser(target); - - actor.TimeOut = DateTimeOffset.Now; - SetUser(actor); - - await _database.SaveChangesAsync(); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); - - eb.WithColor(new Color(138, 219, 146)); - eb.Title = Localization.Karma.Increased; - eb.AddInlineField(Localization.Karma.By, Context.User.Username); - eb.AddInlineField(Localization.Karma.Amount, "+1"); - eb.AddInlineField(Localization.Karma.Current, target.Karma); - await ReplyAsync("", false, eb.Build()); - } - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - - [Command("bad", RunMode = RunMode.Async)] - [Summary("Decrease Someones Karma")] - public async Task Bad([Summary("@someone")] IUser user) - { - try - { - var actor = await GetUser(Context.User.Id); - if (user.Id == Context.User.Id) - { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnDown, Context.User.Username)); - } - else if (TimeoutFinished(actor.TimeOut)) - { - var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); - } - else - { - var target = await GetUser(user.Id); - target.Karma -= 1; - SetUser(target); - - actor.TimeOut = DateTimeOffset.Now; - SetUser(actor); - - await _database.SaveChangesAsync(); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); - - eb.WithColor(new Color(138, 219, 146)); - eb.Title = Localization.Karma.Decreased; - eb.AddInlineField(Localization.Karma.By, Context.User.Username); - eb.AddInlineField(Localization.Karma.Amount, "-1"); - eb.AddInlineField(Localization.Karma.Current, target.Karma); - await ReplyAsync("", false, eb.Build()); - } - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - - [Command("neutral", RunMode = RunMode.Async)] - [Summary("Do nothing to someones karma")] - public async Task Neutral([Summary("@someone")] IUser user) - { - try - { - var actor = await GetUser(Context.User.Id); - if (user.Id == Context.User.Id) - { - await ReplyAsync(string.Format(Localization.Karma.CannotChangeOwnSame, Context.User.Username)); - return; - } - - if (TimeoutFinished(actor.TimeOut)) - { - var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); - await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); - return; - } - - var target = await GetUser(user.Id); - - var eb = new EmbedBuilder(); - eb.WithAuthor(new EmbedAuthorBuilder() - .WithIconUrl(user.GetAvatarUrl()) - .WithName(user.Username)); - - eb.WithColor(new Color(138, 219, 146)); - eb.Title = Localization.Karma.Neutral; - eb.AddInlineField(Localization.Karma.By, Context.User.Username); - eb.AddInlineField(Localization.Karma.Amount, "0"); - eb.AddInlineField(Localization.Karma.Current, target.Karma); - await ReplyAsync("", false, eb.Build()); - - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - - private bool TimeoutFinished(DateTimeOffset lastKarma) - { - return lastKarma.AddMinutes(3) > DateTimeOffset.Now; - } - - private async Task GetUser(ulong userId) - { - var user = _database.Karma.FirstOrDefault(u =>u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); - return user; - } - - private void SetUser(KarmaModel user) - { - _database.Karma.Update(user); - } - - private async Task CreateNewRow(ulong userId) - { - var user = new KarmaModel() - { - GuildId = Context.Guild.Id.AsLong(), - UserId = userId.AsLong(), - Karma = 0, - TimeOut = DateTimeOffset.MinValue - }; - var newUser = _database.Karma.Add(user).Entity; - await _database.SaveChangesAsync(); - return newUser; - } - } -} \ No newline at end of file diff --git a/src/Bot/Commands/User/Karma/Karma.cs b/src/Bot/Commands/User/Karma/Karma.cs new file mode 100644 index 0000000..a248422 --- /dev/null +++ b/src/Bot/Commands/User/Karma/Karma.cs @@ -0,0 +1,137 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Geekbot.Bot.Utils; +using Geekbot.Core; +using Geekbot.Core.CommandPreconditions; +using Geekbot.Core.Database; +using Geekbot.Core.Database.Models; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.Extensions; +using Geekbot.Core.GuildSettingsManager; + +namespace Geekbot.Bot.Commands.User.Karma +{ + [DisableInDirectMessage] + public class Karma : GeekbotCommandBase + { + private readonly DatabaseContext _database; + + public Karma(DatabaseContext database, IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) + { + _database = database; + } + + [Command("good", RunMode = RunMode.Async)] + [Summary("Increase Someones Karma")] + public async Task Good([Summary("@someone")] IUser user) + { + await ChangeKarma(user, KarmaChange.Up); + } + + [Command("bad", RunMode = RunMode.Async)] + [Summary("Decrease Someones Karma")] + public async Task Bad([Summary("@someone")] IUser user) + { + await ChangeKarma(user, KarmaChange.Down); + } + + [Command("neutral", RunMode = RunMode.Async)] + [Summary("Do nothing to someones Karma")] + public async Task Neutral([Summary("@someone")] IUser user) + { + await ChangeKarma(user, KarmaChange.Same); + } + + private async Task ChangeKarma(IUser user, KarmaChange change) + { + try + { + // Get the user + var actor = await GetUser(Context.User.Id); + + // Check if the user can change karma + if (user.Id == Context.User.Id) + { + var message = change switch + { + KarmaChange.Up => Localization.Karma.CannotChangeOwnUp, + KarmaChange.Same => Localization.Karma.CannotChangeOwnSame, + KarmaChange.Down => Localization.Karma.CannotChangeOwnDown, + _ => throw new ArgumentOutOfRangeException(nameof(change), change, null) + }; + await ReplyAsync(string.Format(message, Context.User.Username)); + return; + } + + if (actor.TimeOut.AddMinutes(3) > DateTimeOffset.Now) + { + var formatedWaitTime = DateLocalization.FormatDateTimeAsRemaining(actor.TimeOut.AddMinutes(3)); + await ReplyAsync(string.Format(Localization.Karma.WaitUntill, Context.User.Username, formatedWaitTime)); + return; + } + + // Get the values for the change direction + var (title, amount) = change switch + { + KarmaChange.Up => (Localization.Karma.Increased, 1), + KarmaChange.Same => (Localization.Karma.Neutral, 0), + KarmaChange.Down => (Localization.Karma.Decreased, -1), + _ => throw new ArgumentOutOfRangeException(nameof(change), change, null) + }; + + // Change it + var target = await GetUser(user.Id); + target.Karma += amount; + _database.Karma.Update(target); + + actor.TimeOut = DateTimeOffset.Now; + _database.Karma.Update(actor); + + await _database.SaveChangesAsync(); + + // Respond + var eb = new EmbedBuilder() + { + Author = new EmbedAuthorBuilder() + { + Name = user.Username, + IconUrl = user.GetAvatarUrl() + }, + Title = title, + Color = new Color(138, 219, 146) + }; + eb.AddInlineField(Localization.Karma.By, Context.User.Username); + eb.AddInlineField(Localization.Karma.Amount, amount.ToString()); + eb.AddInlineField(Localization.Karma.Current, target.Karma.ToString()); + await ReplyAsync("", false, eb.Build()); + } + catch (Exception e) + { + await ErrorHandler.HandleCommandException(e, Context); + } + } + + private async Task GetUser(ulong userId) + { + var user = _database.Karma.FirstOrDefault(u => u.GuildId.Equals(Context.Guild.Id.AsLong()) && u.UserId.Equals(userId.AsLong())) ?? await CreateNewRow(userId); + return user; + } + + private async Task CreateNewRow(ulong userId) + { + var user = new KarmaModel() + { + GuildId = Context.Guild.Id.AsLong(), + UserId = userId.AsLong(), + Karma = 0, + TimeOut = DateTimeOffset.MinValue + }; + var newUser = _database.Karma.Add(user).Entity; + await _database.SaveChangesAsync(); + return newUser; + } + } +} \ No newline at end of file diff --git a/src/Bot/Commands/User/Karma/KarmaChange.cs b/src/Bot/Commands/User/Karma/KarmaChange.cs new file mode 100644 index 0000000..01dafc1 --- /dev/null +++ b/src/Bot/Commands/User/Karma/KarmaChange.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Bot.Commands.User.Karma +{ + public enum KarmaChange + { + Up, + Same, + Down + } +} \ No newline at end of file From 1c643285874df4a92b633cf3dd2c63a2559084f5 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 19 Mar 2021 00:21:35 +0100 Subject: [PATCH 023/149] Upgrade to .net6 preview --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- src/Bot/Bot.csproj | 2 +- src/Bot/Commands/Utils/Quote/Quote.cs | 1 + src/Core/Core.csproj | 26 ++++++++++++++++---------- src/Web/Web.csproj | 2 +- tests/Tests.csproj | 6 +++--- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 20b1c84..967def1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ variables: Build: stage: build - image: mcr.microsoft.com/dotnet/sdk:5.0 + image: mcr.microsoft.com/dotnet/sdk:6.0 artifacts: expire_in: 1h paths: diff --git a/Dockerfile b/Dockerfile index 245e06b..39529ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 +FROM mcr.microsoft.com/dotnet/aspnet:6.0 COPY ./app /app/ diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 6c6f56f..86ab9a3 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -1,7 +1,7 @@ Exe - net5.0 + net6.0 win-x64;linux-x64 derp.ico $(VersionSuffix) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 6a94309..e79663c 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -14,6 +14,7 @@ using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; using Geekbot.Core.UserRepository; +using Microsoft.EntityFrameworkCore; namespace Geekbot.Bot.Commands.Utils.Quote { diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 0a4e989..474478e 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV @@ -14,18 +14,24 @@ - - - - - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + - + diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 5080a3d..744cadf 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/tests/Tests.csproj b/tests/Tests.csproj index 75a5f9c..6b9b84f 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -1,13 +1,13 @@  - net5.0 + net6.0 false NU1701 xUnit1026 - - + + From f25c9250ec109485e05f366f32fb18f5f9c2b309 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 19 Mar 2021 01:10:22 +0100 Subject: [PATCH 024/149] Switch to an alpine container and single file, self-contained deployments --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- src/Bot/Bot.csproj | 2 +- src/Core/Core.csproj | 1 + src/Web/Web.csproj | 1 + tests/Tests.csproj | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 967def1..f92ba14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-musl-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/Dockerfile b/Dockerfile index 39529ff..6e81339 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0 +FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine COPY ./app /app/ diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 86ab9a3..9312ac1 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -2,7 +2,7 @@ Exe net6.0 - win-x64;linux-x64 + win10-x64;linux-x64;linux-musl-x64 derp.ico $(VersionSuffix) Geekbot.Bot diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 474478e..17b4a26 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -2,6 +2,7 @@ net6.0 + win10-x64;linux-x64;linux-musl-x64 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 744cadf..d57c63c 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -2,6 +2,7 @@ net6.0 + win10-x64;linux-x64;linux-musl-x64 $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/tests/Tests.csproj b/tests/Tests.csproj index 6b9b84f..4823e0b 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -1,6 +1,7 @@  net6.0 + win10-x64;linux-x64;linux-musl-x64 false NU1701 xUnit1026 From 52fe5bdec11dc2327f4703e83bd1b6eb7ff2c646 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 20 Mar 2021 04:06:10 +0100 Subject: [PATCH 025/149] Switch back to a debian container, alpine is missing locale info --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f92ba14..b0135b6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix "$VERSION" -r linux-musl-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ Package: stage: docker diff --git a/Dockerfile b/Dockerfile index 6e81339..39529ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine +FROM mcr.microsoft.com/dotnet/aspnet:6.0 COPY ./app /app/ From 49870b6b91da13fdb7ec3b9b4a53696eafc2e058 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 20 Mar 2021 04:17:14 +0100 Subject: [PATCH 026/149] Stop using single-file deployments due to missing locale data --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b0135b6..967def1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ Build: script: - dotnet restore - dotnet test tests - - dotnet publish --version-suffix "$VERSION" -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./app ./src/Bot/ + - dotnet publish --version-suffix "$VERSION" -r linux-x64 -c Release -o ./app ./src/Bot/ Package: stage: docker From 41e0a9f8d72c24766019a4e7844337cab62ce281 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 26 Mar 2021 00:11:15 +0100 Subject: [PATCH 027/149] Add !evergiven to see if the ship is still stuck in the suez canal --- src/Bot/Bot.csproj | 9 +++ src/Bot/Commands/Utils/Evergiven.cs | 50 +++++++++++++ src/Bot/Localization/Evergiven.Designer.cs | 81 ++++++++++++++++++++++ src/Bot/Localization/Evergiven.de-ch.resx | 20 ++++++ src/Bot/Localization/Evergiven.resx | 27 ++++++++ src/Bot/Utils/DateLocalization.cs | 6 +- 6 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/Bot/Commands/Utils/Evergiven.cs create mode 100644 src/Bot/Localization/Evergiven.Designer.cs create mode 100644 src/Bot/Localization/Evergiven.de-ch.resx create mode 100644 src/Bot/Localization/Evergiven.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 9312ac1..2b1cdae 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -88,6 +88,10 @@ ResXFileCodeGenerator Corona.Designer.cs + + ResXFileCodeGenerator + Evergiven.Designer.cs + @@ -153,5 +157,10 @@ True Corona.resx + + True + True + Evergiven.resx + diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs new file mode 100644 index 0000000..663fb0a --- /dev/null +++ b/src/Bot/Commands/Utils/Evergiven.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Discord.Commands; +using Geekbot.Bot.Utils; +using Geekbot.Core; +using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GuildSettingsManager; +using HtmlAgilityPack; + +namespace Geekbot.Bot.Commands.Utils +{ + public class Evergiven : GeekbotCommandBase + { + public Evergiven(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) + { + } + + [Command("evergiven", RunMode = RunMode.Async)] + [Summary("Check if the evergiven ship is still stuck in the suez canal")] + public async Task GetStatus() + { + try + { + var httpClient = HttpAbstractions.CreateDefaultClient(); + var response = await httpClient.GetAsync("https://istheshipstillstuck.com/"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + + var doc = new HtmlDocument(); + doc.LoadHtml(stringResponse); + var yesOrNoNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); + + if (yesOrNoNode?.InnerHtml == "Yes.") + { + var stuckSince = DateTime.Now - new DateTime(2021, 03, 23, 10, 39, 0); + var formatted = DateLocalization.FormatDateTimeAsRemaining(stuckSince); + await ReplyAsync(string.Format(Localization.Evergiven.StillStuck, formatted));// $"Ever Given is **still stuck** in the suez canal! It has been stuck for {formatted}"); + return; + } + + await ReplyAsync(Localization.Evergiven.NotStuckAnymore); + } + catch (Exception e) + { + await ErrorHandler.HandleCommandException(e, Context); + } + } + } +} \ No newline at end of file diff --git a/src/Bot/Localization/Evergiven.Designer.cs b/src/Bot/Localization/Evergiven.Designer.cs new file mode 100644 index 0000000..7f66fed --- /dev/null +++ b/src/Bot/Localization/Evergiven.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Evergiven { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Evergiven() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Evergiven", typeof(Evergiven).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Seems like Ever Given has moved on, check https://istheshipstillstuck.com/. + /// + internal static string NotStuckAnymore { + get { + return ResourceManager.GetString("NotStuckAnymore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ever Given is **still stuck** in the suez canal! It has been stuck for {0}. + /// + internal static string StillStuck { + get { + return ResourceManager.GetString("StillStuck", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/Evergiven.de-ch.resx b/src/Bot/Localization/Evergiven.de-ch.resx new file mode 100644 index 0000000..b1563fc --- /dev/null +++ b/src/Bot/Localization/Evergiven.de-ch.resx @@ -0,0 +1,20 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Ever Given **steckt immer no fescht** im Suez Kanal! Es isch derte siit {0} + + + Es gseht danach us das Ever Given wiiter gange isch, gsehne https://istheshipstillstuck.com/ + + \ No newline at end of file diff --git a/src/Bot/Localization/Evergiven.resx b/src/Bot/Localization/Evergiven.resx new file mode 100644 index 0000000..36fb012 --- /dev/null +++ b/src/Bot/Localization/Evergiven.resx @@ -0,0 +1,27 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Seems like Ever Given has moved on, check https://istheshipstillstuck.com/ + + + Ever Given is **still stuck** in the suez canal! It has been stuck for {0} + + \ No newline at end of file diff --git a/src/Bot/Utils/DateLocalization.cs b/src/Bot/Utils/DateLocalization.cs index eea40fb..ee52d73 100644 --- a/src/Bot/Utils/DateLocalization.cs +++ b/src/Bot/Utils/DateLocalization.cs @@ -7,7 +7,11 @@ namespace Geekbot.Bot.Utils { public static string FormatDateTimeAsRemaining(DateTimeOffset dateTime) { - var remaining = dateTime - DateTimeOffset.Now; + return FormatDateTimeAsRemaining(dateTime - DateTimeOffset.Now); + } + + public static string FormatDateTimeAsRemaining(TimeSpan remaining) + { const string formattable = "{0} {1}"; var sb = new StringBuilder(); From 9ad39058ac71a2a1e19091dcc4d910d8fa92d70e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 29 Mar 2021 11:39:50 +0200 Subject: [PATCH 028/149] Update the !evergiven command to directly reflect what istheshipstillstuck.com says --- src/Bot/Bot.csproj | 9 --- src/Bot/Commands/Utils/Evergiven.cs | 28 ++++++-- src/Bot/Localization/Evergiven.Designer.cs | 81 ---------------------- src/Bot/Localization/Evergiven.de-ch.resx | 20 ------ src/Bot/Localization/Evergiven.resx | 27 -------- 5 files changed, 21 insertions(+), 144 deletions(-) delete mode 100644 src/Bot/Localization/Evergiven.Designer.cs delete mode 100644 src/Bot/Localization/Evergiven.de-ch.resx delete mode 100644 src/Bot/Localization/Evergiven.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 2b1cdae..9312ac1 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -88,10 +88,6 @@ ResXFileCodeGenerator Corona.Designer.cs - - ResXFileCodeGenerator - Evergiven.Designer.cs - @@ -157,10 +153,5 @@ True Corona.resx - - True - True - Evergiven.resx - diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs index 663fb0a..1115eaf 100644 --- a/src/Bot/Commands/Utils/Evergiven.cs +++ b/src/Bot/Commands/Utils/Evergiven.cs @@ -1,8 +1,9 @@ using System; using System.Linq; +using System.Text; using System.Threading.Tasks; +using System.Web; using Discord.Commands; -using Geekbot.Bot.Utils; using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GuildSettingsManager; @@ -29,17 +30,30 @@ namespace Geekbot.Bot.Commands.Utils var doc = new HtmlDocument(); doc.LoadHtml(stringResponse); - var yesOrNoNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); + var statusNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); - if (yesOrNoNode?.InnerHtml == "Yes.") + if (statusNode == null) { - var stuckSince = DateTime.Now - new DateTime(2021, 03, 23, 10, 39, 0); - var formatted = DateLocalization.FormatDateTimeAsRemaining(stuckSince); - await ReplyAsync(string.Format(Localization.Evergiven.StillStuck, formatted));// $"Ever Given is **still stuck** in the suez canal! It has been stuck for {formatted}"); + await ReplyAsync("Maybe, check "); return; } - await ReplyAsync(Localization.Evergiven.NotStuckAnymore); + var sb = new StringBuilder(); + + sb.Append($"Is that ship still stuck? {statusNode.InnerHtml}"); + if (statusNode.Attributes.Contains("href")) + { + sb.Append($" {statusNode.Attributes["href"].Value}"); + } + + var stuckTimer = doc.DocumentNode.SelectNodes("//p")?.First(node => node.Attributes.First(attr => attr.Name == "style")?.Value == "text-align:center"); + if (stuckTimer != null) + { + sb.AppendLine(); + sb.AppendLine(HttpUtility.HtmlDecode(stuckTimer.InnerText)); + } + + await ReplyAsync(sb.ToString()); } catch (Exception e) { diff --git a/src/Bot/Localization/Evergiven.Designer.cs b/src/Bot/Localization/Evergiven.Designer.cs deleted file mode 100644 index 7f66fed..0000000 --- a/src/Bot/Localization/Evergiven.Designer.cs +++ /dev/null @@ -1,81 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Geekbot.Bot.Localization { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Evergiven { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Evergiven() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.Evergiven", typeof(Evergiven).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Seems like Ever Given has moved on, check https://istheshipstillstuck.com/. - /// - internal static string NotStuckAnymore { - get { - return ResourceManager.GetString("NotStuckAnymore", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Ever Given is **still stuck** in the suez canal! It has been stuck for {0}. - /// - internal static string StillStuck { - get { - return ResourceManager.GetString("StillStuck", resourceCulture); - } - } - } -} diff --git a/src/Bot/Localization/Evergiven.de-ch.resx b/src/Bot/Localization/Evergiven.de-ch.resx deleted file mode 100644 index b1563fc..0000000 --- a/src/Bot/Localization/Evergiven.de-ch.resx +++ /dev/null @@ -1,20 +0,0 @@ - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Ever Given **steckt immer no fescht** im Suez Kanal! Es isch derte siit {0} - - - Es gseht danach us das Ever Given wiiter gange isch, gsehne https://istheshipstillstuck.com/ - - \ No newline at end of file diff --git a/src/Bot/Localization/Evergiven.resx b/src/Bot/Localization/Evergiven.resx deleted file mode 100644 index 36fb012..0000000 --- a/src/Bot/Localization/Evergiven.resx +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Seems like Ever Given has moved on, check https://istheshipstillstuck.com/ - - - Ever Given is **still stuck** in the suez canal! It has been stuck for {0} - - \ No newline at end of file From 5b99ee951bc6ea45a09347f5840154b7a92f0258 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 29 Mar 2021 17:45:43 +0200 Subject: [PATCH 029/149] Evergiven is free once again --- src/Bot/Commands/Utils/Evergiven.cs | 31 ++++------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs index 1115eaf..c7c4335 100644 --- a/src/Bot/Commands/Utils/Evergiven.cs +++ b/src/Bot/Commands/Utils/Evergiven.cs @@ -23,35 +23,12 @@ namespace Geekbot.Bot.Commands.Utils { try { - var httpClient = HttpAbstractions.CreateDefaultClient(); - var response = await httpClient.GetAsync("https://istheshipstillstuck.com/"); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - - var doc = new HtmlDocument(); - doc.LoadHtml(stringResponse); - var statusNode = doc.DocumentNode.SelectNodes("//a").FirstOrDefault(); - - if (statusNode == null) - { - await ReplyAsync("Maybe, check "); - return; - } - var sb = new StringBuilder(); - sb.Append($"Is that ship still stuck? {statusNode.InnerHtml}"); - if (statusNode.Attributes.Contains("href")) - { - sb.Append($" {statusNode.Attributes["href"].Value}"); - } - - var stuckTimer = doc.DocumentNode.SelectNodes("//p")?.First(node => node.Attributes.First(attr => attr.Name == "style")?.Value == "text-align:center"); - if (stuckTimer != null) - { - sb.AppendLine(); - sb.AppendLine(HttpUtility.HtmlDecode(stuckTimer.InnerText)); - } + sb.AppendLine("Is that ship still stuck?"); + sb.AppendLine("**No!**"); + sb.AppendLine("It was stuck for 6 days, 3 hours and 38 minutes. It (probably) cost \"us\" $59 billion."); + sb.AppendLine("You can follow it here: "); await ReplyAsync(sb.ToString()); } From 153ce3dca4b408a32dbfbdd12bfbcfd8c02acf27 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 29 Mar 2021 19:02:31 +0200 Subject: [PATCH 030/149] Translate !8ball --- src/Bot/Bot.csproj | 9 + src/Bot/Commands/Randomness/EightBall.cs | 41 +--- src/Bot/Localization/EightBall.Designer.cs | 243 +++++++++++++++++++++ src/Bot/Localization/EightBall.de-ch.resx | 94 ++++++++ src/Bot/Localization/EightBall.resx | 200 +++++++++++++++++ 5 files changed, 558 insertions(+), 29 deletions(-) create mode 100644 src/Bot/Localization/EightBall.Designer.cs create mode 100644 src/Bot/Localization/EightBall.de-ch.resx create mode 100644 src/Bot/Localization/EightBall.resx diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index 9312ac1..cd04530 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -88,6 +88,10 @@ ResXFileCodeGenerator Corona.Designer.cs + + ResXFileCodeGenerator + EightBall.Designer.cs + @@ -153,5 +157,10 @@ True Corona.resx + + True + True + EightBall.resx + diff --git a/src/Bot/Commands/Randomness/EightBall.cs b/src/Bot/Commands/Randomness/EightBall.cs index e1a3a71..207afe3 100644 --- a/src/Bot/Commands/Randomness/EightBall.cs +++ b/src/Bot/Commands/Randomness/EightBall.cs @@ -1,18 +1,18 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; +using Geekbot.Core.GuildSettingsManager; namespace Geekbot.Bot.Commands.Randomness { - public class EightBall : ModuleBase + public class EightBall : GeekbotCommandBase { - private readonly IErrorHandler _errorHandler; - - public EightBall(IErrorHandler errorHandler) + public EightBall(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) { - _errorHandler = errorHandler; } [Command("8ball", RunMode = RunMode.Async)] @@ -21,36 +21,19 @@ namespace Geekbot.Bot.Commands.Randomness { try { - var replies = new List + var enumerator = Localization.EightBall.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true).GetEnumerator(); + var replies = new List(); + while (enumerator.MoveNext()) { - "It is certain", - "It is decidedly so", - "Without a doubt", - "Yes, definitely", - "You may rely on it", - "As I see it, yes", - "Most likely", - "Outlook good", - "Yes", - "Signs point to yes", - "Reply hazy try again", - "Ask again later", - "Better not tell you now", - "Cannot predict now", - "Concentrate and ask again", - "Don't count on it", - "My reply is no", - "My sources say no", - "Outlook not so good", - "Very doubtful" - }; - + replies.Add(enumerator.Value?.ToString()); + } + var answer = new Random().Next(replies.Count); await ReplyAsync(replies[answer]); } catch (Exception e) { - await _errorHandler.HandleCommandException(e, Context); + await ErrorHandler.HandleCommandException(e, Context); } } } diff --git a/src/Bot/Localization/EightBall.Designer.cs b/src/Bot/Localization/EightBall.Designer.cs new file mode 100644 index 0000000..8214825 --- /dev/null +++ b/src/Bot/Localization/EightBall.Designer.cs @@ -0,0 +1,243 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Geekbot.Bot.Localization { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class EightBall { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EightBall() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geekbot.Bot.Localization.EightBall", typeof(EightBall).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to As I see it, yes. + /// + internal static string AsISeeItYes { + get { + return ResourceManager.GetString("AsISeeItYes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ask again later. + /// + internal static string AskAgainLater { + get { + return ResourceManager.GetString("AskAgainLater", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Better not tell you now. + /// + internal static string BetterNotTellYouNow { + get { + return ResourceManager.GetString("BetterNotTellYouNow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot predict now. + /// + internal static string CannotPredictNow { + get { + return ResourceManager.GetString("CannotPredictNow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Concentrate and ask again. + /// + internal static string ConcentrateAndAskAgain { + get { + return ResourceManager.GetString("ConcentrateAndAskAgain", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Don't count on it. + /// + internal static string DontCountOnIt { + get { + return ResourceManager.GetString("DontCountOnIt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is certain. + /// + internal static string ItIsCertain { + get { + return ResourceManager.GetString("ItIsCertain", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It is decidedly so. + /// + internal static string ItIsDecidedlySo { + get { + return ResourceManager.GetString("ItIsDecidedlySo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Most likely. + /// + internal static string MostLikely { + get { + return ResourceManager.GetString("MostLikely", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My reply is no. + /// + internal static string MyReplyIsNo { + get { + return ResourceManager.GetString("MyReplyIsNo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to My sources say no. + /// + internal static string MySourcesSayNo { + get { + return ResourceManager.GetString("MySourcesSayNo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Outlook good. + /// + internal static string OutlookGood { + get { + return ResourceManager.GetString("OutlookGood", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Outlook not so good. + /// + internal static string OutlookNotSoGood { + get { + return ResourceManager.GetString("OutlookNotSoGood", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reply hazy try again. + /// + internal static string ReplyHazyTryAgain { + get { + return ResourceManager.GetString("ReplyHazyTryAgain", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Signs point to yes. + /// + internal static string SignsPointToYes { + get { + return ResourceManager.GetString("SignsPointToYes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Very doubtful. + /// + internal static string VeryDoubtful { + get { + return ResourceManager.GetString("VeryDoubtful", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Without a doubt. + /// + internal static string WithoutADoubt { + get { + return ResourceManager.GetString("WithoutADoubt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + internal static string Yes { + get { + return ResourceManager.GetString("Yes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes, definitely. + /// + internal static string YesDefinitely { + get { + return ResourceManager.GetString("YesDefinitely", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You may rely on it. + /// + internal static string YouMayRelyOnIt { + get { + return ResourceManager.GetString("YouMayRelyOnIt", resourceCulture); + } + } + } +} diff --git a/src/Bot/Localization/EightBall.de-ch.resx b/src/Bot/Localization/EightBall.de-ch.resx new file mode 100644 index 0000000..89d7a60 --- /dev/null +++ b/src/Bot/Localization/EightBall.de-ch.resx @@ -0,0 +1,94 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Es isch sicher + + + + So isch es entschiede worde + + + + Ohni zwifel + + + + Ja, absolut + + + + Chasch davo usgoh + + + + Wie ich es gsehn, ja + + + + Sehr waschinli + + + + Ussicht isch guet + + + + Ja + + + + Ahzeiche zeigend uf ja + + + + Antwort isch verschwumme, versuechs nomol + + + + Frög spöter nomol + + + + Segs dir jetzt besser nid + + + + Im mommnet chani das nid vorussege + + + + Konzentrier di und frog nomol + + + + Zähl nid druf + + + + Mini antwort isch nei + + + + Mini quellene seged nei + + + + Ussicht isch ned so guet + + + + Sehr froglich + + + \ No newline at end of file diff --git a/src/Bot/Localization/EightBall.resx b/src/Bot/Localization/EightBall.resx new file mode 100644 index 0000000..6eba369 --- /dev/null +++ b/src/Bot/Localization/EightBall.resx @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + It is certain + + + + It is decidedly so + + + + Without a doubt + + + + Yes, definitely + + + + You may rely on it + + + + As I see it, yes + + + + Most likely + + + + Outlook good + + + + Yes + + + + Signs point to yes + + + + Reply hazy try again + + + + Ask again later + + + + Better not tell you now + + + + Cannot predict now + + + + Concentrate and ask again + + + + Don't count on it + + + + My reply is no + + + + My sources say no + + + + Outlook not so good + + + + Very doubtful + + + \ No newline at end of file From 8bd8efa66a70f9769ee53b2d574ba03879b9a8cb Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 7 Apr 2021 22:49:13 +0200 Subject: [PATCH 031/149] Remove the !evergiven command --- src/Bot/Commands/Utils/Evergiven.cs | 41 ----------------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/Bot/Commands/Utils/Evergiven.cs diff --git a/src/Bot/Commands/Utils/Evergiven.cs b/src/Bot/Commands/Utils/Evergiven.cs deleted file mode 100644 index c7c4335..0000000 --- a/src/Bot/Commands/Utils/Evergiven.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Discord.Commands; -using Geekbot.Core; -using Geekbot.Core.ErrorHandling; -using Geekbot.Core.GuildSettingsManager; -using HtmlAgilityPack; - -namespace Geekbot.Bot.Commands.Utils -{ - public class Evergiven : GeekbotCommandBase - { - public Evergiven(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) : base(errorHandler, guildSettingsManager) - { - } - - [Command("evergiven", RunMode = RunMode.Async)] - [Summary("Check if the evergiven ship is still stuck in the suez canal")] - public async Task GetStatus() - { - try - { - var sb = new StringBuilder(); - - sb.AppendLine("Is that ship still stuck?"); - sb.AppendLine("**No!**"); - sb.AppendLine("It was stuck for 6 days, 3 hours and 38 minutes. It (probably) cost \"us\" $59 billion."); - sb.AppendLine("You can follow it here: "); - - await ReplyAsync(sb.ToString()); - } - catch (Exception e) - { - await ErrorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From 5a50ba58206e4fcfd85a2f55af909be9d7291cdb Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Tue, 20 Apr 2021 22:25:33 +0200 Subject: [PATCH 032/149] Add total quotes of a user to !stats --- src/Bot/Commands/User/Stats.cs | 7 +++++-- src/Bot/Localization/Stats.Designer.cs | 18 ++++++++++++++++++ src/Bot/Localization/Stats.de-ch.resx | 6 ++++++ src/Bot/Localization/Stats.resx | 6 ++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/User/Stats.cs b/src/Bot/Commands/User/Stats.cs index a2a54a2..aad2657 100644 --- a/src/Bot/Commands/User/Stats.cs +++ b/src/Bot/Commands/User/Stats.cs @@ -54,6 +54,8 @@ namespace Geekbot.Bot.Commands.User ?.FirstOrDefault(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())) ?.Cookies ?? 0; + var quotes = _database.Quotes.Count(e => e.GuildId.Equals(Context.Guild.Id.AsLong()) && e.UserId.Equals(userInfo.Id.AsLong())); + var eb = new EmbedBuilder(); eb.WithAuthor(new EmbedAuthorBuilder() .WithIconUrl(userInfo.GetAvatarUrl()) @@ -68,9 +70,9 @@ namespace Geekbot.Bot.Commands.User e.UserId.Equals(userInfo.Id.AsLong())); eb.AddInlineField(Localization.Stats.OnDiscordSince, - $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} days)") + $"{createdAt.Day}.{createdAt.Month}.{createdAt.Year} ({age} {Localization.Stats.Days})") .AddInlineField(Localization.Stats.JoinedServer, - $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} days)") + $"{joinedAt.Day}.{joinedAt.Month}.{joinedAt.Year} ({joinedDayAgo} {Localization.Stats.Days})") .AddInlineField(Localization.Stats.Karma, karma?.Karma ?? 0) .AddInlineField(Localization.Stats.Level, level) .AddInlineField(Localization.Stats.MessagesSent, messages) @@ -78,6 +80,7 @@ namespace Geekbot.Bot.Commands.User if (correctRolls != null) eb.AddInlineField(Localization.Stats.GuessedRolls, correctRolls.Rolls); if (cookies > 0) eb.AddInlineField(Localization.Stats.Cookies, cookies); + if (quotes > 0) eb.AddInlineField(Localization.Stats.Quotes, quotes); await ReplyAsync("", false, eb.Build()); } diff --git a/src/Bot/Localization/Stats.Designer.cs b/src/Bot/Localization/Stats.Designer.cs index d05f937..6f650e2 100644 --- a/src/Bot/Localization/Stats.Designer.cs +++ b/src/Bot/Localization/Stats.Designer.cs @@ -69,6 +69,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Days. + /// + internal static string Days { + get { + return ResourceManager.GetString("Days", resourceCulture); + } + } + /// /// Looks up a localized string similar to Guessed Rolls. /// @@ -123,6 +132,15 @@ namespace Geekbot.Bot.Localization { } } + /// + /// Looks up a localized string similar to Quotes. + /// + internal static string Quotes { + get { + return ResourceManager.GetString("Quotes", resourceCulture); + } + } + /// /// Looks up a localized string similar to Server Total. /// diff --git a/src/Bot/Localization/Stats.de-ch.resx b/src/Bot/Localization/Stats.de-ch.resx index ab44a2e..0af0477 100644 --- a/src/Bot/Localization/Stats.de-ch.resx +++ b/src/Bot/Localization/Stats.de-ch.resx @@ -35,4 +35,10 @@ Guetzli + + Täg + + + Quotes + \ No newline at end of file diff --git a/src/Bot/Localization/Stats.resx b/src/Bot/Localization/Stats.resx index 3b8303a..6eb3a92 100644 --- a/src/Bot/Localization/Stats.resx +++ b/src/Bot/Localization/Stats.resx @@ -42,4 +42,10 @@ Cookies + + Days + + + Quotes + \ No newline at end of file From 611b179d628aa56db4f5503c004814f1dde4bb3e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 9 Jul 2021 20:21:17 +0200 Subject: [PATCH 033/149] Add a piece of low fat mozzarella to the !slap command --- src/Bot/Commands/Randomness/Slap.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs index b512e73..7a858b1 100644 --- a/src/Bot/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -76,7 +76,8 @@ namespace Geekbot.Bot.Commands.Randomness "teapot", "candle", "dictionary", - "powerless banhammer" + "powerless banhammer", + "piece of low fat mozzarella" }; await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); @@ -127,4 +128,4 @@ namespace Geekbot.Bot.Commands.Randomness e.UserId.Equals(userId.AsLong())); } } -} \ No newline at end of file +} From 8fcc6291065e9becd2e5f9ada1955dba7e83ad99 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 9 Jul 2021 20:39:04 +0200 Subject: [PATCH 034/149] Disable MSBuildEnableWorkloadResolver in gitlab ci --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 967def1..fc1cd0e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,8 @@ stages: variables: VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + # ToDo: Remove when .net6 is released + MSBuildEnableWorkloadResolver: false Build: stage: build From 86068ecc443dd18d709dcf1f52d6d291ce06c500 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 9 Jul 2021 20:48:42 +0200 Subject: [PATCH 035/149] Disable self contained publishing for the test, web and bot dlls --- .gitlab-ci.yml | 2 +- src/Bot/Bot.csproj | 1 + src/Web/Web.csproj | 1 + tests/Tests.csproj | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fc1cd0e..7da242b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ variables: VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG # ToDo: Remove when .net6 is released - MSBuildEnableWorkloadResolver: false + MSBuildEnableWorkloadResolver: 'false' Build: stage: build diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index cd04530..ff10a94 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -3,6 +3,7 @@ Exe net6.0 win10-x64;linux-x64;linux-musl-x64 + false derp.ico $(VersionSuffix) Geekbot.Bot diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index d57c63c..a9ffcc4 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -3,6 +3,7 @@ net6.0 win10-x64;linux-x64;linux-musl-x64 + false $(VersionSuffix) $(VersionSuffix) 0.0.0-DEV diff --git a/tests/Tests.csproj b/tests/Tests.csproj index 4823e0b..786164e 100644 --- a/tests/Tests.csproj +++ b/tests/Tests.csproj @@ -2,6 +2,7 @@ net6.0 win10-x64;linux-x64;linux-musl-x64 + false false NU1701 xUnit1026 From 8d037c786ea5b916add8b1219e1d3e2836ed91f6 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 10 Jul 2021 00:41:22 +0200 Subject: [PATCH 036/149] Reenable MSBuildEnableWorkloadResolver --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7da242b..967def1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,8 +7,6 @@ stages: variables: VERSION: 4.3.0-V$CI_COMMIT_SHORT_SHA IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG - # ToDo: Remove when .net6 is released - MSBuildEnableWorkloadResolver: 'false' Build: stage: build From 90668b6aac1bb728eba9d1a4b924743e3503a1d0 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sat, 10 Jul 2021 00:49:03 +0200 Subject: [PATCH 037/149] Add padding at the end of things for the !slap command --- src/Bot/Commands/Randomness/Slap.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs index 7a858b1..f5d21b8 100644 --- a/src/Bot/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -77,10 +77,13 @@ namespace Geekbot.Bot.Commands.Randomness "candle", "dictionary", "powerless banhammer", - "piece of low fat mozzarella" + "piece of low fat mozzarella", + // For some reason it never picks the last one + // Adding this workaround, because i'm to lazy to actually fix it at the time of writing this + "padding" }; - await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(things.Count - 1)]}"); + await ReplyAsync($"{Context.User.Username} slapped {user.Username} with a {things[new Random().Next(0, things.Count - 1)]}"); await UpdateRecieved(user.Id); await UpdateGiven(Context.User.Id); From 9a55d8447fef227f5b69790125651767bd92fb82 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 11 Aug 2021 17:58:06 +0200 Subject: [PATCH 038/149] Upgrade discord.net to version 2.4.0 --- src/Core/Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 17b4a26..629233a 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -14,7 +14,7 @@ - + all From f22956368b3a165a3cbe9135ff829cffa6ba8187 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 11 Aug 2021 17:58:45 +0200 Subject: [PATCH 039/149] Remove !gdq --- src/Bot/Commands/Randomness/Gdq.cs | 36 ------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 src/Bot/Commands/Randomness/Gdq.cs diff --git a/src/Bot/Commands/Randomness/Gdq.cs b/src/Bot/Commands/Randomness/Gdq.cs deleted file mode 100644 index c6d9fa8..0000000 --- a/src/Bot/Commands/Randomness/Gdq.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; -using Discord.Commands; -using Geekbot.Core.ErrorHandling; - -namespace Geekbot.Bot.Commands.Randomness -{ - public class Gdq : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Gdq(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("gdq", RunMode = RunMode.Async)] - [Summary("Get a quote from the GDQ donation generator.")] - public async Task GetQuote() - { - try - { - using var client = new WebClient(); - var url = new Uri("http://taskinoz.com/gdq/api/"); - var response = client.DownloadString(url); - - await ReplyAsync(response); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From 18ece35ffe88aaa8e5aa0204b499d72f5615ece4 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Wed, 11 Aug 2021 23:08:00 +0200 Subject: [PATCH 040/149] Remove System.Timers.Timer ambiguity for .net6-preview7 --- src/Bot/Handlers/StatsHandler.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Bot/Handlers/StatsHandler.cs b/src/Bot/Handlers/StatsHandler.cs index d1384cd..b089515 100644 --- a/src/Bot/Handlers/StatsHandler.cs +++ b/src/Bot/Handlers/StatsHandler.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; -using System.Timers; using Discord.WebSocket; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; @@ -24,7 +22,7 @@ namespace Geekbot.Bot.Handlers _database = database; _season = SeasonsUtils.GetCurrentSeason(); - var timer = new Timer() + var timer = new System.Timers.Timer() { Enabled = true, AutoReset = true, From e712403dd96d824688cc0077b5394397b5b233f2 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 11:21:42 +0200 Subject: [PATCH 041/149] Upgrade Sumologic, jikan and HtmlAgilityPack --- src/Bot/Bot.csproj | 4 ++-- src/Core/Core.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index ff10a94..c64eecb 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 629233a..463c4e9 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -34,7 +34,7 @@ - + From f19ddb30b285352282722bc868f67827e029bddd Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 11:23:20 +0200 Subject: [PATCH 042/149] Replace RNGCryptoServiceProvider with System.Security.Cryptography.RandomNumberGenerator --- src/Core/RandomNumberGenerator/RandomNumberGenerator.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs index db990a7..1b7178b 100644 --- a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs @@ -1,5 +1,4 @@ using System; -using System.Security.Cryptography; using Anemonis.RandomOrg; using Geekbot.Core.GlobalSettings; @@ -7,13 +6,13 @@ namespace Geekbot.Core.RandomNumberGenerator { public class RandomNumberGenerator : IRandomNumberGenerator { - private readonly RNGCryptoServiceProvider csp; + private readonly System.Security.Cryptography.RandomNumberGenerator rng; private readonly bool _canUseRandomOrg; private readonly RandomOrgClient _randomOrgClient; public RandomNumberGenerator(IGlobalSettings globalSettings) { - csp = new RNGCryptoServiceProvider(); + rng = System.Security.Cryptography.RandomNumberGenerator.Create(); var randomOrgApiKey = globalSettings.GetKey("RandomOrgApiKey"); if (!string.IsNullOrEmpty(randomOrgApiKey)) @@ -32,7 +31,7 @@ namespace Geekbot.Core.RandomNumberGenerator if (minValue >= maxInclusiveValue) { - throw new ArgumentOutOfRangeException("minValue must be lower than maxExclusiveValue"); + throw new ArgumentOutOfRangeException("minValue", "must be lower than maxExclusiveValue"); } if (_canUseRandomOrg) @@ -84,7 +83,7 @@ namespace Geekbot.Core.RandomNumberGenerator private byte[] GenerateRandomBytes(int bytesNumber) { var buffer = new byte[bytesNumber]; - csp.GetBytes(buffer); + rng.GetBytes(buffer); return buffer; } } From 989057a0b06c034658bf83d73ea16a289d480803 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 12:22:26 +0200 Subject: [PATCH 043/149] Migrate from RavenSharp to the SentrySDK --- src/Bot/Bot.csproj | 2 +- src/Core/Core.csproj | 2 +- src/Core/ErrorHandling/ErrorHandler.cs | 38 +++++++++++++------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Bot/Bot.csproj b/src/Bot/Bot.csproj index c64eecb..998456c 100644 --- a/src/Bot/Bot.csproj +++ b/src/Bot/Bot.csproj @@ -29,7 +29,7 @@ - + diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 463c4e9..dfce63b 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/Core/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs index 60d97e9..a5ccc8e 100644 --- a/src/Core/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -1,9 +1,9 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; using Geekbot.Core.Logger; -using SharpRaven; -using SharpRaven.Data; +using Sentry; using Exception = System.Exception; namespace Geekbot.Core.ErrorHandling @@ -12,7 +12,6 @@ namespace Geekbot.Core.ErrorHandling { private readonly IGeekbotLogger _logger; private readonly Func _getDefaultErrorText; - private readonly IRavenClient _raven; private readonly bool _errorsInChat; public ErrorHandler(IGeekbotLogger logger, RunParameters runParameters, Func getDefaultErrorText) @@ -22,15 +21,15 @@ namespace Geekbot.Core.ErrorHandling _errorsInChat = runParameters.ExposeErrors; var sentryDsn = runParameters.SentryEndpoint; - if (!string.IsNullOrEmpty(sentryDsn)) + if (string.IsNullOrEmpty(sentryDsn)) return; + + SentrySdk.Init(o => { - _raven = new RavenClient(sentryDsn) { Release = Constants.BotVersion(), Environment = "Production" }; - _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); - } - else - { - _raven = null; - } + o.Dsn = sentryDsn; + o.Release = Constants.BotVersion(); + o.Environment = "Production"; + }); + _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") @@ -83,18 +82,19 @@ namespace Geekbot.Core.ErrorHandling private void ReportExternal(Exception e, MessageDto errorObj) { - if (_raven == null) return; + if (!SentrySdk.IsEnabled) return; + var sentryEvent = new SentryEvent(e) { - Tags = - { - ["discord_server"] = errorObj.Guild.Name, - ["discord_user"] = errorObj.User.Name - }, Message = errorObj.Message.Content, - Extra = errorObj }; - _raven.Capture(sentryEvent); + sentryEvent.SetTag("discord_server", errorObj.Guild.Name); + sentryEvent.SetExtra("Channel", errorObj.Channel); + sentryEvent.SetExtra("Guild", errorObj.Guild); + sentryEvent.SetExtra("Message", errorObj.Message); + sentryEvent.SetExtra("User", errorObj.User); + + SentrySdk.CaptureEvent(sentryEvent); } } } \ No newline at end of file From 5c507b026cc3f8bb94bc4cb8f92d77595c609a5c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:03:35 +0200 Subject: [PATCH 044/149] Remove random.org integration --- src/Bot/Program.cs | 2 +- src/Core/Core.csproj | 1 - .../RandomNumberGenerator.cs | 34 +------------------ tests/Core/DiceParser/DiceParser.test.cs | 2 +- tests/Core/DiceParser/SingleDie.test.cs | 4 +-- 5 files changed, 5 insertions(+), 38 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index dee6ec3..3429fbc 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -162,7 +162,7 @@ namespace Geekbot.Bot var emojiConverter = new EmojiConverter(); var mtgManaConverter = new MtgManaConverter(); var wikipediaClient = new WikipediaClient(); - var randomNumberGenerator = new RandomNumberGenerator(_globalSettings); + var randomNumberGenerator = new RandomNumberGenerator(); var mediaProvider = new MediaProvider(_logger, randomNumberGenerator); var kvMemoryStore = new KvInInMemoryStore(); var errorHandler = new ErrorHandler(_logger, _runParameters, () => Localization.Internal.SomethingWentWrong); diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index dfce63b..6d1b89b 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -12,7 +12,6 @@ - diff --git a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs index 1b7178b..7460677 100644 --- a/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs +++ b/src/Core/RandomNumberGenerator/RandomNumberGenerator.cs @@ -1,25 +1,14 @@ using System; -using Anemonis.RandomOrg; -using Geekbot.Core.GlobalSettings; namespace Geekbot.Core.RandomNumberGenerator { public class RandomNumberGenerator : IRandomNumberGenerator { private readonly System.Security.Cryptography.RandomNumberGenerator rng; - private readonly bool _canUseRandomOrg; - private readonly RandomOrgClient _randomOrgClient; - public RandomNumberGenerator(IGlobalSettings globalSettings) + public RandomNumberGenerator() { rng = System.Security.Cryptography.RandomNumberGenerator.Create(); - - var randomOrgApiKey = globalSettings.GetKey("RandomOrgApiKey"); - if (!string.IsNullOrEmpty(randomOrgApiKey)) - { - _canUseRandomOrg = true; - _randomOrgClient = new RandomOrgClient(randomOrgApiKey); - } } public int Next(int minValue, int maxInclusiveValue) @@ -33,31 +22,10 @@ namespace Geekbot.Core.RandomNumberGenerator { throw new ArgumentOutOfRangeException("minValue", "must be lower than maxExclusiveValue"); } - - if (_canUseRandomOrg) - { - try - { - return GetFromRandomOrg(minValue, maxInclusiveValue); - } - catch - { - // ignore - } - } return GetFromCrypto(minValue, maxInclusiveValue); } - private int GetFromRandomOrg(int minValue, int maxInclusiveValue) - { - return _randomOrgClient - .GenerateIntegersAsync(1, minValue, maxInclusiveValue, false) - .Result - .Random - .Data[0]; - } - private int GetFromCrypto(int minValue, int maxInclusiveValue) { var maxExclusiveValue = maxInclusiveValue + 1; diff --git a/tests/Core/DiceParser/DiceParser.test.cs b/tests/Core/DiceParser/DiceParser.test.cs index ed9425f..fd9e5c5 100644 --- a/tests/Core/DiceParser/DiceParser.test.cs +++ b/tests/Core/DiceParser/DiceParser.test.cs @@ -10,7 +10,7 @@ namespace Tests.Core.DiceParser { public class DiceParserTest { - private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(new Mock().Object); + private static readonly RandomNumberGenerator _randomNumberGenerator = new RandomNumberGenerator(); public struct DiceParserTestDto { diff --git a/tests/Core/DiceParser/SingleDie.test.cs b/tests/Core/DiceParser/SingleDie.test.cs index 5173902..fdba5e7 100644 --- a/tests/Core/DiceParser/SingleDie.test.cs +++ b/tests/Core/DiceParser/SingleDie.test.cs @@ -45,7 +45,7 @@ namespace Tests.Core.DiceParser [Theory, MemberData(nameof(SingleDieNameTestData))] public void SingleDieNameTestFunc(string testName, SingleDieNameTestDto testData) { - var die = new SingleDie(new RandomNumberGenerator(new Mock().Object)) {AdvantageType = testData.AdvantageType}; + var die = new SingleDie(new RandomNumberGenerator()) {AdvantageType = testData.AdvantageType}; Assert.Equal(die.DiceName, testData.Expected); } @@ -108,7 +108,7 @@ namespace Tests.Core.DiceParser [Theory, MemberData(nameof(SingleDieValidationTestData))] public void SingleDieValidationTestFunc(string testName, SingleDieValidationTestDto testData) { - var die = new SingleDie(new RandomNumberGenerator(new Mock().Object)) + var die = new SingleDie(new RandomNumberGenerator()) { Amount = testData.Amount, Sides = testData.Sides From 1f518e980c323b728e43b85d9f829738bd18754e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:04:30 +0200 Subject: [PATCH 045/149] Move Sentry SDK init to the main init process --- src/Bot/Program.cs | 20 +++++++++++++++++++- src/Core/ErrorHandling/ErrorHandler.cs | 12 ------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 3429fbc..4d7526b 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -26,6 +26,8 @@ using Geekbot.Core.WikipediaClient; using Geekbot.Web; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Sentry; +using Constants = Geekbot.Core.Constants; namespace Geekbot.Bot { @@ -90,7 +92,9 @@ namespace Geekbot.Bot _logger.Information(LogSource.Api, "Starting Web API"); StartWebApi(); - + + RegisterSentry(); + _logger.Information(LogSource.Geekbot, "Done and ready for use"); await Task.Delay(-1); @@ -224,5 +228,19 @@ namespace Geekbot.Bot var highscoreManager = new HighscoreManager(_databaseInitializer.Initialize(), _userRepository); WebApiStartup.StartWebApi(_logger, _runParameters, _commands, _databaseInitializer.Initialize(), _client, _globalSettings, highscoreManager); } + + private void RegisterSentry() + { + var sentryDsn = _runParameters.SentryEndpoint; + if (string.IsNullOrEmpty(sentryDsn)) return; + SentrySdk.Init(o => + { + o.Dsn = sentryDsn; + o.Release = Constants.BotVersion(); + o.Environment = "Production"; + o.TracesSampleRate = 1.0; + }); + _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); + } } } \ No newline at end of file diff --git a/src/Core/ErrorHandling/ErrorHandler.cs b/src/Core/ErrorHandling/ErrorHandler.cs index a5ccc8e..0b55bd8 100644 --- a/src/Core/ErrorHandling/ErrorHandler.cs +++ b/src/Core/ErrorHandling/ErrorHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; using Geekbot.Core.Logger; @@ -19,17 +18,6 @@ namespace Geekbot.Core.ErrorHandling _logger = logger; _getDefaultErrorText = getDefaultErrorText; _errorsInChat = runParameters.ExposeErrors; - - var sentryDsn = runParameters.SentryEndpoint; - if (string.IsNullOrEmpty(sentryDsn)) return; - - SentrySdk.Init(o => - { - o.Dsn = sentryDsn; - o.Release = Constants.BotVersion(); - o.Environment = "Production"; - }); - _logger.Information(LogSource.Geekbot, $"Command Errors will be logged to Sentry: {sentryDsn}"); } public async Task HandleCommandException(Exception e, ICommandContext context, string errorMessage = "def") From 3299ac4eabafdb4c053ca0887aad73d0518c9635 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:06:10 +0200 Subject: [PATCH 046/149] Add generic sentry tracing to the main command module --- src/Core/GeekbotCommandBase.cs | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Core/GeekbotCommandBase.cs b/src/Core/GeekbotCommandBase.cs index 43ced95..ae964e7 100644 --- a/src/Core/GeekbotCommandBase.cs +++ b/src/Core/GeekbotCommandBase.cs @@ -1,9 +1,13 @@ +using System.Collections.Generic; using System.Globalization; using System.Threading; +using System.Threading.Tasks; +using Discord; using Discord.Commands; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GuildSettingsManager; +using Sentry; namespace Geekbot.Core { @@ -12,6 +16,7 @@ namespace Geekbot.Core protected readonly IGuildSettingsManager GuildSettingsManager; protected GuildSettingsModel GuildSettings; protected readonly IErrorHandler ErrorHandler; + protected ITransaction Transaction; protected GeekbotCommandBase(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) { @@ -22,9 +27,42 @@ namespace Geekbot.Core protected override void BeforeExecute(CommandInfo command) { base.BeforeExecute(command); + + // Transaction Setup + Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); + Transaction.SetTags(new [] + { + new KeyValuePair("GuildId", Context.Guild.Id.ToString()), + new KeyValuePair("Guild", Context.Guild.Name), + }); + Transaction.User = new User() + { + Id = Context.User.Id.ToString(), + Username = Context.User.Username, + }; + + // Command Setup + var setupSpan = Transaction.StartChild("Setup"); + GuildSettings = GuildSettingsManager.GetSettings(Context?.Guild?.Id ?? 0); var language = GuildSettings.Language; - Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language == "CHDE" ? "de-ch" : language); + Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language); + + setupSpan.Finish(); + } + + protected override void AfterExecute(CommandInfo command) + { + base.AfterExecute(command); + Transaction.Finish(); + } + + protected override Task ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null) + { + var replySpan = Transaction.StartChild("Reply"); + var msg = base.ReplyAsync(message, isTTS, embed, options, allowedMentions, messageReference); + replySpan.Finish(); + return msg; } } } \ No newline at end of file From aa826f962d8715f2579a0c9ee79bee8776c74a4e Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:06:34 +0200 Subject: [PATCH 047/149] Add traces to the !roll command --- src/Bot/Commands/Games/Roll/Roll.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs index 6ef9322..0361cbd 100644 --- a/src/Bot/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -11,6 +11,7 @@ using Geekbot.Core.Extensions; using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.KvInMemoryStore; using Geekbot.Core.RandomNumberGenerator; +using Sentry; namespace Geekbot.Bot.Commands.Games.Roll { @@ -34,43 +35,54 @@ namespace Geekbot.Bot.Commands.Games.Roll { try { + var inputSpan = Transaction.StartChild("CommandInput"); var number = _randomNumberGenerator.Next(1, 100); int.TryParse(stuff, out var guess); + inputSpan.Finish(); + if (guess <= 100 && guess > 0) { + var prevRollCheckSpan = Transaction.StartChild("PrevRollCheck"); var kvKey = $"{Context?.Guild?.Id ?? 0}:{Context.User.Id}:RollsPrevious"; - + var prevRoll = _kvInMemoryStore.Get(kvKey); - + if (prevRoll?.LastGuess == guess && prevRoll?.GuessedOn.AddDays(1) > DateTime.Now) { await ReplyAsync(string.Format( Localization.Roll.NoPrevGuess, Context.Message.Author.Mention, DateLocalization.FormatDateTimeAsRemaining(prevRoll.GuessedOn.AddDays(1)))); + Transaction.Status = SpanStatus.InvalidArgument; return; } _kvInMemoryStore.Set(kvKey, new RollTimeout {LastGuess = guess, GuessedOn = DateTime.Now}); + prevRollCheckSpan.Finish(); await ReplyAsync(string.Format(Localization.Roll.Rolled, Context.Message.Author.Mention, number, guess)); if (guess == number) { + var correctGuessSpan = Transaction.StartChild("CorrectGuess"); await ReplyAsync(string.Format(Localization.Roll.Gratz, Context.Message.Author)); var user = await GetUser(Context.User.Id); user.Rolls += 1; _database.Rolls.Update(user); await _database.SaveChangesAsync(); + correctGuessSpan.Finish(); } } else { await ReplyAsync(string.Format(Localization.Roll.RolledNoGuess, Context.Message.Author.Mention, number)); } + + Transaction.Status = SpanStatus.Ok; } catch (Exception e) { await ErrorHandler.HandleCommandException(e, Context); + Transaction.Status = SpanStatus.InternalError; } } From d708525a2f59711599311782d1c663e7f4f65441 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:07:19 +0200 Subject: [PATCH 048/149] Add traces to the !quote command --- src/Bot/Commands/Utils/Quote/Quote.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index e79663c..fdf1030 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -15,6 +15,8 @@ using Geekbot.Core.Polyfills; using Geekbot.Core.RandomNumberGenerator; using Geekbot.Core.UserRepository; using Microsoft.EntityFrameworkCore; +using Sentry; +using Constants = Geekbot.Core.Constants; namespace Geekbot.Bot.Commands.Utils.Quote { @@ -43,23 +45,32 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { + var getTotalSpan = Transaction.StartChild("TotalQuotes"); var totalQuotes = await _database.Quotes.CountAsync(e => e.GuildId.Equals(Context.Guild.Id.AsLong())); + getTotalSpan.Finish(); if (totalQuotes == 0) { await ReplyAsync(Localization.Quote.NoQuotesFound); + Transaction.Status = SpanStatus.NotFound; return; } + var getQuoteFromDbSpan = Transaction.StartChild("GetQuoteFromDB"); var random = _randomNumberGenerator.Next(0, totalQuotes - 1); var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); + getQuoteFromDbSpan.Finish(); + var replySpan = Transaction.StartChild("Reply"); var embed = QuoteBuilder(quote.FirstOrDefault()); await ReplyAsync("", false, embed.Build()); + replySpan.Finish(); + Transaction.Status = SpanStatus.Ok; } catch (Exception e) { await ErrorHandler.HandleCommandException(e, Context, "Whoops, seems like the quote was to edgy to return"); + Transaction.Status = SpanStatus.InternalError; } } From 833a8a0dd8dfea3fa29019584cf448c41c4cc469 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:27:46 +0200 Subject: [PATCH 049/149] Split Transactions from the GeekbotCommandBase --- src/Core/GeekbotCommandBase.cs | 35 +----------------------- src/Core/TransactionModuleBase.cs | 45 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 src/Core/TransactionModuleBase.cs diff --git a/src/Core/GeekbotCommandBase.cs b/src/Core/GeekbotCommandBase.cs index ae964e7..801c53c 100644 --- a/src/Core/GeekbotCommandBase.cs +++ b/src/Core/GeekbotCommandBase.cs @@ -1,22 +1,17 @@ -using System.Collections.Generic; using System.Globalization; using System.Threading; -using System.Threading.Tasks; -using Discord; using Discord.Commands; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GuildSettingsManager; -using Sentry; namespace Geekbot.Core { - public class GeekbotCommandBase : ModuleBase + public class GeekbotCommandBase : TransactionModuleBase { protected readonly IGuildSettingsManager GuildSettingsManager; protected GuildSettingsModel GuildSettings; protected readonly IErrorHandler ErrorHandler; - protected ITransaction Transaction; protected GeekbotCommandBase(IErrorHandler errorHandler, IGuildSettingsManager guildSettingsManager) { @@ -28,20 +23,6 @@ namespace Geekbot.Core { base.BeforeExecute(command); - // Transaction Setup - Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); - Transaction.SetTags(new [] - { - new KeyValuePair("GuildId", Context.Guild.Id.ToString()), - new KeyValuePair("Guild", Context.Guild.Name), - }); - Transaction.User = new User() - { - Id = Context.User.Id.ToString(), - Username = Context.User.Username, - }; - - // Command Setup var setupSpan = Transaction.StartChild("Setup"); GuildSettings = GuildSettingsManager.GetSettings(Context?.Guild?.Id ?? 0); @@ -50,19 +31,5 @@ namespace Geekbot.Core setupSpan.Finish(); } - - protected override void AfterExecute(CommandInfo command) - { - base.AfterExecute(command); - Transaction.Finish(); - } - - protected override Task ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null) - { - var replySpan = Transaction.StartChild("Reply"); - var msg = base.ReplyAsync(message, isTTS, embed, options, allowedMentions, messageReference); - replySpan.Finish(); - return msg; - } } } \ No newline at end of file diff --git a/src/Core/TransactionModuleBase.cs b/src/Core/TransactionModuleBase.cs new file mode 100644 index 0000000..111ae18 --- /dev/null +++ b/src/Core/TransactionModuleBase.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Sentry; + +namespace Geekbot.Core +{ + public class TransactionModuleBase : ModuleBase + { + protected ITransaction Transaction; + + protected override void BeforeExecute(CommandInfo command) + { + base.BeforeExecute(command); + + // Transaction Setup + Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); + Transaction.SetTags(new [] + { + new KeyValuePair("GuildId", Context.Guild.Id.ToString()), + new KeyValuePair("Guild", Context.Guild.Name), + }); + Transaction.User = new User() + { + Id = Context.User.Id.ToString(), + Username = Context.User.Username, + }; + } + + protected override void AfterExecute(CommandInfo command) + { + base.AfterExecute(command); + Transaction.Finish(); + } + + protected override Task ReplyAsync(string message = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null) + { + var replySpan = Transaction.StartChild("Reply"); + var msg = base.ReplyAsync(message, isTTS, embed, options, allowedMentions, messageReference); + replySpan.Finish(); + return msg; + } + } +} \ No newline at end of file From f02c30e66028930798a3146a188fc1f1ecf8f990 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:30:50 +0200 Subject: [PATCH 050/149] Remove the mod command class --- src/Bot/Commands/Admin/Mod.cs | 38 ----------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 src/Bot/Commands/Admin/Mod.cs diff --git a/src/Bot/Commands/Admin/Mod.cs b/src/Bot/Commands/Admin/Mod.cs deleted file mode 100644 index b642680..0000000 --- a/src/Bot/Commands/Admin/Mod.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Threading.Tasks; -using Discord; -using Discord.Commands; -using Geekbot.Core.CommandPreconditions; -using Geekbot.Core.ErrorHandling; - -namespace Geekbot.Bot.Commands.Admin -{ - [Group("mod")] - [RequireUserPermission(GuildPermission.KickMembers)] - [RequireUserPermission(GuildPermission.ManageMessages)] - [RequireUserPermission(GuildPermission.ManageRoles)] - [DisableInDirectMessage] - public class Mod : ModuleBase - { - private readonly IErrorHandler _errorHandler; - - public Mod(IErrorHandler errorHandler) - { - _errorHandler = errorHandler; - } - - [Command("namehistory", RunMode = RunMode.Async)] - [Summary("See past usernames of an user")] - public async Task UsernameHistory([Summary("@someone")] IUser user) - { - try - { - await Context.Channel.SendMessageAsync("This command has been removed due to low usage and excessively high database usage"); - } - catch (Exception e) - { - await _errorHandler.HandleCommandException(e, Context); - } - } - } -} \ No newline at end of file From a1f8d033c28e97b7963825f7492b423d21b62f2a Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:31:24 +0200 Subject: [PATCH 051/149] Use the TransactionModuleBase for all commands that haven't implemented GeekbotCommandBase --- src/Bot/Commands/Games/Pokedex.cs | 3 ++- src/Bot/Commands/Integrations/LolMmr/LolMmr.cs | 2 +- src/Bot/Commands/Integrations/MagicTheGathering.cs | 3 ++- .../Commands/Integrations/UbranDictionary/UrbanDictionary.cs | 2 +- src/Bot/Commands/Integrations/Wikipedia.cs | 3 ++- src/Bot/Commands/Integrations/Youtube.cs | 3 ++- .../Commands/Randomness/BenedictCumberbatchNameGenerator.cs | 3 ++- src/Bot/Commands/Randomness/Cat/Cat.cs | 2 +- src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs | 2 +- src/Bot/Commands/Randomness/Dad/DadJokes.cs | 2 +- src/Bot/Commands/Randomness/Dog/Dog.cs | 2 +- src/Bot/Commands/Randomness/Fortune.cs | 3 ++- src/Bot/Commands/Randomness/Greetings/Greetings.cs | 2 +- src/Bot/Commands/Randomness/Kanye/Kanye.cs | 2 +- src/Bot/Commands/Randomness/RandomAnimals.cs | 3 ++- src/Bot/Commands/Randomness/Slap.cs | 3 ++- src/Bot/Commands/User/GuildInfo.cs | 3 ++- src/Bot/Commands/Utils/AvatarGetter.cs | 3 ++- src/Bot/Commands/Utils/Changelog/Changelog.cs | 2 +- src/Bot/Commands/Utils/Dice.cs | 3 ++- src/Bot/Commands/Utils/Emojify.cs | 3 ++- src/Bot/Commands/Utils/Help.cs | 3 ++- src/Bot/Commands/Utils/Info.cs | 2 +- src/Bot/Commands/Utils/Lmgtfy.cs | 3 ++- src/Bot/Commands/Utils/Ping.cs | 3 ++- 25 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/Bot/Commands/Games/Pokedex.cs b/src/Bot/Commands/Games/Pokedex.cs index 426761c..325ee8c 100644 --- a/src/Bot/Commands/Games/Pokedex.cs +++ b/src/Bot/Commands/Games/Pokedex.cs @@ -3,13 +3,14 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; using PokeAPI; namespace Geekbot.Bot.Commands.Games { - public class Pokedex : ModuleBase + public class Pokedex : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs b/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs index 4e75034..3049617 100644 --- a/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs +++ b/src/Bot/Commands/Integrations/LolMmr/LolMmr.cs @@ -10,7 +10,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Integrations.LolMmr { - public class LolMmr : ModuleBase + public class LolMmr : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Integrations/MagicTheGathering.cs b/src/Bot/Commands/Integrations/MagicTheGathering.cs index b179d6e..359b41e 100644 --- a/src/Bot/Commands/Integrations/MagicTheGathering.cs +++ b/src/Bot/Commands/Integrations/MagicTheGathering.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -11,7 +12,7 @@ using MtgApiManager.Lib.Service; namespace Geekbot.Bot.Commands.Integrations { - public class MagicTheGathering : ModuleBase + public class MagicTheGathering : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IMtgManaConverter _manaConverter; diff --git a/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs index 72bc8cd..9060b91 100644 --- a/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs +++ b/src/Bot/Commands/Integrations/UbranDictionary/UrbanDictionary.cs @@ -9,7 +9,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Integrations.UbranDictionary { - public class UrbanDictionary : ModuleBase + public class UrbanDictionary : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Integrations/Wikipedia.cs b/src/Bot/Commands/Integrations/Wikipedia.cs index 709f974..82f42a0 100644 --- a/src/Bot/Commands/Integrations/Wikipedia.cs +++ b/src/Bot/Commands/Integrations/Wikipedia.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.ErrorHandling; using Geekbot.Core.Extensions; @@ -14,7 +15,7 @@ using HtmlAgilityPack; namespace Geekbot.Bot.Commands.Integrations { - public class Wikipedia : ModuleBase + public class Wikipedia : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IWikipediaClient _wikipediaClient; diff --git a/src/Bot/Commands/Integrations/Youtube.cs b/src/Bot/Commands/Integrations/Youtube.cs index 60ebdaa..74fcf52 100644 --- a/src/Bot/Commands/Integrations/Youtube.cs +++ b/src/Bot/Commands/Integrations/Youtube.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.GlobalSettings; using Google.Apis.Services; @@ -8,7 +9,7 @@ using Google.Apis.YouTube.v3; namespace Geekbot.Bot.Commands.Integrations { - public class Youtube : ModuleBase + public class Youtube : TransactionModuleBase { private readonly IGlobalSettings _globalSettings; private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs b/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs index 995c921..23187bd 100644 --- a/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs +++ b/src/Bot/Commands/Randomness/BenedictCumberbatchNameGenerator.cs @@ -2,12 +2,13 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; using Geekbot.Core.RandomNumberGenerator; namespace Geekbot.Bot.Commands.Randomness { - public class BenedictCumberbatchNameGenerator : ModuleBase + public class BenedictCumberbatchNameGenerator : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IRandomNumberGenerator _randomNumberGenerator; diff --git a/src/Bot/Commands/Randomness/Cat/Cat.cs b/src/Bot/Commands/Randomness/Cat/Cat.cs index 7bd7e57..1198113 100644 --- a/src/Bot/Commands/Randomness/Cat/Cat.cs +++ b/src/Bot/Commands/Randomness/Cat/Cat.cs @@ -7,7 +7,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Cat { - public class Cat : ModuleBase + public class Cat : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs index be328b4..e2b1f16 100644 --- a/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs +++ b/src/Bot/Commands/Randomness/Chuck/ChuckNorrisJokes.cs @@ -7,7 +7,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Chuck { - public class ChuckNorrisJokes : ModuleBase + public class ChuckNorrisJokes : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Dad/DadJokes.cs b/src/Bot/Commands/Randomness/Dad/DadJokes.cs index 136650c..67f9679 100644 --- a/src/Bot/Commands/Randomness/Dad/DadJokes.cs +++ b/src/Bot/Commands/Randomness/Dad/DadJokes.cs @@ -6,7 +6,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Dad { - public class DadJokes : ModuleBase + public class DadJokes : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Dog/Dog.cs b/src/Bot/Commands/Randomness/Dog/Dog.cs index 051dbf3..39e57c7 100644 --- a/src/Bot/Commands/Randomness/Dog/Dog.cs +++ b/src/Bot/Commands/Randomness/Dog/Dog.cs @@ -7,7 +7,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Dog { - public class Dog : ModuleBase + public class Dog : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Fortune.cs b/src/Bot/Commands/Randomness/Fortune.cs index cc31536..1157603 100644 --- a/src/Bot/Commands/Randomness/Fortune.cs +++ b/src/Bot/Commands/Randomness/Fortune.cs @@ -1,10 +1,11 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Media; namespace Geekbot.Bot.Commands.Randomness { - public class Fortune : ModuleBase + public class Fortune : TransactionModuleBase { private readonly IFortunesProvider _fortunes; diff --git a/src/Bot/Commands/Randomness/Greetings/Greetings.cs b/src/Bot/Commands/Randomness/Greetings/Greetings.cs index cd69010..c32ee6d 100644 --- a/src/Bot/Commands/Randomness/Greetings/Greetings.cs +++ b/src/Bot/Commands/Randomness/Greetings/Greetings.cs @@ -8,7 +8,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Randomness.Greetings { - public class Greetings : ModuleBase + public class Greetings : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/Kanye/Kanye.cs b/src/Bot/Commands/Randomness/Kanye/Kanye.cs index 6ad67cb..e5d2e95 100644 --- a/src/Bot/Commands/Randomness/Kanye/Kanye.cs +++ b/src/Bot/Commands/Randomness/Kanye/Kanye.cs @@ -6,7 +6,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Randomness.Kanye { - public class Kanye : ModuleBase + public class Kanye : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Randomness/RandomAnimals.cs b/src/Bot/Commands/Randomness/RandomAnimals.cs index b9c1bdd..5493485 100644 --- a/src/Bot/Commands/Randomness/RandomAnimals.cs +++ b/src/Bot/Commands/Randomness/RandomAnimals.cs @@ -1,11 +1,12 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Media; namespace Geekbot.Bot.Commands.Randomness { - public class RandomAnimals : ModuleBase + public class RandomAnimals : TransactionModuleBase { private readonly IMediaProvider _mediaProvider; diff --git a/src/Bot/Commands/Randomness/Slap.cs b/src/Bot/Commands/Randomness/Slap.cs index f5d21b8..c99c325 100644 --- a/src/Bot/Commands/Randomness/Slap.cs +++ b/src/Bot/Commands/Randomness/Slap.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.Database.Models; using Geekbot.Core.ErrorHandling; @@ -11,7 +12,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Randomness { - public class Slap : ModuleBase + public class Slap : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; diff --git a/src/Bot/Commands/User/GuildInfo.cs b/src/Bot/Commands/User/GuildInfo.cs index c596186..c7a3b27 100644 --- a/src/Bot/Commands/User/GuildInfo.cs +++ b/src/Bot/Commands/User/GuildInfo.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.CommandPreconditions; using Geekbot.Core.Database; using Geekbot.Core.ErrorHandling; @@ -11,7 +12,7 @@ using Geekbot.Core.Levels; namespace Geekbot.Bot.Commands.User { - public class GuildInfo : ModuleBase + public class GuildInfo : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly DatabaseContext _database; diff --git a/src/Bot/Commands/Utils/AvatarGetter.cs b/src/Bot/Commands/Utils/AvatarGetter.cs index 2aa6b07..458eec8 100644 --- a/src/Bot/Commands/Utils/AvatarGetter.cs +++ b/src/Bot/Commands/Utils/AvatarGetter.cs @@ -2,11 +2,12 @@ using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class AvatarGetter : ModuleBase + public class AvatarGetter : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Changelog/Changelog.cs b/src/Bot/Commands/Utils/Changelog/Changelog.cs index 92d5ddd..989ac0d 100644 --- a/src/Bot/Commands/Utils/Changelog/Changelog.cs +++ b/src/Bot/Commands/Utils/Changelog/Changelog.cs @@ -11,7 +11,7 @@ using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils.Changelog { - public class Changelog : ModuleBase + public class Changelog : TransactionModuleBase { private readonly DiscordSocketClient _client; private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Dice.cs b/src/Bot/Commands/Utils/Dice.cs index 0668493..c57001f 100644 --- a/src/Bot/Commands/Utils/Dice.cs +++ b/src/Bot/Commands/Utils/Dice.cs @@ -3,12 +3,13 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.DiceParser; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Dice : ModuleBase + public class Dice : TransactionModuleBase { private readonly IErrorHandler _errorHandler; private readonly IDiceParser _diceParser; diff --git a/src/Bot/Commands/Utils/Emojify.cs b/src/Bot/Commands/Utils/Emojify.cs index 8bb880e..63b5456 100644 --- a/src/Bot/Commands/Utils/Emojify.cs +++ b/src/Bot/Commands/Utils/Emojify.cs @@ -1,12 +1,13 @@ using System; using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.Converters; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Emojify : ModuleBase + public class Emojify : TransactionModuleBase { private readonly IEmojiConverter _emojiConverter; private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Help.cs b/src/Bot/Commands/Utils/Help.cs index 58630fe..7377bfa 100644 --- a/src/Bot/Commands/Utils/Help.cs +++ b/src/Bot/Commands/Utils/Help.cs @@ -3,11 +3,12 @@ using System.Text; using System.Threading.Tasks; using Discord; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Help : ModuleBase + public class Help : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Info.cs b/src/Bot/Commands/Utils/Info.cs index 663dd07..912528d 100644 --- a/src/Bot/Commands/Utils/Info.cs +++ b/src/Bot/Commands/Utils/Info.cs @@ -11,7 +11,7 @@ using Geekbot.Core.Extensions; namespace Geekbot.Bot.Commands.Utils { - public class Info : ModuleBase + public class Info : TransactionModuleBase { private readonly DiscordSocketClient _client; private readonly CommandService _commands; diff --git a/src/Bot/Commands/Utils/Lmgtfy.cs b/src/Bot/Commands/Utils/Lmgtfy.cs index 6063cf9..76fa6fa 100644 --- a/src/Bot/Commands/Utils/Lmgtfy.cs +++ b/src/Bot/Commands/Utils/Lmgtfy.cs @@ -2,11 +2,12 @@ using System; using System.Threading.Tasks; using System.Web; using Discord.Commands; +using Geekbot.Core; using Geekbot.Core.ErrorHandling; namespace Geekbot.Bot.Commands.Utils { - public class Lmgtfy : ModuleBase + public class Lmgtfy : TransactionModuleBase { private readonly IErrorHandler _errorHandler; diff --git a/src/Bot/Commands/Utils/Ping.cs b/src/Bot/Commands/Utils/Ping.cs index d4faa53..ee751cd 100644 --- a/src/Bot/Commands/Utils/Ping.cs +++ b/src/Bot/Commands/Utils/Ping.cs @@ -1,9 +1,10 @@ using System.Threading.Tasks; using Discord.Commands; +using Geekbot.Core; namespace Geekbot.Bot.Commands.Utils { - public class Ping : ModuleBase + public class Ping : TransactionModuleBase { [Command("👀", RunMode = RunMode.Async)] [Summary("Look at the bot.")] From d16828077d5098a807027857ab5871d4c85668bf Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:33:55 +0200 Subject: [PATCH 052/149] Set Transaction Status to OK by default --- src/Bot/Commands/Games/Roll/Roll.cs | 2 -- src/Bot/Commands/Utils/Quote/Quote.cs | 1 - src/Core/TransactionModuleBase.cs | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Bot/Commands/Games/Roll/Roll.cs b/src/Bot/Commands/Games/Roll/Roll.cs index 0361cbd..172126b 100644 --- a/src/Bot/Commands/Games/Roll/Roll.cs +++ b/src/Bot/Commands/Games/Roll/Roll.cs @@ -76,8 +76,6 @@ namespace Geekbot.Bot.Commands.Games.Roll { await ReplyAsync(string.Format(Localization.Roll.RolledNoGuess, Context.Message.Author.Mention, number)); } - - Transaction.Status = SpanStatus.Ok; } catch (Exception e) { diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index fdf1030..8fbecbc 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -65,7 +65,6 @@ namespace Geekbot.Bot.Commands.Utils.Quote var embed = QuoteBuilder(quote.FirstOrDefault()); await ReplyAsync("", false, embed.Build()); replySpan.Finish(); - Transaction.Status = SpanStatus.Ok; } catch (Exception e) { diff --git a/src/Core/TransactionModuleBase.cs b/src/Core/TransactionModuleBase.cs index 111ae18..c35800b 100644 --- a/src/Core/TransactionModuleBase.cs +++ b/src/Core/TransactionModuleBase.cs @@ -26,6 +26,7 @@ namespace Geekbot.Core Id = Context.User.Id.ToString(), Username = Context.User.Username, }; + Transaction.Status = SpanStatus.Ok; } protected override void AfterExecute(CommandInfo command) From 0a9099a6d28ad99a5696f8c5548341ba666d1f00 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 14:53:24 +0200 Subject: [PATCH 053/149] Move Sentry Init priority between the discord connection and dependency registration --- src/Bot/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 4d7526b..883d92b 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -85,6 +85,8 @@ namespace Geekbot.Bot await Login(); _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); await _client.SetGameAsync(_globalSettings.GetKey("Game")); + + RegisterSentry(); _logger.Information(LogSource.Geekbot, "Loading Dependencies and Handlers"); RegisterDependencies(); @@ -93,8 +95,6 @@ namespace Geekbot.Bot _logger.Information(LogSource.Api, "Starting Web API"); StartWebApi(); - RegisterSentry(); - _logger.Information(LogSource.Geekbot, "Done and ready for use"); await Task.Delay(-1); From 3d117aebe1d8007ed644fcdfcc57d912cffcb140 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 15:12:22 +0200 Subject: [PATCH 054/149] Split reply and quote embed building trace apart in !quote --- src/Bot/Commands/Utils/Quote/Quote.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 8fbecbc..835cdcf 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -61,10 +61,10 @@ namespace Geekbot.Bot.Commands.Utils.Quote var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); getQuoteFromDbSpan.Finish(); - var replySpan = Transaction.StartChild("Reply"); + var buildQuoteEmbedSpan = Transaction.StartChild("BuildQuoteEmbed"); var embed = QuoteBuilder(quote.FirstOrDefault()); + buildQuoteEmbedSpan.Finish(); await ReplyAsync("", false, embed.Build()); - replySpan.Finish(); } catch (Exception e) { From 954c6c2be30ef93c96f3fdef8f61f25cdac718f3 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Fri, 17 Sep 2021 15:55:13 +0200 Subject: [PATCH 055/149] Remove Guild ID from the tracing tags --- src/Core/TransactionModuleBase.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/TransactionModuleBase.cs b/src/Core/TransactionModuleBase.cs index c35800b..726c355 100644 --- a/src/Core/TransactionModuleBase.cs +++ b/src/Core/TransactionModuleBase.cs @@ -18,7 +18,6 @@ namespace Geekbot.Core Transaction = SentrySdk.StartTransaction(new Transaction(command.Name, "Exec")); Transaction.SetTags(new [] { - new KeyValuePair("GuildId", Context.Guild.Id.ToString()), new KeyValuePair("Guild", Context.Guild.Name), }); Transaction.User = new User() From 1b9d8732d5c9cb50c42e40312e719b6466a0500c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 00:57:10 +0200 Subject: [PATCH 056/149] Add tracing to the !quote embed builder --- src/Bot/Commands/Utils/Quote/Quote.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 835cdcf..372bed7 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -268,29 +268,32 @@ namespace Geekbot.Bot.Commands.Utils.Quote private EmbedBuilder QuoteBuilder(QuoteModel quote) { + var getEmbedUserSpan = Transaction.StartChild("GetEmbedUser"); var user = Context.Client.GetUserAsync(quote.UserId.AsUlong()).Result; if (user == null) { + var getEmbedUserFromRepoSpan = Transaction.StartChild("GetEmbedUserFromRepo"); var fallbackUserFromRepo = _userRepository.Get(quote.UserId.AsUlong()); user = new UserPolyfillDto() { Username = fallbackUserFromRepo?.Username ?? "Unknown User", AvatarUrl = fallbackUserFromRepo?.AvatarUrl }; + getEmbedUserFromRepoSpan.Finish(); } + getEmbedUserSpan.Finish(); + + var embedBuilderSpan = Transaction.StartChild("EmbedBuilder"); var eb = new EmbedBuilder(); eb.WithColor(new Color(143, 167, 232)); - if (quote.InternalId == 0) - { - eb.Title = $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; - } - else - { - eb.Title = $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; - } + eb.Title = quote.InternalId == 0 + ? $"{user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}" + : $"#{quote.InternalId} | {user.Username} @ {quote.Time.Day}.{quote.Time.Month}.{quote.Time.Year}"; eb.Description = quote.Quote; eb.ThumbnailUrl = user.GetAvatarUrl(); if (quote.Image != null) eb.ImageUrl = quote.Image; + embedBuilderSpan.Finish(); + return eb; } From 447c6d80422237959dfb7867118c37e888b1b243 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 00:58:00 +0200 Subject: [PATCH 057/149] Remove a database call from !quote by delegating the randomness to the database. --- src/Bot/Commands/Utils/Quote/Quote.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Bot/Commands/Utils/Quote/Quote.cs b/src/Bot/Commands/Utils/Quote/Quote.cs index 372bed7..e85c6fa 100644 --- a/src/Bot/Commands/Utils/Quote/Quote.cs +++ b/src/Bot/Commands/Utils/Quote/Quote.cs @@ -45,22 +45,17 @@ namespace Geekbot.Bot.Commands.Utils.Quote { try { - var getTotalSpan = Transaction.StartChild("TotalQuotes"); - var totalQuotes = await _database.Quotes.CountAsync(e => e.GuildId.Equals(Context.Guild.Id.AsLong())); - getTotalSpan.Finish(); - - if (totalQuotes == 0) + var getQuoteFromDbSpan = Transaction.StartChild("GetQuoteFromDB"); + var quote = _database.Quotes.FromSqlInterpolated($"select * from \"Quotes\" where \"GuildId\" = {Context.Guild.Id} order by random() limit 1"); + getQuoteFromDbSpan.Finish(); + + if (!quote.Any()) { await ReplyAsync(Localization.Quote.NoQuotesFound); Transaction.Status = SpanStatus.NotFound; return; } - var getQuoteFromDbSpan = Transaction.StartChild("GetQuoteFromDB"); - var random = _randomNumberGenerator.Next(0, totalQuotes - 1); - var quote = _database.Quotes.Where(e => e.GuildId.Equals(Context.Guild.Id.AsLong())).Skip(random).Take(1); - getQuoteFromDbSpan.Finish(); - var buildQuoteEmbedSpan = Transaction.StartChild("BuildQuoteEmbed"); var embed = QuoteBuilder(quote.FirstOrDefault()); buildQuoteEmbedSpan.Finish(); From 85d06b76e009b9542acba34d3bed6f2b1a328c8c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 16:06:11 +0200 Subject: [PATCH 058/149] Add --disable-gateway parameter to the run parameters to stop the bot from connecting to discord. Useful when working on the web-api --- src/Bot/Program.cs | 17 ++++++++++------- src/Core/RunParameters.cs | 3 +++ src/Web/WebApiStartup.cs | 8 +++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Bot/Program.cs b/src/Bot/Program.cs index 883d92b..31b67e0 100644 --- a/src/Bot/Program.cs +++ b/src/Bot/Program.cs @@ -80,17 +80,20 @@ namespace Geekbot.Bot var database = ConnectToDatabase(); _globalSettings = new GlobalSettings(database); - logger.Information(LogSource.Geekbot, "Connecting to Discord"); - SetupDiscordClient(); - await Login(); - _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); - await _client.SetGameAsync(_globalSettings.GetKey("Game")); + if (!runParameters.DisableGateway) + { + logger.Information(LogSource.Geekbot, "Connecting to Discord"); + SetupDiscordClient(); + await Login(); + _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); + await _client.SetGameAsync(_globalSettings.GetKey("Game")); + } RegisterSentry(); _logger.Information(LogSource.Geekbot, "Loading Dependencies and Handlers"); RegisterDependencies(); - await RegisterHandlers(); + if (!runParameters.DisableGateway) await RegisterHandlers(); _logger.Information(LogSource.Api, "Starting Web API"); StartWebApi(); @@ -187,9 +190,9 @@ namespace Geekbot.Bot services.AddSingleton(diceParser); services.AddSingleton(_reactionListener); services.AddSingleton(_guildSettingsManager); - services.AddSingleton(_client); services.AddTransient(e => new HighscoreManager(_databaseInitializer.Initialize(), _userRepository)); services.AddTransient(e => _databaseInitializer.Initialize()); + if (!_runParameters.DisableGateway) services.AddSingleton(_client); _servicesProvider = services.BuildServiceProvider(); } diff --git a/src/Core/RunParameters.cs b/src/Core/RunParameters.cs index 3210587..a886a98 100644 --- a/src/Core/RunParameters.cs +++ b/src/Core/RunParameters.cs @@ -20,6 +20,9 @@ namespace Geekbot.Core [Option('e', "expose-errors", HelpText = "Shows internal errors in the chat (default: false) (env: EXPOSE_ERRORS)")] public bool ExposeErrors { get; set; } = ParamFallback("EXPOSE_ERRORS", false); + + [Option("disable-gateway", HelpText = "Disables the Discord Gateway (default: false) (env: GATEWAY_DISABLE)")] + public bool DisableGateway { get; set; } = ParamFallback("GATEWAY_DISABLE", false); /************************************ * Database * diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 0c18886..9c8a805 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -37,12 +37,14 @@ namespace Geekbot.Web options.AddPolicy("AllowSpecificOrigin", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); - - services.AddSingleton(commandService); + services.AddSingleton(databaseContext); - services.AddSingleton(client); services.AddSingleton(globalSettings); services.AddSingleton(highscoreManager); + + if (runParameters.DisableGateway) return; + services.AddSingleton(commandService); + services.AddSingleton(client); }) .Configure(app => { From d81fb2a3d977786079a69525f1d17357fb520ea0 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 16:11:06 +0200 Subject: [PATCH 059/149] Add initial interaction support --- .../Interactions/InteractionController.cs | 90 +++++++++++++++++++ .../Model/ApplicationCommandOption.cs | 16 ++++ .../Interactions/Model/Interaction.cs | 22 +++++ .../Interactions/Model/InteractionData.cs | 14 +++ .../Interactions/Model/InteractionOption.cs | 12 +++ .../Model/InteractionResolvedData.cs | 15 ++++ .../Interactions/Model/InteractionResponse.cs | 13 +++ .../Model/InteractionResponseData.cs | 16 ++++ .../Model/InteractionResponseType.cs | 11 +++ .../Interactions/Model/InteractionType.cs | 9 ++ .../Model/MessageComponents/Component.cs | 7 ++ .../Interactions/Model/Resolved/Channel.cs | 12 +++ .../Model/Resolved/ChannelType.cs | 17 ++++ .../Interactions/Model/Resolved/Member.cs | 16 ++++ .../Interactions/Model/Resolved/RoleTag.cs | 9 ++ .../Interactions/Model/Resolved/Roles.cs | 15 ++++ .../Model/Resolved/ThreadMetadata.cs | 13 +++ .../Interactions/Model/Resolved/User.cs | 21 +++++ src/Web/Web.csproj | 4 + src/Web/WebApiStartup.cs | 5 +- 20 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 src/Web/Controllers/Interactions/InteractionController.cs create mode 100644 src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs create mode 100644 src/Web/Controllers/Interactions/Model/Interaction.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionData.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionOption.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponse.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseData.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseType.cs create mode 100644 src/Web/Controllers/Interactions/Model/InteractionType.cs create mode 100644 src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Channel.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Member.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Roles.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs create mode 100644 src/Web/Controllers/Interactions/Model/Resolved/User.cs diff --git a/src/Web/Controllers/Interactions/InteractionController.cs b/src/Web/Controllers/Interactions/InteractionController.cs new file mode 100644 index 0000000..3501c06 --- /dev/null +++ b/src/Web/Controllers/Interactions/InteractionController.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Geekbot.Core.GlobalSettings; +using Geekbot.Web.Controllers.Interactions.Model; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Sodium; + +namespace Geekbot.Web.Controllers.Interactions +{ + public class InteractionController : Controller + { + private readonly byte[] publicKeyBytes; + + public InteractionController(IGlobalSettings globalSettings) + { + var publicKey = globalSettings.GetKey("DiscordPublicKey"); + publicKeyBytes = Convert.FromHexString(publicKey.AsSpan()); + } + + [HttpPost] + [Route("/interactions")] + public async Task HandleInteraction( + [FromHeader(Name = "X-Signature-Ed25519")] string signature, + [FromHeader(Name = "X-Signature-Timestamp")] string timestamp + ) + { + if (string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(timestamp)) + { + return BadRequest(); + } + + Request.EnableBuffering(); + if (!(await HasValidSignature(signature, timestamp))) + { + return Unauthorized(); + } + + if (Request.Body.CanSeek) Request.Body.Seek(0, SeekOrigin.Begin); + var interaction = await JsonSerializer.DeserializeAsync(Request.Body, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }).ConfigureAwait(false); + if (interaction is null) throw new JsonException("Failed to deserialize JSON body"); + + return (interaction.Type, interaction.Version) switch + { + (InteractionType.Ping, 1) => Ping(), + (InteractionType.ApplicationCommand, 1) => ApplicationCommand(interaction), + (InteractionType.MessageComponent, 1) => MessageComponent(interaction), + _ => StatusCode(501) + }; + } + + private IActionResult Ping() + { + var response = new InteractionResponse() + { + Type = InteractionResponseType.Pong, + }; + return Ok(response); + } + + private IActionResult ApplicationCommand(Interaction interaction) + { + return StatusCode(501); + } + + private IActionResult MessageComponent(Interaction interaction) + { + return StatusCode(501); + } + + private async Task HasValidSignature(string signature, string timestamp) + { + var timestampBytes = Encoding.Default.GetBytes(timestamp); + var signatureBytes = Convert.FromHexString(signature.AsSpan()); + + var memoryStream = new MemoryStream(); + await Request.Body.CopyToAsync(memoryStream).ConfigureAwait(false); + var body = memoryStream.ToArray(); + + var timestampLength = timestampBytes.Length; + Array.Resize(ref timestampBytes, timestampLength + body.Length); + Array.Copy(body, 0, timestampBytes, timestampLength, body.Length); + + return PublicKeyAuth.VerifyDetached(signatureBytes, timestampBytes, publicKeyBytes); + } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs b/src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs new file mode 100644 index 0000000..794102b --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs @@ -0,0 +1,16 @@ +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public enum ApplicationCommandOption + { + SubCommand = 1, + SubCommandGroup = 2, + String = 3, + Integer = 4, + Boolean = 5, + User = 6, + Channel = 7, + Role = 8, + Mentionable = 9, + Number = 10, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Interaction.cs b/src/Web/Controllers/Interactions/Model/Interaction.cs new file mode 100644 index 0000000..6045504 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Interaction.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record Interaction + { + public string Id { get; set; } + public string ApplicationId { get; init; } + [Required] + public InteractionType Type { get; set; } + public InteractionData Data { get; init; } + public string GuildId { get; init; } + public string Name { get; init; } + public string Description { get; init; } + public List Options { get; init; } + public bool DefaultPermission { get; init; } + [Required] + public int Version { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionData.cs b/src/Web/Controllers/Interactions/Model/InteractionData.cs new file mode 100644 index 0000000..cb0f594 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionData.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionData + { + public string Id { get; set; } + public string Name { get; set; } + public int Type { get; set;} + public InteractionResolvedData Resolved { get; set; } + public List Options { get; set; } + public string TargetId { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionOption.cs b/src/Web/Controllers/Interactions/Model/InteractionOption.cs new file mode 100644 index 0000000..c5acfa7 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionOption.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionOption + { + public string Name { get; set; } + public ApplicationCommandOption Type { get; set; } + public string Value { get; set; } + public List Options { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs b/src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs new file mode 100644 index 0000000..ee90f48 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Discord; +using Geekbot.Web.Controllers.Interactions.Model.Resolved; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public class InteractionResolvedData + { + public Dictionary Users { get; set; } + public Dictionary Members { get; set; } + public Dictionary Roles { get; set; } + public Dictionary Channels { get; set; } + // public Dictionary Messages { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResponse.cs b/src/Web/Controllers/Interactions/Model/InteractionResponse.cs new file mode 100644 index 0000000..c3a2a1e --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResponse.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionResponse + { + [JsonPropertyName("type")] + public InteractionResponseType Type { get; set; } + + [JsonPropertyName("data")] + public InteractionData Data { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResponseData.cs b/src/Web/Controllers/Interactions/Model/InteractionResponseData.cs new file mode 100644 index 0000000..146e812 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResponseData.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Discord; +using Geekbot.Web.Controllers.Interactions.Model.MessageComponents; + +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public record InteractionResponseData + { + public bool Tts { get; set; } = false; + public string Content { get; set; } + public List Embeds { get; set; } + public AllowedMentions AllowedMentions { get; set; } + public int Flags { get; set; } + public List Components { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionResponseType.cs b/src/Web/Controllers/Interactions/Model/InteractionResponseType.cs new file mode 100644 index 0000000..5bc85dc --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionResponseType.cs @@ -0,0 +1,11 @@ +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public enum InteractionResponseType + { + Pong = 1, + ChannelMessageWithSource = 4, + DeferredChannelMessageWithSource = 5, + DeferredUpdateMessage = 6, + UpdateMessage = 7, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/InteractionType.cs b/src/Web/Controllers/Interactions/Model/InteractionType.cs new file mode 100644 index 0000000..a8421c5 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/InteractionType.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Web.Controllers.Interactions.Model +{ + public enum InteractionType + { + Ping = 1, + ApplicationCommand = 2, + MessageComponent = 3, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs b/src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs new file mode 100644 index 0000000..72097a4 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs @@ -0,0 +1,7 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.MessageComponents +{ + public record Component + { + + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/Channel.cs b/src/Web/Controllers/Interactions/Model/Resolved/Channel.cs new file mode 100644 index 0000000..4b280d9 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/Channel.cs @@ -0,0 +1,12 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record Channel + { + public string Id { get; set; } + public ChannelType Type { get; set; } + public string Name { get; set; } + public string ParentId { get; set; } + public ThreadMetadata ThreadMetadata { get; set; } + public string Permissions { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs b/src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs new file mode 100644 index 0000000..1fbc0af --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/ChannelType.cs @@ -0,0 +1,17 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public enum ChannelType + { + GuildText = 0, + Dm = 1, + GuildVoice = 2, + GroupDm = 3, + GuildCategory = 4, + GuildNews = 5, + GuildStore = 6, + GuildNewsThread = 10, + GuildPublicThread = 11, + GuildPrivateThread = 12, + GuildStageVoice = 13, + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/Member.cs b/src/Web/Controllers/Interactions/Model/Resolved/Member.cs new file mode 100644 index 0000000..e95a09a --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/Member.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record Member + { + // public User User { get; set; } + public string Nick { get; set; } + public List Roles { get; set; } + public DateTime JoinedAt { get; set; } + public DateTime PremiumSince { get; set; } + public bool Pending { get; set; } + public string Permissions { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs b/src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs new file mode 100644 index 0000000..4f35ae1 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs @@ -0,0 +1,9 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record RoleTag + { + public string BotId { get; set; } + public string IntegrationId { get; set; } + public bool PremiumSubscriber { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/Roles.cs b/src/Web/Controllers/Interactions/Model/Resolved/Roles.cs new file mode 100644 index 0000000..aab5d7c --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/Roles.cs @@ -0,0 +1,15 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record Roles + { + public string Id { get; set; } + public string Name { get; set; } + public int Color { get; set; } + public bool Hoist { get; set; } + public int Position { get; set; } + public string Permissions { get; set; } + public bool Managed { get; set; } + public bool Mentionable { get; set; } + public RoleTag Tags { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs b/src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs new file mode 100644 index 0000000..e43ad89 --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs @@ -0,0 +1,13 @@ +using System; + +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record ThreadMetadata + { + public bool Archived { get; set; } + public int AutoArchiveDuration { get; set; } + public DateTime ArchiveTimestamp { get; set; } + public bool Locked { get; set; } + public bool Invitable { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Controllers/Interactions/Model/Resolved/User.cs b/src/Web/Controllers/Interactions/Model/Resolved/User.cs new file mode 100644 index 0000000..4ef1f8d --- /dev/null +++ b/src/Web/Controllers/Interactions/Model/Resolved/User.cs @@ -0,0 +1,21 @@ +namespace Geekbot.Web.Controllers.Interactions.Model.Resolved +{ + public record User + { + public string Id { get; set; } + public string Username { get; set; } + public string Discriminator { get; set; } + public string Avatar { get; set; } + public bool Bot { get; set; } + public bool System { get; set; } + public bool MfaEnabled { get; set; } + public string Banner { get; set; } + public int AccentColor { get; set; } + public string Locale { get; set; } + public bool Verified { get; set; } + public string Email { get; set; } + public int Flags { get; set; } + public int PremiumType { get; set; } + public int PublicFlags { get; set; } + } +} \ No newline at end of file diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index a9ffcc4..dc6b09a 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -16,4 +16,8 @@ + + + + diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 9c8a805..34090d3 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -31,7 +31,10 @@ namespace Geekbot.Web }) .ConfigureServices(services => { - services.AddControllers(); + services.AddControllers().AddJsonOptions(options => + { + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + }); services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", From 209887e237847fa9d49c1fd60d59e4e65a16adb7 Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Sun, 19 Sep 2021 16:19:40 +0200 Subject: [PATCH 060/149] Add sentry support to the webapi --- src/Web/Web.csproj | 1 + src/Web/WebApiStartup.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index dc6b09a..48fcf86 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -17,6 +17,7 @@ + diff --git a/src/Web/WebApiStartup.cs b/src/Web/WebApiStartup.cs index 34090d3..f62dd58 100644 --- a/src/Web/WebApiStartup.cs +++ b/src/Web/WebApiStartup.cs @@ -40,6 +40,7 @@ namespace Geekbot.Web options.AddPolicy("AllowSpecificOrigin", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); + services.AddSentry(); services.AddSingleton(databaseContext); services.AddSingleton(globalSettings); From 60547140ea5838106c58bd61952ae5bc11be671c Mon Sep 17 00:00:00 2001 From: Daan Boerlage Date: Mon, 20 Sep 2021 01:28:26 +0200 Subject: [PATCH 061/149] Create all interaction models --- .../ApplicationCommand/Command.cs | 73 ++++++++++++ .../ApplicationCommand/CommandType.cs | 21 ++++ .../Interactions/ApplicationCommand/Option.cs | 51 ++++++++ .../ApplicationCommand/OptionChoice.cs | 17 +++ .../ApplicationCommand/OptionChoiceDouble.cs | 14 +++ .../ApplicationCommand/OptionChoiceInteger.cs | 14 +++ .../ApplicationCommand/OptionChoiceString.cs | 14 +++ .../ApplicationCommand/OptionType.cs | 38 ++++++ src/Core/Interactions/Embed/Embed.cs | 88 ++++++++++++++ src/Core/Interactions/Embed/EmbedAuthor.cs | 32 +++++ src/Core/Interactions/Embed/EmbedField.cs | 26 ++++ src/Core/Interactions/Embed/EmbedFooter.cs | 27 +++++ src/Core/Interactions/Embed/EmbedImage.cs | 32 +++++ src/Core/Interactions/Embed/EmbedProvider.cs | 20 ++++ src/Core/Interactions/Embed/EmbedThumbnail.cs | 33 ++++++ src/Core/Interactions/Embed/EmbedTypes.cs | 49 ++++++++ src/Core/Interactions/Embed/EmbedVideo.cs | 32 +++++ .../MessageComponents/ButtonStyle.cs | 31 +++++ .../MessageComponents/Component.cs | 111 ++++++++++++++++++ .../MessageComponents/ComponentEmoji.cs | 33 ++++++ .../MessageComponents/ComponentType.cs | 21 ++++ .../MessageComponents/SelectOption.cs | 38 ++++++ src/Core/Interactions/Request/Interaction.cs | 77 ++++++++++++ .../Interactions/Request/InteractionData.cs | 109 +++++++++++++++++ .../Interactions/Request/InteractionOption.cs | 34 ++++++ .../Request/InteractionResolvedData.cs | 24 ++++ .../Interactions/Request/InteractionType.cs | 10 ++ src/Core/Interactions/Resolved/Attachment.cs | 34 ++++++ src/Core/Interactions/Resolved/Channel.cs | 25 ++++ .../Interactions}/Resolved/ChannelType.cs | 2 +- src/Core/Interactions/Resolved/Emoji.cs | 32 +++++ src/Core/Interactions/Resolved/Member.cs | 27 +++++ src/Core/Interactions/Resolved/Message.cs | 103 ++++++++++++++++ .../Resolved/MessageInteraction.cs | 20 ++++ src/Core/Interactions/Resolved/MessageType.cs | 29 +++++ src/Core/Interactions/Resolved/Reaction.cs | 16 +++ src/Core/Interactions/Resolved/Role.cs | 34 ++++++ src/Core/Interactions/Resolved/RoleTag.cs | 16 +++ .../Interactions/Resolved/ThreadMetadata.cs | 23 ++++ src/Core/Interactions/Resolved/User.cs | 52 ++++++++ .../Response/InteractionResponse.cs | 23 ++++ .../Response/InteractionResponseData.cs | 51 ++++++++ .../Response/InteractionResponseType.cs | 34 ++++++ .../Model/ApplicationCommandOption.cs | 16 --- .../Interactions/Model/Interaction.cs | 22 ---- .../Interactions/Model/InteractionData.cs | 14 --- .../Interactions/Model/InteractionOption.cs | 12 -- .../Model/InteractionResolvedData.cs | 15 --- .../Interactions/Model/InteractionResponse.cs | 13 -- .../Model/InteractionResponseData.cs | 16 --- .../Model/InteractionResponseType.cs | 11 -- .../Interactions/Model/InteractionType.cs | 9 -- .../Model/MessageComponents/Component.cs | 7 -- .../Interactions/Model/Resolved/Channel.cs | 12 -- .../Interactions/Model/Resolved/Member.cs | 16 --- .../Interactions/Model/Resolved/RoleTag.cs | 9 -- .../Interactions/Model/Resolved/Roles.cs | 15 --- .../Model/Resolved/ThreadMetadata.cs | 13 -- .../Interactions/Model/Resolved/User.cs | 21 ---- 59 files changed, 1589 insertions(+), 222 deletions(-) create mode 100644 src/Core/Interactions/ApplicationCommand/Command.cs create mode 100644 src/Core/Interactions/ApplicationCommand/CommandType.cs create mode 100644 src/Core/Interactions/ApplicationCommand/Option.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoice.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoiceDouble.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoiceInteger.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionChoiceString.cs create mode 100644 src/Core/Interactions/ApplicationCommand/OptionType.cs create mode 100644 src/Core/Interactions/Embed/Embed.cs create mode 100644 src/Core/Interactions/Embed/EmbedAuthor.cs create mode 100644 src/Core/Interactions/Embed/EmbedField.cs create mode 100644 src/Core/Interactions/Embed/EmbedFooter.cs create mode 100644 src/Core/Interactions/Embed/EmbedImage.cs create mode 100644 src/Core/Interactions/Embed/EmbedProvider.cs create mode 100644 src/Core/Interactions/Embed/EmbedThumbnail.cs create mode 100644 src/Core/Interactions/Embed/EmbedTypes.cs create mode 100644 src/Core/Interactions/Embed/EmbedVideo.cs create mode 100644 src/Core/Interactions/MessageComponents/ButtonStyle.cs create mode 100644 src/Core/Interactions/MessageComponents/Component.cs create mode 100644 src/Core/Interactions/MessageComponents/ComponentEmoji.cs create mode 100644 src/Core/Interactions/MessageComponents/ComponentType.cs create mode 100644 src/Core/Interactions/MessageComponents/SelectOption.cs create mode 100644 src/Core/Interactions/Request/Interaction.cs create mode 100644 src/Core/Interactions/Request/InteractionData.cs create mode 100644 src/Core/Interactions/Request/InteractionOption.cs create mode 100644 src/Core/Interactions/Request/InteractionResolvedData.cs create mode 100644 src/Core/Interactions/Request/InteractionType.cs create mode 100644 src/Core/Interactions/Resolved/Attachment.cs create mode 100644 src/Core/Interactions/Resolved/Channel.cs rename src/{Web/Controllers/Interactions/Model => Core/Interactions}/Resolved/ChannelType.cs (80%) create mode 100644 src/Core/Interactions/Resolved/Emoji.cs create mode 100644 src/Core/Interactions/Resolved/Member.cs create mode 100644 src/Core/Interactions/Resolved/Message.cs create mode 100644 src/Core/Interactions/Resolved/MessageInteraction.cs create mode 100644 src/Core/Interactions/Resolved/MessageType.cs create mode 100644 src/Core/Interactions/Resolved/Reaction.cs create mode 100644 src/Core/Interactions/Resolved/Role.cs create mode 100644 src/Core/Interactions/Resolved/RoleTag.cs create mode 100644 src/Core/Interactions/Resolved/ThreadMetadata.cs create mode 100644 src/Core/Interactions/Resolved/User.cs create mode 100644 src/Core/Interactions/Response/InteractionResponse.cs create mode 100644 src/Core/Interactions/Response/InteractionResponseData.cs create mode 100644 src/Core/Interactions/Response/InteractionResponseType.cs delete mode 100644 src/Web/Controllers/Interactions/Model/ApplicationCommandOption.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Interaction.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionData.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionOption.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResolvedData.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponse.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseData.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionResponseType.cs delete mode 100644 src/Web/Controllers/Interactions/Model/InteractionType.cs delete mode 100644 src/Web/Controllers/Interactions/Model/MessageComponents/Component.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Channel.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Member.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/RoleTag.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/Roles.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/ThreadMetadata.cs delete mode 100644 src/Web/Controllers/Interactions/Model/Resolved/User.cs diff --git a/src/Core/Interactions/ApplicationCommand/Command.cs b/src/Core/Interactions/ApplicationCommand/Command.cs new file mode 100644 index 0000000..aaf1e74 --- /dev/null +++ b/src/Core/Interactions/ApplicationCommand/Command.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Geekbot.Core.Interactions.ApplicationCommand +{ + /// + public record Command + { + /// + /// unique id of the command + /// + [JsonPropertyName("id")] + public string Id { get; set; } + + /// + /// the type of command, defaults 1 if not set + /// + [JsonPropertyName("type")] + public CommandType Type { get; set; } + + /// + /// unique id of the parent application + /// + [JsonPropertyName("application_id")] + public string ApplicationId { get; set; } + + /// + /// guild id of the command, if not global + /// + [JsonPropertyName("guild_id")] + public string GuildId { get; set; } + + /// + /// 1-32 character name + /// + /// + /// CHAT_INPUT command names and command option names must match the following regex ^[\w-]{1,32}$ with the unicode flag set. If there is a lowercase variant of any letters used, you must use those. + /// Characters with no lowercase variants and/or uncased letters are still allowed. USER and MESSAGE commands may be mixed case and can include spaces. + /// + [JsonPropertyName("name")] + public string Name { get; set; } + + /// + /// 1-100 character description for CHAT_INPUT commands, empty string for USER and MESSAGE commands + /// + /// + /// Exclusive: CHAT_INPUT + /// + [JsonPropertyName("description")] + public string Description { get; set; } + + /// + /// the parameters for the command, max 25 + /// + /// + /// Exclusive: CHAT_INPUT + /// + [JsonPropertyName("options")] + public List