public async Task ConnectAsync(CancellationToken cancellationToken = default) { var handler = new HttpClientHandler() { CookieContainer = _cookies }; var httpClient = new HttpClient(handler) { BaseAddress = _serverUri }; var request = new HttpRequestMessage(HttpMethod.Get, $"/api/join?={_botInformation.DisplayName}&role=Player"); await httpClient.SendAsync(request, cancellationToken); _connection.On("d", new[] { typeof(JArray) }, HandlePayloadAsync); // Binding this because the client crashes on unknown invocations _connection.On("l", new[] { typeof(JArray) }, (data) => Task.CompletedTask); _connection.On("mapSizeIncreased", new[] { typeof(JArray) }, data => Task.CompletedTask); _connection.On("disconnect", () => DisconnectAsync().Wait()); await _connection.StartAsync(cancellationToken); var stateCookie = _cookies.GetCookies(_serverUri)["shootr.state"]; var decodedValue = WebUtility.UrlDecode(stateCookie.Value); var shootRState = JsonConvert.DeserializeObject <ShootRState>(decodedValue); var clientInitializationData = await _connection.InvokeAsync <InitializationData>("bot_initializeClient", shootRState.RegistrationID, cancellationToken); _payloadDecompressor = new PayloadDecompressor(clientInitializationData); await _connection.InvokeAsync("bot_readyForPayloads", cancellationToken); _connected = true; }
public async Task ConnectAsync(CancellationToken cancellationToken = default) { var handler = new HttpClientHandler() { CookieContainer = _cookies }; var httpClient = new HttpClient(handler) { BaseAddress = _serverUri }; var request = new HttpRequestMessage(HttpMethod.Get, $"/api/join?name={_botInformation.DisplayName}&role=Player&photoUrl={_botInformation.Photo}"); await httpClient.SendAsync(request, cancellationToken); _connection.On("d", new[] { typeof(JArray) }, (parameters) => HandlePayloadAsync((JArray)parameters[0])); // Binding this because the client crashes on unknown invocations _connection.On <JArray>("l", (data) => { }); _connection.On <JArray>("mapSizeIncreased", data => { }); _connection.On("disconnect", () => DisconnectAsync().Wait()); _connection.On <string, string, int>("chatMessage", (from, message, type) => Console.WriteLine($"{from}: {message}")); await _connection.StartAsync(cancellationToken); var stateCookie = _cookies.GetCookies(_serverUri)["shootr.state"]; var decodedValue = WebUtility.UrlDecode(stateCookie.Value); var shootRState = JsonConvert.DeserializeObject <ShootRState>(decodedValue); var clientInitializationData = await _connection.InvokeAsync <InitializationData>("bot_initializeClient", shootRState.RegistrationID, cancellationToken); if (clientInitializationData.ServerFull) { throw new Exception("Server Full."); } _initializationData = clientInitializationData; _payloadDecompressor = new PayloadDecompressor(clientInitializationData); await _connection.InvokeAsync("bot_readyForPayloads", cancellationToken); _connected = true; }
internal async Task InternalConnectAsync() { SocketLock socketLock = null; try { if (this.GatewayInfo == null) { await this.InternalUpdateGatewayAsync().ConfigureAwait(false); } await this.InitializeAsync().ConfigureAwait(false); socketLock = this.GetSocketLock(); await socketLock.LockAsync().ConfigureAwait(false); } catch { socketLock?.UnlockAfter(TimeSpan.Zero); throw; } if (!this.Presences.ContainsKey(this.CurrentUser.Id)) { this._presences[this.CurrentUser.Id] = new DiscordPresence { Discord = this, RawActivity = new TransportActivity(), Activity = new DiscordActivity(), Status = UserStatus.Online, InternalUser = new TransportUser { Id = this.CurrentUser.Id, Username = this.CurrentUser.Username, Discriminator = this.CurrentUser.Discriminator, AvatarHash = this.CurrentUser.AvatarHash } }; } else { var pr = this._presences[this.CurrentUser.Id]; pr.RawActivity = new TransportActivity(); pr.Activity = new DiscordActivity(); pr.Status = UserStatus.Online; } Volatile.Write(ref this._skippedHeartbeats, 0); this._webSocketClient = this.Configuration.WebSocketClientFactory(this.Configuration.Proxy); this._payloadDecompressor = this.Configuration.GatewayCompressionLevel != GatewayCompressionLevel.None ? new PayloadDecompressor(this.Configuration.GatewayCompressionLevel) : null; this._cancelTokenSource = new CancellationTokenSource(); this._cancelToken = this._cancelTokenSource.Token; this._webSocketClient.Connected += SocketOnConnect; this._webSocketClient.Disconnected += SocketOnDisconnect; this._webSocketClient.MessageReceived += SocketOnMessage; this._webSocketClient.ExceptionThrown += SocketOnException; var gwuri = new QueryUriBuilder(this.GatewayUri) .AddParameter("v", "6") .AddParameter("encoding", "json"); if (this.Configuration.GatewayCompressionLevel == GatewayCompressionLevel.Stream) { gwuri.AddParameter("compress", "zlib-stream"); } await this._webSocketClient.ConnectAsync(gwuri.Build()).ConfigureAwait(false); Task SocketOnConnect(IWebSocketClient sender, SocketEventArgs e) => this._socketOpened.InvokeAsync(this, e); async Task SocketOnMessage(IWebSocketClient sender, SocketMessageEventArgs e) { MemoryStream msg = default; if (e is SocketTextMessageEventArgs etext) { msg = etext.Message; } else if (e is SocketBinaryMessageEventArgs ebin) // :DDDD { msg = new MemoryStream(); if (!this._payloadDecompressor.TryDecompress(new ArraySegment <byte>(ebin.Message), msg)) { this.Logger.LogError(LoggerEvents.WebSocketReceiveFailure, "Payload decompression failed"); return; } msg.Seek(0, SeekOrigin.Begin); if (this.Configuration.MinimumLogLevel == LogLevel.Trace) { var cs = new MemoryStream(); await msg.CopyToAsync(cs).ConfigureAwait(false); msg.Seek(0, SeekOrigin.Begin); cs.Seek(0, SeekOrigin.Begin); using (var sr = new StreamReader(cs, Utilities.UTF8)) { this.Logger.LogTrace(LoggerEvents.GatewayWsRx, await sr.ReadToEndAsync().ConfigureAwait(false)); } } } try { await this.HandleSocketMessageAsync(msg).ConfigureAwait(false); } catch (Exception ex) { this.Logger.LogError(LoggerEvents.WebSocketReceiveFailure, ex, "Socket handler suppressed an exception"); } } Task SocketOnException(IWebSocketClient sender, SocketErrorEventArgs e) => this._socketErrored.InvokeAsync(this, e); async Task SocketOnDisconnect(IWebSocketClient sender, SocketCloseEventArgs e) { // release session and connection this.ConnectionLock.Set(); this.SessionLock.Set(); if (!this._disposed) { this._cancelTokenSource.Cancel(); } this.Logger.LogDebug(LoggerEvents.ConnectionClose, "Connection closed ({0}, '{1}')", e.CloseCode, e.CloseMessage); await this._socketClosed.InvokeAsync(this, e).ConfigureAwait(false); if (this.Configuration.AutoReconnect && (e.CloseCode < 4001 || e.CloseCode >= 5000)) { this.Logger.LogCritical(LoggerEvents.ConnectionClose, "Connection terminated ({0}, '{1}'), reconnecting", e.CloseCode, e.CloseMessage); if (this._status == null) { await this.ConnectAsync().ConfigureAwait(false); } else if (this._status.IdleSince.HasValue) { await this.ConnectAsync(this._status._activity, this._status.Status, Utilities.GetDateTimeOffsetFromMilliseconds(this._status.IdleSince.Value)).ConfigureAwait(false); } else { await this.ConnectAsync(this._status._activity, this._status.Status).ConfigureAwait(false); } } else { this.Logger.LogCritical(LoggerEvents.ConnectionClose, "Connection terminated ({0}, '{1}')", e.CloseCode, e.CloseMessage); } } }