public override async Task Connect() { // Connect to the gateway socket = new ClientWebSocket(); var uri = new Uri(DefaultGateway); await socket.ConnectAsync(uri, CancellationToken.None); _log.Info("Connected to a Discord socket."); // Receive 10 Hello var response = await ReceiveMessage(); if (response.OpCode != (int)MainOpCodeTypes.Hello) { throw new WebSocketException("Socket Out of Order: First message not OpCode 10, Hello."); } var hello = response.DeserializeDataPayload <HelloPayload>(); // Set up messaging systems SendMessagesAgentAsync(); ReceiveMessagesAgentAsync(); _log.Debug("Started messaging systems."); // Send 1 Heartbeat (and continue to do so) heart = new MainGatewayHeart(hello.HeartbeatInterval, this); _log.Debug("Started heartbeat."); // Send 2 Identify var identify = new IdentifyCommand { Data = { AuthenticationToken = authorizationToken, ConnectionProperties = { OperatingSystemName = "windows", BrowserName = "mjolnir", DeviceName = "mjolnir", }, AllowCompression = false, ConnectionPresence = { ConnectionGame = { Name = "\"PUNCH LINE!\" by Shokotan ♥ Denpa Gumi", }, Status = "online", } } }; await SendMessage(JsonConvert.SerializeObject(identify)); Console.WriteLine(JsonConvert.SerializeObject(identify)); _log.Debug("Sent identity."); // Receive 0 Ready var ready = await readyResponseSource.Task; _log.Info($"Current User: {ready.CurrentUser.Username}"); _log.Info($"Accessible DMs: {ready.AssociatedDirectMessageChannels.Select(c => c.Name).ToSequenceString()}"); _log.Info($"Accessible Guilds: {ready.AssociatedGuilds.Select(g => g.Id).ToSequenceString()}"); currentUser = ready.CurrentUser; sessionId = ready.SessionId; _log.Info($"Fully connected."); }
public override async Task Connect() { // Send 4 Voice State Update var voiceStateUpdateRequest = new VoiceStateUpdateCommand { Data = { GuildId = voiceChannel.GuildId.Value, ChannelId = voiceChannel.Id, MuteSelf = false, DeafenSelf = false, } }; await mainGateway.SendMessage(JsonConvert.SerializeObject(voiceStateUpdateRequest)); // Receive 0 Voice State Update and 0 Voice Server Update var voiceStateUpdate = await InitialVoiceStateUpdateSource.Task; var voiceServerUpdate = await InitialVoiceServerUpdateSource.Task; Debug.Assert(voiceStateUpdate.GuildId.Value == voiceServerUpdate.GuildId); _log.Info("Received voice update messages."); sessionId = voiceStateUpdate.SessionId; token = voiceServerUpdate.VoiceConnectionToken; var endpoint = voiceServerUpdate.Endpoint; if (endpoint.EndsWith(":80")) { endpoint = endpoint.Substring(0, endpoint.Length - ":80".Length); } // Connect to the gateway socket = new ClientWebSocket(); var uri = new Uri("wss://" + endpoint + "/?v=3"); await socket.ConnectAsync(uri, CancellationToken.None); _log.Info($"Connected to a Discord voice socket: {endpoint}"); // Set up messaging systems SendMessagesAgentAsync(); _log.Debug("Started outgoing message system."); // Send 0 Identify var identify = new VoiceIdentifyCommand { Data = { SessionId = voiceStateUpdate.SessionId, UserId = voiceStateUpdate.UserId.ToString(), ServerId = voiceServerUpdate.GuildId.ToString(), VoiceConnectionToken = voiceServerUpdate.VoiceConnectionToken, } }; await SendMessage(JsonConvert.SerializeObject(identify)); _log.Debug("Sent identity."); // Receive 8 Hello var response = await ReceiveMessage(); if (response.OpCode != (int)VoiceOpCodeTypes.Hello) { throw new WebSocketException("Socket Out of Order: First message not OpCode 8, Hello."); } var hello = response.DeserializeDataPayload <HelloPayload>(); _log.Debug("Received 8 Hello."); ReceiveMessagesAgentAsync(); _log.Debug("Started incoming message system."); // Receive 2 Ready var ready = await readyResponseSource.Task; ssrc = ready.SSRC; Debug.Assert(ready.SupportedEncryptionModes.Contains("xsalsa20_poly1305")); // Send 3 Heartbeat (and continue to do so) heart = new VoiceGatewayHeart((int)(hello.HeartbeatInterval * 0.75), this); _log.Debug("Started heartbeat."); // Connect UDP udp = new UdpClient(11000); udp.Connect(endpoint, ready.UdpPort); _log.Info($"Connected to udp port {ready.UdpPort}."); ReceiveDataAgent(); // IP Discovery string ip4Address; using (WebClient client = new WebClient()) { var ip4MeHtml = client.DownloadString("http://ip4.me"); ip4Address = Regex.Match(ip4MeHtml, @"[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+").Value; _log.Info($"Discovered my ip address: {ip4Address}"); } // Send 1 Select Protocol var selectProtocol = new VoiceSelectProtocolCommand { Data = { Data = { ClientExternalIpAddress = ip4Address, ClientPort = 11000, SelectedEncryptionMode = "xsalsa20_poly1305" // the only protocol allowed by Discord } } }; await SendMessage(JsonConvert.SerializeObject(selectProtocol)); _log.Info("Sent select protocol."); // Receive 4 Session Description var sessionDescription = await sessionDescriptionResponseSource.Task; Debug.Assert(sessionDescription.EncryptionMode == "xsalsa20_poly1305"); encryptionKey = sessionDescription.EncryptionKey; _log.Info($"Fully connected."); }