From 150014fdc59c8d433e78e8bead4531ad4957985b Mon Sep 17 00:00:00 2001 From: AnotherZane Date: Sun, 28 Jul 2024 17:03:06 +0530 Subject: [PATCH 1/3] Implemented guild bulk bans --- .../Limits/Entities/Discord.Limits.Guild.cs | 10 +++ .../Models/GuildBulkBanJsonModel.cs | 12 ++++ .../Json/CreateBanJsonRestRequestContent.cs | 5 +- .../Json/CreateBansJsonRestRequestContent.cs | 19 ++++++ .../Methods/RestApiClientExtensions.Guild.cs | 8 +++ .../Requests/Routing/Default/Route.Static.cs | 2 + .../Entities/Core/Guild/IBulkBanResponse.cs | 10 +++ .../Guild/TransientBulkBanResponse.cs | 16 +++++ .../Entity/RestEntityExtensions.Guild.cs | 26 ++++++++ .../Extensions/RestClientExtensions.Guild.cs | 62 ++++++++++++++++++- .../CreateBansPagedEnumerator.cs | 43 +++++++++++++ 11 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 src/Disqord.Core/Models/GuildBulkBanJsonModel.cs create mode 100644 src/Disqord.Rest.Api/Content/Json/CreateBansJsonRestRequestContent.cs create mode 100644 src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs create mode 100644 src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs create mode 100644 src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs diff --git a/src/Disqord.Core/Discord/Limits/Entities/Discord.Limits.Guild.cs b/src/Disqord.Core/Discord/Limits/Entities/Discord.Limits.Guild.cs index f981f192e..1a642a08b 100644 --- a/src/Disqord.Core/Discord/Limits/Entities/Discord.Limits.Guild.cs +++ b/src/Disqord.Core/Discord/Limits/Entities/Discord.Limits.Guild.cs @@ -9,6 +9,16 @@ public static partial class Limits /// public static class Guild { + /// + /// The maximum seconds in the past to delete messages for when a user is banned. + /// + public const int MaxDeleteMessageSeconds = 604800; + + /// + /// The maximum amount of users that can be bulk banned. + /// + public const int MaxBulkBanUsersAmount = 200; + /// /// Represents limits for guild events. /// diff --git a/src/Disqord.Core/Models/GuildBulkBanJsonModel.cs b/src/Disqord.Core/Models/GuildBulkBanJsonModel.cs new file mode 100644 index 000000000..943be157c --- /dev/null +++ b/src/Disqord.Core/Models/GuildBulkBanJsonModel.cs @@ -0,0 +1,12 @@ +using Disqord.Serialization.Json; + +namespace Disqord.Models; + +public class GuildBulkBanJsonModel : JsonModel +{ + [JsonProperty("banned_users")] + public Snowflake[] BannedUsers = null!; + + [JsonProperty("failed_users")] + public Snowflake[] FailedUsers = null!; +} diff --git a/src/Disqord.Rest.Api/Content/Json/CreateBanJsonRestRequestContent.cs b/src/Disqord.Rest.Api/Content/Json/CreateBanJsonRestRequestContent.cs index 8b57ed0f2..b2e4cdcc6 100644 --- a/src/Disqord.Rest.Api/Content/Json/CreateBanJsonRestRequestContent.cs +++ b/src/Disqord.Rest.Api/Content/Json/CreateBanJsonRestRequestContent.cs @@ -5,14 +5,15 @@ namespace Disqord.Rest.Api; public class CreateBanJsonRestRequestContent : JsonModelRestRequestContent { - [JsonProperty("delete_message_days")] - public Optional DeleteMessageDays; + [JsonProperty("delete_message_seconds")] + public Optional DeleteMessageSeconds; [JsonProperty("reason")] public Optional Reason; protected override void OnValidate() { + OptionalGuard.CheckValue(DeleteMessageSeconds, seconds => Guard.IsBetweenOrEqualTo(seconds, 0, Discord.Limits.Guild.MaxDeleteMessageSeconds)); OptionalGuard.CheckValue(Reason, static reason => Guard.HasSizeLessThanOrEqualTo(reason, Discord.Limits.Rest.MaxAuditLogReasonLength)); } } diff --git a/src/Disqord.Rest.Api/Content/Json/CreateBansJsonRestRequestContent.cs b/src/Disqord.Rest.Api/Content/Json/CreateBansJsonRestRequestContent.cs new file mode 100644 index 000000000..04195cead --- /dev/null +++ b/src/Disqord.Rest.Api/Content/Json/CreateBansJsonRestRequestContent.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Rest.Api; + +public class CreateBansJsonRestRequestContent : CreateBanJsonRestRequestContent +{ + [JsonProperty("user_ids")] + public IList UserIds = null!; + + protected override void OnValidate() + { + base.OnValidate(); + + Guard.IsNotNull(UserIds); + Guard.HasSizeLessThanOrEqualTo(UserIds, Discord.Limits.Guild.MaxBulkBanUsersAmount); + } +} diff --git a/src/Disqord.Rest.Api/Methods/RestApiClientExtensions.Guild.cs b/src/Disqord.Rest.Api/Methods/RestApiClientExtensions.Guild.cs index c555988f5..ee67c63b2 100644 --- a/src/Disqord.Rest.Api/Methods/RestApiClientExtensions.Guild.cs +++ b/src/Disqord.Rest.Api/Methods/RestApiClientExtensions.Guild.cs @@ -245,6 +245,14 @@ public static Task DeleteBanAsync(this IRestApiClient client, return client.ExecuteAsync(route, null, options, cancellationToken); } + public static Task CreateBansAsync(this IRestApiClient client, + Snowflake guildId, CreateBanJsonRestRequestContent content, + IRestRequestOptions? options = null, CancellationToken cancellationToken = default) + { + var route = Format(Route.Guild.CreateBans, guildId); + return client.ExecuteAsync(route, content, options, cancellationToken); + } + public static Task FetchRolesAsync(this IRestApiClient client, Snowflake guildId, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) diff --git a/src/Disqord.Rest.Api/Requests/Routing/Default/Route.Static.cs b/src/Disqord.Rest.Api/Requests/Routing/Default/Route.Static.cs index 81ba04d41..f55f1e53f 100644 --- a/src/Disqord.Rest.Api/Requests/Routing/Default/Route.Static.cs +++ b/src/Disqord.Rest.Api/Requests/Routing/Default/Route.Static.cs @@ -188,6 +188,8 @@ public static class Guild public static readonly Route DeleteBan = Delete("guilds/{0:guild_id}/bans/{1:user_id}"); + public static readonly Route CreateBans = Post("guilds/{0:guild_id}/bulk-ban"); + public static readonly Route GetRoles = Get("guilds/{0:guild_id}/roles"); public static readonly Route CreateRole = Post("guilds/{0:guild_id}/roles"); diff --git a/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs b/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs new file mode 100644 index 000000000..69cb9f20b --- /dev/null +++ b/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Disqord.Rest.Entities.Core.Guild; + +public interface IBulkBanResponse +{ + IReadOnlyList BannedUserIds { get; } + + IReadOnlyList FailedUserIds { get; } +} diff --git a/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs b/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs new file mode 100644 index 000000000..3efd6a70f --- /dev/null +++ b/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Disqord.Models; +using Disqord.Rest.Entities.Core.Guild; + +namespace Disqord.Rest; + +public class TransientBulkBanResponse : TransientEntity, IBulkBanResponse +{ + public IReadOnlyList BannedUserIds => Model.BannedUsers; + + public IReadOnlyList FailedUserIds => Model.FailedUsers; + + public TransientBulkBanResponse(GuildBulkBanJsonModel model) + : base(model) + { } +} diff --git a/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs b/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs index 436749780..3c817474f 100644 --- a/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs +++ b/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Disqord.AuditLogs; +using Disqord.Rest.Entities.Core.Guild; using Disqord.Rest.Pagination; namespace Disqord.Rest; @@ -235,6 +236,7 @@ public static Task> FetchBansAsync(this IGuild guild, return client.FetchBanAsync(guild.Id, userId, options, cancellationToken); } + [Obsolete("Parameter deleteMessageDays is deprecated, use a TimeSpan instead.")] public static Task CreateBanAsync(this IGuild guild, Snowflake userId, string? reason = null, int? deleteMessageDays = null, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) @@ -243,6 +245,14 @@ public static Task CreateBanAsync(this IGuild guild, return client.CreateBanAsync(guild.Id, userId, reason, deleteMessageDays, options, cancellationToken); } + public static Task CreateBanAsync(this IGuild guild, + Snowflake userId, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null, CancellationToken cancellationToken = default) + { + var client = guild.GetRestClient(); + return client.CreateBanAsync(guild.Id, userId, reason, deleteMessageTime, options, cancellationToken); + } + public static Task DeleteBanAsync(this IGuild guild, Snowflake userId, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) @@ -251,6 +261,22 @@ public static Task DeleteBanAsync(this IGuild guild, return client.DeleteBanAsync(guild.Id, userId, options, cancellationToken); } + public static IPagedEnumerable EnumerateBanCreation(this IGuild guild, + IEnumerable userIds, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null) + { + var client = guild.GetRestClient(); + return client.EnumerateBanCreation(guild.Id, userIds, reason, deleteMessageTime, options); + } + + public static Task CreateBansAsync(this IGuild guild, + IEnumerable userIds, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null, CancellationToken cancellationToken = default) + { + var client = guild.GetRestClient(); + return client.CreateBansAsync(guild.Id, userIds, reason, deleteMessageTime, options, cancellationToken); + } + public static Task> FetchRolesAsync(this IGuild guild, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) { diff --git a/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs b/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs index 3f3617503..12b70484d 100644 --- a/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs +++ b/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs @@ -1,13 +1,16 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Disqord.Http; using Disqord.Models; using Disqord.Rest.Api; +using Disqord.Rest.Entities.Core.Guild; using Disqord.Rest.Pagination; using Qommon; +using Qommon.Collections; using Qommon.Collections.ReadOnly; namespace Disqord.Rest; @@ -443,13 +446,23 @@ internal static async Task> InternalFetchBansAsync(this IRes } } + [Obsolete("Parameter deleteMessageDays is deprecated, use a TimeSpan instead.")] public static Task CreateBanAsync(this IRestClient client, Snowflake guildId, Snowflake userId, string? reason = null, int? deleteMessageDays = null, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) + { + return client.CreateBanAsync(guildId, userId, reason, + deleteMessageDays.HasValue ? TimeSpan.FromDays(deleteMessageDays.Value) : null, + options, cancellationToken); + } + + public static Task CreateBanAsync(this IRestClient client, + Snowflake guildId, Snowflake userId, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null, CancellationToken cancellationToken = default) { var content = new CreateBanJsonRestRequestContent { - DeleteMessageDays = Optional.FromNullable(deleteMessageDays), + DeleteMessageSeconds = Optional.Convert(Optional.FromNullable(deleteMessageTime), time => (int) time.TotalSeconds), Reason = Optional.FromNullable(reason) }; @@ -463,6 +476,53 @@ public static Task DeleteBanAsync(this IRestClient client, return client.ApiClient.DeleteBanAsync(guildId, userId, options, cancellationToken); } + public static IPagedEnumerable EnumerateBanCreation(this IRestClient client, + Snowflake guildId, IEnumerable userIds, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null) + { + Guard.IsNotNull(userIds); + + return PagedEnumerable.Create((state, cancellationToken) => + { + var (client, guildId, userIds, reason, deleteMessageTime, options) = state; + return new CreateBansPagedEnumerator(client, guildId, userIds, reason, deleteMessageTime, options, cancellationToken); + }, (client, guildId, userIds.ToArray(), reason, deleteMessageTime, options)); + } + + public static async Task> CreateBansAsync(this IRestClient client, + Snowflake guildId, IEnumerable userIds, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null, CancellationToken cancellationToken = default) + { + Guard.IsNotNull(userIds); + + var users = userIds.ToArray(); + Guard.IsNotEmpty(users); + + if (users.Length <= Discord.Limits.Guild.MaxBulkBanUsersAmount) + { + var response = await client.InternalCreateBansAsync(guildId, users, reason, deleteMessageTime, options, cancellationToken).ConfigureAwait(false); + return new[] { response }; + } + + var enumerable = client.EnumerateBanCreation(guildId, users, reason, deleteMessageTime, options); + return await enumerable.FlattenAsync(cancellationToken); + } + + internal static async Task InternalCreateBansAsync(this IRestClient client, + Snowflake guildId, ArraySegment userIds, string? reason = null, TimeSpan? deleteMessageTime = null, + IRestRequestOptions? options = null, CancellationToken cancellationToken = default) + { + var content = new CreateBansJsonRestRequestContent + { + UserIds = userIds, + DeleteMessageSeconds = Optional.Convert(Optional.FromNullable(deleteMessageTime), time => (int) time.TotalSeconds), + Reason = Optional.FromNullable(reason) + }; + + var model = await client.ApiClient.CreateBansAsync(guildId, content, options, cancellationToken); + return new TransientBulkBanResponse(model);; + } + public static async Task> FetchRolesAsync(this IRestClient client, Snowflake guildId, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) diff --git a/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs b/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs new file mode 100644 index 000000000..c78f957d4 --- /dev/null +++ b/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Disqord.Rest.Entities.Core.Guild; + +namespace Disqord.Rest; + +public class CreateBansPagedEnumerator : PagedEnumerator +{ + public override int PageSize => Discord.Limits.Guild.MaxBulkBanUsersAmount; + + private readonly Snowflake _guildId; + private readonly Snowflake[] _userIds; + private readonly string? _reason; + private readonly TimeSpan? _deleteMessagesTime = null; + + private int _offset; + + public CreateBansPagedEnumerator( + IRestClient client, + Snowflake guildId, Snowflake[] userIds, string? reason = null, TimeSpan? deleteMessagesTime = null, + IRestRequestOptions? options = null, + CancellationToken cancellationToken = default) + : base(client, userIds.Length, options, cancellationToken) + { + _guildId = guildId; + _userIds = userIds; + _reason = reason; + _deleteMessagesTime = deleteMessagesTime; + } + + protected override async Task> NextPageAsync(IReadOnlyList? previousPage, IRestRequestOptions? options = null, + CancellationToken cancellationToken = default) + { + var amount = NextPageSize; + var segment = new ArraySegment(_userIds, _offset, amount); + _offset += amount; + var response = await Client.InternalCreateBansAsync(_guildId, segment, _reason, _deleteMessagesTime, options, + cancellationToken); + return new []{response}; + } +} From 73a8ed0753e29a6c06bc842b0c6f715d7492d23f Mon Sep 17 00:00:00 2001 From: AnotherZane Date: Sun, 28 Jul 2024 17:25:11 +0530 Subject: [PATCH 2/3] Fix namespace --- src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs | 2 +- .../Entities/Transient/Guild/TransientBulkBanResponse.cs | 1 - .../Extensions/Entity/RestEntityExtensions.Guild.cs | 1 - src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs | 3 --- .../Pagination/Implementation/CreateBansPagedEnumerator.cs | 1 - 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs b/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs index 69cb9f20b..092a4410e 100644 --- a/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs +++ b/src/Disqord.Rest/Entities/Core/Guild/IBulkBanResponse.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Disqord.Rest.Entities.Core.Guild; +namespace Disqord.Rest; public interface IBulkBanResponse { diff --git a/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs b/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs index 3efd6a70f..ba344cb59 100644 --- a/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs +++ b/src/Disqord.Rest/Entities/Transient/Guild/TransientBulkBanResponse.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Disqord.Models; -using Disqord.Rest.Entities.Core.Guild; namespace Disqord.Rest; diff --git a/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs b/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs index 3c817474f..749c16f8c 100644 --- a/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs +++ b/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs @@ -4,7 +4,6 @@ using System.Threading; using System.Threading.Tasks; using Disqord.AuditLogs; -using Disqord.Rest.Entities.Core.Guild; using Disqord.Rest.Pagination; namespace Disqord.Rest; diff --git a/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs b/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs index 12b70484d..2dbca7d19 100644 --- a/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs +++ b/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Disqord.Http; using Disqord.Models; using Disqord.Rest.Api; -using Disqord.Rest.Entities.Core.Guild; using Disqord.Rest.Pagination; using Qommon; -using Qommon.Collections; using Qommon.Collections.ReadOnly; namespace Disqord.Rest; diff --git a/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs b/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs index c78f957d4..8bfa712c3 100644 --- a/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs +++ b/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Disqord.Rest.Entities.Core.Guild; namespace Disqord.Rest; From 932d1888b30a3f2dc107adbf5b5f57737e900ada Mon Sep 17 00:00:00 2001 From: AnotherZane Date: Sun, 28 Jul 2024 20:29:22 +0530 Subject: [PATCH 3/3] Added CombinedBulkBanReponse --- .../Guild/CombinedBulkBanResponse.cs | 16 ++++++++++++++ .../Entity/RestEntityExtensions.Guild.cs | 2 +- .../Extensions/RestClientExtensions.Guild.cs | 8 +++---- .../CreateBansPagedEnumerator.cs | 4 +++- .../Requests/Pagination/PagedEnumerator`1.cs | 21 ++++++++++--------- 5 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 src/Disqord.Rest/Entities/Transient/Guild/CombinedBulkBanResponse.cs diff --git a/src/Disqord.Rest/Entities/Transient/Guild/CombinedBulkBanResponse.cs b/src/Disqord.Rest/Entities/Transient/Guild/CombinedBulkBanResponse.cs new file mode 100644 index 000000000..b61729b04 --- /dev/null +++ b/src/Disqord.Rest/Entities/Transient/Guild/CombinedBulkBanResponse.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Disqord.Rest; + +public class CombinedBulkBanResponse : IBulkBanResponse +{ + public IReadOnlyList BannedUserIds { get; } + public IReadOnlyList FailedUserIds { get; } + + public CombinedBulkBanResponse(IEnumerable responses) + { + BannedUserIds = responses.SelectMany(response => response.BannedUserIds).ToArray(); + FailedUserIds = responses.SelectMany(response => response.FailedUserIds).ToArray(); + } +} diff --git a/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs b/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs index 749c16f8c..475b6ba83 100644 --- a/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs +++ b/src/Disqord.Rest/Extensions/Entity/RestEntityExtensions.Guild.cs @@ -268,7 +268,7 @@ public static IPagedEnumerable EnumerateBanCreation(this IGuil return client.EnumerateBanCreation(guild.Id, userIds, reason, deleteMessageTime, options); } - public static Task CreateBansAsync(this IGuild guild, + public static Task CreateBansAsync(this IGuild guild, IEnumerable userIds, string? reason = null, TimeSpan? deleteMessageTime = null, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) { diff --git a/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs b/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs index 2dbca7d19..3506353d0 100644 --- a/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs +++ b/src/Disqord.Rest/Extensions/RestClientExtensions.Guild.cs @@ -486,7 +486,7 @@ public static IPagedEnumerable EnumerateBanCreation(this IRest }, (client, guildId, userIds.ToArray(), reason, deleteMessageTime, options)); } - public static async Task> CreateBansAsync(this IRestClient client, + public static async Task CreateBansAsync(this IRestClient client, Snowflake guildId, IEnumerable userIds, string? reason = null, TimeSpan? deleteMessageTime = null, IRestRequestOptions? options = null, CancellationToken cancellationToken = default) { @@ -497,12 +497,12 @@ public static async Task> CreateBansAsync(this I if (users.Length <= Discord.Limits.Guild.MaxBulkBanUsersAmount) { - var response = await client.InternalCreateBansAsync(guildId, users, reason, deleteMessageTime, options, cancellationToken).ConfigureAwait(false); - return new[] { response }; + return await client.InternalCreateBansAsync(guildId, users, reason, deleteMessageTime, options, cancellationToken).ConfigureAwait(false); } var enumerable = client.EnumerateBanCreation(guildId, users, reason, deleteMessageTime, options); - return await enumerable.FlattenAsync(cancellationToken); + var flattened = await enumerable.FlattenAsync(cancellationToken); + return new CombinedBulkBanResponse(flattened); } internal static async Task InternalCreateBansAsync(this IRestClient client, diff --git a/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs b/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs index 8bfa712c3..ee33c8b47 100644 --- a/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs +++ b/src/Disqord.Rest/Requests/Pagination/Implementation/CreateBansPagedEnumerator.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Qommon.Collections.ReadOnly; namespace Disqord.Rest; @@ -37,6 +39,6 @@ protected override async Task> NextPageAsync(IRe _offset += amount; var response = await Client.InternalCreateBansAsync(_guildId, segment, _reason, _deleteMessagesTime, options, cancellationToken); - return new []{response}; + return Enumerable.Repeat(response, PageSize).ToReadOnlyList(); } } diff --git a/src/Disqord.Rest/Requests/Pagination/PagedEnumerator`1.cs b/src/Disqord.Rest/Requests/Pagination/PagedEnumerator`1.cs index 397d44dcd..f59ceffc4 100644 --- a/src/Disqord.Rest/Requests/Pagination/PagedEnumerator`1.cs +++ b/src/Disqord.Rest/Requests/Pagination/PagedEnumerator`1.cs @@ -82,16 +82,17 @@ public async ValueTask MoveNextAsync(IRestRequestOptions? options = null) return false; } - if (current.Count < PageSize) - { - // If Discord returns less entities than the page size, - // it means there are no more entities beyond the ones we just received. - RemainingCount = 0; - } - else - { + // TODO: Rework paged enumerator + // if (current.Count < PageSize) + // { + // // If Discord returns less entities than the page size, + // // it means there are no more entities beyond the ones we just received. + // RemainingCount = 0; + // } + // else + // { RemainingCount -= current.Count; - } + // } return true; } @@ -99,4 +100,4 @@ public async ValueTask MoveNextAsync(IRestRequestOptions? options = null) /// public virtual ValueTask DisposeAsync() => default; -} \ No newline at end of file +}