Compare commits

...

42 Commits

Author SHA1 Message Date
  RogueException b6b0a4dbbd Updated RPC and Webhooks to use the new serializer events 7 years ago
  RogueException ebcdd14fc6 Support serializing streams where CanSeek is false 7 years ago
  RogueException d2c4d81317 Added support for most escape chars 7 years ago
  RogueException 6663a5754c Added StringEnum attribute to EmbedType 7 years ago
  RogueException 1e68b4a6fd Added logging for deserialization errors and unknown properties 7 years ago
  RogueException a4dbef6725 Added support for escapable strings 7 years ago
  RogueException 33861089df Scan base types when searching for serializable props 7 years ago
  RogueException f6c6dbbcad Fixed UserStatus model 7 years ago
  RogueException 10afbb155a Moved StringEnum attribute to enum def 7 years ago
  RogueException 5005ddf98a Added Pool utility class 7 years ago
  RogueException d7fbf9fa20 Added support for strings containing escapes 7 years ago
  RogueException 2381de6bd7 Fixed several serialization errors, added dictionary and array support 7 years ago
  RogueException 016b7fa550 Added support for property selectors and numeric enums 7 years ago
  RogueException 65a2c1e1fd Made DiscordJsonSerializer public 7 years ago
  RogueException e0ce1813a2 Cleaned up Serializers, removed SerializationFormat 7 years ago
  RogueException 894efcca0a Added enum serialization 7 years ago
  RogueException eea11ef8d2 Added image serializer 7 years ago
  RogueException d00aef8982 Replace invalid span usage. 7 years ago
  RogueException ebf12e351d Greatly reduce allocations for float/double/decimal 7 years ago
  RogueException a3e404d8f4 Added serialization support for Utf8String 7 years ago
  RogueException 0bea893076 Improved DateTime(Offset) deserialization 7 years ago
  RogueException 91b4fb3272 Don't allocate strings for property key lookups 7 years ago
  RogueException 9027bcad0c Fixed List serialization 7 years ago
  RogueException d908e01e0e Temp removed char serializer 7 years ago
  RogueException 81f35a6082 Support strings when parsing numbers 7 years ago
  RogueException a1c17856b9 Added serialization support for submodels 7 years ago
  RogueException fed2e94517 Added ExcludeNull support 7 years ago
  RogueException b0147a9126 Added Guid serialization support 7 years ago
  RogueException 1f44306b2e Cleaned csprojs 7 years ago
  RogueException 99d3283d25 Isolated new serialization logic, decoupled from json. 7 years ago
  RogueException 7c25415d32 Removed unused buffers 7 years ago
  RogueException 501c76b2bd Added experimental json serializer 7 years ago
  RogueException c83b1bd321 Abstracted serialization 7 years ago
  RogueException 5714a50b5b Lets try this again 7 years ago
  RogueException c1ad858f9b Avoid GCHandle.IsAllocated 7 years ago
  RogueException 805fa00df0 Pin audio buffers at stream creation 7 years ago
  RogueException f4866e35ce Fix deserialization error from extra data in decompress buffer 7 years ago
  RogueException c56354ff8c Automatically recycle RTPFrame in InputStream.ReadAsync 8 years ago
  RogueException 9224fae4cd Fixed compressed message handling 8 years ago
  RogueException 597092cdaa Fix styling 8 years ago
  RogueException f51e86e736 Reduce voice buffer allocations, add frame recycling 8 years ago
  RogueException 7e62d78160 Bumped version to 1.1.0-alpha 8 years ago
100 changed files with 599 additions and 1010 deletions
Unified View
  1. +22
    -4
      Discord.Net.sln
  2. +3
    -2
      Discord.Net.targets
  3. +3
    -3
      src/Discord.Net.Commands/CommandService.cs
  4. +3
    -0
      src/Discord.Net.Core/Audio/IAudioClient.cs
  5. +1
    -1
      src/Discord.Net.Core/Audio/RTPFrame.cs
  6. +7
    -2
      src/Discord.Net.Core/Discord.Net.Core.csproj
  7. +6
    -1
      src/Discord.Net.Core/Entities/Guilds/PermissionTarget.cs
  8. +6
    -2
      src/Discord.Net.Core/Entities/Image.cs
  9. +11
    -8
      src/Discord.Net.Core/Entities/Messages/EmbedType.cs
  10. +3
    -1
      src/Discord.Net.Core/Entities/Permissions/Overwrite.cs
  11. +10
    -1
      src/Discord.Net.Core/Entities/Users/UserStatus.cs
  12. +2
    -2
      src/Discord.Net.Core/Format.cs
  13. +2
    -1
      src/Discord.Net.Core/Net/Rest/IRestClient.cs
  14. +5
    -5
      src/Discord.Net.Core/Net/Rest/RestResponse.cs
  15. +2
    -3
      src/Discord.Net.Core/Net/WebSockets/IWebSocketClient.cs
  16. +13
    -7
      src/Discord.Net.Providers.WS4Net/WS4NetClient.cs
  17. +8
    -8
      src/Discord.Net.Rest/API/Common/Application.cs
  18. +8
    -8
      src/Discord.Net.Rest/API/Common/Attachment.cs
  19. +3
    -3
      src/Discord.Net.Rest/API/Common/Ban.cs
  20. +14
    -14
      src/Discord.Net.Rest/API/Common/Channel.cs
  21. +6
    -6
      src/Discord.Net.Rest/API/Common/Connection.cs
  22. +14
    -15
      src/Discord.Net.Rest/API/Common/Embed.cs
  23. +5
    -5
      src/Discord.Net.Rest/API/Common/EmbedAuthor.cs
  24. +4
    -4
      src/Discord.Net.Rest/API/Common/EmbedField.cs
  25. +4
    -4
      src/Discord.Net.Rest/API/Common/EmbedFooter.cs
  26. +5
    -5
      src/Discord.Net.Rest/API/Common/EmbedImage.cs
  27. +3
    -3
      src/Discord.Net.Rest/API/Common/EmbedProvider.cs
  28. +5
    -5
      src/Discord.Net.Rest/API/Common/EmbedThumbnail.cs
  29. +4
    -4
      src/Discord.Net.Rest/API/Common/EmbedVideo.cs
  30. +6
    -6
      src/Discord.Net.Rest/API/Common/Emoji.cs
  31. +4
    -12
      src/Discord.Net.Rest/API/Common/Game.cs
  32. +18
    -18
      src/Discord.Net.Rest/API/Common/Guild.cs
  33. +3
    -3
      src/Discord.Net.Rest/API/Common/GuildEmbed.cs
  34. +7
    -7
      src/Discord.Net.Rest/API/Common/GuildMember.cs
  35. +12
    -12
      src/Discord.Net.Rest/API/Common/Integration.cs
  36. +3
    -3
      src/Discord.Net.Rest/API/Common/IntegrationAccount.cs
  37. +4
    -4
      src/Discord.Net.Rest/API/Common/Invite.cs
  38. +4
    -4
      src/Discord.Net.Rest/API/Common/InviteChannel.cs
  39. +4
    -4
      src/Discord.Net.Rest/API/Common/InviteGuild.cs
  40. +8
    -8
      src/Discord.Net.Rest/API/Common/InviteMetadata.cs
  41. +17
    -17
      src/Discord.Net.Rest/API/Common/Message.cs
  42. +5
    -5
      src/Discord.Net.Rest/API/Common/Overwrite.cs
  43. +7
    -7
      src/Discord.Net.Rest/API/Common/Presence.cs
  44. +4
    -4
      src/Discord.Net.Rest/API/Common/Reaction.cs
  45. +4
    -4
      src/Discord.Net.Rest/API/Common/ReadState.cs
  46. +4
    -4
      src/Discord.Net.Rest/API/Common/Relationship.cs
  47. +9
    -9
      src/Discord.Net.Rest/API/Common/Role.cs
  48. +9
    -9
      src/Discord.Net.Rest/API/Common/User.cs
  49. +6
    -6
      src/Discord.Net.Rest/API/Common/UserGuild.cs
  50. +7
    -7
      src/Discord.Net.Rest/API/Common/VoiceRegion.cs
  51. +10
    -10
      src/Discord.Net.Rest/API/Common/VoiceState.cs
  52. +4
    -1
      src/Discord.Net.Rest/API/Image.cs
  53. +5
    -6
      src/Discord.Net.Rest/API/Rest/CreateChannelInviteParams.cs
  54. +2
    -3
      src/Discord.Net.Rest/API/Rest/CreateDMChannelParams.cs
  55. +4
    -5
      src/Discord.Net.Rest/API/Rest/CreateGuildChannelParams.cs
  56. +3
    -4
      src/Discord.Net.Rest/API/Rest/CreateGuildIntegrationParams.cs
  57. +4
    -5
      src/Discord.Net.Rest/API/Rest/CreateGuildParams.cs
  58. +5
    -6
      src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs
  59. +7
    -8
      src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs
  60. +2
    -3
      src/Discord.Net.Rest/API/Rest/DeleteMessagesParams.cs
  61. +3
    -3
      src/Discord.Net.Rest/API/Rest/GetBotGatewayResponse.cs
  62. +2
    -2
      src/Discord.Net.Rest/API/Rest/GetGatewayResponse.cs
  63. +2
    -2
      src/Discord.Net.Rest/API/Rest/GetGuildPruneCountResponse.cs
  64. +2
    -3
      src/Discord.Net.Rest/API/Rest/GuildPruneParams.cs
  65. +4
    -5
      src/Discord.Net.Rest/API/Rest/ModifyChannelPermissionsParams.cs
  66. +2
    -3
      src/Discord.Net.Rest/API/Rest/ModifyCurrentUserNickParams.cs
  67. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyCurrentUserParams.cs
  68. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyGuildChannelParams.cs
  69. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyGuildChannelsParams.cs
  70. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyGuildEmbedParams.cs
  71. +4
    -5
      src/Discord.Net.Rest/API/Rest/ModifyGuildIntegrationParams.cs
  72. +6
    -7
      src/Discord.Net.Rest/API/Rest/ModifyGuildMemberParams.cs
  73. +11
    -12
      src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
  74. +6
    -7
      src/Discord.Net.Rest/API/Rest/ModifyGuildRoleParams.cs
  75. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyGuildRolesParams.cs
  76. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyMessageParams.cs
  77. +2
    -3
      src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs
  78. +3
    -4
      src/Discord.Net.Rest/API/Rest/ModifyVoiceChannelParams.cs
  79. +6
    -4
      src/Discord.Net.Rest/BaseDiscordClient.cs
  80. +9
    -0
      src/Discord.Net.Rest/Discord.Net.Rest.csproj
  81. +61
    -51
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  82. +20
    -4
      src/Discord.Net.Rest/DiscordRestClient.cs
  83. +1
    -1
      src/Discord.Net.Rest/Extensions/EntityExtensions.cs
  84. +25
    -0
      src/Discord.Net.Rest/Extensions/StreamExtensions.cs
  85. +0
    -59
      src/Discord.Net.Rest/Net/Converters/ArrayConverter.cs
  86. +0
    -102
      src/Discord.Net.Rest/Net/Converters/DiscordContractResolver.cs
  87. +0
    -36
      src/Discord.Net.Rest/Net/Converters/ImageConverter.cs
  88. +0
    -50
      src/Discord.Net.Rest/Net/Converters/NullableConverter.cs
  89. +0
    -38
      src/Discord.Net.Rest/Net/Converters/OptionalConverter.cs
  90. +0
    -42
      src/Discord.Net.Rest/Net/Converters/PermissionTargetConverter.cs
  91. +0
    -27
      src/Discord.Net.Rest/Net/Converters/StringEntityConverter.cs
  92. +0
    -25
      src/Discord.Net.Rest/Net/Converters/UInt64Converter.cs
  93. +0
    -28
      src/Discord.Net.Rest/Net/Converters/UInt64EntityConverter.cs
  94. +0
    -42
      src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs
  95. +0
    -58
      src/Discord.Net.Rest/Net/Converters/UserStatusConverter.cs
  96. +8
    -8
      src/Discord.Net.Rest/Net/DefaultRestClient.cs
  97. +1
    -1
      src/Discord.Net.Rest/Net/Queue/RequestQueue.cs
  98. +22
    -16
      src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
  99. +5
    -4
      src/Discord.Net.Rest/Net/Queue/Requests/JsonRestRequest.cs
  100. +3
    -3
      src/Discord.Net.Rest/Net/Queue/Requests/WebSocketRequest.cs

+ 22
- 4
Discord.Net.sln View File

@@ -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

+ 3
- 2
Discord.Net.targets View File

@@ -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>


+ 3
- 3
src/Discord.Net.Commands/CommandService.cs View File

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




+ 3
- 0
src/Discord.Net.Core/Audio/IAudioClient.cs View File

@@ -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);
} }
} }

+ 1
- 1
src/Discord.Net.Core/Audio/RTPFrame.cs View File

@@ -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
- 2
src/Discord.Net.Core/Discord.Net.Core.csproj View File

@@ -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>

+ 6
- 1
src/Discord.Net.Core/Entities/Guilds/PermissionTarget.cs View File

@@ -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
} }
} }

+ 6
- 2
src/Discord.Net.Core/Entities/Image.cs View File

@@ -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
} }


+ 11
- 8
src/Discord.Net.Core/Entities/Messages/EmbedType.cs View File

@@ -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
} }
} }

+ 3
- 1
src/Discord.Net.Core/Entities/Permissions/Overwrite.cs View File

@@ -1,4 +1,6 @@
namespace Discord
using Discord.Serialization;

namespace Discord
{ {
public struct Overwrite public struct Overwrite
{ {


+ 10
- 1
src/Discord.Net.Core/Entities/Users/UserStatus.cs View File

@@ -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,
} }
} }

+ 2
- 2
src/Discord.Net.Core/Format.cs View File

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


+ 2
- 1
src/Discord.Net.Core/Net/Rest/IRestClient.cs View File

@@ -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);
} }
} }

+ 5
- 5
src/Discord.Net.Core/Net/Rest/RestResponse.cs View File

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

+ 2
- 3
src/Discord.Net.Core/Net/WebSockets/IWebSocketClient.cs View File

@@ -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);
} }
} }

+ 13
- 7
src/Discord.Net.Providers.WS4Net/WS4NetClient.cs View File

@@ -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)
{ {


+ 8
- 8
src/Discord.Net.Rest/API/Common/Application.cs View File

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

+ 8
- 8
src/Discord.Net.Rest/API/Common/Attachment.cs View File

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

+ 3
- 3
src/Discord.Net.Rest/API/Common/Ban.cs View File

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

+ 14
- 14
src/Discord.Net.Rest/API/Common/Channel.cs View File

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

+ 6
- 6
src/Discord.Net.Rest/API/Common/Connection.cs View File

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

+ 14
- 15
src/Discord.Net.Rest/API/Common/Embed.cs View File

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

+ 5
- 5
src/Discord.Net.Rest/API/Common/EmbedAuthor.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/EmbedField.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/EmbedFooter.cs View File

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

+ 5
- 5
src/Discord.Net.Rest/API/Common/EmbedImage.cs View File

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

+ 3
- 3
src/Discord.Net.Rest/API/Common/EmbedProvider.cs View File

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

+ 5
- 5
src/Discord.Net.Rest/API/Common/EmbedThumbnail.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/EmbedVideo.cs View File

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

+ 6
- 6
src/Discord.Net.Rest/API/Common/Emoji.cs View File

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

+ 4
- 12
src/Discord.Net.Rest/API/Common/Game.cs View File

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

+ 18
- 18
src/Discord.Net.Rest/API/Common/Guild.cs View File

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

+ 3
- 3
src/Discord.Net.Rest/API/Common/GuildEmbed.cs View File

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

+ 7
- 7
src/Discord.Net.Rest/API/Common/GuildMember.cs View File

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

+ 12
- 12
src/Discord.Net.Rest/API/Common/Integration.cs View File

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

+ 3
- 3
src/Discord.Net.Rest/API/Common/IntegrationAccount.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/Invite.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/InviteChannel.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/InviteGuild.cs View File

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

+ 8
- 8
src/Discord.Net.Rest/API/Common/InviteMetadata.cs View File

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

+ 17
- 17
src/Discord.Net.Rest/API/Common/Message.cs View File

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

+ 5
- 5
src/Discord.Net.Rest/API/Common/Overwrite.cs View File

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

+ 7
- 7
src/Discord.Net.Rest/API/Common/Presence.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/Reaction.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/ReadState.cs View File

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

+ 4
- 4
src/Discord.Net.Rest/API/Common/Relationship.cs View File

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

+ 9
- 9
src/Discord.Net.Rest/API/Common/Role.cs View File

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

+ 9
- 9
src/Discord.Net.Rest/API/Common/User.cs View File

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

+ 6
- 6
src/Discord.Net.Rest/API/Common/UserGuild.cs View File

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

+ 7
- 7
src/Discord.Net.Rest/API/Common/VoiceRegion.cs View File

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

+ 10
- 10
src/Discord.Net.Rest/API/Common/VoiceState.cs View File

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

+ 4
- 1
src/Discord.Net.Rest/API/Image.cs View File

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


+ 5
- 6
src/Discord.Net.Rest/API/Rest/CreateChannelInviteParams.cs View File

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

+ 2
- 3
src/Discord.Net.Rest/API/Rest/CreateDMChannelParams.cs View File

@@ -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)


+ 4
- 5
src/Discord.Net.Rest/API/Rest/CreateGuildChannelParams.cs View File

@@ -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)


+ 3
- 4
src/Discord.Net.Rest/API/Rest/CreateGuildIntegrationParams.cs View File

@@ -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)


+ 4
- 5
src/Discord.Net.Rest/API/Rest/CreateGuildParams.cs View File

@@ -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)


+ 5
- 6
src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs View File

@@ -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)


+ 7
- 8
src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs View File

@@ -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)


+ 2
- 3
src/Discord.Net.Rest/API/Rest/DeleteMessagesParams.cs View File

@@ -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)


+ 3
- 3
src/Discord.Net.Rest/API/Rest/GetBotGatewayResponse.cs View File

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

+ 2
- 2
src/Discord.Net.Rest/API/Rest/GetGatewayResponse.cs View File

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

+ 2
- 2
src/Discord.Net.Rest/API/Rest/GetGuildPruneCountResponse.cs View File

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

+ 2
- 3
src/Discord.Net.Rest/API/Rest/GuildPruneParams.cs View File

@@ -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)


+ 4
- 5
src/Discord.Net.Rest/API/Rest/ModifyChannelPermissionsParams.cs View File

@@ -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)


+ 2
- 3
src/Discord.Net.Rest/API/Rest/ModifyCurrentUserNickParams.cs View File

@@ -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)


+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyCurrentUserParams.cs View File

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

+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyGuildChannelParams.cs View File

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

+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyGuildChannelsParams.cs View File

@@ -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)


+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyGuildEmbedParams.cs View File

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

+ 4
- 5
src/Discord.Net.Rest/API/Rest/ModifyGuildIntegrationParams.cs View File

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

+ 6
- 7
src/Discord.Net.Rest/API/Rest/ModifyGuildMemberParams.cs View File

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

+ 11
- 12
src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs View File

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

+ 6
- 7
src/Discord.Net.Rest/API/Rest/ModifyGuildRoleParams.cs View File

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

+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyGuildRolesParams.cs View File

@@ -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)


+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyMessageParams.cs View File

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

+ 2
- 3
src/Discord.Net.Rest/API/Rest/ModifyTextChannelParams.cs View File

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

+ 3
- 4
src/Discord.Net.Rest/API/Rest/ModifyVoiceChannelParams.cs View File

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

+ 6
- 4
src/Discord.Net.Rest/BaseDiscordClient.cs View File

@@ -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)


+ 9
- 0
src/Discord.Net.Rest/Discord.Net.Rest.csproj View File

@@ -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 -->


+ 61
- 51
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -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


+ 20
- 4
src/Discord.Net.Rest/DiscordRestClient.cs View File

@@ -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)


+ 1
- 1
src/Discord.Net.Rest/Extensions/EntityExtensions.cs View File

@@ -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)


+ 25
- 0
src/Discord.Net.Rest/Extensions/StreamExtensions.cs View File

@@ -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);
}
}

+ 0
- 59
src/Discord.Net.Rest/Net/Converters/ArrayConverter.cs View File

@@ -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();
}
}
}

+ 0
- 102
src/Discord.Net.Rest/Net/Converters/DiscordContractResolver.cs View File

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

+ 0
- 36
src/Discord.Net.Rest/Net/Converters/ImageConverter.cs View File

@@ -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);
}
}
}

+ 0
- 50
src/Discord.Net.Rest/Net/Converters/NullableConverter.cs View File

@@ -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));
}
}
}
}

+ 0
- 38
src/Discord.Net.Rest/Net/Converters/OptionalConverter.cs View File

@@ -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));
}
}
}

+ 0
- 42
src/Discord.Net.Rest/Net/Converters/PermissionTargetConverter.cs View File

@@ -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");
}
}
}
}

+ 0
- 27
src/Discord.Net.Rest/Net/Converters/StringEntityConverter.cs View File

@@ -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();
}
}
}

+ 0
- 25
src/Discord.Net.Rest/Net/Converters/UInt64Converter.cs View File

@@ -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));
}
}
}

+ 0
- 28
src/Discord.Net.Rest/Net/Converters/UInt64EntityConverter.cs View File

@@ -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();
}
}
}

+ 0
- 42
src/Discord.Net.Rest/Net/Converters/UInt64EntityOrIdConverter.cs View File

@@ -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();
}
}
}

+ 0
- 58
src/Discord.Net.Rest/Net/Converters/UserStatusConverter.cs View File

@@ -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");
}
}
}
}

+ 8
- 8
src/Discord.Net.Rest/Net/DefaultRestClient.cs View File

@@ -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");


+ 1
- 1
src/Discord.Net.Rest/Net/Queue/RequestQueue.cs View File

@@ -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;


+ 22
- 16
src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs View File

@@ -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


+ 5
- 4
src/Discord.Net.Rest/Net/Queue/Requests/JsonRestRequest.cs View File

@@ -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);
} }
} }
} }

+ 3
- 3
src/Discord.Net.Rest/Net/Queue/Requests/WebSocketRequest.cs View File

@@ -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);
} }
} }
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save