internal async Task SendHeartbeatAsync(long seq) { var more_than_5 = Volatile.Read(ref this._skippedHeartbeats) > 5; var guilds_comp = Volatile.Read(ref this._guildDownloadCompleted); if (guilds_comp && more_than_5) { this.Logger.LogCritical(LoggerEvents.HeartbeatFailure, "Server failed to acknowledge more than 5 heartbeats - connection is zombie"); await this.InternalReconnectAsync(code : 4001, message : "Too many heartbeats missed").ConfigureAwait(false); return; } else if (!guilds_comp && more_than_5) { this.Logger.LogWarning(LoggerEvents.HeartbeatFailure, "Server failed to acknowledge more than 5 heartbeats, but the guild download is still running - check your connection speed"); } Volatile.Write(ref this._lastSequence, seq); this.Logger.LogTrace(LoggerEvents.Heartbeat, "Sending heartbeat"); var heartbeat = new GatewayPayload { OpCode = GatewayOpCode.Heartbeat, Data = seq }; var heartbeat_str = JsonConvert.SerializeObject(heartbeat); await this.WsSendAsync(heartbeat_str).ConfigureAwait(false); this._lastHeartbeat = DateTimeOffset.Now; Interlocked.Increment(ref this._skippedHeartbeats); }
public void Send(GatewayPayload payload) { if (!_runCts.IsCancellationRequested) { _sendQueue?.Add(payload); } }
protected override void OnMessage(GatewayPayload payload) { switch (payload.OpCode) { case GatewayOpCode.Voice_Hello: var helloData = Convert <HelloEventData>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.Hello, helloData); break; case GatewayOpCode.Voice_Ready: var readyData = Convert <VoiceReadyResponse>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.Ready, readyData); break; case GatewayOpCode.Voice_Heartbeat: var heartbeatData = Convert <int>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.HeartbeatACK, heartbeatData); break; case GatewayOpCode.Voice_SessionDescription: var sessionData = Convert <SessionDesciptionResponse>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.SessionDesciption, sessionData); break; case GatewayOpCode.Voice_Speaking: var speakingData = Convert <SpeakingResponse>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.Speaking, speakingData); break; } }
public void SendIdentify(string token) { Task.Factory.StartNew(async() => { var identifyPayload = new IdentifyEventData() { Token = token, Properties = new IdentifyProperties() { OperatingSystem = "windows", Browser = "test_lib", Device = "test_lib" } }; var identifyPayloadJson = JsonConvert.SerializeObject(identifyPayload); var identifyRequest = new GatewayPayload() { Opcode = DiscordOpcodeEnum.Identify, EventData = JToken.FromObject(identifyPayload) }; await SendAsync(identifyRequest); }); }
private void HandleEvent(GatewayPayload evnt, TaskCompletionSource <bool> readySignal) { switch (evnt.Operation) { case GatewayOperation.Dispatch: HandleDispatchEvent(evnt, readySignal); break; case GatewayOperation.InvalidSession: if ((bool)evnt.Data != true) // Is resumable { SetSession(null); } readySignal.TrySetResult(false); GatewayInvalidSession?.Invoke((bool)evnt.Data); break; case GatewayOperation.Heartbeat: SendHeartbeatAck(); GatewayHeartbeat?.Invoke(); break; case GatewayOperation.HeartbeatAck: GatewayHeartbeatAck?.Invoke(); break; case GatewayOperation.Hello: GatewayHello?.Invoke(evnt.Data as HelloEvent); break; case GatewayOperation.Reconnect: GatewayReconnect?.Invoke(); break; } }
public async Task RunHeartbeat(int heartbeatInterval) { _logger.LogInformation("Starting heartbeating - interval {0}ms", heartbeatInterval); while (!_heartbeatToken.IsCancellationRequested) { int now = Environment.TickCount; if (_heartbeatTimes.Count != 0 && (now - _lastMessageTime) > heartbeatInterval) { _logger.LogCritical("Did not receive HeartbeatAck"); CloseHeartbeating(); await CreateConnectionAsync(WebSocketCloseStatus.EndpointUnavailable); break; } _heartbeatTimes.Enqueue(now); var heartbeatEvent = new GatewayPayload { Opcode = GatewayOpCode.Heartbeat, EventData = _sequenceNumber ?? null, }; var heartbeatEventBytes = Encoding.UTF8.GetBytes( JsonConvert.SerializeObject(heartbeatEvent)); await _discordSocketClient.SendAsync(heartbeatEventBytes, true); await Task.Delay(heartbeatInterval, _heartbeatToken); } _logger.LogWarning("Client stopped heartbeating"); }
public async Task SendAsync(GatewayPayload payload) { var text = JsonConvert.SerializeObject(payload); await _socket.SendAsync( new ArraySegment <byte>(Encoding.UTF8.GetBytes(text)), WebSocketMessageType.Text, true, CancellationToken.None).ConfigureAwait(false); }
internal async Task SendIdentifyAsync(StatusUpdate status) { var identify = new GatewayIdentify { Token = Utilities.GetFormattedToken(this), Compress = this.Configuration.GatewayCompressionLevel == GatewayCompressionLevel.Payload, LargeThreshold = this.Configuration.LargeThreshold, ShardInfo = new ShardInfo { ShardId = this.Configuration.ShardId, ShardCount = this.Configuration.ShardCount }, Presence = status, Intents = this.Configuration.Intents }; var payload = new GatewayPayload { OpCode = GatewayOpCode.Identify, Data = identify }; var payloadstr = JsonConvert.SerializeObject(payload); await this.WsSendAsync(payloadstr).ConfigureAwait(false); if (this.Configuration.Intents.HasValue) { this.Logger.LogDebug(LoggerEvents.Intents, "Registered gateway intents ({0})", this.Configuration.Intents.Value); } }
/// <summary> /// Handles Gateway Payloads received from the SocketClient /// </summary> /// <param name="payload">Payload received from the SocketClient</param> /// <returns></returns> private async Task HandleGatewayPayload(GatewayPayload payload) { var opcode = payload.Opcode; switch (opcode) { case OpCodes.Dispatch: break; case OpCodes.Heartbeat: await this._socketClient.SendAsync(OpCodes.Heartbeat, LastSequenceNumber); break; case OpCodes.Reconnect: break; case OpCodes.InvalidSession: break; case OpCodes.Hello: await OnHelloMessageAsync((payload.Data as JObject).ToObject <GatewayHello>()); break; case OpCodes.HeartbeatAcknowledge: this._socketClient.LastHeartbeatAcknowledge = DateTime.Now; break; default: break; } }
private protected override async Task OnMessageAsync(MessageEventArgs messageEventArgs) { if (messageEventArgs.Data.Length <= 0) { Logger.LogWarning("Gateway sent empty payload data."); return; } var gatewayPayload = new GatewayPayload(messageEventArgs.Data); Logger.LogDebug($"Received {Enum.GetName(typeof(OpCode), gatewayPayload.OpCode)}."); switch (gatewayPayload.OpCode) { case OpCode.Hello when gatewayPayload.OpData is HelloPayload helloPayload: _heartBeatTask = SetupHeartbeatAsync(helloPayload.Interval); break; case OpCode.Ready when gatewayPayload.OpData is ReadyPayload readyPayload: await SelectProtocolAsync(readyPayload); break; case OpCode.SessionDescription when gatewayPayload.OpData is SessionDescriptionPayload descriptionPayload: break; case OpCode.HeartbeatAcknowledge when gatewayPayload.OpData is int nonce: Logger.LogDebug($"Heartbeat ACK {nonce}"); break; } }
private async Task SetupHeartbeatAsync(int interval) { while (Volatile.Read(ref _isOpen)) { var heartbeatPayload = new GatewayPayload(OpCode.Heartbeat, DateTime.Now.Ticks); await SocketClient.SendAsync(heartbeatPayload); await Task.Delay(interval); } }
public async Task ProcessMessageAsync(GatewayPayload payload) { var message = JsonConvert.DeserializeObject <GatewayMessage>(payload.EventData.ToString()); if (_commandValidator.IsCommand(message)) { var command = new Command(message); await _commandDispatcher.DispatchAsync(command); } }
public async Task DispatchEvent(GatewayPayload @event) { switch (@event.EventName) { case "MESSAGE_CREATE": { await _commandProcessor.ProcessMessageAsync(@event); } break; case "MESSAGE_DELETE": { // Delete tracked message } break; case "MESSAGE_REACTION_ADD": { await _commandProcessor.ProcessReactionAsync(@event); } break; case "MESSAGE_REACTION_REMOVE": { await _commandProcessor.ProcessReactionAsync(@event); } break; case "GUILD_CREATE": { await _componentContext.Resolve <IGatewayEventHandler <Guild> >() .HandleAsync(@event.EventData); } break; case "READY": { await _componentContext.Resolve <IGatewayEventHandler <ReadyEvent> >() .HandleAsync(@event.EventData); } break; case "RESUMED": { _logger.LogWarning("Session resumed!"); } break; default: _logger.LogWarning($"Unhandled event received [{@event.Opcode} - {@event.EventName}]"); break; } }
protected override void OnMessage(GatewayPayload payload) { switch (payload.OpCode) { case GatewayOpCode.Hello: var helloData = Convert <HelloEventData>(payload.Data); Messenger.Broadcast(DiscordEvent.Hello, helloData); break; case GatewayOpCode.HeartbeatACK: Messenger.Broadcast(DiscordEvent.HeartbeatACK); break; case GatewayOpCode.Dispatch: Messenger.Broadcast(DiscordEvent.SequenceNumber, payload.SequenceNumber); switch (payload.EventName) { case TypingStartEventData.Name: var typingData = Convert <TypingStartEventData>(payload.Data); Messenger.Broadcast(DiscordEvent.TypingStart, typingData); break; case MessageCreateEventData.Name: var messageData = Convert <MessageCreateEventData>(payload.Data); Messenger.Broadcast(DiscordEvent.MessageCreate, messageData); break; case ReadyEventData.Name: var readyData = Convert <ReadyEventData>(payload.Data); Messenger.Broadcast(DiscordEvent.Ready, readyData); break; case GuildCreateEventData.Name: var guildData = Convert <GuildCreateEventData>(payload.Data); Messenger.Broadcast(DiscordEvent.GuildCreate, guildData); break; case VoiceServerUpdate.Name: var voiceServerUpdate = Convert <VoiceServerUpdate>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.ServerUpdate, voiceServerUpdate); break; case VoiceStateUpdateResponse.Name: var voiceStateUpdate = Convert <VoiceStateUpdateResponse>(payload.Data); Messenger.Broadcast(DiscordEvent.Voice.StatusUpdate, voiceStateUpdate); break; } break; } }
public async Task SendAsync(GatewayPayload payload) { var name = Enum.GetName(typeof(DiscordOpcodeEnum), payload.Opcode); var jsonString = JsonConvert.SerializeObject(payload); var buffer = new ArraySegment <byte>(Encoding.UTF8.GetBytes(jsonString)); await _client.SendAsync( buffer, WebSocketMessageType.Text, true, CancellationToken.None); }
internal async Task InternalUpdateStatusAsync(DiscordActivity activity, UserStatus?userStatus, DateTimeOffset?idleSince) { if (activity != null && activity.Name != null && activity.Name.Length > 128) { throw new Exception("Game name can't be longer than 128 characters!"); } var since_unix = idleSince != null ? (long?)Utilities.GetUnixTime(idleSince.Value) : null; var act = activity ?? new DiscordActivity(); var status = new StatusUpdate { Activity = new TransportActivity(act), IdleSince = since_unix, IsAFK = idleSince != null, Status = userStatus ?? UserStatus.Online }; // Solution to have status persist between sessions this._status = status; var status_update = new GatewayPayload { OpCode = GatewayOpCode.StatusUpdate, Data = status }; var statusstr = JsonConvert.SerializeObject(status_update); await this.WsSendAsync(statusstr).ConfigureAwait(false); if (!this._presences.ContainsKey(this.CurrentUser.Id)) { this._presences[this.CurrentUser.Id] = new DiscordPresence { Discord = this, Activity = act, Status = userStatus ?? UserStatus.Online, InternalUser = new TransportUser { Id = this.CurrentUser.Id } }; } else { var pr = this._presences[this.CurrentUser.Id]; pr.Activity = act; pr.Status = userStatus ?? pr.Status; } }
private void ToggleSpeaking(bool speaking) { var payload = new GatewayPayload { OpCode = GatewayOpCode.Voice_Speaking, Data = new SpeakingRequest { speaking = speaking, delay = 0, ssrc = udpClient.ssrc } }; voiceGateway.Send(payload); }
public async Task SendAsync(int opcode, object data, string t = null) { var payload = new GatewayPayload { Opcode = opcode, Data = JToken.FromObject(data) }; if (t != null) { payload.Event = t; } await SendAsync(payload); }
public static IEventData GetEventData(this GatewayPayload payload) { IEventData result = null; if (payload.EventName == EventNameConst.MESSAGE_CREATE) { result = JsonConvert.DeserializeObject <MessageCreateEventData>(payload.EventData.ToString()); } if (payload.EventName == EventNameConst.READY) { result = JsonConvert.DeserializeObject <ReadyEventData>(payload.EventData.ToString()); } return(result); }
private async Task ResumeSession(string sessionId) { var resumeEvent = new GatewayPayload { Opcode = GatewayOpCode.Resume, EventData = new ResumeEvent { Token = Environment.GetEnvironmentVariable("BOT_TOKEN"), SessionId = sessionId, Sequence = _sequenceNumber.Value } }; var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(resumeEvent)); await _discordSocketClient.SendAsync(bytes, true); }
private void SendHeartbeat() { //Debug.Log($"{gateway.Name}: Heartbeat"); if (!acknowledged) { Debug.LogError($"{gateway.Name}: Previous heartbeat wasn't acknowledged"); } var heartbeat = new GatewayPayload { OpCode = OpCode, Data = Data }; acknowledged = false; gateway.Send(heartbeat); }
public void JoinVoice(string guildId, string channelId) { var payload = new GatewayPayload { OpCode = GatewayOpCode.VoiceStateUpdate, Data = new VoiceStateUpdateRequest { guild_id = guildId, channel_id = channelId, self_mute = false, self_deaf = false } }; gateway.Send(payload); }
/// <inheritdoc /> public override async Task UpdateSpeakingAsync(SpeakingFlags speakingFlags) { if (!Volatile.Read(ref _isOpen)) { throw new InvalidOperationException(); } var speakingPayload = new GatewayPayload(OpCode.Speaking, new SpeakingPayload { Speaking = speakingFlags, Delay = 0, SSRC = _ssrc }); await SocketClient.SendAsync(speakingPayload); }
private async Task SelectProtocolAsync(ReadyPayload readyPayload) { _ssrc = readyPayload.SSRC; Logger.LogDebug($"UDP client connecting to {readyPayload.Ip}:{readyPayload.Port}"); _udpClient.Connect(readyPayload.Ip, readyPayload.Port); var selectPayload = new GatewayPayload(OpCode.SelectProtocol, new SelectPayload { Protocol = "udp", Data = new { address = readyPayload.Ip, port = readyPayload.Port, mode = EncryptionMode.Select(readyPayload.Modes) } }); await SocketClient.SendAsync(selectPayload); }
//TODO: Handle Resume: ///<summary> ///See <a href="https://discordapp.com/developers/docs/topics/voice-connections#resuming-voice-connection">Discord API Documentation</a> ///</summary> /// private void OnHello(HelloEventData e) { var payload = new GatewayPayload { OpCode = GatewayOpCode.Voice_Identify, Data = new VoiceIdentifyRequest { server_id = guildId, user_id = userId, session_id = sessionId, token = token } }; voiceGateway.Send(payload); heartbeatService = new VoiceHeartbeatService(voiceGateway, e.heartbeat_interval); }
public void StartHeartbeat() { Task.Factory.StartNew(async() => { while (true) { await Task.Delay(_heartbeatInterval); var heartbeatRequest = new GatewayPayload() { Opcode = DiscordOpcodeEnum.Heartbeat, EventData = new JValue(_lastSequence) }; await SendAsync(heartbeatRequest); } }); }
internal async Task SendResumeAsync() { var resume = new GatewayResume { Token = Utilities.GetFormattedToken(this), SessionId = this._sessionId, SequenceNumber = Volatile.Read(ref this._lastSequence) }; var resume_payload = new GatewayPayload { OpCode = GatewayOpCode.Resume, Data = resume }; var resumestr = JsonConvert.SerializeObject(resume_payload); await this.WsSendAsync(resumestr).ConfigureAwait(false); }
/// <summary> /// Sending payloads to the websocket /// </summary> /// <param name="opCode">OpCode of the operation wanted to perform</param> /// <param name="data">Data to send with the payload</param> /// <param name="sequence">Sequence Number</param> /// <param name="eventName">Event Name</param> public async Task SendAsync(OpCodes opCode, object data, int?sequence = null, string eventName = null) { var payload = new GatewayPayload { Opcode = opCode, Data = data, SequenceNumber = sequence, EventName = eventName }; string jsonString = JsonConvert.SerializeObject(payload); var buffer = UTF8Encoding.UTF8.GetBytes(jsonString); ArraySegment <byte> arraySegment = new ArraySegment <byte>(buffer); await this._webSocket.SendAsync(arraySegment, WebSocketMessageType.Binary, true, this._cancellationTokenSource.Token); this._logger?.Debug("Sent payload to the server"); }
public async Task HandleAsync(GatewayPayload payload) { var s = JsonConvert.SerializeObject(payload, Formatting.Indented); _logger.LogInformation(s); var dispatchEvent = payload.GetEventData(); if (dispatchEvent is MessageCreateEventData) { var messageCreateEventData = dispatchEvent as MessageCreateEventData; await _messageCreateHandlerService.HandleAsync('!', messageCreateEventData); } else if (dispatchEvent is ReadyEventData) { var readyEventData = dispatchEvent as ReadyEventData; _userService.DiscordAuthInfo.User = readyEventData.User; } }
private async Task IdentifyClient() { var identityEvent = new GatewayPayload { Opcode = GatewayOpCode.Identify, EventData = new IdentifyEvent { Token = Environment.GetEnvironmentVariable("BOT_TOKEN"), Intents = 1791, Compress = false, Properties = new Dictionary <string, string> { { "$os", "windows" }, { "$browser", "crabot" }, { "$device", "crabot" } } } }; var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(identityEvent)); await _discordSocketClient.SendAsync(bytes, true); }