sharp-chat/SharpChat/WebDatabase.cs

234 lines
9.4 KiB
C#

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<string> 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<string> 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<HttpResponseMessage>? 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<string> values))
Logger.Write($@"DBS - GetEvent: {values.FirstOrDefault()}");
}
}
return null;
}
public static IEnumerable<IChatEvent> GetEvents(IPacketTarget target, int amount, int offset) {
List<IChatEvent> 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<HttpResponseMessage>? awaiter = null;
HttpResponseMessage response = null;
try {
awaiter = SockChatServer.HttpClient.SendAsync(request).GetAwaiter();
response = awaiter.Value.GetResult();
byte[] trash = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
IEnumerable<DatabaseRow> rows = (IEnumerable<DatabaseRow>)JsonSerializer.Deserialize(trash, typeof(IEnumerable<DatabaseRow>));
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<string> values))
Logger.Write($@"DBS - GetEvents: {values.FirstOrDefault()}");
}
}
return events;
}
}
}