Beispiel #1
0
        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.");
        }
Beispiel #2
0
        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.");
        }