[Feature] Thread user member & thread members pagination (#2580)

* initial commit

* return & update old method

* mark old method as obsolete
This commit is contained in:
Misha133
2023-02-09 14:37:26 +03:00
committed by GitHub
parent 75f3c91f9a
commit b085621ca6
9 changed files with 96 additions and 23 deletions

View File

@@ -16,5 +16,8 @@ namespace Discord.API
[JsonProperty("flags")]
public int Flags { get; set; } // No enum type (yet?)
[JsonProperty("member")]
public Optional<GuildMember> GuildMember { get; set; }
}
}

View File

@@ -563,16 +563,23 @@ namespace Discord.API
await SendAsync("DELETE", () => $"channels/{channelId}/thread-members/{userId}", bucket, options: options).ConfigureAwait(false);
}
public async Task<ThreadMember[]> ListThreadMembersAsync(ulong channelId, RequestOptions options = null)
public async Task<ThreadMember[]> ListThreadMembersAsync(ulong channelId, ulong? after = null, int? limit = null, RequestOptions options = null)
{
Preconditions.NotEqual(channelId, 0, nameof(channelId));
var query = "?with_member=true";
if (limit.HasValue)
query += $"&limit={limit}";
if (after.HasValue)
query += $"&after={after}";
options = RequestOptions.CreateOrClone(options);
var bucket = new BucketIds(channelId: channelId);
return await SendAsync<ThreadMember[]>("GET", () => $"channels/{channelId}/thread-members", bucket, options: options).ConfigureAwait(false);
return await SendAsync<ThreadMember[]>("GET", () => $"channels/{channelId}/thread-members{query}", bucket, options: options).ConfigureAwait(false);
}
public async Task<ThreadMember> GetThreadMemberAsync(ulong channelId, ulong userId, RequestOptions options = null)
@@ -583,8 +590,9 @@ namespace Discord.API
options = RequestOptions.CreateOrClone(options);
var bucket = new BucketIds(channelId: channelId);
var query = "?with_member=true";
return await SendAsync<ThreadMember>("GET", () => $"channels/{channelId}/thread-members/{userId}", bucket, options: options).ConfigureAwait(false);
return await SendAsync<ThreadMember>("GET", () => $"channels/{channelId}/thread-members/{userId}{query}", bucket, options: options).ConfigureAwait(false);
}
public async Task<ChannelThreads> GetActiveThreadsAsync(ulong guildId, RequestOptions options = null)
@@ -2524,7 +2532,7 @@ namespace Discord.API
=> await SendAsync<RoleConnectionMetadata[]>("GET", () => $"applications/{CurrentApplicationId}/role-connections/metadata", new BucketIds(), options: options).ConfigureAwait(false);
public async Task<RoleConnectionMetadata[]> UpdateApplicationRoleConnectionMetadataRecordsAsync(RoleConnectionMetadata[] roleConnections, RequestOptions options = null)
=> await SendJsonAsync <RoleConnectionMetadata[]>("PUT", () => $"applications/{CurrentApplicationId}/role-connections/metadata", roleConnections, new BucketIds(), options: options).ConfigureAwait(false);
=> await SendJsonAsync<RoleConnectionMetadata[]>("PUT", () => $"applications/{CurrentApplicationId}/role-connections/metadata", roleConnections, new BucketIds(), options: options).ConfigureAwait(false);
public async Task<RoleConnection> GetUserApplicationRoleConnectionAsync(ulong applicationId, RequestOptions options = null)
=> await SendAsync<RoleConnection>("GET", () => $"users/@me/applications/{applicationId}/role-connection", new BucketIds(), options: options);

View File

@@ -101,6 +101,17 @@ namespace Discord.Rest
public new Task<RestThreadUser> GetUserAsync(ulong userId, RequestOptions options = null)
=> ThreadHelper.GetUserAsync(userId, this, Discord, options);
/// <summary>
/// Gets a collection of users within this thread.
/// </summary>
/// <param name="limit">Sets the limit of the user count for each request. 100 by default.</param>
/// <returns>
/// A task that represents the asynchronous get operation. The task result contains a collection of thread
/// users found within this thread channel.
/// </returns>
public IAsyncEnumerable<IReadOnlyCollection<RestThreadUser>> GetThreadUsersAsync(int limit = DiscordConfig.MaxThreadMembersPerBatch, RequestOptions options = null)
=> ThreadHelper.GetUsersAsync(this, Discord, limit, null, options);
/// <summary>
/// Gets a collection of users within this thread.
/// </summary>
@@ -109,8 +120,9 @@ namespace Discord.Rest
/// A task representing the asynchronous get operation. The task returns a
/// <see cref="IReadOnlyCollection{T}"/> of <see cref="RestThreadUser"/>'s.
/// </returns>
[Obsolete("Please use GetThreadUsersAsync instead of this. Will be removed in next major version.", false)]
public new async Task<IReadOnlyCollection<RestThreadUser>> GetUsersAsync(RequestOptions options = null)
=> (await ThreadHelper.GetUsersAsync(this, Discord, options).ConfigureAwait(false)).ToImmutableArray();
=> (await GetThreadUsersAsync(options: options).FlattenAsync()).ToImmutableArray();
/// <inheritdoc/>
public override async Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null)

View File

@@ -85,11 +85,27 @@ namespace Discord.Rest
return result.Threads.Select(x => RestThreadChannel.Create(client, channel.Guild, x)).ToImmutableArray();
}
public static async Task<RestThreadUser[]> GetUsersAsync(IThreadChannel channel, BaseDiscordClient client, RequestOptions options = null)
public static IAsyncEnumerable<IReadOnlyCollection<RestThreadUser>> GetUsersAsync(IThreadChannel channel, BaseDiscordClient client, int limit = DiscordConfig.MaxThreadMembersPerBatch, ulong? afterId = null, RequestOptions options = null)
{
var users = await client.ApiClient.ListThreadMembersAsync(channel.Id, options);
return users.Select(x => RestThreadUser.Create(client, channel.Guild, x, channel)).ToArray();
return new PagedAsyncEnumerable<RestThreadUser>(
limit,
async (info, ct) =>
{
if (info.Position != null)
afterId = info.Position.Value;
var users = await client.ApiClient.ListThreadMembersAsync(channel.Id, afterId, limit, options);
return users.Select(x => RestThreadUser.Create(client, channel.Guild, x, channel)).ToImmutableArray();
},
nextPage: (info, lastPage) =>
{
if (lastPage.Count != limit)
return false;
info.Position = lastPage.Max(x => x.Id);
return true;
},
start: afterId,
count: limit
);
}
public static async Task<RestThreadUser> GetUserAsync(ulong userId, IThreadChannel channel, BaseDiscordClient client, RequestOptions options = null)

View File

@@ -18,6 +18,9 @@ namespace Discord.Rest
/// <inheritdoc/>
public IGuild Guild { get; }
/// <inheritdoc cref="IThreadUser.GuildUser"/>
public RestGuildUser GuildUser { get; private set; }
/// <inheritdoc/>
public string Mention => MentionUtils.MentionUser(Id);
@@ -38,8 +41,13 @@ namespace Discord.Rest
internal void Update(Model model)
{
ThreadJoinedAt = model.JoinTimestamp;
if(model.GuildMember.IsSpecified)
GuildUser = RestGuildUser.Create(Discord, Guild, model.GuildMember.Value);
}
/// <inheritdoc />
IGuildUser IThreadUser.GuildUser => GuildUser;
/// <summary>
/// Gets the guild user for this thread user.
/// </summary>