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