run dotnet format
This commit is contained in:
parent
05989242f9
commit
ac2671452d
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Myriad.Types;
|
||||
|
||||
@ -11,66 +11,71 @@ namespace Myriad.Builders
|
||||
|
||||
public EmbedBuilder Title(string? title)
|
||||
{
|
||||
_embed = _embed with {Title = title};
|
||||
_embed = _embed with { Title = title };
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Description(string? description)
|
||||
{
|
||||
_embed = _embed with { Description = description};
|
||||
_embed = _embed with { Description = description };
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Url(string? url)
|
||||
{
|
||||
_embed = _embed with {Url = url};
|
||||
_embed = _embed with { Url = url };
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Color(uint? color)
|
||||
{
|
||||
_embed = _embed with {Color = color};
|
||||
_embed = _embed with { Color = color };
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Footer(Embed.EmbedFooter? footer)
|
||||
{
|
||||
_embed = _embed with {
|
||||
_embed = _embed with
|
||||
{
|
||||
Footer = footer
|
||||
};
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Image(Embed.EmbedImage? image)
|
||||
{
|
||||
_embed = _embed with {
|
||||
_embed = _embed with
|
||||
{
|
||||
Image = image
|
||||
};
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public EmbedBuilder Thumbnail(Embed.EmbedThumbnail? thumbnail)
|
||||
{
|
||||
_embed = _embed with {
|
||||
_embed = _embed with
|
||||
{
|
||||
Thumbnail = thumbnail
|
||||
};
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Author(Embed.EmbedAuthor? author)
|
||||
{
|
||||
_embed = _embed with {
|
||||
_embed = _embed with
|
||||
{
|
||||
Author = author
|
||||
};
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbedBuilder Timestamp(string? timestamp)
|
||||
{
|
||||
_embed = _embed with {
|
||||
_embed = _embed with
|
||||
{
|
||||
Timestamp = timestamp
|
||||
};
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Gateway;
|
||||
|
||||
@ -69,9 +69,9 @@ namespace Myriad.Cache
|
||||
private static async ValueTask SaveMessageCreate(this IDiscordCache cache, MessageCreateEvent evt)
|
||||
{
|
||||
await cache.TrySaveDmChannelStub(evt.GuildId, evt.ChannelId);
|
||||
|
||||
|
||||
await cache.SaveUser(evt.Author);
|
||||
foreach (var mention in evt.Mentions)
|
||||
foreach (var mention in evt.Mentions)
|
||||
await cache.SaveUser(mention);
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ namespace Myriad.Cache
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Types;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -15,7 +15,7 @@ namespace Myriad.Cache
|
||||
private readonly ConcurrentDictionary<ulong, CachedGuild> _guilds = new();
|
||||
private readonly ConcurrentDictionary<ulong, Role> _roles = new();
|
||||
private readonly ConcurrentDictionary<ulong, User> _users = new();
|
||||
|
||||
|
||||
public ValueTask SaveGuild(Guild guild)
|
||||
{
|
||||
SaveGuildRaw(guild);
|
||||
@ -61,18 +61,20 @@ namespace Myriad.Cache
|
||||
var found = false;
|
||||
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;
|
||||
|
||||
|
||||
guild.Guild.Roles[i] = role;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
_guilds[guildId] = guild with {
|
||||
Guild = guild.Guild with {
|
||||
Roles = guild.Guild.Roles.Concat(new[] { role}).ToArray()
|
||||
_guilds[guildId] = guild with
|
||||
{
|
||||
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
|
||||
_channels.GetOrAdd(channelId, id => new Channel
|
||||
{
|
||||
Id = id,
|
||||
Id = id,
|
||||
Type = Channel.ChannelType.Dm
|
||||
});
|
||||
return default;
|
||||
@ -134,7 +136,7 @@ namespace Myriad.Cache
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetChannel(ulong channelId, out Channel channel) =>
|
||||
public bool TryGetChannel(ulong channelId, out Channel channel) =>
|
||||
_channels.TryGetValue(channelId, out channel!);
|
||||
|
||||
public bool TryGetDmChannel(ulong userId, out Channel channel)
|
||||
@ -143,7 +145,7 @@ namespace Myriad.Cache
|
||||
if (!_dmChannels.TryGetValue(userId, out var channelId))
|
||||
return false;
|
||||
return TryGetChannel(channelId, out channel);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetUser(ulong userId, out User user) =>
|
||||
_users.TryGetValue(userId, out user!);
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Myriad.Cache;
|
||||
@ -15,7 +15,7 @@ namespace Myriad.Extensions
|
||||
throw new KeyNotFoundException($"Guild {guildId} not found in cache");
|
||||
return guild;
|
||||
}
|
||||
|
||||
|
||||
public static Channel GetChannel(this IDiscordCache cache, ulong channelId)
|
||||
{
|
||||
if (!cache.TryGetChannel(channelId, out var channel))
|
||||
@ -36,14 +36,14 @@ namespace Myriad.Extensions
|
||||
throw new KeyNotFoundException($"User {userId} not found in cache");
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
public static Role GetRole(this IDiscordCache cache, ulong roleId)
|
||||
{
|
||||
if (!cache.TryGetRole(roleId, out var role))
|
||||
throw new KeyNotFoundException($"User {roleId} not found in cache");
|
||||
return role;
|
||||
}
|
||||
|
||||
|
||||
public static async ValueTask<User?> GetOrFetchUser(this IDiscordCache cache, DiscordApiClient rest, ulong userId)
|
||||
{
|
||||
if (cache.TryGetUser(userId, out var cacheUser))
|
||||
@ -54,7 +54,7 @@ namespace Myriad.Extensions
|
||||
await cache.SaveUser(restUser);
|
||||
return restUser;
|
||||
}
|
||||
|
||||
|
||||
public static async ValueTask<Channel?> GetOrFetchChannel(this IDiscordCache cache, DiscordApiClient rest, ulong channelId)
|
||||
{
|
||||
if (cache.TryGetChannel(channelId, out var cacheChannel))
|
||||
@ -79,9 +79,9 @@ namespace Myriad.Extensions
|
||||
public static Channel GetRootChannel(this IDiscordCache cache, ulong channelOrThread)
|
||||
{
|
||||
var channel = cache.GetChannel(channelOrThread);
|
||||
if (!channel.IsThread())
|
||||
if (!channel.IsThread())
|
||||
return channel;
|
||||
|
||||
|
||||
var parent = cache.GetChannel(channel.ParentId!.Value);
|
||||
return parent;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Extensions
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace Myriad.Extensions
|
||||
namespace Myriad.Extensions
|
||||
{
|
||||
public static class GuildExtensions
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Gateway;
|
||||
using Myriad.Gateway;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Extensions
|
||||
@ -7,7 +7,7 @@ namespace Myriad.Extensions
|
||||
{
|
||||
public static string JumpLink(this Message msg) =>
|
||||
$"https://discord.com/channels/{msg.GuildId}/{msg.ChannelId}/{msg.Id}";
|
||||
|
||||
|
||||
public static string JumpLink(this MessageReactionAddEvent msg) =>
|
||||
$"https://discord.com/channels/{msg.GuildId}/{msg.ChannelId}/{msg.MessageId}";
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@ -21,12 +21,12 @@ namespace Myriad.Extensions
|
||||
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)
|
||||
@ -34,10 +34,10 @@ namespace Myriad.Extensions
|
||||
|
||||
return PermissionsFor(guild, rootChannel, userId, member);
|
||||
}
|
||||
|
||||
|
||||
public static PermissionSet EveryonePermissions(this Guild guild) =>
|
||||
guild.Roles.FirstOrDefault(r => r.Id == guild.Id)?.Permissions ?? PermissionSet.Dm;
|
||||
|
||||
|
||||
public static PermissionSet EveryonePermissions(this IDiscordCache cache, Channel channel)
|
||||
{
|
||||
if (channel.Type == Channel.ChannelType.Dm)
|
||||
@ -62,7 +62,7 @@ namespace Myriad.Extensions
|
||||
{
|
||||
if (channel.Type == Channel.ChannelType.Dm)
|
||||
return PermissionSet.Dm;
|
||||
|
||||
|
||||
if (member == null)
|
||||
// this happens with system (Discord platform-owned) users - they're not actually in the guild, so there is no member object.
|
||||
return EveryonePermissions(guild);
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
using Myriad.Types;
|
||||
|
||||
@ -7,7 +7,7 @@ namespace Myriad.Extensions
|
||||
public static class SnowflakeExtensions
|
||||
{
|
||||
public static readonly DateTimeOffset DiscordEpoch = new(2015, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
|
||||
|
||||
public static DateTimeOffset SnowflakeToTimestamp(ulong snowflake) =>
|
||||
DiscordEpoch + TimeSpan.FromMilliseconds(snowflake >> 22);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Extensions
|
||||
{
|
||||
@ -6,7 +6,7 @@ namespace Myriad.Extensions
|
||||
{
|
||||
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}";
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -30,7 +30,7 @@ namespace Myriad.Gateway
|
||||
public IReadOnlyDictionary<int, Shard> Shards => _shards;
|
||||
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 async Task Start(GatewayInfo.Bot info)
|
||||
{
|
||||
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)
|
||||
{
|
||||
_ratelimiter = GetRateLimiter(recommendedConcurrency);
|
||||
|
||||
|
||||
var shardCount = shardMax - shardMin + 1;
|
||||
_logger.Information("Starting {ShardCount} of {ShardTotal} shards (#{ShardMin}-#{ShardMax}) at {Url}",
|
||||
shardCount, shardTotal, shardMin, shardMax, url);
|
||||
@ -51,7 +51,7 @@ namespace Myriad.Gateway
|
||||
private async Task StartShards()
|
||||
{
|
||||
_logger.Information("Connecting shards...");
|
||||
foreach (var shard in _shards.Values)
|
||||
foreach (var shard in _shards.Values)
|
||||
await shard.Start();
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ namespace Myriad.Gateway
|
||||
var shard = new Shard(_gatewaySettings, shardInfo, _ratelimiter!, url, _logger);
|
||||
shard.OnEventReceived += evt => OnShardEventReceived(shard, evt);
|
||||
_shards[shardInfo.ShardId] = shard;
|
||||
|
||||
|
||||
ShardCreated?.Invoke(shard);
|
||||
}
|
||||
|
||||
@ -69,12 +69,12 @@ namespace Myriad.Gateway
|
||||
if (EventReceived != null)
|
||||
await EventReceived(shard, evt);
|
||||
}
|
||||
|
||||
|
||||
private int GetActualShardConcurrency(int recommendedConcurrency)
|
||||
{
|
||||
if (_gatewaySettings.MaxShardConcurrency == null)
|
||||
return recommendedConcurrency;
|
||||
|
||||
|
||||
return Math.Min(_gatewaySettings.MaxShardConcurrency.Value, recommendedConcurrency);
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ namespace Myriad.Gateway
|
||||
{
|
||||
return new TwilightGatewayRatelimiter(_logger, _gatewaySettings.GatewayQueueUrl);
|
||||
}
|
||||
|
||||
|
||||
var concurrency = GetActualShardConcurrency(recommendedConcurrency);
|
||||
return new LocalGatewayRatelimiter(_logger, concurrency);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record GuildDeleteEvent(ulong Id, bool Unavailable): IGatewayEvent;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record GuildRoleDeleteEvent(ulong GuildId, ulong RoleId): IGatewayEvent;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
@ -7,33 +7,33 @@ namespace Myriad.Gateway
|
||||
{
|
||||
public static readonly Dictionary<string, Type> EventTypes = new()
|
||||
{
|
||||
{"READY", typeof(ReadyEvent)},
|
||||
{"RESUMED", typeof(ResumedEvent)},
|
||||
{"GUILD_CREATE", typeof(GuildCreateEvent)},
|
||||
{"GUILD_UPDATE", typeof(GuildUpdateEvent)},
|
||||
{"GUILD_DELETE", typeof(GuildDeleteEvent)},
|
||||
{"GUILD_MEMBER_ADD", typeof(GuildMemberAddEvent)},
|
||||
{"GUILD_MEMBER_REMOVE", typeof(GuildMemberRemoveEvent)},
|
||||
{"GUILD_MEMBER_UPDATE", typeof(GuildMemberUpdateEvent)},
|
||||
{"GUILD_ROLE_CREATE", typeof(GuildRoleCreateEvent)},
|
||||
{"GUILD_ROLE_UPDATE", typeof(GuildRoleUpdateEvent)},
|
||||
{"GUILD_ROLE_DELETE", typeof(GuildRoleDeleteEvent)},
|
||||
{"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)},
|
||||
{"MESSAGE_DELETE_BULK", typeof(MessageDeleteBulkEvent)},
|
||||
{"MESSAGE_REACTION_ADD", typeof(MessageReactionAddEvent)},
|
||||
{"MESSAGE_REACTION_REMOVE", typeof(MessageReactionRemoveEvent)},
|
||||
{"MESSAGE_REACTION_REMOVE_ALL", typeof(MessageReactionRemoveAllEvent)},
|
||||
{"MESSAGE_REACTION_REMOVE_EMOJI", typeof(MessageReactionRemoveEmojiEvent)},
|
||||
{"INTERACTION_CREATE", typeof(InteractionCreateEvent)}
|
||||
{ "READY", typeof(ReadyEvent) },
|
||||
{ "RESUMED", typeof(ResumedEvent) },
|
||||
{ "GUILD_CREATE", typeof(GuildCreateEvent) },
|
||||
{ "GUILD_UPDATE", typeof(GuildUpdateEvent) },
|
||||
{ "GUILD_DELETE", typeof(GuildDeleteEvent) },
|
||||
{ "GUILD_MEMBER_ADD", typeof(GuildMemberAddEvent) },
|
||||
{ "GUILD_MEMBER_REMOVE", typeof(GuildMemberRemoveEvent) },
|
||||
{ "GUILD_MEMBER_UPDATE", typeof(GuildMemberUpdateEvent) },
|
||||
{ "GUILD_ROLE_CREATE", typeof(GuildRoleCreateEvent) },
|
||||
{ "GUILD_ROLE_UPDATE", typeof(GuildRoleUpdateEvent) },
|
||||
{ "GUILD_ROLE_DELETE", typeof(GuildRoleDeleteEvent) },
|
||||
{ "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) },
|
||||
{ "MESSAGE_DELETE_BULK", typeof(MessageDeleteBulkEvent) },
|
||||
{ "MESSAGE_REACTION_ADD", typeof(MessageReactionAddEvent) },
|
||||
{ "MESSAGE_REACTION_REMOVE", typeof(MessageReactionRemoveEvent) },
|
||||
{ "MESSAGE_REACTION_REMOVE_ALL", typeof(MessageReactionRemoveAllEvent) },
|
||||
{ "MESSAGE_REACTION_REMOVE_EMOJI", typeof(MessageReactionRemoveEmojiEvent) },
|
||||
{ "INTERACTION_CREATE", typeof(InteractionCreateEvent) }
|
||||
};
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record MessageDeleteBulkEvent(ulong[] Ids, ulong ChannelId, ulong? GuildId): IGatewayEvent;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record MessageDeleteEvent(ulong Id, ulong ChannelId, ulong? GuildId): IGatewayEvent;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record MessageReactionRemoveAllEvent(ulong ChannelId, ulong MessageId, ulong? GuildId): IGatewayEvent;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
using Myriad.Utils;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Myriad.Types;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record ResumedEvent: IGatewayEvent;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
// TODO: unused?
|
||||
public class GatewayCloseException: Exception
|
||||
{
|
||||
public GatewayCloseException(int closeCode, string closeReason): base($"{closeCode}: {closeReason}")
|
||||
public GatewayCloseException(int closeCode, string closeReason) : base($"{closeCode}: {closeReason}")
|
||||
{
|
||||
CloseCode = closeCode;
|
||||
CloseReason = closeReason;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
@ -7,10 +7,12 @@ namespace Myriad.Gateway
|
||||
[JsonPropertyName("op")] public GatewayOpcode Opcode { 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; }
|
||||
|
||||
[JsonPropertyName("t")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("t")]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? EventType { get; init; }
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record GatewaySettings
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Myriad.Gateway.Limit
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -14,7 +14,7 @@ namespace Myriad.Gateway.Limit
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(60)
|
||||
};
|
||||
|
||||
|
||||
public TwilightGatewayRatelimiter(ILogger logger, string url)
|
||||
{
|
||||
_url = url;
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record GatewayHello(int HeartbeatInterval);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record GatewayResume(string Token, string SessionId, int Seq);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Myriad.Serialization;
|
||||
using Myriad.Types;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
@ -68,18 +68,18 @@ namespace Myriad.Gateway
|
||||
|
||||
_conn = new ShardConnection(_jsonSerializerOptions, _logger);
|
||||
}
|
||||
|
||||
|
||||
private async Task ShardLoop()
|
||||
{
|
||||
// may be superfluous but this adds shard id to ambient context which is nice
|
||||
using var _ = LogContext.PushProperty("ShardId", _info.ShardId);
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectInner();
|
||||
|
||||
|
||||
await HandleConnectionOpened();
|
||||
|
||||
while (_conn.State == WebSocketState.Open)
|
||||
@ -90,7 +90,7 @@ namespace Myriad.Gateway
|
||||
|
||||
await _stateManager.HandlePacketReceived(packet);
|
||||
}
|
||||
|
||||
|
||||
await HandleConnectionClosed(_conn.CloseStatus, _conn.CloseStatusDescription);
|
||||
|
||||
_logger.Information("Shard {ShardId}: Reconnecting after delay {ReconnectDelay}",
|
||||
@ -103,20 +103,20 @@ namespace Myriad.Gateway
|
||||
catch (Exception e)
|
||||
{
|
||||
_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...
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task Start()
|
||||
{
|
||||
if (_worker == null)
|
||||
_worker = ShardLoop();
|
||||
|
||||
// we can probably TCS this instead of spin loop but w/e
|
||||
while (State != ShardState.Identifying)
|
||||
while (State != ShardState.Identifying)
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ namespace Myriad.Gateway
|
||||
Payload = payload
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private async Task ConnectInner()
|
||||
{
|
||||
while (true)
|
||||
@ -148,12 +148,12 @@ namespace Myriad.Gateway
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task DisconnectInner(WebSocketCloseStatus closeStatus)
|
||||
{
|
||||
await _conn.Disconnect(closeStatus, null);
|
||||
}
|
||||
|
||||
|
||||
private async Task SendIdentify()
|
||||
{
|
||||
await _conn.Send(new GatewayPacket
|
||||
@ -165,8 +165,8 @@ namespace Myriad.Gateway
|
||||
Intents = _settings.Intents,
|
||||
Properties = new GatewayIdentify.ConnectionProperties
|
||||
{
|
||||
Browser = LibraryName,
|
||||
Device = LibraryName,
|
||||
Browser = LibraryName,
|
||||
Device = LibraryName,
|
||||
Os = Environment.OSVersion.ToString()
|
||||
},
|
||||
Shard = _info,
|
||||
@ -175,7 +175,7 @@ namespace Myriad.Gateway
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private async Task SendResume((string SessionId, int? LastSeq) arg)
|
||||
{
|
||||
await _conn.Send(new GatewayPacket
|
||||
@ -184,12 +184,12 @@ namespace Myriad.Gateway
|
||||
Payload = new GatewayResume(_settings.Token, arg.SessionId, arg.LastSeq ?? 0)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
_reconnectDelay = delay;
|
||||
@ -202,7 +202,7 @@ namespace Myriad.Gateway
|
||||
Ready?.Invoke();
|
||||
if (arg is ResumedEvent)
|
||||
Resumed?.Invoke();
|
||||
|
||||
|
||||
await (OnEventReceived?.Invoke(arg) ?? Task.CompletedTask);
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ namespace Myriad.Gateway
|
||||
|
||||
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>");
|
||||
await _stateManager.HandleConnectionClosed();
|
||||
SocketClosed?.Invoke(closeStatus, description);
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
@ -13,11 +13,11 @@ namespace Myriad.Gateway
|
||||
private ClientWebSocket? _client;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ShardPacketSerializer _serializer;
|
||||
|
||||
|
||||
public WebSocketState State => _client?.State ?? WebSocketState.Closed;
|
||||
public WebSocketCloseStatus? CloseStatus => _client?.CloseStatus;
|
||||
public string? CloseStatusDescription => _client?.CloseStatusDescription;
|
||||
|
||||
|
||||
public ShardConnection(JsonSerializerOptions jsonSerializerOptions, ILogger logger)
|
||||
{
|
||||
_logger = logger.ForContext<ShardConnection>();
|
||||
@ -28,7 +28,7 @@ namespace Myriad.Gateway
|
||||
{
|
||||
_client?.Dispose();
|
||||
_client = new ClientWebSocket();
|
||||
|
||||
|
||||
await _client.ConnectAsync(GetConnectionUri(url), ct);
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ namespace Myriad.Gateway
|
||||
public async Task Send(GatewayPacket packet)
|
||||
{
|
||||
// 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;
|
||||
|
||||
try
|
||||
@ -62,7 +62,7 @@ namespace Myriad.Gateway
|
||||
public async Task<GatewayPacket?> Read()
|
||||
{
|
||||
// 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;
|
||||
|
||||
try
|
||||
@ -79,7 +79,7 @@ namespace Myriad.Gateway
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Uri GetConnectionUri(string baseUri) => new UriBuilder(baseUri)
|
||||
{
|
||||
Query = "v=9&encoding=json"
|
||||
@ -89,10 +89,10 @@ namespace Myriad.Gateway
|
||||
{
|
||||
if (_client == null)
|
||||
return;
|
||||
|
||||
|
||||
var client = _client;
|
||||
_client = null;
|
||||
|
||||
|
||||
// from `ManagedWebSocket.s_validCloseStates`
|
||||
if (client.State is WebSocketState.Open or WebSocketState.CloseReceived or WebSocketState.CloseSent)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway
|
||||
namespace Myriad.Gateway
|
||||
{
|
||||
public record ShardInfo(int ShardId, int NumShards);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Net.WebSockets;
|
||||
@ -10,7 +10,7 @@ namespace Myriad.Gateway
|
||||
public class ShardPacketSerializer
|
||||
{
|
||||
private const int BufferSize = 64 * 1024;
|
||||
|
||||
|
||||
private readonly JsonSerializerOptions _jsonSerializerOptions;
|
||||
|
||||
public ShardPacketSerializer(JsonSerializerOptions jsonSerializerOptions)
|
||||
@ -21,15 +21,15 @@ namespace Myriad.Gateway
|
||||
public async ValueTask<(WebSocketMessageType type, GatewayPacket? packet)> ReadPacket(ClientWebSocket socket)
|
||||
{
|
||||
using var buf = MemoryPool<byte>.Shared.Rent(BufferSize);
|
||||
|
||||
|
||||
var res = await socket.ReceiveAsync(buf.Memory, default);
|
||||
if (res.MessageType == WebSocketMessageType.Close)
|
||||
return (res.MessageType, null);
|
||||
|
||||
|
||||
if (res.EndOfMessage)
|
||||
// Entire packet fits within one buffer, deserialize directly
|
||||
return DeserializeSingleBuffer(buf, res);
|
||||
|
||||
|
||||
// Otherwise copy to stream buffer and deserialize from there
|
||||
return await DeserializeMultipleBuffer(socket, buf, res);
|
||||
}
|
||||
@ -51,7 +51,7 @@ namespace Myriad.Gateway
|
||||
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(
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -8,7 +8,7 @@ namespace Myriad.Gateway.State
|
||||
{
|
||||
private Task? _worker;
|
||||
private CancellationTokenSource? _workerCts;
|
||||
|
||||
|
||||
public TimeSpan? CurrentHeartbeatInterval { get; private set; }
|
||||
|
||||
public async ValueTask Start(TimeSpan heartbeatInterval, Func<Task> callback)
|
||||
@ -23,9 +23,9 @@ namespace Myriad.Gateway.State
|
||||
|
||||
public async ValueTask Stop()
|
||||
{
|
||||
if (_worker == null)
|
||||
if (_worker == null)
|
||||
return;
|
||||
|
||||
|
||||
_workerCts?.Cancel();
|
||||
try
|
||||
{
|
||||
@ -38,12 +38,12 @@ namespace Myriad.Gateway.State
|
||||
_worker = null;
|
||||
CurrentHeartbeatInterval = null;
|
||||
}
|
||||
|
||||
|
||||
private async Task Worker(TimeSpan heartbeatInterval, Func<Task> callback, CancellationToken ct)
|
||||
{
|
||||
var initialDelay = GetInitialHeartbeatDelay(heartbeatInterval);
|
||||
await Task.Delay(initialDelay, ct);
|
||||
|
||||
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
await callback();
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Gateway.State
|
||||
namespace Myriad.Gateway.State
|
||||
{
|
||||
public enum ShardState
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
@ -18,7 +18,7 @@ namespace Myriad.Gateway
|
||||
private readonly ShardInfo _info;
|
||||
private readonly JsonSerializerOptions _jsonSerializerOptions;
|
||||
private ShardState _state = ShardState.Disconnected;
|
||||
|
||||
|
||||
private DateTimeOffset? _lastHeartbeatSent;
|
||||
private TimeSpan? _latency;
|
||||
private bool _hasReceivedHeartbeatAck;
|
||||
@ -30,7 +30,7 @@ namespace Myriad.Gateway
|
||||
public TimeSpan? Latency => _latency;
|
||||
public User? User { get; private set; }
|
||||
public ApplicationPartial? Application { get; private set; }
|
||||
|
||||
|
||||
public Func<Task> SendIdentify { get; init; }
|
||||
public Func<(string SessionId, int? LastSeq), Task> SendResume { get; init; }
|
||||
public Func<int?, Task> SendHeartbeat { get; init; }
|
||||
@ -52,7 +52,7 @@ namespace Myriad.Gateway
|
||||
_state = ShardState.Handshaking;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public async Task HandleConnectionClosed()
|
||||
{
|
||||
_latency = null;
|
||||
@ -71,36 +71,36 @@ namespace Myriad.Gateway
|
||||
case GatewayOpcode.Heartbeat:
|
||||
await HandleHeartbeatRequest();
|
||||
break;
|
||||
|
||||
|
||||
case GatewayOpcode.HeartbeatAck:
|
||||
await HandleHeartbeatAck();
|
||||
break;
|
||||
|
||||
|
||||
case GatewayOpcode.Reconnect:
|
||||
{
|
||||
await HandleReconnect();
|
||||
break;
|
||||
}
|
||||
{
|
||||
await HandleReconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
case GatewayOpcode.InvalidSession:
|
||||
{
|
||||
var canResume = DeserializePayload<bool>(packet);
|
||||
await HandleInvalidSession(canResume);
|
||||
break;
|
||||
}
|
||||
{
|
||||
var canResume = DeserializePayload<bool>(packet);
|
||||
await HandleInvalidSession(canResume);
|
||||
break;
|
||||
}
|
||||
|
||||
case GatewayOpcode.Dispatch:
|
||||
case GatewayOpcode.Dispatch:
|
||||
_lastSeq = packet.Sequence;
|
||||
|
||||
var evt = DeserializeEvent(packet.EventType!, (JsonElement) packet.Payload!);
|
||||
var evt = DeserializeEvent(packet.EventType!, (JsonElement)packet.Payload!);
|
||||
if (evt != null)
|
||||
{
|
||||
if (evt is ReadyEvent ready)
|
||||
if (evt is ReadyEvent ready)
|
||||
await HandleReady(ready);
|
||||
|
||||
if (evt is ResumedEvent)
|
||||
|
||||
if (evt is ResumedEvent)
|
||||
await HandleResumed();
|
||||
|
||||
|
||||
await HandleEvent(evt);
|
||||
}
|
||||
break;
|
||||
@ -110,7 +110,7 @@ namespace Myriad.Gateway
|
||||
private async Task HandleHello(GatewayHello hello)
|
||||
{
|
||||
var interval = TimeSpan.FromMilliseconds(hello.HeartbeatInterval);
|
||||
|
||||
|
||||
_hasReceivedHeartbeatAck = true;
|
||||
await _heartbeatWorker.Start(interval, HandleHeartbeatTimer);
|
||||
await IdentifyOrResume();
|
||||
@ -152,14 +152,14 @@ namespace Myriad.Gateway
|
||||
_sessionId = null;
|
||||
_lastSeq = null;
|
||||
}
|
||||
|
||||
|
||||
_logger.Information("Shard {ShardId}: Received Invalid Session (can resume? {CanResume})",
|
||||
_info.ShardId, canResume);
|
||||
|
||||
var delay = TimeSpan.FromMilliseconds(new Random().Next(1000, 5000));
|
||||
await DoReconnect(WebSocketCloseStatus.NormalClosure, delay);
|
||||
}
|
||||
|
||||
|
||||
private async Task HandleReconnect()
|
||||
{
|
||||
_logger.Information("Shard {ShardId}: Received Reconnect", _info.ShardId);
|
||||
@ -167,7 +167,7 @@ namespace Myriad.Gateway
|
||||
// we use 1005 (no error specified) instead
|
||||
await DoReconnect(WebSocketCloseStatus.Empty, TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
|
||||
private Task HandleReady(ReadyEvent ready)
|
||||
{
|
||||
_logger.Information("Shard {ShardId}: Received Ready", _info.ShardId);
|
||||
@ -218,10 +218,10 @@ namespace Myriad.Gateway
|
||||
|
||||
private T DeserializePayload<T>(GatewayPacket packet)
|
||||
{
|
||||
var packetPayload = (JsonElement) packet.Payload!;
|
||||
var packetPayload = (JsonElement)packet.Payload!;
|
||||
return JsonSerializer.Deserialize<T>(packetPayload.GetRawText(), _jsonSerializerOptions)!;
|
||||
}
|
||||
|
||||
|
||||
private IGatewayEvent? DeserializeEvent(string eventType, JsonElement payload)
|
||||
{
|
||||
if (!IGatewayEvent.EventTypes.TryGetValue(eventType, out var clrType))
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
@ -52,7 +52,7 @@ namespace Myriad.Rest
|
||||
var waitPolicy = Policy
|
||||
.Handle<RatelimitBucketExhaustedException>()
|
||||
.WaitAndRetryAsync(3,
|
||||
(_, e, _) => ((RatelimitBucketExhaustedException) e).RetryAfter,
|
||||
(_, e, _) => ((RatelimitBucketExhaustedException)e).RetryAfter,
|
||||
(_, _, _, _) => Task.CompletedTask)
|
||||
.AsAsyncPolicy<HttpResponseMessage>();
|
||||
|
||||
@ -68,7 +68,7 @@ namespace Myriad.Rest
|
||||
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),
|
||||
ratelimitParams, true);
|
||||
@ -81,7 +81,7 @@ namespace Myriad.Rest
|
||||
}
|
||||
|
||||
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(() =>
|
||||
{
|
||||
@ -91,9 +91,9 @@ namespace Myriad.Rest
|
||||
}, ratelimitParams);
|
||||
return await ReadResponse<T>(response);
|
||||
}
|
||||
|
||||
|
||||
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(() =>
|
||||
{
|
||||
@ -105,7 +105,7 @@ namespace Myriad.Rest
|
||||
}
|
||||
|
||||
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(() =>
|
||||
{
|
||||
@ -117,7 +117,7 @@ namespace Myriad.Rest
|
||||
}
|
||||
|
||||
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(() =>
|
||||
{
|
||||
@ -160,7 +160,7 @@ namespace Myriad.Rest
|
||||
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)
|
||||
return null;
|
||||
@ -174,7 +174,7 @@ namespace Myriad.Rest
|
||||
return await _retryPolicy.ExecuteAsync(async _ =>
|
||||
{
|
||||
using var __ = LogContext.PushProperty("EndpointName", ratelimitParams.endpointName);
|
||||
|
||||
|
||||
var request = createRequest();
|
||||
_logger.Debug("Request: {RequestMethod} {RequestPath}",
|
||||
request.Method, request.RequestUri);
|
||||
@ -189,7 +189,7 @@ namespace Myriad.Rest
|
||||
|
||||
_logger.Debug(
|
||||
"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);
|
||||
|
||||
@ -211,7 +211,7 @@ namespace Myriad.Rest
|
||||
return;
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var apiError = TryParseApiError(body);
|
||||
var apiError = TryParseApiError(body);
|
||||
if (apiError != null)
|
||||
_logger.Warning("Discord API error: {DiscordErrorCode} {DiscordErrorMessage}", apiError.Code, apiError.Message);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -34,7 +34,7 @@ namespace Myriad.Rest
|
||||
|
||||
public Task<Guild?> GetGuild(ulong id) =>
|
||||
_client.Get<Guild>($"/guilds/{id}", ("GetGuild", id));
|
||||
|
||||
|
||||
public Task<Channel[]> GetGuildChannels(ulong id) =>
|
||||
_client.Get<Channel[]>($"/guilds/{id}/channels", ("GetGuildChannels", id))!;
|
||||
|
||||
@ -108,7 +108,7 @@ namespace Myriad.Rest
|
||||
|
||||
public Task<Webhook> CreateWebhook(ulong channelId, CreateWebhookRequest request) =>
|
||||
_client.Post<Webhook>($"/channels/{channelId}/webhooks", ("CreateWebhook", channelId), request)!;
|
||||
|
||||
|
||||
public Task<Webhook> GetWebhook(ulong webhookId) =>
|
||||
_client.Get<Webhook>($"/webhooks/{webhookId}/webhooks", ("GetWebhook", webhookId))!;
|
||||
|
||||
@ -121,7 +121,7 @@ namespace Myriad.Rest
|
||||
var url = $"/webhooks/{webhookId}/{webhookToken}?wait=true";
|
||||
if (threadId != null)
|
||||
url += $"&thread_id={threadId}";
|
||||
|
||||
|
||||
return _client.PostMultipart<Message>(url,
|
||||
("ExecuteWebhook", webhookId), request, files)!;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Myriad.Rest
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
|
||||
@ -29,43 +29,49 @@ namespace Myriad.Rest.Exceptions
|
||||
|
||||
public class NotFoundException: DiscordRequestException
|
||||
{
|
||||
public NotFoundException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base(
|
||||
response, responseBody, apiError) { }
|
||||
public NotFoundException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
|
||||
response, responseBody, apiError)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class UnauthorizedException: DiscordRequestException
|
||||
{
|
||||
public UnauthorizedException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base(
|
||||
response, responseBody, apiError) { }
|
||||
public UnauthorizedException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
|
||||
response, responseBody, apiError)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class ForbiddenException: DiscordRequestException
|
||||
{
|
||||
public ForbiddenException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base(
|
||||
response, responseBody, apiError) { }
|
||||
public ForbiddenException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
|
||||
response, responseBody, apiError)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class ConflictException: DiscordRequestException
|
||||
{
|
||||
public ConflictException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base(
|
||||
response, responseBody, apiError) { }
|
||||
public ConflictException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
|
||||
response, responseBody, apiError)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class BadRequestException: DiscordRequestException
|
||||
{
|
||||
public BadRequestException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError): base(
|
||||
response, responseBody, apiError) { }
|
||||
public BadRequestException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) : base(
|
||||
response, responseBody, apiError)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class TooManyRequestsException: DiscordRequestException
|
||||
{
|
||||
public TooManyRequestsException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError):
|
||||
base(response, responseBody, apiError) { }
|
||||
public TooManyRequestsException(HttpResponseMessage response, string responseBody, DiscordApiError? apiError) :
|
||||
base(response, responseBody, apiError)
|
||||
{ }
|
||||
}
|
||||
|
||||
public class UnknownDiscordRequestException: DiscordRequestException
|
||||
{
|
||||
public UnknownDiscordRequestException(HttpResponseMessage response, string responseBody,
|
||||
DiscordApiError? apiError): base(response, responseBody, apiError) { }
|
||||
DiscordApiError? apiError) : base(response, responseBody, apiError) { }
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
using Myriad.Rest.Ratelimit;
|
||||
|
||||
@ -6,12 +6,12 @@ namespace Myriad.Rest.Exceptions
|
||||
{
|
||||
public class RatelimitException: Exception
|
||||
{
|
||||
public RatelimitException(string? message): base(message) { }
|
||||
public RatelimitException(string? message) : base(message) { }
|
||||
}
|
||||
|
||||
public class RatelimitBucketExhaustedException: RatelimitException
|
||||
{
|
||||
public RatelimitBucketExhaustedException(Bucket bucket, TimeSpan retryAfter): base(
|
||||
public RatelimitBucketExhaustedException(Bucket bucket, TimeSpan retryAfter) : base(
|
||||
"Rate limit bucket exhausted, request blocked")
|
||||
{
|
||||
Bucket = bucket;
|
||||
@ -24,6 +24,6 @@ namespace Myriad.Rest.Exceptions
|
||||
|
||||
public class GloballyRatelimitedException: RatelimitException
|
||||
{
|
||||
public GloballyRatelimitedException(): base("Global rate limit hit") { }
|
||||
public GloballyRatelimitedException() : base("Global rate limit hit") { }
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Serilog;
|
||||
@ -54,7 +54,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
"{BucketKey}/{BucketMajor}: Bucket has [{BucketRemaining}/{BucketLimit} left], allowing through",
|
||||
Key, Major, Remaining, Limit);
|
||||
Remaining--;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
try
|
||||
{
|
||||
_semaphore.Wait();
|
||||
|
||||
|
||||
_logger.Verbose("{BucketKey}/{BucketMajor}: Received rate limit headers: {@RateLimitHeaders}",
|
||||
Key, Major, headers);
|
||||
|
||||
@ -90,7 +90,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
}
|
||||
}
|
||||
|
||||
if (headers.Limit != null)
|
||||
if (headers.Limit != null)
|
||||
Limit = headers.Limit.Value;
|
||||
|
||||
if (headers.Remaining != null && !_hasReceivedHeaders)
|
||||
@ -98,7 +98,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
var oldRemaining = 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);
|
||||
_hasReceivedHeaders = true;
|
||||
}
|
||||
@ -114,7 +114,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
try
|
||||
{
|
||||
_semaphore.Wait();
|
||||
|
||||
|
||||
// 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
|
||||
// but it ensures the stale timeout doesn't trigger early by using `default` value
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -72,7 +72,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
{
|
||||
if (now - bucket.LastUsed <= StaleBucketTimeout)
|
||||
continue;
|
||||
|
||||
|
||||
_logger.Debug("Pruning unused bucket {BucketKey}/{BucketMajor} (last used at {BucketLastUsed})",
|
||||
bucket.Key, bucket.Major, bucket.LastUsed);
|
||||
_buckets.TryRemove(key, out _);
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@ -13,7 +13,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
private const string ResetAfterHeader = "X-RateLimit-Reset-After";
|
||||
private const string BucketHeader = "X-RateLimit-Bucket";
|
||||
private const string GlobalHeader = "X-RateLimit-Global";
|
||||
|
||||
|
||||
public bool Global { get; private set; }
|
||||
public int? Limit { get; private set; }
|
||||
public int? Remaining { get; private set; }
|
||||
@ -25,7 +25,7 @@ namespace Myriad.Rest.Ratelimit
|
||||
|
||||
public bool HasRatelimitInfo =>
|
||||
Limit != null && Remaining != null && Reset != null && ResetAfter != null && Bucket != null;
|
||||
|
||||
|
||||
public RatelimitHeaders() { }
|
||||
|
||||
public static RatelimitHeaders Parse(HttpResponseMessage response)
|
||||
@ -41,12 +41,12 @@ namespace Myriad.Rest.Ratelimit
|
||||
|
||||
var resetTimestamp = TryGetDouble(response, ResetHeader);
|
||||
if (resetTimestamp != null)
|
||||
headers.Reset = DateTimeOffset.FromUnixTimeMilliseconds((long) (resetTimestamp.Value * 1000));
|
||||
headers.Reset = DateTimeOffset.FromUnixTimeMilliseconds((long)(resetTimestamp.Value * 1000));
|
||||
|
||||
var resetAfterSeconds = TryGetDouble(response, ResetAfterHeader);
|
||||
if (resetAfterSeconds != null)
|
||||
headers.ResetAfter = TimeSpan.FromSeconds(resetAfterSeconds.Value);
|
||||
|
||||
|
||||
var global = TryGetHeader(response, GlobalHeader);
|
||||
if (global != null && bool.TryParse(global, out var globalBool))
|
||||
headers.Global = globalBool;
|
||||
@ -58,27 +58,27 @@ namespace Myriad.Rest.Ratelimit
|
||||
{
|
||||
if (!response.Headers.TryGetValues(headerName, out var values))
|
||||
return null;
|
||||
|
||||
|
||||
return values.FirstOrDefault();
|
||||
}
|
||||
|
||||
private static int? TryGetInt(HttpResponseMessage response, string headerName)
|
||||
{
|
||||
var valueString = TryGetHeader(response, headerName);
|
||||
|
||||
|
||||
if (!int.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
|
||||
return null;
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static double? TryGetDouble(HttpResponseMessage response, string headerName)
|
||||
{
|
||||
var valueString = TryGetHeader(response, headerName);
|
||||
|
||||
|
||||
if (!double.TryParse(valueString, NumberStyles.Float, CultureInfo.InvariantCulture, out var value))
|
||||
return null;
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
using Myriad.Rest.Exceptions;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Myriad.Serialization;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
|
||||
namespace Myriad.Rest.Types
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Myriad.Types;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Rest.Types.Requests
|
||||
namespace Myriad.Rest.Types.Requests
|
||||
{
|
||||
public record CreateDmRequest(ulong RecipientId);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Rest.Types.Requests
|
||||
namespace Myriad.Rest.Types.Requests
|
||||
{
|
||||
public record CreateWebhookRequest(string Name);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Rest.Types.Requests
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Myriad.Types;
|
||||
using Myriad.Utils;
|
||||
@ -8,14 +8,14 @@ namespace Myriad.Rest.Types.Requests
|
||||
public record MessageEditRequest
|
||||
{
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<string?> Content { get; init; }
|
||||
|
||||
public Optional<string?> Content { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<Embed?> Embed { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<Message.MessageFlags> Flags { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<AllowedMentions> AllowedMentions { get; init; }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Myriad.Types;
|
||||
using Myriad.Types;
|
||||
|
||||
namespace Myriad.Rest.Types.Requests
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Rest.Types
|
||||
namespace Myriad.Rest.Types
|
||||
{
|
||||
public record ModifyGuildMemberRequest
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Myriad.Utils;
|
||||
|
||||
@ -7,8 +7,8 @@ namespace Myriad.Rest.Types.Requests
|
||||
public record WebhookMessageEditRequest
|
||||
{
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<string?> Content { get; init; }
|
||||
|
||||
public Optional<string?> Content { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<AllowedMentions> AllowedMentions { get; init; }
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Myriad.Serialization
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
@ -22,11 +22,11 @@ namespace Myriad.Serialization
|
||||
JsonSerializer.Serialize(writer, value.HasValue ? value.GetValue() : default, typeof(T), options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var innerType = typeToConvert.GetGenericArguments()[0];
|
||||
return (JsonConverter?) Activator.CreateInstance(
|
||||
return (JsonConverter?)Activator.CreateInstance(
|
||||
typeof(Inner<>).MakeGenericType(innerType),
|
||||
BindingFlags.Instance | BindingFlags.Public,
|
||||
null,
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@ -13,12 +13,12 @@ namespace Myriad.Serialization
|
||||
var str = reader.GetString();
|
||||
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)
|
||||
{
|
||||
writer.WriteStringValue(((ulong) value).ToString());
|
||||
writer.WriteStringValue(((ulong)value).ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Activity: ActivityPartial
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public record ActivityPartial
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public ActivityType Type { get; init; }
|
||||
public string? Url { get; init; }
|
||||
}
|
||||
|
||||
|
||||
public enum ActivityType
|
||||
{
|
||||
Game = 0,
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Application: ApplicationPartial
|
||||
{
|
||||
@ -16,7 +16,7 @@
|
||||
public string? Slug { get; init; }
|
||||
public string? CoverImage { get; init; }
|
||||
}
|
||||
|
||||
|
||||
public record ApplicationPartial
|
||||
{
|
||||
public ulong Id { get; init; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record ApplicationCommand
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record ApplicationCommandInteractionData
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record ApplicationCommandInteractionDataOption
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record ApplicationCommandOption(ApplicationCommandOption.OptionType Type, string Name, string Description)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Interaction
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using Myriad.Rest.Types;
|
||||
using Myriad.Utils;
|
||||
@ -9,19 +9,19 @@ namespace Myriad.Types
|
||||
{
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<bool?> Tts { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<string?> Content { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<Embed[]?> Embeds { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<AllowedMentions?> AllowedMentions { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<Message.MessageFlags> Flags { get; init; }
|
||||
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public Optional<MessageComponent[]?> Components { get; init; }
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record InteractionResponse
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Channel
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Embed
|
||||
{
|
||||
@ -16,44 +16,44 @@
|
||||
public EmbedAuthor? Author { get; init; }
|
||||
public Field[]? Fields { get; init; }
|
||||
|
||||
public record EmbedFooter (
|
||||
public record EmbedFooter(
|
||||
string Text,
|
||||
string? IconUrl = null,
|
||||
string? ProxyIconUrl = null
|
||||
);
|
||||
|
||||
public record EmbedImage (
|
||||
public record EmbedImage(
|
||||
string? Url,
|
||||
uint? Width = null,
|
||||
uint? Height = null
|
||||
);
|
||||
|
||||
public record EmbedThumbnail (
|
||||
public record EmbedThumbnail(
|
||||
string? Url,
|
||||
string? ProxyUrl = null,
|
||||
uint? Width = null,
|
||||
uint? Height = null
|
||||
);
|
||||
|
||||
public record EmbedVideo (
|
||||
public record EmbedVideo(
|
||||
string? Url,
|
||||
uint? Width = null,
|
||||
uint? Height = null
|
||||
);
|
||||
|
||||
public record EmbedProvider (
|
||||
public record EmbedProvider(
|
||||
string? Name,
|
||||
string? Url
|
||||
);
|
||||
|
||||
public record EmbedAuthor (
|
||||
public record EmbedAuthor(
|
||||
string? Name = null,
|
||||
string? Url = null,
|
||||
string? IconUrl = null,
|
||||
string? ProxyIconUrl = null
|
||||
);
|
||||
|
||||
public record Field (
|
||||
public record Field(
|
||||
string Name,
|
||||
string Value,
|
||||
bool Inline = false
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Emoji
|
||||
{
|
||||
|
@ -1,9 +1,9 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record GatewayInfo
|
||||
{
|
||||
public string Url { get; init; }
|
||||
|
||||
|
||||
public record Bot: GatewayInfo
|
||||
{
|
||||
public int Shards { get; init; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record SessionStartLimit
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Myriad.Types
|
||||
namespace Myriad.Types
|
||||
{
|
||||
public record Guild
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user