From 3ef05f8aa7fd92eaeb9249a4edcbbada667be3ed Mon Sep 17 00:00:00 2001 From: Kwoth Date: Thu, 2 May 2024 22:14:25 +0000 Subject: [PATCH] Nuked humanizer. Some of the strings might look worse but the output directory will no longer look terrible. Added stats for todo list command --- src/NadekoBot/GlobalUsings.cs | 1 - .../Administration/Self/SelfService.cs | 2 +- .../UserPunish/UserPunishCommands.cs | 3 +- src/NadekoBot/Modules/Gambling/Gambling.cs | 4 +- .../CommandCooldown/CmdCdsCommands.cs | 4 +- .../Crypto/DefaultStockDataService.cs | 5 +- .../Modules/Utility/Remind/RemindCommands.cs | 6 +-- .../Modules/Utility/Remind/RemindService.cs | 5 +- .../Modules/Utility/Todo/TodoCommands.cs | 51 +++++++++++-------- src/NadekoBot/Modules/Xp/Club/ClubService.cs | 2 +- src/NadekoBot/Modules/Xp/XpService.cs | 4 +- src/NadekoBot/NadekoBot.csproj | 5 -- src/NadekoBot/Program.cs | 3 -- src/NadekoBot/Services/Impl/ImageCache.cs | 2 +- .../Extensions/StringExtensions.cs | 12 ++++- .../_common/Patronage/PatronExtensions.cs | 8 ++- .../_common/Services/Impl/StatsService.cs | 17 +++++-- .../_common/_Extensions/Extensions.cs | 30 +++++++++-- .../strings/responses/responses.en-US.json | 6 ++- 19 files changed, 104 insertions(+), 66 deletions(-) diff --git a/src/NadekoBot/GlobalUsings.cs b/src/NadekoBot/GlobalUsings.cs index fe71f464d..a37de50a7 100644 --- a/src/NadekoBot/GlobalUsings.cs +++ b/src/NadekoBot/GlobalUsings.cs @@ -3,7 +3,6 @@ global using NonBlocking; // packages global using Serilog; -global using Humanizer; // nadekobot global using NadekoBot; diff --git a/src/NadekoBot/Modules/Administration/Self/SelfService.cs b/src/NadekoBot/Modules/Administration/Self/SelfService.cs index 2d40b96ee..578e21eb9 100644 --- a/src/NadekoBot/Modules/Administration/Self/SelfService.cs +++ b/src/NadekoBot/Modules/Administration/Self/SelfService.cs @@ -344,7 +344,7 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService return false; } - if (sr.GetContentLength() > 8.Megabytes().Bytes) + if (sr.GetContentLength() > 8.Megabytes()) { return false; } diff --git a/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs b/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs index d1d6cca36..5604f06be 100644 --- a/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs +++ b/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs @@ -1,6 +1,5 @@ #nullable disable using CommandLine; -using Humanizer.Localisation; using NadekoBot.Common.TypeReaders.Models; using NadekoBot.Modules.Administration.Services; using NadekoBot.Db.Models; @@ -458,7 +457,7 @@ public partial class Administration .AddField(GetText(strs.username), user?.ToString() ?? userId.ToString(), true) .AddField("ID", userId.ToString(), true) .AddField(GetText(strs.duration), - time.Time.Humanize(3, minUnit: TimeUnit.Minute, culture: Culture), + time.Time.ToPrettyStringHm(), true); if (dmFailed) diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index 54de7a1bb..229ee5408 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -396,8 +396,8 @@ public partial class Gambling : GamblingModule ("rps", _, _) => $"Rock Paper Scissors - {subType}", (null, _, _) => null, (_, null, _) => null, - (_, _, ulong userId) => $"{type.Titleize()} - {subType.Titleize()} | [{userId}]", - _ => $"{type.Titleize()} - {subType.Titleize()}" + (_, _, ulong userId) => $"{type} - {subType} | [{userId}]", + _ => $"{type} - {subType}" }; [Cmd] diff --git a/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs b/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs index d045ca647..c04caf472 100644 --- a/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs +++ b/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs @@ -1,5 +1,4 @@ #nullable disable -using Humanizer.Localisation; using Microsoft.EntityFrameworkCore; using NadekoBot.Common.TypeReaders; using NadekoBot.Db; @@ -81,7 +80,6 @@ public partial class Permissions if (--page < 0) return; - var channel = (ITextChannel)ctx.Channel; var localSet = _service.GetCommandCooldowns(ctx.Guild.Id); if (!localSet.Any()) @@ -96,7 +94,7 @@ public partial class Permissions .Page((items, _) => { var output = items.Select(x => - $"{Format.Code(x.CommandName)}: {x.Seconds.Seconds().Humanize(maxUnit: TimeUnit.Second, culture: Culture)}"); + $"{Format.Code(x.CommandName)}: {x.Seconds}s"); return _sender.CreateEmbed() .WithOkColor() diff --git a/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs b/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs index 9bb57c148..6c13bf927 100644 --- a/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs +++ b/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs @@ -105,10 +105,7 @@ public sealed class DefaultStockDataService : IStockDataService, INService .ToList(); } - private static CsvConfiguration _csvConfig = new(CultureInfo.InvariantCulture) - { - PrepareHeaderForMatch = args => args.Header.Humanize(LetterCasing.Title) - }; + private static CsvConfiguration _csvConfig = new(CultureInfo.InvariantCulture); public async Task> GetCandleDataAsync(string query) { diff --git a/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs b/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs index a520fc6e4..51be0ce61 100644 --- a/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs +++ b/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs @@ -1,9 +1,7 @@ #nullable disable -using Humanizer.Localisation; using NadekoBot.Db; using NadekoBot.Modules.Utility.Services; using NadekoBot.Db.Models; -using System.Resources; namespace NadekoBot.Modules.Utility; @@ -118,7 +116,7 @@ public partial class Utility var diff = when - DateTime.UtcNow; embed.AddField( $"#{++i + (page * 10)} {rem.When:HH:mm yyyy-MM-dd} UTC " - + $"(in {diff.Humanize(2, minUnit: TimeUnit.Minute, culture: Culture)})", + + $"(in {diff.ToPrettyStringHm()})", $@"`Target:` {(rem.IsPrivate ? "DM" : "Channel")} `TargetId:` {rem.ChannelId} `Message:` {rem.Message?.TrimTo(50)}"); @@ -212,7 +210,7 @@ public partial class Utility .Confirm($"\u23f0 {GetText(strs.remind( Format.Bold(!isPrivate ? $"<#{targetId}>" : ctx.User.Username), Format.Bold(message), - ts.Humanize(3, minUnit: TimeUnit.Second, culture: Culture), + ts.ToPrettyStringHm(), gTime, gTime))}") .SendAsync(); diff --git a/src/NadekoBot/Modules/Utility/Remind/RemindService.cs b/src/NadekoBot/Modules/Utility/Remind/RemindService.cs index c7510f350..603c8c932 100644 --- a/src/NadekoBot/Modules/Utility/Remind/RemindService.cs +++ b/src/NadekoBot/Modules/Utility/Remind/RemindService.cs @@ -11,8 +11,7 @@ namespace NadekoBot.Modules.Utility.Services; public class RemindService : INService, IReadyExecutor, IRemindService { private readonly Regex _regex = - new( - @"^(?:(?:at|on(?:\sthe)?)?\s*(?(?:\d{2}:\d{2}\s)?\d{1,2}\.\d{1,2}(?:\.\d{2,4})?)|(?:in\s?)?\s*(?:(?\d+)(?:\s?(?:months?|mos?),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:weeks?|w),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:days?|d),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:hours?|h),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:minutes?|mins?|m),?))?)\s+(?:to:?\s+)?(?(?:\r\n|[\r\n]|.)+)", + new(@"^(?:(?:at|on(?:\sthe)?)?\s*(?(?:\d{2}:\d{2}\s)?\d{1,2}\.\d{1,2}(?:\.\d{2,4})?)|(?:in\s?)?\s*(?:(?\d+)(?:\s?(?:months?|mos?),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:weeks?|w),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:days?|d),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:hours?|h),?))?(?:(?:\sand\s|\s*)?(?\d+)(?:\s?(?:minutes?|mins?|m),?))?)\s+(?:to:?\s+)?(?(?:\r\n|[\r\n]|.)+)", RegexOptions.Compiled | RegexOptions.Multiline); private readonly DiscordSocketClient _client; @@ -62,7 +61,7 @@ public class RemindService : INService, IReadyExecutor, IRemindService Log.Information("Executing {ReminderCount} reminders", reminders.Count); - // make groups of 5, with 1.5 second inbetween each one to ensure against ratelimits + // make groups of 5, with 1.5 second in between each one to ensure against ratelimits foreach (var group in reminders.Chunk(5)) { var executedReminders = group.ToList(); diff --git a/src/NadekoBot/Modules/Utility/Todo/TodoCommands.cs b/src/NadekoBot/Modules/Utility/Todo/TodoCommands.cs index f1445fdfb..008a4f2ad 100644 --- a/src/NadekoBot/Modules/Utility/Todo/TodoCommands.cs +++ b/src/NadekoBot/Modules/Utility/Todo/TodoCommands.cs @@ -44,7 +44,26 @@ public partial class Utility return; } - await ShowTodosAsync(todos); + await Response() + .Paginated() + .Items(todos) + .PageSize(9) + .AddFooter(false) + .Page((items, _) => + { + var eb = _sender.CreateEmbed() + .WithOkColor() + .WithTitle(GetText(strs.todo_list)); + + ShowTodoItem(items, eb); + + eb.WithFooter(GetText(strs.todo_stats(todos.Length, + todos.Count(x => x.IsDone), + todos.Count(x => !x.IsDone)))); + + return eb; + }) + .SendAsync(); } @@ -81,23 +100,6 @@ public partial class Utility } - private Task ShowTodosAsync(TodoModel[] todos) - => Response() - .Paginated() - .Items(todos) - .PageSize(9) - .Page((items, _) => - { - var eb = _sender.CreateEmbed() - .WithOkColor() - .WithTitle(GetText(strs.todo_list)); - - ShowTodoItem(items, eb); - - return eb; - }) - .SendAsync(); - private static void ShowTodoItem(IReadOnlyCollection todos, EmbedBuilder eb) { var sb = new StringBuilder(); @@ -155,8 +157,8 @@ public partial class Utility .Page((items, _) => { var eb = _sender.CreateEmbed() - .WithTitle(GetText(strs.todo_archive_list)) - .WithOkColor(); + .WithTitle(GetText(strs.todo_archive_list)) + .WithOkColor(); foreach (var archivedList in items) { @@ -182,14 +184,19 @@ public partial class Utility .Paginated() .Items(list.Items) .PageSize(9) + .AddFooter(false) .Page((items, _) => { var eb = _sender.CreateEmbed() - .WithOkColor() - .WithTitle(GetText(strs.todo_list)); + .WithOkColor() + .WithTitle(GetText(strs.todo_archived_list)); ShowTodoItem(items, eb); + eb.WithFooter(GetText(strs.todo_stats(list.Items.Count, + list.Items.Count(x => x.IsDone), + list.Items.Count(x => !x.IsDone)))); + return eb; }) .SendAsync(); diff --git a/src/NadekoBot/Modules/Xp/Club/ClubService.cs b/src/NadekoBot/Modules/Xp/Club/ClubService.cs index b7c52d7b1..e31fa1bb6 100644 --- a/src/NadekoBot/Modules/Xp/Club/ClubService.cs +++ b/src/NadekoBot/Modules/Xp/Club/ClubService.cs @@ -110,7 +110,7 @@ public class ClubService : INService, IClubService if (!temp.IsImage()) return SetClubIconResult.InvalidFileType; - if (temp.GetContentLength() > 5.Megabytes().Bytes) + if (temp.GetContentLength() > 5.Megabytes()) return SetClubIconResult.TooLarge; } diff --git a/src/NadekoBot/Modules/Xp/XpService.cs b/src/NadekoBot/Modules/Xp/XpService.cs index 8662dcff9..96d235c8d 100644 --- a/src/NadekoBot/Modules/Xp/XpService.cs +++ b/src/NadekoBot/Modules/Xp/XpService.cs @@ -127,7 +127,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand { _ = Task.Run(() => _levelUpQueue.RunAsync()); - using var timer = new PeriodicTimer(5.Seconds()); + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(5)); while (await timer.WaitForNextTickAsync()) { await UpdateXp(); @@ -1364,7 +1364,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand using (var http = _httpFactory.CreateClient()) using (var temp = await http.GetAsync(imgUrl, HttpCompletionOption.ResponseHeadersRead)) { - if (!temp.IsImage() || temp.GetContentLength() > 11.Megabytes().Bytes) + if (!temp.IsImage() || temp.GetContentLength() > 11 * 1024 * 1024) return; var imgData = await temp.Content.ReadAsByteArrayAsync(); diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index 4df09c0ea..64b9a5bb5 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -77,11 +77,6 @@ - - all - True - - diff --git a/src/NadekoBot/Program.cs b/src/NadekoBot/Program.cs index 9587d6028..53b8fcde5 100644 --- a/src/NadekoBot/Program.cs +++ b/src/NadekoBot/Program.cs @@ -1,6 +1,3 @@ -using Humanizer.Localisation; -using System.Resources; - var pid = Environment.ProcessId; var shardId = 0; diff --git a/src/NadekoBot/Services/Impl/ImageCache.cs b/src/NadekoBot/Services/Impl/ImageCache.cs index 6c3292416..0b8c24e5f 100644 --- a/src/NadekoBot/Services/Impl/ImageCache.cs +++ b/src/NadekoBot/Services/Impl/ImageCache.cs @@ -35,7 +35,7 @@ public sealed class ImageCache : IImageCache, INService var bytes = await http.GetByteArrayAsync(url); return bytes; }, - expiry: 48.Hours()); + expiry: TimeSpan.FromHours(48)); private async Task GetRandomImageDataAsync(Uri[] urls) { diff --git a/src/NadekoBot/_common/Abstractions/Extensions/StringExtensions.cs b/src/NadekoBot/_common/Abstractions/Extensions/StringExtensions.cs index e0289c83b..94be111fa 100644 --- a/src/NadekoBot/_common/Abstractions/Extensions/StringExtensions.cs +++ b/src/NadekoBot/_common/Abstractions/Extensions/StringExtensions.cs @@ -29,7 +29,17 @@ public static class StringExtensions => Regex.Replace(input, "<.*?>", string.Empty); public static string? TrimTo(this string? str, int maxLength, bool hideDots = false) - => hideDots ? str?.Truncate(maxLength, string.Empty) : str?.Truncate(maxLength); + { + if (hideDots) + { + return str?.Substring(0, maxLength); + } + + if (str is null || str.Length <= maxLength) + return str; + + return string.Concat(str.AsSpan(0, maxLength - 1), "…"); + } public static string ToTitleCase(this string str) { diff --git a/src/NadekoBot/_common/Patronage/PatronExtensions.cs b/src/NadekoBot/_common/Patronage/PatronExtensions.cs index 1b261fce1..b5e29d52b 100644 --- a/src/NadekoBot/_common/Patronage/PatronExtensions.cs +++ b/src/NadekoBot/_common/Patronage/PatronExtensions.cs @@ -9,7 +9,13 @@ public static class PatronExtensions }; public static string ToFullName(this QuotaPer per) - => per.Humanize(LetterCasing.LowerCase); + => per switch + { + QuotaPer.PerDay => "per day", + QuotaPer.PerHour => "per hour", + QuotaPer.PerMonth => "per month", + _ => "Unknown", + }; public static DateTime DayOfNextMonth(this DateTime date, int day) { diff --git a/src/NadekoBot/_common/Services/Impl/StatsService.cs b/src/NadekoBot/_common/Services/Impl/StatsService.cs index aaeefee05..1b6dc1bc5 100644 --- a/src/NadekoBot/_common/Services/Impl/StatsService.cs +++ b/src/NadekoBot/_common/Services/Impl/StatsService.cs @@ -1,5 +1,4 @@ #nullable disable -using Humanizer.Localisation; using NadekoBot.Common.ModuleBehaviors; using System.Diagnostics; @@ -178,13 +177,23 @@ public sealed class StatsService : IStatsService, IReadyExecutor, INService public string GetUptimeString(string separator = ", ") { var time = GetUptime(); - return time.Humanize(3, maxUnit: TimeUnit.Day, minUnit: TimeUnit.Minute); + + if (time.Days > 0) + return $"{time.Days}d {time.Hours}h {time.Minutes}m"; + + if (time.Hours > 0) + return $"{time.Hours}h {time.Minutes}m"; + + if (time.Minutes > 0) + return $"{time.Minutes}m {time.Seconds}s"; + + return $"{time.Seconds}s"; } - + public double GetPrivateMemoryMegabytes() { _currentProcess.Refresh(); - return _currentProcess.PrivateMemorySize64 / 1.Megabytes().Bytes; + return _currentProcess.PrivateMemorySize64 / 1.Megabytes(); } public GuildInfo GetGuildInfo(string name) diff --git a/src/NadekoBot/_common/_Extensions/Extensions.cs b/src/NadekoBot/_common/_Extensions/Extensions.cs index 2d3dc1e04..19c965e35 100644 --- a/src/NadekoBot/_common/_Extensions/Extensions.cs +++ b/src/NadekoBot/_common/_Extensions/Extensions.cs @@ -1,4 +1,3 @@ -using Humanizer.Localisation; using System.Diagnostics; using System.Globalization; using System.Text.Json; @@ -11,7 +10,7 @@ public static class Extensions { private static readonly Regex _urlRegex = new(@"^(https?|ftp)://(?[^\s/$.?#].[^\s]*)$", RegexOptions.Compiled); - + /// /// Converts to /// @@ -51,7 +50,7 @@ public static class Extensions public static ulong[] GetGuildIds(this DiscordSocketClient client) => client.Guilds - .Map(x => x.Id); + .Map(x => x.Id); /// /// Generates a string in the format HHH:mm if timespan is >= 2m. @@ -60,7 +59,30 @@ public static class Extensions /// Timespan to convert to string /// Formatted duration string public static string ToPrettyStringHm(this TimeSpan span) - => span.Humanize(2, minUnit: TimeUnit.Second); + { + if(span > TimeSpan.FromHours(24)) + return $"{span.Days:00}d:{span.Hours:00}h"; + + if (span > TimeSpan.FromMinutes(2)) + return $"{span.Hours:00}h:{span.Minutes:00}m"; + + return $"{span.Minutes:00}m:{span.Seconds:00}s"; + } + + public static double Megabytes(this int mb) + => mb * 1024d * 1024; + + public static TimeSpan Hours(this int hours) + => TimeSpan.FromHours(hours); + + public static TimeSpan Minutes(this int minutes) + => TimeSpan.FromMinutes(minutes); + + public static TimeSpan Days(this int days) + => TimeSpan.FromDays(days); + + public static TimeSpan Seconds(this int seconds) + => TimeSpan.FromSeconds(seconds); public static bool TryGetUrlPath(this string input, out string path) { diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index f0303446e..47f5500ed 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -1080,12 +1080,14 @@ "giveaway_list": "List of active giveways", "todo_list_empty": "Your todo list is empty." , "todo_list": "Todo List", - "todo_add_max_limit": "You've reached the maximum amount of todos you can have.", + "todo_stats": "{0} items | {1} completed | {2} remaining", + "todo_add_max_limit": "You'reached the maximum amount of todos you can have.", "todo_not_found": "Todo not found.", "todo_cleared": "All unarchived todos have been cleared.", "todo_no_todos": "There are no todos in your todo list.", "todo_archive_max_limit": "You've reached the maximum amount of archived todos you can have.", "todo_archive_empty": "You have no archived todos.", "todo_archive_list": "Archived Todo Lists", - "todo_archive_not_found": "Archived todo list not found." + "todo_archive_not_found": "Archived todo list not found.", + "todo_archived_list": "Archived Todo List" }