Skip to content

Commit

Permalink
More socket message tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gehongyan committed May 7, 2024
1 parent 6caa01f commit 0c470bb
Show file tree
Hide file tree
Showing 12 changed files with 348 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ namespace Kook;
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class FileModule : IMediaModule, IEquatable<FileModule>, IEquatable<IModule>
{
internal FileModule(string source, string? title)
internal FileModule(string source, string? title, int? size = null)
{
Source = source;
Title = title;
Size = size;
}

/// <inheritdoc />
Expand All @@ -24,6 +25,11 @@ internal FileModule(string source, string? title)
/// <inheritdoc />
public string? Title { get; }

/// <summary>
/// The size of the file in bytes.
/// </summary>
public int? Size { get; }

private string DebuggerDisplay => $"{Type}: {Title}";

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Kook.Net.Core/Utils/UrlValidation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static bool ValidateKookAssetUrl(string url)
if (string.IsNullOrEmpty(url)) return false;

if (!Regex.IsMatch(url,
@"^https?:\/\/(img\.(kaiheila|kookapp)\.cn|kaiheila\.oss-cn-beijing\.aliyuncs\.com)\/(assets|attachments)\/\d{4}-\d{2}(\/\d{2})?\/\w{8,16}\.\w+$",
@"^https?:\/\/(img\.(kaiheila|kookapp)\.cn|kaiheila\.oss-cn-beijing\.aliyuncs\.com)\/(assets|attachments)\/\d{4}-\d{2}(\/\d{2})?\/\w{8,16}(\.\w+)?$",
RegexOptions.Compiled | RegexOptions.IgnoreCase))
throw new InvalidOperationException($"The url {url} must be a valid Kook asset URL");

Expand Down
6 changes: 6 additions & 0 deletions src/Kook.Net.Rest/API/Common/Cards/Modules/FileModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ internal class FileModule : ModuleBase

[JsonPropertyName("title")]
public string? Title { get; set; }

[JsonPropertyName("size")]
public int? Size { get; set; }

[JsonPropertyName("canDownload")]
public bool? CanDownload { get; set; }
}
2 changes: 1 addition & 1 deletion src/Kook.Net.Rest/Entities/Messages/MessageHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ public static IReadOnlyCollection<Attachment> ParseAttachments(IEnumerable<Card>
switch (module)
{
case FileModule fileModule:
Attachment file = new(AttachmentType.File, fileModule.Source, fileModule.Title);
Attachment file = new(AttachmentType.File, fileModule.Source, fileModule.Title, fileModule.Size);
attachments.Add(file);
break;
case AudioModule audioModule:
Expand Down
4 changes: 4 additions & 0 deletions src/Kook.Net.Rest/Entities/Messages/RestUserMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ internal override void Update(Message model)
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, refMsgAuthor);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down Expand Up @@ -152,6 +154,8 @@ internal override void Update(DirectMessage model)
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, refMsgAuthor);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down
2 changes: 1 addition & 1 deletion src/Kook.Net.Rest/Extensions/EntityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static DividerModule ToEntity(this API.DividerModule model) =>
new();

public static FileModule ToEntity(this API.FileModule model) =>
new(model.Source, model.Title);
new(model.Source, model.Title, model.Size);

public static AudioModule ToEntity(this API.AudioModule model) =>
new(model.Source, model.Title, model.Cover);
Expand Down
12 changes: 12 additions & 0 deletions src/Kook.Net.WebSocket/Entities/Messages/SocketUserMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ internal override void Update(ClientState state, GatewayEvent<GatewayGroupMessag
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, author);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down Expand Up @@ -181,6 +183,8 @@ internal override void Update(ClientState state, GatewayEvent<GatewayPersonMessa
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, author);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down Expand Up @@ -231,6 +235,8 @@ internal override void Update(ClientState state, API.Message model)
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, author);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down Expand Up @@ -272,6 +278,8 @@ internal override void Update(ClientState state, API.DirectMessage model)
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, author);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down Expand Up @@ -322,6 +330,8 @@ internal override void Update(ClientState state, MessageUpdateEvent model)
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, author);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down Expand Up @@ -360,6 +370,8 @@ internal override void Update(ClientState state, DirectMessageUpdateEvent model)
else if (quotedMessageId.HasValue)
Quote = global::Kook.Quote.Create(quotedMessageId.Value, quote.Type, quote.Content, quote.CreateAt, author);
}
else
Quote = null;

if (model.Attachment is { } attachment)
_attachments = [.._attachments, Attachment.Create(attachment)];
Expand Down
62 changes: 62 additions & 0 deletions test/Kook.Net.Tests.Integration.Socket/Extensions/TaskExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Threading.Tasks;

namespace Kook;

/// <summary>
/// Adds extension methods to the <see cref="Task"/> class.
/// </summary>
public static class TaskExtension
{
private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);

/// <summary>
/// Waits for the task to complete within the specified timeout.
/// </summary>
/// <param name="task"> The task to wait for. </param>
/// <returns> The task. </returns>
/// <exception cref="TimeoutException"> The task did not complete within the specified timeout. </exception>
public static async Task WithTimeout(this Task task) => await task.WithTimeout(DefaultTimeout);

/// <summary>
/// Waits for the task to complete within the specified timeout.
/// </summary>
/// <param name="task"> The task to wait for. </param>
/// <param name="timeout"> A <see cref="TimeSpan"/> representing the timeout duration. </param>
/// <returns> The task. </returns>
/// <exception cref="TimeoutException"> The task did not complete within the specified timeout. </exception>
public static async Task WithTimeout(this Task task, TimeSpan timeout)
{
Task delayTask = Task.Delay(timeout);
Task completedTask = await Task.WhenAny(task, delayTask);
if (completedTask == delayTask)
throw new TimeoutException();
await task;
}

/// <summary>
/// Waits for the task to complete within the specified timeout.
/// </summary>
/// <param name="task"> The task to wait for. </param>
/// <typeparam name="T"> The type of the task result. </typeparam>
/// <returns> The result of the task. </returns>
/// <exception cref="TimeoutException"> The task did not complete within the specified timeout. </exception>
public static Task<T> WithTimeout<T>(this Task<T> task) => WithTimeout(task, DefaultTimeout);

/// <summary>
/// Waits for the task to complete within the specified timeout.
/// </summary>
/// <param name="task"> The task to wait for. </param>
/// <param name="timeout"> A <see cref="TimeSpan"/> representing the timeout duration. </param>
/// <typeparam name="T"> The type of the task result. </typeparam>
/// <returns> The result of the task. </returns>
/// <exception cref="TimeoutException"> The task did not complete within the specified timeout. </exception>
public static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout)
{
Task delayTask = Task.Delay(timeout);
Task completedTask = await Task.WhenAny(task, delayTask);
if (completedTask == delayTask)
throw new TimeoutException();
return await task;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Kook;

public class KookSocketClientFixture : IDisposable, IAsyncDisposable
{
private readonly TaskCompletionSource _ready = new();
private readonly TaskCompletionSource _readyPromise = new();

public KookSocketClient Client { get; private set; }

Expand All @@ -27,20 +27,21 @@ private async Task InitializeAsync()
{
LogLevel = LogSeverity.Debug,
DefaultRetryMode = RetryMode.AlwaysRetry,
AlwaysDownloadUsers = false,
AlwaysDownloadBoostSubscriptions = false,
AlwaysDownloadVoiceStates = false
AlwaysDownloadUsers = true,
AlwaysDownloadBoostSubscriptions = true,
AlwaysDownloadVoiceStates = true,
MessageCacheSize = 100
});
Client.Ready += ClientOnReady;
await Client.LoginAsync(TokenType.Bot, token);
await Client.StartAsync();
await _ready.Task;
await _readyPromise.Task.WithTimeout();
Client.Ready -= ClientOnReady;
}

private Task ClientOnReady()
{
_ready.SetResult();
_readyPromise.SetResult();
return Task.CompletedTask;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public class SocketChannelFixture : SocketGuildFixture
private const string TextChannelName = "TEST TEXT CHANNEL";
private const string VoiceChannelName = "TEST VOICE CHANNEL";

private readonly TaskCompletionSource<SocketTextChannel> _textChannelCreated = new();
private readonly TaskCompletionSource<SocketVoiceChannel> _voiceChannelCreated = new();
private readonly TaskCompletionSource<SocketTextChannel> _textChannelPromise = new();
private readonly TaskCompletionSource<SocketVoiceChannel> _voiceChannelPromise = new();

public SocketTextChannel TextChannel { get; private set; }

Expand All @@ -27,17 +27,17 @@ private async Task InitializeAsync()
Client.ChannelCreated += OnChannelCreated;
await Guild.CreateTextChannelAsync(TextChannelName);

Check warning on line 28 in test/Kook.Net.Tests.Integration.Socket/Fixtures/SocketChannelFixture.cs

View workflow job for this annotation

GitHub Actions / Build and Test (macOS-latest) / Build and Test

Member 'TextChannel' must have a non-null value when exiting.

Check warning on line 28 in test/Kook.Net.Tests.Integration.Socket/Fixtures/SocketChannelFixture.cs

View workflow job for this annotation

GitHub Actions / Build and Test (macOS-latest) / Build and Test

Member 'VoiceChannel' must have a non-null value when exiting.

Check warning on line 28 in test/Kook.Net.Tests.Integration.Socket/Fixtures/SocketChannelFixture.cs

View workflow job for this annotation

GitHub Actions / Build and Test (ubuntu-latest) / Build and Test

Member 'TextChannel' must have a non-null value when exiting.

Check warning on line 28 in test/Kook.Net.Tests.Integration.Socket/Fixtures/SocketChannelFixture.cs

View workflow job for this annotation

GitHub Actions / Build and Test (ubuntu-latest) / Build and Test

Member 'VoiceChannel' must have a non-null value when exiting.
await Guild.CreateVoiceChannelAsync(VoiceChannelName);
TextChannel = await _textChannelCreated.Task;
VoiceChannel = await _voiceChannelCreated.Task;
TextChannel = await _textChannelPromise.Task.WithTimeout();
VoiceChannel = await _voiceChannelPromise.Task.WithTimeout();
Client.ChannelCreated -= OnChannelCreated;
}

private Task OnChannelCreated(SocketChannel arg)
{
if (arg is SocketVoiceChannel { Name: VoiceChannelName } voiceChannel)
_voiceChannelCreated.SetResult(voiceChannel);
_voiceChannelPromise.SetResult(voiceChannel);
else if (arg is SocketTextChannel { Name: TextChannelName } textChannel)
_textChannelCreated.SetResult(textChannel);
_textChannelPromise.SetResult(textChannel);
return Task.CompletedTask;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Kook;

public class SocketGuildFixture : KookSocketClientFixture
{
private readonly TaskCompletionSource<SocketGuild> _joined = new();
private readonly TaskCompletionSource<SocketGuild> _joinedPromise = new();

public SocketGuild Guild { get; private set; }

Expand Down Expand Up @@ -41,7 +41,7 @@ private async Task InitializeAsync()
{
Client.JoinedGuild += OnJoinedGuild;
await Client.CreateGuildAsync(guildName);
Guild = await _joined.Task;
Guild = await _joinedPromise.Task.WithTimeout();
Client.JoinedGuild -= OnJoinedGuild;
}

Expand All @@ -51,7 +51,7 @@ private async Task InitializeAsync()

private Task OnJoinedGuild(SocketGuild guild)
{
_joined.SetResult(guild);
_joinedPromise.SetResult(guild);
return Task.CompletedTask;
}

Expand Down
Loading

0 comments on commit 0c470bb

Please sign in to comment.