run dotnet format

This commit is contained in:
spiral 2021-08-27 11:03:47 -04:00
parent 05989242f9
commit ac2671452d
No known key found for this signature in database
GPG Key ID: A6059F0CA0E1BD31
278 changed files with 1913 additions and 1808 deletions

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using Myriad.Types; using Myriad.Types;
@ -11,66 +11,71 @@ namespace Myriad.Builders
public EmbedBuilder Title(string? title) public EmbedBuilder Title(string? title)
{ {
_embed = _embed with {Title = title}; _embed = _embed with { Title = title };
return this; return this;
} }
public EmbedBuilder Description(string? description) public EmbedBuilder Description(string? description)
{ {
_embed = _embed with { Description = description}; _embed = _embed with { Description = description };
return this; return this;
} }
public EmbedBuilder Url(string? url) public EmbedBuilder Url(string? url)
{ {
_embed = _embed with {Url = url}; _embed = _embed with { Url = url };
return this; return this;
} }
public EmbedBuilder Color(uint? color) public EmbedBuilder Color(uint? color)
{ {
_embed = _embed with {Color = color}; _embed = _embed with { Color = color };
return this; return this;
} }
public EmbedBuilder Footer(Embed.EmbedFooter? footer) public EmbedBuilder Footer(Embed.EmbedFooter? footer)
{ {
_embed = _embed with { _embed = _embed with
{
Footer = footer Footer = footer
}; };
return this; return this;
} }
public EmbedBuilder Image(Embed.EmbedImage? image) public EmbedBuilder Image(Embed.EmbedImage? image)
{ {
_embed = _embed with { _embed = _embed with
{
Image = image Image = image
}; };
return this; return this;
} }
public EmbedBuilder Thumbnail(Embed.EmbedThumbnail? thumbnail) public EmbedBuilder Thumbnail(Embed.EmbedThumbnail? thumbnail)
{ {
_embed = _embed with { _embed = _embed with
{
Thumbnail = thumbnail Thumbnail = thumbnail
}; };
return this; return this;
} }
public EmbedBuilder Author(Embed.EmbedAuthor? author) public EmbedBuilder Author(Embed.EmbedAuthor? author)
{ {
_embed = _embed with { _embed = _embed with
{
Author = author Author = author
}; };
return this; return this;
} }
public EmbedBuilder Timestamp(string? timestamp) public EmbedBuilder Timestamp(string? timestamp)
{ {
_embed = _embed with { _embed = _embed with
{
Timestamp = timestamp Timestamp = timestamp
}; };
return this; return this;
} }

View File

@ -1,4 +1,4 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Myriad.Gateway; using Myriad.Gateway;
@ -69,9 +69,9 @@ namespace Myriad.Cache
private static async ValueTask SaveMessageCreate(this IDiscordCache cache, MessageCreateEvent evt) private static async ValueTask SaveMessageCreate(this IDiscordCache cache, MessageCreateEvent evt)
{ {
await cache.TrySaveDmChannelStub(evt.GuildId, evt.ChannelId); await cache.TrySaveDmChannelStub(evt.GuildId, evt.ChannelId);
await cache.SaveUser(evt.Author); await cache.SaveUser(evt.Author);
foreach (var mention in evt.Mentions) foreach (var mention in evt.Mentions)
await cache.SaveUser(mention); await cache.SaveUser(mention);
} }
@ -84,7 +84,7 @@ namespace Myriad.Cache
private static async ValueTask SaveThreadListSync(this IDiscordCache cache, ThreadListSyncEvent evt) private static async ValueTask SaveThreadListSync(this IDiscordCache cache, ThreadListSyncEvent evt)
{ {
foreach (var thread in evt.Threads) foreach (var thread in evt.Threads)
await cache.SaveChannel(thread); await cache.SaveChannel(thread);
} }
} }

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Myriad.Types; using Myriad.Types;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -15,7 +15,7 @@ namespace Myriad.Cache
private readonly ConcurrentDictionary<ulong, CachedGuild> _guilds = new(); private readonly ConcurrentDictionary<ulong, CachedGuild> _guilds = new();
private readonly ConcurrentDictionary<ulong, Role> _roles = new(); private readonly ConcurrentDictionary<ulong, Role> _roles = new();
private readonly ConcurrentDictionary<ulong, User> _users = new(); private readonly ConcurrentDictionary<ulong, User> _users = new();
public ValueTask SaveGuild(Guild guild) public ValueTask SaveGuild(Guild guild)
{ {
SaveGuildRaw(guild); SaveGuildRaw(guild);
@ -61,18 +61,20 @@ namespace Myriad.Cache
var found = false; var found = false;
for (var i = 0; i < guild.Guild.Roles.Length; i++) for (var i = 0; i < guild.Guild.Roles.Length; i++)
{ {
if (guild.Guild.Roles[i].Id != role.Id) if (guild.Guild.Roles[i].Id != role.Id)
continue; continue;
guild.Guild.Roles[i] = role; guild.Guild.Roles[i] = role;
found = true; found = true;
} }
if (!found) if (!found)
{ {
_guilds[guildId] = guild with { _guilds[guildId] = guild with
Guild = guild.Guild with { {
Roles = guild.Guild.Roles.Concat(new[] { role}).ToArray() Guild = guild.Guild with
{
Roles = guild.Guild.Roles.Concat(new[] { role }).ToArray()
} }
}; };
} }
@ -87,7 +89,7 @@ namespace Myriad.Cache
// We may get a message create before channel create and we want to have it saved // We may get a message create before channel create and we want to have it saved
_channels.GetOrAdd(channelId, id => new Channel _channels.GetOrAdd(channelId, id => new Channel
{ {
Id = id, Id = id,
Type = Channel.ChannelType.Dm Type = Channel.ChannelType.Dm
}); });
return default; return default;
@ -134,7 +136,7 @@ namespace Myriad.Cache
return false; return false;
} }
public bool TryGetChannel(ulong channelId, out Channel channel) => public bool TryGetChannel(ulong channelId, out Channel channel) =>
_channels.TryGetValue(channelId, out channel!); _channels.TryGetValue(channelId, out channel!);
public bool TryGetDmChannel(ulong userId, out Channel channel) public bool TryGetDmChannel(ulong userId, out Channel channel)
@ -143,7 +145,7 @@ namespace Myriad.Cache
if (!_dmChannels.TryGetValue(userId, out var channelId)) if (!_dmChannels.TryGetValue(userId, out var channelId))
return false; return false;
return TryGetChannel(channelId, out channel); return TryGetChannel(channelId, out channel);
} }
public bool TryGetUser(ulong userId, out User user) => public bool TryGetUser(ulong userId, out User user) =>
_users.TryGetValue(userId, out user!); _users.TryGetValue(userId, out user!);

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Myriad.Cache; using Myriad.Cache;
@ -15,7 +15,7 @@ namespace Myriad.Extensions
throw new KeyNotFoundException($"Guild {guildId} not found in cache"); throw new KeyNotFoundException($"Guild {guildId} not found in cache");
return guild; return guild;
} }
public static Channel GetChannel(this IDiscordCache cache, ulong channelId) public static Channel GetChannel(this IDiscordCache cache, ulong channelId)
{ {
if (!cache.TryGetChannel(channelId, out var channel)) if (!cache.TryGetChannel(channelId, out var channel))
@ -36,14 +36,14 @@ namespace Myriad.Extensions
throw new KeyNotFoundException($"User {userId} not found in cache"); throw new KeyNotFoundException($"User {userId} not found in cache");
return user; return user;
} }
public static Role GetRole(this IDiscordCache cache, ulong roleId) public static Role GetRole(this IDiscordCache cache, ulong roleId)
{ {
if (!cache.TryGetRole(roleId, out var role)) if (!cache.TryGetRole(roleId, out var role))
throw new KeyNotFoundException($"User {roleId} not found in cache"); throw new KeyNotFoundException($"User {roleId} not found in cache");
return role; return role;
} }
public static async ValueTask<User?> GetOrFetchUser(this IDiscordCache cache, DiscordApiClient rest, ulong userId) public static async ValueTask<User?> GetOrFetchUser(this IDiscordCache cache, DiscordApiClient rest, ulong userId)
{ {
if (cache.TryGetUser(userId, out var cacheUser)) if (cache.TryGetUser(userId, out var cacheUser))
@ -54,7 +54,7 @@ namespace Myriad.Extensions
await cache.SaveUser(restUser); await cache.SaveUser(restUser);
return restUser; return restUser;
} }
public static async ValueTask<Channel?> GetOrFetchChannel(this IDiscordCache cache, DiscordApiClient rest, ulong channelId) public static async ValueTask<Channel?> GetOrFetchChannel(this IDiscordCache cache, DiscordApiClient rest, ulong channelId)
{ {
if (cache.TryGetChannel(channelId, out var cacheChannel)) if (cache.TryGetChannel(channelId, out var cacheChannel))
@ -79,9 +79,9 @@ namespace Myriad.Extensions
public static Channel GetRootChannel(this IDiscordCache cache, ulong channelOrThread) public static Channel GetRootChannel(this IDiscordCache cache, ulong channelOrThread)
{ {
var channel = cache.GetChannel(channelOrThread); var channel = cache.GetChannel(channelOrThread);
if (!channel.IsThread()) if (!channel.IsThread())
return channel; return channel;
var parent = cache.GetChannel(channel.ParentId!.Value); var parent = cache.GetChannel(channel.ParentId!.Value);
return parent; return parent;
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Extensions namespace Myriad.Extensions
{ {

View File

@ -1,7 +1,7 @@
namespace Myriad.Extensions namespace Myriad.Extensions
{ {
public static class GuildExtensions public static class GuildExtensions
{ {
} }
} }

View File

@ -1,4 +1,4 @@
using Myriad.Gateway; using Myriad.Gateway;
using Myriad.Types; using Myriad.Types;
namespace Myriad.Extensions namespace Myriad.Extensions
@ -7,7 +7,7 @@ namespace Myriad.Extensions
{ {
public static string JumpLink(this Message msg) => public static string JumpLink(this Message msg) =>
$"https://discord.com/channels/{msg.GuildId}/{msg.ChannelId}/{msg.Id}"; $"https://discord.com/channels/{msg.GuildId}/{msg.ChannelId}/{msg.Id}";
public static string JumpLink(this MessageReactionAddEvent msg) => public static string JumpLink(this MessageReactionAddEvent msg) =>
$"https://discord.com/channels/{msg.GuildId}/{msg.ChannelId}/{msg.MessageId}"; $"https://discord.com/channels/{msg.GuildId}/{msg.ChannelId}/{msg.MessageId}";
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -21,12 +21,12 @@ namespace Myriad.Extensions
if (!cache.TryGetChannel(channelId, out var channel)) if (!cache.TryGetChannel(channelId, out var channel))
// todo: handle channel not found better // todo: handle channel not found better
return PermissionSet.Dm; return PermissionSet.Dm;
if (channel.GuildId == null) if (channel.GuildId == null)
return PermissionSet.Dm; return PermissionSet.Dm;
var rootChannel = cache.GetRootChannel(channelId); var rootChannel = cache.GetRootChannel(channelId);
var guild = cache.GetGuild(channel.GuildId.Value); var guild = cache.GetGuild(channel.GuildId.Value);
if (isWebhook) if (isWebhook)
@ -34,10 +34,10 @@ namespace Myriad.Extensions
return PermissionsFor(guild, rootChannel, userId, member); return PermissionsFor(guild, rootChannel, userId, member);
} }
public static PermissionSet EveryonePermissions(this Guild guild) => public static PermissionSet EveryonePermissions(this Guild guild) =>
guild.Roles.FirstOrDefault(r => r.Id == guild.Id)?.Permissions ?? PermissionSet.Dm; guild.Roles.FirstOrDefault(r => r.Id == guild.Id)?.Permissions ?? PermissionSet.Dm;
public static PermissionSet EveryonePermissions(this IDiscordCache cache, Channel channel) public static PermissionSet EveryonePermissions(this IDiscordCache cache, Channel channel)
{ {
if (channel.Type == Channel.ChannelType.Dm) if (channel.Type == Channel.ChannelType.Dm)
@ -62,7 +62,7 @@ namespace Myriad.Extensions
{ {
if (channel.Type == Channel.ChannelType.Dm) if (channel.Type == Channel.ChannelType.Dm)
return PermissionSet.Dm; return PermissionSet.Dm;
if (member == null) if (member == null)
// this happens with system (Discord platform-owned) users - they're not actually in the guild, so there is no member object. // this happens with system (Discord platform-owned) users - they're not actually in the guild, so there is no member object.
return EveryonePermissions(guild); return EveryonePermissions(guild);

View File

@ -1,4 +1,4 @@
using System; using System;
using Myriad.Types; using Myriad.Types;
@ -7,7 +7,7 @@ namespace Myriad.Extensions
public static class SnowflakeExtensions public static class SnowflakeExtensions
{ {
public static readonly DateTimeOffset DiscordEpoch = new(2015, 1, 1, 0, 0, 0, TimeSpan.Zero); public static readonly DateTimeOffset DiscordEpoch = new(2015, 1, 1, 0, 0, 0, TimeSpan.Zero);
public static DateTimeOffset SnowflakeToTimestamp(ulong snowflake) => public static DateTimeOffset SnowflakeToTimestamp(ulong snowflake) =>
DiscordEpoch + TimeSpan.FromMilliseconds(snowflake >> 22); DiscordEpoch + TimeSpan.FromMilliseconds(snowflake >> 22);

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Extensions namespace Myriad.Extensions
{ {
@ -6,7 +6,7 @@ namespace Myriad.Extensions
{ {
public static string Mention(this User user) => $"<@{user.Id}>"; public static string Mention(this User user) => $"<@{user.Id}>";
public static string AvatarUrl(this User user, string? format = "png", int? size = 128) => public static string AvatarUrl(this User user, string? format = "png", int? size = 128) =>
$"https://cdn.discordapp.com/avatars/{user.Id}/{user.Avatar}.{format}?size={size}"; $"https://cdn.discordapp.com/avatars/{user.Id}/{user.Avatar}.{format}?size={size}";
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -30,7 +30,7 @@ namespace Myriad.Gateway
public IReadOnlyDictionary<int, Shard> Shards => _shards; public IReadOnlyDictionary<int, Shard> Shards => _shards;
public User? User => _shards.Values.Select(s => s.User).FirstOrDefault(s => s != null); public User? User => _shards.Values.Select(s => s.User).FirstOrDefault(s => s != null);
public ApplicationPartial? Application => _shards.Values.Select(s => s.Application).FirstOrDefault(s => s != null); public ApplicationPartial? Application => _shards.Values.Select(s => s.Application).FirstOrDefault(s => s != null);
public async Task Start(GatewayInfo.Bot info) public async Task Start(GatewayInfo.Bot info)
{ {
await Start(info.Url, 0, info.Shards - 1, info.Shards, info.SessionStartLimit.MaxConcurrency); await Start(info.Url, 0, info.Shards - 1, info.Shards, info.SessionStartLimit.MaxConcurrency);
@ -39,7 +39,7 @@ namespace Myriad.Gateway
public async Task Start(string url, int shardMin, int shardMax, int shardTotal, int recommendedConcurrency) public async Task Start(string url, int shardMin, int shardMax, int shardTotal, int recommendedConcurrency)
{ {
_ratelimiter = GetRateLimiter(recommendedConcurrency); _ratelimiter = GetRateLimiter(recommendedConcurrency);
var shardCount = shardMax - shardMin + 1; var shardCount = shardMax - shardMin + 1;
_logger.Information("Starting {ShardCount} of {ShardTotal} shards (#{ShardMin}-#{ShardMax}) at {Url}", _logger.Information("Starting {ShardCount} of {ShardTotal} shards (#{ShardMin}-#{ShardMax}) at {Url}",
shardCount, shardTotal, shardMin, shardMax, url); shardCount, shardTotal, shardMin, shardMax, url);
@ -51,7 +51,7 @@ namespace Myriad.Gateway
private async Task StartShards() private async Task StartShards()
{ {
_logger.Information("Connecting shards..."); _logger.Information("Connecting shards...");
foreach (var shard in _shards.Values) foreach (var shard in _shards.Values)
await shard.Start(); await shard.Start();
} }
@ -60,7 +60,7 @@ namespace Myriad.Gateway
var shard = new Shard(_gatewaySettings, shardInfo, _ratelimiter!, url, _logger); var shard = new Shard(_gatewaySettings, shardInfo, _ratelimiter!, url, _logger);
shard.OnEventReceived += evt => OnShardEventReceived(shard, evt); shard.OnEventReceived += evt => OnShardEventReceived(shard, evt);
_shards[shardInfo.ShardId] = shard; _shards[shardInfo.ShardId] = shard;
ShardCreated?.Invoke(shard); ShardCreated?.Invoke(shard);
} }
@ -69,12 +69,12 @@ namespace Myriad.Gateway
if (EventReceived != null) if (EventReceived != null)
await EventReceived(shard, evt); await EventReceived(shard, evt);
} }
private int GetActualShardConcurrency(int recommendedConcurrency) private int GetActualShardConcurrency(int recommendedConcurrency)
{ {
if (_gatewaySettings.MaxShardConcurrency == null) if (_gatewaySettings.MaxShardConcurrency == null)
return recommendedConcurrency; return recommendedConcurrency;
return Math.Min(_gatewaySettings.MaxShardConcurrency.Value, recommendedConcurrency); return Math.Min(_gatewaySettings.MaxShardConcurrency.Value, recommendedConcurrency);
} }
@ -84,7 +84,7 @@ namespace Myriad.Gateway
{ {
return new TwilightGatewayRatelimiter(_logger, _gatewaySettings.GatewayQueueUrl); return new TwilightGatewayRatelimiter(_logger, _gatewaySettings.GatewayQueueUrl);
} }
var concurrency = GetActualShardConcurrency(recommendedConcurrency); var concurrency = GetActualShardConcurrency(recommendedConcurrency);
return new LocalGatewayRatelimiter(_logger, concurrency); return new LocalGatewayRatelimiter(_logger, concurrency);
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record GuildDeleteEvent(ulong Id, bool Unavailable): IGatewayEvent; public record GuildDeleteEvent(ulong Id, bool Unavailable): IGatewayEvent;
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record GuildRoleDeleteEvent(ulong GuildId, ulong RoleId): IGatewayEvent; public record GuildRoleDeleteEvent(ulong GuildId, ulong RoleId): IGatewayEvent;
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Myriad.Gateway namespace Myriad.Gateway
@ -7,33 +7,33 @@ namespace Myriad.Gateway
{ {
public static readonly Dictionary<string, Type> EventTypes = new() public static readonly Dictionary<string, Type> EventTypes = new()
{ {
{"READY", typeof(ReadyEvent)}, { "READY", typeof(ReadyEvent) },
{"RESUMED", typeof(ResumedEvent)}, { "RESUMED", typeof(ResumedEvent) },
{"GUILD_CREATE", typeof(GuildCreateEvent)}, { "GUILD_CREATE", typeof(GuildCreateEvent) },
{"GUILD_UPDATE", typeof(GuildUpdateEvent)}, { "GUILD_UPDATE", typeof(GuildUpdateEvent) },
{"GUILD_DELETE", typeof(GuildDeleteEvent)}, { "GUILD_DELETE", typeof(GuildDeleteEvent) },
{"GUILD_MEMBER_ADD", typeof(GuildMemberAddEvent)}, { "GUILD_MEMBER_ADD", typeof(GuildMemberAddEvent) },
{"GUILD_MEMBER_REMOVE", typeof(GuildMemberRemoveEvent)}, { "GUILD_MEMBER_REMOVE", typeof(GuildMemberRemoveEvent) },
{"GUILD_MEMBER_UPDATE", typeof(GuildMemberUpdateEvent)}, { "GUILD_MEMBER_UPDATE", typeof(GuildMemberUpdateEvent) },
{"GUILD_ROLE_CREATE", typeof(GuildRoleCreateEvent)}, { "GUILD_ROLE_CREATE", typeof(GuildRoleCreateEvent) },
{"GUILD_ROLE_UPDATE", typeof(GuildRoleUpdateEvent)}, { "GUILD_ROLE_UPDATE", typeof(GuildRoleUpdateEvent) },
{"GUILD_ROLE_DELETE", typeof(GuildRoleDeleteEvent)}, { "GUILD_ROLE_DELETE", typeof(GuildRoleDeleteEvent) },
{"CHANNEL_CREATE", typeof(ChannelCreateEvent)}, { "CHANNEL_CREATE", typeof(ChannelCreateEvent) },
{"CHANNEL_UPDATE", typeof(ChannelUpdateEvent)}, { "CHANNEL_UPDATE", typeof(ChannelUpdateEvent) },
{"CHANNEL_DELETE", typeof(ChannelDeleteEvent)}, { "CHANNEL_DELETE", typeof(ChannelDeleteEvent) },
{"THREAD_CREATE", typeof(ThreadCreateEvent)}, { "THREAD_CREATE", typeof(ThreadCreateEvent) },
{"THREAD_UPDATE", typeof(ThreadUpdateEvent)}, { "THREAD_UPDATE", typeof(ThreadUpdateEvent) },
{"THREAD_DELETE", typeof(ThreadDeleteEvent)}, { "THREAD_DELETE", typeof(ThreadDeleteEvent) },
{"THREAD_LIST_SYNC", typeof(ThreadListSyncEvent)}, { "THREAD_LIST_SYNC", typeof(ThreadListSyncEvent) },
{"MESSAGE_CREATE", typeof(MessageCreateEvent)}, { "MESSAGE_CREATE", typeof(MessageCreateEvent) },
{"MESSAGE_UPDATE", typeof(MessageUpdateEvent)}, { "MESSAGE_UPDATE", typeof(MessageUpdateEvent) },
{"MESSAGE_DELETE", typeof(MessageDeleteEvent)}, { "MESSAGE_DELETE", typeof(MessageDeleteEvent) },
{"MESSAGE_DELETE_BULK", typeof(MessageDeleteBulkEvent)}, { "MESSAGE_DELETE_BULK", typeof(MessageDeleteBulkEvent) },
{"MESSAGE_REACTION_ADD", typeof(MessageReactionAddEvent)}, { "MESSAGE_REACTION_ADD", typeof(MessageReactionAddEvent) },
{"MESSAGE_REACTION_REMOVE", typeof(MessageReactionRemoveEvent)}, { "MESSAGE_REACTION_REMOVE", typeof(MessageReactionRemoveEvent) },
{"MESSAGE_REACTION_REMOVE_ALL", typeof(MessageReactionRemoveAllEvent)}, { "MESSAGE_REACTION_REMOVE_ALL", typeof(MessageReactionRemoveAllEvent) },
{"MESSAGE_REACTION_REMOVE_EMOJI", typeof(MessageReactionRemoveEmojiEvent)}, { "MESSAGE_REACTION_REMOVE_EMOJI", typeof(MessageReactionRemoveEmojiEvent) },
{"INTERACTION_CREATE", typeof(InteractionCreateEvent)} { "INTERACTION_CREATE", typeof(InteractionCreateEvent) }
}; };
} }
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record MessageDeleteBulkEvent(ulong[] Ids, ulong ChannelId, ulong? GuildId): IGatewayEvent; public record MessageDeleteBulkEvent(ulong[] Ids, ulong ChannelId, ulong? GuildId): IGatewayEvent;
} }

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record MessageDeleteEvent(ulong Id, ulong ChannelId, ulong? GuildId): IGatewayEvent; public record MessageDeleteEvent(ulong Id, ulong ChannelId, ulong? GuildId): IGatewayEvent;
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record MessageReactionRemoveAllEvent(ulong ChannelId, ulong MessageId, ulong? GuildId): IGatewayEvent; public record MessageReactionRemoveAllEvent(ulong ChannelId, ulong MessageId, ulong? GuildId): IGatewayEvent;
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
using Myriad.Utils; using Myriad.Utils;
namespace Myriad.Gateway namespace Myriad.Gateway

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Myriad.Types; using Myriad.Types;

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record ResumedEvent: IGatewayEvent; public record ResumedEvent: IGatewayEvent;
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,11 +1,11 @@
using System; using System;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
// TODO: unused? // TODO: unused?
public class GatewayCloseException: Exception public class GatewayCloseException: Exception
{ {
public GatewayCloseException(int closeCode, string closeReason): base($"{closeCode}: {closeReason}") public GatewayCloseException(int closeCode, string closeReason) : base($"{closeCode}: {closeReason}")
{ {
CloseCode = closeCode; CloseCode = closeCode;
CloseReason = closeReason; CloseReason = closeReason;

View File

@ -1,4 +1,4 @@
using System; using System;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
@ -7,10 +7,12 @@ namespace Myriad.Gateway
[JsonPropertyName("op")] public GatewayOpcode Opcode { get; init; } [JsonPropertyName("op")] public GatewayOpcode Opcode { get; init; }
[JsonPropertyName("d")] public object? Payload { get; init; } [JsonPropertyName("d")] public object? Payload { get; init; }
[JsonPropertyName("s")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("s")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Sequence { get; init; } public int? Sequence { get; init; }
[JsonPropertyName("t")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("t")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? EventType { get; init; } public string? EventType { get; init; }
} }

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record GatewaySettings public record GatewaySettings
{ {

View File

@ -1,4 +1,4 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Myriad.Gateway.Limit namespace Myriad.Gateway.Limit
{ {

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -14,7 +14,7 @@ namespace Myriad.Gateway.Limit
{ {
Timeout = TimeSpan.FromSeconds(60) Timeout = TimeSpan.FromSeconds(60)
}; };
public TwilightGatewayRatelimiter(ILogger logger, string url) public TwilightGatewayRatelimiter(ILogger logger, string url)
{ {
_url = url; _url = url;

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record GatewayHello(int HeartbeatInterval); public record GatewayHello(int HeartbeatInterval);
} }

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Myriad.Gateway namespace Myriad.Gateway
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record GatewayResume(string Token, string SessionId, int Seq); public record GatewayResume(string Token, string SessionId, int Seq);
} }

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Myriad.Serialization; using Myriad.Serialization;
using Myriad.Types; using Myriad.Types;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -68,18 +68,18 @@ namespace Myriad.Gateway
_conn = new ShardConnection(_jsonSerializerOptions, _logger); _conn = new ShardConnection(_jsonSerializerOptions, _logger);
} }
private async Task ShardLoop() private async Task ShardLoop()
{ {
// may be superfluous but this adds shard id to ambient context which is nice // may be superfluous but this adds shard id to ambient context which is nice
using var _ = LogContext.PushProperty("ShardId", _info.ShardId); using var _ = LogContext.PushProperty("ShardId", _info.ShardId);
while (true) while (true)
{ {
try try
{ {
await ConnectInner(); await ConnectInner();
await HandleConnectionOpened(); await HandleConnectionOpened();
while (_conn.State == WebSocketState.Open) while (_conn.State == WebSocketState.Open)
@ -90,7 +90,7 @@ namespace Myriad.Gateway
await _stateManager.HandlePacketReceived(packet); await _stateManager.HandlePacketReceived(packet);
} }
await HandleConnectionClosed(_conn.CloseStatus, _conn.CloseStatusDescription); await HandleConnectionClosed(_conn.CloseStatus, _conn.CloseStatusDescription);
_logger.Information("Shard {ShardId}: Reconnecting after delay {ReconnectDelay}", _logger.Information("Shard {ShardId}: Reconnecting after delay {ReconnectDelay}",
@ -103,20 +103,20 @@ namespace Myriad.Gateway
catch (Exception e) catch (Exception e)
{ {
_logger.Error(e, "Shard {ShardId}: Error in main shard loop, reconnecting in 5 seconds...", _info.ShardId); _logger.Error(e, "Shard {ShardId}: Error in main shard loop, reconnecting in 5 seconds...", _info.ShardId);
// todo: exponential backoff here? this should never happen, ideally... // todo: exponential backoff here? this should never happen, ideally...
await Task.Delay(TimeSpan.FromSeconds(5)); await Task.Delay(TimeSpan.FromSeconds(5));
} }
} }
} }
public async Task Start() public async Task Start()
{ {
if (_worker == null) if (_worker == null)
_worker = ShardLoop(); _worker = ShardLoop();
// we can probably TCS this instead of spin loop but w/e // we can probably TCS this instead of spin loop but w/e
while (State != ShardState.Identifying) while (State != ShardState.Identifying)
await Task.Delay(100); await Task.Delay(100);
} }
@ -128,7 +128,7 @@ namespace Myriad.Gateway
Payload = payload Payload = payload
}); });
} }
private async Task ConnectInner() private async Task ConnectInner()
{ {
while (true) while (true)
@ -148,12 +148,12 @@ namespace Myriad.Gateway
} }
} }
} }
private async Task DisconnectInner(WebSocketCloseStatus closeStatus) private async Task DisconnectInner(WebSocketCloseStatus closeStatus)
{ {
await _conn.Disconnect(closeStatus, null); await _conn.Disconnect(closeStatus, null);
} }
private async Task SendIdentify() private async Task SendIdentify()
{ {
await _conn.Send(new GatewayPacket await _conn.Send(new GatewayPacket
@ -165,8 +165,8 @@ namespace Myriad.Gateway
Intents = _settings.Intents, Intents = _settings.Intents,
Properties = new GatewayIdentify.ConnectionProperties Properties = new GatewayIdentify.ConnectionProperties
{ {
Browser = LibraryName, Browser = LibraryName,
Device = LibraryName, Device = LibraryName,
Os = Environment.OSVersion.ToString() Os = Environment.OSVersion.ToString()
}, },
Shard = _info, Shard = _info,
@ -175,7 +175,7 @@ namespace Myriad.Gateway
} }
}); });
} }
private async Task SendResume((string SessionId, int? LastSeq) arg) private async Task SendResume((string SessionId, int? LastSeq) arg)
{ {
await _conn.Send(new GatewayPacket await _conn.Send(new GatewayPacket
@ -184,12 +184,12 @@ namespace Myriad.Gateway
Payload = new GatewayResume(_settings.Token, arg.SessionId, arg.LastSeq ?? 0) Payload = new GatewayResume(_settings.Token, arg.SessionId, arg.LastSeq ?? 0)
}); });
} }
private async Task SendHeartbeat(int? lastSeq) private async Task SendHeartbeat(int? lastSeq)
{ {
await _conn.Send(new GatewayPacket {Opcode = GatewayOpcode.Heartbeat, Payload = lastSeq}); await _conn.Send(new GatewayPacket { Opcode = GatewayOpcode.Heartbeat, Payload = lastSeq });
} }
private async Task Reconnect(WebSocketCloseStatus closeStatus, TimeSpan delay) private async Task Reconnect(WebSocketCloseStatus closeStatus, TimeSpan delay)
{ {
_reconnectDelay = delay; _reconnectDelay = delay;
@ -202,7 +202,7 @@ namespace Myriad.Gateway
Ready?.Invoke(); Ready?.Invoke();
if (arg is ResumedEvent) if (arg is ResumedEvent)
Resumed?.Invoke(); Resumed?.Invoke();
await (OnEventReceived?.Invoke(arg) ?? Task.CompletedTask); await (OnEventReceived?.Invoke(arg) ?? Task.CompletedTask);
} }
@ -215,7 +215,7 @@ namespace Myriad.Gateway
private async Task HandleConnectionClosed(WebSocketCloseStatus? closeStatus, string? description) private async Task HandleConnectionClosed(WebSocketCloseStatus? closeStatus, string? description)
{ {
_logger.Information("Shard {ShardId}: Connection closed ({CloseStatus}/{Description})", _logger.Information("Shard {ShardId}: Connection closed ({CloseStatus}/{Description})",
_info.ShardId, closeStatus, description ?? "<null>"); _info.ShardId, closeStatus, description ?? "<null>");
await _stateManager.HandleConnectionClosed(); await _stateManager.HandleConnectionClosed();
SocketClosed?.Invoke(closeStatus, description); SocketClosed?.Invoke(closeStatus, description);

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
@ -13,11 +13,11 @@ namespace Myriad.Gateway
private ClientWebSocket? _client; private ClientWebSocket? _client;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ShardPacketSerializer _serializer; private readonly ShardPacketSerializer _serializer;
public WebSocketState State => _client?.State ?? WebSocketState.Closed; public WebSocketState State => _client?.State ?? WebSocketState.Closed;
public WebSocketCloseStatus? CloseStatus => _client?.CloseStatus; public WebSocketCloseStatus? CloseStatus => _client?.CloseStatus;
public string? CloseStatusDescription => _client?.CloseStatusDescription; public string? CloseStatusDescription => _client?.CloseStatusDescription;
public ShardConnection(JsonSerializerOptions jsonSerializerOptions, ILogger logger) public ShardConnection(JsonSerializerOptions jsonSerializerOptions, ILogger logger)
{ {
_logger = logger.ForContext<ShardConnection>(); _logger = logger.ForContext<ShardConnection>();
@ -28,7 +28,7 @@ namespace Myriad.Gateway
{ {
_client?.Dispose(); _client?.Dispose();
_client = new ClientWebSocket(); _client = new ClientWebSocket();
await _client.ConnectAsync(GetConnectionUri(url), ct); await _client.ConnectAsync(GetConnectionUri(url), ct);
} }
@ -40,7 +40,7 @@ namespace Myriad.Gateway
public async Task Send(GatewayPacket packet) public async Task Send(GatewayPacket packet)
{ {
// from `ManagedWebSocket.s_validSendStates` // from `ManagedWebSocket.s_validSendStates`
if (_client is not {State: WebSocketState.Open or WebSocketState.CloseReceived}) if (_client is not { State: WebSocketState.Open or WebSocketState.CloseReceived })
return; return;
try try
@ -62,7 +62,7 @@ namespace Myriad.Gateway
public async Task<GatewayPacket?> Read() public async Task<GatewayPacket?> Read()
{ {
// from `ManagedWebSocket.s_validReceiveStates` // from `ManagedWebSocket.s_validReceiveStates`
if (_client is not {State: WebSocketState.Open or WebSocketState.CloseSent}) if (_client is not { State: WebSocketState.Open or WebSocketState.CloseSent })
return null; return null;
try try
@ -79,7 +79,7 @@ namespace Myriad.Gateway
return null; return null;
} }
private Uri GetConnectionUri(string baseUri) => new UriBuilder(baseUri) private Uri GetConnectionUri(string baseUri) => new UriBuilder(baseUri)
{ {
Query = "v=9&encoding=json" Query = "v=9&encoding=json"
@ -89,10 +89,10 @@ namespace Myriad.Gateway
{ {
if (_client == null) if (_client == null)
return; return;
var client = _client; var client = _client;
_client = null; _client = null;
// from `ManagedWebSocket.s_validCloseStates` // from `ManagedWebSocket.s_validCloseStates`
if (client.State is WebSocketState.Open or WebSocketState.CloseReceived or WebSocketState.CloseSent) if (client.State is WebSocketState.Open or WebSocketState.CloseReceived or WebSocketState.CloseSent)
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway namespace Myriad.Gateway
{ {
public record ShardInfo(int ShardId, int NumShards); public record ShardInfo(int ShardId, int NumShards);
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.IO; using System.IO;
using System.Net.WebSockets; using System.Net.WebSockets;
@ -10,7 +10,7 @@ namespace Myriad.Gateway
public class ShardPacketSerializer public class ShardPacketSerializer
{ {
private const int BufferSize = 64 * 1024; private const int BufferSize = 64 * 1024;
private readonly JsonSerializerOptions _jsonSerializerOptions; private readonly JsonSerializerOptions _jsonSerializerOptions;
public ShardPacketSerializer(JsonSerializerOptions jsonSerializerOptions) public ShardPacketSerializer(JsonSerializerOptions jsonSerializerOptions)
@ -21,15 +21,15 @@ namespace Myriad.Gateway
public async ValueTask<(WebSocketMessageType type, GatewayPacket? packet)> ReadPacket(ClientWebSocket socket) public async ValueTask<(WebSocketMessageType type, GatewayPacket? packet)> ReadPacket(ClientWebSocket socket)
{ {
using var buf = MemoryPool<byte>.Shared.Rent(BufferSize); using var buf = MemoryPool<byte>.Shared.Rent(BufferSize);
var res = await socket.ReceiveAsync(buf.Memory, default); var res = await socket.ReceiveAsync(buf.Memory, default);
if (res.MessageType == WebSocketMessageType.Close) if (res.MessageType == WebSocketMessageType.Close)
return (res.MessageType, null); return (res.MessageType, null);
if (res.EndOfMessage) if (res.EndOfMessage)
// Entire packet fits within one buffer, deserialize directly // Entire packet fits within one buffer, deserialize directly
return DeserializeSingleBuffer(buf, res); return DeserializeSingleBuffer(buf, res);
// Otherwise copy to stream buffer and deserialize from there // Otherwise copy to stream buffer and deserialize from there
return await DeserializeMultipleBuffer(socket, buf, res); return await DeserializeMultipleBuffer(socket, buf, res);
} }
@ -51,7 +51,7 @@ namespace Myriad.Gateway
stream.Write(buf.Memory.Span.Slice(0, res.Count)); stream.Write(buf.Memory.Span.Slice(0, res.Count));
} }
return DeserializeObject(res, stream.GetBuffer().AsSpan(0, (int) stream.Length)); return DeserializeObject(res, stream.GetBuffer().AsSpan(0, (int)stream.Length));
} }
private (WebSocketMessageType type, GatewayPacket packet) DeserializeSingleBuffer( private (WebSocketMessageType type, GatewayPacket packet) DeserializeSingleBuffer(

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -8,7 +8,7 @@ namespace Myriad.Gateway.State
{ {
private Task? _worker; private Task? _worker;
private CancellationTokenSource? _workerCts; private CancellationTokenSource? _workerCts;
public TimeSpan? CurrentHeartbeatInterval { get; private set; } public TimeSpan? CurrentHeartbeatInterval { get; private set; }
public async ValueTask Start(TimeSpan heartbeatInterval, Func<Task> callback) public async ValueTask Start(TimeSpan heartbeatInterval, Func<Task> callback)
@ -23,9 +23,9 @@ namespace Myriad.Gateway.State
public async ValueTask Stop() public async ValueTask Stop()
{ {
if (_worker == null) if (_worker == null)
return; return;
_workerCts?.Cancel(); _workerCts?.Cancel();
try try
{ {
@ -38,12 +38,12 @@ namespace Myriad.Gateway.State
_worker = null; _worker = null;
CurrentHeartbeatInterval = null; CurrentHeartbeatInterval = null;
} }
private async Task Worker(TimeSpan heartbeatInterval, Func<Task> callback, CancellationToken ct) private async Task Worker(TimeSpan heartbeatInterval, Func<Task> callback, CancellationToken ct)
{ {
var initialDelay = GetInitialHeartbeatDelay(heartbeatInterval); var initialDelay = GetInitialHeartbeatDelay(heartbeatInterval);
await Task.Delay(initialDelay, ct); await Task.Delay(initialDelay, ct);
while (!ct.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
await callback(); await callback();

View File

@ -1,4 +1,4 @@
namespace Myriad.Gateway.State namespace Myriad.Gateway.State
{ {
public enum ShardState public enum ShardState
{ {

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -18,7 +18,7 @@ namespace Myriad.Gateway
private readonly ShardInfo _info; private readonly ShardInfo _info;
private readonly JsonSerializerOptions _jsonSerializerOptions; private readonly JsonSerializerOptions _jsonSerializerOptions;
private ShardState _state = ShardState.Disconnected; private ShardState _state = ShardState.Disconnected;
private DateTimeOffset? _lastHeartbeatSent; private DateTimeOffset? _lastHeartbeatSent;
private TimeSpan? _latency; private TimeSpan? _latency;
private bool _hasReceivedHeartbeatAck; private bool _hasReceivedHeartbeatAck;
@ -30,7 +30,7 @@ namespace Myriad.Gateway
public TimeSpan? Latency => _latency; public TimeSpan? Latency => _latency;
public User? User { get; private set; } public User? User { get; private set; }
public ApplicationPartial? Application { get; private set; } public ApplicationPartial? Application { get; private set; }
public Func<Task> SendIdentify { get; init; } public Func<Task> SendIdentify { get; init; }
public Func<(string SessionId, int? LastSeq), Task> SendResume { get; init; } public Func<(string SessionId, int? LastSeq), Task> SendResume { get; init; }
public Func<int?, Task> SendHeartbeat { get; init; } public Func<int?, Task> SendHeartbeat { get; init; }
@ -52,7 +52,7 @@ namespace Myriad.Gateway
_state = ShardState.Handshaking; _state = ShardState.Handshaking;
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task HandleConnectionClosed() public async Task HandleConnectionClosed()
{ {
_latency = null; _latency = null;
@ -71,36 +71,36 @@ namespace Myriad.Gateway
case GatewayOpcode.Heartbeat: case GatewayOpcode.Heartbeat:
await HandleHeartbeatRequest(); await HandleHeartbeatRequest();
break; break;
case GatewayOpcode.HeartbeatAck: case GatewayOpcode.HeartbeatAck:
await HandleHeartbeatAck(); await HandleHeartbeatAck();
break; break;
case GatewayOpcode.Reconnect: case GatewayOpcode.Reconnect:
{ {
await HandleReconnect(); await HandleReconnect();
break; break;
} }
case GatewayOpcode.InvalidSession: case GatewayOpcode.InvalidSession:
{ {
var canResume = DeserializePayload<bool>(packet); var canResume = DeserializePayload<bool>(packet);
await HandleInvalidSession(canResume); await HandleInvalidSession(canResume);
break; break;
} }
case GatewayOpcode.Dispatch: case GatewayOpcode.Dispatch:
_lastSeq = packet.Sequence; _lastSeq = packet.Sequence;
var evt = DeserializeEvent(packet.EventType!, (JsonElement) packet.Payload!); var evt = DeserializeEvent(packet.EventType!, (JsonElement)packet.Payload!);
if (evt != null) if (evt != null)
{ {
if (evt is ReadyEvent ready) if (evt is ReadyEvent ready)
await HandleReady(ready); await HandleReady(ready);
if (evt is ResumedEvent) if (evt is ResumedEvent)
await HandleResumed(); await HandleResumed();
await HandleEvent(evt); await HandleEvent(evt);
} }
break; break;
@ -110,7 +110,7 @@ namespace Myriad.Gateway
private async Task HandleHello(GatewayHello hello) private async Task HandleHello(GatewayHello hello)
{ {
var interval = TimeSpan.FromMilliseconds(hello.HeartbeatInterval); var interval = TimeSpan.FromMilliseconds(hello.HeartbeatInterval);
_hasReceivedHeartbeatAck = true; _hasReceivedHeartbeatAck = true;
await _heartbeatWorker.Start(interval, HandleHeartbeatTimer); await _heartbeatWorker.Start(interval, HandleHeartbeatTimer);
await IdentifyOrResume(); await IdentifyOrResume();
@ -152,14 +152,14 @@ namespace Myriad.Gateway
_sessionId = null; _sessionId = null;
_lastSeq = null; _lastSeq = null;
} }
_logger.Information("Shard {ShardId}: Received Invalid Session (can resume? {CanResume})", _logger.Information("Shard {ShardId}: Received Invalid Session (can resume? {CanResume})",
_info.ShardId, canResume); _info.ShardId, canResume);
var delay = TimeSpan.FromMilliseconds(new Random().Next(1000, 5000)); var delay = TimeSpan.FromMilliseconds(new Random().Next(1000, 5000));
await DoReconnect(WebSocketCloseStatus.NormalClosure, delay); await DoReconnect(WebSocketCloseStatus.NormalClosure, delay);
} }
private async Task HandleReconnect() private async Task HandleReconnect()
{ {
_logger.Information("Shard {ShardId}: Received Reconnect", _info.ShardId); _logger.Information("Shard {ShardId}: Received Reconnect", _info.ShardId);
@ -167,7 +167,7 @@ namespace Myriad.Gateway
// we use 1005 (no error specified) instead // we use 1005 (no error specified) instead
await DoReconnect(WebSocketCloseStatus.Empty, TimeSpan.FromSeconds(1)); await DoReconnect(WebSocketCloseStatus.Empty, TimeSpan.FromSeconds(1));
} }
private Task HandleReady(ReadyEvent ready) private Task HandleReady(ReadyEvent ready)
{ {
_logger.Information("Shard {ShardId}: Received Ready", _info.ShardId); _logger.Information("Shard {ShardId}: Received Ready", _info.ShardId);
@ -218,10 +218,10 @@ namespace Myriad.Gateway
private T DeserializePayload<T>(GatewayPacket packet) private T DeserializePayload<T>(GatewayPacket packet)
{ {
var packetPayload = (JsonElement) packet.Payload!; var packetPayload = (JsonElement)packet.Payload!;
return JsonSerializer.Deserialize<T>(packetPayload.GetRawText(), _jsonSerializerOptions)!; return JsonSerializer.Deserialize<T>(packetPayload.GetRawText(), _jsonSerializerOptions)!;
} }
private IGatewayEvent? DeserializeEvent(string eventType, JsonElement payload) private IGatewayEvent? DeserializeEvent(string eventType, JsonElement payload)
{ {
if (!IGatewayEvent.EventTypes.TryGetValue(eventType, out var clrType)) if (!IGatewayEvent.EventTypes.TryGetValue(eventType, out var clrType))

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Net; using System.Net;
@ -52,7 +52,7 @@ namespace Myriad.Rest
var waitPolicy = Policy var waitPolicy = Policy
.Handle<RatelimitBucketExhaustedException>() .Handle<RatelimitBucketExhaustedException>()
.WaitAndRetryAsync(3, .WaitAndRetryAsync(3,
(_, e, _) => ((RatelimitBucketExhaustedException) e).RetryAfter, (_, e, _) => ((RatelimitBucketExhaustedException)e).RetryAfter,
(_, _, _, _) => Task.CompletedTask) (_, _, _, _) => Task.CompletedTask)
.AsAsyncPolicy<HttpResponseMessage>(); .AsAsyncPolicy<HttpResponseMessage>();
@ -68,7 +68,7 @@ namespace Myriad.Rest
return default; return default;
} }
public async Task<T?> Get<T>(string path, (string endpointName, ulong major) ratelimitParams) where T: class public async Task<T?> Get<T>(string path, (string endpointName, ulong major) ratelimitParams) where T : class
{ {
using var response = await Send(() => new HttpRequestMessage(HttpMethod.Get, ApiBaseUrl + path), using var response = await Send(() => new HttpRequestMessage(HttpMethod.Get, ApiBaseUrl + path),
ratelimitParams, true); ratelimitParams, true);
@ -81,7 +81,7 @@ namespace Myriad.Rest
} }
public async Task<T?> Post<T>(string path, (string endpointName, ulong major) ratelimitParams, object? body) public async Task<T?> Post<T>(string path, (string endpointName, ulong major) ratelimitParams, object? body)
where T: class where T : class
{ {
using var response = await Send(() => using var response = await Send(() =>
{ {
@ -91,9 +91,9 @@ namespace Myriad.Rest
}, ratelimitParams); }, ratelimitParams);
return await ReadResponse<T>(response); return await ReadResponse<T>(response);
} }
public async Task<T?> PostMultipart<T>(string path, (string endpointName, ulong major) ratelimitParams, object? payload, MultipartFile[]? files) public async Task<T?> PostMultipart<T>(string path, (string endpointName, ulong major) ratelimitParams, object? payload, MultipartFile[]? files)
where T: class where T : class
{ {
using var response = await Send(() => using var response = await Send(() =>
{ {
@ -105,7 +105,7 @@ namespace Myriad.Rest
} }
public async Task<T?> Patch<T>(string path, (string endpointName, ulong major) ratelimitParams, object? body) public async Task<T?> Patch<T>(string path, (string endpointName, ulong major) ratelimitParams, object? body)
where T: class where T : class
{ {
using var response = await Send(() => using var response = await Send(() =>
{ {
@ -117,7 +117,7 @@ namespace Myriad.Rest
} }
public async Task<T?> Put<T>(string path, (string endpointName, ulong major) ratelimitParams, object? body) public async Task<T?> Put<T>(string path, (string endpointName, ulong major) ratelimitParams, object? body)
where T: class where T : class
{ {
using var response = await Send(() => using var response = await Send(() =>
{ {
@ -160,7 +160,7 @@ namespace Myriad.Rest
request.Content = mfd; request.Content = mfd;
} }
private async Task<T?> ReadResponse<T>(HttpResponseMessage response) where T: class private async Task<T?> ReadResponse<T>(HttpResponseMessage response) where T : class
{ {
if (response.StatusCode == HttpStatusCode.NoContent) if (response.StatusCode == HttpStatusCode.NoContent)
return null; return null;
@ -174,7 +174,7 @@ namespace Myriad.Rest
return await _retryPolicy.ExecuteAsync(async _ => return await _retryPolicy.ExecuteAsync(async _ =>
{ {
using var __ = LogContext.PushProperty("EndpointName", ratelimitParams.endpointName); using var __ = LogContext.PushProperty("EndpointName", ratelimitParams.endpointName);
var request = createRequest(); var request = createRequest();
_logger.Debug("Request: {RequestMethod} {RequestPath}", _logger.Debug("Request: {RequestMethod} {RequestPath}",
request.Method, request.RequestUri); request.Method, request.RequestUri);
@ -189,7 +189,7 @@ namespace Myriad.Rest
_logger.Debug( _logger.Debug(
"Response: {RequestMethod} {RequestPath} -> {StatusCode} {ReasonPhrase} (in {ResponseDurationMs} ms)", "Response: {RequestMethod} {RequestPath} -> {StatusCode} {ReasonPhrase} (in {ResponseDurationMs} ms)",
request.Method, request.RequestUri, (int) response.StatusCode, response.ReasonPhrase, stopwatch.ElapsedMilliseconds); request.Method, request.RequestUri, (int)response.StatusCode, response.ReasonPhrase, stopwatch.ElapsedMilliseconds);
await HandleApiError(response, ignoreNotFound); await HandleApiError(response, ignoreNotFound);
@ -211,7 +211,7 @@ namespace Myriad.Rest
return; return;
var body = await response.Content.ReadAsStringAsync(); var body = await response.Content.ReadAsStringAsync();
var apiError = TryParseApiError(body); var apiError = TryParseApiError(body);
if (apiError != null) if (apiError != null)
_logger.Warning("Discord API error: {DiscordErrorCode} {DiscordErrorMessage}", apiError.Code, apiError.Message); _logger.Warning("Discord API error: {DiscordErrorCode} {DiscordErrorMessage}", apiError.Code, apiError.Message);

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -34,7 +34,7 @@ namespace Myriad.Rest
public Task<Guild?> GetGuild(ulong id) => public Task<Guild?> GetGuild(ulong id) =>
_client.Get<Guild>($"/guilds/{id}", ("GetGuild", id)); _client.Get<Guild>($"/guilds/{id}", ("GetGuild", id));
public Task<Channel[]> GetGuildChannels(ulong id) => public Task<Channel[]> GetGuildChannels(ulong id) =>
_client.Get<Channel[]>($"/guilds/{id}/channels", ("GetGuildChannels", id))!; _client.Get<Channel[]>($"/guilds/{id}/channels", ("GetGuildChannels", id))!;
@ -108,7 +108,7 @@ namespace Myriad.Rest
public Task<Webhook> CreateWebhook(ulong channelId, CreateWebhookRequest request) => public Task<Webhook> CreateWebhook(ulong channelId, CreateWebhookRequest request) =>
_client.Post<Webhook>($"/channels/{channelId}/webhooks", ("CreateWebhook", channelId), request)!; _client.Post<Webhook>($"/channels/{channelId}/webhooks", ("CreateWebhook", channelId), request)!;
public Task<Webhook> GetWebhook(ulong webhookId) => public Task<Webhook> GetWebhook(ulong webhookId) =>
_client.Get<Webhook>($"/webhooks/{webhookId}/webhooks", ("GetWebhook", webhookId))!; _client.Get<Webhook>($"/webhooks/{webhookId}/webhooks", ("GetWebhook", webhookId))!;
@ -121,7 +121,7 @@ namespace Myriad.Rest
var url = $"/webhooks/{webhookId}/{webhookToken}?wait=true"; var url = $"/webhooks/{webhookId}/{webhookToken}?wait=true";
if (threadId != null) if (threadId != null)
url += $"&thread_id={threadId}"; url += $"&thread_id={threadId}";
return _client.PostMultipart<Message>(url, return _client.PostMultipart<Message>(url,
("ExecuteWebhook", webhookId), request, files)!; ("ExecuteWebhook", webhookId), request, files)!;
} }

View File

@ -1,4 +1,4 @@
using System.Text.Json; using System.Text.Json;
namespace Myriad.Rest namespace Myriad.Rest
{ {

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
@ -29,43 +29,49 @@ namespace Myriad.Rest.Exceptions
public class NotFoundException: DiscordRequestException public class NotFoundException: DiscordRequestException
{ {
public NotFoundException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base( public NotFoundException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
response, responseBody, apiError) { } response, responseBody, apiError)
{ }
} }
public class UnauthorizedException: DiscordRequestException public class UnauthorizedException: DiscordRequestException
{ {
public UnauthorizedException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base( public UnauthorizedException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
response, responseBody, apiError) { } response, responseBody, apiError)
{ }
} }
public class ForbiddenException: DiscordRequestException public class ForbiddenException: DiscordRequestException
{ {
public ForbiddenException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base( public ForbiddenException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
response, responseBody, apiError) { } response, responseBody, apiError)
{ }
} }
public class ConflictException: DiscordRequestException public class ConflictException: DiscordRequestException
{ {
public ConflictException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base( public ConflictException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
response, responseBody, apiError) { } response, responseBody, apiError)
{ }
} }
public class BadRequestException: DiscordRequestException public class BadRequestException: DiscordRequestException
{ {
public BadRequestException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base( public BadRequestException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
response, responseBody, apiError) { } response, responseBody, apiError)
{ }
} }
public class TooManyRequestsException: DiscordRequestException public class TooManyRequestsException: DiscordRequestException
{ {
public TooManyRequestsException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): public TooManyRequestsException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) :
base(response, responseBody, apiError) { } base(response, responseBody, apiError)
{ }
} }
public class UnknownDiscordRequestException: DiscordRequestException public class UnknownDiscordRequestException: DiscordRequestException
{ {
public UnknownDiscordRequestException(HttpResponseMessage response, string responseBody, public UnknownDiscordRequestException(HttpResponseMessage response, string responseBody,
DiscordApiError? apiError): base(response, responseBody, apiError) { } DiscordApiError? apiError) : base(response, responseBody, apiError) { }
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using Myriad.Rest.Ratelimit; using Myriad.Rest.Ratelimit;
@ -6,12 +6,12 @@ namespace Myriad.Rest.Exceptions
{ {
public class RatelimitException: Exception public class RatelimitException: Exception
{ {
public RatelimitException(string? message): base(message) { } public RatelimitException(string? message) : base(message) { }
} }
public class RatelimitBucketExhaustedException: RatelimitException public class RatelimitBucketExhaustedException: RatelimitException
{ {
public RatelimitBucketExhaustedException(Bucket bucket, TimeSpan retryAfter): base( public RatelimitBucketExhaustedException(Bucket bucket, TimeSpan retryAfter) : base(
"Rate limit bucket exhausted, request blocked") "Rate limit bucket exhausted, request blocked")
{ {
Bucket = bucket; Bucket = bucket;
@ -24,6 +24,6 @@ namespace Myriad.Rest.Exceptions
public class GloballyRatelimitedException: RatelimitException public class GloballyRatelimitedException: RatelimitException
{ {
public GloballyRatelimitedException(): base("Global rate limit hit") { } public GloballyRatelimitedException() : base("Global rate limit hit") { }
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using Serilog; using Serilog;
@ -54,7 +54,7 @@ namespace Myriad.Rest.Ratelimit
"{BucketKey}/{BucketMajor}: Bucket has [{BucketRemaining}/{BucketLimit} left], allowing through", "{BucketKey}/{BucketMajor}: Bucket has [{BucketRemaining}/{BucketLimit} left], allowing through",
Key, Major, Remaining, Limit); Key, Major, Remaining, Limit);
Remaining--; Remaining--;
return true; return true;
} }
@ -73,7 +73,7 @@ namespace Myriad.Rest.Ratelimit
try try
{ {
_semaphore.Wait(); _semaphore.Wait();
_logger.Verbose("{BucketKey}/{BucketMajor}: Received rate limit headers: {@RateLimitHeaders}", _logger.Verbose("{BucketKey}/{BucketMajor}: Received rate limit headers: {@RateLimitHeaders}",
Key, Major, headers); Key, Major, headers);
@ -90,7 +90,7 @@ namespace Myriad.Rest.Ratelimit
} }
} }
if (headers.Limit != null) if (headers.Limit != null)
Limit = headers.Limit.Value; Limit = headers.Limit.Value;
if (headers.Remaining != null && !_hasReceivedHeaders) if (headers.Remaining != null && !_hasReceivedHeaders)
@ -98,7 +98,7 @@ namespace Myriad.Rest.Ratelimit
var oldRemaining = Remaining; var oldRemaining = Remaining;
Remaining = Math.Min(headers.Remaining.Value, Remaining); Remaining = Math.Min(headers.Remaining.Value, Remaining);
_logger.Debug("{BucketKey}/{BucketMajor}: Received first remaining of {HeaderRemaining}, previous local remaining is {LocalRemaining}, new local remaining is {Remaining}", _logger.Debug("{BucketKey}/{BucketMajor}: Received first remaining of {HeaderRemaining}, previous local remaining is {LocalRemaining}, new local remaining is {Remaining}",
Key, Major, headers.Remaining.Value, oldRemaining, Remaining); Key, Major, headers.Remaining.Value, oldRemaining, Remaining);
_hasReceivedHeaders = true; _hasReceivedHeaders = true;
} }
@ -114,7 +114,7 @@ namespace Myriad.Rest.Ratelimit
try try
{ {
_semaphore.Wait(); _semaphore.Wait();
// If we don't have any reset data, "snap" it to now // If we don't have any reset data, "snap" it to now
// This happens before first request and at this point the reset is invalid anyway, so it's fine // This happens before first request and at this point the reset is invalid anyway, so it's fine
// but it ensures the stale timeout doesn't trigger early by using `default` value // but it ensures the stale timeout doesn't trigger early by using `default` value

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -72,7 +72,7 @@ namespace Myriad.Rest.Ratelimit
{ {
if (now - bucket.LastUsed <= StaleBucketTimeout) if (now - bucket.LastUsed <= StaleBucketTimeout)
continue; continue;
_logger.Debug("Pruning unused bucket {BucketKey}/{BucketMajor} (last used at {BucketLastUsed})", _logger.Debug("Pruning unused bucket {BucketKey}/{BucketMajor} (last used at {BucketLastUsed})",
bucket.Key, bucket.Major, bucket.LastUsed); bucket.Key, bucket.Major, bucket.LastUsed);
_buckets.TryRemove(key, out _); _buckets.TryRemove(key, out _);

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
@ -13,7 +13,7 @@ namespace Myriad.Rest.Ratelimit
private const string ResetAfterHeader = "X-RateLimit-Reset-After"; private const string ResetAfterHeader = "X-RateLimit-Reset-After";
private const string BucketHeader = "X-RateLimit-Bucket"; private const string BucketHeader = "X-RateLimit-Bucket";
private const string GlobalHeader = "X-RateLimit-Global"; private const string GlobalHeader = "X-RateLimit-Global";
public bool Global { get; private set; } public bool Global { get; private set; }
public int? Limit { get; private set; } public int? Limit { get; private set; }
public int? Remaining { get; private set; } public int? Remaining { get; private set; }
@ -25,7 +25,7 @@ namespace Myriad.Rest.Ratelimit
public bool HasRatelimitInfo => public bool HasRatelimitInfo =>
Limit != null && Remaining != null && Reset != null && ResetAfter != null && Bucket != null; Limit != null && Remaining != null && Reset != null && ResetAfter != null && Bucket != null;
public RatelimitHeaders() { } public RatelimitHeaders() { }
public static RatelimitHeaders Parse(HttpResponseMessage response) public static RatelimitHeaders Parse(HttpResponseMessage response)
@ -41,12 +41,12 @@ namespace Myriad.Rest.Ratelimit
var resetTimestamp = TryGetDouble(response, ResetHeader); var resetTimestamp = TryGetDouble(response, ResetHeader);
if (resetTimestamp != null) if (resetTimestamp != null)
headers.Reset = DateTimeOffset.FromUnixTimeMilliseconds((long) (resetTimestamp.Value * 1000)); headers.Reset = DateTimeOffset.FromUnixTimeMilliseconds((long)(resetTimestamp.Value * 1000));
var resetAfterSeconds = TryGetDouble(response, ResetAfterHeader); var resetAfterSeconds = TryGetDouble(response, ResetAfterHeader);
if (resetAfterSeconds != null) if (resetAfterSeconds != null)
headers.ResetAfter = TimeSpan.FromSeconds(resetAfterSeconds.Value); headers.ResetAfter = TimeSpan.FromSeconds(resetAfterSeconds.Value);
var global = TryGetHeader(response, GlobalHeader); var global = TryGetHeader(response, GlobalHeader);
if (global != null && bool.TryParse(global, out var globalBool)) if (global != null && bool.TryParse(global, out var globalBool))
headers.Global = globalBool; headers.Global = globalBool;
@ -58,27 +58,27 @@ namespace Myriad.Rest.Ratelimit
{ {
if (!response.Headers.TryGetValues(headerName, out var values)) if (!response.Headers.TryGetValues(headerName, out var values))
return null; return null;
return values.FirstOrDefault(); return values.FirstOrDefault();
} }
private static int? TryGetInt(HttpResponseMessage response, string headerName) private static int? TryGetInt(HttpResponseMessage response, string headerName)
{ {
var valueString = TryGetHeader(response, headerName); var valueString = TryGetHeader(response, headerName);
if (!int.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) if (!int.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
return null; return null;
return value; return value;
} }
private static double? TryGetDouble(HttpResponseMessage response, string headerName) private static double? TryGetDouble(HttpResponseMessage response, string headerName)
{ {
var valueString = TryGetHeader(response, headerName); var valueString = TryGetHeader(response, headerName);
if (!double.TryParse(valueString, NumberStyles.Float, CultureInfo.InvariantCulture, out var value)) if (!double.TryParse(valueString, NumberStyles.Float, CultureInfo.InvariantCulture, out var value))
return null; return null;
return value; return value;
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using Myriad.Rest.Exceptions; using Myriad.Rest.Exceptions;

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Myriad.Serialization; using Myriad.Serialization;

View File

@ -1,4 +1,4 @@
using System.IO; using System.IO;
namespace Myriad.Rest.Types namespace Myriad.Rest.Types
{ {

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using Myriad.Types; using Myriad.Types;

View File

@ -1,4 +1,4 @@
namespace Myriad.Rest.Types.Requests namespace Myriad.Rest.Types.Requests
{ {
public record CreateDmRequest(ulong RecipientId); public record CreateDmRequest(ulong RecipientId);
} }

View File

@ -1,4 +1,4 @@
namespace Myriad.Rest.Types.Requests namespace Myriad.Rest.Types.Requests
{ {
public record CreateWebhookRequest(string Name); public record CreateWebhookRequest(string Name);
} }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Rest.Types.Requests namespace Myriad.Rest.Types.Requests
{ {

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Myriad.Types; using Myriad.Types;
using Myriad.Utils; using Myriad.Utils;
@ -8,14 +8,14 @@ namespace Myriad.Rest.Types.Requests
public record MessageEditRequest public record MessageEditRequest
{ {
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<string?> Content { get; init; } public Optional<string?> Content { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<Embed?> Embed { get; init; } public Optional<Embed?> Embed { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<Message.MessageFlags> Flags { get; init; } public Optional<Message.MessageFlags> Flags { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<AllowedMentions> AllowedMentions { get; init; } public Optional<AllowedMentions> AllowedMentions { get; init; }

View File

@ -1,4 +1,4 @@
using Myriad.Types; using Myriad.Types;
namespace Myriad.Rest.Types.Requests namespace Myriad.Rest.Types.Requests
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Rest.Types namespace Myriad.Rest.Types
{ {
public record ModifyGuildMemberRequest public record ModifyGuildMemberRequest
{ {

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Myriad.Utils; using Myriad.Utils;
@ -7,8 +7,8 @@ namespace Myriad.Rest.Types.Requests
public record WebhookMessageEditRequest public record WebhookMessageEditRequest
{ {
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<string?> Content { get; init; } public Optional<string?> Content { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<AllowedMentions> AllowedMentions { get; init; } public Optional<AllowedMentions> AllowedMentions { get; init; }
} }

View File

@ -1,4 +1,4 @@
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Myriad.Serialization namespace Myriad.Serialization

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Reflection; using System.Reflection;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -22,11 +22,11 @@ namespace Myriad.Serialization
JsonSerializer.Serialize(writer, value.HasValue ? value.GetValue() : default, typeof(T), options); JsonSerializer.Serialize(writer, value.HasValue ? value.GetValue() : default, typeof(T), options);
} }
} }
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{ {
var innerType = typeToConvert.GetGenericArguments()[0]; var innerType = typeToConvert.GetGenericArguments()[0];
return (JsonConverter?) Activator.CreateInstance( return (JsonConverter?)Activator.CreateInstance(
typeof(Inner<>).MakeGenericType(innerType), typeof(Inner<>).MakeGenericType(innerType),
BindingFlags.Instance | BindingFlags.Public, BindingFlags.Instance | BindingFlags.Public,
null, null,

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -13,12 +13,12 @@ namespace Myriad.Serialization
var str = reader.GetString(); var str = reader.GetString();
if (str == null) return default; if (str == null) return default;
return (PermissionSet) ulong.Parse(str); return (PermissionSet)ulong.Parse(str);
} }
public override void Write(Utf8JsonWriter writer, PermissionSet value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, PermissionSet value, JsonSerializerOptions options)
{ {
writer.WriteStringValue(((ulong) value).ToString()); writer.WriteStringValue(((ulong)value).ToString());
} }
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;

View File

@ -1,16 +1,16 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Activity: ActivityPartial public record Activity: ActivityPartial
{ {
} }
public record ActivityPartial public record ActivityPartial
{ {
public string Name { get; init; } public string Name { get; init; }
public ActivityType Type { get; init; } public ActivityType Type { get; init; }
public string? Url { get; init; } public string? Url { get; init; }
} }
public enum ActivityType public enum ActivityType
{ {
Game = 0, Game = 0,

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Application: ApplicationPartial public record Application: ApplicationPartial
{ {
@ -16,7 +16,7 @@
public string? Slug { get; init; } public string? Slug { get; init; }
public string? CoverImage { get; init; } public string? CoverImage { get; init; }
} }
public record ApplicationPartial public record ApplicationPartial
{ {
public ulong Id { get; init; } public ulong Id { get; init; }

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record ApplicationCommand public record ApplicationCommand
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record ApplicationCommandInteractionData public record ApplicationCommandInteractionData
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record ApplicationCommandInteractionDataOption public record ApplicationCommandInteractionDataOption
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record ApplicationCommandOption(ApplicationCommandOption.OptionType Type, string Name, string Description) public record ApplicationCommandOption(ApplicationCommandOption.OptionType Type, string Name, string Description)
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Interaction public record Interaction
{ {

View File

@ -1,4 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Myriad.Rest.Types; using Myriad.Rest.Types;
using Myriad.Utils; using Myriad.Utils;
@ -9,19 +9,19 @@ namespace Myriad.Types
{ {
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<bool?> Tts { get; init; } public Optional<bool?> Tts { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<string?> Content { get; init; } public Optional<string?> Content { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<Embed[]?> Embeds { get; init; } public Optional<Embed[]?> Embeds { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<AllowedMentions?> AllowedMentions { get; init; } public Optional<AllowedMentions?> AllowedMentions { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<Message.MessageFlags> Flags { get; init; } public Optional<Message.MessageFlags> Flags { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<MessageComponent[]?> Components { get; init; } public Optional<MessageComponent[]?> Components { get; init; }
} }

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record InteractionResponse public record InteractionResponse
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Channel public record Channel
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Embed public record Embed
{ {
@ -16,44 +16,44 @@
public EmbedAuthor? Author { get; init; } public EmbedAuthor? Author { get; init; }
public Field[]? Fields { get; init; } public Field[]? Fields { get; init; }
public record EmbedFooter ( public record EmbedFooter(
string Text, string Text,
string? IconUrl = null, string? IconUrl = null,
string? ProxyIconUrl = null string? ProxyIconUrl = null
); );
public record EmbedImage ( public record EmbedImage(
string? Url, string? Url,
uint? Width = null, uint? Width = null,
uint? Height = null uint? Height = null
); );
public record EmbedThumbnail ( public record EmbedThumbnail(
string? Url, string? Url,
string? ProxyUrl = null, string? ProxyUrl = null,
uint? Width = null, uint? Width = null,
uint? Height = null uint? Height = null
); );
public record EmbedVideo ( public record EmbedVideo(
string? Url, string? Url,
uint? Width = null, uint? Width = null,
uint? Height = null uint? Height = null
); );
public record EmbedProvider ( public record EmbedProvider(
string? Name, string? Name,
string? Url string? Url
); );
public record EmbedAuthor ( public record EmbedAuthor(
string? Name = null, string? Name = null,
string? Url = null, string? Url = null,
string? IconUrl = null, string? IconUrl = null,
string? ProxyIconUrl = null string? ProxyIconUrl = null
); );
public record Field ( public record Field(
string Name, string Name,
string Value, string Value,
bool Inline = false bool Inline = false

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Emoji public record Emoji
{ {

View File

@ -1,9 +1,9 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record GatewayInfo public record GatewayInfo
{ {
public string Url { get; init; } public string Url { get; init; }
public record Bot: GatewayInfo public record Bot: GatewayInfo
{ {
public int Shards { get; init; } public int Shards { get; init; }

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record SessionStartLimit public record SessionStartLimit
{ {

View File

@ -1,4 +1,4 @@
namespace Myriad.Types namespace Myriad.Types
{ {
public record Guild public record Guild
{ {

Some files were not shown because too many files have changed in this diff Show More