Isolated API definitions to their own library
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Application
|
||||
{
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
[JsonProperty("rpc_origins")]
|
||||
public string[] RPCOrigins { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[JsonProperty("flags"), Int53]
|
||||
public Optional<ulong> Flags { get; set; }
|
||||
[JsonProperty("owner")]
|
||||
public Optional<User> Owner { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Attachment
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("filename")]
|
||||
public string Filename { get; set; }
|
||||
[JsonProperty("size")]
|
||||
public int Size { get; set; }
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("proxy_url")]
|
||||
public string ProxyUrl { get; set; }
|
||||
[JsonProperty("height")]
|
||||
public Optional<int> Height { get; set; }
|
||||
[JsonProperty("width")]
|
||||
public Optional<int> Width { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Ban
|
||||
{
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
[JsonProperty("reason")]
|
||||
public string Reason { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Channel
|
||||
{
|
||||
//Shared
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public ChannelType Type { get; set; }
|
||||
[JsonProperty("last_message_id")]
|
||||
public ulong? LastMessageId { get; set; }
|
||||
|
||||
//GuildChannel
|
||||
[JsonProperty("guild_id")]
|
||||
public Optional<ulong> GuildId { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public Optional<string> Name { get; set; }
|
||||
[JsonProperty("position")]
|
||||
public Optional<int> Position { get; set; }
|
||||
[JsonProperty("permission_overwrites")]
|
||||
public Optional<Overwrite[]> PermissionOverwrites { get; set; }
|
||||
|
||||
//TextChannel
|
||||
[JsonProperty("topic")]
|
||||
public Optional<string> Topic { get; set; }
|
||||
[JsonProperty("last_pin_timestamp")]
|
||||
public Optional<DateTimeOffset?> LastPinTimestamp { get; set; }
|
||||
|
||||
//VoiceChannel
|
||||
[JsonProperty("bitrate")]
|
||||
public Optional<int> Bitrate { get; set; }
|
||||
[JsonProperty("user_limit")]
|
||||
public Optional<int> UserLimit { get; set; }
|
||||
|
||||
//PrivateChannel
|
||||
[JsonProperty("recipients")]
|
||||
public Optional<User[]> Recipients { get; set; }
|
||||
|
||||
//GroupChannel
|
||||
[JsonProperty("icon")]
|
||||
public Optional<string> Icon { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Connection
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("revoked")]
|
||||
public bool Revoked { get; set; }
|
||||
|
||||
[JsonProperty("integrations")]
|
||||
public IReadOnlyCollection<ulong> Integrations { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Embed
|
||||
{
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("color")]
|
||||
public uint? Color { get; set; }
|
||||
[JsonProperty("timestamp")]
|
||||
public DateTimeOffset? Timestamp { get; set; }
|
||||
[JsonProperty("author")]
|
||||
public Optional<EmbedAuthor> Author { get; set; }
|
||||
[JsonProperty("footer")]
|
||||
public Optional<EmbedFooter> Footer { get; set; }
|
||||
[JsonProperty("video")]
|
||||
public Optional<EmbedVideo> Video { get; set; }
|
||||
[JsonProperty("thumbnail")]
|
||||
public Optional<EmbedThumbnail> Thumbnail { get; set; }
|
||||
[JsonProperty("image")]
|
||||
public Optional<EmbedImage> Image { get; set; }
|
||||
[JsonProperty("provider")]
|
||||
public Optional<EmbedProvider> Provider { get; set; }
|
||||
[JsonProperty("fields")]
|
||||
public Optional<EmbedField[]> Fields { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedAuthor
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
[JsonProperty("proxy_icon_url")]
|
||||
public string ProxyIconUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedField
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("value")]
|
||||
public string Value { get; set; }
|
||||
[JsonProperty("inline")]
|
||||
public bool Inline { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedFooter
|
||||
{
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
[JsonProperty("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
[JsonProperty("proxy_icon_url")]
|
||||
public string ProxyIconUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedImage
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("proxy_url")]
|
||||
public string ProxyUrl { get; set; }
|
||||
[JsonProperty("height")]
|
||||
public Optional<int> Height { get; set; }
|
||||
[JsonProperty("width")]
|
||||
public Optional<int> Width { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedProvider
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedThumbnail
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("proxy_url")]
|
||||
public string ProxyUrl { get; set; }
|
||||
[JsonProperty("height")]
|
||||
public Optional<int> Height { get; set; }
|
||||
[JsonProperty("width")]
|
||||
public Optional<int> Width { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class EmbedVideo
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("height")]
|
||||
public Optional<int> Height { get; set; }
|
||||
[JsonProperty("width")]
|
||||
public Optional<int> Width { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Emoji
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong? Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("roles")]
|
||||
public ulong[] Roles { get; set; }
|
||||
[JsonProperty("require_colons")]
|
||||
public bool RequireColons { get; set; }
|
||||
[JsonProperty("managed")]
|
||||
public bool Managed { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Game
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("url")]
|
||||
public Optional<string> StreamUrl { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public Optional<StreamType?> StreamType { get; set; }
|
||||
|
||||
[OnError]
|
||||
internal void OnError(StreamingContext context, ErrorContext errorContext)
|
||||
{
|
||||
errorContext.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Guild
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("icon")]
|
||||
public string Icon { get; set; }
|
||||
[JsonProperty("splash")]
|
||||
public string Splash { get; set; }
|
||||
[JsonProperty("owner_id")]
|
||||
public ulong OwnerId { get; set; }
|
||||
[JsonProperty("region")]
|
||||
public string Region { get; set; }
|
||||
[JsonProperty("afk_channel_id")]
|
||||
public ulong? AFKChannelId { get; set; }
|
||||
[JsonProperty("afk_timeout")]
|
||||
public int AFKTimeout { get; set; }
|
||||
[JsonProperty("embed_enabled")]
|
||||
public bool EmbedEnabled { get; set; }
|
||||
[JsonProperty("embed_channel_id")]
|
||||
public ulong? EmbedChannelId { get; set; }
|
||||
[JsonProperty("verification_level")]
|
||||
public VerificationLevel VerificationLevel { get; set; }
|
||||
[JsonProperty("voice_states")]
|
||||
public VoiceState[] VoiceStates { get; set; }
|
||||
[JsonProperty("roles")]
|
||||
public Role[] Roles { get; set; }
|
||||
[JsonProperty("emojis")]
|
||||
public Emoji[] Emojis { get; set; }
|
||||
[JsonProperty("features")]
|
||||
public string[] Features { get; set; }
|
||||
[JsonProperty("mfa_level")]
|
||||
public MfaLevel MfaLevel { get; set; }
|
||||
[JsonProperty("default_message_notifications")]
|
||||
public DefaultMessageNotifications DefaultMessageNotifications { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class GuildEmbed
|
||||
{
|
||||
[JsonProperty("enabled")]
|
||||
public bool Enabled { get; set; }
|
||||
[JsonProperty("channel_id")]
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class GuildMember
|
||||
{
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
[JsonProperty("nick")]
|
||||
public Optional<string> Nick { get; set; }
|
||||
[JsonProperty("roles")]
|
||||
public ulong[] Roles { get; set; }
|
||||
[JsonProperty("joined_at")]
|
||||
public DateTimeOffset JoinedAt { get; set; }
|
||||
[JsonProperty("deaf")]
|
||||
public bool Deaf { get; set; }
|
||||
[JsonProperty("mute")]
|
||||
public bool Mute { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Integration
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
[JsonProperty("enabled")]
|
||||
public bool Enabled { get; set; }
|
||||
[JsonProperty("syncing")]
|
||||
public bool Syncing { get; set; }
|
||||
[JsonProperty("role_id")]
|
||||
public ulong RoleId { get; set; }
|
||||
[JsonProperty("expire_behavior")]
|
||||
public ulong ExpireBehavior { get; set; }
|
||||
[JsonProperty("expire_grace_period")]
|
||||
public ulong ExpireGracePeriod { get; set; }
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
[JsonProperty("account")]
|
||||
public IntegrationAccount Account { get; set; }
|
||||
[JsonProperty("synced_at")]
|
||||
public DateTimeOffset SyncedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class IntegrationAccount
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Invite
|
||||
{
|
||||
[JsonProperty("code")]
|
||||
public string Code { get; set; }
|
||||
[JsonProperty("guild")]
|
||||
public InviteGuild Guild { get; set; }
|
||||
[JsonProperty("channel")]
|
||||
public InviteChannel Channel { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class InviteChannel
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class InviteGuild
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("splash_hash")]
|
||||
public string SplashHash { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class InviteMetadata : Invite
|
||||
{
|
||||
[JsonProperty("inviter")]
|
||||
public User Inviter { get; set; }
|
||||
[JsonProperty("uses")]
|
||||
public int Uses { get; set; }
|
||||
[JsonProperty("max_uses")]
|
||||
public int MaxUses { get; set; }
|
||||
[JsonProperty("max_age")]
|
||||
public int MaxAge { get; set; }
|
||||
[JsonProperty("temporary")]
|
||||
public bool Temporary { get; set; }
|
||||
[JsonProperty("created_at")]
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
[JsonProperty("revoked")]
|
||||
public bool Revoked { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Message
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public MessageType Type { get; set; }
|
||||
[JsonProperty("channel_id")]
|
||||
public ulong ChannelId { get; set; }
|
||||
[JsonProperty("webhook_id")]
|
||||
public Optional<ulong> WebhookId { get; set; }
|
||||
[JsonProperty("author")]
|
||||
public Optional<User> Author { get; set; }
|
||||
[JsonProperty("content")]
|
||||
public Optional<string> Content { get; set; }
|
||||
[JsonProperty("timestamp")]
|
||||
public Optional<DateTimeOffset> Timestamp { get; set; }
|
||||
[JsonProperty("edited_timestamp")]
|
||||
public Optional<DateTimeOffset?> EditedTimestamp { get; set; }
|
||||
[JsonProperty("tts")]
|
||||
public Optional<bool> IsTextToSpeech { get; set; }
|
||||
[JsonProperty("mention_everyone")]
|
||||
public Optional<bool> MentionEveryone { get; set; }
|
||||
[JsonProperty("mentions")]
|
||||
public Optional<EntityOrId<User>[]> UserMentions { get; set; }
|
||||
[JsonProperty("mention_roles")]
|
||||
public Optional<ulong[]> RoleMentions { get; set; }
|
||||
[JsonProperty("attachments")]
|
||||
public Optional<Attachment[]> Attachments { get; set; }
|
||||
[JsonProperty("embeds")]
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
[JsonProperty("pinned")]
|
||||
public Optional<bool> Pinned { get; set; }
|
||||
[JsonProperty("reactions")]
|
||||
public Optional<Reaction[]> Reactions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Overwrite
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong TargetId { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public PermissionTarget TargetType { get; set; }
|
||||
[JsonProperty("deny"), Int53]
|
||||
public ulong Deny { get; set; }
|
||||
[JsonProperty("allow"), Int53]
|
||||
public ulong Allow { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Presence
|
||||
{
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
[JsonProperty("guild_id")]
|
||||
public Optional<ulong> GuildId { get; set; }
|
||||
[JsonProperty("status")]
|
||||
public UserStatus Status { get; set; }
|
||||
[JsonProperty("game")]
|
||||
public Game Game { get; set; }
|
||||
|
||||
[JsonProperty("roles")]
|
||||
public Optional<ulong[]> Roles { get; set; }
|
||||
[JsonProperty("nick")]
|
||||
public Optional<string> Nick { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Reaction
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("me")]
|
||||
public bool Me { get; set; }
|
||||
[JsonProperty("emoji")]
|
||||
public Emoji Emoji { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class ReadState
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("mention_count")]
|
||||
public int MentionCount { get; set; }
|
||||
[JsonProperty("last_message_id")]
|
||||
public Optional<ulong> LastMessageId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Relationship
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public RelationshipType Type { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
namespace Discord.API
|
||||
{
|
||||
public enum RelationshipType
|
||||
{
|
||||
Friend = 1,
|
||||
Blocked = 2,
|
||||
IncomingPending = 3,
|
||||
OutgoingPending = 4
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class Role
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("color")]
|
||||
public uint Color { get; set; }
|
||||
[JsonProperty("hoist")]
|
||||
public bool Hoist { get; set; }
|
||||
[JsonProperty("mentionable")]
|
||||
public bool Mentionable { get; set; }
|
||||
[JsonProperty("position")]
|
||||
public int Position { get; set; }
|
||||
[JsonProperty("permissions"), Int53]
|
||||
public ulong Permissions { get; set; }
|
||||
[JsonProperty("managed")]
|
||||
public bool Managed { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class User
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("username")]
|
||||
public Optional<string> Username { get; set; }
|
||||
[JsonProperty("discriminator")]
|
||||
public Optional<string> Discriminator { get; set; }
|
||||
[JsonProperty("bot")]
|
||||
public Optional<bool> Bot { get; set; }
|
||||
[JsonProperty("avatar")]
|
||||
public Optional<string> Avatar { get; set; }
|
||||
|
||||
//CurrentUser
|
||||
[JsonProperty("verified")]
|
||||
public Optional<bool> Verified { get; set; }
|
||||
[JsonProperty("email")]
|
||||
public Optional<string> Email { get; set; }
|
||||
[JsonProperty("mfa_enabled")]
|
||||
public Optional<bool> MfaEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class UserGuild
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("icon")]
|
||||
public string Icon { get; set; }
|
||||
[JsonProperty("owner")]
|
||||
public bool Owner { get; set; }
|
||||
[JsonProperty("permissions"), Int53]
|
||||
public ulong Permissions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class VoiceRegion
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("vip")]
|
||||
public bool IsVip { get; set; }
|
||||
[JsonProperty("optimal")]
|
||||
public bool IsOptimal { get; set; }
|
||||
[JsonProperty("sample_hostname")]
|
||||
public string SampleHostname { get; set; }
|
||||
[JsonProperty("sample_port")]
|
||||
public int SamplePort { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public class VoiceState
|
||||
{
|
||||
[JsonProperty("guild_id")]
|
||||
public ulong? GuildId { get; set; }
|
||||
[JsonProperty("channel_id")]
|
||||
public ulong? ChannelId { get; set; }
|
||||
[JsonProperty("user_id")]
|
||||
public ulong UserId { get; set; }
|
||||
[JsonProperty("session_id")]
|
||||
public string SessionId { get; set; }
|
||||
[JsonProperty("deaf")]
|
||||
public bool Deaf { get; set; }
|
||||
[JsonProperty("mute")]
|
||||
public bool Mute { get; set; }
|
||||
[JsonProperty("self_deaf")]
|
||||
public bool SelfDeaf { get; set; }
|
||||
[JsonProperty("self_mute")]
|
||||
public bool SelfMute { get; set; }
|
||||
[JsonProperty("suppress")]
|
||||
public bool Suppress { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
namespace Discord.API
|
||||
{
|
||||
public struct EntityOrId<T>
|
||||
{
|
||||
public ulong Id { get; }
|
||||
public T Object { get; }
|
||||
|
||||
public EntityOrId(ulong id)
|
||||
{
|
||||
Id = id;
|
||||
Object = default(T);
|
||||
}
|
||||
public EntityOrId(T obj)
|
||||
{
|
||||
Id = 0;
|
||||
Object = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
public struct Image
|
||||
{
|
||||
public Stream Stream { get; }
|
||||
public string Hash { get; }
|
||||
|
||||
public Image(Stream stream)
|
||||
{
|
||||
Stream = stream;
|
||||
Hash = null;
|
||||
}
|
||||
public Image(string hash)
|
||||
{
|
||||
Stream = null;
|
||||
Hash = hash;
|
||||
}
|
||||
|
||||
internal static Image Create(Discord.Image image)
|
||||
{
|
||||
return new Image(image.Stream);
|
||||
}
|
||||
internal static Image? Create(Discord.Image? image)
|
||||
{
|
||||
if (image.HasValue)
|
||||
return new Image(image.Value.Stream);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using System;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class Int53Attribute : Attribute { }
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class CreateChannelInviteParams
|
||||
{
|
||||
[JsonProperty("max_age")]
|
||||
public Optional<int> MaxAge { get; set; }
|
||||
[JsonProperty("max_uses")]
|
||||
public Optional<int> MaxUses { get; set; }
|
||||
[JsonProperty("temporary")]
|
||||
public Optional<bool> IsTemporary { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class CreateDMChannelParams
|
||||
{
|
||||
[JsonProperty("recipient_id")]
|
||||
public ulong RecipientId { get; }
|
||||
|
||||
public CreateDMChannelParams(ulong recipientId)
|
||||
{
|
||||
RecipientId = recipientId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class CreateGuildBanParams
|
||||
{
|
||||
public Optional<int> DeleteMessageDays { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class CreateGuildChannelParams
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; }
|
||||
[JsonProperty("type")]
|
||||
public ChannelType Type { get; }
|
||||
|
||||
[JsonProperty("bitrate")]
|
||||
public Optional<int> Bitrate { get; set; }
|
||||
|
||||
public CreateGuildChannelParams(string name, ChannelType type)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class CreateGuildIntegrationParams
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; }
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; }
|
||||
|
||||
public CreateGuildIntegrationParams(ulong id, string type)
|
||||
{
|
||||
Id = id;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class CreateGuildParams
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; }
|
||||
[JsonProperty("region")]
|
||||
public string RegionId { get; }
|
||||
|
||||
[JsonProperty("icon")]
|
||||
public Optional<Image?> Icon { get; set; }
|
||||
|
||||
public CreateGuildParams(string name, string regionId)
|
||||
{
|
||||
Name = name;
|
||||
RegionId = regionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class CreateMessageParams
|
||||
{
|
||||
[JsonProperty("content")]
|
||||
public string Content { get; }
|
||||
|
||||
[JsonProperty("nonce")]
|
||||
public Optional<string> Nonce { get; set; }
|
||||
[JsonProperty("tts")]
|
||||
public Optional<bool> IsTTS { get; set; }
|
||||
[JsonProperty("embed")]
|
||||
public Optional<Embed> Embed { get; set; }
|
||||
|
||||
public CreateMessageParams(string content)
|
||||
{
|
||||
Content = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class DeleteMessagesParams
|
||||
{
|
||||
[JsonProperty("messages")]
|
||||
public ulong[] MessageIds { get; }
|
||||
|
||||
public DeleteMessagesParams(ulong[] messageIds)
|
||||
{
|
||||
MessageIds = messageIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class GetChannelMessagesParams
|
||||
{
|
||||
public Optional<int> Limit { get; set; }
|
||||
public Optional<Direction> RelativeDirection { get; set; }
|
||||
public Optional<ulong> RelativeMessageId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class GetGatewayResponse
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class GetGuildMembersParams
|
||||
{
|
||||
public Optional<int> Limit { get; set; }
|
||||
public Optional<ulong> AfterUserId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class GetGuildPruneCountResponse
|
||||
{
|
||||
[JsonProperty("pruned")]
|
||||
public int Pruned { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class GetReactionUsersParams
|
||||
{
|
||||
public Optional<int> Limit { get; set; }
|
||||
public Optional<ulong> AfterUserId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class GuildPruneParams
|
||||
{
|
||||
[JsonProperty("days")]
|
||||
public int Days { get; }
|
||||
|
||||
public GuildPruneParams(int days)
|
||||
{
|
||||
Days = days;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyChannelPermissionsParams
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; }
|
||||
[JsonProperty("allow")]
|
||||
public ulong Allow { get; }
|
||||
[JsonProperty("deny")]
|
||||
public ulong Deny { get; }
|
||||
|
||||
public ModifyChannelPermissionsParams(string type, ulong allow, ulong deny)
|
||||
{
|
||||
Type = type;
|
||||
Allow = allow;
|
||||
Deny = deny;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyCurrentUserNickParams
|
||||
{
|
||||
[JsonProperty("nick")]
|
||||
public string Nickname { get; }
|
||||
|
||||
public ModifyCurrentUserNickParams(string nickname)
|
||||
{
|
||||
Nickname = nickname;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyCurrentUserParams
|
||||
{
|
||||
[JsonProperty("username")]
|
||||
public Optional<string> Username { get; set; }
|
||||
[JsonProperty("avatar")]
|
||||
public Optional<Image?> Avatar { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildChannelParams
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public Optional<string> Name { get; set; }
|
||||
[JsonProperty("position")]
|
||||
public Optional<int> Position { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildChannelsParams
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
[JsonProperty("position")]
|
||||
public int Position { get; set; }
|
||||
|
||||
public ModifyGuildChannelsParams(ulong id, int position)
|
||||
{
|
||||
Id = id;
|
||||
Position = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildEmbedParams
|
||||
{
|
||||
[JsonProperty("enabled")]
|
||||
public Optional<bool> Enabled { get; set; }
|
||||
[JsonProperty("channel")]
|
||||
public Optional<ulong?> ChannelId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildIntegrationParams
|
||||
{
|
||||
[JsonProperty("expire_behavior")]
|
||||
public Optional<int> ExpireBehavior { get; set; }
|
||||
[JsonProperty("expire_grace_period")]
|
||||
public Optional<int> ExpireGracePeriod { get; set; }
|
||||
[JsonProperty("enable_emoticons")]
|
||||
public Optional<bool> EnableEmoticons { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildMemberParams
|
||||
{
|
||||
[JsonProperty("mute")]
|
||||
public Optional<bool> Mute { get; set; }
|
||||
[JsonProperty("deaf")]
|
||||
public Optional<bool> Deaf { get; set; }
|
||||
[JsonProperty("nick")]
|
||||
public Optional<string> Nickname { get; set; }
|
||||
[JsonProperty("roles")]
|
||||
public Optional<ulong[]> RoleIds { get; set; }
|
||||
[JsonProperty("channel_id")]
|
||||
public Optional<ulong> ChannelId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildParams
|
||||
{
|
||||
[JsonProperty("username")]
|
||||
public Optional<string> Username { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public Optional<string> Name { get; set; }
|
||||
[JsonProperty("region")]
|
||||
public Optional<string> RegionId { get; set; }
|
||||
[JsonProperty("verification_level")]
|
||||
public Optional<VerificationLevel> VerificationLevel { get; set; }
|
||||
[JsonProperty("default_message_notifications")]
|
||||
public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; }
|
||||
[JsonProperty("afk_timeout")]
|
||||
public Optional<int> AfkTimeout { get; set; }
|
||||
[JsonProperty("icon")]
|
||||
public Optional<Image?> Icon { get; set; }
|
||||
[JsonProperty("splash")]
|
||||
public Optional<Image?> Splash { get; set; }
|
||||
[JsonProperty("afk_channel_id")]
|
||||
public Optional<ulong?> AfkChannelId { get; set; }
|
||||
[JsonProperty("owner_id")]
|
||||
public Optional<ulong> OwnerId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildRoleParams
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public Optional<string> Name { get; set; }
|
||||
[JsonProperty("permissions")]
|
||||
public Optional<ulong> Permissions { get; set; }
|
||||
[JsonProperty("position")]
|
||||
public Optional<int> Position { get; set; }
|
||||
[JsonProperty("color")]
|
||||
public Optional<uint> Color { get; set; }
|
||||
[JsonProperty("hoist")]
|
||||
public Optional<bool> Hoist { get; set; }
|
||||
[JsonProperty("mentionable")]
|
||||
public Optional<bool> Mentionable { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyGuildRolesParams : ModifyGuildRoleParams
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; }
|
||||
|
||||
public ModifyGuildRolesParams(ulong id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyMessageParams
|
||||
{
|
||||
[JsonProperty("content")]
|
||||
public Optional<string> Content { get; set; }
|
||||
[JsonProperty("embed")]
|
||||
public Optional<Embed> Embed { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyTextChannelParams : ModifyGuildChannelParams
|
||||
{
|
||||
[JsonProperty("topic")]
|
||||
public Optional<string> Topic { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
public class ModifyVoiceChannelParams : ModifyGuildChannelParams
|
||||
{
|
||||
[JsonProperty("bitrate")]
|
||||
public Optional<int> Bitrate { get; set; }
|
||||
[JsonProperty("user_limit")]
|
||||
public Optional<int> UserLimit { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
using Discord.Net.Rest;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
{
|
||||
public class UploadFileParams
|
||||
{
|
||||
public Stream File { get; }
|
||||
|
||||
public Optional<string> Filename { get; set; }
|
||||
public Optional<string> Content { get; set; }
|
||||
public Optional<string> Nonce { get; set; }
|
||||
public Optional<bool> IsTTS { get; set; }
|
||||
|
||||
public UploadFileParams(Stream file)
|
||||
{
|
||||
File = file;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, object> ToDictionary()
|
||||
{
|
||||
var d = new Dictionary<string, object>();
|
||||
d["file"] = new MultipartFile(File, Filename.GetValueOrDefault("unknown.dat"));
|
||||
if (Content.IsSpecified)
|
||||
d["content"] = Content.Value;
|
||||
if (IsTTS.IsSpecified)
|
||||
d["tts"] = IsTTS.Value.ToString();
|
||||
if (Nonce.IsSpecified)
|
||||
d["nonce"] = Nonce.Value;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,6 @@ namespace Discord.Audio
|
||||
Task DisconnectAsync();
|
||||
|
||||
Stream CreateOpusStream(int samplesPerFrame, int bufferSize = 4000);
|
||||
Stream CreatePCMStream(int samplesPerFrame, int? bitrate = null, OpusApplication application = OpusApplication.MusicOrMixed, int bufferSize = 4000);
|
||||
Stream CreatePCMStream(int samplesPerFrame, int? bitrate = null, int bufferSize = 4000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Discord.Audio
|
||||
{
|
||||
public enum OpusApplication : int
|
||||
{
|
||||
Voice = 2048,
|
||||
MusicOrMixed = 2049,
|
||||
LowLatency = 2051
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Discord.API
|
||||
namespace Discord
|
||||
{
|
||||
public static class CDN
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Description>A .Net API wrapper and bot framework for Discord.</Description>
|
||||
<VersionPrefix>1.0.0-beta2</VersionPrefix>
|
||||
@@ -9,17 +9,26 @@
|
||||
<PackageLicenseUrl>http://opensource.org/licenses/MIT</PackageLicenseUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>git://github.com/RogueException/Discord.Net</RepositoryUrl>
|
||||
<RootNamespace>Discord</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="**\*.cs" />
|
||||
<EmbeddedResource Include="**\*.resx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Discord.Net.API\Discord.Net.API.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
||||
<PackageReference Include="System.Collections.Concurrent" Version="4.3.0" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="1.3.0" />
|
||||
<PackageReference Include="System.Interactive.Async" Version="3.1.0" />
|
||||
<PackageReference Include="System.Linq" Version="4.1.0" />
|
||||
<PackageReference Include="System.Linq.Expressions" Version="4.1.0" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.0" />
|
||||
<PackageReference Include="System.Reflection" Version="4.1.0" />
|
||||
<PackageReference Include="System.Resources.ResourceManager" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime" Version="4.1.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.1.1" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum ChannelType
|
||||
{
|
||||
Text = 0,
|
||||
DM = 1,
|
||||
Voice = 2,
|
||||
Group = 3
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum DefaultMessageNotifications
|
||||
{
|
||||
/// <summary> By default, all messages will trigger notifications. </summary>
|
||||
AllMessages = 0,
|
||||
/// <summary> By default, only mentions will trigger notifications. </summary>
|
||||
MentionsOnly = 1
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum MfaLevel
|
||||
{
|
||||
/// <summary> Users have no additional MFA restriction on this guild. </summary>
|
||||
Disabled = 0,
|
||||
/// <summary> Users must have MFA enabled on their account to perform administrative actions. </summary>
|
||||
Enabled = 1
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum VerificationLevel
|
||||
{
|
||||
/// <summary> Users have no additional restrictions on sending messages to this guild. </summary>
|
||||
None = 0,
|
||||
/// <summary> Users must have a verified email on their account. </summary>
|
||||
Low = 1,
|
||||
/// <summary> Users must fulfill the requirements of Low, and be registered on Discord for at least 5 minutes. </summary>
|
||||
Medium = 2,
|
||||
/// <summary> Users must fulfill the requirements of Medium, and be a member of this guild for at least 10 minutes. </summary>
|
||||
High = 3
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using Model = Discord.API.Image;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
@@ -29,5 +30,10 @@ namespace Discord
|
||||
Stream = File.OpenRead(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
public Model ToModel()
|
||||
{
|
||||
return new Model(Stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum Direction
|
||||
{
|
||||
Before,
|
||||
After,
|
||||
Around
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum MessageType
|
||||
{
|
||||
Default = 0,
|
||||
RecipientAdd = 1,
|
||||
RecipientRemove = 2,
|
||||
Call = 3,
|
||||
ChannelNameChange = 4,
|
||||
ChannelIconChange = 5,
|
||||
ChannelPinnedMessage = 6
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum PermissionTarget
|
||||
{
|
||||
Role,
|
||||
User
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,6 @@
|
||||
/// <summary>
|
||||
/// Your avatar
|
||||
/// </summary>
|
||||
public Optional<Image> Avatar { get; set; }
|
||||
public Optional<Image?> Avatar { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum StreamType
|
||||
{
|
||||
NotStreaming = 0,
|
||||
Twitch = 1
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Discord
|
||||
{
|
||||
public enum UserStatus
|
||||
{
|
||||
Unknown,
|
||||
Online,
|
||||
Idle,
|
||||
AFK,
|
||||
DoNotDisturb,
|
||||
Invisible,
|
||||
Offline
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using Discord.API;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -9,7 +8,6 @@ namespace Discord
|
||||
public interface IDiscordClient : IDisposable
|
||||
{
|
||||
ConnectionState ConnectionState { get; }
|
||||
DiscordRestApiClient ApiClient { get; }
|
||||
ISelfUser CurrentUser { get; }
|
||||
|
||||
Task ConnectAsync();
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
public enum ClientBucketType
|
||||
{
|
||||
Unbucketed = 0,
|
||||
SendEdit = 1
|
||||
}
|
||||
internal struct ClientBucket
|
||||
{
|
||||
private static readonly ImmutableDictionary<ClientBucketType, ClientBucket> _defsByType;
|
||||
private static readonly ImmutableDictionary<string, ClientBucket> _defsById;
|
||||
|
||||
static ClientBucket()
|
||||
{
|
||||
var buckets = new[]
|
||||
{
|
||||
new ClientBucket(ClientBucketType.Unbucketed, "<unbucketed>", 10, 10),
|
||||
new ClientBucket(ClientBucketType.SendEdit, "<send_edit>", 10, 10)
|
||||
};
|
||||
|
||||
var builder = ImmutableDictionary.CreateBuilder<ClientBucketType, ClientBucket>();
|
||||
foreach (var bucket in buckets)
|
||||
builder.Add(bucket.Type, bucket);
|
||||
_defsByType = builder.ToImmutable();
|
||||
|
||||
var builder2 = ImmutableDictionary.CreateBuilder<string, ClientBucket>();
|
||||
foreach (var bucket in buckets)
|
||||
builder2.Add(bucket.Id, bucket);
|
||||
_defsById = builder2.ToImmutable();
|
||||
}
|
||||
|
||||
public static ClientBucket Get(ClientBucketType type) => _defsByType[type];
|
||||
public static ClientBucket Get(string id) => _defsById[id];
|
||||
|
||||
public ClientBucketType Type { get; }
|
||||
public string Id { get; }
|
||||
public int WindowCount { get; }
|
||||
public int WindowSeconds { get; }
|
||||
|
||||
public ClientBucket(ClientBucketType type, string id, int count, int seconds)
|
||||
{
|
||||
Type = type;
|
||||
Id = id;
|
||||
WindowCount = count;
|
||||
WindowSeconds = seconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
#if DEBUG_LIMITS
|
||||
using System.Diagnostics;
|
||||
#endif
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
public class RequestQueue : IDisposable
|
||||
{
|
||||
public event Func<string, RateLimitInfo?, Task> RateLimitTriggered;
|
||||
|
||||
private readonly ConcurrentDictionary<string, RequestBucket> _buckets;
|
||||
private readonly SemaphoreSlim _tokenLock;
|
||||
private CancellationTokenSource _clearToken;
|
||||
private CancellationToken _parentToken;
|
||||
private CancellationToken _requestCancelToken; //Parent token + Clear token
|
||||
private CancellationTokenSource _cancelToken; //Dispose token
|
||||
private DateTimeOffset _waitUntil;
|
||||
|
||||
private Task _cleanupTask;
|
||||
|
||||
public RequestQueue()
|
||||
{
|
||||
_tokenLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
_clearToken = new CancellationTokenSource();
|
||||
_cancelToken = new CancellationTokenSource();
|
||||
_requestCancelToken = CancellationToken.None;
|
||||
_parentToken = CancellationToken.None;
|
||||
|
||||
_buckets = new ConcurrentDictionary<string, RequestBucket>();
|
||||
|
||||
_cleanupTask = RunCleanup();
|
||||
}
|
||||
|
||||
public async Task SetCancelTokenAsync(CancellationToken cancelToken)
|
||||
{
|
||||
await _tokenLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
_parentToken = cancelToken;
|
||||
_requestCancelToken = CancellationTokenSource.CreateLinkedTokenSource(cancelToken, _clearToken.Token).Token;
|
||||
}
|
||||
finally { _tokenLock.Release(); }
|
||||
}
|
||||
public async Task ClearAsync()
|
||||
{
|
||||
await _tokenLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
_clearToken?.Cancel();
|
||||
_clearToken = new CancellationTokenSource();
|
||||
if (_parentToken != null)
|
||||
_requestCancelToken = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken).Token;
|
||||
else
|
||||
_requestCancelToken = _clearToken.Token;
|
||||
}
|
||||
finally { _tokenLock.Release(); }
|
||||
}
|
||||
|
||||
public async Task<Stream> SendAsync(RestRequest request)
|
||||
{
|
||||
if (request.Options.CancelToken.CanBeCanceled)
|
||||
request.Options.CancelToken = CancellationTokenSource.CreateLinkedTokenSource(_requestCancelToken, request.Options.CancelToken).Token;
|
||||
else
|
||||
request.Options.CancelToken = _requestCancelToken;
|
||||
|
||||
var bucket = GetOrCreateBucket(request.Options.BucketId, request);
|
||||
return await bucket.SendAsync(request).ConfigureAwait(false);
|
||||
}
|
||||
public async Task SendAsync(WebSocketRequest request)
|
||||
{
|
||||
//TODO: Re-impl websocket buckets
|
||||
request.CancelToken = _requestCancelToken;
|
||||
await request.SendAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal async Task EnterGlobalAsync(int id, RestRequest request)
|
||||
{
|
||||
int millis = (int)Math.Ceiling((_waitUntil - DateTimeOffset.UtcNow).TotalMilliseconds);
|
||||
if (millis > 0)
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Sleeping {millis} ms (Pre-emptive) [Global]");
|
||||
#endif
|
||||
await Task.Delay(millis).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
internal void PauseGlobal(RateLimitInfo info, TimeSpan lag)
|
||||
{
|
||||
_waitUntil = DateTimeOffset.UtcNow.AddMilliseconds(info.RetryAfter.Value + lag.TotalMilliseconds);
|
||||
}
|
||||
|
||||
private RequestBucket GetOrCreateBucket(string id, RestRequest request)
|
||||
{
|
||||
return _buckets.GetOrAdd(id, x => new RequestBucket(this, request, x));
|
||||
}
|
||||
internal async Task RaiseRateLimitTriggered(string bucketId, RateLimitInfo? info)
|
||||
{
|
||||
await RateLimitTriggered(bucketId, info).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task RunCleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!_cancelToken.IsCancellationRequested)
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
foreach (var bucket in _buckets.Select(x => x.Value))
|
||||
{
|
||||
RequestBucket ignored;
|
||||
if ((now - bucket.LastAttemptAt).TotalMinutes > 1.0)
|
||||
_buckets.TryRemove(bucket.Id, out ignored);
|
||||
}
|
||||
await Task.Delay(60000, _cancelToken.Token); //Runs each minute
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (ObjectDisposedException) { }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cancelToken.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
#if DEBUG_LIMITS
|
||||
using System.Diagnostics;
|
||||
#endif
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
internal class RequestBucket
|
||||
{
|
||||
private readonly object _lock;
|
||||
private readonly RequestQueue _queue;
|
||||
private int _semaphore;
|
||||
private DateTimeOffset? _resetTick;
|
||||
|
||||
public string Id { get; private set; }
|
||||
public int WindowCount { get; private set; }
|
||||
public DateTimeOffset LastAttemptAt { get; private set; }
|
||||
|
||||
public RequestBucket(RequestQueue queue, RestRequest request, string id)
|
||||
{
|
||||
_queue = queue;
|
||||
Id = id;
|
||||
|
||||
_lock = new object();
|
||||
|
||||
if (request.Options.IsClientBucket)
|
||||
WindowCount = ClientBucket.Get(request.Options.BucketId).WindowCount;
|
||||
else
|
||||
WindowCount = 1; //Only allow one request until we get a header back
|
||||
_semaphore = WindowCount;
|
||||
_resetTick = null;
|
||||
LastAttemptAt = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
static int nextId = 0;
|
||||
public async Task<Stream> SendAsync(RestRequest request)
|
||||
{
|
||||
int id = Interlocked.Increment(ref nextId);
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Start");
|
||||
#endif
|
||||
LastAttemptAt = DateTimeOffset.UtcNow;
|
||||
while (true)
|
||||
{
|
||||
await _queue.EnterGlobalAsync(id, request).ConfigureAwait(false);
|
||||
await EnterAsync(id, request).ConfigureAwait(false);
|
||||
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Sending...");
|
||||
#endif
|
||||
TimeSpan lag = default(TimeSpan);
|
||||
RateLimitInfo info = default(RateLimitInfo);
|
||||
try
|
||||
{
|
||||
var response = await request.SendAsync().ConfigureAwait(false);
|
||||
lag = DateTimeOffset.UtcNow - DateTimeOffset.Parse(response.Headers["Date"]);
|
||||
info = new RateLimitInfo(response.Headers);
|
||||
|
||||
if (response.StatusCode < (HttpStatusCode)200 || response.StatusCode >= (HttpStatusCode)300)
|
||||
{
|
||||
switch (response.StatusCode)
|
||||
{
|
||||
case (HttpStatusCode)429:
|
||||
if (info.IsGlobal)
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] (!) 429 [Global]");
|
||||
#endif
|
||||
_queue.PauseGlobal(info, lag);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] (!) 429");
|
||||
#endif
|
||||
UpdateRateLimit(id, request, info, lag, true);
|
||||
}
|
||||
await _queue.RaiseRateLimitTriggered(Id, info).ConfigureAwait(false);
|
||||
continue; //Retry
|
||||
case HttpStatusCode.BadGateway: //502
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] (!) 502");
|
||||
#endif
|
||||
if ((request.Options.RetryMode & RetryMode.Retry502) == 0)
|
||||
throw new HttpException(HttpStatusCode.BadGateway, null);
|
||||
|
||||
continue; //Retry
|
||||
default:
|
||||
string reason = null;
|
||||
if (response.Stream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var reader = new StreamReader(response.Stream))
|
||||
using (var jsonReader = new JsonTextReader(reader))
|
||||
{
|
||||
var json = JToken.Load(jsonReader);
|
||||
reason = json.Value<string>("message");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
throw new HttpException(response.StatusCode, reason);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Success");
|
||||
#endif
|
||||
return response.Stream;
|
||||
}
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Timeout");
|
||||
#endif
|
||||
if ((request.Options.RetryMode & RetryMode.RetryTimeouts) == 0)
|
||||
throw;
|
||||
|
||||
await Task.Delay(500);
|
||||
continue; //Retry
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Error");
|
||||
#endif
|
||||
if ((request.Options.RetryMode & RetryMode.RetryErrors) == 0)
|
||||
throw;
|
||||
|
||||
await Task.Delay(500);
|
||||
continue; //Retry
|
||||
}
|
||||
finally
|
||||
{
|
||||
UpdateRateLimit(id, request, info, lag, false);
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Stop");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task EnterAsync(int id, RestRequest request)
|
||||
{
|
||||
int windowCount;
|
||||
DateTimeOffset? resetAt;
|
||||
bool isRateLimited = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (DateTimeOffset.UtcNow > request.TimeoutAt || request.Options.CancelToken.IsCancellationRequested)
|
||||
{
|
||||
if (!isRateLimited)
|
||||
throw new TimeoutException();
|
||||
else
|
||||
throw new RateLimitedException();
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
windowCount = WindowCount;
|
||||
resetAt = _resetTick;
|
||||
}
|
||||
|
||||
DateTimeOffset? timeoutAt = request.TimeoutAt;
|
||||
if (windowCount > 0 && Interlocked.Decrement(ref _semaphore) < 0)
|
||||
{
|
||||
if (!isRateLimited)
|
||||
{
|
||||
isRateLimited = true;
|
||||
await _queue.RaiseRateLimitTriggered(Id, null).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if ((request.Options.RetryMode & RetryMode.RetryRatelimit) == 0)
|
||||
throw new RateLimitedException();
|
||||
|
||||
if (resetAt.HasValue)
|
||||
{
|
||||
if (resetAt > timeoutAt)
|
||||
throw new RateLimitedException();
|
||||
int millis = (int)Math.Ceiling((resetAt.Value - DateTimeOffset.UtcNow).TotalMilliseconds);
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Sleeping {millis} ms (Pre-emptive)");
|
||||
#endif
|
||||
if (millis > 0)
|
||||
await Task.Delay(millis, request.Options.CancelToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((timeoutAt.Value - DateTimeOffset.UtcNow).TotalMilliseconds < 500.0)
|
||||
throw new RateLimitedException();
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Sleeping 500* ms (Pre-emptive)");
|
||||
#endif
|
||||
await Task.Delay(500, request.Options.CancelToken).ConfigureAwait(false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#if DEBUG_LIMITS
|
||||
else
|
||||
Debug.WriteLine($"[{id}] Entered Semaphore ({_semaphore}/{WindowCount} remaining)");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRateLimit(int id, RestRequest request, RateLimitInfo info, TimeSpan lag, bool is429)
|
||||
{
|
||||
if (WindowCount == 0)
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
bool hasQueuedReset = _resetTick != null;
|
||||
if (info.Limit.HasValue && WindowCount != info.Limit.Value)
|
||||
{
|
||||
WindowCount = info.Limit.Value;
|
||||
_semaphore = info.Remaining.Value;
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Upgraded Semaphore to {info.Remaining.Value}/{WindowCount}");
|
||||
#endif
|
||||
}
|
||||
|
||||
var now = DateTimeUtils.ToUnixSeconds(DateTimeOffset.UtcNow);
|
||||
DateTimeOffset? resetTick = null;
|
||||
|
||||
//Using X-RateLimit-Remaining causes a race condition
|
||||
/*if (info.Remaining.HasValue)
|
||||
{
|
||||
Debug.WriteLine($"[{id}] X-RateLimit-Remaining: " + info.Remaining.Value);
|
||||
_semaphore = info.Remaining.Value;
|
||||
}*/
|
||||
if (info.RetryAfter.HasValue)
|
||||
{
|
||||
//RetryAfter is more accurate than Reset, where available
|
||||
resetTick = DateTimeOffset.UtcNow.AddMilliseconds(info.RetryAfter.Value);
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Retry-After: {info.RetryAfter.Value} ({info.RetryAfter.Value} ms)");
|
||||
#endif
|
||||
}
|
||||
else if (info.Reset.HasValue)
|
||||
{
|
||||
resetTick = info.Reset.Value.AddSeconds(/*1.0 +*/ lag.TotalSeconds);
|
||||
int diff = (int)(resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds;
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {lag.TotalMilliseconds} ms lag)");
|
||||
#endif
|
||||
}
|
||||
else if (request.Options.IsClientBucket && request.Options.BucketId != null)
|
||||
{
|
||||
resetTick = DateTimeOffset.UtcNow.AddSeconds(ClientBucket.Get(request.Options.BucketId).WindowSeconds);
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Client Bucket ({ClientBucket.Get(request.Options.BucketId).WindowSeconds * 1000} ms)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (resetTick == null)
|
||||
{
|
||||
WindowCount = 0; //No rate limit info, disable limits on this bucket (should only ever happen with a user token)
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Disabled Semaphore");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasQueuedReset || resetTick > _resetTick)
|
||||
{
|
||||
_resetTick = resetTick;
|
||||
LastAttemptAt = resetTick.Value; //Make sure we dont destroy this until after its been reset
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] Reset in {(int)Math.Ceiling((resetTick - DateTimeOffset.UtcNow).Value.TotalMilliseconds)} ms");
|
||||
#endif
|
||||
|
||||
if (!hasQueuedReset)
|
||||
{
|
||||
var _ = QueueReset(id, (int)Math.Ceiling((_resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task QueueReset(int id, int millis)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (millis > 0)
|
||||
await Task.Delay(millis).ConfigureAwait(false);
|
||||
lock (_lock)
|
||||
{
|
||||
millis = (int)Math.Ceiling((_resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds);
|
||||
if (millis <= 0) //Make sure we havent gotten a more accurate reset time
|
||||
{
|
||||
#if DEBUG_LIMITS
|
||||
Debug.WriteLine($"[{id}] * Reset *");
|
||||
#endif
|
||||
_semaphore = WindowCount;
|
||||
_resetTick = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using Discord.Net.Rest;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
public class JsonRestRequest : RestRequest
|
||||
{
|
||||
public string Json { get; }
|
||||
|
||||
public JsonRestRequest(IRestClient client, string method, string endpoint, string json, RequestOptions options)
|
||||
: base(client, method, endpoint, options)
|
||||
{
|
||||
Json = json;
|
||||
}
|
||||
|
||||
public override async Task<RestResponse> SendAsync()
|
||||
{
|
||||
return await Client.SendAsync(Method, Endpoint, Json, Options.CancelToken, Options.HeaderOnly).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Discord.Net.Rest;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
public class MultipartRestRequest : RestRequest
|
||||
{
|
||||
public IReadOnlyDictionary<string, object> MultipartParams { get; }
|
||||
|
||||
public MultipartRestRequest(IRestClient client, string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, RequestOptions options)
|
||||
: base(client, method, endpoint, options)
|
||||
{
|
||||
MultipartParams = multipartParams;
|
||||
}
|
||||
|
||||
public override async Task<RestResponse> SendAsync()
|
||||
{
|
||||
return await Client.SendAsync(Method, Endpoint, MultipartParams, Options.CancelToken, Options.HeaderOnly).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Discord.Net.Rest;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
public class RestRequest
|
||||
{
|
||||
public IRestClient Client { get; }
|
||||
public string Method { get; }
|
||||
public string Endpoint { get; }
|
||||
public DateTimeOffset? TimeoutAt { get; }
|
||||
public TaskCompletionSource<Stream> Promise { get; }
|
||||
public RequestOptions Options { get; }
|
||||
|
||||
public RestRequest(IRestClient client, string method, string endpoint, RequestOptions options)
|
||||
{
|
||||
Preconditions.NotNull(options, nameof(options));
|
||||
|
||||
Client = client;
|
||||
Method = method;
|
||||
Endpoint = endpoint;
|
||||
Options = options;
|
||||
TimeoutAt = options.Timeout.HasValue ? DateTimeOffset.UtcNow.AddMilliseconds(options.Timeout.Value) : (DateTimeOffset?)null;
|
||||
Promise = new TaskCompletionSource<Stream>();
|
||||
}
|
||||
|
||||
public virtual async Task<RestResponse> SendAsync()
|
||||
{
|
||||
return await Client.SendAsync(Method, Endpoint, Options.CancelToken, Options.HeaderOnly).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Discord.Net.WebSockets;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.Queue
|
||||
{
|
||||
public class WebSocketRequest
|
||||
{
|
||||
public IWebSocketClient Client { get; }
|
||||
public string BucketId { get; }
|
||||
public byte[] Data { get; }
|
||||
public bool IsText { get; }
|
||||
public DateTimeOffset? TimeoutAt { get; }
|
||||
public TaskCompletionSource<Stream> Promise { get; }
|
||||
public RequestOptions Options { get; }
|
||||
public CancellationToken CancelToken { get; internal set; }
|
||||
|
||||
public WebSocketRequest(IWebSocketClient client, string bucketId, byte[] data, bool isText, RequestOptions options)
|
||||
{
|
||||
Preconditions.NotNull(options, nameof(options));
|
||||
|
||||
Client = client;
|
||||
BucketId = bucketId;
|
||||
Data = data;
|
||||
IsText = isText;
|
||||
Options = options;
|
||||
TimeoutAt = options.Timeout.HasValue ? DateTimeOffset.UtcNow.AddMilliseconds(options.Timeout.Value) : (DateTimeOffset?)null;
|
||||
Promise = new TaskCompletionSource<Stream>();
|
||||
}
|
||||
|
||||
public async Task SendAsync()
|
||||
{
|
||||
await Client.SendAsync(Data, 0, Data.Length, IsText).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.Net
|
||||
{
|
||||
public struct RateLimitInfo
|
||||
{
|
||||
public bool IsGlobal { get; }
|
||||
public int? Limit { get; }
|
||||
public int? Remaining { get; }
|
||||
public int? RetryAfter { get; }
|
||||
public DateTimeOffset? Reset { get; }
|
||||
|
||||
internal RateLimitInfo(Dictionary<string, string> headers)
|
||||
{
|
||||
string temp;
|
||||
IsGlobal = headers.TryGetValue("X-RateLimit-Global", out temp) ? bool.Parse(temp) : false;
|
||||
Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) ? int.Parse(temp) : (int?)null;
|
||||
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) ? int.Parse(temp) : (int?)null;
|
||||
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) ? DateTimeUtils.FromUnixSeconds(int.Parse(temp)) : (DateTimeOffset?)null;
|
||||
RetryAfter = headers.TryGetValue("Retry-After", out temp) ? int.Parse(temp) : (int?)null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Discord.Net.Rest
|
||||
{
|
||||
struct MultipartFile
|
||||
{
|
||||
public Stream Stream { get; }
|
||||
public string Filename { get; }
|
||||
|
||||
public MultipartFile(Stream stream, string filename)
|
||||
{
|
||||
Stream = stream;
|
||||
Filename = filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
//Based on https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Nullable.cs
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public struct Optional<T>
|
||||
{
|
||||
public static Optional<T> Unspecified => default(Optional<T>);
|
||||
private readonly T _value;
|
||||
|
||||
/// <summary> Gets the value for this paramter. </summary>
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsSpecified)
|
||||
throw new InvalidOperationException("This property has no value set.");
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
/// <summary> Returns true if this value has been specified. </summary>
|
||||
public bool IsSpecified { get; }
|
||||
|
||||
/// <summary> Creates a new Parameter with the provided value. </summary>
|
||||
public Optional(T value)
|
||||
{
|
||||
_value = value;
|
||||
IsSpecified = true;
|
||||
}
|
||||
|
||||
public T GetValueOrDefault() => _value;
|
||||
public T GetValueOrDefault(T defaultValue) => IsSpecified ? _value : defaultValue;
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!IsSpecified) return other == null;
|
||||
if (other == null) return false;
|
||||
return _value.Equals(other);
|
||||
}
|
||||
public override int GetHashCode() => IsSpecified ? _value.GetHashCode() : 0;
|
||||
|
||||
public override string ToString() => IsSpecified ? _value?.ToString() : null;
|
||||
private string DebuggerDisplay => IsSpecified ? (_value?.ToString() ?? "<null>") : "<unspecified>";
|
||||
|
||||
public static implicit operator Optional<T>(T value) => new Optional<T>(value);
|
||||
public static explicit operator T(Optional<T> value) => value.Value;
|
||||
}
|
||||
public static class Optional
|
||||
{
|
||||
public static Optional<T> Create<T>() => Optional<T>.Unspecified;
|
||||
public static Optional<T> Create<T>(T value) => new Optional<T>(value);
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,15 @@
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"Discord.Net.API": {
|
||||
"target": "project"
|
||||
},
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"System.Collections.Concurrent": "4.3.0",
|
||||
"System.Collections.Immutable": "1.3.0",
|
||||
"System.Interactive.Async": "3.1.0",
|
||||
"System.Net.Http": "4.3.0",
|
||||
"System.Runtime": "4.3.0",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1"
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user