Preliminary support for APIv9 and threads

This commit is contained in:
Ske
2021-07-15 12:41:19 +02:00
parent 0e7bcb993e
commit 1f2b9f998d
19 changed files with 127 additions and 24 deletions

View File

@@ -38,6 +38,14 @@ namespace Myriad.Cache
return cache.TrySaveDmChannelStub(md.GuildId, md.ChannelId);
case MessageDeleteBulkEvent md:
return cache.TrySaveDmChannelStub(md.GuildId, md.ChannelId);
case ThreadCreateEvent tc:
return cache.SaveChannel(tc);
case ThreadUpdateEvent tu:
return cache.SaveChannel(tu);
case ThreadDeleteEvent td:
return cache.RemoveChannel(td.Id);
case ThreadListSyncEvent tls:
return cache.SaveThreadListSync(tls);
}
return default;
@@ -53,6 +61,9 @@ namespace Myriad.Cache
foreach (var member in guildCreate.Members)
await cache.SaveUser(member.User);
foreach (var thread in guildCreate.Threads)
await cache.SaveChannel(thread);
}
private static async ValueTask SaveMessageCreate(this IDiscordCache cache, MessageCreateEvent evt)
@@ -70,5 +81,11 @@ namespace Myriad.Cache
// some kind of stub channel object until we get the real one
return guildId != null ? default : cache.SaveDmChannelStub(channelId);
}
private static async ValueTask SaveThreadListSync(this IDiscordCache cache, ThreadListSyncEvent evt)
{
foreach (var thread in evt.Threads)
await cache.SaveChannel(thread);
}
}
}

View File

@@ -75,5 +75,15 @@ namespace Myriad.Extensions
await cache.SaveChannel(restChannel);
return restChannel;
}
public static Channel GetRootChannel(this IDiscordCache cache, ulong channelOrThread)
{
var channel = cache.GetChannel(channelOrThread);
if (!channel.IsThread())
return channel;
var parent = cache.GetChannel(channel.ParentId!.Value);
return parent;
}
}
}

View File

@@ -5,5 +5,12 @@ namespace Myriad.Extensions
public static class ChannelExtensions
{
public static string Mention(this Channel channel) => $"<#{channel.Id}>";
public static bool IsThread(this Channel channel) => channel.Type.IsThread();
public static bool IsThread(this Channel.ChannelType type) =>
type is Channel.ChannelType.GuildPublicThread
or Channel.ChannelType.GuildPrivateThread
or Channel.ChannelType.GuildNewsThread;
}
}

View File

@@ -11,7 +11,7 @@ namespace Myriad.Extensions
public static class PermissionExtensions
{
public static PermissionSet PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) =>
PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member?.Roles, isWebhook: message.Author.Discriminator == "0000");
PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member?.Roles, isWebhook: message.WebhookId != null);
public static PermissionSet PermissionsFor(this IDiscordCache cache, ulong channelId, GuildMember member) =>
PermissionsFor(cache, channelId, member.User.Id, member.Roles);
@@ -21,16 +21,21 @@ namespace Myriad.Extensions
public static PermissionSet PermissionsFor(this IDiscordCache cache, ulong channelId, ulong userId, ICollection<ulong>? userRoles, bool isWebhook = false)
{
var channel = cache.GetChannel(channelId);
if (!cache.TryGetChannel(channelId, out var channel))
// todo: handle channel not found better
return PermissionSet.Dm;
if (channel.GuildId == null)
return PermissionSet.Dm;
var rootChannel = cache.GetRootChannel(channelId);
var guild = cache.GetGuild(channel.GuildId.Value);
if (isWebhook)
return EveryonePermissions(guild);
return PermissionsFor(guild, channel, userId, userRoles);
return PermissionsFor(guild, rootChannel, userId, userRoles);
}
public static PermissionSet EveryonePermissions(this Guild guild) =>

View File

@@ -6,5 +6,6 @@ namespace Myriad.Gateway
{
public Channel[] Channels { get; init; }
public GuildMember[] Members { get; init; }
public Channel[] Threads { get; init; }
}
}

View File

@@ -21,6 +21,10 @@ namespace Myriad.Gateway
{"CHANNEL_CREATE", typeof(ChannelCreateEvent)},
{"CHANNEL_UPDATE", typeof(ChannelUpdateEvent)},
{"CHANNEL_DELETE", typeof(ChannelDeleteEvent)},
{"THREAD_CREATE", typeof(ThreadCreateEvent)},
{"THREAD_UPDATE", typeof(ThreadUpdateEvent)},
{"THREAD_DELETE", typeof(ThreadDeleteEvent)},
{"THREAD_LIST_SYNC", typeof(ThreadListSyncEvent)},
{"MESSAGE_CREATE", typeof(MessageCreateEvent)},
{"MESSAGE_UPDATE", typeof(MessageUpdateEvent)},
{"MESSAGE_DELETE", typeof(MessageDeleteEvent)},

View File

@@ -0,0 +1,6 @@
using Myriad.Types;
namespace Myriad.Gateway
{
public record ThreadCreateEvent: Channel, IGatewayEvent;
}

View File

@@ -0,0 +1,12 @@
using Myriad.Types;
namespace Myriad.Gateway
{
public record ThreadDeleteEvent: IGatewayEvent
{
public ulong Id { get; init; }
public ulong? GuildId { get; init; }
public ulong? ParentId { get; init; }
public Channel.ChannelType Type { get; init; }
}
}

View File

@@ -0,0 +1,11 @@
using Myriad.Types;
namespace Myriad.Gateway
{
public record ThreadListSyncEvent: IGatewayEvent
{
public ulong GuildId { get; init; }
public ulong[]? ChannelIds { get; init; }
public Channel[] Threads { get; init; }
}
}

View File

@@ -0,0 +1,6 @@
using Myriad.Types;
namespace Myriad.Gateway
{
public record ThreadUpdateEvent: Channel, IGatewayEvent;
}

View File

@@ -82,7 +82,7 @@ namespace Myriad.Gateway
private Uri GetConnectionUri(string baseUri) => new UriBuilder(baseUri)
{
Query = "v=8&encoding=json"
Query = "v=9&encoding=json"
}.Uri;
private async Task CloseInner(WebSocketCloseStatus closeStatus, string? description)

View File

@@ -22,7 +22,7 @@ namespace Myriad.Rest
{
public class BaseRestClient: IAsyncDisposable
{
private const string ApiBaseUrl = "https://discord.com/api/v8";
private const string ApiBaseUrl = "https://discord.com/api/v9";
private readonly Version _httpVersion = new(2, 0);
private readonly JsonSerializerOptions _jsonSerializerOptions;

View File

@@ -116,9 +116,15 @@ namespace Myriad.Rest
_client.Get<Webhook[]>($"/channels/{channelId}/webhooks", ("GetChannelWebhooks", channelId))!;
public Task<Message> ExecuteWebhook(ulong webhookId, string webhookToken, ExecuteWebhookRequest request,
MultipartFile[]? files = null) =>
_client.PostMultipart<Message>($"/webhooks/{webhookId}/{webhookToken}?wait=true",
MultipartFile[]? files = null, ulong? threadId = null)
{
var url = $"/webhooks/{webhookId}/{webhookToken}?wait=true";
if (threadId != null)
url += $"&thread_id={threadId}";
return _client.PostMultipart<Message>(url,
("ExecuteWebhook", webhookId), request, files)!;
}
public Task<Message> EditWebhookMessage(ulong webhookId, string webhookToken, ulong messageId,
WebhookMessageEditRequest request) =>