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; }
+ }
+}