Apparently this is what's actually running on the server.
This commit is contained in:
parent
5d2b9f62c1
commit
23f0bd478f
13 changed files with 411 additions and 75 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,6 +1,12 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
welcome.txt
|
||||
mariadb.txt
|
||||
login_key.txt
|
||||
http-motd.txt
|
||||
_webdb.txt
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
|
|
|
@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.29025.244
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpChat", "SharpChat\SharpChat.csproj", "{DDB24C19-B802-4C96-AC15-0449C6FC77F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hamakaze", "Hamakaze\Hamakaze.csproj", "{6059200F-141C-42A5-AA3F-E38C9721AEC8}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpChatTest", "SharpChatTest\SharpChatTest.csproj", "{6CD6DB9D-E0FF-4DEB-8E28-0C3EA6BA26B2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -17,10 +17,10 @@ Global
|
|||
{DDB24C19-B802-4C96-AC15-0449C6FC77F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DDB24C19-B802-4C96-AC15-0449C6FC77F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DDB24C19-B802-4C96-AC15-0449C6FC77F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6059200F-141C-42A5-AA3F-E38C9721AEC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6059200F-141C-42A5-AA3F-E38C9721AEC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6059200F-141C-42A5-AA3F-E38C9721AEC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6059200F-141C-42A5-AA3F-E38C9721AEC8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CD6DB9D-E0FF-4DEB-8E28-0C3EA6BA26B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6CD6DB9D-E0FF-4DEB-8E28-0C3EA6BA26B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6CD6DB9D-E0FF-4DEB-8E28-0C3EA6BA26B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CD6DB9D-E0FF-4DEB-8E28-0C3EA6BA26B2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -144,19 +144,24 @@ namespace SharpChat {
|
|||
}
|
||||
|
||||
public void RefreshFlashiiBans() {
|
||||
FlashiiBan.GetList(bans => {
|
||||
if(!bans.Any())
|
||||
FlashiiBan.GetList(SockChatServer.HttpClient).ContinueWith(x => {
|
||||
if(x.IsFaulted) {
|
||||
Logger.Write($@"Ban Refresh: {x.Exception}");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!x.Result.Any())
|
||||
return;
|
||||
|
||||
lock(BanList) {
|
||||
foreach(FlashiiBan fb in bans) {
|
||||
foreach(FlashiiBan fb in x.Result) {
|
||||
if(!BanList.OfType<BannedUser>().Any(x => x.UserId == fb.UserId))
|
||||
Add(new BannedUser(fb));
|
||||
if(!BanList.OfType<BannedIPAddress>().Any(x => x.Address.ToString() == fb.UserIP))
|
||||
Add(new BannedIPAddress(fb));
|
||||
}
|
||||
}
|
||||
}, ex => Logger.Write($@"Ban Refresh: {ex}"));
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<IBan> All() {
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace SharpChat {
|
|||
Channels = new ChannelManager(this);
|
||||
Events = new ChatEventManager(this);
|
||||
|
||||
BumpTimer = new Timer(e => FlashiiBump.Submit(Users.WithActiveConnections()), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
|
||||
BumpTimer = new Timer(e => FlashiiBump.Submit(SockChatServer.HttpClient, Users.WithActiveConnections()), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace SharpChat {
|
|||
public ChatEventManager(ChatContext context) {
|
||||
Context = context;
|
||||
|
||||
if (!Database.HasDatabase)
|
||||
if (!Database.HasDatabase && !WebDatabase.IsAvailable)
|
||||
Events = new List<IChatEvent>();
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,9 @@ namespace SharpChat {
|
|||
lock(Events)
|
||||
Events.Add(evt);
|
||||
|
||||
if(WebDatabase.IsAvailable)
|
||||
WebDatabase.LogEvent(evt);
|
||||
|
||||
if(Database.HasDatabase)
|
||||
Database.LogEvent(evt);
|
||||
}
|
||||
|
@ -39,6 +42,9 @@ namespace SharpChat {
|
|||
lock (Events)
|
||||
Events.Remove(evt);
|
||||
|
||||
if(WebDatabase.IsAvailable)
|
||||
WebDatabase.DeleteEvent(evt);
|
||||
|
||||
if (Database.HasDatabase)
|
||||
Database.DeleteEvent(evt);
|
||||
|
||||
|
@ -49,6 +55,9 @@ namespace SharpChat {
|
|||
if (seqId < 1)
|
||||
return null;
|
||||
|
||||
if(WebDatabase.IsAvailable)
|
||||
return WebDatabase.GetEvent(seqId);
|
||||
|
||||
if (Database.HasDatabase)
|
||||
return Database.GetEvent(seqId);
|
||||
|
||||
|
@ -60,6 +69,9 @@ namespace SharpChat {
|
|||
}
|
||||
|
||||
public IEnumerable<IChatEvent> GetTargetLog(IPacketTarget target, int amount = 20, int offset = 0) {
|
||||
if(WebDatabase.IsAvailable)
|
||||
return WebDatabase.GetEvents(target, amount, offset);
|
||||
|
||||
if (Database.HasDatabase)
|
||||
return Database.GetEvents(target, amount, offset).Reverse();
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace SharpChat {
|
|||
public ChatChannel CurrentChannel { get; private set; }
|
||||
|
||||
public bool IsSilenced
|
||||
=> DateTimeOffset.UtcNow - SilencedUntil <= TimeSpan.Zero;
|
||||
=> SilencedUntil != null && DateTimeOffset.UtcNow - SilencedUntil <= TimeSpan.Zero;
|
||||
|
||||
public bool HasSessions {
|
||||
get {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using Hamakaze;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiAuthRequest {
|
||||
|
@ -47,13 +49,15 @@ namespace SharpChat.Flashii {
|
|||
[JsonPropertyName(@"perms")]
|
||||
public ChatUserPermissions Permissions { get; set; }
|
||||
|
||||
public static void Attempt(FlashiiAuthRequest authRequest, Action<FlashiiAuth> onComplete, Action<Exception> onError) {
|
||||
public static async Task<FlashiiAuth> Attempt(HttpClient httpClient, FlashiiAuthRequest authRequest) {
|
||||
if(httpClient == null)
|
||||
throw new ArgumentNullException(nameof(httpClient));
|
||||
if(authRequest == null)
|
||||
throw new ArgumentNullException(nameof(authRequest));
|
||||
|
||||
#if DEBUG
|
||||
if(authRequest.UserId >= 10000) {
|
||||
onComplete(new FlashiiAuth {
|
||||
if (authRequest.UserId >= 10000)
|
||||
return new FlashiiAuth {
|
||||
Success = true,
|
||||
UserId = authRequest.UserId,
|
||||
Username = @"Misaka-" + (authRequest.UserId - 10000),
|
||||
|
@ -61,21 +65,21 @@ namespace SharpChat.Flashii {
|
|||
Rank = 0,
|
||||
SilencedUntil = DateTimeOffset.MinValue,
|
||||
Permissions = ChatUserPermissions.SendMessage | ChatUserPermissions.EditOwnMessage | ChatUserPermissions.DeleteOwnMessage,
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
HttpRequestMessage hrm = new HttpRequestMessage(@"POST", FlashiiUrls.AUTH);
|
||||
hrm.AddHeader(@"X-SharpChat-Signature", authRequest.Hash);
|
||||
hrm.SetBody(authRequest.GetJSON());
|
||||
HttpClient.Send(hrm, (t, r) => {
|
||||
try {
|
||||
onComplete(JsonSerializer.Deserialize<FlashiiAuth>(r.GetBodyBytes()));
|
||||
} catch(Exception ex) {
|
||||
onError(ex);
|
||||
}
|
||||
}, (t, e) => onError(e));
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, FlashiiUrls.AUTH) {
|
||||
Content = new ByteArrayContent(authRequest.GetJSON()),
|
||||
Headers = {
|
||||
{ @"X-SharpChat-Signature", authRequest.Hash },
|
||||
},
|
||||
};
|
||||
|
||||
using HttpResponseMessage response = await httpClient.SendAsync(request);
|
||||
|
||||
return JsonSerializer.Deserialize<FlashiiAuth>(
|
||||
await response.Content.ReadAsByteArrayAsync()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using Hamakaze;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiBan {
|
||||
|
@ -20,21 +21,19 @@ namespace SharpChat.Flashii {
|
|||
[JsonPropertyName(@"username")]
|
||||
public string Username { get; set; }
|
||||
|
||||
public static void GetList(Action<IEnumerable<FlashiiBan>> onComplete, Action<Exception> onError) {
|
||||
if(onComplete == null)
|
||||
throw new ArgumentNullException(nameof(onComplete));
|
||||
if(onError == null)
|
||||
throw new ArgumentNullException(nameof(onError));
|
||||
public static async Task<IEnumerable<FlashiiBan>> GetList(HttpClient httpClient) {
|
||||
if(httpClient == null)
|
||||
throw new ArgumentNullException(nameof(httpClient));
|
||||
|
||||
HttpRequestMessage hrm = new HttpRequestMessage(@"GET", FlashiiUrls.BANS);
|
||||
hrm.AddHeader(@"X-SharpChat-Signature", STRING.GetSignedHash());
|
||||
HttpClient.Send(hrm, (t, r) => {
|
||||
try {
|
||||
onComplete(JsonSerializer.Deserialize<IEnumerable<FlashiiBan>>(r.GetBodyBytes()));
|
||||
} catch(Exception ex) {
|
||||
onError(ex);
|
||||
}
|
||||
}, (t, e) => onError(e));
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, FlashiiUrls.BANS) {
|
||||
Headers = {
|
||||
{ @"X-SharpChat-Signature", STRING.GetSignedHash() },
|
||||
},
|
||||
};
|
||||
|
||||
using HttpResponseMessage response = await httpClient.SendAsync(request);
|
||||
|
||||
return JsonSerializer.Deserialize<IEnumerable<FlashiiBan>>(await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using Hamakaze;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpChat.Flashii {
|
||||
public class FlashiiBump {
|
||||
|
@ -13,14 +14,16 @@ namespace SharpChat.Flashii {
|
|||
[JsonPropertyName(@"ip")]
|
||||
public string UserIP { get; set; }
|
||||
|
||||
public static void Submit(IEnumerable<ChatUser> users) {
|
||||
public static void Submit(HttpClient httpClient, IEnumerable<ChatUser> users) {
|
||||
List<FlashiiBump> bups = users.Where(u => u.HasSessions).Select(x => new FlashiiBump { UserId = x.UserId, UserIP = x.RemoteAddresses.First().ToString() }).ToList();
|
||||
|
||||
if(bups.Any())
|
||||
Submit(bups);
|
||||
if (bups.Any())
|
||||
Submit(httpClient, bups);
|
||||
}
|
||||
|
||||
public static void Submit(IEnumerable<FlashiiBump> users) {
|
||||
public static void Submit(HttpClient httpClient, IEnumerable<FlashiiBump> users) {
|
||||
if(httpClient == null)
|
||||
throw new ArgumentNullException(nameof(httpClient));
|
||||
if(users == null)
|
||||
throw new ArgumentNullException(nameof(users));
|
||||
if(!users.Any())
|
||||
|
@ -28,10 +31,17 @@ namespace SharpChat.Flashii {
|
|||
|
||||
byte[] data = JsonSerializer.SerializeToUtf8Bytes(users);
|
||||
|
||||
HttpRequestMessage hrm = new HttpRequestMessage(@"POST", FlashiiUrls.BUMP);
|
||||
hrm.AddHeader(@"X-SharpChat-Signature", data.GetSignedHash());
|
||||
hrm.SetBody(data);
|
||||
HttpClient.Send(hrm, onError: (t, e) => Logger.Write($@"Flashii Bump Error: {e}"));
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, FlashiiUrls.BUMP) {
|
||||
Content = new ByteArrayContent(data),
|
||||
Headers = {
|
||||
{ @"X-SharpChat-Signature", data.GetSignedHash() },
|
||||
}
|
||||
};
|
||||
|
||||
httpClient.SendAsync(request).ContinueWith(x => {
|
||||
if(x.IsFaulted)
|
||||
Logger.Write($@"Flashii Bump Error: {x.Exception}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using Hamakaze;
|
||||
using SharpChat.Flashii;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace SharpChat {
|
||||
|
@ -17,14 +19,66 @@ namespace SharpChat {
|
|||
Console.WriteLine(@"============================================ DEBUG ==");
|
||||
#endif
|
||||
|
||||
HttpClient.Instance.DefaultUserAgent = @"SharpChat/0.9";
|
||||
#if DEBUG
|
||||
Console.WriteLine(@"HOLD A KEY TO START A TEST NOW");
|
||||
Thread.Sleep(1000);
|
||||
if (Console.KeyAvailable)
|
||||
switch (Console.ReadKey(true).Key) {
|
||||
case ConsoleKey.F:
|
||||
TestMisuzuAuth();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Database.ReadConfig();
|
||||
WebDatabase.ReadConfig();
|
||||
if(!WebDatabase.IsAvailable)
|
||||
Database.ReadConfig();
|
||||
|
||||
using ManualResetEvent mre = new ManualResetEvent(false);
|
||||
using SockChatServer scs = new SockChatServer(PORT);
|
||||
Console.CancelKeyPress += (s, e) => { e.Cancel = true; mre.Set(); };
|
||||
mre.WaitOne();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private static void TestMisuzuAuth() {
|
||||
Console.WriteLine($@"Enter token found on {FlashiiUrls.BASE_URL}/login:");
|
||||
string[] token = Console.ReadLine().Split(new[] { '_' }, 2);
|
||||
|
||||
System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(@"SharpChat");
|
||||
|
||||
FlashiiAuth authRes = FlashiiAuth.Attempt(httpClient, new FlashiiAuthRequest {
|
||||
UserId = int.Parse(token[0]), Token = token[1], IPAddress = @"1.2.4.8"
|
||||
}).GetAwaiter().GetResult();
|
||||
|
||||
if(authRes.Success) {
|
||||
Console.WriteLine(@"Auth success!");
|
||||
Console.WriteLine($@" User ID: {authRes.UserId}");
|
||||
Console.WriteLine($@" Username: {authRes.Username}");
|
||||
Console.WriteLine($@" Colour: {authRes.ColourRaw:X8}");
|
||||
Console.WriteLine($@" Hierarchy: {authRes.Rank}");
|
||||
Console.WriteLine($@" Silenced: {authRes.SilencedUntil}");
|
||||
Console.WriteLine($@" Perms: {authRes.Permissions}");
|
||||
} else {
|
||||
Console.WriteLine($@"Auth failed: {authRes.Reason}");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine(@"Bumping last seen...");
|
||||
FlashiiBump.Submit(httpClient, new[] { new ChatUser(authRes) });
|
||||
|
||||
Console.WriteLine(@"Fetching ban list...");
|
||||
IEnumerable<FlashiiBan> bans = FlashiiBan.GetList(httpClient).GetAwaiter().GetResult();
|
||||
Console.WriteLine($@"{bans.Count()} BANS");
|
||||
foreach(FlashiiBan ban in bans) {
|
||||
Console.WriteLine($@"BAN INFO");
|
||||
Console.WriteLine($@" User ID: {ban.UserId}");
|
||||
Console.WriteLine($@" Username: {ban.Username}");
|
||||
Console.WriteLine($@" IP Address: {ban.UserIP}");
|
||||
Console.WriteLine($@" Expires: {ban.Expires}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,4 @@
|
|||
<PackageReference Include="MySqlConnector" Version="1.3.11" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Hamakaze\Hamakaze.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -8,6 +8,8 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpChat {
|
||||
|
@ -37,6 +39,8 @@ namespace SharpChat {
|
|||
public IWebSocketServer Server { get; }
|
||||
public ChatContext Context { get; }
|
||||
|
||||
public static HttpClient HttpClient { get; }
|
||||
|
||||
private IReadOnlyCollection<IChatCommand> Commands { get; } = new IChatCommand[] {
|
||||
new AFKCommand(),
|
||||
};
|
||||
|
@ -49,6 +53,12 @@ namespace SharpChat {
|
|||
return Sessions.FirstOrDefault(x => x.Connection == conn);
|
||||
}
|
||||
|
||||
static SockChatServer() {
|
||||
// "fuck it"
|
||||
HttpClient = new HttpClient();
|
||||
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(@"SharpChat");
|
||||
}
|
||||
|
||||
public SockChatServer(ushort port) {
|
||||
Logger.Write("Starting Sock Chat server...");
|
||||
|
||||
|
@ -162,11 +172,20 @@ namespace SharpChat {
|
|||
if(args.Length < 3 || !long.TryParse(args[1], out long aUserId))
|
||||
break;
|
||||
|
||||
FlashiiAuth.Attempt(new FlashiiAuthRequest {
|
||||
FlashiiAuth.Attempt(HttpClient, new FlashiiAuthRequest {
|
||||
UserId = aUserId,
|
||||
Token = args[2],
|
||||
IPAddress = sess.RemoteAddress.ToString(),
|
||||
}, auth => {
|
||||
}).ContinueWith(authTask => {
|
||||
if(authTask.IsFaulted) {
|
||||
Logger.Write($@"<{sess.Id}> Auth task fail: {authTask.Exception}");
|
||||
sess.Send(new AuthFailPacket(AuthFailReason.AuthInvalid));
|
||||
sess.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
FlashiiAuth auth = authTask.Result;
|
||||
|
||||
if(!auth.Success) {
|
||||
Logger.Debug($@"<{sess.Id}> Auth fail: {auth.Reason}");
|
||||
sess.Send(new AuthFailPacket(AuthFailReason.AuthInvalid));
|
||||
|
@ -214,10 +233,6 @@ namespace SharpChat {
|
|||
}
|
||||
|
||||
Context.HandleJoin(aUser, Context.Channels.DefaultChannel, sess);
|
||||
}, ex => {
|
||||
Logger.Write($@"<{sess.Id}> Auth task fail: {ex}");
|
||||
sess.Send(new AuthFailPacket(AuthFailReason.AuthInvalid));
|
||||
sess.Dispose();
|
||||
});
|
||||
break;
|
||||
|
||||
|
@ -529,7 +544,7 @@ namespace SharpChat {
|
|||
}
|
||||
|
||||
string createChanName = string.Join('_', parts.Skip(createChanHasHierarchy ? 2 : 1));
|
||||
ChatChannel createChan = new() {
|
||||
ChatChannel createChan = new ChatChannel {
|
||||
Name = createChanName,
|
||||
IsTemporary = !user.Can(ChatUserPermissions.SetChannelPermanent),
|
||||
Rank = createChanHierarchy,
|
||||
|
@ -816,14 +831,12 @@ namespace SharpChat {
|
|||
}
|
||||
|
||||
~SockChatServer()
|
||||
=> DoDispose();
|
||||
=> Dispose(false);
|
||||
|
||||
public void Dispose() {
|
||||
DoDispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
public void Dispose()
|
||||
=> Dispose(true);
|
||||
|
||||
private void DoDispose() {
|
||||
private void Dispose(bool disposing) {
|
||||
if(IsDisposed)
|
||||
return;
|
||||
IsDisposed = true;
|
||||
|
@ -831,6 +844,10 @@ namespace SharpChat {
|
|||
Sessions?.Clear();
|
||||
Server?.Dispose();
|
||||
Context?.Dispose();
|
||||
HttpClient?.Dispose();
|
||||
|
||||
if(disposing)
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
233
SharpChat/WebDatabase.cs
Normal file
233
SharpChat/WebDatabase.cs
Normal file
|
@ -0,0 +1,233 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue