@@ -2,6 +2,7 @@ | |||||
namespace Discord.Commands | namespace Discord.Commands | ||||
{ | { | ||||
//TODO: Check support for escaping | |||||
public static class CommandParser | public static class CommandParser | ||||
{ | { | ||||
private enum CommandParserPart | private enum CommandParserPart | ||||
@@ -35,6 +35,17 @@ | |||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | <TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'FullDebug|AnyCPU'"> | |||||
<DebugSymbols>true</DebugSymbols> | |||||
<OutputPath>bin\FullDebug\</OutputPath> | |||||
<DefineConstants>TRACE;DEBUG;NET45,TEST_RESPONSES</DefineConstants> | |||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||||
<WarningLevel>2</WarningLevel> | |||||
<DebugType>full</DebugType> | |||||
<PlatformTarget>AnyCPU</PlatformTarget> | |||||
<ErrorReport>prompt</ErrorReport> | |||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> | |||||
</PropertyGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | ||||
<HintPath>..\..\..\DiscordBot\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | <HintPath>..\..\..\DiscordBot\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | ||||
@@ -57,6 +68,33 @@ | |||||
<None Include="packages.config" /> | <None Include="packages.config" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Compile Include="..\Discord.Net\API\Common.cs"> | |||||
<Link>API\Common.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\Endpoints.cs"> | |||||
<Link>API\Endpoints.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\HttpException.cs"> | |||||
<Link>API\HttpException.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\Requests.cs"> | |||||
<Link>API\Requests.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\Responses.cs"> | |||||
<Link>API\Responses.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\RestClient.BuiltIn.cs"> | |||||
<Link>API\RestClient.BuiltIn.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\RestClient.cs"> | |||||
<Link>API\RestClient.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\RestClient.Events.cs"> | |||||
<Link>API\RestClient.Events.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\API\RestClient.SharpRest.cs"> | |||||
<Link>API\RestClient.SharpRest.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Audio\Opus.cs"> | <Compile Include="..\Discord.Net\Audio\Opus.cs"> | ||||
<Link>Audio\Opus.cs</Link> | <Link>Audio\Opus.cs</Link> | ||||
</Compile> | </Compile> | ||||
@@ -84,6 +122,9 @@ | |||||
<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> | ||||
@@ -150,74 +191,44 @@ | |||||
<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\Net\API\Common.cs"> | |||||
<Link>Net\API\Common.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\DiscordAPIClient.cs"> | |||||
<Link>Net\API\DiscordAPIClient.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\Endpoints.cs"> | |||||
<Link>Net\API\Endpoints.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\HttpException.cs"> | |||||
<Link>Net\API\HttpException.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\Requests.cs"> | |||||
<Link>Net\API\Requests.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\Responses.cs"> | |||||
<Link>Net\API\Responses.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\RestClient.BuiltIn.cs"> | |||||
<Link>Net\API\RestClient.BuiltIn.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\RestClient.cs"> | |||||
<Link>Net\API\RestClient.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\RestClient.Events.cs"> | |||||
<Link>Net\API\RestClient.Events.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\API\RestClient.SharpRest.cs"> | |||||
<Link>Net\API\RestClient.SharpRest.cs</Link> | |||||
</Compile> | |||||
<Compile Include="..\Discord.Net\Net\WebSockets\Commands.cs"> | |||||
<Link>Net\WebSockets\Commands.cs</Link> | |||||
<Compile Include="..\Discord.Net\TimeoutException.cs"> | |||||
<Link>TimeoutException.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\DataWebSocket.cs"> | |||||
<Link>Net\WebSockets\DataWebSocket.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Data\Commands.cs"> | |||||
<Link>WebSockets\Data\Commands.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\DataWebSockets.Events.cs"> | |||||
<Link>Net\WebSockets\DataWebSockets.Events.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Data\DataWebSocket.cs"> | |||||
<Link>WebSockets\Data\DataWebSocket.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\Events.cs"> | |||||
<Link>Net\WebSockets\Events.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Data\DataWebSockets.Events.cs"> | |||||
<Link>WebSockets\Data\DataWebSockets.Events.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\VoiceCommands.cs"> | |||||
<Link>Net\WebSockets\VoiceCommands.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Data\Events.cs"> | |||||
<Link>WebSockets\Data\Events.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\VoiceEvents.cs"> | |||||
<Link>Net\WebSockets\VoiceEvents.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Voice\Commands.cs"> | |||||
<Link>WebSockets\Voice\Commands.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\VoiceWebSocket.cs"> | |||||
<Link>Net\WebSockets\VoiceWebSocket.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Voice\Events.cs"> | |||||
<Link>WebSockets\Voice\Events.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\VoiceWebSocket.Events.cs"> | |||||
<Link>Net\WebSockets\VoiceWebSocket.Events.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Voice\VoiceWebSocket.cs"> | |||||
<Link>WebSockets\Voice\VoiceWebSocket.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\WebSocket.BuiltIn.cs"> | |||||
<Link>Net\WebSockets\WebSocket.BuiltIn.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\Voice\VoiceWebSocket.Events.cs"> | |||||
<Link>WebSockets\Voice\VoiceWebSocket.Events.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\WebSocket.cs"> | |||||
<Link>Net\WebSockets\WebSocket.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\WebSocket.BuiltIn.cs"> | |||||
<Link>WebSockets\WebSocket.BuiltIn.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\WebSocket.Events.cs"> | |||||
<Link>Net\WebSockets\WebSocket.Events.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\WebSocket.cs"> | |||||
<Link>WebSockets\WebSocket.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\Net\WebSockets\WebSocketMessage.cs"> | |||||
<Link>Net\WebSockets\WebSocketMessage.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\WebSocket.Events.cs"> | |||||
<Link>WebSockets\WebSocket.Events.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="..\Discord.Net\TimeoutException.cs"> | |||||
<Link>TimeoutException.cs</Link> | |||||
<Compile Include="..\Discord.Net\WebSockets\WebSocketMessage.cs"> | |||||
<Link>WebSockets\WebSocketMessage.cs</Link> | |||||
</Compile> | </Compile> | ||||
<Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -0,0 +1,295 @@ | |||||
//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("user")] | |||||
public UserReference User; | |||||
[JsonProperty("guild_id")] | |||||
public string GuildId; | |||||
} | |||||
public class MemberInfo : MemberReference | |||||
{ | |||||
[JsonProperty("joined_at")] | |||||
public DateTime? JoinedAt; | |||||
[JsonProperty("roles")] | |||||
public string[] Roles; | |||||
} | |||||
public class ExtendedMemberInfo : MemberInfo | |||||
{ | |||||
[JsonProperty("mute")] | |||||
public bool IsMuted; | |||||
[JsonProperty("deaf")] | |||||
public bool IsDeafened; | |||||
} | |||||
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("suppress")] | |||||
public bool? IsSuppressed; | |||||
[JsonProperty("session_id")] | |||||
public string SessionId; | |||||
[JsonProperty("self_mute")] | |||||
public bool? IsSelfMuted; | |||||
[JsonProperty("self_deaf")] | |||||
public bool? IsSelfDeafened; | |||||
[JsonProperty("mute")] | |||||
public bool IsMuted; | |||||
[JsonProperty("deaf")] | |||||
public bool IsDeafened; | |||||
[JsonProperty("token")] | |||||
public string Token; | |||||
} | |||||
//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("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; | |||||
} | |||||
//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 int Permissions; | |||||
[JsonProperty("name")] | |||||
public string Name; | |||||
[JsonProperty("id")] | |||||
public string Id; | |||||
} | |||||
//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; | |||||
} | |||||
} |
@@ -1,4 +1,4 @@ | |||||
namespace Discord.Net.API | |||||
namespace Discord.API | |||||
{ | { | ||||
internal static class Endpoints | internal static class Endpoints | ||||
{ | { | ||||
@@ -45,5 +45,6 @@ | |||||
public const string StatusActiveMaintenance = "scheduled-maintenances/active.json"; | public const string StatusActiveMaintenance = "scheduled-maintenances/active.json"; | ||||
public const string StatusUnresolvedMaintenance = "scheduled-maintenances/unresolved.json"; | public const string StatusUnresolvedMaintenance = "scheduled-maintenances/unresolved.json"; | ||||
public const string StatusUpcomingMaintenance = "scheduled-maintenances/upcoming.json"; | |||||
} | } | ||||
} | } |
@@ -1,7 +1,7 @@ | |||||
using System; | using System; | ||||
using System.Net; | using System.Net; | ||||
namespace Discord.Net.API | |||||
namespace Discord.API | |||||
{ | { | ||||
public class HttpException : Exception | public class HttpException : Exception | ||||
{ | { |
@@ -0,0 +1,142 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
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; | |||||
} | |||||
//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 string[] Roles; | |||||
} | |||||
//Messages | |||||
internal sealed class SendMessageRequest | |||||
{ | |||||
[JsonProperty("content")] | |||||
public string Content; | |||||
[JsonProperty("mentions")] | |||||
public 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 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", NullValueHandling = NullValueHandling.Ignore)] | |||||
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; | |||||
} | |||||
//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; | |||||
} | |||||
} |
@@ -1,7 +1,7 @@ | |||||
using System; | using System; | ||||
using System.Net.Http; | using System.Net.Http; | ||||
namespace Discord.Net.API | |||||
namespace Discord.API | |||||
{ | { | ||||
internal partial class RestClient | internal partial class RestClient | ||||
{ | { |
@@ -6,7 +6,7 @@ using System.Net.Http; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.Net.API | |||||
namespace Discord.API | |||||
{ | { | ||||
internal class RestSharpRestEngine : IRestEngine | internal class RestSharpRestEngine : IRestEngine | ||||
{ | { |
@@ -6,7 +6,7 @@ using System.Reflection; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.Net.API | |||||
namespace Discord.API | |||||
{ | { | ||||
internal interface IRestEngine | internal interface IRestEngine | ||||
{ | { |
@@ -1,6 +1,5 @@ | |||||
using Discord.Helpers; | |||||
using Discord.Net; | |||||
using Discord.Net.API; | |||||
using Discord.API; | |||||
using Discord.Helpers; | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | using System.Linq; | ||||
@@ -17,34 +16,54 @@ namespace Discord | |||||
public partial class DiscordClient | public partial class DiscordClient | ||||
{ | { | ||||
//Servers | |||||
/// <summary> Creates a new server with the provided name and region (see Regions). </summary> | |||||
public async Task<Server> CreateServer(string name, string region) | |||||
public const int MaxMessageSize = 2000; | |||||
//Bans | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(Member member) | |||||
=> Ban(member?.ServerId, member?.UserId); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(Server server, User user) | |||||
=> Ban(server?.Id, user?.Id); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(Server server, string userId) | |||||
=> Ban(server?.Id, userId); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(string server, User user) | |||||
=> Ban(server, user?.Id); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(string serverId, string userId) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||||
if (region == null) throw new ArgumentNullException(nameof(region)); | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
var response = await _api.CreateServer(name, region).ConfigureAwait(false); | |||||
var server = _servers.GetOrAdd(response.Id); | |||||
server.Update(response); | |||||
return server; | |||||
return _api.Ban(serverId, userId); | |||||
} | } | ||||
/// <summary> Leaves the provided server, destroying it if you are the owner. </summary> | |||||
public Task<Server> LeaveServer(Server server) | |||||
=> LeaveServer(server?.Id); | |||||
/// <summary> Leaves the provided server, destroying it if you are the owner. </summary> | |||||
public async Task<Server> LeaveServer(string serverId) | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(Member member) | |||||
=> Unban(member?.ServerId, member?.UserId); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(Server server, User user) | |||||
=> Unban(server?.Id, user?.Id); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(Server server, string userId) | |||||
=> Unban(server?.Id, userId); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(string server, User user) | |||||
=> Unban(server, user?.Id); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public async Task Unban(string serverId, string userId) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | ||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
try { await _api.LeaveServer(serverId).ConfigureAwait(false); } | |||||
try { await _api.Unban(serverId, userId).ConfigureAwait(false); } | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
return _servers.TryRemove(serverId); | |||||
} | } | ||||
//Channels | //Channels | ||||
/// <summary> Creates a new channel with the provided name and type (see ChannelTypes). </summary> | /// <summary> Creates a new channel with the provided name and type (see ChannelTypes). </summary> | ||||
public Task<Channel> CreateChannel(Server server, string name, string type) | public Task<Channel> CreateChannel(Server server, string name, string type) | ||||
@@ -62,6 +81,7 @@ namespace Discord | |||||
channel.Update(response); | channel.Update(response); | ||||
return channel; | return channel; | ||||
} | } | ||||
/// <summary> Returns the private channel with the provided user, creating one if it does not currently exist. </summary> | /// <summary> Returns the private channel with the provided user, creating one if it does not currently exist. </summary> | ||||
public Task<Channel> CreatePMChannel(string userId) => CreatePMChannel(_users[userId], userId); | public Task<Channel> CreatePMChannel(string userId) => CreatePMChannel(_users[userId], userId); | ||||
/// <summary> Returns the private channel with the provided user, creating one if it does not currently exist. </summary> | /// <summary> Returns the private channel with the provided user, creating one if it does not currently exist. </summary> | ||||
@@ -70,7 +90,7 @@ namespace Discord | |||||
public Task<Channel> CreatePMChannel(Member member) => CreatePMChannel(member.User, member.UserId); | public Task<Channel> CreatePMChannel(Member member) => CreatePMChannel(member.User, member.UserId); | ||||
private async Task<Channel> CreatePMChannel(User user, string userId) | private async Task<Channel> CreatePMChannel(User user, string userId) | ||||
{ | { | ||||
CheckReady(); | |||||
CheckReady(); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | if (userId == null) throw new ArgumentNullException(nameof(userId)); | ||||
Channel channel = null; | Channel channel = null; | ||||
@@ -85,6 +105,19 @@ namespace Discord | |||||
return channel; | return channel; | ||||
} | } | ||||
/// <summary> Edits the provided channel, changing only non-null attributes. </summary> | |||||
public Task EditChannel(Channel channel) | |||||
=> EditChannel(channel?.Id); | |||||
/// <summary> Edits the provided channel, changing only non-null attributes. </summary> | |||||
public Task EditChannel(string channelId, string name = null, string topic = null) | |||||
{ | |||||
CheckReady(); | |||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | |||||
if (topic == null) throw new ArgumentNullException(nameof(topic)); | |||||
return _api.EditChannel(channelId, name: name, topic: topic); | |||||
} | |||||
/// <summary> Destroys the provided channel. </summary> | /// <summary> Destroys the provided channel. </summary> | ||||
public Task<Channel> DestroyChannel(Channel channel) | public Task<Channel> DestroyChannel(Channel channel) | ||||
=> DestroyChannel(channel?.Id); | => DestroyChannel(channel?.Id); | ||||
@@ -99,52 +132,6 @@ namespace Discord | |||||
return _channels.TryRemove(channelId); | return _channels.TryRemove(channelId); | ||||
} | } | ||||
//Bans | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(Member member) | |||||
=> Ban(member?.ServerId, member?.UserId); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(Server server, User user) | |||||
=> Ban(server?.Id, user?.Id); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(Server server, string userId) | |||||
=> Ban(server?.Id, userId); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(string server, User user) | |||||
=> Ban(server, user?.Id); | |||||
/// <summary> Bans a user from the provided server. </summary> | |||||
public Task Ban(string serverId, string userId) | |||||
{ | |||||
CheckReady(); | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
return _api.Ban(serverId, userId); | |||||
} | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(Member member) | |||||
=> Unban(member?.ServerId, member?.UserId); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(Server server, User user) | |||||
=> Unban(server?.Id, user?.Id); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(Server server, string userId) | |||||
=> Unban(server?.Id, userId); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public Task Unban(string server, User user) | |||||
=> Unban(server, user?.Id); | |||||
/// <summary> Unbans a user from the provided server. </summary> | |||||
public async Task Unban(string serverId, string userId) | |||||
{ | |||||
CheckReady(); | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
try { await _api.Unban(serverId, userId).ConfigureAwait(false); } | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||||
} | |||||
//Invites | //Invites | ||||
/// <summary> Creates a new invite to the default channel of the provided server. </summary> | /// <summary> Creates a new invite to the default channel of the provided server. </summary> | ||||
/// <param name="maxAge"> Time (in seconds) until the invite expires. Set to 0 to never expire. </param> | /// <param name="maxAge"> Time (in seconds) until the invite expires. Set to 0 to never expire. </param> | ||||
@@ -178,14 +165,29 @@ namespace Discord | |||||
return invite; | return invite; | ||||
} | } | ||||
/// <summary> Deletes the provided invite. </summary> | |||||
public async Task DestroyInvite(string inviteId) | |||||
{ | |||||
CheckReady(); | |||||
if (inviteId == null) throw new ArgumentNullException(nameof(inviteId)); | |||||
try | |||||
{ | |||||
//Check if this is a human-readable link and get its ID | |||||
var response = await _api.GetInvite(inviteId).ConfigureAwait(false); | |||||
await _api.DeleteInvite(response.Code).ConfigureAwait(false); | |||||
} | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||||
} | |||||
/// <summary> Gets more info about the provided invite code. </summary> | /// <summary> Gets more info about the provided invite code. </summary> | ||||
/// <remarks> Supported formats: inviteCode, xkcdCode, https://discord.gg/inviteCode, https://discord.gg/xkcdCode </remarks> | /// <remarks> Supported formats: inviteCode, xkcdCode, https://discord.gg/inviteCode, https://discord.gg/xkcdCode </remarks> | ||||
public async Task<Invite> GetInvite(string id) | |||||
public async Task<Invite> GetInvite(string inviteIdOrXkcd) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (id == null) throw new ArgumentNullException(nameof(id)); | |||||
if (inviteIdOrXkcd == null) throw new ArgumentNullException(nameof(inviteIdOrXkcd)); | |||||
var response = await _api.GetInvite(id).ConfigureAwait(false); | |||||
var response = await _api.GetInvite(inviteIdOrXkcd).ConfigureAwait(false); | |||||
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id); | var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id); | ||||
invite.Update(response); | invite.Update(response); | ||||
return invite; | return invite; | ||||
@@ -200,39 +202,42 @@ namespace Discord | |||||
return _api.AcceptInvite(invite.Id); | return _api.AcceptInvite(invite.Id); | ||||
} | } | ||||
/// <summary> Accepts the provided invite. </summary> | /// <summary> Accepts the provided invite. </summary> | ||||
public async Task AcceptInvite(string code) | |||||
public async Task AcceptInvite(string inviteId) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (code == null) throw new ArgumentNullException(nameof(code)); | |||||
if (inviteId == null) throw new ArgumentNullException(nameof(inviteId)); | |||||
//Remove trailing slash and any non-code url parts | //Remove trailing slash and any non-code url parts | ||||
if (code.Length > 0 && code[code.Length - 1] == '/') | |||||
code = code.Substring(0, code.Length - 1); | |||||
int index = code.LastIndexOf('/'); | |||||
if (inviteId.Length > 0 && inviteId[inviteId.Length - 1] == '/') | |||||
inviteId = inviteId.Substring(0, inviteId.Length - 1); | |||||
int index = inviteId.LastIndexOf('/'); | |||||
if (index >= 0) | if (index >= 0) | ||||
code = code.Substring(index + 1); | |||||
inviteId = inviteId.Substring(index + 1); | |||||
//Check if this is a human-readable link and get its ID | //Check if this is a human-readable link and get its ID | ||||
var invite = await GetInvite(code).ConfigureAwait(false); | |||||
var invite = await GetInvite(inviteId).ConfigureAwait(false); | |||||
await _api.AcceptInvite(invite.Id).ConfigureAwait(false); | await _api.AcceptInvite(invite.Id).ConfigureAwait(false); | ||||
} | } | ||||
/// <summary> Deletes the provided invite. </summary> | |||||
public async Task DeleteInvite(string code) | |||||
//Members | |||||
public Task EditMember(Member member, bool? mute = null, bool? deaf = null, string[] roles = null) | |||||
=> EditMember(member?.ServerId, member?.UserId, mute, deaf, roles); | |||||
public Task EditMember(Server server, User user, bool? mute = null, bool? deaf = null, string[] roles = null) | |||||
=> EditMember(server?.Id, user?.Id, mute, deaf, roles); | |||||
public Task EditMember(Server server, string userId, bool? mute = null, bool? deaf = null, string[] roles = null) | |||||
=> EditMember(server?.Id, userId, mute, deaf, roles); | |||||
public Task EditMember(string serverId, User user, bool? mute = null, bool? deaf = null, string[] roles = null) | |||||
=> EditMember(serverId, user?.Id, mute, deaf, roles); | |||||
public Task EditMember(string serverId, string userId, bool? mute = null, bool? deaf = null, string[] roles = null) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (code == null) throw new ArgumentNullException(nameof(code)); | |||||
if (serverId == null) throw new NullReferenceException(nameof(serverId)); | |||||
if (userId == null) throw new NullReferenceException(nameof(userId)); | |||||
try | |||||
{ | |||||
//Check if this is a human-readable link and get its ID | |||||
var response = await _api.GetInvite(code).ConfigureAwait(false); | |||||
await _api.DeleteInvite(response.Code).ConfigureAwait(false); | |||||
} | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||||
return _api.EditMember(serverId, userId, mute, deaf, roles); | |||||
} | } | ||||
//Chat | |||||
//Messages | |||||
/// <summary> Sends a message to the provided channel. </summary> | /// <summary> Sends a message to the provided channel. </summary> | ||||
public Task<Message[]> SendMessage(Channel channel, string text) | public Task<Message[]> SendMessage(Channel channel, string text) | ||||
=> SendMessage(channel?.Id, text, new string[0]); | => SendMessage(channel?.Id, text, new string[0]); | ||||
@@ -252,18 +257,18 @@ namespace Discord | |||||
if (text == null) throw new ArgumentNullException(nameof(text)); | if (text == null) throw new ArgumentNullException(nameof(text)); | ||||
if (mentions == null) throw new ArgumentNullException(nameof(mentions)); | if (mentions == null) throw new ArgumentNullException(nameof(mentions)); | ||||
int blockCount = (int)Math.Ceiling(text.Length / (double)DiscordAPIClient.MaxMessageSize); | |||||
int blockCount = (int)Math.Ceiling(text.Length / (double)MaxMessageSize); | |||||
Message[] result = new Message[blockCount]; | Message[] result = new Message[blockCount]; | ||||
for (int i = 0; i < blockCount; i++) | for (int i = 0; i < blockCount; i++) | ||||
{ | { | ||||
int index = i * DiscordAPIClient.MaxMessageSize; | |||||
int index = i * MaxMessageSize; | |||||
string blockText = text.Substring(index, Math.Min(2000, text.Length - index)); | string blockText = text.Substring(index, Math.Min(2000, text.Length - index)); | ||||
var nonce = GenerateNonce(); | var nonce = GenerateNonce(); | ||||
if (_config.UseMessageQueue) | if (_config.UseMessageQueue) | ||||
{ | { | ||||
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 Net.API.Message | |||||
msg.Update(new API.Message | |||||
{ | { | ||||
Content = blockText, | Content = blockText, | ||||
Timestamp = DateTime.UtcNow, | Timestamp = DateTime.UtcNow, | ||||
@@ -302,35 +307,37 @@ namespace Discord | |||||
return await SendMessage(channel, text, new string[0]).ConfigureAwait(false); | return await SendMessage(channel, text, new string[0]).ConfigureAwait(false); | ||||
} | } | ||||
/// <summary> Edits a message the provided message. </summary> | |||||
public Task EditMessage(Message message, string text) | |||||
=> EditMessage(message?.ChannelId, message?.Id, text, new string[0]); | |||||
/// <summary> Edits a message the provided message. </summary> | |||||
public Task EditMessage(Channel channel, string messageId, string text) | |||||
=> EditMessage(channel?.Id, messageId, text, new string[0]); | |||||
/// <summary> Edits a message the provided message. </summary> | |||||
public Task EditMessage(string channelId, string messageId, string text) | |||||
=> EditMessage(channelId, messageId, text, new string[0]); | |||||
/// <summary> Edits a message the provided message, mentioning certain users. </summary> | |||||
/// <summary> Sends a file to the provided channel. </summary> | |||||
public Task SendFile(Channel channel, string filePath) | |||||
=> SendFile(channel?.Id, filePath); | |||||
/// <summary> Sends a file to the provided channel. </summary> | |||||
public Task SendFile(string channelId, string filePath) | |||||
{ | |||||
CheckReady(); | |||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | |||||
if (filePath == null) throw new ArgumentNullException(nameof(filePath)); | |||||
return _api.SendFile(channelId, filePath); | |||||
} | |||||
/// <summary> Edits the provided message, changing only non-null attributes. </summary> | |||||
/// <remarks> While not required, it is recommended to include a mention reference in the text (see Mention.User). </remarks> | /// <remarks> While not required, it is recommended to include a mention reference in the text (see Mention.User). </remarks> | ||||
public Task EditMessage(Message message, string text, string[] mentions) | |||||
public Task EditMessage(Message message, string text = null, string[] mentions = null) | |||||
=> EditMessage(message?.ChannelId, message?.Id, text, mentions); | => EditMessage(message?.ChannelId, message?.Id, text, mentions); | ||||
/// <summary> Edits a message the provided message, mentioning certain users. </summary> | |||||
/// <summary> Edits the provided message, changing only non-null attributes. </summary> | |||||
/// <remarks> While not required, it is recommended to include a mention reference in the text (see Mention.User). </remarks> | /// <remarks> While not required, it is recommended to include a mention reference in the text (see Mention.User). </remarks> | ||||
public Task EditMessage(Channel channel, string messageId, string text, string[] mentions) | |||||
public Task EditMessage(Channel channel, string messageId, string text = null, string[] mentions = null) | |||||
=> EditMessage(channel?.Id, messageId, text, mentions); | => EditMessage(channel?.Id, messageId, text, mentions); | ||||
/// <summary> Edits a message the provided message, mentioning certain users. </summary> | |||||
/// <summary> Edits the provided message, changing only non-null attributes. </summary> | |||||
/// <remarks> While not required, it is recommended to include a mention reference in the text (see Mention.User). </remarks> | /// <remarks> While not required, it is recommended to include a mention reference in the text (see Mention.User). </remarks> | ||||
public async Task EditMessage(string channelId, string messageId, string text, string[] mentions) | |||||
public async Task EditMessage(string channelId, string messageId, string text = null, string[] mentions = null) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | ||||
if (messageId == null) throw new ArgumentNullException(nameof(messageId)); | if (messageId == null) throw new ArgumentNullException(nameof(messageId)); | ||||
if (text == null) throw new ArgumentNullException(nameof(text)); | |||||
if (mentions == null) throw new ArgumentNullException(nameof(mentions)); | |||||
if (text.Length > DiscordAPIClient.MaxMessageSize) | |||||
text = text.Substring(0, DiscordAPIClient.MaxMessageSize); | |||||
if (text != null && text.Length > MaxMessageSize) | |||||
text = text.Substring(0, MaxMessageSize); | |||||
var model = await _api.EditMessage(messageId, channelId, text, mentions).ConfigureAwait(false); | var model = await _api.EditMessage(messageId, channelId, text, mentions).ConfigureAwait(false); | ||||
var msg = _messages[messageId]; | var msg = _messages[messageId]; | ||||
@@ -383,19 +390,6 @@ namespace Discord | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
} | } | ||||
} | } | ||||
/// <summary> Sends a file to the provided channel. </summary> | |||||
public Task SendFile(Channel channel, string filePath) | |||||
=> SendFile(channel?.Id, filePath); | |||||
/// <summary> Sends a file to the provided channel. </summary> | |||||
public Task SendFile(string channelId, string filePath) | |||||
{ | |||||
CheckReady(); | |||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | |||||
if (filePath == null) throw new ArgumentNullException(nameof(filePath)); | |||||
return _api.SendFile(channelId, filePath); | |||||
} | |||||
/// <summary> Downloads last count messages from the server, starting at beforeMessageId if it's provided. </summary> | /// <summary> Downloads last count messages from the server, starting at beforeMessageId if it's provided. </summary> | ||||
public Task<Message[]> DownloadMessages(Channel channel, int count, string beforeMessageId = null, bool cache = true) | public Task<Message[]> DownloadMessages(Channel channel, int count, string beforeMessageId = null, bool cache = true) | ||||
@@ -449,113 +443,6 @@ namespace Discord | |||||
return null; | return null; | ||||
} | } | ||||
//Roles | |||||
/// <summary>Note: due to current API limitations, the created role cannot be returned. </summary> | |||||
public Task CreateRole(Server server) | |||||
=> CreateRole(server?.Id); | |||||
/// <summary>Note: due to current API limitations, the created role cannot be returned. </summary> | |||||
public Task CreateRole(string serverId) | |||||
{ | |||||
CheckReady(); | |||||
if (serverId == null) throw new NullReferenceException(nameof(serverId)); | |||||
return _api.CreateRole(serverId); | |||||
} | |||||
public Task RenameRole(Role role, string newName) | |||||
=> RenameRole(role?.ServerId, role?.Id, newName); | |||||
public Task RenameRole(string serverId, string roleId, string newName) | |||||
{ | |||||
CheckReady(); | |||||
if (roleId == null) throw new NullReferenceException(nameof(roleId)); | |||||
if (newName == null) throw new NullReferenceException(nameof(newName)); | |||||
return _api.RenameRole(serverId, roleId, newName); | |||||
} | |||||
public Task DeleteRole(Role role) | |||||
=> DeleteRole(role?.ServerId, role?.Id); | |||||
public Task DeleteRole(string serverId, string roleId) | |||||
{ | |||||
CheckReady(); | |||||
if (roleId == null) throw new NullReferenceException(nameof(roleId)); | |||||
return _api.DeleteRole(serverId, roleId); | |||||
} | |||||
public Task AddRoleMember(Role role, string serverId, string userId) | |||||
=> AddRoleMember(role?.Id, GetMember(serverId, userId)); | |||||
public Task AddRoleMember(Role role, string serverId, User user) | |||||
=> AddRoleMember(role?.Id, GetMember(serverId, user)); | |||||
public Task AddRoleMember(Role role, Server server, string userId) | |||||
=> AddRoleMember(role?.Id, GetMember(server, userId)); | |||||
public Task AddRoleMember(Role role, Server server, User user) | |||||
=> AddRoleMember(role?.Id, GetMember(server, user)); | |||||
public Task AddRoleMember(Role role, Member member) | |||||
=> AddRoleMember(role?.Id, member); | |||||
public Task AddRoleMember(string roleId, string serverId, string userId) | |||||
=> AddRoleMember(roleId, GetMember(serverId, userId)); | |||||
public Task AddRoleMember(string roleId, string serverId, User user) | |||||
=> AddRoleMember(roleId, GetMember(serverId, user)); | |||||
public Task AddRoleMember(string roleId, Server server, string userId) | |||||
=> AddRoleMember(roleId, GetMember(server, userId)); | |||||
public Task AddRoleMember(string roleId, Server server, User user) | |||||
=> AddRoleMember(roleId, GetMember(server, user)); | |||||
public Task AddRoleMember(string roleId, Member member) | |||||
{ | |||||
CheckReady(); | |||||
if (roleId == null) throw new NullReferenceException(nameof(roleId)); | |||||
if (member == null) throw new NullReferenceException(nameof(member)); | |||||
if (!member.RoleIds.Contains(roleId)) | |||||
{ | |||||
var oldRoles = member.RoleIds; | |||||
string[] newRoles = new string[oldRoles.Length + 1]; | |||||
for (int i = 0; i < oldRoles.Length; i++) | |||||
newRoles[i] = oldRoles[i]; | |||||
return _api.SetMemberRoles(member.ServerId, member.UserId, newRoles); | |||||
} | |||||
return TaskHelper.CompletedTask; | |||||
} | |||||
public Task RemoveRoleMember(Role role, string serverId, string userId) | |||||
=> RemoveRoleMember(role?.Id, GetMember(serverId, userId)); | |||||
public Task RemoveRoleMember(Role role, string serverId, User user) | |||||
=> RemoveRoleMember(role?.Id, GetMember(serverId, user)); | |||||
public Task RemoveRoleMember(Role role, Server server, string userId) | |||||
=> RemoveRoleMember(role?.Id, GetMember(server, userId)); | |||||
public Task RemoveRoleMember(Role role, Server server, User user) | |||||
=> RemoveRoleMember(role?.Id, GetMember(server, user)); | |||||
public Task RemoveRoleMember(Role role, Member member) | |||||
=> RemoveRoleMember(role?.Id, member); | |||||
public Task RemoveRoleMember(string roleId, string serverId, string userId) | |||||
=> RemoveRoleMember(roleId, GetMember(serverId, userId)); | |||||
public Task RemoveRoleMember(string roleId, string serverId, User user) | |||||
=> RemoveRoleMember(roleId, GetMember(serverId, user)); | |||||
public Task RemoveRoleMember(string roleId, Server server, string userId) | |||||
=> RemoveRoleMember(roleId, GetMember(server, userId)); | |||||
public Task RemoveRoleMember(string roleId, Server server, User user) | |||||
=> RemoveRoleMember(roleId, GetMember(server, user)); | |||||
public Task RemoveRoleMember(string roleId, Member member) | |||||
{ | |||||
CheckReady(); | |||||
if (roleId == null) throw new NullReferenceException(nameof(roleId)); | |||||
if (member == null) throw new NullReferenceException(nameof(member)); | |||||
if (member.RoleIds.Contains(roleId)) | |||||
{ | |||||
var oldRoles = member.RoleIds; | |||||
string[] newRoles = new string[oldRoles.Length - 1]; | |||||
for (int i = 0, j = 0; i < oldRoles.Length; i++) | |||||
{ | |||||
if (oldRoles[i] != roleId) | |||||
newRoles[j++] = oldRoles[i]; | |||||
} | |||||
return _api.SetMemberRoles(member.ServerId, member.UserId, newRoles); | |||||
} | |||||
return TaskHelper.CompletedTask; | |||||
} | |||||
//Permissions | //Permissions | ||||
public Task SetChannelUserPermissions(Channel channel, Member member, PackedPermissions allow, PackedPermissions deny) | public Task SetChannelUserPermissions(Channel channel, Member member, PackedPermissions allow, PackedPermissions deny) | ||||
=> SetChannelPermissions(channel?.Id, member?.UserId, "member", allow, deny); | => SetChannelPermissions(channel?.Id, member?.UserId, "member", allow, deny); | ||||
@@ -585,7 +472,7 @@ namespace Discord | |||||
if (channelId == null) throw new NullReferenceException(nameof(channelId)); | if (channelId == null) throw new NullReferenceException(nameof(channelId)); | ||||
if (userOrRoleId == null) throw new NullReferenceException(nameof(userOrRoleId)); | if (userOrRoleId == null) throw new NullReferenceException(nameof(userOrRoleId)); | ||||
return _api.SetChannelPermissions(channelId, userOrRoleId, idType, allow, deny); | |||||
return _api.SetChannelPermissions(channelId, userOrRoleId, idType, allow.RawValue, deny.RawValue); | |||||
//TODO: Remove permission from cache | //TODO: Remove permission from cache | ||||
} | } | ||||
@@ -625,128 +512,90 @@ namespace Discord | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
} | } | ||||
//Voice | |||||
/// <summary> Mutes a user on the provided server. </summary> | |||||
public Task Mute(Member member) | |||||
=> Mute(member?.ServerId, member?.UserId); | |||||
/// <summary> Mutes a user on the provided server. </summary> | |||||
public Task Mute(Server server, User user) | |||||
=> Mute(server?.Id, user?.Id); | |||||
/// <summary> Mutes a user on the provided server. </summary> | |||||
public Task Mute(Server server, string userId) | |||||
=> Mute(server?.Id, userId); | |||||
/// <summary> Mutes a user on the provided server. </summary> | |||||
public Task Mute(string server, User user) | |||||
=> Mute(server, user?.Id); | |||||
/// <summary> Mutes a user on the provided server. </summary> | |||||
public Task Mute(string serverId, string userId) | |||||
//Profile | |||||
public Task<EditProfileResponse> EditProfile(string currentPassword, | |||||
string username = null, string email = null, string password = null, | |||||
AvatarImageType avatarType = AvatarImageType.Png, byte[] avatar = null) | |||||
{ | { | ||||
CheckReady(); | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword)); | |||||
return _api.Mute(serverId, userId); | |||||
return _api.EditProfile(currentPassword, username: username, email: email, password: password, | |||||
avatarType: avatarType, avatar: avatar); | |||||
} | } | ||||
/// <summary> Mutes a user on the provided server. </summary> | |||||
public Task Unmute(Member member) | |||||
=> Unmute(member?.ServerId, member?.UserId); | |||||
/// <summary> Unmutes a user on the provided server. </summary> | |||||
public Task Unmute(Server server, User user) | |||||
=> Unmute(server?.Id, user?.Id); | |||||
/// <summary> Unmutes a user on the provided server. </summary> | |||||
public Task Unmute(Server server, string userId) | |||||
=> Unmute(server?.Id, userId); | |||||
/// <summary> Unmutes a user on the provided server. </summary> | |||||
public Task Unmute(string server, User user) | |||||
=> Unmute(server, user?.Id); | |||||
/// <summary> Unmutes a user on the provided server. </summary> | |||||
public Task Unmute(string serverId, string userId) | |||||
//Roles | |||||
/// <summary> Note: due to current API limitations, the created role cannot be returned. </summary> | |||||
public Task CreateRole(Server server) | |||||
=> CreateRole(server?.Id); | |||||
/// <summary> Note: due to current API limitations, the created role cannot be returned. </summary> | |||||
public Task CreateRole(string serverId) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
if (serverId == null) throw new NullReferenceException(nameof(serverId)); | |||||
return _api.Unmute(serverId, userId); | |||||
return _api.CreateRole(serverId); | |||||
} | } | ||||
/// <summary> Deafens a user on the provided server. </summary> | |||||
public Task Deafen(Member member) | |||||
=> Deafen(member?.ServerId, member?.UserId); | |||||
/// <summary> Deafens a user on the provided server. </summary> | |||||
public Task Deafen(Server server, User user) | |||||
=> Deafen(server?.Id, user?.Id); | |||||
/// <summary> Deafens a user on the provided server. </summary> | |||||
public Task Deafen(Server server, string userId) | |||||
=> Deafen(server?.Id, userId); | |||||
/// <summary> Deafens a user on the provided server. </summary> | |||||
public Task Deafen(string server, User user) | |||||
=> Deafen(server, user?.Id); | |||||
/// <summary> Deafens a user on the provided server. </summary> | |||||
public Task Deafen(string serverId, string userId) | |||||
public Task EditRole(Role role, string newName) | |||||
=> EditRole(role?.ServerId, role?.Id, newName); | |||||
public Task EditRole(string serverId, string roleId, string name = null, PackedPermissions permissions = null) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
if (serverId == null) throw new NullReferenceException(nameof(serverId)); | |||||
if (roleId == null) throw new NullReferenceException(nameof(roleId)); | |||||
return _api.Deafen(serverId, userId); | |||||
return _api.EditRole(serverId, roleId, name: name, permissions: permissions?.RawValue); | |||||
} | } | ||||
/// <summary> Undeafens a user on the provided server. </summary> | |||||
public Task Undeafen(Member member) | |||||
=> Undeafen(member?.ServerId, member?.UserId); | |||||
/// <summary> Undeafens a user on the provided server. </summary> | |||||
public Task Undeafen(Server server, User user) | |||||
=> Undeafen(server?.Id, user?.Id); | |||||
/// <summary> Undeafens a user on the provided server. </summary> | |||||
public Task Undeafen(Server server, string userId) | |||||
=> Undeafen(server?.Id, userId); | |||||
/// <summary> Undeafens a user on the provided server. </summary> | |||||
public Task Undeafen(string server, User user) | |||||
=> Undeafen(server, user?.Id); | |||||
/// <summary> Undeafens a user on the provided server. </summary> | |||||
public Task Undeafen(string serverId, string userId) | |||||
public Task DeleteRole(Role role) | |||||
=> DeleteRole(role?.ServerId, role?.Id); | |||||
public Task DeleteRole(string serverId, string roleId) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | |||||
if (serverId == null) throw new NullReferenceException(nameof(serverId)); | |||||
if (roleId == null) throw new NullReferenceException(nameof(roleId)); | |||||
return _api.Undeafen(serverId, userId); | |||||
return _api.DeleteRole(serverId, roleId); | |||||
} | } | ||||
//Profile | |||||
/// <summary> Changes your username to newName. </summary> | |||||
public async Task ChangeUsername(string newName, string currentEmail, string currentPassword) | |||||
{ | |||||
CheckReady(); | |||||
var response = await _api.ChangeUsername(newName, currentEmail, currentPassword).ConfigureAwait(false); | |||||
_currentUser.Update(response); | |||||
foreach (var membership in _currentUser.Memberships) | |||||
membership.Update(response); | |||||
} | |||||
/// <summary> Changes your email to newEmail. </summary> | |||||
public async Task ChangeEmail(string newEmail, string currentPassword) | |||||
//Servers | |||||
/// <summary> Creates a new server with the provided name and region (see Regions). </summary> | |||||
public async Task<Server> CreateServer(string name, string region) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
var response = await _api.ChangeEmail(newEmail, currentPassword).ConfigureAwait(false); | |||||
_currentUser.Update(response); | |||||
if (name == null) throw new ArgumentNullException(nameof(name)); | |||||
if (region == null) throw new ArgumentNullException(nameof(region)); | |||||
var response = await _api.CreateServer(name, region).ConfigureAwait(false); | |||||
var server = _servers.GetOrAdd(response.Id); | |||||
server.Update(response); | |||||
return server; | |||||
} | } | ||||
/// <summary> Changes your password to newPassword. </summary> | |||||
public async Task ChangePassword(string newPassword, string currentEmail, string currentPassword) | |||||
/// <summary> Edits the provided server, changing only non-null attributes. </summary> | |||||
public Task EditServer(Server server) | |||||
=> EditServer(server?.Id); | |||||
/// <summary> Edits the provided server, changing only non-null attributes. </summary> | |||||
public Task EditServer(string serverId, string name = null, string region = null) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
await _api.ChangePassword(newPassword, currentEmail, currentPassword).ConfigureAwait(false); | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
return _api.EditServer(serverId, name: name, region: region); | |||||
} | } | ||||
/// <summary> Changes your avatar. </summary> | |||||
/// <remarks>Only supports PNG and JPEG (see AvatarImageType)</remarks> | |||||
public async Task ChangeAvatar(AvatarImageType imageType, byte[] bytes, string currentEmail, string currentPassword) | |||||
/// <summary> Leaves the provided server, destroying it if you are the owner. </summary> | |||||
public Task<Server> LeaveServer(Server server) | |||||
=> LeaveServer(server?.Id); | |||||
/// <summary> Leaves the provided server, destroying it if you are the owner. </summary> | |||||
public async Task<Server> LeaveServer(string serverId) | |||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
var response = await _api.ChangeAvatar(imageType, bytes, currentEmail, currentPassword).ConfigureAwait(false); | |||||
_currentUser.Update(response); | |||||
foreach (var membership in _currentUser.Memberships) | |||||
membership.Update(response); | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
try { await _api.LeaveServer(serverId).ConfigureAwait(false); } | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | |||||
return _servers.TryRemove(serverId); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
using Discord.Helpers; | using Discord.Helpers; | ||||
using Discord.WebSockets; | |||||
using System; | using System; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -36,7 +37,7 @@ namespace Discord | |||||
{ | { | ||||
CheckReady(checkVoice: true); | CheckReady(checkVoice: true); | ||||
if (_voiceSocket.State != Net.WebSockets.WebSocketState.Disconnected) | |||||
if (_voiceSocket.State != WebSocketState.Disconnected) | |||||
{ | { | ||||
var serverId = _voiceSocket.CurrentVoiceServerId; | var serverId = _voiceSocket.CurrentVoiceServerId; | ||||
if (serverId != null) | if (serverId != null) | ||||
@@ -1,8 +1,8 @@ | |||||
using Discord.Collections; | |||||
using Discord.API; | |||||
using Discord.Collections; | |||||
using Discord.Helpers; | using Discord.Helpers; | ||||
using Discord.Net; | |||||
using Discord.Net.API; | |||||
using Discord.Net.WebSockets; | |||||
using Discord.WebSockets; | |||||
using Discord.WebSockets.Data; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
@@ -10,6 +10,7 @@ using System.Net; | |||||
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 | ||||
{ | { | ||||
@@ -279,7 +280,7 @@ namespace Discord | |||||
//Global | //Global | ||||
case "READY": //Resync | case "READY": //Resync | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.Ready>(_serializer); | |||||
var data = e.Payload.ToObject<ReadyEvent>(_serializer); | |||||
_currentUserId = data.User.Id; | _currentUserId = data.User.Id; | ||||
_currentUser = _users.GetOrAdd(data.User.Id); | _currentUser = _users.GetOrAdd(data.User.Id); | ||||
_currentUser.Update(data.User); | _currentUser.Update(data.User); | ||||
@@ -303,7 +304,7 @@ namespace Discord | |||||
//Servers | //Servers | ||||
case "GUILD_CREATE": | case "GUILD_CREATE": | ||||
{ | { | ||||
var model = e.Payload.ToObject<Events.GuildCreate>(_serializer); | |||||
var model = e.Payload.ToObject<GuildCreateEvent>(_serializer); | |||||
var server = _servers.GetOrAdd(model.Id); | var server = _servers.GetOrAdd(model.Id); | ||||
server.Update(model); | server.Update(model); | ||||
RaiseServerCreated(server); | RaiseServerCreated(server); | ||||
@@ -311,7 +312,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_UPDATE": | case "GUILD_UPDATE": | ||||
{ | { | ||||
var model = e.Payload.ToObject<Events.GuildUpdate>(_serializer); | |||||
var model = e.Payload.ToObject<GuildUpdateEvent>(_serializer); | |||||
var server = _servers[model.Id]; | var server = _servers[model.Id]; | ||||
if (server != null) | if (server != null) | ||||
{ | { | ||||
@@ -322,7 +323,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_DELETE": | case "GUILD_DELETE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildDelete>(_serializer); | |||||
var data = e.Payload.ToObject<GuildDeleteEvent>(_serializer); | |||||
var server = _servers.TryRemove(data.Id); | var server = _servers.TryRemove(data.Id); | ||||
if (server != null) | if (server != null) | ||||
RaiseServerDestroyed(server); | RaiseServerDestroyed(server); | ||||
@@ -332,7 +333,7 @@ namespace Discord | |||||
//Channels | //Channels | ||||
case "CHANNEL_CREATE": | case "CHANNEL_CREATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.ChannelCreate>(_serializer); | |||||
var data = e.Payload.ToObject<ChannelCreateEvent>(_serializer); | |||||
Channel channel; | Channel channel; | ||||
if (data.IsPrivate) | if (data.IsPrivate) | ||||
{ | { | ||||
@@ -348,7 +349,7 @@ namespace Discord | |||||
break; | break; | ||||
case "CHANNEL_UPDATE": | case "CHANNEL_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.ChannelUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<ChannelUpdateEvent>(_serializer); | |||||
var channel = _channels[data.Id]; | var channel = _channels[data.Id]; | ||||
if (channel != null) | if (channel != null) | ||||
{ | { | ||||
@@ -359,7 +360,7 @@ namespace Discord | |||||
break; | break; | ||||
case "CHANNEL_DELETE": | case "CHANNEL_DELETE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.ChannelDelete>(_serializer); | |||||
var data = e.Payload.ToObject<ChannelDeleteEvent>(_serializer); | |||||
var channel = _channels.TryRemove(data.Id); | var channel = _channels.TryRemove(data.Id); | ||||
if (channel != null) | if (channel != null) | ||||
RaiseChannelDestroyed(channel); | RaiseChannelDestroyed(channel); | ||||
@@ -369,7 +370,7 @@ namespace Discord | |||||
//Members | //Members | ||||
case "GUILD_MEMBER_ADD": | case "GUILD_MEMBER_ADD": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildMemberAdd>(_serializer); | |||||
var data = e.Payload.ToObject<GuildMemberAddEvent>(_serializer); | |||||
var user = _users.GetOrAdd(data.User.Id); | var user = _users.GetOrAdd(data.User.Id); | ||||
var member = _members.GetOrAdd(data.User.Id, data.GuildId); | var member = _members.GetOrAdd(data.User.Id, data.GuildId); | ||||
user.Update(data.User); | user.Update(data.User); | ||||
@@ -381,7 +382,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_MEMBER_UPDATE": | case "GUILD_MEMBER_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildMemberUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<GuildMemberUpdateEvent>(_serializer); | |||||
var member = _members[data.User.Id, data.GuildId]; | var member = _members[data.User.Id, data.GuildId]; | ||||
if (member != null) | if (member != null) | ||||
{ | { | ||||
@@ -392,7 +393,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_MEMBER_REMOVE": | case "GUILD_MEMBER_REMOVE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildMemberRemove>(_serializer); | |||||
var data = e.Payload.ToObject<GuildMemberRemoveEvent>(_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); | ||||
@@ -402,7 +403,7 @@ namespace Discord | |||||
//Roles | //Roles | ||||
case "GUILD_ROLE_CREATE": | case "GUILD_ROLE_CREATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildRoleCreate>(_serializer); | |||||
var data = e.Payload.ToObject<GuildRoleCreateEvent>(_serializer); | |||||
var role = _roles.GetOrAdd(data.Data.Id, data.GuildId); | var role = _roles.GetOrAdd(data.Data.Id, data.GuildId); | ||||
role.Update(data.Data); | role.Update(data.Data); | ||||
RaiseRoleUpdated(role); | RaiseRoleUpdated(role); | ||||
@@ -410,7 +411,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_ROLE_UPDATE": | case "GUILD_ROLE_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildRoleUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<GuildRoleUpdateEvent>(_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); | ||||
@@ -419,7 +420,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_ROLE_DELETE": | case "GUILD_ROLE_DELETE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildRoleDelete>(_serializer); | |||||
var data = e.Payload.ToObject<GuildRoleDeleteEvent>(_serializer); | |||||
var role = _roles.TryRemove(data.RoleId); | var role = _roles.TryRemove(data.RoleId); | ||||
if (role != null) | if (role != null) | ||||
RaiseRoleDeleted(role); | RaiseRoleDeleted(role); | ||||
@@ -429,7 +430,7 @@ namespace Discord | |||||
//Bans | //Bans | ||||
case "GUILD_BAN_ADD": | case "GUILD_BAN_ADD": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildBanAdd>(_serializer); | |||||
var data = e.Payload.ToObject<GuildBanAddEvent>(_serializer); | |||||
var server = _servers[data.GuildId]; | var server = _servers[data.GuildId]; | ||||
if (server != null) | if (server != null) | ||||
{ | { | ||||
@@ -440,7 +441,7 @@ namespace Discord | |||||
break; | break; | ||||
case "GUILD_BAN_REMOVE": | case "GUILD_BAN_REMOVE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.GuildBanRemove>(_serializer); | |||||
var data = e.Payload.ToObject<GuildBanRemoveEvent>(_serializer); | |||||
var server = _servers[data.GuildId]; | var server = _servers[data.GuildId]; | ||||
if (server != null && server.RemoveBan(data.UserId)) | if (server != null && server.RemoveBan(data.UserId)) | ||||
RaiseBanRemoved(data.UserId, server); | RaiseBanRemoved(data.UserId, server); | ||||
@@ -450,7 +451,7 @@ namespace Discord | |||||
//Messages | //Messages | ||||
case "MESSAGE_CREATE": | case "MESSAGE_CREATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.MessageCreate>(_serializer); | |||||
var data = e.Payload.ToObject<MessageCreateEvent>(_serializer); | |||||
Message msg = null; | Message msg = null; | ||||
bool wasLocal = _config.UseMessageQueue && data.Author.Id == _currentUserId && data.Nonce != null; | bool wasLocal = _config.UseMessageQueue && data.Author.Id == _currentUserId && data.Nonce != null; | ||||
@@ -490,7 +491,7 @@ namespace Discord | |||||
break; | break; | ||||
case "MESSAGE_UPDATE": | case "MESSAGE_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.MessageUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<MessageUpdateEvent>(_serializer); | |||||
var msg = _messages[data.Id]; | var msg = _messages[data.Id]; | ||||
if (msg != null) | if (msg != null) | ||||
{ | { | ||||
@@ -501,7 +502,7 @@ namespace Discord | |||||
break; | break; | ||||
case "MESSAGE_DELETE": | case "MESSAGE_DELETE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.MessageDelete>(_serializer); | |||||
var data = e.Payload.ToObject<MessageDeleteEvent>(_serializer); | |||||
var msg = _messages.TryRemove(data.Id); | var msg = _messages.TryRemove(data.Id); | ||||
if (msg != null) | if (msg != null) | ||||
RaiseMessageDeleted(msg); | RaiseMessageDeleted(msg); | ||||
@@ -509,7 +510,7 @@ namespace Discord | |||||
break; | break; | ||||
case "MESSAGE_ACK": | case "MESSAGE_ACK": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.MessageAck>(_serializer); | |||||
var data = e.Payload.ToObject<MessageAckEvent>(_serializer); | |||||
var msg = GetMessage(data.MessageId); | var msg = GetMessage(data.MessageId); | ||||
if (msg != null) | if (msg != null) | ||||
RaiseMessageReadRemotely(msg); | RaiseMessageReadRemotely(msg); | ||||
@@ -519,7 +520,7 @@ namespace Discord | |||||
//Statuses | //Statuses | ||||
case "PRESENCE_UPDATE": | case "PRESENCE_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.PresenceUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<PresenceUpdateEvent>(_serializer); | |||||
var member = _members[data.User.Id, data.GuildId]; | var member = _members[data.User.Id, data.GuildId]; | ||||
/*if (_config.TrackActivity) | /*if (_config.TrackActivity) | ||||
{ | { | ||||
@@ -536,7 +537,7 @@ namespace Discord | |||||
break; | break; | ||||
case "VOICE_STATE_UPDATE": | case "VOICE_STATE_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.VoiceStateUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<VoiceStateUpdateEvent>(_serializer); | |||||
var member = _members[data.UserId, data.GuildId]; | var member = _members[data.UserId, data.GuildId]; | ||||
/*if (_config.TrackActivity) | /*if (_config.TrackActivity) | ||||
{ | { | ||||
@@ -558,7 +559,7 @@ namespace Discord | |||||
break; | break; | ||||
case "TYPING_START": | case "TYPING_START": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.TypingStart>(_serializer); | |||||
var data = e.Payload.ToObject<TypingStartEvent>(_serializer); | |||||
var channel = _channels[data.ChannelId]; | var channel = _channels[data.ChannelId]; | ||||
var user = _users[data.UserId]; | var user = _users[data.UserId]; | ||||
@@ -587,7 +588,7 @@ namespace Discord | |||||
//Voice | //Voice | ||||
case "VOICE_SERVER_UPDATE": | case "VOICE_SERVER_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.VoiceServerUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_serializer); | |||||
if (data.GuildId == _voiceSocket.CurrentVoiceServerId) | if (data.GuildId == _voiceSocket.CurrentVoiceServerId) | ||||
{ | { | ||||
var server = _servers[data.GuildId]; | var server = _servers[data.GuildId]; | ||||
@@ -603,7 +604,7 @@ namespace Discord | |||||
//Settings | //Settings | ||||
case "USER_UPDATE": | case "USER_UPDATE": | ||||
{ | { | ||||
var data = e.Payload.ToObject<Events.UserUpdate>(_serializer); | |||||
var data = e.Payload.ToObject<UserUpdateEvent>(_serializer); | |||||
var user = _users[data.Id]; | var user = _users[data.Id]; | ||||
if (user != null) | if (user != null) | ||||
{ | { | ||||
@@ -670,8 +671,8 @@ namespace Discord | |||||
_token = token; | _token = token; | ||||
_state = (int)DiscordClientState.Connecting; | _state = (int)DiscordClientState.Connecting; | ||||
string url = (await _api.GetWebSocketEndpoint().ConfigureAwait(false)).Url; | |||||
if (_config.LogLevel >= LogMessageSeverity.Verbose) | |||||
string url = (await _api.Gateway().ConfigureAwait(false)).Url; | |||||
if (_config.LogLevel >= LogMessageSeverity.Verbose) | |||||
RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Websocket endpoint: {url}"); | RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Websocket endpoint: {url}"); | ||||
_dataSocket.Host = url; | _dataSocket.Host = url; | ||||
@@ -838,7 +839,7 @@ namespace Discord | |||||
while (_pendingMessages.TryDequeue(out msg)) | while (_pendingMessages.TryDequeue(out msg)) | ||||
{ | { | ||||
bool hasFailed = false; | bool hasFailed = false; | ||||
Responses.SendMessage response = null; | |||||
SendMessageResponse response = null; | |||||
try | try | ||||
{ | { | ||||
response = await _api.SendMessage(msg.ChannelId, msg.RawText, msg.MentionIds, msg.Nonce, msg.IsTTS).ConfigureAwait(false); | response = await _api.SendMessage(msg.ChannelId, msg.RawText, msg.MentionIds, msg.Nonce, msg.IsTTS).ConfigureAwait(false); | ||||
@@ -1,5 +1,4 @@ | |||||
using Discord.Net.API; | |||||
using System.Text; | |||||
using System.Text; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -11,7 +10,7 @@ namespace Discord | |||||
static Format() | static Format() | ||||
{ | { | ||||
_patterns = new string[] { "__", "_", "**", "*", "~~" }; | _patterns = new string[] { "__", "_", "**", "*", "~~" }; | ||||
_builder = new StringBuilder(DiscordAPIClient.MaxMessageSize); | |||||
_builder = new StringBuilder(DiscordClient.MaxMessageSize); | |||||
} | } | ||||
/// <summary> Removes all special formatting characters from the provided text. </summary> | /// <summary> Removes all special formatting characters from the provided text. </summary> | ||||
@@ -1,9 +1,4 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
namespace Discord | |||||
{ | { | ||||
public static class Mention | public static class Mention | ||||
{ | { | ||||
@@ -1,5 +1,4 @@ | |||||
using Discord.Net.API; | |||||
using Newtonsoft.Json; | |||||
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; | ||||
@@ -64,14 +63,14 @@ namespace Discord | |||||
_messages = new ConcurrentDictionary<string, bool>(); | _messages = new ConcurrentDictionary<string, bool>(); | ||||
} | } | ||||
internal void Update(ChannelReference model) | |||||
internal void Update(API.ChannelReference model) | |||||
{ | { | ||||
Name = model.Name; | Name = model.Name; | ||||
Type = model.Type; | Type = model.Type; | ||||
} | } | ||||
internal void Update(ChannelInfo model) | |||||
internal void Update(API.ChannelInfo model) | |||||
{ | { | ||||
Update(model as ChannelReference); | |||||
Update(model as API.ChannelReference); | |||||
Position = model.Position; | Position = model.Position; | ||||
@@ -1,5 +1,4 @@ | |||||
using Discord.Net.API; | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -24,7 +23,7 @@ namespace Discord | |||||
public string XkcdPass { get; } | public string XkcdPass { get; } | ||||
/// <summary> Returns a URL for this invite using XkcdPass if available or Id if not. </summary> | /// <summary> Returns a URL for this invite using XkcdPass if available or Id if not. </summary> | ||||
public string Url => Endpoints.InviteUrl(XkcdPass ?? Id); | |||||
public string Url => API.Endpoints.InviteUrl(XkcdPass ?? Id); | |||||
/// <summary> Returns the id of the user that created this invite. </summary> | /// <summary> Returns the id of the user that created this invite. </summary> | ||||
public string InviterId { get; internal set; } | public string InviterId { get; internal set; } | ||||
@@ -54,16 +53,16 @@ namespace Discord | |||||
public override string ToString() => XkcdPass ?? Id; | public override string ToString() => XkcdPass ?? Id; | ||||
internal void Update(Net.API.Invite model) | |||||
internal void Update(API.Invite model) | |||||
{ | { | ||||
ChannelId = model.Channel.Id; | ChannelId = model.Channel.Id; | ||||
InviterId = model.Inviter?.Id; | InviterId = model.Inviter?.Id; | ||||
ServerId = model.Guild.Id; | ServerId = model.Guild.Id; | ||||
} | } | ||||
internal void Update(Net.API.ExtendedInvite model) | |||||
internal void Update(API.ExtendedInvite model) | |||||
{ | { | ||||
Update(model as Net.API.Invite); | |||||
Update(model as API.Invite); | |||||
IsRevoked = model.IsRevoked; | IsRevoked = model.IsRevoked; | ||||
IsTemporary = model.IsTemporary; | IsTemporary = model.IsTemporary; | ||||
MaxAge = model.MaxAge; | MaxAge = model.MaxAge; | ||||
@@ -1,5 +1,4 @@ | |||||
using Discord.Net.API; | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json; | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | using System.Linq; | ||||
@@ -17,7 +16,7 @@ namespace Discord | |||||
/// <summary> Returns the unique identifier for this user's current avatar. </summary> | /// <summary> Returns the unique identifier for this user's current avatar. </summary> | ||||
public string AvatarId { get; internal set; } | public string AvatarId { get; internal set; } | ||||
/// <summary> Returns the URL to this user's current avatar. </summary> | /// <summary> Returns the URL to this user's current avatar. </summary> | ||||
public string AvatarUrl => Endpoints.UserAvatar(UserId, AvatarId); | |||||
public string AvatarUrl => API.Endpoints.UserAvatar(UserId, AvatarId); | |||||
/// <summary> Returns the datetime that this user joined this server. </summary> | /// <summary> Returns the datetime that this user joined this server. </summary> | ||||
public DateTime JoinedAt { get; internal set; } | public DateTime JoinedAt { get; internal set; } | ||||
@@ -70,7 +69,7 @@ namespace Discord | |||||
public override string ToString() => UserId; | public override string ToString() => UserId; | ||||
internal void Update(UserReference model) | |||||
internal void Update(API.UserReference model) | |||||
{ | { | ||||
if (model.Avatar != null) | if (model.Avatar != null) | ||||
AvatarId = model.Avatar; | AvatarId = model.Avatar; | ||||
@@ -79,7 +78,7 @@ namespace Discord | |||||
if (model.Username != null) | if (model.Username != null) | ||||
Name = model.Username; | Name = model.Username; | ||||
} | } | ||||
internal void Update(MemberInfo model) | |||||
internal void Update(API.MemberInfo model) | |||||
{ | { | ||||
if (model.User != null) | if (model.User != null) | ||||
Update(model.User); | Update(model.User); | ||||
@@ -87,13 +86,13 @@ namespace Discord | |||||
if (model.JoinedAt.HasValue) | if (model.JoinedAt.HasValue) | ||||
JoinedAt = model.JoinedAt.Value; | JoinedAt = model.JoinedAt.Value; | ||||
} | } | ||||
internal void Update(ExtendedMemberInfo model) | |||||
internal void Update(API.ExtendedMemberInfo model) | |||||
{ | { | ||||
Update(model as MemberInfo); | |||||
Update(model as API.MemberInfo); | |||||
IsDeafened = model.IsDeafened; | IsDeafened = model.IsDeafened; | ||||
IsMuted = model.IsMuted; | IsMuted = model.IsMuted; | ||||
} | } | ||||
internal void Update(PresenceMemberInfo model) | |||||
internal void Update(API.PresenceMemberInfo model) | |||||
{ | { | ||||
if (Status != model.Status) | if (Status != model.Status) | ||||
{ | { | ||||
@@ -103,7 +102,7 @@ namespace Discord | |||||
} | } | ||||
GameId = model.GameId; | GameId = model.GameId; | ||||
} | } | ||||
internal void Update(VoiceMemberInfo model) | |||||
internal void Update(API.VoiceMemberInfo model) | |||||
{ | { | ||||
IsDeafened = model.IsDeafened; | IsDeafened = model.IsDeafened; | ||||
IsMuted = model.IsMuted; | IsMuted = model.IsMuted; | ||||
@@ -122,7 +122,7 @@ namespace Discord | |||||
UserId = userId; | UserId = userId; | ||||
} | } | ||||
internal void Update(Net.API.Message model) | |||||
internal void Update(API.Message model) | |||||
{ | { | ||||
if (model.Attachments != null) | if (model.Attachments != null) | ||||
{ | { | ||||
@@ -71,8 +71,7 @@ namespace Discord | |||||
else | else | ||||
_rawValue &= ~(1U << (pos - 1)); | _rawValue &= ~(1U << (pos - 1)); | ||||
} | } | ||||
public static implicit operator uint (PackedPermissions perms) => perms._rawValue; | |||||
public PackedPermissions Copy() => new PackedPermissions(false, _rawValue); | public PackedPermissions Copy() => new PackedPermissions(false, _rawValue); | ||||
} | } | ||||
} | } |
@@ -1,5 +1,4 @@ | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System.Threading; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -29,7 +28,7 @@ namespace Discord | |||||
Permissions = new PackedPermissions(true); | Permissions = new PackedPermissions(true); | ||||
} | } | ||||
internal void Update(Net.API.RoleInfo model) | |||||
internal void Update(API.RoleInfo model) | |||||
{ | { | ||||
Name = model.Name; | Name = model.Name; | ||||
Permissions.RawValue = (uint)model.Permissions; | Permissions.RawValue = (uint)model.Permissions; | ||||
@@ -1,5 +1,4 @@ | |||||
using Discord.Net.API; | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json; | |||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -100,7 +99,7 @@ namespace Discord | |||||
_roles = new ConcurrentDictionary<string, bool>(); | _roles = new ConcurrentDictionary<string, bool>(); | ||||
} | } | ||||
internal void Update(GuildInfo model) | |||||
internal void Update(API.GuildInfo model) | |||||
{ | { | ||||
AFKChannelId = model.AFKChannelId; | AFKChannelId = model.AFKChannelId; | ||||
AFKTimeout = model.AFKTimeout; | AFKTimeout = model.AFKTimeout; | ||||
@@ -117,9 +116,9 @@ namespace Discord | |||||
role.Update(subModel); | role.Update(subModel); | ||||
} | } | ||||
} | } | ||||
internal void Update(ExtendedGuildInfo model) | |||||
internal void Update(API.ExtendedGuildInfo model) | |||||
{ | { | ||||
Update(model as GuildInfo); | |||||
Update(model as API.GuildInfo); | |||||
var channels = _client.Channels; | var channels = _client.Channels; | ||||
foreach (var subModel in model.Channels) | foreach (var subModel in model.Channels) | ||||
@@ -1,5 +1,4 @@ | |||||
using Discord.Net.API; | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json; | |||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -24,7 +23,7 @@ namespace Discord | |||||
/// <summary> Returns the unique identifier for this user's current avatar. </summary> | /// <summary> Returns the unique identifier for this user's current avatar. </summary> | ||||
public string AvatarId { get; internal set; } | public string AvatarId { get; internal set; } | ||||
/// <summary> Returns the URL to this user's current avatar. </summary> | /// <summary> Returns the URL to this user's current avatar. </summary> | ||||
public string AvatarUrl => Endpoints.UserAvatar(Id, AvatarId); | |||||
public string AvatarUrl => API.Endpoints.UserAvatar(Id, AvatarId); | |||||
/// <summary> Returns the email for this user. </summary> | /// <summary> Returns the email for this user. </summary> | ||||
/// <remarks> This field is only ever populated for the current logged in user. </remarks> | /// <remarks> This field is only ever populated for the current logged in user. </remarks> | ||||
@@ -78,7 +77,7 @@ namespace Discord | |||||
_servers = new ConcurrentDictionary<string, bool>(); | _servers = new ConcurrentDictionary<string, bool>(); | ||||
} | } | ||||
internal void Update(UserReference model) | |||||
internal void Update(API.UserReference model) | |||||
{ | { | ||||
if (model.Avatar != null) | if (model.Avatar != null) | ||||
AvatarId = model.Avatar; | AvatarId = model.Avatar; | ||||
@@ -87,9 +86,9 @@ namespace Discord | |||||
if (model.Username != null) | if (model.Username != null) | ||||
Name = model.Username; | Name = model.Username; | ||||
} | } | ||||
internal void Update(SelfUserInfo model) | |||||
internal void Update(API.SelfUserInfo model) | |||||
{ | { | ||||
Update(model as UserReference); | |||||
Update(model as API.UserReference); | |||||
Email = model.Email; | Email = model.Email; | ||||
IsVerified = model.IsVerified; | IsVerified = model.IsVerified; | ||||
} | } | ||||
@@ -1,295 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.API | |||||
{ | |||||
//User | |||||
internal class UserReference | |||||
{ | |||||
[JsonProperty(PropertyName = "username")] | |||||
public string Username; | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "discriminator")] | |||||
public string Discriminator; | |||||
[JsonProperty(PropertyName = "avatar")] | |||||
public string Avatar; | |||||
} | |||||
internal class SelfUserInfo : UserReference | |||||
{ | |||||
[JsonProperty(PropertyName = "email")] | |||||
public string Email; | |||||
[JsonProperty(PropertyName = "verified")] | |||||
public bool IsVerified; | |||||
} | |||||
//Members | |||||
internal class MemberReference | |||||
{ | |||||
[JsonProperty(PropertyName = "user_id")] | |||||
public string UserId; | |||||
[JsonProperty(PropertyName = "user")] | |||||
public UserReference User; | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string GuildId; | |||||
} | |||||
internal class MemberInfo : MemberReference | |||||
{ | |||||
[JsonProperty(PropertyName = "joined_at")] | |||||
public DateTime? JoinedAt; | |||||
[JsonProperty(PropertyName = "roles")] | |||||
public string[] Roles; | |||||
} | |||||
internal class ExtendedMemberInfo : MemberInfo | |||||
{ | |||||
[JsonProperty(PropertyName = "mute")] | |||||
public bool IsMuted; | |||||
[JsonProperty(PropertyName = "deaf")] | |||||
public bool IsDeafened; | |||||
} | |||||
internal class PresenceMemberInfo : MemberReference | |||||
{ | |||||
[JsonProperty(PropertyName = "game_id")] | |||||
public string GameId; | |||||
[JsonProperty(PropertyName = "status")] | |||||
public string Status; | |||||
} | |||||
internal class VoiceMemberInfo : MemberReference | |||||
{ | |||||
[JsonProperty(PropertyName = "channel_id")] | |||||
public string ChannelId; | |||||
[JsonProperty(PropertyName = "suppress")] | |||||
public bool? IsSuppressed; | |||||
[JsonProperty(PropertyName = "session_id")] | |||||
public string SessionId; | |||||
[JsonProperty(PropertyName = "self_mute")] | |||||
public bool? IsSelfMuted; | |||||
[JsonProperty(PropertyName = "self_deaf")] | |||||
public bool? IsSelfDeafened; | |||||
[JsonProperty(PropertyName = "mute")] | |||||
public bool IsMuted; | |||||
[JsonProperty(PropertyName = "deaf")] | |||||
public bool IsDeafened; | |||||
[JsonProperty(PropertyName = "token")] | |||||
public string Token; | |||||
} | |||||
//Channels | |||||
internal class ChannelReference | |||||
{ | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string GuildId; | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
[JsonProperty(PropertyName = "type")] | |||||
public string Type; | |||||
} | |||||
internal class ChannelInfo : ChannelReference | |||||
{ | |||||
public sealed class PermissionOverwrite | |||||
{ | |||||
[JsonProperty(PropertyName = "type")] | |||||
public string Type; | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "deny")] | |||||
public uint Deny; | |||||
[JsonProperty(PropertyName = "allow")] | |||||
public uint Allow; | |||||
} | |||||
[JsonProperty(PropertyName = "last_message_id")] | |||||
public string LastMessageId; | |||||
[JsonProperty(PropertyName = "is_private")] | |||||
public bool IsPrivate; | |||||
[JsonProperty(PropertyName = "position")] | |||||
public int Position; | |||||
[JsonProperty(PropertyName = "permission_overwrites")] | |||||
public PermissionOverwrite[] PermissionOverwrites; | |||||
[JsonProperty(PropertyName = "recipient")] | |||||
public UserReference Recipient; | |||||
} | |||||
//Guilds (Servers) | |||||
internal class GuildReference | |||||
{ | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
} | |||||
internal class GuildInfo : GuildReference | |||||
{ | |||||
[JsonProperty(PropertyName = "afk_channel_id")] | |||||
public string AFKChannelId; | |||||
[JsonProperty(PropertyName = "afk_timeout")] | |||||
public int AFKTimeout; | |||||
[JsonProperty(PropertyName = "embed_channel_id")] | |||||
public string EmbedChannelId; | |||||
[JsonProperty(PropertyName = "embed_enabled")] | |||||
public bool EmbedEnabled; | |||||
[JsonProperty(PropertyName = "icon")] | |||||
public string Icon; | |||||
[JsonProperty(PropertyName = "joined_at")] | |||||
public DateTime? JoinedAt; | |||||
[JsonProperty(PropertyName = "owner_id")] | |||||
public string OwnerId; | |||||
[JsonProperty(PropertyName = "region")] | |||||
public string Region; | |||||
[JsonProperty(PropertyName = "roles")] | |||||
public RoleInfo[] Roles; | |||||
} | |||||
internal class ExtendedGuildInfo : GuildInfo | |||||
{ | |||||
[JsonProperty(PropertyName = "channels")] | |||||
public ChannelInfo[] Channels; | |||||
[JsonProperty(PropertyName = "members")] | |||||
public ExtendedMemberInfo[] Members; | |||||
[JsonProperty(PropertyName = "presences")] | |||||
public PresenceMemberInfo[] Presences; | |||||
[JsonProperty(PropertyName = "voice_states")] | |||||
public VoiceMemberInfo[] VoiceStates; | |||||
} | |||||
//Messages | |||||
internal class MessageReference | |||||
{ | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "channel_id")] | |||||
public string ChannelId; | |||||
[JsonProperty(PropertyName = "message_id")] | |||||
public string MessageId { get { return Id; } set { Id = value; } } | |||||
} | |||||
internal class Message : MessageReference | |||||
{ | |||||
public sealed class Attachment | |||||
{ | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string Url; | |||||
[JsonProperty(PropertyName = "proxy_url")] | |||||
public string ProxyUrl; | |||||
[JsonProperty(PropertyName = "size")] | |||||
public int Size; | |||||
[JsonProperty(PropertyName = "filename")] | |||||
public string Filename; | |||||
[JsonProperty(PropertyName = "width")] | |||||
public int Width; | |||||
[JsonProperty(PropertyName = "height")] | |||||
public int Height; | |||||
} | |||||
public sealed class Embed | |||||
{ | |||||
public sealed class Reference | |||||
{ | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string Url; | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
} | |||||
public sealed class ThumbnailInfo | |||||
{ | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string Url; | |||||
[JsonProperty(PropertyName = "proxy_url")] | |||||
public string ProxyUrl; | |||||
[JsonProperty(PropertyName = "width")] | |||||
public int Width; | |||||
[JsonProperty(PropertyName = "height")] | |||||
public int Height; | |||||
} | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string Url; | |||||
[JsonProperty(PropertyName = "type")] | |||||
public string Type; | |||||
[JsonProperty(PropertyName = "title")] | |||||
public string Title; | |||||
[JsonProperty(PropertyName = "description")] | |||||
public string Description; | |||||
[JsonProperty(PropertyName = "author")] | |||||
public Reference Author; | |||||
[JsonProperty(PropertyName = "provider")] | |||||
public Reference Provider; | |||||
[JsonProperty(PropertyName = "thumbnail")] | |||||
public ThumbnailInfo Thumbnail; | |||||
} | |||||
[JsonProperty(PropertyName = "tts")] | |||||
public bool IsTextToSpeech; | |||||
[JsonProperty(PropertyName = "mention_everyone")] | |||||
public bool IsMentioningEveryone; | |||||
[JsonProperty(PropertyName = "timestamp")] | |||||
public DateTime Timestamp; | |||||
[JsonProperty(PropertyName = "edited_timestamp")] | |||||
public DateTime? EditedTimestamp; | |||||
[JsonProperty(PropertyName = "mentions")] | |||||
public UserReference[] Mentions; | |||||
[JsonProperty(PropertyName = "embeds")] | |||||
public Embed[] Embeds; //TODO: Parse this | |||||
[JsonProperty(PropertyName = "attachments")] | |||||
public Attachment[] Attachments; | |||||
[JsonProperty(PropertyName = "content")] | |||||
public string Content; | |||||
[JsonProperty(PropertyName = "author")] | |||||
public UserReference Author; | |||||
[JsonProperty(PropertyName = "nonce")] | |||||
public string Nonce; | |||||
} | |||||
//Roles | |||||
internal class RoleReference | |||||
{ | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string GuildId; | |||||
[JsonProperty(PropertyName = "role_id")] | |||||
public string RoleId; | |||||
} | |||||
internal class RoleInfo | |||||
{ | |||||
[JsonProperty(PropertyName = "permissions")] | |||||
public int Permissions; | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
} | |||||
//Invites | |||||
internal class Invite | |||||
{ | |||||
[JsonProperty(PropertyName = "inviter")] | |||||
public UserReference Inviter; | |||||
[JsonProperty(PropertyName = "guild")] | |||||
public GuildReference Guild; | |||||
[JsonProperty(PropertyName = "channel")] | |||||
public ChannelReference Channel; | |||||
[JsonProperty(PropertyName = "code")] | |||||
public string Code; | |||||
[JsonProperty(PropertyName = "xkcdpass")] | |||||
public string XkcdPass; | |||||
} | |||||
internal class ExtendedInvite : Invite | |||||
{ | |||||
[JsonProperty(PropertyName = "max_age")] | |||||
public int MaxAge; | |||||
[JsonProperty(PropertyName = "max_uses")] | |||||
public int MaxUses; | |||||
[JsonProperty(PropertyName = "revoked")] | |||||
public bool IsRevoked; | |||||
[JsonProperty(PropertyName = "temporary")] | |||||
public bool IsTemporary; | |||||
[JsonProperty(PropertyName = "uses")] | |||||
public int Uses; | |||||
[JsonProperty(PropertyName = "created_at")] | |||||
public DateTime CreatedAt; | |||||
} | |||||
} |
@@ -1,212 +0,0 @@ | |||||
using System; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.Net.API | |||||
{ | |||||
internal class DiscordAPIClient | |||||
{ | |||||
public const int MaxMessageSize = 2000; | |||||
public RestClient RestClient => _rest; | |||||
private readonly RestClient _rest; | |||||
public DiscordAPIClient(LogMessageSeverity logLevel, int timeout) | |||||
{ | |||||
_rest = new RestClient(logLevel, timeout); | |||||
} | |||||
private string _token; | |||||
public string Token | |||||
{ | |||||
get { return _token; } | |||||
set { _token = value; _rest.SetToken(value); } | |||||
} | |||||
private CancellationToken _cancelToken; | |||||
public CancellationToken CancelToken | |||||
{ | |||||
get { return _cancelToken; } | |||||
set { _cancelToken = value; _rest.SetCancelToken(value); } | |||||
} | |||||
//Auth | |||||
public Task<Responses.Gateway> GetWebSocketEndpoint() | |||||
=> _rest.Get<Responses.Gateway>(Endpoints.Gateway); | |||||
public async Task<Responses.AuthRegister> LoginAnonymous(string username) | |||||
{ | |||||
var fingerprintResponse = await _rest.Post<Responses.AuthFingerprint>(Endpoints.AuthFingerprint).ConfigureAwait(false); | |||||
var registerRequest = new Requests.AuthRegister { Fingerprint = fingerprintResponse.Fingerprint, Username = username }; | |||||
var registerResponse = await _rest.Post<Responses.AuthRegister>(Endpoints.AuthRegister, registerRequest).ConfigureAwait(false); | |||||
return registerResponse; | |||||
} | |||||
public async Task<Responses.AuthLogin> Login(string email, string password) | |||||
{ | |||||
var request = new Requests.AuthLogin { Email = email, Password = password }; | |||||
var response = await _rest.Post<Responses.AuthLogin>(Endpoints.AuthLogin, request).ConfigureAwait(false); | |||||
return response; | |||||
} | |||||
public Task Logout() | |||||
=> _rest.Post(Endpoints.AuthLogout); | |||||
//Servers | |||||
public Task<Responses.CreateServer> CreateServer(string name, string region) | |||||
{ | |||||
var request = new Requests.CreateServer { Name = name, Region = region }; | |||||
return _rest.Post<Responses.CreateServer>(Endpoints.Servers, request); | |||||
} | |||||
public Task LeaveServer(string id) | |||||
=> _rest.Delete<Responses.DeleteServer>(Endpoints.Server(id)); | |||||
//Channels | |||||
public Task<Responses.CreateChannel> CreateChannel(string serverId, string name, string channelType) | |||||
{ | |||||
var request = new Requests.CreateChannel { Name = name, Type = channelType }; | |||||
return _rest.Post<Responses.CreateChannel>(Endpoints.ServerChannels(serverId), request); | |||||
} | |||||
public Task<Responses.CreateChannel> CreatePMChannel(string myId, string recipientId) | |||||
{ | |||||
var request = new Requests.CreatePMChannel { RecipientId = recipientId }; | |||||
return _rest.Post<Responses.CreateChannel>(Endpoints.UserChannels(myId), request); | |||||
} | |||||
public Task<Responses.DestroyChannel> DestroyChannel(string channelId) | |||||
=> _rest.Delete<Responses.DestroyChannel>(Endpoints.Channel(channelId)); | |||||
public Task<Responses.GetMessages[]> GetMessages(string channelId, int count) | |||||
=> _rest.Get<Responses.GetMessages[]>(Endpoints.ChannelMessages(channelId, count)); | |||||
//Members | |||||
public Task Kick(string serverId, string userId) | |||||
=> _rest.Delete(Endpoints.ServerMember(serverId, userId)); | |||||
public Task Ban(string serverId, string userId) | |||||
=> _rest.Put(Endpoints.ServerBan(serverId, userId)); | |||||
public Task Unban(string serverId, string userId) | |||||
=> _rest.Delete(Endpoints.ServerBan(serverId, userId)); | |||||
public Task SetMemberRoles(string serverId, string userId, string[] roles) | |||||
{ | |||||
var request = new Requests.ModifyMember { Roles = roles }; | |||||
return _rest.Patch(Endpoints.ServerMember(serverId, userId)); | |||||
} | |||||
//Invites | |||||
public Task<Responses.CreateInvite> CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool withXkcdPass) | |||||
{ | |||||
var request = new Requests.CreateInvite { MaxAge = maxAge, MaxUses = maxUses, IsTemporary = isTemporary, WithXkcdPass = withXkcdPass }; | |||||
return _rest.Post<Responses.CreateInvite>(Endpoints.ChannelInvites(channelId), request); | |||||
} | |||||
public Task<Responses.GetInvite> GetInvite(string id) | |||||
=> _rest.Get<Responses.GetInvite>(Endpoints.Invite(id)); | |||||
public Task AcceptInvite(string id) | |||||
=> _rest.Post<Responses.AcceptInvite>(Endpoints.Invite(id)); | |||||
public Task DeleteInvite(string id) | |||||
=> _rest.Delete(Endpoints.Invite(id)); | |||||
//Roles | |||||
public Task CreateRole(string serverId) | |||||
{ | |||||
//TODO: Return a result when Discord starts giving us one | |||||
return _rest.Post(Endpoints.ServerRoles(serverId)); | |||||
} | |||||
public Task RenameRole(string serverId, string roleId, string newName) | |||||
{ | |||||
var request = new Requests.ModifyRole { Name = newName }; | |||||
return _rest.Patch(Endpoints.ServerRole(serverId, roleId), request); | |||||
} | |||||
public Task SetRolePermissions(string serverId, string roleId, PackedPermissions permissions) | |||||
{ | |||||
var request = new Requests.ModifyRole { Permissions = permissions.RawValue }; | |||||
return _rest.Patch(Endpoints.ServerRole(serverId, roleId), request); | |||||
} | |||||
public Task DeleteRole(string serverId, string roleId) | |||||
{ | |||||
return _rest.Delete(Endpoints.ServerRole(serverId, roleId)); | |||||
} | |||||
//Permissions | |||||
public Task SetChannelPermissions(string channelId, string userOrRoleId, string idType, PackedPermissions allow, PackedPermissions deny) | |||||
{ | |||||
var request = new Requests.SetChannelPermissions { Id = userOrRoleId, Type = idType, Allow = allow.RawValue, Deny = deny.RawValue }; | |||||
return _rest.Put(Endpoints.ChannelPermission(channelId, userOrRoleId), request); | |||||
} | |||||
public Task DeleteChannelPermissions(string channelId, string userOrRoleId) | |||||
{ | |||||
return _rest.Delete(Endpoints.ChannelPermission(channelId, userOrRoleId), null); | |||||
} | |||||
//Chat | |||||
public Task<Responses.SendMessage> SendMessage(string channelId, string message, string[] mentions, string nonce, bool isTTS) | |||||
{ | |||||
var request = new Requests.SendMessage { Content = message, Mentions = mentions, Nonce = nonce, IsTTS = isTTS }; | |||||
return _rest.Post<Responses.SendMessage>(Endpoints.ChannelMessages(channelId), request); | |||||
} | |||||
public Task<Responses.EditMessage> EditMessage(string messageId, string channelId, string message, string[] mentions) | |||||
{ | |||||
var request = new Requests.EditMessage { Content = message, Mentions = mentions }; | |||||
return _rest.Patch<Responses.EditMessage>(Endpoints.ChannelMessage(channelId, messageId), request); | |||||
} | |||||
public Task SendIsTyping(string channelId) | |||||
=> _rest.Post(Endpoints.ChannelTyping(channelId)); | |||||
public Task DeleteMessage(string channelId, string msgId) | |||||
=> _rest.Delete(Endpoints.ChannelMessage(channelId, msgId)); | |||||
public Task SendFile(string channelId, string filePath) | |||||
=> _rest.PostFile<Responses.SendMessage>(Endpoints.ChannelMessages(channelId), filePath); | |||||
//Voice | |||||
public Task<Responses.GetRegions[]> GetVoiceRegions() | |||||
=> _rest.Get<Responses.GetRegions[]>(Endpoints.VoiceRegions); | |||||
public Task<Responses.GetIce> GetVoiceIce() | |||||
=> _rest.Get<Responses.GetIce>(Endpoints.VoiceIce); | |||||
public Task Mute(string serverId, string memberId) | |||||
{ | |||||
var request = new Requests.SetMemberMute { Value = true }; | |||||
return _rest.Patch(Endpoints.ServerMember(serverId, memberId)); | |||||
} | |||||
public Task Unmute(string serverId, string memberId) | |||||
{ | |||||
var request = new Requests.SetMemberMute { Value = false }; | |||||
return _rest.Patch(Endpoints.ServerMember(serverId, memberId)); | |||||
} | |||||
public Task Deafen(string serverId, string memberId) | |||||
{ | |||||
var request = new Requests.SetMemberDeaf { Value = true }; | |||||
return _rest.Patch(Endpoints.ServerMember(serverId, memberId)); | |||||
} | |||||
public Task Undeafen(string serverId, string memberId) | |||||
{ | |||||
var request = new Requests.SetMemberDeaf { Value = false }; | |||||
return _rest.Patch(Endpoints.ServerMember(serverId, memberId)); | |||||
} | |||||
//Profile | |||||
public Task<Responses.ChangeProfile> ChangeUsername(string newUsername, string currentEmail, string currentPassword) | |||||
{ | |||||
var request = new Requests.ChangeUsername { Username = newUsername, CurrentEmail = currentEmail, CurrentPassword = currentPassword }; | |||||
return _rest.Patch<Responses.ChangeProfile>(Endpoints.UserMe, request); | |||||
} | |||||
public Task<Responses.ChangeProfile> ChangeEmail(string newEmail, string currentPassword) | |||||
{ | |||||
var request = new Requests.ChangeEmail { NewEmail = newEmail, CurrentPassword = currentPassword }; | |||||
return _rest.Patch<Responses.ChangeProfile>(Endpoints.UserMe, request); | |||||
} | |||||
public Task<Responses.ChangeProfile> ChangePassword(string newPassword, string currentEmail, string currentPassword) | |||||
{ | |||||
var request = new Requests.ChangePassword { NewPassword = newPassword, CurrentEmail = currentEmail, CurrentPassword = currentPassword }; | |||||
return _rest.Patch<Responses.ChangeProfile>(Endpoints.UserMe, request); | |||||
} | |||||
public Task<Responses.ChangeProfile> ChangeAvatar(AvatarImageType imageType, byte[] bytes, string currentEmail, string currentPassword) | |||||
{ | |||||
string base64 = Convert.ToBase64String(bytes); | |||||
string type = imageType == AvatarImageType.Jpeg ? "image/jpeg;base64" : "image/png;base64"; | |||||
var request = new Requests.ChangeAvatar { Avatar = $"data:{type},/9j/{base64}", CurrentEmail = currentEmail, CurrentPassword = currentPassword }; | |||||
return _rest.Patch<Responses.ChangeProfile>(Endpoints.UserMe, request); | |||||
} | |||||
//Other | |||||
/*public Task<Responses.Status> GetUnresolvedIncidents() | |||||
{ | |||||
return _rest.Get<Responses.Status>(Endpoints.StatusUnresolvedMaintenance); | |||||
} | |||||
public Task<Responses.Status> GetActiveIncidents() | |||||
{ | |||||
return _rest.Get<Responses.Status>(Endpoints.StatusActiveMaintenance); | |||||
}*/ | |||||
} | |||||
} |
@@ -1,158 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
namespace Discord.Net.API | |||||
{ | |||||
internal static class Requests | |||||
{ | |||||
//Auth | |||||
public sealed class AuthRegister | |||||
{ | |||||
[JsonProperty(PropertyName = "fingerprint")] | |||||
public string Fingerprint; | |||||
[JsonProperty(PropertyName = "username")] | |||||
public string Username; | |||||
} | |||||
public sealed class AuthLogin | |||||
{ | |||||
[JsonProperty(PropertyName = "email")] | |||||
public string Email; | |||||
[JsonProperty(PropertyName = "password")] | |||||
public string Password; | |||||
} | |||||
//Servers | |||||
public sealed class CreateServer | |||||
{ | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
[JsonProperty(PropertyName = "region")] | |||||
public string Region; | |||||
} | |||||
//Channels | |||||
public sealed class CreateChannel | |||||
{ | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
[JsonProperty(PropertyName = "type")] | |||||
public string Type; | |||||
} | |||||
public sealed class CreatePMChannel | |||||
{ | |||||
[JsonProperty(PropertyName = "recipient_id")] | |||||
public string RecipientId; | |||||
} | |||||
//Invites | |||||
public sealed class CreateInvite | |||||
{ | |||||
[JsonProperty(PropertyName = "max_age")] | |||||
public int MaxAge; | |||||
[JsonProperty(PropertyName = "max_uses")] | |||||
public int MaxUses; | |||||
[JsonProperty(PropertyName = "temporary")] | |||||
public bool IsTemporary; | |||||
[JsonProperty(PropertyName = "xkcdpass")] | |||||
public bool WithXkcdPass; | |||||
} | |||||
//Messages | |||||
public sealed class SendMessage | |||||
{ | |||||
[JsonProperty(PropertyName = "content")] | |||||
public string Content; | |||||
[JsonProperty(PropertyName = "mentions")] | |||||
public string[] Mentions; | |||||
[JsonProperty(PropertyName = "nonce")] | |||||
public string Nonce; | |||||
[JsonProperty(PropertyName = "tts")] | |||||
public bool IsTTS; | |||||
} | |||||
public sealed class EditMessage | |||||
{ | |||||
[JsonProperty(PropertyName = "content")] | |||||
public string Content; | |||||
[JsonProperty(PropertyName = "mentions")] | |||||
public string[] Mentions; | |||||
} | |||||
//Members | |||||
public sealed class SetMemberMute | |||||
{ | |||||
[JsonProperty(PropertyName = "mute")] | |||||
public bool Value; | |||||
} | |||||
public sealed class SetMemberDeaf | |||||
{ | |||||
[JsonProperty(PropertyName = "deaf")] | |||||
public bool Value; | |||||
} | |||||
public sealed class ModifyMember | |||||
{ | |||||
[JsonProperty(PropertyName = "roles")] | |||||
public string[] Roles; | |||||
} | |||||
//Profile | |||||
public sealed class ChangeUsername | |||||
{ | |||||
[JsonProperty(PropertyName = "email")] | |||||
public string CurrentEmail; | |||||
[JsonProperty(PropertyName = "password")] | |||||
public string CurrentPassword; | |||||
[JsonProperty(PropertyName = "username")] | |||||
public string Username; | |||||
} | |||||
public sealed class ChangeEmail | |||||
{ | |||||
[JsonProperty(PropertyName = "email")] | |||||
public string NewEmail; | |||||
[JsonProperty(PropertyName = "password")] | |||||
public string CurrentPassword; | |||||
} | |||||
public sealed class ChangePassword | |||||
{ | |||||
[JsonProperty(PropertyName = "email")] | |||||
public string CurrentEmail; | |||||
[JsonProperty(PropertyName = "password")] | |||||
public string CurrentPassword; | |||||
[JsonProperty(PropertyName = "new_password")] | |||||
public string NewPassword; | |||||
} | |||||
public sealed class ChangeAvatar | |||||
{ | |||||
[JsonProperty(PropertyName = "email")] | |||||
public string CurrentEmail; | |||||
[JsonProperty(PropertyName = "password")] | |||||
public string CurrentPassword; | |||||
[JsonProperty(PropertyName = "avatar")] | |||||
public string Avatar; | |||||
} | |||||
//Roles | |||||
public sealed class ModifyRole | |||||
{ | |||||
[JsonProperty(PropertyName = "name", NullValueHandling = NullValueHandling.Ignore)] | |||||
public string Name; | |||||
[JsonProperty(PropertyName = "permissions", NullValueHandling = NullValueHandling.Ignore)] | |||||
public uint Permissions; | |||||
} | |||||
//Permissions | |||||
public sealed class SetChannelPermissions | |||||
{ | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "type")] | |||||
public string Type; | |||||
[JsonProperty(PropertyName = "allow")] | |||||
public uint Allow; | |||||
[JsonProperty(PropertyName = "deny")] | |||||
public uint Deny; | |||||
} | |||||
} | |||||
} |
@@ -1,85 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
namespace Discord.Net.API | |||||
{ | |||||
internal static class Responses | |||||
{ | |||||
//Auth | |||||
public sealed class Gateway | |||||
{ | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string Url; | |||||
} | |||||
public sealed class AuthFingerprint | |||||
{ | |||||
[JsonProperty(PropertyName = "fingerprint")] | |||||
public string Fingerprint; | |||||
} | |||||
public sealed class AuthRegister | |||||
{ | |||||
[JsonProperty(PropertyName = "token")] | |||||
public string Token; | |||||
} | |||||
public sealed class AuthLogin | |||||
{ | |||||
[JsonProperty(PropertyName = "token")] | |||||
public string Token; | |||||
} | |||||
//Users | |||||
public sealed class ChangeProfile : SelfUserInfo { } | |||||
//Servers | |||||
public sealed class CreateServer : GuildInfo { } | |||||
public sealed class DeleteServer : GuildInfo { } | |||||
//Channels | |||||
public sealed class CreateChannel : ChannelInfo { } | |||||
public sealed class DestroyChannel : ChannelInfo { } | |||||
//Invites | |||||
public sealed class CreateInvite : ExtendedInvite { } | |||||
public sealed class GetInvite : Invite { } | |||||
public sealed class AcceptInvite : Invite { } | |||||
//Messages | |||||
public sealed class SendMessage : Message { } | |||||
public sealed class EditMessage : Message { } | |||||
public sealed class GetMessages : Message { } | |||||
//Voice | |||||
public sealed class GetRegions | |||||
{ | |||||
[JsonProperty(PropertyName = "sample_hostname")] | |||||
public string Hostname; | |||||
[JsonProperty(PropertyName = "sample_port")] | |||||
public int Port; | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string Id; | |||||
[JsonProperty(PropertyName = "name")] | |||||
public string Name; | |||||
} | |||||
public sealed class GetIce | |||||
{ | |||||
[JsonProperty(PropertyName = "ttl")] | |||||
public string TTL; | |||||
[JsonProperty(PropertyName = "servers")] | |||||
public Server[] Servers; | |||||
public sealed class Server | |||||
{ | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string URL; | |||||
[JsonProperty(PropertyName = "username")] | |||||
public string Username; | |||||
[JsonProperty(PropertyName = "credential")] | |||||
public string Credential; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,71 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json.Linq; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
namespace Discord.Net.WebSockets | |||||
{ | |||||
internal static class Commands | |||||
{ | |||||
public sealed class KeepAlive : WebSocketMessage<ulong> | |||||
{ | |||||
public KeepAlive() : base(1, GetTimestamp()) { } | |||||
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | |||||
private static ulong GetTimestamp() => (ulong)(DateTime.UtcNow - epoch).TotalMilliseconds; | |||||
} | |||||
public sealed class Login : WebSocketMessage<Login.Data> | |||||
{ | |||||
public Login() : base(2) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty(PropertyName = "token")] | |||||
public string Token; | |||||
[JsonProperty(PropertyName = "v")] | |||||
public int Version = 3; | |||||
[JsonProperty(PropertyName = "properties")] | |||||
public Dictionary<string, string> Properties = new Dictionary<string, string>(); | |||||
} | |||||
} | |||||
public sealed class UpdateStatus : WebSocketMessage<UpdateStatus.Data> | |||||
{ | |||||
public UpdateStatus() : base(3) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty(PropertyName = "idle_since")] | |||||
public string IdleSince; | |||||
[JsonProperty(PropertyName = "game_id")] | |||||
public string GameId; | |||||
} | |||||
} | |||||
public sealed class JoinVoice : WebSocketMessage<JoinVoice.Data> | |||||
{ | |||||
public JoinVoice() : base(4) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string ServerId; | |||||
[JsonProperty(PropertyName = "channel_id")] | |||||
public string ChannelId; | |||||
[JsonProperty(PropertyName = "self_mute")] | |||||
public string SelfMute; | |||||
[JsonProperty(PropertyName = "self_deaf")] | |||||
public string SelfDeaf; | |||||
} | |||||
} | |||||
public sealed class Resume : WebSocketMessage<Resume.Data> | |||||
{ | |||||
public Resume() : base(6) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty(PropertyName = "session_id")] | |||||
public string SessionId; | |||||
[JsonProperty(PropertyName = "seq")] | |||||
public int Sequence; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,118 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Discord.Net.API; | |||||
using Newtonsoft.Json; | |||||
namespace Discord.Net.WebSockets | |||||
{ | |||||
internal static class Events | |||||
{ | |||||
public sealed class Ready | |||||
{ | |||||
public sealed class ReadStateInfo | |||||
{ | |||||
[JsonProperty(PropertyName = "id")] | |||||
public string ChannelId; | |||||
[JsonProperty(PropertyName = "mention_count")] | |||||
public int MentionCount; | |||||
[JsonProperty(PropertyName = "last_message_id")] | |||||
public string LastMessageId; | |||||
} | |||||
[JsonProperty(PropertyName = "v")] | |||||
public int Version; | |||||
[JsonProperty(PropertyName = "user")] | |||||
public SelfUserInfo User; | |||||
[JsonProperty(PropertyName = "session_id")] | |||||
public string SessionId; | |||||
[JsonProperty(PropertyName = "read_state")] | |||||
public ReadStateInfo[] ReadState; | |||||
[JsonProperty(PropertyName = "guilds")] | |||||
public ExtendedGuildInfo[] Guilds; | |||||
[JsonProperty(PropertyName = "private_channels")] | |||||
public ChannelInfo[] PrivateChannels; | |||||
[JsonProperty(PropertyName = "heartbeat_interval")] | |||||
public int HeartbeatInterval; | |||||
} | |||||
public sealed class Resumed | |||||
{ | |||||
[JsonProperty(PropertyName = "heartbeat_interval")] | |||||
public int HeartbeatInterval; | |||||
} | |||||
public sealed class Redirect | |||||
{ | |||||
[JsonProperty(PropertyName = "url")] | |||||
public string Url; | |||||
} | |||||
//Servers | |||||
public sealed class GuildCreate : ExtendedGuildInfo { } | |||||
public sealed class GuildUpdate : GuildInfo { } | |||||
public sealed class GuildDelete : ExtendedGuildInfo { } | |||||
//Channels | |||||
public sealed class ChannelCreate : ChannelInfo { } | |||||
public sealed class ChannelDelete : ChannelInfo { } | |||||
public sealed class ChannelUpdate : ChannelInfo { } | |||||
//Memberships | |||||
public sealed class GuildMemberAdd : MemberInfo { } | |||||
public sealed class GuildMemberUpdate : MemberInfo { } | |||||
public sealed class GuildMemberRemove : MemberInfo { } | |||||
//Roles | |||||
public sealed class GuildRoleCreate | |||||
{ | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string GuildId; | |||||
[JsonProperty(PropertyName = "role")] | |||||
public RoleInfo Data; | |||||
} | |||||
public sealed class GuildRoleUpdate | |||||
{ | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string GuildId; | |||||
[JsonProperty(PropertyName = "role")] | |||||
public RoleInfo Data; | |||||
} | |||||
public sealed class GuildRoleDelete : RoleReference { } | |||||
//Bans | |||||
public sealed class GuildBanAdd : MemberReference { } | |||||
public sealed class GuildBanRemove : MemberReference { } | |||||
//User | |||||
public sealed class UserUpdate : SelfUserInfo { } | |||||
public sealed class PresenceUpdate : PresenceMemberInfo { } | |||||
public sealed class VoiceStateUpdate : VoiceMemberInfo { } | |||||
//Chat | |||||
public sealed class MessageCreate : API.Message { } | |||||
public sealed class MessageUpdate : API.Message { } | |||||
public sealed class MessageDelete : MessageReference { } | |||||
public sealed class MessageAck : MessageReference { } | |||||
public sealed class TypingStart | |||||
{ | |||||
[JsonProperty(PropertyName = "user_id")] | |||||
public string UserId; | |||||
[JsonProperty(PropertyName = "channel_id")] | |||||
public string ChannelId; | |||||
[JsonProperty(PropertyName = "timestamp")] | |||||
public int Timestamp; | |||||
} | |||||
//Voice | |||||
public sealed class VoiceServerUpdate | |||||
{ | |||||
[JsonProperty(PropertyName = "guild_id")] | |||||
public string GuildId; | |||||
[JsonProperty(PropertyName = "endpoint")] | |||||
public string Endpoint; | |||||
[JsonProperty(PropertyName = "token")] | |||||
public string Token; | |||||
} | |||||
} | |||||
} |
@@ -1,62 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
namespace Discord.Net.WebSockets | |||||
{ | |||||
internal static class VoiceCommands | |||||
{ | |||||
public sealed class Login : WebSocketMessage<Login.Data> | |||||
{ | |||||
public Login() : base(0) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty(PropertyName = "server_id")] | |||||
public string ServerId; | |||||
[JsonProperty(PropertyName = "user_id")] | |||||
public string UserId; | |||||
[JsonProperty(PropertyName = "session_id")] | |||||
public string SessionId; | |||||
[JsonProperty(PropertyName = "token")] | |||||
public string Token; | |||||
} | |||||
} | |||||
public sealed class Login2 : WebSocketMessage<Login2.Data> | |||||
{ | |||||
public Login2() : base(1) { } | |||||
public class Data | |||||
{ | |||||
public class SocketInfo | |||||
{ | |||||
[JsonProperty(PropertyName = "address")] | |||||
public string Address; | |||||
[JsonProperty(PropertyName = "port")] | |||||
public int Port; | |||||
[JsonProperty(PropertyName = "mode")] | |||||
public string Mode = "xsalsa20_poly1305"; | |||||
} | |||||
[JsonProperty(PropertyName = "protocol")] | |||||
public string Protocol = "udp"; | |||||
[JsonProperty(PropertyName = "data")] | |||||
public SocketInfo SocketData = new SocketInfo(); | |||||
} | |||||
} | |||||
public sealed class KeepAlive : WebSocketMessage<object> | |||||
{ | |||||
public KeepAlive() : base(3, null) { } | |||||
} | |||||
public sealed class IsTalking : WebSocketMessage<IsTalking.Data> | |||||
{ | |||||
public IsTalking() : base(5) { } | |||||
public class Data | |||||
{ | |||||
[JsonProperty(PropertyName = "delay")] | |||||
public int Delay; | |||||
[JsonProperty(PropertyName = "speaking")] | |||||
public bool IsSpeaking; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,41 +0,0 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
namespace Discord.Net.WebSockets | |||||
{ | |||||
internal static class VoiceEvents | |||||
{ | |||||
public sealed class Ready | |||||
{ | |||||
[JsonProperty(PropertyName = "ssrc")] | |||||
public uint SSRC; | |||||
[JsonProperty(PropertyName = "port")] | |||||
public ushort Port; | |||||
[JsonProperty(PropertyName = "modes")] | |||||
public string[] Modes; | |||||
[JsonProperty(PropertyName = "heartbeat_interval")] | |||||
public int HeartbeatInterval; | |||||
} | |||||
public sealed class JoinServer | |||||
{ | |||||
[JsonProperty(PropertyName = "secret_key")] | |||||
public byte[] SecretKey; | |||||
[JsonProperty(PropertyName = "mode")] | |||||
public string Mode; | |||||
} | |||||
public sealed class IsTalking | |||||
{ | |||||
[JsonProperty(PropertyName = "user_id")] | |||||
public string UserId; | |||||
[JsonProperty(PropertyName = "ssrc")] | |||||
public uint SSRC; | |||||
[JsonProperty(PropertyName = "speaking")] | |||||
public bool IsSpeaking; | |||||
} | |||||
} | |||||
} |
@@ -1,8 +1,4 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -0,0 +1,67 @@ | |||||
//Ignore unused/unassigned variable warnings | |||||
#pragma warning disable CS0649 | |||||
#pragma warning disable CS0169 | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
namespace Discord.WebSockets.Data | |||||
{ | |||||
internal sealed class KeepAliveCommand : WebSocketMessage<ulong> | |||||
{ | |||||
public KeepAliveCommand() : base(1, GetTimestamp()) { } | |||||
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | |||||
private static ulong GetTimestamp() => (ulong)(DateTime.UtcNow - epoch).TotalMilliseconds; | |||||
} | |||||
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 string IdleSince; | |||||
[JsonProperty("game_id")] | |||||
public string 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; | |||||
} | |||||
} | |||||
} |
@@ -1,10 +1,9 @@ | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||
using System; | using System; | ||||
using System.Threading; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets.Data | |||||
{ | { | ||||
internal partial class DataWebSocket : WebSocket | internal partial class DataWebSocket : WebSocket | ||||
{ | { | ||||
@@ -22,7 +21,7 @@ namespace Discord.Net.WebSockets | |||||
{ | { | ||||
await Connect().ConfigureAwait(false); | await Connect().ConfigureAwait(false); | ||||
Commands.Login msg = new Commands.Login(); | |||||
LoginCommand msg = new LoginCommand(); | |||||
msg.Payload.Token = token; | msg.Payload.Token = token; | ||||
msg.Payload.Properties["$device"] = "Discord.Net"; | msg.Payload.Properties["$device"] = "Discord.Net"; | ||||
QueueMessage(msg); | QueueMessage(msg); | ||||
@@ -32,7 +31,7 @@ namespace Discord.Net.WebSockets | |||||
await DisconnectInternal(isUnexpected: false).ConfigureAwait(false); | await DisconnectInternal(isUnexpected: false).ConfigureAwait(false); | ||||
await Connect().ConfigureAwait(false); | await Connect().ConfigureAwait(false); | ||||
var resumeMsg = new Commands.Resume(); | |||||
var resumeMsg = new ResumeCommand(); | |||||
resumeMsg.Payload.SessionId = _sessionId; | resumeMsg.Payload.SessionId = _sessionId; | ||||
resumeMsg.Payload.Sequence = _lastSeq; | resumeMsg.Payload.Sequence = _lastSeq; | ||||
QueueMessage(resumeMsg); | QueueMessage(resumeMsg); | ||||
@@ -75,16 +74,16 @@ namespace Discord.Net.WebSockets | |||||
JToken token = msg.Payload as JToken; | JToken token = msg.Payload as JToken; | ||||
if (msg.Type == "READY") | if (msg.Type == "READY") | ||||
{ | { | ||||
var payload = token.ToObject<Events.Ready>(); | |||||
var payload = token.ToObject<ReadyEvent>(); | |||||
_sessionId = payload.SessionId; | _sessionId = payload.SessionId; | ||||
_heartbeatInterval = payload.HeartbeatInterval; | _heartbeatInterval = payload.HeartbeatInterval; | ||||
QueueMessage(new Commands.UpdateStatus()); | |||||
QueueMessage(new UpdateStatusCommand()); | |||||
} | } | ||||
else if (msg.Type == "RESUMED") | else if (msg.Type == "RESUMED") | ||||
{ | { | ||||
var payload = token.ToObject<Events.Resumed>(); | |||||
var payload = token.ToObject<ResumedEvent>(); | |||||
_heartbeatInterval = payload.HeartbeatInterval; | _heartbeatInterval = payload.HeartbeatInterval; | ||||
QueueMessage(new Commands.UpdateStatus()); | |||||
QueueMessage(new UpdateStatusCommand()); | |||||
} | } | ||||
RaiseReceivedEvent(msg.Type, token); | RaiseReceivedEvent(msg.Type, token); | ||||
if (msg.Type == "READY" || msg.Type == "RESUMED") | if (msg.Type == "READY" || msg.Type == "RESUMED") | ||||
@@ -93,7 +92,7 @@ namespace Discord.Net.WebSockets | |||||
break; | break; | ||||
case 7: //Redirect | case 7: //Redirect | ||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<Events.Redirect>(); | |||||
var payload = (msg.Payload as JToken).ToObject<RedirectEvent>(); | |||||
Host = payload.Url; | Host = payload.Url; | ||||
if (_logLevel >= LogMessageSeverity.Info) | if (_logLevel >= LogMessageSeverity.Info) | ||||
RaiseOnLog(LogMessageSeverity.Info, "Redirected to " + payload.Url); | RaiseOnLog(LogMessageSeverity.Info, "Redirected to " + payload.Url); | ||||
@@ -109,19 +108,19 @@ namespace Discord.Net.WebSockets | |||||
protected override object GetKeepAlive() | protected override object GetKeepAlive() | ||||
{ | { | ||||
return new Commands.KeepAlive(); | |||||
return new KeepAliveCommand(); | |||||
} | } | ||||
public void SendJoinVoice(string serverId, string channelId) | public void SendJoinVoice(string serverId, string channelId) | ||||
{ | { | ||||
var joinVoice = new Commands.JoinVoice(); | |||||
var joinVoice = new JoinVoiceCommand(); | |||||
joinVoice.Payload.ServerId = serverId; | joinVoice.Payload.ServerId = serverId; | ||||
joinVoice.Payload.ChannelId = channelId; | joinVoice.Payload.ChannelId = channelId; | ||||
QueueMessage(joinVoice); | QueueMessage(joinVoice); | ||||
} | } | ||||
public void SendLeaveVoice(string serverId) | public void SendLeaveVoice(string serverId) | ||||
{ | { | ||||
var leaveVoice = new Commands.JoinVoice(); | |||||
var leaveVoice = new JoinVoiceCommand(); | |||||
leaveVoice.Payload.ServerId = serverId; | leaveVoice.Payload.ServerId = serverId; | ||||
QueueMessage(leaveVoice); | QueueMessage(leaveVoice); | ||||
} | } |
@@ -1,9 +1,9 @@ | |||||
using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||
using System; | using System; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets.Data | |||||
{ | { | ||||
public sealed class WebSocketEventEventArgs : EventArgs | |||||
internal sealed class WebSocketEventEventArgs : EventArgs | |||||
{ | { | ||||
public readonly string Type; | public readonly string Type; | ||||
public readonly JToken Payload; | public readonly JToken Payload; |
@@ -0,0 +1,115 @@ | |||||
//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,0 +1,59 @@ | |||||
//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,0 +1,38 @@ | |||||
//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; | |||||
} | |||||
} |
@@ -1,6 +1,6 @@ | |||||
using System; | using System; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets.Voice | |||||
{ | { | ||||
public sealed class IsTalkingEventArgs : EventArgs | public sealed class IsTalkingEventArgs : EventArgs | ||||
{ | { |
@@ -12,7 +12,7 @@ using System.Text; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets.Voice | |||||
{ | { | ||||
internal partial class VoiceWebSocket : WebSocket | internal partial class VoiceWebSocket : WebSocket | ||||
{ | { | ||||
@@ -106,7 +106,7 @@ namespace Discord.Net.WebSockets | |||||
_udp.AllowNatTraversal(true); | _udp.AllowNatTraversal(true); | ||||
#endif | #endif | ||||
VoiceCommands.Login msg = new VoiceCommands.Login(); | |||||
LoginCommand msg = new LoginCommand(); | |||||
msg.Payload.ServerId = _serverId; | msg.Payload.ServerId = _serverId; | ||||
msg.Payload.SessionId = _sessionId; | msg.Payload.SessionId = _sessionId; | ||||
msg.Payload.Token = _token; | msg.Payload.Token = _token; | ||||
@@ -294,7 +294,7 @@ namespace Discord.Net.WebSockets | |||||
{ | { | ||||
if (_state != (int)WebSocketState.Connected) | if (_state != (int)WebSocketState.Connected) | ||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<VoiceEvents.Ready>(); | |||||
var payload = (msg.Payload as JToken).ToObject<ReadyEvent>(); | |||||
_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); | ||||
@@ -319,7 +319,7 @@ namespace Discord.Net.WebSockets | |||||
break; | break; | ||||
case 4: //SESSION_DESCRIPTION | case 4: //SESSION_DESCRIPTION | ||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<VoiceEvents.JoinServer>(); | |||||
var payload = (msg.Payload as JToken).ToObject<JoinServerEvent>(); | |||||
_secretKey = payload.SecretKey; | _secretKey = payload.SecretKey; | ||||
SendIsTalking(true); | SendIsTalking(true); | ||||
_connectWaitOnLogin.Set(); | _connectWaitOnLogin.Set(); | ||||
@@ -327,7 +327,7 @@ namespace Discord.Net.WebSockets | |||||
break; | break; | ||||
case 5: | case 5: | ||||
{ | { | ||||
var payload = (msg.Payload as JToken).ToObject<VoiceEvents.IsTalking>(); | |||||
var payload = (msg.Payload as JToken).ToObject<IsTalkingEvent>(); | |||||
RaiseIsSpeaking(payload.UserId, payload.IsSpeaking); | RaiseIsSpeaking(payload.UserId, payload.IsSpeaking); | ||||
} | } | ||||
break; | break; | ||||
@@ -358,7 +358,7 @@ namespace Discord.Net.WebSockets | |||||
CompleteConnect(); | CompleteConnect(); | ||||
var login2 = new VoiceCommands.Login2(); | |||||
var login2 = new Login2Command(); | |||||
login2.Payload.Protocol = "udp"; | login2.Payload.Protocol = "udp"; | ||||
login2.Payload.SocketData.Address = ip; | login2.Payload.SocketData.Address = ip; | ||||
login2.Payload.SocketData.Mode = _isEncrypted ? EncryptedMode : UnencryptedMode; | login2.Payload.SocketData.Mode = _isEncrypted ? EncryptedMode : UnencryptedMode; | ||||
@@ -503,7 +503,7 @@ namespace Discord.Net.WebSockets | |||||
private void SendIsTalking(bool value) | private void SendIsTalking(bool value) | ||||
{ | { | ||||
var isTalking = new VoiceCommands.IsTalking(); | |||||
var isTalking = new IsTalkingCommand(); | |||||
isTalking.Payload.IsSpeaking = value; | isTalking.Payload.IsSpeaking = value; | ||||
isTalking.Payload.Delay = 0; | isTalking.Payload.Delay = 0; | ||||
QueueMessage(isTalking); | QueueMessage(isTalking); | ||||
@@ -511,7 +511,7 @@ namespace Discord.Net.WebSockets | |||||
protected override object GetKeepAlive() | protected override object GetKeepAlive() | ||||
{ | { | ||||
return new VoiceCommands.KeepAlive(); | |||||
return new KeepAliveCommand(); | |||||
} | } | ||||
public void WaitForQueue() | public void WaitForQueue() |
@@ -8,7 +8,7 @@ using System.Threading; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using State = System.Net.WebSockets.WebSocketState; | using State = System.Net.WebSockets.WebSocketState; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets | |||||
{ | { | ||||
internal class BuiltInWebSocketEngine : IWebSocketEngine | internal class BuiltInWebSocketEngine : IWebSocketEngine | ||||
{ | { |
@@ -1,6 +1,6 @@ | |||||
using System; | using System; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets | |||||
{ | { | ||||
internal partial class WebSocket | internal partial class WebSocket | ||||
{ | { |
@@ -7,7 +7,7 @@ using System.Text; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets | |||||
{ | { | ||||
public enum WebSocketState : byte | public enum WebSocketState : byte | ||||
{ | { | ||||
@@ -88,7 +88,7 @@ namespace Discord.Net.WebSockets | |||||
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, ParentCancelToken).Token; | _cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, ParentCancelToken).Token; | ||||
else | else | ||||
_cancelToken = _cancelTokenSource.Token; | _cancelToken = _cancelTokenSource.Token; | ||||
await _engine.Connect(Host, _cancelToken).ConfigureAwait(false); | await _engine.Connect(Host, _cancelToken).ConfigureAwait(false); | ||||
_lastHeartbeat = DateTime.UtcNow; | _lastHeartbeat = DateTime.UtcNow; | ||||
@@ -107,8 +107,6 @@ namespace Discord.Net.WebSockets | |||||
_connectedEvent.Set(); | _connectedEvent.Set(); | ||||
RaiseConnected(); | RaiseConnected(); | ||||
} | } | ||||
/*public Task Reconnect(CancellationToken cancelToken) | |||||
=> Connect(_host, _cancelToken);*/ | |||||
public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false); | public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false); | ||||
protected async Task DisconnectInternal(Exception ex = null, bool isUnexpected = true, bool skipAwait = false) | protected async Task DisconnectInternal(Exception ex = null, bool isUnexpected = true, bool skipAwait = false) |
@@ -1,17 +1,17 @@ | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||
namespace Discord.Net.WebSockets | |||||
namespace Discord.WebSockets | |||||
{ | { | ||||
public class WebSocketMessage | public class WebSocketMessage | ||||
{ | { | ||||
[JsonProperty(PropertyName = "op")] | |||||
[JsonProperty("op")] | |||||
public int Operation; | public int Operation; | ||||
[JsonProperty(PropertyName = "d")] | |||||
[JsonProperty("d")] | |||||
public object Payload; | public object Payload; | ||||
[JsonProperty(PropertyName = "t", NullValueHandling = NullValueHandling.Ignore)] | |||||
[JsonProperty("t", NullValueHandling = NullValueHandling.Ignore)] | |||||
public string Type; | public string Type; | ||||
[JsonProperty(PropertyName = "s", NullValueHandling = NullValueHandling.Ignore)] | |||||
[JsonProperty("s", NullValueHandling = NullValueHandling.Ignore)] | |||||
public int? Sequence; | public int? Sequence; | ||||
} | } | ||||
internal abstract class WebSocketMessage<T> : WebSocketMessage | internal abstract class WebSocketMessage<T> : WebSocketMessage |