| @@ -1,4 +1,4 @@ | |||||
| using System.Reflection; | |||||
| using System.Reflection; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -20,6 +20,7 @@ namespace Discord | |||||
| public const int MaxMessagesPerBatch = 100; | public const int MaxMessagesPerBatch = 100; | ||||
| public const int MaxUsersPerBatch = 1000; | public const int MaxUsersPerBatch = 1000; | ||||
| public const int MaxGuildsPerBatch = 100; | public const int MaxGuildsPerBatch = 100; | ||||
| public const int MaxUserReactionsPerBatch = 100; | |||||
| /// <summary> Gets or sets how a request should act in the case of an error, by default. </summary> | /// <summary> Gets or sets how a request should act in the case of an error, by default. </summary> | ||||
| public RetryMode DefaultRetryMode { get; set; } = RetryMode.AlwaysRetry; | public RetryMode DefaultRetryMode { get; set; } = RetryMode.AlwaysRetry; | ||||
| @@ -231,6 +231,7 @@ namespace Discord | |||||
| { | { | ||||
| private string _name; | private string _name; | ||||
| private string _value; | private string _value; | ||||
| private EmbedField _field; | |||||
| public const int MaxFieldNameLength = 256; | public const int MaxFieldNameLength = 256; | ||||
| public const int MaxFieldValueLength = 1024; | public const int MaxFieldValueLength = 1024; | ||||
| @@ -618,15 +618,15 @@ namespace Discord.API | |||||
| Preconditions.NotNullOrWhitespace(emoji, nameof(emoji)); | Preconditions.NotNullOrWhitespace(emoji, nameof(emoji)); | ||||
| Preconditions.NotNull(args, nameof(args)); | Preconditions.NotNull(args, nameof(args)); | ||||
| Preconditions.GreaterThan(args.Limit, 0, nameof(args.Limit)); | Preconditions.GreaterThan(args.Limit, 0, nameof(args.Limit)); | ||||
| Preconditions.AtMost(args.Limit, DiscordConfig.MaxUsersPerBatch, nameof(args.Limit)); | |||||
| Preconditions.AtMost(args.Limit, DiscordConfig.MaxUserReactionsPerBatch, nameof(args.Limit)); | |||||
| Preconditions.GreaterThan(args.AfterUserId, 0, nameof(args.AfterUserId)); | Preconditions.GreaterThan(args.AfterUserId, 0, nameof(args.AfterUserId)); | ||||
| options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
| int limit = args.Limit.GetValueOrDefault(int.MaxValue); | |||||
| ulong afterUserId = args.AfterUserId.GetValueOrDefault(0); | |||||
| var limit = args.Limit.GetValueOrDefault(DiscordConfig.MaxUserReactionsPerBatch); | |||||
| var afterUserId = args.AfterUserId.GetValueOrDefault(0); | |||||
| var ids = new BucketIds(channelId: channelId); | var ids = new BucketIds(channelId: channelId); | ||||
| Expression<Func<string>> endpoint = () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}"; | |||||
| Expression<Func<string>> endpoint = () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}?limit={limit}&after={afterUserId}"; | |||||
| return await SendAsync<IReadOnlyCollection<User>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | return await SendAsync<IReadOnlyCollection<User>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | ||||
| } | } | ||||
| public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null) | public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null) | ||||
| @@ -49,14 +49,19 @@ namespace Discord.Rest | |||||
| public static IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IMessage msg, IEmote emote, | public static IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IMessage msg, IEmote emote, | ||||
| Action<GetReactionUsersParams> func, BaseDiscordClient client, RequestOptions options) | Action<GetReactionUsersParams> func, BaseDiscordClient client, RequestOptions options) | ||||
| { | { | ||||
| var args = new GetReactionUsersParams(); | |||||
| func(args); | |||||
| Preconditions.NotNull(emote, nameof(emote)); | |||||
| var emoji = (emote is Emote e ? $"{e.Name}:{e.Id}" : emote.Name); | var emoji = (emote is Emote e ? $"{e.Name}:{e.Id}" : emote.Name); | ||||
| var arguments = new GetReactionUsersParams(); | |||||
| func(arguments); | |||||
| return new PagedAsyncEnumerable<IUser>( | return new PagedAsyncEnumerable<IUser>( | ||||
| DiscordConfig.MaxUsersPerBatch, | |||||
| DiscordConfig.MaxUserReactionsPerBatch, | |||||
| async (info, ct) => | async (info, ct) => | ||||
| { | { | ||||
| var args = new GetReactionUsersParams(); | |||||
| func(args); | |||||
| if (info.Position != null) | if (info.Position != null) | ||||
| args.AfterUserId = info.Position.Value; | args.AfterUserId = info.Position.Value; | ||||
| @@ -73,10 +78,11 @@ namespace Discord.Rest | |||||
| if (lastPage.Count != DiscordConfig.MaxUsersPerBatch) | if (lastPage.Count != DiscordConfig.MaxUsersPerBatch) | ||||
| return false; | return false; | ||||
| info.Position = lastPage.OrderBy(u => u.Id).First().Id; | |||||
| info.Position = lastPage.Max(x => x.Id); | |||||
| return true; | return true; | ||||
| }, | }, | ||||
| count: args.Limit.Value | |||||
| start: arguments.AfterUserId.Value, | |||||
| count: arguments.Limit.Value | |||||
| ); | ); | ||||
| } | } | ||||