From 7a157fdc5d696f9d10e0b8e9760bc2848327b87e Mon Sep 17 00:00:00 2001 From: JacobTech Date: Sat, 13 May 2023 16:44:21 -0400 Subject: [PATCH] Starting API One of the leading API requests has been added in an early form. So I can go back and make this code better. This is to get something to go off. --- LuskiServer/Classes/EXT.cs | 5 + LuskiServer/Classes/TableDef/Categories.cs | 4 +- LuskiServer/Classes/TableDef/Channels.cs | 28 ++-- LuskiServer/Classes/TableDef/Users.cs | 6 +- LuskiServer/Classes/WebTypes/File.cs | 21 +++ .../Classes/WebTypes/SocketBulkMessage.cs | 6 + LuskiServer/Classes/WebTypes/SocketMessage.cs | 10 ++ .../v1/SocketBulkMessageController.cs | 148 ++++++++++++++++++ LuskiServer/LuskiServer.csproj | 4 +- 9 files changed, 214 insertions(+), 18 deletions(-) create mode 100644 LuskiServer/Classes/WebTypes/File.cs create mode 100644 LuskiServer/Classes/WebTypes/SocketBulkMessage.cs create mode 100644 LuskiServer/Classes/WebTypes/SocketMessage.cs create mode 100644 LuskiServer/Controllers/v1/SocketBulkMessageController.cs diff --git a/LuskiServer/Classes/EXT.cs b/LuskiServer/Classes/EXT.cs index 1ef47bf..403fa30 100644 --- a/LuskiServer/Classes/EXT.cs +++ b/LuskiServer/Classes/EXT.cs @@ -51,6 +51,11 @@ public static class EXT return Base.ShowError(ErrorCode.ServerError, Error.Message); } + + public static IActionResult ResponseToResult(this ControllerBase Base, TResult Result) where TResult : HTTPResponse + { + return Base.StatusCode(StatusCodes.Status200OK, Result); + } public static IActionResult ShowError(this ControllerBase Base, ErrorCode code, string Error) { diff --git a/LuskiServer/Classes/TableDef/Categories.cs b/LuskiServer/Classes/TableDef/Categories.cs index ad80f30..20867c4 100644 --- a/LuskiServer/Classes/TableDef/Categories.cs +++ b/LuskiServer/Classes/TableDef/Categories.cs @@ -5,8 +5,8 @@ namespace LuskiServer.Classes.TableDef; public static class Categories { public static TableColumn ID { get; } = new("id", true); - public static TableColumn Name { get; } = new("name"); - public static TableColumn Description { get; } = new("description"); + public static TableColumn Name { get; } = new("name") { DefaultValue = "New Category"}; + public static TableColumn Description { get; } = new("description") { DefaultValue = "Default Description"}; public static TableColumn InnerCategories { get; } = new("inner_categories") { DefaultValue = Array.Empty() }; public static TableColumn Channels { get; } = new("channels") { DefaultValue = Array.Empty() }; public static TableColumn RoleOverides { get; } = new("role_overides") { DefaultValue = Array.Empty() }; diff --git a/LuskiServer/Classes/TableDef/Channels.cs b/LuskiServer/Classes/TableDef/Channels.cs index bb4f332..f6a8ad3 100644 --- a/LuskiServer/Classes/TableDef/Channels.cs +++ b/LuskiServer/Classes/TableDef/Channels.cs @@ -1,3 +1,4 @@ +using System.Text; using JacobTechEncryption.Enums; using LuskiServer.Enums; using ServerDatabase; @@ -9,15 +10,20 @@ public static class Channels public static TableColumn ID { get; } = new("id", true); public static TableColumn Type { get; } = new("type"); public static TableColumn Epoch { get; } = new("epoch"); - public static TableColumn Name { get; } = new("name"); - public static TableColumn Description { get; } = new("description"); - public static TableColumn Key { get; } = new("key"); - public static TableColumn RoleOverides { get; } = new("role_overides"); - public static TableColumn UserOverides { get; } = new("member_overides"); - public static TableColumn TitleEncryptionType { get; } = new("title_encryption_type"); - public static TableColumn DescriptionEncryptionType { get; } = new("description_encryption_type"); - public static TableColumn AllowedEncryptionTypes { get; } = new("allowed_encryption_types"); - public static TableColumn TitleEncoderType { get; } = new("title_encoder_type"); - public static TableColumn DescriptionEncoderType { get; } = new("description_encoder_type"); - public static TableColumn AllowedEncoderTypes { get; } = new("allowed_encoder_types"); + public static TableColumn Name { get; } = new("name") { DefaultValue = Encoding.UTF8.GetBytes("New Channel") }; + public static TableColumn Description { get; } = new("description") { DefaultValue = Encoding.UTF8.GetBytes("New Channel") }; + public static TableColumn Key { get; } = new("key") { DefaultValue = string.Empty }; + public static TableColumn RoleOverides { get; } = new("role_overides") { DefaultValue = Array.Empty() }; + public static TableColumn UserOverides { get; } = new("member_overides") { DefaultValue = Array.Empty() }; + public static TableColumn TitleEncryptionType { get; } = new("title_encryption_type") { DefaultValue = EncryptionType.None }; + public static TableColumn DescriptionEncryptionType { get; } = new("description_encryption_type") { DefaultValue = EncryptionType.None }; + public static TableColumn AllowedEncryptionTypes { get; } = new("allowed_encryption_types") { DefaultValue = new [] { EncryptionType.RSA } }; + public static TableColumn TitleEncoderType { get; } = new("title_encoder_type") { DefaultValue = EncoderType.UTF8 }; + public static TableColumn DescriptionEncoderType { get; } = new("description_encoder_type") { DefaultValue = EncoderType.UTF8 }; + public static TableColumn AllowedEncoderTypes { get; } = new("allowed_encoder_types") { DefaultValue = new [] + { + EncoderType.UTF8, EncoderType.UTF16, + EncoderType.UTF32, EncoderType.ASCII, + EncoderType.Latin1, EncoderType.BigEndianUnicode + } }; } \ No newline at end of file diff --git a/LuskiServer/Classes/TableDef/Users.cs b/LuskiServer/Classes/TableDef/Users.cs index 3b3e111..bf553bf 100644 --- a/LuskiServer/Classes/TableDef/Users.cs +++ b/LuskiServer/Classes/TableDef/Users.cs @@ -8,8 +8,8 @@ public class Users public static TableColumn ID { get; } = new("id", true); public static TableColumn DisplayName { get; } = new("displayname"); public static TableColumn SelectedChannel { get; } = new("selected_channel"); - public static TableColumn Status { get; } = new("status"); - public static TableColumn PictureType { get; } = new("picture_type"); + public static TableColumn Status { get; } = new("status") { DefaultValue = Enums.Status.Offline }; + public static TableColumn PictureType { get; } = new("picture_type") {DefaultValue = Enums.PictureType.png }; public static TableColumn Picture { get; } = new("picture"); public static TableColumn Roles { get; } = new("roles"); public static TableColumn Username { get; } = new("username"); @@ -20,5 +20,5 @@ public class Users public static TableColumn WSSTCP { get; } = new("wsstcp"); public static TableColumn Token { get; } = new("token"); public static TableColumn OfflineData { get; } = new("offline_data"); - public static TableColumn OffileKey { get; } = new("offline_key"); + public static TableColumn OffileKey { get; } = new("offline_key") {DefaultValue = string.Empty}; } \ No newline at end of file diff --git a/LuskiServer/Classes/WebTypes/File.cs b/LuskiServer/Classes/WebTypes/File.cs new file mode 100644 index 0000000..020e145 --- /dev/null +++ b/LuskiServer/Classes/WebTypes/File.cs @@ -0,0 +1,21 @@ +using System.Security.Cryptography; +using JacobTechEncryption; + +namespace LuskiServer.Classes.WebTypes; + +public class File +{ + public string name { get; set; } = default!; + public string[] data { get; set; } = default!; + public ulong? size { get; set; } = default!; + public long? id { get; set; } = default!; + + internal void decrypt(RSAParameters key, string outkey) + { + if (name != null) name = Convert.ToBase64String(Encryption.RSA.Encrypt(Encryption.RSA.Decrypt(Convert.FromBase64String(name), key), outkey)); + //for (int i = 0; i < data.Count(); i++) + // { + // data[i] = Convert.ToBase64String(Encryption.Encrypt(Encryption.Decrypt(Convert.FromBase64String(data[i]), key), outkey)); + //} + } +} \ No newline at end of file diff --git a/LuskiServer/Classes/WebTypes/SocketBulkMessage.cs b/LuskiServer/Classes/WebTypes/SocketBulkMessage.cs new file mode 100644 index 0000000..818377b --- /dev/null +++ b/LuskiServer/Classes/WebTypes/SocketBulkMessage.cs @@ -0,0 +1,6 @@ +namespace LuskiServer.Classes.WebTypes; + +public class SocketBulkMessage : HTTPResponse +{ + public SocketMessage[] messages { get; set; } = default!; +} \ No newline at end of file diff --git a/LuskiServer/Classes/WebTypes/SocketMessage.cs b/LuskiServer/Classes/WebTypes/SocketMessage.cs new file mode 100644 index 0000000..92cc039 --- /dev/null +++ b/LuskiServer/Classes/WebTypes/SocketMessage.cs @@ -0,0 +1,10 @@ +namespace LuskiServer.Classes.WebTypes; + +public class SocketMessage : HTTPResponse +{ + public long channel_id { get; set; } = default!; + public long user_id { get; set; } = default!; + public long id { get; set; } = default!; + public string content { get; set; } = default!; + public File[] files { get; set; } = default!; +} \ No newline at end of file diff --git a/LuskiServer/Controllers/v1/SocketBulkMessageController.cs b/LuskiServer/Controllers/v1/SocketBulkMessageController.cs new file mode 100644 index 0000000..71a6d7d --- /dev/null +++ b/LuskiServer/Controllers/v1/SocketBulkMessageController.cs @@ -0,0 +1,148 @@ +using Asp.Versioning; +using JacobTechEncryption; +using JacobTechEncryption.Enums; +using LuskiServer.Classes; +using LuskiServer.Classes.TableDef; +using LuskiServer.Classes.WebTypes; +using LuskiServer.Enums; +using Microsoft.AspNetCore.Mvc; +using ServerDatabase; + +namespace LuskiServer.Controllers.v1; + +[ApiVersion(1)] +[ApiController] +public class SocketBulkMessageController : ControllerBase +{ + [HttpGet] + public IActionResult Get() + { + try + { + if (!this.CanTokenRequest(out long ID, out IActionResult? toc) && toc != null) return toc; + if (!Request.Headers.ContainsKey("id")) return this.ShowError(ErrorCode.MissingHeader, "You did not give an channel id for the channel you want to get a message from"); + string channel_id = Request.Headers["id"].First(); + long MessagesToDownload = 50; + long Max = 200; + if (long.TryParse(channel_id, out long Channel_Id) && !Tables.Channels.TryRead(Channels.ID, out _, Channels.ID.CreateParameter(Channel_Id))) return this.ShowError(ErrorCode.InvalidHeader, "The the channel id you have given the server is not a valed id"); + //This needs to be added but using the new permission system. + //if (!Luski.HasAccessToChannel(ID, Channel_Id)) return this.ShowError(ErrorCode.Forbidden); + if (Request.Headers.ContainsKey("messages")) _ = long.TryParse(Request.Headers["messages"].First(), out MessagesToDownload); + if (MessagesToDownload > Max) MessagesToDownload = Max; + string? MostRecentID = null; + string sign = "<"; + if (!Request.Headers.ContainsKey("mostrecentid") || !long.TryParse(MostRecentID = Request.Headers["mostrecentid"].First(), out long mrid) || !Tables.Messages.TryRead(Messages.ID, out _, Messages.ID.CreateParameter(mrid), Messages.ChannelID.CreateParameter(Channel_Id))) + { + try + { + bool HasMRID = Tables.Messages.TryRead(Messages.ID, new Order() { Assending = false, Type = Messages.TimeStamp.Name }, out long MRID, Messages.ChannelID.CreateParameter(Channel_Id)); + Console.WriteLine(MRID); + if (HasMRID) + { + MostRecentID = MRID.ToString(); + sign += "="; + } + } + catch + { + return this.ResponseToResult( + new SocketBulkMessage() + { + messages = Array.Empty() + }); + } + } + SocketBulkMessage all = new(); + ///StartDatabse(MessagesToDownload, Channel_Id, MostRecentID, sign, out SocketMessage[]? mmm); + SocketMessage[]? mmm = null; + if (MostRecentID != null) + { + var con2 = Luski.Database.CreateConnection(); + con2.Open(); + var cmd2 = con2.CreateCommand(); + Console.WriteLine($"SELECT context,author_id,message_id,files FROM messages WHERE ts {sign} '{new Luski.Snowflake(long.Parse(MostRecentID)).Timestamp}' AND channel_id = '{Channel_Id}' ORDER BY ts DESC LIMIT {MessagesToDownload};"); + cmd2.CommandText = $"SELECT context,author_id,message_id,files FROM messages WHERE ts {sign} '{new Luski.Snowflake(long.Parse(MostRecentID)).Timestamp}' AND channel_id = '{Channel_Id}' ORDER BY ts DESC LIMIT {MessagesToDownload};"; + var reader2 = cmd2.ExecuteReader(); + //Loop(Messages, Channel_Id, out mmm, reader); + long current = 0; + var mmmm = new List(); + while (reader2.Read()) + { + current++; + if (current <= MessagesToDownload) + { + SocketMessage Current = new(); + //ReadRow(Channel_Id, reader, ref mmm); + Current.channel_id = Channel_Id; + int i2 = 0; + while (i2 < reader2.FieldCount) + { + //ReadCollume(reader.GetValue(i), ref msg, reader.GetName(i)); + string name = reader2.GetName(i2); + object val = reader2.GetValue(i2); + if (name == "context") Current.content = Convert.ToBase64String((byte[])val); + else if (name == "author_id") Current.user_id = long.Parse(val.ToString()); + else if (name == "message_id") Current.id = long.Parse(val.ToString()); + else if (name == "files") + { + if (val is not DBNull) + { + if ((long[]?)val is not null && ((long[])val).Length > 0) + { + List list = new(); + foreach (long b in (long[])val) + { + var con = Luski.Database.CreateConnection(); + con.Open(); + var cmd = con.CreateCommand(); + cmd.CommandText = $"SELECT name,size FROM files WHERE id = '{b}';"; + var reader = cmd.ExecuteReader(); + int i3 = 0; + Classes.WebTypes.File file = new() + { + data = null!, + id = b + }; + while (reader.Read()) + { + while (i3 < reader.FieldCount) + { + //ReadFileCollume(reader.GetValue(i), ref file, reader.GetName(i)); + string name2 = reader2.GetName(i3); + object val2 = reader2.GetValue(i3); + if (name2 == "name") file.name = Convert.ToBase64String((byte[])val2); + else if (name2 == "size") file.size = ulong.Parse(val2.ToString()); + else; + i3++; + } + if (i3 >= reader.FieldCount) break; + } + + list.Add(file); + con.Close(); + } + Current.files = list.ToArray(); + } + } + } + i2++; + } + if (mmm == null) break; + mmmm.Add(Current); + } + else break; + } + mmm = mmmm.ToArray(); + con2.Close(); + } + + if (mmm is not null) all.messages = mmm; + else all.messages = Array.Empty(); + return this.ResponseToResult(all); + } + catch (Exception ex) + { + return this.ShowError(ex); + } + } +} \ No newline at end of file diff --git a/LuskiServer/LuskiServer.csproj b/LuskiServer/LuskiServer.csproj index b455079..bd75fa3 100644 --- a/LuskiServer/LuskiServer.csproj +++ b/LuskiServer/LuskiServer.csproj @@ -19,10 +19,10 @@ - + - +