2024-08-06 15:29:29 -04:00
using CommonSocketLibrary.Abstract ;
using Microsoft.Extensions.DependencyInjection ;
2024-06-16 20:19:31 -04:00
using Serilog ;
2024-07-16 00:48:55 -04:00
using TwitchChatTTS.Hermes.Socket ;
2024-08-06 15:29:29 -04:00
using TwitchChatTTS.Twitch.Socket ;
2024-08-04 19:46:10 -04:00
using TwitchChatTTS.Twitch.Socket.Messages ;
2024-07-19 12:56:41 -04:00
using static TwitchChatTTS . Chat . Commands . TTSCommands ;
2024-06-16 20:19:31 -04:00
namespace TwitchChatTTS.Chat.Commands
{
2024-07-19 12:56:41 -04:00
public class TTSCommand : IChatCommand
2024-06-16 20:19:31 -04:00
{
2024-08-06 15:29:29 -04:00
private readonly TwitchWebsocketClient _twitch ;
2024-06-24 18:11:36 -04:00
private readonly User _user ;
2024-08-06 15:29:29 -04:00
private readonly TwitchApiClient _client ;
2024-06-24 18:11:36 -04:00
private readonly ILogger _logger ;
2024-06-16 20:19:31 -04:00
2024-07-19 12:56:41 -04:00
2024-08-06 15:29:29 -04:00
public TTSCommand (
[FromKeyedServices("twitch")] SocketClient < TwitchWebsocketMessage > twitch ,
User user ,
TwitchApiClient client ,
ILogger logger )
2024-06-16 20:19:31 -04:00
{
2024-08-06 15:29:29 -04:00
_twitch = ( twitch as TwitchWebsocketClient ) ! ;
2024-06-24 18:11:36 -04:00
_user = user ;
2024-08-06 15:29:29 -04:00
_client = client ;
2024-06-16 20:19:31 -04:00
_logger = logger ;
2024-07-19 12:56:41 -04:00
}
public string Name = > "tts" ;
public void Build ( ICommandBuilder builder )
{
builder . CreateCommandTree ( Name , b = >
{
b . CreateStaticInputParameter ( "add" , b = >
{
b . CreateVoiceNameParameter ( "voiceName" , false )
. CreateCommand ( new AddTTSVoiceCommand ( _user , _logger ) ) ;
} )
2024-08-04 19:46:10 -04:00
. AddAlias ( "insert" , "add" )
2024-07-19 12:56:41 -04:00
. CreateStaticInputParameter ( "delete" , b = >
{
b . CreateVoiceNameParameter ( "voiceName" , true )
. CreateCommand ( new DeleteTTSVoiceCommand ( _user , _logger ) ) ;
} )
2024-08-04 19:46:10 -04:00
. AddAlias ( "del" , "delete" )
. AddAlias ( "remove" , "delete" )
2024-07-19 12:56:41 -04:00
. CreateStaticInputParameter ( "enable" , b = >
{
b . CreateVoiceNameParameter ( "voiceName" , false )
. CreateCommand ( new SetTTSVoiceStateCommand ( true , _user , _logger ) ) ;
} )
2024-08-04 19:46:10 -04:00
. AddAlias ( "on" , "enable" )
. AddAlias ( "enabled" , "enable" )
. AddAlias ( "true" , "enable" )
2024-07-19 12:56:41 -04:00
. CreateStaticInputParameter ( "disable" , b = >
{
b . CreateVoiceNameParameter ( "voiceName" , true )
. CreateCommand ( new SetTTSVoiceStateCommand ( false , _user , _logger ) ) ;
} )
2024-08-04 19:46:10 -04:00
. AddAlias ( "off" , "disable" )
. AddAlias ( "disabled" , "disable" )
2024-08-06 15:29:29 -04:00
. AddAlias ( "false" , "disable" )
. CreateStaticInputParameter ( "join" , b = >
{
b . CreateMentionParameter ( "mention" , true )
. AddPermission ( "tts.commands.tts.join" )
. CreateCommand ( new JoinRoomCommand ( _twitch , _client , _user , _logger ) ) ;
} )
. CreateStaticInputParameter ( "leave" , b = >
{
b . CreateMentionParameter ( "mention" , true )
. AddPermission ( "tts.commands.tts.leave" )
. CreateCommand ( new LeaveRoomCommand ( _twitch , _client , _user , _logger ) ) ;
} ) ;
2024-07-19 12:56:41 -04:00
} ) ;
}
private sealed class AddTTSVoiceCommand : IChatPartialCommand
{
private readonly User _user ;
private readonly ILogger _logger ;
public bool AcceptCustomPermission { get = > false ; }
public AddTTSVoiceCommand ( User user , ILogger logger )
{
_user = user ;
_logger = logger ;
}
2024-08-04 19:46:10 -04:00
public async Task Execute ( IDictionary < string , string > values , ChannelChatMessage message , HermesSocketClient client )
2024-07-19 12:56:41 -04:00
{
if ( _user = = null | | _user . VoicesAvailable = = null )
return ;
var voiceName = values [ "voiceName" ] ;
var voiceNameLower = voiceName . ToLower ( ) ;
var exists = _user . VoicesAvailable . Any ( v = > v . Value . ToLower ( ) = = voiceNameLower ) ;
if ( exists )
{
2024-08-04 19:46:10 -04:00
_logger . Warning ( $"Voice already exists [voice: {voiceName}][id: {message.ChatterUserId}]" ) ;
2024-07-19 12:56:41 -04:00
return ;
}
await client . CreateTTSVoice ( voiceName ) ;
2024-08-04 19:46:10 -04:00
_logger . Information ( $"Added a new TTS voice [voice: {voiceName}][creator: {message.ChatterUserLogin}][creator id: {message.ChatterUserId}]" ) ;
2024-07-19 12:56:41 -04:00
}
2024-06-16 20:19:31 -04:00
}
2024-07-19 12:56:41 -04:00
private sealed class DeleteTTSVoiceCommand : IChatPartialCommand
2024-06-16 20:19:31 -04:00
{
2024-07-19 12:56:41 -04:00
private readonly User _user ;
private ILogger _logger ;
public bool AcceptCustomPermission { get = > false ; }
public DeleteTTSVoiceCommand ( User user , ILogger logger )
{
_user = user ;
_logger = logger ;
}
2024-08-04 19:46:10 -04:00
public async Task Execute ( IDictionary < string , string > values , ChannelChatMessage message , HermesSocketClient client )
2024-07-19 12:56:41 -04:00
{
if ( _user = = null | | _user . VoicesAvailable = = null )
{
2024-08-04 19:46:10 -04:00
_logger . Warning ( $"Voices available are not loaded [chatter: {message.ChatterUserLogin}][chatter id: {message.ChatterUserId}]" ) ;
2024-07-19 12:56:41 -04:00
return ;
}
var voiceName = values [ "voiceName" ] ;
var voiceNameLower = voiceName . ToLower ( ) ;
var exists = _user . VoicesAvailable . Any ( v = > v . Value . ToLower ( ) = = voiceNameLower ) ;
if ( ! exists )
{
2024-08-04 19:46:10 -04:00
_logger . Warning ( $"Voice does not exist [voice: {voiceName}][chatter: {message.ChatterUserLogin}][chatter id: {message.ChatterUserId}]" ) ;
return ;
}
var voiceId = _user . VoicesAvailable . FirstOrDefault ( v = > v . Value . ToLower ( ) = = voiceNameLower ) . Key ;
2024-08-06 15:29:29 -04:00
if ( voiceId = = null )
{
2024-08-04 19:46:10 -04:00
_logger . Warning ( $"Could not find the identifier for the tts voice [voice name: {voiceName}]" ) ;
2024-07-19 12:56:41 -04:00
return ;
}
await client . DeleteTTSVoice ( voiceId ) ;
2024-08-04 19:46:10 -04:00
_logger . Information ( $"Deleted a TTS voice [voice: {voiceName}][chatter: {message.ChatterUserLogin}][chatter id: {message.ChatterUserId}]" ) ;
2024-07-19 12:56:41 -04:00
}
2024-06-16 20:19:31 -04:00
}
2024-07-19 12:56:41 -04:00
private sealed class SetTTSVoiceStateCommand : IChatPartialCommand
2024-06-16 20:19:31 -04:00
{
2024-07-19 12:56:41 -04:00
private bool _state ;
private readonly User _user ;
private ILogger _logger ;
public bool AcceptCustomPermission { get = > true ; }
public SetTTSVoiceStateCommand ( bool state , User user , ILogger logger )
{
_state = state ;
_user = user ;
_logger = logger ;
}
2024-08-04 19:46:10 -04:00
public async Task Execute ( IDictionary < string , string > values , ChannelChatMessage message , HermesSocketClient client )
2024-07-19 12:56:41 -04:00
{
if ( _user = = null | | _user . VoicesAvailable = = null )
return ;
2024-06-16 20:19:31 -04:00
2024-07-19 12:56:41 -04:00
var voiceName = values [ "voiceName" ] ;
var voiceNameLower = voiceName . ToLower ( ) ;
var voiceId = _user . VoicesAvailable . FirstOrDefault ( v = > v . Value . ToLower ( ) = = voiceNameLower ) . Key ;
2024-06-16 20:19:31 -04:00
2024-07-19 12:56:41 -04:00
await client . UpdateTTSVoiceState ( voiceId , _state ) ;
2024-08-04 19:46:10 -04:00
_logger . Information ( $"Changed state for TTS voice [voice: {voiceName}][state: {_state}][invoker: {message.ChatterUserLogin}][id: {message.ChatterUserId}]" ) ;
2024-07-19 12:56:41 -04:00
}
2024-06-16 20:19:31 -04:00
}
2024-08-06 15:29:29 -04:00
private sealed class JoinRoomCommand : IChatPartialCommand
{
private readonly TwitchWebsocketClient _twitch ;
private readonly TwitchApiClient _client ;
private readonly User _user ;
private ILogger _logger ;
public bool AcceptCustomPermission { get = > true ; }
public JoinRoomCommand (
[FromKeyedServices("twitch")] SocketClient < TwitchWebsocketMessage > twitch ,
TwitchApiClient client ,
User user ,
ILogger logger
)
{
_twitch = ( twitch as TwitchWebsocketClient ) ! ;
_client = client ;
_user = user ;
_logger = logger ;
}
public async Task Execute ( IDictionary < string , string > values , ChannelChatMessage message , HermesSocketClient client )
{
var mention = values [ "mention" ] . ToLower ( ) ;
var fragment = message . Message . Fragments . FirstOrDefault ( f = > f . Mention ! = null & & f . Text . ToLower ( ) = = mention ) ;
if ( fragment = = null )
{
_logger . Warning ( "Cannot find the channel to join chat with." ) ;
return ;
}
await _client . CreateEventSubscription ( "channel.chat.message" , "1" , _twitch . SessionId , _user . TwitchUserId . ToString ( ) , fragment . Mention ! . UserId ) ;
_logger . Information ( $"Joined chat room [channel: {fragment.Mention.UserLogin}][channel id: {fragment.Mention.UserId}][invoker: {message.ChatterUserLogin}][id: {message.ChatterUserId}]" ) ;
}
}
private sealed class LeaveRoomCommand : IChatPartialCommand
{
private readonly TwitchWebsocketClient _twitch ;
private readonly TwitchApiClient _client ;
private readonly User _user ;
private ILogger _logger ;
public bool AcceptCustomPermission { get = > true ; }
public LeaveRoomCommand (
[FromKeyedServices("twitch")] SocketClient < TwitchWebsocketMessage > twitch ,
TwitchApiClient client ,
User user ,
ILogger logger
)
{
_twitch = ( twitch as TwitchWebsocketClient ) ! ;
_client = client ;
_user = user ;
_logger = logger ;
}
public async Task Execute ( IDictionary < string , string > values , ChannelChatMessage message , HermesSocketClient client )
{
var mention = values [ "mention" ] . ToLower ( ) ;
var fragment = message . Message . Fragments . FirstOrDefault ( f = > f . Mention ! = null & & f . Text . ToLower ( ) = = mention ) ;
if ( fragment ? . Mention = = null )
{
_logger . Warning ( "Cannot find the channel to leave chat from." ) ;
return ;
}
var subscriptionId = _twitch . GetSubscriptionId ( _user . TwitchUserId . ToString ( ) , "channel.chat.message" ) ;
if ( subscriptionId = = null )
{
_logger . Warning ( "Cannot find the subscription for that channel." ) ;
return ;
}
try
{
await _client . DeleteEventSubscription ( subscriptionId ) ;
_twitch . RemoveSubscription ( fragment . Mention . UserId , "channel.chat.message" ) ;
_logger . Information ( $"Joined chat room [channel: {fragment.Mention.UserLogin}][channel id: {fragment.Mention.UserId}][invoker: {message.ChatterUserLogin}][id: {message.ChatterUserId}]" ) ;
}
catch ( Exception ex )
{
_logger . Error ( ex , "Failed to delete the subscription from Twitch." ) ;
}
}
}
2024-06-16 20:19:31 -04:00
}
}