Fixed emote duplicate issue. Improved chatter tracking. Used stores in Login Handler in cases where databases was used instead.

This commit is contained in:
Tom
2025-03-07 17:34:27 +00:00
parent fd0bca5c7c
commit 4d0743c4aa
4 changed files with 64 additions and 69 deletions

View File

@ -6,10 +6,12 @@ namespace HermesSocketServer.Socket.Handlers
{
public class ChatterHandler : ISocketHandler
{
private const int CHATTER_BUFFER_SIZE = 2000;
public int OperationCode { get; } = 6;
private readonly Database _database;
private readonly HashSet<long> _chatters;
private readonly ChatterMessage[] _array;
private readonly long[] _array;
private readonly ILogger _logger;
private readonly object _lock;
@ -19,8 +21,8 @@ namespace HermesSocketServer.Socket.Handlers
{
_database = database;
_logger = logger;
_chatters = new HashSet<long>(1001);
_array = new ChatterMessage[1000];
_chatters = new HashSet<long>(CHATTER_BUFFER_SIZE);
_array = new long[CHATTER_BUFFER_SIZE];
_index = -1;
_lock = new object();
}
@ -40,7 +42,11 @@ namespace HermesSocketServer.Socket.Handlers
if (_index == _array.Length - 1)
_index = -1;
_array[++_index] = data;
var previous = _array[++_index];
if (previous != 0) {
_chatters.Remove(previous);
}
_array[_index] = data.Id;
}
try

View File

@ -7,18 +7,25 @@ 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<string> _emotes;
private readonly string[] _array;
private readonly ILogger _logger;
private readonly object _lock;
private int _index;
public EmoteDetailsHandler(Database database, ILogger logger)
{
_database = database;
_emotes = new HashSet<string>(EMOTE_BUFFER_SIZE);
_array = new string[EMOTE_BUFFER_SIZE];
_logger = logger;
_emotes = new HashSet<string>(501);
_lock = new object();
_index = -1;
}
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
@ -40,6 +47,16 @@ namespace HermesSocketServer.Socket.Handlers
}
_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;
}
}
@ -47,7 +64,7 @@ namespace HermesSocketServer.Socket.Handlers
return;
int rows = 0;
string sql = "INSERT INTO \"Emote\" (id, name) VALUES (@idd, @name)";
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))

View File

@ -42,33 +42,30 @@ namespace HermesSocketServer.Socket.Handlers
var result = await _database.ExecuteScalar(sql, new Dictionary<string, object>() { { "key", data.ApiKey } });
string? userId = result?.ToString();
if (userId == null)
if (string.IsNullOrWhiteSpace(userId))
return;
IEnumerable<WebSocketUser?> recipients = Enumerable.Empty<WebSocketUser?>();
lock (_lock)
{
if (sender.Id != null)
throw new Exception("User already logged in.");
return;
sender.Id = userId;
if (string.IsNullOrWhiteSpace(sender.Id))
throw new Exception("Credentials do not match.");
recipients = _sockets.GetSockets(userId).ToList().Where(s => s.SessionId != sender.SessionId);
sender.Slave = data.WebLogin || recipients.Where(r => r?.WebLogin != true).Any();
sender.Slave = data.WebLogin || recipients.Where(r => r != null && !r.WebLogin).Any();
}
sender.ApiKey = data.ApiKey;
sender.WebLogin = data.WebLogin;
// Fetch channel data.
var channel = _manager.Get(userId);
if (channel == null)
{
channel = await _manager.Add(userId);
if (channel == null)
return;
throw new Exception("Channel does not exist.");
}
sender.Name = channel.User.Name;
@ -79,8 +76,6 @@ namespace HermesSocketServer.Socket.Handlers
_logger.Error($"Could not find username for a certain user [user id: {userId}][api key: {data.ApiKey}]");
return;
}
if (string.IsNullOrEmpty(channel.User.DefaultVoice))
_logger.Warning($"No default voice was set for an user [user id: {userId}][api key: {data.ApiKey}]");
sql = "select \"providerAccountId\" from \"Account\" where \"userId\" = @user and provider = @provider";
var result2 = await _database.ExecuteScalar(sql, new Dictionary<string, object>() { { "user", userId }, { "provider", "twitch" } });
@ -91,6 +86,7 @@ namespace HermesSocketServer.Socket.Handlers
return;
}
var voices = _voices.Get();
var ack = new LoginAckMessage()
{
UserId = userId,
@ -103,35 +99,14 @@ namespace HermesSocketServer.Socket.Handlers
WordFilters = channel.Filters.Get().Values,
DefaultTTSVoice = channel.User.DefaultVoice ?? _configuration.Tts.DefaultTtsVoice,
TTSVoicesAvailable = _voices.Get().ToDictionary(v => v.Key, v => v.Value.Name),
EnabledTTSVoices = channel.VoiceStates.Get().Values.Where(v => v.Enabled && voices.ContainsKey(v.Id)).Select(v => voices[v.Id].Name).ToList(),
Connections = channel.Connections.Get().Values.ToList(),
Slave = sender.Slave,
};
var userIdDict = new Dictionary<string, object>() { { "user", userId } };
ack.Connections = new List<Connection>();
string sql3 = "select \"name\", \"type\", \"clientId\", \"accessToken\", \"grantType\", \"scope\", \"expiresAt\", \"default\" from \"Connection\" where \"userId\" = @user";
await _database.Execute(sql3, userIdDict, sql =>
ack.Connections.Add(new Connection()
{
UserId = channel.Id,
Name = sql.GetString(0),
Type = sql.GetString(1),
ClientId = sql.GetString(2),
AccessToken = sql.GetString(3),
GrantType = sql.GetString(4),
Scope = sql.GetString(5),
ExpiresAt = sql.GetDateTime(6),
Default = sql.GetBoolean(7)
})
);
ack.EnabledTTSVoices = new List<string>();
string sql5 = $"SELECT v.name FROM \"TtsVoiceState\" s "
+ "INNER JOIN \"TtsVoice\" v ON s.\"ttsVoiceId\" = v.id "
+ "WHERE \"userId\" = @user AND state = true";
await _database.Execute(sql5, userIdDict, (r) => ack.EnabledTTSVoices.Add(r.GetString(0)));
await sender.Send(2, ack);
// Sending notification to other clients about another client logging in.
string version = $"{data.MajorVersion}.{data.MinorVersion}.{data.PatchVersion}";
_logger.Information($"Hermes client logged in {(sender.Admin ? "as administrator " : "")}[name: {sender.Name}][id: {userId}][ip: {sender.IPAddress}][version: {version}][web: {data.WebLogin}]");
@ -148,7 +123,7 @@ namespace HermesSocketServer.Socket.Handlers
{
try
{
tasks.Add(socket.Send(2, ack));
tasks.Add(socket!.Send(2, ack));
}
catch (Exception)
{