2024-03-12 14:05:27 -04:00
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Hosting ;
2024-06-16 20:19:31 -04:00
using Serilog ;
2024-03-12 14:05:27 -04:00
using NAudio.Wave.SampleProviders ;
2024-06-24 18:11:36 -04:00
using org.mariuszgromada.math.mxparser ;
2024-07-12 13:36:09 -04:00
using TwitchChatTTS.Hermes.Socket ;
2024-07-16 00:48:55 -04:00
using TwitchChatTTS.Seven.Socket ;
using TwitchChatTTS.Chat.Emotes ;
using CommonSocketLibrary.Abstract ;
using CommonSocketLibrary.Common ;
2024-07-19 12:56:41 -04:00
using TwitchChatTTS.OBS.Socket ;
2024-08-04 19:46:10 -04:00
using TwitchChatTTS.Twitch.Socket.Messages ;
using TwitchChatTTS.Twitch.Socket ;
2024-08-06 15:29:29 -04:00
using TwitchChatTTS.Chat.Commands ;
2024-08-07 15:33:10 -04:00
using System.Text ;
2024-08-12 12:42:53 -04:00
using TwitchChatTTS.Chat.Speech ;
2024-12-02 15:51:04 -05:00
using TwitchChatTTS.Veadotube ;
2024-03-12 14:05:27 -04:00
namespace TwitchChatTTS
{
public class TTS : IHostedService
{
2024-08-04 19:46:10 -04:00
public const int MAJOR_VERSION = 4 ;
2024-12-02 21:39:46 -05:00
public const int MINOR_VERSION = 5 ;
2024-06-16 20:19:31 -04:00
2024-07-06 23:42:33 -04:00
private readonly User _user ;
private readonly HermesApiClient _hermesApiClient ;
private readonly SevenApiClient _sevenApiClient ;
2024-08-04 19:46:10 -04:00
private readonly HermesSocketClient _hermes ;
2024-07-19 12:56:41 -04:00
private readonly OBSSocketClient _obs ;
private readonly SevenSocketClient _seven ;
2024-08-04 19:46:10 -04:00
private readonly TwitchWebsocketClient _twitch ;
2024-12-02 15:51:04 -05:00
private readonly VeadoSocketClient _veado ;
2024-08-06 15:29:29 -04:00
private readonly ICommandFactory _commandFactory ;
private readonly ICommandManager _commandManager ;
2024-07-19 12:56:41 -04:00
private readonly IEmoteDatabase _emotes ;
2024-03-15 08:27:35 -04:00
private readonly TTSPlayer _player ;
2024-08-04 19:46:10 -04:00
private readonly AudioPlaybackEngine _playback ;
2024-08-06 15:29:29 -04:00
private readonly Configuration _configuration ;
2024-06-24 18:11:36 -04:00
private readonly ILogger _logger ;
2024-03-12 14:05:27 -04:00
2024-06-24 18:11:36 -04:00
public TTS (
User user ,
HermesApiClient hermesApiClient ,
SevenApiClient sevenApiClient ,
2024-07-16 00:48:55 -04:00
[FromKeyedServices("hermes")] SocketClient < WebSocketMessage > hermes ,
2024-07-19 12:56:41 -04:00
[FromKeyedServices("obs")] SocketClient < WebSocketMessage > obs ,
[FromKeyedServices("7tv")] SocketClient < WebSocketMessage > seven ,
2024-08-04 19:46:10 -04:00
[FromKeyedServices("twitch")] SocketClient < TwitchWebsocketMessage > twitch ,
2024-12-02 15:51:04 -05:00
[FromKeyedServices("veadotube")] SocketClient < object > veado ,
2024-08-06 15:29:29 -04:00
ICommandFactory commandFactory ,
ICommandManager commandManager ,
2024-07-19 12:56:41 -04:00
IEmoteDatabase emotes ,
2024-06-24 18:11:36 -04:00
TTSPlayer player ,
2024-08-04 19:46:10 -04:00
AudioPlaybackEngine playback ,
2024-08-06 15:29:29 -04:00
Configuration configuration ,
2024-06-24 18:11:36 -04:00
ILogger logger
)
2024-06-16 20:19:31 -04:00
{
2024-07-06 23:42:33 -04:00
_user = user ;
_hermesApiClient = hermesApiClient ;
_sevenApiClient = sevenApiClient ;
2024-07-16 00:48:55 -04:00
_hermes = ( hermes as HermesSocketClient ) ! ;
2024-07-19 12:56:41 -04:00
_obs = ( obs as OBSSocketClient ) ! ;
_seven = ( seven as SevenSocketClient ) ! ;
2024-08-04 19:46:10 -04:00
_twitch = ( twitch as TwitchWebsocketClient ) ! ;
2024-12-02 15:51:04 -05:00
_veado = ( veado as VeadoSocketClient ) ! ;
2024-08-06 15:29:29 -04:00
_commandFactory = commandFactory ;
_commandManager = commandManager ;
2024-07-19 12:56:41 -04:00
_emotes = emotes ;
2024-03-15 08:27:35 -04:00
_configuration = configuration ;
_player = player ;
2024-08-04 19:46:10 -04:00
_playback = playback ;
2024-06-24 18:11:36 -04:00
_logger = logger ;
2024-03-12 14:05:27 -04:00
}
2024-06-16 20:19:31 -04:00
public async Task StartAsync ( CancellationToken cancellationToken )
{
2024-03-12 14:05:27 -04:00
Console . Title = "TTS - Twitch Chat" ;
2024-08-07 15:33:10 -04:00
Console . OutputEncoding = Encoding . UTF8 ;
2024-07-06 23:42:33 -04:00
License . iConfirmCommercialUse ( "abcdef" ) ;
2024-06-16 20:19:31 -04:00
2024-07-16 00:48:55 -04:00
if ( string . IsNullOrWhiteSpace ( _configuration . Hermes ? . Token ) )
2024-07-12 13:36:09 -04:00
{
2024-07-06 23:42:33 -04:00
_logger . Error ( "Hermes API token not set in the configuration file." ) ;
return ;
}
2024-03-15 08:27:35 -04:00
2024-07-12 13:36:09 -04:00
var hermesVersion = await _hermesApiClient . GetLatestTTSVersion ( ) ;
if ( hermesVersion = = null )
{
2024-12-02 16:25:12 -05:00
_logger . Error ( "Failed to fetch latest TTS version. Something went wrong." ) ;
return ;
2024-07-12 13:36:09 -04:00
}
2024-12-02 16:25:12 -05:00
if ( hermesVersion . MajorVersion > TTS . MAJOR_VERSION | | hermesVersion . MajorVersion = = TTS . MAJOR_VERSION & & hermesVersion . MinorVersion > TTS . MINOR_VERSION )
2024-06-16 20:19:31 -04:00
{
_logger . Information ( $"A new update for TTS is avaiable! Version {hermesVersion.MajorVersion}.{hermesVersion.MinorVersion} is available at {hermesVersion.Download}" ) ;
var changes = hermesVersion . Changelog . Split ( "\n" ) ;
if ( changes ! = null & & changes . Any ( ) )
2024-08-12 15:45:17 -04:00
_logger . Information ( "Changelog:\n - " + string . Join ( "\n - " , changes ) + "\n\n" ) ;
2024-06-16 20:19:31 -04:00
await Task . Delay ( 15 * 1000 ) ;
}
2024-03-15 08:27:35 -04:00
2024-07-16 00:48:55 -04:00
await InitializeHermesWebsocket ( ) ;
2024-06-16 20:19:31 -04:00
try
{
2024-08-04 19:46:10 -04:00
var hermesAccount = await _hermesApiClient . FetchHermesAccountDetails ( ) ;
_user . HermesUserId = hermesAccount . Id ;
_user . HermesUsername = hermesAccount . Username ;
_user . TwitchUsername = hermesAccount . Username ;
2024-08-06 15:29:29 -04:00
_user . TwitchUserId = long . Parse ( hermesAccount . BroadcasterId ) ;
}
catch ( ArgumentNullException )
{
_logger . Error ( "Ensure you have your Twitch account linked to TTS." ) ;
await Task . Delay ( TimeSpan . FromSeconds ( 30 ) ) ;
return ;
}
catch ( FormatException )
{
_logger . Error ( "Ensure you have your Twitch account linked to TTS." ) ;
await Task . Delay ( TimeSpan . FromSeconds ( 30 ) ) ;
return ;
2024-06-16 20:19:31 -04:00
}
catch ( Exception ex )
{
2024-07-16 00:48:55 -04:00
_logger . Error ( ex , "Failed to initialize properly. Restart app please." ) ;
2024-08-06 15:29:29 -04:00
await Task . Delay ( TimeSpan . FromSeconds ( 30 ) ) ;
2024-06-16 20:19:31 -04:00
return ;
}
2024-08-07 18:01:04 -04:00
2024-08-12 12:42:53 -04:00
_playback . AddOnMixerInputEnded ( ( object? s , SampleProviderEventArgs e ) = >
{
if ( _player . Playing ? . Audio = = e . SampleProvider )
{
_player . Playing = null ;
}
} ) ;
2024-12-02 15:51:04 -05:00
try
{
_veado . Initialize ( ) ;
await _veado . Connect ( ) ;
}
catch ( Exception e ) {
_logger . Warning ( e , "Failed to connect to Veado websocket server." ) ;
}
2024-08-07 18:01:04 -04:00
try
{
await _twitch . Connect ( ) ;
}
catch ( Exception e )
{
_logger . Error ( e , "Failed to connect to Twitch websocket server." ) ;
await Task . Delay ( TimeSpan . FromSeconds ( 30 ) ) ;
return ;
}
2024-03-15 08:27:35 -04:00
2024-07-06 23:42:33 -04:00
var emoteSet = await _sevenApiClient . FetchChannelEmoteSet ( _user . TwitchUserId . ToString ( ) ) ;
2024-07-16 00:48:55 -04:00
if ( emoteSet ! = null )
_user . SevenEmoteSetId = emoteSet . Id ;
2024-07-12 13:36:09 -04:00
2024-08-06 15:29:29 -04:00
_commandManager . Update ( _commandFactory ) ;
2024-07-06 23:42:33 -04:00
await InitializeEmotes ( _sevenApiClient , emoteSet ) ;
2024-07-12 13:36:09 -04:00
await InitializeSevenTv ( ) ;
2024-03-12 14:05:27 -04:00
await InitializeObs ( ) ;
}
2024-08-12 12:42:53 -04:00
public Task StopAsync ( CancellationToken cancellationToken )
2024-03-12 14:05:27 -04:00
{
if ( cancellationToken . IsCancellationRequested )
2024-06-16 20:19:31 -04:00
_logger . Warning ( "Application has stopped due to cancellation token." ) ;
2024-03-12 14:05:27 -04:00
else
2024-06-16 20:19:31 -04:00
_logger . Warning ( "Application has stopped." ) ;
2024-08-12 12:42:53 -04:00
return Task . CompletedTask ;
2024-03-15 08:27:35 -04:00
}
2024-06-16 20:19:31 -04:00
private async Task InitializeHermesWebsocket ( )
{
try
{
2024-07-16 00:48:55 -04:00
_hermes . Initialize ( ) ;
await _hermes . Connect ( ) ;
2024-03-15 08:27:35 -04:00
}
2024-07-16 00:48:55 -04:00
catch ( Exception e )
2024-06-16 20:19:31 -04:00
{
2024-07-16 00:48:55 -04:00
_logger . Error ( e , "Connecting to hermes failed. Skipping hermes websockets." ) ;
2024-03-15 08:27:35 -04:00
}
2024-06-16 20:19:31 -04:00
}
2024-03-15 08:27:35 -04:00
2024-07-12 13:36:09 -04:00
private async Task InitializeSevenTv ( )
2024-06-16 20:19:31 -04:00
{
try
{
2024-07-19 12:56:41 -04:00
_seven . Initialize ( ) ;
await _seven . Connect ( ) ;
2024-06-16 20:19:31 -04:00
}
2024-07-16 00:48:55 -04:00
catch ( Exception e )
2024-06-16 20:19:31 -04:00
{
2024-07-16 00:48:55 -04:00
_logger . Error ( e , "Connecting to 7tv failed. Skipping 7tv websockets." ) ;
2024-03-12 14:05:27 -04:00
}
}
2024-06-16 20:19:31 -04:00
private async Task InitializeObs ( )
{
try
{
2024-07-19 12:56:41 -04:00
_obs . Initialize ( ) ;
await _obs . Connect ( ) ;
2024-06-16 20:19:31 -04:00
}
catch ( Exception )
{
_logger . Warning ( "Connecting to obs failed. Skipping obs websockets." ) ;
2024-03-12 14:05:27 -04:00
}
}
2024-07-16 00:48:55 -04:00
private async Task InitializeEmotes ( SevenApiClient sevenapi , EmoteSet ? channelEmotes )
2024-06-16 20:19:31 -04:00
{
var globalEmotes = await sevenapi . FetchGlobalSevenEmotes ( ) ;
if ( channelEmotes ! = null & & channelEmotes . Emotes . Any ( ) )
{
_logger . Information ( $"Loaded {channelEmotes.Emotes.Count()} 7tv channel emotes." ) ;
foreach ( var entry in channelEmotes . Emotes )
2024-07-19 12:56:41 -04:00
_emotes . Add ( entry . Name , entry . Id ) ;
2024-06-16 20:19:31 -04:00
}
if ( globalEmotes ! = null & & globalEmotes . Any ( ) )
{
_logger . Information ( $"Loaded {globalEmotes.Count()} 7tv global emotes." ) ;
foreach ( var entry in globalEmotes )
2024-07-19 12:56:41 -04:00
_emotes . Add ( entry . Name , entry . Id ) ;
2024-06-16 20:19:31 -04:00
}
2024-03-12 14:05:27 -04:00
}
}
}