using SharpChat.Events; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Text.Json; using System.Text.Json.Serialization; namespace SharpChat { public static class WebDatabase { private static string EndPoint = null; public static bool IsAvailable => !string.IsNullOrWhiteSpace(EndPoint); public static void ReadConfig() { if(!File.Exists(@"webdb.txt")) return; string[] config = File.ReadAllLines(@"webdb.txt"); if(config.Length < 1 && !string.IsNullOrWhiteSpace(config[0])) return; Init(config[0]); } public static void Init(string endPoint) { EndPoint = endPoint; } public static void Deinit() { EndPoint = null; } public static void LogEvent(IChatEvent evt) { if(evt.SequenceId < 1) evt.SequenceId = Database.GenerateId(); string sId = evt.SequenceId.ToString(); string sCreated = evt.DateTime.ToUnixTimeSeconds().ToString(); string sType = evt.GetType().FullName; string sTarget = evt.Target.TargetName ?? string.Empty; string sFlags = ((byte)evt.Flags).ToString(); string sData = JsonSerializer.Serialize(evt, evt.GetType()); string sSender = evt.Sender?.UserId < 1 ? string.Empty : evt.Sender.UserId.ToString(); string sSenderName = evt.Sender?.Username.ToString() ?? string.Empty; string sSenderColour = evt.Sender?.Colour.Raw.ToString() ?? string.Empty; string sSenderRank = evt.Sender?.Rank.ToString() ?? string.Empty; string sSenderNick = evt.Sender?.Nickname?.ToString() ?? string.Empty; string sSenderPerms = evt.Sender == null ? string.Empty : ((int)evt.Sender.Permissions).ToString(); string sHash = string.Join('#', @"crev", sId, sCreated, sType, sTarget, sFlags, sSender, sSenderColour, sSenderRank, sSenderPerms, sSenderName, sSenderNick, sData); MultipartFormDataContent mfdc = new(); mfdc.Add(new StringContent(sId), @"i"); mfdc.Add(new StringContent(sCreated), @"c"); mfdc.Add(new StringContent(sType), @"t"); mfdc.Add(new StringContent(sTarget), @"l"); mfdc.Add(new StringContent(sFlags), @"f"); mfdc.Add(new StringContent(sData), @"d"); mfdc.Add(new StringContent(sSender), @"s"); mfdc.Add(new StringContent(sSenderName), @"su"); mfdc.Add(new StringContent(sSenderColour), @"sc"); mfdc.Add(new StringContent(sSenderRank), @"sr"); mfdc.Add(new StringContent(sSenderNick), @"sn"); mfdc.Add(new StringContent(sSenderPerms), @"sp"); HttpRequestMessage request = new(HttpMethod.Post, EndPoint + @"?m=crev") { Content = mfdc, Headers = { { @"X-SharpChat-Signature", sHash.GetSignedHash() }, } }; SockChatServer.HttpClient.SendAsync(request).ContinueWith(x => { if(x.IsCompleted) { if(x.Result.Headers.TryGetValues(@"X-SharpChat-Error", out IEnumerable values)) Logger.Write($@"DBS - LogEvent: {values.FirstOrDefault()}"); } if(x.IsFaulted) Logger.Write($@"DBS - LogEvent: {x.Exception}"); }).Wait(); } public static void DeleteEvent(IChatEvent evt) { string msgId = evt.SequenceId.ToString(); using HttpRequestMessage request = new(HttpMethod.Delete, EndPoint + @"?m=deev&i=" + msgId) { Headers = { { @"X-SharpChat-Signature", (@"deev#" + msgId).GetSignedHash() }, } }; SockChatServer.HttpClient.SendAsync(request).ContinueWith(x => { if(x.IsCompleted) { if(x.Result.Headers.TryGetValues(@"X-SharpChat-Error", out IEnumerable values)) Logger.Write($@"DBS - DeleteEvent: {values.FirstOrDefault()}"); } if(x.IsFaulted) Logger.Write($@"DBS - DeleteEvent: {x.Exception}"); }).Wait(); } private class DatabaseRow { [JsonPropertyName(@"i")] public long EventId { get; set; } [JsonPropertyName(@"s")] public long EventSenderId { get; set; } [JsonPropertyName(@"su")] public string EventSenderName { get; set; } [JsonPropertyName(@"sc")] public int EventSenderColour { get; set; } [JsonPropertyName(@"sr")] public int EventSenderRank { get; set; } [JsonPropertyName(@"sn")] public string EventSenderNick { get; set; } [JsonPropertyName(@"sp")] public int EventSenderPerms { get; set; } [JsonPropertyName(@"c")] public int EventCreated { get; set; } [JsonPropertyName(@"t")] public string EventType { get; set; } [JsonPropertyName(@"l")] public string EventTarget { get; set; } [JsonPropertyName(@"f")] public byte EventFlags { get; set; } [JsonPropertyName(@"d")] public string EventData { get; set; } } private static IChatEvent ReadEvent(DatabaseRow row, IPacketTarget target = null) { Type evtType = Type.GetType(row.EventType); IChatEvent evt = JsonSerializer.Deserialize(row.EventData, evtType) as IChatEvent; evt.SequenceId = row.EventId; evt.Target = target; evt.TargetName = target?.TargetName ?? row.EventTarget; evt.Flags = (ChatMessageFlags)row.EventFlags; evt.DateTime = DateTimeOffset.FromUnixTimeSeconds(row.EventCreated); if(row.EventSenderId > 0) { evt.Sender = new BasicUser { UserId = row.EventSenderId, Username = row.EventSenderName, Colour = new ChatColour(row.EventSenderColour), Rank = row.EventSenderRank, Nickname = string.IsNullOrEmpty(row.EventSenderNick) ? null : row.EventSenderNick, Permissions = (ChatUserPermissions)row.EventSenderPerms }; } return evt; } public static IChatEvent GetEvent(long seqId) { string sSeqId = seqId.ToString(); using HttpRequestMessage request = new(HttpMethod.Get, EndPoint + @"?m=geev&i=" + sSeqId) { Headers = { { @"X-SharpChat-Signature", (@"geev#" + sSeqId).GetSignedHash() }, } }; // jesus christ what is this System.Runtime.CompilerServices.TaskAwaiter? awaiter = null; HttpResponseMessage response = null; try { awaiter = SockChatServer.HttpClient.SendAsync(request).GetAwaiter(); response = awaiter.Value.GetResult(); byte[] garbage = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult(); return ReadEvent( (DatabaseRow)JsonSerializer.Deserialize(garbage, typeof(DatabaseRow)) ); } catch(Exception ex) { Logger.Write($@"DBS - GetEvent: {ex}"); } finally { if(awaiter.HasValue && awaiter.Value.IsCompleted) { if(response != null && response.Headers.TryGetValues(@"X-SharpChat-Error", out IEnumerable values)) Logger.Write($@"DBS - GetEvent: {values.FirstOrDefault()}"); } } return null; } public static IEnumerable GetEvents(IPacketTarget target, int amount, int offset) { List events = new(); using HttpRequestMessage request = new(HttpMethod.Get, EndPoint + @"?m=feev&l=" + target.TargetName + @"&a=" + amount + @"&o=" + offset) { Headers = { { @"X-SharpChat-Signature", string.Join('#', @"feev", amount, offset, target.TargetName).GetSignedHash() }, } }; System.Runtime.CompilerServices.TaskAwaiter? awaiter = null; HttpResponseMessage response = null; try { awaiter = SockChatServer.HttpClient.SendAsync(request).GetAwaiter(); response = awaiter.Value.GetResult(); byte[] trash = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult(); IEnumerable rows = (IEnumerable)JsonSerializer.Deserialize(trash, typeof(IEnumerable)); foreach(DatabaseRow row in rows) events.Add(ReadEvent(row, target)); } catch(Exception ex) { Logger.Write($@"DBS - GetEvents: {ex}"); } finally { if(awaiter.HasValue && awaiter.Value.IsCompleted) { if(response != null && response.Headers.TryGetValues(@"X-SharpChat-Error", out IEnumerable values)) Logger.Write($@"DBS - GetEvents: {values.FirstOrDefault()}"); } } return events; } } }