using System.Collections.Concurrent; using System.Text.RegularExpressions; using CommonSocketLibrary.Abstract; using CommonSocketLibrary.Common; using HermesSocketLibrary.Socket.Data; using Serilog; using TwitchChatTTS.Bus; namespace TwitchChatTTS.Hermes.Socket.Handlers { public class LoginAckHandler : IWebSocketHandler { private readonly User _user; private readonly NightbotApiClient _nightbot; private readonly ServiceBusCentral _bus; private readonly ILogger _logger; public int OperationCode { get; } = 2; public LoginAckHandler(User user, NightbotApiClient nightbot, ServiceBusCentral bus, ILogger logger) { _user = user; _nightbot = nightbot; _bus = bus; _logger = logger; } public async Task Execute(SocketClient sender, Data data) { if (data is not LoginAckMessage message || message == null) return; if (sender is not HermesSocketClient client) return; if (message.AnotherClient) { if (client.LoggedIn) _logger.Warning($"Another client has connected to the same account via {(message.WebLogin ? "web login" : "application")}."); return; } if (client.LoggedIn) { _logger.Error("Attempted to log in again while still logged in."); return; } _user.Slave = message.Slave; _logger.Information(_user.Slave ? "This client is not responsible for reacting to chat messages." : "This client is responsible for reacting to chat messages."); _user.HermesUserId = message.UserId; _user.HermesUsername = message.UserName; _user.TwitchUsername = message.UserName; _user.TwitchUserId = long.Parse(message.ProviderAccountId); _user.OwnerId = message.OwnerId; _user.DefaultTTSVoice = message.DefaultTTSVoice; _user.VoicesAvailable = new ConcurrentDictionary(message.TTSVoicesAvailable); _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"); 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); re.Match(string.Empty); filter.Regex = re; } catch (Exception) { _logger.Warning($"Failed to create a regular expression for a TTS filter [filter id: {filter.Search}]"); } } _user.RegexFilters = filters; client.LoggedIn = true; _logger.Information($"Logged in as {_user.TwitchUsername} {(message.WebLogin ? "via web" : "via TTS app")}."); await client.FetchTTSChatterVoices(); await client.FetchChatterIdentifiers(); await client.FetchEmotes(); await client.FetchRedemptions(); await client.FetchPermissions(); await client.FetchPolicies(); if (_user.NightbotConnection != null) { _nightbot.Initialize(_user.NightbotConnection.ClientId, _user.NightbotConnection.AccessToken); var span = _user.NightbotConnection.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($"Nightbot connection has {timeLeft} before it is revoked."); else if (span.Minutes >= 0) _logger.Warning($"Nightbot connection has {timeLeft} before it is revoked. Refreshing the token is soon required."); else _logger.Error("Nightbot connection has its permissions revoked. Refresh the token. Anything related to Nightbot from this application will not work."); } _logger.Information("TTS is now ready."); _bus.Send(this, "tts_connected", _user); client.Ready = true; } } }