feature: adjust the ratelimit for reactions (#1108)

* feature: adjust the ratelimit for reactions

allows users to add reactions quickly

* fix: don't force DEBUG_LIMITS

* fix: undefined behavior using DateTime on intel architerctures

it's fine

* fix: ensure add/del rxn ends up in the same bucket
This commit is contained in:
Christopher F
2018-09-30 17:10:10 -04:00
committed by GitHub
parent c9ba79ec80
commit 6b21b11f7d
3 changed files with 14 additions and 3 deletions

View File

@@ -1,4 +1,4 @@
using System.Threading; using System.Threading;
namespace Discord namespace Discord
{ {
@@ -22,6 +22,7 @@ namespace Discord
internal bool IgnoreState { get; set; } internal bool IgnoreState { get; set; }
internal string BucketId { get; set; } internal string BucketId { get; set; }
internal bool IsClientBucket { get; set; } internal bool IsClientBucket { get; set; }
internal bool IsReactionBucket { get; set; }
internal static RequestOptions CreateOrClone(RequestOptions options) internal static RequestOptions CreateOrClone(RequestOptions options)
{ {

View File

@@ -580,6 +580,7 @@ namespace Discord.API
var ids = new BucketIds(channelId: channelId); var ids = new BucketIds(channelId: channelId);
return await SendJsonAsync<Message>("PATCH", () => $"channels/{channelId}/messages/{messageId}", args, ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false); return await SendJsonAsync<Message>("PATCH", () => $"channels/{channelId}/messages/{messageId}", args, ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false);
} }
public async Task AddReactionAsync(ulong channelId, ulong messageId, string emoji, RequestOptions options = null) public async Task AddReactionAsync(ulong channelId, ulong messageId, string emoji, RequestOptions options = null)
{ {
Preconditions.NotEqual(channelId, 0, nameof(channelId)); Preconditions.NotEqual(channelId, 0, nameof(channelId));
@@ -587,10 +588,13 @@ namespace Discord.API
Preconditions.NotNullOrWhitespace(emoji, nameof(emoji)); Preconditions.NotNullOrWhitespace(emoji, nameof(emoji));
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
options.IsReactionBucket = true;
var ids = new BucketIds(channelId: channelId); var ids = new BucketIds(channelId: channelId);
await SendAsync("PUT", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}/@me", ids, options: options).ConfigureAwait(false); // @me is non-const to fool the ratelimiter, otherwise it will put add/remove in separate buckets
var me = "@me";
await SendAsync("PUT", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}/{me}", ids, options: options).ConfigureAwait(false);
} }
public async Task RemoveReactionAsync(ulong channelId, ulong messageId, ulong userId, string emoji, RequestOptions options = null) public async Task RemoveReactionAsync(ulong channelId, ulong messageId, ulong userId, string emoji, RequestOptions options = null)
{ {
@@ -599,10 +603,12 @@ namespace Discord.API
Preconditions.NotNullOrWhitespace(emoji, nameof(emoji)); Preconditions.NotNullOrWhitespace(emoji, nameof(emoji));
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
options.IsReactionBucket = true;
var ids = new BucketIds(channelId: channelId); var ids = new BucketIds(channelId: channelId);
await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}/{userId}", ids, options: options).ConfigureAwait(false); var user = CurrentUserId.HasValue ? (userId == CurrentUserId.Value ? "@me" : userId.ToString()) : userId.ToString();
await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}/{user}", ids, options: options).ConfigureAwait(false);
} }
public async Task RemoveAllReactionsAsync(ulong channelId, ulong messageId, RequestOptions options = null) public async Task RemoveAllReactionsAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{ {

View File

@@ -250,6 +250,10 @@ namespace Discord.Net.Queue
else if (info.Reset.HasValue) else if (info.Reset.HasValue)
{ {
resetTick = info.Reset.Value.AddSeconds(info.Lag?.TotalSeconds ?? 1.0); resetTick = info.Reset.Value.AddSeconds(info.Lag?.TotalSeconds ?? 1.0);
if (request.Options.IsReactionBucket)
resetTick = DateTimeOffset.Now.AddMilliseconds(250);
int diff = (int)(resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds; int diff = (int)(resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds;
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {info.Lag?.TotalMilliseconds} ms lag)"); Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {info.Lag?.TotalMilliseconds} ms lag)");