Added database table data into configuration. Store saves is auto-handled. Added Action & Redemption stores.
This commit is contained in:
53
Store/ActionStore.cs
Normal file
53
Store/ActionStore.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System.Text.Json;
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketLibrary.Requests.Messages;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class ActionStore : AutoSavedStore<string, RedeemableAction>
|
||||
{
|
||||
private readonly string _userId;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
|
||||
|
||||
public ActionStore(string userId, DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_userId = userId;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
{
|
||||
var data = new Dictionary<string, object>() { { "user", _userId } };
|
||||
string sql = $"SELECT name, type, data FROM \"Action\" WHERE \"userId\" = @user";
|
||||
await _database.Execute(sql, data, (reader) =>
|
||||
{
|
||||
var name = reader.GetString(0);
|
||||
_store.Add(name.ToString(), new RedeemableAction()
|
||||
{
|
||||
UserId = _userId,
|
||||
Name = name,
|
||||
Type = reader.GetString(1),
|
||||
Data = JsonSerializer.Deserialize<IDictionary<string, string>>(reader.GetString(2))!
|
||||
});
|
||||
});
|
||||
_logger.Information($"Loaded {_store.Count} TTS chatter voices from database.");
|
||||
}
|
||||
|
||||
protected override void OnInitialAdd(string key, RedeemableAction value)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnInitialModify(string key, RedeemableAction value)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnInitialRemove(string key)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +1,22 @@
|
||||
using System.Collections.Immutable;
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketServer.Models;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class ChatterStore : GroupSaveStore<string, ChatterVoice>
|
||||
public class ChatterStore : AutoSavedStore<string, ChatterVoice>
|
||||
{
|
||||
private readonly string _userId;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
private readonly GroupSaveSqlGenerator<ChatterVoice> _generator;
|
||||
|
||||
|
||||
public ChatterStore(string userId, Database database, Serilog.ILogger logger) : base(logger)
|
||||
public ChatterStore(string userId, DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_userId = userId;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
|
||||
var ctp = new Dictionary<string, string>
|
||||
{
|
||||
{ "chatterId", "ChatterId" },
|
||||
{ "ttsVoiceId", "VoiceId" },
|
||||
{ "userId", "UserId" },
|
||||
};
|
||||
_generator = new GroupSaveSqlGenerator<ChatterVoice>(ctp, _logger);
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
@ -55,54 +47,5 @@ namespace HermesSocketServer.Store
|
||||
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("TtsChatVoice", count, ["userId", "chatterId", "ttsVoiceId"]);
|
||||
|
||||
_logger.Debug($"Chatter - Adding {count} rows to database: {sql}");
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await _generator.DoPreparedStatement(_database, sql, values, ["userId", "chatterId", "ttsVoiceId"]);
|
||||
}
|
||||
if (_modified.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _modified.ToImmutableList();
|
||||
_modified.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedUpdateSql("TtsChatVoice", count, ["userId", "chatterId"], ["ttsVoiceId"]);
|
||||
|
||||
_logger.Debug($"Chatter - Modifying {count} rows in database: {sql}");
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await _generator.DoPreparedStatement(_database, sql, values, ["userId", "chatterId", "ttsVoiceId"]);
|
||||
}
|
||||
if (_deleted.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _deleted.ToImmutableList();
|
||||
_deleted.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedDeleteSql("TtsChatVoice", count, ["userId", "chatterId"]);
|
||||
|
||||
_logger.Debug($"Chatter - Deleting {count} rows from database: {sql}");
|
||||
await _generator.DoPreparedStatementRaw(_database, sql, list, ["userId", "chatterId"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ namespace HermesSocketServer.Store
|
||||
IDictionary<K, V> Get();
|
||||
Task Load();
|
||||
bool Modify(K? key, Action<V> action);
|
||||
void Remove(K? key);
|
||||
bool Remove(K? key);
|
||||
Task Save();
|
||||
bool Set(K? key, V? value);
|
||||
}
|
||||
|
11
Store/Internal/DatabaseTable.cs
Normal file
11
Store/Internal/DatabaseTable.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace HermesSocketServer.Store.Internal
|
||||
{
|
||||
public class DatabaseTable
|
||||
{
|
||||
public required string TableName { get; set; }
|
||||
public required string[] KeyColumns { get; set; }
|
||||
public required string[] DataColumns { get; set; }
|
||||
public required IDictionary<string, string> PropertyMapping { get; set; }
|
||||
public IDictionary<string, string>? TypeMapping { get; set; }
|
||||
}
|
||||
}
|
@ -1,20 +1,29 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using HermesSocketLibrary.db;
|
||||
using NpgsqlTypes;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
namespace HermesSocketServer.Store.Internal
|
||||
{
|
||||
public class GroupSaveSqlGenerator<T>
|
||||
{
|
||||
private readonly IDictionary<string, PropertyInfo?> columnPropertyRelations;
|
||||
private readonly IDictionary<string, PropertyInfo?> _columnPropertyRelations;
|
||||
private readonly IDictionary<string, NpgsqlDbType> _columnTypes;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
|
||||
public GroupSaveSqlGenerator(IDictionary<string, string> columnsToProperties, Serilog.ILogger logger)
|
||||
: this(columnsToProperties, new Dictionary<string, NpgsqlDbType>(), logger)
|
||||
{
|
||||
columnPropertyRelations = columnsToProperties.ToDictionary(p => p.Key, p => typeof(T).GetProperty(p.Value));
|
||||
}
|
||||
|
||||
public GroupSaveSqlGenerator(IDictionary<string, string> columnsToProperties, IDictionary<string, NpgsqlDbType> columnTypes, Serilog.ILogger logger)
|
||||
{
|
||||
_columnPropertyRelations = columnsToProperties.ToDictionary(p => p.Key, p => typeof(T).GetProperty(p.Value));
|
||||
_columnTypes = columnTypes;
|
||||
_logger = logger;
|
||||
|
||||
var nullProperties = columnPropertyRelations.Where(p => p.Value == null)
|
||||
var nullProperties = _columnPropertyRelations.Where(p => p.Value == null)
|
||||
.Select(p => columnsToProperties[p.Key]);
|
||||
if (nullProperties.Any())
|
||||
throw new ArgumentException("Some properties do not exist on the values given: " + string.Join(", ", nullProperties));
|
||||
@ -31,8 +40,15 @@ namespace HermesSocketServer.Store
|
||||
{
|
||||
foreach (var column in columns)
|
||||
{
|
||||
var propValue = columnPropertyRelations[column]!.GetValue(value);
|
||||
c.Parameters.AddWithValue(column.ToLower() + valueCounter, propValue ?? DBNull.Value);
|
||||
var propValue = _columnPropertyRelations[column]!.GetValue(value);
|
||||
if (_columnTypes.Any() && _columnTypes.TryGetValue(column, out var type))
|
||||
{
|
||||
if (type == NpgsqlDbType.Jsonb)
|
||||
propValue = JsonSerializer.Serialize(propValue);
|
||||
c.Parameters.AddWithValue(column.ToLower() + valueCounter, type, propValue ?? DBNull.Value);
|
||||
}
|
||||
else
|
||||
c.Parameters.AddWithValue(column.ToLower() + valueCounter, propValue ?? DBNull.Value);
|
||||
}
|
||||
valueCounter++;
|
||||
}
|
||||
@ -81,7 +97,7 @@ namespace HermesSocketServer.Store
|
||||
if (!columns.Any())
|
||||
throw new ArgumentException("Empty list given.", nameof(columns));
|
||||
|
||||
var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]);
|
||||
var ctp = columns.ToDictionary(c => c, c => _columnPropertyRelations[c]);
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"INSERT INTO \"{table}\" (\"{string.Join("\", \"", columns)}\") VALUES ");
|
||||
foreach (var value in values)
|
||||
@ -89,8 +105,8 @@ namespace HermesSocketServer.Store
|
||||
sb.Append("(");
|
||||
foreach (var column in columns)
|
||||
{
|
||||
var propValue = columnPropertyRelations[column]!.GetValue(value);
|
||||
var propType = columnPropertyRelations[column]!.PropertyType;
|
||||
var propValue = _columnPropertyRelations[column]!.GetValue(value);
|
||||
var propType = _columnPropertyRelations[column]!.PropertyType;
|
||||
WriteValue(sb, propValue ?? DBNull.Value, propType);
|
||||
sb.Append(",");
|
||||
}
|
||||
@ -111,7 +127,7 @@ namespace HermesSocketServer.Store
|
||||
if (!columns.Any())
|
||||
throw new ArgumentException("Empty list given.", nameof(columns));
|
||||
|
||||
var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]);
|
||||
var ctp = columns.ToDictionary(c => c, c => _columnPropertyRelations[c]);
|
||||
var sb = new StringBuilder();
|
||||
var columnsLower = columns.Select(c => c.ToLower());
|
||||
sb.Append($"INSERT INTO \"{table}\" (\"{string.Join("\", \"", columns)}\") VALUES ");
|
||||
@ -151,7 +167,7 @@ namespace HermesSocketServer.Store
|
||||
throw new ArgumentException("Empty list given.", nameof(updateColumns));
|
||||
|
||||
var columns = keyColumns.Union(updateColumns);
|
||||
var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]);
|
||||
var ctp = columns.ToDictionary(c => c, c => _columnPropertyRelations[c]);
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"UPDATE \"{table}\" as t SET {string.Join(", ", updateColumns.Select(c => "\"" + c + "\" = c.\"" + c + "\""))} FROM (VALUES ");
|
||||
foreach (var value in values)
|
||||
@ -159,8 +175,8 @@ namespace HermesSocketServer.Store
|
||||
sb.Append("(");
|
||||
foreach (var column in columns)
|
||||
{
|
||||
var propValue = columnPropertyRelations[column]!.GetValue(value);
|
||||
var propType = columnPropertyRelations[column]!.PropertyType;
|
||||
var propValue = _columnPropertyRelations[column]!.GetValue(value);
|
||||
var propType = _columnPropertyRelations[column]!.PropertyType;
|
||||
WriteValue(sb, propValue, propType);
|
||||
sb.Append(",");
|
||||
}
|
||||
@ -189,7 +205,7 @@ namespace HermesSocketServer.Store
|
||||
throw new ArgumentException("Empty list given.", nameof(updateColumns));
|
||||
|
||||
var columns = keyColumns.Union(updateColumns);
|
||||
var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]);
|
||||
var ctp = columns.ToDictionary(c => c, c => _columnPropertyRelations[c]);
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"UPDATE \"{table}\" as t SET {string.Join(", ", updateColumns.Select(c => "\"" + c + "\" = c.\"" + c + "\""))} FROM (VALUES ");
|
||||
for (var row = 0; row < rows; row++)
|
||||
@ -226,7 +242,7 @@ namespace HermesSocketServer.Store
|
||||
if (!keyColumns.Any())
|
||||
throw new ArgumentException("Empty list given.", nameof(keyColumns));
|
||||
|
||||
var ctp = keyColumns.ToDictionary(c => c, c => columnPropertyRelations[c]);
|
||||
var ctp = keyColumns.ToDictionary(c => c, c => _columnPropertyRelations[c]);
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"DELETE FROM \"{table}\" WHERE (\"{string.Join("\", \"", keyColumns)}\") IN (");
|
||||
foreach (var k in keys)
|
||||
@ -234,7 +250,7 @@ namespace HermesSocketServer.Store
|
||||
sb.Append("(");
|
||||
foreach (var column in keyColumns)
|
||||
{
|
||||
var propType = columnPropertyRelations[column]!.PropertyType;
|
||||
var propType = _columnPropertyRelations[column]!.PropertyType;
|
||||
WriteValue(sb, k, propType);
|
||||
sb.Append(",");
|
||||
}
|
||||
@ -256,7 +272,7 @@ namespace HermesSocketServer.Store
|
||||
if (!keyColumns.Any())
|
||||
throw new ArgumentException("Empty list given.", nameof(keyColumns));
|
||||
|
||||
var ctp = keyColumns.ToDictionary(c => c, c => columnPropertyRelations[c]);
|
||||
var ctp = keyColumns.ToDictionary(c => c, c => _columnPropertyRelations[c]);
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"DELETE FROM \"{table}\" WHERE (\"{string.Join("\", \"", keyColumns)}\") IN (");
|
||||
for (var row = 0; row < rows; row++)
|
||||
@ -289,7 +305,12 @@ namespace HermesSocketServer.Store
|
||||
.Append(value?.ToString())
|
||||
.Append("')");
|
||||
else if (type == typeof(TimeSpan))
|
||||
sb.Append(((TimeSpan)value).TotalMilliseconds);
|
||||
{
|
||||
if (value == null)
|
||||
sb.Append("0");
|
||||
else
|
||||
sb.Append(((TimeSpan)value).TotalMilliseconds);
|
||||
}
|
||||
else
|
||||
sb.Append(value);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
namespace HermesSocketServer.Store.Internal
|
||||
{
|
||||
public abstract class GroupSaveStore<K, V> : IStore<K, V> where K : class where V : class
|
||||
{
|
||||
@ -60,30 +60,30 @@ namespace HermesSocketServer.Store
|
||||
if (value == null)
|
||||
return false;
|
||||
|
||||
OnInitialModify(key, value);
|
||||
action(value);
|
||||
if (!_added.Contains(key) && !_modified.Contains(key))
|
||||
{
|
||||
_modified.Add(key);
|
||||
_logger.Information($"added key to _modified {key}");
|
||||
}
|
||||
OnInitialModify(key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Remove(K? key)
|
||||
public bool Remove(K? key)
|
||||
{
|
||||
if (key == null)
|
||||
return;
|
||||
return false;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
OnInitialRemove(key);
|
||||
if (_store.Remove(key))
|
||||
{
|
||||
_logger.Information($"removed key from _deleted {key}");
|
||||
OnInitialRemove(key);
|
||||
if (!_added.Remove(key))
|
||||
{
|
||||
_modified.Remove(key);
|
||||
@ -94,8 +94,10 @@ namespace HermesSocketServer.Store
|
||||
_logger.Information($"added key to _deleted {key}");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Set(K? key, V? value)
|
61
Store/Internal/SelfGeneratedStore.cs
Normal file
61
Store/Internal/SelfGeneratedStore.cs
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using HermesSocketLibrary.db;
|
||||
|
||||
namespace HermesSocketServer.Store.Internal
|
||||
{
|
||||
public abstract class AutoSavedStore<K, V> : GroupSaveStore<K, V> where K : class where V : class
|
||||
{
|
||||
private readonly GroupSaveSqlGenerator<V> _generator;
|
||||
private readonly DatabaseTable _table;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
|
||||
|
||||
public AutoSavedStore(DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
_generator = new GroupSaveSqlGenerator<V>(table.PropertyMapping, logger);
|
||||
_table = table;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task Save()
|
||||
{
|
||||
var allColumns = _table.KeyColumns.Union(_table.DataColumns).ToArray();
|
||||
|
||||
await GenerateQuery(_added,
|
||||
(size) => _generator.GeneratePreparedInsertSql(_table.TableName, size, allColumns),
|
||||
async (query, _, values) => await _generator.DoPreparedStatement(_database, query, values, allColumns));
|
||||
|
||||
await GenerateQuery(_modified,
|
||||
(size) => _generator.GeneratePreparedUpdateSql(_table.TableName, size, _table.KeyColumns, _table.DataColumns),
|
||||
async (query, _, values) => await _generator.DoPreparedStatement(_database, query, values, allColumns));
|
||||
|
||||
await GenerateQuery(_deleted,
|
||||
(size) => _generator.GeneratePreparedDeleteSql(_table.TableName, size, _table.KeyColumns),
|
||||
async (query, keys, _) => await _generator.DoPreparedStatementRaw(_database, query, keys, _table.KeyColumns));
|
||||
}
|
||||
|
||||
private async Task GenerateQuery(IList<K> keys, Func<int, string> generate, Func<string, IEnumerable<K>, IEnumerable<V>, Task> execute)
|
||||
{
|
||||
ImmutableList<K>? list = null;
|
||||
lock (_lock)
|
||||
{
|
||||
if (!keys.Any())
|
||||
return;
|
||||
|
||||
list = keys.ToImmutableList();
|
||||
keys.Clear();
|
||||
}
|
||||
|
||||
var query = generate(list.Count);
|
||||
_logger.Debug($"{_table.TableName} - Adding {list.Count} rows to database: {query}");
|
||||
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await execute(query, list, values);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +1,22 @@
|
||||
using System.Collections.Immutable;
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketServer.Models;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class PolicyStore : GroupSaveStore<string, PolicyMessage>
|
||||
public class PolicyStore : AutoSavedStore<string, PolicyMessage>
|
||||
{
|
||||
private readonly string _userId;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
private readonly GroupSaveSqlGenerator<PolicyMessage> _generator;
|
||||
|
||||
|
||||
public PolicyStore(string userId, Database database, Serilog.ILogger logger) : base(logger)
|
||||
public PolicyStore(string userId, DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_userId = userId;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
|
||||
var ctp = new Dictionary<string, string>
|
||||
{
|
||||
{ "id", "Id" },
|
||||
{ "userId", "UserId" },
|
||||
{ "groupId", "GroupId" },
|
||||
{ "path", "Path" },
|
||||
{ "count", "Usage" },
|
||||
{ "timespan", "Span" },
|
||||
};
|
||||
_generator = new GroupSaveSqlGenerator<PolicyMessage>(ctp, _logger);
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
@ -61,54 +50,5 @@ namespace HermesSocketServer.Store
|
||||
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("GroupPermissionPolicy", count, ["id", "userId", "groupId", "path", "count", "timespan"]);
|
||||
|
||||
_logger.Debug($"GroupPermissionPolicy - 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", "groupId", "path", "count", "timespan"]);
|
||||
}
|
||||
if (_modified.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _modified.ToImmutableList();
|
||||
_modified.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedUpdateSql("GroupPermissionPolicy", count, ["id"], ["userId", "groupId", "path", "count", "timespan"]);
|
||||
|
||||
_logger.Debug($"GroupPermissionPolicy - 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", "groupId", "path", "count", "timespan"]);
|
||||
}
|
||||
if (_deleted.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _deleted.ToImmutableList();
|
||||
_deleted.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedDeleteSql("GroupPermissionPolicy", count, ["id"]);
|
||||
|
||||
_logger.Debug($"GroupPermissionPolicy - Deleting {count} rows from database: {sql}");
|
||||
await _generator.DoPreparedStatementRaw(_database, sql, list.Select(id => new Guid(id)), ["id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
54
Store/RedemptionStore.cs
Normal file
54
Store/RedemptionStore.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketLibrary.Requests.Messages;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class RedemptionStore : AutoSavedStore<string, Redemption>
|
||||
{
|
||||
private readonly string _userId;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
|
||||
|
||||
public RedemptionStore(string userId, DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_userId = userId;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
{
|
||||
var data = new Dictionary<string, object>() { { "user", _userId } };
|
||||
string sql = $"SELECT id, \"redemptionId\", \"order\", \"state\", \"actionName\" FROM \"Redemption\" WHERE \"userId\" = @user";
|
||||
await _database.Execute(sql, data, (reader) =>
|
||||
{
|
||||
var id = reader.GetGuid(0);
|
||||
_store.Add(id.ToString(), new Redemption()
|
||||
{
|
||||
Id = id.ToString(),
|
||||
UserId = _userId,
|
||||
RedemptionId = reader.GetString(1),
|
||||
Order = reader.GetInt32(2),
|
||||
State = reader.GetBoolean(3),
|
||||
ActionName = reader.GetString(4),
|
||||
});
|
||||
});
|
||||
_logger.Information($"Loaded {_store.Count} TTS chatter voices from database.");
|
||||
}
|
||||
|
||||
protected override void OnInitialAdd(string key, Redemption value)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnInitialModify(string key, Redemption value)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnInitialRemove(string key)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +1,22 @@
|
||||
using System.Collections.Immutable;
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketLibrary.Requests.Messages;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class TTSFilterStore : GroupSaveStore<string, TTSWordFilter>
|
||||
public class TTSFilterStore : AutoSavedStore<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)
|
||||
public TTSFilterStore(string userId, DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, 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()
|
||||
@ -56,54 +47,5 @@ namespace HermesSocketServer.Store
|
||||
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"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +1,20 @@
|
||||
using System.Collections.Immutable;
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketServer.Models;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class UserStore : GroupSaveStore<string, User>
|
||||
public class UserStore : AutoSavedStore<string, User>
|
||||
{
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
private readonly GroupSaveSqlGenerator<User> _generator;
|
||||
|
||||
|
||||
public UserStore(Database database, Serilog.ILogger logger) : base(logger)
|
||||
public UserStore([FromKeyedServices("User")] DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
|
||||
var ctp = new Dictionary<string, string>
|
||||
{
|
||||
{ "id", "Id" },
|
||||
{ "name", "Name" },
|
||||
{ "email", "Email" },
|
||||
{ "role", "Role" },
|
||||
{ "ttsDefaultVoice", "DefaultVoice" }
|
||||
};
|
||||
_generator = new GroupSaveSqlGenerator<User>(ctp, _logger);
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
@ -56,54 +46,5 @@ namespace HermesSocketServer.Store
|
||||
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("User", count, ["id", "name", "email", "role", "ttsDefaultVoice"]);
|
||||
|
||||
_logger.Debug($"User - Adding {count} rows to database: {sql}");
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]);
|
||||
}
|
||||
if (_modified.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _modified.ToImmutableList();
|
||||
_modified.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedUpdateSql("User", count, ["id"], ["name", "email", "role", "ttsDefaultVoice"]);
|
||||
|
||||
_logger.Debug($"User - Modifying {count} rows in database: {sql}");
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]);
|
||||
}
|
||||
if (_deleted.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _deleted.ToImmutableList();
|
||||
_deleted.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedDeleteSql("User", count, ["id"]);
|
||||
|
||||
_logger.Debug($"User - Deleting {count} rows from database: {sql}");
|
||||
await _generator.DoPreparedStatementRaw(_database, sql, list, ["id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
55
Store/VoiceStateStore.cs
Normal file
55
Store/VoiceStateStore.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketLibrary.Requests.Messages;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
using HermesSocketServer.Validators;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class VoiceStateStore : AutoSavedStore<string, TTSVoiceState>
|
||||
{
|
||||
private readonly string _userId;
|
||||
private readonly VoiceIdValidator _idValidator;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
|
||||
|
||||
public VoiceStateStore(string userId, VoiceIdValidator voiceIdValidator, DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_userId = userId;
|
||||
_idValidator = voiceIdValidator;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
{
|
||||
var data = new Dictionary<string, object>() { { "user", _userId } };
|
||||
string sql = "SELECT \"ttsVoiceId\", state FROM \"TtsVoiceState\" WHERE \"userId\" = @user";
|
||||
await _database.Execute(sql, data, (reader) =>
|
||||
{
|
||||
string id = reader.GetString(0);
|
||||
_store.Add(id, new TTSVoiceState()
|
||||
{
|
||||
Id = id,
|
||||
Enabled = reader.GetBoolean(1),
|
||||
UserId = _userId,
|
||||
});
|
||||
});
|
||||
_logger.Information($"Loaded {_store.Count} TTS voice states from database.");
|
||||
}
|
||||
|
||||
protected override void OnInitialAdd(string key, TTSVoiceState value)
|
||||
{
|
||||
_idValidator.Check(value.Id);
|
||||
}
|
||||
|
||||
protected override void OnInitialModify(string key, TTSVoiceState value)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnInitialRemove(string key)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +1,25 @@
|
||||
using System.Collections.Immutable;
|
||||
using HermesSocketLibrary.db;
|
||||
using HermesSocketServer.Models;
|
||||
using HermesSocketLibrary.Requests.Messages;
|
||||
using HermesSocketServer.Store.Internal;
|
||||
using HermesSocketServer.Validators;
|
||||
|
||||
namespace HermesSocketServer.Store
|
||||
{
|
||||
public class VoiceStore : GroupSaveStore<string, Voice>
|
||||
public class VoiceStore : AutoSavedStore<string, TTSVoice>
|
||||
{
|
||||
private readonly VoiceIdValidator _idValidator;
|
||||
private readonly VoiceNameValidator _nameValidator;
|
||||
private readonly Database _database;
|
||||
private readonly Serilog.ILogger _logger;
|
||||
private readonly GroupSaveSqlGenerator<Voice> _generator;
|
||||
|
||||
|
||||
public VoiceStore(VoiceIdValidator voiceIdValidator, VoiceNameValidator voiceNameValidator, Database database, Serilog.ILogger logger) : base(logger)
|
||||
public VoiceStore(VoiceIdValidator voiceIdValidator, VoiceNameValidator voiceNameValidator, [FromKeyedServices("Voice")] DatabaseTable table, Database database, Serilog.ILogger logger)
|
||||
: base(table, database, logger)
|
||||
{
|
||||
_idValidator = voiceIdValidator;
|
||||
_nameValidator = voiceNameValidator;
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
|
||||
var ctp = new Dictionary<string, string>
|
||||
{
|
||||
{ "id", "Id" },
|
||||
{ "name", "Name" }
|
||||
};
|
||||
_generator = new GroupSaveSqlGenerator<Voice>(ctp, _logger);
|
||||
}
|
||||
|
||||
public override async Task Load()
|
||||
@ -35,7 +28,7 @@ namespace HermesSocketServer.Store
|
||||
await _database.Execute(sql, new Dictionary<string, object>(), (reader) =>
|
||||
{
|
||||
string id = reader.GetString(0);
|
||||
_store.Add(id, new Voice()
|
||||
_store.Add(id, new TTSVoice()
|
||||
{
|
||||
Id = id,
|
||||
Name = reader.GetString(1),
|
||||
@ -44,13 +37,13 @@ namespace HermesSocketServer.Store
|
||||
_logger.Information($"Loaded {_store.Count} TTS voices from database.");
|
||||
}
|
||||
|
||||
protected override void OnInitialAdd(string key, Voice value)
|
||||
protected override void OnInitialAdd(string key, TTSVoice value)
|
||||
{
|
||||
_idValidator.Check(value.Id);
|
||||
_nameValidator.Check(value.Name);
|
||||
}
|
||||
|
||||
protected override void OnInitialModify(string key, Voice value)
|
||||
protected override void OnInitialModify(string key, TTSVoice value)
|
||||
{
|
||||
_nameValidator.Check(value.Name);
|
||||
}
|
||||
@ -58,54 +51,5 @@ namespace HermesSocketServer.Store
|
||||
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("TtsVoice", count, ["id", "name"]);
|
||||
|
||||
_logger.Debug($"Voice - Adding {count} rows to database: {sql}");
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]);
|
||||
}
|
||||
if (_modified.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _modified.ToImmutableList();
|
||||
_modified.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedUpdateSql("TtsVoice", count, ["id"], ["name"]);
|
||||
|
||||
_logger.Debug($"Voice - Modifying {count} rows in database: {sql}");
|
||||
var values = list.Select(id => _store[id]).Where(v => v != null);
|
||||
await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]);
|
||||
}
|
||||
if (_deleted.Any())
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
list = _deleted.ToImmutableList();
|
||||
_deleted.Clear();
|
||||
}
|
||||
count = list.Count;
|
||||
sql = _generator.GeneratePreparedDeleteSql("TtsVoice", count, ["id"]);
|
||||
|
||||
_logger.Debug($"Voice - Deleting {count} rows from database: {sql}");
|
||||
await _generator.DoPreparedStatementRaw(_database, sql, list, ["id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user