Fixed command permissions. Moved to using Twitch's EventSub via websockets. Cleaned some code up. Added detection for subscription messages (no TTS), message deletion, full or partial chat clear. Removes messages from TTS queue if applicable. Added command aliases for static parameters. Word filters use compiled regex if possible. Fixed TTS voice deletion.

This commit is contained in:
Tom
2024-08-04 23:46:10 +00:00
parent 472bfcee5d
commit 75fcb8e0f8
61 changed files with 2268 additions and 925 deletions

View File

@ -0,0 +1,46 @@
namespace TwitchChatTTS.Hermes
{
public interface ICustomDataManager {
void Add(string key, object value, string type);
void Change(string key, object value);
void Delete(string key);
object? Get(string key);
}
public class CustomDataManager : ICustomDataManager
{
private IDictionary<string, DataInfo> _data;
public CustomDataManager() {
_data = new Dictionary<string, DataInfo>();
}
public void Add(string key, object value, string type)
{
throw new NotImplementedException();
}
public void Change(string key, object value)
{
throw new NotImplementedException();
}
public void Delete(string key)
{
throw new NotImplementedException();
}
public object? Get(string key)
{
throw new NotImplementedException();
}
}
// type: text (string), whole number (int), number (double), boolean, formula (string, data type of number)
public struct DataInfo {
public string Id { get; set; }
public string Type { get; set; }
public object Value { get; set; }
}
}

View File

@ -3,29 +3,68 @@ using TwitchChatTTS;
using System.Text.Json;
using HermesSocketLibrary.Requests.Messages;
using TwitchChatTTS.Hermes;
using TwitchChatTTS.Chat.Groups.Permissions;
using TwitchChatTTS.Chat.Groups;
using HermesSocketLibrary.Socket.Data;
using Serilog;
public class HermesApiClient
{
private readonly TwitchBotAuth _token;
private readonly WebClientWrap _web;
private readonly ILogger _logger;
public const string BASE_URL = "tomtospeech.com";
public HermesApiClient(Configuration configuration)
public HermesApiClient(TwitchBotAuth token, Configuration configuration, ILogger logger)
{
if (string.IsNullOrWhiteSpace(configuration.Hermes?.Token))
{
throw new Exception("Ensure you have written your API key in \".token\" file, in the same folder as this application.");
}
_token = token;
_web = new WebClientWrap(new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = false,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
});
_web.AddHeader("x-api-key", configuration.Hermes.Token);
_logger = logger;
}
public async Task<bool> AuthorizeTwitch()
{
try
{
_logger.Debug($"Attempting to authorize Twitch API...");
var authorize = await _web.GetJson<TwitchBotAuth>($"https://{HermesApiClient.BASE_URL}/api/account/reauthorize");
if (authorize != null)
{
_token.AccessToken = authorize.AccessToken;
_token.RefreshToken = authorize.RefreshToken;
_token.UserId = authorize.UserId;
_token.BroadcasterId = authorize.BroadcasterId;
_token.ExpiresIn = authorize.ExpiresIn;
_token.UpdatedAt = DateTime.Now;
_logger.Information("Updated Twitch API tokens.");
_logger.Debug($"Twitch API Auth data [user id: {_token.UserId}][id: {_token.BroadcasterId}][expires in: {_token.ExpiresIn}][expires at: {_token.ExpiresAt.ToShortTimeString()}]");
}
else if (authorize != null)
{
_logger.Error("Twitch API Authorization failed: " + authorize.AccessToken + " | " + authorize.RefreshToken + " | " + authorize.UserId + " | " + authorize.BroadcasterId);
return false;
}
_logger.Debug($"Authorized Twitch API.");
return true;
}
catch (JsonException)
{
_logger.Debug($"Failed to Authorize Twitch API due to JSON error.");
}
catch (Exception e)
{
_logger.Error(e, "Failed to authorize to Twitch API.");
}
return false;
}
public async Task<TTSVersion?> GetLatestTTSVersion()

View File

@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using System.Text.Json;
using System.Text.RegularExpressions;
using CommonSocketLibrary.Abstract;
using CommonSocketLibrary.Common;
using HermesSocketLibrary.Requests.Callbacks;
@ -160,8 +161,7 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
if (chatters == null)
return;
var client = _serviceProvider.GetRequiredService<ChatMessageHandler>();
client.Chatters = [.. chatters];
_user.Chatters = [.. chatters];
_logger.Information($"Fetched {chatters.Count()} chatters' id.");
}
else if (message.Request.Type == "get_emotes")
@ -232,7 +232,7 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
continue;
}
var path = $"{group.Name}.{permission.Path}";
permissionManager.Set(path, permission.Allow);
_logger.Debug($"Added group permission [id: {permission.Id}][group id: {permission.GroupId}][path: {permission.Path}]");
@ -254,8 +254,19 @@ namespace TwitchChatTTS.Hermes.Socket.Handlers
return;
}
_user.RegexFilters = wordFilters.ToList();
_logger.Information($"TTS word filters [count: {_user.RegexFilters.Count}] have been refreshed.");
var filters = wordFilters.Where(f => f.Search != null && f.Replace != null).ToArray();
foreach (var filter in filters)
{
try
{
var re = new Regex(filter.Search!, RegexOptions.Compiled);
re.Match(string.Empty);
filter.Regex = re;
}
catch (Exception e) { }
}
_user.RegexFilters = filters;
_logger.Information($"TTS word filters [count: {_user.RegexFilters.Count()}] have been refreshed.");
}
else if (message.Request.Type == "update_tts_voice_state")
{

View File

@ -383,7 +383,7 @@ namespace TwitchChatTTS.Hermes.Socket
}
catch (WebSocketException wse) when (wse.Message.Contains("502"))
{
_logger.Error("Hermes websocket server cannot be found.");
_logger.Error($"Hermes websocket server cannot be found [code: {wse.ErrorCode}]");
}
catch (Exception ex)
{

View File

@ -1,5 +1,4 @@
using System.Reflection;
using CommonSocketLibrary.Abstract;
using CommonSocketLibrary.Common;
using CommonSocketLibrary.Socket.Manager;
using Microsoft.Extensions.DependencyInjection;

View File

@ -1,5 +0,0 @@
public class TTSUsernameFilter {
public string Username { get; set; }
public string Tag { get; set; }
public string UserId { get; set; }
}