From 042007626d96bce23387e72d81c82bc946dfde64 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Tue, 10 Mar 2020 22:02:59 -0500 Subject: [PATCH 01/11] Implement help command basics --- .../Attributes/ExamplesAttribute.cs | 14 ++ src/Miunie.Discord/CommandHandler.cs | 9 ++ .../CommandModules/HelpCommand.cs | 35 +++++ src/Miunie.Discord/Embeds/EmbedConstructor.cs | 13 ++ .../Extensions/CommandInfoExtensions.cs | 16 +++ src/Miunie.Discord/Services/HelpService.cs | 126 ++++++++++++++++++ 6 files changed, 213 insertions(+) create mode 100644 src/Miunie.Discord/Attributes/ExamplesAttribute.cs create mode 100644 src/Miunie.Discord/CommandModules/HelpCommand.cs create mode 100644 src/Miunie.Discord/Extensions/CommandInfoExtensions.cs create mode 100644 src/Miunie.Discord/Services/HelpService.cs diff --git a/src/Miunie.Discord/Attributes/ExamplesAttribute.cs b/src/Miunie.Discord/Attributes/ExamplesAttribute.cs new file mode 100644 index 0000000..30516ea --- /dev/null +++ b/src/Miunie.Discord/Attributes/ExamplesAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace Miunie.Discord.Attributes +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class ExamplesAttribute : Attribute + { + public ExamplesAttribute(params string[] examples) + { + Examples = examples; + } + public string[] Examples { get; } + } +} diff --git a/src/Miunie.Discord/CommandHandler.cs b/src/Miunie.Discord/CommandHandler.cs index c1cf2d2..047ff82 100644 --- a/src/Miunie.Discord/CommandHandler.cs +++ b/src/Miunie.Discord/CommandHandler.cs @@ -7,6 +7,11 @@ using System; using System.Reflection; using System.Threading.Tasks; +using Discord; +using System.Linq; +using System.Collections.Generic; +using Miunie.Discord.Attributes; +using System.Text; namespace Miunie.Discord { @@ -34,6 +39,10 @@ public async Task InitializeAsync() _discord.Client.MessageReceived += HandleCommandAsync; await _commandService.AddModulesAsync(Assembly.GetExecutingAssembly(), _services); } + + public HelpService GetHelpService() + => new HelpService(_commandService); + private async Task HandleCommandAsync(SocketMessage s) { if (!(s is SocketUserMessage msg)) diff --git a/src/Miunie.Discord/CommandModules/HelpCommand.cs b/src/Miunie.Discord/CommandModules/HelpCommand.cs new file mode 100644 index 0000000..a49bc5b --- /dev/null +++ b/src/Miunie.Discord/CommandModules/HelpCommand.cs @@ -0,0 +1,35 @@ +using Discord; +using Discord.Commands; +using Discord.WebSocket; +using Miunie.Core; +using Miunie.Discord.Convertors; +using System.Threading.Tasks; + +// TODO: remove HelpEntry and HelpSection, as IDiscord can handle +// sending messages. +namespace Miunie.Discord.CommandModules +{ + public class HelpCommand : ModuleBase + { + private readonly EntityConvertor _entityConvertor; + private readonly HelpService _helpService; + + public HelpCommand(CommandHandler commandHandler, EntityConvertor entityConvertor) + { + _helpService = commandHandler.GetHelpService(); + _entityConvertor = entityConvertor; + } + + [Command("help")] + public async Task GetHelp() + { + await _helpService.ShowDefaultHelpAsync(Context.Channel); + } + + [Command("help")] + public async Task GetHelp([Remainder]string input) + { + await _helpService.ShowCommandHelpAsync(Context.Channel, input); + } + } +} diff --git a/src/Miunie.Discord/Embeds/EmbedConstructor.cs b/src/Miunie.Discord/Embeds/EmbedConstructor.cs index 4892845..9eb9f5f 100644 --- a/src/Miunie.Discord/Embeds/EmbedConstructor.cs +++ b/src/Miunie.Discord/Embeds/EmbedConstructor.cs @@ -24,6 +24,19 @@ private static string FormatReputationType(ReputationType type) throw new ArgumentException("Unknown ReputationType."); } } + + public static Embed CreateHelpEmbed(HelpResult result) + { + EmbedBuilder builder = new EmbedBuilder(); + + if (!string.IsNullOrWhiteSpace(result.Title)) + builder.WithTitle(result.Title); + + foreach (HelpSection section in result.Sections) + builder.AddField(section.Title, section.Content, false); + + return builder.Build(); + } public static Embed CreateReputationLog(IEnumerable entries, int index, ILanguageProvider lang) { diff --git a/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs b/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs new file mode 100644 index 0000000..91b23b0 --- /dev/null +++ b/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs @@ -0,0 +1,16 @@ +using Discord.Commands; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Miunie.Discord +{ + internal static class CommandInfoExtensions + { + internal static TAttribute FindAttribute(this CommandInfo command) where TAttribute : Attribute + => command.Attributes.FirstOrDefault(x => x is TAttribute) as TAttribute; + + internal static IEnumerable FindAttributes(this CommandInfo command) where TAttribute : Attribute + => command.Attributes.Where(x => x is TAttribute).Select(x => x as TAttribute); + } +} diff --git a/src/Miunie.Discord/Services/HelpService.cs b/src/Miunie.Discord/Services/HelpService.cs new file mode 100644 index 0000000..d1875dd --- /dev/null +++ b/src/Miunie.Discord/Services/HelpService.cs @@ -0,0 +1,126 @@ +using Discord; +using Discord.Commands; +using Discord.WebSocket; +using Miunie.Core; +using Miunie.Discord.Attributes; +using Miunie.Discord.Embeds; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Miunie.Discord +{ + public class HelpSection + { + public HelpSection(string title, string content) + { + Title = title; + Content = content; + } + + public string Title { get; } + public string Content { get; } + } + + public class HelpResult + { + public HelpResult() + { + + } + + public string Title { get; set; } + public List Sections { get; } = new List(); + } + + public class HelpService + { + private readonly CommandService _commandService; + + public HelpService(CommandService commandService) + { + _commandService = commandService; + } + + public HelpResult GetDefault() + { + HelpResult entry = new HelpResult(); + entry.Title = "**HELP MENU**"; + + foreach (ModuleInfo module in _commandService.Modules) + { + string title = module.Name; + string content = string.Join(" ", module.Commands.GroupBy(x => x.Name).Select(x => $"`{x.Key}`")); + entry.Sections.Add(new HelpSection(title, content)); + } + + return entry; + } + + private IEnumerable GetCommands(string input) + { + SearchResult result = _commandService.Search(input); + + if (!result.IsSuccess) + throw new Exception(result.ErrorReason); + + return result.Commands.Select(x => x.Command); + } + + private string GetSectionTitle(CommandInfo command) + => $"{command.Name} " + + $"{string.Join(" ", command.Parameters.OrderBy(x => x.IsOptional).Select(x => $"{(x.IsOptional ? $"[{x.Name}]" : $"<{x.Name}>")}"))}"; + + private string GetExamples(CommandInfo command) + { + string[] examples = command.FindAttribute()?.Examples; + + if (examples != null) + { + return string.Join(", ", examples.Select(x => $"`{x}`")); + } + + return "No examples provided."; + } + + private string GetSummary(CommandInfo command) + => (command.FindAttribute()?.Text) ?? "No summary was provided."; + + public HelpResult Search(string input) + { + HelpResult entry = new HelpResult(); + + foreach (CommandInfo command in GetCommands(input)) + { + string title = GetSectionTitle(command); + + StringBuilder content = new StringBuilder(); + + content.Append("**Summary**: "); + string summary = GetSummary(command); + content.AppendLine(summary); + content.AppendLine(); + + content.Append("**Examples**: "); + string examples = GetExamples(command); + content.Append(examples); + + entry.Sections.Add(new HelpSection(title, content.ToString())); + } + + return entry; + } + + public async Task ShowDefaultHelpAsync(ISocketMessageChannel channel) + { + await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(GetDefault())); + } + + public async Task ShowCommandHelpAsync(ISocketMessageChannel channel, string input) + { + await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(Search(input))); + } + } +} From 6dae33fd431ffc3aa17e4ce06c3bbe82def2892c Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Wed, 11 Mar 2020 00:33:37 -0500 Subject: [PATCH 02/11] Update all dependencies and StyleCop pass This ensures that all projects within Miunie are now set to the latest .NET Core, .NET Standard, and C# Language versions. All dependencies specified in Miunie were updated to their most recent counterparts. All classes mentioned were modified to follow StyleCop standards. One readonly value was made in EmbedConstructor to simplify .WithColor() when creating new embeds. All existing summaries were moved into HelpStrings.resx. HelpService now attempts to fetch a summary for the specified ID in SummaryAttribute for a CommandInfo, and will now use ILanguageProvider for default string values. --- src/Miunie.Avalonia/Miunie.Avalonia.csproj | 10 +- .../Miunie.ConsoleApp.csproj | 2 +- .../Miunie.Core.XUnit.Tests.csproj | 12 +- src/Miunie.Core/Entities/PhraseKey.cs | 5 + src/Miunie.Core/Miunie.Core.csproj | 4 +- src/Miunie.Core/Strings.Designer.cs | 45 ++++ src/Miunie.Core/Strings.resx | 20 ++ .../Adapters/DiscordMessagesAdapter.cs | 1 - .../Attributes/ExamplesAttribute.cs | 18 +- src/Miunie.Discord/CommandHandler.cs | 10 +- .../CommandModules/HelpCommand.cs | 31 ++- .../CommandModules/MiscCommands.cs | 2 + .../CommandModules/ProfileCommand.cs | 7 + .../CommandModules/RemoteRepositoryCommand.cs | 3 +- .../CommandModules/TimeCommand.cs | 7 + src/Miunie.Discord/Embeds/EmbedConstructor.cs | 44 ++-- src/Miunie.Discord/Entities/HelpResult.cs | 26 +++ src/Miunie.Discord/Entities/HelpSection.cs | 30 +++ .../Extensions/CommandInfoExtensions.cs | 23 +- src/Miunie.Discord/HelpStrings.Designer.cs | 207 ++++++++++++++++++ src/Miunie.Discord/HelpStrings.resx | 184 ++++++++++++++++ src/Miunie.Discord/Miunie.Discord.csproj | 18 +- src/Miunie.Discord/Services/HelpService.cs | 143 ++++++------ .../TypeReaders/MiunieUserTypeReader.cs | 2 +- .../Miunie.InversionOfControl.csproj | 3 +- .../Miunie.LiteDbStorage.csproj | 7 +- src/Miunie.Logger/Miunie.Logger.csproj | 3 +- .../Miunie.SystemInfrastructure.csproj | 3 +- 28 files changed, 729 insertions(+), 141 deletions(-) create mode 100644 src/Miunie.Discord/Entities/HelpResult.cs create mode 100644 src/Miunie.Discord/Entities/HelpSection.cs create mode 100644 src/Miunie.Discord/HelpStrings.Designer.cs create mode 100644 src/Miunie.Discord/HelpStrings.resx diff --git a/src/Miunie.Avalonia/Miunie.Avalonia.csproj b/src/Miunie.Avalonia/Miunie.Avalonia.csproj index 3903f86..a599fd3 100644 --- a/src/Miunie.Avalonia/Miunie.Avalonia.csproj +++ b/src/Miunie.Avalonia/Miunie.Avalonia.csproj @@ -1,8 +1,8 @@  WinExe - netcoreapp3.0 - 8.0 + netcoreapp3.1 + latest ../.ruleset @@ -16,9 +16,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj b/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj index 6b3aaec..f48230b 100644 --- a/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj +++ b/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj b/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj index 542fe0c..0f1d3b0 100644 --- a/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj +++ b/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj @@ -5,14 +5,18 @@ false ../.ruleset + latest - + - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Miunie.Core/Entities/PhraseKey.cs b/src/Miunie.Core/Entities/PhraseKey.cs index d66d469..1e6b6cd 100644 --- a/src/Miunie.Core/Entities/PhraseKey.cs +++ b/src/Miunie.Core/Entities/PhraseKey.cs @@ -23,6 +23,7 @@ public enum PhraseKey SHOW_REMOTE_REPO, USER_EMBED_TITLE, USER_EMBED_NAME_TITLE, + USER_EMBED_HELP_TITLE, USER_EMBED_IS_BOT, USER_EMBED_IS_HUMAN, USER_EMBED_REALNESS_TITLE, @@ -54,6 +55,10 @@ public enum PhraseKey INCORRECT_VERB, REPUTATION_TAKEN_BOT, REPUTATION_GIVEN_BOT, + HELP_EXAMPLE_EMPTY, + HELP_EXAMPLE_TITLE, + HELP_SUMMARY_EMPTY, + HELP_SUMMARY_TITLE, GPL3_NOTICE } } diff --git a/src/Miunie.Core/Miunie.Core.csproj b/src/Miunie.Core/Miunie.Core.csproj index 582cf88..64aee3d 100644 --- a/src/Miunie.Core/Miunie.Core.csproj +++ b/src/Miunie.Core/Miunie.Core.csproj @@ -1,9 +1,9 @@  - netstandard2.0 + netstandard2.1 ../.ruleset - 8.0 + latest diff --git a/src/Miunie.Core/Strings.Designer.cs b/src/Miunie.Core/Strings.Designer.cs index 1c1fa71..7f368a3 100644 --- a/src/Miunie.Core/Strings.Designer.cs +++ b/src/Miunie.Core/Strings.Designer.cs @@ -131,6 +131,42 @@ public static string GUILD_EMBED_TITLE { } } + /// + /// Looks up a localized string similar to No examples were provided.. + /// + public static string HELP_EXAMPLE_EMPTY { + get { + return ResourceManager.GetString("HELP_EXAMPLE_EMPTY", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to **Examples**: . + /// + public static string HELP_EXAMPLE_TITLE { + get { + return ResourceManager.GetString("HELP_EXAMPLE_TITLE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No summary was provided.. + /// + public static string HELP_SUMMARY_EMPTY { + get { + return ResourceManager.GetString("HELP_SUMMARY_EMPTY", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to **Summary**: . + /// + public static string HELP_SUMMARY_TITLE { + get { + return ResourceManager.GetString("HELP_SUMMARY_TITLE", resourceCulture); + } + } + /// /// Looks up a localized string similar to You better start making sense with other than '{0}'{{OR}} ///Come again, I don't understand '{0}'{{OR}} @@ -318,6 +354,15 @@ public static string USER_EMBED_CREATED_AT_TITLE { } } + /// + /// Looks up a localized string similar to **HELP MENU**. + /// + public static string USER_EMBED_HELP_TITLE { + get { + return ResourceManager.GetString("USER_EMBED_HELP_TITLE", resourceCulture); + } + } + /// /// Looks up a localized string similar to _A software person._{{OR}} ///_A bot._ :robot:{{OR}} diff --git a/src/Miunie.Core/Strings.resx b/src/Miunie.Core/Strings.resx index b8e7f28..419c355 100644 --- a/src/Miunie.Core/Strings.resx +++ b/src/Miunie.Core/Strings.resx @@ -158,6 +158,22 @@ Source code available at: {1} **ABOUT THIS SERVER** No formatting options. + + No examples were provided. + No formatting options. + + + **Examples**: + No formatting options. + + + No summary was provided. + No formatting options. + + + **Summary**: + No formatting options. + You better start making sense with other than '{0}'{{OR}} Come again, I don't understand '{0}'{{OR}} @@ -258,6 +274,10 @@ What are you trying to say with {0} {1} :calendar_spiral: Creation date No formatting options. + + **HELP MENU** + No formatting options. + _A software person._{{OR}} _A bot._ :robot:{{OR}} diff --git a/src/Miunie.Discord/Adapters/DiscordMessagesAdapter.cs b/src/Miunie.Discord/Adapters/DiscordMessagesAdapter.cs index 08275a3..d1c906c 100644 --- a/src/Miunie.Discord/Adapters/DiscordMessagesAdapter.cs +++ b/src/Miunie.Discord/Adapters/DiscordMessagesAdapter.cs @@ -14,7 +14,6 @@ // along with Miunie. If not, see . using Discord.WebSocket; -using Miunie.Core; using Miunie.Core.Discord; using Miunie.Core.Entities; using Miunie.Core.Entities.Discord; diff --git a/src/Miunie.Discord/Attributes/ExamplesAttribute.cs b/src/Miunie.Discord/Attributes/ExamplesAttribute.cs index 30516ea..e03df55 100644 --- a/src/Miunie.Discord/Attributes/ExamplesAttribute.cs +++ b/src/Miunie.Discord/Attributes/ExamplesAttribute.cs @@ -1,4 +1,19 @@ -using System; +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + +using System; namespace Miunie.Discord.Attributes { @@ -9,6 +24,7 @@ public ExamplesAttribute(params string[] examples) { Examples = examples; } + public string[] Examples { get; } } } diff --git a/src/Miunie.Discord/CommandHandler.cs b/src/Miunie.Discord/CommandHandler.cs index 9d13034..c0bfe3f 100644 --- a/src/Miunie.Discord/CommandHandler.cs +++ b/src/Miunie.Discord/CommandHandler.cs @@ -18,16 +18,12 @@ using Miunie.Core.Configuration; using Miunie.Core.Entities.Discord; using Miunie.Core.Logging; +using Miunie.Core.Providers; using Miunie.Discord.Convertors; using Miunie.Discord.TypeReaders; using System; using System.Reflection; using System.Threading.Tasks; -using Discord; -using System.Linq; -using System.Collections.Generic; -using Miunie.Discord.Attributes; -using System.Text; namespace Miunie.Discord { @@ -58,8 +54,8 @@ public async Task InitializeAsync() _ = await _commandService.AddModulesAsync(Assembly.GetExecutingAssembly(), _services); } - public HelpService GetHelpService() - => new HelpService(_commandService); + public HelpService GetHelpService(ILanguageProvider lang) + => new HelpService(_commandService, lang); private async Task HandleCommandAsync(SocketMessage s) { diff --git a/src/Miunie.Discord/CommandModules/HelpCommand.cs b/src/Miunie.Discord/CommandModules/HelpCommand.cs index a49bc5b..753e7e2 100644 --- a/src/Miunie.Discord/CommandModules/HelpCommand.cs +++ b/src/Miunie.Discord/CommandModules/HelpCommand.cs @@ -1,32 +1,43 @@ -using Discord; +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + using Discord.Commands; -using Discord.WebSocket; -using Miunie.Core; -using Miunie.Discord.Convertors; +using Miunie.Core.Providers; using System.Threading.Tasks; -// TODO: remove HelpEntry and HelpSection, as IDiscord can handle -// sending messages. namespace Miunie.Discord.CommandModules { + [Name("Help")] public class HelpCommand : ModuleBase { - private readonly EntityConvertor _entityConvertor; private readonly HelpService _helpService; - public HelpCommand(CommandHandler commandHandler, EntityConvertor entityConvertor) + public HelpCommand(CommandHandler commandHandler, ILanguageProvider lang) { - _helpService = commandHandler.GetHelpService(); - _entityConvertor = entityConvertor; + _helpService = commandHandler.GetHelpService(lang); } [Command("help")] + [Summary("HELP_HELP")] public async Task GetHelp() { await _helpService.ShowDefaultHelpAsync(Context.Channel); } [Command("help")] + [Summary("HELP_HELP_SEARCH")] public async Task GetHelp([Remainder]string input) { await _helpService.ShowCommandHelpAsync(Context.Channel, input); diff --git a/src/Miunie.Discord/CommandModules/MiscCommands.cs b/src/Miunie.Discord/CommandModules/MiscCommands.cs index 18d1afa..74dfa03 100644 --- a/src/Miunie.Discord/CommandModules/MiscCommands.cs +++ b/src/Miunie.Discord/CommandModules/MiscCommands.cs @@ -21,6 +21,7 @@ namespace Miunie.Discord.CommandModules { + [Name("Misc")] public class MiscCommands : ModuleBase { private readonly MiscService _service; @@ -33,6 +34,7 @@ public MiscCommands(MiscService service, EntityConvertor entityConvertor) } [Command("what do you think?")] + [Summary("HELP_WHAT_DO_YOU_THINK")] public async Task SendRandomYesNoMaybeAnswer() { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); diff --git a/src/Miunie.Discord/CommandModules/ProfileCommand.cs b/src/Miunie.Discord/CommandModules/ProfileCommand.cs index 12584e6..17c81a7 100644 --- a/src/Miunie.Discord/CommandModules/ProfileCommand.cs +++ b/src/Miunie.Discord/CommandModules/ProfileCommand.cs @@ -22,6 +22,7 @@ namespace Miunie.Discord.CommandModules { + [Name("Profile")] public class ProfileCommand : ModuleBase { private readonly EntityConvertor _entityConvertor; @@ -34,6 +35,7 @@ public ProfileCommand(EntityConvertor entityConvertor, ProfileService profileSer } [Command("profile")] + [Summary("HELP_PROFILE")] public async Task ShowProfileAsync(MiunieUser user = null) { if (user is null) @@ -46,6 +48,7 @@ public async Task ShowProfileAsync(MiunieUser user = null) } [Command("rep log")] + [Summary("HELP_REP_LOG")] public async Task ShowReputationLogAsync(int page = 1) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -54,6 +57,7 @@ public async Task ShowReputationLogAsync(int page = 1) } [Command("rep log for")] + [Summary("HELP_REP_LOG_FOR")] public async Task ShowReputationLogAsync(MiunieUser user, int page = 1) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -62,6 +66,7 @@ public async Task ShowReputationLogAsync(MiunieUser user, int page = 1) } [Command("+rep")] + [Summary("HELP_PLUS_REP")] public async Task AddReputationAsync(MiunieUser user) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -70,6 +75,7 @@ public async Task AddReputationAsync(MiunieUser user) } [Command("-rep")] + [Summary("HELP_MINUS_REP")] public async Task RemoveReputationAsync(MiunieUser user) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -78,6 +84,7 @@ public async Task RemoveReputationAsync(MiunieUser user) } [Command("guild")] + [Summary("HELP_GUILD")] public async Task ShowGuildInfoAsync() { var guild = _entityConvertor.ConvertGuild(Context.Guild); diff --git a/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs b/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs index 113a72a..3c78da5 100644 --- a/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs +++ b/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs @@ -21,6 +21,7 @@ namespace Miunie.Discord.CommandModules { + [Name("Remote Repository")] public class RemoteRepositoryCommand : ModuleBase { private readonly RemoteRepositoryService _remoteRepoService; @@ -33,7 +34,7 @@ public RemoteRepositoryCommand(RemoteRepositoryService remoteRepoService, Entity } [Command("repo")] - [Summary("Shows the official remote repository hosting the code of this bot")] + [Summary("HELP_REPO")] public async Task ShowRepository() { var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); diff --git a/src/Miunie.Discord/CommandModules/TimeCommand.cs b/src/Miunie.Discord/CommandModules/TimeCommand.cs index 94d615a..6c1eeb8 100644 --- a/src/Miunie.Discord/CommandModules/TimeCommand.cs +++ b/src/Miunie.Discord/CommandModules/TimeCommand.cs @@ -24,6 +24,7 @@ namespace Miunie.Discord.CommandModules { + [Name("Time")] public class TimeCommand : ModuleBase { private readonly TimeService _service; @@ -36,6 +37,7 @@ public TimeCommand(TimeService service, EntityConvertor entityConvertor) } [Command("time for")] + [Summary("HELP_TIME_FOR")] public async Task ShowTimeForUser(MiunieUser user) { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); @@ -43,6 +45,7 @@ public async Task ShowTimeForUser(MiunieUser user) } [Command("time for")] + [Summary("HELP_TIME_FOR_OFFSET")] public async Task ShowTimeForUserWithOffset(MiunieUser user, string verb, int units, string timeframe) { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); @@ -50,6 +53,7 @@ public async Task ShowTimeForUserWithOffset(MiunieUser user, string verb, int un } [Command("time get")] + [Summary("HELP_TIME_GET")] public async Task ShowTimeForUserComparedToCurrentUser(DateTime requestTime, string verb, MiunieUser user) { var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -58,6 +62,7 @@ public async Task ShowTimeForUserComparedToCurrentUser(DateTime requestTime, str } [Command("time of")] + [Summary("HELP_TIME_OF")] public async Task ShowTimeForMessage(ulong messageId) { var m = await Context.Channel.GetMessageAsync(messageId); @@ -69,6 +74,7 @@ public async Task ShowTimeForMessage(ulong messageId) } [Command("time set")] + [Summary("HELP_TIME_SET")] public async Task SetMyTimeOffset(DateTime currentTime) { var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -78,6 +84,7 @@ public async Task SetMyTimeOffset(DateTime currentTime) [RequireUserPermission(GuildPermission.Administrator)] [Command("time set for")] + [Summary("HELP_TIME_SET_FOR")] public async Task SetMyTimeOffset(MiunieUser user, DateTime currentTime) { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); diff --git a/src/Miunie.Discord/Embeds/EmbedConstructor.cs b/src/Miunie.Discord/Embeds/EmbedConstructor.cs index 021ea21..90b1f82 100644 --- a/src/Miunie.Discord/Embeds/EmbedConstructor.cs +++ b/src/Miunie.Discord/Embeds/EmbedConstructor.cs @@ -17,6 +17,7 @@ using Miunie.Core.Entities; using Miunie.Core.Entities.Discord; using Miunie.Core.Providers; +using Miunie.Discord.Entities; using System; using System.Collections.Generic; using System.Linq; @@ -26,29 +27,21 @@ namespace Miunie.Discord.Embeds internal static class EmbedConstructor { private static readonly int RepLogPageSize = 10; + private static readonly uint DefaultEmbedColor = 0xEC407A; // 236, 64, 122 - private static string FormatReputationType(ReputationType type) - { - switch(type) - { - case ReputationType.Plus: - return "+1"; - case ReputationType.Minus: - return "-1"; - default: - throw new ArgumentException("Unknown ReputationType."); - } - } - public static Embed CreateHelpEmbed(HelpResult result) { EmbedBuilder builder = new EmbedBuilder(); if (!string.IsNullOrWhiteSpace(result.Title)) - builder.WithTitle(result.Title); + { + _ = builder.WithTitle(result.Title); + } foreach (HelpSection section in result.Sections) - builder.AddField(section.Title, section.Content, false); + { + _ = builder.AddField(section.Title, section.Content, false); + } return builder.Build(); } @@ -58,7 +51,7 @@ public static Embed CreateReputationLog(IEnumerable entries, in var embed = Paginator.PaginateEmbed( entries, new EmbedBuilder() - .WithColor(new Color(236, 64, 122)) + .WithColor(new Color(DefaultEmbedColor)) .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_REP_LOG_TITLE.ToString())), index, RepLogPageSize, @@ -77,7 +70,7 @@ public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang) var realnessPhrase = lang.GetPhrase((mUser.IsBot ? PhraseKey.USER_EMBED_IS_BOT : PhraseKey.USER_EMBED_IS_HUMAN).ToString()); return new EmbedBuilder() - .WithColor(new Color(236, 64, 122)) + .WithColor(new Color(DefaultEmbedColor)) .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_TITLE.ToString())) .WithThumbnailUrl(mUser.AvatarUrl) .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_NAME_TITLE.ToString()), mUser.Name) @@ -92,7 +85,7 @@ public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang) public static Embed ToEmbed(this MiunieGuild mGuild, ILanguageProvider lang) => new EmbedBuilder() - .WithColor(new Color(236, 64, 122)) + .WithColor(new Color(DefaultEmbedColor)) .WithThumbnailUrl(mGuild.IconUrl) .WithTitle(lang.GetPhrase(PhraseKey.GUILD_EMBED_TITLE.ToString())) .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_NAME_TITLE.ToString()), mGuild.Name) @@ -102,16 +95,11 @@ public static Embed ToEmbed(this MiunieGuild mGuild, ILanguageProvider lang) .Build(); private static string FormatReputationType(ReputationType type) - { - switch (type) + => type switch { - case ReputationType.Plus: - return "+1"; - case ReputationType.Minus: - return "-1"; - default: - throw new ArgumentException("Unknown ReputationType."); - } - } + ReputationType.Plus => "+1", + ReputationType.Minus => "-1", + _ => throw new ArgumentException("Unknown ReputationType.") + }; } } diff --git a/src/Miunie.Discord/Entities/HelpResult.cs b/src/Miunie.Discord/Entities/HelpResult.cs new file mode 100644 index 0000000..3a00f4c --- /dev/null +++ b/src/Miunie.Discord/Entities/HelpResult.cs @@ -0,0 +1,26 @@ +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + +using System.Collections.Generic; + +namespace Miunie.Discord.Entities +{ + public class HelpResult + { + public string Title { get; set; } + + public List Sections { get; } = new List(); + } +} diff --git a/src/Miunie.Discord/Entities/HelpSection.cs b/src/Miunie.Discord/Entities/HelpSection.cs new file mode 100644 index 0000000..acdb591 --- /dev/null +++ b/src/Miunie.Discord/Entities/HelpSection.cs @@ -0,0 +1,30 @@ +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + +namespace Miunie.Discord.Entities +{ + public class HelpSection + { + public HelpSection(string title, string content) + { + Title = title; + Content = content; + } + + public string Title { get; } + + public string Content { get; } + } +} diff --git a/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs b/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs index 91b23b0..84fdc23 100644 --- a/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs +++ b/src/Miunie.Discord/Extensions/CommandInfoExtensions.cs @@ -1,4 +1,19 @@ -using Discord.Commands; +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + +using Discord.Commands; using System; using System.Collections.Generic; using System.Linq; @@ -7,10 +22,12 @@ namespace Miunie.Discord { internal static class CommandInfoExtensions { - internal static TAttribute FindAttribute(this CommandInfo command) where TAttribute : Attribute + internal static TAttribute FindAttribute(this CommandInfo command) + where TAttribute : Attribute => command.Attributes.FirstOrDefault(x => x is TAttribute) as TAttribute; - internal static IEnumerable FindAttributes(this CommandInfo command) where TAttribute : Attribute + internal static IEnumerable FindAttributes(this CommandInfo command) + where TAttribute : Attribute => command.Attributes.Where(x => x is TAttribute).Select(x => x as TAttribute); } } diff --git a/src/Miunie.Discord/HelpStrings.Designer.cs b/src/Miunie.Discord/HelpStrings.Designer.cs new file mode 100644 index 0000000..fde595d --- /dev/null +++ b/src/Miunie.Discord/HelpStrings.Designer.cs @@ -0,0 +1,207 @@ +//------------------------------------------------------------------------------ +// +// 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 Miunie.Discord { + 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", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class HelpStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal HelpStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Miunie.Discord.HelpStrings", typeof(HelpStrings).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)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Pull up information about a guild.. + /// + public static string HELP_GUILD { + get { + return ResourceManager.GetString("HELP_GUILD", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I'm here for you.. + /// + public static string HELP_HELP { + get { + return ResourceManager.GetString("HELP_HELP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gets help for a specified command.. + /// + public static string HELP_HELP_SEARCH { + get { + return ResourceManager.GetString("HELP_HELP_SEARCH", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Give a cold-blooded negative reputation for a user.... + /// + public static string HELP_MINUS_REP { + get { + return ResourceManager.GetString("HELP_MINUS_REP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Give a good ol' positive reputation for a user!. + /// + public static string HELP_PLUS_REP { + get { + return ResourceManager.GetString("HELP_PLUS_REP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pull up a dank profile!. + /// + public static string HELP_PROFILE { + get { + return ResourceManager.GetString("HELP_PROFILE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pull up your current reputation log~. + /// + public static string HELP_REP_LOG { + get { + return ResourceManager.GetString("HELP_REP_LOG", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pull up a reputation log for the specified user!. + /// + public static string HELP_REP_LOG_FOR { + get { + return ResourceManager.GetString("HELP_REP_LOG_FOR", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shows the official remote repository hosting the code of this bot. + /// + public static string HELP_REPO { + get { + return ResourceManager.GetString("HELP_REPO", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gets the local time for the specified user.. + /// + public static string HELP_TIME_FOR { + get { + return ResourceManager.GetString("HELP_TIME_FOR", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gets the local time offset by a specified amount for a user.. + /// + public static string HELP_TIME_FOR_OFFSET { + get { + return ResourceManager.GetString("HELP_TIME_FOR_OFFSET", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compares a user's time with your time.. + /// + public static string HELP_TIME_GET { + get { + return ResourceManager.GetString("HELP_TIME_GET", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shows your local time for the specified message.. + /// + public static string HELP_TIME_OF { + get { + return ResourceManager.GetString("HELP_TIME_OF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set your current time offset.. + /// + public static string HELP_TIME_SET { + get { + return ResourceManager.GetString("HELP_TIME_SET", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set a user's time offset.. + /// + public static string HELP_TIME_SET_FOR { + get { + return ResourceManager.GetString("HELP_TIME_SET_FOR", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What do I think? I guess you'll have to find out~. + /// + public static string HELP_WHAT_DO_YOU_THINK { + get { + return ResourceManager.GetString("HELP_WHAT_DO_YOU_THINK", resourceCulture); + } + } + } +} diff --git a/src/Miunie.Discord/HelpStrings.resx b/src/Miunie.Discord/HelpStrings.resx new file mode 100644 index 0000000..d37c5ca --- /dev/null +++ b/src/Miunie.Discord/HelpStrings.resx @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Pull up information about a guild. + ProfileCommand + + + I'm here for you. + HelpCommand + + + Gets help for a specified command. + HelpCommand + + + Give a cold-blooded negative reputation for a user... + ProfileCommand + + + Give a good ol' positive reputation for a user! + ProfileCommand + + + Pull up a dank profile! + ProfileCommand + + + Shows the official remote repository hosting the code of this bot + RemoteRepositoryCommand + + + Pull up your current reputation log~ + ProfileCommand + + + Pull up a reputation log for the specified user! + ProfileCommand + + + Gets the local time for the specified user. + TimeCommand + + + Gets the local time offset by a specified amount for a user. + TimeCommand + + + Compares a user's time with your time. + TimeCommand + + + Shows your local time for the specified message. + TimeCommand + + + Set your current time offset. + TimeCommand + + + Set a user's time offset. + TimeCommand + + + What do I think? I guess you'll have to find out~ + MiscCommands + + \ No newline at end of file diff --git a/src/Miunie.Discord/Miunie.Discord.csproj b/src/Miunie.Discord/Miunie.Discord.csproj index 6d337b1..af8e9ce 100644 --- a/src/Miunie.Discord/Miunie.Discord.csproj +++ b/src/Miunie.Discord/Miunie.Discord.csproj @@ -13,8 +13,9 @@ - netstandard2.0 + netstandard2.1 ../.ruleset + latest @@ -23,4 +24,19 @@ + + + True + True + HelpStrings.resx + + + + + + PublicResXFileCodeGenerator + HelpStrings.Designer.cs + + + diff --git a/src/Miunie.Discord/Services/HelpService.cs b/src/Miunie.Discord/Services/HelpService.cs index d1875dd..a370a64 100644 --- a/src/Miunie.Discord/Services/HelpService.cs +++ b/src/Miunie.Discord/Services/HelpService.cs @@ -1,9 +1,25 @@ -using Discord; +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + using Discord.Commands; using Discord.WebSocket; -using Miunie.Core; +using Miunie.Core.Entities; +using Miunie.Core.Providers; using Miunie.Discord.Attributes; using Miunie.Discord.Embeds; +using Miunie.Discord.Entities; using System; using System.Collections.Generic; using System.Linq; @@ -12,100 +28,53 @@ namespace Miunie.Discord { - public class HelpSection - { - public HelpSection(string title, string content) - { - Title = title; - Content = content; - } - - public string Title { get; } - public string Content { get; } - } - - public class HelpResult - { - public HelpResult() - { - - } - - public string Title { get; set; } - public List Sections { get; } = new List(); - } - public class HelpService { private readonly CommandService _commandService; + private readonly ILanguageProvider _lang; - public HelpService(CommandService commandService) + public HelpService(CommandService commandService, ILanguageProvider lang) { _commandService = commandService; + _lang = lang; } public HelpResult GetDefault() { - HelpResult entry = new HelpResult(); - entry.Title = "**HELP MENU**"; + HelpResult entry = new HelpResult + { + Title = _lang.GetPhrase(PhraseKey.USER_EMBED_HELP_TITLE.ToString()) + }; foreach (ModuleInfo module in _commandService.Modules) { string title = module.Name; - string content = string.Join(" ", module.Commands.GroupBy(x => x.Name).Select(x => $"`{x.Key}`")); + string content = string.Join(" ", module.Commands + .GroupBy(x => x.Name) + .Select(x => $"`{x.Key}`")); + entry.Sections.Add(new HelpSection(title, content)); } return entry; } - private IEnumerable GetCommands(string input) - { - SearchResult result = _commandService.Search(input); - - if (!result.IsSuccess) - throw new Exception(result.ErrorReason); - - return result.Commands.Select(x => x.Command); - } - - private string GetSectionTitle(CommandInfo command) - => $"{command.Name} " + - $"{string.Join(" ", command.Parameters.OrderBy(x => x.IsOptional).Select(x => $"{(x.IsOptional ? $"[{x.Name}]" : $"<{x.Name}>")}"))}"; - - private string GetExamples(CommandInfo command) - { - string[] examples = command.FindAttribute()?.Examples; - - if (examples != null) - { - return string.Join(", ", examples.Select(x => $"`{x}`")); - } - - return "No examples provided."; - } - - private string GetSummary(CommandInfo command) - => (command.FindAttribute()?.Text) ?? "No summary was provided."; - public HelpResult Search(string input) { HelpResult entry = new HelpResult(); - + foreach (CommandInfo command in GetCommands(input)) { string title = GetSectionTitle(command); + string summary = GetSummary(command); + string examples = GetExamples(command); StringBuilder content = new StringBuilder(); - content.Append("**Summary**: "); - string summary = GetSummary(command); - content.AppendLine(summary); - content.AppendLine(); - - content.Append("**Examples**: "); - string examples = GetExamples(command); - content.Append(examples); + _ = content.Append(_lang.GetPhrase(PhraseKey.HELP_SUMMARY_TITLE.ToString())) + .AppendLine(summary) + .Append(_lang.GetPhrase(PhraseKey.HELP_EXAMPLE_TITLE.ToString())) + .Append(examples); entry.Sections.Add(new HelpSection(title, content.ToString())); } @@ -114,13 +83,47 @@ public HelpResult Search(string input) } public async Task ShowDefaultHelpAsync(ISocketMessageChannel channel) + => await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(GetDefault())); + + public async Task ShowCommandHelpAsync(ISocketMessageChannel channel, string input) + => await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(Search(input))); + + private IEnumerable GetCommands(string input) { - await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(GetDefault())); + SearchResult result = _commandService.Search(input); + + if (!result.IsSuccess) + { + throw new Exception(result.ErrorReason); + } + + return result.Commands.Select(x => x.Command); } - public async Task ShowCommandHelpAsync(ISocketMessageChannel channel, string input) + private string GetSectionTitle(CommandInfo command) + => $"{command.Name} {GetSectionParameters(command)}"; + + private string GetSectionParameters(CommandInfo command) + => string.Join(" ", command.Parameters + .OrderBy(x => x.IsOptional) + .Select(x => x.IsOptional ? $"[{x.Name}]" : $"<{x.Name}>")); + + private string GetExamples(CommandInfo command) { - await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(Search(input))); + string[] examples = command.FindAttribute()?.Examples; + + return examples != null + ? string.Join(", ", examples.Select(x => $"`{x}`")) + : _lang.GetPhrase(PhraseKey.HELP_EXAMPLE_EMPTY.ToString()); } + + private string FindSummary(string id) + => id != null + ? HelpStrings.ResourceManager.GetString(id) + : null; + + private string GetSummary(CommandInfo command) + => FindSummary(command.Summary) + ?? _lang.GetPhrase(PhraseKey.HELP_SUMMARY_EMPTY.ToString()); } } diff --git a/src/Miunie.Discord/TypeReaders/MiunieUserTypeReader.cs b/src/Miunie.Discord/TypeReaders/MiunieUserTypeReader.cs index a2ec0f7..fc8ec83 100644 --- a/src/Miunie.Discord/TypeReaders/MiunieUserTypeReader.cs +++ b/src/Miunie.Discord/TypeReaders/MiunieUserTypeReader.cs @@ -33,7 +33,7 @@ public MiunieUserTypeReader(EntityConvertor convertor) public override async Task ReadAsync(ICommandContext context, string input, IServiceProvider services) { - var discordUserId = MentionUtils.TryParseUser(input, out var userId); + _ = MentionUtils.TryParseUser(input, out var userId); if (await context.Guild.GetUserAsync(userId) is SocketGuildUser discordUser) { diff --git a/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj b/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj index d4f6013..8675ac1 100644 --- a/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj +++ b/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj @@ -1,8 +1,9 @@  - netstandard2.0 + netstandard2.1 ../.ruleset + latest diff --git a/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj b/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj index 5341737..99c9b05 100644 --- a/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj +++ b/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj @@ -1,12 +1,13 @@ - + - netstandard2.0 + netstandard2.1 ../.ruleset + latest - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Miunie.Logger/Miunie.Logger.csproj b/src/Miunie.Logger/Miunie.Logger.csproj index 74b8040..fc3f0ce 100644 --- a/src/Miunie.Logger/Miunie.Logger.csproj +++ b/src/Miunie.Logger/Miunie.Logger.csproj @@ -1,8 +1,9 @@  - netstandard2.0 + netstandard2.1 ../.ruleset + latest diff --git a/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj b/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj index 0fec008..622ed6b 100644 --- a/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj +++ b/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj @@ -1,8 +1,9 @@  - netstandard2.0 + netstandard2.1 ../.ruleset + latest From cec1b616c36e8863c2c7b8c45c543a53c662c688 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Wed, 11 Mar 2020 11:05:00 -0500 Subject: [PATCH 03/11] Set LangVersion to 8.0 and refactor This update should fix all issues previously mentioned and make some methods easier to handle. Changes - Created StringExtensions, which contains two methods of ValueOrDefault(this string, string) and JoinOrDefault(this IEnumerable, string, string). - Created TExtensions, which contains one method of StringJoinOrDefault(this IEnumerable, Func, string, string). - Set all LangVersion properties to 8.0. - Modified HelpCommand, MiscCommands, ProfileCommand, RemoteRepositoryCommand, and TimeCommand to store their direct summaries and include examples. - Modified HelpCommandProvider to include three new methods of GetAllModuleSections(), GetSection(ModuleInfo), and GetSection(CommandInfo). - Modified HelpCommandProvider.Search to use GetSection(Command). - Modified HelpCommandProvider.GetDefault to use GetAllModuleSections(). - Modified HelpCommandProvider.GetExamples(CommandInfo) to use .StringJoinOrDefault(). - Modified HelpResult.Sections to implement IEnumerable instead. - Modified HelpResult.Sections to expose the set property. - Modified Strings.resx to make HELP_SUMMARY_EMPTY and HELP_EXAMPLE_EMPTY include multiple response values. - Modified EmbedConstructor.GetHelpEmbed(HelpResult) to use MiuniePinkColor for its EmbedBuilder. - Renamed EmbedConstructor.DefaultEmbedColor to MiuniePinkColor and removed comment. - Renamed HelpService to HelpCommandProvider. - Renamed CommandService.GetHelpService(ILanguageProvider) to CommandService.GetHelpProvider(ILanguageProvider). - Reverted all .NET Standard targets back to 2.0. - Deleted HelpStrings.resx. --- src/Miunie.Avalonia/Miunie.Avalonia.csproj | 2 +- .../Miunie.ConsoleApp.csproj | 2 +- .../Miunie.Core.XUnit.Tests.csproj | 3 +- src/Miunie.Core/Miunie.Core.csproj | 4 +- src/Miunie.Core/Strings.Designer.cs | 10 +- src/Miunie.Core/Strings.resx | 10 +- src/Miunie.Discord/CommandHandler.cs | 4 +- .../CommandModules/HelpCommand.cs | 11 +- .../CommandModules/MiscCommands.cs | 4 +- .../CommandModules/ProfileCommand.cs | 19 +- .../CommandModules/RemoteRepositoryCommand.cs | 4 +- .../CommandModules/TimeCommand.cs | 19 +- src/Miunie.Discord/Embeds/EmbedConstructor.cs | 10 +- src/Miunie.Discord/Entities/HelpResult.cs | 2 +- .../Extensions/StringExtensions.cs | 35 +++ src/Miunie.Discord/Extensions/TExtensions.cs | 33 +++ src/Miunie.Discord/HelpStrings.Designer.cs | 207 ------------------ src/Miunie.Discord/HelpStrings.resx | 184 ---------------- src/Miunie.Discord/Miunie.Discord.csproj | 19 +- .../HelpCommandProvider.cs} | 93 ++++---- .../Miunie.InversionOfControl.csproj | 4 +- .../Miunie.LiteDbStorage.csproj | 4 +- src/Miunie.Logger/Miunie.Logger.csproj | 4 +- .../Miunie.SystemInfrastructure.csproj | 4 +- 24 files changed, 192 insertions(+), 499 deletions(-) create mode 100644 src/Miunie.Discord/Extensions/StringExtensions.cs create mode 100644 src/Miunie.Discord/Extensions/TExtensions.cs delete mode 100644 src/Miunie.Discord/HelpStrings.Designer.cs delete mode 100644 src/Miunie.Discord/HelpStrings.resx rename src/Miunie.Discord/{Services/HelpService.cs => Providers/HelpCommandProvider.cs} (62%) diff --git a/src/Miunie.Avalonia/Miunie.Avalonia.csproj b/src/Miunie.Avalonia/Miunie.Avalonia.csproj index a599fd3..9519671 100644 --- a/src/Miunie.Avalonia/Miunie.Avalonia.csproj +++ b/src/Miunie.Avalonia/Miunie.Avalonia.csproj @@ -2,7 +2,7 @@ WinExe netcoreapp3.1 - latest + 8.0 ../.ruleset diff --git a/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj b/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj index f48230b..f335da0 100644 --- a/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj +++ b/src/Miunie.ConsoleApp/Miunie.ConsoleApp.csproj @@ -3,7 +3,7 @@ Exe netcoreapp3.1 - latest + 8.0 ../.ruleset diff --git a/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj b/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj index 0f1d3b0..47d46b6 100644 --- a/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj +++ b/src/Miunie.Core.XUnit.Tests/Miunie.Core.XUnit.Tests.csproj @@ -2,10 +2,9 @@ netcoreapp3.1 - false ../.ruleset - latest + 8.0 diff --git a/src/Miunie.Core/Miunie.Core.csproj b/src/Miunie.Core/Miunie.Core.csproj index 64aee3d..582cf88 100644 --- a/src/Miunie.Core/Miunie.Core.csproj +++ b/src/Miunie.Core/Miunie.Core.csproj @@ -1,9 +1,9 @@  - netstandard2.1 + netstandard2.0 ../.ruleset - latest + 8.0 diff --git a/src/Miunie.Core/Strings.Designer.cs b/src/Miunie.Core/Strings.Designer.cs index 7f368a3..d665e12 100644 --- a/src/Miunie.Core/Strings.Designer.cs +++ b/src/Miunie.Core/Strings.Designer.cs @@ -132,7 +132,11 @@ public static string GUILD_EMBED_TITLE { } /// - /// Looks up a localized string similar to No examples were provided.. + /// Looks up a localized string similar to You'll figure it out.{{OR}} + ///You know what? I've never used this command.{{OR}} + ///Yeah, you're on your own with this one, buddy.{{OR}} + ///I got nothing here.{{OR}} + ///Just mess around with this, you'll figure it out eventually.. /// public static string HELP_EXAMPLE_EMPTY { get { @@ -150,7 +154,9 @@ public static string HELP_EXAMPLE_TITLE { } /// - /// Looks up a localized string similar to No summary was provided.. + /// Looks up a localized string similar to This is kind of difficult to explain...{{OR}} + ///How am I supposed to put this into words?{{OR}} + ///It's a command, I think? Not sure.. /// public static string HELP_SUMMARY_EMPTY { get { diff --git a/src/Miunie.Core/Strings.resx b/src/Miunie.Core/Strings.resx index 419c355..7d0789a 100644 --- a/src/Miunie.Core/Strings.resx +++ b/src/Miunie.Core/Strings.resx @@ -159,7 +159,11 @@ Source code available at: {1} No formatting options. - No examples were provided. + You'll figure it out.{{OR}} +You know what? I've never used this command.{{OR}} +Yeah, you're on your own with this one, buddy.{{OR}} +I got nothing here.{{OR}} +Just mess around with this, you'll figure it out eventually. No formatting options. @@ -167,7 +171,9 @@ Source code available at: {1} No formatting options. - No summary was provided. + This is kind of difficult to explain...{{OR}} +How am I supposed to put this into words?{{OR}} +It's a command, I think? Not sure. No formatting options. diff --git a/src/Miunie.Discord/CommandHandler.cs b/src/Miunie.Discord/CommandHandler.cs index c0bfe3f..17e49c1 100644 --- a/src/Miunie.Discord/CommandHandler.cs +++ b/src/Miunie.Discord/CommandHandler.cs @@ -54,8 +54,8 @@ public async Task InitializeAsync() _ = await _commandService.AddModulesAsync(Assembly.GetExecutingAssembly(), _services); } - public HelpService GetHelpService(ILanguageProvider lang) - => new HelpService(_commandService, lang); + public HelpCommandProvider GetHelpProvider(ILanguageProvider lang) + => new HelpCommandProvider(_commandService, lang); private async Task HandleCommandAsync(SocketMessage s) { diff --git a/src/Miunie.Discord/CommandModules/HelpCommand.cs b/src/Miunie.Discord/CommandModules/HelpCommand.cs index 753e7e2..9002069 100644 --- a/src/Miunie.Discord/CommandModules/HelpCommand.cs +++ b/src/Miunie.Discord/CommandModules/HelpCommand.cs @@ -15,6 +15,7 @@ using Discord.Commands; using Miunie.Core.Providers; +using Miunie.Discord.Attributes; using System.Threading.Tasks; namespace Miunie.Discord.CommandModules @@ -22,22 +23,24 @@ namespace Miunie.Discord.CommandModules [Name("Help")] public class HelpCommand : ModuleBase { - private readonly HelpService _helpService; + private readonly HelpCommandProvider _helpService; public HelpCommand(CommandHandler commandHandler, ILanguageProvider lang) { - _helpService = commandHandler.GetHelpService(lang); + _helpService = commandHandler.GetHelpProvider(lang); } [Command("help")] - [Summary("HELP_HELP")] + [Summary("I'm here for you.")] + [Examples("help")] public async Task GetHelp() { await _helpService.ShowDefaultHelpAsync(Context.Channel); } [Command("help")] - [Summary("HELP_HELP_SEARCH")] + [Summary("Gets help for a specified command.")] + [Examples("help repo")] public async Task GetHelp([Remainder]string input) { await _helpService.ShowCommandHelpAsync(Context.Channel, input); diff --git a/src/Miunie.Discord/CommandModules/MiscCommands.cs b/src/Miunie.Discord/CommandModules/MiscCommands.cs index 74dfa03..d2630de 100644 --- a/src/Miunie.Discord/CommandModules/MiscCommands.cs +++ b/src/Miunie.Discord/CommandModules/MiscCommands.cs @@ -16,6 +16,7 @@ using Discord.Commands; using Discord.WebSocket; using Miunie.Core; +using Miunie.Discord.Attributes; using Miunie.Discord.Convertors; using System.Threading.Tasks; @@ -34,7 +35,8 @@ public MiscCommands(MiscService service, EntityConvertor entityConvertor) } [Command("what do you think?")] - [Summary("HELP_WHAT_DO_YOU_THINK")] + [Summary("What do I think? I guess you'll have to find out~")] + [Examples("what do you think?")] public async Task SendRandomYesNoMaybeAnswer() { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); diff --git a/src/Miunie.Discord/CommandModules/ProfileCommand.cs b/src/Miunie.Discord/CommandModules/ProfileCommand.cs index 17c81a7..b40557e 100644 --- a/src/Miunie.Discord/CommandModules/ProfileCommand.cs +++ b/src/Miunie.Discord/CommandModules/ProfileCommand.cs @@ -17,6 +17,7 @@ using Discord.WebSocket; using Miunie.Core; using Miunie.Core.Entities.Discord; +using Miunie.Discord.Attributes; using Miunie.Discord.Convertors; using System.Threading.Tasks; @@ -35,7 +36,8 @@ public ProfileCommand(EntityConvertor entityConvertor, ProfileService profileSer } [Command("profile")] - [Summary("HELP_PROFILE")] + [Summary("Pull up a dank profile!")] + [Examples("profile", "profile @Miunie")] public async Task ShowProfileAsync(MiunieUser user = null) { if (user is null) @@ -48,7 +50,8 @@ public async Task ShowProfileAsync(MiunieUser user = null) } [Command("rep log")] - [Summary("HELP_REP_LOG")] + [Summary("Pull up your current reputation log~")] + [Examples("rep log", "rep log 1")] public async Task ShowReputationLogAsync(int page = 1) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -57,7 +60,8 @@ public async Task ShowReputationLogAsync(int page = 1) } [Command("rep log for")] - [Summary("HELP_REP_LOG_FOR")] + [Summary("Pull up a reputation log for the specified user!")] + [Examples("rep log for @Miunie", "rep log for @Mackie 1")] public async Task ShowReputationLogAsync(MiunieUser user, int page = 1) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -66,7 +70,8 @@ public async Task ShowReputationLogAsync(MiunieUser user, int page = 1) } [Command("+rep")] - [Summary("HELP_PLUS_REP")] + [Summary("Give a good ol' positive reputation for a user!")] + [Examples("+rep @Miunie")] public async Task AddReputationAsync(MiunieUser user) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -75,7 +80,8 @@ public async Task AddReputationAsync(MiunieUser user) } [Command("-rep")] - [Summary("HELP_MINUS_REP")] + [Summary("Give a cold-blooded negative reputation for a user...")] + [Examples("-rep @You")] public async Task RemoveReputationAsync(MiunieUser user) { var source = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -84,7 +90,8 @@ public async Task RemoveReputationAsync(MiunieUser user) } [Command("guild")] - [Summary("HELP_GUILD")] + [Summary("Pull up information about this guild.")] + [Examples("guild")] public async Task ShowGuildInfoAsync() { var guild = _entityConvertor.ConvertGuild(Context.Guild); diff --git a/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs b/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs index 3c78da5..c46527e 100644 --- a/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs +++ b/src/Miunie.Discord/CommandModules/RemoteRepositoryCommand.cs @@ -16,6 +16,7 @@ using Discord.Commands; using Discord.WebSocket; using Miunie.Core; +using Miunie.Discord.Attributes; using Miunie.Discord.Convertors; using System.Threading.Tasks; @@ -34,7 +35,8 @@ public RemoteRepositoryCommand(RemoteRepositoryService remoteRepoService, Entity } [Command("repo")] - [Summary("HELP_REPO")] + [Summary("Shows the official remote repository hosting the code of this bot.")] + [Examples("repo")] public async Task ShowRepository() { var channel = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); diff --git a/src/Miunie.Discord/CommandModules/TimeCommand.cs b/src/Miunie.Discord/CommandModules/TimeCommand.cs index 6c1eeb8..f920706 100644 --- a/src/Miunie.Discord/CommandModules/TimeCommand.cs +++ b/src/Miunie.Discord/CommandModules/TimeCommand.cs @@ -18,6 +18,7 @@ using Discord.WebSocket; using Miunie.Core; using Miunie.Core.Entities.Discord; +using Miunie.Discord.Attributes; using Miunie.Discord.Convertors; using System; using System.Threading.Tasks; @@ -37,7 +38,8 @@ public TimeCommand(TimeService service, EntityConvertor entityConvertor) } [Command("time for")] - [Summary("HELP_TIME_FOR")] + [Summary("Gets the local time for the specified user.")] + [Examples("time for @Miunie")] public async Task ShowTimeForUser(MiunieUser user) { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); @@ -45,7 +47,8 @@ public async Task ShowTimeForUser(MiunieUser user) } [Command("time for")] - [Summary("HELP_TIME_FOR_OFFSET")] + [Summary("Gets the local time offset by a specified amount for a user.")] + [Examples("time for @Miunie in 4 hours", "time for @Peter in 2 minutes", "time for @Draxis in 1 second")] public async Task ShowTimeForUserWithOffset(MiunieUser user, string verb, int units, string timeframe) { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); @@ -53,7 +56,8 @@ public async Task ShowTimeForUserWithOffset(MiunieUser user, string verb, int un } [Command("time get")] - [Summary("HELP_TIME_GET")] + [Summary("Compares a user's time with your time.")] + [Examples("time get 03:30 for @Miunie")] public async Task ShowTimeForUserComparedToCurrentUser(DateTime requestTime, string verb, MiunieUser user) { var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -62,7 +66,8 @@ public async Task ShowTimeForUserComparedToCurrentUser(DateTime requestTime, str } [Command("time of")] - [Summary("HELP_TIME_OF")] + [Summary("Shows your local time for the specified message.")] + [Examples("time of 647141579345100840")] public async Task ShowTimeForMessage(ulong messageId) { var m = await Context.Channel.GetMessageAsync(messageId); @@ -74,7 +79,8 @@ public async Task ShowTimeForMessage(ulong messageId) } [Command("time set")] - [Summary("HELP_TIME_SET")] + [Summary("Set your current time offset.")] + [Examples("time set 16:17")] public async Task SetMyTimeOffset(DateTime currentTime) { var u = _entityConvertor.ConvertUser(Context.User as SocketGuildUser); @@ -84,7 +90,8 @@ public async Task SetMyTimeOffset(DateTime currentTime) [RequireUserPermission(GuildPermission.Administrator)] [Command("time set for")] - [Summary("HELP_TIME_SET_FOR")] + [Summary("Set a user's time offset.")] + [Examples("time set for @Draxis 00:00")] public async Task SetMyTimeOffset(MiunieUser user, DateTime currentTime) { var c = _entityConvertor.ConvertChannel(Context.Channel as SocketGuildChannel); diff --git a/src/Miunie.Discord/Embeds/EmbedConstructor.cs b/src/Miunie.Discord/Embeds/EmbedConstructor.cs index 90b1f82..a2bf627 100644 --- a/src/Miunie.Discord/Embeds/EmbedConstructor.cs +++ b/src/Miunie.Discord/Embeds/EmbedConstructor.cs @@ -27,11 +27,11 @@ namespace Miunie.Discord.Embeds internal static class EmbedConstructor { private static readonly int RepLogPageSize = 10; - private static readonly uint DefaultEmbedColor = 0xEC407A; // 236, 64, 122 + private static readonly uint MiuniePinkColor = 0xEC407A; public static Embed CreateHelpEmbed(HelpResult result) { - EmbedBuilder builder = new EmbedBuilder(); + EmbedBuilder builder = new EmbedBuilder().WithColor(MiuniePinkColor); if (!string.IsNullOrWhiteSpace(result.Title)) { @@ -51,7 +51,7 @@ public static Embed CreateReputationLog(IEnumerable entries, in var embed = Paginator.PaginateEmbed( entries, new EmbedBuilder() - .WithColor(new Color(DefaultEmbedColor)) + .WithColor(new Color(MiuniePinkColor)) .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_REP_LOG_TITLE.ToString())), index, RepLogPageSize, @@ -70,7 +70,7 @@ public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang) var realnessPhrase = lang.GetPhrase((mUser.IsBot ? PhraseKey.USER_EMBED_IS_BOT : PhraseKey.USER_EMBED_IS_HUMAN).ToString()); return new EmbedBuilder() - .WithColor(new Color(DefaultEmbedColor)) + .WithColor(new Color(MiuniePinkColor)) .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_TITLE.ToString())) .WithThumbnailUrl(mUser.AvatarUrl) .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_NAME_TITLE.ToString()), mUser.Name) @@ -85,7 +85,7 @@ public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang) public static Embed ToEmbed(this MiunieGuild mGuild, ILanguageProvider lang) => new EmbedBuilder() - .WithColor(new Color(DefaultEmbedColor)) + .WithColor(new Color(MiuniePinkColor)) .WithThumbnailUrl(mGuild.IconUrl) .WithTitle(lang.GetPhrase(PhraseKey.GUILD_EMBED_TITLE.ToString())) .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_NAME_TITLE.ToString()), mGuild.Name) diff --git a/src/Miunie.Discord/Entities/HelpResult.cs b/src/Miunie.Discord/Entities/HelpResult.cs index 3a00f4c..c4ae7dc 100644 --- a/src/Miunie.Discord/Entities/HelpResult.cs +++ b/src/Miunie.Discord/Entities/HelpResult.cs @@ -21,6 +21,6 @@ public class HelpResult { public string Title { get; set; } - public List Sections { get; } = new List(); + public IEnumerable Sections { get; set; } } } diff --git a/src/Miunie.Discord/Extensions/StringExtensions.cs b/src/Miunie.Discord/Extensions/StringExtensions.cs new file mode 100644 index 0000000..f0aa24d --- /dev/null +++ b/src/Miunie.Discord/Extensions/StringExtensions.cs @@ -0,0 +1,35 @@ +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + +using System.Collections.Generic; + +namespace Miunie.Discord +{ + internal static class StringExtensions + { + internal static string ValueOrDefault(this string value, string fallback = "") + => string.IsNullOrWhiteSpace(value) + ? fallback ?? string.Empty + : value; + + internal static string JoinOrDefault( + this IEnumerable values, + string separator, + string fallback = "") + => values?.Length > 0 + ? string.Join(separator, values) + : fallback ?? string.Empty; + } +} diff --git a/src/Miunie.Discord/Extensions/TExtensions.cs b/src/Miunie.Discord/Extensions/TExtensions.cs new file mode 100644 index 0000000..526b7b3 --- /dev/null +++ b/src/Miunie.Discord/Extensions/TExtensions.cs @@ -0,0 +1,33 @@ +// This file is part of Miunie. +// +// Miunie is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Miunie is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Miunie. If not, see . + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Miunie.Discord +{ + internal static class TExtensions + { + internal static string StringJoinOrDefault( + this IEnumerable values, + Func formatter, + string separator, + string fallback = "") + => values?.Count() > 0 + ? string.Join(separator, values.Select(x => formatter.Invoke(x))) + : fallback ?? string.Empty; + } +} diff --git a/src/Miunie.Discord/HelpStrings.Designer.cs b/src/Miunie.Discord/HelpStrings.Designer.cs deleted file mode 100644 index fde595d..0000000 --- a/src/Miunie.Discord/HelpStrings.Designer.cs +++ /dev/null @@ -1,207 +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 Miunie.Discord { - 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", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class HelpStrings { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal HelpStrings() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Miunie.Discord.HelpStrings", typeof(HelpStrings).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)] - public static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Pull up information about a guild.. - /// - public static string HELP_GUILD { - get { - return ResourceManager.GetString("HELP_GUILD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to I'm here for you.. - /// - public static string HELP_HELP { - get { - return ResourceManager.GetString("HELP_HELP", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Gets help for a specified command.. - /// - public static string HELP_HELP_SEARCH { - get { - return ResourceManager.GetString("HELP_HELP_SEARCH", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Give a cold-blooded negative reputation for a user.... - /// - public static string HELP_MINUS_REP { - get { - return ResourceManager.GetString("HELP_MINUS_REP", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Give a good ol' positive reputation for a user!. - /// - public static string HELP_PLUS_REP { - get { - return ResourceManager.GetString("HELP_PLUS_REP", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Pull up a dank profile!. - /// - public static string HELP_PROFILE { - get { - return ResourceManager.GetString("HELP_PROFILE", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Pull up your current reputation log~. - /// - public static string HELP_REP_LOG { - get { - return ResourceManager.GetString("HELP_REP_LOG", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Pull up a reputation log for the specified user!. - /// - public static string HELP_REP_LOG_FOR { - get { - return ResourceManager.GetString("HELP_REP_LOG_FOR", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Shows the official remote repository hosting the code of this bot. - /// - public static string HELP_REPO { - get { - return ResourceManager.GetString("HELP_REPO", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Gets the local time for the specified user.. - /// - public static string HELP_TIME_FOR { - get { - return ResourceManager.GetString("HELP_TIME_FOR", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Gets the local time offset by a specified amount for a user.. - /// - public static string HELP_TIME_FOR_OFFSET { - get { - return ResourceManager.GetString("HELP_TIME_FOR_OFFSET", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compares a user's time with your time.. - /// - public static string HELP_TIME_GET { - get { - return ResourceManager.GetString("HELP_TIME_GET", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Shows your local time for the specified message.. - /// - public static string HELP_TIME_OF { - get { - return ResourceManager.GetString("HELP_TIME_OF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Set your current time offset.. - /// - public static string HELP_TIME_SET { - get { - return ResourceManager.GetString("HELP_TIME_SET", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Set a user's time offset.. - /// - public static string HELP_TIME_SET_FOR { - get { - return ResourceManager.GetString("HELP_TIME_SET_FOR", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to What do I think? I guess you'll have to find out~. - /// - public static string HELP_WHAT_DO_YOU_THINK { - get { - return ResourceManager.GetString("HELP_WHAT_DO_YOU_THINK", resourceCulture); - } - } - } -} diff --git a/src/Miunie.Discord/HelpStrings.resx b/src/Miunie.Discord/HelpStrings.resx deleted file mode 100644 index d37c5ca..0000000 --- a/src/Miunie.Discord/HelpStrings.resx +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - Pull up information about a guild. - ProfileCommand - - - I'm here for you. - HelpCommand - - - Gets help for a specified command. - HelpCommand - - - Give a cold-blooded negative reputation for a user... - ProfileCommand - - - Give a good ol' positive reputation for a user! - ProfileCommand - - - Pull up a dank profile! - ProfileCommand - - - Shows the official remote repository hosting the code of this bot - RemoteRepositoryCommand - - - Pull up your current reputation log~ - ProfileCommand - - - Pull up a reputation log for the specified user! - ProfileCommand - - - Gets the local time for the specified user. - TimeCommand - - - Gets the local time offset by a specified amount for a user. - TimeCommand - - - Compares a user's time with your time. - TimeCommand - - - Shows your local time for the specified message. - TimeCommand - - - Set your current time offset. - TimeCommand - - - Set a user's time offset. - TimeCommand - - - What do I think? I guess you'll have to find out~ - MiscCommands - - \ No newline at end of file diff --git a/src/Miunie.Discord/Miunie.Discord.csproj b/src/Miunie.Discord/Miunie.Discord.csproj index af8e9ce..75f6dd8 100644 --- a/src/Miunie.Discord/Miunie.Discord.csproj +++ b/src/Miunie.Discord/Miunie.Discord.csproj @@ -13,9 +13,9 @@ - netstandard2.1 + netstandard2.0 ../.ruleset - latest + 8.0 @@ -24,19 +24,4 @@ - - - True - True - HelpStrings.resx - - - - - - PublicResXFileCodeGenerator - HelpStrings.Designer.cs - - - diff --git a/src/Miunie.Discord/Services/HelpService.cs b/src/Miunie.Discord/Providers/HelpCommandProvider.cs similarity index 62% rename from src/Miunie.Discord/Services/HelpService.cs rename to src/Miunie.Discord/Providers/HelpCommandProvider.cs index a370a64..2f28860 100644 --- a/src/Miunie.Discord/Services/HelpService.cs +++ b/src/Miunie.Discord/Providers/HelpCommandProvider.cs @@ -28,58 +28,36 @@ namespace Miunie.Discord { - public class HelpService + public class HelpCommandProvider { private readonly CommandService _commandService; private readonly ILanguageProvider _lang; - public HelpService(CommandService commandService, ILanguageProvider lang) + public HelpCommandProvider(CommandService commandService, ILanguageProvider lang) { _commandService = commandService; _lang = lang; } public HelpResult GetDefault() - { - HelpResult entry = new HelpResult + => new HelpResult { - Title = _lang.GetPhrase(PhraseKey.USER_EMBED_HELP_TITLE.ToString()) + Title = _lang.GetPhrase(PhraseKey.USER_EMBED_HELP_TITLE.ToString()), + Sections = GetAllModuleSections() }; - foreach (ModuleInfo module in _commandService.Modules) - { - string title = module.Name; - string content = string.Join(" ", module.Commands - .GroupBy(x => x.Name) - .Select(x => $"`{x.Key}`")); - - entry.Sections.Add(new HelpSection(title, content)); - } - - return entry; - } - public HelpResult Search(string input) { - HelpResult entry = new HelpResult(); - + var sections = new List(); foreach (CommandInfo command in GetCommands(input)) { - string title = GetSectionTitle(command); - string summary = GetSummary(command); - string examples = GetExamples(command); - - StringBuilder content = new StringBuilder(); - - _ = content.Append(_lang.GetPhrase(PhraseKey.HELP_SUMMARY_TITLE.ToString())) - .AppendLine(summary) - .Append(_lang.GetPhrase(PhraseKey.HELP_EXAMPLE_TITLE.ToString())) - .Append(examples); - - entry.Sections.Add(new HelpSection(title, content.ToString())); + sections.Add(GetSection(command)); } - return entry; + return new HelpResult() + { + Sections = sections + }; } public async Task ShowDefaultHelpAsync(ISocketMessageChannel channel) @@ -100,6 +78,38 @@ private IEnumerable GetCommands(string input) return result.Commands.Select(x => x.Command); } + private IEnumerable GetAllModuleSections() + { + var sections = new List(); + foreach (ModuleInfo module in _commandService.Modules) + { + sections.Add(GetSection(module)); + } + + return sections; + } + + private HelpSection GetSection(ModuleInfo module) + => new HelpSection(module.Name, string.Join(" ", module.Commands + .GroupBy(x => x.Name) + .Select(x => $"`{x.Key}`"))); + + private HelpSection GetSection(CommandInfo command) + { + string title = GetSectionTitle(command); + string summary = GetSummary(command); + string examples = GetExamples(command); + + var content = new StringBuilder(); + + _ = content.Append(_lang.GetPhrase(PhraseKey.HELP_SUMMARY_TITLE.ToString())) + .AppendLine(summary) + .Append(_lang.GetPhrase(PhraseKey.HELP_EXAMPLE_TITLE.ToString())) + .Append(examples); + + return new HelpSection(title, content.ToString()); + } + private string GetSectionTitle(CommandInfo command) => $"{command.Name} {GetSectionParameters(command)}"; @@ -109,21 +119,10 @@ private string GetSectionParameters(CommandInfo command) .Select(x => x.IsOptional ? $"[{x.Name}]" : $"<{x.Name}>")); private string GetExamples(CommandInfo command) - { - string[] examples = command.FindAttribute()?.Examples; - - return examples != null - ? string.Join(", ", examples.Select(x => $"`{x}`")) - : _lang.GetPhrase(PhraseKey.HELP_EXAMPLE_EMPTY.ToString()); - } - - private string FindSummary(string id) - => id != null - ? HelpStrings.ResourceManager.GetString(id) - : null; + => command.FindAttribute()?.Examples + .StringJoinOrDefault(x => $"`{x}`", ", ", _lang.GetPhrase(PhraseKey.HELP_EXAMPLE_EMPTY.ToString())); private string GetSummary(CommandInfo command) - => FindSummary(command.Summary) - ?? _lang.GetPhrase(PhraseKey.HELP_SUMMARY_EMPTY.ToString()); + => command.Summary.ValueOrDefault(_lang.GetPhrase(PhraseKey.HELP_SUMMARY_EMPTY.ToString())); } } diff --git a/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj b/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj index 8675ac1..298cc1c 100644 --- a/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj +++ b/src/Miunie.InversionOfControl/Miunie.InversionOfControl.csproj @@ -1,9 +1,9 @@  - netstandard2.1 + netstandard2.0 ../.ruleset - latest + 8.0 diff --git a/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj b/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj index 99c9b05..28407cc 100644 --- a/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj +++ b/src/Miunie.LiteDbStorage/Miunie.LiteDbStorage.csproj @@ -1,9 +1,9 @@  - netstandard2.1 + netstandard2.0 ../.ruleset - latest + 8.0 diff --git a/src/Miunie.Logger/Miunie.Logger.csproj b/src/Miunie.Logger/Miunie.Logger.csproj index fc3f0ce..e23d738 100644 --- a/src/Miunie.Logger/Miunie.Logger.csproj +++ b/src/Miunie.Logger/Miunie.Logger.csproj @@ -1,9 +1,9 @@  - netstandard2.1 + netstandard2.0 ../.ruleset - latest + 8.0 diff --git a/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj b/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj index 622ed6b..685d8a2 100644 --- a/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj +++ b/src/Miunie.SystemInfrastructure/Miunie.SystemInfrastructure.csproj @@ -1,9 +1,9 @@  - netstandard2.1 + netstandard2.0 ../.ruleset - latest + 8.0 From f5a9da94f23b2298ed97d817293b353a23538a38 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Wed, 11 Mar 2020 11:10:58 -0500 Subject: [PATCH 04/11] Replace collection count property A quick change that fixes the previous string[].Length to now use the required IEnumerable.Count(). --- src/Miunie.Discord/Extensions/StringExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Miunie.Discord/Extensions/StringExtensions.cs b/src/Miunie.Discord/Extensions/StringExtensions.cs index f0aa24d..0d676cb 100644 --- a/src/Miunie.Discord/Extensions/StringExtensions.cs +++ b/src/Miunie.Discord/Extensions/StringExtensions.cs @@ -14,6 +14,7 @@ // along with Miunie. If not, see . using System.Collections.Generic; +using System.Linq; namespace Miunie.Discord { @@ -28,7 +29,7 @@ internal static string JoinOrDefault( this IEnumerable values, string separator, string fallback = "") - => values?.Length > 0 + => values?.Count() > 0 ? string.Join(separator, values) : fallback ?? string.Empty; } From b2597680fe75edb0025ac211e1e17dc17b9b7dff Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Wed, 11 Mar 2020 11:20:48 -0500 Subject: [PATCH 05/11] Apply implicit declaration where needed Another minor fix that applies implicit declaration where it was needed, alongside adding a blank line in between a variable and a for each statement. --- src/Miunie.Discord/Embeds/EmbedConstructor.cs | 2 +- src/Miunie.Discord/Providers/HelpCommandProvider.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Miunie.Discord/Embeds/EmbedConstructor.cs b/src/Miunie.Discord/Embeds/EmbedConstructor.cs index a2bf627..1c70240 100644 --- a/src/Miunie.Discord/Embeds/EmbedConstructor.cs +++ b/src/Miunie.Discord/Embeds/EmbedConstructor.cs @@ -31,7 +31,7 @@ internal static class EmbedConstructor public static Embed CreateHelpEmbed(HelpResult result) { - EmbedBuilder builder = new EmbedBuilder().WithColor(MiuniePinkColor); + var builder = new EmbedBuilder().WithColor(MiuniePinkColor); if (!string.IsNullOrWhiteSpace(result.Title)) { diff --git a/src/Miunie.Discord/Providers/HelpCommandProvider.cs b/src/Miunie.Discord/Providers/HelpCommandProvider.cs index 2f28860..11d4e77 100644 --- a/src/Miunie.Discord/Providers/HelpCommandProvider.cs +++ b/src/Miunie.Discord/Providers/HelpCommandProvider.cs @@ -81,6 +81,7 @@ private IEnumerable GetCommands(string input) private IEnumerable GetAllModuleSections() { var sections = new List(); + foreach (ModuleInfo module in _commandService.Modules) { sections.Add(GetSection(module)); From 2ad22abf054aacc9111518dab49e5b2badc15902 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Wed, 11 Mar 2020 13:11:28 -0500 Subject: [PATCH 06/11] Minor refactor in code - Created new method GetModuleCommandBlocks(ModuleInfo) in HelpCommandProvider. - Modified ProfileCommand to use "to" instead of "for" in both summaries. - Modified HelpCommandProvider.GetDefault() to use _commandService.Modules.Select() instead. - Modified HelpCommandProvider.GetSection(ModuleInfo) to use GetModuleCommandBlocks(). - Removed HelpCommandProvider.GetAllModuleHelpSections(). --- .../CommandModules/HelpCommand.cs | 8 +++---- .../CommandModules/ProfileCommand.cs | 4 ++-- .../Providers/HelpCommandProvider.cs | 23 ++++++------------- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/Miunie.Discord/CommandModules/HelpCommand.cs b/src/Miunie.Discord/CommandModules/HelpCommand.cs index 9002069..a1fe025 100644 --- a/src/Miunie.Discord/CommandModules/HelpCommand.cs +++ b/src/Miunie.Discord/CommandModules/HelpCommand.cs @@ -23,11 +23,11 @@ namespace Miunie.Discord.CommandModules [Name("Help")] public class HelpCommand : ModuleBase { - private readonly HelpCommandProvider _helpService; + private readonly HelpCommandProvider _helpProvider; public HelpCommand(CommandHandler commandHandler, ILanguageProvider lang) { - _helpService = commandHandler.GetHelpProvider(lang); + _helpProvider = commandHandler.GetHelpProvider(lang); } [Command("help")] @@ -35,7 +35,7 @@ public HelpCommand(CommandHandler commandHandler, ILanguageProvider lang) [Examples("help")] public async Task GetHelp() { - await _helpService.ShowDefaultHelpAsync(Context.Channel); + await _helpProvider.ShowDefaultHelpAsync(Context.Channel); } [Command("help")] @@ -43,7 +43,7 @@ public async Task GetHelp() [Examples("help repo")] public async Task GetHelp([Remainder]string input) { - await _helpService.ShowCommandHelpAsync(Context.Channel, input); + await _helpProvider.ShowCommandHelpAsync(Context.Channel, input); } } } diff --git a/src/Miunie.Discord/CommandModules/ProfileCommand.cs b/src/Miunie.Discord/CommandModules/ProfileCommand.cs index b40557e..a33cc1c 100644 --- a/src/Miunie.Discord/CommandModules/ProfileCommand.cs +++ b/src/Miunie.Discord/CommandModules/ProfileCommand.cs @@ -70,7 +70,7 @@ public async Task ShowReputationLogAsync(MiunieUser user, int page = 1) } [Command("+rep")] - [Summary("Give a good ol' positive reputation for a user!")] + [Summary("Give a good ol' positive reputation to a user!")] [Examples("+rep @Miunie")] public async Task AddReputationAsync(MiunieUser user) { @@ -80,7 +80,7 @@ public async Task AddReputationAsync(MiunieUser user) } [Command("-rep")] - [Summary("Give a cold-blooded negative reputation for a user...")] + [Summary("Give a cold-blooded negative reputation to a user...")] [Examples("-rep @You")] public async Task RemoveReputationAsync(MiunieUser user) { diff --git a/src/Miunie.Discord/Providers/HelpCommandProvider.cs b/src/Miunie.Discord/Providers/HelpCommandProvider.cs index 11d4e77..89b6cd7 100644 --- a/src/Miunie.Discord/Providers/HelpCommandProvider.cs +++ b/src/Miunie.Discord/Providers/HelpCommandProvider.cs @@ -43,7 +43,7 @@ public HelpResult GetDefault() => new HelpResult { Title = _lang.GetPhrase(PhraseKey.USER_EMBED_HELP_TITLE.ToString()), - Sections = GetAllModuleSections() + Sections = _commandService.Modules.Select(x => GetSection(x)) }; public HelpResult Search(string input) @@ -78,22 +78,13 @@ private IEnumerable GetCommands(string input) return result.Commands.Select(x => x.Command); } - private IEnumerable GetAllModuleSections() - { - var sections = new List(); - - foreach (ModuleInfo module in _commandService.Modules) - { - sections.Add(GetSection(module)); - } - - return sections; - } - private HelpSection GetSection(ModuleInfo module) - => new HelpSection(module.Name, string.Join(" ", module.Commands - .GroupBy(x => x.Name) - .Select(x => $"`{x.Key}`"))); + => new HelpSection(module.Name, GetModuleCommandBlocks(module)); + + private string GetModuleCommandBlocks(ModuleInfo module) + => string.Join(" ", module.Commands + .GroupBy(x => x.Name) + .Select(x => $"`{x.Key}`")); private HelpSection GetSection(CommandInfo command) { From 7b934ffe610b138b7bda0612cab65fc857ff9432 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Wed, 11 Mar 2020 14:06:31 -0500 Subject: [PATCH 07/11] Change search method format - Modified HelpCommandProvider.Search(string) to use the similar .Select() method used in GetDefault(). --- src/Miunie.Discord/Providers/HelpCommandProvider.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Miunie.Discord/Providers/HelpCommandProvider.cs b/src/Miunie.Discord/Providers/HelpCommandProvider.cs index 89b6cd7..a774e94 100644 --- a/src/Miunie.Discord/Providers/HelpCommandProvider.cs +++ b/src/Miunie.Discord/Providers/HelpCommandProvider.cs @@ -47,18 +47,10 @@ public HelpResult GetDefault() }; public HelpResult Search(string input) - { - var sections = new List(); - foreach (CommandInfo command in GetCommands(input)) + => new HelpResult() { - sections.Add(GetSection(command)); - } - - return new HelpResult() - { - Sections = sections + Sections = GetCommands(input).Select(x => GetSection(x)) }; - } public async Task ShowDefaultHelpAsync(ISocketMessageChannel channel) => await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(GetDefault())); From e842f9cbaf9a3523fcaaf36e8d8ec6e3bfadb9d0 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Thu, 12 Mar 2020 13:34:44 -0500 Subject: [PATCH 08/11] Adjust methods and dependencies - Modify Container.AddMiunieTypes(this IServiceCollection) to include CommandService - Modify method GetHelp() in HelpCommand to handle sending the message result - Modify method GetHelp(string) in HelpCommand to handle sending the message result - Renamed HelpCommandProvider to CommandHelpProvider - Rename method GetDefault() to ForAllCommands() in CommandHelpProvider - Rename method Search(string) to FromInput(string) in CommandHelpProvider - Remove method GetHelpProvider(ILanguageProvider) from CommandHandler - Remove method ShowDefaultHelpAsync(IMessageChannel) in CommandHelpProvider - Remove method ShowCommandHelpAsync(IMessageChannel, string) from CommandHelpProvider - Delete StringExtensions - Delete TExtensions --- src/Miunie.Discord/CommandHandler.cs | 8 +-- .../CommandModules/HelpCommand.cs | 13 +++-- .../Extensions/StringExtensions.cs | 36 ------------ src/Miunie.Discord/Extensions/TExtensions.cs | 33 ----------- ...mandProvider.cs => CommandHelpProvider.cs} | 57 ++++++++++++------- src/Miunie.InversionOfControl/Container.cs | 2 + 6 files changed, 49 insertions(+), 100 deletions(-) delete mode 100644 src/Miunie.Discord/Extensions/StringExtensions.cs delete mode 100644 src/Miunie.Discord/Extensions/TExtensions.cs rename src/Miunie.Discord/Providers/{HelpCommandProvider.cs => CommandHelpProvider.cs} (71%) diff --git a/src/Miunie.Discord/CommandHandler.cs b/src/Miunie.Discord/CommandHandler.cs index 17e49c1..f42b611 100644 --- a/src/Miunie.Discord/CommandHandler.cs +++ b/src/Miunie.Discord/CommandHandler.cs @@ -18,7 +18,6 @@ using Miunie.Core.Configuration; using Miunie.Core.Entities.Discord; using Miunie.Core.Logging; -using Miunie.Core.Providers; using Miunie.Discord.Convertors; using Miunie.Discord.TypeReaders; using System; @@ -36,10 +35,10 @@ public class CommandHandler private readonly EntityConvertor _convertor; private readonly IBotConfiguration _botConfig; - public CommandHandler(IDiscord discord, IServiceProvider services, ILogWriter logger, EntityConvertor convertor, IBotConfiguration botConfig) + public CommandHandler(IDiscord discord, CommandService commandService, IServiceProvider services, ILogWriter logger, EntityConvertor convertor, IBotConfiguration botConfig) { _discord = discord; - _commandService = new CommandService(); + _commandService = commandService; _services = services; _logger = logger; _convertor = convertor; @@ -54,9 +53,6 @@ public async Task InitializeAsync() _ = await _commandService.AddModulesAsync(Assembly.GetExecutingAssembly(), _services); } - public HelpCommandProvider GetHelpProvider(ILanguageProvider lang) - => new HelpCommandProvider(_commandService, lang); - private async Task HandleCommandAsync(SocketMessage s) { if (_botConfig.CommandsEnabled == false) diff --git a/src/Miunie.Discord/CommandModules/HelpCommand.cs b/src/Miunie.Discord/CommandModules/HelpCommand.cs index a1fe025..135e70d 100644 --- a/src/Miunie.Discord/CommandModules/HelpCommand.cs +++ b/src/Miunie.Discord/CommandModules/HelpCommand.cs @@ -16,6 +16,7 @@ using Discord.Commands; using Miunie.Core.Providers; using Miunie.Discord.Attributes; +using Miunie.Discord.Embeds; using System.Threading.Tasks; namespace Miunie.Discord.CommandModules @@ -23,11 +24,11 @@ namespace Miunie.Discord.CommandModules [Name("Help")] public class HelpCommand : ModuleBase { - private readonly HelpCommandProvider _helpProvider; + private readonly CommandHelpProvider _helpProvider; - public HelpCommand(CommandHandler commandHandler, ILanguageProvider lang) + public HelpCommand(CommandService commandService, ILanguageProvider lang) { - _helpProvider = commandHandler.GetHelpProvider(lang); + _helpProvider = new CommandHelpProvider(commandService, lang); } [Command("help")] @@ -35,7 +36,8 @@ public HelpCommand(CommandHandler commandHandler, ILanguageProvider lang) [Examples("help")] public async Task GetHelp() { - await _helpProvider.ShowDefaultHelpAsync(Context.Channel); + var helpResult = _helpProvider.ForAllCommands(); + _ = await Context.Channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(helpResult)); } [Command("help")] @@ -43,7 +45,8 @@ public async Task GetHelp() [Examples("help repo")] public async Task GetHelp([Remainder]string input) { - await _helpProvider.ShowCommandHelpAsync(Context.Channel, input); + var helpResult = _helpProvider.FromInput(input); + _ = await Context.Channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(helpResult)); } } } diff --git a/src/Miunie.Discord/Extensions/StringExtensions.cs b/src/Miunie.Discord/Extensions/StringExtensions.cs deleted file mode 100644 index 0d676cb..0000000 --- a/src/Miunie.Discord/Extensions/StringExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -// This file is part of Miunie. -// -// Miunie is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Miunie is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Miunie. If not, see . - -using System.Collections.Generic; -using System.Linq; - -namespace Miunie.Discord -{ - internal static class StringExtensions - { - internal static string ValueOrDefault(this string value, string fallback = "") - => string.IsNullOrWhiteSpace(value) - ? fallback ?? string.Empty - : value; - - internal static string JoinOrDefault( - this IEnumerable values, - string separator, - string fallback = "") - => values?.Count() > 0 - ? string.Join(separator, values) - : fallback ?? string.Empty; - } -} diff --git a/src/Miunie.Discord/Extensions/TExtensions.cs b/src/Miunie.Discord/Extensions/TExtensions.cs deleted file mode 100644 index 526b7b3..0000000 --- a/src/Miunie.Discord/Extensions/TExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -// This file is part of Miunie. -// -// Miunie is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Miunie is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Miunie. If not, see . - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Miunie.Discord -{ - internal static class TExtensions - { - internal static string StringJoinOrDefault( - this IEnumerable values, - Func formatter, - string separator, - string fallback = "") - => values?.Count() > 0 - ? string.Join(separator, values.Select(x => formatter.Invoke(x))) - : fallback ?? string.Empty; - } -} diff --git a/src/Miunie.Discord/Providers/HelpCommandProvider.cs b/src/Miunie.Discord/Providers/CommandHelpProvider.cs similarity index 71% rename from src/Miunie.Discord/Providers/HelpCommandProvider.cs rename to src/Miunie.Discord/Providers/CommandHelpProvider.cs index a774e94..1c59a89 100644 --- a/src/Miunie.Discord/Providers/HelpCommandProvider.cs +++ b/src/Miunie.Discord/Providers/CommandHelpProvider.cs @@ -14,50 +14,41 @@ // along with Miunie. If not, see . using Discord.Commands; -using Discord.WebSocket; using Miunie.Core.Entities; using Miunie.Core.Providers; using Miunie.Discord.Attributes; -using Miunie.Discord.Embeds; using Miunie.Discord.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace Miunie.Discord { - public class HelpCommandProvider + public class CommandHelpProvider { private readonly CommandService _commandService; private readonly ILanguageProvider _lang; - public HelpCommandProvider(CommandService commandService, ILanguageProvider lang) + public CommandHelpProvider(CommandService commandService, ILanguageProvider lang) { _commandService = commandService; _lang = lang; } - public HelpResult GetDefault() + public HelpResult ForAllCommands() => new HelpResult { Title = _lang.GetPhrase(PhraseKey.USER_EMBED_HELP_TITLE.ToString()), Sections = _commandService.Modules.Select(x => GetSection(x)) }; - public HelpResult Search(string input) + public HelpResult FromInput(string input) => new HelpResult() { Sections = GetCommands(input).Select(x => GetSection(x)) }; - public async Task ShowDefaultHelpAsync(ISocketMessageChannel channel) - => await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(GetDefault())); - - public async Task ShowCommandHelpAsync(ISocketMessageChannel channel, string input) - => await channel.SendMessageAsync(embed: EmbedConstructor.CreateHelpEmbed(Search(input))); - private IEnumerable GetCommands(string input) { SearchResult result = _commandService.Search(input); @@ -74,9 +65,13 @@ private HelpSection GetSection(ModuleInfo module) => new HelpSection(module.Name, GetModuleCommandBlocks(module)); private string GetModuleCommandBlocks(ModuleInfo module) - => string.Join(" ", module.Commands + { + var commands = module.Commands .GroupBy(x => x.Name) - .Select(x => $"`{x.Key}`")); + .Select(x => $"`{x.Key}`"); + + return string.Join(" ", commands); + } private HelpSection GetSection(CommandInfo command) { @@ -98,15 +93,37 @@ private string GetSectionTitle(CommandInfo command) => $"{command.Name} {GetSectionParameters(command)}"; private string GetSectionParameters(CommandInfo command) - => string.Join(" ", command.Parameters + { + var parameters = command.Parameters .OrderBy(x => x.IsOptional) - .Select(x => x.IsOptional ? $"[{x.Name}]" : $"<{x.Name}>")); + .Select(x => GetParameterBlock(x)); + + return string.Join(" ", parameters); + } + + private string GetParameterBlock(ParameterInfo parameter) + => parameter.IsOptional ? $"[{parameter.Name}]" : $"<{parameter.Name}>"; private string GetExamples(CommandInfo command) - => command.FindAttribute()?.Examples - .StringJoinOrDefault(x => $"`{x}`", ", ", _lang.GetPhrase(PhraseKey.HELP_EXAMPLE_EMPTY.ToString())); + { + var examples = command.FindAttribute()?.Examples; + + if (!examples?.Any() ?? true) + { + return _lang.GetPhrase(PhraseKey.HELP_EXAMPLE_EMPTY.ToString()); + } + + return string.Join(", ", examples.Select(x => $"`{x}`")); + } private string GetSummary(CommandInfo command) - => command.Summary.ValueOrDefault(_lang.GetPhrase(PhraseKey.HELP_SUMMARY_EMPTY.ToString())); + { + if (string.IsNullOrWhiteSpace(command.Summary)) + { + return _lang.GetPhrase(PhraseKey.HELP_SUMMARY_EMPTY.ToString()); + } + + return command.Summary; + } } } diff --git a/src/Miunie.InversionOfControl/Container.cs b/src/Miunie.InversionOfControl/Container.cs index 4d3f29f..1bd5453 100644 --- a/src/Miunie.InversionOfControl/Container.cs +++ b/src/Miunie.InversionOfControl/Container.cs @@ -13,6 +13,7 @@ // You should have received a copy of the GNU General Public License // along with Miunie. If not, see . +using Discord.Commands; using Microsoft.Extensions.DependencyInjection; using Miunie.Core.Attributes; using Miunie.Core.Configuration; @@ -47,6 +48,7 @@ public static IServiceCollection AddMiunieTypes(this IServiceCollection collecti .AddSingleton() .AddScoped() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddMiunieServices(); From 82060bd4e42eeeaec2eb8d78363edd422fc3e48a Mon Sep 17 00:00:00 2001 From: Abner <25711694+AbnerSquared@users.noreply.github.com> Date: Fri, 13 Mar 2020 00:14:40 -0500 Subject: [PATCH 09/11] Rename private variables This quick formatting fix properly renames the specified variables, as brought to light by 1n5an1ty. --- src/Miunie.Discord/Embeds/EmbedConstructor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Miunie.Discord/Embeds/EmbedConstructor.cs b/src/Miunie.Discord/Embeds/EmbedConstructor.cs index 1c70240..af75e3e 100644 --- a/src/Miunie.Discord/Embeds/EmbedConstructor.cs +++ b/src/Miunie.Discord/Embeds/EmbedConstructor.cs @@ -26,8 +26,8 @@ namespace Miunie.Discord.Embeds { internal static class EmbedConstructor { - private static readonly int RepLogPageSize = 10; - private static readonly uint MiuniePinkColor = 0xEC407A; + private static readonly int _repLogPageSize = 10; + private static readonly uint _miuniePinkColor = 0xEC407A; public static Embed CreateHelpEmbed(HelpResult result) { From bd998ee3fe6497a154dff28e03e6dbae2ddcfbf6 Mon Sep 17 00:00:00 2001 From: AbnerSquared <25711694+AbnerSquared@users.noreply.github.com> Date: Fri, 13 Mar 2020 00:19:20 -0500 Subject: [PATCH 10/11] Properly rename private variables This push now correctly renames the private variables mentioned. --- src/Miunie.Discord/Embeds/EmbedConstructor.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Miunie.Discord/Embeds/EmbedConstructor.cs b/src/Miunie.Discord/Embeds/EmbedConstructor.cs index 1c70240..651127a 100644 --- a/src/Miunie.Discord/Embeds/EmbedConstructor.cs +++ b/src/Miunie.Discord/Embeds/EmbedConstructor.cs @@ -26,12 +26,12 @@ namespace Miunie.Discord.Embeds { internal static class EmbedConstructor { - private static readonly int RepLogPageSize = 10; - private static readonly uint MiuniePinkColor = 0xEC407A; + private static readonly int _repLogPageSize = 10; + private static readonly uint _miuniePinkColor = 0xEC407A; public static Embed CreateHelpEmbed(HelpResult result) { - var builder = new EmbedBuilder().WithColor(MiuniePinkColor); + var builder = new EmbedBuilder().WithColor(_miuniePinkColor); if (!string.IsNullOrWhiteSpace(result.Title)) { @@ -51,10 +51,10 @@ public static Embed CreateReputationLog(IEnumerable entries, in var embed = Paginator.PaginateEmbed( entries, new EmbedBuilder() - .WithColor(new Color(MiuniePinkColor)) + .WithColor(new Color(_miuniePinkColor)) .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_REP_LOG_TITLE.ToString())), index, - RepLogPageSize, + _repLogPageSize, x => $"{(x.IsFromInvoker ? "**To:**" : "**From:**")} {x.TargetName} (**{FormatReputationType(x.Type)}**) {x.GivenAt:d} at {x.GivenAt:t} UTC"); if (string.IsNullOrWhiteSpace(embed.Description)) @@ -70,7 +70,7 @@ public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang) var realnessPhrase = lang.GetPhrase((mUser.IsBot ? PhraseKey.USER_EMBED_IS_BOT : PhraseKey.USER_EMBED_IS_HUMAN).ToString()); return new EmbedBuilder() - .WithColor(new Color(MiuniePinkColor)) + .WithColor(new Color(_miuniePinkColor)) .WithTitle(lang.GetPhrase(PhraseKey.USER_EMBED_TITLE.ToString())) .WithThumbnailUrl(mUser.AvatarUrl) .AddField(lang.GetPhrase(PhraseKey.USER_EMBED_NAME_TITLE.ToString()), mUser.Name) @@ -85,7 +85,7 @@ public static Embed ToEmbed(this MiunieUser mUser, ILanguageProvider lang) public static Embed ToEmbed(this MiunieGuild mGuild, ILanguageProvider lang) => new EmbedBuilder() - .WithColor(new Color(MiuniePinkColor)) + .WithColor(new Color(_miuniePinkColor)) .WithThumbnailUrl(mGuild.IconUrl) .WithTitle(lang.GetPhrase(PhraseKey.GUILD_EMBED_TITLE.ToString())) .AddField(lang.GetPhrase(PhraseKey.GUILD_EMBED_NAME_TITLE.ToString()), mGuild.Name) From add39db515e10329cdfa2449821613eae6db93a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Sedl=C3=A1=C4=8Dek?= Date: Fri, 13 Mar 2020 09:48:35 +0000 Subject: [PATCH 11/11] Update src/Miunie.Discord/Providers/CommandHelpProvider.cs --- src/Miunie.Discord/Providers/CommandHelpProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Miunie.Discord/Providers/CommandHelpProvider.cs b/src/Miunie.Discord/Providers/CommandHelpProvider.cs index 1c59a89..c6b3121 100644 --- a/src/Miunie.Discord/Providers/CommandHelpProvider.cs +++ b/src/Miunie.Discord/Providers/CommandHelpProvider.cs @@ -108,7 +108,7 @@ private string GetExamples(CommandInfo command) { var examples = command.FindAttribute()?.Examples; - if (!examples?.Any() ?? true) + if (examples is null || !examples.Any()) { return _lang.GetPhrase(PhraseKey.HELP_EXAMPLE_EMPTY.ToString()); }