From 5e6f977469b143bc5ad17c630fad3481c9184861 Mon Sep 17 00:00:00 2001 From: Christopher Felegy Date: Mon, 6 Jan 2020 01:37:47 -0500 Subject: [PATCH] rest: write out channel model + its dependencies Optional struct needs work still, + writing the converter for it is going to be a headache --- ep.txt | 106 +++++++++++++++++++++ src/Discord.Net/Entities/Snowflake.cs | 24 +++++ src/Discord.Net/Rest/DiscordRestApi.cs | 10 +- src/Discord.Net/Rest/IDiscordRestApi.cs | 23 ++++- src/Discord.Net/Rest/Models/Channel/Channel.cs | 59 ++++++++++++ src/Discord.Net/Rest/Models/Channel/ChannelType.cs | 13 +++ src/Discord.Net/Rest/Models/GatewayInfo.cs | 6 +- .../Rest/Models/Permissions/ChannelPermissions.cs | 36 +++++++ .../Rest/Models/Permissions/GuildPermissions.cs | 45 +++++++++ .../Rest/Models/Permissions/Overwrite.cs | 16 ++++ .../Rest/Models/Permissions/PermissionTarget.cs | 8 ++ src/Discord.Net/Rest/Models/Users/AccountFlags.cs | 20 ++++ src/Discord.Net/Rest/Models/Users/PremiumType.cs | 8 ++ src/Discord.Net/Rest/Models/Users/User.cs | 33 +++++++ .../JsonContentSerializer.cs | 2 +- src/Discord.Net/Serialization/OptionalConverter.cs | 22 +++++ src/Discord.Net/Utilities/Optional.cs | 12 +++ 17 files changed, 433 insertions(+), 10 deletions(-) create mode 100644 ep.txt create mode 100644 src/Discord.Net/Entities/Snowflake.cs create mode 100644 src/Discord.Net/Rest/Models/Channel/Channel.cs create mode 100644 src/Discord.Net/Rest/Models/Channel/ChannelType.cs create mode 100644 src/Discord.Net/Rest/Models/Permissions/ChannelPermissions.cs create mode 100644 src/Discord.Net/Rest/Models/Permissions/GuildPermissions.cs create mode 100644 src/Discord.Net/Rest/Models/Permissions/Overwrite.cs create mode 100644 src/Discord.Net/Rest/Models/Permissions/PermissionTarget.cs create mode 100644 src/Discord.Net/Rest/Models/Users/AccountFlags.cs create mode 100644 src/Discord.Net/Rest/Models/Users/PremiumType.cs create mode 100644 src/Discord.Net/Rest/Models/Users/User.cs rename src/Discord.Net/{Rest => Serialization}/JsonContentSerializer.cs (98%) create mode 100644 src/Discord.Net/Serialization/OptionalConverter.cs create mode 100644 src/Discord.Net/Utilities/Optional.cs diff --git a/ep.txt b/ep.txt new file mode 100644 index 000000000..aad389688 --- /dev/null +++ b/ep.txt @@ -0,0 +1,106 @@ +https://gist.github.com/SinisterRectus/9518f3e7d0d1ccb4335b2a0d389c30b0 + +Sorted By Route +-------------------------------------------------------------------------------------------------------------------- +Get Entitlements GET /applications/{application.id}/entitlements +Get Entitlement GET /applications/{application.id}/entitlements/{entitlement.id} +Delete Test Entitlement DELETE /applications/{application.id}/entitlements/{entitlement.id}/ +Consume SKU POST /applications/{application.id}/entitlements/{entitlement.id}/consume +Get SKUs GET /applications/{application.id}/skus +Delete/Close Channel DELETE /channels/{channel.id} +Get Channel GET /channels/{channel.id} +Modify Channel PUT/PATCH /channels/{channel.id} +Get Channel Invites GET /channels/{channel.id}/invites +Create Channel Invite POST /channels/{channel.id}/invites +Get Channel Messages GET /channels/{channel.id}/messages +Create Message POST /channels/{channel.id}/messages +Bulk Delete Messages POST /channels/{channel.id}/messages/bulk-delete +Bulk Delete Messages (deprecated) POST /channels/{channel.id}/messages/bulk_delete +Delete Message DELETE /channels/{channel.id}/messages/{message.id} +Get Channel Message GET /channels/{channel.id}/messages/{message.id} +Edit Message PATCH /channels/{channel.id}/messages/{message.id} +Delete All Reactions DELETE /channels/{channel.id}/messages/{message.id}/reactions +Get Reactions GET /channels/{channel.id}/messages/{message.id}/reactions/{emoji} +Delete Own Reaction DELETE /channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me +Create Reaction PUT /channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me +Delete User Reaction DELETE /channels/{channel.id}/messages/{message.id}/reactions/{emoji}/{user.id} +Delete Channel Permission DELETE /channels/{channel.id}/permissions/{overwrite.id} +Edit Channel Permissions PUT /channels/{channel.id}/permissions/{overwrite.id} +Get Pinned Messages GET /channels/{channel.id}/pins +Delete Pinned Channel Message DELETE /channels/{channel.id}/pins/{message.id} +Add Pinned Channel Message PUT /channels/{channel.id}/pins/{message.id} +Group DM Remove Recipient DELETE /channels/{channel.id}/recipients/{user.id} +Group DM Add Recipient PUT /channels/{channel.id}/recipients/{user.id} +Trigger Typing Indicator POST /channels/{channel.id}/typing +Get Channel Webhooks GET /channels/{channel.id}/webhooks +Create Webhook POST /channels/{channel.id}/webhooks +Get Gateway GET /gateway +Get Gateway Bot GET /gateway/bot +Create Guild POST /guilds +Delete Guild DELETE /guilds/{guild.id} +Get Guild GET /guilds/{guild.id} +Modify Guild PATCH /guilds/{guild.id} +Get Guild Audit Log GET /guilds/{guild.id}/audit-logs +Get Guild Bans GET /guilds/{guild.id}/bans +Remove Guild Ban DELETE /guilds/{guild.id}/bans/{user.id} +Get Guild Ban GET /guilds/{guild.id}/bans/{user.id} +Create Guild Ban PUT /guilds/{guild.id}/bans/{user.id} +Get Guild Channels GET /guilds/{guild.id}/channels +Modify Guild Channel Positions PATCH /guilds/{guild.id}/channels +Create Guild Channel POST /guilds/{guild.id}/channels +Get Guild Embed GET /guilds/{guild.id}/embed +Modify Guild Embed PATCH /guilds/{guild.id}/embed +List Guild Emojis GET /guilds/{guild.id}/emojis +Create Guild Emoji POST /guilds/{guild.id}/emojis +Delete Guild Emoji DELETE /guilds/{guild.id}/emojis/{emoji.id} +Get Guild Emoji GET /guilds/{guild.id}/emojis/{emoji.id} +Modify Guild Emoji PATCH /guilds/{guild.id}/emojis/{emoji.id} +Get Guild Integrations GET /guilds/{guild.id}/integrations +Create Guild Integration POST /guilds/{guild.id}/integrations +Delete Guild Integration DELETE /guilds/{guild.id}/integrations/{integration.id} +Modify Guild Integration PATCH /guilds/{guild.id}/integrations/{integration.id} +Sync Guild Integration POST /guilds/{guild.id}/integrations/{integration.id}/sync +Get Guild Invites GET /guilds/{guild.id}/invites +List Guild Members GET /guilds/{guild.id}/members +Modify Current User Nick PATCH /guilds/{guild.id}/members/@me/nick +Remove Guild Member DELETE /guilds/{guild.id}/members/{user.id} +Get Guild Member GET /guilds/{guild.id}/members/{user.id} +Modify Guild Member PATCH /guilds/{guild.id}/members/{user.id} +Add Guild Member PUT /guilds/{guild.id}/members/{user.id} +Remove Guild Member Role DELETE /guilds/{guild.id}/members/{user.id}/roles/{role.id} +Add Guild Member Role PUT /guilds/{guild.id}/members/{user.id}/roles/{role.id} +Get Guild Prune Count GET /guilds/{guild.id}/prune +Begin Guild Prune POST /guilds/{guild.id}/prune +Get Guild Voice Regions GET /guilds/{guild.id}/regions +Get Guild Roles GET /guilds/{guild.id}/roles +Modify Guild Role Positions PATCH /guilds/{guild.id}/roles +Create Guild Role POST /guilds/{guild.id}/roles +Delete Guild Role DELETE /guilds/{guild.id}/roles/{role.id} +Modify Guild Role PATCH /guilds/{guild.id}/roles/{role.id} +Get Guild Vanity URL GET /guilds/{guild.id}/vanity-url +Get Guild Webhooks GET /guilds/{guild.id}/webhooks +Get Guild Widget Image GET /guilds/{guild.id}/widget.png +Delete Invite DELETE /invites/{invite.code} +Get Invite GET /invites/{invite.code} +Get Current Application Information GET /oauth2/applications/@me +Delete Purchase Discount DELETE /store/skus/{sku.id}/discounts/{user.id}/ +Create Purchase Discount PUT /store/skus/{sku.id}/discounts/{user.id}/ +Get Current User GET /users/@me +Modify Current User PATCH /users/@me +Get User DMs GET /users/@me/channels +Create DM POST /users/@me/channels +Create Group DM POST /users/@me/channels +Get User Connections GET /users/@me/connections +Get Current User Guilds GET /users/@me/guilds +Leave Guild DELETE /users/@me/guilds/{guild.id} +Get User GET /users/{user.id} +List Voice Regions GET /voice/regions +Delete Webhook DELETE /webhooks/{webhook.id} +Get Webhook GET /webhooks/{webhook.id} +Modify Webhook PATCH /webhooks/{webhook.id} +Delete Webhook with Token DELETE /webhooks/{webhook.id}/{webhook.token} +Get Webhook with Token GET /webhooks/{webhook.id}/{webhook.token} +Modify Webhook with Token PATCH /webhooks/{webhook.id}/{webhook.token} +Execute Webhook POST /webhooks/{webhook.id}/{webhook.token} +Execute GitHub-Compatible Webhook POST /webhooks/{webhook.id}/{webhook.token}/github +Execute Slack-Compatible Webhook POST /webhooks/{webhook.id}/{webhook.token}/slack \ No newline at end of file diff --git a/src/Discord.Net/Entities/Snowflake.cs b/src/Discord.Net/Entities/Snowflake.cs new file mode 100644 index 000000000..5dc8dad0f --- /dev/null +++ b/src/Discord.Net/Entities/Snowflake.cs @@ -0,0 +1,24 @@ +namespace Discord +{ + /// + /// A Snowflake represents a unique, 64-bit identifier. + /// + public struct Snowflake + { + private readonly ulong _value; + + private Snowflake(ulong value) + { + _value = value; + } + + public static implicit operator ulong(Snowflake snowflake) + { + return snowflake._value; + } + public static implicit operator Snowflake(ulong value) + { + return new Snowflake(value); + } + } +} diff --git a/src/Discord.Net/Rest/DiscordRestApi.cs b/src/Discord.Net/Rest/DiscordRestApi.cs index 146b8025b..94395fb29 100644 --- a/src/Discord.Net/Rest/DiscordRestApi.cs +++ b/src/Discord.Net/Rest/DiscordRestApi.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Threading.Tasks; using Refit; -using Discord.Rest.Models; +using Discord.Models; using System.Net.Http.Headers; using System; using System.Net.Http; @@ -32,11 +32,11 @@ namespace Discord.Rest }; _api = RestService.For(_http, refitSettings); } - + public Task GetGatewayInfoAsync() - { - return _api.GetGatewayInfoAsync(); - } + => _api.GetGatewayInfoAsync(); + public Task GetBotGatewayInfoAsync() + => _api.GetBotGatewayInfoAsync(); public void Dispose() { diff --git a/src/Discord.Net/Rest/IDiscordRestApi.cs b/src/Discord.Net/Rest/IDiscordRestApi.cs index 0f963351a..83b510329 100644 --- a/src/Discord.Net/Rest/IDiscordRestApi.cs +++ b/src/Discord.Net/Rest/IDiscordRestApi.cs @@ -1,13 +1,34 @@ using System; using System.Threading.Tasks; using Refit; -using Discord.Rest.Models; +using Discord.Models; namespace Discord.Rest { public interface IDiscordRestApi { + // --- /applications + + // --- /channels + + // --- /gateway [Get("/gateway/bot")] Task GetGatewayInfoAsync(); + [Get("/gateway/bot")] + Task GetBotGatewayInfoAsync(); + + // --- /guilds + + // --- /invites + + // --- /oauth2 + + // --- /store + + // --- /users + + // --- /voice + + // --- /webhooks } } diff --git a/src/Discord.Net/Rest/Models/Channel/Channel.cs b/src/Discord.Net/Rest/Models/Channel/Channel.cs new file mode 100644 index 000000000..463daecf5 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Channel/Channel.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Discord.Models +{ + public class Channel + { + public const int MinChannelNameLength = 2; + public const int MaxChannelNameLength = 100; + + public const int MinChannelTopicLength = 0; + public const int MaxChannelTopicLength = 1024; + + public const int MinUserLimit = 0; + public const int MaxUserLimit = 100; + + public const int MinBitrate = 8000; + public const int MaxBitrate = 384000; + + public const int MinRateLimitPerUser = 0; + public const int MaxRateLimitPerUser = 21600; + + [JsonPropertyName("id")] + public Snowflake Id { get; set; } + [JsonPropertyName("type")] + public ChannelType Type { get; set; } + [JsonPropertyName("guild_id")] + public Optional GuildId { get; set; } + [JsonPropertyName("position")] + public Optional Position { get; set; } + [JsonPropertyName("permission_overwrites")] + public Optional Overwrites { get; set; } + [JsonPropertyName("name")] + public Optional Name { get; set; } + [JsonPropertyName("topic")] + public Optional Topic { get; set; } + [JsonPropertyName("nsfw")] + public Optional Nsfw { get; set; } + [JsonPropertyName("user_limit")] + public Optional Bitrate { get; set; } + [JsonPropertyName("rate_limit_per_user")] + public Optional RateLimitPerUser { get; set; } + [JsonPropertyName("recipients")] + public Optional Recipients { get; set; } + [JsonPropertyName("icon")] + public Optional IconId { get; set; } + [JsonPropertyName("owner_id")] + public Optional OwnerId { get; set; } + [JsonPropertyName("application_id")] + public Optional ApplicationId { get; set; } + [JsonPropertyName("parent_id")] + public Optional ParentId { get; set; } + [JsonPropertyName("last_pin_timestamp")] + public Optional LastPinTimestamp { get; set; } + // omitted: last_message_id + } +} diff --git a/src/Discord.Net/Rest/Models/Channel/ChannelType.cs b/src/Discord.Net/Rest/Models/Channel/ChannelType.cs new file mode 100644 index 000000000..47d8bb055 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Channel/ChannelType.cs @@ -0,0 +1,13 @@ +namespace Discord.Models +{ + public enum ChannelType : byte + { + Text = 0, + Direct = 1, + Voice = 2, + Group = 3, + Category = 4, + News = 5, + Store = 6 + } +} diff --git a/src/Discord.Net/Rest/Models/GatewayInfo.cs b/src/Discord.Net/Rest/Models/GatewayInfo.cs index e1497be06..59331bddf 100644 --- a/src/Discord.Net/Rest/Models/GatewayInfo.cs +++ b/src/Discord.Net/Rest/Models/GatewayInfo.cs @@ -1,16 +1,16 @@ #pragma warning disable CS8618 // Uninitialized NRT expected in models using System.Text.Json.Serialization; -namespace Discord.Rest.Models +namespace Discord.Models { public class GatewayInfo { [JsonPropertyName("url")] public string Url { get; set; } [JsonPropertyName("shards")] - public int Shards { get; set; } + public int? Shards { get; set; } [JsonPropertyName("session_start_limit")] - public GatewaySessionStartInfo SessionStartInfo { get; set; } + public GatewaySessionStartInfo? SessionStartInfo { get; set; } } public class GatewaySessionStartInfo diff --git a/src/Discord.Net/Rest/Models/Permissions/ChannelPermissions.cs b/src/Discord.Net/Rest/Models/Permissions/ChannelPermissions.cs new file mode 100644 index 000000000..d3b018ab4 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Permissions/ChannelPermissions.cs @@ -0,0 +1,36 @@ +using System; + +namespace Discord.Models +{ + [Flags] + public enum ChannelPermissions : ulong + { + // General + CreateInstantInvite = 0x0000_0001, + ManageChannel = 0x0000_0010, + AddReactions = 0x0000_0040, + ViewChannel = 0x0000_0400, + ManagePermissions = 0x1000_0000, + ManageWebhooks = 0x2000_0000, + + // Messages + SendMessages = 0x0000_0800, + SendTtsMessages = 0x0000_0100, + ManageMessages = 0x0000_02000, + EmbedLinks = 0x0000_4000, + AttachFiles = 0x0000_8000, + ReadMessageHistory = 0x0001_0000, + MentionEveryone = 0x0002_0000, + UseExternalEmoji = 0x0004_0000, + + // Voice + Connect = 0x0010_0000, + Speak = 0x0020_0000, + MuteMembers = 0x0040_0000, + DeafenMembers = 0x0080_0000, + MoveMembers = 0x0100_0000, + UseVoiceActivity = 0x0200_0000, + PrioritySpeaker = 0x0000_0100, + Stream = 0x0000_0200, + } +} diff --git a/src/Discord.Net/Rest/Models/Permissions/GuildPermissions.cs b/src/Discord.Net/Rest/Models/Permissions/GuildPermissions.cs new file mode 100644 index 000000000..5ce197a48 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Permissions/GuildPermissions.cs @@ -0,0 +1,45 @@ +using System; + +namespace Discord.Models +{ + // todo: doc these when other models exist + [Flags] + public enum GuildPermissions : ulong + { + // General + CreateInstantInvite = 0x0000_0001, + KickMembers = 0x0000_0002, + BanMembers = 0x0000_0004, + Administrator = 0x0000_0008, + ManageChannels = 0x0000_0010, + ManageGuild = 0x0000_0020, + AddReactions = 0x0000_0040, + ViewAuditLog = 0x0000_0080, + ViewChannel = 0x0000_0400, + ChangeNickname = 0x0400_0000, + ManageNicknames = 0x0800_0000, + ManageRoles = 0x1000_0000, + ManageWebhooks = 0x2000_0000, + ManageEmoji = 0x4000_0000, + + // Messages + SendMessages = 0x0000_0800, + SendTtsMessages = 0x0000_0100, + ManageMessages = 0x0000_02000, + EmbedLinks = 0x0000_4000, + AttachFiles = 0x0000_8000, + ReadMessageHistory = 0x0001_0000, + MentionEveryone = 0x0002_0000, + UseExternalEmoji = 0x0004_0000, + + // Voice + Connect = 0x0010_0000, + Speak = 0x0020_0000, + MuteMembers = 0x0040_0000, + DeafenMembers = 0x0080_0000, + MoveMembers = 0x0100_0000, + UseVoiceActivity = 0x0200_0000, + PrioritySpeaker = 0x0000_0100, + Stream = 0x0000_0200, + } +} diff --git a/src/Discord.Net/Rest/Models/Permissions/Overwrite.cs b/src/Discord.Net/Rest/Models/Permissions/Overwrite.cs new file mode 100644 index 000000000..4b947eab4 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Permissions/Overwrite.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Discord.Models +{ + public class Overwrite + { + [JsonPropertyName("id")] + public Snowflake Id { get; set; } + [JsonPropertyName("type")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public PermissionTarget TargetType { get; set; } + } +} diff --git a/src/Discord.Net/Rest/Models/Permissions/PermissionTarget.cs b/src/Discord.Net/Rest/Models/Permissions/PermissionTarget.cs new file mode 100644 index 000000000..980aac453 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Permissions/PermissionTarget.cs @@ -0,0 +1,8 @@ +namespace Discord.Models +{ + public enum PermissionTarget + { + Member, + Role + } +} diff --git a/src/Discord.Net/Rest/Models/Users/AccountFlags.cs b/src/Discord.Net/Rest/Models/Users/AccountFlags.cs new file mode 100644 index 000000000..4ce70def6 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Users/AccountFlags.cs @@ -0,0 +1,20 @@ +using System; + +namespace Discord.Models +{ + [Flags] + public enum AccountFlags : short + { + None = 0, + Employee = 1<<0, + Partner = 1<<1, + HypesquadEvents = 1<<2, + BugHunter = 1<<3, + HypesquadBravery = 1<<6, + HypesquadBrilliance = 1<<7, + HypesquadBalance = 1<<8, + EarlySupporter = 1<<9, + TeamUser = 1<<10, + System = 1<<12, + } +} diff --git a/src/Discord.Net/Rest/Models/Users/PremiumType.cs b/src/Discord.Net/Rest/Models/Users/PremiumType.cs new file mode 100644 index 000000000..492586ffc --- /dev/null +++ b/src/Discord.Net/Rest/Models/Users/PremiumType.cs @@ -0,0 +1,8 @@ +namespace Discord.Models +{ + public enum PremiumType : byte + { + Classic = 1, + Nitro = 2 + } +} diff --git a/src/Discord.Net/Rest/Models/Users/User.cs b/src/Discord.Net/Rest/Models/Users/User.cs new file mode 100644 index 000000000..e6d643e47 --- /dev/null +++ b/src/Discord.Net/Rest/Models/Users/User.cs @@ -0,0 +1,33 @@ +#pragma warning disable CS8618 // Uninitialized NRT expected in models +using System.Text.Json.Serialization; + +namespace Discord.Models +{ + public class User + { + [JsonPropertyName("id")] + public Snowflake Id { get; set; } + [JsonPropertyName("username")] + public string Username { get; set; } + [JsonPropertyName("discriminator")] + public ushort Discriminator { get; set; } + [JsonPropertyName("avatar")] + public string? AvatarId { get; set; } + [JsonPropertyName("bot")] + public Optional Bot { get; set; } + [JsonPropertyName("system")] + public Optional System { get; set; } + [JsonPropertyName("mfa_enabled")] + public Optional MfaEnabled { get; set; } + [JsonPropertyName("locale")] + public Optional Locale { get; set; } + [JsonPropertyName("verified")] + public Optional Verified { get; set; } + [JsonPropertyName("email")] + public Optional Email { get; set; } + [JsonPropertyName("flags")] + public Optional Flags { get; set; } + [JsonPropertyName("premium_type")] + public Optional PremiumType { get; set; } + } +} diff --git a/src/Discord.Net/Rest/JsonContentSerializer.cs b/src/Discord.Net/Serialization/JsonContentSerializer.cs similarity index 98% rename from src/Discord.Net/Rest/JsonContentSerializer.cs rename to src/Discord.Net/Serialization/JsonContentSerializer.cs index 9c03ad59e..4fd4c1971 100644 --- a/src/Discord.Net/Rest/JsonContentSerializer.cs +++ b/src/Discord.Net/Serialization/JsonContentSerializer.cs @@ -8,7 +8,7 @@ using Refit; // https://blog.martincostello.com/refit-and-system-text-json/ -namespace Discord.Rest +namespace Discord { public class JsonContentSerializer : IContentSerializer { diff --git a/src/Discord.Net/Serialization/OptionalConverter.cs b/src/Discord.Net/Serialization/OptionalConverter.cs new file mode 100644 index 000000000..55b988ea1 --- /dev/null +++ b/src/Discord.Net/Serialization/OptionalConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Discord.Serialization +{ + // 😅 + public class OptionalConverter : JsonConverter> + { + public override Optional Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, Optional value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Discord.Net/Utilities/Optional.cs b/src/Discord.Net/Utilities/Optional.cs new file mode 100644 index 000000000..a87cc2f7a --- /dev/null +++ b/src/Discord.Net/Utilities/Optional.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +// todo: impl +namespace Discord +{ + public struct Optional + { + public bool IsSpecified { get; private set; } + public T Value { get; set; } + } +}