Removed event flags attribute.

This commit is contained in:
flash 2024-05-24 00:23:31 +00:00
parent 651c3f127d
commit 454a460441
7 changed files with 113 additions and 88 deletions

View file

@ -5,6 +5,7 @@ using SharpChat.SockChat.PacketsS2C;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json;
using System.Threading; using System.Threading;
namespace SharpChat { namespace SharpChat {
@ -65,14 +66,16 @@ namespace SharpChat {
)); ));
} }
object msgData = mce.IsAction
? new { text = mce.MessageText, action = true }
: new { text = mce.MessageText };
Events.AddEvent( Events.AddEvent(
mce.MessageId, "msg:add", mce.MessageId,
mce.ChannelName, "msg:add",
mce.IsBroadcast ? null : mce.ChannelName,
mce.SenderId, mce.SenderName, mce.SenderColour, mce.SenderRank, mce.SenderNickName, mce.SenderPerms, mce.SenderId, mce.SenderName, mce.SenderColour, mce.SenderRank, mce.SenderNickName, mce.SenderPerms,
new { text = mce.MessageText }, msgData
(mce.IsBroadcast ? StoredEventFlags.Broadcast : 0)
| (mce.IsAction ? StoredEventFlags.Action : 0)
| (mce.IsPrivate ? StoredEventFlags.Private : 0)
); );
return; return;
} }
@ -204,45 +207,78 @@ namespace SharpChat {
} }
public void HandleChannelEventLog(string channelName, Action<ISockChatS2CPacket> handler) { public void HandleChannelEventLog(string channelName, Action<ISockChatS2CPacket> handler) {
foreach(StoredEventInfo msg in Events.GetChannelEventLog(channelName)) foreach(StoredEventInfo msg in Events.GetChannelEventLog(channelName)) {
handler(msg.Type switch { ISockChatS2CPacket packet;
"msg:add" => new MessageAddLogS2CPacket(
msg.Id, switch(msg.Type) {
msg.Created, case "msg:add":
msg.Sender?.UserId ?? -1, string maText = string.Empty;
msg.Sender == null ? "ChatBot" : SockChatUtility.GetUserName(msg.Sender), if(msg.Data.RootElement.TryGetProperty("text", out JsonElement maTextElem))
msg.Sender?.Colour ?? Colour.None, maText = maTextElem.ToString();
msg.Sender?.Rank ?? 0,
msg.Sender?.Permissions ?? 0, bool maAction = false;
msg.Data.RootElement.GetProperty("text").GetString() ?? string.Empty, if(msg.Data.RootElement.TryGetProperty("action", out JsonElement maIsActionElem))
msg.Flags.HasFlag(StoredEventFlags.Action), maAction = maIsActionElem.ValueKind == JsonValueKind.True;
msg.Flags.HasFlag(StoredEventFlags.Private),
msg.Flags.HasFlag(StoredEventFlags.Broadcast), packet = new MessageAddLogS2CPacket(
false msg.Id,
), msg.Created,
"user:connect" => new UserConnectLogS2CPacket( msg.Sender?.UserId ?? -1,
msg.Id, msg.Sender == null ? "ChatBot" : SockChatUtility.GetUserName(msg.Sender),
msg.Created, msg.Sender?.Colour ?? Colour.None,
msg.Sender == null ? string.Empty : SockChatUtility.GetUserName(msg.Sender) msg.Sender?.Rank ?? 0,
), msg.Sender?.Permissions ?? 0,
"user:disconnect" => new UserDisconnectLogS2CPacket( maText,
msg.Id, maAction,
msg.Created, msg.ChannelName?.StartsWith('@') == true,
msg.Sender == null ? string.Empty : SockChatUtility.GetUserNameWithStatus(msg.Sender), msg.ChannelName == null,
(UserDisconnectReason)msg.Data.RootElement.GetProperty("reason").GetByte() false
), );
"chan:join" => new UserChannelJoinLogS2CPacket( break;
msg.Id,
msg.Created, case "user:connect":
msg.Sender == null ? string.Empty : SockChatUtility.GetUserName(msg.Sender) packet = new UserConnectLogS2CPacket(
), msg.Id,
"chan:leave" => new UserChannelLeaveLogS2CPacket( msg.Created,
msg.Id, msg.Sender == null ? string.Empty : SockChatUtility.GetUserName(msg.Sender)
msg.Created, );
msg.Sender == null ? string.Empty : SockChatUtility.GetUserName(msg.Sender) break;
),
_ => throw new Exception($"Unsupported backlog type: {msg.Type}"), case "user:disconnect":
}); UserDisconnectReason udReason = 0;
if(msg.Data.RootElement.TryGetProperty("reason", out JsonElement udElem) && udElem.TryGetByte(out byte udReasonRaw))
udReason = (UserDisconnectReason)udReasonRaw;
packet = new UserDisconnectLogS2CPacket(
msg.Id,
msg.Created,
msg.Sender == null ? string.Empty : SockChatUtility.GetUserNameWithStatus(msg.Sender),
udReason
);
break;
case "chan:join":
packet = new UserChannelJoinLogS2CPacket(
msg.Id,
msg.Created,
msg.Sender == null ? string.Empty : SockChatUtility.GetUserName(msg.Sender)
);
break;
case "chan:leave":
packet = new UserChannelLeaveLogS2CPacket(
msg.Id,
msg.Created,
msg.Sender == null ? string.Empty : SockChatUtility.GetUserName(msg.Sender)
);
break;
default:
throw new Exception($"Unsupported backlog type: {msg.Type}");
}
handler(packet);
}
} }
public void HandleJoin(UserInfo user, ChannelInfo chan, SockChatConnectionInfo conn, int maxMsgLength) { public void HandleJoin(UserInfo user, ChannelInfo chan, SockChatConnectionInfo conn, int maxMsgLength) {
@ -267,8 +303,7 @@ namespace SharpChat {
user.Rank, user.Rank,
user.NickName, user.NickName,
user.Permissions, user.Permissions,
null, null
StoredEventFlags.Log
); );
} }
@ -330,8 +365,7 @@ namespace SharpChat {
user.Rank, user.Rank,
user.NickName, user.NickName,
user.Permissions, user.Permissions,
new { reason = (int)reason }, new { reason = (int)reason }
StoredEventFlags.Log
); );
if(chan.IsTemporary && chan.IsOwner(user)) if(chan.IsTemporary && chan.IsOwner(user))
@ -377,8 +411,7 @@ namespace SharpChat {
user.Rank, user.Rank,
user.NickName, user.NickName,
user.Permissions, user.Permissions,
null, null
StoredEventFlags.Log
); );
} }
@ -401,8 +434,7 @@ namespace SharpChat {
user.Rank, user.Rank,
user.NickName, user.NickName,
user.Permissions, user.Permissions,
null, null
StoredEventFlags.Log
); );
SendTo(user, new ContextClearS2CPacket(ContextClearS2CPacket.ClearMode.MessagesUsers)); SendTo(user, new ContextClearS2CPacket(ContextClearS2CPacket.ClearMode.MessagesUsers));

View file

@ -12,12 +12,11 @@ namespace SharpChat.EventStorage {
int senderRank, int senderRank,
string? senderNick, string? senderNick,
UserPermissions senderPerms, UserPermissions senderPerms,
object? data = null, object? data = null
StoredEventFlags flags = StoredEventFlags.None
); );
void RemoveEvent(StoredEventInfo evt); void RemoveEvent(StoredEventInfo evt);
StoredEventInfo? GetEvent(long seqId); StoredEventInfo? GetEvent(long seqId);
IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int offset = 0); IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int startAt = 0);
} }
} }

View file

@ -22,18 +22,16 @@ namespace SharpChat.EventStorage {
int senderRank, int senderRank,
string? senderNick, string? senderNick,
UserPermissions senderPerms, UserPermissions senderPerms,
object? data = null, object? data = null
StoredEventFlags flags = StoredEventFlags.None
) { ) {
RunCommand( RunCommand(
"INSERT INTO `sqc_events` (`event_id`, `event_created`, `event_type`, `event_target`, `event_flags`, `event_data`" "INSERT INTO `sqc_events` (`event_id`, `event_created`, `event_type`, `event_target`, `event_data`"
+ ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`)" + ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`)"
+ " VALUES (@id, NOW(), @type, @target, @flags, @data" + " VALUES (@id, NOW(), @type, @target, @data"
+ ", @sender, @sender_name, @sender_colour, @sender_rank, @sender_nick, @sender_perms)", + ", @sender, @sender_name, @sender_colour, @sender_rank, @sender_nick, @sender_perms)",
new MySqlParameter("id", id), new MySqlParameter("id", id),
new MySqlParameter("type", type), new MySqlParameter("type", type),
new MySqlParameter("target", string.IsNullOrWhiteSpace(channelName) ? null : channelName), new MySqlParameter("target", string.IsNullOrWhiteSpace(channelName) ? null : channelName),
new MySqlParameter("flags", (byte)flags),
new MySqlParameter("data", data == null ? "{}" : JsonSerializer.SerializeToUtf8Bytes(data)), new MySqlParameter("data", data == null ? "{}" : JsonSerializer.SerializeToUtf8Bytes(data)),
new MySqlParameter("sender", senderId < 1 ? null : senderId), new MySqlParameter("sender", senderId < 1 ? null : senderId),
new MySqlParameter("sender_name", senderName), new MySqlParameter("sender_name", senderName),
@ -47,7 +45,7 @@ namespace SharpChat.EventStorage {
public StoredEventInfo? GetEvent(long seqId) { public StoredEventInfo? GetEvent(long seqId) {
try { try {
using MySqlDataReader? reader = RunQuery( using MySqlDataReader? reader = RunQuery(
"SELECT `event_id`, `event_type`, `event_flags`, `event_data`, `event_target`" "SELECT `event_id`, `event_type`, `event_data`, `event_target`"
+ ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`" + ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`"
+ ", UNIX_TIMESTAMP(`event_created`) AS `event_created`" + ", UNIX_TIMESTAMP(`event_created`) AS `event_created`"
+ ", UNIX_TIMESTAMP(`event_deleted`) AS `event_deleted`" + ", UNIX_TIMESTAMP(`event_deleted`) AS `event_deleted`"
@ -84,17 +82,16 @@ namespace SharpChat.EventStorage {
DateTimeOffset.FromUnixTimeSeconds(reader.GetInt32("event_created")), DateTimeOffset.FromUnixTimeSeconds(reader.GetInt32("event_created")),
reader.IsDBNull(reader.GetOrdinal("event_deleted")) ? null : DateTimeOffset.FromUnixTimeSeconds(reader.GetInt32("event_deleted")), reader.IsDBNull(reader.GetOrdinal("event_deleted")) ? null : DateTimeOffset.FromUnixTimeSeconds(reader.GetInt32("event_deleted")),
reader.IsDBNull(reader.GetOrdinal("event_target")) ? null : Encoding.ASCII.GetString((byte[])reader["event_target"]), reader.IsDBNull(reader.GetOrdinal("event_target")) ? null : Encoding.ASCII.GetString((byte[])reader["event_target"]),
JsonDocument.Parse(Encoding.ASCII.GetString((byte[])reader["event_data"])), JsonDocument.Parse(Encoding.ASCII.GetString((byte[])reader["event_data"]))
(StoredEventFlags)reader.GetByte("event_flags")
); );
} }
public IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int offset = 0) { public IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int startAt = 0) {
List<StoredEventInfo> events = new(); List<StoredEventInfo> events = new();
try { try {
using MySqlDataReader? reader = RunQuery( using MySqlDataReader? reader = RunQuery(
"SELECT `event_id`, `event_type`, `event_flags`, `event_data`, `event_target`" "SELECT `event_id`, `event_type`, `event_data`, `event_target`"
+ ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`" + ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`"
+ ", UNIX_TIMESTAMP(`event_created`) AS `event_created`" + ", UNIX_TIMESTAMP(`event_created`) AS `event_created`"
+ ", UNIX_TIMESTAMP(`event_deleted`) AS `event_deleted`" + ", UNIX_TIMESTAMP(`event_deleted`) AS `event_deleted`"
@ -105,7 +102,7 @@ namespace SharpChat.EventStorage {
+ " LIMIT @amount", + " LIMIT @amount",
new MySqlParameter("target", channelName), new MySqlParameter("target", channelName),
new MySqlParameter("amount", amount), new MySqlParameter("amount", amount),
new MySqlParameter("offset", offset) new MySqlParameter("offset", startAt)
); );
if(reader != null) if(reader != null)

View file

@ -31,6 +31,19 @@ namespace SharpChat.EventStorage {
DoMigration("create_events_table", CreateEventsTable); DoMigration("create_events_table", CreateEventsTable);
DoMigration("allow_null_target", AllowNullTarget); DoMigration("allow_null_target", AllowNullTarget);
DoMigration("update_event_type_names", UpdateEventTypeNames); DoMigration("update_event_type_names", UpdateEventTypeNames);
DoMigration("deprecate_event_flags", DeprecateEventFlags);
}
private void DeprecateEventFlags() {
// StoredEventFlags.Action is just a field in the data object
RunCommand(@"UPDATE sqc_events SET event_data = JSON_MERGE_PATCH(event_data, JSON_OBJECT('action', true)) WHERE event_flags & 1");
// StoredEventFlags.Broadcast can be implied by just having a NULL as the channel name
RunCommand(@"UPDATE sqc_events SET event_target = NULL WHERE event_flags & 2");
// StoredEventFlags.Log was never meaningfully used by anything and basically just meant "not-msg:add"
// StoredEventFlags.Private was also never meaningfully used, can be determined by checking if the channel name starts with @
RunCommand(@"ALTER TABLE sqc_events DROP COLUMN event_flags");
} }
private void UpdateEventTypeNames() { private void UpdateEventTypeNames() {

View file

@ -1,12 +0,0 @@
using System;
namespace SharpChat.EventStorage {
[Flags]
public enum StoredEventFlags {
None = 0,
Action = 1,
Broadcast = 1 << 1,
Log = 1 << 2,
Private = 1 << 3,
}
}

View file

@ -9,7 +9,6 @@ namespace SharpChat.EventStorage {
public DateTimeOffset Created { get; set; } public DateTimeOffset Created { get; set; }
public DateTimeOffset? Deleted { get; set; } public DateTimeOffset? Deleted { get; set; }
public string? ChannelName { get; set; } public string? ChannelName { get; set; }
public StoredEventFlags Flags { get; set; }
public JsonDocument Data { get; set; } public JsonDocument Data { get; set; }
public StoredEventInfo( public StoredEventInfo(
@ -19,8 +18,7 @@ namespace SharpChat.EventStorage {
DateTimeOffset created, DateTimeOffset created,
DateTimeOffset? deleted, DateTimeOffset? deleted,
string? channelName, string? channelName,
JsonDocument data, JsonDocument data
StoredEventFlags flags
) { ) {
Id = id; Id = id;
Type = type; Type = type;
@ -29,7 +27,6 @@ namespace SharpChat.EventStorage {
Deleted = deleted; Deleted = deleted;
ChannelName = channelName; ChannelName = channelName;
Data = data; Data = data;
Flags = flags;
} }
} }
} }

View file

@ -17,8 +17,7 @@ namespace SharpChat.EventStorage {
int senderRank, int senderRank,
string? senderNick, string? senderNick,
UserPermissions senderPerms, UserPermissions senderPerms,
object? data = null, object? data = null
StoredEventFlags flags = StoredEventFlags.None
) { ) {
// VES is meant as an emergency fallback but this is something else // VES is meant as an emergency fallback but this is something else
JsonDocument hack = JsonDocument.Parse(data == null ? "{}" : JsonSerializer.Serialize(data)); JsonDocument hack = JsonDocument.Parse(data == null ? "{}" : JsonSerializer.Serialize(data));
@ -29,7 +28,7 @@ namespace SharpChat.EventStorage {
senderRank, senderRank,
senderPerms, senderPerms,
senderNick senderNick
), DateTimeOffset.Now, null, channelName, hack, flags)); ), DateTimeOffset.Now, null, channelName, hack));
} }
public StoredEventInfo? GetEvent(long seqId) { public StoredEventInfo? GetEvent(long seqId) {
@ -40,10 +39,10 @@ namespace SharpChat.EventStorage {
Events.Remove(evt.Id); Events.Remove(evt.Id);
} }
public IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int offset = 0) { public IEnumerable<StoredEventInfo> GetChannelEventLog(string channelName, int amount = 20, int startAt = 0) {
IEnumerable<StoredEventInfo> subset = Events.Values.Where(ev => ev.ChannelName == channelName); IEnumerable<StoredEventInfo> subset = Events.Values.Where(ev => ev.ChannelName == channelName);
int start = subset.Count() - offset - amount; int start = subset.Count() - startAt - amount;
if(start < 0) { if(start < 0) {
amount += start; amount += start;
start = 0; start = 0;