From 9e9a11d4b09362aadac6d32be0ac83fdddc5e19e Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Thu, 6 Sep 2018 19:08:45 -0700 Subject: [PATCH 1/3] Fix swapped parameters in ArgumentException, ArgumentNullException cstrs (#1139) * Fix swapped parameters in ArgumentException and ArgumentNullException cstrs The constructors of ArgumentException and ArgumentNullException are inconsistent with each other, which results in their parameters being swapped here and there. * Use named parameters for ArgumentException constructors Cleans up some of the methods of EmbedBuilder to use simpler syntax as well --- src/Discord.Net.Core/Entities/Emotes/Emote.cs | 4 +- .../Entities/Messages/EmbedBuilder.cs | 34 ++++++++--------- .../Permissions/ChannelPermissions.cs | 2 +- .../Utils/ConcurrentHashSet.cs | 24 ++++++------ src/Discord.Net.Core/Utils/MentionUtils.cs | 6 +-- src/Discord.Net.Core/Utils/Preconditions.cs | 38 +++++-------------- src/Discord.Net.Core/Utils/TokenUtils.cs | 6 +-- src/Discord.Net.Rest/DiscordRestApiClient.cs | 6 +-- .../Entities/Guilds/GuildHelper.cs | 10 ++--- 9 files changed, 56 insertions(+), 74 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Emotes/Emote.cs b/src/Discord.Net.Core/Entities/Emotes/Emote.cs index e3a228c83..a71a73327 100644 --- a/src/Discord.Net.Core/Entities/Emotes/Emote.cs +++ b/src/Discord.Net.Core/Entities/Emotes/Emote.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; namespace Discord @@ -58,7 +58,7 @@ namespace Discord { if (TryParse(text, out Emote result)) return result; - throw new ArgumentException("Invalid emote format", nameof(text)); + throw new ArgumentException(message: "Invalid emote format", paramName: nameof(text)); } public static bool TryParse(string text, out Emote result) diff --git a/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs b/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs index 7e288ef6b..82e94e39f 100644 --- a/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs +++ b/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs @@ -29,7 +29,7 @@ namespace Discord get => _title; set { - if (value?.Length > MaxTitleLength) throw new ArgumentException($"Title length must be less than or equal to {MaxTitleLength}.", nameof(Title)); + if (value?.Length > MaxTitleLength) throw new ArgumentException(message: $"Title length must be less than or equal to {MaxTitleLength}.", paramName: nameof(Title)); _title = value; } } @@ -38,7 +38,7 @@ namespace Discord get => _description; set { - if (value?.Length > MaxDescriptionLength) throw new ArgumentException($"Description length must be less than or equal to {MaxDescriptionLength}.", nameof(Description)); + if (value?.Length > MaxDescriptionLength) throw new ArgumentException(message: $"Description length must be less than or equal to {MaxDescriptionLength}.", paramName: nameof(Description)); _description = value; } } @@ -48,7 +48,7 @@ namespace Discord get => _url; set { - if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(Url)); + if (!value.IsNullOrUri()) throw new ArgumentException(message: "Url must be a well-formed URI", paramName: nameof(Url)); _url = value; } } @@ -57,7 +57,7 @@ namespace Discord get => _thumbnail?.Url; set { - if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(ThumbnailUrl)); + if (!value.IsNullOrUri()) throw new ArgumentException(message: "Url must be a well-formed URI", paramName: nameof(ThumbnailUrl)); _thumbnail = new EmbedThumbnail(value, null, null, null); } } @@ -66,7 +66,7 @@ namespace Discord get => _image?.Url; set { - if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(ImageUrl)); + if (!value.IsNullOrUri()) throw new ArgumentException(message: "Url must be a well-formed URI", paramName: nameof(ImageUrl)); _image = new EmbedImage(value, null, null, null); } } @@ -75,8 +75,8 @@ namespace Discord get => _fields; set { - if (value == null) throw new ArgumentNullException("Cannot set an embed builder's fields collection to null", nameof(Fields)); - if (value.Count > MaxFieldCount) throw new ArgumentException($"Field count must be less than or equal to {MaxFieldCount}.", nameof(Fields)); + if (value == null) throw new ArgumentNullException(paramName: nameof(Fields), message: "Cannot set an embed builder's fields collection to null"); + if (value.Count > MaxFieldCount) throw new ArgumentException(message: $"Field count must be less than or equal to {MaxFieldCount}.", paramName: nameof(Fields)); _fields = value; } } @@ -200,7 +200,7 @@ namespace Discord { if (Fields.Count >= MaxFieldCount) { - throw new ArgumentException($"Field count must be less than or equal to {MaxFieldCount}.", nameof(field)); + throw new ArgumentException(message: $"Field count must be less than or equal to {MaxFieldCount}.", paramName: nameof(field)); } Fields.Add(field); @@ -239,8 +239,8 @@ namespace Discord get => _name; set { - if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Field name must not be null, empty or entirely whitespace.", nameof(Name)); - if (value.Length > MaxFieldNameLength) throw new ArgumentException($"Field name length must be less than or equal to {MaxFieldNameLength}.", nameof(Name)); + if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException(message: "Field name must not be null, empty or entirely whitespace.", paramName: nameof(Name)); + if (value.Length > MaxFieldNameLength) throw new ArgumentException(message: $"Field name length must be less than or equal to {MaxFieldNameLength}.", paramName: nameof(Name)); _name = value; } } @@ -251,8 +251,8 @@ namespace Discord set { var stringValue = value?.ToString(); - if (string.IsNullOrEmpty(stringValue)) throw new ArgumentException("Field value must not be null or empty.", nameof(Value)); - if (stringValue.Length > MaxFieldValueLength) throw new ArgumentException($"Field value length must be less than or equal to {MaxFieldValueLength}.", nameof(Value)); + if (string.IsNullOrEmpty(stringValue)) throw new ArgumentException(message: "Field value must not be null or empty.", paramName: nameof(Value)); + if (stringValue.Length > MaxFieldValueLength) throw new ArgumentException(message: $"Field value length must be less than or equal to {MaxFieldValueLength}.", paramName: nameof(Value)); _value = stringValue; } } @@ -290,7 +290,7 @@ namespace Discord get => _name; set { - if (value?.Length > MaxAuthorNameLength) throw new ArgumentException($"Author name length must be less than or equal to {MaxAuthorNameLength}.", nameof(Name)); + if (value?.Length > MaxAuthorNameLength) throw new ArgumentException(message: $"Author name length must be less than or equal to {MaxAuthorNameLength}.", paramName: nameof(Name)); _name = value; } } @@ -299,7 +299,7 @@ namespace Discord get => _url; set { - if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(Url)); + if (!value.IsNullOrUri()) throw new ArgumentException(message: "Url must be a well-formed URI", paramName: nameof(Url)); _url = value; } } @@ -308,7 +308,7 @@ namespace Discord get => _iconUrl; set { - if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(IconUrl)); + if (!value.IsNullOrUri()) throw new ArgumentException(message: "Url must be a well-formed URI", paramName: nameof(IconUrl)); _iconUrl = value; } } @@ -345,7 +345,7 @@ namespace Discord get => _text; set { - if (value?.Length > MaxFooterTextLength) throw new ArgumentException($"Footer text length must be less than or equal to {MaxFooterTextLength}.", nameof(Text)); + if (value?.Length > MaxFooterTextLength) throw new ArgumentException(message: $"Footer text length must be less than or equal to {MaxFooterTextLength}.", paramName: nameof(Text)); _text = value; } } @@ -354,7 +354,7 @@ namespace Discord get => _iconUrl; set { - if (!value.IsNullOrUri()) throw new ArgumentException("Url must be a well-formed URI", nameof(IconUrl)); + if (!value.IsNullOrUri()) throw new ArgumentException(message: "Url must be a well-formed URI", paramName: nameof(IconUrl)); _iconUrl = value; } } diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs index 61d588f8a..ea56734ff 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs @@ -29,7 +29,7 @@ namespace Discord case ICategoryChannel _: return Category; case IDMChannel _: return DM; case IGroupChannel _: return Group; - default: throw new ArgumentException("Unknown channel type", nameof(channel)); + default: throw new ArgumentException(message: "Unknown channel type", paramName: nameof(channel)); } } diff --git a/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs b/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs index 1fc11587e..e9edfb772 100644 --- a/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs +++ b/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -160,23 +160,23 @@ namespace Discord public ConcurrentHashSet(IEnumerable collection, IEqualityComparer comparer) : this(comparer) { - if (collection == null) throw new ArgumentNullException(nameof(collection)); + if (collection == null) throw new ArgumentNullException(paramName: nameof(collection)); InitializeFromCollection(collection); } public ConcurrentHashSet(int concurrencyLevel, IEnumerable collection, IEqualityComparer comparer) : this(concurrencyLevel, DefaultCapacity, false, comparer) { - if (collection == null) throw new ArgumentNullException(nameof(collection)); - if (comparer == null) throw new ArgumentNullException(nameof(comparer)); + if (collection == null) throw new ArgumentNullException(paramName: nameof(collection)); + if (comparer == null) throw new ArgumentNullException(paramName: nameof(comparer)); InitializeFromCollection(collection); } public ConcurrentHashSet(int concurrencyLevel, int capacity, IEqualityComparer comparer) : this(concurrencyLevel, capacity, false, comparer) { } internal ConcurrentHashSet(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer comparer) { - if (concurrencyLevel < 1) throw new ArgumentOutOfRangeException(nameof(concurrencyLevel)); - if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity)); - if (comparer == null) throw new ArgumentNullException(nameof(comparer)); + if (concurrencyLevel < 1) throw new ArgumentOutOfRangeException(paramName: nameof(concurrencyLevel)); + if (capacity < 0) throw new ArgumentOutOfRangeException(paramName: nameof(capacity)); + if (comparer == null) throw new ArgumentNullException(paramName: nameof(comparer)); if (capacity < concurrencyLevel) capacity = concurrencyLevel; @@ -197,7 +197,7 @@ namespace Discord { foreach (var value in collection) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(paramName: "key"); if (!TryAddInternal(value, _comparer.GetHashCode(value), false)) throw new ArgumentException(); @@ -209,7 +209,7 @@ namespace Discord public bool ContainsKey(T value) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(paramName: "key"); return ContainsKeyInternal(value, _comparer.GetHashCode(value)); } private bool ContainsKeyInternal(T value, int hashcode) @@ -232,7 +232,7 @@ namespace Discord public bool TryAdd(T value) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(paramName: "key"); return TryAddInternal(value, _comparer.GetHashCode(value), true); } private bool TryAddInternal(T value, int hashcode, bool acquireLock) @@ -281,7 +281,7 @@ namespace Discord public bool TryRemove(T value) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(paramName: "key"); return TryRemoveInternal(value); } private bool TryRemoveInternal(T value) @@ -467,4 +467,4 @@ namespace Discord Monitor.Exit(_tables._locks[i]); } } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Core/Utils/MentionUtils.cs b/src/Discord.Net.Core/Utils/MentionUtils.cs index f2afe497a..a081b5a5a 100644 --- a/src/Discord.Net.Core/Utils/MentionUtils.cs +++ b/src/Discord.Net.Core/Utils/MentionUtils.cs @@ -21,7 +21,7 @@ namespace Discord { if (TryParseUser(text, out ulong id)) return id; - throw new ArgumentException("Invalid mention format", nameof(text)); + throw new ArgumentException(message: "Invalid mention format", paramName: nameof(text)); } /// Tries to parse a provided user mention string. public static bool TryParseUser(string text, out ulong userId) @@ -45,7 +45,7 @@ namespace Discord { if (TryParseChannel(text, out ulong id)) return id; - throw new ArgumentException("Invalid mention format", nameof(text)); + throw new ArgumentException(message: "Invalid mention format", paramName: nameof(text)); } /// Tries to parse a provided channel mention string. public static bool TryParseChannel(string text, out ulong channelId) @@ -66,7 +66,7 @@ namespace Discord { if (TryParseRole(text, out ulong id)) return id; - throw new ArgumentException("Invalid mention format", nameof(text)); + throw new ArgumentException(message: "Invalid mention format", paramName: nameof(text)); } /// Tries to parse a provided role mention string. public static bool TryParseRole(string text, out ulong roleId) diff --git a/src/Discord.Net.Core/Utils/Preconditions.cs b/src/Discord.Net.Core/Utils/Preconditions.cs index 1a297a6a1..6cbf4a173 100644 --- a/src/Discord.Net.Core/Utils/Preconditions.cs +++ b/src/Discord.Net.Core/Utils/Preconditions.cs @@ -10,8 +10,8 @@ namespace Discord private static ArgumentNullException CreateNotNullException(string name, string msg) { - if (msg == null) return new ArgumentNullException(name); - else return new ArgumentNullException(name, msg); + if (msg == null) return new ArgumentNullException(paramName: name); + else return new ArgumentNullException(paramName: name, message: msg); } //Strings @@ -45,10 +45,7 @@ namespace Discord } private static ArgumentException CreateNotEmptyException(string name, string msg) - { - if (msg == null) return new ArgumentException("Argument cannot be blank", name); - else return new ArgumentException(name, msg); - } + => new ArgumentException(message: msg ?? "Argument cannot be blank.", paramName: name); //Numerics public static void NotEqual(sbyte obj, sbyte value, string name, string msg = null) { if (obj == value) throw CreateNotEqualException(name, msg, value); } @@ -85,11 +82,8 @@ namespace Discord public static void NotEqual(Optional obj, ulong value, string name, string msg = null) { if (obj.IsSpecified && obj.Value == value) throw CreateNotEqualException(name, msg, value); } private static ArgumentException CreateNotEqualException(string name, string msg, T value) - { - if (msg == null) return new ArgumentException($"Value may not be equal to {value}", name); - else return new ArgumentException(msg, name); - } - + => new ArgumentException(message: msg ?? $"Value may not be equal to {value}", paramName: name); + public static void AtLeast(sbyte obj, sbyte value, string name, string msg = null) { if (obj < value) throw CreateAtLeastException(name, msg, value); } public static void AtLeast(byte obj, byte value, string name, string msg = null) { if (obj < value) throw CreateAtLeastException(name, msg, value); } public static void AtLeast(short obj, short value, string name, string msg = null) { if (obj < value) throw CreateAtLeastException(name, msg, value); } @@ -108,10 +102,7 @@ namespace Discord public static void AtLeast(Optional obj, ulong value, string name, string msg = null) { if (obj.IsSpecified && obj.Value < value) throw CreateAtLeastException(name, msg, value); } private static ArgumentException CreateAtLeastException(string name, string msg, T value) - { - if (msg == null) return new ArgumentException($"Value must be at least {value}", name); - else return new ArgumentException(msg, name); - } + => new ArgumentException(message: msg ?? $"Value must be at least {value}", paramName: name); public static void GreaterThan(sbyte obj, sbyte value, string name, string msg = null) { if (obj <= value) throw CreateGreaterThanException(name, msg, value); } public static void GreaterThan(byte obj, byte value, string name, string msg = null) { if (obj <= value) throw CreateGreaterThanException(name, msg, value); } @@ -131,10 +122,7 @@ namespace Discord public static void GreaterThan(Optional obj, ulong value, string name, string msg = null) { if (obj.IsSpecified && obj.Value <= value) throw CreateGreaterThanException(name, msg, value); } private static ArgumentException CreateGreaterThanException(string name, string msg, T value) - { - if (msg == null) return new ArgumentException($"Value must be greater than {value}", name); - else return new ArgumentException(msg, name); - } + => new ArgumentException(message: msg ?? $"Value must be greater than {value}", paramName: name); public static void AtMost(sbyte obj, sbyte value, string name, string msg = null) { if (obj > value) throw CreateAtMostException(name, msg, value); } public static void AtMost(byte obj, byte value, string name, string msg = null) { if (obj > value) throw CreateAtMostException(name, msg, value); } @@ -154,10 +142,7 @@ namespace Discord public static void AtMost(Optional obj, ulong value, string name, string msg = null) { if (obj.IsSpecified && obj.Value > value) throw CreateAtMostException(name, msg, value); } private static ArgumentException CreateAtMostException(string name, string msg, T value) - { - if (msg == null) return new ArgumentException($"Value must be at most {value}", name); - else return new ArgumentException(msg, name); - } + => new ArgumentException(message: msg ?? $"Value must be at most {value}", paramName: name); public static void LessThan(sbyte obj, sbyte value, string name, string msg = null) { if (obj >= value) throw CreateLessThanException(name, msg, value); } public static void LessThan(byte obj, byte value, string name, string msg = null) { if (obj >= value) throw CreateLessThanException(name, msg, value); } @@ -177,10 +162,7 @@ namespace Discord public static void LessThan(Optional obj, ulong value, string name, string msg = null) { if (obj.IsSpecified && obj.Value >= value) throw CreateLessThanException(name, msg, value); } private static ArgumentException CreateLessThanException(string name, string msg, T value) - { - if (msg == null) return new ArgumentException($"Value must be less than {value}", name); - else return new ArgumentException(msg, name); - } + => new ArgumentException(message: msg ?? $"Value must be less than {value}", paramName: name); // Bulk Delete public static void YoungerThanTwoWeeks(ulong[] collection, string name) @@ -198,7 +180,7 @@ namespace Discord for (var i = 0; i < roles.Length; i++) { if (roles[i] == guildId) - throw new ArgumentException("The everyone role cannot be assigned to a user", name); + throw new ArgumentException(message: "The everyone role cannot be assigned to a user", paramName: name); } } } diff --git a/src/Discord.Net.Core/Utils/TokenUtils.cs b/src/Discord.Net.Core/Utils/TokenUtils.cs index 2cc0f1041..6decdc52f 100644 --- a/src/Discord.Net.Core/Utils/TokenUtils.cs +++ b/src/Discord.Net.Core/Utils/TokenUtils.cs @@ -19,7 +19,7 @@ namespace Discord { // A Null or WhiteSpace token of any type is invalid. if (string.IsNullOrWhiteSpace(token)) - throw new ArgumentNullException("A token cannot be null, empty, or contain only whitespace.", nameof(token)); + throw new ArgumentNullException(paramName: nameof(token), message: "A token cannot be null, empty, or contain only whitespace."); switch (tokenType) { @@ -34,11 +34,11 @@ namespace Discord // this value was determined by referencing examples in the discord documentation, and by comparing with // pre-existing tokens if (token.Length < 59) - throw new ArgumentException("A Bot token must be at least 59 characters in length.", nameof(token)); + throw new ArgumentException(message: "A Bot token must be at least 59 characters in length.", paramName: nameof(token)); break; default: // All unrecognized TokenTypes (including User tokens) are considered to be invalid. - throw new ArgumentException("Unrecognized TokenType.", nameof(token)); + throw new ArgumentException(message: "Unrecognized TokenType.", paramName: nameof(token)); } } diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index f8e3e6f50..02529310f 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -78,7 +78,7 @@ namespace Discord.API case TokenType.Bearer: return $"Bearer {token}"; default: - throw new ArgumentException("Unknown OAuth token type", nameof(tokenType)); + throw new ArgumentException(message: "Unknown OAuth token type", paramName: nameof(tokenType)); } } internal virtual void Dispose(bool disposing) @@ -473,7 +473,7 @@ namespace Discord.API Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); if (args.Content?.Length > DiscordConfig.MaxMessageSize) - throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); + throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content)); options = RequestOptions.CreateOrClone(options); var ids = new BucketIds(channelId: channelId); @@ -490,7 +490,7 @@ namespace Discord.API Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); if (args.Content?.Length > DiscordConfig.MaxMessageSize) - throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); + throw new ArgumentException(message: $"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", paramName: nameof(args.Content)); options = RequestOptions.CreateOrClone(options); return await SendJsonAsync("POST", () => $"webhooks/{webhookId}/{AuthToken}?wait=true", args, new BucketIds(), clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false); diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 4bd0e9972..3b2935149 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -147,7 +147,7 @@ namespace Discord.Rest public static async Task CreateTextChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options, Action func = null) { - if (name == null) throw new ArgumentNullException(nameof(name)); + if (name == null) throw new ArgumentNullException(paramName: nameof(name)); var props = new TextChannelProperties(); func?.Invoke(props); @@ -164,7 +164,7 @@ namespace Discord.Rest public static async Task CreateVoiceChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options, Action func = null) { - if (name == null) throw new ArgumentNullException(nameof(name)); + if (name == null) throw new ArgumentNullException(paramName: nameof(name)); var props = new VoiceChannelProperties(); func?.Invoke(props); @@ -181,7 +181,7 @@ namespace Discord.Rest public static async Task CreateCategoryChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options) { - if (name == null) throw new ArgumentNullException(nameof(name)); + if (name == null) throw new ArgumentNullException(paramName: nameof(name)); var args = new CreateGuildChannelParams(name, ChannelType.Category); var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); @@ -221,7 +221,7 @@ namespace Discord.Rest public static async Task CreateRoleAsync(IGuild guild, BaseDiscordClient client, string name, GuildPermissions? permissions, Color? color, bool isHoisted, RequestOptions options) { - if (name == null) throw new ArgumentNullException(nameof(name)); + if (name == null) throw new ArgumentNullException(paramName: nameof(name)); var model = await client.ApiClient.CreateGuildRoleAsync(guild.Id, options).ConfigureAwait(false); var role = RestRole.Create(client, guild, model); @@ -356,7 +356,7 @@ namespace Discord.Rest public static async Task ModifyEmoteAsync(IGuild guild, BaseDiscordClient client, ulong id, Action func, RequestOptions options) { - if (func == null) throw new ArgumentNullException(nameof(func)); + if (func == null) throw new ArgumentNullException(paramName: nameof(func)); var props = new EmoteProperties(); func(props); From 97d17cfdda22a04173b63247c646acc7cd1122a7 Mon Sep 17 00:00:00 2001 From: Christopher F Date: Tue, 11 Sep 2018 18:21:22 -0400 Subject: [PATCH 2/3] api: add slow mode This adds the following property to ITextChannel - SlowMode (int) The SlowMode field defines the time in seconds users must wait between sending messages; if zero, slow-mode is disabled. Bots are not affected by slow-mode, and as such, no changes need to be made to the REST client's internal ratelimiting. This is strictly a read/write cosmetic property for bots. --- .../Entities/Channels/ITextChannel.cs | 3 +++ .../Entities/Channels/TextChannelProperties.cs | 14 +++++++++++++- src/Discord.Net.Rest/API/Common/Channel.cs | 4 +++- .../API/Rest/ModifyTextChannelParams.cs | 4 +++- src/Discord.Net.Rest/DiscordRestApiClient.cs | 2 ++ .../Entities/Channels/ChannelHelper.cs | 3 ++- .../Entities/Channels/RestTextChannel.cs | 2 ++ .../Entities/Channels/SocketTextChannel.cs | 2 ++ 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs b/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs index 2aa070b03..e9350601d 100644 --- a/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs @@ -13,6 +13,9 @@ namespace Discord /// Gets the current topic for this text channel. string Topic { get; } + /// Gets the current slow-mode delay for this channel. 0 if disabled. + int SlowMode { get; } + /// Bulk deletes multiple messages. Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null); /// Bulk deletes multiple messages. diff --git a/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs b/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs index b7b568133..e3c0557dd 100644 --- a/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs +++ b/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs @@ -1,4 +1,6 @@ -namespace Discord +using System; + +namespace Discord { /// public class TextChannelProperties : GuildChannelProperties @@ -11,5 +13,15 @@ /// Should this channel be flagged as NSFW? /// public Optional IsNsfw { get; set; } + /// + /// What the slow-mode ratelimit for this channel should be set to; 0 will disable slow-mode. + /// + /// + /// This value must fall within [0, 120] + /// + /// Users with will be exempt from slow-mode. + /// + /// Throws ArgummentOutOfRange if the value does not fall within [0, 120] + public Optional SlowMode { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Common/Channel.cs b/src/Discord.Net.Rest/API/Common/Channel.cs index 97c35a57b..57a5ce9ab 100644 --- a/src/Discord.Net.Rest/API/Common/Channel.cs +++ b/src/Discord.Net.Rest/API/Common/Channel.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591 using Newtonsoft.Json; using System; @@ -33,6 +33,8 @@ namespace Discord.API public Optional LastPinTimestamp { get; set; } [JsonProperty("nsfw")] public Optional Nsfw { get; set; } + [JsonProperty("rate_limit_per_user")] + public Optional SlowMode { get; set; } //VoiceChannel [JsonProperty("bitrate")] diff --git a/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs index 9cabc67c1..7cb1405c9 100644 --- a/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs +++ b/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591 using Newtonsoft.Json; namespace Discord.API.Rest @@ -10,5 +10,7 @@ namespace Discord.API.Rest public Optional Topic { get; set; } [JsonProperty("nsfw")] public Optional IsNsfw { get; set; } + [JsonProperty("rate_limit_per_user")] + public Optional SlowMode { get; set; } } } diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 02529310f..f7e86a8f3 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -356,6 +356,8 @@ namespace Discord.API Preconditions.NotNull(args, nameof(args)); Preconditions.AtLeast(args.Position, 0, nameof(args.Position)); Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name)); + Preconditions.AtLeast(args.SlowMode, 0, nameof(args.SlowMode)); + Preconditions.AtMost(args.SlowMode, 120, nameof(args.SlowMode)); options = RequestOptions.CreateOrClone(options); var ids = new BucketIds(channelId: channelId); diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index 50cb352a7..47f82f612 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -45,7 +45,8 @@ namespace Discord.Rest Position = args.Position, CategoryId = args.CategoryId, Topic = args.Topic, - IsNsfw = args.IsNsfw + IsNsfw = args.IsNsfw, + SlowMode = args.SlowMode, }; return await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false); } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs index 7f57c96ff..8fe17ba2f 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs @@ -12,6 +12,7 @@ namespace Discord.Rest public class RestTextChannel : RestGuildChannel, IRestMessageChannel, ITextChannel { public string Topic { get; private set; } + public int SlowMode { get; private set; } public ulong? CategoryId { get; private set; } public string Mention => MentionUtils.MentionChannel(Id); @@ -34,6 +35,7 @@ namespace Discord.Rest base.Update(model); CategoryId = model.CategoryId; Topic = model.Topic.Value; + SlowMode = model.SlowMode.Value; _nsfw = model.Nsfw.GetValueOrDefault(); } diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index e41c2ba94..d6982bf6a 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -16,6 +16,7 @@ namespace Discord.WebSocket private readonly MessageCache _messages; public string Topic { get; private set; } + public int SlowMode { get; private set; } public ulong? CategoryId { get; private set; } public ICategoryChannel Category => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; @@ -47,6 +48,7 @@ namespace Discord.WebSocket base.Update(state, model); CategoryId = model.CategoryId; Topic = model.Topic.Value; + SlowMode = model.SlowMode.GetValueOrDefault(); // some guilds haven't been patched to include this yet? _nsfw = model.Nsfw.GetValueOrDefault(); } From 232f525b59e801332ec9dca755366944c79afa1d Mon Sep 17 00:00:00 2001 From: Christopher F Date: Tue, 11 Sep 2018 18:28:31 -0400 Subject: [PATCH 3/3] lint: refactor SlowMode -> SlowModeInterval this was the name change i always wanted --- src/Discord.Net.Core/Entities/Channels/ITextChannel.cs | 2 +- .../Entities/Channels/TextChannelProperties.cs | 2 +- src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs | 2 +- src/Discord.Net.Rest/DiscordRestApiClient.cs | 4 ++-- src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs | 2 +- src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs | 4 ++-- src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs | 2 +- .../Entities/Channels/SocketTextChannel.cs | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs b/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs index e9350601d..89e10e65e 100644 --- a/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs @@ -14,7 +14,7 @@ namespace Discord string Topic { get; } /// Gets the current slow-mode delay for this channel. 0 if disabled. - int SlowMode { get; } + int SlowModeInterval { get; } /// Bulk deletes multiple messages. Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null); diff --git a/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs b/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs index e3c0557dd..87adccb85 100644 --- a/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs +++ b/src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs @@ -22,6 +22,6 @@ namespace Discord /// Users with will be exempt from slow-mode. /// /// Throws ArgummentOutOfRange if the value does not fall within [0, 120] - public Optional SlowMode { get; set; } + public Optional SlowModeInterval { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs index 7cb1405c9..94f149fc1 100644 --- a/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs +++ b/src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs @@ -11,6 +11,6 @@ namespace Discord.API.Rest [JsonProperty("nsfw")] public Optional IsNsfw { get; set; } [JsonProperty("rate_limit_per_user")] - public Optional SlowMode { get; set; } + public Optional SlowModeInterval { get; set; } } } diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index f7e86a8f3..35fa0e989 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -356,8 +356,8 @@ namespace Discord.API Preconditions.NotNull(args, nameof(args)); Preconditions.AtLeast(args.Position, 0, nameof(args.Position)); Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name)); - Preconditions.AtLeast(args.SlowMode, 0, nameof(args.SlowMode)); - Preconditions.AtMost(args.SlowMode, 120, nameof(args.SlowMode)); + Preconditions.AtLeast(args.SlowModeInterval, 0, nameof(args.SlowModeInterval)); + Preconditions.AtMost(args.SlowModeInterval, 120, nameof(args.SlowModeInterval)); options = RequestOptions.CreateOrClone(options); var ids = new BucketIds(channelId: channelId); diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index 47f82f612..74ce7870f 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -46,7 +46,7 @@ namespace Discord.Rest CategoryId = args.CategoryId, Topic = args.Topic, IsNsfw = args.IsNsfw, - SlowMode = args.SlowMode, + SlowModeInterval = args.SlowModeInterval, }; return await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false); } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs index 8fe17ba2f..12437c969 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs @@ -12,7 +12,7 @@ namespace Discord.Rest public class RestTextChannel : RestGuildChannel, IRestMessageChannel, ITextChannel { public string Topic { get; private set; } - public int SlowMode { get; private set; } + public int SlowModeInterval { get; private set; } public ulong? CategoryId { get; private set; } public string Mention => MentionUtils.MentionChannel(Id); @@ -35,7 +35,7 @@ namespace Discord.Rest base.Update(model); CategoryId = model.CategoryId; Topic = model.Topic.Value; - SlowMode = model.SlowMode.Value; + SlowModeInterval = model.SlowMode.Value; _nsfw = model.Nsfw.GetValueOrDefault(); } diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 3b2935149..bde36922a 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -156,7 +156,7 @@ namespace Discord.Rest { CategoryId = props.CategoryId, Topic = props.Topic, - IsNsfw = props.IsNsfw + IsNsfw = props.IsNsfw, }; var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); return RestTextChannel.Create(client, guild, model); diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index d6982bf6a..2e9cd90be 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -16,7 +16,7 @@ namespace Discord.WebSocket private readonly MessageCache _messages; public string Topic { get; private set; } - public int SlowMode { get; private set; } + public int SlowModeInterval { get; private set; } public ulong? CategoryId { get; private set; } public ICategoryChannel Category => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; @@ -48,7 +48,7 @@ namespace Discord.WebSocket base.Update(state, model); CategoryId = model.CategoryId; Topic = model.Topic.Value; - SlowMode = model.SlowMode.GetValueOrDefault(); // some guilds haven't been patched to include this yet? + SlowModeInterval = model.SlowMode.GetValueOrDefault(); // some guilds haven't been patched to include this yet? _nsfw = model.Nsfw.GetValueOrDefault(); }