static async Task Main(string[] args) { // register to unhandled exceptions handling // this allows logging exceptions that were not handled with a try-catch block AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; // optional: create a logger factory ILoggerFactory logFactory = CreateLoggerFactory(); // optional: enable DI - add logger factory to it as well IServiceCollection services = new ServiceCollection() .AddSingleton <ILoggerFactory>(logFactory); // create client and listen to events we're interested in _client = new WolfClient(logFactory.CreateLogger <WolfClient>()); _client.AddMessageListener <WelcomeEvent>(OnWelcome); // these 2 callbacks are invoked if received message is a WolfEvent (first callback) // initialize commands system CommandsOptions options = new CommandsOptions() { Prefix = "!", // set prefix RequirePrefix = PrefixRequirement.Always, // make prefix always required - can also for example require it in group only CaseSensitivity = false // make commands case insensitive }; CommandsService commands = new CommandsService(_client, options, logFactory.CreateLogger <CommandsService>(), services.BuildServiceProvider()); await commands.StartAsync(); // calling StartAsync causes reload of all commands // start connection and prevent the application from closing await _client.ConnectAsync(); await Task.Delay(-1); }
static async Task Main(string[] args) { // register to unhandled exceptions handling // this allows logging exceptions that were not handled with a try-catch block AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; // optional: create a logger ILogger <WolfClient> log = CreateLogger <WolfClient>(); // create client and listen to events we're interested in _client = new WolfClient(log); _client.MessageReceived += OnMessageReceived; // This event is raised when client receives and parses any message type. _client.AddMessageListener <WelcomeEvent>(OnWelcome); // these 2 callbacks are invoked if received message is a WolfEvent (first callback) _client.AddMessageListener <ChatMessage>(OnChatMessage); // or a chat message (second callback). // reconnector is part of Wolfringo.Utilities package WolfClientReconnector reconnector = new WolfClientReconnector(_client); reconnector.FailedToReconnect += OnFailedToReconnect; // start connection and prevent the application from closing await _client.ConnectAsync(); await Task.Delay(-1); }
/// <summary>Reconnects the client.</summary> /// <remarks>This method is invoked when the client has disconnected.</remarks> /// <exception cref="AggregateException">Aggregate exception containing all exceptions occured over all reconnect attempts.</exception> private async void OnClientDisconnected(object sender, EventArgs e) { this.Config.Log?.LogDebug("Attempting to reconnect, max {Attempts} times. Delay: {Delay}", this.Config.ReconnectAttempts, this.Config.ReconnectionDelay); bool isInfinite = this.Config.ReconnectAttempts < 0; ICollection <Exception> exceptions = new List <Exception>(isInfinite ? 0 : this.Config.ReconnectAttempts); for (int i = 1; isInfinite || i <= this.Config.ReconnectAttempts; i++) { try { this.Config.CancellationToken.ThrowIfCancellationRequested(); this.Config.Log?.LogTrace("Reconnection attempt {Attempt}", i); // wait reconnection delay if any if (this.Config.ReconnectionDelay > TimeSpan.Zero) { await Task.Delay(this.Config.ReconnectionDelay, this.Config.CancellationToken).ConfigureAwait(false); } // attempt to reconnnect unconditionally await _client.ConnectAsync(this.Config.CancellationToken).ConfigureAwait(false); return; } catch (OperationCanceledException ex) { exceptions.Add(ex); break; } catch (Exception ex) when( (isInfinite && ex.LogAsError(this.Config.Log, "Failed to auto-reconnect")) || ex.LogAsWarning(this.Config.Log, "Failed to auto-reconnect")) { exceptions.Add(ex); } } AggregateException aggrEx = exceptions.Any() ? new AggregateException("Error(s) occured when trying to automatically reconnect", exceptions) : new AggregateException("Failed to reconnect, but no exceptions were thrown"); this.Config.Log?.LogCritical(aggrEx, "Failed to reconnect after {Attempts} attempts", this.Config.ReconnectAttempts > 0 ? this.Config.ReconnectAttempts.ToString() : "Infinite"); FailedToReconnect?.Invoke(this, new UnhandledExceptionEventArgs(aggrEx, true)); throw aggrEx; }
/// <summary>Reconnects the client.</summary> /// <remarks>This method is invoked when the client has disconnected.</remarks> /// <exception cref="AggregateException">Aggregate exception containing all exceptions occured over all reconnect attempts.</exception> private async void OnClientDisconnected(object sender, EventArgs e) { this.Config.Log?.LogDebug("Attempting to reconnect, max {Attempts} times. Delay: {Delay}", this.Config.ReconnectAttempts, this.Config.ReconnectionDelay); ICollection <Exception> exceptions = new List <Exception>(this.Config.ReconnectAttempts); for (int i = 1; i <= this.Config.ReconnectAttempts; i++) { try { this.Config.Log?.LogTrace("Reconnection attempt {Attempt}", i); // wait reconnection delay if any if (this.Config.ReconnectionDelay > TimeSpan.Zero) { await Task.Delay(this.Config.ReconnectionDelay); } // attempt to reconnnect unconditionally await _client.ConnectAsync(this.Config.CancellationToken).ConfigureAwait(false); return; } catch (Exception ex) { exceptions.Add(ex); } } AggregateException aggrEx = exceptions.Any() ? new AggregateException("Error(s) occured when trying to automatically reconnect", exceptions) : new AggregateException("Failed to reconnect, but no exceptions were thrown"); this.Config.Log?.LogError(aggrEx, "Failed to reconnect after {Attempts} attempts", this.Config.ReconnectAttempts); FailedToReconnect?.Invoke(this, new UnhandledExceptionEventArgs(aggrEx, true)); throw aggrEx; }