Browse Source

Starting reorganization - grouped all API serialization definitions together, moved Audio to Interop and grouped Net classes together.

tags/docs-0.9
RogueException 9 years ago
parent
commit
a0b1237d33
65 changed files with 1258 additions and 1246 deletions
  1. +2
    -2
      src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs
  2. +92
    -77
      src/Discord.Net.Net45/Discord.Net.csproj
  3. BIN
      src/Discord.Net.Net45/lib/libopus.so
  4. BIN
      src/Discord.Net.Net45/lib/libsodium.dll
  5. BIN
      src/Discord.Net.Net45/lib/opus.dll
  6. +29
    -0
      src/Discord.Net/API/Auth.cs
  7. +6
    -0
      src/Discord.Net/API/Bans.cs
  8. +100
    -0
      src/Discord.Net/API/Channels.cs
  9. +0
    -318
      src/Discord.Net/API/Common.cs
  10. +3
    -2
      src/Discord.Net/API/Endpoints.cs
  11. +59
    -0
      src/Discord.Net/API/Invites.cs
  12. +33
    -0
      src/Discord.Net/API/Maintenance.cs
  13. +88
    -0
      src/Discord.Net/API/Members.cs
  14. +133
    -0
      src/Discord.Net/API/Messages.cs
  15. +21
    -0
      src/Discord.Net/API/Permissions.cs
  16. +33
    -0
      src/Discord.Net/API/Presence.cs
  17. +0
    -178
      src/Discord.Net/API/Requests.cs
  18. +0
    -106
      src/Discord.Net/API/Responses.cs
  19. +0
    -67
      src/Discord.Net/API/RestClient.BuiltIn.cs
  20. +87
    -0
      src/Discord.Net/API/Roles.cs
  21. +80
    -0
      src/Discord.Net/API/Servers.cs
  22. +47
    -0
      src/Discord.Net/API/Users.cs
  23. +153
    -0
      src/Discord.Net/API/Voice.cs
  24. +112
    -0
      src/Discord.Net/API/WebSockets.cs
  25. +8
    -13
      src/Discord.Net/DiscordClient.API.cs
  26. +10
    -12
      src/Discord.Net/DiscordClient.cs
  27. +1
    -2
      src/Discord.Net/DiscordSimpleClient.cs
  28. +47
    -0
      src/Discord.Net/Helpers/Extensions.cs
  29. +0
    -0
      src/Discord.Net/Helpers/Format.cs
  30. +0
    -0
      src/Discord.Net/Helpers/Mention.cs
  31. +0
    -0
      src/Discord.Net/Helpers/Shared/CollectionHelper.cs
  32. +0
    -0
      src/Discord.Net/Helpers/Shared/TaskHelper.cs
  33. +0
    -56
      src/Discord.Net/Helpers/TaskExtensions.cs
  34. +0
    -0
      src/Discord.Net/Helpers/TimeoutException.cs
  35. +1
    -1
      src/Discord.Net/Interop/Opus.cs
  36. +1
    -1
      src/Discord.Net/Interop/OpusDecoder.cs
  37. +1
    -1
      src/Discord.Net/Interop/OpusEncoder.cs
  38. +1
    -1
      src/Discord.Net/Interop/Sodium.cs
  39. +5
    -4
      src/Discord.Net/Models/Channel.cs
  40. +5
    -4
      src/Discord.Net/Models/Invite.cs
  41. +7
    -6
      src/Discord.Net/Models/Member.cs
  42. +3
    -2
      src/Discord.Net/Models/Message.cs
  43. +3
    -2
      src/Discord.Net/Models/Role.cs
  44. +5
    -4
      src/Discord.Net/Models/Server.cs
  45. +10
    -6
      src/Discord.Net/Models/User.cs
  46. +3
    -2
      src/Discord.Net/Net/DataWebSocket.cs
  47. +1
    -1
      src/Discord.Net/Net/DataWebSockets.Events.cs
  48. +23
    -23
      src/Discord.Net/Net/DiscordAPIClient.cs
  49. +2
    -2
      src/Discord.Net/Net/HttpException.cs
  50. +1
    -1
      src/Discord.Net/Net/RestClient.Events.cs
  51. +9
    -9
      src/Discord.Net/Net/RestClient.SharpRest.cs
  52. +9
    -15
      src/Discord.Net/Net/RestClient.cs
  53. +11
    -3
      src/Discord.Net/Net/VoiceBuffer.cs
  54. +1
    -1
      src/Discord.Net/Net/VoiceWebSocket.Events.cs
  55. +7
    -6
      src/Discord.Net/Net/VoiceWebSocket.cs
  56. +2
    -4
      src/Discord.Net/Net/WebSocket.BuiltIn.cs.old
  57. +1
    -1
      src/Discord.Net/Net/WebSocket.Events.cs
  58. +1
    -1
      src/Discord.Net/Net/WebSocket.WebSocketSharp.cs
  59. +1
    -1
      src/Discord.Net/Net/WebSocket.cs
  60. +0
    -64
      src/Discord.Net/WebSockets/Data/Commands.cs
  61. +0
    -115
      src/Discord.Net/WebSockets/Data/Events.cs
  62. +0
    -59
      src/Discord.Net/WebSockets/Voice/Commands.cs
  63. +0
    -38
      src/Discord.Net/WebSockets/Voice/Events.cs
  64. +0
    -31
      src/Discord.Net/WebSockets/WebSocketMessage.cs
  65. +0
    -4
      src/Discord.Net/packages.config

+ 2
- 2
src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs View File

@@ -13,6 +13,6 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
[assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] [assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")]


[assembly: AssemblyVersion("0.7.3.0")]
[assembly: AssemblyFileVersion("0.7.3.0")]
[assembly: AssemblyVersion("0.8.0.0")]
[assembly: AssemblyFileVersion("0.8.0.0")]



+ 92
- 77
src/Discord.Net.Net45/Discord.Net.csproj View File

@@ -67,49 +67,50 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="lib\libopus.so" />
<Content Include="lib\libsodium.dll" />
<Content Include="lib\opus.dll" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Discord.Net\API\Common.cs">
<Link>API\Common.cs</Link>
<Compile Include="..\Discord.Net\API\Auth.cs">
<Link>API\Auth.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\API\Bans.cs">
<Link>API\Bans.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\API\Channels.cs">
<Link>API\Channels.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\Endpoints.cs"> <Compile Include="..\Discord.Net\API\Endpoints.cs">
<Link>API\Endpoints.cs</Link> <Link>API\Endpoints.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\HttpException.cs">
<Link>API\HttpException.cs</Link>
<Compile Include="..\Discord.Net\API\Invites.cs">
<Link>API\Invites.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\Requests.cs">
<Link>API\Requests.cs</Link>
<Compile Include="..\Discord.Net\API\Maintenance.cs">
<Link>API\Maintenance.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\Responses.cs">
<Link>API\Responses.cs</Link>
<Compile Include="..\Discord.Net\API\Members.cs">
<Link>API\Members.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\RestClient.BuiltIn.cs">
<Link>API\RestClient.BuiltIn.cs</Link>
<Compile Include="..\Discord.Net\API\Messages.cs">
<Link>API\Messages.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\RestClient.cs">
<Link>API\RestClient.cs</Link>
<Compile Include="..\Discord.Net\API\Permissions.cs">
<Link>API\Permissions.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\RestClient.Events.cs">
<Link>API\RestClient.Events.cs</Link>
<Compile Include="..\Discord.Net\API\Presence.cs">
<Link>API\Presence.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\API\RestClient.SharpRest.cs">
<Link>API\RestClient.SharpRest.cs</Link>
<Compile Include="..\Discord.Net\API\Roles.cs">
<Link>API\Roles.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Audio\Opus.cs">
<Link>Audio\Opus.cs</Link>
<Compile Include="..\Discord.Net\API\Servers.cs">
<Link>API\Servers.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Audio\OpusDecoder.cs">
<Link>Audio\OpusDecoder.cs</Link>
<Compile Include="..\Discord.Net\API\Users.cs">
<Link>API\Users.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Audio\OpusEncoder.cs">
<Link>Audio\OpusEncoder.cs</Link>
<Compile Include="..\Discord.Net\API\Voice.cs">
<Link>API\Voice.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Audio\Sodium.cs">
<Link>Audio\Sodium.cs</Link>
<Compile Include="..\Discord.Net\API\WebSockets.cs">
<Link>API\WebSockets.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Collections\AsyncCollection.cs"> <Compile Include="..\Discord.Net\Collections\AsyncCollection.cs">
<Link>Collections\AsyncCollection.cs</Link> <Link>Collections\AsyncCollection.cs</Link>
@@ -132,9 +133,6 @@
<Compile Include="..\Discord.Net\Collections\Users.cs"> <Compile Include="..\Discord.Net\Collections\Users.cs">
<Link>Collections\Users.cs</Link> <Link>Collections\Users.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\DiscordAPIClient.cs">
<Link>DiscordAPIClient.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordClient.API.cs"> <Compile Include="..\Discord.Net\DiscordClient.API.cs">
<Link>DiscordClient.API.cs</Link> <Link>DiscordClient.API.cs</Link>
</Compile> </Compile>
@@ -174,26 +172,41 @@
<Compile Include="..\Discord.Net\Enums\UserStatus.cs"> <Compile Include="..\Discord.Net\Enums\UserStatus.cs">
<Link>Enums\UserStatus.cs</Link> <Link>Enums\UserStatus.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Format.cs">
<Link>Format.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Helpers\CollectionHelper.cs">
<Link>Helpers\CollectionHelper.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Helpers\EpochTime.cs"> <Compile Include="..\Discord.Net\Helpers\EpochTime.cs">
<Link>Helpers\EpochTime.cs</Link> <Link>Helpers\EpochTime.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Helpers\Extensions.cs"> <Compile Include="..\Discord.Net\Helpers\Extensions.cs">
<Link>Helpers\Extensions.cs</Link> <Link>Helpers\Extensions.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Helpers\Format.cs">
<Link>Helpers\Format.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Helpers\Mention.cs">
<Link>Helpers\Mention.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Helpers\MessageCleaner.cs"> <Compile Include="..\Discord.Net\Helpers\MessageCleaner.cs">
<Link>Helpers\MessageCleaner.cs</Link> <Link>Helpers\MessageCleaner.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Helpers\TaskExtensions.cs">
<Link>Helpers\TaskExtensions.cs</Link>
<Compile Include="..\Discord.Net\Helpers\Shared\CollectionHelper.cs">
<Link>Helpers\Shared\CollectionHelper.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Helpers\Shared\TaskHelper.cs">
<Link>Helpers\Shared\TaskHelper.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Mention.cs">
<Link>Mention.cs</Link>
<Compile Include="..\Discord.Net\Helpers\TimeoutException.cs">
<Link>Helpers\TimeoutException.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Interop\Opus.cs">
<Link>Interop\Opus.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Interop\OpusDecoder.cs">
<Link>Interop\OpusDecoder.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Interop\OpusEncoder.cs">
<Link>Interop\OpusEncoder.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Interop\Sodium.cs">
<Link>Interop\Sodium.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Models\Channel.cs"> <Compile Include="..\Discord.Net\Models\Channel.cs">
<Link>Models\Channel.cs</Link> <Link>Models\Channel.cs</Link>
@@ -222,59 +235,61 @@
<Compile Include="..\Discord.Net\Models\User.cs"> <Compile Include="..\Discord.Net\Models\User.cs">
<Link>Models\User.cs</Link> <Link>Models\User.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\Shared\TaskHelper.cs">
<Link>Shared\TaskHelper.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\TimeoutException.cs">
<Link>TimeoutException.cs</Link>
<Compile Include="..\Discord.Net\Net\DataWebSocket.cs">
<Link>Net\DataWebSocket.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Data\Commands.cs">
<Link>WebSockets\Data\Commands.cs</Link>
<Compile Include="..\Discord.Net\Net\DataWebSockets.Events.cs">
<Link>Net\DataWebSockets.Events.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Data\DataWebSocket.cs">
<Link>WebSockets\Data\DataWebSocket.cs</Link>
<Compile Include="..\Discord.Net\Net\DiscordAPIClient.cs">
<Link>Net\DiscordAPIClient.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Data\DataWebSockets.Events.cs">
<Link>WebSockets\Data\DataWebSockets.Events.cs</Link>
<Compile Include="..\Discord.Net\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Data\Events.cs">
<Link>WebSockets\Data\Events.cs</Link>
<Compile Include="..\Discord.Net\Net\RestClient.cs">
<Link>Net\RestClient.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Voice\Commands.cs">
<Link>WebSockets\Voice\Commands.cs</Link>
<Compile Include="..\Discord.Net\Net\RestClient.Events.cs">
<Link>Net\RestClient.Events.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Voice\Events.cs">
<Link>WebSockets\Voice\Events.cs</Link>
<Compile Include="..\Discord.Net\Net\RestClient.SharpRest.cs">
<Link>Net\RestClient.SharpRest.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Voice\VoiceBuffer.cs">
<Link>WebSockets\Voice\VoiceBuffer.cs</Link>
<Compile Include="..\Discord.Net\Net\VoiceBuffer.cs">
<Link>Net\VoiceBuffer.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Voice\VoiceWebSocket.cs">
<Link>WebSockets\Voice\VoiceWebSocket.cs</Link>
<Compile Include="..\Discord.Net\Net\VoiceWebSocket.cs">
<Link>Net\VoiceWebSocket.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\Voice\VoiceWebSocket.Events.cs">
<Link>WebSockets\Voice\VoiceWebSocket.Events.cs</Link>
<Compile Include="..\Discord.Net\Net\VoiceWebSocket.Events.cs">
<Link>Net\VoiceWebSocket.Events.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocket.BuiltIn.cs">
<Link>WebSockets\WebSocket.BuiltIn.cs</Link>
<Compile Include="..\Discord.Net\Net\WebSocket.cs">
<Link>Net\WebSocket.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocket.cs">
<Link>WebSockets\WebSocket.cs</Link>
<Compile Include="..\Discord.Net\Net\WebSocket.Events.cs">
<Link>Net\WebSocket.Events.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocket.Events.cs">
<Link>WebSockets\WebSocket.Events.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocket.WebSocketSharp.cs">
<Link>WebSockets\WebSocket.WebSocketSharp.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\WebSockets\WebSocketMessage.cs">
<Link>WebSockets\WebSocketMessage.cs</Link>
<Compile Include="..\Discord.Net\Net\WebSocket.WebSocketSharp.cs">
<Link>Net\WebSocket.WebSocketSharp.cs</Link>
</Compile> </Compile>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\Discord.Net\lib\libopus.so">
<Link>lib\libopus.so</Link>
</None>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="..\Discord.Net\lib\libsodium.dll">
<Link>lib\libsodium.dll</Link>
</Content>
<Content Include="..\Discord.Net\lib\opus.dll">
<Link>lib\opus.dll</Link>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.


BIN
src/Discord.Net.Net45/lib/libopus.so View File


BIN
src/Discord.Net.Net45/lib/libsodium.dll View File


BIN
src/Discord.Net.Net45/lib/opus.dll View File


+ 29
- 0
src/Discord.Net/API/Auth.cs View File

@@ -0,0 +1,29 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;

namespace Discord.API
{
//Gateway
public class GatewayResponse
{
[JsonProperty("url")]
public string Url;
}

//Login
public sealed class LoginRequest
{
[JsonProperty("email")]
public string Email;
[JsonProperty("password")]
public string Password;
}
public sealed class LoginResponse
{
[JsonProperty("token")]
public string Token;
}
}

+ 6
- 0
src/Discord.Net/API/Bans.cs View File

@@ -0,0 +1,6 @@
namespace Discord.API
{
//Events
internal sealed class BanAddEvent : MemberReference { }
internal sealed class BanRemoveEvent : MemberReference { }
}

+ 100
- 0
src/Discord.Net/API/Channels.cs View File

@@ -0,0 +1,100 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;

namespace Discord.API
{
//Common
public class ChannelReference
{
[JsonProperty("id")]
public string Id;
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("name")]
public string Name;
[JsonProperty("type")]
public string Type;
}
public class ChannelInfo : ChannelReference
{
public sealed class PermissionOverwrite
{
[JsonProperty("type")]
public string Type;
[JsonProperty("id")]
public string Id;
[JsonProperty("deny")]
public uint Deny;
[JsonProperty("allow")]
public uint Allow;
}

[JsonProperty("last_message_id")]
public string LastMessageId;
[JsonProperty("is_private")]
public bool IsPrivate;
[JsonProperty("position")]
public int? Position;
[JsonProperty(PropertyName = "topic")]
public string Topic;
[JsonProperty("permission_overwrites")]
public PermissionOverwrite[] PermissionOverwrites;
[JsonProperty("recipient")]
public UserReference Recipient;
}

//Create
public class CreateChannelRequest
{
[JsonProperty("name")]
public string Name;
[JsonProperty("type")]
public string Type;
}
public class CreatePMChannelRequest
{
[JsonProperty("recipient_id")]
public string RecipientId;
}
public class CreateChannelResponse : ChannelInfo { }

//Edit
public class EditChannelRequest
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name;
[JsonProperty("topic", NullValueHandling = NullValueHandling.Ignore)]
public string Topic;
}
public class EditChannelResponse : ChannelInfo { }

//Destroy
public class DestroyChannelResponse : ChannelInfo { }

//Reorder
public class ReorderChannelsRequest : IEnumerable<ReorderChannelsRequest.Channel>
{
public sealed class Channel
{
[JsonProperty("id")]
public string Id;
[JsonProperty("position")]
public uint Position;
}
private IEnumerable<Channel> _channels;
public ReorderChannelsRequest(IEnumerable<Channel> channels) { _channels = channels; }

public IEnumerator<Channel> GetEnumerator() => _channels.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _channels.GetEnumerator();
}

//Events
internal sealed class ChannelCreateEvent : ChannelInfo { }
internal sealed class ChannelDeleteEvent : ChannelInfo { }
internal sealed class ChannelUpdateEvent : ChannelInfo { }
}

+ 0
- 318
src/Discord.Net/API/Common.cs View File

@@ -1,318 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;

namespace Discord.API
{
//User
public class UserReference
{
[JsonProperty("username")]
public string Username;
[JsonProperty("id")]
public string Id;
[JsonProperty("discriminator")]
public string Discriminator;
[JsonProperty("avatar")]
public string Avatar;
}
public class SelfUserInfo : UserReference
{
[JsonProperty("email")]
public string Email;
[JsonProperty("verified")]
public bool IsVerified;
}

//Members
public class MemberReference
{
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("guild_id")]
public string GuildId;

[JsonProperty("user")]
private UserReference _user;
public UserReference User
{
get { return _user; }
set
{
_user = value;
UserId = User.Id;
}
}
}
public class MemberInfo : MemberReference
{
[JsonProperty("joined_at")]
public DateTime? JoinedAt;
[JsonProperty("roles")]
public string[] Roles;
}
public class ExtendedMemberInfo : MemberInfo
{
[JsonProperty("mute")]
public bool? IsServerMuted;
[JsonProperty("deaf")]
public bool? IsServerDeafened;
}
public class PresenceMemberInfo : MemberReference
{
[JsonProperty("game_id")]
public string GameId;
[JsonProperty("status")]
public string Status;
}
public class VoiceMemberInfo : MemberReference
{
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("token")]
public string Token;

[JsonProperty("self_mute")]
public bool? IsSelfMuted;
[JsonProperty("self_deaf")]
public bool? IsSelfDeafened;
[JsonProperty("mute")]
public bool? IsServerMuted;
[JsonProperty("deaf")]
public bool? IsServerDeafened;
[JsonProperty("suppress")]
public bool? IsServerSuppressed;
}

//Channels
public class ChannelReference
{
[JsonProperty("id")]
public string Id;
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("name")]
public string Name;
[JsonProperty("type")]
public string Type;
}
public class ChannelInfo : ChannelReference
{
public sealed class PermissionOverwrite
{
[JsonProperty("type")]
public string Type;
[JsonProperty("id")]
public string Id;
[JsonProperty("deny")]
public uint Deny;
[JsonProperty("allow")]
public uint Allow;
}

[JsonProperty("last_message_id")]
public string LastMessageId;
[JsonProperty("is_private")]
public bool IsPrivate;
[JsonProperty("position")]
public int? Position;
[JsonProperty(PropertyName = "topic")]
public string Topic;
[JsonProperty("permission_overwrites")]
public PermissionOverwrite[] PermissionOverwrites;
[JsonProperty("recipient")]
public UserReference Recipient;
}

//Guilds (Servers)
public class GuildReference
{
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
}
public class GuildInfo : GuildReference
{
[JsonProperty("afk_channel_id")]
public string AFKChannelId;
[JsonProperty("afk_timeout")]
public int AFKTimeout;
[JsonProperty("embed_channel_id")]
public string EmbedChannelId;
[JsonProperty("embed_enabled")]
public bool EmbedEnabled;
[JsonProperty("icon")]
public string Icon;
[JsonProperty("joined_at")]
public DateTime? JoinedAt;
[JsonProperty("owner_id")]
public string OwnerId;
[JsonProperty("region")]
public string Region;
[JsonProperty("roles")]
public RoleInfo[] Roles;
}
public class ExtendedGuildInfo : GuildInfo
{
[JsonProperty("channels")]
public ChannelInfo[] Channels;
[JsonProperty("members")]
public ExtendedMemberInfo[] Members;
[JsonProperty("presences")]
public PresenceMemberInfo[] Presences;
[JsonProperty("voice_states")]
public VoiceMemberInfo[] VoiceStates;
[JsonProperty("unavailable")]
public bool Unavailable;
}

//Messages
public class MessageReference
{
[JsonProperty("id")]
public string Id;
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("message_id")]
public string MessageId { get { return Id; } set { Id = value; } }
}
public class Message : MessageReference
{
public sealed class Attachment
{
[JsonProperty("id")]
public string Id;
[JsonProperty("url")]
public string Url;
[JsonProperty("proxy_url")]
public string ProxyUrl;
[JsonProperty("size")]
public int Size;
[JsonProperty("filename")]
public string Filename;
[JsonProperty("width")]
public int Width;
[JsonProperty("height")]
public int Height;
}
public sealed class Embed
{
public sealed class Reference
{
[JsonProperty("url")]
public string Url;
[JsonProperty("name")]
public string Name;
}
public sealed class ThumbnailInfo
{
[JsonProperty("url")]
public string Url;
[JsonProperty("proxy_url")]
public string ProxyUrl;
[JsonProperty("width")]
public int Width;
[JsonProperty("height")]
public int Height;
}

[JsonProperty("url")]
public string Url;
[JsonProperty("type")]
public string Type;
[JsonProperty("title")]
public string Title;
[JsonProperty("description")]
public string Description;
[JsonProperty("author")]
public Reference Author;
[JsonProperty("provider")]
public Reference Provider;
[JsonProperty("thumbnail")]
public ThumbnailInfo Thumbnail;
}

[JsonProperty("tts")]
public bool? IsTextToSpeech;
[JsonProperty("mention_everyone")]
public bool? IsMentioningEveryone;
[JsonProperty("timestamp")]
public DateTime? Timestamp;
[JsonProperty("edited_timestamp")]
public DateTime? EditedTimestamp;
[JsonProperty("mentions")]
public UserReference[] Mentions;
[JsonProperty("embeds")]
public Embed[] Embeds; //TODO: Parse this
[JsonProperty("attachments")]
public Attachment[] Attachments;
[JsonProperty("content")]
public string Content;
[JsonProperty("author")]
public UserReference Author;
[JsonProperty("nonce")]
public string Nonce;
}

//Roles
public class RoleReference
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("role_id")]
public string RoleId;
}
public class RoleInfo
{
[JsonProperty("permissions")]
public uint? Permissions;
[JsonProperty("name")]
public string Name;
[JsonProperty("position")]
public int? Position;
[JsonProperty("hoist")]
public bool? Hoist;
[JsonProperty("color")]
public uint? Color;
[JsonProperty("id")]
public string Id;
[JsonProperty("managed")]
public bool? Managed;
}

//Invites
public class Invite
{
[JsonProperty("inviter")]
public UserReference Inviter;
[JsonProperty("guild")]
public GuildReference Guild;
[JsonProperty("channel")]
public ChannelReference Channel;
[JsonProperty("code")]
public string Code;
[JsonProperty("xkcdpass")]
public string XkcdPass;
}
public class ExtendedInvite : Invite
{
[JsonProperty("max_age")]
public int ?MaxAge;
[JsonProperty("max_uses")]
public int? MaxUses;
[JsonProperty("revoked")]
public bool? IsRevoked;
[JsonProperty("temporary")]
public bool? IsTemporary;
[JsonProperty("uses")]
public int? Uses;
[JsonProperty("created_at")]
public DateTime? CreatedAt;
}
}

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

@@ -1,9 +1,10 @@
namespace Discord.API namespace Discord.API
{ {
internal static class Endpoints
public static class Endpoints
{ {
public const string BaseStatusApi = "https://status.discordapp.com/api/v2/"; public const string BaseStatusApi = "https://status.discordapp.com/api/v2/";
public const string BaseApi = "https://discordapp.com/api/"; public const string BaseApi = "https://discordapp.com/api/";

public const string Gateway = "gateway"; public const string Gateway = "gateway";


public const string Auth = "auth"; public const string Auth = "auth";
@@ -39,7 +40,7 @@
public const string Voice = "voice"; public const string Voice = "voice";
public const string VoiceRegions = "voice/regions"; public const string VoiceRegions = "voice/regions";
public const string VoiceIce = "voice/ice";
//public const string VoiceIce = "voice/ice";


public const string StatusActiveMaintenance = "scheduled-maintenances/active.json"; public const string StatusActiveMaintenance = "scheduled-maintenances/active.json";
public const string StatusUpcomingMaintenance = "scheduled-maintenances/upcoming.json"; public const string StatusUpcomingMaintenance = "scheduled-maintenances/upcoming.json";


+ 59
- 0
src/Discord.Net/API/Invites.cs View File

@@ -0,0 +1,59 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;

namespace Discord.API
{
//Common
public class InviteReference
{
[JsonProperty("inviter")]
public UserReference Inviter;
[JsonProperty("guild")]
public GuildReference Guild;
[JsonProperty("channel")]
public ChannelReference Channel;
[JsonProperty("code")]
public string Code;
[JsonProperty("xkcdpass")]
public string XkcdPass;
}
public class InviteInfo : InviteReference
{
[JsonProperty("max_age")]
public int? MaxAge;
[JsonProperty("max_uses")]
public int? MaxUses;
[JsonProperty("revoked")]
public bool? IsRevoked;
[JsonProperty("temporary")]
public bool? IsTemporary;
[JsonProperty("uses")]
public int? Uses;
[JsonProperty("created_at")]
public DateTime? CreatedAt;
}

//Create
public class CreateInviteRequest
{
[JsonProperty("max_age")]
public int MaxAge;
[JsonProperty("max_uses")]
public int MaxUses;
[JsonProperty("temporary")]
public bool IsTemporary;
[JsonProperty("xkcdpass")]
public bool WithXkcdPass;
}
public class CreateInviteResponse : InviteInfo { }

//Get
public class GetInviteResponse : InviteReference { }

//Accept
public class AcceptInviteResponse : InviteReference { }
}

+ 33
- 0
src/Discord.Net/API/Maintenance.cs View File

@@ -0,0 +1,33 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;

namespace Discord.API
{
public class GetIncidentsResponse
{
[JsonProperty("page")]
public PageData Page;
[JsonProperty("scheduled_maintenances")]
public MaintenanceData[] ScheduledMaintenances;

public sealed class PageData
{
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
[JsonProperty("url")]
public string Url;
[JsonProperty("updated-at")]
public DateTime? UpdatedAt;
}

public sealed class MaintenanceData
{
}
}
}

+ 88
- 0
src/Discord.Net/API/Members.cs View File

@@ -0,0 +1,88 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace Discord.API
{
//Common
public class MemberReference
{
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("guild_id")]
public string GuildId;

[JsonProperty("user")]
private UserReference _user;
public UserReference User
{
get { return _user; }
set
{
_user = value;
UserId = User.Id;
}
}
}
public class MemberInfo : MemberReference
{
[JsonProperty("joined_at")]
public DateTime? JoinedAt;
[JsonProperty("roles")]
public string[] Roles;
}
public class ExtendedMemberInfo : MemberInfo
{
[JsonProperty("mute")]
public bool? IsServerMuted;
[JsonProperty("deaf")]
public bool? IsServerDeafened;
}
public class PresenceInfo : MemberReference
{
[JsonProperty("game_id")]
public string GameId;
[JsonProperty("status")]
public string Status;
}
public class VoiceMemberInfo : MemberReference
{
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("token")]
public string Token;

[JsonProperty("self_mute")]
public bool? IsSelfMuted;
[JsonProperty("self_deaf")]
public bool? IsSelfDeafened;
[JsonProperty("mute")]
public bool? IsServerMuted;
[JsonProperty("deaf")]
public bool? IsServerDeafened;
[JsonProperty("suppress")]
public bool? IsServerSuppressed;
}

public class EditMemberRequest
{
[JsonProperty(PropertyName = "mute", NullValueHandling = NullValueHandling.Ignore)]
public bool? Mute;
[JsonProperty(PropertyName = "deaf", NullValueHandling = NullValueHandling.Ignore)]
public bool? Deaf;
[JsonProperty(PropertyName = "roles", NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<string> Roles;
}

//Events
internal sealed class MemberAddEvent : MemberInfo { }
internal sealed class MemberUpdateEvent : MemberInfo { }
internal sealed class MemberRemoveEvent : MemberInfo { }
internal sealed class MemberVoiceStateUpdateEvent : VoiceMemberInfo { }
}

+ 133
- 0
src/Discord.Net/API/Messages.cs View File

@@ -0,0 +1,133 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace Discord.API
{
//Common
public class MessageReference
{
[JsonProperty("id")]
public string Id;
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("message_id")]
public string MessageId { get { return Id; } set { Id = value; } }
}
public class MessageInfo : MessageReference
{
public sealed class Attachment
{
[JsonProperty("id")]
public string Id;
[JsonProperty("url")]
public string Url;
[JsonProperty("proxy_url")]
public string ProxyUrl;
[JsonProperty("size")]
public int Size;
[JsonProperty("filename")]
public string Filename;
[JsonProperty("width")]
public int Width;
[JsonProperty("height")]
public int Height;
}

public sealed class Embed
{
public sealed class Reference
{
[JsonProperty("url")]
public string Url;
[JsonProperty("name")]
public string Name;
}

public sealed class ThumbnailInfo
{
[JsonProperty("url")]
public string Url;
[JsonProperty("proxy_url")]
public string ProxyUrl;
[JsonProperty("width")]
public int Width;
[JsonProperty("height")]
public int Height;
}

[JsonProperty("url")]
public string Url;
[JsonProperty("type")]
public string Type;
[JsonProperty("title")]
public string Title;
[JsonProperty("description")]
public string Description;
[JsonProperty("author")]
public Reference Author;
[JsonProperty("provider")]
public Reference Provider;
[JsonProperty("thumbnail")]
public ThumbnailInfo Thumbnail;
}

[JsonProperty("tts")]
public bool? IsTextToSpeech;
[JsonProperty("mention_everyone")]
public bool? IsMentioningEveryone;
[JsonProperty("timestamp")]
public DateTime? Timestamp;
[JsonProperty("edited_timestamp")]
public DateTime? EditedTimestamp;
[JsonProperty("mentions")]
public UserReference[] Mentions;
[JsonProperty("embeds")]
public Embed[] Embeds; //TODO: Parse this
[JsonProperty("attachments")]
public Attachment[] Attachments;
[JsonProperty("content")]
public string Content;
[JsonProperty("author")]
public UserReference Author;
[JsonProperty("nonce")]
public string Nonce;
}

//Create
internal sealed class SendMessageRequest
{
[JsonProperty("content")]
public string Content;
[JsonProperty("mentions")]
public IEnumerable<string> Mentions;
[JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)]
public string Nonce;
[JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)]
public bool IsTTS;
}
public sealed class SendMessageResponse : MessageInfo { }

//Edit
internal sealed class EditMessageRequest
{
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
public string Content;
[JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<string> Mentions;
}
public sealed class EditMessageResponse : MessageInfo { }

//Get
public sealed class GetMessagesResponse : List<MessageInfo> { }

//Events
internal sealed class MessageCreateEvent : MessageInfo { }
internal sealed class MessageUpdateEvent : MessageInfo { }
internal sealed class MessageDeleteEvent : MessageReference { }
internal sealed class MessageAckEvent : MessageReference { }
}

+ 21
- 0
src/Discord.Net/API/Permissions.cs View File

@@ -0,0 +1,21 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;

namespace Discord.API
{
//Create/Edit
internal sealed class SetChannelPermissionsRequest
{
[JsonProperty("id")]
public string Id;
[JsonProperty("type")]
public string Type;
[JsonProperty("allow")]
public uint Allow;
[JsonProperty("deny")]
public uint Deny;
}
}

+ 33
- 0
src/Discord.Net/API/Presence.cs View File

@@ -0,0 +1,33 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;

namespace Discord.API
{
//Commands
internal sealed class UpdateStatusCommand : WebSocketMessage<UpdateStatusCommand.Data>
{
public UpdateStatusCommand() : base(3) { }
public class Data
{
[JsonProperty("idle_since")]
public ulong? IdleSince;
[JsonProperty("game_id")]
public int? GameId;
}
}

//Events
internal sealed class TypingStartEvent
{
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("timestamp")]
public int Timestamp;
}
internal sealed class PresenceUpdateEvent : PresenceInfo { }
}

+ 0
- 178
src/Discord.Net/API/Requests.cs View File

@@ -1,178 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Collections;

namespace Discord.API
{
//Auth
internal sealed class RegisterRequest
{
[JsonProperty("fingerprint")]
public string Fingerprint;
[JsonProperty("username")]
public string Username;
}
internal sealed class LoginRequest
{
[JsonProperty("email")]
public string Email;
[JsonProperty("password")]
public string Password;
}

//Channels
internal sealed class CreateChannelRequest
{
[JsonProperty("name")]
public string Name;
[JsonProperty("type")]
public string Type;
}
internal sealed class CreatePMChannelRequest
{
[JsonProperty("recipient_id")]
public string RecipientId;
}
internal sealed class EditChannelRequest
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name;
[JsonProperty("topic", NullValueHandling = NullValueHandling.Ignore)]
public string Topic;
}
internal sealed class ReorderChannelsRequest : IEnumerable<ReorderChannelsRequest.Channel>
{
public sealed class Channel
{
[JsonProperty("id")]
public string Id;
[JsonProperty("position")]
public uint Position;
}
private IEnumerable<Channel> _channels;
public ReorderChannelsRequest(IEnumerable<Channel> channels) { _channels = channels; }

public IEnumerator<Channel> GetEnumerator() =>_channels.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _channels.GetEnumerator();
}

//Invites
internal sealed class CreateInviteRequest
{
[JsonProperty("max_age")]
public int MaxAge;
[JsonProperty("max_uses")]
public int MaxUses;
[JsonProperty("temporary")]
public bool IsTemporary;
[JsonProperty("xkcdpass")]
public bool WithXkcdPass;
}

//Members
internal sealed class EditMemberRequest
{
[JsonProperty(PropertyName = "mute", NullValueHandling = NullValueHandling.Ignore)]
public bool? Mute;
[JsonProperty(PropertyName = "deaf", NullValueHandling = NullValueHandling.Ignore)]
public bool? Deaf;
[JsonProperty(PropertyName = "roles", NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<string> Roles;
}

//Messages
internal sealed class SendMessageRequest
{
[JsonProperty("content")]
public string Content;
[JsonProperty("mentions")]
public IEnumerable<string> Mentions;
[JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)]
public string Nonce;
[JsonProperty("tts", NullValueHandling = NullValueHandling.Ignore)]
public bool IsTTS;
}
internal sealed class EditMessageRequest
{
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
public string Content;
[JsonProperty("mentions", NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<string> Mentions;
}

//Permissions
internal sealed class SetChannelPermissionsRequest //Both creates and modifies
{
[JsonProperty("id")]
public string Id;
[JsonProperty("type")]
public string Type;
[JsonProperty("allow")]
public uint Allow;
[JsonProperty("deny")]
public uint Deny;
}

//Profile
internal sealed class EditProfileRequest
{
[JsonProperty(PropertyName = "password")]
public string CurrentPassword;
[JsonProperty(PropertyName = "email", NullValueHandling = NullValueHandling.Ignore)]
public string Email;
[JsonProperty(PropertyName = "new_password")]
public string Password;
[JsonProperty(PropertyName = "username", NullValueHandling = NullValueHandling.Ignore)]
public string Username;
[JsonProperty(PropertyName = "avatar", NullValueHandling = NullValueHandling.Ignore)]
public string Avatar;
}

//Roles
internal sealed class EditRoleRequest
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name;
[JsonProperty("permissions", NullValueHandling = NullValueHandling.Ignore)]
public uint? Permissions;
[JsonProperty("hoist", NullValueHandling = NullValueHandling.Ignore)]
public bool? Hoist;
[JsonProperty("color", NullValueHandling = NullValueHandling.Ignore)]
public uint? Color;
}
internal sealed class ReorderRolesRequest : IEnumerable<ReorderRolesRequest.Role>
{
public sealed class Role
{
[JsonProperty("id")]
public string Id;
[JsonProperty("position")]
public uint Position;
}
private IEnumerable<Role> _roles;
public ReorderRolesRequest(IEnumerable<Role> roles) { _roles = roles; }

public IEnumerator<Role> GetEnumerator() => _roles.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _roles.GetEnumerator();
}

//Servers
internal sealed class CreateServerRequest
{
[JsonProperty("name")]
public string Name;
[JsonProperty("region")]
public string Region;
}
internal sealed class EditServerRequest
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name;
[JsonProperty("region", NullValueHandling = NullValueHandling.Ignore)]
public string Region;
}
}

+ 0
- 106
src/Discord.Net/API/Responses.cs View File

@@ -1,106 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace Discord.API
{
//Auth
public sealed class GatewayResponse
{
[JsonProperty("url")]
public string Url;
}
public sealed class LoginResponse
{
[JsonProperty("token")]
public string Token;
}

//Channels
public sealed class CreateChannelResponse : ChannelInfo { }
public sealed class DestroyChannelResponse : ChannelInfo { }
public sealed class EditChannelResponse : ChannelInfo { }

//Invites
public sealed class CreateInviteResponse : ExtendedInvite { }
public sealed class GetInviteResponse : Invite { }
public sealed class AcceptInviteResponse : Invite { }

//Messages
public sealed class SendMessageResponse : Message { }
public sealed class EditMessageResponse : Message { }
public sealed class GetMessagesResponse : List<Message> { }

//Profile
public sealed class EditProfileResponse : SelfUserInfo { }

//Roles
public sealed class CreateRoleResponse : RoleInfo { }
public sealed class EditRoleResponse : RoleInfo { }
//Servers
public sealed class CreateServerResponse : GuildInfo { }
public sealed class DeleteServerResponse : GuildInfo { }
public sealed class EditServerResponse : GuildInfo { }

//Voice
public sealed class GetRegionsResponse : List<GetRegionsResponse.RegionData>
{
public sealed class RegionData
{
[JsonProperty("sample_hostname")]
public string Hostname;
[JsonProperty("sample_port")]
public int Port;
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
}
}
public sealed class GetIceResponse
{
[JsonProperty("ttl")]
public string TTL;
[JsonProperty("servers")]
public ServerData[] Servers;

public sealed class ServerData
{
[JsonProperty("url")]
public string URL;
[JsonProperty("username")]
public string Username;
[JsonProperty("credential")]
public string Credential;
}
}

public sealed class GetIncidentsResponse
{
[JsonProperty("page")]
public PageData Page;
[JsonProperty("scheduled_maintenances")]
public MaintenanceData[] ScheduledMaintenances;

public sealed class PageData
{
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
[JsonProperty("url")]
public string Url;
[JsonProperty("updated-at")]
public DateTime? UpdatedAt;
}

public sealed class MaintenanceData
{
}
}
}

+ 0
- 67
src/Discord.Net/API/RestClient.BuiltIn.cs View File

@@ -1,67 +0,0 @@
/*
using Discord.API;
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Discord.API
{
internal class BuiltInRestEngine : IRestEngine
{
private readonly HttpClient _client;

public BuiltInRestEngine(string userAgent, int timeout)
{
_client = new HttpClient(new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
UseCookies = false,
PreAuthenticate = false //We do auth ourselves
});
_client.DefaultRequestHeaders.Add("accept", "*\/*");
_client.DefaultRequestHeaders.Add("accept-encoding", "gzip,deflate");
_client.DefaultRequestHeaders.Add("user-agent", userAgent);
_client.Timeout = TimeSpan.FromMilliseconds(timeout);
}

public void SetToken(string token)
{
_client.DefaultRequestHeaders.Remove("authorization");
if (token != null)
_client.DefaultRequestHeaders.Add("authorization", token);
}

public async Task<string> Send(HttpMethod method, string path, string json, CancellationToken cancelToken)
{
using (var request = new HttpRequestMessage(method, Endpoints.BaseApi + path))
{
if (json != null)
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
return await Send(request, cancelToken);
}
}
public async Task<string> SendFile(HttpMethod method, string path, string filePath, CancellationToken cancelToken)
{
using (var request = new HttpRequestMessage(method, Endpoints.BaseApi + path))
{
var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture));
content.Add(new StreamContent(File.OpenRead(filePath)), "file", Path.GetFileName(filePath));
request.Content = content;
return await Send(request, cancelToken);
}
}
private async Task<string> Send(HttpRequestMessage request, CancellationToken cancelToken)
{
var response = await _client.SendAsync(request, cancelToken).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
throw new HttpException(response.StatusCode);
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
*/

+ 87
- 0
src/Discord.Net/API/Roles.cs View File

@@ -0,0 +1,87 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;

namespace Discord.API
{
//Common
public class RoleReference
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("role_id")]
public string RoleId;
}
public class RoleInfo
{
[JsonProperty("permissions")]
public uint? Permissions;
[JsonProperty("name")]
public string Name;
[JsonProperty("position")]
public int? Position;
[JsonProperty("hoist")]
public bool? Hoist;
[JsonProperty("color")]
public uint? Color;
[JsonProperty("id")]
public string Id;
[JsonProperty("managed")]
public bool? Managed;
}

//Create
public sealed class CreateRoleResponse : RoleInfo { }

//Edit
public sealed class EditRoleRequest
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name;
[JsonProperty("permissions", NullValueHandling = NullValueHandling.Ignore)]
public uint? Permissions;
[JsonProperty("hoist", NullValueHandling = NullValueHandling.Ignore)]
public bool? Hoist;
[JsonProperty("color", NullValueHandling = NullValueHandling.Ignore)]
public uint? Color;
}
public sealed class EditRoleResponse : RoleInfo { }

//Reorder
public sealed class ReorderRolesRequest : IEnumerable<ReorderRolesRequest.Role>
{
public sealed class Role
{
[JsonProperty("id")]
public string Id;
[JsonProperty("position")]
public uint Position;
}
private IEnumerable<Role> _roles;
public ReorderRolesRequest(IEnumerable<Role> roles) { _roles = roles; }

public IEnumerator<Role> GetEnumerator() => _roles.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _roles.GetEnumerator();
}

//Events
internal sealed class RoleCreateEvent
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("role")]
public RoleInfo Data;
}
internal sealed class RoleUpdateEvent
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("role")]
public RoleInfo Data;
}
internal sealed class RoleDeleteEvent : RoleReference { }
}

+ 80
- 0
src/Discord.Net/API/Servers.cs View File

@@ -0,0 +1,80 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System;

namespace Discord.API
{
//Common
public class GuildReference
{
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
}
public class GuildInfo : GuildReference
{
[JsonProperty("afk_channel_id")]
public string AFKChannelId;
[JsonProperty("afk_timeout")]
public int AFKTimeout;
[JsonProperty("embed_channel_id")]
public string EmbedChannelId;
[JsonProperty("embed_enabled")]
public bool EmbedEnabled;
[JsonProperty("icon")]
public string Icon;
[JsonProperty("joined_at")]
public DateTime? JoinedAt;
[JsonProperty("owner_id")]
public string OwnerId;
[JsonProperty("region")]
public string Region;
[JsonProperty("roles")]
public RoleInfo[] Roles;
}
public class ExtendedGuildInfo : GuildInfo
{
[JsonProperty("channels")]
public ChannelInfo[] Channels;
[JsonProperty("members")]
public ExtendedMemberInfo[] Members;
[JsonProperty("presences")]
public PresenceInfo[] Presences;
[JsonProperty("voice_states")]
public VoiceMemberInfo[] VoiceStates;
[JsonProperty("unavailable")]
public bool Unavailable;
}

//Create
internal sealed class CreateServerRequest
{
[JsonProperty("name")]
public string Name;
[JsonProperty("region")]
public string Region;
}
public sealed class CreateServerResponse : GuildInfo { }

//Edit
internal sealed class EditServerRequest
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name;
[JsonProperty("region", NullValueHandling = NullValueHandling.Ignore)]
public string Region;
}
public sealed class EditServerResponse : GuildInfo { }

//Delete
public sealed class DeleteServerResponse : GuildInfo { }

//Events
internal sealed class GuildCreateEvent : ExtendedGuildInfo { }
internal sealed class GuildUpdateEvent : GuildInfo { }
internal sealed class GuildDeleteEvent : ExtendedGuildInfo { }
}

+ 47
- 0
src/Discord.Net/API/Users.cs View File

@@ -0,0 +1,47 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;

namespace Discord.API
{
//Common
public class UserReference
{
[JsonProperty("username")]
public string Username;
[JsonProperty("id")]
public string Id;
[JsonProperty("discriminator")]
public string Discriminator;
[JsonProperty("avatar")]
public string Avatar;
}
public class UserInfo : UserReference
{
[JsonProperty("email")]
public string Email;
[JsonProperty("verified")]
public bool? IsVerified;
}

//Edit
internal sealed class EditUserRequest
{
[JsonProperty(PropertyName = "password")]
public string CurrentPassword;
[JsonProperty(PropertyName = "email", NullValueHandling = NullValueHandling.Ignore)]
public string Email;
[JsonProperty(PropertyName = "new_password")]
public string Password;
[JsonProperty(PropertyName = "username", NullValueHandling = NullValueHandling.Ignore)]
public string Username;
[JsonProperty(PropertyName = "avatar", NullValueHandling = NullValueHandling.Ignore)]
public string Avatar;
}
public sealed class EditUserResponse : UserInfo { }

//Events
internal sealed class UserUpdateEvent : UserInfo { }
}

+ 153
- 0
src/Discord.Net/API/Voice.cs View File

@@ -0,0 +1,153 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System.Collections.Generic;

namespace Discord.API
{
public class GetRegionsResponse : List<GetRegionsResponse.RegionData>
{
public sealed class RegionData
{
[JsonProperty("sample_hostname")]
public string Hostname;
[JsonProperty("sample_port")]
public int Port;
[JsonProperty("id")]
public string Id;
[JsonProperty("name")]
public string Name;
}
}

public class GetIceResponse
{
[JsonProperty("ttl")]
public string TTL;
[JsonProperty("servers")]
public ServerData[] Servers;

public sealed class ServerData
{
[JsonProperty("url")]
public string URL;
[JsonProperty("username")]
public string Username;
[JsonProperty("credential")]
public string Credential;
}
}

//Commands
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data>
{
public JoinVoiceCommand() : base(4) { }
public class Data
{
[JsonProperty("guild_id")]
public string ServerId;
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("self_mute")]
public string SelfMute;
[JsonProperty("self_deaf")]
public string SelfDeaf;
}
}

//Events
internal sealed class VoiceServerUpdateEvent
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("endpoint")]
public string Endpoint;
[JsonProperty("token")]
public string Token;
}

//Commands (Voice)
internal sealed class VoiceLoginCommand : WebSocketMessage<VoiceLoginCommand.Data>
{
public VoiceLoginCommand() : base(0) { }
public class Data
{
[JsonProperty("server_id")]
public string ServerId;
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("token")]
public string Token;
}
}
internal sealed class VoiceLogin2Command : WebSocketMessage<VoiceLogin2Command.Data>
{
public VoiceLogin2Command() : base(1) { }
public class Data
{
public class SocketInfo
{
[JsonProperty("address")]
public string Address;
[JsonProperty("port")]
public int Port;
[JsonProperty("mode")]
public string Mode = "xsalsa20_poly1305";
}
[JsonProperty("protocol")]
public string Protocol = "udp";
[JsonProperty("data")]
public SocketInfo SocketData = new SocketInfo();
}
}
internal sealed class VoiceKeepAliveCommand : WebSocketMessage<object>
{
public VoiceKeepAliveCommand() : base(3, null) { }
}
internal sealed class IsTalkingCommand : WebSocketMessage<IsTalkingCommand.Data>
{
public IsTalkingCommand() : base(5) { }
public class Data
{
[JsonProperty("delay")]
public int Delay;
[JsonProperty("speaking")]
public bool IsSpeaking;
}
}

//Events (Voice)
public class VoiceReadyEvent
{
[JsonProperty("ssrc")]
public uint SSRC;
[JsonProperty("port")]
public ushort Port;
[JsonProperty("modes")]
public string[] Modes;
[JsonProperty("heartbeat_interval")]
public int HeartbeatInterval;
}

public class JoinServerEvent
{
[JsonProperty("secret_key")]
public byte[] SecretKey;
[JsonProperty("mode")]
public string Mode;
}

public class IsTalkingEvent
{
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("ssrc")]
public uint SSRC;
[JsonProperty("speaking")]
public bool IsSpeaking;
}
}

+ 112
- 0
src/Discord.Net/API/WebSockets.cs View File

@@ -0,0 +1,112 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;

namespace Discord.API
{
//Common
public class WebSocketMessage
{
[JsonProperty("op")]
public int Operation;
[JsonProperty("d")]
public object Payload;
[JsonProperty("t", NullValueHandling = NullValueHandling.Ignore)]
public string Type;
[JsonProperty("s", NullValueHandling = NullValueHandling.Ignore)]
public int? Sequence;
}
internal abstract class WebSocketMessage<T> : WebSocketMessage
where T : new()
{
public WebSocketMessage() { Payload = new T(); }
public WebSocketMessage(int op) { Operation = op; Payload = new T(); }
public WebSocketMessage(int op, T payload) { Operation = op; Payload = payload; }

[JsonIgnore]
public new T Payload
{
get
{
if (base.Payload is JToken)
base.Payload = (base.Payload as JToken).ToObject<T>();
return (T)base.Payload;
}
set { base.Payload = value; }
}
}

//Commands
internal sealed class KeepAliveCommand : WebSocketMessage<ulong>
{
public KeepAliveCommand() : base(1, EpochTime.GetMilliseconds()) { }
}
internal sealed class LoginCommand : WebSocketMessage<LoginCommand.Data>
{
public LoginCommand() : base(2) { }
public class Data
{
[JsonProperty("token")]
public string Token;
[JsonProperty("v")]
public int Version = 3;
[JsonProperty("properties")]
public Dictionary<string, string> Properties = new Dictionary<string, string>();
}
}
internal sealed class ResumeCommand : WebSocketMessage<ResumeCommand.Data>
{
public ResumeCommand() : base(6) { }
public class Data
{
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("seq")]
public int Sequence;
}
}

//Events
internal sealed class ReadyEvent
{
public sealed class ReadStateInfo
{
[JsonProperty("id")]
public string ChannelId;
[JsonProperty("mention_count")]
public int MentionCount;
[JsonProperty("last_message_id")]
public string LastMessageId;
}

[JsonProperty("v")]
public int Version;
[JsonProperty("user")]
public UserInfo User;
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("read_state")]
public ReadStateInfo[] ReadState;
[JsonProperty("guilds")]
public ExtendedGuildInfo[] Guilds;
[JsonProperty("private_channels")]
public ChannelInfo[] PrivateChannels;
[JsonProperty("heartbeat_interval")]
public int HeartbeatInterval;
}
internal sealed class ResumedEvent
{
[JsonProperty("heartbeat_interval")]
public int HeartbeatInterval;
}

internal sealed class RedirectEvent
{
[JsonProperty("url")]
public string Url;
}
}

+ 8
- 13
src/Discord.Net/DiscordClient.API.cs View File

@@ -1,4 +1,5 @@
using Discord.API; using Discord.API;
using Discord.Net;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -312,7 +313,7 @@ namespace Discord
{ {
var msg = _messages.GetOrAdd("nonce_" + nonce, channel.Id, CurrentUserId); var msg = _messages.GetOrAdd("nonce_" + nonce, channel.Id, CurrentUserId);
var currentMember = _members[msg.UserId, channel.ServerId]; var currentMember = _members[msg.UserId, channel.ServerId];
msg.Update(new API.Message
msg.Update(new MessageInfo
{ {
Content = blockText, Content = blockText,
Timestamp = DateTime.UtcNow, Timestamp = DateTime.UtcNow,
@@ -611,26 +612,20 @@ namespace Discord
} }


//Profile //Profile
public Task<EditProfileResponse> EditProfile(string currentPassword = "",
public Task<EditUserResponse> EditProfile(string currentPassword = "",
string username = null, string email = null, string password = null, string username = null, string email = null, string password = null,
AvatarImageType avatarType = AvatarImageType.Png, byte[] avatar = null) AvatarImageType avatarType = AvatarImageType.Png, byte[] avatar = null)
{ {
if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword)); if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword));


return _api.EditProfile(currentPassword: currentPassword, username: username ?? _currentUser?.Name, email: email ?? _currentUser?.Email, password: password,
return _api.EditUser(currentPassword: currentPassword, username: username ?? _currentUser?.Name, email: email ?? _currentUser?.Email, password: password,
avatarType: avatarType, avatar: avatar); avatarType: avatarType, avatar: avatar);
} }
public Task SetStatus(string status) public Task SetStatus(string status)
{ {
switch (status)
{
case UserStatus.Online:
case UserStatus.Away:
_status = status;
break;
default:
throw new ArgumentException($"Invalid status, must be {UserStatus.Online} or {UserStatus.Away}");
}
if (status != UserStatus.Online && status != UserStatus.Idle)
throw new ArgumentException($"Invalid status, must be {UserStatus.Online} or {UserStatus.Idle}");
_status = status;
return SendStatus(); return SendStatus();
} }
public Task SetGame(int? gameId) public Task SetGame(int? gameId)
@@ -640,7 +635,7 @@ namespace Discord
} }
private Task SendStatus() private Task SendStatus()
{ {
_dataSocket.SendStatus(_status == UserStatus.Away ? EpochTime.GetMilliseconds() - (10 * 60 * 1000) : (ulong?)null, _gameId);
_dataSocket.SendStatus(_status == UserStatus.Idle ? EpochTime.GetMilliseconds() - (10 * 60 * 1000) : (ulong?)null, _gameId);
return TaskHelper.CompletedTask; return TaskHelper.CompletedTask;
} }




+ 10
- 12
src/Discord.Net/DiscordClient.cs View File

@@ -1,7 +1,6 @@
using Discord.API; using Discord.API;
using Discord.Collections; using Discord.Collections;
using Discord.WebSockets;
using Discord.WebSockets.Data;
using Discord.Net;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@@ -9,7 +8,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using VoiceWebSocket = Discord.WebSockets.Voice.VoiceWebSocket;


namespace Discord namespace Discord
{ {
@@ -474,7 +472,7 @@ namespace Discord
//Members //Members
case "GUILD_MEMBER_ADD": case "GUILD_MEMBER_ADD":
{ {
var data = e.Payload.ToObject<GuildMemberAddEvent>(_serializer);
var data = e.Payload.ToObject<MemberAddEvent>(_serializer);
var user = _users.GetOrAdd(data.User.Id); var user = _users.GetOrAdd(data.User.Id);
user.Update(data.User); user.Update(data.User);
var member = _members.GetOrAdd(data.User.Id, data.GuildId); var member = _members.GetOrAdd(data.User.Id, data.GuildId);
@@ -486,7 +484,7 @@ namespace Discord
break; break;
case "GUILD_MEMBER_UPDATE": case "GUILD_MEMBER_UPDATE":
{ {
var data = e.Payload.ToObject<GuildMemberUpdateEvent>(_serializer);
var data = e.Payload.ToObject<MemberUpdateEvent>(_serializer);
var member = _members[data.User.Id, data.GuildId]; var member = _members[data.User.Id, data.GuildId];
if (member != null) if (member != null)
{ {
@@ -497,7 +495,7 @@ namespace Discord
break; break;
case "GUILD_MEMBER_REMOVE": case "GUILD_MEMBER_REMOVE":
{ {
var data = e.Payload.ToObject<GuildMemberRemoveEvent>(_serializer);
var data = e.Payload.ToObject<MemberRemoveEvent>(_serializer);
var member = _members.TryRemove(data.UserId, data.GuildId); var member = _members.TryRemove(data.UserId, data.GuildId);
if (member != null) if (member != null)
RaiseUserRemoved(member); RaiseUserRemoved(member);
@@ -507,7 +505,7 @@ namespace Discord
//Roles //Roles
case "GUILD_ROLE_CREATE": case "GUILD_ROLE_CREATE":
{ {
var data = e.Payload.ToObject<GuildRoleCreateEvent>(_serializer);
var data = e.Payload.ToObject<RoleCreateEvent>(_serializer);
var role = _roles.GetOrAdd(data.Data.Id, data.GuildId, false); var role = _roles.GetOrAdd(data.Data.Id, data.GuildId, false);
role.Update(data.Data); role.Update(data.Data);
var server = _servers[data.GuildId]; var server = _servers[data.GuildId];
@@ -518,7 +516,7 @@ namespace Discord
break; break;
case "GUILD_ROLE_UPDATE": case "GUILD_ROLE_UPDATE":
{ {
var data = e.Payload.ToObject<GuildRoleUpdateEvent>(_serializer);
var data = e.Payload.ToObject<RoleUpdateEvent>(_serializer);
var role = _roles[data.Data.Id]; var role = _roles[data.Data.Id];
if (role != null) if (role != null)
role.Update(data.Data); role.Update(data.Data);
@@ -527,7 +525,7 @@ namespace Discord
break; break;
case "GUILD_ROLE_DELETE": case "GUILD_ROLE_DELETE":
{ {
var data = e.Payload.ToObject<GuildRoleDeleteEvent>(_serializer);
var data = e.Payload.ToObject<RoleDeleteEvent>(_serializer);
var server = _servers[data.GuildId]; var server = _servers[data.GuildId];
if (server != null) if (server != null)
server.RemoveRole(data.RoleId); server.RemoveRole(data.RoleId);
@@ -540,7 +538,7 @@ namespace Discord
//Bans //Bans
case "GUILD_BAN_ADD": case "GUILD_BAN_ADD":
{ {
var data = e.Payload.ToObject<GuildBanAddEvent>(_serializer);
var data = e.Payload.ToObject<BanAddEvent>(_serializer);
var server = _servers[data.GuildId]; var server = _servers[data.GuildId];
if (server != null) if (server != null)
{ {
@@ -551,7 +549,7 @@ namespace Discord
break; break;
case "GUILD_BAN_REMOVE": case "GUILD_BAN_REMOVE":
{ {
var data = e.Payload.ToObject<GuildBanRemoveEvent>(_serializer);
var data = e.Payload.ToObject<BanRemoveEvent>(_serializer);
var server = _servers[data.GuildId]; var server = _servers[data.GuildId];
if (server != null && server.RemoveBan(data.User?.Id)) if (server != null && server.RemoveBan(data.User?.Id))
RaiseBanRemoved(data.User?.Id, server); RaiseBanRemoved(data.User?.Id, server);
@@ -682,7 +680,7 @@ namespace Discord
//Voice //Voice
case "VOICE_STATE_UPDATE": case "VOICE_STATE_UPDATE":
{ {
var data = e.Payload.ToObject<VoiceStateUpdateEvent>(_serializer);
var data = e.Payload.ToObject<MemberVoiceStateUpdateEvent>(_serializer);
var member = _members[data.UserId, data.GuildId]; var member = _members[data.UserId, data.GuildId];
if (member != null) if (member != null)
{ {


+ 1
- 2
src/Discord.Net/DiscordSimpleClient.cs View File

@@ -1,11 +1,10 @@
using Discord.WebSockets.Data;
using Discord.Net;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VoiceWebSocket = Discord.WebSockets.Voice.VoiceWebSocket;


namespace Discord namespace Discord
{ {


+ 47
- 0
src/Discord.Net/Helpers/Extensions.cs View File

@@ -6,6 +6,53 @@ namespace Discord
{ {
internal static class Extensions internal static class Extensions
{ {
public static async Task Timeout(this Task self, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(self, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
await self.ConfigureAwait(false);
}
public static async Task<T> Timeout<T>(this Task<T> self, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(self, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
return await self.ConfigureAwait(false);
}
public static async Task Timeout(this Task self, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
await self.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}
public static async Task<T> Timeout<T>(this Task<T> self, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
return await self.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}

public static async Task Wait(this CancellationTokenSource tokenSource) public static async Task Wait(this CancellationTokenSource tokenSource)
{ {
var token = tokenSource.Token; var token = tokenSource.Token;


src/Discord.Net/Format.cs → src/Discord.Net/Helpers/Format.cs View File


src/Discord.Net/Mention.cs → src/Discord.Net/Helpers/Mention.cs View File


src/Discord.Net/Helpers/CollectionHelper.cs → src/Discord.Net/Helpers/Shared/CollectionHelper.cs View File


src/Discord.Net/Shared/TaskHelper.cs → src/Discord.Net/Helpers/Shared/TaskHelper.cs View File


+ 0
- 56
src/Discord.Net/Helpers/TaskExtensions.cs View File

@@ -1,56 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Discord
{
public static class TaskExtensions
{
public static async Task Timeout(this Task self, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(self, timeoutTask);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
await self;
}
public static async Task<T> Timeout<T>(this Task<T> self, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(self, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
return await self.ConfigureAwait(false);
}
public static async Task Timeout(this Task self, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
await self.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}
public static async Task<T> Timeout<T>(this Task<T> self, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
return await self.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}
}
}

src/Discord.Net/TimeoutException.cs → src/Discord.Net/Helpers/TimeoutException.cs View File


src/Discord.Net/Audio/Opus.cs → src/Discord.Net/Interop/Opus.cs View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;


namespace Discord.Audio
namespace Discord.Interop
{ {
internal unsafe static class Opus internal unsafe static class Opus
{ {

src/Discord.Net/Audio/OpusDecoder.cs → src/Discord.Net/Interop/OpusDecoder.cs View File

@@ -1,6 +1,6 @@
using System; using System;


namespace Discord.Audio
namespace Discord.Interop
{ {
/// <summary> Opus codec wrapper. </summary> /// <summary> Opus codec wrapper. </summary>
internal class OpusDecoder : IDisposable internal class OpusDecoder : IDisposable

src/Discord.Net/Audio/OpusEncoder.cs → src/Discord.Net/Interop/OpusEncoder.cs View File

@@ -1,6 +1,6 @@
using System; using System;


namespace Discord.Audio
namespace Discord.Interop
{ {
/// <summary> Opus codec wrapper. </summary> /// <summary> Opus codec wrapper. </summary>
internal class OpusEncoder : IDisposable internal class OpusEncoder : IDisposable

src/Discord.Net/Audio/Sodium.cs → src/Discord.Net/Interop/Sodium.cs View File

@@ -1,6 +1,6 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;


namespace Discord.Audio
namespace Discord.Interop
{ {
internal unsafe static class Sodium internal unsafe static class Sodium
{ {

+ 5
- 4
src/Discord.Net/Models/Channel.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -99,16 +100,16 @@ namespace Discord
_areMembersStale = true; _areMembersStale = true;
} }


internal void Update(API.ChannelReference model)
internal void Update(ChannelReference model)
{ {
if (model.Name != null) if (model.Name != null)
Name = model.Name; Name = model.Name;
if (model.Type != null) if (model.Type != null)
Type = model.Type; Type = model.Type;
} }
internal void Update(API.ChannelInfo model)
internal void Update(ChannelInfo model)
{ {
Update(model as API.ChannelReference);
Update(model as ChannelReference);
if (model.Position != null) if (model.Position != null)
Position = model.Position.Value; Position = model.Position.Value;


+ 5
- 4
src/Discord.Net/Models/Invite.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;


namespace Discord namespace Discord
{ {
@@ -53,7 +54,7 @@ namespace Discord


public override string ToString() => XkcdPass ?? Id; public override string ToString() => XkcdPass ?? Id;


internal void Update(API.Invite model)
internal void Update(InviteReference model)
{ {
if (model.Channel != null) if (model.Channel != null)
ChannelId = model.Channel.Id; ChannelId = model.Channel.Id;
@@ -61,9 +62,9 @@ namespace Discord
InviterId = model.Inviter.Id; InviterId = model.Inviter.Id;
} }


internal void Update(API.ExtendedInvite model)
internal void Update(InviteInfo model)
{ {
Update(model as API.Invite);
Update(model as InviteReference);
if (model.IsRevoked != null) if (model.IsRevoked != null)
IsRevoked = model.IsRevoked.Value; IsRevoked = model.IsRevoked.Value;
if (model.IsTemporary != null) if (model.IsTemporary != null)


+ 7
- 6
src/Discord.Net/Models/Member.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@@ -77,7 +78,7 @@ namespace Discord


public override string ToString() => UserId; public override string ToString() => UserId;


internal void Update(API.UserReference model)
internal void Update(UserReference model)
{ {
if (model.Avatar != null) if (model.Avatar != null)
AvatarId = model.Avatar; AvatarId = model.Avatar;
@@ -86,7 +87,7 @@ namespace Discord
if (model.Username != null) if (model.Username != null)
Name = model.Username; Name = model.Username;
} }
internal void Update(API.MemberInfo model)
internal void Update(MemberInfo model)
{ {
if (model.User != null) if (model.User != null)
Update(model.User); Update(model.User);
@@ -102,7 +103,7 @@ namespace Discord


UpdatePermissions(); UpdatePermissions();
} }
internal void Update(API.ExtendedMemberInfo model)
internal void Update(ExtendedMemberInfo model)
{ {
Update(model as API.MemberInfo); Update(model as API.MemberInfo);
if (model.IsServerDeafened != null) if (model.IsServerDeafened != null)
@@ -110,7 +111,7 @@ namespace Discord
if (model.IsServerMuted != null) if (model.IsServerMuted != null)
IsServerMuted = model.IsServerMuted.Value; IsServerMuted = model.IsServerMuted.Value;
} }
internal void Update(API.PresenceMemberInfo model)
internal void Update(PresenceInfo model)
{ {
//Allows null //Allows null
if (Status != model.Status) if (Status != model.Status)
@@ -121,7 +122,7 @@ namespace Discord
} }
GameId = model.GameId; GameId = model.GameId;
} }
internal void Update(API.VoiceMemberInfo model)
internal void Update(VoiceMemberInfo model)
{ {
if (model.IsServerDeafened != null) if (model.IsServerDeafened != null)
IsServerDeafened = model.IsServerDeafened.Value; IsServerDeafened = model.IsServerDeafened.Value;


+ 3
- 2
src/Discord.Net/Models/Message.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -175,7 +176,7 @@ namespace Discord
MentionIds = _initialMentions; MentionIds = _initialMentions;
} }


internal void Update(API.Message model)
internal void Update(MessageInfo model)
{ {
if (model.Attachments != null) if (model.Attachments != null)
{ {


+ 3
- 2
src/Discord.Net/Models/Role.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;


@@ -52,7 +53,7 @@ namespace Discord
Position = int.MinValue; Position = int.MinValue;
} }


internal void Update(API.RoleInfo model)
internal void Update(RoleInfo model)
{ {
if (model.Name != null) if (model.Name != null)
Name = model.Name; Name = model.Name;


+ 5
- 4
src/Discord.Net/Models/Server.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@@ -103,7 +104,7 @@ namespace Discord
_roles = new ConcurrentDictionary<string, bool>(); _roles = new ConcurrentDictionary<string, bool>();
} }


internal void Update(API.GuildInfo model)
internal void Update(GuildInfo model)
{ {
AFKChannelId = model.AFKChannelId; AFKChannelId = model.AFKChannelId;
AFKTimeout = model.AFKTimeout; AFKTimeout = model.AFKTimeout;
@@ -124,9 +125,9 @@ namespace Discord
isEveryone = false; isEveryone = false;
} }
} }
internal void Update(API.ExtendedGuildInfo model)
internal void Update(ExtendedGuildInfo model)
{ {
Update(model as API.GuildInfo);
Update(model as GuildInfo);


var channels = _client.Channels; var channels = _client.Channels;
foreach (var subModel in model.Channels) foreach (var subModel in model.Channels)


+ 10
- 6
src/Discord.Net/Models/User.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@@ -77,7 +78,7 @@ namespace Discord
_servers = new ConcurrentDictionary<string, bool>(); _servers = new ConcurrentDictionary<string, bool>();
} }


internal void Update(API.UserReference model)
internal void Update(UserReference model)
{ {
if (model.Avatar != null) if (model.Avatar != null)
AvatarId = model.Avatar; AvatarId = model.Avatar;
@@ -86,11 +87,14 @@ namespace Discord
if (model.Username != null) if (model.Username != null)
Name = model.Username; Name = model.Username;
} }
internal void Update(API.SelfUserInfo model)
internal void Update(UserInfo model)
{ {
Update(model as API.UserReference);
Email = model.Email;
IsVerified = model.IsVerified;
Update(model as UserReference);

if (model.Email != null)
Email = model.Email;
if (model.IsVerified != null)
IsVerified = model.IsVerified;
} }
internal void UpdateActivity(DateTime? activity = null) internal void UpdateActivity(DateTime? activity = null)
{ {


src/Discord.Net/WebSockets/Data/DataWebSocket.cs → src/Discord.Net/Net/DataWebSocket.cs View File

@@ -1,9 +1,10 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.WebSockets.Data
namespace Discord.Net
{ {
internal partial class DataWebSocket : WebSocket internal partial class DataWebSocket : WebSocket
{ {

src/Discord.Net/WebSockets/Data/DataWebSockets.Events.cs → src/Discord.Net/Net/DataWebSockets.Events.cs View File

@@ -1,7 +1,7 @@
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;


namespace Discord.WebSockets.Data
namespace Discord.Net
{ {
internal sealed class WebSocketEventEventArgs : EventArgs internal sealed class WebSocketEventEventArgs : EventArgs
{ {

src/Discord.Net/DiscordAPIClient.cs → src/Discord.Net/Net/DiscordAPIClient.cs View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord
namespace Discord.Net
{ {
/// <summary> A lightweight wrapper around the Discord API. </summary> /// <summary> A lightweight wrapper around the Discord API. </summary>
public class DiscordAPIClient public class DiscordAPIClient
@@ -225,26 +225,6 @@ namespace Discord
return _rest.Delete(Endpoints.ChannelPermission(channelId, userOrRoleId), null); return _rest.Delete(Endpoints.ChannelPermission(channelId, userOrRoleId), null);
} }


//Profile
public Task<EditProfileResponse> EditProfile(string currentPassword = "",
string username = null, string email = null, string password = null,
AvatarImageType avatarType = AvatarImageType.Png, byte[] avatar = null)
{
if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword));

string avatarBase64 = null;
if (avatarType == AvatarImageType.None)
avatarBase64 = "";
else if (avatar != null)
{
string base64 = Convert.ToBase64String(avatar);
string type = avatarType == AvatarImageType.Jpeg ? "image/jpeg;base64" : "image/png;base64";
avatarBase64 = $"data:{type},{base64}";
}
var request = new EditProfileRequest { CurrentPassword = currentPassword, Username = username, Email = email, Password = password, Avatar = avatarBase64 };
return _rest.Patch<EditProfileResponse>(Endpoints.UserMe, request);
}

//Roles //Roles
public Task<RoleInfo> CreateRole(string serverId) public Task<RoleInfo> CreateRole(string serverId)
{ {
@@ -302,10 +282,30 @@ namespace Discord
return _rest.Patch<EditServerResponse>(Endpoints.Server(serverId), request); return _rest.Patch<EditServerResponse>(Endpoints.Server(serverId), request);
} }


//User
public Task<EditUserResponse> EditUser(string currentPassword = "",
string username = null, string email = null, string password = null,
AvatarImageType avatarType = AvatarImageType.Png, byte[] avatar = null)
{
if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword));

string avatarBase64 = null;
if (avatarType == AvatarImageType.None)
avatarBase64 = "";
else if (avatar != null)
{
string base64 = Convert.ToBase64String(avatar);
string type = avatarType == AvatarImageType.Jpeg ? "image/jpeg;base64" : "image/png;base64";
avatarBase64 = $"data:{type},{base64}";
}
var request = new EditUserRequest { CurrentPassword = currentPassword, Username = username, Email = email, Password = password, Avatar = avatarBase64 };
return _rest.Patch<EditUserResponse>(Endpoints.UserMe, request);
}

//Voice //Voice
public Task<GetRegionsResponse> GetVoiceRegions() public Task<GetRegionsResponse> GetVoiceRegions()
=> _rest.Get<GetRegionsResponse>(Endpoints.VoiceRegions); => _rest.Get<GetRegionsResponse>(Endpoints.VoiceRegions);
public Task<GetIceResponse> GetVoiceIce()
=> _rest.Get<GetIceResponse>(Endpoints.VoiceIce);
/*public Task<GetIceResponse> GetVoiceIce()
=> _rest.Get<GetIceResponse>(Endpoints.VoiceIce);*/
} }
} }

src/Discord.Net/API/HttpException.cs → src/Discord.Net/Net/HttpException.cs View File

@@ -1,14 +1,14 @@
using System; using System;
using System.Net; using System.Net;


namespace Discord.API
namespace Discord.Net
{ {
public class HttpException : Exception public class HttpException : Exception
{ {
public HttpStatusCode StatusCode { get; } public HttpStatusCode StatusCode { get; }


public HttpException(HttpStatusCode statusCode) public HttpException(HttpStatusCode statusCode)
: base($"The server responded with error {statusCode}")
: base($"The server responded with error {(int)statusCode} ({statusCode})")
{ {
StatusCode = statusCode; StatusCode = statusCode;
} }

src/Discord.Net/API/RestClient.Events.cs → src/Discord.Net/Net/RestClient.Events.cs View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Net.Http; using System.Net.Http;


namespace Discord.API
namespace Discord.Net
{ {
internal partial class RestClient internal partial class RestClient
{ {

src/Discord.Net/API/RestClient.SharpRest.cs → src/Discord.Net/Net/RestClient.SharpRest.cs View File

@@ -1,17 +1,17 @@
using RestSharp;
using Discord.API;
using RestSharp;
using System; using System;
using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.API
namespace Discord.Net
{ {
internal class RestSharpRestEngine : IRestEngine
internal partial class RestClient
{ {
private readonly RestSharp.RestClient _client;
private RestSharp.RestClient _client;


public RestSharpRestEngine(string userAgent, int timeout)
partial void Initialize(string userAgent, int timeout)
{ {
_client = new RestSharp.RestClient(Endpoints.BaseApi) _client = new RestSharp.RestClient(Endpoints.BaseApi)
{ {
@@ -24,20 +24,20 @@ namespace Discord.API
_client.ReadWriteTimeout = timeout; _client.ReadWriteTimeout = timeout;
} }


public void SetToken(string token)
internal void SetToken(string token)
{ {
_client.RemoveDefaultParameter("authorization"); _client.RemoveDefaultParameter("authorization");
if (token != null) if (token != null)
_client.AddDefaultHeader("authorization", token); _client.AddDefaultHeader("authorization", token);
} }


public Task<string> Send(HttpMethod method, string path, string json, CancellationToken cancelToken)
private Task<string> SendInternal(HttpMethod method, string path, string json, CancellationToken cancelToken)
{ {
var request = new RestRequest(path, GetMethod(method)); var request = new RestRequest(path, GetMethod(method));
request.AddParameter("application/json", json, ParameterType.RequestBody); request.AddParameter("application/json", json, ParameterType.RequestBody);
return Send(request, cancelToken); return Send(request, cancelToken);
} }
public Task<string> SendFile(HttpMethod method, string path, string filePath, CancellationToken cancelToken)
private Task<string> SendFileInternal(HttpMethod method, string path, string filePath, CancellationToken cancelToken)
{ {
var request = new RestRequest(path, Method.POST); var request = new RestRequest(path, Method.POST);
request.AddFile("file", filePath); request.AddFile("file", filePath);

src/Discord.Net/API/RestClient.cs → src/Discord.Net/Net/RestClient.cs View File

@@ -1,32 +1,25 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.API
namespace Discord.Net
{ {
internal interface IRestEngine
{
void SetToken(string token);
Task<string> Send(HttpMethod method, string path, string json, CancellationToken cancelToken);
Task<string> SendFile(HttpMethod method, string path, string filePath, CancellationToken cancelToken);
}

internal partial class RestClient internal partial class RestClient
{ {
private readonly IRestEngine _engine;
private readonly LogMessageSeverity _logLevel; private readonly LogMessageSeverity _logLevel;
private CancellationToken _cancelToken; private CancellationToken _cancelToken;


public RestClient(LogMessageSeverity logLevel, string userAgent, int timeout) public RestClient(LogMessageSeverity logLevel, string userAgent, int timeout)
{ {
_logLevel = logLevel; _logLevel = logLevel;
_engine = new RestSharpRestEngine(userAgent, timeout);
} }
partial void Initialize(string userAgent, int timeout);


//DELETE
private static readonly HttpMethod _delete = HttpMethod.Delete; private static readonly HttpMethod _delete = HttpMethod.Delete;
internal Task<ResponseT> Delete<ResponseT>(string path, object data) where ResponseT : class internal Task<ResponseT> Delete<ResponseT>(string path, object data) where ResponseT : class
=> Send<ResponseT>(_delete, path, data); => Send<ResponseT>(_delete, path, data);
@@ -37,12 +30,14 @@ namespace Discord.API
internal Task Delete(string path) internal Task Delete(string path)
=> Send(_delete, path); => Send(_delete, path);


//GET
private static readonly HttpMethod _get = HttpMethod.Get; private static readonly HttpMethod _get = HttpMethod.Get;
internal Task<ResponseT> Get<ResponseT>(string path) where ResponseT : class internal Task<ResponseT> Get<ResponseT>(string path) where ResponseT : class
=> Send<ResponseT>(_get, path); => Send<ResponseT>(_get, path);
internal Task Get(string path) internal Task Get(string path)
=> Send(_get, path); => Send(_get, path);


//PATCH
private static readonly HttpMethod _patch = new HttpMethod("PATCH"); private static readonly HttpMethod _patch = new HttpMethod("PATCH");
internal Task<ResponseT> Patch<ResponseT>(string path, object data) where ResponseT : class internal Task<ResponseT> Patch<ResponseT>(string path, object data) where ResponseT : class
=> Send<ResponseT>(_patch, path, data); => Send<ResponseT>(_patch, path, data);
@@ -97,7 +92,7 @@ namespace Discord.API
if (_logLevel >= LogMessageSeverity.Verbose) if (_logLevel >= LogMessageSeverity.Verbose)
stopwatch = Stopwatch.StartNew(); stopwatch = Stopwatch.StartNew();
string responseJson = await _engine.Send(method, path, requestJson, _cancelToken).ConfigureAwait(false);
string responseJson = await SendInternal(method, path, requestJson, _cancelToken).ConfigureAwait(false);


#if TEST_RESPONSES #if TEST_RESPONSES
if (!hasResponse && !string.IsNullOrEmpty(responseJson)) if (!hasResponse && !string.IsNullOrEmpty(responseJson))
@@ -136,7 +131,7 @@ namespace Discord.API
if (_logLevel >= LogMessageSeverity.Verbose) if (_logLevel >= LogMessageSeverity.Verbose)
stopwatch = Stopwatch.StartNew(); stopwatch = Stopwatch.StartNew();
string responseJson = await _engine.SendFile(method, path, filePath, _cancelToken).ConfigureAwait(false);
string responseJson = await SendFileInternal(method, path, filePath, _cancelToken).ConfigureAwait(false);


#if TEST_RESPONSES #if TEST_RESPONSES
if (!hasResponse && !string.IsNullOrEmpty(responseJson)) if (!hasResponse && !string.IsNullOrEmpty(responseJson))
@@ -173,7 +168,6 @@ namespace Discord.API
#endif #endif
} }


internal void SetToken(string token) => _engine.SetToken(token);
internal void SetCancelToken(CancellationToken token) => _cancelToken = token; internal void SetCancelToken(CancellationToken token) => _cancelToken = token;
} }
} }

src/Discord.Net/WebSockets/Voice/VoiceBuffer.cs → src/Discord.Net/Net/VoiceBuffer.cs View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Threading; using System.Threading;


namespace Discord.WebSockets.Voice
namespace Discord.Net
{ {
internal class VoiceBuffer : IDiscordVoiceBuffer internal class VoiceBuffer : IDiscordVoiceBuffer
{ {
@@ -46,7 +46,11 @@ namespace Discord.WebSockets.Voice
if (_readCursor == nextPosition) if (_readCursor == nextPosition)
{ {
_notOverflowEvent.Reset(); _notOverflowEvent.Reset();
_notOverflowEvent.Wait(cancelToken);
try
{
_notOverflowEvent.Wait(cancelToken);
}
catch (OperationCanceledException) { return; }
} }


if (i == wholeFrames) if (i == wholeFrames)
@@ -100,7 +104,11 @@ namespace Discord.WebSockets.Voice
_isClearing = true; _isClearing = true;
for (int i = 0; i < _frameCount; i++) for (int i = 0; i < _frameCount; i++)
Buffer.BlockCopy(_blankFrame, 0, _buffer, i * _frameCount, i++); Buffer.BlockCopy(_blankFrame, 0, _buffer, i * _frameCount, i++);
_underflowEvent.Wait(cancelToken);
try
{
_underflowEvent.Wait(cancelToken);
}
catch (OperationCanceledException) { }
_writeCursor = 0; _writeCursor = 0;
_readCursor = 0; _readCursor = 0;
_isClearing = false; _isClearing = false;

src/Discord.Net/WebSockets/Voice/VoiceWebSocket.Events.cs → src/Discord.Net/Net/VoiceWebSocket.Events.cs View File

@@ -1,6 +1,6 @@
using System; using System;


namespace Discord.WebSockets.Voice
namespace Discord.Net
{ {
internal sealed class IsTalkingEventArgs : EventArgs internal sealed class IsTalkingEventArgs : EventArgs
{ {

src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs → src/Discord.Net/Net/VoiceWebSocket.cs View File

@@ -1,5 +1,6 @@
#define USE_THREAD #define USE_THREAD
using Discord.Audio;
using Discord.API;
using Discord.Interop;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
@@ -13,7 +14,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.WebSockets.Voice
namespace Discord.Net
{ {
internal partial class VoiceWebSocket : WebSocket internal partial class VoiceWebSocket : WebSocket
{ {
@@ -109,8 +110,8 @@ namespace Discord.WebSockets.Voice
#if !DNX451 && !__MonoCS__ #if !DNX451 && !__MonoCS__
_udp.AllowNatTraversal(true); _udp.AllowNatTraversal(true);
#endif #endif
LoginCommand msg = new LoginCommand();
VoiceLoginCommand msg = new VoiceLoginCommand();
msg.Payload.ServerId = _serverId; msg.Payload.ServerId = _serverId;
msg.Payload.SessionId = _sessionId; msg.Payload.SessionId = _sessionId;
msg.Payload.Token = _token; msg.Payload.Token = _token;
@@ -238,7 +239,7 @@ namespace Discord.WebSockets.Voice
int port = packet[68] | packet[69] << 8; int port = packet[68] | packet[69] << 8;
string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0'); string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0');


var login2 = new Login2Command();
var login2 = new VoiceLogin2Command();
login2.Payload.Protocol = "udp"; login2.Payload.Protocol = "udp";
login2.Payload.SocketData.Address = ip; login2.Payload.SocketData.Address = ip;
login2.Payload.SocketData.Mode = _encryptionMode; login2.Payload.SocketData.Mode = _encryptionMode;
@@ -458,7 +459,7 @@ namespace Discord.WebSockets.Voice
{ {
if (_state != (int)WebSocketState.Connected) if (_state != (int)WebSocketState.Connected)
{ {
var payload = (msg.Payload as JToken).ToObject<ReadyEvent>();
var payload = (msg.Payload as JToken).ToObject<VoiceReadyEvent>();
_heartbeatInterval = payload.HeartbeatInterval; _heartbeatInterval = payload.HeartbeatInterval;
_ssrc = payload.SSRC; _ssrc = payload.SSRC;
_endpoint = new IPEndPoint((await Dns.GetHostAddressesAsync(Host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(), payload.Port); _endpoint = new IPEndPoint((await Dns.GetHostAddressesAsync(Host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(), payload.Port);

src/Discord.Net/WebSockets/WebSocket.BuiltIn.cs → src/Discord.Net/Net/WebSocket.BuiltIn.cs.old View File

@@ -1,5 +1,4 @@
/*
using Discord.Helpers;
using Discord.Helpers;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@@ -149,5 +148,4 @@ namespace Discord.WebSockets
_sendQueue.Enqueue(message); _sendQueue.Enqueue(message);
} }
} }
}
*/
}

src/Discord.Net/WebSockets/WebSocket.Events.cs → src/Discord.Net/Net/WebSocket.Events.cs View File

@@ -1,6 +1,6 @@
using System; using System;


namespace Discord.WebSockets
namespace Discord.Net
{ {
internal abstract partial class WebSocket internal abstract partial class WebSocket
{ {

src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs → src/Discord.Net/Net/WebSocket.WebSocketSharp.cs View File

@@ -5,7 +5,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using WSSharpNWebSocket = WebSocketSharp.WebSocket; using WSSharpNWebSocket = WebSocketSharp.WebSocket;


namespace Discord.WebSockets
namespace Discord.Net
{ {
internal class WSSharpWebSocketEngine : IWebSocketEngine internal class WSSharpWebSocketEngine : IWebSocketEngine
{ {

src/Discord.Net/WebSockets/WebSocket.cs → src/Discord.Net/Net/WebSocket.cs View File

@@ -6,7 +6,7 @@ using System.Runtime.ExceptionServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.WebSockets
namespace Discord.Net
{ {
public enum WebSocketState : byte public enum WebSocketState : byte
{ {

+ 0
- 64
src/Discord.Net/WebSockets/Data/Commands.cs View File

@@ -1,64 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;
using System.Collections.Generic;

namespace Discord.WebSockets.Data
{
internal sealed class KeepAliveCommand : WebSocketMessage<ulong>
{
public KeepAliveCommand() : base(1, EpochTime.GetMilliseconds()) { }
}
internal sealed class LoginCommand : WebSocketMessage<LoginCommand.Data>
{
public LoginCommand() : base(2) { }
public class Data
{
[JsonProperty("token")]
public string Token;
[JsonProperty("v")]
public int Version = 3;
[JsonProperty("properties")]
public Dictionary<string, string> Properties = new Dictionary<string, string>();
}
}
internal sealed class UpdateStatusCommand : WebSocketMessage<UpdateStatusCommand.Data>
{
public UpdateStatusCommand() : base(3) { }
public class Data
{
[JsonProperty("idle_since")]
public ulong? IdleSince;
[JsonProperty("game_id")]
public int? GameId;
}
}
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data>
{
public JoinVoiceCommand() : base(4) { }
public class Data
{
[JsonProperty("guild_id")]
public string ServerId;
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("self_mute")]
public string SelfMute;
[JsonProperty("self_deaf")]
public string SelfDeaf;
}
}
internal sealed class ResumeCommand : WebSocketMessage<ResumeCommand.Data>
{
public ResumeCommand() : base(6) { }
public class Data
{
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("seq")]
public int Sequence;
}
}
}

+ 0
- 115
src/Discord.Net/WebSockets/Data/Events.cs View File

@@ -1,115 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Discord.API;
using Newtonsoft.Json;

namespace Discord.WebSockets.Data
{
internal sealed class ReadyEvent
{
public sealed class ReadStateInfo
{
[JsonProperty("id")]
public string ChannelId;
[JsonProperty("mention_count")]
public int MentionCount;
[JsonProperty("last_message_id")]
public string LastMessageId;
}

[JsonProperty("v")]
public int Version;
[JsonProperty("user")]
public SelfUserInfo User;
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("read_state")]
public ReadStateInfo[] ReadState;
[JsonProperty("guilds")]
public ExtendedGuildInfo[] Guilds;
[JsonProperty("private_channels")]
public ChannelInfo[] PrivateChannels;
[JsonProperty("heartbeat_interval")]
public int HeartbeatInterval;
}
internal sealed class ResumedEvent
{
[JsonProperty("heartbeat_interval")]
public int HeartbeatInterval;
}

internal sealed class RedirectEvent
{
[JsonProperty("url")]
public string Url;
}

//Servers
internal sealed class GuildCreateEvent : ExtendedGuildInfo { }
internal sealed class GuildUpdateEvent : GuildInfo { }
internal sealed class GuildDeleteEvent : ExtendedGuildInfo { }

//Channels
internal sealed class ChannelCreateEvent : ChannelInfo { }
internal sealed class ChannelDeleteEvent : ChannelInfo { }
internal sealed class ChannelUpdateEvent : ChannelInfo { }

//Memberships
internal sealed class GuildMemberAddEvent : MemberInfo { }
internal sealed class GuildMemberUpdateEvent : MemberInfo { }
internal sealed class GuildMemberRemoveEvent : MemberInfo { }

//Roles
internal sealed class GuildRoleCreateEvent
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("role")]
public RoleInfo Data;
}
internal sealed class GuildRoleUpdateEvent
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("role")]
public RoleInfo Data;
}
internal sealed class GuildRoleDeleteEvent : RoleReference { }

//Bans
internal sealed class GuildBanAddEvent : MemberReference { }
internal sealed class GuildBanRemoveEvent : MemberReference { }

//User
internal sealed class UserUpdateEvent : SelfUserInfo { }
internal sealed class PresenceUpdateEvent : PresenceMemberInfo { }
internal sealed class VoiceStateUpdateEvent : VoiceMemberInfo { }

//Chat
internal sealed class MessageCreateEvent : API.Message { }
internal sealed class MessageUpdateEvent : API.Message { }
internal sealed class MessageDeleteEvent : MessageReference { }
internal sealed class MessageAckEvent : MessageReference { }
internal sealed class TypingStartEvent
{
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("channel_id")]
public string ChannelId;
[JsonProperty("timestamp")]
public int Timestamp;
}

//Voice
internal sealed class VoiceServerUpdateEvent
{
[JsonProperty("guild_id")]
public string GuildId;
[JsonProperty("endpoint")]
public string Endpoint;
[JsonProperty("token")]
public string Token;
}
}

+ 0
- 59
src/Discord.Net/WebSockets/Voice/Commands.cs View File

@@ -1,59 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;

namespace Discord.WebSockets.Voice
{
internal sealed class LoginCommand : WebSocketMessage<LoginCommand.Data>
{
public LoginCommand() : base(0) { }
public class Data
{
[JsonProperty("server_id")]
public string ServerId;
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("session_id")]
public string SessionId;
[JsonProperty("token")]
public string Token;
}
}
internal sealed class Login2Command : WebSocketMessage<Login2Command.Data>
{
public Login2Command() : base(1) { }
public class Data
{
public class SocketInfo
{
[JsonProperty("address")]
public string Address;
[JsonProperty("port")]
public int Port;
[JsonProperty("mode")]
public string Mode = "xsalsa20_poly1305";
}
[JsonProperty("protocol")]
public string Protocol = "udp";
[JsonProperty("data")]
public SocketInfo SocketData = new SocketInfo();
}
}
internal sealed class KeepAliveCommand : WebSocketMessage<object>
{
public KeepAliveCommand() : base(3, null) { }
}
internal sealed class IsTalkingCommand : WebSocketMessage<IsTalkingCommand.Data>
{
public IsTalkingCommand() : base(5) { }
public class Data
{
[JsonProperty("delay")]
public int Delay;
[JsonProperty("speaking")]
public bool IsSpeaking;
}
}
}

+ 0
- 38
src/Discord.Net/WebSockets/Voice/Events.cs View File

@@ -1,38 +0,0 @@
//Ignore unused/unassigned variable warnings
#pragma warning disable CS0649
#pragma warning disable CS0169

using Newtonsoft.Json;

namespace Discord.WebSockets.Voice
{
internal sealed class ReadyEvent
{
[JsonProperty("ssrc")]
public uint SSRC;
[JsonProperty("port")]
public ushort Port;
[JsonProperty("modes")]
public string[] Modes;
[JsonProperty("heartbeat_interval")]
public int HeartbeatInterval;
}

internal sealed class JoinServerEvent
{
[JsonProperty("secret_key")]
public byte[] SecretKey;
[JsonProperty("mode")]
public string Mode;
}

internal sealed class IsTalkingEvent
{
[JsonProperty("user_id")]
public string UserId;
[JsonProperty("ssrc")]
public uint SSRC;
[JsonProperty("speaking")]
public bool IsSpeaking;
}
}

+ 0
- 31
src/Discord.Net/WebSockets/WebSocketMessage.cs View File

@@ -1,31 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Discord.WebSockets
{
public class WebSocketMessage
{
[JsonProperty("op")]
public int Operation;
[JsonProperty("d")]
public object Payload;
[JsonProperty("t", NullValueHandling = NullValueHandling.Ignore)]
public string Type;
[JsonProperty("s", NullValueHandling = NullValueHandling.Ignore)]
public int? Sequence;
}
internal abstract class WebSocketMessage<T> : WebSocketMessage
where T : new()
{
public WebSocketMessage() { Payload = new T(); }
public WebSocketMessage(int op) { Operation = op; Payload = new T(); }
public WebSocketMessage(int op, T payload) { Operation = op; Payload = payload; }

[JsonIgnore]
public new T Payload
{
get { if (base.Payload is JToken) { base.Payload = (base.Payload as JToken).ToObject<T>(); } return (T)base.Payload; }
set { base.Payload = value; }
}
}
}

+ 0
- 4
src/Discord.Net/packages.config View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>

Loading…
Cancel
Save