From de6d461e781a9b5f23fde72146b2af36bbcaf120 Mon Sep 17 00:00:00 2001 From: Cenngo Date: Tue, 19 Apr 2022 16:07:31 +0300 Subject: [PATCH] add inline docs --- .../Entities/Guilds/IGuild.cs | 4 ++ .../Interactions/ApplicationCommandOption.cs | 10 +++- .../ApplicationCommandOptionChoice.cs | 4 ++ .../ApplicationCommandProperties.cs | 49 ++++++++++++++++++- .../ContextMenus/MessageCommandBuilder.cs | 19 ++++++- .../ContextMenus/UserCommandBuilder.cs | 19 ++++++- .../Interactions/IApplicationCommand.cs | 18 +++++++ .../Interactions/IApplicationCommandOption.cs | 18 +++++++ .../IApplicationCommandOptionChoice.cs | 9 ++++ .../SlashCommands/SlashCommandBuilder.cs | 49 +++++++++++++++++++ .../InteractionService.cs | 8 ++- .../Utilities/ApplicationCommandRestUtil.cs | 14 +++--- src/Discord.Net.Rest/DiscordRestApiClient.cs | 1 + 13 files changed, 208 insertions(+), 14 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 07c426f09..207c9485f 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -1142,6 +1142,10 @@ namespace Discord /// /// Gets this guilds application commands. /// + /// + /// Whether to include full localization dictionaries in the returned objects, + /// instead of the localized name and description fields. + /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs index 98c7e8f79..556257b47 100644 --- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs +++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs @@ -87,6 +87,10 @@ namespace Discord /// public List ChannelTypes { get; set; } + /// + /// Gets or sets the localization dictionary for the name field of this option. + /// + /// Thrown when any of the dictionary keys is an invalid locale. public IDictionary NameLocalizations { get => _nameLocalizations; @@ -103,6 +107,10 @@ namespace Discord } } + /// + /// Gets or sets the localization dictionary for the description field of this option. + /// + /// Thrown when any of the dictionary keys is an invalid locale. public IDictionary DescriptionLocalizations { get => _descriptionLocalizations; @@ -115,7 +123,7 @@ namespace Discord EnsureValidOptionDescription(description); } - _nameLocalizations = value; + _descriptionLocalizations = value; } } diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs index 60db06cdc..8f1ecc6d2 100644 --- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs +++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs @@ -46,6 +46,10 @@ namespace Discord } } + /// + /// Gets or sets the localization dictionary for the name field of this choice. + /// + /// Thrown when any of the dictionary keys is an invalid locale. public IDictionary NameLocalizations { get => _nameLocalizations; diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs index 9fa5d67a8..3c1312504 100644 --- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs +++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandProperties.cs @@ -1,5 +1,9 @@ +using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text.RegularExpressions; namespace Discord { @@ -8,6 +12,9 @@ namespace Discord /// public abstract class ApplicationCommandProperties { + private IReadOnlyDictionary _nameLocalizations; + private IReadOnlyDictionary _descriptionLocalizations; + internal abstract ApplicationCommandType Type { get; } /// @@ -20,9 +27,47 @@ namespace Discord /// public Optional IsDefaultPermission { get; set; } - public IDictionary? NameLocalizations { get; set; } + /// + /// Gets or sets the localization dictionary for the name field of this command. + /// + public IReadOnlyDictionary? NameLocalizations + { + get => _nameLocalizations; + set + { + foreach (var (locale, name) in value) + { + if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) + throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); + + Preconditions.AtLeast(name.Length, 1, nameof(name)); + Preconditions.AtMost(name.Length, SlashCommandBuilder.MaxNameLength, nameof(name)); + if (!Regex.IsMatch(name, @"^[\w-]{1,32}$")) + throw new ArgumentException("Option name cannot contain any special characters or whitespaces!", nameof(name)); + } + _nameLocalizations = value; + } + } + + /// + /// Gets or sets the localization dictionary for the description field of this command. + /// + public IReadOnlyDictionary? DescriptionLocalizations + { + get => _descriptionLocalizations; + set + { + foreach (var (locale, description) in value) + { + if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) + throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); - public IDictionary? DescriptionLocalizations { get; set; } + Preconditions.AtLeast(description.Length, 1, nameof(description)); + Preconditions.AtMost(description.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(description)); + } + _descriptionLocalizations = value; + } + } internal ApplicationCommandProperties() { } } diff --git a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs index 831a5a54c..32bcab936 100644 --- a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs @@ -36,6 +36,9 @@ namespace Discord /// public bool IsDefaultPermission { get; set; } = true; + /// + /// Gets the localization dictionary for the name field of this command. + /// public IReadOnlyDictionary NameLocalizations => _nameLocalizations; private string _name; @@ -82,6 +85,13 @@ namespace Discord return this; } + /// + /// Sets the collection. + /// + /// Localization dictionary for the name field of this command. + /// + /// Thrown if is null. + /// Thrown if any dictionary key is an invalid locale string. public MessageCommandBuilder WithNameLocalizations(IDictionary nameLocalizations) { if (nameLocalizations is null) @@ -99,6 +109,13 @@ namespace Discord return this; } + /// + /// Adds a new entry to the collection. + /// + /// Locale of the entry. + /// Localized string for the name field. + /// The current builder. + /// Thrown if is an invalid locale string. public MessageCommandBuilder AddNameLocalization(string locale, string name) { if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) @@ -112,7 +129,7 @@ namespace Discord return this; } - internal static void EnsureValidCommandName(string name) + private static void EnsureValidCommandName(string name) { Preconditions.NotNullOrEmpty(name, nameof(name)); Preconditions.AtLeast(name.Length, 1, nameof(name)); diff --git a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs index 4ae0c18e3..7c94dcb25 100644 --- a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs @@ -36,6 +36,9 @@ namespace Discord /// public bool IsDefaultPermission { get; set; } = true; + /// + /// Gets the localization dictionary for the name field of this command. + /// public IReadOnlyDictionary NameLocalizations => _nameLocalizations; private string _name; @@ -80,6 +83,13 @@ namespace Discord return this; } + /// + /// Sets the collection. + /// + /// Localization dictionary for the name field of this command. + /// + /// Thrown if is null. + /// Thrown if any dictionary key is an invalid locale string. public UserCommandBuilder WithNameLocalizations(IDictionary nameLocalizations) { if (nameLocalizations is null) @@ -97,6 +107,13 @@ namespace Discord return this; } + /// + /// Adds a new entry to the collection. + /// + /// Locale of the entry. + /// Localized string for the name field. + /// The current builder. + /// Thrown if is an invalid locale string. public UserCommandBuilder AddNameLocalization(string locale, string name) { if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) @@ -110,7 +127,7 @@ namespace Discord return this; } - internal static void EnsureValidCommandName(string name) + private static void EnsureValidCommandName(string name) { Preconditions.NotNullOrEmpty(name, nameof(name)); Preconditions.AtLeast(name.Length, 1, nameof(name)); diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs index 1b7e28159..e30d795ff 100644 --- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs +++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs @@ -39,12 +39,30 @@ namespace Discord /// IReadOnlyCollection Options { get; } + /// + /// Gets the localization dictionary for the name field of this command. + /// IReadOnlyDictionary? NameLocalizations { get; } + /// + /// Gets the localization dictionary for the description field of this command. + /// IReadOnlyDictionary? DescriptionLocalizations { get; } + /// + /// Gets the localized name of this command. + /// + /// + /// Only returned when the `withLocalizations` query parameter is set to true when requesting the command. + /// string? NameLocalized { get; } + /// + /// Gets the localized description of this command. + /// + /// + /// Only returned when the `withLocalizations` query parameter is set to true when requesting the command. + /// string? DescriptionLocalized { get; } /// diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs index 78f6487df..68bf00ebf 100644 --- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs +++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs @@ -62,12 +62,30 @@ namespace Discord /// IReadOnlyCollection ChannelTypes { get; } + /// + /// Gets the localization dictionary for the name field of this command. + /// IReadOnlyDictionary? NameLocalizations { get; } + /// + /// Gets the localization dictionary for the description field of this command. + /// IReadOnlyDictionary? DescriptionLocalizations { get; } + /// + /// Gets the localized name of this command. + /// + /// + /// Only returned when the `withLocalizations` query parameter is set to true when requesting the command. + /// string? NameLocalized { get; } + /// + /// Gets the localized description of this command. + /// + /// + /// Only returned when the `withLocalizations` query parameter is set to true when requesting the command. + /// string? DescriptionLocalized { get; } } } diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs index 96b5c4b5d..66d0f1b9b 100644 --- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs +++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs @@ -17,8 +17,17 @@ namespace Discord /// object Value { get; } + /// + /// Gets the localization dictionary for the name field of this command. + /// IReadOnlyDictionary? NameLocalizations { get; } + /// + /// Gets the localized name of this command. + /// + /// + /// Only returned when the `withLocalizations` query parameter is set to true when requesting the command. + /// string? NameLocalized { get; } } } diff --git a/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs index e553fd7fa..2a6862fd3 100644 --- a/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs @@ -65,8 +65,14 @@ namespace Discord } } + /// + /// Gets the localization dictionary for the name field of this command. + /// public IReadOnlyDictionary NameLocalizations => _nameLocalizations; + /// + /// Gets the localization dictionary for the description field of this command. + /// public IReadOnlyDictionary DescriptionLocalizations => _descriptionLocalizations; /// @@ -153,6 +159,8 @@ namespace Discord /// If this option is set to autocomplete. /// The options of the option to add. /// The allowed channel types for this option. + /// Localization dictionary for the name field of this command. + /// Localization dictionary for the description field of this command. /// The choices of this option. /// The smallest number value the user can input. /// The largest number value the user can input. @@ -244,6 +252,13 @@ namespace Discord return this; } + /// + /// Sets the collection. + /// + /// Localization dictionary for the name field of this command. + /// + /// Thrown if is null. + /// Thrown if any dictionary key is an invalid locale string. public SlashCommandBuilder WithNameLocalizations(IDictionary nameLocalizations) { if (nameLocalizations is null) @@ -261,6 +276,13 @@ namespace Discord return this; } + /// + /// Sets the collection. + /// + /// Localization dictionary for the name field of this command. + /// + /// Thrown if is null. + /// Thrown if any dictionary key is an invalid locale string. public SlashCommandBuilder WithDescriptionLocalizations(IDictionary descriptionLocalizations) { if (descriptionLocalizations is null) @@ -278,6 +300,13 @@ namespace Discord return this; } + /// + /// Adds a new entry to the collection. + /// + /// Locale of the entry. + /// Localized string for the name field. + /// The current builder. + /// Thrown if is an invalid locale string. public SlashCommandBuilder AddNameLocalization(string locale, string name) { if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) @@ -291,6 +320,13 @@ namespace Discord return this; } + /// + /// Adds a new entry to the collection. + /// + /// Locale of the entry. + /// Localized string for the description field. + /// The current builder. + /// Thrown if is an invalid locale string. public SlashCommandBuilder AddDescriptionLocalization(string locale, string description) { if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) @@ -426,8 +462,14 @@ namespace Discord /// public List ChannelTypes { get; set; } + /// + /// Gets the localization dictionary for the name field of this command. + /// public IReadOnlyDictionary NameLocalizations => _nameLocalizations; + /// + /// Gets the localization dictionary for the description field of this command. + /// public IReadOnlyDictionary DescriptionLocalizations => _descriptionLocalizations; /// @@ -482,6 +524,8 @@ namespace Discord /// If this option supports autocomplete. /// The options of the option to add. /// The allowed channel types for this option. + /// Localization dictionary for the description field of this command. + /// Localization dictionary for the description field of this command. /// The choices of this option. /// The smallest number value the user can input. /// The largest number value the user can input. @@ -556,6 +600,7 @@ namespace Discord /// /// The name of the choice. /// The value of the choice. + /// Localization dictionary for the description field of this command. /// The current builder. public SlashCommandOptionBuilder AddChoice(string name, int value, IDictionary nameLocalizations = null) { @@ -567,6 +612,7 @@ namespace Discord /// /// The name of the choice. /// The value of the choice. + /// Localization dictionary for the description field of this command. /// The current builder. public SlashCommandOptionBuilder AddChoice(string name, string value, IDictionary nameLocalizations = null) { @@ -578,6 +624,7 @@ namespace Discord /// /// The name of the choice. /// The value of the choice. + /// Localization dictionary for the description field of this command. /// The current builder. public SlashCommandOptionBuilder AddChoice(string name, double value, IDictionary nameLocalizations = null) { @@ -589,6 +636,7 @@ namespace Discord /// /// The name of the choice. /// The value of the choice. + /// Localization dictionary for the description field of this command. /// The current builder. public SlashCommandOptionBuilder AddChoice(string name, float value, IDictionary nameLocalizations = null) { @@ -600,6 +648,7 @@ namespace Discord /// /// The name of the choice. /// The value of the choice. + /// Localization dictionary for the description field of this command. /// The current builder. public SlashCommandOptionBuilder AddChoice(string name, long value, IDictionary nameLocalizations = null) { diff --git a/src/Discord.Net.Interactions/InteractionService.cs b/src/Discord.Net.Interactions/InteractionService.cs index a34185407..a858d3e9d 100644 --- a/src/Discord.Net.Interactions/InteractionService.cs +++ b/src/Discord.Net.Interactions/InteractionService.cs @@ -60,6 +60,11 @@ namespace Discord.Interactions public event Func ModalCommandExecuted { add { _modalCommandExecutedEvent.Add(value); } remove { _modalCommandExecutedEvent.Remove(value); } } internal readonly AsyncEvent> _modalCommandExecutedEvent = new(); + /// + /// Get the used by this Interaction Service instance to localize strings. + /// + public ILocalizationManager LocalizationManager { get; set; } + private readonly ConcurrentDictionary _typedModuleDefs; private readonly CommandMap _slashCommandMap; private readonly ConcurrentDictionary> _contextCommandMaps; @@ -81,7 +86,6 @@ namespace Discord.Interactions internal readonly string _wildCardExp; internal readonly RunMode _runMode; internal readonly RestResponseCallback _restResponseCallback; - internal readonly ILocalizationManager _localizationManager; /// /// Rest client to be used to register application commands. @@ -181,7 +185,7 @@ namespace Discord.Interactions _enableAutocompleteHandlers = config.EnableAutocompleteHandlers; _autoServiceScopes = config.AutoServiceScopes; _restResponseCallback = config.RestResponseCallback; - _localizationManager = config.LocalizationManager; + LocalizationManager = config.LocalizationManager; _typeConverterMap = new TypeMap(this, new ConcurrentDictionary { diff --git a/src/Discord.Net.Interactions/Utilities/ApplicationCommandRestUtil.cs b/src/Discord.Net.Interactions/Utilities/ApplicationCommandRestUtil.cs index 99acf3b4d..655d4cf88 100644 --- a/src/Discord.Net.Interactions/Utilities/ApplicationCommandRestUtil.cs +++ b/src/Discord.Net.Interactions/Utilities/ApplicationCommandRestUtil.cs @@ -10,7 +10,7 @@ namespace Discord.Interactions #region Parameters public static ApplicationCommandOptionProperties ToApplicationCommandOptionProps(this SlashCommandParameterInfo parameterInfo) { - var localizationManager = parameterInfo.Command.Module.CommandService._localizationManager; + var localizationManager = parameterInfo.Command.Module.CommandService.LocalizationManager; var parameterPath = parameterInfo.GetParameterPath(); var props = new ApplicationCommandOptionProperties @@ -43,7 +43,7 @@ namespace Discord.Interactions public static SlashCommandProperties ToApplicationCommandProps(this SlashCommandInfo commandInfo) { var commandPath = commandInfo.GetCommandPath(); - var localizationManager = commandInfo.Module.CommandService._localizationManager; + var localizationManager = commandInfo.Module.CommandService.LocalizationManager; var props = new SlashCommandBuilder() { @@ -64,7 +64,7 @@ namespace Discord.Interactions public static ApplicationCommandOptionProperties ToApplicationCommandOptionProps(this SlashCommandInfo commandInfo) { - var localizationManager = commandInfo.Module.CommandService._localizationManager; + var localizationManager = commandInfo.Module.CommandService.LocalizationManager; var commandPath = commandInfo.GetCommandPath(); return new ApplicationCommandOptionProperties @@ -82,7 +82,7 @@ namespace Discord.Interactions public static ApplicationCommandProperties ToApplicationCommandProps(this ContextCommandInfo commandInfo) { - var localizationManager = commandInfo.Module.CommandService._localizationManager; + var localizationManager = commandInfo.Module.CommandService.LocalizationManager; var commandPath = commandInfo.GetCommandPath(); return commandInfo.CommandType switch @@ -136,7 +136,7 @@ namespace Discord.Interactions options.AddRange(moduleInfo.SubModules?.SelectMany(x => x.ParseSubModule(args, ignoreDontRegister))); - var localizationManager = moduleInfo.CommandService._localizationManager; + var localizationManager = moduleInfo.CommandService.LocalizationManager; var modulePath = moduleInfo.GetModulePath(); var props = new SlashCommandBuilder @@ -186,9 +186,9 @@ namespace Discord.Interactions Description = moduleInfo.Description, Type = ApplicationCommandOptionType.SubCommandGroup, Options = options, - NameLocalizations = moduleInfo.CommandService._localizationManager?.GetAllNames(moduleInfo.GetModulePath(), LocalizationTarget.Group) + NameLocalizations = moduleInfo.CommandService.LocalizationManager?.GetAllNames(moduleInfo.GetModulePath(), LocalizationTarget.Group) ?? ImmutableDictionary.Empty, - DescriptionLocalizations = moduleInfo.CommandService._localizationManager?.GetAllDescriptions(moduleInfo.GetModulePath(), LocalizationTarget.Group) + DescriptionLocalizations = moduleInfo.CommandService.LocalizationManager?.GetAllDescriptions(moduleInfo.GetModulePath(), LocalizationTarget.Group) ?? ImmutableDictionary.Empty, } }; } diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 5fe9d922d..9b09d5157 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Diagnostics; using System.Globalization; using System.IO;