From 397bb83ba8b617dcae6adfcd8038ee118c2301dd Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Mon, 24 Jul 2023 22:35:45 +0500 Subject: [PATCH 1/3] Add code analysis to prohibit using bad methods and properties (#70) This PR adds the package `Microsoft.CodeAnalysis.BannedApiAnalyzers` to scan for banned code (defined by `CodeAnalysis/BannedSymbols.txt`) and provide warnings if it is used. The list of banned symbols is borrowed from osu! and other projects Signed-off-by: Octol1ttle --- Boyfriend.csproj | 4 ++++ CodeAnalysis/BannedSymbols.txt | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 CodeAnalysis/BannedSymbols.txt diff --git a/Boyfriend.csproj b/Boyfriend.csproj index 8c4cd81..366d1c5 100644 --- a/Boyfriend.csproj +++ b/Boyfriend.csproj @@ -22,6 +22,7 @@ + @@ -34,4 +35,7 @@ Messages.Designer.cs + + + diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt new file mode 100644 index 0000000..f664b89 --- /dev/null +++ b/CodeAnalysis/BannedSymbols.txt @@ -0,0 +1,19 @@ +M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. +M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable or EqualityComparer.Default instead. +M:System.Nullable`1.Equals(System.Object)~System.Boolean;Use == instead. +T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. +M:System.Guid.#ctor;Probably meaning to use Guid.NewGuid() instead. If actually wanting empty, use Guid.Empty. +M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. +P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. +M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever. +M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture. +M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture. +M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString. +M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString. +M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead. +M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead. +M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead. +M:Humanizer.InflectorExtensions.Kebaberize(System.String);Humanizer's .Kebaberize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToKebabCase() instead. +P:System.DateTime.Now;Use System.DateTime.UtcNow instead. +P:System.DateTimeOffset.Now;Use System.DateTimeOffset.UtcNow instead. +P:System.DateTimeOffset.DateTime;Use System.DateTimeOffset.UtcDateTime instead. From 05fd343dce7c5ae92a8e007b18cf3deb4baa4a3b Mon Sep 17 00:00:00 2001 From: Macintosh II <95250141+mctaylors@users.noreply.github.com> Date: Tue, 25 Jul 2023 17:53:11 +0300 Subject: [PATCH 2/3] Improved /settingslist + fixed /settings pt.1 (#65) This PR is mainly aimed at improving /settingslist and fixing /settings List of things to do before merging: - [x] #62 - [x] Add the pages feature to /settingslist - [x] Add bullets like these -> ![](https://github.com/TeamOctolings/Boyfriend/assets/95250141/fdf1a3b8-bb64-473d-9f57-bc6e34812811) And since the development has already been taking more than 2 days, I suggest splitting the PR into 2 parts. List of other things that will be in the future PR: - mctaylors#1 - Fix bot not answering when an invalid setting is specified in /settings - Options list for /settings --------- Signed-off-by: Macintosh II <95250141+mctaylors@users.noreply.github.com> --- locale/Messages.resx | 17 +++++++++++++- locale/Messages.ru.resx | 21 ++++++++++++++--- locale/Messages.tt-ru.resx | 17 +++++++++++++- src/Commands/SettingsCommandGroup.cs | 34 +++++++++++++++++++++------- src/Data/Options/BoolOption.cs | 5 ++-- src/Messages.Designer.cs | 30 ++++++++++++++++++++++++ 6 files changed, 109 insertions(+), 15 deletions(-) diff --git a/locale/Messages.resx b/locale/Messages.resx index b701495..72ad974 100644 --- a/locale/Messages.resx +++ b/locale/Messages.resx @@ -168,7 +168,7 @@ Current settings: - + Language @@ -561,4 +561,19 @@ Rename members who attempt to hoist themselves + + page + + + Page not found! + + + There are total pages + + + Next + + + Previous + diff --git a/locale/Messages.ru.resx b/locale/Messages.ru.resx index 22bf3a9..1d703ed 100644 --- a/locale/Messages.ru.resx +++ b/locale/Messages.ru.resx @@ -165,7 +165,7 @@ Текущие настройки: - + Язык @@ -433,8 +433,8 @@ Я не смог найти этого пользователя ни в одном из серверов, в которых я есть. Проверь правильность ID и нахождение пользователя на этом сервере максимум 30 дней назад - Общая роль - + Роль по умолчанию + Добавляет напоминание @@ -561,4 +561,19 @@ Переименовывать участников, которые пытаются поднять себя + + страница + + + Страница не найдена! + + + Всего страниц существует + + + Далее + + + Назад + diff --git a/locale/Messages.tt-ru.resx b/locale/Messages.tt-ru.resx index dca7f71..0fd4ebc 100644 --- a/locale/Messages.tt-ru.resx +++ b/locale/Messages.tt-ru.resx @@ -168,7 +168,7 @@ настройки: - + язык @@ -561,4 +561,19 @@ переобувать шизоидов пытающихся поднять себя в табе + + это страница + + + если я был бы html, я бы сказал 404 + + + ну а если быть точнее, тут всего страниц + + + следующее + + + предыдущее + diff --git a/src/Commands/SettingsCommandGroup.cs b/src/Commands/SettingsCommandGroup.cs index c4ea21b..48d7b0d 100644 --- a/src/Commands/SettingsCommandGroup.cs +++ b/src/Commands/SettingsCommandGroup.cs @@ -68,7 +68,8 @@ public class SettingsCommandGroup : CommandGroup { [RequireDiscordPermission(DiscordPermission.ManageGuild)] [Description("Shows settings list for this server")] [UsedImplicitly] - public async Task ExecuteSettingsListAsync() { + public async Task ExecuteSettingsListAsync( + [Description("Settings list page")] int page) { if (!_context.TryGetContextIDs(out var guildId, out _, out _)) return Result.FromError( new ArgumentNullError(nameof(_context), "Unable to retrieve necessary IDs from command context")); @@ -80,23 +81,40 @@ public class SettingsCommandGroup : CommandGroup { var cfg = await _dataService.GetSettings(guildId, CancellationToken); Messages.Culture = GuildSettings.Language.Get(cfg); - return await SendSettingsListAsync(cfg, currentUser, CancellationToken); + return await SendSettingsListAsync(cfg, currentUser, page, CancellationToken); } - private async Task SendSettingsListAsync(JsonNode cfg, IUser currentUser, CancellationToken ct = default) { + private async Task SendSettingsListAsync(JsonNode cfg, IUser currentUser, int page, CancellationToken ct = default) { var builder = new StringBuilder(); - - foreach (var option in AllOptions) { - builder.Append(Markdown.InlineCode(option.Name)) - .Append(": "); - builder.AppendLine(option.Display(cfg)); + var footer = new StringBuilder(); + const int optionsPerList = 7; + var totalPages = (AllOptions.Length + optionsPerList - 1)/optionsPerList; + for (var i = optionsPerList * page - optionsPerList; i <= optionsPerList * page - 1; i++) { + try { + builder.AppendLine($"Settings{AllOptions[i].Name}".Localized()) + .Append(Markdown.InlineCode(AllOptions[i].Name)) + .Append(": ") + .AppendLine(AllOptions[i].Display(cfg)) + .AppendLine(); + } catch { /* hilariously ignored */ } } + footer.Append($"{Messages.Page} {page}/{totalPages} "); + for (var i = 1; i <= totalPages; i++) footer.Append(i == page ? "●" : "○"); + var embed = new EmbedBuilder().WithSmallTitle(Messages.SettingsListTitle, currentUser) .WithDescription(builder.ToString()) .WithColour(ColorsList.Default) + .WithFooter(footer.ToString()) .Build(); + if (optionsPerList * page - optionsPerList >= AllOptions.Length) { + embed = new EmbedBuilder().WithSmallTitle(Messages.PageNotFound, currentUser) + .WithDescription($"{Messages.PagesAllowed}: {Markdown.Bold(totalPages.ToString())}") + .WithColour(ColorsList.Red) + .Build(); + } + return await _feedbackService.SendContextualEmbedResultAsync(embed, ct); } diff --git a/src/Data/Options/BoolOption.cs b/src/Data/Options/BoolOption.cs index a8ee954..55b846e 100644 --- a/src/Data/Options/BoolOption.cs +++ b/src/Data/Options/BoolOption.cs @@ -19,12 +19,13 @@ public class BoolOption : Option { } private static bool TryParseBool(string from, out bool value) { + from = from.ToLower(); value = false; switch (from) { - case "1" or "y" or "yes" or "д" or "да": + case "true" or "1" or "y" or "yes" or "д" or "да": value = true; return true; - case "0" or "n" or "no" or "н" or "не" or "нет": + case "false" or "0" or "n" or "no" or "н" or "не" or "нет" or "нъет": value = false; return true; default: diff --git a/src/Messages.Designer.cs b/src/Messages.Designer.cs index 42a05be..1f6fbc7 100644 --- a/src/Messages.Designer.cs +++ b/src/Messages.Designer.cs @@ -947,5 +947,35 @@ namespace Boyfriend { return ResourceManager.GetString("SettingIsNow", resourceCulture); } } + + internal static string Page { + get { + return ResourceManager.GetString("Page", resourceCulture); + } + } + + internal static string PageNotFound { + get { + return ResourceManager.GetString("PageNotFound", resourceCulture); + } + } + + internal static string PagesAllowed { + get { + return ResourceManager.GetString("PagesAllowed", resourceCulture); + } + } + + internal static string Next { + get { + return ResourceManager.GetString("Next", resourceCulture); + } + } + + internal static string Previous { + get { + return ResourceManager.GetString("Previous", resourceCulture); + } + } } } From 8f95e4cd2c3fbc7a8937aa39c26aee2eb4fd4c7c Mon Sep 17 00:00:00 2001 From: Macintosh II <95250141+mctaylors@users.noreply.github.com> Date: Tue, 25 Jul 2023 19:20:09 +0300 Subject: [PATCH 3/3] Replace "ToLower" with "ToLowerInvariant" to fix a missed warning (#71) --- src/Data/Options/BoolOption.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Options/BoolOption.cs b/src/Data/Options/BoolOption.cs index 55b846e..e8be77a 100644 --- a/src/Data/Options/BoolOption.cs +++ b/src/Data/Options/BoolOption.cs @@ -19,7 +19,7 @@ public class BoolOption : Option { } private static bool TryParseBool(string from, out bool value) { - from = from.ToLower(); + from = from.ToLowerInvariant(); value = false; switch (from) { case "true" or "1" or "y" or "yes" or "д" or "да":