@@ -43,8 +43,11 @@ | |||
<Reference Include="System" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="..\Discord.Net.Audio\API\Voice.cs"> | |||
<Link>API\Voice.cs</Link> | |||
<Compile Include="..\Discord.Net.Audio\API\Messages\GatewaySocket.cs"> | |||
<Link>API\Messages\GatewaySocket.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Audio\API\Messages\VoiceSocket.cs"> | |||
<Link>API\Messages\VoiceSocket.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Audio\AudioExtensions.cs"> | |||
<Link>AudioExtensions.cs</Link> | |||
@@ -58,11 +61,11 @@ | |||
<Compile Include="..\Discord.Net.Audio\DiscordAudioClient.cs"> | |||
<Link>DiscordAudioClient.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Audio\Net\VoiceWebSocket.cs"> | |||
<Link>Net\VoiceWebSocket.cs</Link> | |||
<Compile Include="..\Discord.Net.Audio\Net\WebSockets\VoiceWebSocket.cs"> | |||
<Link>Net\WebSockets\VoiceWebSocket.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Audio\Net\VoiceWebSocket.Events.cs"> | |||
<Link>Net\VoiceWebSocket.Events.cs</Link> | |||
<Compile Include="..\Discord.Net.Audio\Net\WebSockets\VoiceWebSocket.Events.cs"> | |||
<Link>Net\WebSockets\VoiceWebSocket.Events.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net.Audio\Opus.cs"> | |||
<Link>Opus.cs</Link> | |||
@@ -0,0 +1,20 @@ | |||
//Ignore unused/unassigned variable warnings | |||
#pragma warning disable CS0649 | |||
#pragma warning disable CS0169 | |||
using Discord.API.Converters; | |||
using Newtonsoft.Json; | |||
namespace Discord.Audio.API | |||
{ | |||
internal sealed class VoiceServerUpdateEvent | |||
{ | |||
[JsonProperty("guild_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ServerId; | |||
[JsonProperty("endpoint")] | |||
public string Endpoint; | |||
[JsonProperty("token")] | |||
public string Token; | |||
} | |||
} |
@@ -149,7 +149,7 @@ namespace Discord.Audio | |||
{ | |||
int id = unchecked(++_nextClientId); | |||
var logger = Client.Log().CreateLogger($"Voice #{id}"); | |||
GatewayWebSocket dataSocket = null; | |||
GatewayWebSocket gatewaySocket = null; | |||
var voiceSocket = new VoiceWebSocket(Client.Config, _config, logger); | |||
var voiceClient = new DiscordAudioClient(this, id, logger, gatewaySocket, voiceSocket); | |||
voiceClient.SetServerId(server.Id); | |||
@@ -59,7 +59,7 @@ namespace Discord.Audio | |||
_voiceSocket.ParentCancelToken = _cancelToken; | |||
};*/ | |||
_gatewaySocket.ReceivedEvent += async (s, e) => | |||
_gatewaySocket.ReceivedDispatch += async (s, e) => | |||
{ | |||
try | |||
{ | |||
@@ -527,9 +527,9 @@ namespace Discord.Net.WebSockets | |||
QueueMessage(isTalking); | |||
} | |||
protected override object GetKeepAlive() | |||
public override void SendHeartbeat() | |||
{ | |||
return new VoiceKeepAliveCommand(); | |||
QueueMessage(new VoiceKeepAliveCommand()); | |||
} | |||
public void WaitForQueue() |
@@ -68,15 +68,6 @@ | |||
</Reference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="..\Discord.Net\API\Auth.cs"> | |||
<Link>API\Auth.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Bans.cs"> | |||
<Link>API\Bans.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Channels.cs"> | |||
<Link>API\Channels.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Converters\LongCollectionConverter.cs"> | |||
<Link>API\Converters\LongCollectionConverter.cs</Link> | |||
</Compile> | |||
@@ -101,38 +92,38 @@ | |||
<Compile Include="..\Discord.Net\API\Enums\UserStatus.cs"> | |||
<Link>API\Enums\UserStatus.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Invites.cs"> | |||
<Link>API\Invites.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Auth.cs"> | |||
<Link>API\Messages\Auth.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Maintenance.cs"> | |||
<Link>API\Maintenance.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Channels.cs"> | |||
<Link>API\Messages\Channels.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Members.cs"> | |||
<Link>API\Members.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\GatewaySocket.cs"> | |||
<Link>API\Messages\GatewaySocket.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Messages.cs"> | |||
<Link>API\Messages.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Invites.cs"> | |||
<Link>API\Messages\Invites.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Permissions.cs"> | |||
<Link>API\Permissions.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Maintenance.cs"> | |||
<Link>API\Messages\Maintenance.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Presence.cs"> | |||
<Link>API\Presence.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Members.cs"> | |||
<Link>API\Messages\Members.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Roles.cs"> | |||
<Link>API\Roles.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Messages.cs"> | |||
<Link>API\Messages\Messages.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Servers.cs"> | |||
<Link>API\Servers.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Permissions.cs"> | |||
<Link>API\Messages\Permissions.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Users.cs"> | |||
<Link>API\Users.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Roles.cs"> | |||
<Link>API\Messages\Roles.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\Voice.cs"> | |||
<Link>API\Voice.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Servers.cs"> | |||
<Link>API\Messages\Servers.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\API\WebSockets.cs"> | |||
<Link>API\WebSockets.cs</Link> | |||
<Compile Include="..\Discord.Net\API\Messages\Users.cs"> | |||
<Link>API\Messages\Users.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\DiscordAPIClient.cs"> | |||
<Link>DiscordAPIClient.cs</Link> | |||
@@ -239,11 +230,11 @@ | |||
<Compile Include="..\Discord.Net\Net\Rest\SharpRestEngine.cs"> | |||
<Link>Net\Rest\SharpRestEngine.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Net\WebSockets\DataWebSocket.cs"> | |||
<Link>Net\WebSockets\DataWebSocket.cs</Link> | |||
<Compile Include="..\Discord.Net\Net\WebSockets\GatewayWebSocket.cs"> | |||
<Link>Net\WebSockets\GatewayWebSocket.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Net\WebSockets\DataWebSockets.Events.cs"> | |||
<Link>Net\WebSockets\DataWebSockets.Events.cs</Link> | |||
<Compile Include="..\Discord.Net\Net\WebSockets\GatewayWebSockets.Events.cs"> | |||
<Link>Net\WebSockets\GatewayWebSockets.Events.cs</Link> | |||
</Compile> | |||
<Compile Include="..\Discord.Net\Net\WebSockets\IWebSocketEngine.cs"> | |||
<Link>Net\WebSockets\IWebSocketEngine.cs</Link> | |||
@@ -2,12 +2,26 @@ | |||
#pragma warning disable CS0649 | |||
#pragma warning disable CS0169 | |||
using Discord.API.Converters; | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
using System.Collections.Generic; | |||
namespace Discord.API | |||
{ | |||
public enum GatewayOpCodes : byte | |||
{ | |||
Dispatch = 0, | |||
Heartbeat = 1, | |||
Identify = 2, | |||
StatusUpdate = 3, | |||
VoiceStateUpdate = 4, | |||
//VoiceServerPing = 5, (Unused?) | |||
Resume = 6, | |||
Redirect = 7, | |||
RequestGuildMembers = 8 | |||
} | |||
//Common | |||
public class WebSocketMessage | |||
{ | |||
@@ -44,13 +58,13 @@ namespace Discord.API | |||
} | |||
//Commands | |||
internal sealed class KeepAliveCommand : WebSocketMessage<long> | |||
internal sealed class HeartbeatCommand : WebSocketMessage<long> | |||
{ | |||
public KeepAliveCommand() : base(1, EpochTime.GetMilliseconds()) { } | |||
public HeartbeatCommand() : base((int)GatewayOpCodes.Heartbeat, EpochTime.GetMilliseconds()) { } | |||
} | |||
internal sealed class LoginCommand : WebSocketMessage<LoginCommand.Data> | |||
internal sealed class IdentifyCommand : WebSocketMessage<IdentifyCommand.Data> | |||
{ | |||
public LoginCommand() : base(2) { } | |||
public IdentifyCommand() : base((int)GatewayOpCodes.Identify) { } | |||
public class Data | |||
{ | |||
[JsonProperty("token")] | |||
@@ -65,9 +79,43 @@ namespace Discord.API | |||
public bool? Compress; | |||
} | |||
} | |||
internal sealed class StatusUpdateCommand : WebSocketMessage<StatusUpdateCommand.Data> | |||
{ | |||
public StatusUpdateCommand() : base((int)GatewayOpCodes.StatusUpdate) { } | |||
public class Data | |||
{ | |||
[JsonProperty("idle_since")] | |||
public long? IdleSince; | |||
[JsonProperty("game_id")] | |||
public int? GameId; | |||
} | |||
} | |||
//Commands | |||
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data> | |||
{ | |||
public JoinVoiceCommand() : base((int)GatewayOpCodes.VoiceStateUpdate) { } | |||
public class Data | |||
{ | |||
[JsonProperty("guild_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ServerId; | |||
[JsonProperty("channel_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ChannelId; | |||
[JsonProperty("self_mute")] | |||
public string SelfMute; | |||
[JsonProperty("self_deaf")] | |||
public string SelfDeaf; | |||
} | |||
} | |||
//Events | |||
internal sealed class ResumeCommand : WebSocketMessage<ResumeCommand.Data> | |||
{ | |||
public ResumeCommand() : base(6) { } | |||
public ResumeCommand() : base((int)GatewayOpCodes.Resume) { } | |||
public class Data | |||
{ | |||
[JsonProperty("session_id")] | |||
@@ -105,15 +153,15 @@ namespace Discord.API | |||
[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; | |||
} | |||
internal sealed class ResumeEvent | |||
{ | |||
[JsonProperty("heartbeat_interval")] | |||
public int HeartbeatInterval; | |||
} | |||
} |
@@ -5,6 +5,7 @@ | |||
using Discord.API.Converters; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
namespace Discord.API | |||
{ | |||
@@ -85,6 +86,21 @@ namespace Discord.API | |||
//Delete | |||
public sealed class DeleteServerResponse : GuildInfo { } | |||
//GetRegions | |||
public class GetRegionsResponse : List<GetRegionsResponse.RegionData> | |||
{ | |||
public sealed class RegionData | |||
{ | |||
[JsonProperty("sample_hostname")] | |||
public string Hostname; | |||
[JsonProperty("sample_port")] | |||
public int Port; | |||
[JsonProperty("id")] | |||
public string Id; | |||
[JsonProperty("name")] | |||
public string Name; | |||
} | |||
} | |||
//Events | |||
internal sealed class GuildCreateEvent : ExtendedGuildInfo { } | |||
internal sealed class GuildUpdateEvent : GuildInfo { } |
@@ -46,6 +46,18 @@ namespace Discord.API | |||
//Events | |||
internal sealed class UserUpdateEvent : UserInfo { } | |||
internal sealed class PresenceUpdateEvent : PresenceInfo { } | |||
internal sealed class TypingStartEvent | |||
{ | |||
[JsonProperty("user_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long UserId; | |||
[JsonProperty("channel_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ChannelId; | |||
[JsonProperty("timestamp")] | |||
public int Timestamp; | |||
} | |||
internal sealed class BanAddEvent : MemberReference { } | |||
internal sealed class BanRemoveEvent : MemberReference { } | |||
} |
@@ -1,36 +0,0 @@ | |||
//Ignore unused/unassigned variable warnings | |||
#pragma warning disable CS0649 | |||
#pragma warning disable CS0169 | |||
using Discord.API.Converters; | |||
using Newtonsoft.Json; | |||
namespace Discord.API | |||
{ | |||
//Commands | |||
internal sealed class UpdateStatusCommand : WebSocketMessage<UpdateStatusCommand.Data> | |||
{ | |||
public UpdateStatusCommand() : base(3) { } | |||
public class Data | |||
{ | |||
[JsonProperty("idle_since")] | |||
public long? IdleSince; | |||
[JsonProperty("game_id")] | |||
public int? GameId; | |||
} | |||
} | |||
//Events | |||
internal sealed class TypingStartEvent | |||
{ | |||
[JsonProperty("user_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long UserId; | |||
[JsonProperty("channel_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ChannelId; | |||
[JsonProperty("timestamp")] | |||
public int Timestamp; | |||
} | |||
internal sealed class PresenceUpdateEvent : PresenceInfo { } | |||
} |
@@ -1,56 +0,0 @@ | |||
//Ignore unused/unassigned variable warnings | |||
#pragma warning disable CS0649 | |||
#pragma warning disable CS0169 | |||
using Discord.API.Converters; | |||
using Newtonsoft.Json; | |||
using System.Collections.Generic; | |||
namespace Discord.API | |||
{ | |||
public class GetRegionsResponse : List<GetRegionsResponse.RegionData> | |||
{ | |||
public sealed class RegionData | |||
{ | |||
[JsonProperty("sample_hostname")] | |||
public string Hostname; | |||
[JsonProperty("sample_port")] | |||
public int Port; | |||
[JsonProperty("id")] | |||
public string Id; | |||
[JsonProperty("name")] | |||
public string Name; | |||
} | |||
} | |||
//Commands | |||
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data> | |||
{ | |||
public JoinVoiceCommand() : base(4) { } | |||
public class Data | |||
{ | |||
[JsonProperty("guild_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ServerId; | |||
[JsonProperty("channel_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ChannelId; | |||
[JsonProperty("self_mute")] | |||
public string SelfMute; | |||
[JsonProperty("self_deaf")] | |||
public string SelfDeaf; | |||
} | |||
} | |||
//Events | |||
internal sealed class VoiceServerUpdateEvent | |||
{ | |||
[JsonProperty("guild_id")] | |||
[JsonConverter(typeof(LongStringConverter))] | |||
public long ServerId; | |||
[JsonProperty("endpoint")] | |||
public string Endpoint; | |||
[JsonProperty("token")] | |||
public string Token; | |||
} | |||
} |
@@ -302,7 +302,7 @@ namespace Discord | |||
} | |||
private Task SendStatus() | |||
{ | |||
_webSocket.SendStatus(_status == UserStatus.Idle ? EpochTime.GetMilliseconds() - (10 * 60 * 1000) : (long?)null, _gameId); | |||
_webSocket.SendStatusUpdate(_status == UserStatus.Idle ? EpochTime.GetMilliseconds() - (10 * 60 * 1000) : (long?)null, _gameId); | |||
return TaskHelper.CompletedTask; | |||
} | |||
} |
@@ -273,7 +273,7 @@ namespace Discord | |||
await socket.Reconnect(_token).ConfigureAwait(false); | |||
}; | |||
socket.ReceivedEvent += async (s, e) => await OnReceivedEvent(e).ConfigureAwait(false); | |||
socket.ReceivedDispatch += async (s, e) => await OnReceivedEvent(e).ConfigureAwait(false); | |||
return socket; | |||
} | |||
@@ -8,19 +8,6 @@ namespace Discord.Net.WebSockets | |||
{ | |||
public partial class GatewayWebSocket : WebSocket | |||
{ | |||
internal enum OpCodes : byte | |||
{ | |||
Dispatch = 0, | |||
Heartbeat = 1, | |||
Identify = 2, | |||
StatusUpdate = 3, | |||
VoiceStateUpdate = 4, | |||
VoiceServerPing = 5, | |||
Resume = 6, | |||
Redirect = 7, | |||
RequestGuildMembers = 8 | |||
} | |||
private int _lastSeq; | |||
public string SessionId => _sessionId; | |||
@@ -35,14 +22,8 @@ namespace Discord.Net.WebSockets | |||
{ | |||
await BeginConnect().ConfigureAwait(false); | |||
await Start().ConfigureAwait(false); | |||
LoginCommand msg = new LoginCommand(); | |||
msg.Payload.Token = token; | |||
msg.Payload.Properties["$device"] = "Discord.Net"; | |||
if (_config.UseLargeThreshold) | |||
msg.Payload.LargeThreshold = 100; | |||
msg.Payload.Compress = true; | |||
QueueMessage(msg); | |||
SendIdentify(token); | |||
} | |||
private async Task Redirect(string server) | |||
{ | |||
@@ -51,10 +32,7 @@ namespace Discord.Net.WebSockets | |||
await BeginConnect().ConfigureAwait(false); | |||
await Start().ConfigureAwait(false); | |||
var resumeMsg = new ResumeCommand(); | |||
resumeMsg.Payload.SessionId = _sessionId; | |||
resumeMsg.Payload.Sequence = _lastSeq; | |||
QueueMessage(resumeMsg); | |||
SendResume(); | |||
} | |||
public async Task Reconnect(string token) | |||
{ | |||
@@ -88,10 +66,10 @@ namespace Discord.Net.WebSockets | |||
if (msg.Sequence.HasValue) | |||
_lastSeq = msg.Sequence.Value; | |||
var opCode = (OpCodes)msg.Operation; | |||
var opCode = (GatewayOpCodes)msg.Operation; | |||
switch (opCode) | |||
{ | |||
case OpCodes.Dispatch: | |||
case GatewayOpCodes.Dispatch: | |||
{ | |||
JToken token = msg.Payload as JToken; | |||
if (msg.Type == "READY") | |||
@@ -102,15 +80,15 @@ namespace Discord.Net.WebSockets | |||
} | |||
else if (msg.Type == "RESUMED") | |||
{ | |||
var payload = token.ToObject<ResumedEvent>(_serializer); | |||
var payload = token.ToObject<ResumeEvent>(_serializer); | |||
_heartbeatInterval = payload.HeartbeatInterval; | |||
} | |||
RaiseReceivedEvent(msg.Type, token); | |||
RaiseReceivedDispatch(msg.Type, token); | |||
if (msg.Type == "READY" || msg.Type == "RESUMED") | |||
EndConnect(); | |||
} | |||
break; | |||
case OpCodes.Redirect: | |||
case GatewayOpCodes.Redirect: | |||
{ | |||
var payload = (msg.Payload as JToken).ToObject<RedirectEvent>(_serializer); | |||
if (payload.Url != null) | |||
@@ -129,14 +107,33 @@ namespace Discord.Net.WebSockets | |||
} | |||
} | |||
protected override object GetKeepAlive() | |||
public void SendIdentify(string token) | |||
{ | |||
return new KeepAliveCommand(); | |||
IdentifyCommand msg = new IdentifyCommand(); | |||
msg.Payload.Token = token; | |||
msg.Payload.Properties["$device"] = "Discord.Net"; | |||
if (_config.UseLargeThreshold) | |||
msg.Payload.LargeThreshold = 100; | |||
msg.Payload.Compress = true; | |||
QueueMessage(msg); | |||
} | |||
public void SendStatus(long? idleSince, int? gameId) | |||
public void SendResume() | |||
{ | |||
var updateStatus = new UpdateStatusCommand(); | |||
var resumeMsg = new ResumeCommand(); | |||
resumeMsg.Payload.SessionId = _sessionId; | |||
resumeMsg.Payload.Sequence = _lastSeq; | |||
QueueMessage(resumeMsg); | |||
} | |||
public override void SendHeartbeat() | |||
{ | |||
QueueMessage(new HeartbeatCommand()); | |||
} | |||
public void SendStatusUpdate(long? idleSince, int? gameId) | |||
{ | |||
var updateStatus = new StatusUpdateCommand(); | |||
updateStatus.Payload.IdleSince = idleSince; | |||
updateStatus.Payload.GameId = gameId; | |||
QueueMessage(updateStatus); | |||
@@ -155,6 +152,7 @@ namespace Discord.Net.WebSockets | |||
leaveVoice.Payload.ServerId = serverId; | |||
QueueMessage(leaveVoice); | |||
} | |||
public void SendRequestUsers(long serverId, string query = "", int limit = 0) | |||
{ | |||
var getOfflineUsers = new GetUsersCommand(); | |||
@@ -16,11 +16,11 @@ namespace Discord.Net.WebSockets | |||
public partial class GatewayWebSocket | |||
{ | |||
public event EventHandler<WebSocketEventEventArgs> ReceivedEvent; | |||
private void RaiseReceivedEvent(string type, JToken payload) | |||
public event EventHandler<WebSocketEventEventArgs> ReceivedDispatch; | |||
private void RaiseReceivedDispatch(string type, JToken payload) | |||
{ | |||
if (ReceivedEvent != null) | |||
ReceivedEvent(this, new WebSocketEventEventArgs(type, payload)); | |||
if (ReceivedDispatch != null) | |||
ReceivedDispatch(this, new WebSocketEventEventArgs(type, payload)); | |||
} | |||
} | |||
} |
@@ -243,7 +243,6 @@ namespace Discord.Net.WebSockets | |||
_logger.Log(LogSeverity.Debug, $"In: {json}"); | |||
return TaskHelper.CompletedTask; | |||
} | |||
protected abstract object GetKeepAlive(); | |||
protected void QueueMessage(object message) | |||
{ | |||
@@ -255,7 +254,7 @@ namespace Discord.Net.WebSockets | |||
private Task HeartbeatAsync(CancellationToken cancelToken) | |||
{ | |||
return Task.Run(async () => | |||
return Task.Run((Func<Task>)(async () => | |||
{ | |||
try | |||
{ | |||
@@ -263,7 +262,7 @@ namespace Discord.Net.WebSockets | |||
{ | |||
if (_state == (int)WebSocketState.Connected) | |||
{ | |||
QueueMessage(GetKeepAlive()); | |||
SendHeartbeat(); | |||
await Task.Delay(_heartbeatInterval, cancelToken).ConfigureAwait(false); | |||
} | |||
else | |||
@@ -271,7 +270,7 @@ namespace Discord.Net.WebSockets | |||
} | |||
} | |||
catch (OperationCanceledException) { } | |||
}); | |||
})); | |||
} | |||
protected internal void ThrowError() | |||
@@ -283,5 +282,7 @@ namespace Discord.Net.WebSockets | |||
reason.Throw(); | |||
} | |||
} | |||
public abstract void SendHeartbeat(); | |||
} | |||
} |