using System.Text.Json.Serialization; namespace Whisper; // Every database write, as data, so the writer can run them in order off the game thread and keep // them in the spool file while the database is down. Each is safe to run twice: messages are keyed, // block adds are INSERT IGNOREs and removes are deletes. [JsonPolymorphic(TypeDiscriminatorPropertyName = "op")] [JsonDerivedType(typeof(MessageRecord), "message")] [JsonDerivedType(typeof(BlockAdd), "block_add")] [JsonDerivedType(typeof(BlockRemove), "block_remove")] public abstract record Op; // A player as they were when the message was sent. Console: SteamId 0, no team. public sealed record PlayerState(ulong SteamId, string Name, int? Team, bool? Alive) { public static readonly PlayerState Console = new(0, "Console", null, null); } public sealed record MessageRecord( string Key, DateTime At, int? ServerId, string Map, string Channel, PlayerState Sender, PlayerState? Recipient, string? Target, string Message, string Result) : Op; public sealed record BlockAdd(ulong Blocker, ulong Blocked, string BlockedName, DateTime At) : Op; public sealed record BlockRemove(ulong Blocker, ulong Blocked) : Op; // Where a message went (wh_messages.channel). SimpleAdmin's commands are logged by their own name. public static class ChatChannel { public const string All = "all"; public const string Team = "team"; public const string Pm = "pm"; public const string Staff = "staff"; public const string ToStaff = "to_staff"; } // What the message log calls each outcome (wh_messages.result). public static class Result { public const string Sent = "sent"; public const string Command = "command"; public const string Blocked = "blocked"; public const string Gagged = "gagged"; public const string Cooldown = "cooldown"; public const string NoTarget = "no_target"; public const string Ambiguous = "ambiguous"; public const string GroupTarget = "group_target"; public const string TooLong = "too_long"; }