sharp-chat/SharpChat/EventStorage/MariaDBEventStorage.cs

130 lines
5.9 KiB
C#

using MySqlConnector;
using SharpChat.Events;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
namespace SharpChat.EventStorage {
public partial class MariaDBEventStorage : IEventStorage {
private string ConnectionString { get; }
public MariaDBEventStorage(string connString) {
ConnectionString = connString ?? throw new ArgumentNullException(nameof(connString));
}
public void AddEvent(IChatEvent evt) {
if(evt == null)
throw new ArgumentNullException(nameof(evt));
if(evt.SequenceId < 1)
evt.SequenceId = SharpId.Next();
RunCommand(
"INSERT INTO `sqc_events` (`event_id`, `event_created`, `event_type`, `event_target`, `event_flags`, `event_data`"
+ ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`)"
+ " VALUES (@id, FROM_UNIXTIME(@created), @type, @target, @flags, @data"
+ ", @sender, @sender_name, @sender_colour, @sender_rank, @sender_nick, @sender_perms)",
new MySqlParameter("id", evt.SequenceId),
new MySqlParameter("created", evt.DateTime.ToUnixTimeSeconds()),
new MySqlParameter("type", evt.GetType().FullName),
new MySqlParameter("target", evt.ChannelName),
new MySqlParameter("flags", (byte)evt.Flags),
new MySqlParameter("data", JsonSerializer.SerializeToUtf8Bytes(evt, evt.GetType())),
new MySqlParameter("sender", evt.Sender?.UserId < 1 ? null : (long?)evt.Sender.UserId),
new MySqlParameter("sender_name", evt.Sender?.UserName),
new MySqlParameter("sender_colour", evt.Sender?.Colour.ToMisuzu()),
new MySqlParameter("sender_rank", evt.Sender?.Rank),
new MySqlParameter("sender_nick", evt.Sender?.NickName),
new MySqlParameter("sender_perms", evt.Sender?.Permissions)
);
}
public IChatEvent GetEvent(long seqId) {
try {
using MySqlDataReader reader = RunQuery(
"SELECT `event_id`, `event_type`, `event_flags`, `event_data`, `event_target`"
+ ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`"
+ ", UNIX_TIMESTAMP(`event_created`) AS `event_created`"
+ " FROM `sqc_events`"
+ " WHERE `event_id` = @id",
new MySqlParameter("id", seqId)
);
while(reader.Read()) {
IChatEvent evt = ReadEvent(reader);
if(evt != null)
return evt;
}
} catch(MySqlException ex) {
Logger.Write(ex);
}
return null;
}
private static IChatEvent ReadEvent(MySqlDataReader reader) {
Type evtType = Type.GetType(Encoding.ASCII.GetString((byte[])reader["event_type"]));
IChatEvent evt = JsonSerializer.Deserialize(Encoding.ASCII.GetString((byte[])reader["event_data"]), evtType) as IChatEvent;
evt.SequenceId = reader.GetInt64("event_id");
evt.ChannelName = Encoding.ASCII.GetString((byte[])reader["event_target"]);
evt.Flags = (ChatMessageFlags)reader.GetByte("event_flags");
evt.DateTime = DateTimeOffset.FromUnixTimeSeconds(reader.GetInt32("event_created"));
if(!reader.IsDBNull(reader.GetOrdinal("event_sender"))) {
evt.Sender = new ChatUser(
reader.GetInt64("event_sender"),
reader.GetString("event_sender_name"),
ChatColour.FromMisuzu(reader.GetInt32("event_sender_colour")),
reader.GetInt32("event_sender_rank"),
(ChatUserPermissions)reader.GetInt32("event_sender_perms"),
reader.IsDBNull(reader.GetOrdinal("event_sender_nick")) ? null : reader.GetString("event_sender_nick")
);
}
return evt;
}
public IEnumerable<IChatEvent> GetChannelEventLog(string channelName, int amount = 20, int offset = 0) {
List<IChatEvent> events = new();
try {
using MySqlDataReader reader = RunQuery(
"SELECT `event_id`, `event_type`, `event_flags`, `event_data`, `event_target`"
+ ", `event_sender`, `event_sender_name`, `event_sender_colour`, `event_sender_rank`, `event_sender_nick`, `event_sender_perms`"
+ ", UNIX_TIMESTAMP(`event_created`) AS `event_created`"
+ " FROM `sqc_events`"
+ " WHERE `event_deleted` IS NULL AND `event_target` = @target"
+ " AND `event_id` > @offset"
+ " ORDER BY `event_id` DESC"
+ " LIMIT @amount",
new MySqlParameter("target", channelName),
new MySqlParameter("amount", amount),
new MySqlParameter("offset", offset)
);
while(reader.Read()) {
IChatEvent evt = ReadEvent(reader);
if(evt != null)
events.Add(evt);
}
} catch(MySqlException ex) {
Logger.Write(ex);
}
events.Reverse();
return events;
}
public void RemoveEvent(IChatEvent evt) {
if(evt == null)
throw new ArgumentNullException(nameof(evt));
RunCommand(
"UPDATE IGNORE `sqc_events` SET `event_deleted` = NOW() WHERE `event_id` = @id AND `event_deleted` IS NULL",
new MySqlParameter("id", evt.SequenceId)
);
}
}
}