Added several request messages. Added redemptions. Added life TTS voice changes. A bunch of stuffs.
This commit is contained in:
parent
95bc073a73
commit
c771a56971
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ obj/
|
|||||||
appsettings*.json
|
appsettings*.json
|
||||||
server.config*.yml
|
server.config*.yml
|
||||||
logs/
|
logs/
|
||||||
|
screenlog*
|
@ -1,34 +0,0 @@
|
|||||||
// using System.Text.Json;
|
|
||||||
// using HermesSocketLibrary.db;
|
|
||||||
// using HermesSocketLibrary.Requests;
|
|
||||||
|
|
||||||
// namespace HermesSocketServer.Requests
|
|
||||||
// {
|
|
||||||
// public class BanTTSUser : IRequest
|
|
||||||
// {
|
|
||||||
// public string Name => "ban_tts_user";
|
|
||||||
// private Database _database;
|
|
||||||
// private ILogger _logger;
|
|
||||||
|
|
||||||
// public BanTTSUser(Database database, ILogger logger)
|
|
||||||
// {
|
|
||||||
// _database = database;
|
|
||||||
// _logger = logger;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public async Task<RequestResult> Grant(IDictionary<string, object> data)
|
|
||||||
// {
|
|
||||||
// // if (long.TryParse(data["user"].ToString(), out long user))
|
|
||||||
// // data["user"] = user;
|
|
||||||
// // if (data["broadcaster"] is JsonElement b)
|
|
||||||
// // data["broadcaster"] = b.ToString();
|
|
||||||
// // if (data["voice"] is JsonElement v)
|
|
||||||
// // data["voice"] = v.ToString();
|
|
||||||
|
|
||||||
// // string sql = "UPDATE \"TtsChatVoice\" (\"broadcasterId\", \"chatterId\", \"ttsVoiceId\") VALUES (@broadcaster, @user, @voice)";
|
|
||||||
// // var result = await _database.Execute(sql, data);
|
|
||||||
// // _logger.Information($"Selected a tts voice for {data["user"]} in channel {data["broadcaster"]}: {data["voice"]}");
|
|
||||||
// return new RequestResult(1 == 1, null);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -17,8 +17,14 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (long.TryParse(data["chatter"].ToString(), out long chatter))
|
if (long.TryParse(data["chatter"].ToString(), out long chatter))
|
||||||
data["chatter"] = chatter;
|
data["chatter"] = chatter;
|
||||||
if (data["voice"] is JsonElement v)
|
if (data["voice"] is JsonElement v)
|
||||||
@ -26,13 +32,12 @@ namespace HermesSocketServer.Requests
|
|||||||
data["user"] = sender;
|
data["user"] = sender;
|
||||||
|
|
||||||
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;
|
||||||
if (check is not bool state || !state){
|
if (check is not bool state || !state)
|
||||||
return new RequestResult(false, null);
|
return new RequestResult(false, null);
|
||||||
}
|
|
||||||
|
|
||||||
string sql = "INSERT INTO \"TtsChatVoice\" (\"userId\", \"chatterId\", \"ttsVoiceId\") VALUES (@user, @chatter, @voice)";
|
string sql = "INSERT INTO \"TtsChatVoice\" (\"userId\", \"chatterId\", \"ttsVoiceId\") VALUES (@user, @chatter, @voice)";
|
||||||
var result = await _database.Execute(sql, data);
|
var result = await _database.Execute(sql, data);
|
||||||
_logger.Information($"Selected a tts voice for {data["chatter"]} in channel {data["user"]}: {data["voice"]}");
|
_logger.Information($"Selected a tts voice [voice: {data["voice"]}] for user [chatter: {data["chatter"]}] in channel [channel: {data["user"]}]");
|
||||||
return new RequestResult(result == 1, null);
|
return new RequestResult(result == 1, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,14 @@ 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 (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
string id = RandomString(25);
|
string id = RandomString(25);
|
||||||
data.Add("idd", id);
|
data.Add("idd", id);
|
||||||
|
|
||||||
@ -30,7 +36,7 @@ namespace HermesSocketServer.Requests
|
|||||||
|
|
||||||
string sql = "INSERT INTO \"TtsVoice\" (id, name) VALUES (@idd, @voice)";
|
string sql = "INSERT INTO \"TtsVoice\" (id, name) VALUES (@idd, @voice)";
|
||||||
var result = await _database.Execute(sql, data);
|
var result = await _database.Execute(sql, data);
|
||||||
_logger.Information($"Added a new voice: {data["voice"]} (id: {data["idd"]})");
|
_logger.Information($"Added a new voice [voice: {data["voice"]}][voice id: {data["idd"]}]");
|
||||||
|
|
||||||
data.Remove("idd");
|
data.Remove("idd");
|
||||||
return new RequestResult(result == 1, id);
|
return new RequestResult(result == 1, id);
|
||||||
|
@ -17,14 +17,20 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (data["voice"] is JsonElement v)
|
if (data["voice"] is JsonElement v)
|
||||||
data["voice"] = v.ToString();
|
data["voice"] = v.ToString();
|
||||||
|
|
||||||
string sql = "DELETE FROM \"TtsVoice\" WHERE id = @voice";
|
string sql = "DELETE FROM \"TtsVoice\" WHERE id = @voice";
|
||||||
var result = await _database.Execute(sql, data);
|
var result = await _database.Execute(sql, data);
|
||||||
_logger.Information($"Deleted a voice by id: {data["voice"]}");
|
_logger.Information($"Deleted a voice by id [voice id: {data["voice"]}]");
|
||||||
return new RequestResult(result == 1, null);
|
return new RequestResult(result == 1, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using HermesSocketLibrary.db;
|
using HermesSocketLibrary.db;
|
||||||
using HermesSocketLibrary.Requests;
|
using HermesSocketLibrary.Requests;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
@ -17,12 +16,12 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
IList<long> ids = new List<long>();
|
IList<long> ids = new List<long>();
|
||||||
string sql = $"SELECT id FROM \"Chatter\"";
|
string sql = $"SELECT id FROM \"Chatter\"";
|
||||||
await _database.Execute(sql, data, (r) => ids.Add(r.GetInt64(0)));
|
await _database.Execute(sql, (IDictionary<string, object>?) null, (r) => ids.Add(r.GetInt64(0)));
|
||||||
_logger.Information($"Fetched all chatters.");
|
_logger.Information($"Fetched all chatters for channel [channel: {sender}]");
|
||||||
return new RequestResult(true, ids, notifyClientsOnAccount: false);
|
return new RequestResult(true, ids, notifyClientsOnAccount: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
Requests/GetDefaultTTSVoice.cs
Normal file
29
Requests/GetDefaultTTSVoice.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Requests
|
||||||
|
{
|
||||||
|
public class GetDefaultTTSVoice : IRequest
|
||||||
|
{
|
||||||
|
public string Name => "get_default_tts_voice";
|
||||||
|
private Database _database;
|
||||||
|
private ILogger _logger;
|
||||||
|
|
||||||
|
public GetDefaultTTSVoice(Database database, ILogger logger)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
|
||||||
|
{
|
||||||
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
|
string sql = $"SELECT \"ttsDefaultVoice\" FROM \"User\" WHERE id = @user";
|
||||||
|
string? value = (string?)await _database.ExecuteScalar(sql, temp);
|
||||||
|
_logger.Information($"Fetched the default TTS voice for channel [channel: {sender}]");
|
||||||
|
return new RequestResult(true, value, notifyClientsOnAccount: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,16 +18,16 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
IList<EmoteInfo> emotes = new List<EmoteInfo>();
|
IList<EmoteInfo> emotes = new List<EmoteInfo>();
|
||||||
string sql = $"SELECT id, name FROM \"Emote\"";
|
string sql = $"SELECT id, name FROM \"Emote\"";
|
||||||
await _database.Execute(sql, data, (r) => emotes.Add(new EmoteInfo()
|
await _database.Execute(sql, (IDictionary<string, object>?) null, (r) => emotes.Add(new EmoteInfo()
|
||||||
{
|
{
|
||||||
Id = r.GetString(0),
|
Id = r.GetString(0),
|
||||||
Name = r.GetString(1)
|
Name = r.GetString(1)
|
||||||
}));
|
}));
|
||||||
_logger.Information($"Fetched all emotes.");
|
_logger.Information($"Fetched all emotes for channel [channel: {sender}]");
|
||||||
return new RequestResult(true, emotes, notifyClientsOnAccount: false);
|
return new RequestResult(true, emotes, notifyClientsOnAccount: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
Requests/GetEnabledTTSVoices.cs
Normal file
33
Requests/GetEnabledTTSVoices.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Requests
|
||||||
|
{
|
||||||
|
public class GetEnabledTTSVoices : IRequest
|
||||||
|
{
|
||||||
|
public string Name => "get_enabled_tts_voices";
|
||||||
|
|
||||||
|
private readonly Database _database;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public GetEnabledTTSVoices(Database database, ILogger logger)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
|
||||||
|
{
|
||||||
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
|
var voices = new List<string>();
|
||||||
|
string sql = $"SELECT v.name FROM \"TtsVoiceState\" s "
|
||||||
|
+ "INNER JOIN \"TtsVoice\" v ON s.\"ttsVoiceId\" = v.id "
|
||||||
|
+ "WHERE \"userId\" = @user AND state = true";
|
||||||
|
await _database.Execute(sql, temp, (r) => voices.Add(r.GetString(0)));
|
||||||
|
_logger.Information($"Fetched all enabled TTS voice for channel [channel: {sender}]");
|
||||||
|
return new RequestResult(true, voices, notifyClientsOnAccount: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
Requests/GetPermissions.cs
Normal file
62
Requests/GetPermissions.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests;
|
||||||
|
using HermesSocketLibrary.Requests.Messages;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Requests
|
||||||
|
{
|
||||||
|
public class GetPermissions : IRequest
|
||||||
|
{
|
||||||
|
public string Name => "get_permissions";
|
||||||
|
|
||||||
|
private readonly Database _database;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public GetPermissions(Database database, ILogger logger)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
|
||||||
|
{
|
||||||
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
|
var groups = new List<Group>();
|
||||||
|
string sql = $"SELECT id, name, priority FROM \"Group\" WHERE \"userId\" = @user";
|
||||||
|
await _database.Execute(sql, temp, (r) => groups.Add(new Group()
|
||||||
|
{
|
||||||
|
Id = r.GetGuid(0).ToString("D"),
|
||||||
|
Name = r.GetString(1),
|
||||||
|
Priority = r.GetInt32(2)
|
||||||
|
}));
|
||||||
|
|
||||||
|
var groupChatters = new List<GroupChatter>();
|
||||||
|
sql = $"SELECT \"groupId\", \"chatterId\", \"chatterId\" FROM \"ChatterGroup\" WHERE \"userId\" = @user";
|
||||||
|
await _database.Execute(sql, temp, (r) => groupChatters.Add(new GroupChatter()
|
||||||
|
{
|
||||||
|
GroupId = r.GetGuid(0).ToString("D"),
|
||||||
|
ChatterId = r.GetInt32(1)
|
||||||
|
}));
|
||||||
|
|
||||||
|
var groupPermissions = new List<GroupPermission>();
|
||||||
|
sql = $"SELECT id, \"groupId\", \"path\", \"allow\" FROM \"GroupPermission\" WHERE \"userId\" = @user";
|
||||||
|
await _database.Execute(sql, temp, (r) => groupPermissions.Add(new GroupPermission()
|
||||||
|
{
|
||||||
|
Id = r.GetGuid(0).ToString("D"),
|
||||||
|
GroupId = r.GetGuid(1).ToString("D"),
|
||||||
|
Path = r.GetString(2),
|
||||||
|
Allow = r.GetBoolean(3)
|
||||||
|
}));
|
||||||
|
_logger.Information($"Fetched all redemptions for channel [channel: {sender}]");
|
||||||
|
|
||||||
|
var info = new GroupInfo()
|
||||||
|
{
|
||||||
|
Groups = groups,
|
||||||
|
GroupChatters = groupChatters,
|
||||||
|
GroupPermissions = groupPermissions
|
||||||
|
};
|
||||||
|
return new RequestResult(true, info, notifyClientsOnAccount: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
Requests/GetRedeemableActions.cs
Normal file
40
Requests/GetRedeemableActions.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests;
|
||||||
|
using HermesSocketLibrary.Requests.Messages;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Requests
|
||||||
|
{
|
||||||
|
public class GetRedeemableActions : IRequest
|
||||||
|
{
|
||||||
|
public string Name => "get_redeemable_actions";
|
||||||
|
|
||||||
|
private readonly JsonSerializerOptions _options;
|
||||||
|
private readonly Database _database;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public GetRedeemableActions(JsonSerializerOptions options, Database database, ILogger logger)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
_database = database;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
|
||||||
|
{
|
||||||
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
|
var redemptions = new List<RedeemableAction>();
|
||||||
|
string sql = $"SELECT name, type, data FROM \"Action\" WHERE \"userId\" = @user";
|
||||||
|
await _database.Execute(sql, temp, (r) => redemptions.Add(new RedeemableAction()
|
||||||
|
{
|
||||||
|
Name = r.GetString(0),
|
||||||
|
Type = r.GetString(1),
|
||||||
|
Data = JsonSerializer.Deserialize<IDictionary<string, string>>(r.GetString(2), _options)!
|
||||||
|
}));
|
||||||
|
_logger.Information($"Fetched all chatters' selected tts voice for channel [channel: {sender}]");
|
||||||
|
return new RequestResult(true, redemptions, notifyClientsOnAccount: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
Requests/GetRedemptions.cs
Normal file
39
Requests/GetRedemptions.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests;
|
||||||
|
using HermesSocketLibrary.Requests.Messages;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Requests
|
||||||
|
{
|
||||||
|
public class GetRedemptions : IRequest
|
||||||
|
{
|
||||||
|
public string Name => "get_redemptions";
|
||||||
|
|
||||||
|
private readonly Database _database;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public GetRedemptions(Database database, ILogger logger)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
|
||||||
|
{
|
||||||
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
|
var redemptions = new List<Redemption>();
|
||||||
|
string sql = $"SELECT id, \"redemptionId\", \"actionName\", \"order\", state FROM \"Redemption\" WHERE \"userId\" = @user";
|
||||||
|
await _database.Execute(sql, temp, (r) => redemptions.Add(new Redemption()
|
||||||
|
{
|
||||||
|
Id = r.GetGuid(0).ToString("D"),
|
||||||
|
RedemptionId = r.GetString(1),
|
||||||
|
ActionName = r.GetString(2),
|
||||||
|
Order = r.GetInt32(3),
|
||||||
|
State = r.GetBoolean(4)
|
||||||
|
}));
|
||||||
|
_logger.Information($"Fetched all redemptions for channel [channel: {sender}]");
|
||||||
|
return new RequestResult(true, redemptions, notifyClientsOnAccount: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using HermesSocketLibrary.db;
|
using HermesSocketLibrary.db;
|
||||||
using HermesSocketLibrary.Requests;
|
using HermesSocketLibrary.Requests;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
@ -17,14 +16,14 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
data["user"] = sender;
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
IDictionary<long, string> users = new Dictionary<long, string>();
|
IDictionary<long, string> users = new Dictionary<long, string>();
|
||||||
string sql = $"SELECT \"ttsVoiceId\", \"chatterId\" FROM \"TtsChatVoice\" WHERE \"userId\" = @user";
|
string sql = $"SELECT \"ttsVoiceId\", \"chatterId\" FROM \"TtsChatVoice\" WHERE \"userId\" = @user";
|
||||||
await _database.Execute(sql, data, (r) => users.Add(r.GetInt64(1), r.GetString(0)));
|
await _database.Execute(sql, temp, (r) => users.Add(r.GetInt64(1), r.GetString(0)));
|
||||||
_logger.Information($"Fetched all chatters' selected tts voice for channel {data["user"]}.");
|
_logger.Information($"Fetched all chatters' selected tts voice for channel [channel: {sender}]");
|
||||||
return new RequestResult(true, users, notifyClientsOnAccount: false);
|
return new RequestResult(true, users, notifyClientsOnAccount: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,16 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
IList<VoiceDetails> voices = new List<VoiceDetails>();
|
IList<VoiceDetails> voices = new List<VoiceDetails>();
|
||||||
string sql = "SELECT id, name FROM \"TtsVoice\"";
|
string sql = "SELECT id, name FROM \"TtsVoice\"";
|
||||||
await _database.Execute(sql, data, (r) => voices.Add(new VoiceDetails()
|
await _database.Execute(sql, (IDictionary<string, object>?) null, (r) => voices.Add(new VoiceDetails()
|
||||||
{
|
{
|
||||||
Id = r.GetString(0),
|
Id = r.GetString(0),
|
||||||
Name = r.GetString(1)
|
Name = r.GetString(1)
|
||||||
}));
|
}));
|
||||||
_logger.Information("Fetched all TTS voices.");
|
_logger.Information($"Fetched all TTS voices for channel [channel: {sender}]");
|
||||||
return new RequestResult(true, voices, notifyClientsOnAccount: false);
|
return new RequestResult(true, voices, notifyClientsOnAccount: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Text.Json;
|
using System.Text.RegularExpressions;
|
||||||
using HermesSocketLibrary.db;
|
using HermesSocketLibrary.db;
|
||||||
using HermesSocketLibrary.Requests;
|
using HermesSocketLibrary.Requests;
|
||||||
using HermesSocketLibrary.Requests.Messages;
|
using HermesSocketLibrary.Requests.Messages;
|
||||||
@ -18,18 +18,19 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
data["user"] = sender;
|
var temp = new Dictionary<string, object>() { { "user", sender } };
|
||||||
|
|
||||||
IList<TTSWordFilter> filters = new List<TTSWordFilter>();
|
IList<TTSWordFilter> filters = new List<TTSWordFilter>();
|
||||||
string sql = $"SELECT id, search, replace FROM \"TtsWordFilter\" WHERE \"userId\" = @user";
|
string sql = $"SELECT id, search, replace FROM \"TtsWordFilter\" WHERE \"userId\" = @user";
|
||||||
await _database.Execute(sql, data, (r) => filters.Add(new TTSWordFilter()
|
await _database.Execute(sql, temp, (r) => filters.Add(new TTSWordFilter()
|
||||||
{
|
{
|
||||||
Id = r.GetString(0),
|
Id = r.GetString(0),
|
||||||
Search = r.GetString(1),
|
Search = r.GetString(1),
|
||||||
Replace = r.GetString(2)
|
Replace = r.GetString(2)
|
||||||
}));
|
}));
|
||||||
|
_logger.Information($"Fetched all word filters for channel [channel: {sender}]");
|
||||||
return new RequestResult(true, filters, notifyClientsOnAccount: false);
|
return new RequestResult(true, filters, notifyClientsOnAccount: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
using HermesSocketLibrary.Requests;
|
|
||||||
using ILogger = Serilog.ILogger;
|
|
||||||
|
|
||||||
namespace HermesSocketServer
|
|
||||||
{
|
|
||||||
public class ServerRequestManager : RequestManager
|
|
||||||
{
|
|
||||||
public ServerRequestManager(IServiceProvider serviceProvider, ILogger logger) : base(serviceProvider, logger)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string AssemblyName => "SocketServer";
|
|
||||||
}
|
|
||||||
}
|
|
36
Requests/UpdateDefaultTTSVoice.cs
Normal file
36
Requests/UpdateDefaultTTSVoice.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Requests
|
||||||
|
{
|
||||||
|
public class UpdateDefaultTTSVoice : IRequest
|
||||||
|
{
|
||||||
|
public string Name => "update_default_tts_voice";
|
||||||
|
private Database _database;
|
||||||
|
private ILogger _logger;
|
||||||
|
|
||||||
|
public UpdateDefaultTTSVoice(Database database, ILogger logger)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestResult> Grant(string sender, IDictionary<string, object>? data)
|
||||||
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
data["user"] = data["user"].ToString();
|
||||||
|
data["voice"] = data["voice"].ToString();
|
||||||
|
|
||||||
|
string sql = $"UPDATE \"User\" SET ttsDefaultVoice = @voice WHERE id = @user";
|
||||||
|
await _database.Execute(sql, data);
|
||||||
|
_logger.Information($"Updated default TTS voice for channel [channel: {sender}][voice: {data["voice"]}]");
|
||||||
|
return new RequestResult(true, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,17 +8,26 @@ namespace HermesSocketServer.Requests
|
|||||||
public class UpdateTTSUser : IRequest
|
public class UpdateTTSUser : IRequest
|
||||||
{
|
{
|
||||||
public string Name => "update_tts_user";
|
public string Name => "update_tts_user";
|
||||||
|
|
||||||
|
private readonly ServerConfiguration _configuration;
|
||||||
private readonly Database _database;
|
private readonly Database _database;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public UpdateTTSUser(Database database, ILogger logger)
|
public UpdateTTSUser(ServerConfiguration configuration, Database database, ILogger logger)
|
||||||
{
|
{
|
||||||
|
_configuration = configuration;
|
||||||
_database = database;
|
_database = database;
|
||||||
_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)
|
||||||
{
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (long.TryParse(data["chatter"].ToString(), out long chatterId))
|
if (long.TryParse(data["chatter"].ToString(), out long chatterId))
|
||||||
data["chatter"] = chatterId;
|
data["chatter"] = chatterId;
|
||||||
if (data["voice"] is JsonElement v)
|
if (data["voice"] is JsonElement v)
|
||||||
@ -26,14 +35,14 @@ namespace HermesSocketServer.Requests
|
|||||||
data["user"] = sender;
|
data["user"] = sender;
|
||||||
|
|
||||||
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;
|
||||||
if (check is not bool state || !state)
|
if ((check is not bool state || !state) && chatterId != _configuration.OwnerId)
|
||||||
{
|
{
|
||||||
return new RequestResult(false, null);
|
return new RequestResult(false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
string sql = "UPDATE \"TtsChatVoice\" SET \"ttsVoiceId\" = @voice WHERE \"userId\" = @user AND \"chatterId\" = @chatter";
|
string sql = "UPDATE \"TtsChatVoice\" SET \"ttsVoiceId\" = @voice WHERE \"userId\" = @user AND \"chatterId\" = @chatter";
|
||||||
var result = await _database.Execute(sql, data);
|
var result = await _database.Execute(sql, data);
|
||||||
_logger.Information($"Updated {data["chatter"]}'s selected tts voice to {data["voice"]} in channel {data["user"]}.");
|
_logger.Information($"Updated chatter's [chatter: {data["chatter"]}] selected tts voice [voice: {data["voice"]}] in channel [channel: {sender}]");
|
||||||
return new RequestResult(result == 1, null);
|
return new RequestResult(result == 1, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,14 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (data["voice"] is JsonElement v)
|
if (data["voice"] is JsonElement v)
|
||||||
data["voice"] = v.ToString();
|
data["voice"] = v.ToString();
|
||||||
if (data["voiceid"] is JsonElement id)
|
if (data["voiceid"] is JsonElement id)
|
||||||
@ -26,7 +32,7 @@ namespace HermesSocketServer.Requests
|
|||||||
|
|
||||||
string sql = "UPDATE \"TtsVoice\" SET name = @voice WHERE id = @voiceid";
|
string sql = "UPDATE \"TtsVoice\" SET name = @voice WHERE id = @voiceid";
|
||||||
var result = await _database.Execute(sql, data);
|
var result = await _database.Execute(sql, data);
|
||||||
_logger.Information($"Updated voice {data["voiceid"]}'s name to {data["voice"]}.");
|
_logger.Information($"Updated voice's [voice id: {data["voiceid"]}] name [new name: {data["voice"]}]");
|
||||||
return new RequestResult(result == 1, null);
|
return new RequestResult(result == 1, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,23 @@ namespace HermesSocketServer.Requests
|
|||||||
_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)
|
||||||
{
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.Warning("Data received from request is null. Ignoring it.");
|
||||||
|
return new RequestResult(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (data["voice"] is JsonElement voice)
|
if (data["voice"] is JsonElement voice)
|
||||||
data["voice"] = voice.ToString();
|
data["voice"] = voice.ToString();
|
||||||
if (data["state"] is JsonElement state)
|
if (data["state"] is JsonElement state)
|
||||||
data["state"] = state.ToString() == "True";
|
data["state"] = state.ToString() == "True";
|
||||||
data["user"] = sender;
|
data["user"] = sender;
|
||||||
|
|
||||||
//string sql = "UPDATE \"TtsVoiceState\" SET state = @state WHERE \"userId\" = @user AND \"ttsVoiceId\" = @voice";
|
|
||||||
string sql = "INSERT INTO \"TtsVoiceState\" (\"userId\", \"ttsVoiceId\", state) VALUES (@user, @voice, @state) ON CONFLICT (\"userId\", \"ttsVoiceId\") DO UPDATE SET state = @state";
|
string sql = "INSERT INTO \"TtsVoiceState\" (\"userId\", \"ttsVoiceId\", state) VALUES (@user, @voice, @state) ON CONFLICT (\"userId\", \"ttsVoiceId\") DO UPDATE SET state = @state";
|
||||||
var result = await _database.Execute(sql, data);
|
var result = await _database.Execute(sql, data);
|
||||||
_logger.Information($"Updated voice {data["voice"]}'s state (from {data["user"]}) to {data["state"]}.");
|
_logger.Information($"Updated voice's [voice id: {data["voice"]}] state [new state: {data["state"]}][channel: {data["user"]}]");
|
||||||
return new RequestResult(result == 1, null);
|
return new RequestResult(result == 1, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
36
Server.cs
36
Server.cs
@ -1,6 +1,7 @@
|
|||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using CommonSocketLibrary.Common;
|
||||||
using HermesSocketLibrary.Socket.Data;
|
using HermesSocketLibrary.Socket.Data;
|
||||||
using HermesSocketServer.Socket;
|
using HermesSocketServer.Socket;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
@ -31,7 +32,7 @@ namespace HermesSocketLibrary
|
|||||||
|
|
||||||
public async Task Handle(WebSocketUser socket, HttpContext context)
|
public async Task Handle(WebSocketUser socket, HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.Information($"Socket connected [ip: {socket.IPAddress}]");
|
_logger.Information($"Socket connected [ip: {socket.IPAddress}][uid: {socket.UID}]");
|
||||||
_sockets.Add(socket);
|
_sockets.Add(socket);
|
||||||
var buffer = new byte[1024 * 8];
|
var buffer = new byte[1024 * 8];
|
||||||
|
|
||||||
@ -44,12 +45,12 @@ namespace HermesSocketLibrary
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
string message = Encoding.UTF8.GetString(buffer, 0, result.Count).TrimEnd('\0');
|
string message = Encoding.UTF8.GetString(buffer, 0, result.Count).TrimEnd('\0');
|
||||||
var obj = JsonSerializer.Deserialize<SocketMessage>(message, _options);
|
var obj = JsonSerializer.Deserialize<WebSocketMessage>(message, _options);
|
||||||
if (obj == null || !obj.OpCode.HasValue)
|
if (obj == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (obj.OpCode != 0)
|
if (obj.OpCode != 0)
|
||||||
_logger.Information("Message: " + message);
|
_logger.Information($"rxm: {message} [ip: {socket.IPAddress}][id: {socket.Id}][name: {socket.Name}][token: {socket.ApiKey}][uid: {socket.UID}]");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0: Heartbeat
|
* 0: Heartbeat
|
||||||
@ -57,11 +58,11 @@ namespace HermesSocketLibrary
|
|||||||
* 2: Login Ack TX
|
* 2: Login Ack TX
|
||||||
* 3: Request RX
|
* 3: Request RX
|
||||||
* 4: Request Ack TX
|
* 4: Request Ack TX
|
||||||
* 5: Error RX/TX
|
* 5: Logging RX/TX
|
||||||
*/
|
*/
|
||||||
if (obj.Data == null)
|
if (obj.Data == null)
|
||||||
{
|
{
|
||||||
await socket.Send(5, new ErrorMessage("Received no data in the message."));
|
await socket.Send(5, new LoggingMessage("Received no data in the message.", HermesLoggingLevel.Warn));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (obj.OpCode == 0)
|
else if (obj.OpCode == 0)
|
||||||
@ -71,7 +72,7 @@ namespace HermesSocketLibrary
|
|||||||
else if (obj.OpCode == 3)
|
else if (obj.OpCode == 3)
|
||||||
obj.Data = JsonSerializer.Deserialize<RequestMessage>(obj.Data.ToString(), _options);
|
obj.Data = JsonSerializer.Deserialize<RequestMessage>(obj.Data.ToString(), _options);
|
||||||
else if (obj.OpCode == 5)
|
else if (obj.OpCode == 5)
|
||||||
obj.Data = JsonSerializer.Deserialize<ErrorMessage>(obj.Data.ToString(), _options);
|
obj.Data = JsonSerializer.Deserialize<LoggingMessage>(obj.Data.ToString(), _options);
|
||||||
else if (obj.OpCode == 6)
|
else if (obj.OpCode == 6)
|
||||||
obj.Data = JsonSerializer.Deserialize<ChatterMessage>(obj.Data.ToString(), _options);
|
obj.Data = JsonSerializer.Deserialize<ChatterMessage>(obj.Data.ToString(), _options);
|
||||||
else if (obj.OpCode == 7)
|
else if (obj.OpCode == 7)
|
||||||
@ -80,27 +81,36 @@ namespace HermesSocketLibrary
|
|||||||
obj.Data = JsonSerializer.Deserialize<EmoteUsageMessage>(obj.Data.ToString(), _options);
|
obj.Data = JsonSerializer.Deserialize<EmoteUsageMessage>(obj.Data.ToString(), _options);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await socket.Send(5, new ErrorMessage("Received an invalid message: " + message));
|
await socket.Send(5, new LoggingMessage("Received an invalid message: " + message, HermesLoggingLevel.Error));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await _handlers.Execute(socket, obj.OpCode.Value, obj.Data);
|
await _handlers.Execute(socket, obj.OpCode, obj.Data);
|
||||||
|
}
|
||||||
|
catch (WebSocketException wse)
|
||||||
|
{
|
||||||
|
_logger.Error(wse, $"Error trying to process a socket message [code: {wse.ErrorCode}][ip: {socket.IPAddress}][id: {socket.Id}][name: {socket.Name}][token: {socket.ApiKey}][uid: {socket.UID}]");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Error(e, "Error trying to process a socket message");
|
_logger.Error(e, $"Error trying to process a socket message [ip: {socket.IPAddress}][id: {socket.Id}][name: {socket.Name}][token: {socket.ApiKey}][uid: {socket.UID}]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (socket.Connected)
|
if (socket.Connected)
|
||||||
await socket.Close(socket.CloseStatus ?? WebSocketCloseStatus.NormalClosure, socket.CloseStatusDescription, CancellationToken.None);
|
await socket.Close(socket.CloseStatus ?? WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
_logger.Information(e, $"Client failed to disconnect [ip: {socket.IPAddress}][id: {socket.Id}][name: {socket.Name}][token: {socket.ApiKey}][uid: {socket.UID}]");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
socket.Dispose();
|
||||||
_sockets.Remove(socket);
|
_sockets.Remove(socket);
|
||||||
}
|
}
|
||||||
_logger.Information($"Client disconnected [username: {socket.Name}][id: {socket.Id}][ip: {socket.IPAddress}]");
|
_logger.Information($"Client disconnected [ip: {socket.IPAddress}][id: {socket.Id}][name: {socket.Name}][token: {socket.ApiKey}][uid: {socket.UID}]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,8 @@ namespace HermesSocketServer
|
|||||||
public string Environment;
|
public string Environment;
|
||||||
public WebsocketServerConfiguration WebsocketServer;
|
public WebsocketServerConfiguration WebsocketServer;
|
||||||
public DatabaseConfiguration Database;
|
public DatabaseConfiguration Database;
|
||||||
|
public long OwnerId;
|
||||||
|
public string AdminPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WebsocketServerConfiguration
|
public class WebsocketServerConfiguration
|
||||||
|
@ -6,7 +6,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
{
|
{
|
||||||
public class ChatterHandler : ISocketHandler
|
public class ChatterHandler : ISocketHandler
|
||||||
{
|
{
|
||||||
public int OpCode { get; } = 6;
|
public int OperationCode { get; } = 6;
|
||||||
private readonly Database _database;
|
private readonly Database _database;
|
||||||
private readonly HashSet<long> _chatters;
|
private readonly HashSet<long> _chatters;
|
||||||
private readonly ChatterMessage[] _array;
|
private readonly ChatterMessage[] _array;
|
||||||
@ -27,7 +27,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
|
|
||||||
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
||||||
{
|
{
|
||||||
if (message is not ChatterMessage data)
|
if (message is not ChatterMessage data || sender.Id == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
@ -45,7 +45,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string sql = "INSERT INTO \"Chatter\" (id, name) VALUES (@idd, @name)";
|
string sql = "INSERT INTO \"Chatter\" (id, name) VALUES (@idd, @name) ON CONFLICT (id) DO UPDATE SET name = @name";
|
||||||
await _database.Execute(sql, new Dictionary<string, object>() { { "idd", data.Id }, { "name", data.Name } });
|
await _database.Execute(sql, new Dictionary<string, object>() { { "idd", data.Id }, { "name", data.Name } });
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -7,7 +7,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
{
|
{
|
||||||
public class EmoteDetailsHandler : ISocketHandler
|
public class EmoteDetailsHandler : ISocketHandler
|
||||||
{
|
{
|
||||||
public int OpCode { get; } = 7;
|
public int OperationCode { get; } = 7;
|
||||||
private readonly Database _database;
|
private readonly Database _database;
|
||||||
private readonly HashSet<string> _emotes;
|
private readonly HashSet<string> _emotes;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
@ -23,7 +23,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
|
|
||||||
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
||||||
{
|
{
|
||||||
if (message is not EmoteDetailsMessage data)
|
if (message is not EmoteDetailsMessage data || sender.Id == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (data.Emotes == null)
|
if (data.Emotes == null)
|
||||||
|
@ -7,7 +7,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
{
|
{
|
||||||
public class EmoteUsageHandler : ISocketHandler
|
public class EmoteUsageHandler : ISocketHandler
|
||||||
{
|
{
|
||||||
public int OpCode { get; } = 8;
|
public int OperationCode { get; } = 8;
|
||||||
|
|
||||||
private readonly Database _database;
|
private readonly Database _database;
|
||||||
private readonly HashSet<string> _history;
|
private readonly HashSet<string> _history;
|
||||||
@ -28,7 +28,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
|
|
||||||
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
||||||
{
|
{
|
||||||
if (message is not EmoteUsageMessage data)
|
if (message is not EmoteUsageMessage data || sender.Id == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_logger)
|
lock (_logger)
|
||||||
@ -69,7 +69,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Information($"Tracked {rows} emote(s) to history.");
|
_logger.Debug($"Tracked {rows} emote(s) to history.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,29 +0,0 @@
|
|||||||
using HermesSocketLibrary.Socket.Data;
|
|
||||||
using ILogger = Serilog.ILogger;
|
|
||||||
|
|
||||||
namespace HermesSocketServer.Socket.Handlers
|
|
||||||
{
|
|
||||||
public class ErrorHandler : ISocketHandler
|
|
||||||
{
|
|
||||||
public int OpCode { get; } = 0;
|
|
||||||
|
|
||||||
private ILogger _logger;
|
|
||||||
|
|
||||||
public ErrorHandler(ILogger logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
|
||||||
{
|
|
||||||
if (message is not ErrorMessage data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (data.Exception == null)
|
|
||||||
_logger.Error(data.Message);
|
|
||||||
else
|
|
||||||
_logger.Error(data.Exception, data.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
{
|
{
|
||||||
public class HeartbeatHandler : ISocketHandler
|
public class HeartbeatHandler : ISocketHandler
|
||||||
{
|
{
|
||||||
public int OpCode { get; } = 0;
|
public int OperationCode { get; } = 0;
|
||||||
|
|
||||||
private ILogger _logger;
|
private ILogger _logger;
|
||||||
|
|
||||||
@ -23,6 +23,8 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
_logger.Verbose($"Received heartbeat from socket [ip: {sender.IPAddress}].");
|
_logger.Verbose($"Received heartbeat from socket [ip: {sender.IPAddress}].");
|
||||||
|
|
||||||
if (data.Respond)
|
if (data.Respond)
|
||||||
|
{
|
||||||
|
sender.LastHearbeatSent = DateTime.UtcNow;
|
||||||
await sender.Send(0, new HeartbeatMessage()
|
await sender.Send(0, new HeartbeatMessage()
|
||||||
{
|
{
|
||||||
DateTime = DateTime.UtcNow,
|
DateTime = DateTime.UtcNow,
|
||||||
@ -31,3 +33,4 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using HermesSocketLibrary.db;
|
using HermesSocketLibrary.db;
|
||||||
|
using HermesSocketLibrary.Requests.Messages;
|
||||||
using HermesSocketLibrary.Socket.Data;
|
using HermesSocketLibrary.Socket.Data;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
@ -6,15 +7,17 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
{
|
{
|
||||||
public class HermesLoginHandler : ISocketHandler
|
public class HermesLoginHandler : ISocketHandler
|
||||||
{
|
{
|
||||||
public int OpCode { get; } = 1;
|
public int OperationCode { get; } = 1;
|
||||||
|
|
||||||
|
private readonly ServerConfiguration _configuration;
|
||||||
private readonly Database _database;
|
private readonly Database _database;
|
||||||
private readonly HermesSocketManager _sockets;
|
private readonly HermesSocketManager _sockets;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly object _lock;
|
private readonly object _lock;
|
||||||
|
|
||||||
public HermesLoginHandler(Database database, HermesSocketManager sockets, ILogger logger)
|
public HermesLoginHandler(ServerConfiguration configuration, Database database, HermesSocketManager sockets, ILogger logger)
|
||||||
{
|
{
|
||||||
|
_configuration = configuration;
|
||||||
_database = database;
|
_database = database;
|
||||||
_sockets = sockets;
|
_sockets = sockets;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@ -36,48 +39,89 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
if (userId == null)
|
if (userId == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var recipients = _sockets.GetSockets(userId).ToList();
|
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (sender.Id != null)
|
if (sender.Id != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sender.Id = userId;
|
sender.Id = userId;
|
||||||
|
sender.ApiKey = data.ApiKey;
|
||||||
|
sender.WebLogin = data.WebLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
string sql2 = "select \"name\" from \"User\" where id = @user";
|
string sql2 = "select name, role from \"User\" where id = @user";
|
||||||
var result2 = await _database.ExecuteScalar(sql2, new Dictionary<string, object>() { { "user", userId } });
|
await _database.Execute(sql2, new Dictionary<string, object>() { { "user", userId } }, sql =>
|
||||||
string? name = result2?.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
sender.Name = name;
|
|
||||||
|
|
||||||
await sender.Send(2, new LoginAckMessage()
|
|
||||||
{
|
{
|
||||||
UserId = userId
|
sender.Name = sql.GetString(0);
|
||||||
|
sender.Admin = sql.GetString(1) == "ADMIN";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(sender.Name))
|
||||||
|
{
|
||||||
|
_logger.Error($"Could not find username using the user id [user id: {userId}][api key: {data.ApiKey}]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var ack = new LoginAckMessage()
|
var ack = new LoginAckMessage()
|
||||||
{
|
{
|
||||||
AnotherClient = true,
|
UserId = userId,
|
||||||
UserId = userId
|
OwnerId = _configuration.OwnerId,
|
||||||
|
Admin = sender.Admin,
|
||||||
|
WebLogin = data.WebLogin,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var connections = new List<Connection>();
|
||||||
|
string sql3 = "select \"name\", \"type\", \"clientId\", \"accessToken\", \"grantType\", \"scope\", \"expiresAt\", \"default\" from \"Connection\" where \"userId\" = @user";
|
||||||
|
await _database.Execute(sql3, new Dictionary<string, object>() { { "user", userId } }, sql =>
|
||||||
|
connections.Add(new Connection()
|
||||||
|
{
|
||||||
|
Name = sql.GetString(0),
|
||||||
|
Type = sql.GetString(1),
|
||||||
|
ClientId = sql.GetString(2),
|
||||||
|
AccessToken = sql.GetString(3),
|
||||||
|
GrantType = sql.GetString(4),
|
||||||
|
Scope = sql.GetString(5),
|
||||||
|
ExpiresIn = sql.GetDateTime(6),
|
||||||
|
Default = sql.GetBoolean(7)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
ack.Connections = connections.ToArray();
|
||||||
|
|
||||||
|
IList<VoiceDetails> voices = new List<VoiceDetails>();
|
||||||
|
string sql4 = "SELECT id, name FROM \"TtsVoice\"";
|
||||||
|
await _database.Execute(sql4, (IDictionary<string, object>?) null, (r) => voices.Add(new VoiceDetails()
|
||||||
|
{
|
||||||
|
Id = r.GetString(0),
|
||||||
|
Name = r.GetString(1)
|
||||||
|
}));
|
||||||
|
ack.TTSVoicesAvailable = voices.ToDictionary(e => e.Id, e => e.Name);
|
||||||
|
|
||||||
|
await sender.Send(2, ack);
|
||||||
|
|
||||||
|
string version = data.MajorVersion == null ? "unknown" : $"{data.MajorVersion}.{data.MinorVersion}";
|
||||||
|
_logger.Information($"Hermes client logged in {(sender.Admin ? "as administrator " : "")}[name: {sender.Name}][id: {userId}][ip: {sender.IPAddress}][version: {version}][web: {data.WebLogin}]");
|
||||||
|
|
||||||
|
ack = new LoginAckMessage()
|
||||||
|
{
|
||||||
|
AnotherClient = true,
|
||||||
|
UserId = userId,
|
||||||
|
OwnerId = _configuration.OwnerId,
|
||||||
|
WebLogin = data.WebLogin
|
||||||
|
};
|
||||||
|
|
||||||
|
var recipients = _sockets.GetSockets(userId).ToList().Where(s => s.UID != sender.UID);
|
||||||
|
var tasks = new List<Task>();
|
||||||
foreach (var socket in recipients)
|
foreach (var socket in recipients)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await socket.Send(2, ack);
|
tasks.Add(socket.Send(2, ack));
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
_logger.Information($"Hermes client logged in [name: {name}][id: {userId}][ip: {sender.IPAddress}]");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,8 @@
|
|||||||
using System.Net.WebSockets;
|
|
||||||
|
|
||||||
namespace HermesSocketServer.Socket.Handlers
|
namespace HermesSocketServer.Socket.Handlers
|
||||||
{
|
{
|
||||||
public interface ISocketHandler
|
public interface ISocketHandler
|
||||||
{
|
{
|
||||||
int OpCode { get; }
|
int OperationCode { get; }
|
||||||
Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets);
|
Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets);
|
||||||
}
|
}
|
||||||
}
|
}
|
44
Socket/Handlers/LoggingHandler.cs
Normal file
44
Socket/Handlers/LoggingHandler.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using HermesSocketLibrary.Socket.Data;
|
||||||
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
|
namespace HermesSocketServer.Socket.Handlers
|
||||||
|
{
|
||||||
|
public class LoggingHandler : ISocketHandler
|
||||||
|
{
|
||||||
|
public int OperationCode { get; } = 5;
|
||||||
|
|
||||||
|
private ILogger _logger;
|
||||||
|
|
||||||
|
public LoggingHandler(ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task Execute<T>(WebSocketUser sender, T data, HermesSocketManager sockets)
|
||||||
|
{
|
||||||
|
if (data is not LoggingMessage message || sender.Id == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Action<Exception?, string> logging;
|
||||||
|
if (message.Level == HermesLoggingLevel.Trace)
|
||||||
|
logging = _logger.Verbose;
|
||||||
|
else if (message.Level == HermesLoggingLevel.Debug)
|
||||||
|
logging = _logger.Debug;
|
||||||
|
else if (message.Level == HermesLoggingLevel.Info)
|
||||||
|
logging = _logger.Information;
|
||||||
|
else if (message.Level == HermesLoggingLevel.Warn)
|
||||||
|
logging = _logger.Warning;
|
||||||
|
else if (message.Level == HermesLoggingLevel.Error)
|
||||||
|
logging = _logger.Error;
|
||||||
|
else if (message.Level == HermesLoggingLevel.Critical)
|
||||||
|
logging = _logger.Fatal;
|
||||||
|
else {
|
||||||
|
_logger.Warning("Failed to receive a logging level from client.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.Invoke(message.Exception, message.Message + $" [ip: {sender.IPAddress}][id: {sender.Id}][name: {sender.Name}][token: {sender.ApiKey}][uid: {sender.UID}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,12 +6,12 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
{
|
{
|
||||||
public class RequestHandler : ISocketHandler
|
public class RequestHandler : ISocketHandler
|
||||||
{
|
{
|
||||||
public int OpCode { get; } = 3;
|
public int OperationCode { get; } = 3;
|
||||||
private readonly RequestManager _requests;
|
private readonly IRequestManager _requests;
|
||||||
private readonly HermesSocketManager _sockets;
|
private readonly HermesSocketManager _sockets;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public RequestHandler(RequestManager requests, HermesSocketManager sockets, ILogger logger)
|
public RequestHandler(IRequestManager requests, HermesSocketManager sockets, ILogger logger)
|
||||||
{
|
{
|
||||||
_requests = requests;
|
_requests = requests;
|
||||||
_sockets = sockets;
|
_sockets = sockets;
|
||||||
@ -21,9 +21,7 @@ namespace HermesSocketServer.Socket.Handlers
|
|||||||
|
|
||||||
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
public async Task Execute<T>(WebSocketUser sender, T message, HermesSocketManager sockets)
|
||||||
{
|
{
|
||||||
if (sender.Id == null)
|
if (message is not RequestMessage data || sender.Id == null)
|
||||||
return;
|
|
||||||
if (message is not RequestMessage data)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RequestResult? result = null;
|
RequestResult? result = null;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using CommonSocketLibrary.Abstract;
|
using CommonSocketLibrary.Abstract;
|
||||||
using HermesSocketServer.Socket.Handlers;
|
using HermesSocketServer.Socket.Handlers;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
@ -8,22 +7,15 @@ namespace HermesSocketServer.Socket
|
|||||||
public class SocketHandlerManager : HandlerManager<WebSocketUser, ISocketHandler>
|
public class SocketHandlerManager : HandlerManager<WebSocketUser, ISocketHandler>
|
||||||
{
|
{
|
||||||
private readonly HermesSocketManager _sockets;
|
private readonly HermesSocketManager _sockets;
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
|
|
||||||
|
|
||||||
public SocketHandlerManager(HermesSocketManager sockets, IServiceProvider serviceProvider, ILogger logger)
|
public SocketHandlerManager(HermesSocketManager sockets, IEnumerable<ISocketHandler> handlers, ILogger logger)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
_sockets = sockets;
|
_sockets = sockets;
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
|
|
||||||
Add(0, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-heartbeat"));
|
foreach (ISocketHandler handler in handlers)
|
||||||
Add(1, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-hermeslogin"));
|
Add(handler.OperationCode, handler);
|
||||||
Add(3, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-request"));
|
|
||||||
Add(5, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-error"));
|
|
||||||
Add(6, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-chatter"));
|
|
||||||
Add(7, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-emotedetails"));
|
|
||||||
Add(8, _serviceProvider.GetRequiredKeyedService<ISocketHandler>("hermes-emoteusage"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task Execute<T>(WebSocketUser sender, ISocketHandler handler, T value)
|
protected override async Task Execute<T>(WebSocketUser sender, ISocketHandler handler, T value)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Net.WebSockets;
|
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using HermesSocketLibrary.Socket.Data;
|
using HermesSocketLibrary.Socket.Data;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
@ -16,7 +15,6 @@ namespace HermesSocketServer.Socket
|
|||||||
{
|
{
|
||||||
_sockets = new List<WebSocketUser>();
|
_sockets = new List<WebSocketUser>();
|
||||||
_timer = new System.Timers.Timer(TimeSpan.FromSeconds(1));
|
_timer = new System.Timers.Timer(TimeSpan.FromSeconds(1));
|
||||||
_timer.AutoReset = true;
|
|
||||||
_timer.Elapsed += async (sender, e) => await HandleHeartbeats(e);
|
_timer.Elapsed += async (sender, e) => await HandleHeartbeats(e);
|
||||||
_timer.Enabled = true;
|
_timer.Enabled = true;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@ -66,25 +64,27 @@ namespace HermesSocketServer.Socket
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
socket.LastHearbeatSent = DateTime.UtcNow;
|
socket.LastHearbeatSent = DateTime.UtcNow;
|
||||||
await socket.Send(0, new HeartbeatMessage() { DateTime = socket.LastHearbeatSent });
|
await socket.Send(0, new HeartbeatMessage() { DateTime = signalTime, Respond = true });
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (signalTime - socket.LastHeartbeatReceived > TimeSpan.FromSeconds(60))
|
||||||
|
{
|
||||||
|
_logger.Debug($"Closing socket [ip: {socket.IPAddress}] for not responding for 2 minutes.");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
socket.Dispose();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Failed to send the heartbeat to socket [ip: {socket.IPAddress}].");
|
|
||||||
await socket.Close(WebSocketCloseStatus.NormalClosure, "Failed to send a heartbeat message.", CancellationToken.None);
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (!socket.Connected)
|
|
||||||
_sockets.RemoveAt(i--);
|
_sockets.RemoveAt(i--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (signalTime - socket.LastHeartbeatReceived > TimeSpan.FromSeconds(120))
|
|
||||||
{
|
|
||||||
_logger.Debug($"Closing socket [ip: {socket.IPAddress}] for not responding for 2 minutes.");
|
|
||||||
await socket.Close(WebSocketCloseStatus.NormalClosure, "No heartbeat received.", CancellationToken.None);
|
|
||||||
_sockets.RemoveAt(i--);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ using System.Net;
|
|||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using HermesSocketLibrary.Socket.Data;
|
using CommonSocketLibrary.Common;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
|
|
||||||
namespace HermesSocketServer.Socket
|
namespace HermesSocketServer.Socket
|
||||||
{
|
{
|
||||||
public class WebSocketUser
|
public class WebSocketUser : IDisposable
|
||||||
{
|
{
|
||||||
private readonly WebSocket _socket;
|
private readonly WebSocket _socket;
|
||||||
private readonly JsonSerializerOptions _options;
|
private readonly JsonSerializerOptions _options;
|
||||||
@ -22,8 +22,12 @@ namespace HermesSocketServer.Socket
|
|||||||
public WebSocketState State { get => _socket.State; }
|
public WebSocketState State { get => _socket.State; }
|
||||||
public IPAddress? IPAddress { get => _ipAddress; }
|
public IPAddress? IPAddress { get => _ipAddress; }
|
||||||
public bool Connected { get => _connected; }
|
public bool Connected { get => _connected; }
|
||||||
|
public string UID { get; }
|
||||||
|
public string ApiKey { get; set; }
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
public bool Admin { get; set; }
|
||||||
|
public bool WebLogin { get; set; }
|
||||||
public DateTime LastHeartbeatReceived { get; set; }
|
public DateTime LastHeartbeatReceived { get; set; }
|
||||||
public DateTime LastHearbeatSent { get; set; }
|
public DateTime LastHearbeatSent { get; set; }
|
||||||
public CancellationToken Token { get => _cts.Token; }
|
public CancellationToken Token { get => _cts.Token; }
|
||||||
@ -36,7 +40,10 @@ namespace HermesSocketServer.Socket
|
|||||||
_options = options;
|
_options = options;
|
||||||
_connected = true;
|
_connected = true;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
Admin = false;
|
||||||
|
WebLogin = false;
|
||||||
_cts = new CancellationTokenSource();
|
_cts = new CancellationTokenSource();
|
||||||
|
UID = Guid.NewGuid().ToString("D");
|
||||||
LastHeartbeatReceived = DateTime.UtcNow;
|
LastHeartbeatReceived = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +72,11 @@ namespace HermesSocketServer.Socket
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_socket.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task Send<Data>(int opcode, Data data)
|
public async Task Send<Data>(int opcode, Data data)
|
||||||
{
|
{
|
||||||
var message = GenerateMessage(opcode, data);
|
var message = GenerateMessage(opcode, data);
|
||||||
@ -101,9 +113,9 @@ namespace HermesSocketServer.Socket
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketMessage GenerateMessage<Data>(int opcode, Data data)
|
private WebSocketMessage GenerateMessage<Data>(int opcode, Data data)
|
||||||
{
|
{
|
||||||
return new SocketMessage()
|
return new WebSocketMessage()
|
||||||
{
|
{
|
||||||
OpCode = opcode,
|
OpCode = opcode,
|
||||||
Data = data
|
Data = data
|
||||||
|
@ -11,18 +11,13 @@
|
|||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
|
||||||
<PackageReference Include="Serilog" Version="4.0.0" />
|
<PackageReference Include="Serilog" Version="4.0.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2-dev-00338" />
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2-dev-00338" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.1-dev-10391" />
|
|
||||||
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.1" />
|
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.2" />
|
||||||
<PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
|
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972" />
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
|
<PackageReference Include="YamlDotNet" Version="16.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Trace" Version="4.0.0" />
|
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
86
Startup.cs
86
Startup.cs
@ -12,17 +12,19 @@ using Serilog;
|
|||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using YamlDotNet.Serialization;
|
using YamlDotNet.Serialization;
|
||||||
using YamlDotNet.Serialization.NamingConventions;
|
using YamlDotNet.Serialization.NamingConventions;
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
|
||||||
|
|
||||||
var deserializer = new DeserializerBuilder()
|
var yamlDeserializer = new DeserializerBuilder()
|
||||||
.WithNamingConvention(HyphenatedNamingConvention.Instance)
|
.WithNamingConvention(HyphenatedNamingConvention.Instance)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var configFileName = "server.config.yml";
|
var configFileName = "server.config.yml";
|
||||||
if (File.Exists("server.config." + Environment.GetEnvironmentVariable("TTS_ENV").ToLower() + ".yml"))
|
var environment = Environment.GetEnvironmentVariable("TTS_ENV")!.ToLower();
|
||||||
configFileName = "server.config." + Environment.GetEnvironmentVariable("TTS_ENV").ToLower() + ".yml";
|
if (File.Exists("server.config." + environment + ".yml"))
|
||||||
|
configFileName = "server.config." + environment + ".yml";
|
||||||
var configContent = File.ReadAllText(configFileName);
|
var configContent = File.ReadAllText(configFileName);
|
||||||
var configuration = deserializer.Deserialize<ServerConfiguration>(configContent);
|
var configuration = yamlDeserializer.Deserialize<ServerConfiguration>(configContent);
|
||||||
|
|
||||||
if (configuration.Environment.ToUpper() != "QA" && configuration.Environment.ToUpper() != "PROD")
|
if (configuration.Environment.ToUpper() != "QA" && configuration.Environment.ToUpper() != "PROD")
|
||||||
throw new Exception("Invalid environment set.");
|
throw new Exception("Invalid environment set.");
|
||||||
@ -36,12 +38,20 @@ builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
builder.WebHost.UseUrls($"http://{configuration.WebsocketServer.Host}:{configuration.WebsocketServer.Port}");
|
builder.WebHost.UseUrls($"http://{configuration.WebsocketServer.Host}:{configuration.WebsocketServer.Port}");
|
||||||
var logger = new LoggerConfiguration()
|
var loggerConfiguration = new LoggerConfiguration();
|
||||||
.MinimumLevel.Debug()
|
if (configuration.Environment.ToUpper() == "QA")
|
||||||
.Enrich.FromLogContext()
|
loggerConfiguration.MinimumLevel.Verbose();
|
||||||
.WriteTo.File("logs/log.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7)
|
else
|
||||||
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information)
|
loggerConfiguration.MinimumLevel.Debug();
|
||||||
.CreateLogger();
|
|
||||||
|
loggerConfiguration.Enrich.FromLogContext()
|
||||||
|
.WriteTo.File($"logs/{configuration.Environment.ToUpper()}/serverlog-.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7);
|
||||||
|
if (configuration.Environment.ToUpper() == "QA")
|
||||||
|
loggerConfiguration.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Debug);
|
||||||
|
else
|
||||||
|
loggerConfiguration.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information);
|
||||||
|
|
||||||
|
var logger = loggerConfiguration.CreateLogger();
|
||||||
|
|
||||||
builder.Host.UseSerilog(logger);
|
builder.Host.UseSerilog(logger);
|
||||||
builder.Logging.AddSerilog(logger);
|
builder.Logging.AddSerilog(logger);
|
||||||
@ -54,32 +64,37 @@ s.AddSingleton<Database>();
|
|||||||
|
|
||||||
// Socket message handlers
|
// Socket message handlers
|
||||||
s.AddSingleton<Serilog.ILogger>(logger);
|
s.AddSingleton<Serilog.ILogger>(logger);
|
||||||
s.AddKeyedSingleton<ISocketHandler, HeartbeatHandler>("hermes-heartbeat");
|
s.AddSingleton<ISocketHandler, HeartbeatHandler>();
|
||||||
s.AddKeyedSingleton<ISocketHandler, HermesLoginHandler>("hermes-hermeslogin");
|
s.AddSingleton<ISocketHandler, HermesLoginHandler>();
|
||||||
s.AddKeyedSingleton<ISocketHandler, RequestHandler>("hermes-request");
|
s.AddSingleton<ISocketHandler, RequestHandler>();
|
||||||
s.AddKeyedSingleton<ISocketHandler, ErrorHandler>("hermes-error");
|
s.AddSingleton<ISocketHandler, LoggingHandler>();
|
||||||
s.AddKeyedSingleton<ISocketHandler, ChatterHandler>("hermes-chatter");
|
s.AddSingleton<ISocketHandler, ChatterHandler>();
|
||||||
s.AddKeyedSingleton<ISocketHandler, EmoteDetailsHandler>("hermes-emotedetails");
|
s.AddSingleton<ISocketHandler, EmoteDetailsHandler>();
|
||||||
s.AddKeyedSingleton<ISocketHandler, EmoteUsageHandler>("hermes-emoteusage");
|
s.AddSingleton<ISocketHandler, EmoteUsageHandler>();
|
||||||
|
|
||||||
// Request handlers
|
// Request handlers
|
||||||
s.AddKeyedSingleton<IRequest, GetTTSUsers>("BanTTSUser");
|
s.AddSingleton<IRequest, GetTTSUsers>();
|
||||||
s.AddKeyedSingleton<IRequest, GetTTSUsers>("GetTTSUsers");
|
s.AddSingleton<IRequest, GetTTSVoices>();
|
||||||
s.AddKeyedSingleton<IRequest, GetTTSVoices>("GetTTSVoices");
|
s.AddSingleton<IRequest, GetTTSWordFilters>();
|
||||||
s.AddKeyedSingleton<IRequest, GetTTSWordFilters>("GetTTSWordFilters");
|
s.AddSingleton<IRequest, CreateTTSUser>();
|
||||||
s.AddKeyedSingleton<IRequest, CreateTTSUser>("CreateTTSUser");
|
s.AddSingleton<IRequest, CreateTTSVoice>();
|
||||||
s.AddKeyedSingleton<IRequest, CreateTTSVoice>("CreateTTSVoice");
|
s.AddSingleton<IRequest, DeleteTTSVoice>();
|
||||||
s.AddKeyedSingleton<IRequest, DeleteTTSVoice>("DeleteTTSVoice");
|
s.AddSingleton<IRequest, UpdateTTSUser>();
|
||||||
s.AddKeyedSingleton<IRequest, UpdateTTSUser>("UpdateTTSUser");
|
s.AddSingleton<IRequest, UpdateTTSVoice>();
|
||||||
s.AddKeyedSingleton<IRequest, UpdateTTSVoice>("UpdateTTSVoice");
|
s.AddSingleton<IRequest, GetChatterIds>();
|
||||||
s.AddKeyedSingleton<IRequest, GetChatterIds>("GetChatterIds");
|
s.AddSingleton<IRequest, GetDefaultTTSVoice>();
|
||||||
s.AddKeyedSingleton<IRequest, GetEmotes>("GetEmotes");
|
s.AddSingleton<IRequest, GetEmotes>();
|
||||||
s.AddKeyedSingleton<IRequest, UpdateTTSVoiceState>("UpdateTTSVoiceState");
|
s.AddSingleton<IRequest, GetEnabledTTSVoices>();
|
||||||
|
s.AddSingleton<IRequest, GetPermissions>();
|
||||||
|
s.AddSingleton<IRequest, GetRedemptions>();
|
||||||
|
s.AddSingleton<IRequest, GetRedeemableActions>();
|
||||||
|
s.AddSingleton<IRequest, UpdateTTSVoiceState>();
|
||||||
|
s.AddSingleton<IRequest, UpdateDefaultTTSVoice>();
|
||||||
|
|
||||||
s.AddSingleton<HermesSocketManager>();
|
s.AddSingleton<HermesSocketManager>();
|
||||||
s.AddSingleton<SocketHandlerManager>();
|
s.AddSingleton<SocketHandlerManager>();
|
||||||
s.AddSingleton<RequestManager, ServerRequestManager>();
|
s.AddSingleton<IRequestManager, RequestManager>();
|
||||||
s.AddSingleton<JsonSerializerOptions>(new JsonSerializerOptions()
|
s.AddSingleton(new JsonSerializerOptions()
|
||||||
{
|
{
|
||||||
PropertyNameCaseInsensitive = false,
|
PropertyNameCaseInsensitive = false,
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
||||||
@ -89,10 +104,15 @@ s.AddSingleton<Server>();
|
|||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
app.UseForwardedHeaders();
|
app.UseForwardedHeaders();
|
||||||
app.UseSerilogRequestLogging();
|
app.UseSerilogRequestLogging();
|
||||||
app.UseWebSockets(new WebSocketOptions()
|
|
||||||
|
var wsOptions = new WebSocketOptions()
|
||||||
{
|
{
|
||||||
KeepAliveInterval = TimeSpan.FromSeconds(30)
|
KeepAliveInterval = TimeSpan.FromSeconds(30)
|
||||||
});
|
};
|
||||||
|
// wsOptions.AllowedOrigins.Add("wss://tomtospeech.com");
|
||||||
|
//wsOptions.AllowedOrigins.Add("ws.tomtospeech.com");
|
||||||
|
//wsOptions.AllowedOrigins.Add("hermes-ws.goblincaves.com");
|
||||||
|
app.UseWebSockets(wsOptions);
|
||||||
|
|
||||||
var options = app.Services.GetRequiredService<JsonSerializerOptions>();
|
var options = app.Services.GetRequiredService<JsonSerializerOptions>();
|
||||||
var server = app.Services.GetRequiredService<Server>();
|
var server = app.Services.GetRequiredService<Server>();
|
||||||
|
Loading…
Reference in New Issue
Block a user