Optional struct needs work still, + writing the converter for it is going to be a headachepull/1435/head
@@ -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 |
@@ -0,0 +1,24 @@ | |||
namespace Discord | |||
{ | |||
/// <summary> | |||
/// A Snowflake represents a unique, 64-bit identifier. | |||
/// </summary> | |||
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); | |||
} | |||
} | |||
} |
@@ -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<IDiscordRestApi>(_http, refitSettings); | |||
} | |||
public Task<GatewayInfo> GetGatewayInfoAsync() | |||
{ | |||
return _api.GetGatewayInfoAsync(); | |||
} | |||
=> _api.GetGatewayInfoAsync(); | |||
public Task<GatewayInfo> GetBotGatewayInfoAsync() | |||
=> _api.GetBotGatewayInfoAsync(); | |||
public void Dispose() | |||
{ | |||
@@ -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<GatewayInfo> GetGatewayInfoAsync(); | |||
[Get("/gateway/bot")] | |||
Task<GatewayInfo> GetBotGatewayInfoAsync(); | |||
// --- /guilds | |||
// --- /invites | |||
// --- /oauth2 | |||
// --- /store | |||
// --- /users | |||
// --- /voice | |||
// --- /webhooks | |||
} | |||
} |
@@ -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<Snowflake> GuildId { get; set; } | |||
[JsonPropertyName("position")] | |||
public Optional<short> Position { get; set; } | |||
[JsonPropertyName("permission_overwrites")] | |||
public Optional<Overwrite[]> Overwrites { get; set; } | |||
[JsonPropertyName("name")] | |||
public Optional<string> Name { get; set; } | |||
[JsonPropertyName("topic")] | |||
public Optional<string?> Topic { get; set; } | |||
[JsonPropertyName("nsfw")] | |||
public Optional<bool> Nsfw { get; set; } | |||
[JsonPropertyName("user_limit")] | |||
public Optional<short> Bitrate { get; set; } | |||
[JsonPropertyName("rate_limit_per_user")] | |||
public Optional<int> RateLimitPerUser { get; set; } | |||
[JsonPropertyName("recipients")] | |||
public Optional<User[]> Recipients { get; set; } | |||
[JsonPropertyName("icon")] | |||
public Optional<string?> IconId { get; set; } | |||
[JsonPropertyName("owner_id")] | |||
public Optional<Snowflake> OwnerId { get; set; } | |||
[JsonPropertyName("application_id")] | |||
public Optional<Snowflake> ApplicationId { get; set; } | |||
[JsonPropertyName("parent_id")] | |||
public Optional<Snowflake> ParentId { get; set; } | |||
[JsonPropertyName("last_pin_timestamp")] | |||
public Optional<DateTimeOffset> LastPinTimestamp { get; set; } | |||
// omitted: last_message_id | |||
} | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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 | |||
@@ -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, | |||
} | |||
} |
@@ -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, | |||
} | |||
} |
@@ -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; } | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
namespace Discord.Models | |||
{ | |||
public enum PermissionTarget | |||
{ | |||
Member, | |||
Role | |||
} | |||
} |
@@ -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, | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
namespace Discord.Models | |||
{ | |||
public enum PremiumType : byte | |||
{ | |||
Classic = 1, | |||
Nitro = 2 | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
#pragma warning disable CS8618 // Uninitialized NRT expected in models <username> | |||
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<bool> Bot { get; set; } | |||
[JsonPropertyName("system")] | |||
public Optional<bool> System { get; set; } | |||
[JsonPropertyName("mfa_enabled")] | |||
public Optional<bool> MfaEnabled { get; set; } | |||
[JsonPropertyName("locale")] | |||
public Optional<string> Locale { get; set; } | |||
[JsonPropertyName("verified")] | |||
public Optional<bool> Verified { get; set; } | |||
[JsonPropertyName("email")] | |||
public Optional<string> Email { get; set; } | |||
[JsonPropertyName("flags")] | |||
public Optional<AccountFlags> Flags { get; set; } | |||
[JsonPropertyName("premium_type")] | |||
public Optional<PremiumType> PremiumType { get; set; } | |||
} | |||
} |
@@ -8,7 +8,7 @@ using Refit; | |||
// https://blog.martincostello.com/refit-and-system-text-json/ | |||
namespace Discord.Rest | |||
namespace Discord | |||
{ | |||
public class JsonContentSerializer : IContentSerializer | |||
{ |
@@ -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<T> : JsonConverter<Optional<T>> | |||
{ | |||
public override Optional<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
// todo: impl | |||
namespace Discord | |||
{ | |||
public struct Optional<T> | |||
{ | |||
public bool IsSpecified { get; private set; } | |||
public T Value { get; set; } | |||
} | |||
} |