diff --git a/Hermes/Socket/Handlers/LoginAckHandler.cs b/Hermes/Socket/Handlers/LoginAckHandler.cs index fb96cfb..277b32a 100644 --- a/Hermes/Socket/Handlers/LoginAckHandler.cs +++ b/Hermes/Socket/Handlers/LoginAckHandler.cs @@ -53,19 +53,24 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers _user.VoicesEnabled = new HashSet(message.EnabledTTSVoices); _user.TwitchConnection = message.Connections.FirstOrDefault(c => c.Default && c.Type == "twitch"); _user.NightbotConnection = message.Connections.FirstOrDefault(c => c.Default && c.Type == "nightbot"); - - _bus.Send(this, "twitch id", _user.TwitchUserId); + if (_user.TwitchConnection != null) + { + _logger.Information("Twitch connection: " + _user.TwitchConnection.Name + " / " + _user.TwitchConnection.AccessToken); + } var filters = message.WordFilters.Where(f => f.Search != null && f.Replace != null).ToList(); foreach (var filter in filters) { try { - var re = new Regex(filter.Search, ((RegexOptions) filter.Flag) | RegexOptions.Compiled); + var re = new Regex(filter.Search, ((RegexOptions)filter.Flag) | RegexOptions.Compiled); re.Match(string.Empty); filter.Regex = re; } - catch (Exception) { } + catch (Exception) + { + _logger.Warning($"Failed to create a regular expression for a TTS filter [filter id: {filter.Search}]"); + } } _user.RegexFilters = filters; @@ -93,6 +98,7 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers } _logger.Information("TTS is now ready."); + _bus.Send(this, "tts_connected", _user); client.Ready = true; } } diff --git a/Hermes/Socket/HermesSocketClient.cs b/Hermes/Socket/HermesSocketClient.cs index 9425849..2d50c04 100644 --- a/Hermes/Socket/HermesSocketClient.cs +++ b/Hermes/Socket/HermesSocketClient.cs @@ -247,7 +247,7 @@ namespace TwitchChatTTS.Hermes.Socket public void Initialize() { - _logger.Information("Initializing Hermes websocket client."); + _logger.Information("Initializing Tom to Speech websocket client."); OnConnected += async (sender, e) => { @@ -257,7 +257,7 @@ namespace TwitchChatTTS.Hermes.Socket return; Connected = true; } - _logger.Information("Hermes websocket client connected."); + _logger.Information("Tom to Speech websocket client connected."); _heartbeatTimer.Enabled = true; LastHeartbeatReceived = DateTime.UtcNow; @@ -281,7 +281,7 @@ namespace TwitchChatTTS.Hermes.Socket LoggedIn = false; Ready = false; - _logger.Warning("Hermes websocket client disconnected."); + _logger.Warning("Tom to Speech websocket client disconnected."); _heartbeatTimer.Enabled = false; await Reconnect(_backoff); @@ -396,7 +396,7 @@ namespace TwitchChatTTS.Hermes.Socket } catch (Exception ex) { - _logger.Error(ex, "Failed to send a heartbeat back to the Hermes websocket server."); + _logger.Error(ex, "Failed to send a heartbeat back to the Tom to Speech websocket server."); } } else if (signalTime - LastHeartbeatReceived > TimeSpan.FromSeconds(120)) @@ -407,7 +407,7 @@ namespace TwitchChatTTS.Hermes.Socket } catch (Exception ex) { - _logger.Error(ex, "Failed to disconnect from Hermes websocket server."); + _logger.Error(ex, "Failed to disconnect from Tom to Speech websocket server."); Ready = false; LoggedIn = false; Connected = false; @@ -423,7 +423,7 @@ namespace TwitchChatTTS.Hermes.Socket { if (!Connected) { - _logger.Warning("Hermes websocket client is not connected. Not sending a message."); + _logger.Warning("Tom to Speech websocket client is not connected. Not sending a message."); return; } diff --git a/Hermes/Socket/Requests/CreateTTSFilterAck.cs b/Hermes/Socket/Requests/CreateTTSFilterAck.cs index e6f091b..6819546 100644 --- a/Hermes/Socket/Requests/CreateTTSFilterAck.cs +++ b/Hermes/Socket/Requests/CreateTTSFilterAck.cs @@ -48,7 +48,7 @@ namespace TwitchChatTTS.Hermes.Socket.Requests } catch (Exception) { - _logger.Warning($"Failed to generate a Regular Expression using '{filter.Search}' [filter id: {filter.Id}]"); + _logger.Warning($"Failed to create a regular expression for a TTS filter [filter id: {filter.Search}]"); } _logger.Debug($"Filter data [filter id: {filter.Id}][search: {filter.Search}][replace: {filter.Replace}]"); diff --git a/Hermes/Socket/Requests/GetTTSWordFiltersAck.cs b/Hermes/Socket/Requests/GetTTSWordFiltersAck.cs index 72a194a..c5f546e 100644 --- a/Hermes/Socket/Requests/GetTTSWordFiltersAck.cs +++ b/Hermes/Socket/Requests/GetTTSWordFiltersAck.cs @@ -33,11 +33,14 @@ namespace TwitchChatTTS.Hermes.Socket.Requests { try { - var re = new Regex(filter.Search, ((RegexOptions) filter.Flag) | RegexOptions.Compiled); + var re = new Regex(filter.Search, ((RegexOptions)filter.Flag) | RegexOptions.Compiled); re.Match(string.Empty); filter.Regex = re; } - catch (Exception) { } + catch (Exception) + { + _logger.Warning($"Failed to create a regular expression for a TTS filter [filter id: {filter.Search}]"); + } } _user.RegexFilters = filters; _logger.Information($"TTS word filters [count: {_user.RegexFilters.Count}] have been refreshed."); diff --git a/Hermes/Socket/Requests/UpdateTTSFilterAck.cs b/Hermes/Socket/Requests/UpdateTTSFilterAck.cs index 27f8790..dd4b59a 100644 --- a/Hermes/Socket/Requests/UpdateTTSFilterAck.cs +++ b/Hermes/Socket/Requests/UpdateTTSFilterAck.cs @@ -52,7 +52,10 @@ namespace TwitchChatTTS.Hermes.Socket.Requests re.Match(string.Empty); current.Regex = re; } - catch (Exception) { } + catch (Exception) + { + _logger.Warning($"Failed to create a regular expression for a TTS filter [filter id: {filter.Search}]"); + } _logger.Information($"Filter has been updated [filter id: {filter.Id}]"); } diff --git a/Startup.cs b/Startup.cs index 4b00f08..a631304 100644 --- a/Startup.cs +++ b/Startup.cs @@ -181,7 +181,6 @@ s.AddKeyedTransient, TwitchWebsocketClient> { var factory = sp.GetRequiredService(); var client = factory.GetWorkingClient(); - client.Connect().Wait(); return client; }); s.AddKeyedTransient, TwitchWebsocketClient>("twitch-create"); diff --git a/TTS.cs b/TTS.cs index 4ab961f..b275e1d 100644 --- a/TTS.cs +++ b/TTS.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; -using NAudio.Wave.SampleProviders; using org.mariuszgromada.math.mxparser; using TwitchChatTTS.Hermes.Socket; using TwitchChatTTS.Seven.Socket; @@ -13,10 +12,10 @@ using TwitchChatTTS.Twitch.Socket.Messages; using TwitchChatTTS.Twitch.Socket; using TwitchChatTTS.Chat.Commands; using System.Text; -using TwitchChatTTS.Chat.Speech; using TwitchChatTTS.Veadotube; using TwitchChatTTS.Bus; using System.Reactive.Linq; +using System.Net.WebSockets; namespace TwitchChatTTS { @@ -36,8 +35,6 @@ namespace TwitchChatTTS private readonly ICommandFactory _commandFactory; private readonly ICommandManager _commandManager; private readonly IEmoteDatabase _emotes; - private readonly TTSPlayer _player; - private readonly AudioPlaybackEngine _playback; private readonly ServiceBusCentral _bus; private readonly Configuration _configuration; private readonly ILogger _logger; @@ -54,8 +51,6 @@ namespace TwitchChatTTS ICommandFactory commandFactory, ICommandManager commandManager, IEmoteDatabase emotes, - TTSPlayer player, - AudioPlaybackEngine playback, ServiceBusCentral bus, Configuration configuration, ILogger logger @@ -72,8 +67,6 @@ namespace TwitchChatTTS _commandFactory = commandFactory; _commandManager = commandManager; _emotes = emotes; - _player = player; - _playback = playback; _bus = bus; _configuration = configuration; _logger = logger; @@ -87,7 +80,7 @@ namespace TwitchChatTTS if (string.IsNullOrWhiteSpace(_configuration.Hermes?.Token)) { - _logger.Error("Hermes API token not set in the configuration file."); + _logger.Error("Tom to Speech API token not set in the yml file."); return; } @@ -113,56 +106,70 @@ namespace TwitchChatTTS _logger.Warning("Failed to check for version updates."); } + var disposables = new List(); + // 7tv - var twitchTopic = _bus.GetTopic("twitch id"); - twitchTopic.FirstAsync().Subscribe(async (data) => + var connected = _bus.GetTopic("tts_connected"); + disposables.Add(connected.FirstAsync().Subscribe(async (data) => { - var twitchId = data.Value?.ToString(); - if (twitchId == null) + if (data.Value is not User user) + { + _logger.Warning("Something went wrong. Unable to fetch 7tv data."); return; + } + if (user.TwitchUserId == default) + { + _logger.Warning("Unable to fetch 7tv data. If this is wrong, ensure your Tom to Speech token is valid."); + return; + } var emoteSet = await _sevenApiClient.FetchChannelEmoteSet(_user.TwitchUserId); if (emoteSet != null) + { _user.SevenEmoteSetId = emoteSet.Id; + _logger.Debug($"Fetched the 7tv emote set id [emote set id: {emoteSet.Id}]"); + } await InitializeEmotes(_sevenApiClient, emoteSet); await InitializeSevenTv(); - }); + })); - await InitializeHermesWebsocket(); - - _playback.AddOnMixerInputEnded((object? s, SampleProviderEventArgs e) => + disposables.Add(connected.FirstAsync().Subscribe(async (data) => { - if (_player.Playing?.Audio == e.SampleProvider) + if (data.Value is not User user) { - _player.Playing = null; + _logger.Warning("Something went wrong. Not connecting to Twitch."); + return; + } + if (user.TwitchUserId == default) + { + _logger.Warning("Not connecting to Twitch. If this is wrong, ensure your Tom to Speech token is valid."); + return; } - }); - try - { - _veado.Initialize(); - await _veado.Connect(); - } - catch (Exception e) - { - _logger.Warning(e, "Failed to connect to Veado websocket server."); - } - - try - { - await _twitch.Connect(); - } - catch (Exception e) - { - _logger.Error(e, "Failed to connect to Twitch websocket server."); - await Task.Delay(TimeSpan.FromSeconds(30)); - return; - } + try + { + await _twitch.Connect(); + } + catch (Exception e) + { + _logger.Error(e, "Failed to connect to Twitch websocket server."); + } + })); _commandManager.Update(_commandFactory); + await InitializeVeadotube(); + await InitializeHermesWebsocket(); await InitializeObs(); + + // Check if user has successfully connected. + await Task.Run(async () => + { + await Task.Delay(TimeSpan.FromSeconds(5)); + if (_user.TwitchUserId == default) + _logger.Warning("Ensure your Tom to Speech token in the tts.config.yml file is valid."); + }); } public Task StopAsync(CancellationToken cancellationToken) @@ -181,6 +188,10 @@ namespace TwitchChatTTS _hermes.Initialize(); await _hermes.Connect(); } + catch (WebSocketException e) when (e.Message.Contains("The server returned status code '502'")) + { + _logger.Error("Could not connect to Tom to Speech server."); + } catch (Exception e) { _logger.Error(e, "Connecting to hermes failed. Skipping hermes websockets."); @@ -213,6 +224,19 @@ namespace TwitchChatTTS } } + private async Task InitializeVeadotube() + { + try + { + _veado.Initialize(); + await _veado.Connect(); + } + catch (Exception e) + { + _logger.Warning(e, "Failed to connect to Veado websocket server."); + } + } + private async Task InitializeEmotes(SevenApiClient sevenapi, EmoteSet? channelEmotes) { var globalEmotes = await sevenapi.FetchGlobalSevenEmotes(); diff --git a/TTSListening.cs b/TTSListening.cs index 77f6218..60aef92 100644 --- a/TTSListening.cs +++ b/TTSListening.cs @@ -30,6 +30,14 @@ namespace TwitchChatTTS public Task StartAsync(CancellationToken cancellationToken) { + _playback.AddOnMixerInputEnded((object? s, SampleProviderEventArgs e) => + { + if (_player.Playing?.Audio == e.SampleProvider) + { + _player.Playing = null; + } + }); + Task.Run(async () => { while (true) diff --git a/Twitch/Socket/Handlers/SessionWelcomeHandler.cs b/Twitch/Socket/Handlers/SessionWelcomeHandler.cs index 7ad51d5..9318cc9 100644 --- a/Twitch/Socket/Handlers/SessionWelcomeHandler.cs +++ b/Twitch/Socket/Handlers/SessionWelcomeHandler.cs @@ -29,18 +29,9 @@ namespace TwitchChatTTS.Twitch.Socket.Handlers return; } - int waited = 0; - while ((_user.TwitchUserId <= 0 || _user.TwitchConnection == null) && ++waited < 5) - await Task.Delay(TimeSpan.FromSeconds(1)); - - if (_user.TwitchConnection == null) - { - _logger.Error("Ensure you have linked either your Twitch account or TTS' bot to your TTS account. Twitch client will not be connecting."); - return; - } - - _api.Initialize(_user.TwitchConnection.ClientId, _user.TwitchConnection.AccessToken); - var span = _user.TwitchConnection.ExpiresAt - DateTime.Now; + var twitchConnection = _user.TwitchConnection!; + _api.Initialize(twitchConnection.ClientId, twitchConnection.AccessToken); + var span = twitchConnection.ExpiresAt - DateTime.Now; var timeLeft = span.Days >= 2 ? span.Days + " days" : (span.Hours >= 2 ? span.Hours + " hours" : span.Minutes + " minutes"); if (span.Days >= 3) _logger.Information($"Twitch connection has {timeLeft} before it is revoked."); @@ -48,7 +39,7 @@ namespace TwitchChatTTS.Twitch.Socket.Handlers _logger.Warning($"Twitch connection has {timeLeft} before it is revoked. Refreshing the token is soon required."); else { - _logger.Error("Twitch connection has its permissions revoked. Refresh the token. Twith client will not be connecting."); + _logger.Error("Twitch connection has its permissions revoked. Refresh the token. Twitch client will not be connecting."); return; }