@@ -1,20 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API | |||||
{ | |||||
internal sealed class VoiceServerUpdateEvent | |||||
{ | |||||
[JsonProperty("guild_id")] | |||||
[JsonConverter(typeof(LongStringConverter))] | |||||
public ulong ServerId; | |||||
[JsonProperty("endpoint")] | |||||
public string Endpoint; | |||||
[JsonProperty("token")] | |||||
public string Token; | |||||
} | |||||
} |
@@ -1,111 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API | |||||
{ | |||||
public enum VoiceOpCodes : byte | |||||
{ | |||||
/// <summary> Client --> Server - Used to associate a connection with a token. </summary> | |||||
Identify = 0, | |||||
/// <summary> Client --> Server - Used to specify configuration. </summary> | |||||
SelectProtocol = 1, | |||||
/// <summary> Client <-- Server - Used to notify that the voice connection was successful and informs the client of available protocols. </summary> | |||||
Ready = 2, | |||||
/// <summary> Client <-> Server - Used to keep the connection alive and measure latency. </summary> | |||||
Heartbeat = 3, | |||||
/// <summary> Client <-- Server - Used to provide an encryption key to the client. </summary> | |||||
SessionDescription = 4, | |||||
/// <summary> Client <-> Server - Used to inform that a certain user is speaking. </summary> | |||||
Speaking = 5 | |||||
} | |||||
//Commands | |||||
internal sealed class IdentifyCommand : WebSocketMessage<IdentifyCommand.Data> | |||||
{ | |||||
public IdentifyCommand() : base((int)VoiceOpCodes.Identify) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty("server_id")] | |||||
[JsonConverter(typeof(LongStringConverter))] | |||||
public ulong ServerId; | |||||
[JsonProperty("user_id")] | |||||
[JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId; | |||||
[JsonProperty("session_id")] | |||||
public string SessionId; | |||||
[JsonProperty("token")] | |||||
public string Token; | |||||
} | |||||
} | |||||
internal sealed class SelectProtocolCommand : WebSocketMessage<SelectProtocolCommand.Data> | |||||
{ | |||||
public SelectProtocolCommand() : base((int)VoiceOpCodes.SelectProtocol) { } | |||||
public class Data | |||||
{ | |||||
public class SocketInfo | |||||
{ | |||||
[JsonProperty("address")] | |||||
public string Address; | |||||
[JsonProperty("port")] | |||||
public int Port; | |||||
[JsonProperty("mode")] | |||||
public string Mode = "xsalsa20_poly1305"; | |||||
} | |||||
[JsonProperty("protocol")] | |||||
public string Protocol = "udp"; | |||||
[JsonProperty("data")] | |||||
public SocketInfo SocketData = new SocketInfo(); | |||||
} | |||||
} | |||||
internal sealed class HeartbeatCommand : WebSocketMessage<long> | |||||
{ | |||||
public HeartbeatCommand() : base((int)VoiceOpCodes.Heartbeat, EpochTime.GetMilliseconds()) { } | |||||
} | |||||
internal sealed class SpeakingCommand : WebSocketMessage<SpeakingCommand.Data> | |||||
{ | |||||
public SpeakingCommand() : base((int)VoiceOpCodes.Speaking) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty("delay")] | |||||
public int Delay; | |||||
[JsonProperty("speaking")] | |||||
public bool IsSpeaking; | |||||
} | |||||
} | |||||
//Events | |||||
public class VoiceReadyEvent | |||||
{ | |||||
[JsonProperty("ssrc")] | |||||
public uint SSRC; | |||||
[JsonProperty("port")] | |||||
public ushort Port; | |||||
[JsonProperty("modes")] | |||||
public string[] Modes; | |||||
[JsonProperty("heartbeat_interval")] | |||||
public int HeartbeatInterval; | |||||
} | |||||
public class JoinServerEvent | |||||
{ | |||||
[JsonProperty("secret_key")] | |||||
public byte[] SecretKey; | |||||
[JsonProperty("mode")] | |||||
public string Mode; | |||||
} | |||||
public class IsTalkingEvent | |||||
{ | |||||
[JsonProperty("user_id")] | |||||
[JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId; | |||||
[JsonProperty("ssrc")] | |||||
public uint SSRC; | |||||
[JsonProperty("speaking")] | |||||
public bool IsSpeaking; | |||||
} | |||||
} |
@@ -7,7 +7,7 @@ | |||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> | ||||
<PropertyGroup Label="Globals"> | <PropertyGroup Label="Globals"> | ||||
<ProjectGuid>dff7afe3-ca77-4109-bade-b4b49a4f6648</ProjectGuid> | <ProjectGuid>dff7afe3-ca77-4109-bade-b4b49a4f6648</ProjectGuid> | ||||
<RootNamespace>Discord.Audio</RootNamespace> | |||||
<RootNamespace>Discord</RootNamespace> | |||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> | ||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | <OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
@@ -1,4 +1,5 @@ | |||||
using Discord.API; | using Discord.API; | ||||
using Discord.API.Client.GatewaySocket; | |||||
using Discord.Net.WebSockets; | using Discord.Net.WebSockets; | ||||
using System; | using System; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -76,7 +77,7 @@ namespace Discord.Audio | |||||
case "VOICE_SERVER_UPDATE": | case "VOICE_SERVER_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_gatewaySocket.Serializer); | var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_gatewaySocket.Serializer); | ||||
var serverId = data.ServerId; | |||||
var serverId = data.GuildId; | |||||
if (serverId == ServerId) | if (serverId == ServerId) | ||||
{ | { | ||||
@@ -96,10 +97,6 @@ namespace Discord.Audio | |||||
}; | }; | ||||
} | } | ||||
public Task Disconnect() | |||||
{ | |||||
return _voiceSocket.Disconnect(); | |||||
} | |||||
internal void SetServerId(ulong serverId) | internal void SetServerId(ulong serverId) | ||||
{ | { | ||||
@@ -115,14 +112,17 @@ namespace Discord.Audio | |||||
await _voiceSocket.Disconnect().ConfigureAwait(false); | await _voiceSocket.Disconnect().ConfigureAwait(false); | ||||
_voiceSocket.ChannelId = channel.Id; | _voiceSocket.ChannelId = channel.Id; | ||||
_gatewaySocket.SendJoinVoice(channel.Server.Id, channel.Id); | |||||
_gatewaySocket.SendUpdateVoice(channel.Server.Id, channel.Id, | |||||
(_service.Config.Mode | AudioMode.Outgoing) == 0, | |||||
(_service.Config.Mode | AudioMode.Incoming) == 0); | |||||
await _voiceSocket.WaitForConnection(_service.Config.ConnectionTimeout).ConfigureAwait(false); | await _voiceSocket.WaitForConnection(_service.Config.ConnectionTimeout).ConfigureAwait(false); | ||||
} | |||||
} | |||||
public Task Disconnect() => _voiceSocket.Disconnect(); | |||||
/// <summary> Sends a PCM frame to the voice server. Will block until space frees up in the outgoing buffer. </summary> | |||||
/// <param name="data">PCM frame to send. This must be a single or collection of uncompressed 48Kz monochannel 20ms PCM frames. </param> | |||||
/// <param name="count">Number of bytes in this frame. </param> | |||||
public void Send(byte[] data, int count) | |||||
/// <summary> Sends a PCM frame to the voice server. Will block until space frees up in the outgoing buffer. </summary> | |||||
/// <param name="data">PCM frame to send. This must be a single or collection of uncompressed 48Kz monochannel 20ms PCM frames. </param> | |||||
/// <param name="count">Number of bytes in this frame. </param> | |||||
public void Send(byte[] data, int count) | |||||
{ | { | ||||
if (data == null) throw new ArgumentException(nameof(data)); | if (data == null) throw new ArgumentException(nameof(data)); | ||||
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count)); | if (count < 0) throw new ArgumentOutOfRangeException(nameof(count)); | ||||
@@ -1,4 +1,6 @@ | |||||
using Discord.API; | using Discord.API; | ||||
using Discord.API.Client; | |||||
using Discord.API.Client.VoiceSocket; | |||||
using Discord.Audio; | using Discord.Audio; | ||||
using Discord.Audio.Opus; | using Discord.Audio.Opus; | ||||
using Discord.Audio.Sodium; | using Discord.Audio.Sodium; | ||||
@@ -394,14 +396,14 @@ namespace Discord.Net.WebSockets | |||||
{ | { | ||||
await base.ProcessMessage(json).ConfigureAwait(false); | await base.ProcessMessage(json).ConfigureAwait(false); | ||||
var msg = JsonConvert.DeserializeObject<WebSocketMessage>(json); | var msg = JsonConvert.DeserializeObject<WebSocketMessage>(json); | ||||
var opCode = (VoiceOpCodes)msg.Operation; | |||||
var opCode = (OpCodes)msg.Operation; | |||||
switch (opCode) | switch (opCode) | ||||
{ | { | ||||
case VoiceOpCodes.Ready: | |||||
case OpCodes.Ready: | |||||
{ | { | ||||
if (_state != ConnectionState.Connected) | if (_state != ConnectionState.Connected) | ||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<VoiceReadyEvent>(_serializer); | |||||
var payload = (msg.Payload as JToken).ToObject<ReadyEvent>(_serializer); | |||||
_heartbeatInterval = payload.HeartbeatInterval; | _heartbeatInterval = payload.HeartbeatInterval; | ||||
_ssrc = payload.SSRC; | _ssrc = payload.SSRC; | ||||
var address = (await Dns.GetHostAddressesAsync(Host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(); | var address = (await Dns.GetHostAddressesAsync(Host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(); | ||||
@@ -435,7 +437,7 @@ namespace Discord.Net.WebSockets | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case VoiceOpCodes.Heartbeat: | |||||
case OpCodes.Heartbeat: | |||||
{ | { | ||||
long time = EpochTime.GetMilliseconds(); | long time = EpochTime.GetMilliseconds(); | ||||
var payload = (long)msg.Payload; | var payload = (long)msg.Payload; | ||||
@@ -443,17 +445,17 @@ namespace Discord.Net.WebSockets | |||||
//TODO: Use this to estimate latency | //TODO: Use this to estimate latency | ||||
} | } | ||||
break; | break; | ||||
case VoiceOpCodes.SessionDescription: | |||||
case OpCodes.SessionDescription: | |||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<JoinServerEvent>(_serializer); | |||||
var payload = (msg.Payload as JToken).ToObject<SessionDescriptionEvent>(_serializer); | |||||
_secretKey = payload.SecretKey; | _secretKey = payload.SecretKey; | ||||
SendIsTalking(true); | |||||
SendSetSpeaking(true); | |||||
EndConnect(); | EndConnect(); | ||||
} | } | ||||
break; | break; | ||||
case VoiceOpCodes.Speaking: | |||||
case OpCodes.Speaking: | |||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<IsTalkingEvent>(_serializer); | |||||
var payload = (msg.Payload as JToken).ToObject<SpeakingEvent>(_serializer); | |||||
RaiseIsSpeaking(payload.UserId, payload.IsSpeaking); | RaiseIsSpeaking(payload.UserId, payload.IsSpeaking); | ||||
} | } | ||||
break; | break; | ||||
@@ -493,37 +495,14 @@ namespace Discord.Net.WebSockets | |||||
}); | }); | ||||
} | } | ||||
public void SendIdentify() | |||||
{ | |||||
var msg = new IdentifyCommand(); | |||||
msg.Payload.ServerId = _serverId.Value; | |||||
msg.Payload.SessionId = _client.SessionId; | |||||
msg.Payload.Token = _audioClient.Token; | |||||
msg.Payload.UserId = _client.UserId.Value; | |||||
QueueMessage(msg); | |||||
} | |||||
public void SendSelectProtocol(string externalIp, int externalPort) | |||||
{ | |||||
var msg = new SelectProtocolCommand(); | |||||
msg.Payload.Protocol = "udp"; | |||||
msg.Payload.SocketData.Address = externalIp; | |||||
msg.Payload.SocketData.Mode = _encryptionMode; | |||||
msg.Payload.SocketData.Port = externalPort; | |||||
QueueMessage(msg); | |||||
} | |||||
public override void SendHeartbeat() | |||||
=> QueueMessage(new HeartbeatCommand()); | |||||
public void SendIdentify() | |||||
=> QueueMessage(new IdentifyCommand { GuildId = _serverId.Value, UserId = _client.UserId.Value, SessionId = _client.SessionId, Token = _audioClient.Token }); | |||||
public void SendSelectProtocol(string externalAddress, int externalPort) | |||||
=> QueueMessage(new SelectProtocolCommand { Protocol = "udp", ExternalAddress = externalAddress, ExternalPort = externalPort, EncryptionMode = _encryptionMode }); | |||||
public void SendSetSpeaking(bool value) | |||||
=> QueueMessage(new SetSpeakingCommand { IsSpeaking = value, Delay = 0 }); | |||||
public void SendIsTalking(bool value) | |||||
{ | |||||
var isTalking = new SpeakingCommand(); | |||||
isTalking.Payload.IsSpeaking = value; | |||||
isTalking.Payload.Delay = 0; | |||||
QueueMessage(isTalking); | |||||
} | |||||
public override void SendHeartbeat() | |||||
{ | |||||
QueueMessage(new HeartbeatCommand()); | |||||
} | |||||
} | } | ||||
} | } |
@@ -0,0 +1,34 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class Channel : ChannelReference | |||||
{ | |||||
public sealed class PermissionOverwrite | |||||
{ | |||||
[JsonProperty("type")] | |||||
public string Type { get; set; } | |||||
[JsonProperty("id")] | |||||
[JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("deny")] | |||||
public uint Deny { get; set; } | |||||
[JsonProperty("allow")] | |||||
public uint Allow { get; set; } | |||||
} | |||||
[JsonProperty("last_message_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong LastMessageId { get; set; } | |||||
[JsonProperty("is_private")] | |||||
public bool IsPrivate { get; set; } | |||||
[JsonProperty("position")] | |||||
public int Position { get; set; } | |||||
[JsonProperty("topic")] | |||||
public string Topic { get; set; } | |||||
[JsonProperty("permission_overwrites")] | |||||
public PermissionOverwrite[] PermissionOverwrites { get; set; } | |||||
[JsonProperty("recipient")] | |||||
public UserReference Recipient { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class ChannelReference | |||||
{ | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("type")] | |||||
public string Type { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,26 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class ExtendedGuild : Guild | |||||
{ | |||||
public sealed class ExtendedMemberInfo : Member | |||||
{ | |||||
[JsonProperty("mute")] | |||||
public bool? IsServerMuted { get; set; } | |||||
[JsonProperty("deaf")] | |||||
public bool? IsServerDeafened { get; set; } | |||||
} | |||||
[JsonProperty("channels")] | |||||
public Channel[] Channels { get; set; } | |||||
[JsonProperty("members")] | |||||
public ExtendedMemberInfo[] Members { get; set; } | |||||
[JsonProperty("presences")] | |||||
public MemberPresence[] Presences { get; set; } | |||||
[JsonProperty("voice_states")] | |||||
public MemberVoiceState[] VoiceStates { get; set; } | |||||
[JsonProperty("unavailable")] | |||||
public bool? Unavailable { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,28 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class Guild : GuildReference | |||||
{ | |||||
[JsonProperty("afk_channel_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong? AFKChannelId { get; set; } | |||||
[JsonProperty("afk_timeout")] | |||||
public int? AFKTimeout { get; set; } | |||||
[JsonProperty("embed_channel_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong? EmbedChannelId { get; set; } | |||||
[JsonProperty("embed_enabled")] | |||||
public bool EmbedEnabled { get; set; } | |||||
[JsonProperty("icon")] | |||||
public string Icon { get; set; } | |||||
[JsonProperty("joined_at")] | |||||
public DateTime? JoinedAt { get; set; } | |||||
[JsonProperty("owner_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong? OwnerId { get; set; } | |||||
[JsonProperty("region")] | |||||
public string Region { get; set; } | |||||
[JsonProperty("roles")] | |||||
public Role[] Roles { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class GuildReference | |||||
{ | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class Invite : InviteReference | |||||
{ | |||||
[JsonProperty("max_age")] | |||||
public int? MaxAge { get; set; } | |||||
[JsonProperty("max_uses")] | |||||
public int? MaxUses { get; set; } | |||||
[JsonProperty("revoked")] | |||||
public bool? IsRevoked { get; set; } | |||||
[JsonProperty("temporary")] | |||||
public bool? IsTemporary { get; set; } | |||||
[JsonProperty("uses")] | |||||
public int? Uses { get; set; } | |||||
[JsonProperty("created_at")] | |||||
public DateTime? CreatedAt { get; set; } | |||||
[JsonProperty("inviter")] | |||||
public UserReference Inviter { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,16 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class InviteReference | |||||
{ | |||||
[JsonProperty("guild")] | |||||
public GuildReference Guild { get; set; } | |||||
[JsonProperty("channel")] | |||||
public ChannelReference Channel { get; set; } | |||||
[JsonProperty("code")] | |||||
public string Code { get; set; } | |||||
[JsonProperty("xkcdpass")] | |||||
public string XkcdPass { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,14 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class Member : MemberReference | |||||
{ | |||||
[JsonProperty("joined_at")] | |||||
public DateTime? JoinedAt { get; set; } | |||||
[JsonProperty("roles"), JsonConverter(typeof(LongStringArrayConverter))] | |||||
public ulong[] Roles { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,15 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class MemberPresence : MemberReference | |||||
{ | |||||
[JsonProperty("game_id")] | |||||
public int? GameId { get; set; } | |||||
[JsonProperty("status")] | |||||
public string Status { get; set; } | |||||
[JsonProperty("roles"), JsonConverter(typeof(LongStringArrayConverter))] | |||||
public ulong[] Roles { get; set; } //TODO: Might be temporary | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class MemberReference | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("user")] | |||||
public UserReference User { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,26 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class MemberVoiceState : MemberReference | |||||
{ | |||||
[JsonProperty("channel_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong? ChannelId { get; set; } | |||||
[JsonProperty("session_id")] | |||||
public string SessionId { get; set; } | |||||
[JsonProperty("token")] | |||||
public string Token { get; set; } | |||||
[JsonProperty("self_mute")] | |||||
public bool? IsSelfMuted { get; set; } | |||||
[JsonProperty("self_deaf")] | |||||
public bool? IsSelfDeafened { get; set; } | |||||
[JsonProperty("mute")] | |||||
public bool? IsServerMuted { get; set; } | |||||
[JsonProperty("deaf")] | |||||
public bool? IsServerDeafened { get; set; } | |||||
[JsonProperty("suppress")] | |||||
public bool? IsServerSuppressed { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,85 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class Message : MessageReference | |||||
{ | |||||
public sealed class Attachment | |||||
{ | |||||
[JsonProperty("id")] | |||||
public string Id { get; set; } | |||||
[JsonProperty("url")] | |||||
public string Url { get; set; } | |||||
[JsonProperty("proxy_url")] | |||||
public string ProxyUrl { get; set; } | |||||
[JsonProperty("size")] | |||||
public int Size { get; set; } | |||||
[JsonProperty("filename")] | |||||
public string Filename { get; set; } | |||||
[JsonProperty("width")] | |||||
public int Width { get; set; } | |||||
[JsonProperty("height")] | |||||
public int Height { get; set; } | |||||
} | |||||
public sealed class Embed | |||||
{ | |||||
public sealed class Reference | |||||
{ | |||||
[JsonProperty("url")] | |||||
public string Url { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
} | |||||
public sealed class ThumbnailInfo | |||||
{ | |||||
[JsonProperty("url")] | |||||
public string Url { get; set; } | |||||
[JsonProperty("proxy_url")] | |||||
public string ProxyUrl { get; set; } | |||||
[JsonProperty("width")] | |||||
public int Width { get; set; } | |||||
[JsonProperty("height")] | |||||
public int Height { get; set; } | |||||
} | |||||
[JsonProperty("url")] | |||||
public string Url { get; set; } | |||||
[JsonProperty("type")] | |||||
public string Type { get; set; } | |||||
[JsonProperty("title")] | |||||
public string Title { get; set; } | |||||
[JsonProperty("description")] | |||||
public string Description { get; set; } | |||||
[JsonProperty("author")] | |||||
public Reference Author { get; set; } | |||||
[JsonProperty("provider")] | |||||
public Reference Provider { get; set; } | |||||
[JsonProperty("thumbnail")] | |||||
public ThumbnailInfo Thumbnail { get; set; } | |||||
} | |||||
[JsonProperty("tts")] | |||||
public bool? IsTextToSpeech { get; set; } | |||||
[JsonProperty("mention_everyone")] | |||||
public bool? IsMentioningEveryone { get; set; } | |||||
[JsonProperty("timestamp")] | |||||
public DateTime? Timestamp { get; set; } | |||||
[JsonProperty("edited_timestamp")] | |||||
public DateTime? EditedTimestamp { get; set; } | |||||
[JsonProperty("mentions")] | |||||
public UserReference[] Mentions { get; set; } | |||||
[JsonProperty("embeds")] | |||||
public Embed[] Embeds { get; set; } //TODO: Parse this | |||||
[JsonProperty("attachments")] | |||||
public Attachment[] Attachments { get; set; } | |||||
[JsonProperty("content")] | |||||
public string Content { get; set; } | |||||
[JsonProperty("author")] | |||||
public UserReference Author { get; set; } | |||||
[JsonProperty("nonce")] | |||||
public string Nonce { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,15 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class MessageReference | |||||
{ | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("message_id"), JsonConverter(typeof(LongStringConverter))] //Only used in MESSAGE_ACK | |||||
public ulong MessageId { get { return Id; } set { Id = value; } } | |||||
[JsonProperty("channel_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong ChannelId { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class RoleReference | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("role_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong RoleId { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public class UserReference | |||||
{ | |||||
[JsonProperty("username")] | |||||
public string Username { get; set; } | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("discriminator")] | |||||
public ushort? Discriminator { get; set; } | |||||
[JsonProperty("avatar")] | |||||
public string Avatar { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,12 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class HeartbeatCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.Heartbeat; | |||||
object IWebSocketMessage.Payload => EpochTime.GetMilliseconds(); | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
using Newtonsoft.Json; | |||||
using System.Collections.Generic; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
internal sealed class IdentifyCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.Identify; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
[JsonProperty("v")] | |||||
public int Version { get; set; } | |||||
[JsonProperty("token")] | |||||
public string Token { get; set; } | |||||
[JsonProperty("properties")] | |||||
public Dictionary<string, string> Properties { get; set; } | |||||
[JsonProperty("large_threshold", NullValueHandling = NullValueHandling.Ignore)] | |||||
public int? LargeThreshold { get; set; } | |||||
[JsonProperty("compress")] | |||||
public bool UseCompression { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
internal sealed class RequestMembersCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.RequestGuildMembers; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("query")] | |||||
public string Query { get; set; } | |||||
[JsonProperty("limit")] | |||||
public int Limit { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class ResumeCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.Resume; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
[JsonProperty("session_id")] | |||||
public string SessionId { get; set; } | |||||
[JsonProperty("seq")] | |||||
public int Sequence { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateStatusCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.StatusUpdate; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
[JsonProperty("idle_since")] | |||||
public long? IdleSince { get; set; } | |||||
[JsonProperty("game_id")] | |||||
public int? GameId { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateVoiceCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.StatusUpdate; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("channel_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong ChannelId { get; set; } | |||||
[JsonProperty("self_mute")] | |||||
public bool IsSelfMuted { get; set; } | |||||
[JsonProperty("self_deaf")] | |||||
public bool IsSelfDeafened { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class ChannelCreateEvent : Channel { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class ChannelDeleteEvent : Channel { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class ChannelUpdateEvent : Channel { } | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildBanAddEvent | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("user_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId { get; } | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildBanRemoveEvent | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("user_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId { get; } | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildCreateEvent : ExtendedGuild { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildDeleteEvent : ExtendedGuild { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
//public sealed class GuildIntegrationsUpdateEvent { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildMemberAddEvent : Member { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildMemberRemoveEvent : Member { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildMemberUpdateEvent : Member { } | |||||
} |
@@ -0,0 +1,10 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildMembersChunkEvent | |||||
{ | |||||
[JsonProperty("members")] | |||||
public Member[] Members; | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildRoleCreateEvent | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("role")] | |||||
public Role Data { get; } | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildRoleDeleteEvent : RoleReference { } | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildRoleUpdateEvent | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("role")] | |||||
public Role Data { get; } | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class GuildUpdateEvent : Guild { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class MessageAckEvent : MessageReference { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class MessageCreateEvent : Message { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class MessageDeleteEvent : MessageReference { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class MessageUpdateEvent : Message { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class PresenceUpdateEvent : MemberPresence { } | |||||
} |
@@ -0,0 +1,32 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class ReadyEvent | |||||
{ | |||||
public sealed class ReadState | |||||
{ | |||||
[JsonProperty("id")] | |||||
public string ChannelId { get; } | |||||
[JsonProperty("mention_count")] | |||||
public int MentionCount { get; } | |||||
[JsonProperty("last_message_id")] | |||||
public string LastMessageId { get; } | |||||
} | |||||
[JsonProperty("v")] | |||||
public int Version { get; } | |||||
[JsonProperty("user")] | |||||
public User User { get; } | |||||
[JsonProperty("session_id")] | |||||
public string SessionId { get; } | |||||
[JsonProperty("read_state")] | |||||
public ReadState[] ReadStates { get; } | |||||
[JsonProperty("guilds")] | |||||
public ExtendedGuild[] Guilds { get; } | |||||
[JsonProperty("private_channels")] | |||||
public Channel[] PrivateChannels { get; } | |||||
[JsonProperty("heartbeat_interval")] | |||||
public int HeartbeatInterval { get; } | |||||
} | |||||
} |
@@ -0,0 +1,10 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class RedirectEvent | |||||
{ | |||||
[JsonProperty("url")] | |||||
public string Url { get; } | |||||
} | |||||
} |
@@ -0,0 +1,10 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class ResumedEvent | |||||
{ | |||||
[JsonProperty("heartbeat_interval")] | |||||
public int HeartbeatInterval { get; } | |||||
} | |||||
} |
@@ -0,0 +1,15 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class TypingStartEvent | |||||
{ | |||||
[JsonProperty("user_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId { get; } | |||||
[JsonProperty("channel_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong ChannelId { get; } | |||||
[JsonProperty("timestamp")] | |||||
public int Timestamp { get; } | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
//public sealed class UserSettingsUpdateEvent { } | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class UserUpdateEvent : User { } | |||||
} |
@@ -0,0 +1,15 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class VoiceServerUpdateEvent | |||||
{ | |||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("endpoint")] | |||||
public string Endpoint { get; } | |||||
[JsonProperty("token")] | |||||
public string Token { get; } | |||||
} | |||||
} |
@@ -0,0 +1,4 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public sealed class VoiceStateUpdateEvent : MemberVoiceState { } | |||||
} |
@@ -0,0 +1,24 @@ | |||||
namespace Discord.API.Client.GatewaySocket | |||||
{ | |||||
public enum OpCodes : byte | |||||
{ | |||||
/// <summary> C←S - Used to send most events. </summary> | |||||
Dispatch = 0, | |||||
/// <summary> C↔S - Used to keep the connection alive and measure latency. </summary> | |||||
Heartbeat = 1, | |||||
/// <summary> C→S - Used to associate a connection with a token and specify configuration. </summary> | |||||
Identify = 2, | |||||
/// <summary> C→S - Used to update client's status and current game id. </summary> | |||||
StatusUpdate = 3, | |||||
/// <summary> C→S - Used to join a particular voice channel. </summary> | |||||
VoiceStateUpdate = 4, | |||||
/// <summary> C→S - Used to ensure the server's voice server is alive. Only send this if voice connection fails or suddenly drops. </summary> | |||||
VoiceServerPing = 5, | |||||
/// <summary> C→S - Used to resume a connection after a redirect occurs. </summary> | |||||
Resume = 6, | |||||
/// <summary> C←S - Used to notify a client that they must reconnect to another gateway. </summary> | |||||
Redirect = 7, | |||||
/// <summary> C→S - Used to request all members that were withheld by large_threshold </summary> | |||||
RequestGuildMembers = 8 | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client | |||||
{ | |||||
public interface IWebSocketMessage | |||||
{ | |||||
int OpCode { get; } | |||||
object Payload { get; } | |||||
bool IsPrivate { get; } | |||||
} | |||||
public class WebSocketMessage | |||||
{ | |||||
[JsonProperty("op")] | |||||
public int Operation { get; } | |||||
[JsonProperty("d")] | |||||
public object Payload { get; } | |||||
[JsonProperty("t", NullValueHandling = NullValueHandling.Ignore)] | |||||
public string Type { get; } | |||||
[JsonProperty("s", NullValueHandling = NullValueHandling.Ignore)] | |||||
public int? Sequence { get; } | |||||
public WebSocketMessage() { } | |||||
public WebSocketMessage(IWebSocketMessage msg) | |||||
{ | |||||
Operation = msg.OpCode; | |||||
Payload = msg.Payload; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class AcceptInviteRequest : IRestRequest<InviteReference> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/invite/{InviteId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public string InviteId { get; } | |||||
public AcceptInviteRequest(string inviteId) | |||||
{ | |||||
InviteId = inviteId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,25 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class AckMessageRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/messages/{MessageId}/ack"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public ulong MessageId { get; } | |||||
/*[JsonProperty("manual")] | |||||
public bool Manual { get; set; }*/ | |||||
public AckMessageRequest(ulong channelId, ulong messageId) | |||||
{ | |||||
ChannelId = channelId; | |||||
MessageId = messageId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,24 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class AddGuildBanRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "PUT"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/bans/{UserId}?delete-message-days={PruneDays}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public ulong UserId { get; } | |||||
public int PruneDays { get; set; } = 0; | |||||
public AddGuildBanRequest(ulong guildId, ulong userId) | |||||
{ | |||||
GuildId = guildId; | |||||
UserId = UserId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class BroadcastTypingRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/typing"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public BroadcastTypingRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,25 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class CreateChannelRequest : IRestRequest<Channel> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/channels"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("type")] | |||||
public string Type { get; set; } | |||||
public CreateChannelRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class CreateGuildRequest : IRestRequest<Guild> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("region")] | |||||
public string Region { get; set; } | |||||
[JsonProperty("icon")] | |||||
public string IconBase64 { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,31 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class CreateInviteRequest : IRestRequest<Invite> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/invites"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
[JsonProperty("max_age")] | |||||
public int MaxAge { get; set; } = 1800; | |||||
[JsonProperty("max_uses")] | |||||
public int MaxUses { get; set; } = 0; | |||||
[JsonProperty("temporary")] | |||||
public bool IsTemporary { get; set; } = false; | |||||
[JsonProperty("xkcdpass")] | |||||
public bool WithXkcdPass { get; set; } = false; | |||||
/*[JsonProperty("validate")] | |||||
public bool Validate { get; set; }*/ | |||||
public CreateInviteRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class CreatePrivateChannelRequest : IRestRequest<Channel> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/users/@me/channels"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
[JsonProperty("recipient_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong RecipientId { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class CreateRoleRequest : IRestRequest<Role> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/roles"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public CreateRoleRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class DeleteChannelRequest : IRestRequest<Channel> | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public DeleteChannelRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class DeleteInviteRequest : IRestRequest<Invite> | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/invite/{InviteCode}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public string InviteCode { get; } | |||||
public DeleteInviteRequest(string inviteCode) | |||||
{ | |||||
InviteCode = inviteCode; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class DeleteMessageRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/messages/{MessageId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public ulong MessageId { get; } | |||||
public DeleteMessageRequest(ulong channelId, ulong messageId) | |||||
{ | |||||
ChannelId = channelId; | |||||
MessageId = messageId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class DeleteRoleRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/roles/{RoleId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public ulong RoleId { get; } | |||||
public DeleteRoleRequest(ulong guildId, ulong roleId) | |||||
{ | |||||
GuildId = guildId; | |||||
RoleId = roleId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,19 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class GatewayRequest : IRestRequest<GatewayResponse> | |||||
{ | |||||
string IRestRequest.Method => "GET"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/gateway"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
} | |||||
public sealed class GatewayResponse | |||||
{ | |||||
[JsonProperty("url")] | |||||
public string Url { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class GetInviteRequest : IRestRequest<InviteReference> | |||||
{ | |||||
string IRestRequest.Method => "GET"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/invite/{InviteCode}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public string InviteCode { get; } | |||||
public GetInviteRequest(string inviteCode) | |||||
{ | |||||
InviteCode = inviteCode; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class GetInvitesRequest : IRestRequest<InviteReference[]> | |||||
{ | |||||
string IRestRequest.Method => "GET"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/invites"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public GetInvitesRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,35 @@ | |||||
using Newtonsoft.Json; | |||||
using System.Text; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class GetMessagesRequest : IRestRequest<Message[]> | |||||
{ | |||||
string IRestRequest.Method => "GET"; | |||||
string IRestRequest.Endpoint | |||||
{ | |||||
get | |||||
{ | |||||
StringBuilder query = new StringBuilder(); | |||||
this.AddQueryParam(query, "limit", Limit.ToString()); | |||||
if (RelativeDir != null) | |||||
this.AddQueryParam(query, RelativeDir, RelativeId.Value.ToString()); | |||||
return $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/messages{query}"; | |||||
} | |||||
} | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public int Limit { get; set; } = 100; | |||||
public string RelativeDir { get; set; } = null; | |||||
public ulong? RelativeId { get; set; } = 0; | |||||
public GetMessagesRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,25 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class GetVoiceRegionsRequest : IRestRequest<GetVoiceRegionsResponse[]> | |||||
{ | |||||
string IRestRequest.Method => "GET"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/voice/regions"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
} | |||||
public sealed class GetVoiceRegionsResponse | |||||
{ | |||||
[JsonProperty("sample_hostname")] | |||||
public string Hostname { get; set; } | |||||
[JsonProperty("sample_port")] | |||||
public int Port { get; set; } | |||||
[JsonProperty("id")] | |||||
public string Id { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class GetWidgetRequest : IRestRequest<GetWidgetResponse> | |||||
{ | |||||
string IRestRequest.Method => "GET"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/servers/{GuildId}/widget.json"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public GetWidgetRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
public sealed class GetWidgetResponse | |||||
{ | |||||
public sealed class Channel | |||||
{ | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("position")] | |||||
public int Position { get; set; } | |||||
} | |||||
public sealed class User : UserReference | |||||
{ | |||||
[JsonProperty("avatar_url")] | |||||
public string AvatarUrl { get; set; } | |||||
[JsonProperty("status")] | |||||
public string Status { get; set; } | |||||
[JsonProperty("game")] | |||||
public UserGame Game { get; set; } | |||||
} | |||||
public sealed class UserGame | |||||
{ | |||||
[JsonProperty("id")] | |||||
public int Id { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
} | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; set; } | |||||
[JsonProperty("channels")] | |||||
public Channel[] Channels { get; set; } | |||||
[JsonProperty("members")] | |||||
public MemberReference[] Members { get; set; } | |||||
[JsonProperty("instant_invite")] | |||||
public string InstantInviteUrl { get; set; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class KickMemberRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/members/{UserId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public ulong UserId { get; } | |||||
public KickMemberRequest(ulong guildId, ulong userId) | |||||
{ | |||||
GuildId = guildId; | |||||
UserId = userId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class LeaveGuildRequest : IRestRequest<Guild> | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public LeaveGuildRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class LogoutRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/auth/logout"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class PruneMembersRequest : IRestRequest<PruneMembersResponse> | |||||
{ | |||||
string IRestRequest.Method => IsSimulation ? "GET" : "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/prune?days={Days}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public int Days { get; set; } = 30; | |||||
public bool IsSimulation { get; set; } = false; | |||||
public PruneMembersRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
public sealed class PruneMembersResponse | |||||
{ | |||||
[JsonProperty("pruned")] | |||||
public int Pruned { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class RemoveChannelPermissionsRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/permissions/{TargetId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public ulong TargetId { get; } | |||||
public RemoveChannelPermissionsRequest(ulong channelId, ulong targetId) | |||||
{ | |||||
ChannelId = channelId; | |||||
TargetId = targetId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class RemoveGuildBanRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "DELETE"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/bans/{UserId}"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public ulong UserId { get; } | |||||
public RemoveGuildBanRequest(ulong guildId, ulong userId) | |||||
{ | |||||
GuildId = guildId; | |||||
UserId = userId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,46 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
using System.Linq; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class ReorderChannelsRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/channels"; | |||||
object IRestRequest.Payload | |||||
{ | |||||
get | |||||
{ | |||||
int pos = StartPos; | |||||
return ChannelIds.Select(x => new Channel(x, pos++)); | |||||
} | |||||
} | |||||
bool IRestRequest.IsPrivate => false; | |||||
public sealed class Channel | |||||
{ | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id; | |||||
[JsonProperty("position")] | |||||
public int Position; | |||||
public Channel(ulong id, int position) | |||||
{ | |||||
Id = id; | |||||
Position = position; | |||||
} | |||||
} | |||||
public ulong GuildId { get; } | |||||
public ulong[] ChannelIds { get; set; } = new ulong[0]; | |||||
public int StartPos { get; set; } = 0; | |||||
public ReorderChannelsRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,46 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
using System.Linq; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class ReorderRolesRequest : IRestRequest<Role[]> | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/roles"; | |||||
object IRestRequest.Payload | |||||
{ | |||||
get | |||||
{ | |||||
int pos = StartPos; | |||||
return RoleIds.Select(x => new Role(x, pos++)); | |||||
} | |||||
} | |||||
bool IRestRequest.IsPrivate => false; | |||||
public sealed class Role | |||||
{ | |||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong Id { get; } | |||||
[JsonProperty("position")] | |||||
public int Position { get; } | |||||
public Role(ulong id, int pos) | |||||
{ | |||||
Id = id; | |||||
Position = pos; | |||||
} | |||||
} | |||||
public ulong GuildId { get; } | |||||
public ulong[] RoleIds { get; set; } = new ulong[0]; | |||||
public int StartPos { get; set; } = 0; | |||||
public ReorderRolesRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,26 @@ | |||||
using Newtonsoft.Json; | |||||
using System.IO; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class SendFileRequest : IRestFileRequest<Message> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/messages"; | |||||
object IRestRequest.Payload => null; | |||||
bool IRestRequest.IsPrivate => false; | |||||
string IRestFileRequest.Filename => Filename; | |||||
Stream IRestFileRequest.Stream => Stream; | |||||
public ulong ChannelId { get; } | |||||
public string Filename { get; set; } | |||||
public Stream Stream { get; set; } | |||||
public SendFileRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,30 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class SendMessageRequest : IRestRequest<Message> | |||||
{ | |||||
string IRestRequest.Method => "POST"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/messages"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
[JsonProperty("content")] | |||||
public string Content { get; set; } | |||||
[JsonProperty("mentions"), JsonConverter(typeof(LongStringArrayConverter))] | |||||
public ulong[] MentionedUserIds { get; set; } | |||||
[JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)] | |||||
public string Nonce { get; set; } | |||||
[JsonProperty("tts")] | |||||
public bool IsTTS { get; set; } | |||||
public SendMessageRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,27 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateChannelRequest : IRestRequest<Channel> | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("topic")] | |||||
public string Topic { get; set; } | |||||
[JsonProperty("position")] | |||||
public int Position { get; set; } | |||||
public UpdateChannelRequest(ulong channelId) | |||||
{ | |||||
ChannelId = channelId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,32 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateGuildRequest : IRestRequest<Guild> | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("region")] | |||||
public string Region { get; set; } | |||||
[JsonProperty("icon")] | |||||
public string IconBase64 { get; set; } | |||||
[JsonProperty("afk_channel_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong? AFKChannelId { get; set; } | |||||
[JsonProperty("afk_timeout")] | |||||
public int AFKTimeout { get; set; } | |||||
public UpdateGuildRequest(ulong guildId) | |||||
{ | |||||
GuildId = guildId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,33 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
using System.Collections.Generic; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateMemberRequest : IRestRequest | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/members/{UserId}"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public ulong UserId { get; } | |||||
[JsonProperty("mute")] | |||||
public bool IsMuted { get; set; } | |||||
[JsonProperty("deaf")] | |||||
public bool IsDeafened { get; set; } | |||||
[JsonProperty("channel_id"), JsonConverter(typeof(NullableLongStringConverter))] | |||||
public ulong? VoiceChannelId { get; set; } | |||||
[JsonProperty("roles"), JsonConverter(typeof(LongStringArrayConverter))] | |||||
public ulong[] RoleIds { get; set; } | |||||
public UpdateMemberRequest(ulong guildId, ulong userId) | |||||
{ | |||||
GuildId = guildId; | |||||
UserId = userId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,28 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateMessageRequest : IRestRequest<Message> | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/channels/{ChannelId}/messages/{MessageId}"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong ChannelId { get; } | |||||
public ulong MessageId { get; } | |||||
[JsonProperty("content")] | |||||
public string Content { get; set; } = ""; | |||||
[JsonProperty("mentions"), JsonConverter(typeof(LongStringArrayConverter))] | |||||
public ulong[] MentionedUserIds { get; set; } = new ulong[0]; | |||||
public UpdateMessageRequest(ulong channelId, ulong messageId) | |||||
{ | |||||
ChannelId = channelId; | |||||
MessageId = messageId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,24 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateProfileRequest : IRestRequest<User> | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/users/@me"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
[JsonProperty("password")] | |||||
public string CurrentPassword { get; set; } | |||||
[JsonProperty("email")] | |||||
public string Email { get; set; } | |||||
[JsonProperty("new_password")] | |||||
public string Password { get; set; } | |||||
[JsonProperty("username")] | |||||
public string Username { get; set; } | |||||
[JsonProperty("avatar")] | |||||
public string AvatarBase64 { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,31 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.Rest | |||||
{ | |||||
[JsonObject(MemberSerialization.OptIn)] | |||||
public sealed class UpdateRoleRequest : IRestRequest<Role> | |||||
{ | |||||
string IRestRequest.Method => "PATCH"; | |||||
string IRestRequest.Endpoint => $"{DiscordConfig.ClientAPIUrl}/guilds/{GuildId}/roles/{RoleId}"; | |||||
object IRestRequest.Payload => this; | |||||
bool IRestRequest.IsPrivate => false; | |||||
public ulong GuildId { get; } | |||||
public ulong RoleId { get; } | |||||
[JsonProperty("name")] | |||||
public string Name { get; set; } | |||||
[JsonProperty("permissions")] | |||||
public uint Permissions { get; set; } | |||||
[JsonProperty("hoist")] | |||||
public bool IsHoisted { get; set; } | |||||
[JsonProperty("color")] | |||||
public uint Color { get; set; } | |||||
public UpdateRoleRequest(ulong guildId, ulong roleId) | |||||
{ | |||||
GuildId = guildId; | |||||
RoleId = roleId; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class HeartbeatCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.Heartbeat; | |||||
object IWebSocketMessage.Payload => EpochTime.GetMilliseconds(); | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
} | |||||
} |
@@ -0,0 +1,21 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class IdentifyCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.Identify; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => true; | |||||
[JsonProperty("server_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong GuildId { get; set; } | |||||
[JsonProperty("user_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId { get; set; } | |||||
[JsonProperty("session_id")] | |||||
public string SessionId { get; set; } | |||||
[JsonProperty("token")] | |||||
public string Token { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,29 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class SelectProtocolCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.SelectProtocol; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
public sealed class Data | |||||
{ | |||||
[JsonProperty("address")] | |||||
public string Address { get; set; } | |||||
[JsonProperty("port")] | |||||
public int Port { get; set; } | |||||
[JsonProperty("mode")] | |||||
public string Mode { get; set; } | |||||
} | |||||
[JsonProperty("protocol")] | |||||
public string Protocol { get; set; } = "udp"; | |||||
[JsonProperty("data")] | |||||
private Data ProtocolData { get; } = new Data(); | |||||
public string ExternalAddress { get { return ProtocolData.Address; } set { ProtocolData.Address = value; } } | |||||
public int ExternalPort { get { return ProtocolData.Port; } set { ProtocolData.Port = value; } } | |||||
public string EncryptionMode { get { return ProtocolData.Mode; } set { ProtocolData.Mode = value; } } | |||||
} | |||||
} |
@@ -0,0 +1,16 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class SetSpeakingCommand : IWebSocketMessage | |||||
{ | |||||
int IWebSocketMessage.OpCode => (int)OpCodes.Speaking; | |||||
object IWebSocketMessage.Payload => this; | |||||
bool IWebSocketMessage.IsPrivate => false; | |||||
[JsonProperty("speaking")] | |||||
public bool IsSpeaking { get; set; } | |||||
[JsonProperty("delay")] | |||||
public int Delay { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,16 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class ReadyEvent | |||||
{ | |||||
[JsonProperty("ssrc")] | |||||
public uint SSRC { get; set; } | |||||
[JsonProperty("port")] | |||||
public ushort Port { get; set; } | |||||
[JsonProperty("modes")] | |||||
public string[] Modes { get; set; } | |||||
[JsonProperty("heartbeat_interval")] | |||||
public int HeartbeatInterval { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,12 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class SessionDescriptionEvent | |||||
{ | |||||
[JsonProperty("secret_key")] | |||||
public byte[] SecretKey { get; set; } | |||||
[JsonProperty("mode")] | |||||
public string Mode { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,15 @@ | |||||
using Discord.API.Converters; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public sealed class SpeakingEvent | |||||
{ | |||||
[JsonProperty("user_id"), JsonConverter(typeof(LongStringConverter))] | |||||
public ulong UserId { get; set; } | |||||
[JsonProperty("ssrc")] | |||||
public uint SSRC { get; set; } | |||||
[JsonProperty("speaking")] | |||||
public bool IsSpeaking { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,18 @@ | |||||
namespace Discord.API.Client.VoiceSocket | |||||
{ | |||||
public enum OpCodes : byte | |||||
{ | |||||
/// <summary> C→S - Used to associate a connection with a token. </summary> | |||||
Identify = 0, | |||||
/// <summary> C→S - Used to specify configuration. </summary> | |||||
SelectProtocol = 1, | |||||
/// <summary> C←S - Used to notify that the voice connection was successful and informs the client of available protocols. </summary> | |||||
Ready = 2, | |||||
/// <summary> C↔S - Used to keep the connection alive and measure latency. </summary> | |||||
Heartbeat = 3, | |||||
/// <summary> C←S - Used to provide an encryption key to the client. </summary> | |||||
SessionDescription = 4, | |||||
/// <summary> C↔S - Used to inform that a certain user is speaking. </summary> | |||||
Speaking = 5 | |||||
} | |||||
} |