From b00da3d73cf7f18f6957e92a97d9b3bcef763c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radka=20Janekov=C3=A1?= Date: Sun, 8 Sep 2019 18:23:03 +0200 Subject: [PATCH 1/4] feature: add the "Stream" permission. (#1357) --- .../Entities/Permissions/ChannelPermission.cs | 4 ++++ .../Entities/Permissions/ChannelPermissions.cs | 11 +++++++++-- .../Entities/Permissions/GuildPermission.cs | 4 ++++ .../Entities/Permissions/GuildPermissions.cs | 13 ++++++++++--- test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs | 2 ++ test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs | 1 + 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs index e3cfc0e19..e1f78373e 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs @@ -90,6 +90,10 @@ namespace Discord /// UseVAD = 0x02_00_00_00, PrioritySpeaker = 0x00_00_01_00, + /// + /// Allows video streaming in a voice channel. + /// + Stream = 0x00_00_02_00, // More General /// diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs index 7bef3251a..99885b070 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs @@ -13,7 +13,7 @@ namespace Discord /// Gets a that grants all permissions for text channels. public static readonly ChannelPermissions Text = new ChannelPermissions(0b01100_0000000_1111111110001_010001); /// Gets a that grants all permissions for voice channels. - public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000010100_010001); + public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000011100_010001); /// Gets a that grants all permissions for category channels. public static readonly ChannelPermissions Category = new ChannelPermissions(0b01100_1111110_1111111110001_010001); /// Gets a that grants all permissions for direct message channels. @@ -82,6 +82,8 @@ namespace Discord public bool UseVAD => Permissions.GetValue(RawValue, ChannelPermission.UseVAD); /// If true, a user may use priority speaker in a voice channel. public bool PrioritySpeaker => Permissions.GetValue(RawValue, ChannelPermission.PrioritySpeaker); + /// If true, a user may stream video in a voice channel. + public bool Stream => Permissions.GetValue(RawValue, ChannelPermission.Stream); /// If true, a user may adjust role permissions. This also implictly grants all other permissions. public bool ManageRoles => Permissions.GetValue(RawValue, ChannelPermission.ManageRoles); @@ -111,6 +113,7 @@ namespace Discord bool? moveMembers = null, bool? useVoiceActivation = null, bool? prioritySpeaker = null, + bool? stream = null, bool? manageRoles = null, bool? manageWebhooks = null) { @@ -135,6 +138,7 @@ namespace Discord Permissions.SetValue(ref value, moveMembers, ChannelPermission.MoveMembers); Permissions.SetValue(ref value, useVoiceActivation, ChannelPermission.UseVAD); Permissions.SetValue(ref value, prioritySpeaker, ChannelPermission.PrioritySpeaker); + Permissions.SetValue(ref value, stream, ChannelPermission.Stream); Permissions.SetValue(ref value, manageRoles, ChannelPermission.ManageRoles); Permissions.SetValue(ref value, manageWebhooks, ChannelPermission.ManageWebhooks); @@ -162,11 +166,12 @@ namespace Discord bool moveMembers = false, bool useVoiceActivation = false, bool prioritySpeaker = false, + bool stream = false, bool manageRoles = false, bool manageWebhooks = false) : this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, - speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, manageRoles, manageWebhooks) + speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, stream, manageRoles, manageWebhooks) { } /// Creates a new from this one, changing the provided non-null permissions. @@ -190,6 +195,7 @@ namespace Discord bool? moveMembers = null, bool? useVoiceActivation = null, bool? prioritySpeaker = null, + bool? stream = null, bool? manageRoles = null, bool? manageWebhooks = null) => new ChannelPermissions(RawValue, @@ -212,6 +218,7 @@ namespace Discord moveMembers, useVoiceActivation, prioritySpeaker, + stream, manageRoles, manageWebhooks); diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs index c010d90b1..3c8a5e810 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs @@ -126,6 +126,10 @@ namespace Discord /// UseVAD = 0x02_00_00_00, PrioritySpeaker = 0x00_00_01_00, + /// + /// Allows video streaming in a voice channel. + /// + Stream = 0x00_00_02_00, // General 2 /// diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs index 2d2a9e56a..a5adad47c 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs @@ -12,7 +12,7 @@ namespace Discord /// Gets a that grants all guild permissions for webhook users. public static readonly GuildPermissions Webhook = new GuildPermissions(0b00000_0000000_0001101100000_000000); /// Gets a that grants all guild permissions. - public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_1111111110111_111111); + public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_1111111111111_111111); /// Gets a packed value representing all the permissions in this . public ulong RawValue { get; } @@ -70,7 +70,9 @@ namespace Discord /// If true, a user may use voice-activity-detection rather than push-to-talk. public bool UseVAD => Permissions.GetValue(RawValue, GuildPermission.UseVAD); /// If True, a user may use priority speaker in a voice channel. - public bool PrioritySpeaker => Permissions.GetValue(RawValue, ChannelPermission.PrioritySpeaker); + public bool PrioritySpeaker => Permissions.GetValue(RawValue, GuildPermission.PrioritySpeaker); + /// If True, a user may stream video in a voice channel. + public bool Stream => Permissions.GetValue(RawValue, GuildPermission.Stream); /// If true, a user may change their own nickname. public bool ChangeNickname => Permissions.GetValue(RawValue, GuildPermission.ChangeNickname); @@ -111,6 +113,7 @@ namespace Discord bool? moveMembers = null, bool? useVoiceActivation = null, bool? prioritySpeaker = null, + bool? stream = null, bool? changeNickname = null, bool? manageNicknames = null, bool? manageRoles = null, @@ -143,6 +146,7 @@ namespace Discord Permissions.SetValue(ref value, moveMembers, GuildPermission.MoveMembers); Permissions.SetValue(ref value, useVoiceActivation, GuildPermission.UseVAD); Permissions.SetValue(ref value, prioritySpeaker, GuildPermission.PrioritySpeaker); + Permissions.SetValue(ref value, stream, GuildPermission.Stream); Permissions.SetValue(ref value, changeNickname, GuildPermission.ChangeNickname); Permissions.SetValue(ref value, manageNicknames, GuildPermission.ManageNicknames); Permissions.SetValue(ref value, manageRoles, GuildPermission.ManageRoles); @@ -178,6 +182,7 @@ namespace Discord bool moveMembers = false, bool useVoiceActivation = false, bool prioritySpeaker = false, + bool stream = false, bool changeNickname = false, bool manageNicknames = false, bool manageRoles = false, @@ -209,6 +214,7 @@ namespace Discord moveMembers: moveMembers, useVoiceActivation: useVoiceActivation, prioritySpeaker: prioritySpeaker, + stream: stream, changeNickname: changeNickname, manageNicknames: manageNicknames, manageWebhooks: manageWebhooks, @@ -241,6 +247,7 @@ namespace Discord bool? moveMembers = null, bool? useVoiceActivation = null, bool? prioritySpeaker = null, + bool? stream = null, bool? changeNickname = null, bool? manageNicknames = null, bool? manageRoles = null, @@ -249,7 +256,7 @@ namespace Discord => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, viewAuditLog, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, - useVoiceActivation, prioritySpeaker, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis); + useVoiceActivation, prioritySpeaker, stream, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis); /// /// Returns a value that indicates if a specific is enabled diff --git a/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs b/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs index 2625c1e9b..a3566590a 100644 --- a/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs +++ b/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs @@ -82,6 +82,7 @@ namespace Discord AssertFlag(() => new ChannelPermissions(moveMembers: true), ChannelPermission.MoveMembers); AssertFlag(() => new ChannelPermissions(useVoiceActivation: true), ChannelPermission.UseVAD); AssertFlag(() => new ChannelPermissions(prioritySpeaker: true), ChannelPermission.PrioritySpeaker); + AssertFlag(() => new ChannelPermissions(stream: true), ChannelPermission.Stream); AssertFlag(() => new ChannelPermissions(manageRoles: true), ChannelPermission.ManageRoles); AssertFlag(() => new ChannelPermissions(manageWebhooks: true), ChannelPermission.ManageWebhooks); } @@ -147,6 +148,7 @@ namespace Discord AssertUtil(ChannelPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable)); AssertUtil(ChannelPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable)); AssertUtil(ChannelPermission.PrioritySpeaker, x => x.PrioritySpeaker, (p, enable) => p.Modify(prioritySpeaker: enable)); + AssertUtil(ChannelPermission.Stream, x => x.Stream, (p, enable) => p.Modify(stream: enable)); } /// diff --git a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs index 8213a8974..f0611fa24 100644 --- a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs +++ b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs @@ -85,6 +85,7 @@ namespace Discord AssertFlag(() => new GuildPermissions(moveMembers: true), GuildPermission.MoveMembers); AssertFlag(() => new GuildPermissions(useVoiceActivation: true), GuildPermission.UseVAD); AssertFlag(() => new GuildPermissions(prioritySpeaker: true), GuildPermission.PrioritySpeaker); + AssertFlag(() => new GuildPermissions(stream: true), GuildPermission.Stream); AssertFlag(() => new GuildPermissions(changeNickname: true), GuildPermission.ChangeNickname); AssertFlag(() => new GuildPermissions(manageNicknames: true), GuildPermission.ManageNicknames); AssertFlag(() => new GuildPermissions(manageRoles: true), GuildPermission.ManageRoles); From 3755a027b3ccfb404977ba6020ce9e394f3f56f4 Mon Sep 17 00:00:00 2001 From: Adam Gauthier Date: Sun, 8 Sep 2019 18:06:19 -0400 Subject: [PATCH 2/4] feature: Provide ParameterInfo with error ParseResult (#1355) Currently, when handling parsing errors, there is no way to know what parameter caused the error. This change makes the CommandParser create the parsing error with the current parameter info when ParseAsync() fails. It is then available through the ErrorParameter of the ParseResult. --- src/Discord.Net.Commands/CommandParser.cs | 12 +++++----- src/Discord.Net.Commands/Results/ParseResult.cs | 30 ++++++++++++++++++------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/Discord.Net.Commands/CommandParser.cs b/src/Discord.Net.Commands/CommandParser.cs index c77b56042..88698cda5 100644 --- a/src/Discord.Net.Commands/CommandParser.cs +++ b/src/Discord.Net.Commands/CommandParser.cs @@ -103,7 +103,7 @@ namespace Discord.Commands argBuilder.Append(c); continue; } - + if (IsOpenQuote(aliasMap, c)) { curPart = ParserPart.QuotedParameter; @@ -136,7 +136,7 @@ namespace Discord.Commands else argBuilder.Append(c); } - + if (argString != null) { if (curParam == null) @@ -149,7 +149,7 @@ namespace Discord.Commands var typeReaderResult = await curParam.ParseAsync(context, argString, services).ConfigureAwait(false); if (!typeReaderResult.IsSuccess && typeReaderResult.Error != CommandError.MultipleMatches) - return ParseResult.FromError(typeReaderResult); + return ParseResult.FromError(typeReaderResult, curParam); if (curParam.IsMultiple) { @@ -172,7 +172,7 @@ namespace Discord.Commands { var typeReaderResult = await curParam.ParseAsync(context, argBuilder.ToString(), services).ConfigureAwait(false); if (!typeReaderResult.IsSuccess) - return ParseResult.FromError(typeReaderResult); + return ParseResult.FromError(typeReaderResult, curParam); argList.Add(typeReaderResult); } @@ -180,7 +180,7 @@ namespace Discord.Commands return ParseResult.FromError(CommandError.ParseFailed, "Input text may not end on an incomplete escape."); if (curPart == ParserPart.QuotedParameter) return ParseResult.FromError(CommandError.ParseFailed, "A quoted parameter is incomplete."); - + //Add missing optionals for (int i = argList.Count; i < command.Parameters.Count; i++) { @@ -191,7 +191,7 @@ namespace Discord.Commands return ParseResult.FromError(CommandError.BadArgCount, "The input text has too few parameters."); argList.Add(TypeReaderResult.FromSuccess(param.DefaultValue)); } - + return ParseResult.FromSuccess(argList.ToImmutable(), paramList.ToImmutable()); } } diff --git a/src/Discord.Net.Commands/Results/ParseResult.cs b/src/Discord.Net.Commands/Results/ParseResult.cs index 8e10dc66c..43351b6bf 100644 --- a/src/Discord.Net.Commands/Results/ParseResult.cs +++ b/src/Discord.Net.Commands/Results/ParseResult.cs @@ -18,30 +18,40 @@ namespace Discord.Commands /// public string ErrorReason { get; } + /// + /// Provides information about the parameter that caused the parsing error. + /// + /// + /// A indicating the parameter info of the error that may have occurred during parsing; + /// null if the parsing was successful or the parsing error is not specific to a single parameter. + /// + public ParameterInfo ErrorParameter { get; } + /// public bool IsSuccess => !Error.HasValue; - private ParseResult(IReadOnlyList argValues, IReadOnlyList paramValues, CommandError? error, string errorReason) + private ParseResult(IReadOnlyList argValues, IReadOnlyList paramValues, CommandError? error, string errorReason, ParameterInfo errorParamInfo) { ArgValues = argValues; ParamValues = paramValues; Error = error; ErrorReason = errorReason; + ErrorParameter = errorParamInfo; } - + public static ParseResult FromSuccess(IReadOnlyList argValues, IReadOnlyList paramValues) { for (int i = 0; i < argValues.Count; i++) { if (argValues[i].Values.Count > 1) - return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found."); + return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found.", null); } for (int i = 0; i < paramValues.Count; i++) { if (paramValues[i].Values.Count > 1) - return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found."); + return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found.", null); } - return new ParseResult(argValues, paramValues, null, null); + return new ParseResult(argValues, paramValues, null, null, null); } public static ParseResult FromSuccess(IReadOnlyList argValues, IReadOnlyList paramValues) { @@ -55,15 +65,19 @@ namespace Discord.Commands for (int i = 0; i < paramValues.Count; i++) paramList[i] = TypeReaderResult.FromSuccess(paramValues[i]); } - return new ParseResult(argList, paramList, null, null); + return new ParseResult(argList, paramList, null, null, null); } public static ParseResult FromError(CommandError error, string reason) - => new ParseResult(null, null, error, reason); + => new ParseResult(null, null, error, reason, null); + public static ParseResult FromError(CommandError error, string reason, ParameterInfo parameterInfo) + => new ParseResult(null, null, error, reason, parameterInfo); public static ParseResult FromError(Exception ex) => FromError(CommandError.Exception, ex.Message); public static ParseResult FromError(IResult result) - => new ParseResult(null, null, result.Error, result.ErrorReason); + => new ParseResult(null, null, result.Error, result.ErrorReason, null); + public static ParseResult FromError(IResult result, ParameterInfo parameterInfo) + => new ParseResult(null, null, result.Error, result.ErrorReason, parameterInfo); public override string ToString() => IsSuccess ? "Success" : $"{Error}: {ErrorReason}"; private string DebuggerDisplay => IsSuccess ? $"Success ({ArgValues.Count}{(ParamValues.Count > 0 ? $" +{ParamValues.Count} Values" : "")})" : $"{Error}: {ErrorReason}"; From 606dac3e1a36d528f99bf64fb5685202eaef0b49 Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Sat, 14 Sep 2019 09:38:26 -0700 Subject: [PATCH 3/4] fix: Use double precision for X-Reset-After, set CultureInfo when parsing numeric types (#1375) * Parse double for X-Reset-After instead of float, needs more precision Float did not contain enough precision to store the millisecond unix time value, which resulted in the second and millisecond values being slightly off. This can be easily tested using: ```cs > DateTimeOffset.FromUnixTimeMilliseconds((long)(1470173022.123f * 1000)).Millisecond 160 // wrong > DateTimeOffset.FromUnixTimeMilliseconds((long)(1470173022.123 * 1000)).Millisecond 123 // correct ``` * Parse RateLimit-Reset using an IFormatProvider * State NumberStyle and use CultureInfo.InvariantCulture for any parsing This updates most occurances in the code where a Parse or TryParse method was used to explicitly state the NumberStyle, and to use CultureInfo.InvariantCulture. CultureInfo was used over NumberInfo, as it also works on DateTime parsing too. * Use default format spec in Commands --- src/Discord.Net.Core/Utils/TokenUtils.cs | 3 ++- src/Discord.Net.Rest/DiscordRestApiClient.cs | 2 +- src/Discord.Net.Rest/Entities/Users/RestUser.cs | 3 ++- .../Net/Converters/UInt64EntityOrIdConverter.cs | 5 +++-- src/Discord.Net.Rest/Net/RateLimitInfo.cs | 11 ++++++----- src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs | 5 +++-- src/Discord.Net.Webhook/DiscordWebhookClient.cs | 3 ++- 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Discord.Net.Core/Utils/TokenUtils.cs b/src/Discord.Net.Core/Utils/TokenUtils.cs index 2efb1822a..c3dd39237 100644 --- a/src/Discord.Net.Core/Utils/TokenUtils.cs +++ b/src/Discord.Net.Core/Utils/TokenUtils.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; namespace Discord @@ -76,7 +77,7 @@ namespace Discord var bytes = Convert.FromBase64String(encoded); var idStr = Encoding.UTF8.GetString(bytes); // try to parse a ulong from the resulting string - if (ulong.TryParse(idStr, out var id)) + if (ulong.TryParse(idStr, NumberStyles.None, CultureInfo.InvariantCulture, out var id)) return id; } catch (DecoderFallbackException) diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index c76f31835..d3db3e301 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -1488,7 +1488,7 @@ namespace Discord.API builder.Append(format, lastIndex, leftIndex - lastIndex); int rightIndex = format.IndexOf("}", leftIndex); - int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1)); + int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1), NumberStyles.None, CultureInfo.InvariantCulture); string fieldName = GetFieldName(methodArgs[argId + 1]); var mappedId = BucketIds.GetIndex(fieldName); diff --git a/src/Discord.Net.Rest/Entities/Users/RestUser.cs b/src/Discord.Net.Rest/Entities/Users/RestUser.cs index 37385fb7e..d5fffca94 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestUser.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestUser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Immutable; using System.Diagnostics; +using System.Globalization; using System.Threading.Tasks; using Model = Discord.API.User; @@ -57,7 +58,7 @@ namespace Discord.Rest if (model.Avatar.IsSpecified) AvatarId = model.Avatar.Value; if (model.Discriminator.IsSpecified) - DiscriminatorValue = ushort.Parse(model.Discriminator.Value); + DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture); if (model.Bot.IsSpecified) IsBot = model.Bot.Value; if (model.Username.IsSpecified) diff --git a/src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs b/src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs index ae8cf2cb2..e55534833 100644 --- a/src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs +++ b/src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs @@ -1,6 +1,7 @@ -using Discord.API; +using Discord.API; using Newtonsoft.Json; using System; +using System.Globalization; namespace Discord.Net.Converters { @@ -23,7 +24,7 @@ namespace Discord.Net.Converters { case JsonToken.String: case JsonToken.Integer: - return new EntityOrId(ulong.Parse(reader.ReadAsString())); + return new EntityOrId(ulong.Parse(reader.ReadAsString(), NumberStyles.None, CultureInfo.InvariantCulture)); default: T obj; if (_innerConverter != null) diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs index f193ce6ec..fb6f5e2ce 100644 --- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs +++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace Discord.Net { @@ -17,15 +18,15 @@ namespace Discord.Net IsGlobal = headers.TryGetValue("X-RateLimit-Global", out string temp) && bool.TryParse(temp, out var isGlobal) && isGlobal; Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) && - int.TryParse(temp, out var limit) ? limit : (int?)null; + int.TryParse(temp, NumberStyles.None, CultureInfo.InvariantCulture, out var limit) ? limit : (int?)null; Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) && - int.TryParse(temp, out var remaining) ? remaining : (int?)null; + int.TryParse(temp, NumberStyles.None, CultureInfo.InvariantCulture, out var remaining) ? remaining : (int?)null; Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) && - float.TryParse(temp, out var reset) ? DateTimeOffset.FromUnixTimeMilliseconds((long)(reset * 1000)) : (DateTimeOffset?)null; + double.TryParse(temp, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var reset) ? DateTimeOffset.FromUnixTimeMilliseconds((long)(reset * 1000)) : (DateTimeOffset?)null; RetryAfter = headers.TryGetValue("Retry-After", out temp) && - int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null; + int.TryParse(temp, NumberStyles.None, CultureInfo.InvariantCulture, out var retryAfter) ? retryAfter : (int?)null; Lag = headers.TryGetValue("Date", out temp) && - DateTimeOffset.TryParse(temp, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null; + DateTimeOffset.TryParse(temp, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null; } } } diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs index eceb071eb..d4798bedd 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Discord.Rest; @@ -60,10 +61,10 @@ namespace Discord.WebSocket } if (model.Discriminator.IsSpecified) { - var newVal = ushort.Parse(model.Discriminator.Value); + var newVal = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture); if (newVal != DiscriminatorValue) { - DiscriminatorValue = ushort.Parse(model.Discriminator.Value); + DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture); hasChanges = true; } } diff --git a/src/Discord.Net.Webhook/DiscordWebhookClient.cs b/src/Discord.Net.Webhook/DiscordWebhookClient.cs index 5dc3d51aa..542ec7997 100644 --- a/src/Discord.Net.Webhook/DiscordWebhookClient.cs +++ b/src/Discord.Net.Webhook/DiscordWebhookClient.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -132,7 +133,7 @@ namespace Discord.Webhook { // ensure that the first group is a ulong, set the _webhookId // 0th group is always the entire match, so start at index 1 - if (!(match.Groups[1].Success && ulong.TryParse(match.Groups[1].Value, out webhookId))) + if (!(match.Groups[1].Success && ulong.TryParse(match.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out webhookId))) throw ex("The webhook Id could not be parsed."); if (!match.Groups[2].Success) From c54867feba46ce7161096686d4f0a431193afdf9 Mon Sep 17 00:00:00 2001 From: NeKz Date: Sat, 21 Sep 2019 00:29:11 +0200 Subject: [PATCH 4/4] feature: update audit log models (#1373) * Fix bugs * Add missing properties * Add missing properties to ChannelInfo Remove UserLimit property * Add missing properties to GuildInfo Change ContentFilterLevel of type int? to ExplicitContentFilter of type ExplicitContentFilterLevel? * Remove AvatarHash from MemberInfo * Add missing doc comments * Make ExplicitContentFilter public * Add ChannelId property to overwrite audits * Update doc comments based on feedback --- .../DataTypes/ChannelCreateAuditLogData.cs | 39 +++++++++++++++++- .../DataTypes/ChannelDeleteAuditLogData.cs | 38 ++++++++++++++++- .../Entities/AuditLogs/DataTypes/ChannelInfo.cs | 30 +++++++++----- .../DataTypes/ChannelUpdateAuditLogData.cs | 13 +++--- .../Entities/AuditLogs/DataTypes/GuildInfo.cs | 47 ++++++++++++++++++++-- .../AuditLogs/DataTypes/GuildUpdateAuditLogData.cs | 17 ++++++-- .../Entities/AuditLogs/DataTypes/MemberInfo.cs | 29 +++++++++++-- .../DataTypes/MemberUpdateAuditLogData.cs | 19 ++++++--- .../DataTypes/OverwriteCreateAuditLogData.cs | 13 +++++- .../DataTypes/OverwriteDeleteAuditLogData.cs | 13 +++++- .../DataTypes/OverwriteUpdateAuditLogData.cs | 15 +++++-- .../AuditLogs/DataTypes/RoleUpdateAuditLogData.cs | 2 +- 12 files changed, 233 insertions(+), 42 deletions(-) diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelCreateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelCreateAuditLogData.cs index a692829f4..f432b4ca5 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelCreateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelCreateAuditLogData.cs @@ -11,11 +11,14 @@ namespace Discord.Rest /// public class ChannelCreateAuditLogData : IAuditLogData { - private ChannelCreateAuditLogData(ulong id, string name, ChannelType type, IReadOnlyCollection overwrites) + private ChannelCreateAuditLogData(ulong id, string name, ChannelType type, int? rateLimit, bool? nsfw, int? bitrate, IReadOnlyCollection overwrites) { ChannelId = id; ChannelName = name; ChannelType = type; + SlowModeInterval = rateLimit; + IsNsfw = nsfw; + Bitrate = bitrate; Overwrites = overwrites; } @@ -27,9 +30,15 @@ namespace Discord.Rest var overwritesModel = changes.FirstOrDefault(x => x.ChangedProperty == "permission_overwrites"); var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type"); var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name"); + var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user"); + var nsfwModel = changes.FirstOrDefault(x => x.ChangedProperty == "nsfw"); + var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate"); var type = typeModel.NewValue.ToObject(discord.ApiClient.Serializer); var name = nameModel.NewValue.ToObject(discord.ApiClient.Serializer); + int? rateLimitPerUser = rateLimitPerUserModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + bool? nsfw = nsfwModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + int? bitrate = bitrateModel?.NewValue?.ToObject(discord.ApiClient.Serializer); foreach (var overwrite in overwritesModel.NewValue) { @@ -41,7 +50,7 @@ namespace Discord.Rest overwrites.Add(new Overwrite(id, permType, new OverwritePermissions(allow, deny))); } - return new ChannelCreateAuditLogData(entry.TargetId.Value, name, type, overwrites.ToReadOnlyCollection()); + return new ChannelCreateAuditLogData(entry.TargetId.Value, name, type, rateLimitPerUser, nsfw, bitrate, overwrites.ToReadOnlyCollection()); } /// @@ -66,6 +75,32 @@ namespace Discord.Rest /// public ChannelType ChannelType { get; } /// + /// Gets the current slow-mode delay of the created channel. + /// + /// + /// An representing the time in seconds required before the user can send another + /// message; 0 if disabled. + /// null if this is not mentioned in this entry. + /// + public int? SlowModeInterval { get; } + /// + /// Gets the value that indicates whether the created channel is NSFW. + /// + /// + /// true if the created channel has the NSFW flag enabled; otherwise false. + /// null if this is not mentioned in this entry. + /// + public bool? IsNsfw { get; } + /// + /// Gets the bit-rate that the clients in the created voice channel are requested to use. + /// + /// + /// An representing the bit-rate (bps) that the created voice channel defines and requests the + /// client(s) to use. + /// null if this is not mentioned in this entry. + /// + public int? Bitrate { get; } + /// /// Gets a collection of permission overwrites that was assigned to the created channel. /// /// diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelDeleteAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelDeleteAuditLogData.cs index d09b658cf..390749929 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelDeleteAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelDeleteAuditLogData.cs @@ -11,11 +11,14 @@ namespace Discord.Rest /// public class ChannelDeleteAuditLogData : IAuditLogData { - private ChannelDeleteAuditLogData(ulong id, string name, ChannelType type, IReadOnlyCollection overwrites) + private ChannelDeleteAuditLogData(ulong id, string name, ChannelType type, int? rateLimit, bool? nsfw, int? bitrate, IReadOnlyCollection overwrites) { ChannelId = id; ChannelName = name; ChannelType = type; + SlowModeInterval = rateLimit; + IsNsfw = nsfw; + Bitrate = bitrate; Overwrites = overwrites; } @@ -26,15 +29,21 @@ namespace Discord.Rest var overwritesModel = changes.FirstOrDefault(x => x.ChangedProperty == "permission_overwrites"); var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type"); var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name"); + var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user"); + var nsfwModel = changes.FirstOrDefault(x => x.ChangedProperty == "nsfw"); + var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate"); var overwrites = overwritesModel.OldValue.ToObject(discord.ApiClient.Serializer) .Select(x => new Overwrite(x.TargetId, x.TargetType, new OverwritePermissions(x.Allow, x.Deny))) .ToList(); var type = typeModel.OldValue.ToObject(discord.ApiClient.Serializer); var name = nameModel.OldValue.ToObject(discord.ApiClient.Serializer); + int? rateLimitPerUser = rateLimitPerUserModel?.OldValue?.ToObject(discord.ApiClient.Serializer); + bool? nsfw = nsfwModel?.OldValue?.ToObject(discord.ApiClient.Serializer); + int? bitrate = bitrateModel?.OldValue?.ToObject(discord.ApiClient.Serializer); var id = entry.TargetId.Value; - return new ChannelDeleteAuditLogData(id, name, type, overwrites.ToReadOnlyCollection()); + return new ChannelDeleteAuditLogData(id, name, type, rateLimitPerUser, nsfw, bitrate, overwrites.ToReadOnlyCollection()); } /// @@ -59,6 +68,31 @@ namespace Discord.Rest /// public ChannelType ChannelType { get; } /// + /// Gets the slow-mode delay of the deleted channel. + /// + /// + /// An representing the time in seconds required before the user can send another + /// message; 0 if disabled. + /// null if this is not mentioned in this entry. + /// + public int? SlowModeInterval { get; } + /// + /// Gets the value that indicates whether the deleted channel was NSFW. + /// + /// + /// true if this channel had the NSFW flag enabled; otherwise false. + /// null if this is not mentioned in this entry. + /// + public bool? IsNsfw { get; } + /// + /// Gets the bit-rate of this channel if applicable. + /// + /// + /// An representing the bit-rate set of the voice channel. + /// null if this is not mentioned in this entry. + /// + public int? Bitrate { get; } + /// /// Gets a collection of permission overwrites that was assigned to the deleted channel. /// /// diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelInfo.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelInfo.cs index 6382e8250..d6d2fb4b3 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelInfo.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelInfo.cs @@ -5,12 +5,13 @@ namespace Discord.Rest /// public struct ChannelInfo { - internal ChannelInfo(string name, string topic, int? bitrate, int? limit) + internal ChannelInfo(string name, string topic, int? rateLimit, bool? nsfw, int? bitrate) { Name = name; Topic = topic; + SlowModeInterval = rateLimit; + IsNsfw = nsfw; Bitrate = bitrate; - UserLimit = limit; } /// @@ -28,20 +29,29 @@ namespace Discord.Rest /// public string Topic { get; } /// - /// Gets the bit-rate of this channel if applicable. + /// Gets the current slow-mode delay of this channel. /// /// - /// An representing the bit-rate set for the voice channel; null if not - /// applicable. + /// An representing the time in seconds required before the user can send another + /// message; 0 if disabled. + /// null if this is not mentioned in this entry. /// - public int? Bitrate { get; } + public int? SlowModeInterval { get; } + /// + /// Gets the value that indicates whether this channel is NSFW. + /// + /// + /// true if this channel has the NSFW flag enabled; otherwise false. + /// null if this is not mentioned in this entry. + /// + public bool? IsNsfw { get; } /// - /// Gets the number of users allowed to be in this channel if applicable. + /// Gets the bit-rate of this channel if applicable. /// /// - /// An representing the number of users allowed to be in this voice channel; - /// null if not applicable. + /// An representing the bit-rate set for the voice channel; + /// null if this is not mentioned in this entry. /// - public int? UserLimit { get; } + public int? Bitrate { get; } } } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs index f37404906..fa5233145 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs @@ -23,20 +23,23 @@ namespace Discord.Rest var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name"); var topicModel = changes.FirstOrDefault(x => x.ChangedProperty == "topic"); + var rateLimitPerUserModel = changes.FirstOrDefault(x => x.ChangedProperty == "rate_limit_per_user"); + var nsfwModel = changes.FirstOrDefault(x => x.ChangedProperty == "nsfw"); var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate"); - var userLimitModel = changes.FirstOrDefault(x => x.ChangedProperty == "user_limit"); string oldName = nameModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newName = nameModel?.NewValue?.ToObject(discord.ApiClient.Serializer); string oldTopic = topicModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newTopic = topicModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + int? oldRateLimitPerUser = rateLimitPerUserModel?.OldValue?.ToObject(discord.ApiClient.Serializer), + newRateLimitPerUser = rateLimitPerUserModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + bool? oldNsfw = nsfwModel?.OldValue?.ToObject(discord.ApiClient.Serializer), + newNsfw = nsfwModel?.NewValue?.ToObject(discord.ApiClient.Serializer); int? oldBitrate = bitrateModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newBitrate = bitrateModel?.NewValue?.ToObject(discord.ApiClient.Serializer); - int? oldLimit = userLimitModel?.OldValue?.ToObject(discord.ApiClient.Serializer), - newLimit = userLimitModel?.NewValue?.ToObject(discord.ApiClient.Serializer); - var before = new ChannelInfo(oldName, oldTopic, oldBitrate, oldLimit); - var after = new ChannelInfo(newName, newTopic, newBitrate, newLimit); + var before = new ChannelInfo(oldName, oldTopic, oldRateLimitPerUser, oldNsfw, oldBitrate); + var after = new ChannelInfo(newName, newTopic, newRateLimitPerUser, newNsfw, newBitrate); return new ChannelUpdateAuditLogData(entry.TargetId.Value, before, after); } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildInfo.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildInfo.cs index df63251d8..85c7ac438 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildInfo.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildInfo.cs @@ -7,7 +7,8 @@ namespace Discord.Rest { internal GuildInfo(int? afkTimeout, DefaultMessageNotifications? defaultNotifs, ulong? afkChannel, string name, string region, string icon, - VerificationLevel? verification, IUser owner, MfaLevel? mfa, int? filter) + VerificationLevel? verification, IUser owner, MfaLevel? mfa, ExplicitContentFilterLevel? filter, + ulong? systemChannel, ulong? widgetChannel, bool? widget) { AfkTimeout = afkTimeout; DefaultMessageNotifications = defaultNotifs; @@ -18,7 +19,10 @@ namespace Discord.Rest VerificationLevel = verification; Owner = owner; MfaLevel = mfa; - ContentFilterLevel = filter; + ExplicitContentFilter = filter; + SystemChannelId = systemChannel; + EmbedChannelId = widgetChannel; + IsEmbeddable = widget; } /// @@ -28,11 +32,16 @@ namespace Discord.Rest /// /// An representing the amount of time in seconds for a user to be marked as inactive /// and moved into the AFK voice channel. + /// null if this is not mentioned in this entry. /// public int? AfkTimeout { get; } /// /// Gets the default message notifications for users who haven't explicitly set their notification settings. /// + /// + /// The default message notifications setting of this guild. + /// null if this is not mentioned in this entry. + /// public DefaultMessageNotifications? DefaultMessageNotifications { get; } /// /// Gets the ID of the AFK voice channel for this guild. @@ -65,6 +74,7 @@ namespace Discord.Rest /// /// /// The level of requirements. + /// null if this is not mentioned in this entry. /// public VerificationLevel? VerificationLevel { get; } /// @@ -80,8 +90,39 @@ namespace Discord.Rest /// /// /// The level of MFA requirement. + /// null if this is not mentioned in this entry. /// public MfaLevel? MfaLevel { get; } - public int? ContentFilterLevel { get; } + /// + /// Gets the level of content filtering applied to user's content in a Guild. + /// + /// + /// The level of explicit content filtering. + /// + public ExplicitContentFilterLevel? ExplicitContentFilter { get; } + /// + /// Gets the ID of the channel where system messages are sent. + /// + /// + /// A representing the snowflake identifier of the channel where system + /// messages are sent; null if none is set. + /// + public ulong? SystemChannelId { get; } + /// + /// Gets the ID of the widget embed channel of this guild. + /// + /// + /// A representing the snowflake identifier of the embedded channel found within the + /// widget settings of this guild; null if none is set. + /// + public ulong? EmbedChannelId { get; } + /// + /// Gets a value that indicates whether this guild is embeddable (i.e. can use widget). + /// + /// + /// true if this guild can be embedded via widgets; otherwise false. + /// null if this is not mentioned in this entry. + /// + public bool? IsEmbeddable { get; } } } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs index 853fa4b4a..80b719a6d 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs @@ -30,6 +30,9 @@ namespace Discord.Rest var ownerIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "owner_id"); var mfaLevelModel = changes.FirstOrDefault(x => x.ChangedProperty == "mfa_level"); var contentFilterModel = changes.FirstOrDefault(x => x.ChangedProperty == "explicit_content_filter"); + var systemChannelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "system_channel_id"); + var widgetChannelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "widget_channel_id"); + var widgetEnabledModel = changes.FirstOrDefault(x => x.ChangedProperty == "widget_enabled"); int? oldAfkTimeout = afkTimeoutModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newAfkTimeout = afkTimeoutModel?.NewValue?.ToObject(discord.ApiClient.Serializer); @@ -49,8 +52,14 @@ namespace Discord.Rest newOwnerId = ownerIdModel?.NewValue?.ToObject(discord.ApiClient.Serializer); MfaLevel? oldMfaLevel = mfaLevelModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newMfaLevel = mfaLevelModel?.NewValue?.ToObject(discord.ApiClient.Serializer); - int? oldContentFilter = contentFilterModel?.OldValue?.ToObject(discord.ApiClient.Serializer), - newContentFilter = contentFilterModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + ExplicitContentFilterLevel? oldContentFilter = contentFilterModel?.OldValue?.ToObject(discord.ApiClient.Serializer), + newContentFilter = contentFilterModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + ulong? oldSystemChannelId = systemChannelIdModel?.OldValue?.ToObject(discord.ApiClient.Serializer), + newSystemChannelId = systemChannelIdModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + ulong? oldWidgetChannelId = widgetChannelIdModel?.OldValue?.ToObject(discord.ApiClient.Serializer), + newWidgetChannelId = widgetChannelIdModel?.NewValue?.ToObject(discord.ApiClient.Serializer); + bool? oldWidgetEnabled = widgetEnabledModel?.OldValue?.ToObject(discord.ApiClient.Serializer), + newWidgetEnabled = widgetEnabledModel?.NewValue?.ToObject(discord.ApiClient.Serializer); IUser oldOwner = null; if (oldOwnerId != null) @@ -68,10 +77,10 @@ namespace Discord.Rest var before = new GuildInfo(oldAfkTimeout, oldDefaultMessageNotifications, oldAfkChannelId, oldName, oldRegionId, oldIconHash, oldVerificationLevel, oldOwner, - oldMfaLevel, oldContentFilter); + oldMfaLevel, oldContentFilter, oldSystemChannelId, oldWidgetChannelId, oldWidgetEnabled); var after = new GuildInfo(newAfkTimeout, newDefaultMessageNotifications, newAfkChannelId, newName, newRegionId, newIconHash, newVerificationLevel, newOwner, - newMfaLevel, newContentFilter); + newMfaLevel, newContentFilter, newSystemChannelId, newWidgetChannelId, newWidgetEnabled); return new GuildUpdateAuditLogData(before, after); } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs index b0a1a8e5a..ffa316faa 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs @@ -1,18 +1,41 @@ namespace Discord.Rest { + /// + /// Represents information for a member. + /// public struct MemberInfo { - internal MemberInfo(string nick, bool? deaf, bool? mute, string avatar_hash) + internal MemberInfo(string nick, bool? deaf, bool? mute) { Nickname = nick; Deaf = deaf; Mute = mute; - AvatarHash = avatar_hash; } + /// + /// Gets the nickname of the updated member. + /// + /// + /// A string representing the nickname of the updated member; null if none is set. + /// public string Nickname { get; } + /// + /// Gets a value that indicates whether the updated member is deafened by the guild. + /// + /// + /// true if the updated member is deafened (i.e. not permitted to listen to or speak to others) by the guild; + /// otherwise false. + /// null if this is not mentioned in this entry. + /// public bool? Deaf { get; } + /// + /// Gets a value that indicates whether the updated member is muted (i.e. not permitted to speak via voice) by the + /// guild. + /// + /// + /// true if the updated member is muted by the guild; otherwise false. + /// null if this is not mentioned in this entry. + /// public bool? Mute { get; } - public string AvatarHash { get; } } } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs index 238c79843..f22b83e4c 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs @@ -24,7 +24,6 @@ namespace Discord.Rest var nickModel = changes.FirstOrDefault(x => x.ChangedProperty == "nick"); var deafModel = changes.FirstOrDefault(x => x.ChangedProperty == "deaf"); var muteModel = changes.FirstOrDefault(x => x.ChangedProperty == "mute"); - var avatarModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash"); string oldNick = nickModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newNick = nickModel?.NewValue?.ToObject(discord.ApiClient.Serializer); @@ -32,14 +31,12 @@ namespace Discord.Rest newDeaf = deafModel?.NewValue?.ToObject(discord.ApiClient.Serializer); bool? oldMute = muteModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newMute = muteModel?.NewValue?.ToObject(discord.ApiClient.Serializer); - string oldAvatar = avatarModel?.OldValue?.ToObject(discord.ApiClient.Serializer), - newAvatar = avatarModel?.NewValue?.ToObject(discord.ApiClient.Serializer); var targetInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId); var user = RestUser.Create(discord, targetInfo); - var before = new MemberInfo(oldNick, oldDeaf, oldMute, oldAvatar); - var after = new MemberInfo(newNick, newDeaf, newMute, newAvatar); + var before = new MemberInfo(oldNick, oldDeaf, oldMute); + var after = new MemberInfo(newNick, newDeaf, newMute); return new MemberUpdateAuditLogData(user, before, after); } @@ -51,7 +48,19 @@ namespace Discord.Rest /// A user object representing the user who the changes were performed on. /// public IUser Target { get; } + /// + /// Gets the member information before the changes. + /// + /// + /// An information object containing the original member information before the changes were made. + /// public MemberInfo Before { get; } + /// + /// Gets the member information after the changes. + /// + /// + /// An information object containing the member information after the changes were made. + /// public MemberInfo After { get; } } } diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs index a9ccd4db3..3f391187d 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs @@ -10,8 +10,9 @@ namespace Discord.Rest /// public class OverwriteCreateAuditLogData : IAuditLogData { - private OverwriteCreateAuditLogData(Overwrite overwrite) + private OverwriteCreateAuditLogData(ulong channelId, Overwrite overwrite) { + ChannelId = channelId; Overwrite = overwrite; } @@ -30,10 +31,18 @@ namespace Discord.Rest var id = entry.Options.OverwriteTargetId.Value; var type = entry.Options.OverwriteType; - return new OverwriteCreateAuditLogData(new Overwrite(id, type, permissions)); + return new OverwriteCreateAuditLogData(entry.TargetId.Value, new Overwrite(id, type, permissions)); } /// + /// Gets the ID of the channel that the overwrite was created from. + /// + /// + /// A representing the snowflake identifier for the channel that the overwrite was + /// created from. + /// + public ulong ChannelId { get; } + /// /// Gets the permission overwrite object that was created. /// /// diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs index 1e51fa5e3..a193e76ce 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs @@ -10,8 +10,9 @@ namespace Discord.Rest /// public class OverwriteDeleteAuditLogData : IAuditLogData { - private OverwriteDeleteAuditLogData(Overwrite deletedOverwrite) + private OverwriteDeleteAuditLogData(ulong channelId, Overwrite deletedOverwrite) { + ChannelId = channelId; Overwrite = deletedOverwrite; } @@ -29,10 +30,18 @@ namespace Discord.Rest var id = idModel.OldValue.ToObject(discord.ApiClient.Serializer); var allow = allowModel.OldValue.ToObject(discord.ApiClient.Serializer); - return new OverwriteDeleteAuditLogData(new Overwrite(id, type, new OverwritePermissions(allow, deny))); + return new OverwriteDeleteAuditLogData(entry.TargetId.Value, new Overwrite(id, type, new OverwritePermissions(allow, deny))); } /// + /// Gets the ID of the channel that the overwrite was deleted from. + /// + /// + /// A representing the snowflake identifier for the channel that the overwrite was + /// deleted from. + /// + public ulong ChannelId { get; } + /// /// Gets the permission overwrite object that was deleted. /// /// diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs index ac67c85cf..c2b8d423e 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs @@ -10,8 +10,9 @@ namespace Discord.Rest /// public class OverwriteUpdateAuditLogData : IAuditLogData { - private OverwriteUpdateAuditLogData(OverwritePermissions before, OverwritePermissions after, ulong targetId, PermissionTarget targetType) + private OverwriteUpdateAuditLogData(ulong channelId, OverwritePermissions before, OverwritePermissions after, ulong targetId, PermissionTarget targetType) { + ChannelId = channelId; OldPermissions = before; NewPermissions = after; OverwriteTargetId = targetId; @@ -28,17 +29,25 @@ namespace Discord.Rest var beforeAllow = allowModel?.OldValue?.ToObject(discord.ApiClient.Serializer); var afterAllow = allowModel?.NewValue?.ToObject(discord.ApiClient.Serializer); var beforeDeny = denyModel?.OldValue?.ToObject(discord.ApiClient.Serializer); - var afterDeny = denyModel?.OldValue?.ToObject(discord.ApiClient.Serializer); + var afterDeny = denyModel?.NewValue?.ToObject(discord.ApiClient.Serializer); var beforePermissions = new OverwritePermissions(beforeAllow ?? 0, beforeDeny ?? 0); var afterPermissions = new OverwritePermissions(afterAllow ?? 0, afterDeny ?? 0); var type = entry.Options.OverwriteType; - return new OverwriteUpdateAuditLogData(beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, type); + return new OverwriteUpdateAuditLogData(entry.TargetId.Value, beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, type); } /// + /// Gets the ID of the channel that the overwrite was updated from. + /// + /// + /// A representing the snowflake identifier for the channel that the overwrite was + /// updated from. + /// + public ulong ChannelId { get; } + /// /// Gets the overwrite permissions before the changes. /// /// diff --git a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs index f98fc3e23..094e1e0e0 100644 --- a/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs +++ b/src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs @@ -36,7 +36,7 @@ namespace Discord.Rest string oldName = nameModel?.OldValue?.ToObject(discord.ApiClient.Serializer), newName = nameModel?.NewValue?.ToObject(discord.ApiClient.Serializer); ulong? oldPermissionsRaw = permissionsModel?.OldValue?.ToObject(discord.ApiClient.Serializer), - newPermissionsRaw = permissionsModel?.OldValue?.ToObject(discord.ApiClient.Serializer); + newPermissionsRaw = permissionsModel?.NewValue?.ToObject(discord.ApiClient.Serializer); Color? oldColor = null, newColor = null;