Added TTS Filter cache.

This commit is contained in:
Tom 2024-12-27 22:28:22 +00:00
parent 4979553c74
commit 6176e6f3b9
9 changed files with 262 additions and 36 deletions

View File

@ -8,5 +8,6 @@ namespace HermesSocketServer.Models
public User User { get; set; } public User User { get; set; }
public ChatterStore Chatters { get; set; } public ChatterStore Chatters { get; set; }
public PolicyStore Policies { get; set; } public PolicyStore Policies { get; set; }
public TTSFilterStore Filters { get; set; }
} }
} }

View File

@ -0,0 +1,45 @@
using HermesSocketLibrary.Requests.Messages;
using HermesSocketServer.Services;
using ILogger = Serilog.ILogger;
namespace HermesSocketServer.Requests
{
public class CreateTTSFilter : IRequest
{
public string Name => "create_tts_filter";
public string[] RequiredKeys => ["search", "replace"];
private ChannelManager _channels;
private ILogger _logger;
public CreateTTSFilter(ChannelManager channels, ILogger logger)
{
_channels = channels;
_logger = logger;
}
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
{
var id = Guid.NewGuid();
string search = data["search"].ToString()!;
string replace = data["replace"].ToString()!;
var filter = new TTSWordFilter()
{
Id = id.ToString(),
UserId = sender,
Search = search,
Replace = replace,
};
var channel = _channels.Get(sender);
bool result = channel.Filters.Set(id.ToString(), filter);
if (result)
{
_logger.Information($"Added filter to channel [filter id: {id}][search: {search}][replace: {replace}][channel: {sender}]");
return RequestResult.Successful(filter);
}
return RequestResult.Failed("Something went wrong when updating the cache.");
}
}
}

View File

@ -24,11 +24,12 @@ namespace HermesSocketServer.Requests
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data) public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
{ {
if (long.TryParse(data["chatter"].ToString(), out long chatterId)) if (data == null)
data["chatter"] = chatterId; return RequestResult.Failed("Data received from client is null.");
else if (!long.TryParse(data["chatter"].ToString(), out long chatterId))
return RequestResult.Failed("Invalid Twitch user id"); return RequestResult.Failed("Invalid Twitch user id");
data["user"] = sender;
data["voice"] = data["voice"].ToString(); data["voice"] = data["voice"].ToString();
var check = await _database.ExecuteScalar("SELECT state FROM \"TtsVoiceState\" WHERE \"userId\" = @user AND \"ttsVoiceId\" = @voice", data) ?? false; var check = await _database.ExecuteScalar("SELECT state FROM \"TtsVoiceState\" WHERE \"userId\" = @user AND \"ttsVoiceId\" = @voice", data) ?? false;

View File

@ -0,0 +1,28 @@
using HermesSocketServer.Services;
using ILogger = Serilog.ILogger;
namespace HermesSocketServer.Requests
{
public class DeleteTTSFilter : IRequest
{
public string Name => "delete_tts_filter";
public string[] RequiredKeys => ["id"];
private ChannelManager _channels;
private ILogger _logger;
public DeleteTTSFilter(ChannelManager channels, ILogger logger)
{
_channels = channels;
_logger = logger;
}
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
{
var channel = _channels.Get(sender);
channel.Filters.Remove(data!["id"].ToString());
_logger.Information($"Deleted a TTS filter by id [tts filter id: {data["id"]}]");
return RequestResult.Successful(null);
}
}
}

View File

@ -1,5 +1,5 @@
using HermesSocketLibrary.db;
using HermesSocketLibrary.Requests.Messages; using HermesSocketLibrary.Requests.Messages;
using HermesSocketServer.Services;
using ILogger = Serilog.ILogger; using ILogger = Serilog.ILogger;
namespace HermesSocketServer.Requests namespace HermesSocketServer.Requests
@ -8,27 +8,20 @@ namespace HermesSocketServer.Requests
{ {
public string Name => "get_tts_word_filters"; public string Name => "get_tts_word_filters";
public string[] RequiredKeys => []; public string[] RequiredKeys => [];
private readonly Database _database; private ChannelManager _channels;
private readonly ILogger _logger; private ILogger _logger;
public GetTTSWordFilters(Database database, ILogger logger) public GetTTSWordFilters(ChannelManager channels, ILogger logger)
{ {
_database = database; _channels = channels;
_logger = logger; _logger = logger;
} }
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data) public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
{ {
var temp = new Dictionary<string, object>() { { "user", sender } }; var channel = _channels.Get(sender);
IEnumerable<TTSWordFilter> filters = channel.Filters.Get().Values;
IList<TTSWordFilter> filters = new List<TTSWordFilter>();
string sql = $"SELECT id, search, replace FROM \"TtsWordFilter\" WHERE \"userId\" = @user";
await _database.Execute(sql, temp, (r) => filters.Add(new TTSWordFilter()
{
Id = r.GetString(0),
Search = r.GetString(1),
Replace = r.GetString(2)
}));
_logger.Information($"Fetched all word filters for channel [channel: {sender}]"); _logger.Information($"Fetched all word filters for channel [channel: {sender}]");
return RequestResult.Successful(filters, notifyClientsOnAccount: false); return RequestResult.Successful(filters, notifyClientsOnAccount: false);
} }

View File

@ -0,0 +1,45 @@
using HermesSocketLibrary.Requests.Messages;
using HermesSocketServer.Services;
using ILogger = Serilog.ILogger;
namespace HermesSocketServer.Requests
{
public class UpdateTTSFilter : IRequest
{
public string Name => "update_tts_filter";
public string[] RequiredKeys => ["id", "search", "replace"];
private ChannelManager _channels;
private ILogger _logger;
public UpdateTTSFilter(ChannelManager channels, ILogger logger)
{
_channels = channels;
_logger = logger;
}
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
{
var id = data["id"].ToString()!;
string search = data["search"].ToString()!;
string replace = data["replace"].ToString()!;
var filter = new TTSWordFilter()
{
Id = id,
UserId = sender,
Search = search,
Replace = replace,
};
var channel = _channels.Get(sender);
bool result = channel.Filters.Set(id, filter);
if (result)
{
_logger.Information($"Updated filter to channel [filter id: {id}][search: {search}][replace: {replace}][channel: {sender}]");
return RequestResult.Successful(filter);
}
return RequestResult.Failed("Something went wrong when updating the cache.");
}
}
}

View File

@ -36,13 +36,14 @@ namespace HermesSocketServer.Services
{ {
return null; return null;
} }
}
var chatters = new ChatterStore(userId, _database, _logger); var chatters = new ChatterStore(userId, _database, _logger);
var policies = new PolicyStore(userId, _database, _logger); var policies = new PolicyStore(userId, _database, _logger);
await Task.WhenAll([ var filters = new TTSFilterStore(userId, _database, _logger);
Task.WaitAll([
chatters.Load(), chatters.Load(),
policies.Load(), policies.Load(),
filters.Load(),
]); ]);
var channel = new Channel() var channel = new Channel()
@ -50,15 +51,14 @@ namespace HermesSocketServer.Services
Id = userId, Id = userId,
User = user, User = user,
Chatters = chatters, Chatters = chatters,
Policies = policies Policies = policies,
Filters = filters,
}; };
lock (_lock)
{
_channels.Add(userId, channel); _channels.Add(userId, channel);
}
return channel; return channel;
} }
}
public Channel? Get(string channelId) public Channel? Get(string channelId)
{ {
@ -75,6 +75,7 @@ namespace HermesSocketServer.Services
await Task.WhenAll([ await Task.WhenAll([
channel.Chatters.Save(), channel.Chatters.Save(),
channel.Policies.Save(), channel.Policies.Save(),
channel.Filters.Save(),
]); ]);
} }
@ -86,6 +87,7 @@ namespace HermesSocketServer.Services
await Task.WhenAll([ await Task.WhenAll([
channel.Chatters.Save(), channel.Chatters.Save(),
channel.Policies.Save(), channel.Policies.Save(),
channel.Filters.Save(),
]); ]);
} }
} }

View File

@ -2,7 +2,6 @@ using System.Net;
using System.Text.Json; using System.Text.Json;
using HermesSocketLibrary; using HermesSocketLibrary;
using HermesSocketLibrary.db; using HermesSocketLibrary.db;
using HermesSocketLibrary.Requests;
using HermesSocketServer; using HermesSocketServer;
using HermesSocketServer.Requests; using HermesSocketServer.Requests;
using HermesSocketServer.Socket; using HermesSocketServer.Socket;
@ -85,9 +84,11 @@ s.AddSingleton<UserStore>();
// Request handlers // Request handlers
s.AddSingleton<IRequest, CreatePolicy>(); s.AddSingleton<IRequest, CreatePolicy>();
s.AddSingleton<IRequest, CreateTTSFilter>();
s.AddSingleton<IRequest, CreateTTSUser>(); s.AddSingleton<IRequest, CreateTTSUser>();
s.AddSingleton<IRequest, CreateTTSVoice>(); s.AddSingleton<IRequest, CreateTTSVoice>();
s.AddSingleton<IRequest, DeletePolicy>(); s.AddSingleton<IRequest, DeletePolicy>();
s.AddSingleton<IRequest, DeleteTTSFilter>();
s.AddSingleton<IRequest, DeleteTTSVoice>(); s.AddSingleton<IRequest, DeleteTTSVoice>();
s.AddSingleton<IRequest, GetChatterIds>(); s.AddSingleton<IRequest, GetChatterIds>();
s.AddSingleton<IRequest, GetConnections>(); s.AddSingleton<IRequest, GetConnections>();
@ -101,6 +102,7 @@ s.AddSingleton<IRequest, GetPolicies>();
s.AddSingleton<IRequest, GetTTSUsers>(); s.AddSingleton<IRequest, GetTTSUsers>();
s.AddSingleton<IRequest, GetTTSVoices>(); s.AddSingleton<IRequest, GetTTSVoices>();
s.AddSingleton<IRequest, GetTTSWordFilters>(); s.AddSingleton<IRequest, GetTTSWordFilters>();
s.AddSingleton<IRequest, UpdateTTSFilter>();
s.AddSingleton<IRequest, UpdateTTSUser>(); s.AddSingleton<IRequest, UpdateTTSUser>();
s.AddSingleton<IRequest, UpdateTTSVoice>(); s.AddSingleton<IRequest, UpdateTTSVoice>();
s.AddSingleton<IRequest, UpdateDefaultTTSVoice>(); s.AddSingleton<IRequest, UpdateDefaultTTSVoice>();

109
Store/TTSFilterStore.cs Normal file
View File

@ -0,0 +1,109 @@
using System.Collections.Immutable;
using HermesSocketLibrary.db;
using HermesSocketLibrary.Requests.Messages;
namespace HermesSocketServer.Store
{
public class TTSFilterStore : GroupSaveStore<string, TTSWordFilter>
{
private readonly string _userId;
private readonly Database _database;
private readonly Serilog.ILogger _logger;
private readonly GroupSaveSqlGenerator<TTSWordFilter> _generator;
public TTSFilterStore(string userId, Database database, Serilog.ILogger logger) : base(logger)
{
_userId = userId;
_database = database;
_logger = logger;
var ctp = new Dictionary<string, string>
{
{ "id", "Id" },
{ "userId", "UserId" },
{ "search", "Search" },
{ "replace", "Replace" },
};
_generator = new GroupSaveSqlGenerator<TTSWordFilter>(ctp, _logger);
}
public override async Task Load()
{
var data = new Dictionary<string, object>() { { "user", _userId } };
string sql = $"SELECT id, search, replace FROM \"TtsWordFilter\" WHERE \"userId\" = @user";
await _database.Execute(sql, data, (reader) =>
{
var id = reader.GetString(0);
_store.Add(id.ToString(), new TTSWordFilter()
{
Id = id,
Search = reader.GetString(1),
Replace = reader.GetString(2)
});
});
_logger.Information($"Loaded {_store.Count} TTS chatter voices from database.");
}
protected override void OnInitialAdd(string key, TTSWordFilter value)
{
}
protected override void OnInitialModify(string key, TTSWordFilter value)
{
}
protected override void OnInitialRemove(string key)
{
}
public override async Task Save()
{
int count = 0;
string sql = string.Empty;
ImmutableList<string>? list = null;
if (_added.Any())
{
lock (_lock)
{
list = _added.ToImmutableList();
_added.Clear();
}
count = list.Count;
sql = _generator.GeneratePreparedInsertSql("TtsWordFilter", count, ["id", "userId", "search", "replace"]);
_logger.Debug($"TTS Filter - Adding {count} rows to database: {sql}");
var values = list.Select(id => _store[id]).Where(v => v != null);
await _generator.DoPreparedStatement(_database, sql, values, ["id", "userId", "search", "replace"]);
}
if (_modified.Any())
{
lock (_lock)
{
list = _modified.ToImmutableList();
_modified.Clear();
}
count = list.Count;
sql = _generator.GeneratePreparedUpdateSql("TtsWordFilter", count, ["id"], ["userId", "search", "replace"]);
_logger.Debug($"TTS Filter - Modifying {count} rows in database: {sql}");
var values = list.Select(id => _store[id]).Where(v => v != null);
await _generator.DoPreparedStatement(_database, sql, values, ["id", "userId", "search", "replace"]);
}
if (_deleted.Any())
{
lock (_lock)
{
list = _deleted.ToImmutableList();
_deleted.Clear();
}
count = list.Count;
sql = _generator.GeneratePreparedDeleteSql("TtsWordFilter", count, ["id"]);
_logger.Debug($"TTS Filter - Deleting {count} rows from database: {sql}");
await _generator.DoPreparedStatementRaw(_database, sql, list, ["id"]);
}
}
}
}