| @@ -711,10 +711,10 @@ namespace Discord.API | |||||
| Preconditions.NotEqual(guildId, 0, nameof(guildId)); | Preconditions.NotEqual(guildId, 0, nameof(guildId)); | ||||
| 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.AtLeast(args.Offset, 0, nameof(args.Offset)); | |||||
| Preconditions.GreaterThan(args.AfterUserId, 0, nameof(args.AfterUserId)); | |||||
| int limit = args.Limit.GetValueOrDefault(int.MaxValue); | int limit = args.Limit.GetValueOrDefault(int.MaxValue); | ||||
| int offset = args.Offset.GetValueOrDefault(0); | |||||
| ulong afterUserId = args.AfterUserId.GetValueOrDefault(0); | |||||
| List<GuildMember[]> result; | List<GuildMember[]> result; | ||||
| if (args.Limit.IsSpecified) | if (args.Limit.IsSpecified) | ||||
| @@ -725,7 +725,7 @@ namespace Discord.API | |||||
| while (true) | while (true) | ||||
| { | { | ||||
| int runLimit = (limit >= DiscordConfig.MaxUsersPerBatch) ? DiscordConfig.MaxUsersPerBatch : limit; | int runLimit = (limit >= DiscordConfig.MaxUsersPerBatch) ? DiscordConfig.MaxUsersPerBatch : limit; | ||||
| string endpoint = $"guilds/{guildId}/members?limit={runLimit}&offset={offset}"; | |||||
| string endpoint = $"guilds/{guildId}/members?limit={runLimit}&after={afterUserId}"; | |||||
| var models = await SendAsync<GuildMember[]>("GET", endpoint, options: options).ConfigureAwait(false); | var models = await SendAsync<GuildMember[]>("GET", endpoint, options: options).ConfigureAwait(false); | ||||
| //Was this an empty batch? | //Was this an empty batch? | ||||
| @@ -734,7 +734,7 @@ namespace Discord.API | |||||
| result.Add(models); | result.Add(models); | ||||
| limit -= DiscordConfig.MaxUsersPerBatch; | limit -= DiscordConfig.MaxUsersPerBatch; | ||||
| offset += models.Length; | |||||
| afterUserId = models[models.Length - 1].User.Id; | |||||
| //Was this an incomplete (the last) batch? | //Was this an incomplete (the last) batch? | ||||
| if (models.Length != DiscordConfig.MaxUsersPerBatch) break; | if (models.Length != DiscordConfig.MaxUsersPerBatch) break; | ||||
| @@ -3,6 +3,6 @@ | |||||
| public class GetGuildMembersParams | public class GetGuildMembersParams | ||||
| { | { | ||||
| public Optional<int> Limit { get; set; } | public Optional<int> Limit { get; set; } | ||||
| public Optional<int> Offset { get; set; } | |||||
| public Optional<ulong> AfterUserId { get; set; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -60,12 +60,7 @@ namespace Discord | |||||
| public virtual async Task<IReadOnlyCollection<IUser>> GetUsersAsync() | public virtual async Task<IReadOnlyCollection<IUser>> GetUsersAsync() | ||||
| { | { | ||||
| var currentUser = await Discord.GetCurrentUserAsync().ConfigureAwait(false); | var currentUser = await Discord.GetCurrentUserAsync().ConfigureAwait(false); | ||||
| return ImmutableArray.Create<IUser>(currentUser, Recipient); | |||||
| } | |||||
| public virtual async Task<IReadOnlyCollection<IUser>> GetUsersAsync(int limit, int offset) | |||||
| { | |||||
| var currentUser = await Discord.GetCurrentUserAsync().ConfigureAwait(false); | |||||
| return new IUser[] { currentUser, Recipient }.Skip(offset).Take(limit).ToImmutableArray(); | |||||
| return ImmutableArray.Create(currentUser, Recipient); | |||||
| } | } | ||||
| public async Task<IMessage> SendMessageAsync(string text, bool isTTS) | public async Task<IMessage> SendMessageAsync(string text, bool isTTS) | ||||
| @@ -65,7 +65,6 @@ namespace Discord | |||||
| public abstract Task<IGuildUser> GetUserAsync(ulong id); | public abstract Task<IGuildUser> GetUserAsync(ulong id); | ||||
| public abstract Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(); | public abstract Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(); | ||||
| public abstract Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset); | |||||
| public async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync() | public async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync() | ||||
| { | { | ||||
| @@ -151,6 +150,5 @@ namespace Discord | |||||
| async Task<IUser> IChannel.GetUserAsync(ulong id) => await GetUserAsync(id).ConfigureAwait(false); | async Task<IUser> IChannel.GetUserAsync(ulong id) => await GetUserAsync(id).ConfigureAwait(false); | ||||
| async Task<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync() => await GetUsersAsync().ConfigureAwait(false); | async Task<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync() => await GetUsersAsync().ConfigureAwait(false); | ||||
| async Task<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(int limit, int offset) => await GetUsersAsync(limit, offset).ConfigureAwait(false); | |||||
| } | } | ||||
| } | } | ||||
| @@ -7,8 +7,6 @@ namespace Discord | |||||
| { | { | ||||
| /// <summary> Gets a collection of all users in this channel. </summary> | /// <summary> Gets a collection of all users in this channel. </summary> | ||||
| Task<IReadOnlyCollection<IUser>> GetUsersAsync(); | Task<IReadOnlyCollection<IUser>> GetUsersAsync(); | ||||
| /// <summary> Gets a paginated collection of all users in this channel. </summary> | |||||
| Task<IReadOnlyCollection<IUser>> GetUsersAsync(int limit, int offset = 0); | |||||
| /// <summary> Gets a user in this channel with the provided id.</summary> | /// <summary> Gets a user in this channel with the provided id.</summary> | ||||
| Task<IUser> GetUserAsync(ulong id); | Task<IUser> GetUserAsync(ulong id); | ||||
| } | } | ||||
| @@ -52,11 +52,6 @@ namespace Discord | |||||
| var users = await Guild.GetUsersAsync().ConfigureAwait(false); | var users = await Guild.GetUsersAsync().ConfigureAwait(false); | ||||
| return users.Where(x => Permissions.GetValue(Permissions.ResolveChannel(x, this, x.GuildPermissions.RawValue), ChannelPermission.ReadMessages)).ToImmutableArray(); | return users.Where(x => Permissions.GetValue(Permissions.ResolveChannel(x, this, x.GuildPermissions.RawValue), ChannelPermission.ReadMessages)).ToImmutableArray(); | ||||
| } | } | ||||
| public override async Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset) | |||||
| { | |||||
| var users = await Guild.GetUsersAsync(limit, offset).ConfigureAwait(false); | |||||
| return users.Where(x => Permissions.GetValue(Permissions.ResolveChannel(x, this, x.GuildPermissions.RawValue), ChannelPermission.ReadMessages)).ToImmutableArray(); | |||||
| } | |||||
| public async Task<IMessage> SendMessageAsync(string text, bool isTTS) | public async Task<IMessage> SendMessageAsync(string text, bool isTTS) | ||||
| { | { | ||||
| @@ -44,10 +44,6 @@ namespace Discord | |||||
| { | { | ||||
| throw new NotSupportedException(); | throw new NotSupportedException(); | ||||
| } | } | ||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset) | |||||
| { | |||||
| throw new NotSupportedException(); | |||||
| } | |||||
| private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; | private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; | ||||
| } | } | ||||
| @@ -268,12 +268,6 @@ namespace Discord | |||||
| var models = await Discord.ApiClient.GetGuildMembersAsync(Id, args).ConfigureAwait(false); | var models = await Discord.ApiClient.GetGuildMembersAsync(Id, args).ConfigureAwait(false); | ||||
| return models.Select(x => new GuildUser(this, new User(x.User), x)).ToImmutableArray(); | return models.Select(x => new GuildUser(this, new User(x.User), x)).ToImmutableArray(); | ||||
| } | } | ||||
| public virtual async Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset) | |||||
| { | |||||
| var args = new GetGuildMembersParams { Limit = limit, Offset = offset }; | |||||
| var models = await Discord.ApiClient.GetGuildMembersAsync(Id, args).ConfigureAwait(false); | |||||
| return models.Select(x => new GuildUser(this, new User(x.User), x)).ToImmutableArray(); | |||||
| } | |||||
| public async Task<int> PruneUsersAsync(int days = 30, bool simulate = false) | public async Task<int> PruneUsersAsync(int days = 30, bool simulate = false) | ||||
| { | { | ||||
| var args = new GuildPruneParams() { Days = days }; | var args = new GuildPruneParams() { Days = days }; | ||||
| @@ -1,6 +1,5 @@ | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Linq; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using MessageModel = Discord.API.Message; | using MessageModel = Discord.API.Message; | ||||
| using Model = Discord.API.Channel; | using Model = Discord.API.Channel; | ||||
| @@ -26,8 +25,6 @@ namespace Discord | |||||
| public override Task<IUser> GetUserAsync(ulong id) => Task.FromResult<IUser>(GetUser(id)); | public override Task<IUser> GetUserAsync(ulong id) => Task.FromResult<IUser>(GetUser(id)); | ||||
| public override Task<IReadOnlyCollection<IUser>> GetUsersAsync() => Task.FromResult<IReadOnlyCollection<IUser>>(Members); | public override Task<IReadOnlyCollection<IUser>> GetUsersAsync() => Task.FromResult<IReadOnlyCollection<IUser>>(Members); | ||||
| public override Task<IReadOnlyCollection<IUser>> GetUsersAsync(int limit, int offset) | |||||
| => Task.FromResult<IReadOnlyCollection<IUser>>(Members.Skip(offset).Take(limit).ToImmutableArray()); | |||||
| public ICachedUser GetUser(ulong id) | public ICachedUser GetUser(ulong id) | ||||
| { | { | ||||
| var currentUser = Discord.CurrentUser; | var currentUser = Discord.CurrentUser; | ||||
| @@ -143,9 +143,6 @@ namespace Discord | |||||
| => Task.FromResult<IGuildUser>(CurrentUser); | => Task.FromResult<IGuildUser>(CurrentUser); | ||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync() | public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync() | ||||
| => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members); | => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members); | ||||
| //TODO: Is there a better way of exposing pagination? | |||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset) | |||||
| => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members.OrderBy(x => x.Id).Skip(offset).Take(limit).ToImmutableArray()); | |||||
| public CachedGuildUser AddUser(MemberModel model, DataStore dataStore, ConcurrentDictionary<ulong, CachedGuildUser> members = null) | public CachedGuildUser AddUser(MemberModel model, DataStore dataStore, ConcurrentDictionary<ulong, CachedGuildUser> members = null) | ||||
| { | { | ||||
| members = members ?? _members; | members = members ?? _members; | ||||
| @@ -28,8 +28,6 @@ namespace Discord | |||||
| public override Task<IGuildUser> GetUserAsync(ulong id) => Task.FromResult<IGuildUser>(GetUser(id)); | public override Task<IGuildUser> GetUserAsync(ulong id) => Task.FromResult<IGuildUser>(GetUser(id)); | ||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync() => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members); | public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync() => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members); | ||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset) | |||||
| => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members.Skip(offset).Take(limit).ToImmutableArray()); | |||||
| public CachedGuildUser GetUser(ulong id, bool skipCheck = false) | public CachedGuildUser GetUser(ulong id, bool skipCheck = false) | ||||
| { | { | ||||
| var user = Guild.GetUser(id); | var user = Guild.GetUser(id); | ||||
| @@ -23,8 +23,6 @@ namespace Discord | |||||
| => Task.FromResult(GetUser(id)); | => Task.FromResult(GetUser(id)); | ||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync() | public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync() | ||||
| => Task.FromResult(Members); | => Task.FromResult(Members); | ||||
| public override Task<IReadOnlyCollection<IGuildUser>> GetUsersAsync(int limit, int offset) | |||||
| => Task.FromResult<IReadOnlyCollection<IGuildUser>>(Members.OrderBy(x => x.Id).Skip(offset).Take(limit).ToImmutableArray()); | |||||
| public IGuildUser GetUser(ulong id) | public IGuildUser GetUser(ulong id) | ||||
| { | { | ||||
| var user = Guild.GetUser(id); | var user = Guild.GetUser(id); | ||||