Skip to content

Commit 606dac3

Browse files
Chris-Johnstonfoxbot
authored andcommitted
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
1 parent 3755a02 commit 606dac3

File tree

7 files changed

+19
-13
lines changed

7 files changed

+19
-13
lines changed

src/Discord.Net.Core/Utils/TokenUtils.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Globalization;
23
using System.Text;
34

45
namespace Discord
@@ -76,7 +77,7 @@ internal static string PadBase64String(string encodedBase64)
7677
var bytes = Convert.FromBase64String(encoded);
7778
var idStr = Encoding.UTF8.GetString(bytes);
7879
// try to parse a ulong from the resulting string
79-
if (ulong.TryParse(idStr, out var id))
80+
if (ulong.TryParse(idStr, NumberStyles.None, CultureInfo.InvariantCulture, out var id))
8081
return id;
8182
}
8283
catch (DecoderFallbackException)

src/Discord.Net.Rest/DiscordRestApiClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1488,7 +1488,7 @@ private static Func<BucketIds, string> CreateBucketId(Expression<Func<string>> e
14881488
builder.Append(format, lastIndex, leftIndex - lastIndex);
14891489
int rightIndex = format.IndexOf("}", leftIndex);
14901490

1491-
int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1));
1491+
int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1), NumberStyles.None, CultureInfo.InvariantCulture);
14921492
string fieldName = GetFieldName(methodArgs[argId + 1]);
14931493

14941494
var mappedId = BucketIds.GetIndex(fieldName);

src/Discord.Net.Rest/Entities/Users/RestUser.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Immutable;
33
using System.Diagnostics;
4+
using System.Globalization;
45
using System.Threading.Tasks;
56
using Model = Discord.API.User;
67

@@ -57,7 +58,7 @@ internal virtual void Update(Model model)
5758
if (model.Avatar.IsSpecified)
5859
AvatarId = model.Avatar.Value;
5960
if (model.Discriminator.IsSpecified)
60-
DiscriminatorValue = ushort.Parse(model.Discriminator.Value);
61+
DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
6162
if (model.Bot.IsSpecified)
6263
IsBot = model.Bot.Value;
6364
if (model.Username.IsSpecified)

src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
using Discord.API;
1+
using Discord.API;
22
using Newtonsoft.Json;
33
using System;
4+
using System.Globalization;
45

56
namespace Discord.Net.Converters
67
{
@@ -23,7 +24,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
2324
{
2425
case JsonToken.String:
2526
case JsonToken.Integer:
26-
return new EntityOrId<T>(ulong.Parse(reader.ReadAsString()));
27+
return new EntityOrId<T>(ulong.Parse(reader.ReadAsString(), NumberStyles.None, CultureInfo.InvariantCulture));
2728
default:
2829
T obj;
2930
if (_innerConverter != null)

src/Discord.Net.Rest/Net/RateLimitInfo.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34

45
namespace Discord.Net
56
{
@@ -17,15 +18,15 @@ internal RateLimitInfo(Dictionary<string, string> headers)
1718
IsGlobal = headers.TryGetValue("X-RateLimit-Global", out string temp) &&
1819
bool.TryParse(temp, out var isGlobal) && isGlobal;
1920
Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) &&
20-
int.TryParse(temp, out var limit) ? limit : (int?)null;
21+
int.TryParse(temp, NumberStyles.None, CultureInfo.InvariantCulture, out var limit) ? limit : (int?)null;
2122
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) &&
22-
int.TryParse(temp, out var remaining) ? remaining : (int?)null;
23+
int.TryParse(temp, NumberStyles.None, CultureInfo.InvariantCulture, out var remaining) ? remaining : (int?)null;
2324
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) &&
24-
float.TryParse(temp, out var reset) ? DateTimeOffset.FromUnixTimeMilliseconds((long)(reset * 1000)) : (DateTimeOffset?)null;
25+
double.TryParse(temp, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var reset) ? DateTimeOffset.FromUnixTimeMilliseconds((long)(reset * 1000)) : (DateTimeOffset?)null;
2526
RetryAfter = headers.TryGetValue("Retry-After", out temp) &&
26-
int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null;
27+
int.TryParse(temp, NumberStyles.None, CultureInfo.InvariantCulture, out var retryAfter) ? retryAfter : (int?)null;
2728
Lag = headers.TryGetValue("Date", out temp) &&
28-
DateTimeOffset.TryParse(temp, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null;
29+
DateTimeOffset.TryParse(temp, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null;
2930
}
3031
}
3132
}

src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Collections.Immutable;
44
using System.Diagnostics;
5+
using System.Globalization;
56
using System.Linq;
67
using System.Threading.Tasks;
78
using Discord.Rest;
@@ -60,10 +61,10 @@ internal virtual bool Update(ClientState state, Model model)
6061
}
6162
if (model.Discriminator.IsSpecified)
6263
{
63-
var newVal = ushort.Parse(model.Discriminator.Value);
64+
var newVal = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
6465
if (newVal != DiscriminatorValue)
6566
{
66-
DiscriminatorValue = ushort.Parse(model.Discriminator.Value);
67+
DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
6768
hasChanges = true;
6869
}
6970
}

src/Discord.Net.Webhook/DiscordWebhookClient.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.IO;
45
using System.Text.RegularExpressions;
56
using System.Threading.Tasks;
@@ -132,7 +133,7 @@ ArgumentException ex(string reason = null)
132133
{
133134
// ensure that the first group is a ulong, set the _webhookId
134135
// 0th group is always the entire match, so start at index 1
135-
if (!(match.Groups[1].Success && ulong.TryParse(match.Groups[1].Value, out webhookId)))
136+
if (!(match.Groups[1].Success && ulong.TryParse(match.Groups[1].Value, NumberStyles.None, CultureInfo.InvariantCulture, out webhookId)))
136137
throw ex("The webhook Id could not be parsed.");
137138

138139
if (!match.Groups[2].Success)

0 commit comments

Comments
 (0)