using HermesSocketLibrary.db; using HermesSocketLibrary.Socket.Data; using Npgsql; using ILogger = Serilog.ILogger; namespace HermesSocketServer.Socket.Handlers { public class EmoteDetailsHandler : ISocketHandler { private const int EMOTE_BUFFER_SIZE = 5000; public int OperationCode { get; } = 7; private readonly Database _database; private readonly HashSet _emotes; private readonly string[] _array; private readonly ILogger _logger; private readonly Mutex _mutex; private int _index; public EmoteDetailsHandler(Database database, ILogger logger) { _database = database; _emotes = new HashSet(EMOTE_BUFFER_SIZE); _array = new string[EMOTE_BUFFER_SIZE]; _logger = logger; _mutex = new Mutex(); _index = -1; } public async Task Execute(WebSocketUser sender, T message, HermesSocketManager sockets) { if (message is not EmoteDetailsMessage data || sender.Id == null) return; if (data.Emotes == null || !data.Emotes.Any()) return; try { _mutex.WaitOne(); foreach (var entry in data.Emotes) { if (_emotes.Contains(entry.Key)) { data.Emotes.Remove(entry.Key); continue; } _emotes.Add(entry.Key); if (_index == _array.Length - 1) _index = -1; var previous = _array[++_index]; if (previous != null) { _emotes.Remove(previous); } _array[_index] = entry.Key; } } finally { _mutex.ReleaseMutex(); } if (!data.Emotes.Any()) return; int rows = 0; string sql = "INSERT INTO \"Emote\" (id, name) VALUES (@idd, @name) ON CONFLICT (id) DO UPDATE SET name = @name;"; using (var connection = await _database.DataSource.OpenConnectionAsync()) { using (var command = new NpgsqlCommand(sql, connection)) { foreach (var entry in data.Emotes) { command.Parameters.Clear(); command.Parameters.AddWithValue("idd", entry.Key); command.Parameters.AddWithValue("name", entry.Value); await command.PrepareAsync(); try { rows += await command.ExecuteNonQueryAsync(); } catch (Exception e) { _logger.Error(e, "Failed to add emote detail: " + entry.Key + " -> " + entry.Value); } } } } } } }