| @@ -106,13 +106,17 @@ namespace Discord | |||||
| get => _nameLocalizations; | get => _nameLocalizations; | ||||
| set | set | ||||
| { | { | ||||
| foreach (var (locale, name) in value) | |||||
| if (value != null) | |||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| foreach (var (locale, name) in value) | |||||
| { | |||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| EnsureValidOptionName(name); | |||||
| EnsureValidOptionName(name); | |||||
| } | |||||
| } | } | ||||
| _nameLocalizations = value; | _nameLocalizations = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -126,13 +130,17 @@ namespace Discord | |||||
| get => _descriptionLocalizations; | get => _descriptionLocalizations; | ||||
| set | set | ||||
| { | { | ||||
| foreach (var (locale, description) in value) | |||||
| if (value != null) | |||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| foreach (var (locale, description) in value) | |||||
| { | |||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| EnsureValidOptionDescription(description); | |||||
| EnsureValidOptionDescription(description); | |||||
| } | |||||
| } | } | ||||
| _descriptionLocalizations = value; | _descriptionLocalizations = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -55,18 +55,21 @@ namespace Discord | |||||
| get => _nameLocalizations; | get => _nameLocalizations; | ||||
| set | set | ||||
| { | { | ||||
| foreach (var (locale, name) in value) | |||||
| if (value != null) | |||||
| { | { | ||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException("Key values of the dictionary must be valid language codes."); | |||||
| switch (name.Length) | |||||
| foreach (var (locale, name) in value) | |||||
| { | { | ||||
| case > 100: | |||||
| throw new ArgumentOutOfRangeException(nameof(value), | |||||
| "Name length must be less than or equal to 100."); | |||||
| case 0: | |||||
| throw new ArgumentOutOfRangeException(nameof(value), "Name length must at least 1."); | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException("Key values of the dictionary must be valid language codes."); | |||||
| switch (name.Length) | |||||
| { | |||||
| case > 100: | |||||
| throw new ArgumentOutOfRangeException(nameof(value), | |||||
| "Name length must be less than or equal to 100."); | |||||
| case 0: | |||||
| throw new ArgumentOutOfRangeException(nameof(value), "Name length must at least 1."); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -35,16 +35,20 @@ namespace Discord | |||||
| get => _nameLocalizations; | get => _nameLocalizations; | ||||
| set | set | ||||
| { | { | ||||
| foreach (var (locale, name) in value) | |||||
| if (value != null) | |||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| 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)); | |||||
| 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; | _nameLocalizations = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -57,14 +61,18 @@ namespace Discord | |||||
| get => _descriptionLocalizations; | get => _descriptionLocalizations; | ||||
| set | set | ||||
| { | { | ||||
| foreach (var (locale, description) in value) | |||||
| if (value != null) | |||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| foreach (var (locale, description) in value) | |||||
| { | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | |||||
| Preconditions.AtLeast(description.Length, 1, nameof(description)); | |||||
| Preconditions.AtMost(description.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(description)); | |||||
| Preconditions.AtLeast(description.Length, 1, nameof(description)); | |||||
| Preconditions.AtMost(description.Length, SlashCommandBuilder.MaxDescriptionLength, nameof(description)); | |||||
| } | |||||
| } | } | ||||
| _descriptionLocalizations = value; | _descriptionLocalizations = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -910,7 +910,7 @@ namespace Discord | |||||
| if (descriptionLocalizations is null) | if (descriptionLocalizations is null) | ||||
| throw new ArgumentNullException(nameof(descriptionLocalizations)); | throw new ArgumentNullException(nameof(descriptionLocalizations)); | ||||
| foreach (var (locale, description) in _descriptionLocalizations) | |||||
| foreach (var (locale, description) in descriptionLocalizations) | |||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | ||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| @@ -0,0 +1,37 @@ | |||||
| using System; | |||||
| using Discord; | |||||
| using Xunit; | |||||
| namespace Discord; | |||||
| public class CommandBuilderTests | |||||
| { | |||||
| [Fact] | |||||
| public void BuildSimpleSlashCommand() | |||||
| { | |||||
| var command = new SlashCommandBuilder() | |||||
| .WithName("command") | |||||
| .WithDescription("description") | |||||
| .AddOption( | |||||
| "option1", | |||||
| ApplicationCommandOptionType.String, | |||||
| "option1 description", | |||||
| isRequired: true, | |||||
| choices: new [] | |||||
| { | |||||
| new ApplicationCommandOptionChoiceProperties() | |||||
| { | |||||
| Name = "choice1", Value = "1" | |||||
| } | |||||
| }) | |||||
| .AddOptions(new SlashCommandOptionBuilder() | |||||
| .WithName("option2") | |||||
| .WithDescription("option2 description") | |||||
| .WithType(ApplicationCommandOptionType.String) | |||||
| .WithRequired(true) | |||||
| .AddChannelType(ChannelType.Text) | |||||
| .AddChoice("choice1", "1") | |||||
| .AddChoice("choice2", "2")); | |||||
| command.Build(); | |||||
| } | |||||
| } | |||||