@@ -1,6 +1,6 @@ | |||||
Microsoft Visual Studio Solution File, Format Version 12.00 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
# Visual Studio 15 | # Visual Studio 15 | ||||
VisualStudioVersion = 15.0.26228.4 | |||||
VisualStudioVersion = 15.0.26711.1 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "src\Discord.Net.Core\Discord.Net.Core.csproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}" | ||||
EndProject | EndProject | ||||
@@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Commands", "src | |||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.WebSocket", "src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj", "{688FD1D8-7F01-4539-B2E9-F473C5D699C7}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.WebSocket", "src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj", "{688FD1D8-7F01-4539-B2E9-F473C5D699C7}" | ||||
EndProject | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Providers", "Providers", "{B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012}" | |||||
EndProject | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Providers.WS4Net", "src\Discord.Net.Providers.WS4Net\Discord.Net.Providers.WS4Net.csproj", "{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Providers.WS4Net", "src\Discord.Net.Providers.WS4Net\Discord.Net.Providers.WS4Net.csproj", "{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}" | ||||
EndProject | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}" | ||||
@@ -24,6 +22,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests", "test\D | |||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Webhook", "src\Discord.Net.Webhook\Discord.Net.Webhook.csproj", "{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Webhook", "src\Discord.Net.Webhook\Discord.Net.Webhook.csproj", "{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}" | ||||
EndProject | EndProject | ||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{1876A445-1C70-4F84-912B-4D3CEA21E0C3}" | |||||
EndProject | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Serialization", "src\Discord.Net.Serialization\Discord.Net.Serialization.csproj", "{AA3B67BE-767E-4230-9810-F7948B6AE689}" | |||||
EndProject | |||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|Any CPU = Debug|Any CPU | Debug|Any CPU = Debug|Any CPU | ||||
@@ -130,6 +132,18 @@ Global | |||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x64.Build.0 = Release|Any CPU | {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x64.Build.0 = Release|Any CPU | ||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.ActiveCfg = Release|Any CPU | {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.ActiveCfg = Release|Any CPU | ||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.Build.0 = Release|Any CPU | {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Release|x86.Build.0 = Release|Any CPU | ||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x64.ActiveCfg = Debug|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x64.Build.0 = Debug|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x86.ActiveCfg = Debug|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Debug|x86.Build.0 = Debug|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x64.ActiveCfg = Release|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x64.Build.0 = Release|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x86.ActiveCfg = Release|Any CPU | |||||
{AA3B67BE-767E-4230-9810-F7948B6AE689}.Release|x86.Build.0 = Release|Any CPU | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
@@ -139,7 +153,11 @@ Global | |||||
{5688A353-121E-40A1-8BFA-B17B91FB48FB} = {288C363D-A636-4EAE-9AC1-4698B641B26E} | {5688A353-121E-40A1-8BFA-B17B91FB48FB} = {288C363D-A636-4EAE-9AC1-4698B641B26E} | ||||
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} | {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} | ||||
{688FD1D8-7F01-4539-B2E9-F473C5D699C7} = {288C363D-A636-4EAE-9AC1-4698B641B26E} | {688FD1D8-7F01-4539-B2E9-F473C5D699C7} = {288C363D-A636-4EAE-9AC1-4698B641B26E} | ||||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012} | |||||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {1876A445-1C70-4F84-912B-4D3CEA21E0C3} | |||||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} | {9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} | ||||
{AA3B67BE-767E-4230-9810-F7948B6AE689} = {1876A445-1C70-4F84-912B-4D3CEA21E0C3} | |||||
EndGlobalSection | |||||
GlobalSection(ExtensibilityGlobals) = postSolution | |||||
SolutionGuid = {9828C525-49C7-48F4-A9E7-94E223052DA2} | |||||
EndGlobalSection | EndGlobalSection | ||||
EndGlobal | EndGlobal |
@@ -1,7 +1,8 @@ | |||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
<PropertyGroup> | <PropertyGroup> | ||||
<VersionPrefix>1.0.2</VersionPrefix> | |||||
<VersionPrefix>1.1.0-alpha</VersionPrefix> | |||||
<VersionSuffix></VersionSuffix> | <VersionSuffix></VersionSuffix> | ||||
<LangVersion>latest</LangVersion> | |||||
<Authors>RogueException</Authors> | <Authors>RogueException</Authors> | ||||
<PackageTags>discord;discordapp</PackageTags> | <PackageTags>discord;discordapp</PackageTags> | ||||
<PackageProjectUrl>https://github.com/RogueException/Discord.Net</PackageProjectUrl> | <PackageProjectUrl>https://github.com/RogueException/Discord.Net</PackageProjectUrl> | ||||
@@ -18,7 +19,7 @@ | |||||
<VersionSuffix Condition=" '$(VersionSuffix)' == '' ">build-$(BuildNumber)</VersionSuffix> | <VersionSuffix Condition=" '$(VersionSuffix)' == '' ">build-$(BuildNumber)</VersionSuffix> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' Or '$(TargetFramework)' == 'net45' "> | <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' Or '$(TargetFramework)' == 'net45' "> | ||||
<DefineConstants>$(DefineConstants);FILESYSTEM;DEFAULTUDPCLIENT;DEFAULTWEBSOCKET</DefineConstants> | |||||
<DefineConstants>$(DefineConstants);FILESYSTEM;DEFAULTUDPCLIENT;DEFAULTWEBSOCKET;MSBUFFER</DefineConstants> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> | <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> | ||||
<DefineConstants>$(DefineConstants);FORMATSTR;UNIXTIME;MSTRYBUFFER;UDPDISPOSE</DefineConstants> | <DefineConstants>$(DefineConstants);FORMATSTR;UNIXTIME;MSTRYBUFFER;UDPDISPOSE</DefineConstants> | ||||
@@ -309,14 +309,14 @@ namespace Discord.Commands | |||||
if (match.Command.Parameters.Count > 0) | if (match.Command.Parameters.Count > 0) | ||||
{ | { | ||||
var argValuesSum = parseResult.ArgValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0; | |||||
var paramValuesSum = parseResult.ParamValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0; | |||||
float argValuesSum = parseResult.ArgValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0; | |||||
float paramValuesSum = parseResult.ParamValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0; | |||||
argValuesScore = argValuesSum / match.Command.Parameters.Count; | argValuesScore = argValuesSum / match.Command.Parameters.Count; | ||||
paramValuesScore = paramValuesSum / match.Command.Parameters.Count; | paramValuesScore = paramValuesSum / match.Command.Parameters.Count; | ||||
} | } | ||||
var totalArgsScore = (argValuesScore + paramValuesScore) / 2; | |||||
float totalArgsScore = (argValuesScore + paramValuesScore) / 2; | |||||
return match.Command.Priority + totalArgsScore * 0.99f; | return match.Command.Priority + totalArgsScore * 0.99f; | ||||
} | } | ||||
@@ -31,5 +31,8 @@ namespace Discord.Audio | |||||
AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate = null, int bufferMillis = 1000, int packetLoss = 30); | AudioOutStream CreatePCMStream(AudioApplication application, int? bitrate = null, int bufferMillis = 1000, int packetLoss = 30); | ||||
/// <summary>Creates a new direct outgoing stream accepting PCM (raw) data. This is a direct stream with no internal timer.</summary> | /// <summary>Creates a new direct outgoing stream accepting PCM (raw) data. This is a direct stream with no internal timer.</summary> | ||||
AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate = null, int packetLoss = 30); | AudioOutStream CreateDirectPCMStream(AudioApplication application, int? bitrate = null, int packetLoss = 30); | ||||
/// <summary>Recycles an RTPFrame's payload buffer. Do not call more than once for a given frame.</summary> | |||||
void RecycleFrame(RTPFrame frame); | |||||
} | } | ||||
} | } |
@@ -5,7 +5,7 @@ namespace Discord.Audio | |||||
public readonly ushort Sequence; | public readonly ushort Sequence; | ||||
public readonly uint Timestamp; | public readonly uint Timestamp; | ||||
public readonly byte[] Payload; | public readonly byte[] Payload; | ||||
public readonly bool Missed; | |||||
public readonly bool Missed; | |||||
public RTPFrame(ushort sequence, uint timestamp, byte[] payload, bool missed) | public RTPFrame(ushort sequence, uint timestamp, byte[] payload, bool missed) | ||||
{ | { | ||||
@@ -7,8 +7,13 @@ | |||||
<TargetFrameworks>net45;netstandard1.1;netstandard1.3</TargetFrameworks> | <TargetFrameworks>net45;netstandard1.1;netstandard1.3</TargetFrameworks> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" /> | |||||
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" /> | |||||
<PackageReference Include="System.Buffers" Version="4.4.0" /> | |||||
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" /> | |||||
<PackageReference Include="System.Interactive.Async" Version="3.1.1" /> | <PackageReference Include="System.Interactive.Async" Version="3.1.1" /> | ||||
<PackageReference Include="System.Memory" Version="4.4.0-preview2-25405-01" /> | |||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\Discord.Net.Serialization\Discord.Net.Serialization.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
@@ -1,8 +1,13 @@ | |||||
namespace Discord | |||||
using Discord.Serialization; | |||||
namespace Discord | |||||
{ | { | ||||
[ModelStringEnum] | |||||
public enum PermissionTarget | public enum PermissionTarget | ||||
{ | { | ||||
[ModelEnumValue("role")] | |||||
Role, | Role, | ||||
[ModelEnumValue("member")] | |||||
User | User | ||||
} | } | ||||
} | } |
@@ -7,13 +7,16 @@ namespace Discord | |||||
public struct Image | public struct Image | ||||
{ | { | ||||
public Stream Stream { get; } | public Stream Stream { get; } | ||||
public ImageFormat Format { get; } | |||||
/// <summary> | /// <summary> | ||||
/// Create the image with a Stream. | /// Create the image with a Stream. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="stream">This must be some type of stream with the contents of a file in it.</param> | /// <param name="stream">This must be some type of stream with the contents of a file in it.</param> | ||||
public Image(Stream stream) | |||||
public Image(Stream stream, ImageFormat format = ImageFormat.Jpeg) | |||||
{ | { | ||||
Stream = stream; | Stream = stream; | ||||
Format = format; | |||||
} | } | ||||
#if FILESYSTEM | #if FILESYSTEM | ||||
/// <summary> | /// <summary> | ||||
@@ -23,9 +26,10 @@ namespace Discord | |||||
/// This file path is NOT validated, and is passed directly into a <see cref="File.OpenRead(string)"/> | /// This file path is NOT validated, and is passed directly into a <see cref="File.OpenRead(string)"/> | ||||
/// </remarks> | /// </remarks> | ||||
/// <param name="path">The path to the file.</param> | /// <param name="path">The path to the file.</param> | ||||
public Image(string path) | |||||
public Image(string path, ImageFormat format = ImageFormat.Jpeg) | |||||
{ | { | ||||
Stream = File.OpenRead(path); | Stream = File.OpenRead(path); | ||||
Format = format; | |||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
@@ -1,13 +1,16 @@ | |||||
namespace Discord | |||||
using Discord.Serialization; | |||||
namespace Discord | |||||
{ | { | ||||
[ModelStringEnum] | |||||
public enum EmbedType | public enum EmbedType | ||||
{ | { | ||||
Rich, | |||||
Link, | |||||
Video, | |||||
Image, | |||||
Gifv, | |||||
Article, | |||||
Tweet | |||||
[ModelEnumValue("rich")] Rich, | |||||
[ModelEnumValue("link")] Link, | |||||
[ModelEnumValue("video")] Video, | |||||
[ModelEnumValue("image")] Image, | |||||
[ModelEnumValue("gifv")] Gifv, | |||||
[ModelEnumValue("article")] Article, | |||||
[ModelEnumValue("tweet")] Tweet | |||||
} | } | ||||
} | } |
@@ -1,4 +1,6 @@ | |||||
namespace Discord | |||||
using Discord.Serialization; | |||||
namespace Discord | |||||
{ | { | ||||
public struct Overwrite | public struct Overwrite | ||||
{ | { | ||||
@@ -1,12 +1,21 @@ | |||||
namespace Discord | |||||
using Discord.Serialization; | |||||
namespace Discord | |||||
{ | { | ||||
[ModelStringEnum] | |||||
public enum UserStatus | public enum UserStatus | ||||
{ | { | ||||
[ModelEnumValue("offline", EnumValueType.ReadOnly)] | |||||
Offline, | Offline, | ||||
[ModelEnumValue("online")] | |||||
Online, | Online, | ||||
[ModelEnumValue("idle")] | |||||
Idle, | Idle, | ||||
[ModelEnumValue("idle", EnumValueType.WriteOnly)] | |||||
AFK, | AFK, | ||||
[ModelEnumValue("dnd")] | |||||
DoNotDisturb, | DoNotDisturb, | ||||
[ModelEnumValue("invisible", EnumValueType.WriteOnly)] | |||||
Invisible, | Invisible, | ||||
} | } | ||||
} | } |
@@ -3,7 +3,7 @@ | |||||
public static class Format | public static class Format | ||||
{ | { | ||||
// Characters which need escaping | // Characters which need escaping | ||||
private static string[] SensitiveCharacters = { "\\", "*", "_", "~", "`" }; | |||||
private static string[] _sensitiveCharacters = { "\\", "*", "_", "~", "`" }; | |||||
/// <summary> Returns a markdown-formatted string with bold formatting. </summary> | /// <summary> Returns a markdown-formatted string with bold formatting. </summary> | ||||
public static string Bold(string text) => $"**{text}**"; | public static string Bold(string text) => $"**{text}**"; | ||||
@@ -26,7 +26,7 @@ | |||||
/// <summary> Sanitizes the string, safely escaping any Markdown sequences. </summary> | /// <summary> Sanitizes the string, safely escaping any Markdown sequences. </summary> | ||||
public static string Sanitize(string text) | public static string Sanitize(string text) | ||||
{ | { | ||||
foreach (string unsafeChar in SensitiveCharacters) | |||||
foreach (string unsafeChar in _sensitiveCharacters) | |||||
text = text.Replace(unsafeChar, $"\\{unsafeChar}"); | text = text.Replace(unsafeChar, $"\\{unsafeChar}"); | ||||
return text; | return text; | ||||
} | } | ||||
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -10,7 +11,7 @@ namespace Discord.Net.Rest | |||||
void SetCancelToken(CancellationToken cancelToken); | void SetCancelToken(CancellationToken cancelToken); | ||||
Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | ||||
Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, ReadOnlyBuffer<byte> jsonPayload, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | ||||
} | } | ||||
} | } |
@@ -1,5 +1,5 @@ | |||||
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Net; | using System.Net; | ||||
namespace Discord.Net.Rest | namespace Discord.Net.Rest | ||||
@@ -8,13 +8,13 @@ namespace Discord.Net.Rest | |||||
{ | { | ||||
public HttpStatusCode StatusCode { get; } | public HttpStatusCode StatusCode { get; } | ||||
public Dictionary<string, string> Headers { get; } | public Dictionary<string, string> Headers { get; } | ||||
public Stream Stream { get; } | |||||
public ReadOnlyBuffer<byte> Data { get; } | |||||
public RestResponse(HttpStatusCode statusCode, Dictionary<string, string> headers, Stream stream) | |||||
public RestResponse(HttpStatusCode statusCode, Dictionary<string, string> headers, ReadOnlyBuffer<byte> data) | |||||
{ | { | ||||
StatusCode = statusCode; | StatusCode = statusCode; | ||||
Headers = headers; | Headers = headers; | ||||
Stream = stream; | |||||
Data = data; | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -6,8 +6,7 @@ namespace Discord.Net.WebSockets | |||||
{ | { | ||||
public interface IWebSocketClient | public interface IWebSocketClient | ||||
{ | { | ||||
event Func<byte[], int, int, Task> BinaryMessage; | |||||
event Func<string, Task> TextMessage; | |||||
event Func<ReadOnlyBuffer<byte>, bool, Task> Message; | |||||
event Func<Exception, Task> Closed; | event Func<Exception, Task> Closed; | ||||
void SetHeader(string key, string value); | void SetHeader(string key, string value); | ||||
@@ -16,6 +15,6 @@ namespace Discord.Net.WebSockets | |||||
Task ConnectAsync(string host); | Task ConnectAsync(string host); | ||||
Task DisconnectAsync(); | Task DisconnectAsync(); | ||||
Task SendAsync(byte[] data, int index, int count, bool isText); | |||||
Task SendAsync(ReadOnlyBuffer<byte> data, bool isText); | |||||
} | } | ||||
} | } |
@@ -3,6 +3,7 @@ using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | using System.Linq; | ||||
using System.Text; | using System.Text; | ||||
using System.Text.Utf8; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using WebSocket4Net; | using WebSocket4Net; | ||||
@@ -12,8 +13,7 @@ namespace Discord.Net.Providers.WS4Net | |||||
{ | { | ||||
internal class WS4NetClient : IWebSocketClient, IDisposable | internal class WS4NetClient : IWebSocketClient, IDisposable | ||||
{ | { | ||||
public event Func<byte[], int, int, Task> BinaryMessage; | |||||
public event Func<string, Task> TextMessage; | |||||
public event Func<ReadOnlyBuffer<byte>, bool, Task> Message; | |||||
public event Func<Exception, Task> Closed; | public event Func<Exception, Task> Closed; | ||||
private readonly SemaphoreSlim _lock; | private readonly SemaphoreSlim _lock; | ||||
@@ -129,15 +129,20 @@ namespace Discord.Net.Providers.WS4Net | |||||
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token; | _cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token; | ||||
} | } | ||||
public async Task SendAsync(byte[] data, int index, int count, bool isText) | |||||
public async Task SendAsync(ReadOnlyBuffer<byte> data, bool isText) | |||||
{ | { | ||||
await _lock.WaitAsync(_cancelToken).ConfigureAwait(false); | await _lock.WaitAsync(_cancelToken).ConfigureAwait(false); | ||||
try | try | ||||
{ | { | ||||
if (isText) | if (isText) | ||||
_client.Send(Encoding.UTF8.GetString(data, index, count)); | |||||
_client.Send(new Utf8String(data.Span).ToString()); | |||||
else | else | ||||
_client.Send(data, index, count); | |||||
{ | |||||
if (data.DangerousTryGetArray(out var array)) | |||||
_client.Send(array.Array, 0, data.Length); | |||||
else | |||||
_client.Send(data.ToArray(), 0, data.Length); | |||||
} | |||||
} | } | ||||
finally | finally | ||||
{ | { | ||||
@@ -147,11 +152,12 @@ namespace Discord.Net.Providers.WS4Net | |||||
private void OnTextMessage(object sender, MessageReceivedEventArgs e) | private void OnTextMessage(object sender, MessageReceivedEventArgs e) | ||||
{ | { | ||||
TextMessage(e.Message).GetAwaiter().GetResult(); | |||||
//TODO: Inefficient, but were dropping this plugin ASAP | |||||
Message(new ReadOnlyBuffer<byte>(Encoding.UTF8.GetBytes(e.Message)), true).GetAwaiter().GetResult(); | |||||
} | } | ||||
private void OnBinaryMessage(object sender, DataReceivedEventArgs e) | private void OnBinaryMessage(object sender, DataReceivedEventArgs e) | ||||
{ | { | ||||
BinaryMessage(e.Data, 0, e.Data.Count()).GetAwaiter().GetResult(); | |||||
Message(new ReadOnlyBuffer<byte>(e.Data, 0, e.Data.Count()), false).GetAwaiter().GetResult(); | |||||
} | } | ||||
private void OnConnected(object sender, object e) | private void OnConnected(object sender, object e) | ||||
{ | { | ||||
@@ -1,24 +1,24 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Application | internal class Application | ||||
{ | { | ||||
[JsonProperty("description")] | |||||
[ModelProperty("description")] | |||||
public string Description { get; set; } | public string Description { get; set; } | ||||
[JsonProperty("rpc_origins")] | |||||
[ModelProperty("rpc_origins")] | |||||
public string[] RPCOrigins { get; set; } | public string[] RPCOrigins { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("icon")] | |||||
[ModelProperty("icon")] | |||||
public string Icon { get; set; } | public string Icon { get; set; } | ||||
[JsonProperty("flags"), Int53] | |||||
[ModelProperty("flags"), Int53] | |||||
public Optional<ulong> Flags { get; set; } | public Optional<ulong> Flags { get; set; } | ||||
[JsonProperty("owner")] | |||||
[ModelProperty("owner")] | |||||
public Optional<User> Owner { get; set; } | public Optional<User> Owner { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,23 +1,23 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Attachment | internal class Attachment | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("filename")] | |||||
[ModelProperty("filename")] | |||||
public string Filename { get; set; } | public string Filename { get; set; } | ||||
[JsonProperty("size")] | |||||
[ModelProperty("size")] | |||||
public int Size { get; set; } | public int Size { get; set; } | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("proxy_url")] | |||||
[ModelProperty("proxy_url")] | |||||
public string ProxyUrl { get; set; } | public string ProxyUrl { get; set; } | ||||
[JsonProperty("height")] | |||||
[ModelProperty("height")] | |||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | |||||
[ModelProperty("width")] | |||||
public Optional<int> Width { get; set; } | public Optional<int> Width { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,13 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Ban | internal class Ban | ||||
{ | { | ||||
[JsonProperty("user")] | |||||
[ModelProperty("user")] | |||||
public User User { get; set; } | public User User { get; set; } | ||||
[JsonProperty("reason")] | |||||
[ModelProperty("reason")] | |||||
public string Reason { get; set; } | public string Reason { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,5 +1,5 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System; | using System; | ||||
namespace Discord.API | namespace Discord.API | ||||
@@ -7,41 +7,41 @@ namespace Discord.API | |||||
internal class Channel | internal class Channel | ||||
{ | { | ||||
//Shared | //Shared | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public ChannelType Type { get; set; } | public ChannelType Type { get; set; } | ||||
[JsonProperty("last_message_id")] | |||||
[ModelProperty("last_message_id")] | |||||
public ulong? LastMessageId { get; set; } | public ulong? LastMessageId { get; set; } | ||||
//GuildChannel | //GuildChannel | ||||
[JsonProperty("guild_id")] | |||||
[ModelProperty("guild_id")] | |||||
public Optional<ulong> GuildId { get; set; } | public Optional<ulong> GuildId { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
[JsonProperty("position")] | |||||
[ModelProperty("position")] | |||||
public Optional<int> Position { get; set; } | public Optional<int> Position { get; set; } | ||||
[JsonProperty("permission_overwrites")] | |||||
[ModelProperty("permission_overwrites")] | |||||
public Optional<Overwrite[]> PermissionOverwrites { get; set; } | public Optional<Overwrite[]> PermissionOverwrites { get; set; } | ||||
//TextChannel | //TextChannel | ||||
[JsonProperty("topic")] | |||||
[ModelProperty("topic")] | |||||
public Optional<string> Topic { get; set; } | public Optional<string> Topic { get; set; } | ||||
[JsonProperty("last_pin_timestamp")] | |||||
[ModelProperty("last_pin_timestamp")] | |||||
public Optional<DateTimeOffset?> LastPinTimestamp { get; set; } | public Optional<DateTimeOffset?> LastPinTimestamp { get; set; } | ||||
//VoiceChannel | //VoiceChannel | ||||
[JsonProperty("bitrate")] | |||||
[ModelProperty("bitrate")] | |||||
public Optional<int> Bitrate { get; set; } | public Optional<int> Bitrate { get; set; } | ||||
[JsonProperty("user_limit")] | |||||
[ModelProperty("user_limit")] | |||||
public Optional<int> UserLimit { get; set; } | public Optional<int> UserLimit { get; set; } | ||||
//PrivateChannel | //PrivateChannel | ||||
[JsonProperty("recipients")] | |||||
[ModelProperty("recipients")] | |||||
public Optional<User[]> Recipients { get; set; } | public Optional<User[]> Recipients { get; set; } | ||||
//GroupChannel | //GroupChannel | ||||
[JsonProperty("icon")] | |||||
[ModelProperty("icon")] | |||||
public Optional<string> Icon { get; set; } | public Optional<string> Icon { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,21 +1,21 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Connection | internal class Connection | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public string Id { get; set; } | public string Id { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public string Type { get; set; } | public string Type { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("revoked")] | |||||
[ModelProperty("revoked")] | |||||
public bool Revoked { get; set; } | public bool Revoked { get; set; } | ||||
[JsonProperty("integrations")] | |||||
[ModelProperty("integrations")] | |||||
public IReadOnlyCollection<ulong> Integrations { get; set; } | public IReadOnlyCollection<ulong> Integrations { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,37 +1,36 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json.Converters; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Embed | internal class Embed | ||||
{ | { | ||||
[JsonProperty("title")] | |||||
[ModelProperty("title")] | |||||
public string Title { get; set; } | public string Title { get; set; } | ||||
[JsonProperty("description")] | |||||
[ModelProperty("description")] | |||||
public string Description { get; set; } | public string Description { get; set; } | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("color")] | |||||
[ModelProperty("color")] | |||||
public uint? Color { get; set; } | public uint? Color { get; set; } | ||||
[JsonProperty("type"), JsonConverter(typeof(StringEnumConverter))] | |||||
[ModelProperty("type")] | |||||
public EmbedType Type { get; set; } | public EmbedType Type { get; set; } | ||||
[JsonProperty("timestamp")] | |||||
[ModelProperty("timestamp")] | |||||
public DateTimeOffset? Timestamp { get; set; } | public DateTimeOffset? Timestamp { get; set; } | ||||
[JsonProperty("author")] | |||||
[ModelProperty("author")] | |||||
public Optional<EmbedAuthor> Author { get; set; } | public Optional<EmbedAuthor> Author { get; set; } | ||||
[JsonProperty("footer")] | |||||
[ModelProperty("footer")] | |||||
public Optional<EmbedFooter> Footer { get; set; } | public Optional<EmbedFooter> Footer { get; set; } | ||||
[JsonProperty("video")] | |||||
[ModelProperty("video")] | |||||
public Optional<EmbedVideo> Video { get; set; } | public Optional<EmbedVideo> Video { get; set; } | ||||
[JsonProperty("thumbnail")] | |||||
[ModelProperty("thumbnail")] | |||||
public Optional<EmbedThumbnail> Thumbnail { get; set; } | public Optional<EmbedThumbnail> Thumbnail { get; set; } | ||||
[JsonProperty("image")] | |||||
[ModelProperty("image")] | |||||
public Optional<EmbedImage> Image { get; set; } | public Optional<EmbedImage> Image { get; set; } | ||||
[JsonProperty("provider")] | |||||
[ModelProperty("provider")] | |||||
public Optional<EmbedProvider> Provider { get; set; } | public Optional<EmbedProvider> Provider { get; set; } | ||||
[JsonProperty("fields")] | |||||
[ModelProperty("fields")] | |||||
public Optional<EmbedField[]> Fields { get; set; } | public Optional<EmbedField[]> Fields { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,17 +1,17 @@ | |||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedAuthor | internal class EmbedAuthor | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("icon_url")] | |||||
[ModelProperty("icon_url")] | |||||
public string IconUrl { get; set; } | public string IconUrl { get; set; } | ||||
[JsonProperty("proxy_icon_url")] | |||||
[ModelProperty("proxy_icon_url")] | |||||
public string ProxyIconUrl { get; set; } | public string ProxyIconUrl { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,14 @@ | |||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedField | internal class EmbedField | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("value")] | |||||
[ModelProperty("value")] | |||||
public string Value { get; set; } | public string Value { get; set; } | ||||
[JsonProperty("inline")] | |||||
[ModelProperty("inline")] | |||||
public bool Inline { get; set; } | public bool Inline { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,15 +1,15 @@ | |||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedFooter | internal class EmbedFooter | ||||
{ | { | ||||
[JsonProperty("text")] | |||||
[ModelProperty("text")] | |||||
public string Text { get; set; } | public string Text { get; set; } | ||||
[JsonProperty("icon_url")] | |||||
[ModelProperty("icon_url")] | |||||
public string IconUrl { get; set; } | public string IconUrl { get; set; } | ||||
[JsonProperty("proxy_icon_url")] | |||||
[ModelProperty("proxy_icon_url")] | |||||
public string ProxyIconUrl { get; set; } | public string ProxyIconUrl { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,18 +1,18 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedImage | internal class EmbedImage | ||||
{ | { | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("proxy_url")] | |||||
[ModelProperty("proxy_url")] | |||||
public string ProxyUrl { get; set; } | public string ProxyUrl { get; set; } | ||||
[JsonProperty("height")] | |||||
[ModelProperty("height")] | |||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | |||||
[ModelProperty("width")] | |||||
public Optional<int> Width { get; set; } | public Optional<int> Width { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,14 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedProvider | internal class EmbedProvider | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,18 +1,18 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedThumbnail | internal class EmbedThumbnail | ||||
{ | { | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("proxy_url")] | |||||
[ModelProperty("proxy_url")] | |||||
public string ProxyUrl { get; set; } | public string ProxyUrl { get; set; } | ||||
[JsonProperty("height")] | |||||
[ModelProperty("height")] | |||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | |||||
[ModelProperty("width")] | |||||
public Optional<int> Width { get; set; } | public Optional<int> Width { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,16 +1,16 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using System; | using System; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class EmbedVideo | internal class EmbedVideo | ||||
{ | { | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("height")] | |||||
[ModelProperty("height")] | |||||
public Optional<int> Height { get; set; } | public Optional<int> Height { get; set; } | ||||
[JsonProperty("width")] | |||||
[ModelProperty("width")] | |||||
public Optional<int> Width { get; set; } | public Optional<int> Width { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,19 +1,19 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Emoji | internal class Emoji | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong? Id { get; set; } | public ulong? Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("roles")] | |||||
[ModelProperty("roles")] | |||||
public ulong[] Roles { get; set; } | public ulong[] Roles { get; set; } | ||||
[JsonProperty("require_colons")] | |||||
[ModelProperty("require_colons")] | |||||
public bool RequireColons { get; set; } | public bool RequireColons { get; set; } | ||||
[JsonProperty("managed")] | |||||
[ModelProperty("managed")] | |||||
public bool Managed { get; set; } | public bool Managed { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,23 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json.Serialization; | |||||
using System.Runtime.Serialization; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Game | internal class Game | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public Optional<string> StreamUrl { get; set; } | public Optional<string> StreamUrl { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public Optional<StreamType?> StreamType { get; set; } | public Optional<StreamType?> StreamType { get; set; } | ||||
[OnError] | |||||
internal void OnError(StreamingContext context, ErrorContext errorContext) | |||||
{ | |||||
errorContext.Handled = true; | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,43 +1,43 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Guild | internal class Guild | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("icon")] | |||||
[ModelProperty("icon")] | |||||
public string Icon { get; set; } | public string Icon { get; set; } | ||||
[JsonProperty("splash")] | |||||
[ModelProperty("splash")] | |||||
public string Splash { get; set; } | public string Splash { get; set; } | ||||
[JsonProperty("owner_id")] | |||||
[ModelProperty("owner_id")] | |||||
public ulong OwnerId { get; set; } | public ulong OwnerId { get; set; } | ||||
[JsonProperty("region")] | |||||
[ModelProperty("region")] | |||||
public string Region { get; set; } | public string Region { get; set; } | ||||
[JsonProperty("afk_channel_id")] | |||||
[ModelProperty("afk_channel_id")] | |||||
public ulong? AFKChannelId { get; set; } | public ulong? AFKChannelId { get; set; } | ||||
[JsonProperty("afk_timeout")] | |||||
[ModelProperty("afk_timeout")] | |||||
public int AFKTimeout { get; set; } | public int AFKTimeout { get; set; } | ||||
[JsonProperty("embed_enabled")] | |||||
[ModelProperty("embed_enabled")] | |||||
public bool EmbedEnabled { get; set; } | public bool EmbedEnabled { get; set; } | ||||
[JsonProperty("embed_channel_id")] | |||||
[ModelProperty("embed_channel_id")] | |||||
public ulong? EmbedChannelId { get; set; } | public ulong? EmbedChannelId { get; set; } | ||||
[JsonProperty("verification_level")] | |||||
[ModelProperty("verification_level")] | |||||
public VerificationLevel VerificationLevel { get; set; } | public VerificationLevel VerificationLevel { get; set; } | ||||
[JsonProperty("voice_states")] | |||||
[ModelProperty("voice_states")] | |||||
public VoiceState[] VoiceStates { get; set; } | public VoiceState[] VoiceStates { get; set; } | ||||
[JsonProperty("roles")] | |||||
[ModelProperty("roles")] | |||||
public Role[] Roles { get; set; } | public Role[] Roles { get; set; } | ||||
[JsonProperty("emojis")] | |||||
[ModelProperty("emojis")] | |||||
public Emoji[] Emojis { get; set; } | public Emoji[] Emojis { get; set; } | ||||
[JsonProperty("features")] | |||||
[ModelProperty("features")] | |||||
public string[] Features { get; set; } | public string[] Features { get; set; } | ||||
[JsonProperty("mfa_level")] | |||||
[ModelProperty("mfa_level")] | |||||
public MfaLevel MfaLevel { get; set; } | public MfaLevel MfaLevel { get; set; } | ||||
[JsonProperty("default_message_notifications")] | |||||
[ModelProperty("default_message_notifications")] | |||||
public DefaultMessageNotifications DefaultMessageNotifications { get; set; } | public DefaultMessageNotifications DefaultMessageNotifications { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,13 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class GuildEmbed | internal class GuildEmbed | ||||
{ | { | ||||
[JsonProperty("enabled")] | |||||
[ModelProperty("enabled")] | |||||
public bool Enabled { get; set; } | public bool Enabled { get; set; } | ||||
[JsonProperty("channel_id")] | |||||
[ModelProperty("channel_id")] | |||||
public ulong ChannelId { get; set; } | public ulong ChannelId { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,22 +1,22 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System; | using System; | ||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class GuildMember | internal class GuildMember | ||||
{ | { | ||||
[JsonProperty("user")] | |||||
[ModelProperty("user")] | |||||
public User User { get; set; } | public User User { get; set; } | ||||
[JsonProperty("nick")] | |||||
[ModelProperty("nick")] | |||||
public Optional<string> Nick { get; set; } | public Optional<string> Nick { get; set; } | ||||
[JsonProperty("roles")] | |||||
[ModelProperty("roles")] | |||||
public Optional<ulong[]> Roles { get; set; } | public Optional<ulong[]> Roles { get; set; } | ||||
[JsonProperty("joined_at")] | |||||
[ModelProperty("joined_at")] | |||||
public Optional<DateTimeOffset> JoinedAt { get; set; } | public Optional<DateTimeOffset> JoinedAt { get; set; } | ||||
[JsonProperty("deaf")] | |||||
[ModelProperty("deaf")] | |||||
public Optional<bool> Deaf { get; set; } | public Optional<bool> Deaf { get; set; } | ||||
[JsonProperty("mute")] | |||||
[ModelProperty("mute")] | |||||
public Optional<bool> Mute { get; set; } | public Optional<bool> Mute { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,32 +1,32 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System; | using System; | ||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Integration | internal class Integration | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public string Type { get; set; } | public string Type { get; set; } | ||||
[JsonProperty("enabled")] | |||||
[ModelProperty("enabled")] | |||||
public bool Enabled { get; set; } | public bool Enabled { get; set; } | ||||
[JsonProperty("syncing")] | |||||
[ModelProperty("syncing")] | |||||
public bool Syncing { get; set; } | public bool Syncing { get; set; } | ||||
[JsonProperty("role_id")] | |||||
[ModelProperty("role_id")] | |||||
public ulong RoleId { get; set; } | public ulong RoleId { get; set; } | ||||
[JsonProperty("expire_behavior")] | |||||
[ModelProperty("expire_behavior")] | |||||
public ulong ExpireBehavior { get; set; } | public ulong ExpireBehavior { get; set; } | ||||
[JsonProperty("expire_grace_period")] | |||||
[ModelProperty("expire_grace_period")] | |||||
public ulong ExpireGracePeriod { get; set; } | public ulong ExpireGracePeriod { get; set; } | ||||
[JsonProperty("user")] | |||||
[ModelProperty("user")] | |||||
public User User { get; set; } | public User User { get; set; } | ||||
[JsonProperty("account")] | |||||
[ModelProperty("account")] | |||||
public IntegrationAccount Account { get; set; } | public IntegrationAccount Account { get; set; } | ||||
[JsonProperty("synced_at")] | |||||
[ModelProperty("synced_at")] | |||||
public DateTimeOffset SyncedAt { get; set; } | public DateTimeOffset SyncedAt { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,13 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class IntegrationAccount | internal class IntegrationAccount | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,15 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Invite | internal class Invite | ||||
{ | { | ||||
[JsonProperty("code")] | |||||
[ModelProperty("code")] | |||||
public string Code { get; set; } | public string Code { get; set; } | ||||
[JsonProperty("guild")] | |||||
[ModelProperty("guild")] | |||||
public InviteGuild Guild { get; set; } | public InviteGuild Guild { get; set; } | ||||
[JsonProperty("channel")] | |||||
[ModelProperty("channel")] | |||||
public InviteChannel Channel { get; set; } | public InviteChannel Channel { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,15 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class InviteChannel | internal class InviteChannel | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public string Type { get; set; } | public string Type { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,15 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class InviteGuild | internal class InviteGuild | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("splash_hash")] | |||||
[ModelProperty("splash_hash")] | |||||
public string SplashHash { get; set; } | public string SplashHash { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,24 +1,24 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System; | using System; | ||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class InviteMetadata : Invite | internal class InviteMetadata : Invite | ||||
{ | { | ||||
[JsonProperty("inviter")] | |||||
[ModelProperty("inviter")] | |||||
public User Inviter { get; set; } | public User Inviter { get; set; } | ||||
[JsonProperty("uses")] | |||||
[ModelProperty("uses")] | |||||
public int Uses { get; set; } | public int Uses { get; set; } | ||||
[JsonProperty("max_uses")] | |||||
[ModelProperty("max_uses")] | |||||
public int MaxUses { get; set; } | public int MaxUses { get; set; } | ||||
[JsonProperty("max_age")] | |||||
[ModelProperty("max_age")] | |||||
public int MaxAge { get; set; } | public int MaxAge { get; set; } | ||||
[JsonProperty("temporary")] | |||||
[ModelProperty("temporary")] | |||||
public bool Temporary { get; set; } | public bool Temporary { get; set; } | ||||
[JsonProperty("created_at")] | |||||
[ModelProperty("created_at")] | |||||
public DateTimeOffset CreatedAt { get; set; } | public DateTimeOffset CreatedAt { get; set; } | ||||
[JsonProperty("revoked")] | |||||
[ModelProperty("revoked")] | |||||
public bool Revoked { get; set; } | public bool Revoked { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,42 +1,42 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System; | using System; | ||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Message | internal class Message | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public MessageType Type { get; set; } | public MessageType Type { get; set; } | ||||
[JsonProperty("channel_id")] | |||||
[ModelProperty("channel_id")] | |||||
public ulong ChannelId { get; set; } | public ulong ChannelId { get; set; } | ||||
[JsonProperty("webhook_id")] | |||||
[ModelProperty("webhook_id")] | |||||
public Optional<ulong> WebhookId { get; set; } | public Optional<ulong> WebhookId { get; set; } | ||||
[JsonProperty("author")] | |||||
[ModelProperty("author")] | |||||
public Optional<User> Author { get; set; } | public Optional<User> Author { get; set; } | ||||
[JsonProperty("content")] | |||||
[ModelProperty("content")] | |||||
public Optional<string> Content { get; set; } | public Optional<string> Content { get; set; } | ||||
[JsonProperty("timestamp")] | |||||
[ModelProperty("timestamp")] | |||||
public Optional<DateTimeOffset> Timestamp { get; set; } | public Optional<DateTimeOffset> Timestamp { get; set; } | ||||
[JsonProperty("edited_timestamp")] | |||||
[ModelProperty("edited_timestamp")] | |||||
public Optional<DateTimeOffset?> EditedTimestamp { get; set; } | public Optional<DateTimeOffset?> EditedTimestamp { get; set; } | ||||
[JsonProperty("tts")] | |||||
[ModelProperty("tts")] | |||||
public Optional<bool> IsTextToSpeech { get; set; } | public Optional<bool> IsTextToSpeech { get; set; } | ||||
[JsonProperty("mention_everyone")] | |||||
[ModelProperty("mention_everyone")] | |||||
public Optional<bool> MentionEveryone { get; set; } | public Optional<bool> MentionEveryone { get; set; } | ||||
[JsonProperty("mentions")] | |||||
[ModelProperty("mentions")] | |||||
public Optional<EntityOrId<User>[]> UserMentions { get; set; } | public Optional<EntityOrId<User>[]> UserMentions { get; set; } | ||||
[JsonProperty("mention_roles")] | |||||
[ModelProperty("mention_roles")] | |||||
public Optional<ulong[]> RoleMentions { get; set; } | public Optional<ulong[]> RoleMentions { get; set; } | ||||
[JsonProperty("attachments")] | |||||
[ModelProperty("attachments")] | |||||
public Optional<Attachment[]> Attachments { get; set; } | public Optional<Attachment[]> Attachments { get; set; } | ||||
[JsonProperty("embeds")] | |||||
[ModelProperty("embeds")] | |||||
public Optional<Embed[]> Embeds { get; set; } | public Optional<Embed[]> Embeds { get; set; } | ||||
[JsonProperty("pinned")] | |||||
[ModelProperty("pinned")] | |||||
public Optional<bool> Pinned { get; set; } | public Optional<bool> Pinned { get; set; } | ||||
[JsonProperty("reactions")] | |||||
[ModelProperty("reactions")] | |||||
public Optional<Reaction[]> Reactions { get; set; } | public Optional<Reaction[]> Reactions { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,17 +1,17 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Overwrite | internal class Overwrite | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong TargetId { get; set; } | public ulong TargetId { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public PermissionTarget TargetType { get; set; } | public PermissionTarget TargetType { get; set; } | ||||
[JsonProperty("deny"), Int53] | |||||
[ModelProperty("deny"), Int53] | |||||
public ulong Deny { get; set; } | public ulong Deny { get; set; } | ||||
[JsonProperty("allow"), Int53] | |||||
[ModelProperty("allow"), Int53] | |||||
public ulong Allow { get; set; } | public ulong Allow { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,22 +1,22 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Presence | internal class Presence | ||||
{ | { | ||||
[JsonProperty("user")] | |||||
[ModelProperty("user")] | |||||
public User User { get; set; } | public User User { get; set; } | ||||
[JsonProperty("guild_id")] | |||||
[ModelProperty("guild_id")] | |||||
public Optional<ulong> GuildId { get; set; } | public Optional<ulong> GuildId { get; set; } | ||||
[JsonProperty("status")] | |||||
[ModelProperty("status")] | |||||
public UserStatus Status { get; set; } | public UserStatus Status { get; set; } | ||||
[JsonProperty("game")] | |||||
[ModelProperty("game")] | |||||
public Game Game { get; set; } | public Game Game { get; set; } | ||||
[JsonProperty("roles")] | |||||
[ModelProperty("roles")] | |||||
public Optional<ulong[]> Roles { get; set; } | public Optional<ulong[]> Roles { get; set; } | ||||
[JsonProperty("nick")] | |||||
[ModelProperty("nick")] | |||||
public Optional<string> Nick { get; set; } | public Optional<string> Nick { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,14 @@ | |||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Reaction | internal class Reaction | ||||
{ | { | ||||
[JsonProperty("count")] | |||||
[ModelProperty("count")] | |||||
public int Count { get; set; } | public int Count { get; set; } | ||||
[JsonProperty("me")] | |||||
[ModelProperty("me")] | |||||
public bool Me { get; set; } | public bool Me { get; set; } | ||||
[JsonProperty("emoji")] | |||||
[ModelProperty("emoji")] | |||||
public Emoji Emoji { get; set; } | public Emoji Emoji { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,15 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class ReadState | internal class ReadState | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("mention_count")] | |||||
[ModelProperty("mention_count")] | |||||
public int MentionCount { get; set; } | public int MentionCount { get; set; } | ||||
[JsonProperty("last_message_id")] | |||||
[ModelProperty("last_message_id")] | |||||
public Optional<ulong> LastMessageId { get; set; } | public Optional<ulong> LastMessageId { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,15 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Relationship | internal class Relationship | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("user")] | |||||
[ModelProperty("user")] | |||||
public User User { get; set; } | public User User { get; set; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public RelationshipType Type { get; set; } | public RelationshipType Type { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,25 +1,25 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class Role | internal class Role | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("color")] | |||||
[ModelProperty("color")] | |||||
public uint Color { get; set; } | public uint Color { get; set; } | ||||
[JsonProperty("hoist")] | |||||
[ModelProperty("hoist")] | |||||
public bool Hoist { get; set; } | public bool Hoist { get; set; } | ||||
[JsonProperty("mentionable")] | |||||
[ModelProperty("mentionable")] | |||||
public bool Mentionable { get; set; } | public bool Mentionable { get; set; } | ||||
[JsonProperty("position")] | |||||
[ModelProperty("position")] | |||||
public int Position { get; set; } | public int Position { get; set; } | ||||
[JsonProperty("permissions"), Int53] | |||||
[ModelProperty("permissions"), Int53] | |||||
public ulong Permissions { get; set; } | public ulong Permissions { get; set; } | ||||
[JsonProperty("managed")] | |||||
[ModelProperty("managed")] | |||||
public bool Managed { get; set; } | public bool Managed { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,27 +1,27 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class User | internal class User | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("username")] | |||||
[ModelProperty("username")] | |||||
public Optional<string> Username { get; set; } | public Optional<string> Username { get; set; } | ||||
[JsonProperty("discriminator")] | |||||
[ModelProperty("discriminator")] | |||||
public Optional<string> Discriminator { get; set; } | public Optional<string> Discriminator { get; set; } | ||||
[JsonProperty("bot")] | |||||
[ModelProperty("bot")] | |||||
public Optional<bool> Bot { get; set; } | public Optional<bool> Bot { get; set; } | ||||
[JsonProperty("avatar")] | |||||
[ModelProperty("avatar")] | |||||
public Optional<string> Avatar { get; set; } | public Optional<string> Avatar { get; set; } | ||||
//CurrentUser | //CurrentUser | ||||
[JsonProperty("verified")] | |||||
[ModelProperty("verified")] | |||||
public Optional<bool> Verified { get; set; } | public Optional<bool> Verified { get; set; } | ||||
[JsonProperty("email")] | |||||
[ModelProperty("email")] | |||||
public Optional<string> Email { get; set; } | public Optional<string> Email { get; set; } | ||||
[JsonProperty("mfa_enabled")] | |||||
[ModelProperty("mfa_enabled")] | |||||
public Optional<bool> MfaEnabled { get; set; } | public Optional<bool> MfaEnabled { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,19 +1,19 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class UserGuild | internal class UserGuild | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; set; } | public ulong Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("icon")] | |||||
[ModelProperty("icon")] | |||||
public string Icon { get; set; } | public string Icon { get; set; } | ||||
[JsonProperty("owner")] | |||||
[ModelProperty("owner")] | |||||
public bool Owner { get; set; } | public bool Owner { get; set; } | ||||
[JsonProperty("permissions"), Int53] | |||||
[ModelProperty("permissions"), Int53] | |||||
public ulong Permissions { get; set; } | public ulong Permissions { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,21 +1,21 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class VoiceRegion | internal class VoiceRegion | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public string Id { get; set; } | public string Id { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; set; } | public string Name { get; set; } | ||||
[JsonProperty("vip")] | |||||
[ModelProperty("vip")] | |||||
public bool IsVip { get; set; } | public bool IsVip { get; set; } | ||||
[JsonProperty("optimal")] | |||||
[ModelProperty("optimal")] | |||||
public bool IsOptimal { get; set; } | public bool IsOptimal { get; set; } | ||||
[JsonProperty("sample_hostname")] | |||||
[ModelProperty("sample_hostname")] | |||||
public string SampleHostname { get; set; } | public string SampleHostname { get; set; } | ||||
[JsonProperty("sample_port")] | |||||
[ModelProperty("sample_port")] | |||||
public int SamplePort { get; set; } | public int SamplePort { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,27 +1,27 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API | namespace Discord.API | ||||
{ | { | ||||
internal class VoiceState | internal class VoiceState | ||||
{ | { | ||||
[JsonProperty("guild_id")] | |||||
[ModelProperty("guild_id")] | |||||
public ulong? GuildId { get; set; } | public ulong? GuildId { get; set; } | ||||
[JsonProperty("channel_id")] | |||||
[ModelProperty("channel_id")] | |||||
public ulong? ChannelId { get; set; } | public ulong? ChannelId { get; set; } | ||||
[JsonProperty("user_id")] | |||||
[ModelProperty("user_id")] | |||||
public ulong UserId { get; set; } | public ulong UserId { get; set; } | ||||
[JsonProperty("session_id")] | |||||
[ModelProperty("session_id")] | |||||
public string SessionId { get; set; } | public string SessionId { get; set; } | ||||
[JsonProperty("deaf")] | |||||
[ModelProperty("deaf")] | |||||
public bool Deaf { get; set; } | public bool Deaf { get; set; } | ||||
[JsonProperty("mute")] | |||||
[ModelProperty("mute")] | |||||
public bool Mute { get; set; } | public bool Mute { get; set; } | ||||
[JsonProperty("self_deaf")] | |||||
[ModelProperty("self_deaf")] | |||||
public bool SelfDeaf { get; set; } | public bool SelfDeaf { get; set; } | ||||
[JsonProperty("self_mute")] | |||||
[ModelProperty("self_mute")] | |||||
public bool SelfMute { get; set; } | public bool SelfMute { get; set; } | ||||
[JsonProperty("suppress")] | |||||
[ModelProperty("suppress")] | |||||
public bool Suppress { get; set; } | public bool Suppress { get; set; } | ||||
} | } | ||||
} | } |
@@ -5,16 +5,19 @@ namespace Discord.API | |||||
internal struct Image | internal struct Image | ||||
{ | { | ||||
public Stream Stream { get; } | public Stream Stream { get; } | ||||
public ImageFormat StreamFormat { get; } | |||||
public string Hash { get; } | public string Hash { get; } | ||||
public Image(Stream stream) | |||||
public Image(Stream stream, ImageFormat format) | |||||
{ | { | ||||
Stream = stream; | Stream = stream; | ||||
StreamFormat = format; | |||||
Hash = null; | Hash = null; | ||||
} | } | ||||
public Image(string hash) | public Image(string hash) | ||||
{ | { | ||||
Stream = null; | Stream = null; | ||||
StreamFormat = ImageFormat.Jpeg; | |||||
Hash = hash; | Hash = hash; | ||||
} | } | ||||
} | } | ||||
@@ -1,18 +1,17 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateChannelInviteParams | internal class CreateChannelInviteParams | ||||
{ | { | ||||
[JsonProperty("max_age")] | |||||
[ModelProperty("max_age")] | |||||
public Optional<int> MaxAge { get; set; } | public Optional<int> MaxAge { get; set; } | ||||
[JsonProperty("max_uses")] | |||||
[ModelProperty("max_uses")] | |||||
public Optional<int> MaxUses { get; set; } | public Optional<int> MaxUses { get; set; } | ||||
[JsonProperty("temporary")] | |||||
[ModelProperty("temporary")] | |||||
public Optional<bool> IsTemporary { get; set; } | public Optional<bool> IsTemporary { get; set; } | ||||
[JsonProperty("unique")] | |||||
[ModelProperty("unique")] | |||||
public Optional<bool> IsUnique { get; set; } | public Optional<bool> IsUnique { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,12 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateDMChannelParams | internal class CreateDMChannelParams | ||||
{ | { | ||||
[JsonProperty("recipient_id")] | |||||
[ModelProperty("recipient_id")] | |||||
public ulong RecipientId { get; } | public ulong RecipientId { get; } | ||||
public CreateDMChannelParams(ulong recipientId) | public CreateDMChannelParams(ulong recipientId) | ||||
@@ -1,17 +1,16 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateGuildChannelParams | internal class CreateGuildChannelParams | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; } | public string Name { get; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public ChannelType Type { get; } | public ChannelType Type { get; } | ||||
[JsonProperty("bitrate")] | |||||
[ModelProperty("bitrate")] | |||||
public Optional<int> Bitrate { get; set; } | public Optional<int> Bitrate { get; set; } | ||||
public CreateGuildChannelParams(string name, ChannelType type) | public CreateGuildChannelParams(string name, ChannelType type) | ||||
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateGuildIntegrationParams | internal class CreateGuildIntegrationParams | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; } | public ulong Id { get; } | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public string Type { get; } | public string Type { get; } | ||||
public CreateGuildIntegrationParams(ulong id, string type) | public CreateGuildIntegrationParams(ulong id, string type) | ||||
@@ -1,17 +1,16 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateGuildParams | internal class CreateGuildParams | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public string Name { get; } | public string Name { get; } | ||||
[JsonProperty("region")] | |||||
[ModelProperty("region")] | |||||
public string RegionId { get; } | public string RegionId { get; } | ||||
[JsonProperty("icon")] | |||||
[ModelProperty("icon")] | |||||
public Optional<Image?> Icon { get; set; } | public Optional<Image?> Icon { get; set; } | ||||
public CreateGuildParams(string name, string regionId) | public CreateGuildParams(string name, string regionId) | ||||
@@ -1,19 +1,18 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateMessageParams | internal class CreateMessageParams | ||||
{ | { | ||||
[JsonProperty("content")] | |||||
[ModelProperty("content")] | |||||
public string Content { get; } | public string Content { get; } | ||||
[JsonProperty("nonce")] | |||||
[ModelProperty("nonce")] | |||||
public Optional<string> Nonce { get; set; } | public Optional<string> Nonce { get; set; } | ||||
[JsonProperty("tts")] | |||||
[ModelProperty("tts")] | |||||
public Optional<bool> IsTTS { get; set; } | public Optional<bool> IsTTS { get; set; } | ||||
[JsonProperty("embed")] | |||||
[ModelProperty("embed")] | |||||
public Optional<Embed> Embed { get; set; } | public Optional<Embed> Embed { get; set; } | ||||
public CreateMessageParams(string content) | public CreateMessageParams(string content) | ||||
@@ -1,23 +1,22 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class CreateWebhookMessageParams | internal class CreateWebhookMessageParams | ||||
{ | { | ||||
[JsonProperty("content")] | |||||
[ModelProperty("content")] | |||||
public string Content { get; } | public string Content { get; } | ||||
[JsonProperty("nonce")] | |||||
[ModelProperty("nonce")] | |||||
public Optional<string> Nonce { get; set; } | public Optional<string> Nonce { get; set; } | ||||
[JsonProperty("tts")] | |||||
[ModelProperty("tts")] | |||||
public Optional<bool> IsTTS { get; set; } | public Optional<bool> IsTTS { get; set; } | ||||
[JsonProperty("embeds")] | |||||
[ModelProperty("embeds")] | |||||
public Optional<Embed[]> Embeds { get; set; } | public Optional<Embed[]> Embeds { get; set; } | ||||
[JsonProperty("username")] | |||||
[ModelProperty("username")] | |||||
public Optional<string> Username { get; set; } | public Optional<string> Username { get; set; } | ||||
[JsonProperty("avatar_url")] | |||||
[ModelProperty("avatar_url")] | |||||
public Optional<string> AvatarUrl { get; set; } | public Optional<string> AvatarUrl { get; set; } | ||||
public CreateWebhookMessageParams(string content) | public CreateWebhookMessageParams(string content) | ||||
@@ -1,12 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class DeleteMessagesParams | internal class DeleteMessagesParams | ||||
{ | { | ||||
[JsonProperty("messages")] | |||||
[ModelProperty("messages")] | |||||
public ulong[] MessageIds { get; } | public ulong[] MessageIds { get; } | ||||
public DeleteMessagesParams(ulong[] messageIds) | public DeleteMessagesParams(ulong[] messageIds) | ||||
@@ -1,13 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
internal class GetBotGatewayResponse | internal class GetBotGatewayResponse | ||||
{ | { | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
[JsonProperty("shards")] | |||||
[ModelProperty("shards")] | |||||
public int Shards { get; set; } | public int Shards { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,11 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
internal class GetGatewayResponse | internal class GetGatewayResponse | ||||
{ | { | ||||
[JsonProperty("url")] | |||||
[ModelProperty("url")] | |||||
public string Url { get; set; } | public string Url { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,11 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
internal class GetGuildPruneCountResponse | internal class GetGuildPruneCountResponse | ||||
{ | { | ||||
[JsonProperty("pruned")] | |||||
[ModelProperty("pruned")] | |||||
public int Pruned { get; set; } | public int Pruned { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,12 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class GuildPruneParams | internal class GuildPruneParams | ||||
{ | { | ||||
[JsonProperty("days")] | |||||
[ModelProperty("days")] | |||||
public int Days { get; } | public int Days { get; } | ||||
public GuildPruneParams(int days) | public GuildPruneParams(int days) | ||||
@@ -1,16 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyChannelPermissionsParams | internal class ModifyChannelPermissionsParams | ||||
{ | { | ||||
[JsonProperty("type")] | |||||
[ModelProperty("type")] | |||||
public string Type { get; } | public string Type { get; } | ||||
[JsonProperty("allow")] | |||||
[ModelProperty("allow")] | |||||
public ulong Allow { get; } | public ulong Allow { get; } | ||||
[JsonProperty("deny")] | |||||
[ModelProperty("deny")] | |||||
public ulong Deny { get; } | public ulong Deny { get; } | ||||
public ModifyChannelPermissionsParams(string type, ulong allow, ulong deny) | public ModifyChannelPermissionsParams(string type, ulong allow, ulong deny) | ||||
@@ -1,12 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyCurrentUserNickParams | internal class ModifyCurrentUserNickParams | ||||
{ | { | ||||
[JsonProperty("nick")] | |||||
[ModelProperty("nick")] | |||||
public string Nickname { get; } | public string Nickname { get; } | ||||
public ModifyCurrentUserNickParams(string nickname) | public ModifyCurrentUserNickParams(string nickname) | ||||
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyCurrentUserParams | internal class ModifyCurrentUserParams | ||||
{ | { | ||||
[JsonProperty("username")] | |||||
[ModelProperty("username")] | |||||
public Optional<string> Username { get; set; } | public Optional<string> Username { get; set; } | ||||
[JsonProperty("avatar")] | |||||
[ModelProperty("avatar")] | |||||
public Optional<Image?> Avatar { get; set; } | public Optional<Image?> Avatar { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildChannelParams | internal class ModifyGuildChannelParams | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
[JsonProperty("position")] | |||||
[ModelProperty("position")] | |||||
public Optional<int> Position { get; set; } | public Optional<int> Position { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildChannelsParams | internal class ModifyGuildChannelsParams | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; } | public ulong Id { get; } | ||||
[JsonProperty("position")] | |||||
[ModelProperty("position")] | |||||
public int Position { get; } | public int Position { get; } | ||||
public ModifyGuildChannelsParams(ulong id, int position) | public ModifyGuildChannelsParams(ulong id, int position) | ||||
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildEmbedParams | internal class ModifyGuildEmbedParams | ||||
{ | { | ||||
[JsonProperty("enabled")] | |||||
[ModelProperty("enabled")] | |||||
public Optional<bool> Enabled { get; set; } | public Optional<bool> Enabled { get; set; } | ||||
[JsonProperty("channel")] | |||||
[ModelProperty("channel")] | |||||
public Optional<ulong?> ChannelId { get; set; } | public Optional<ulong?> ChannelId { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,16 +1,15 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildIntegrationParams | internal class ModifyGuildIntegrationParams | ||||
{ | { | ||||
[JsonProperty("expire_behavior")] | |||||
[ModelProperty("expire_behavior")] | |||||
public Optional<int> ExpireBehavior { get; set; } | public Optional<int> ExpireBehavior { get; set; } | ||||
[JsonProperty("expire_grace_period")] | |||||
[ModelProperty("expire_grace_period")] | |||||
public Optional<int> ExpireGracePeriod { get; set; } | public Optional<int> ExpireGracePeriod { get; set; } | ||||
[JsonProperty("enable_emoticons")] | |||||
[ModelProperty("enable_emoticons")] | |||||
public Optional<bool> EnableEmoticons { get; set; } | public Optional<bool> EnableEmoticons { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,20 +1,19 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildMemberParams | internal class ModifyGuildMemberParams | ||||
{ | { | ||||
[JsonProperty("mute")] | |||||
[ModelProperty("mute")] | |||||
public Optional<bool> Mute { get; set; } | public Optional<bool> Mute { get; set; } | ||||
[JsonProperty("deaf")] | |||||
[ModelProperty("deaf")] | |||||
public Optional<bool> Deaf { get; set; } | public Optional<bool> Deaf { get; set; } | ||||
[JsonProperty("nick")] | |||||
[ModelProperty("nick")] | |||||
public Optional<string> Nickname { get; set; } | public Optional<string> Nickname { get; set; } | ||||
[JsonProperty("roles")] | |||||
[ModelProperty("roles")] | |||||
public Optional<ulong[]> RoleIds { get; set; } | public Optional<ulong[]> RoleIds { get; set; } | ||||
[JsonProperty("channel_id")] | |||||
[ModelProperty("channel_id")] | |||||
public Optional<ulong> ChannelId { get; set; } | public Optional<ulong> ChannelId { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,30 +1,29 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildParams | internal class ModifyGuildParams | ||||
{ | { | ||||
[JsonProperty("username")] | |||||
[ModelProperty("username")] | |||||
public Optional<string> Username { get; set; } | public Optional<string> Username { get; set; } | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
[JsonProperty("region")] | |||||
[ModelProperty("region")] | |||||
public Optional<string> RegionId { get; set; } | public Optional<string> RegionId { get; set; } | ||||
[JsonProperty("verification_level")] | |||||
[ModelProperty("verification_level")] | |||||
public Optional<VerificationLevel> VerificationLevel { get; set; } | public Optional<VerificationLevel> VerificationLevel { get; set; } | ||||
[JsonProperty("default_message_notifications")] | |||||
[ModelProperty("default_message_notifications")] | |||||
public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; } | public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; } | ||||
[JsonProperty("afk_timeout")] | |||||
[ModelProperty("afk_timeout")] | |||||
public Optional<int> AfkTimeout { get; set; } | public Optional<int> AfkTimeout { get; set; } | ||||
[JsonProperty("icon")] | |||||
[ModelProperty("icon")] | |||||
public Optional<Image?> Icon { get; set; } | public Optional<Image?> Icon { get; set; } | ||||
[JsonProperty("splash")] | |||||
[ModelProperty("splash")] | |||||
public Optional<Image?> Splash { get; set; } | public Optional<Image?> Splash { get; set; } | ||||
[JsonProperty("afk_channel_id")] | |||||
[ModelProperty("afk_channel_id")] | |||||
public Optional<ulong?> AfkChannelId { get; set; } | public Optional<ulong?> AfkChannelId { get; set; } | ||||
[JsonProperty("owner_id")] | |||||
[ModelProperty("owner_id")] | |||||
public Optional<ulong> OwnerId { get; set; } | public Optional<ulong> OwnerId { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,20 +1,19 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildRoleParams | internal class ModifyGuildRoleParams | ||||
{ | { | ||||
[JsonProperty("name")] | |||||
[ModelProperty("name")] | |||||
public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
[JsonProperty("permissions")] | |||||
[ModelProperty("permissions")] | |||||
public Optional<ulong> Permissions { get; set; } | public Optional<ulong> Permissions { get; set; } | ||||
[JsonProperty("color")] | |||||
[ModelProperty("color")] | |||||
public Optional<uint> Color { get; set; } | public Optional<uint> Color { get; set; } | ||||
[JsonProperty("hoist")] | |||||
[ModelProperty("hoist")] | |||||
public Optional<bool> Hoist { get; set; } | public Optional<bool> Hoist { get; set; } | ||||
[JsonProperty("mentionable")] | |||||
[ModelProperty("mentionable")] | |||||
public Optional<bool> Mentionable { get; set; } | public Optional<bool> Mentionable { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyGuildRolesParams : ModifyGuildRoleParams | internal class ModifyGuildRolesParams : ModifyGuildRoleParams | ||||
{ | { | ||||
[JsonProperty("id")] | |||||
[ModelProperty("id")] | |||||
public ulong Id { get; } | public ulong Id { get; } | ||||
[JsonProperty("position")] | |||||
[ModelProperty("position")] | |||||
public int Position { get; } | public int Position { get; } | ||||
public ModifyGuildRolesParams(ulong id, int position) | public ModifyGuildRolesParams(ulong id, int position) | ||||
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyMessageParams | internal class ModifyMessageParams | ||||
{ | { | ||||
[JsonProperty("content")] | |||||
[ModelProperty("content")] | |||||
public Optional<string> Content { get; set; } | public Optional<string> Content { get; set; } | ||||
[JsonProperty("embed")] | |||||
[ModelProperty("embed")] | |||||
public Optional<Embed> Embed { get; set; } | public Optional<Embed> Embed { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,12 +1,11 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyTextChannelParams : ModifyGuildChannelParams | internal class ModifyTextChannelParams : ModifyGuildChannelParams | ||||
{ | { | ||||
[JsonProperty("topic")] | |||||
[ModelProperty("topic")] | |||||
public Optional<string> Topic { get; set; } | public Optional<string> Topic { get; set; } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,13 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
{ | { | ||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
internal class ModifyVoiceChannelParams : ModifyGuildChannelParams | internal class ModifyVoiceChannelParams : ModifyGuildChannelParams | ||||
{ | { | ||||
[JsonProperty("bitrate")] | |||||
[ModelProperty("bitrate")] | |||||
public Optional<int> Bitrate { get; set; } | public Optional<int> Bitrate { get; set; } | ||||
[JsonProperty("user_limit")] | |||||
[ModelProperty("user_limit")] | |||||
public Optional<int> UserLimit { get; set; } | public Optional<int> UserLimit { get; set; } | ||||
} | } | ||||
} | } |
@@ -22,23 +22,25 @@ namespace Discord.Rest | |||||
private readonly SemaphoreSlim _stateLock; | private readonly SemaphoreSlim _stateLock; | ||||
private bool _isFirstLogin, _isDisposed; | private bool _isFirstLogin, _isDisposed; | ||||
internal API.DiscordRestApiClient ApiClient { get; } | |||||
internal LogManager LogManager { get; } | internal LogManager LogManager { get; } | ||||
internal API.DiscordRestApiClient ApiClient { get; private set; } | |||||
public LoginState LoginState { get; private set; } | public LoginState LoginState { get; private set; } | ||||
public ISelfUser CurrentUser { get; protected set; } | public ISelfUser CurrentUser { get; protected set; } | ||||
public TokenType TokenType => ApiClient.AuthTokenType; | public TokenType TokenType => ApiClient.AuthTokenType; | ||||
/// <summary> Creates a new REST-only discord client. </summary> | /// <summary> Creates a new REST-only discord client. </summary> | ||||
internal BaseDiscordClient(DiscordRestConfig config, API.DiscordRestApiClient client) | |||||
internal BaseDiscordClient(DiscordRestConfig config) | |||||
{ | { | ||||
ApiClient = client; | |||||
LogManager = new LogManager(config.LogLevel); | LogManager = new LogManager(config.LogLevel); | ||||
LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false); | LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false); | ||||
_stateLock = new SemaphoreSlim(1, 1); | _stateLock = new SemaphoreSlim(1, 1); | ||||
_restLogger = LogManager.CreateLogger("Rest"); | _restLogger = LogManager.CreateLogger("Rest"); | ||||
_isFirstLogin = config.DisplayInitialLog; | _isFirstLogin = config.DisplayInitialLog; | ||||
} | |||||
internal void SetApiClient(API.DiscordRestApiClient client) | |||||
{ | |||||
ApiClient = client; | |||||
ApiClient.RequestQueue.RateLimitTriggered += async (id, info) => | ApiClient.RequestQueue.RateLimitTriggered += async (id, info) => | ||||
{ | { | ||||
if (info == null) | if (info == null) | ||||
@@ -7,7 +7,16 @@ | |||||
<TargetFrameworks>net45;netstandard1.1;netstandard1.3</TargetFrameworks> | <TargetFrameworks>net45;netstandard1.1;netstandard1.3</TargetFrameworks> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Compile Remove="Serialization\System.Buffers\**" /> | |||||
<Compile Remove="_corefxlab\**" /> | |||||
<EmbeddedResource Remove="Serialization\System.Buffers\**" /> | |||||
<EmbeddedResource Remove="_corefxlab\**" /> | |||||
<None Remove="Serialization\System.Buffers\**" /> | |||||
<None Remove="_corefxlab\**" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" /> | <ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" /> | ||||
<ProjectReference Include="..\Discord.Net.Serialization\Discord.Net.Serialization.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net45' "> | <ItemGroup Condition=" '$(TargetFramework)' != 'net45' "> | ||||
<PackageReference Include="System.Net.Http" Version="4.3.2" /> <!-- https://github.com/dotnet/corefx/issues/19535 --> | <PackageReference Include="System.Net.Http" Version="4.3.2" /> <!-- https://github.com/dotnet/corefx/issues/19535 --> | ||||
@@ -1,21 +1,19 @@ | |||||
#pragma warning disable CS1591 | #pragma warning disable CS1591 | ||||
using Discord.API.Rest; | using Discord.API.Rest; | ||||
using Discord.Net; | using Discord.Net; | ||||
using Discord.Net.Converters; | |||||
using Discord.Net.Queue; | using Discord.Net.Queue; | ||||
using Discord.Net.Rest; | using Discord.Net.Rest; | ||||
using Newtonsoft.Json; | |||||
using Discord.Serialization; | |||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.Globalization; | |||||
using System.IO; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Linq.Expressions; | using System.Linq.Expressions; | ||||
using System.Net; | using System.Net; | ||||
using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||
using System.Text; | using System.Text; | ||||
using System.Text.Formatting; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -27,9 +25,10 @@ namespace Discord.API | |||||
public event Func<string, string, double, Task> SentRequest { add { _sentRequestEvent.Add(value); } remove { _sentRequestEvent.Remove(value); } } | public event Func<string, string, double, Task> SentRequest { add { _sentRequestEvent.Add(value); } remove { _sentRequestEvent.Remove(value); } } | ||||
private readonly AsyncEvent<Func<string, string, double, Task>> _sentRequestEvent = new AsyncEvent<Func<string, string, double, Task>>(); | private readonly AsyncEvent<Func<string, string, double, Task>> _sentRequestEvent = new AsyncEvent<Func<string, string, double, Task>>(); | ||||
protected readonly JsonSerializer _serializer; | |||||
protected readonly SemaphoreSlim _stateLock; | protected readonly SemaphoreSlim _stateLock; | ||||
protected readonly Serializer _serializer; | |||||
protected readonly Pool<ArrayFormatter> _formatters; | |||||
private readonly RestClientProvider _restClientProvider; | private readonly RestClientProvider _restClientProvider; | ||||
protected bool _isDisposed; | protected bool _isDisposed; | ||||
@@ -45,16 +44,16 @@ namespace Discord.API | |||||
internal IRestClient RestClient { get; private set; } | internal IRestClient RestClient { get; private set; } | ||||
internal ulong? CurrentUserId { get; set;} | internal ulong? CurrentUserId { get; set;} | ||||
public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, RetryMode defaultRetryMode = RetryMode.AlwaysRetry, | |||||
JsonSerializer serializer = null) | |||||
public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, Serializer serializer, RetryMode defaultRetryMode = RetryMode.AlwaysRetry) | |||||
{ | { | ||||
_restClientProvider = restClientProvider; | _restClientProvider = restClientProvider; | ||||
UserAgent = userAgent; | UserAgent = userAgent; | ||||
_serializer = serializer; | |||||
DefaultRetryMode = defaultRetryMode; | DefaultRetryMode = defaultRetryMode; | ||||
_serializer = serializer ?? new JsonSerializer { DateFormatString = "yyyy-MM-ddTHH:mm:ssZ", ContractResolver = new DiscordContractResolver() }; | |||||
RequestQueue = new RequestQueue(); | RequestQueue = new RequestQueue(); | ||||
_stateLock = new SemaphoreSlim(1, 1); | _stateLock = new SemaphoreSlim(1, 1); | ||||
_formatters = new Pool<ArrayFormatter>(() => new ArrayFormatter(128, SymbolTable.InvariantUtf8)); | |||||
SetBaseUrl(DiscordConfig.APIUrl); | SetBaseUrl(DiscordConfig.APIUrl); | ||||
} | } | ||||
@@ -188,10 +187,18 @@ namespace Discord.API | |||||
options.HeaderOnly = true; | options.HeaderOnly = true; | ||||
options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | ||||
options.IsClientBucket = AuthTokenType == TokenType.User; | options.IsClientBucket = AuthTokenType == TokenType.User; | ||||
string json = payload != null ? SerializeJson(payload) : null; | |||||
var request = new JsonRestRequest(RestClient, method, endpoint, json, options); | |||||
await SendInternalAsync(method, endpoint, request).ConfigureAwait(false); | |||||
var data = _formatters.Rent(); | |||||
try | |||||
{ | |||||
var request = new JsonRestRequest(RestClient, method, endpoint, SerializeJson(data, payload), options); | |||||
await SendInternalAsync(method, endpoint, request).ConfigureAwait(false); | |||||
} | |||||
finally | |||||
{ | |||||
data.Clear(); | |||||
_formatters.Return(data); | |||||
} | |||||
} | } | ||||
internal Task SendMultipartAsync(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids, | internal Task SendMultipartAsync(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids, | ||||
@@ -210,10 +217,10 @@ namespace Discord.API | |||||
} | } | ||||
internal Task<TResponse> SendAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, BucketIds ids, | internal Task<TResponse> SendAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, BucketIds ids, | ||||
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) where TResponse : class | |||||
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) where TResponse : class, new() | |||||
=> SendAsync<TResponse>(method, GetEndpoint(endpointExpr), GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); | => SendAsync<TResponse>(method, GetEndpoint(endpointExpr), GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); | ||||
public async Task<TResponse> SendAsync<TResponse>(string method, string endpoint, | public async Task<TResponse> SendAsync<TResponse>(string method, string endpoint, | ||||
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) where TResponse : class | |||||
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) where TResponse : class, new() | |||||
{ | { | ||||
options = options ?? new RequestOptions(); | options = options ?? new RequestOptions(); | ||||
options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | ||||
@@ -224,25 +231,33 @@ namespace Discord.API | |||||
} | } | ||||
internal Task<TResponse> SendJsonAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, object payload, BucketIds ids, | internal Task<TResponse> SendJsonAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, object payload, BucketIds ids, | ||||
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) where TResponse : class | |||||
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) where TResponse : class, new() | |||||
=> SendJsonAsync<TResponse>(method, GetEndpoint(endpointExpr), payload, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); | => SendJsonAsync<TResponse>(method, GetEndpoint(endpointExpr), payload, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); | ||||
public async Task<TResponse> SendJsonAsync<TResponse>(string method, string endpoint, object payload, | public async Task<TResponse> SendJsonAsync<TResponse>(string method, string endpoint, object payload, | ||||
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) where TResponse : class | |||||
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) where TResponse : class, new() | |||||
{ | { | ||||
options = options ?? new RequestOptions(); | options = options ?? new RequestOptions(); | ||||
options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | ||||
options.IsClientBucket = AuthTokenType == TokenType.User; | options.IsClientBucket = AuthTokenType == TokenType.User; | ||||
string json = payload != null ? SerializeJson(payload) : null; | |||||
var request = new JsonRestRequest(RestClient, method, endpoint, json, options); | |||||
return DeserializeJson<TResponse>(await SendInternalAsync(method, endpoint, request).ConfigureAwait(false)); | |||||
var data = _formatters.Rent(); | |||||
try | |||||
{ | |||||
var request = new JsonRestRequest(RestClient, method, endpoint, SerializeJson(data, payload), options); | |||||
return DeserializeJson<TResponse>(await SendInternalAsync(method, endpoint, request).ConfigureAwait(false)); | |||||
} | |||||
finally | |||||
{ | |||||
data.Clear(); | |||||
_formatters.Return(data); | |||||
} | |||||
} | } | ||||
internal Task<TResponse> SendMultipartAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids, | internal Task<TResponse> SendMultipartAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids, | ||||
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) | |||||
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null) where TResponse : class, new() | |||||
=> SendMultipartAsync<TResponse>(method, GetEndpoint(endpointExpr), multipartArgs, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); | => SendMultipartAsync<TResponse>(method, GetEndpoint(endpointExpr), multipartArgs, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options); | ||||
public async Task<TResponse> SendMultipartAsync<TResponse>(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, | public async Task<TResponse> SendMultipartAsync<TResponse>(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, | ||||
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) | |||||
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null) where TResponse : class, new() | |||||
{ | { | ||||
options = options ?? new RequestOptions(); | options = options ?? new RequestOptions(); | ||||
options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId; | ||||
@@ -252,7 +267,7 @@ namespace Discord.API | |||||
return DeserializeJson<TResponse>(await SendInternalAsync(method, endpoint, request).ConfigureAwait(false)); | return DeserializeJson<TResponse>(await SendInternalAsync(method, endpoint, request).ConfigureAwait(false)); | ||||
} | } | ||||
private async Task<Stream> SendInternalAsync(string method, string endpoint, RestRequest request) | |||||
private async Task<ReadOnlyBuffer<byte>> SendInternalAsync(string method, string endpoint, RestRequest request) | |||||
{ | { | ||||
if (!request.Options.IgnoreState) | if (!request.Options.IgnoreState) | ||||
CheckState(); | CheckState(); | ||||
@@ -260,13 +275,13 @@ namespace Discord.API | |||||
request.Options.RetryMode = DefaultRetryMode; | request.Options.RetryMode = DefaultRetryMode; | ||||
var stopwatch = Stopwatch.StartNew(); | var stopwatch = Stopwatch.StartNew(); | ||||
var responseStream = await RequestQueue.SendAsync(request).ConfigureAwait(false); | |||||
var response = await RequestQueue.SendAsync(request).ConfigureAwait(false); | |||||
stopwatch.Stop(); | stopwatch.Stop(); | ||||
double milliseconds = ToMilliseconds(stopwatch); | double milliseconds = ToMilliseconds(stopwatch); | ||||
await _sentRequestEvent.InvokeAsync(method, endpoint, milliseconds).ConfigureAwait(false); | await _sentRequestEvent.InvokeAsync(method, endpoint, milliseconds).ConfigureAwait(false); | ||||
return responseStream; | |||||
return response; | |||||
} | } | ||||
//Auth | //Auth | ||||
@@ -311,7 +326,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendAsync<IReadOnlyCollection<Channel>>("GET", () => $"guilds/{guildId}/channels", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Channel>>("GET", () => $"guilds/{guildId}/channels", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<Channel> CreateGuildChannelAsync(ulong guildId, CreateGuildChannelParams args, RequestOptions options = null) | public async Task<Channel> CreateGuildChannelAsync(ulong guildId, CreateGuildChannelParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -454,7 +469,7 @@ namespace Discord.API | |||||
endpoint = () => $"channels/{channelId}/messages?limit={limit}&{relativeDir}={relativeId}"; | endpoint = () => $"channels/{channelId}/messages?limit={limit}&{relativeDir}={relativeId}"; | ||||
else | else | ||||
endpoint = () => $"channels/{channelId}/messages?limit={limit}"; | endpoint = () => $"channels/{channelId}/messages?limit={limit}"; | ||||
return await SendAsync<IReadOnlyCollection<Message>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Message>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<Message> CreateMessageAsync(ulong channelId, CreateMessageParams args, RequestOptions options = null) | public async Task<Message> CreateMessageAsync(ulong channelId, CreateMessageParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -620,7 +635,7 @@ namespace Discord.API | |||||
var ids = new BucketIds(channelId: channelId); | var ids = new BucketIds(channelId: channelId); | ||||
Expression<Func<string>> endpoint = () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}"; | Expression<Func<string>> endpoint = () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}"; | ||||
return await SendAsync<IReadOnlyCollection<User>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<User>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null) | public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null) | ||||
{ | { | ||||
@@ -687,7 +702,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(channelId: channelId); | var ids = new BucketIds(channelId: channelId); | ||||
return await SendAsync<IReadOnlyCollection<Message>>("GET", () => $"channels/{channelId}/pins", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Message>>("GET", () => $"channels/{channelId}/pins", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
//Channel Recipients | //Channel Recipients | ||||
@@ -791,7 +806,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendAsync<IReadOnlyCollection<Ban>>("GET", () => $"guilds/{guildId}/bans", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Ban>>("GET", () => $"guilds/{guildId}/bans", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task CreateGuildBanAsync(ulong guildId, ulong userId, CreateGuildBanParams args, RequestOptions options = null) | public async Task CreateGuildBanAsync(ulong guildId, ulong userId, CreateGuildBanParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -846,7 +861,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendAsync<IReadOnlyCollection<Integration>>("GET", () => $"guilds/{guildId}/integrations", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Integration>>("GET", () => $"guilds/{guildId}/integrations", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<Integration> CreateGuildIntegrationAsync(ulong guildId, CreateGuildIntegrationParams args, RequestOptions options = null) | public async Task<Integration> CreateGuildIntegrationAsync(ulong guildId, CreateGuildIntegrationParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -915,7 +930,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendAsync<IReadOnlyCollection<InviteMetadata>>("GET", () => $"guilds/{guildId}/invites", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync< List<InviteMetadata>>("GET", () => $"guilds/{guildId}/invites", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<IReadOnlyCollection<InviteMetadata>> GetChannelInvitesAsync(ulong channelId, RequestOptions options = null) | public async Task<IReadOnlyCollection<InviteMetadata>> GetChannelInvitesAsync(ulong channelId, RequestOptions options = null) | ||||
{ | { | ||||
@@ -923,7 +938,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(channelId: channelId); | var ids = new BucketIds(channelId: channelId); | ||||
return await SendAsync<IReadOnlyCollection<InviteMetadata>>("GET", () => $"channels/{channelId}/invites", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<InviteMetadata>>("GET", () => $"channels/{channelId}/invites", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<InviteMetadata> CreateChannelInviteAsync(ulong channelId, CreateChannelInviteParams args, RequestOptions options = null) | public async Task<InviteMetadata> CreateChannelInviteAsync(ulong channelId, CreateChannelInviteParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -979,7 +994,7 @@ namespace Discord.API | |||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
Expression<Func<string>> endpoint = () => $"guilds/{guildId}/members?limit={limit}&after={afterUserId}"; | Expression<Func<string>> endpoint = () => $"guilds/{guildId}/members?limit={limit}&after={afterUserId}"; | ||||
return await SendAsync<IReadOnlyCollection<GuildMember>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync< List<GuildMember>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task RemoveGuildMemberAsync(ulong guildId, ulong userId, string reason, RequestOptions options = null) | public async Task RemoveGuildMemberAsync(ulong guildId, ulong userId, string reason, RequestOptions options = null) | ||||
{ | { | ||||
@@ -1020,7 +1035,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendAsync<IReadOnlyCollection<Role>>("GET", () => $"guilds/{guildId}/roles", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Role>>("GET", () => $"guilds/{guildId}/roles", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<Role> CreateGuildRoleAsync(ulong guildId, RequestOptions options = null) | public async Task<Role> CreateGuildRoleAsync(ulong guildId, RequestOptions options = null) | ||||
{ | { | ||||
@@ -1058,7 +1073,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendJsonAsync<IReadOnlyCollection<Role>>("PATCH", () => $"guilds/{guildId}/roles", args, ids, options: options).ConfigureAwait(false); | |||||
return await SendJsonAsync<List<Role>>("PATCH", () => $"guilds/{guildId}/roles", args, ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
//Users | //Users | ||||
@@ -1083,12 +1098,12 @@ namespace Discord.API | |||||
public async Task<IReadOnlyCollection<Connection>> GetMyConnectionsAsync(RequestOptions options = null) | public async Task<IReadOnlyCollection<Connection>> GetMyConnectionsAsync(RequestOptions options = null) | ||||
{ | { | ||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
return await SendAsync<IReadOnlyCollection<Connection>>("GET", () => "users/@me/connections", new BucketIds(), options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Connection>>("GET", () => "users/@me/connections", new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<IReadOnlyCollection<Channel>> GetMyPrivateChannelsAsync(RequestOptions options = null) | public async Task<IReadOnlyCollection<Channel>> GetMyPrivateChannelsAsync(RequestOptions options = null) | ||||
{ | { | ||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
return await SendAsync<IReadOnlyCollection<Channel>>("GET", () => "users/@me/channels", new BucketIds(), options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<Channel>>("GET", () => "users/@me/channels", new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<IReadOnlyCollection<UserGuild>> GetMyGuildsAsync(GetGuildSummariesParams args, RequestOptions options = null) | public async Task<IReadOnlyCollection<UserGuild>> GetMyGuildsAsync(GetGuildSummariesParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -1101,7 +1116,7 @@ namespace Discord.API | |||||
int limit = args.Limit.GetValueOrDefault(int.MaxValue); | int limit = args.Limit.GetValueOrDefault(int.MaxValue); | ||||
ulong afterGuildId = args.AfterGuildId.GetValueOrDefault(0); | ulong afterGuildId = args.AfterGuildId.GetValueOrDefault(0); | ||||
return await SendAsync<IReadOnlyCollection<UserGuild>>("GET", () => $"users/@me/guilds?limit={limit}&after={afterGuildId}", new BucketIds(), options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<UserGuild>>("GET", () => $"users/@me/guilds?limit={limit}&after={afterGuildId}", new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<Application> GetMyApplicationAsync(RequestOptions options = null) | public async Task<Application> GetMyApplicationAsync(RequestOptions options = null) | ||||
{ | { | ||||
@@ -1138,7 +1153,7 @@ namespace Discord.API | |||||
public async Task<IReadOnlyCollection<VoiceRegion>> GetVoiceRegionsAsync(RequestOptions options = null) | public async Task<IReadOnlyCollection<VoiceRegion>> GetVoiceRegionsAsync(RequestOptions options = null) | ||||
{ | { | ||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
return await SendAsync<IReadOnlyCollection<VoiceRegion>>("GET", () => "voice/regions", new BucketIds(), options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<VoiceRegion>>("GET", () => "voice/regions", new BucketIds(), options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task<IReadOnlyCollection<VoiceRegion>> GetGuildVoiceRegionsAsync(ulong guildId, RequestOptions options = null) | public async Task<IReadOnlyCollection<VoiceRegion>> GetGuildVoiceRegionsAsync(ulong guildId, RequestOptions options = null) | ||||
{ | { | ||||
@@ -1146,7 +1161,7 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
return await SendAsync<IReadOnlyCollection<VoiceRegion>>("GET", () => $"guilds/{guildId}/regions", ids, options: options).ConfigureAwait(false); | |||||
return await SendAsync<List<VoiceRegion>>("GET", () => $"guilds/{guildId}/regions", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
//Helpers | //Helpers | ||||
@@ -1156,19 +1171,14 @@ namespace Discord.API | |||||
throw new InvalidOperationException("Client is not logged in."); | throw new InvalidOperationException("Client is not logged in."); | ||||
} | } | ||||
protected static double ToMilliseconds(Stopwatch stopwatch) => Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2); | protected static double ToMilliseconds(Stopwatch stopwatch) => Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2); | ||||
protected string SerializeJson(object value) | |||||
protected ReadOnlyBuffer<byte> SerializeJson<T>(ArrayFormatter data, T value) | |||||
{ | { | ||||
var sb = new StringBuilder(256); | |||||
using (TextWriter text = new StringWriter(sb, CultureInfo.InvariantCulture)) | |||||
using (JsonWriter writer = new JsonTextWriter(text)) | |||||
_serializer.Serialize(writer, value); | |||||
return sb.ToString(); | |||||
_serializer.Write(data, value); | |||||
return new ReadOnlyBuffer<byte>(data.Formatted.Array, 0, data.Formatted.Count); | |||||
} | } | ||||
protected T DeserializeJson<T>(Stream jsonStream) | |||||
protected T DeserializeJson<T>(ReadOnlyBuffer<byte> data) | |||||
{ | { | ||||
using (TextReader text = new StreamReader(jsonStream)) | |||||
using (JsonReader reader = new JsonTextReader(text)) | |||||
return _serializer.Deserialize<T>(reader); | |||||
return _serializer.Read<T>(data); | |||||
} | } | ||||
internal class BucketIds | internal class BucketIds | ||||
@@ -1,4 +1,6 @@ | |||||
using System.Collections.Generic; | |||||
using Discord.Serialization; | |||||
using Discord.Serialization.Json; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
using System.IO; | using System.IO; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -7,15 +9,29 @@ namespace Discord.Rest | |||||
{ | { | ||||
public class DiscordRestClient : BaseDiscordClient, IDiscordClient | public class DiscordRestClient : BaseDiscordClient, IDiscordClient | ||||
{ | { | ||||
private readonly Serializer _serializer; | |||||
private RestApplication _applicationInfo; | private RestApplication _applicationInfo; | ||||
public new RestSelfUser CurrentUser => base.CurrentUser as RestSelfUser; | public new RestSelfUser CurrentUser => base.CurrentUser as RestSelfUser; | ||||
public DiscordRestClient() : this(new DiscordRestConfig()) { } | public DiscordRestClient() : this(new DiscordRestConfig()) { } | ||||
public DiscordRestClient(DiscordRestConfig config) : base(config, CreateApiClient(config)) { } | |||||
public DiscordRestClient(DiscordRestConfig config) : base(config) | |||||
{ | |||||
_serializer = DiscordRestJsonSerializer.Global.CreateScope(); | |||||
if (config.LogLevel >= LogSeverity.Warning) | |||||
{ | |||||
_serializer.ModelError += (path, ex) | |||||
=> _restLogger.WarningAsync($"Failed to deserialize {path}", ex).GetAwaiter().GetResult(); | |||||
} | |||||
if (config.LogLevel >= LogSeverity.Debug) | |||||
{ | |||||
_serializer.UnmappedProperty += path | |||||
=> _restLogger.DebugAsync($"Unmapped property: {path}"); | |||||
} | |||||
SetApiClient(new API.DiscordRestApiClient(config.RestClientProvider, DiscordConfig.UserAgent, _serializer, config.DefaultRetryMode)); | |||||
} | |||||
private static API.DiscordRestApiClient CreateApiClient(DiscordRestConfig config) | |||||
=> new API.DiscordRestApiClient(config.RestClientProvider, DiscordRestConfig.UserAgent); | |||||
internal override void Dispose(bool disposing) | internal override void Dispose(bool disposing) | ||||
{ | { | ||||
if (disposing) | if (disposing) | ||||
@@ -114,7 +114,7 @@ namespace Discord.Rest | |||||
public static API.Image ToModel(this Image entity) | public static API.Image ToModel(this Image entity) | ||||
{ | { | ||||
return new API.Image(entity.Stream); | |||||
return new API.Image(entity.Stream, entity.Format); | |||||
} | } | ||||
public static Overwrite ToEntity(this API.Overwrite model) | public static Overwrite ToEntity(this API.Overwrite model) | ||||
@@ -0,0 +1,25 @@ | |||||
using System; | |||||
using System.IO; | |||||
namespace Discord | |||||
{ | |||||
internal static class StreamExtensions | |||||
{ | |||||
#if MSTRYBUFFER | |||||
public static byte[] GetBuffer(this MemoryStream stream) | |||||
{ | |||||
if (stream.TryGetBuffer(out var streamBuffer)) | |||||
return streamBuffer.Array; | |||||
else | |||||
return stream.ToArray(); | |||||
} | |||||
#elif !MSBUFFER | |||||
public static byte[] GetBuffer(this MemoryStream stream) => stream.ToArray(); | |||||
#endif | |||||
public static ReadOnlyBuffer<byte> ToReadOnlyBuffer(this MemoryStream stream) | |||||
=> new ReadOnlyBuffer<byte>(stream.GetBuffer(), 0, (int)stream.Length); | |||||
public static ReadOnlySpan<byte> ToSpan(this MemoryStream stream) | |||||
=> new ReadOnlySpan<byte>(stream.GetBuffer(), 0, (int)stream.Length); | |||||
} | |||||
} |
@@ -1,59 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class ArrayConverter<T> : JsonConverter | |||||
{ | |||||
private readonly JsonConverter _innerConverter; | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public ArrayConverter(JsonConverter innerConverter) | |||||
{ | |||||
_innerConverter = innerConverter; | |||||
} | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
var result = new List<T>(); | |||||
if (reader.TokenType == JsonToken.StartArray) | |||||
{ | |||||
reader.Read(); | |||||
while (reader.TokenType != JsonToken.EndArray) | |||||
{ | |||||
T obj; | |||||
if (_innerConverter != null) | |||||
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer); | |||||
else | |||||
obj = serializer.Deserialize<T>(reader); | |||||
result.Add(obj); | |||||
reader.Read(); | |||||
} | |||||
} | |||||
return result.ToArray(); | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
if (value != null) | |||||
{ | |||||
writer.WriteStartArray(); | |||||
var a = (T[])value; | |||||
for (int i = 0; i < a.Length; i++) | |||||
{ | |||||
if (_innerConverter != null) | |||||
_innerConverter.WriteJson(writer, a[i], serializer); | |||||
else | |||||
serializer.Serialize(writer, a[i], typeof(T)); | |||||
} | |||||
writer.WriteEndArray(); | |||||
} | |||||
else | |||||
writer.WriteNull(); | |||||
} | |||||
} | |||||
} |
@@ -1,102 +0,0 @@ | |||||
using Discord.API; | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json.Serialization; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Reflection; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class DiscordContractResolver : DefaultContractResolver | |||||
{ | |||||
private static readonly TypeInfo _ienumerable = typeof(IEnumerable<ulong[]>).GetTypeInfo(); | |||||
private static readonly MethodInfo _shouldSerialize = typeof(DiscordContractResolver).GetTypeInfo().GetDeclaredMethod("ShouldSerialize"); | |||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) | |||||
{ | |||||
var property = base.CreateProperty(member, memberSerialization); | |||||
if (property.Ignored) | |||||
return property; | |||||
if (member is PropertyInfo propInfo) | |||||
{ | |||||
var converter = GetConverter(property, propInfo, propInfo.PropertyType, 0); | |||||
if (converter != null) | |||||
{ | |||||
property.Converter = converter; | |||||
property.MemberConverter = converter; | |||||
} | |||||
} | |||||
else | |||||
throw new InvalidOperationException($"{member.DeclaringType.FullName}.{member.Name} is not a property."); | |||||
return property; | |||||
} | |||||
private static JsonConverter GetConverter(JsonProperty property, PropertyInfo propInfo, Type type, int depth) | |||||
{ | |||||
if (type.IsArray) | |||||
return MakeGenericConverter(property, propInfo, typeof(ArrayConverter<>), type.GetElementType(), depth); | |||||
if (type.IsConstructedGenericType) | |||||
{ | |||||
Type genericType = type.GetGenericTypeDefinition(); | |||||
if (depth == 0 && genericType == typeof(Optional<>)) | |||||
{ | |||||
var typeInput = propInfo.DeclaringType; | |||||
var innerTypeOutput = type.GenericTypeArguments[0]; | |||||
var getter = typeof(Func<,>).MakeGenericType(typeInput, type); | |||||
var getterDelegate = propInfo.GetMethod.CreateDelegate(getter); | |||||
var shouldSerialize = _shouldSerialize.MakeGenericMethod(typeInput, innerTypeOutput); | |||||
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>)); | |||||
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate); | |||||
return MakeGenericConverter(property, propInfo, typeof(OptionalConverter<>), innerTypeOutput, depth); | |||||
} | |||||
else if (genericType == typeof(Nullable<>)) | |||||
return MakeGenericConverter(property, propInfo, typeof(NullableConverter<>), type.GenericTypeArguments[0], depth); | |||||
else if (genericType == typeof(EntityOrId<>)) | |||||
return MakeGenericConverter(property, propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0], depth); | |||||
} | |||||
//Primitives | |||||
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null; | |||||
if (!hasInt53) | |||||
{ | |||||
if (type == typeof(ulong)) | |||||
return UInt64Converter.Instance; | |||||
} | |||||
//Enums | |||||
if (type == typeof(PermissionTarget)) | |||||
return PermissionTargetConverter.Instance; | |||||
if (type == typeof(UserStatus)) | |||||
return UserStatusConverter.Instance; | |||||
//Special | |||||
if (type == typeof(API.Image)) | |||||
return ImageConverter.Instance; | |||||
//Entities | |||||
var typeInfo = type.GetTypeInfo(); | |||||
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>))) | |||||
return UInt64EntityConverter.Instance; | |||||
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<string>))) | |||||
return StringEntityConverter.Instance; | |||||
return null; | |||||
} | |||||
private static bool ShouldSerialize<TOwner, TValue>(object owner, Delegate getter) | |||||
{ | |||||
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified; | |||||
} | |||||
private static JsonConverter MakeGenericConverter(JsonProperty property, PropertyInfo propInfo, Type converterType, Type innerType, int depth) | |||||
{ | |||||
var genericType = converterType.MakeGenericType(innerType).GetTypeInfo(); | |||||
var innerConverter = GetConverter(property, propInfo, innerType, depth + 1); | |||||
return genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter; | |||||
} | |||||
} | |||||
} |
@@ -1,36 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using Model = Discord.API.Image; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class ImageConverter : JsonConverter | |||||
{ | |||||
public static readonly ImageConverter Instance = new ImageConverter(); | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
throw new InvalidOperationException(); | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
var image = (Model)value; | |||||
if (image.Stream != null) | |||||
{ | |||||
byte[] bytes = new byte[image.Stream.Length - image.Stream.Position]; | |||||
image.Stream.Read(bytes, 0, bytes.Length); | |||||
string base64 = Convert.ToBase64String(bytes); | |||||
writer.WriteValue($"data:image/jpeg;base64,{base64}"); | |||||
} | |||||
else if (image.Hash != null) | |||||
writer.WriteValue(image.Hash); | |||||
} | |||||
} | |||||
} |
@@ -1,50 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class NullableConverter<T> : JsonConverter | |||||
where T : struct | |||||
{ | |||||
private readonly JsonConverter _innerConverter; | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public NullableConverter(JsonConverter innerConverter) | |||||
{ | |||||
_innerConverter = innerConverter; | |||||
} | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
object value = reader.Value; | |||||
if (value == null) | |||||
return null; | |||||
else | |||||
{ | |||||
T obj; | |||||
if (_innerConverter != null) | |||||
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer); | |||||
else | |||||
obj = serializer.Deserialize<T>(reader); | |||||
return obj; | |||||
} | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
if (value == null) | |||||
writer.WriteNull(); | |||||
else | |||||
{ | |||||
var nullable = (T?)value; | |||||
if (_innerConverter != null) | |||||
_innerConverter.WriteJson(writer, nullable.Value, serializer); | |||||
else | |||||
serializer.Serialize(writer, nullable.Value, typeof(T)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,38 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class OptionalConverter<T> : JsonConverter | |||||
{ | |||||
private readonly JsonConverter _innerConverter; | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public OptionalConverter(JsonConverter innerConverter) | |||||
{ | |||||
_innerConverter = innerConverter; | |||||
} | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
T obj; | |||||
if (_innerConverter != null) | |||||
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer); | |||||
else | |||||
obj = serializer.Deserialize<T>(reader); | |||||
return new Optional<T>(obj); | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
value = ((Optional<T>)value).Value; | |||||
if (_innerConverter != null) | |||||
_innerConverter.WriteJson(writer, value, serializer); | |||||
else | |||||
serializer.Serialize(writer, value, typeof(T)); | |||||
} | |||||
} | |||||
} |
@@ -1,42 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class PermissionTargetConverter : JsonConverter | |||||
{ | |||||
public static readonly PermissionTargetConverter Instance = new PermissionTargetConverter(); | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
switch ((string)reader.Value) | |||||
{ | |||||
case "member": | |||||
return PermissionTarget.User; | |||||
case "role": | |||||
return PermissionTarget.Role; | |||||
default: | |||||
throw new JsonSerializationException("Unknown permission target"); | |||||
} | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
switch ((PermissionTarget)value) | |||||
{ | |||||
case PermissionTarget.User: | |||||
writer.WriteValue("member"); | |||||
break; | |||||
case PermissionTarget.Role: | |||||
writer.WriteValue("role"); | |||||
break; | |||||
default: | |||||
throw new JsonSerializationException("Invalid permission target"); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,27 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class StringEntityConverter : JsonConverter | |||||
{ | |||||
public static readonly StringEntityConverter Instance = new StringEntityConverter(); | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => false; | |||||
public override bool CanWrite => true; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
throw new InvalidOperationException(); | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
if (value != null) | |||||
writer.WriteValue((value as IEntity<string>).Id); | |||||
else | |||||
writer.WriteNull(); | |||||
} | |||||
} | |||||
} |
@@ -1,25 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Globalization; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class UInt64Converter : JsonConverter | |||||
{ | |||||
public static readonly UInt64Converter Instance = new UInt64Converter(); | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
return ulong.Parse((string)reader.Value, NumberStyles.None, CultureInfo.InvariantCulture); | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
writer.WriteValue(((ulong)value).ToString(CultureInfo.InvariantCulture)); | |||||
} | |||||
} | |||||
} |
@@ -1,28 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Globalization; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class UInt64EntityConverter : JsonConverter | |||||
{ | |||||
public static readonly UInt64EntityConverter Instance = new UInt64EntityConverter(); | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => false; | |||||
public override bool CanWrite => true; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
throw new InvalidOperationException(); | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
if (value != null) | |||||
writer.WriteValue((value as IEntity<ulong>).Id.ToString(CultureInfo.InvariantCulture)); | |||||
else | |||||
writer.WriteNull(); | |||||
} | |||||
} | |||||
} |
@@ -1,42 +0,0 @@ | |||||
using Discord.API; | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class UInt64EntityOrIdConverter<T> : JsonConverter | |||||
{ | |||||
private readonly JsonConverter _innerConverter; | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => false; | |||||
public UInt64EntityOrIdConverter(JsonConverter innerConverter) | |||||
{ | |||||
_innerConverter = innerConverter; | |||||
} | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
switch (reader.TokenType) | |||||
{ | |||||
case JsonToken.String: | |||||
case JsonToken.Integer: | |||||
return new EntityOrId<T>(ulong.Parse(reader.ReadAsString())); | |||||
default: | |||||
T obj; | |||||
if (_innerConverter != null) | |||||
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer); | |||||
else | |||||
obj = serializer.Deserialize<T>(reader); | |||||
return new EntityOrId<T>(obj); | |||||
} | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
throw new InvalidOperationException(); | |||||
} | |||||
} | |||||
} |
@@ -1,58 +0,0 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class UserStatusConverter : JsonConverter | |||||
{ | |||||
public static readonly UserStatusConverter Instance = new UserStatusConverter(); | |||||
public override bool CanConvert(Type objectType) => true; | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => true; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
switch ((string)reader.Value) | |||||
{ | |||||
case "online": | |||||
return UserStatus.Online; | |||||
case "idle": | |||||
return UserStatus.Idle; | |||||
case "dnd": | |||||
return UserStatus.DoNotDisturb; | |||||
case "invisible": | |||||
return UserStatus.Invisible; //Should never happen | |||||
case "offline": | |||||
return UserStatus.Offline; | |||||
default: | |||||
throw new JsonSerializationException("Unknown user status"); | |||||
} | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
{ | |||||
switch ((UserStatus)value) | |||||
{ | |||||
case UserStatus.Online: | |||||
writer.WriteValue("online"); | |||||
break; | |||||
case UserStatus.Idle: | |||||
case UserStatus.AFK: | |||||
writer.WriteValue("idle"); | |||||
break; | |||||
case UserStatus.DoNotDisturb: | |||||
writer.WriteValue("dnd"); | |||||
break; | |||||
case UserStatus.Invisible: | |||||
writer.WriteValue("invisible"); | |||||
break; | |||||
case UserStatus.Offline: | |||||
writer.WriteValue("offline"); | |||||
break; | |||||
default: | |||||
throw new JsonSerializationException("Invalid user status"); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,11 +1,11 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Globalization; | using System.Globalization; | ||||
using System.IO; | using System.IO; | ||||
using System.Linq; | using System.Linq; | ||||
using System.Net; | using System.Net; | ||||
using System.Net.Http; | using System.Net.Http; | ||||
using System.Net.Http.Headers; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -18,7 +18,6 @@ namespace Discord.Net.Rest | |||||
private readonly HttpClient _client; | private readonly HttpClient _client; | ||||
private readonly string _baseUrl; | private readonly string _baseUrl; | ||||
private readonly JsonSerializer _errorDeserializer; | |||||
private CancellationToken _cancelToken; | private CancellationToken _cancelToken; | ||||
private bool _isDisposed; | private bool _isDisposed; | ||||
@@ -35,7 +34,6 @@ namespace Discord.Net.Rest | |||||
SetHeader("accept-encoding", "gzip, deflate"); | SetHeader("accept-encoding", "gzip, deflate"); | ||||
_cancelToken = CancellationToken.None; | _cancelToken = CancellationToken.None; | ||||
_errorDeserializer = new JsonSerializer(); | |||||
} | } | ||||
private void Dispose(bool disposing) | private void Dispose(bool disposing) | ||||
{ | { | ||||
@@ -71,13 +69,15 @@ namespace Discord.Net.Rest | |||||
return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | ||||
} | } | ||||
} | } | ||||
public async Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
public async Task<RestResponse> SendAsync(string method, string endpoint, ReadOnlyBuffer<byte> json, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
string uri = Path.Combine(_baseUrl, endpoint); | string uri = Path.Combine(_baseUrl, endpoint); | ||||
using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | ||||
{ | { | ||||
if (reason != null) restRequest.Headers.Add("X-Audit-Log-Reason", Uri.EscapeDataString(reason)); | if (reason != null) restRequest.Headers.Add("X-Audit-Log-Reason", Uri.EscapeDataString(reason)); | ||||
restRequest.Content = new StringContent(json, Encoding.UTF8, "application/json"); | |||||
var content = new ByteArrayContent(json.ToArray()); | |||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); | |||||
restRequest.Content = content; | |||||
return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | ||||
} | } | ||||
} | } | ||||
@@ -125,9 +125,9 @@ namespace Discord.Net.Rest | |||||
HttpResponseMessage response = await _client.SendAsync(request, cancelToken).ConfigureAwait(false); | HttpResponseMessage response = await _client.SendAsync(request, cancelToken).ConfigureAwait(false); | ||||
var headers = response.Headers.ToDictionary(x => x.Key, x => x.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase); | var headers = response.Headers.ToDictionary(x => x.Key, x => x.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase); | ||||
var stream = !headerOnly ? await response.Content.ReadAsStreamAsync().ConfigureAwait(false) : null; | |||||
var data = !headerOnly ? await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false) : null; | |||||
return new RestResponse(response.StatusCode, headers, stream); | |||||
return new RestResponse(response.StatusCode, headers, new ReadOnlyBuffer<byte>(data)); | |||||
} | } | ||||
private static readonly HttpMethod _patch = new HttpMethod("PATCH"); | private static readonly HttpMethod _patch = new HttpMethod("PATCH"); | ||||
@@ -63,7 +63,7 @@ namespace Discord.Net.Queue | |||||
finally { _tokenLock.Release(); } | finally { _tokenLock.Release(); } | ||||
} | } | ||||
public async Task<Stream> SendAsync(RestRequest request) | |||||
public async Task<ReadOnlyBuffer<byte>> SendAsync(RestRequest request) | |||||
{ | { | ||||
if (request.Options.CancelToken.CanBeCanceled) | if (request.Options.CancelToken.CanBeCanceled) | ||||
request.Options.CancelToken = CancellationTokenSource.CreateLinkedTokenSource(_requestCancelToken, request.Options.CancelToken).Token; | request.Options.CancelToken = CancellationTokenSource.CreateLinkedTokenSource(_requestCancelToken, request.Options.CancelToken).Token; | ||||
@@ -1,5 +1,6 @@ | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json.Linq; | |||||
using Discord.Rest; | |||||
using Discord.Serialization; | |||||
using Discord.Serialization.Json; | |||||
using System; | using System; | ||||
#if DEBUG_LIMITS | #if DEBUG_LIMITS | ||||
using System.Diagnostics; | using System.Diagnostics; | ||||
@@ -13,6 +14,16 @@ namespace Discord.Net.Queue | |||||
{ | { | ||||
internal class RequestBucket | internal class RequestBucket | ||||
{ | { | ||||
private class Error | |||||
{ | |||||
[ModelProperty("code")] | |||||
public int Code { get; set; } | |||||
[ModelProperty("message")] | |||||
public string Message { get; set; } | |||||
} | |||||
private static int _nextId = 0; | |||||
private readonly object _lock; | private readonly object _lock; | ||||
private readonly RequestQueue _queue; | private readonly RequestQueue _queue; | ||||
private int _semaphore; | private int _semaphore; | ||||
@@ -38,10 +49,9 @@ namespace Discord.Net.Queue | |||||
LastAttemptAt = DateTimeOffset.UtcNow; | LastAttemptAt = DateTimeOffset.UtcNow; | ||||
} | } | ||||
static int nextId = 0; | |||||
public async Task<Stream> SendAsync(RestRequest request) | |||||
public async Task<ReadOnlyBuffer<byte>> SendAsync(RestRequest request) | |||||
{ | { | ||||
int id = Interlocked.Increment(ref nextId); | |||||
int id = Interlocked.Increment(ref _nextId); | |||||
#if DEBUG_LIMITS | #if DEBUG_LIMITS | ||||
Debug.WriteLine($"[{id}] Start"); | Debug.WriteLine($"[{id}] Start"); | ||||
#endif | #endif | ||||
@@ -54,7 +64,7 @@ namespace Discord.Net.Queue | |||||
#if DEBUG_LIMITS | #if DEBUG_LIMITS | ||||
Debug.WriteLine($"[{id}] Sending..."); | Debug.WriteLine($"[{id}] Sending..."); | ||||
#endif | #endif | ||||
RateLimitInfo info = default(RateLimitInfo); | |||||
var info = default(RateLimitInfo); | |||||
try | try | ||||
{ | { | ||||
var response = await request.SendAsync().ConfigureAwait(false); | var response = await request.SendAsync().ConfigureAwait(false); | ||||
@@ -92,17 +102,13 @@ namespace Discord.Net.Queue | |||||
default: | default: | ||||
int? code = null; | int? code = null; | ||||
string reason = null; | string reason = null; | ||||
if (response.Stream != null) | |||||
if (response.Data.Length > 0) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
using (var reader = new StreamReader(response.Stream)) | |||||
using (var jsonReader = new JsonTextReader(reader)) | |||||
{ | |||||
var json = JToken.Load(jsonReader); | |||||
try { code = json.Value<int>("code"); } catch { }; | |||||
try { reason = json.Value<string>("message"); } catch { }; | |||||
} | |||||
var error = DiscordRestJsonSerializer.Global.Read<Error>(response.Data); | |||||
code = error.Code; | |||||
reason = error.Message; | |||||
} | } | ||||
catch { } | catch { } | ||||
} | } | ||||
@@ -114,7 +120,7 @@ namespace Discord.Net.Queue | |||||
#if DEBUG_LIMITS | #if DEBUG_LIMITS | ||||
Debug.WriteLine($"[{id}] Success"); | Debug.WriteLine($"[{id}] Success"); | ||||
#endif | #endif | ||||
return response.Stream; | |||||
return response.Data; | |||||
} | } | ||||
} | } | ||||
//catch (HttpException) { throw; } //Pass through | //catch (HttpException) { throw; } //Pass through | ||||
@@ -231,7 +237,7 @@ namespace Discord.Net.Queue | |||||
#endif | #endif | ||||
} | } | ||||
var now = DateTimeUtils.ToUnixSeconds(DateTimeOffset.UtcNow); | |||||
long now = DateTimeUtils.ToUnixSeconds(DateTimeOffset.UtcNow); | |||||
DateTimeOffset? resetTick = null; | DateTimeOffset? resetTick = null; | ||||
//Using X-RateLimit-Remaining causes a race condition | //Using X-RateLimit-Remaining causes a race condition | ||||
@@ -1,21 +1,22 @@ | |||||
using Discord.Net.Rest; | using Discord.Net.Rest; | ||||
using System; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.Net.Queue | namespace Discord.Net.Queue | ||||
{ | { | ||||
public class JsonRestRequest : RestRequest | public class JsonRestRequest : RestRequest | ||||
{ | { | ||||
public string Json { get; } | |||||
public ReadOnlyBuffer<byte> Payload { get; } | |||||
public JsonRestRequest(IRestClient client, string method, string endpoint, string json, RequestOptions options) | |||||
public JsonRestRequest(IRestClient client, string method, string endpoint, ReadOnlyBuffer<byte> payload, RequestOptions options) | |||||
: base(client, method, endpoint, options) | : base(client, method, endpoint, options) | ||||
{ | { | ||||
Json = json; | |||||
Payload = payload; | |||||
} | } | ||||
public override async Task<RestResponse> SendAsync() | public override async Task<RestResponse> SendAsync() | ||||
{ | { | ||||
return await Client.SendAsync(Method, Endpoint, Json, Options.CancelToken, Options.HeaderOnly, Options.AuditLogReason).ConfigureAwait(false); | |||||
return await Client.SendAsync(Method, Endpoint, Payload, Options.CancelToken, Options.HeaderOnly, Options.AuditLogReason).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -10,14 +10,14 @@ namespace Discord.Net.Queue | |||||
{ | { | ||||
public IWebSocketClient Client { get; } | public IWebSocketClient Client { get; } | ||||
public string BucketId { get; } | public string BucketId { get; } | ||||
public byte[] Data { get; } | |||||
public ReadOnlyBuffer<byte> Data { get; } | |||||
public bool IsText { get; } | public bool IsText { get; } | ||||
public DateTimeOffset? TimeoutAt { get; } | public DateTimeOffset? TimeoutAt { get; } | ||||
public TaskCompletionSource<Stream> Promise { get; } | public TaskCompletionSource<Stream> Promise { get; } | ||||
public RequestOptions Options { get; } | public RequestOptions Options { get; } | ||||
public CancellationToken CancelToken { get; internal set; } | public CancellationToken CancelToken { get; internal set; } | ||||
public WebSocketRequest(IWebSocketClient client, string bucketId, byte[] data, bool isText, RequestOptions options) | |||||
public WebSocketRequest(IWebSocketClient client, string bucketId, ReadOnlyBuffer<byte> data, bool isText, RequestOptions options) | |||||
{ | { | ||||
Preconditions.NotNull(options, nameof(options)); | Preconditions.NotNull(options, nameof(options)); | ||||
@@ -32,7 +32,7 @@ namespace Discord.Net.Queue | |||||
public async Task SendAsync() | public async Task SendAsync() | ||||
{ | { | ||||
await Client.SendAsync(Data, 0, Data.Length, IsText).ConfigureAwait(false); | |||||
await Client.SendAsync(Data, IsText).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } |