Skip to content

Commit

Permalink
Fix UserUnbanned not working
Browse files Browse the repository at this point in the history
  • Loading branch information
gehongyan committed Nov 20, 2022
1 parent bb81aa0 commit b3d5080
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 202 deletions.
254 changes: 67 additions & 187 deletions samples/Kook.Net.Samples.SimpleBot/Program.cs

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/Kook.Net.Core/Entities/Guilds/IGuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ public interface IGuild : IEntity<ulong>
/// </returns>
Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetBoostSubscriptionsAsync(RequestOptions options = null);

/// <summary>
/// Gets subscriptions which are not expired for this guild.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous retrieval operation. The task result contains
/// a collection of <see cref="BoostSubscriptionMetadata"/> which are not expired,
/// each representing the subscriptions information.
/// </returns>
Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetActiveBoostSubscriptionsAsync(RequestOptions options = null);

#endregion

#region Guild Bans
Expand Down
6 changes: 3 additions & 3 deletions src/Kook.Net.Rest/BaseKookClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ namespace Kook.Rest;
public abstract class BaseKookClient : IKookClient
{
#region BaseKookClient
public event Func<LogMessage, Task> Log { add { _logEvent.Add(value); } remove { _logEvent.Remove(value); } }
public event Func<LogMessage, Task> Log { add => _logEvent.Add(value); remove => _logEvent.Remove(value); }
internal readonly AsyncEvent<Func<LogMessage, Task>> _logEvent = new AsyncEvent<Func<LogMessage, Task>>();
public event Func<Task> LoggedIn { add { _loggedInEvent.Add(value); } remove { _loggedInEvent.Remove(value); } }
public event Func<Task> LoggedIn { add => _loggedInEvent.Add(value); remove => _loggedInEvent.Remove(value); }
private readonly AsyncEvent<Func<Task>> _loggedInEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> LoggedOut { add { _loggedOutEvent.Add(value); } remove { _loggedOutEvent.Remove(value); } }
public event Func<Task> LoggedOut { add => _loggedOutEvent.Add(value); remove => _loggedOutEvent.Remove(value); }
private readonly AsyncEvent<Func<Task>> _loggedOutEvent = new AsyncEvent<Func<Task>>();

internal readonly Logger _restLogger;
Expand Down
12 changes: 12 additions & 0 deletions src/Kook.Net.Rest/Entities/Guilds/GuildHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ public static async Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSub
.ToImmutableArray() as IReadOnlyCollection<BoostSubscriptionMetadata>);
}

public static async Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetActiveBoostSubscriptionsAsync(
IGuild guild, BaseKookClient client, RequestOptions options)
{
IEnumerable<BoostSubscription> subscriptions = await client.ApiClient
.GetGuildBoostSubscriptionsAsync(guild.Id, since: DateTimeOffset.Now, options: options).FlattenAsync();
return subscriptions.GroupBy(x => x.UserId)
.ToImmutableDictionary(x => RestUser.Create(client, x.First().User) as IUser,
x => x.GroupBy(y => (y.StartTime, y.EndTime))
.Select(y => new BoostSubscriptionMetadata(y.Key.StartTime, y.Key.EndTime, y.Count()))
.ToImmutableArray() as IReadOnlyCollection<BoostSubscriptionMetadata>);
}

public static int GetMaxBitrate(IGuild guild)
{
var tierFactor = guild.BoostLevel switch
Expand Down
3 changes: 3 additions & 0 deletions src/Kook.Net.Rest/Entities/Guilds/RestGuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ public Task LeaveAsync(RequestOptions options = null)
/// <inheritdoc />
public Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetBoostSubscriptionsAsync(RequestOptions options = null)
=> GuildHelper.GetBoostSubscriptionsAsync(this, Kook, options);
/// <inheritdoc />
public Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetActiveBoostSubscriptionsAsync(RequestOptions options = null)
=> GuildHelper.GetActiveBoostSubscriptionsAsync(this, Kook, options);

#endregion

Expand Down
6 changes: 5 additions & 1 deletion src/Kook.Net.Rest/KookRestApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,13 +439,17 @@ public async Task RemoveGuildMuteDeafAsync(CreateOrRemoveGuildMuteDeafParams arg
}

public IAsyncEnumerable<IReadOnlyCollection<BoostSubscription>> GetGuildBoostSubscriptionsAsync(ulong guildId,
DateTimeOffset? since = null, DateTimeOffset? until = null,
int limit = KookConfig.MaxUsersPerBatch, int fromPage = 1, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
string query = $"guild_id={guildId}";
if (since.HasValue) query += $"&start_time={since.Value.ToUnixTimeMilliseconds()}";
if (until.HasValue) query += $"&end_time={until.Value.ToUnixTimeMilliseconds()}";
options = RequestOptions.CreateOrClone(options);

var ids = new BucketIds(guildId: guildId);
return SendPagedAsync<BoostSubscription>(HttpMethod.Get, (pageSize, page) => $"guild-boost/history?guild_id={guildId}&page_size={pageSize}&page={page}",
return SendPagedAsync<BoostSubscription>(HttpMethod.Get, (pageSize, page) => $"guild-boost/history?{query}&page_size={pageSize}&page={page}",
ids, clientBucket: ClientBucketType.SendEdit, pageMeta: new PageMeta(pageSize: 50), options: options);
}

Expand Down
28 changes: 21 additions & 7 deletions src/Kook.Net.Rest/Net/DefaultRestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ internal sealed class DefaultRestClient : IRestClient, IDisposable

private readonly HttpClient _client;
private readonly string _baseUrl;
private readonly JsonSerializerOptions _serializerOptions;
private CancellationToken _cancelToken;
private bool _isDisposed;

#if DEBUG_REST
private readonly JsonSerializerOptions _serializerOptions;
private int _requestId;
private readonly SemaphoreSlim _requestIdLock = new SemaphoreSlim(1, 1);
#endif

public DefaultRestClient(string baseUrl, bool useProxy = false)
{
_baseUrl = baseUrl;
Expand All @@ -44,11 +49,14 @@ public DefaultRestClient(string baseUrl, bool useProxy = false)
SetHeader("accept-encoding", "gzip, deflate");

_cancelToken = CancellationToken.None;

#if DEBUG_REST
_serializerOptions = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
NumberHandling = JsonNumberHandling.AllowReadingFromString
};
#endif
}
private void Dispose(bool disposing)
{
Expand Down Expand Up @@ -164,12 +172,18 @@ public async Task<RestResponse> SendAsync(HttpMethod method, string endpoint, IR

private async Task<RestResponse> SendInternalAsync(HttpRequestMessage request, CancellationToken cancelToken)
{
#if DEBUG_REST
await _requestIdLock.WaitAsync(1, cancelToken);
_requestId++;
int requestId = _requestId;
_requestIdLock.Release();
#endif
using (var cancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_cancelToken, cancelToken))
{
#if DEBUG_REST
Debug.WriteLine($"[REST] {request.Method} {request.RequestUri} {request.Content?.Headers.ContentType?.MediaType}");
if (request.Content?.Headers.ContentType?.MediaType == "application/json")
Debug.WriteLine($"[REST] {await request.Content.ReadAsStringAsync().ConfigureAwait(false)}");
Debug.WriteLine($"[REST] [{requestId}] {request.Method} {request.RequestUri} {request.Content?.Headers.ContentType?.MediaType}");
if (request.Content?.Headers.ContentType?.MediaType == "application/json")
Debug.WriteLine($"[REST] {await request.Content.ReadAsStringAsync().ConfigureAwait(false)}");
#endif
cancelToken = cancelTokenSource.Token;
HttpResponseMessage response = await _client.SendAsync(request, cancelToken).ConfigureAwait(false);
Expand All @@ -178,11 +192,11 @@ private async Task<RestResponse> SendInternalAsync(HttpRequestMessage request, C
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

#if DEBUG_REST
Debug.WriteLine($"[REST] {response.StatusCode} {response.ReasonPhrase}");
Debug.WriteLine($"[REST] [{requestId}] {response.StatusCode} {response.ReasonPhrase}");
if (response.Content?.Headers.ContentType?.MediaType == "application/json")
Debug.WriteLine($"[REST] {await response.Content.ReadAsStringAsync().ConfigureAwait(false)}");
Debug.WriteLine($"[REST] [{requestId}] {await response.Content.ReadAsStringAsync().ConfigureAwait(false)}");
#endif
return new RestResponse(response.StatusCode, headers, stream, response.Content.Headers.ContentType);
return new RestResponse(response.StatusCode, headers, stream, response.Content?.Headers.ContentType);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Kook.Net.Rest/Net/Queue/RequestQueueBucket.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using System.Net.Mime;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
Expand Down
13 changes: 11 additions & 2 deletions src/Kook.Net.WebSocket/BaseSocketClient.Event.cs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ public event Func<SocketGuild, SocketUser, DateTimeOffset, Task> UserLeft
/// The guild where the banning action takes place is passed in the event handler parameter as
/// <see cref="SocketGuild"/>.
/// </para>
/// <para>
/// The banning actions are usually taken with kicking, and the kicking action takes place
/// before the banning action according to the KOOK gateway events. Therefore, the banned users
/// parameter is usually a collection of <see cref="SocketUnknownUser"/>.
/// </para>
/// </remarks>
public event Func<IReadOnlyCollection<SocketUser>, SocketUser, SocketGuild, Task> UserBanned
{
Expand Down Expand Up @@ -441,12 +446,16 @@ public event Func<IReadOnlyCollection<SocketUser>, SocketUser, SocketGuild, Task
/// <see cref="SocketGuild"/>.
/// </para>
/// </remarks>
public event Func<SocketUser, SocketGuild, Task> UserUnbanned
/// <para>
/// The unbanning actions are usually taken to users that are not in the guild. Therefore, the unbanned users
/// parameter is usually a collection of <see cref="SocketUnknownUser"/>.
/// </para>
public event Func<IReadOnlyCollection<SocketUser>, SocketUser, SocketGuild, Task> UserUnbanned
{
add => _userUnbannedEvent.Add(value);
remove => _userUnbannedEvent.Remove(value);
}
internal readonly AsyncEvent<Func<SocketUser, SocketGuild, Task>> _userUnbannedEvent = new AsyncEvent<Func<SocketUser, SocketGuild, Task>>();
internal readonly AsyncEvent<Func<IReadOnlyCollection<SocketUser>, SocketUser, SocketGuild, Task>> _userUnbannedEvent = new AsyncEvent<Func<IReadOnlyCollection<SocketUser>, SocketUser, SocketGuild, Task>>();
/// <summary> Fired when a user is updated. </summary>
public event Func<SocketUser, SocketUser, Task> UserUpdated
{
Expand Down
2 changes: 2 additions & 0 deletions src/Kook.Net.WebSocket/Entities/Guilds/SocketGuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ public Task LeaveAsync(RequestOptions options = null)
/// <inheritdoc />
public Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetBoostSubscriptionsAsync(RequestOptions options = null)
=> SocketGuildHelper.GetBoostSubscriptionsAsync(this, Kook, options);
public Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetActiveBoostSubscriptionsAsync(RequestOptions options = null)
=> SocketGuildHelper.GetActiveBoostSubscriptionsAsync(this, Kook, options);

#endregion

Expand Down
12 changes: 12 additions & 0 deletions src/Kook.Net.WebSocket/Entities/Guilds/SocketGuildHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,16 @@ public static async Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSub
.ToImmutableArray() as IReadOnlyCollection<BoostSubscriptionMetadata>);
}

public static async Task<ImmutableDictionary<IUser, IReadOnlyCollection<BoostSubscriptionMetadata>>> GetActiveBoostSubscriptionsAsync(
SocketGuild guild, BaseSocketClient client, RequestOptions options)
{
IEnumerable<BoostSubscription> subscriptions = await client.ApiClient
.GetGuildBoostSubscriptionsAsync(guild.Id, since: DateTimeOffset.Now, options: options).FlattenAsync();
return subscriptions.GroupBy(x => x.UserId)
.ToImmutableDictionary(x => guild.GetUser(x.Key) ?? client.GetUser(x.Key) ?? RestUser.Create(client, x.First().User) as IUser,
x => x.GroupBy(y => (y.StartTime, y.EndTime))
.Select(y => new BoostSubscriptionMetadata(y.Key.StartTime, y.Key.EndTime, y.Count()))
.ToImmutableArray() as IReadOnlyCollection<BoostSubscriptionMetadata>);
}

}
4 changes: 2 additions & 2 deletions src/Kook.Net.WebSocket/KookSocketClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,10 +1260,10 @@ private async Task ProcessMessageAsync(GatewaySocketFrameType gatewaySocketFrame
{
SocketUser operatorUser = guild.GetUser(data.OperatorUserId)
?? (SocketUser) SocketUnknownUser.Create(this, State, data.OperatorUserId);
var bannedUsers = data.UserIds.Select(id => guild.GetUser(id)
var unbannedUsers = data.UserIds.Select(id => guild.GetUser(id)
?? (SocketUser) SocketUnknownUser.Create(this, State, id))
.ToReadOnlyCollection(() => data.UserIds.Length);
await TimedInvokeAsync(_userBannedEvent, nameof(UserBanned), bannedUsers, operatorUser, guild).ConfigureAwait(false);
await TimedInvokeAsync(_userUnbannedEvent, nameof(UserUnbanned), unbannedUsers, operatorUser, guild).ConfigureAwait(false);
}
else
{
Expand Down

0 comments on commit b3d5080

Please sign in to comment.