From 106d0d60787ab8a0407fbc56764c0021c241e0ae Mon Sep 17 00:00:00 2001 From: JacobTech Date: Mon, 3 Jul 2023 23:24:35 -0400 Subject: [PATCH] Migration starts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • A lot of work needs to be done to make sure this works. • I already know this push won't work, but it will build. • I need to come up with a new way of storing local info. This will also bee needed to fix the very broken key system in this rushed commit. --- Luski.net.sln | 6 - Luski.net/API.cs | 36 ++ .../{Encryption.cs => ClientEncryption.cs} | 104 +++-- Luski.net/Enums/Branch.cs | 8 - Luski.net/Enums/DataType.cs | 2 +- Luski.net/Enums/{ => Main}/ChannelType.cs | 2 +- Luski.net/Enums/{ => Main}/FriendStatus.cs | 2 +- Luski.net/Enums/{ => Main}/UserFlag.cs | 2 +- Luski.net/Enums/Public/ChannelType.cs | 6 + Luski.net/Enums/ServerType.cs | 9 + Luski.net/Interfaces/IAppUser.cs | 11 + Luski.net/Interfaces/IAudioClient.cs | 48 -- Luski.net/Interfaces/IChannel.cs | 32 -- Luski.net/Interfaces/IServer.cs | 38 ++ Luski.net/Interfaces/IUser.cs | 23 +- Luski.net/Interfaces/IWebRequest.cs | 6 + Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs | 3 +- Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs | 4 +- .../JsonTypes/BaseTypes/SocketUserBase.cs | 118 ----- Luski.net/JsonTypes/HTTP/FriendRequest.cs | 12 +- Luski.net/JsonTypes/OfflineData.cs | 21 + Luski.net/JsonTypes/SocketAppUser.cs | 178 -------- Luski.net/JsonTypes/SocketDMChannel.cs | 33 -- Luski.net/Luski.net.csproj | 10 +- Luski.net/Server.Account.cs | 174 ++++++++ Luski.net/Server.Cleanup.cs | 17 - Luski.net/Server.Constructors.cs | 129 ------ Luski.net/Server.CreateAccount.cs | 93 ---- Luski.net/Server.Events.cs | 17 +- Luski.net/Server.Globals.cs | 76 ++-- Luski.net/Server.Incoming.cs | 83 ++-- Luski.net/Server.Login.cs | 12 - Luski.net/Server.cs | 359 +++++++-------- Luski.net/Server.old.Globals.cs | 97 ++++ Luski.net/Server.old.cs | 281 ++++++++++++ Luski.net/Sockets/SocketAudioClient.cs | 388 ---------------- Luski.net/Sound/Devices.cs | 58 --- Luski.net/Sound/JitterBuffer.cs | 124 ------ Luski.net/Sound/Player.cs | 417 ------------------ Luski.net/Sound/Protocol.cs | 95 ---- Luski.net/Sound/RTPPacket.cs | 139 ------ Luski.net/Sound/Recorder.cs | 340 -------------- Luski.net/Sound/Timer.cs | 64 --- Luski.net/Sound/Utils.cs | 195 -------- Luski.net/Sound/WaveFile.cs | 104 ----- Luski.net/Sound/Win32.cs | 241 ---------- Luski.net/Sound/WinSound.cs | 94 ---- Luski.net/{JsonTypes => Structures}/File.cs | 32 +- .../Structures/Main/MainSocketAppUser.cs | 194 ++++++++ .../Main/MainSocketChannel.cs} | 97 ++-- .../Structures/Main/MainSocketDMChannel.cs | 34 ++ .../Main/MainSocketGroupChannel.cs} | 8 +- .../Main/MainSocketRemoteUser.cs} | 16 +- .../Main/MainSocketTextChannel.cs} | 58 ++- .../Structures/Public/PublicSocketAppUser.cs | 35 ++ .../SocketBulkMessage.cs | 3 +- .../SocketMessage.cs | 45 +- Luski.net/Structures/SocketUserBase.cs | 53 +++ 58 files changed, 1428 insertions(+), 3458 deletions(-) create mode 100644 Luski.net/API.cs rename Luski.net/{Encryption.cs => ClientEncryption.cs} (88%) delete mode 100755 Luski.net/Enums/Branch.cs rename Luski.net/Enums/{ => Main}/ChannelType.cs (61%) rename Luski.net/Enums/{ => Main}/FriendStatus.cs (71%) rename Luski.net/Enums/{ => Main}/UserFlag.cs (79%) create mode 100755 Luski.net/Enums/Public/ChannelType.cs create mode 100644 Luski.net/Enums/ServerType.cs create mode 100644 Luski.net/Interfaces/IAppUser.cs delete mode 100755 Luski.net/Interfaces/IAudioClient.cs delete mode 100755 Luski.net/Interfaces/IChannel.cs create mode 100644 Luski.net/Interfaces/IServer.cs create mode 100644 Luski.net/Interfaces/IWebRequest.cs delete mode 100755 Luski.net/JsonTypes/BaseTypes/SocketUserBase.cs create mode 100644 Luski.net/JsonTypes/OfflineData.cs delete mode 100755 Luski.net/JsonTypes/SocketAppUser.cs delete mode 100755 Luski.net/JsonTypes/SocketDMChannel.cs create mode 100644 Luski.net/Server.Account.cs delete mode 100755 Luski.net/Server.Cleanup.cs delete mode 100755 Luski.net/Server.Constructors.cs delete mode 100755 Luski.net/Server.CreateAccount.cs mode change 100755 => 100644 Luski.net/Server.Events.cs mode change 100755 => 100644 Luski.net/Server.Globals.cs mode change 100755 => 100644 Luski.net/Server.Incoming.cs delete mode 100755 Luski.net/Server.Login.cs mode change 100755 => 100644 Luski.net/Server.cs create mode 100755 Luski.net/Server.old.Globals.cs create mode 100755 Luski.net/Server.old.cs delete mode 100755 Luski.net/Sockets/SocketAudioClient.cs delete mode 100755 Luski.net/Sound/Devices.cs delete mode 100755 Luski.net/Sound/JitterBuffer.cs delete mode 100755 Luski.net/Sound/Player.cs delete mode 100755 Luski.net/Sound/Protocol.cs delete mode 100755 Luski.net/Sound/RTPPacket.cs delete mode 100755 Luski.net/Sound/Recorder.cs delete mode 100755 Luski.net/Sound/Timer.cs delete mode 100755 Luski.net/Sound/Utils.cs delete mode 100755 Luski.net/Sound/WaveFile.cs delete mode 100755 Luski.net/Sound/Win32.cs delete mode 100755 Luski.net/Sound/WinSound.cs rename Luski.net/{JsonTypes => Structures}/File.cs (76%) create mode 100755 Luski.net/Structures/Main/MainSocketAppUser.cs rename Luski.net/{JsonTypes/SocketChannel.cs => Structures/Main/MainSocketChannel.cs} (51%) create mode 100755 Luski.net/Structures/Main/MainSocketDMChannel.cs rename Luski.net/{JsonTypes/SocketGroupChannel.cs => Structures/Main/MainSocketGroupChannel.cs} (59%) rename Luski.net/{JsonTypes/SocketRemoteUser.cs => Structures/Main/MainSocketRemoteUser.cs} (60%) rename Luski.net/{JsonTypes/SocketTextChannel.cs => Structures/Main/MainSocketTextChannel.cs} (71%) create mode 100755 Luski.net/Structures/Public/PublicSocketAppUser.cs rename Luski.net/{JsonTypes => Structures}/SocketBulkMessage.cs (89%) rename Luski.net/{JsonTypes => Structures}/SocketMessage.cs (50%) create mode 100644 Luski.net/Structures/SocketUserBase.cs diff --git a/Luski.net.sln b/Luski.net.sln index f68549b..4c1e359 100755 --- a/Luski.net.sln +++ b/Luski.net.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.0.31717.71 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luski.net", "Luski.net\Luski.net.csproj", "{3DF9B870-51B3-4338-84EC-75E4B8802F0C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luski.net.tests", "Luski.net.tests\Luski.net.tests.csproj", "{FCA149C8-379B-454A-962A-856F30965C4E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -17,10 +15,6 @@ Global {3DF9B870-51B3-4338-84EC-75E4B8802F0C}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DF9B870-51B3-4338-84EC-75E4B8802F0C}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DF9B870-51B3-4338-84EC-75E4B8802F0C}.Release|Any CPU.Build.0 = Release|Any CPU - {FCA149C8-379B-454A-962A-856F30965C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FCA149C8-379B-454A-962A-856F30965C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FCA149C8-379B-454A-962A-856F30965C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FCA149C8-379B-454A-962A-856F30965C4E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Luski.net/API.cs b/Luski.net/API.cs new file mode 100644 index 0000000..a6c87f0 --- /dev/null +++ b/Luski.net/API.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using Luski.net.Structures.Main; +using Luski.net.Structures.Public; + +namespace Luski.net; + +public class API +{ + public Server MainServer { get; internal set; } + internal List> InternalServers { get; } = new(); + public IReadOnlyList> LoadedServers => InternalServers.AsReadOnly(); + + public Server GetPublicServer(string Domain, string Version = "v1") + { + IEnumerable> isl = InternalServers.Where(a => (a.Domain == Domain && a.ApiVersion == Version)); + if (isl.Any()) return isl.First(); + Server s = new() + { + Domain = Domain, + ApiVersion = Version, + }; + InternalServers.Add(s); + return s; + } + + public Server GetMainServer(string Domain, string Version = "v1") + { + MainServer = new() + { + Domain = Domain, + ApiVersion = Version, + }; + return MainServer; + } +} \ No newline at end of file diff --git a/Luski.net/Encryption.cs b/Luski.net/ClientEncryption.cs similarity index 88% rename from Luski.net/Encryption.cs rename to Luski.net/ClientEncryption.cs index 8d62272..4d86d68 100755 --- a/Luski.net/Encryption.cs +++ b/Luski.net/ClientEncryption.cs @@ -3,15 +3,16 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Text.Json; -using System.Threading.Tasks; +using JacobTechEncryption; namespace Luski.net { - public static class Encryption + public static class ClientEncryption { internal static string? MyPublicKey; internal static readonly UnicodeEncoding Encoder = new(); @@ -23,15 +24,7 @@ namespace Luski.net internal static string? outofkey = null; internal static string pw = ""; public static int NewKeySize = 4096; - internal static string ServerPublicKey - { - get - { - if (_serverpublickey is null) _serverpublickey = new HttpClient().GetAsync($"https://{Server.InternalDomain}/{Server.API_Ver}/Keys/PublicKey").Result.Content.ReadAsStringAsync().Result; - return _serverpublickey; - } - } - + public static void GenerateKeys() { if (!Generating) @@ -43,7 +36,7 @@ namespace Luski.net } } - internal static void GenerateNewKeys(out string Public, out string Private) + public static void GenerateNewKeys(out string Public, out string Private) { using RSACryptoServiceProvider r = new(NewKeySize); Private = r.ToXmlString(true); @@ -55,16 +48,22 @@ namespace Luski.net { internal static void SetOfflineKey(string key) { - MakeFile(Server.GetKeyFilePath, pw); - LuskiDataFile? fileLayout = JsonSerializer.Deserialize(FileString(Server.GetKeyFilePath, pw)); + MakeFile("Server.GetKeyFilePath", pw); + LuskiDataFile? fileLayout = JsonSerializer.Deserialize(FileString("Server.GetKeyFilePath", pw)); fileLayout.OfflineKey = key; - fileLayout.Save(Server.GetKeyFilePath, pw); + fileLayout.Save("Server.GetKeyFilePath", pw); + } + + public static LuskiDataFile GetFile() + { + MakeFile("Server.GetKeyFilePath", pw); + return JsonSerializer.Deserialize(FileString("Server.GetKeyFilePath", pw))!; } internal static string? GetOfflineKey() { - MakeFile(Server.GetKeyFilePath, pw); - LuskiDataFile? fileLayout = JsonSerializer.Deserialize(FileString(Server.GetKeyFilePath, pw)); + MakeFile("Server.GetKeyFilePath", pw); + LuskiDataFile? fileLayout = JsonSerializer.Deserialize(FileString("Server.GetKeyFilePath", pw)); return fileLayout?.OfflineKey; } @@ -122,32 +121,13 @@ namespace Luski.net #pragma warning disable CS8603 // Possible null reference return. if (channel == 0) return myPrivateKey; #pragma warning restore CS8603 // Possible null reference return. - MakeFile(Server.GetKeyFilePath, pw); - fileLayout = JsonSerializer.Deserialize(FileString(Server.GetKeyFilePath, pw)); + MakeFile("Server.GetKeyFilePath", pw); + fileLayout = JsonSerializer.Deserialize(FileString("Server.GetKeyFilePath", pw)); lis = fileLayout?.channels?.Where(s => s.id == channel); if (lis?.Count() > 0) { return lis.First().key; } - foreach (Branch b in (Branch[])Enum.GetValues(typeof(Branch))) - { - if (b != Server.Branch) - { - try - { - string temp = GetKeyBranch(channel, b); - if (temp is not null) - { - AddKey(channel, temp); - return temp; - } - } - catch - { - - } - } - } throw new Exception("You dont have a key for that channel"); } finally @@ -157,7 +137,7 @@ namespace Luski.net } } - internal static string GetKeyBranch(long channel, Branch branch) + internal static string GetKeyBranch(long channel) { LuskiDataFile? fileLayout; IEnumerable? lis; @@ -166,8 +146,8 @@ namespace Luski.net #pragma warning disable CS8603 // Possible null reference return. if (channel == 0) return myPrivateKey; #pragma warning restore CS8603 // Possible null reference return. - MakeFile(Server.GetKeyFilePathBr(branch.ToString()), pw); - fileLayout = JsonSerializer.Deserialize(FileString(Server.GetKeyFilePathBr(branch.ToString()), pw)); + MakeFile("Server.GetKeyFilePathBr(branch.ToString())", pw); + fileLayout = JsonSerializer.Deserialize(FileString("", pw)); lis = fileLayout?.channels?.Where(s => s.id == channel); if (lis?.Count() > 0) { @@ -184,10 +164,10 @@ namespace Luski.net public static void AddKey(long channel, string key) { - MakeFile(Server.GetKeyFilePath, pw); - LuskiDataFile? fileLayout = JsonSerializer.Deserialize(FileString(Server.GetKeyFilePath, pw)); + MakeFile("Server.GetKeyFilePath", pw); + LuskiDataFile? fileLayout = JsonSerializer.Deserialize(FileString("Server.GetKeyFilePath", pw)); fileLayout?.Addchannelkey(channel, key); - fileLayout?.Save(Server.GetKeyFilePath, pw); + fileLayout?.Save("Server.GetKeyFilePath", pw); } } @@ -210,9 +190,9 @@ namespace Luski.net internal static LuskiDataFile GetDefualtDataFile() { - return GetDataFile(Server.GetKeyFilePath, pw); + return GetDataFile("Server.GetKeyFilePath", pw); } - + public ChannelLayout[]? channels { get; set; } = default!; public string? OfflineKey { get; set; } = default!; @@ -273,6 +253,17 @@ namespace Luski.net chans?.Add(l); channels = chans?.ToArray(); } + else + { + chans.Remove(chans.Where(s => s.id == chan).First()); + ChannelLayout l = new() + { + id = chan, + key = Key + }; + chans?.Add(l); + channels = chans?.ToArray(); + } } } @@ -282,7 +273,7 @@ namespace Luski.net public string key { get; set; } = default!; } } - + /* public class AES { public static string Encrypt(string path, string Password) @@ -353,7 +344,7 @@ namespace Luski.net cs.Dispose(); fsCrypt.Close(); fsCrypt.Dispose(); - NewPath = p;*/ + NewPath = p; } public static void Decrypt(byte[] data, string Password, string File) @@ -387,7 +378,7 @@ namespace Luski.net fsOut.Dispose(); } } - +*/ internal const int PasswordVersion = 0; internal static byte[] LocalPasswordEncrypt(byte[] Password, int PasswordVersion = PasswordVersion) @@ -403,10 +394,15 @@ namespace Luski.net { return PasswordVersion switch { - 0 => Convert.ToBase64String(Encrypt(LocalPasswordEncrypt(Password, PasswordVersion))), + 0 => Convert.ToBase64String(Encryption.RSA.Encrypt(LocalPasswordEncrypt(Password, PasswordVersion), MyPublicKey)), _ => throw new ArgumentException("The value provided was not accepted", nameof(PasswordVersion)), }; } +/* + public static byte[] Hash(byte[] data) + { + return SHA256.Create().ComputeHash(data); + } internal static byte[] Encrypt(string data) { @@ -427,7 +423,7 @@ namespace Luski.net { using RSACryptoServiceProvider rsa = new(); rsa.FromXmlString(key); - int size = rsa.KeySize / 8; + int size = ((rsa.KeySize - 384) / 8) + 7; double x = data.Length / (double)size; int bbb = int.Parse(x.ToString().Split('.')[0]); if (x.ToString().Contains('.')) bbb++; @@ -443,7 +439,7 @@ namespace Luski.net MaxDegreeOfParallelism = num }, i => { - decccc[i] = rsa.Encrypt(data.Skip(i * size).Take(size).ToArray(), false); + decccc[i] = rsa.Encrypt(data.Skip(i * size).Take(size).ToArray(), true); }); foreach (byte[] dataa in decccc) { @@ -495,7 +491,7 @@ namespace Luski.net MaxDegreeOfParallelism = num }, i => { - decccc[i] = rsa.Decrypt(EncryptedText.Skip(i * size).Take(size).ToArray(), false); + decccc[i] = rsa.Decrypt(EncryptedText.Skip(i * size).Take(size).ToArray(), true); }); foreach (byte[] data in decccc) { @@ -510,6 +506,6 @@ namespace Luski.net } } return datasplitout; - } + }*/ } } diff --git a/Luski.net/Enums/Branch.cs b/Luski.net/Enums/Branch.cs deleted file mode 100755 index ccc27b3..0000000 --- a/Luski.net/Enums/Branch.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Luski.net.Enums; - -public enum Branch : short -{ - Dev, - Beta, - Master, -} diff --git a/Luski.net/Enums/DataType.cs b/Luski.net/Enums/DataType.cs index ff8ca21..37dea2a 100755 --- a/Luski.net/Enums/DataType.cs +++ b/Luski.net/Enums/DataType.cs @@ -1,6 +1,6 @@ namespace Luski.net.Enums; -internal enum DataType +public enum DataType { Message_Create, Status_Update, diff --git a/Luski.net/Enums/ChannelType.cs b/Luski.net/Enums/Main/ChannelType.cs similarity index 61% rename from Luski.net/Enums/ChannelType.cs rename to Luski.net/Enums/Main/ChannelType.cs index c2bf1c5..09fe9c0 100755 --- a/Luski.net/Enums/ChannelType.cs +++ b/Luski.net/Enums/Main/ChannelType.cs @@ -1,4 +1,4 @@ -namespace Luski.net.Enums; +namespace Luski.net.Enums.Main; public enum ChannelType : short { diff --git a/Luski.net/Enums/FriendStatus.cs b/Luski.net/Enums/Main/FriendStatus.cs similarity index 71% rename from Luski.net/Enums/FriendStatus.cs rename to Luski.net/Enums/Main/FriendStatus.cs index 1651479..75aad9b 100755 --- a/Luski.net/Enums/FriendStatus.cs +++ b/Luski.net/Enums/Main/FriendStatus.cs @@ -1,4 +1,4 @@ -namespace Luski.net.Enums; +namespace Luski.net.Enums.Main; public enum FriendStatus { diff --git a/Luski.net/Enums/UserFlag.cs b/Luski.net/Enums/Main/UserFlag.cs similarity index 79% rename from Luski.net/Enums/UserFlag.cs rename to Luski.net/Enums/Main/UserFlag.cs index d4d0a35..aa1378a 100755 --- a/Luski.net/Enums/UserFlag.cs +++ b/Luski.net/Enums/Main/UserFlag.cs @@ -1,6 +1,6 @@ using System; -namespace Luski.net.Enums; +namespace Luski.net.Enums.Main; [Flags] public enum UserFlag : short diff --git a/Luski.net/Enums/Public/ChannelType.cs b/Luski.net/Enums/Public/ChannelType.cs new file mode 100755 index 0000000..e52037b --- /dev/null +++ b/Luski.net/Enums/Public/ChannelType.cs @@ -0,0 +1,6 @@ +namespace Luski.net.Enums.Public; + +public enum ChannelType : short +{ + TextAndVoice = 0 +} diff --git a/Luski.net/Enums/ServerType.cs b/Luski.net/Enums/ServerType.cs new file mode 100644 index 0000000..cbace6a --- /dev/null +++ b/Luski.net/Enums/ServerType.cs @@ -0,0 +1,9 @@ +namespace Luski.net.Enums; + +public enum ServerType : byte +{ + Public = 0, + Main = 1, + PublicSub = 2, + MainSub = 3 +} \ No newline at end of file diff --git a/Luski.net/Interfaces/IAppUser.cs b/Luski.net/Interfaces/IAppUser.cs new file mode 100644 index 0000000..d29c9b3 --- /dev/null +++ b/Luski.net/Interfaces/IAppUser.cs @@ -0,0 +1,11 @@ +using Luski.net.Enums; +using Luski.net.Structures.Public; + +namespace Luski.net.Interfaces; + +public interface IAppUser : IUser +{ + public ErrorCode? Error { get; } + public string? ErrorMessage { get; } + public string Username { get; } +} \ No newline at end of file diff --git a/Luski.net/Interfaces/IAudioClient.cs b/Luski.net/Interfaces/IAudioClient.cs deleted file mode 100755 index dc21ee5..0000000 --- a/Luski.net/Interfaces/IAudioClient.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Luski.net.Sound; -using System; -using System.Threading.Tasks; -using static Luski.net.Exceptions; - -namespace Luski.net.Interfaces; - -public interface IAudioClient -{ - /// - /// the event is fired when your has joined the call - /// - event Func Connected; - /// - /// Tells you if you are muted - /// - bool Muted { get; } - /// - /// Tells you if you are deafned - /// - bool Deafened { get; } - /// - /// Toggles if you are speaking to your friends - /// - void ToggleMic(); - /// - /// Toggles if you can hear audio - /// - void ToggleAudio(); - /// - /// Changes what the call gets its data from - /// - /// This is the you want to recored from - /// - void RecordSoundFrom(RecordingDevice Device); - /// - /// Changes what the call gets its data from - /// - /// This is the you want to heare outhers - /// - void PlaySoundTo(PlaybackDevice Device); - /// - /// Joins the Voice call - /// - /// - void JoinCall(); - void LeaveCall(); -} diff --git a/Luski.net/Interfaces/IChannel.cs b/Luski.net/Interfaces/IChannel.cs deleted file mode 100755 index 98ab035..0000000 --- a/Luski.net/Interfaces/IChannel.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Luski.net.Enums; -using Luski.net.JsonTypes; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Luski.net.Interfaces; - -/// -/// contains a list of variables that all channels from luski have -/// -public interface ITextChannel -{ - long Id { get; } - string Title { get; } - string Description { get; } - string Key { get; } - /// - /// returns the current of the - /// - ChannelType Type { get; } - /// - /// Sends a to the server for the currently selected - /// - /// The messate you want to send to the server - Task SendMessage(string Message, params File[] Files); - Task SendKeysToUsers(); - Task GetMessage(long ID); - Task> GetMessages(long Message_Id, int count = 50); - Task> GetMessages(int count = 50); - Task GetPicture(); - IReadOnlyList Members { get; } -} diff --git a/Luski.net/Interfaces/IServer.cs b/Luski.net/Interfaces/IServer.cs new file mode 100644 index 0000000..5214204 --- /dev/null +++ b/Luski.net/Interfaces/IServer.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; +using Luski.net.JsonTypes.BaseTypes; +using Luski.net.Structures; +using Luski.net.Structures.Public; + +namespace Luski.net.Interfaces; + +public interface IServer +{ + public IAppUser IAppUser { get; } + public string Cache { get; } + public void SendServer(Tvalue Payload, JsonTypeInfo jsonTypeInfo) where Tvalue : IncomingWSS; + + public HttpResponseMessage GetFromServer(string Path, CancellationToken CancellationToken, + params KeyValuePair[] Headers); + + public Task GetFromServer(string Path, string File, CancellationToken CancellationToken, + params KeyValuePair[] Headers); + + public Task GetFromServer(string Path, JsonTypeInfo Type, + CancellationToken CancellationToken, params KeyValuePair[] Headers) + where Tresult : IncomingHTTP, new(); + + public Task SendServer(string Path, Tvalue Payload, + JsonTypeInfo jsonTypeInfo, JsonTypeInfo ReturnjsonTypeInfo, + CancellationToken CancellationToken, params KeyValuePair[] Headers) + where Tvalue : IWebRequest where Tresult : IncomingHTTP, new(); + + public Task SendServer(string Path, string File, JsonTypeInfo ReturnjsonTypeInfo, + CancellationToken CancellationToken, params KeyValuePair[] Headers) + where Tresult : IncomingHTTP, new(); + public Task GetUser(long UserID, CancellationToken CancellationToken) where Tuser : SocketUserBase, new(); + +} \ No newline at end of file diff --git a/Luski.net/Interfaces/IUser.cs b/Luski.net/Interfaces/IUser.cs index 1355fea..d06108f 100755 --- a/Luski.net/Interfaces/IUser.cs +++ b/Luski.net/Interfaces/IUser.cs @@ -1,5 +1,7 @@ -using Luski.net.Enums; +using System.Threading; +using Luski.net.Enums; using System.Threading.Tasks; +using Luski.net.JsonTypes; namespace Luski.net.Interfaces; @@ -15,12 +17,7 @@ public interface IUser /// /// The cerrent username of the user /// - string Username { get; } - /// - /// The current tag for the user - /// Ex: #1234 - /// - //short Tag { get; } + string DisplayName { get; } /// /// The current status of the user /// @@ -30,16 +27,16 @@ public interface IUser /// PictureType PictureType { get; } /// - /// the current flags of a user - /// - UserFlag Flags { get; } - /// /// Gets the current avatar of the user /// - Task GetAvatar(); + Task GetAvatar(CancellationToken CancellationToken); /// /// Gets the current user key /// /// - Task GetUserKey(); + Task GetUserKey(CancellationToken CancellationToken); + /// + /// The server that the user comes from + /// + IServer Server { get; } } diff --git a/Luski.net/Interfaces/IWebRequest.cs b/Luski.net/Interfaces/IWebRequest.cs new file mode 100644 index 0000000..8ebc582 --- /dev/null +++ b/Luski.net/Interfaces/IWebRequest.cs @@ -0,0 +1,6 @@ +namespace Luski.net.Interfaces; + +public interface IWebRequest +{ + +} \ No newline at end of file diff --git a/Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs b/Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs index f539e17..f54a522 100755 --- a/Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs +++ b/Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs @@ -1,9 +1,10 @@ using System.Text.Json.Serialization; using Luski.net.Enums; +using Luski.net.Interfaces; namespace Luski.net.JsonTypes.BaseTypes; -internal class HTTPRequest +internal class HTTPRequest : IWebRequest { [JsonPropertyName("data_type")] [JsonInclude] diff --git a/Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs b/Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs index ec2ba6f..66b4fd9 100755 --- a/Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs +++ b/Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; namespace Luski.net.JsonTypes.BaseTypes; -internal class IncomingWSS +public class IncomingWSS { [JsonPropertyName("type")] [JsonInclude] @@ -18,7 +18,7 @@ internal class IncomingWSS GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, WriteIndented = false)] -internal partial class IncomingWSSContext : JsonSerializerContext +public partial class IncomingWSSContext : JsonSerializerContext { } diff --git a/Luski.net/JsonTypes/BaseTypes/SocketUserBase.cs b/Luski.net/JsonTypes/BaseTypes/SocketUserBase.cs deleted file mode 100755 index 4577c75..0000000 --- a/Luski.net/JsonTypes/BaseTypes/SocketUserBase.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Luski.net.Enums; -using Luski.net.Interfaces; -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.Json.Serialization; -using System.Text.Json.Serialization.Metadata; -using System.Threading.Tasks; - -namespace Luski.net.JsonTypes.BaseTypes; - -[Browsable(false)] -[EditorBrowsable(EditorBrowsableState.Never)] -public abstract class SocketUserBase : IncomingHTTP, IUser -{ - [JsonPropertyName("id")] - [JsonInclude] - public long Id { get; internal set; } = default!; - [JsonPropertyName("username")] - [JsonInclude] - public string Username { get; internal set; } = default!; - // [JsonPropertyName("tag")] - //[JsonInclude] - //public short Tag { get; internal set; } = default!; - [JsonPropertyName("status")] - [JsonInclude] - public UserStatus Status { get; internal set; } = default!; - [JsonPropertyName("picture_type")] - [JsonInclude] - public PictureType PictureType { get; internal set; } = default!; - - [JsonPropertyName("flags")] - [JsonInclude] - public UserFlag Flags { get; internal set; } = default!; - - public async Task GetAvatar() - { - if (Server.Cache != null) - { - bool isc = System.IO.File.Exists($"{Server.Cache}/avatars/{Id}"); - if (!isc) await Server.GetFromServer($"socketuserprofile/Avatar/{Id}", $"{Server.Cache}/avatars/{Id}"); - } - return System.IO.File.ReadAllBytes($"{Server.Cache}/avatars/{Id}"); - } - - public Task GetUserKey() - { - if (Server._user is null) throw new Exception("you are not loged in"); - if (Id == Server._user.Id && Encryption.MyPublicKey is not null) return Task.FromResult(Encryption.MyPublicKey); - string data = Server.GetFromServer($"Keys/GetUserKey/{Id}").Content.ReadAsStringAsync().Result; - return Task.FromResult(data); - } - - internal static async Task GetUser(long UserId, JsonTypeInfo Json) where TUser : SocketUserBase, new() - { - TUser user; - if (Server.poeople is null) Server.poeople = new(); - if (Server.poeople.Count > 0 && Server.poeople.Any(s => s.Id == UserId)) - { - TUser temp = Server.poeople.Where(s => s is TUser && s.Id == UserId).Cast().FirstOrDefault()!; - if (temp is SocketRemoteUser && (temp as SocketRemoteUser)!.Channel == null) - { - foreach (SocketDMChannel chan in Server.chans.Where(s => s is SocketDMChannel).Cast()) - { - if (chan.Type == ChannelType.DM && chan.Id != 0 && chan.MemberIdList is not null) - { - if (chan.MemberIdList.Any(s => s == UserId)) (temp as SocketRemoteUser)!.Channel = chan; - } - } - } - return temp!; - } - while (true) - { - if (Server.CanRequest) - { - user = await Server.GetFromServer("socketuser", - Json, - new System.Collections.Generic.KeyValuePair("id", UserId.ToString())); - break; - } - } - - if (user is null) throw new Exception("Server did not return a user"); - if (Server.poeople.Count > 0 && Server.poeople.Any(s => s.Id == UserId)) - { - foreach (IUser? p in Server.poeople.Where(s => s.Id == UserId)) - { - Server.poeople.Remove(p); - } - } - if (Server._user is not null && UserId != 0 && UserId != Server._user.Id) - { - foreach (SocketDMChannel chan in Server.chans.Where(s => s is SocketDMChannel).Cast()) - { - if (chan.Id != 0 && chan.MemberIdList is not null) - { - if (chan.MemberIdList.Any(s => s == UserId)) (user as SocketRemoteUser)!.Channel = chan; - } - } - } - Server.poeople.Add(user); - return user; - } -} - -[JsonSerializable(typeof(SocketUserBase))] -[JsonSourceGenerationOptions( - GenerationMode = JsonSourceGenerationMode.Default, - PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, - WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.Never)] -internal partial class SocketUserBaseContext : JsonSerializerContext -{ - -} diff --git a/Luski.net/JsonTypes/HTTP/FriendRequest.cs b/Luski.net/JsonTypes/HTTP/FriendRequest.cs index 528d4c4..707818b 100755 --- a/Luski.net/JsonTypes/HTTP/FriendRequest.cs +++ b/Luski.net/JsonTypes/HTTP/FriendRequest.cs @@ -5,18 +5,12 @@ namespace Luski.net.JsonTypes.HTTP; internal class FriendRequest : HTTPRequest { + [JsonPropertyName("code")] + [JsonInclude] + public string code { get; set; } = default!; [JsonPropertyName("id")] [JsonInclude] public long Id { get; set; } = default!; - [JsonPropertyName("subtype")] - [JsonInclude] - public int SubType { get; set; } = default!; - [JsonPropertyName("username")] - [JsonInclude] - public string Username { get; set; } = default!; - [JsonPropertyName("tag")] - [JsonInclude] - public short Tag { get; set; } = default!; } [JsonSerializable(typeof(FriendRequest))] diff --git a/Luski.net/JsonTypes/OfflineData.cs b/Luski.net/JsonTypes/OfflineData.cs new file mode 100644 index 0000000..2d88763 --- /dev/null +++ b/Luski.net/JsonTypes/OfflineData.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using Luski.net.JsonTypes.BaseTypes; + +namespace Luski.net.JsonTypes; + +public class OfflineData : IncomingHTTP +{ + [JsonPropertyName("data")] + [JsonInclude] + public string[]? Data { get; internal set; } = default!; +} + +[JsonSerializable(typeof(OfflineData))] +[JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Default, + PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, + WriteIndented = false)] +internal partial class OfflineDataContext : JsonSerializerContext +{ + +} \ No newline at end of file diff --git a/Luski.net/JsonTypes/SocketAppUser.cs b/Luski.net/JsonTypes/SocketAppUser.cs deleted file mode 100755 index 15b5e60..0000000 --- a/Luski.net/JsonTypes/SocketAppUser.cs +++ /dev/null @@ -1,178 +0,0 @@ -using Luski.net.Interfaces; -using Luski.net.JsonTypes.BaseTypes; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Serialization; - -namespace Luski.net.JsonTypes; - -public class SocketAppUser : SocketUserBase -{ - [JsonPropertyName("email")] - [JsonInclude] - public string Email { get; internal set; } = default!; - [JsonIgnore] - public IReadOnlyList Channels - { - get - { - if (_Channels is null || ChannelIdList is not null) - { - if (ChannelIdList.Length != 0) - { - _Channels = new List(); - foreach (long channel in ChannelIdList) - { - SocketChannel s = SocketChannel.GetChannel(channel, SocketChannelContext.Default.SocketChannel).Result; - Server.chans.Remove(s); - switch (s.Type) - { - case Enums.ChannelType.GROUP: - _Channels.Add(SocketChannel.GetChannel(channel, SocketGroupChannelContext.Default.SocketGroupChannel).Result); - break; - case Enums.ChannelType.DM: - _Channels.Add(SocketChannel.GetChannel(channel, SocketDMChannelContext.Default.SocketDMChannel).Result); - break; - } - } - } - else _Channels = new List(); - } - return _Channels.AsReadOnly(); - } - } - [JsonIgnore] - public IReadOnlyList FriendRequests - { - get - { - if (_FriendRequests is null || FriendRequestsRaw is not null) - { - _FriendRequests = new(); - if (ChannelIdList.Length != 0 && FriendRequestsRaw is not null) - { - foreach (FR person in FriendRequestsRaw) - { - //_Friends.Add(SocketRemoteUser.GetUser(person)); - long id = person.user_id == Id ? person.from : person.user_id; - SocketRemoteUser frq = GetUser(id, SocketRemoteUserContext.Default.SocketRemoteUser).Result; - _FriendRequests.Add(frq); - } - } - else _FriendRequests = new(); - } - return _FriendRequests.AsReadOnly(); - } - } - [JsonIgnore] - public IReadOnlyList Friends - { - get - { - if (_Friends is null || FriendIdList is not null) - { - if (ChannelIdList.Length != 0) - { - _Friends = new List(); - foreach (long person in FriendIdList) - { - _Friends.Add(GetUser(person, SocketRemoteUserContext.Default.SocketRemoteUser).Result); - } - } - else _Friends = new List(); - } - return _Friends.AsReadOnly(); - } - } - [JsonPropertyName("selected_channel")] - [JsonInclude] - public long SelectedChannel { get; internal set; } = default!; - [JsonPropertyName("channels")] - [JsonInclude] - public long[] ChannelIdList { get; internal set; } = default!; - [JsonPropertyName("friends")] - [JsonInclude] - public long[] FriendIdList { get; internal set; } = default!; - [JsonPropertyName("friend_requests")] - [JsonInclude] - public FR[] FriendRequestsRaw { get; internal set; } = default!; - [JsonIgnore] - private List _Channels = default!; - [JsonIgnore] - private List _Friends = default!; - [JsonIgnore] - private List _FriendRequests = default!; - - public class FR - { - public long from { get; set; } = default!; - public long user_id { get; set; } = default!; - } - - internal void AddFriend(SocketRemoteUser User) - { - if (Server.poeople.Any(s => s.Id == User.Id)) - { - IEnumerable b = Server.poeople.Where(s => s.Id == User.Id); - foreach (IUser item in b) - { - Server.poeople.Remove(item); - } - Server.poeople.Add(User); - } - else - { - Server.poeople.Add(User); - } - _Friends.Add(User); - } - - internal void RemoveFriendRequest(SocketRemoteUser User) - { - if (Server.poeople.Any(s => s.Id == User.Id)) - { - IEnumerable b = Server.poeople.Where(s => s.Id == User.Id); - foreach (IUser item in b) - { - Server.poeople.Remove(item); - } - } - Server.poeople.Add(User); - foreach (SocketRemoteUser user in _FriendRequests) - { - if (User.Id == user.Id) - { - _FriendRequests.Remove(User); - } - } - } - - internal void AddFriendRequest(SocketRemoteUser User) - { - if (Server.poeople.Any(s => s.Id == User.Id)) - { - IEnumerable b = Server.poeople.Where(s => s.Id == User.Id); - foreach (IUser item in b) - { - Server.poeople.Remove(item); - } - Server.poeople.Add(User); - } - else - { - Server.poeople.Add(User); - } - _FriendRequests.Add(User); - } -} - -[JsonSerializable(typeof(SocketAppUser))] -[JsonSourceGenerationOptions( - GenerationMode = JsonSourceGenerationMode.Default, - PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, - WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.Never)] -internal partial class SocketAppUserContext : JsonSerializerContext -{ - -} diff --git a/Luski.net/JsonTypes/SocketDMChannel.cs b/Luski.net/JsonTypes/SocketDMChannel.cs deleted file mode 100755 index 2c6ea6a..0000000 --- a/Luski.net/JsonTypes/SocketDMChannel.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Luski.net.JsonTypes.BaseTypes; -using System.Linq; -using System.Text.Json.Serialization; - -namespace Luski.net.JsonTypes; - -public class SocketDMChannel : SocketTextChannel -{ - public SocketRemoteUser User - { - get - { - if (_user is null) - { - var list = MemberIdList.ToList(); - list.Remove(Server._user!.Id); - _user = SocketUserBase.GetUser(list.FirstOrDefault(), SocketRemoteUserContext.Default.SocketRemoteUser).Result; - } - return _user; - } - } - public SocketRemoteUser _user = null!; -} - -[JsonSerializable(typeof(SocketDMChannel))] -[JsonSourceGenerationOptions( - GenerationMode = JsonSourceGenerationMode.Default, - PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, - WriteIndented = false)] -internal partial class SocketDMChannelContext : JsonSerializerContext -{ - -} diff --git a/Luski.net/Luski.net.csproj b/Luski.net/Luski.net.csproj index 87b0f19..a4622e6 100755 --- a/Luski.net/Luski.net.csproj +++ b/Luski.net/Luski.net.csproj @@ -13,21 +13,17 @@ https://github.com/JacobTech-com/Luski.net True 1.0.0 - 1.1.4-alpha + 1.1.3-alpha23 + - - - - - - + diff --git a/Luski.net/Server.Account.cs b/Luski.net/Server.Account.cs new file mode 100644 index 0000000..e450715 --- /dev/null +++ b/Luski.net/Server.Account.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Security.Authentication; +using System.Text; +using System.Text.Json; +using System.Threading; +using JacobTechEncryption; +using JacobTechEncryption.Enums; +using Luski.net.Enums; +using Luski.net.JsonTypes; +using Luski.net.JsonTypes.WSS; +using Luski.net.Structures.Main; +using Luski.net.Structures.Public; +using WebSocketSharp; +using File = System.IO.File; + +namespace Luski.net; + +public partial class Server +{ + public void Login(string Email, string Password, CancellationToken CancellationToken) + { + Both(Email, Password, CancellationToken); + } + + public void CreateAccount(string Email, string Password, string Username, string PFP, CancellationToken CancellationToken) + { + Both(Email, Password, CancellationToken, Username, PFP); + } + + private void Both(string Email, string Password, CancellationToken CancellationToken, string? Username = null, string? pfp = null) + { + if (!ClientEncryption.Generating) + { + ClientEncryption.GenerateKeys(); + } + while (!ClientEncryption.Generated) { } + + login = true; + Login json; + List> heads = new() + { + new("key", ClientEncryption.MyPublicKey), + new("username", Convert.ToBase64String(Encryption.RSA.Encrypt(Email, ClientEncryption.MyPublicKey, EncoderType.UTF8))), + new("password", ClientEncryption.RemotePasswordEncrypt(Encoding.UTF8.GetBytes(Password))) + }; + if (File.Exists("LastPassVer.txt") && int.TryParse(File.ReadAllText("LastPassVer.txt"), out int lpv) && lpv < ClientEncryption.PasswordVersion && lpv >= 0) + { + heads.Add(new("old_password", ClientEncryption.RemotePasswordEncrypt(Encoding.UTF8.GetBytes(Password), lpv))); + heads.Add(new("old_version", lpv.ToString())); + } + if (pfp is not null) + { + heads.Add(new("username", Username)); + json = SendServer( + "CreateAccount", + pfp, + LoginContext.Default.Login, + CancellationToken, + heads.ToArray()).Result; + } + else + { + json = GetFromServer( + "Login", + LoginContext.Default.Login, + CancellationToken, + heads.ToArray()).Result; + } + if (json.Error is not null) throw new Exception($"Luski appears to be down at the current moment: {json.ErrorMessage}"); + if (ClientEncryption.ofkey is null || ClientEncryption.outofkey is null) throw new Exception("Something went wrong generating the offline keys"); + login = false; + if (json is not null && json.Error is null) + { + ServerOut = new WebSocket($"wss://{Domain}/WSS/{ApiVersion}"); + ServerOut.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12; + ServerOut.OnMessage += DataFromServer; + ServerOut.WaitTime = new TimeSpan(0, 0, 5); + ServerOut.OnError += ServerOut_OnError; + ServerOut.Connect(); + SendServer(new WSSLogin() { Token = json.Token! }, WSSLoginContext.Default.WSSLogin); + while (Token is null && Error is null) + { + + } + if (Error is not null) + { + throw new Exception(Error); + } + + if (Token is null) throw new Exception("Server did not send a token"); + CanRequest = true; + long id = long.Parse(Encoding.UTF8.GetString(Convert.FromBase64String( + Token.Split('.')[0] + ))); + TUser t = new(); + User = t switch + { + MainSocketAppUser => (GetUser(id, MainSocketAppUserContext.Default.MainSocketAppUser, + CancellationToken.None) + .Result as TUser)!, + _ => (GetUser(id, PublicSocketAppUserContext.Default.PublicSocketAppUser, CancellationToken.None) + .Result as TUser)! + }; + if (User is null || User.Error is not null) + { + string error = "User was null"; + if (User is not null && User.Error is not null) error = $"{User.Error}: {User.ErrorMessage}"; + throw new Exception($"Something went wrong getting your user infermation\n{error}"); + } + Console.WriteLine("User got"); + Console.WriteLine("Insert"); + //User.Email = Email; + _ = UpdateStatus(UserStatus.Online, CancellationToken); + Console.WriteLine("stat"); + try + { + ClientEncryption.pw = Email.ToLower() + Password; + _ = ClientEncryption.File.GetOfflineKey(); + } + catch + { + try + { + ClientEncryption.pw = Email + Password; + var temp222 = ClientEncryption.File.LuskiDataFile.GetDefualtDataFile(); + ClientEncryption.pw = Email.ToLower() + Password; + if (temp222 is not null) temp222.Save("key.lsk", ClientEncryption.pw); + } + catch + { + Token = null; + Error = null; + ServerOut.Close(); + throw new Exception("The key file you have is getting the wrong pasword. Type your Email in the same way you creaated your account to fix this error."); + } + } + Console.WriteLine("req offline"); + OfflineData offlinedata = GetFromServer("Keys/GetOfflineData", OfflineDataContext.Default.OfflineData, CancellationToken).Result; + if (offlinedata.Data is not null && offlinedata.Data.Any()) Console.WriteLine(offlinedata.Data); + if (offlinedata is not null && offlinedata.Error is null && offlinedata.Data is not null && offlinedata.Data.Length > 0) + { + foreach (string keyex in offlinedata.Data) + { + Console.WriteLine(keyex); + KeyExchange? okd = JsonSerializer.Deserialize(keyex); + Console.WriteLine(okd); + if (okd is not null && !string.IsNullOrEmpty(okd.key)) + { + Console.WriteLine(okd.channel); + Console.WriteLine(okd.key); + ClientEncryption.File.Channels.AddKey(okd.channel, Encoding.UTF8.GetString(Encryption.RSA.Decrypt(Convert.FromBase64String(okd.key), ClientEncryption.File.GetOfflineKey()))); + } + } + } + Console.WriteLine("lpv"); + System.IO.File.WriteAllText("LastPassVer.txt", ClientEncryption.PasswordVersion.ToString()); + ClientEncryption.File.SetOfflineKey(ClientEncryption.ofkey); + using HttpClient setkey = new(); + setkey.DefaultRequestHeaders.Add("token", Token); + _ = setkey.PostAsync($"https://{Domain}/{ApiVersion}/Keys/SetOfflineKey", new StringContent(ClientEncryption.outofkey)).Result; + //_ = User.Channels; + foreach (var ch in chans) + { + _ = ch.Members; + } + ClientEncryption.outofkey = null; + ClientEncryption.ofkey = null; + } + else throw new Exception(json?.ErrorMessage); + } +} \ No newline at end of file diff --git a/Luski.net/Server.Cleanup.cs b/Luski.net/Server.Cleanup.cs deleted file mode 100755 index 8fbc84c..0000000 --- a/Luski.net/Server.Cleanup.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.IO; - -namespace Luski.net; - -public sealed partial class Server : IDisposable -{ - ~Server() - { - try { if (Directory.Exists(Cache)) Directory.Delete(Cache, true); } catch { } - } - - public void Dispose() - { - try { if (Directory.Exists(Cache)) Directory.Delete(Cache, true); } catch { } - } -} diff --git a/Luski.net/Server.Constructors.cs b/Luski.net/Server.Constructors.cs deleted file mode 100755 index 6cce45f..0000000 --- a/Luski.net/Server.Constructors.cs +++ /dev/null @@ -1,129 +0,0 @@ -using Luski.net.Enums; -using Luski.net.JsonTypes; -using Luski.net.JsonTypes.BaseTypes; -using Luski.net.JsonTypes.WSS; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using WebSocketSharp; -using File = System.IO.File; - -namespace Luski.net; - -public sealed partial class Server -{ - internal Server(string Email, string Password, Branch branch = Branch.Master, string? Username = null, string? pfp = null) - { - if (!Encryption.Generating) - { - Encryption.GenerateKeys(); - } - while (!Encryption.Generated) { } - InternalDomain = $"api.{branch}.luski.JacobTech.com"; - Branch = branch; - login = true; - Login json; - List> heads = new() - { - new("key", Encryption.MyPublicKey), - new("email", Convert.ToBase64String(Encryption.Encrypt(Email))), - new("password", Encryption.RemotePasswordEncrypt(Encryption.Encoder.GetBytes(Password))) - }; - if (File.Exists("LastPassVer.txt") && int.TryParse(File.ReadAllText("LastPassVer.txt"), out int lpv) && lpv < Encryption.PasswordVersion && lpv >= 0) - { - heads.Add(new("old_password", Encryption.RemotePasswordEncrypt(Encryption.Encoder.GetBytes(Password), lpv))); - heads.Add(new("old_version", lpv.ToString())); - } - if (pfp is not null) - { - heads.Add(new("username", Username)); - json = SendServer( - "CreateAccount", - pfp, - LoginContext.Default.Login, - heads.ToArray()).Result; - } - else - { - json = GetFromServer( - "Login", - LoginContext.Default.Login, - heads.ToArray()).Result; - } - - if (json.Error is not null) throw new Exception($"Luski appears to be down at the current moment: {json.ErrorMessage}"); - if (Encryption.ofkey is null || Encryption.outofkey is null) throw new Exception("Something went wrong generating the offline keys"); - login = false; - if (json is not null && json.Error is null) - { - ServerOut = new WebSocket($"wss://{InternalDomain}/WSS/{API_Ver}"); - ServerOut.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls13; - ServerOut.OnMessage += DataFromServer; - ServerOut.WaitTime = new TimeSpan(0, 0, 5); - ServerOut.OnError += ServerOut_OnError; - ServerOut.Connect(); - string Infermation = $"{{\"token\": \"{json.Token}\"}}"; - SendServer(new WSSLogin() { Token = json.Token! }, WSSLoginContext.Default.WSSLogin); - while (Token is null && Error is null) - { - - } - if (Error is not null) - { - throw new Exception(Error); - } - if (Token is null) throw new Exception("Server did not send a token"); - CanRequest = true; - _user = SocketUserBase.GetUser(long.Parse(Encoding.UTF8.GetString(Convert.FromBase64String(Token.Split('.')[0]))), SocketAppUserContext.Default.SocketAppUser).Result; - if (_user is null || _user.Error is not null) throw new Exception("Something went wrong getting your user infermation"); - _ = _user.Channels; - foreach (var ch in chans) - { - _ = ch.Members; - } - _user.Email = Email; - _ = UpdateStatus(UserStatus.Online); - - try - { - Encryption.pw = Email.ToLower() + Password; - _ = Encryption.File.GetOfflineKey(); - } - catch - { - try - { - Encryption.pw = Email + Password; - var temp222 = Encryption.File.LuskiDataFile.GetDefualtDataFile(); - Encryption.pw = Email.ToLower() + Password; - if (temp222 is not null) temp222.Save(GetKeyFilePath, Encryption.pw); - } - catch - { - Token = null; - Error = null; - ServerOut.Close(); - throw new Exception("The key file you have is getting the wrong pasword. Type your Email in the same way you creaated your account to fix this error."); - } - } - OfflineKeyData offlinedata = GetFromServer("Keys/GetOfflineData", OfflineKeyDataContext.Default.OfflineKeyData).Result; - if (string.IsNullOrEmpty(Encryption.File.GetOfflineKey())) Encryption.File.SetOfflineKey(Encryption.ofkey); - if (offlinedata is not null && offlinedata.Error is null && offlinedata.keys is not null) - { - foreach (KeyExchange key in offlinedata.keys) - { - Encryption.File.Channels.AddKey(key.channel, Encryption.Encoder.GetString(Encryption.Decrypt(Convert.FromBase64String(key.key), Encryption.File.GetOfflineKey()))); - } - } - System.IO.File.WriteAllText("LastPassVer.txt", Encryption.PasswordVersion.ToString()); - Encryption.File.SetOfflineKey(Encryption.ofkey); - using HttpClient setkey = new(); - setkey.DefaultRequestHeaders.Add("token", Token); - _ = setkey.PostAsync($"https://{InternalDomain}/{API_Ver}/Keys/SetOfflineKey", new StringContent(Encryption.outofkey)).Result; - Encryption.outofkey = null; - Encryption.ofkey = null; - } - else throw new Exception(json?.ErrorMessage); - } -} diff --git a/Luski.net/Server.CreateAccount.cs b/Luski.net/Server.CreateAccount.cs deleted file mode 100755 index 8dd53b7..0000000 --- a/Luski.net/Server.CreateAccount.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using Luski.net.Enums; -using Luski.net.JsonTypes; -using Luski.net.JsonTypes.WSS; -using WebSocketSharp; - -namespace Luski.net; - -public sealed partial class Server -{ - internal Server(string Email, string Password, string Username, byte[] PFP, Branch branch = Branch.Master) - { - Encryption.pw = Email.ToLower() + Password; - if (!Encryption.Generating) - { - Encryption.GenerateKeys(); - } - while (!Encryption.Generated) { } - if (Encryption.ofkey is null || Encryption.outofkey is null) throw new Exception("Something went wrong generating the offline keys"); - string Result; - InternalDomain = $"api.{branch}.luski.JacobTech.com"; - Branch = branch; - using (HttpClient web = new()) - { - web.DefaultRequestHeaders.Add("key", Encryption.MyPublicKey); - web.DefaultRequestHeaders.Add("email", Convert.ToBase64String(Encryption.Encrypt(Email))); - web.DefaultRequestHeaders.Add("password", Convert.ToBase64String(Encryption.Encrypt(Password))); - web.DefaultRequestHeaders.Add("username", Username); - HttpResponseMessage? d = web.PostAsync($"https://{InternalDomain}/{API_Ver}/CreateAccount", new StringContent(Convert.ToBase64String(PFP))).Result; - if (d is null || !d.IsSuccessStatusCode) throw new Exception("Luski appears to be down at the current moment"); - Result = d.Content.ReadAsStringAsync().Result; - web.DefaultRequestHeaders.Clear(); - } - Login? json = JsonSerializer.Deserialize(Result, LoginContext.Default.Login); - if (json is not null && json.Error is null) - { - ServerOut = new WebSocket($"wss://{InternalDomain}/{API_Ver}"); - ServerOut.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls13; - ServerOut.OnMessage += DataFromServer; - ServerOut.WaitTime = new TimeSpan(0, 0, 5); - ServerOut.OnError += ServerOut_OnError; - ServerOut.Connect(); - string Infermation = $"{{\"token\": \"{json.Token}\"}}"; - SendServer(new WSSLogin() { Token = json.Token}, WSSLoginContext.Default.WSSLogin); - while (Token is null && Error is null) - { - - } - if (Error is not null) - { - throw new Exception(Error); - } - if (Token is null) throw new Exception("Server did not send a token"); - CanRequest = true; - string data; - using (HttpClient web = new()) - { - web.DefaultRequestHeaders.Add("token", Token); - web.DefaultRequestHeaders.Add("id", Encoding.UTF8.GetString(Convert.FromBase64String(Token.Split('.')[0]))); - data = web.GetAsync($"https://{InternalDomain}/{API_Ver}/SocketUser").Result.Content.ReadAsStringAsync().Result; - } - _user = JsonSerializer.Deserialize(data); - if (_user is null || _user.Error is not null) throw new Exception("Something went wrong getting your user infermation"); - _ = _user.Channels; - foreach (var ch in chans) - { - _ = ch.Members; - } - _user.Email = Email; - UpdateStatus(UserStatus.Online); - Encryption.File.SetOfflineKey(Encryption.ofkey); - using HttpClient setkey = new(); - setkey.DefaultRequestHeaders.Add("token", Token); - _ = setkey.PostAsync($"https://{InternalDomain}/{API_Ver}/Keys/SetOfflineKey", new StringContent(Encryption.outofkey)).Result; - Encryption.outofkey = null; - Encryption.ofkey = null; - } - else throw new Exception(json?.ErrorMessage); - } - - public static Server CreateAccount(string Email, string Password, string Username, byte[] PFP, Branch branch = Branch.Master) - { - return new Server(Email, Password, Username, PFP, branch); - } - - public static Server CreateAccount(string Email, string Password, string Username, string PFP, Branch branch = Branch.Master) - { - return new Server(Email, Password, branch, Username, PFP); - } -} diff --git a/Luski.net/Server.Events.cs b/Luski.net/Server.Events.cs old mode 100755 new mode 100644 index 8ed8955..132efcd --- a/Luski.net/Server.Events.cs +++ b/Luski.net/Server.Events.cs @@ -1,21 +1,20 @@ -using Luski.net.Interfaces; -using Luski.net.JsonTypes; using System; using System.Threading.Tasks; +using Luski.net.Interfaces; +using Luski.net.JsonTypes; +using Luski.net.Structures; namespace Luski.net; -public sealed partial class Server +public partial class Server { public event Func? MessageReceived; public event Func? UserStatusUpdate; - public event Func? ReceivedFriendRequest; - - public event Func? FriendRequestResult; - - public event Func? IncommingCall; + public event Func? ReceivedFriendRequest; + public event Func? FriendRequestResult; + public event Func? OnError; -} +} \ No newline at end of file diff --git a/Luski.net/Server.Globals.cs b/Luski.net/Server.Globals.cs old mode 100755 new mode 100644 index 0832213..4959487 --- a/Luski.net/Server.Globals.cs +++ b/Luski.net/Server.Globals.cs @@ -1,31 +1,28 @@ -using Luski.net.Enums; -using Luski.net.Interfaces; -using Luski.net.JsonTypes; -using Luski.net.Sockets; using System; using System.Collections.Generic; using System.IO; +using Luski.net.Enums; +using Luski.net.Interfaces; +using Luski.net.JsonTypes; +using Luski.net.Structures.Main; +using Luski.net.Structures.Public; using WebSocketSharp; namespace Luski.net; -public sealed partial class Server +public partial class Server where TUser : class, IAppUser, new() { - internal static string JT { get { return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/JacobTech"; } } - internal static SocketAudioClient? AudioClient = null; - internal static string? Token = null, Error = null; - internal static bool CanRequest = false; - internal static SocketAppUser? _user; - internal static string InternalDomain = "api.master.luski.jacobtech.com", platform = "win-x64"; - internal static Branch Branch; - internal static double Percent = 0.5; - private static WebSocket? ServerOut; - private static string? gen = null; - private static bool login = false; - - public string Domain { get { return InternalDomain; } } - - internal static string Cache + public ServerType ServerType { get; internal set; } = ServerType.Public; + public string Domain { get; internal set; } = default!; + public IAppUser IAppUser => User; + public TUser User { get; internal set; } + public string ApiVersion { get; internal set; } = "v1"; + private WebSocket? ServerOut; + internal string? Token = null, Error = null, gen = null; + internal bool CanRequest = false, login = false; + internal List poeople = new(); + internal List chans { get; set; } = new(); + public string Cache { get { @@ -34,13 +31,9 @@ public sealed partial class Server if (!Directory.Exists(JT)) Directory.CreateDirectory(JT); string path = JT + "/Luski/"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += Branch.ToString() + "/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += platform + "/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); path += "Data/"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += _user?.Id + "/"; + path += User.Id + "/"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); path += "Cache/"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); @@ -53,31 +46,18 @@ public sealed partial class Server return gen; } } - internal const string API_Ver = "v1"; - internal static List poeople = new(); - internal static List chans { get; set; } = new(); - internal static string GetKeyFilePath + + internal static string JT { get { - return GetKeyFilePathBr(Branch.ToString()); + string tmp = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "JacobTech"); + if (OperatingSystem.IsLinux()) + { + tmp = Path.Combine(Environment.GetEnvironmentVariable("HOME")!, ".config/"); + tmp += "JacobTech"; + } + return tmp; } } - - internal static string GetKeyFilePathBr(string br) - { - if (!Directory.Exists(JT)) Directory.CreateDirectory(JT); - string path = JT + "/Luski/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += br + "/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += platform + "/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += "Data/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += _user?.Id + "/"; - if (!Directory.Exists(path)) Directory.CreateDirectory(path); - path += "keys.lsk"; - return path; - } -} +} \ No newline at end of file diff --git a/Luski.net/Server.Incoming.cs b/Luski.net/Server.Incoming.cs old mode 100755 new mode 100644 index cb5aae3..75f9347 --- a/Luski.net/Server.Incoming.cs +++ b/Luski.net/Server.Incoming.cs @@ -1,25 +1,39 @@ -using Luski.net.Enums; +using System; +using System.Text.Json; +using System.Threading; +using JacobTechEncryption; +using Luski.net.Enums; using Luski.net.JsonTypes; using Luski.net.JsonTypes.BaseTypes; using Luski.net.JsonTypes.HTTP; using Luski.net.JsonTypes.WSS; -using System; -using System.Text.Json; +using Luski.net.Structures; +using Luski.net.Structures.Main; using WebSocketSharp; -namespace Luski.net +namespace Luski.net; + +public partial class Server { - public sealed partial class Server + private void ServerOut_OnError(object? sender, WebSocketSharp.ErrorEventArgs e) { - private void DataFromServer(object? sender, MessageEventArgs e) + if (OnError is not null) OnError.Invoke(new Exception(e.Message)); + } + + private void DataFromServer(object? sender, MessageEventArgs e) + { + if (e.IsPing) return; + try { - if (e.IsPing) return; + Console.WriteLine("From Server: {0}", e.Data); IncomingWSS? data = JsonSerializer.Deserialize(e.Data, IncomingWSSContext.Default.IncomingWSS); switch (data?.Type) { case DataType.Login: + Console.WriteLine("Pre auth"); WSSLogin n = JsonSerializer.Deserialize(e.Data, WSSLoginContext.Default.WSSLogin)!; Token = n.Token; + Console.WriteLine("Token: {0}",Token); break; case DataType.Error: if (Token is null) @@ -40,7 +54,7 @@ namespace Luski.net SocketMessage? m = JsonSerializer.Deserialize(e.Data); if (m is not null) { - m.decrypt(Encryption.File.Channels.GetKey(m.ChannelID)); + m.decrypt(ClientEncryption.File.Channels.GetKey(m.ChannelID), CancellationToken.None); _ = MessageReceived.Invoke(m); } } @@ -51,9 +65,9 @@ namespace Luski.net StatusUpdate? SU = JsonSerializer.Deserialize(e.Data); if (SU is not null) { - SocketRemoteUser after = SocketUserBase.GetUser(SU.id, SocketRemoteUserContext.Default.SocketRemoteUser).Result; + MainSocketRemoteUser after = GetUser(SU.id, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken.None).Result; after.Status = SU.after; - SocketRemoteUser before = after.Clone(); + MainSocketRemoteUser before = after.Clone(); before.Status = SU.before; _ = UserStatusUpdate.Invoke(before, after); } @@ -62,57 +76,56 @@ namespace Luski.net case DataType.Friend_Request: if (ReceivedFriendRequest is not null) { - FriendRequest? request = JsonSerializer.Deserialize(e.Data, FriendRequestContext.Default.FriendRequest); - if (request is not null) _ = ReceivedFriendRequest.Invoke(SocketUserBase.GetUser(request.Id, SocketRemoteUserContext.Default.SocketRemoteUser).Result); + FriendRequest? request = + JsonSerializer.Deserialize(e.Data, FriendRequestContext.Default.FriendRequest); + if (request is not null) + _ = ReceivedFriendRequest.Invoke(GetUser(request.Id, + MainSocketRemoteUserContext.Default.MainSocketRemoteUser, + CancellationToken.None).Result); } break; case DataType.Friend_Request_Result: if (FriendRequestResult is not null) { FriendRequestResult? FRR = JsonSerializer.Deserialize(e.Data); - if (FRR is not null && FRR.Channel is not null && FRR.Id is not null && FRR.Result is not null) + if (FRR is not null && FRR.Channel is not null && FRR.Id is not null && + FRR.Result is not null) { - SocketDMChannel chan = SocketChannel.GetChannel((long)FRR.Channel, SocketDMChannelContext.Default.SocketDMChannel).Result; + MainSocketDMChannel chan = GetChannel((long)FRR.Channel, + MainSocketDMChannelContext.Default.MainSocketDMChannel, + CancellationToken.None).Result; chans.Add(chan); - SocketRemoteUser from1 = SocketUserBase.GetUser((long)FRR.Id, SocketRemoteUserContext.Default.SocketRemoteUser).Result; - from1.Channel = chan; + MainSocketRemoteUser from1 = GetUser((long)FRR.Id, + MainSocketRemoteUserContext.Default.MainSocketRemoteUser, + CancellationToken.None).Result; + //from1.Channel = chan; _ = FriendRequestResult.Invoke(from1, (bool)FRR.Result); } } break; - case DataType.Call_Info: - if (IncommingCall is not null) - { - callinfoinc? ci = JsonSerializer.Deserialize(e.Data); - if (ci is not null) _ = IncommingCall.Invoke(SocketChannel.GetChannel(ci.channel, SocketTextChannelContext.Default.SocketTextChannel).Result, SocketUserBase.GetUser(ci.from, SocketRemoteUserContext.Default.SocketRemoteUser).Result); - } - break; - case DataType.Call_Data: - if (AudioClient is not null) - { - AudioClient.Givedata(e.Data); - } - break; case DataType.Key_Exchange: try { KeyExchange? KE = JsonSerializer.Deserialize(e.Data); - if (KE is not null) Encryption.File.Channels.AddKey(KE.channel, Encryption.Encoder.GetString(Encryption.Decrypt(Convert.FromBase64String(KE.key)))); + if (KE is not null) + ClientEncryption.File.Channels.AddKey(KE.channel, + ClientEncryption.Encoder.GetString(Encryption.RSA.Decrypt(Convert.FromBase64String(KE.key), ClientEncryption.ofkey))); } catch (Exception ex) { if (OnError is not null) OnError.Invoke(ex); } + break; default: + Console.WriteLine("Unknown"); break; } } - - private class callinfoinc + catch (Exception exception) { - public long channel { get; set; } = default!; - public long from { get; set; } = default!; + if (OnError is not null) _ = OnError.Invoke(exception); + else throw exception; } } -} +} \ No newline at end of file diff --git a/Luski.net/Server.Login.cs b/Luski.net/Server.Login.cs deleted file mode 100755 index e0b1596..0000000 --- a/Luski.net/Server.Login.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Luski.net.Enums; -using System.Threading.Tasks; - -namespace Luski.net; - -public sealed partial class Server -{ - public static async Task Login(string Email, string Password, Branch branch = Branch.Master) - { - return new Server(Email, Password, branch); - } -} diff --git a/Luski.net/Server.cs b/Luski.net/Server.cs old mode 100755 new mode 100644 index b6cfbe9..814b71d --- a/Luski.net/Server.cs +++ b/Luski.net/Server.cs @@ -1,191 +1,79 @@ -using Luski.net.Enums; -using Luski.net.Interfaces; -using Luski.net.JsonTypes; -using Luski.net.JsonTypes.BaseTypes; -using Luski.net.JsonTypes.HTTP; -using Luski.net.Sockets; using System; using System.Collections.Generic; using System.IO; -using System.Net; +using System.Linq; using System.Net.Http; using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Serialization.Metadata; +using System.Threading; using System.Threading.Tasks; +using Luski.net.Enums; +using Luski.net.Interfaces; +using Luski.net.JsonTypes; +using Luski.net.JsonTypes.BaseTypes; +using Luski.net.JsonTypes.HTTP; +using Luski.net.Structures; +using Luski.net.Structures.Main; +using Luski.net.Structures.Public; +using File = System.IO.File; namespace Luski.net; -public sealed partial class Server +public partial class Server : IServer { -#pragma warning disable CA1822 // Mark members as static - /// - /// Creates an audio client for the you want to talk on - /// - /// The channel you want to talk on - /// - public IAudioClient CreateAudioClient(long channel_id) + internal Server() + { } + + public async Task GetAvatar(CancellationToken CancellationToken) { - // if (AudioClient != null) throw new Exception("audio client alread created"); - SocketAudioClient client = new(channel_id, OnError); - AudioClient = client; - return client; + if (Cache != null) + { + bool isc = File.Exists($"{Cache}/servers/{Domain}"); + if (!isc) await GetFromServer($"socketserver/Avatar/", $"{Cache}/servers/{Domain}-{ApiVersion}", CancellationToken); + } + return File.ReadAllBytes($"{Cache}/servers/{Domain}"); } - public async Task SendFriendResult(long user, bool answer) + public async Task GetUser(long UserID, CancellationToken CancellationToken) where Tuser : SocketUserBase, new() { - - FriendRequestResult json = await SendServer("FriendRequestResult", - new FriendRequestResultOut() - { - Id = user, - Result = answer - }, - FriendRequestResultOutContext.Default.FriendRequestResultOut, - FriendRequestResultContext.Default.FriendRequestResult); - - if (json is not null && json.Error is null && json.ErrorMessage is null && answer && json.Channel is not null) + Tuser user = new(); + switch (user) { - SocketDMChannel chan = await SocketChannel.GetChannel((long)json.Channel, SocketDMChannelContext.Default.SocketDMChannel); - _ = chan.StartKeyProcessAsync(); - chans.Add(chan); + case MainSocketAppUser: + user = (GetUser(UserID, MainSocketAppUserContext.Default.MainSocketAppUser, CancellationToken).Result as Tuser)!; + break; + case PublicSocketAppUser: + user = (GetUser(UserID, PublicSocketAppUserContext.Default.PublicSocketAppUser, CancellationToken).Result as Tuser)!; + break; + case SocketUserBase: + user = (GetUser(UserID, SocketUserBaseContext.Default.SocketUserBase, CancellationToken).Result as Tuser)!; + break; + case null: + throw new NullReferenceException(nameof(Tuser)); + default: + throw new Exception("Unknown channel type"); } - else - { - throw new Exception(json?.Error.ToString()); - } - return SocketUserBase.GetUser(user, SocketRemoteUserContext.Default.SocketRemoteUser).Result; + + return user; } - - public async Task SendFriendRequest(long user) - { - FriendRequestResult? json = await SendServer("FriendRequest", new FriendRequest() { Id = user, SubType = 0 }, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult); - - if (json.StatusCode != HttpStatusCode.Accepted) - { - if (json is not null && json.Error is not null) - { - switch ((ErrorCode)(int)json.Error) - { - case ErrorCode.InvalidToken: - throw new Exception("Your current token is no longer valid"); - case ErrorCode.ServerError: - throw new Exception($"Error from server: {json.ErrorMessage}"); - case ErrorCode.InvalidPostData: - throw new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version"); - case ErrorCode.Forbidden: - throw new Exception("You already have an outgoing request or the persone is not real"); - } - } - - if (json is not null && json.Channel is not null) - { - SocketDMChannel chan = await SocketChannel.GetChannel((long)json.Channel, (JsonTypeInfo)SocketDMChannelContext.Default.SocketDMChannel); - _ = chan.StartKeyProcessAsync(); - chans.Add(chan); - } - } - - SocketRemoteUser b = await SocketUserBase.GetUser(user, SocketRemoteUserContext.Default.SocketRemoteUser); - b.FriendStatus = FriendStatus.PendingOut; - return b; - } - - public async Task SendFriendRequest(string username, short tag) - { - FriendRequestResult json = await SendServer("FriendRequest", new FriendRequest() { Username = username, Tag = tag, SubType = 1 }, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult); - - if (json is not null && json.Error is not null) - { - throw (ErrorCode)(int)json.Error switch - { - ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"), - ErrorCode.ServerError => new Exception("Error from server: " + json.ErrorMessage), - ErrorCode.InvalidPostData => new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version"), - ErrorCode.Forbidden => new Exception("You already have an outgoing request or the persone is not real"), - _ => new Exception(JsonSerializer.Serialize(json)), - }; - } - else if (json is not null && json.Channel is not null && json.Id is not null) - { - SocketDMChannel chan = await SocketChannel.GetChannel(json.Channel.Value, (JsonTypeInfo)SocketDMChannelContext.Default.SocketDMChannel); - _ = chan.StartKeyProcessAsync(); - chans.Add(chan); - return await SocketUserBase.GetUser((long)json.Id, SocketRemoteUserContext.Default.SocketRemoteUser); - } - else throw new Exception("missing data from server"); - } - - /// - /// Sends the server a request to update the of you account - /// - /// The you want to set your status to - /// - public async Task UpdateStatus(UserStatus Status) - { - if (_user is null) throw new Exception("You must login to make a request"); - IncomingHTTP? data = await SendServer("SocketUserProfile/Status", new Status() { UserStatus = Status }, StatusContext.Default.Status, IncomingHTTPContext.Default.IncomingHTTP); - if (data.Error is not null && ((int)data.StatusCode < 200 || (int)data.StatusCode > 299)) - { - if (data?.ErrorMessage is not null) throw new Exception(data.ErrorMessage); - if (data?.Error is not null) throw new Exception(((int)data.Error).ToString()); - else throw new Exception("Something went worng"); - } - - _user.Status = Status; - return Task.CompletedTask; - } - - public async Task ChangeChannel(long Channel) - { - if (_user is null) throw new Exception("You must login to make a request"); - IncomingHTTP? data = await SendServer("ChangeChannel", new Channel() { Id = Channel }, ChannelContext.Default.Channel, IncomingHTTPContext.Default.IncomingHTTP); - if (data.StatusCode != HttpStatusCode.Accepted) - { - if (data?.Error is not null) - { - switch (data.Error) - { - case ErrorCode.InvalidToken: - throw new Exception("Your current token is no longer valid"); - case ErrorCode.ServerError: - throw new Exception("Error from server: " + data.ErrorMessage); - } - } - else throw new Exception("Something went worng"); - } - - _user.SelectedChannel = Channel; - } - - public async Task SendMessage(string Message, long Channel, params JsonTypes.File[] Files) => (await GetChannel(Channel)).SendMessage(Message, Files); - - public void SetMultiThreadPercent(double num) - { - if (num < 1 || num > 100) throw new Exception("Number must be from 1 - 100"); - Percent = num / 100; - } - - public async Task GetMessage(long MessageId) => await SocketMessage.GetMessage(MessageId); - - public async Task GetUser(long UserID) => await SocketUserBase.GetUser(UserID, SocketRemoteUserContext.Default.SocketRemoteUser); - - public async Task GetChannel(long Channel) where TChannel : SocketChannel, new() + + public async Task GetChannel(long Channel, CancellationToken CancellationToken) where TChannel : MainSocketChannel, new() { TChannel Return = new(); switch (Return) { - case SocketDMChannel: - Return = (await SocketChannel.GetChannel(Channel, SocketDMChannelContext.Default.SocketDMChannel) as TChannel)!; + case MainSocketDMChannel: + Return = (await GetChannel(Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken) as TChannel)!; break; - case SocketGroupChannel: - Return = (await SocketChannel.GetChannel(Channel, SocketGroupChannelContext.Default.SocketGroupChannel) as TChannel)!; + case MainSocketGroupChannel: + Return = (await GetChannel(Channel, MainSocketGroupChannelContext.Default.MainSocketGroupChannel, CancellationToken) as TChannel)!; break; - case SocketTextChannel: - Return = (await SocketChannel.GetChannel(Channel, SocketTextChannelContext.Default.SocketTextChannel) as TChannel)!; + case MainSocketTextChannel: + Return = (await GetChannel(Channel, MainSocketTextChannelContext.Default.MainSocketTextChannel, CancellationToken) as TChannel)!; break; - case SocketChannel: - Return = (await SocketChannel.GetChannel(Channel, SocketChannelContext.Default.SocketChannel) as TChannel)!; + case MainSocketChannel: + Return = (await GetChannel(Channel, MainSocketChannelContext.Default.MainSocketChannel, CancellationToken) as TChannel)!; break; case null: throw new NullReferenceException(nameof(TChannel)); @@ -194,84 +82,169 @@ public sealed partial class Server } return Return; } - - - public SocketAppUser CurrentUser + + internal async Task GetChannel(long id, JsonTypeInfo Json, CancellationToken CancellationToken) where TChannel : MainSocketChannel, new() { - get + TChannel request; + if (chans.Count > 0 && chans.Any(s => s.Id == id)) { - if (_user is null) throw new Exception("You must Login first"); - return _user; + return chans.Where(s => s is TChannel && s.Id == id).Cast().FirstOrDefault()!; } + while (true) + { + if (CanRequest) + { + request = await GetFromServer($"SocketChannel/Get/{id}", Json, CancellationToken); + break; + } + } + if (request is null) throw new Exception("Something was wrong with the server responce"); + if (request.Error is null) + { + if (chans.Count > 0 && chans.Any(s => s.Id == request.Id)) + { + foreach (MainSocketChannel? p in chans.Where(s => s.Id == request.Id)) + { + chans.Remove(p); + } + } + chans.Add(request); + return request; + } + throw request.Error switch + { + ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"), + ErrorCode.Forbidden => new Exception("The server rejected your request"), + ErrorCode.ServerError => new Exception("Error from server: " + request.ErrorMessage), + ErrorCode.InvalidURL or ErrorCode.MissingHeader => new Exception(request.ErrorMessage), + _ => new Exception($"Unknown data: '{request.ErrorMessage}'"), + }; } -#pragma warning restore CA1822 // Mark members as static - - private void ServerOut_OnError(object? sender, WebSocketSharp.ErrorEventArgs e) + + public async Task GetMessage(long id, CancellationToken CancellationToken) { - if (OnError is not null) OnError.Invoke(new Exception(e.Message)); + SocketMessage message; + while (true) + { + if (CanRequest) + { + message = await GetFromServer("socketmessage", + SocketMessageContext.Default.SocketMessage, + CancellationToken, + new System.Collections.Generic.KeyValuePair("msg_id", id.ToString())); + break; + } + } + if (message is not null) return message; + throw new Exception("Server did not return a message"); } - - [Obsolete("Move to new Data layout")] - internal static void SendServer(string data) + + /// + /// Sends the server a request to update the of you account + /// + /// The you want to set your status to + /// + public async Task UpdateStatus(UserStatus Status, CancellationToken CancellationToken) { - ServerOut?.Send(data); + IncomingHTTP? data = await SendServer("SocketUserProfile/Status", new Status() { UserStatus = Status }, StatusContext.Default.Status, IncomingHTTPContext.Default.IncomingHTTP, CancellationToken); + if (data.Error is not null && ((int)data.StatusCode < 200 || (int)data.StatusCode > 299)) + { + if (data?.ErrorMessage is not null) throw new Exception(data.ErrorMessage); + if (data?.Error is not null) throw new Exception(((int)data.Error).ToString()); + else throw new Exception("Something went worng"); + } + + (User as SocketUserBase)!.Status = Status; + return Task.CompletedTask; + } + + internal async Task GetUser(long UserId, JsonTypeInfo Json, CancellationToken CancellationToken) where Tuser : SocketUserBase, new() + { + Tuser user; + if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId)) + { + Tuser temp = poeople.Where(s => s is Tuser && s.Id == UserId).Cast().FirstOrDefault()!; + return temp; + } + while (true) + { + if (CanRequest) + { + user = await GetFromServer("socketuser", + Json, + CancellationToken, + new KeyValuePair("id", UserId.ToString())); + break; + } + } + + if (user is null) throw new Exception("Server did not return a user"); + if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId)) + { + foreach (IUser? p in poeople.Where(s => s.Id == UserId)) + { + poeople.Remove(p); + } + } + poeople.Add(user); + return user; } - internal static void SendServer(Tvalue Payload, JsonTypeInfo jsonTypeInfo) where Tvalue : IncomingWSS + public void SendServer(Tvalue Payload, JsonTypeInfo jsonTypeInfo) where Tvalue : IncomingWSS { ServerOut?.Send(JsonSerializer.Serialize(Payload, jsonTypeInfo)); } - internal static HttpResponseMessage GetFromServer(string Path, params KeyValuePair[] Headers) + public HttpResponseMessage GetFromServer(string Path, CancellationToken CancellationToken, params KeyValuePair[] Headers) { using HttpClient web = new(); web.Timeout = TimeSpan.FromSeconds(10); if (!login) web.DefaultRequestHeaders.Add("token", Token); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); - return web.GetAsync($"https://{InternalDomain}/{API_Ver}/{Path}").Result; + return web.GetAsync($"https://{Domain}/{ApiVersion}/{Path}", cancellationToken: CancellationToken).Result; } - internal static Task GetFromServer(string Path, string File, params KeyValuePair[] Headers) + public Task GetFromServer(string Path, string File, CancellationToken CancellationToken, params KeyValuePair[] Headers) { using HttpClient web = new(); web.Timeout = TimeSpan.FromMinutes(10); if (!login) web.DefaultRequestHeaders.Add("token", Token); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); - HttpResponseMessage Response = web.GetAsync($"https://{InternalDomain}/{API_Ver}/{Path}").Result; - Stream stream = Response.Content.ReadAsStreamAsync().Result; + HttpResponseMessage Response = web.GetAsync($"https://{Domain}/{ApiVersion}/{Path}", CancellationToken).Result; + Stream stream = Response.Content.ReadAsStreamAsync(CancellationToken).Result; using FileStream fs = System.IO.File.Create(File); stream.CopyTo(fs); return Task.CompletedTask; } - internal static async Task GetFromServer(string Path, JsonTypeInfo Type, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() + public async Task GetFromServer(string Path, JsonTypeInfo Type, CancellationToken CancellationToken, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() { - HttpResponseMessage ServerResponce = GetFromServer(Path, Headers); + HttpResponseMessage ServerResponce = GetFromServer(Path, CancellationToken, Headers); if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; - Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync().Result, Type); + Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).Result, Type); if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; return temp; } - internal static async Task SendServer(string Path, Tvalue Payload, JsonTypeInfo jsonTypeInfo, JsonTypeInfo ReturnjsonTypeInfo, params KeyValuePair[] Headers) where Tvalue : HTTPRequest where Tresult : IncomingHTTP, new() + public async Task SendServer(string Path, Tvalue Payload, JsonTypeInfo jsonTypeInfo, JsonTypeInfo ReturnjsonTypeInfo, CancellationToken CancellationToken, params KeyValuePair[] Headers) where Tvalue : IWebRequest where Tresult : IncomingHTTP, new() { using HttpClient web = new(); if (!login) web.DefaultRequestHeaders.Add("token", Token); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); - HttpResponseMessage ServerResponce = web.PostAsJsonAsync($"https://{InternalDomain}/{API_Ver}/{Path}", Payload, jsonTypeInfo).Result; + HttpResponseMessage ServerResponce = web.PostAsJsonAsync($"https://{Domain}/{ApiVersion}/{Path}", Payload, jsonTypeInfo, CancellationToken).Result; if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; Tresult error = new() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; - if (string.IsNullOrWhiteSpace(ServerResponce.Content.ReadAsStringAsync().Result)) return error; + if (string.IsNullOrWhiteSpace(ServerResponce.Content.ReadAsStringAsync(CancellationToken).Result)) return error; try { - Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync().Result, ReturnjsonTypeInfo); + Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).Result, ReturnjsonTypeInfo); if (temp is null) return error; return temp; } catch { return error; } } - internal static async Task SendServer(string Path, string File, JsonTypeInfo ReturnjsonTypeInfo, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() + public async Task SendServer(string Path, string File, JsonTypeInfo ReturnjsonTypeInfo, CancellationToken CancellationToken, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() { var fs = System.IO.File.OpenRead(File); try @@ -280,11 +253,11 @@ public sealed partial class Server if (!login) web.DefaultRequestHeaders.Add("token", Token); web.Timeout = new TimeSpan(0, 10, 0); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); - HttpResponseMessage ServerResponce = web.PostAsync($"https://{InternalDomain}/{API_Ver}/{Path}", new StreamContent(fs)).Result; + HttpResponseMessage ServerResponce = web.PostAsync($"https://{Domain}/{ApiVersion}/{Path}", new StreamContent(fs), CancellationToken).Result; if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; try { - Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync().Result, ReturnjsonTypeInfo); + Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).Result, ReturnjsonTypeInfo); if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; return temp; } @@ -295,4 +268,4 @@ public sealed partial class Server fs.Close(); } } -} +} \ No newline at end of file diff --git a/Luski.net/Server.old.Globals.cs b/Luski.net/Server.old.Globals.cs new file mode 100755 index 0000000..5d0d5a6 --- /dev/null +++ b/Luski.net/Server.old.Globals.cs @@ -0,0 +1,97 @@ +/*using Luski.net.Enums; +using Luski.net.Interfaces; +using Luski.net.JsonTypes; +using Luski.net.Sockets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using WebSocketSharp; + +namespace Luski.net; + +public sealed partial class Serverold +{ + internal static string JT + { + get + { + string tmp = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "JacobTech"); + if (OperatingSystem.IsLinux()) + { + tmp = Path.Combine(Environment.GetEnvironmentVariable("HOME")!, ".config/"); + tmp += "JacobTech"; + } + return tmp; + } + } + internal static SocketAudioClient? AudioClient = null; + internal static string? Token = null, Error = null; + internal static bool CanRequest = false; + internal static SocketAppUser? _user; + internal static string platform = "win-x64"; + internal static Branch Branch; + internal static double Percent = 0.5; + private static WebSocket? ServerOut; + private static string? gen = null; + private static bool login = false; + + public static SocketServer CurrentServer = null!; + + internal static string Cache + { + get + { + if (gen is null) + { + if (!Directory.Exists(JT)) Directory.CreateDirectory(JT); + string path = JT + "/Luski/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += Branch.ToString() + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += platform + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += "Data/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += _user?.Id + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += "Cache/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += Path.GetRandomFileName() + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + gen = path; + } + if (!Directory.Exists($"{gen}/avatars")) Directory.CreateDirectory($"{gen}/avatars"); + if (!Directory.Exists($"{gen}/channels")) Directory.CreateDirectory($"{gen}/channels"); + return gen; + } + } + internal static List poeople = new(); + internal static List chans { get; set; } = new(); + internal static string GetKeyFilePath + { + get + { + return GetKeyFilePathBr(Branch.ToString()); + } + } + + internal static string GetKeyFilePathBr(string br) + { + if (!Directory.Exists(JT)) Directory.CreateDirectory(JT); + string path = JT + "/Luski/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += br + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += platform + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += "Data/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += _user?.Id + "/"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path += "keys.lsk"; + return path; + } +} +*/ \ No newline at end of file diff --git a/Luski.net/Server.old.cs b/Luski.net/Server.old.cs new file mode 100755 index 0000000..025c3ea --- /dev/null +++ b/Luski.net/Server.old.cs @@ -0,0 +1,281 @@ +/*using Luski.net.Enums; +using Luski.net.Interfaces; +using Luski.net.JsonTypes; +using Luski.net.JsonTypes.BaseTypes; +using Luski.net.JsonTypes.HTTP; +using Luski.net.Sockets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Json; +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; + +namespace Luski.net; + +public sealed partial class Serverold +{ +#pragma warning disable CA1822 // Mark members as static + public async Task SendFriendResult(long user, bool answer, CancellationToken CancellationToken) + { + + FriendRequestResult json = await SendServer(_user!.Servers.First(),"FriendRequestResult", + new FriendRequestResultOut() + { + Id = user, + Result = answer + }, + FriendRequestResultOutContext.Default.FriendRequestResultOut, + FriendRequestResultContext.Default.FriendRequestResult, + CancellationToken); + + if (json is not null && json.Error is null && json.ErrorMessage is null && answer && json.Channel is not null) + { + SocketDMChannel chan = await SocketChannel.GetChannel((long)json.Channel, SocketDMChannelContext.Default.SocketDMChannel, CancellationToken, _user!.Servers.First()); + _ = chan.StartKeyProcessAsync(CancellationToken); + chans.Add(chan); + } + else + { + throw new Exception(json?.Error.ToString()); + } + return SocketUserBase.GetUser(user, SocketRemoteUserContext.Default.SocketRemoteUser, CancellationToken, _user!.Servers.First()).Result; + } + + public async Task SendFriendRequest(long code, CancellationToken CancellationToken) + { + string ccode = Convert.ToBase64String(Encryption.Hash(Encryption.Encoder.GetBytes(code.ToString()))); + FriendRequestResult? json = await SendServer(_user!.Servers.First(),"FriendRequest", new FriendRequest() { code = ccode}, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult, CancellationToken); + + if (json.StatusCode != HttpStatusCode.Accepted) + { + if (json is not null && json.Error is not null) + { + switch ((ErrorCode)(int)json.Error) + { + case ErrorCode.InvalidToken: + throw new Exception("Your current token is no longer valid"); + case ErrorCode.ServerError: + throw new Exception($"Error from server: {json.ErrorMessage}"); + case ErrorCode.InvalidPostData: + throw new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version"); + case ErrorCode.Forbidden: + throw new Exception("You already have an outgoing request or the persone is not real"); + } + } + + if (json is not null && json.Channel is not null) + { + SocketDMChannel chan = await SocketChannel.GetChannel((long)json.Channel, (JsonTypeInfo)SocketDMChannelContext.Default.SocketDMChannel, CancellationToken, _user!.Servers.First()); + _ = chan.StartKeyProcessAsync(CancellationToken); + chans.Add(chan); + } + } + + MainSocketRemoteUser b = await SocketUserBase.GetUser(code, SocketRemoteUserContext.Default.SocketRemoteUser, CancellationToken, _user!.Servers.First()); + if (json.Channel is not null) + b.FriendStatus = FriendStatus.Friends; + else + b.FriendStatus = FriendStatus.PendingOut; + return b; + } + + /// + /// Sends the server a request to update the of you account + /// + /// The you want to set your status to + /// + public async Task UpdateStatus(UserStatus Status, CancellationToken CancellationToken) + { + if (_user is null) throw new Exception("You must login to make a request"); + IncomingHTTP? data = await SendServer(_user!.Servers.First(),"SocketUserProfile/Status", new Status() { UserStatus = Status }, StatusContext.Default.Status, IncomingHTTPContext.Default.IncomingHTTP, CancellationToken); + if (data.Error is not null && ((int)data.StatusCode < 200 || (int)data.StatusCode > 299)) + { + if (data?.ErrorMessage is not null) throw new Exception(data.ErrorMessage); + if (data?.Error is not null) throw new Exception(((int)data.Error).ToString()); + else throw new Exception("Something went worng"); + } + + _user.Status = Status; + return Task.CompletedTask; + } + + public async Task ChangeChannel(long Channel, CancellationToken CancellationToken, SocketServer Server) + { + if (_user is null) throw new Exception("You must login to make a request"); + IncomingHTTP? data = await SendServer(Server, "ChangeChannel", new Channel() { Id = Channel }, ChannelContext.Default.Channel, IncomingHTTPContext.Default.IncomingHTTP, CancellationToken); + if (data.StatusCode != HttpStatusCode.Accepted) + { + if (data?.Error is not null) + { + switch (data.Error) + { + case ErrorCode.InvalidToken: + throw new Exception("Your current token is no longer valid"); + case ErrorCode.ServerError: + throw new Exception("Error from server: " + data.ErrorMessage); + } + } + else throw new Exception("Something went worng"); + } + + _user.SelectedChannel = Channel; + } + + public Task SendMessage(string Message, long Channel, SocketServer Server, CancellationToken CancellationToken, params JsonTypes.File[] Files) + { + try + { + _ = GetChannel(Channel, CancellationToken, Server).Result.SendMessage(Message, CancellationToken, Files); + } + catch (Exception e) + { + if (OnError is not null) _ = OnError.Invoke(e); + else throw e; + } + + return Task.CompletedTask; + } + + public void SetMultiThreadPercent(double num) + { + if (num < 1 || num > 100) throw new Exception("Number must be from 1 - 100"); + Percent = num / 100; + } + + public async Task GetMessage(long MessageId, CancellationToken CancellationToken, SocketServer Server) => await SocketMessage.GetMessage(MessageId, CancellationToken, Server); + + public async Task GetUser(long UserID, CancellationToken CancellationToken, SocketServer Server) => await SocketUserBase.GetUser(UserID, SocketRemoteUserContext.Default.SocketRemoteUser, CancellationToken, Server); + + public async Task GetChannel(long Channel, CancellationToken CancellationToken, SocketServer Server) where TChannel : SocketChannel, new() + { + TChannel Return = new(); + switch (Return) + { + case SocketDMChannel: + Return = (await SocketChannel.GetChannel(Channel, SocketDMChannelContext.Default.SocketDMChannel, CancellationToken, Server) as TChannel)!; + break; + case SocketGroupChannel: + Return = (await SocketChannel.GetChannel(Channel, SocketGroupChannelContext.Default.SocketGroupChannel, CancellationToken, Server) as TChannel)!; + break; + case SocketTextChannel: + Return = (await SocketChannel.GetChannel(Channel, SocketTextChannelContext.Default.SocketTextChannel, CancellationToken, Server) as TChannel)!; + break; + case SocketChannel: + Return = (await SocketChannel.GetChannel(Channel, SocketChannelContext.Default.SocketChannel, CancellationToken, Server) as TChannel)!; + break; + case null: + throw new NullReferenceException(nameof(TChannel)); + default: + throw new Exception("Unknown channel type"); + } + return Return; + } + + + public SocketAppUser CurrentUser + { + get + { + if (_user is null) throw new Exception("You must Login first"); + return _user; + } + } +#pragma warning restore CA1822 // Mark members as static + + private void ServerOut_OnError(object? sender, WebSocketSharp.ErrorEventArgs e) + { + if (OnError is not null) OnError.Invoke(new Exception(e.Message)); + } + + [Obsolete("Move to new Data layout")] + internal static void SendServer(string data) + { + ServerOut?.Send(data); + } + + internal static void SendServer(Tvalue Payload, JsonTypeInfo jsonTypeInfo) where Tvalue : IncomingWSS + { + ServerOut?.Send(JsonSerializer.Serialize(Payload, jsonTypeInfo)); + } + + internal static HttpResponseMessage GetFromServer(SocketServer Server, string Path, CancellationToken CancellationToken, params KeyValuePair[] Headers) + { + using HttpClient web = new(); + web.Timeout = TimeSpan.FromSeconds(10); + if (!login) web.DefaultRequestHeaders.Add("token", Token); + if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); + return web.GetAsync($"https://{Server.Domain}/{Server.ApiVersion}/{Path}", cancellationToken: CancellationToken).Result; + } + + internal static Task GetFromServer(SocketServer Server, string Path, string File, CancellationToken CancellationToken, params KeyValuePair[] Headers) + { + using HttpClient web = new(); + web.Timeout = TimeSpan.FromMinutes(10); + if (!login) web.DefaultRequestHeaders.Add("token", Token); + if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); + HttpResponseMessage Response = web.GetAsync($"https://{Server.Domain}/{Server.ApiVersion}/{Path}", CancellationToken).Result; + Stream stream = Response.Content.ReadAsStreamAsync(CancellationToken).Result; + using FileStream fs = System.IO.File.Create(File); + stream.CopyTo(fs); + return Task.CompletedTask; + } + + internal static async Task GetFromServer(SocketServer Server, string Path, JsonTypeInfo Type, CancellationToken CancellationToken, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() + { + HttpResponseMessage ServerResponce = GetFromServer(Server, Path, CancellationToken, Headers); + if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; + Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).Result, Type); + if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; + return temp; + } + + internal static async Task SendServer(SocketServer Server, string Path, Tvalue Payload, JsonTypeInfo jsonTypeInfo, JsonTypeInfo ReturnjsonTypeInfo, CancellationToken CancellationToken, params KeyValuePair[] Headers) where Tvalue : IWebRequest where Tresult : IncomingHTTP, new() + { + using HttpClient web = new(); + if (!login) web.DefaultRequestHeaders.Add("token", Token); + if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); + HttpResponseMessage ServerResponce = web.PostAsJsonAsync($"https://{Server.Domain}/{Server.ApiVersion}/{Path}", Payload, jsonTypeInfo, CancellationToken).Result; + if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; + Tresult error = new() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; + if (string.IsNullOrWhiteSpace(ServerResponce.Content.ReadAsStringAsync(CancellationToken).Result)) return error; + try + { + Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).Result, ReturnjsonTypeInfo); + if (temp is null) return error; + return temp; + } + catch { return error; } + } + + internal static async Task SendServer(SocketServer Server, string Path, string File, JsonTypeInfo ReturnjsonTypeInfo, CancellationToken CancellationToken, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() + { + var fs = System.IO.File.OpenRead(File); + try + { + using HttpClient web = new(); + if (!login) web.DefaultRequestHeaders.Add("token", Token); + web.Timeout = new TimeSpan(0, 10, 0); + if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); + HttpResponseMessage ServerResponce = web.PostAsync($"https://{Server.Domain}/{Server.ApiVersion}/{Path}", new StreamContent(fs), CancellationToken).Result; + if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; + try + { + Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).Result, ReturnjsonTypeInfo); + if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; + return temp; + } + catch { return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; } + } + finally + { + fs.Close(); + } + } +} +*/ \ No newline at end of file diff --git a/Luski.net/Sockets/SocketAudioClient.cs b/Luski.net/Sockets/SocketAudioClient.cs deleted file mode 100755 index 7388aaa..0000000 --- a/Luski.net/Sockets/SocketAudioClient.cs +++ /dev/null @@ -1,388 +0,0 @@ -using Luski.net.Enums; -using Luski.net.Interfaces; -using Luski.net.JsonTypes.BaseTypes; -using Luski.net.Sound; -using System; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; -using static Luski.net.Exceptions; - -namespace Luski.net.Sockets -{ - internal class SocketAudioClient : IAudioClient - { - internal SocketAudioClient(long Channel, Func? error) - { - this.Channel = Channel; - errorin = error; - Muted = false; - PrototolClient.DataComplete += new Protocol.DelegateDataComplete(OnProtocolClient_DataComplete); - DataRecived += SocketAudioClient_DataRecived; - } - - public event Func? Connected; - - public bool Muted { get; private set; } - - public bool Deafened { get; private set; } - - public void ToggleMic() - { - if (Muted == true) - { - Muted = false; - } - else - { - Muted = true; - } - } - - public void ToggleAudio() - { - if (Deafened == true) - { - Deafened = false; - } - else - { - Deafened = true; - } - } - - public void RecordSoundFrom(RecordingDevice Device) - { - if (Connectedb) - { - StartRecordingFromSounddevice_Client(Device); - } - else - { - throw new NotConnectedException(this, "The call has not been connected yet!"); - } - } - - public void PlaySoundTo(PlaybackDevice Device) - { - if (Connectedb) - { - StartPlayingToSounddevice_Client(Device); - } - else - { - throw new NotConnectedException(this, "The call has not been connected yet!"); - } - } - - public void JoinCall() - { - if (Connected == null) - { - throw new MissingEventException("Connected"); - } - else - { - //get info - string data; - while (true) - { - if (Server.CanRequest) - { - using HttpClient web = new(); - web.DefaultRequestHeaders.Add("token", Server.Token); - web.DefaultRequestHeaders.Add("id", Channel.ToString()); - data = web.GetAsync($"https://{Server.InternalDomain}/{Server.API_Ver}/GetCallInfo").Result.Content.ReadAsStringAsync().Result; - break; - } - } - call? json = JsonSerializer.Deserialize(data); - Server.SendServer(JsonRequest.Send(DataType.Join_Call, JsonRequest.JoinCall(Channel)).ToString()); - Samples = json.samples; - } - } - - private class call : IncomingHTTP - { - public int samples { get; set; } = default!; - public string[] members { get; set; } = default!; - } - - public void LeaveCall() - { - Server.SendServer(JsonRequest.Send(DataType.Leave_Call, JsonRequest.JoinCall(Channel)).ToString()); - StopRecordingFromSounddevice_Client(); - } - - private readonly Protocol PrototolClient = new(ProtocolTypes.LH, Encoding.Default); - private JitterBuffer RecordingJitterBuffer = new(null, JitterBuffer, 20); - private JitterBuffer PlayingJitterBuffer = new(null, JitterBuffer, 20); - private readonly Func? errorin; - private event Func DataRecived; - private static readonly uint JitterBuffer = 5; - private readonly int BitsPerSample = 16; - private long SequenceNumber = 4596; - private readonly int Channels = 1; - private Recorder? RecorderClient; - private bool Connectedb = false; - private bool recording = false; - private long m_TimeStamp = 0; - private Player? PlayerClient; - private readonly long Channel; - - private void StopPlayingToSounddevice_Client() - { - if (PlayerClient != null) - { - PlayerClient.Close(); - PlayerClient = null; - } - - if (PlayingJitterBuffer != null) - { - PlayingJitterBuffer.Stop(); - } - } - - private async Task SocketAudioClient_DataRecived(string arg) - { - cdata d = JsonSerializer.Deserialize(arg); - byte[] data = Convert.FromBase64String(d.data); - PrototolClient.Receive_LH(this, data); - } - - private class cdata - { - public string data { get; set; } = default!; - public long from { get; set; } = default!; - } - - private void SendData(byte[] data) - { - if (!Connectedb) - { - return; - } - - Server.SendServer(JsonRequest.Send(DataType.Call_Data, JsonRequest.SendCallData(PrototolClient.ToBytes(data), Channel))); - } - - internal void Givedata(dynamic data) - { - DataRecived.Invoke(((object)data).ToString()); - } - - private int _samp; - - internal int Samples - { - get => _samp; - set - { - _samp = value; - Connectedb = true; - if (Connected is not null) Connected.Invoke(); - PlaySoundTo(Devices.GetDefaltPlaybackDevice()); - RecordSoundFrom(Devices.GetDefaltRecordingDevice()); - } - } - - private bool playing = false; - - private void StartPlayingToSounddevice_Client(PlaybackDevice device) - { - if (playing) - { - StopPlayingToSounddevice_Client(); - } - playing = true; - if (PlayingJitterBuffer != null) - { - PlayingJitterBuffer.DataAvailable -= new JitterBuffer.DelegateDataAvailable(OnJitterBufferClientDataAvailablePlaying); - - PlayingJitterBuffer = new JitterBuffer(null, JitterBuffer, 20); - PlayingJitterBuffer.DataAvailable += new JitterBuffer.DelegateDataAvailable(OnJitterBufferClientDataAvailablePlaying); - PlayingJitterBuffer.Start(); - } - - if (PlayerClient == null) - { - PlayerClient = new Player(); - PlayerClient.Open(device.Name, Samples, BitsPerSample, Channels, (int)JitterBuffer); - } - } - - private void OnJitterBufferClientDataAvailablePlaying(object sender, RTPPacket rtp) - { - try - { - if (PlayerClient != null) - { - if (PlayerClient.Opened) - { - if (Deafened == false) - { - byte[] linearBytes = Utils.MuLawToLinear(rtp.Data, BitsPerSample, Channels); - PlayerClient.PlayData(linearBytes, false); - } - } - } - } - catch (Exception ex) - { - System.Diagnostics.StackFrame sf = new(true); - errorin?.Invoke(new Exception(string.Format("Exception: {0} StackTrace: {1}. FileName: {2} Method: {3} Line: {4}", ex.Message, ex.StackTrace, sf.GetFileName(), sf.GetMethod(), sf.GetFileLineNumber()))); - } - } - - private void StartRecordingFromSounddevice_Client(RecordingDevice device) - { - try - { - if (recording) - { - StopRecordingFromSounddevice_Client(); - } - recording = true; - InitJitterBufferClientRecording(); - int bufferSize = 0; - bufferSize = Utils.GetBytesPerInterval((uint)Samples, BitsPerSample, Channels) * 4; - - if (bufferSize > 0) - { - RecorderClient = new Recorder(); - RecorderClient.DataRecorded += new Recorder.DelegateDataRecorded(OnDataReceivedFromSoundcard_Client); - - if (RecorderClient.Start(device.Name, Samples, BitsPerSample, Channels, 8, bufferSize)) - { - - RecordingJitterBuffer.Start(); - } - } - } - catch (Exception ex) - { - errorin.Invoke(ex); - } - } - - private void StopRecordingFromSounddevice_Client() - { - RecorderClient.Stop(); - - RecorderClient.DataRecorded -= new Recorder.DelegateDataRecorded(OnDataReceivedFromSoundcard_Client); - RecorderClient = null; - - RecordingJitterBuffer.Stop(); - } - - private void InitJitterBufferClientRecording() - { - if (RecordingJitterBuffer != null) - { - RecordingJitterBuffer.DataAvailable -= new JitterBuffer.DelegateDataAvailable(OnJitterBufferClientDataAvailableRecording); - } - - RecordingJitterBuffer = new JitterBuffer(null, 8, 20); - RecordingJitterBuffer.DataAvailable += new JitterBuffer.DelegateDataAvailable(OnJitterBufferClientDataAvailableRecording); - } - - private void OnJitterBufferClientDataAvailableRecording(object sender, RTPPacket rtp) - { - if (Muted == false && rtp != null && rtp.Data != null && rtp.Data.Length > 0) - { - byte[] rtpBytes = rtp.ToBytes(); - SendData(rtpBytes); - } - } - - private void OnDataReceivedFromSoundcard_Client(byte[] data) - { - try - { - lock (this) - { - int bytesPerInterval = Utils.GetBytesPerInterval((uint)Samples, BitsPerSample, Channels); - int count = data.Length / bytesPerInterval; - int currentPos = 0; - for (int i = 0; i < count; i++) - { - byte[] partBytes = new byte[bytesPerInterval]; - Array.Copy(data, currentPos, partBytes, 0, bytesPerInterval); - currentPos += bytesPerInterval; - RTPPacket rtp = ToRTPPacket(partBytes, BitsPerSample, Channels); - - RecordingJitterBuffer.AddData(rtp); - } - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(ex.Message); - } - } - - private RTPPacket ToRTPPacket(byte[] linearData, int bitsPerSample, int channels) - { - byte[] mulaws = Utils.LinearToMulaw(linearData, bitsPerSample, channels); - - RTPPacket rtp = new() - { - Data = mulaws, - CSRCCount = 0, - Extension = false, - HeaderLength = RTPPacket.MinHeaderLength, - Marker = false, - Padding = false, - PayloadType = 0, - Version = 2, - SourceId = 0 - }; - - try - { - rtp.SequenceNumber = Convert.ToUInt16(SequenceNumber); - SequenceNumber++; - } - catch (Exception) - { - SequenceNumber = 0; - } - try - { - rtp.Timestamp = Convert.ToUInt32(m_TimeStamp); - m_TimeStamp += mulaws.Length; - } - catch (Exception) - { - m_TimeStamp = 0; - } - - return rtp; - } - - private void OnProtocolClient_DataComplete(object sender, byte[] data) - { - try - { - if (PlayerClient != null && PlayerClient.Opened) - { - RTPPacket rtp = new(data); - - if (rtp.Data != null) - { - if (PlayingJitterBuffer != null) - { - PlayingJitterBuffer.AddData(rtp); - } - } - } - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - } -} diff --git a/Luski.net/Sound/Devices.cs b/Luski.net/Sound/Devices.cs deleted file mode 100755 index 8bf90f2..0000000 --- a/Luski.net/Sound/Devices.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Collections.Generic; - -namespace Luski.net.Sound -{ - public static class Devices - { - public static RecordingDevice GetDefaltRecordingDevice() - { - return GetRecordingDevices()[0]; - } - - public static PlaybackDevice GetDefaltPlaybackDevice() - { - return GetPlaybackDevices()[0]; - } - - public static IReadOnlyList GetRecordingDevices() - { - List RecordingNames = WinSound.GetRecordingNames(); - List RecordingDevices = new(); - foreach (string Device in RecordingNames) - { - RecordingDevices.Add(new RecordingDevice(Device)); - } - return RecordingDevices.AsReadOnly(); - } - public static IReadOnlyList GetPlaybackDevices() - { - List PlaybackName = WinSound.GetPlaybackNames(); - List PlaybackDevices = new(); - foreach (string Device in PlaybackName) - { - PlaybackDevices.Add(new PlaybackDevice(Device)); - } - return PlaybackDevices.AsReadOnly(); - } - } - - public class RecordingDevice - { - internal RecordingDevice(string name) - { - Name = name; - } - - public string Name { get; } - } - - public class PlaybackDevice - { - internal PlaybackDevice(string name) - { - Name = name; - } - - public string Name { get; } - } -} diff --git a/Luski.net/Sound/JitterBuffer.cs b/Luski.net/Sound/JitterBuffer.cs deleted file mode 100755 index 27348ab..0000000 --- a/Luski.net/Sound/JitterBuffer.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Luski.net.Sound -{ - internal class JitterBuffer - { - internal JitterBuffer(object? sender, uint maxRTPPackets, uint timerIntervalInMilliseconds) - { - if (maxRTPPackets < 2) - { - throw new Exception("Wrong Arguments. Minimum maxRTPPackets is 2"); - } - - m_Sender = sender; - Maximum = maxRTPPackets; - IntervalInMilliseconds = timerIntervalInMilliseconds; - - Init(); - } - - private readonly object? m_Sender = null; - private readonly EventTimer m_Timer = new(); - private readonly Queue m_Buffer = new(); - private RTPPacket m_LastRTPPacket = new(); - private bool m_Underflow = true; - private bool m_Overflow = false; - - internal delegate void DelegateDataAvailable(object sender, RTPPacket packet); - internal event DelegateDataAvailable? DataAvailable; - - internal uint Maximum { get; } = 10; - internal uint IntervalInMilliseconds { get; } = 20; - private void Init() - { - InitTimer(); - } - private void InitTimer() - { - m_Timer.TimerTick += new EventTimer.DelegateTimerTick(OnTimerTick); - } - internal void Start() - { - m_Timer.Start(IntervalInMilliseconds); - m_Underflow = true; - } - internal void Stop() - { - m_Timer.Stop(); - m_Buffer.Clear(); - } - private void OnTimerTick() - { - try - { - if (DataAvailable != null) - { - if (m_Buffer.Count > 0) - { - if (m_Overflow) - { - if (m_Buffer.Count <= Maximum / 2) - { - m_Overflow = false; - } - } - - if (m_Underflow) - { - if (m_Buffer.Count < Maximum / 2) - { - return; - } - else - { - m_Underflow = false; - } - } - - m_LastRTPPacket = m_Buffer.Dequeue(); - DataAvailable(m_Sender, m_LastRTPPacket); - } - else - { - m_Overflow = false; - - if (m_LastRTPPacket != null && m_Underflow == false) - { - if (m_LastRTPPacket.Data != null) - { - m_Underflow = true; - } - } - } - } - } - catch (Exception ex) - { - Console.WriteLine(string.Format("JitterBuffer.cs | OnTimerTick() | {0}", ex.Message)); - } - } - internal void AddData(RTPPacket packet) - { - try - { - if (m_Overflow == false) - { - if (m_Buffer.Count <= Maximum) - { - m_Buffer.Enqueue(packet); - } - else - { - m_Overflow = true; - } - } - } - catch (Exception ex) - { - Console.WriteLine(string.Format("JitterBuffer.cs | AddData() | {0}", ex.Message)); - } - } - } -} diff --git a/Luski.net/Sound/Player.cs b/Luski.net/Sound/Player.cs deleted file mode 100755 index 173594d..0000000 --- a/Luski.net/Sound/Player.cs +++ /dev/null @@ -1,417 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Threading; - -namespace Luski.net.Sound -{ - internal unsafe class Player - { - internal Player() - { - - delegateWaveOutProc = new Win32.DelegateWaveOutProc(WaveOutProc); - } - - private readonly LockerClass Locker = new(); - private readonly LockerClass LockerCopy = new(); - private IntPtr hWaveOut = IntPtr.Zero; - private string WaveOutDeviceName = ""; - private bool IsWaveOutOpened = false; - private bool IsThreadPlayWaveOutRunning = false; - private bool IsClosed = false; - private bool IsPaused = false; - private bool IsStarted = false; - private bool IsBlocking = false; - private int SamplesPerSecond = 8000; - private int BitsPerSample = 16; - private int Channels = 1; - private int BufferCount = 8; - private readonly int BufferLength = 1024; - private Win32.WAVEHDR*[] WaveOutHeaders; - private readonly Win32.DelegateWaveOutProc delegateWaveOutProc; - private Thread? ThreadPlayWaveOut; - private readonly AutoResetEvent AutoResetEventDataPlayed = new(false); - - internal delegate void DelegateStopped(); - internal event DelegateStopped? PlayerClosed; - internal event DelegateStopped? PlayerStopped; - - internal bool Opened => IsWaveOutOpened & IsClosed == false; - - internal bool Playing - { - get - { - if (Opened && IsStarted) - { - foreach (Win32.WAVEHDR* pHeader in WaveOutHeaders) - { - if (IsHeaderInqueue(*pHeader)) - { - return true; - } - } - } - return false; - } - } - - private bool CreateWaveOutHeaders() - { - WaveOutHeaders = new Win32.WAVEHDR*[BufferCount]; - int createdHeaders = 0; - - for (int i = 0; i < BufferCount; i++) - { - WaveOutHeaders[i] = (Win32.WAVEHDR*)Marshal.AllocHGlobal(sizeof(Win32.WAVEHDR)); - - WaveOutHeaders[i]->dwLoops = 0; - WaveOutHeaders[i]->dwUser = IntPtr.Zero; - WaveOutHeaders[i]->lpNext = IntPtr.Zero; - WaveOutHeaders[i]->reserved = IntPtr.Zero; - WaveOutHeaders[i]->lpData = Marshal.AllocHGlobal(BufferLength); - WaveOutHeaders[i]->dwBufferLength = (uint)BufferLength; - WaveOutHeaders[i]->dwBytesRecorded = 0; - WaveOutHeaders[i]->dwFlags = 0; - - Win32.MMRESULT hr = Win32.waveOutPrepareHeader(hWaveOut, WaveOutHeaders[i], sizeof(Win32.WAVEHDR)); - if (hr == Win32.MMRESULT.MMSYSERR_NOERROR) - { - createdHeaders++; - } - } - - return (createdHeaders == BufferCount); - } - - private void FreeWaveOutHeaders() - { - try - { - if (WaveOutHeaders != null) - { - for (int i = 0; i < WaveOutHeaders.Length; i++) - { - Win32.MMRESULT hr = Win32.waveOutUnprepareHeader(hWaveOut, WaveOutHeaders[i], sizeof(Win32.WAVEHDR)); - - int count = 0; - while (count <= 100 && (WaveOutHeaders[i]->dwFlags & Win32.WaveHdrFlags.WHDR_INQUEUE) == Win32.WaveHdrFlags.WHDR_INQUEUE) - { - Thread.Sleep(20); - count++; - } - - if ((WaveOutHeaders[i]->dwFlags & Win32.WaveHdrFlags.WHDR_INQUEUE) != Win32.WaveHdrFlags.WHDR_INQUEUE) - { - if (WaveOutHeaders[i]->lpData != IntPtr.Zero) - { - Marshal.FreeHGlobal(WaveOutHeaders[i]->lpData); - WaveOutHeaders[i]->lpData = IntPtr.Zero; - } - } - } - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.Write(ex.Message); - } - } - - private void StartThreadPlayWaveOut() - { - if (IsThreadPlayWaveOutRunning == false) - { - ThreadPlayWaveOut = new System.Threading.Thread(new System.Threading.ThreadStart(OnThreadPlayWaveOut)); - IsThreadPlayWaveOutRunning = true; - ThreadPlayWaveOut.Name = "PlayWaveOut"; - ThreadPlayWaveOut.Priority = System.Threading.ThreadPriority.Highest; - ThreadPlayWaveOut.Start(); - } - } - - private bool OpenWaveOut() - { - if (hWaveOut == IntPtr.Zero) - { - if (IsWaveOutOpened == false) - { - Win32.WAVEFORMATEX waveFormatEx = new() - { - wFormatTag = (ushort)Win32.WaveFormatFlags.WAVE_FORMAT_PCM, - nChannels = (ushort)Channels, - nSamplesPerSec = (ushort)SamplesPerSecond, - wBitsPerSample = (ushort)BitsPerSample - }; - waveFormatEx.nBlockAlign = (ushort)((waveFormatEx.wBitsPerSample * waveFormatEx.nChannels) >> 3); - waveFormatEx.nAvgBytesPerSec = waveFormatEx.nBlockAlign * waveFormatEx.nSamplesPerSec; - - int deviceId = WinSound.GetWaveOutDeviceIdByName(WaveOutDeviceName); - Win32.MMRESULT hr = Win32.waveOutOpen(ref hWaveOut, deviceId, ref waveFormatEx, delegateWaveOutProc, 0, (int)Win32.WaveProcFlags.CALLBACK_FUNCTION); - - if (hr != Win32.MMRESULT.MMSYSERR_NOERROR) - { - IsWaveOutOpened = false; - return false; - } - - GCHandle.Alloc(hWaveOut, GCHandleType.Pinned); - } - } - - IsWaveOutOpened = true; - return true; - } - - internal bool Open(string waveOutDeviceName, int samplesPerSecond, int bitsPerSample, int channels, int bufferCount) - { - try - { - lock (Locker) - { - if (Opened == false) - { - - WaveOutDeviceName = waveOutDeviceName; - SamplesPerSecond = samplesPerSecond; - BitsPerSample = bitsPerSample; - Channels = channels; - BufferCount = Math.Max(bufferCount, 1); - - if (OpenWaveOut()) - { - if (CreateWaveOutHeaders()) - { - StartThreadPlayWaveOut(); - IsClosed = false; - return true; - } - } - } - - return false; - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Start | {0}", ex.Message)); - return false; - } - } - - internal bool PlayData(byte[] datas, bool isBlocking) - { - try - { - if (Opened) - { - int index = GetNextFreeWaveOutHeaderIndex(); - if (index != -1) - { - IsBlocking = isBlocking; - - if (WaveOutHeaders[index]->dwBufferLength != datas.Length) - { - Marshal.FreeHGlobal(WaveOutHeaders[index]->lpData); - WaveOutHeaders[index]->lpData = Marshal.AllocHGlobal(datas.Length); - WaveOutHeaders[index]->dwBufferLength = (uint)datas.Length; - } - - WaveOutHeaders[index]->dwBufferLength = (uint)datas.Length; - WaveOutHeaders[index]->dwUser = (IntPtr)index; - Marshal.Copy(datas, 0, WaveOutHeaders[index]->lpData, datas.Length); - - IsStarted = true; - Win32.MMRESULT hr = Win32.waveOutWrite(hWaveOut, WaveOutHeaders[index], sizeof(Win32.WAVEHDR)); - if (hr == Win32.MMRESULT.MMSYSERR_NOERROR) - { - if (isBlocking) - { - AutoResetEventDataPlayed.WaitOne(); - AutoResetEventDataPlayed.Set(); - } - return true; - } - else - { - AutoResetEventDataPlayed.Set(); - return false; - } - } - else - { - System.Diagnostics.Debug.WriteLine(string.Format("No free WaveOut Buffer found | {0}", DateTime.Now.ToLongTimeString())); - return false; - } - } - else - { - return false; - } - - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("PlayData | {0}", ex.Message)); - return false; - } - } - - internal bool Close() - { - try - { - lock (Locker) - { - if (Opened) - { - IsClosed = true; - - int count = 0; - while (Win32.waveOutReset(hWaveOut) != Win32.MMRESULT.MMSYSERR_NOERROR && count <= 100) - { - Thread.Sleep(50); - count++; - } - - FreeWaveOutHeaders(); - - count = 0; - while (Win32.waveOutClose(hWaveOut) != Win32.MMRESULT.MMSYSERR_NOERROR && count <= 100) - { - Thread.Sleep(50); - count++; - } - - IsWaveOutOpened = false; - AutoResetEventDataPlayed.Set(); - return true; - } - return false; - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Close | {0}", ex.Message)); - return false; - } - } - - private int GetNextFreeWaveOutHeaderIndex() - { - for (int i = 0; i < WaveOutHeaders.Length; i++) - { - if (IsHeaderPrepared(*WaveOutHeaders[i]) && !IsHeaderInqueue(*WaveOutHeaders[i])) - { - return i; - } - } - return -1; - } - - private static bool IsHeaderPrepared(Win32.WAVEHDR header) - { - return (header.dwFlags & Win32.WaveHdrFlags.WHDR_PREPARED) > 0; - } - - private static bool IsHeaderInqueue(Win32.WAVEHDR header) - { - return (header.dwFlags & Win32.WaveHdrFlags.WHDR_INQUEUE) > 0; - } - - private void WaveOutProc(IntPtr hWaveOut, Win32.WOM_Messages msg, IntPtr dwInstance, Win32.WAVEHDR* pWaveHeader, IntPtr lParam) - { - try - { - switch (msg) - { - //Open - case Win32.WOM_Messages.OPEN: - break; - - //Done - case Win32.WOM_Messages.DONE: - IsStarted = true; - AutoResetEventDataPlayed.Set(); - break; - - //Close - case Win32.WOM_Messages.CLOSE: - IsStarted = false; - IsWaveOutOpened = false; - IsPaused = false; - IsClosed = true; - AutoResetEventDataPlayed.Set(); - hWaveOut = IntPtr.Zero; - break; - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Player.cs | waveOutProc() | {0}", ex.Message)); - AutoResetEventDataPlayed.Set(); - } - } - - private void OnThreadPlayWaveOut() - { - while (Opened && !IsClosed) - { - AutoResetEventDataPlayed.WaitOne(); - - lock (Locker) - { - if (Opened && !IsClosed) - { - IsThreadPlayWaveOutRunning = true; - - if (!Playing) - { - if (IsStarted) - { - IsStarted = false; - if (PlayerStopped != null) - { - try - { - PlayerStopped(); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Player Stopped | {0}", ex.Message)); - } - finally - { - AutoResetEventDataPlayed.Set(); - } - } - } - } - } - } - - if (IsBlocking) - { - AutoResetEventDataPlayed.Set(); - } - } - - lock (Locker) - { - IsThreadPlayWaveOutRunning = false; - } - - if (PlayerClosed != null) - { - try - { - PlayerClosed(); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Player Closed | {0}", ex.Message)); - } - } - } - } -} diff --git a/Luski.net/Sound/Protocol.cs b/Luski.net/Sound/Protocol.cs deleted file mode 100755 index 2ba7550..0000000 --- a/Luski.net/Sound/Protocol.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Luski.net.Sound -{ - internal enum ProtocolTypes - { - LH - } - - internal class Protocol - { - internal Protocol(ProtocolTypes type, Encoding encoding) - { - m_ProtocolType = type; - m_Encoding = encoding; - } - - private readonly List m_DataBuffer = new(); - private const int m_MaxBufferLength = 10000; - private readonly ProtocolTypes m_ProtocolType = ProtocolTypes.LH; - private readonly Encoding m_Encoding = Encoding.Default; - internal object m_LockerReceive = new(); - - internal delegate void DelegateDataComplete(object sender, byte[] data); - internal delegate void DelegateExceptionAppeared(object sender, Exception ex); - internal event DelegateDataComplete DataComplete; - internal event DelegateExceptionAppeared ExceptionAppeared; - - internal byte[] ToBytes(byte[] data) - { - try - { - byte[] bytesLength = BitConverter.GetBytes(data.Length); - - byte[] allBytes = new byte[bytesLength.Length + data.Length]; - Array.Copy(bytesLength, allBytes, bytesLength.Length); - Array.Copy(data, 0, allBytes, bytesLength.Length, data.Length); - - return allBytes; - } - catch (Exception ex) - { - ExceptionAppeared(null, ex); - } - - return data; - } - - internal void Receive_LH(object sender, byte[] data) - { - lock (m_LockerReceive) - { - try - { - m_DataBuffer.AddRange(data); - - if (m_DataBuffer.Count > m_MaxBufferLength) - { - m_DataBuffer.Clear(); - } - - byte[] bytes = m_DataBuffer.Take(4).ToArray(); - int length = BitConverter.ToInt32(bytes.ToArray(), 0); - - if (length > m_MaxBufferLength) - { - m_DataBuffer.Clear(); - } - - while (m_DataBuffer.Count >= length + 4) - { - byte[] message = m_DataBuffer.Skip(4).Take(length).ToArray(); - - DataComplete?.Invoke(sender, message); - m_DataBuffer.RemoveRange(0, length + 4); - - if (m_DataBuffer.Count > 4) - { - bytes = m_DataBuffer.Take(4).ToArray(); - length = BitConverter.ToInt32(bytes.ToArray(), 0); - } - } - } - catch (Exception ex) - { - m_DataBuffer.Clear(); - ExceptionAppeared(null, ex); - } - } - } - } -} diff --git a/Luski.net/Sound/RTPPacket.cs b/Luski.net/Sound/RTPPacket.cs deleted file mode 100755 index c446114..0000000 --- a/Luski.net/Sound/RTPPacket.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Linq; - -namespace Luski.net.Sound -{ - internal class RTPPacket - { - internal RTPPacket() - { - - } - - internal RTPPacket(byte[] data) - { - Parse(data); - } - - internal static int MinHeaderLength = 12; - internal int HeaderLength = MinHeaderLength; - internal int Version = 0; - internal bool Padding = false; - internal bool Extension = false; - internal int CSRCCount = 0; - internal bool Marker = false; - internal int PayloadType = 0; - internal ushort SequenceNumber = 0; - internal uint Timestamp = 0; - internal uint SourceId = 0; - internal byte[]? Data; - internal ushort ExtensionHeaderId = 0; - internal ushort ExtensionLengthAsCount = 0; - internal int ExtensionLengthInBytes = 0; - - private void Parse(byte[] data) - { - if (data.Length >= MinHeaderLength) - { - Version = ValueFromByte(data[0], 6, 2); - Padding = Convert.ToBoolean(ValueFromByte(data[0], 5, 1)); - Extension = Convert.ToBoolean(ValueFromByte(data[0], 4, 1)); - CSRCCount = ValueFromByte(data[0], 0, 4); - Marker = Convert.ToBoolean(ValueFromByte(data[1], 7, 1)); - PayloadType = ValueFromByte(data[1], 0, 7); - HeaderLength = MinHeaderLength + (CSRCCount * 4); - - //Sequence Nummer - byte[] seqNum = new byte[2]; - seqNum[0] = data[3]; - seqNum[1] = data[2]; - SequenceNumber = BitConverter.ToUInt16(seqNum, 0); - - //TimeStamp - byte[] timeStmp = new byte[4]; - timeStmp[0] = data[7]; - timeStmp[1] = data[6]; - timeStmp[2] = data[5]; - timeStmp[3] = data[4]; - Timestamp = BitConverter.ToUInt32(timeStmp, 0); - - //SourceId - byte[] srcId = new byte[4]; - srcId[0] = data[8]; - srcId[1] = data[9]; - srcId[2] = data[10]; - srcId[3] = data[11]; - SourceId = BitConverter.ToUInt32(srcId, 0); - - if (Extension) - { - byte[] extHeaderId = new byte[2]; - extHeaderId[1] = data[HeaderLength + 0]; - extHeaderId[0] = data[HeaderLength + 1]; - ExtensionHeaderId = BitConverter.ToUInt16(extHeaderId, 0); - - byte[] extHeaderLength16 = new byte[2]; - extHeaderLength16[1] = data[HeaderLength + 2]; - extHeaderLength16[0] = data[HeaderLength + 3]; - ExtensionLengthAsCount = BitConverter.ToUInt16(extHeaderLength16.ToArray(), 0); - - ExtensionLengthInBytes = ExtensionLengthAsCount * 4; - HeaderLength += ExtensionLengthInBytes + 4; - } - - Data = new byte[data.Length - HeaderLength]; - Array.Copy(data, HeaderLength, Data, 0, data.Length - HeaderLength); - } - } - - private static int ValueFromByte(byte value, int startPos, int length) - { - byte mask = 0; - for (int i = 0; i < length; i++) - { - mask = (byte)(mask | 0x1 << startPos + i); - } - - byte result = (byte)((value & mask) >> startPos); - return Convert.ToInt32(result); - } - - internal byte[] ToBytes() - { - byte[] bytes = new byte[HeaderLength + Data.Length]; - - //Byte 0 - bytes[0] = (byte)(Version << 6); - bytes[0] |= (byte)(Convert.ToInt32(Padding) << 5); - bytes[0] |= (byte)(Convert.ToInt32(Extension) << 4); - bytes[0] |= (byte)(Convert.ToInt32(CSRCCount)); - - //Byte 1 - bytes[1] = (byte)(Convert.ToInt32(Marker) << 7); - bytes[1] |= (byte)(Convert.ToInt32(PayloadType)); - - //Byte 2 + 3 - byte[] bytesSequenceNumber = BitConverter.GetBytes(SequenceNumber); - bytes[2] = bytesSequenceNumber[1]; - bytes[3] = bytesSequenceNumber[0]; - - //Byte 4 bis 7 - byte[] bytesTimeStamp = BitConverter.GetBytes(Timestamp); - bytes[4] = bytesTimeStamp[3]; - bytes[5] = bytesTimeStamp[2]; - bytes[6] = bytesTimeStamp[1]; - bytes[7] = bytesTimeStamp[0]; - - //Byte 8 bis 11 - byte[] bytesSourceId = BitConverter.GetBytes(SourceId); - bytes[8] = bytesSourceId[3]; - bytes[9] = bytesSourceId[2]; - bytes[10] = bytesSourceId[1]; - bytes[11] = bytesSourceId[0]; - - Array.Copy(Data, 0, bytes, HeaderLength, Data.Length); - - return bytes; - } - } -} diff --git a/Luski.net/Sound/Recorder.cs b/Luski.net/Sound/Recorder.cs deleted file mode 100755 index 93a0093..0000000 --- a/Luski.net/Sound/Recorder.cs +++ /dev/null @@ -1,340 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Threading; - -namespace Luski.net.Sound -{ - internal unsafe class Recorder - { - internal Recorder() - { - delegateWaveInProc = new Win32.DelegateWaveInProc(WaveInProc); - } - - private readonly LockerClass Locker = new(); - private readonly LockerClass LockerCopy = new(); - private IntPtr hWaveIn = IntPtr.Zero; - private string WaveInDeviceName = ""; - private bool IsWaveInOpened = false; - private bool IsWaveInStarted = false; - private bool IsThreadRecordingRunning = false; - private bool IsDataIncomming = false; - private bool Stopped = false; - private int SamplesPerSecond = 8000; - private int BitsPerSample = 16; - private int Channels = 1; - private int BufferCount = 8; - private int BufferSize = 1024; - private Win32.WAVEHDR*[] WaveInHeaders; - private Win32.WAVEHDR* CurrentRecordedHeader; - private readonly Win32.DelegateWaveInProc delegateWaveInProc; - private Thread ThreadRecording; - private readonly AutoResetEvent AutoResetEventDataRecorded = new(false); - - internal delegate void DelegateStopped(); - internal delegate void DelegateDataRecorded(byte[] bytes); - internal event DelegateStopped RecordingStopped; - internal event DelegateDataRecorded DataRecorded; - - internal bool Started => IsWaveInStarted && IsWaveInOpened && IsThreadRecordingRunning; - - private bool CreateWaveInHeaders() - { - WaveInHeaders = new Win32.WAVEHDR*[BufferCount]; - int createdHeaders = 0; - - for (int i = 0; i < BufferCount; i++) - { - WaveInHeaders[i] = (Win32.WAVEHDR*)Marshal.AllocHGlobal(sizeof(Win32.WAVEHDR)); - - WaveInHeaders[i]->dwLoops = 0; - WaveInHeaders[i]->dwUser = IntPtr.Zero; - WaveInHeaders[i]->lpNext = IntPtr.Zero; - WaveInHeaders[i]->reserved = IntPtr.Zero; - WaveInHeaders[i]->lpData = Marshal.AllocHGlobal(BufferSize); - WaveInHeaders[i]->dwBufferLength = (uint)BufferSize; - WaveInHeaders[i]->dwBytesRecorded = 0; - WaveInHeaders[i]->dwFlags = 0; - - Win32.MMRESULT hr = Win32.waveInPrepareHeader(hWaveIn, WaveInHeaders[i], sizeof(Win32.WAVEHDR)); - if (hr == Win32.MMRESULT.MMSYSERR_NOERROR) - { - if (i == 0) - { - hr = Win32.waveInAddBuffer(hWaveIn, WaveInHeaders[i], sizeof(Win32.WAVEHDR)); - } - createdHeaders++; - } - } - - return (createdHeaders == BufferCount); - } - - private void FreeWaveInHeaders() - { - try - { - if (WaveInHeaders != null) - { - for (int i = 0; i < WaveInHeaders.Length; i++) - { - Win32.MMRESULT hr = Win32.waveInUnprepareHeader(hWaveIn, WaveInHeaders[i], sizeof(Win32.WAVEHDR)); - - int count = 0; - while (count <= 100 && (WaveInHeaders[i]->dwFlags & Win32.WaveHdrFlags.WHDR_INQUEUE) == Win32.WaveHdrFlags.WHDR_INQUEUE) - { - Thread.Sleep(20); - count++; - } - - if ((WaveInHeaders[i]->dwFlags & Win32.WaveHdrFlags.WHDR_INQUEUE) != Win32.WaveHdrFlags.WHDR_INQUEUE) - { - if (WaveInHeaders[i]->lpData != IntPtr.Zero) - { - Marshal.FreeHGlobal(WaveInHeaders[i]->lpData); - WaveInHeaders[i]->lpData = IntPtr.Zero; - } - } - } - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.Write(ex.Message); - } - } - - private void StartThreadRecording() - { - if (Started == false) - { - ThreadRecording = new Thread(new ThreadStart(OnThreadRecording)); - IsThreadRecordingRunning = true; - ThreadRecording.Name = "Recording"; - ThreadRecording.Priority = ThreadPriority.Highest; - ThreadRecording.Start(); - } - } - - private bool OpenWaveIn() - { - if (hWaveIn == IntPtr.Zero) - { - if (IsWaveInOpened == false) - { - Win32.WAVEFORMATEX waveFormatEx = new() - { - wFormatTag = (ushort)Win32.WaveFormatFlags.WAVE_FORMAT_PCM, - nChannels = (ushort)Channels, - nSamplesPerSec = (ushort)SamplesPerSecond, - wBitsPerSample = (ushort)BitsPerSample - }; - waveFormatEx.nBlockAlign = (ushort)((waveFormatEx.wBitsPerSample * waveFormatEx.nChannels) >> 3); - waveFormatEx.nAvgBytesPerSec = waveFormatEx.nBlockAlign * waveFormatEx.nSamplesPerSec; - - int deviceId = WinSound.GetWaveInDeviceIdByName(WaveInDeviceName); - Win32.MMRESULT hr = Win32.waveInOpen(ref hWaveIn, deviceId, ref waveFormatEx, delegateWaveInProc, 0, (int)Win32.WaveProcFlags.CALLBACK_FUNCTION); - - if (hWaveIn == IntPtr.Zero) - { - IsWaveInOpened = false; - return false; - } - - GCHandle.Alloc(hWaveIn, GCHandleType.Pinned); - } - } - - IsWaveInOpened = true; - return true; - } - - internal bool Start(string waveInDeviceName, int samplesPerSecond, int bitsPerSample, int channels, int bufferCount, int bufferSize) - { - try - { - lock (Locker) - { - if (Started == false) - { - WaveInDeviceName = waveInDeviceName; - SamplesPerSecond = samplesPerSecond; - BitsPerSample = bitsPerSample; - Channels = channels; - BufferCount = bufferCount; - BufferSize = bufferSize; - - if (OpenWaveIn()) - { - if (CreateWaveInHeaders()) - { - Win32.MMRESULT hr = Win32.waveInStart(hWaveIn); - if (hr == Win32.MMRESULT.MMSYSERR_NOERROR) - { - IsWaveInStarted = true; - StartThreadRecording(); - Stopped = false; - return true; - } - else - { - return false; - } - } - } - } - - return false; - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Start | {0}", ex.Message)); - return false; - } - } - - internal bool Stop() - { - try - { - lock (Locker) - { - if (Started) - { - Stopped = true; - IsThreadRecordingRunning = false; - - CloseWaveIn(); - - AutoResetEventDataRecorded.Set(); - return true; - } - return false; - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Stop | {0}", ex.Message)); - return false; - } - } - - private void CloseWaveIn() - { - Win32.MMRESULT hr = Win32.waveInStop(hWaveIn); - - int resetCount = 0; - while (IsAnyWaveInHeaderInState(Win32.WaveHdrFlags.WHDR_INQUEUE) & resetCount < 20) - { - hr = Win32.waveInReset(hWaveIn); - Thread.Sleep(50); - resetCount++; - } - - FreeWaveInHeaders(); - hr = Win32.waveInClose(hWaveIn); - } - - private bool IsAnyWaveInHeaderInState(Win32.WaveHdrFlags state) - { - for (int i = 0; i < WaveInHeaders.Length; i++) - { - if ((WaveInHeaders[i]->dwFlags & state) == state) - { - return true; - } - } - return false; - } - - private void WaveInProc(IntPtr hWaveIn, Win32.WIM_Messages msg, IntPtr dwInstance, Win32.WAVEHDR* pWaveHdr, IntPtr lParam) - { - switch (msg) - { - //Open - case Win32.WIM_Messages.OPEN: - break; - - //Data - case Win32.WIM_Messages.DATA: - IsDataIncomming = true; - CurrentRecordedHeader = pWaveHdr; - AutoResetEventDataRecorded.Set(); - break; - - //Close - case Win32.WIM_Messages.CLOSE: - IsDataIncomming = false; - IsWaveInOpened = false; - AutoResetEventDataRecorded.Set(); - this.hWaveIn = IntPtr.Zero; - break; - } - } - - private void OnThreadRecording() - { - while (Started && !Stopped) - { - AutoResetEventDataRecorded.WaitOne(); - - try - { - if (Started && !Stopped) - { - if (CurrentRecordedHeader->dwBytesRecorded > 0) - { - if (DataRecorded != null && IsDataIncomming) - { - try - { - byte[] bytes = new byte[CurrentRecordedHeader->dwBytesRecorded]; - Marshal.Copy(CurrentRecordedHeader->lpData, bytes, 0, (int)CurrentRecordedHeader->dwBytesRecorded); - - DataRecorded(bytes); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Recorder.cs | OnThreadRecording() | {0}", ex.Message)); - } - } - - for (int i = 0; i < WaveInHeaders.Length; i++) - { - if ((WaveInHeaders[i]->dwFlags & Win32.WaveHdrFlags.WHDR_INQUEUE) == 0) - { - Win32.MMRESULT hr = Win32.waveInAddBuffer(hWaveIn, WaveInHeaders[i], sizeof(Win32.WAVEHDR)); - } - } - - } - } - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(ex.Message); - } - } - - - lock (Locker) - { - IsWaveInStarted = false; - IsThreadRecordingRunning = false; - } - - if (RecordingStopped != null) - { - try - { - RecordingStopped(); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format("Recording Stopped | {0}", ex.Message)); - } - } - } - } -} diff --git a/Luski.net/Sound/Timer.cs b/Luski.net/Sound/Timer.cs deleted file mode 100755 index 3884ad9..0000000 --- a/Luski.net/Sound/Timer.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Luski.net.Sound -{ - internal class EventTimer - { - internal EventTimer() - { - m_DelegateTimeEvent = new Win32.TimerEventHandler(OnTimer); - } - - private bool m_IsRunning = false; - private uint m_Milliseconds = 20; - private uint m_TimerId = 0; - private GCHandle m_GCHandleTimer; - private uint m_UserData = 0; - private uint m_ResolutionInMilliseconds = 0; - - private readonly Win32.TimerEventHandler m_DelegateTimeEvent; - internal delegate void DelegateTimerTick(); - internal event DelegateTimerTick? TimerTick; - - internal void Start(uint milliseconds) - { - m_Milliseconds = milliseconds; - - Win32.TimeCaps tc = new(); - Win32.TimeGetDevCaps(ref tc, (uint)Marshal.SizeOf(typeof(Win32.TimeCaps))); - m_ResolutionInMilliseconds = Math.Max(tc.wPeriodMin, 0); - - Win32.TimeBeginPeriod(m_ResolutionInMilliseconds); - - m_TimerId = Win32.TimeSetEvent(m_Milliseconds, m_ResolutionInMilliseconds, m_DelegateTimeEvent, ref m_UserData, Win32.TIME_PERIODIC); - if (m_TimerId > 0) - { - m_GCHandleTimer = GCHandle.Alloc(m_TimerId, GCHandleType.Pinned); - m_IsRunning = true; - } - } - - internal void Stop() - { - if (m_TimerId > 0) - { - _ = Win32.TimeKillEvent(m_TimerId); - Win32.TimeEndPeriod(m_ResolutionInMilliseconds); - - if (m_GCHandleTimer.IsAllocated) - { - m_GCHandleTimer.Free(); - } - - m_TimerId = 0; - m_IsRunning = false; - } - } - - private void OnTimer(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2) - { - TimerTick?.Invoke(); - } - } -} diff --git a/Luski.net/Sound/Utils.cs b/Luski.net/Sound/Utils.cs deleted file mode 100755 index 2ccb7ae..0000000 --- a/Luski.net/Sound/Utils.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; - -namespace Luski.net.Sound -{ - internal class Utils - { - internal Utils() - { - - } - - private const int SIGN_BIT = 0x80; - private const int QUANT_MASK = 0xf; - private const int SEG_SHIFT = 4; - private const int SEG_MASK = 0x70; - private const int BIAS = 0x84; - private const int CLIP = 8159; - private static readonly short[] seg_uend = new short[] { 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF }; - - internal static int GetBytesPerInterval(uint SamplesPerSecond, int BitsPerSample, int Channels) - { - int blockAlign = ((BitsPerSample * Channels) >> 3); - int bytesPerSec = (int)(blockAlign * SamplesPerSecond); - uint sleepIntervalFactor = 1000 / 20; - int bytesPerInterval = (int)(bytesPerSec / sleepIntervalFactor); - - return bytesPerInterval; - } - - internal static int MulawToLinear(int ulaw) - { - ulaw = ~ulaw; - int t = ((ulaw & QUANT_MASK) << 3) + BIAS; - t <<= (ulaw & SEG_MASK) >> SEG_SHIFT; - return ((ulaw & SIGN_BIT) > 0 ? (BIAS - t) : (t - BIAS)); - } - - private static short Search(short val, short[] table, short size) - { - short i; - int index = 0; - for (i = 0; i < size; i++) - { - if (val <= table[index]) - { - return (i); - } - index++; - } - return (size); - } - - internal static byte Linear2ulaw(short pcm_val) - { - - /* Get the sign and the magnitude of the value. */ - pcm_val = (short)(pcm_val >> 2); - short mask; - if (pcm_val < 0) - { - pcm_val = (short)-pcm_val; - mask = 0x7F; - } - else - { - mask = 0xFF; - } - /* clip the magnitude */ - if (pcm_val > CLIP) - { - pcm_val = CLIP; - } - pcm_val += (BIAS >> 2); - - /* Convert the scaled magnitude to segment number. */ - short seg = Search(pcm_val, seg_uend, 8); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - /* out of range, return maximum value. */ - if (seg >= 8) - { - return (byte)(0x7F ^ mask); - } - else - { - byte uval = (byte)((seg << 4) | ((pcm_val >> (seg + 1)) & 0xF)); - return ((byte)(uval ^ mask)); - } - } - - internal static byte[] MuLawToLinear(byte[] bytes, int bitsPerSample, int channels) - { - int blockAlign = channels * bitsPerSample / 8; - - byte[] result = new byte[bytes.Length * blockAlign]; - for (int i = 0, counter = 0; i < bytes.Length; i++, counter += blockAlign) - { - int value = MulawToLinear(bytes[i]); - byte[] values = BitConverter.GetBytes(value); - - switch (bitsPerSample) - { - case 8: - switch (channels) - { - //8 Bit 1 Channel - case 1: - result[counter] = values[0]; - break; - - //8 Bit 2 Channel - case 2: - result[counter] = values[0]; - result[counter + 1] = values[0]; - break; - } - break; - - case 16: - switch (channels) - { - //16 Bit 1 Channel - case 1: - result[counter] = values[0]; - result[counter + 1] = values[1]; - break; - - //16 Bit 2 Channels - case 2: - result[counter] = values[0]; - result[counter + 1] = values[1]; - result[counter + 2] = values[0]; - result[counter + 3] = values[1]; - break; - } - break; - } - } - - return result; - } - - internal static byte[] LinearToMulaw(byte[] bytes, int bitsPerSample, int channels) - { - int blockAlign = channels * bitsPerSample / 8; - - byte[] result = new byte[bytes.Length / blockAlign]; - int resultIndex = 0; - for (int i = 0; i < result.Length; i++) - { - switch (bitsPerSample) - { - case 8: - switch (channels) - { - //8 Bit 1 Channel - case 1: - result[i] = Linear2ulaw(bytes[resultIndex]); - resultIndex += 1; - break; - - //8 Bit 2 Channel - case 2: - result[i] = Linear2ulaw(bytes[resultIndex]); - resultIndex += 2; - break; - } - break; - - case 16: - switch (channels) - { - //16 Bit 1 Channel - case 1: - result[i] = Linear2ulaw(BitConverter.ToInt16(bytes, resultIndex)); - resultIndex += 2; - break; - - //16 Bit 2 Channels - case 2: - result[i] = Linear2ulaw(BitConverter.ToInt16(bytes, resultIndex)); - resultIndex += 4; - break; - } - break; - } - } - - return result; - } - } -} diff --git a/Luski.net/Sound/WaveFile.cs b/Luski.net/Sound/WaveFile.cs deleted file mode 100755 index 398c5e3..0000000 --- a/Luski.net/Sound/WaveFile.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.IO; -using System.Text; - -namespace Luski.net.Sound -{ - internal class WaveFile - { - internal WaveFile() - { - - } - - internal const int WAVE_FORMAT_PCM = 1; - - - internal static WaveFileHeader Read(string fileName) - { - WaveFileHeader header = ReadHeader(fileName); - - return header; - } - - private static WaveFileHeader ReadHeader(string fileName) - { - WaveFileHeader header = new(); - - if (File.Exists(fileName)) - { - FileStream fs = new(fileName, FileMode.Open, FileAccess.Read); - BinaryReader rd = new(fs, Encoding.UTF8); - - if (fs.CanRead) - { - header.RIFF = rd.ReadChars(4); - header.RiffSize = (uint)rd.ReadInt32(); - header.RiffFormat = rd.ReadChars(4); - - header.FMT = rd.ReadChars(4); - header.FMTSize = (uint)rd.ReadInt32(); - header.FMTPos = fs.Position; - header.AudioFormat = rd.ReadInt16(); - header.Channels = rd.ReadInt16(); - header.SamplesPerSecond = (uint)rd.ReadInt32(); - header.BytesPerSecond = (uint)rd.ReadInt32(); - header.BlockAlign = rd.ReadInt16(); - header.BitsPerSample = rd.ReadInt16(); - - fs.Seek(header.FMTPos + header.FMTSize, SeekOrigin.Begin); - - header.DATA = rd.ReadChars(4); - header.DATASize = (uint)rd.ReadInt32(); - header.DATAPos = (int)fs.Position; - - if (new string(header.DATA).ToUpper() != "DATA") - { - uint DataChunkSize = header.DATASize + 8; - fs.Seek(DataChunkSize, SeekOrigin.Current); - header.DATASize = (uint)(fs.Length - header.DATAPos - DataChunkSize); - } - - if (header.DATASize <= fs.Length - header.DATAPos) - { - header.Payload = rd.ReadBytes((int)header.DATASize); - } - } - - rd.Close(); - fs.Close(); - } - - return header; - } - } - - internal class WaveFileHeader - { - internal WaveFileHeader() - { - - } - - internal char[] RIFF = new char[4]; - internal uint RiffSize = 8; - internal char[] RiffFormat = new char[4]; - - internal char[] FMT = new char[4]; - internal uint FMTSize = 16; - internal short AudioFormat; - internal short Channels; - internal uint SamplesPerSecond; - internal uint BytesPerSecond; - internal short BlockAlign; - internal short BitsPerSample; - - internal char[] DATA = new char[4]; - internal uint DATASize; - - internal byte[] Payload = Array.Empty(); - - internal int DATAPos = 44; - internal long FMTPos = 20; - } -} diff --git a/Luski.net/Sound/Win32.cs b/Luski.net/Sound/Win32.cs deleted file mode 100755 index 0275eaf..0000000 --- a/Luski.net/Sound/Win32.cs +++ /dev/null @@ -1,241 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Luski.net.Sound -{ - internal unsafe class Win32 - { - internal Win32() - { - - } - - internal const int WAVE_MAPPER = -1; - - internal const int WT_EXECUTEDEFAULT = 0x00000000; - internal const int WT_EXECUTEINIOTHREAD = 0x00000001; - internal const int WT_EXECUTEINTIMERTHREAD = 0x00000020; - internal const int WT_EXECUTEINPERSISTENTTHREAD = 0x00000080; - - internal const int TIME_ONESHOT = 0; - internal const int TIME_PERIODIC = 1; - - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)] - internal struct WAVEOUTCAPS - { - internal short wMid; - internal short wPid; - internal int vDriverVersion; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - internal string szPname; - internal uint dwFormats; - internal short wChannels; - internal short wReserved; - internal int dwSupport; - } - - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)] - internal struct WAVEINCAPS - { - internal short wMid; - internal short wPid; - internal int vDriverVersion; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - internal string szPname; - internal uint dwFormats; - internal short wChannels; - internal short wReserved; - internal int dwSupport; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct WAVEFORMATEX - { - internal ushort wFormatTag; - internal ushort nChannels; - internal uint nSamplesPerSec; - internal uint nAvgBytesPerSec; - internal ushort nBlockAlign; - internal ushort wBitsPerSample; - internal ushort cbSize; - } - - internal enum MMRESULT : uint - { - MMSYSERR_NOERROR = 0, - MMSYSERR_ERROR = 1, - MMSYSERR_BADDEVICEID = 2, - MMSYSERR_NOTENABLED = 3, - MMSYSERR_ALLOCATED = 4, - MMSYSERR_INVALHANDLE = 5, - MMSYSERR_NODRIVER = 6, - MMSYSERR_NOMEM = 7, - MMSYSERR_NOTSUPPORTED = 8, - MMSYSERR_BADERRNUM = 9, - MMSYSERR_INVALFLAG = 10, - MMSYSERR_INVALPARAM = 11, - MMSYSERR_HANDLEBUSY = 12, - MMSYSERR_INVALIDALIAS = 13, - MMSYSERR_BADDB = 14, - MMSYSERR_KEYNOTFOUND = 15, - MMSYSERR_READERROR = 16, - MMSYSERR_WRITEERROR = 17, - MMSYSERR_DELETEERROR = 18, - MMSYSERR_VALNOTFOUND = 19, - MMSYSERR_NODRIVERCB = 20, - WAVERR_BADFORMAT = 32, - WAVERR_STILLPLAYING = 33, - WAVERR_UNPREPARED = 34 - } - - [Flags] - internal enum WaveHdrFlags : uint - { - WHDR_DONE = 1, - WHDR_PREPARED = 2, - WHDR_BEGINLOOP = 4, - WHDR_ENDLOOP = 8, - WHDR_INQUEUE = 16 - } - - [Flags] - internal enum WaveProcFlags : int - { - CALLBACK_NULL = 0, - CALLBACK_FUNCTION = 0x30000, - CALLBACK_EVENT = 0x50000, - CALLBACK_WINDOW = 0x10000, - CALLBACK_THREAD = 0x20000, - WAVE_FORMAT_QUERY = 1, - WAVE_MAPPED = 4, - WAVE_FORMAT_DIRECT = 8 - } - - [Flags] - internal enum HRESULT : long - { - S_OK = 0L, - S_FALSE = 1L - } - - [Flags] - internal enum WaveFormatFlags : int - { - WAVE_FORMAT_PCM = 0x0001 - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - internal struct WAVEHDR - { - internal IntPtr lpData; - internal uint dwBufferLength; - internal uint dwBytesRecorded; - internal IntPtr dwUser; - internal WaveHdrFlags dwFlags; - internal uint dwLoops; - internal IntPtr lpNext; - internal IntPtr reserved; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct TimeCaps - { - internal uint wPeriodMin; - internal uint wPeriodMax; - }; - - internal enum WOM_Messages : int - { - OPEN = 0x03BB, - CLOSE = 0x03BC, - DONE = 0x03BD - } - - internal enum WIM_Messages : int - { - OPEN = 0x03BE, - CLOSE = 0x03BF, - DATA = 0x03C0 - } - - internal delegate void DelegateWaveOutProc(IntPtr hWaveOut, WOM_Messages msg, IntPtr dwInstance, WAVEHDR* pWaveHdr, IntPtr lParam); - internal delegate void DelegateWaveInProc(IntPtr hWaveIn, WIM_Messages msg, IntPtr dwInstance, WAVEHDR* pWaveHdr, IntPtr lParam); - internal delegate void DelegateTimerProc(IntPtr lpParameter, bool TimerOrWaitFired); - internal delegate void TimerEventHandler(uint id, uint msg, ref uint userCtx, uint rsv1, uint rsv2); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")] - internal static extern uint TimeSetEvent(uint msDelay, uint msResolution, TimerEventHandler handler, ref uint userCtx, uint eventType); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent")] - internal static extern uint TimeKillEvent(uint timerId); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeGetDevCaps")] - internal static extern MMRESULT TimeGetDevCaps(ref TimeCaps timeCaps, uint sizeTimeCaps); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeBeginPeriod")] - internal static extern MMRESULT TimeBeginPeriod(uint uPeriod); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeEndPeriod")] - internal static extern MMRESULT TimeEndPeriod(uint uPeriod); - - [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern MMRESULT waveOutOpen(ref IntPtr hWaveOut, int uDeviceID, ref WAVEFORMATEX lpFormat, DelegateWaveOutProc dwCallBack, int dwInstance, int dwFlags); - - [DllImport("winmm.dll")] - internal static extern MMRESULT waveInOpen(ref IntPtr hWaveIn, int deviceId, ref WAVEFORMATEX wfx, DelegateWaveInProc dwCallBack, int dwInstance, int dwFlags); - - [DllImport("winmm.dll", SetLastError = true)] - internal static extern MMRESULT waveInStart(IntPtr hWaveIn); - - [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern uint waveInGetDevCaps(int index, ref WAVEINCAPS pwic, int cbwic); - - [DllImport("winmm.dll", SetLastError = true)] - internal static extern uint waveInGetNumDevs(); - - [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern uint waveOutGetDevCaps(int index, ref WAVEOUTCAPS pwoc, int cbwoc); - - [DllImport("winmm.dll", SetLastError = true)] - internal static extern uint waveOutGetNumDevs(); - - [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern MMRESULT waveOutWrite(IntPtr hWaveOut, WAVEHDR* pwh, int cbwh); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "waveOutPrepareHeader", CharSet = CharSet.Auto)] - internal static extern MMRESULT waveOutPrepareHeader(IntPtr hWaveOut, WAVEHDR* lpWaveOutHdr, int uSize); - - [DllImport("winmm.dll", SetLastError = true, EntryPoint = "waveOutUnprepareHeader", CharSet = CharSet.Auto)] - internal static extern MMRESULT waveOutUnprepareHeader(IntPtr hWaveOut, WAVEHDR* lpWaveOutHdr, int uSize); - - [DllImport("winmm.dll", EntryPoint = "waveInStop", SetLastError = true)] - internal static extern MMRESULT waveInStop(IntPtr hWaveIn); - - [DllImport("winmm.dll", EntryPoint = "waveInReset", SetLastError = true)] - internal static extern MMRESULT waveInReset(IntPtr hWaveIn); - - [DllImport("winmm.dll", EntryPoint = "waveOutReset", SetLastError = true)] - internal static extern MMRESULT waveOutReset(IntPtr hWaveOut); - - [DllImport("winmm.dll", SetLastError = true)] - internal static extern MMRESULT waveInPrepareHeader(IntPtr hWaveIn, WAVEHDR* pwh, int cbwh); - - [DllImport("winmm.dll", SetLastError = true)] - internal static extern MMRESULT waveInUnprepareHeader(IntPtr hWaveIn, WAVEHDR* pwh, int cbwh); - - [DllImport("winmm.dll", EntryPoint = "waveInAddBuffer", SetLastError = true)] - internal static extern MMRESULT waveInAddBuffer(IntPtr hWaveIn, WAVEHDR* pwh, int cbwh); - - [DllImport("winmm.dll", SetLastError = true)] - internal static extern MMRESULT waveInClose(IntPtr hWaveIn); - - [DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)] - internal static extern MMRESULT waveOutClose(IntPtr hWaveOut); - - [DllImport("winmm.dll")] - internal static extern MMRESULT waveOutPause(IntPtr hWaveOut); - - [DllImport("winmm.dll", EntryPoint = "waveOutRestart", SetLastError = true)] - internal static extern MMRESULT waveOutRestart(IntPtr hWaveOut); - } -} diff --git a/Luski.net/Sound/WinSound.cs b/Luski.net/Sound/WinSound.cs deleted file mode 100755 index c5d48ce..0000000 --- a/Luski.net/Sound/WinSound.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace Luski.net.Sound -{ - internal class LockerClass - { - - } - - internal class WinSound - { - internal WinSound() - { - - } - - internal static List GetPlaybackNames() - { - List list = new(); - Win32.WAVEOUTCAPS waveOutCap = new(); - - uint num = Win32.waveOutGetNumDevs(); - for (int i = 0; i < num; i++) - { - uint hr = Win32.waveOutGetDevCaps(i, ref waveOutCap, Marshal.SizeOf(typeof(Win32.WAVEOUTCAPS))); - if (hr == (int)Win32.HRESULT.S_OK) - { - list.Add(waveOutCap.szPname); - } - } - - return list; - } - - internal static List GetRecordingNames() - { - List list = new(); - Win32.WAVEINCAPS waveInCap = new(); - - uint num = Win32.waveInGetNumDevs(); - for (int i = 0; i < num; i++) - { - uint hr = Win32.waveInGetDevCaps(i, ref waveInCap, Marshal.SizeOf(typeof(Win32.WAVEINCAPS))); - if (hr == (int)Win32.HRESULT.S_OK) - { - list.Add(waveInCap.szPname); - } - } - - return list; - } - - internal static int GetWaveInDeviceIdByName(string name) - { - uint num = Win32.waveInGetNumDevs(); - - Win32.WAVEINCAPS caps = new(); - for (int i = 0; i < num; i++) - { - Win32.HRESULT hr = (Win32.HRESULT)Win32.waveInGetDevCaps(i, ref caps, Marshal.SizeOf(typeof(Win32.WAVEINCAPS))); - if (hr == Win32.HRESULT.S_OK) - { - if (caps.szPname == name) - { - return i; - } - } - } - - return Win32.WAVE_MAPPER; - } - - internal static int GetWaveOutDeviceIdByName(string name) - { - uint num = Win32.waveOutGetNumDevs(); - - Win32.WAVEOUTCAPS caps = new(); - for (int i = 0; i < num; i++) - { - Win32.HRESULT hr = (Win32.HRESULT)Win32.waveOutGetDevCaps(i, ref caps, Marshal.SizeOf(typeof(Win32.WAVEOUTCAPS))); - if (hr == Win32.HRESULT.S_OK) - { - if (caps.szPname == name) - { - return i; - } - } - } - - return Win32.WAVE_MAPPER; - } - } -} diff --git a/Luski.net/JsonTypes/File.cs b/Luski.net/Structures/File.cs similarity index 76% rename from Luski.net/JsonTypes/File.cs rename to Luski.net/Structures/File.cs index 901cd14..8c3e76f 100755 --- a/Luski.net/JsonTypes/File.cs +++ b/Luski.net/Structures/File.cs @@ -9,12 +9,16 @@ using System.Net.Http; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; +using JacobTechEncryption; +using Luski.net.Interfaces; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures; public class File : IncomingHTTP { + public IServer Server { get; internal set; } [JsonInclude] [JsonPropertyName("name")] public string Name { get; internal set; } = default!; @@ -29,7 +33,7 @@ public class File : IncomingHTTP [JsonIgnore] internal string loc { get; set; } = default!; - public async void DownloadBytes(string Loc, long key) + public async Task DownloadBytes(string Loc, long key, CancellationToken CancellationToken) { //using HttpClient web = new(); //web.DefaultRequestHeaders.Add("token", Server.Token); @@ -37,9 +41,9 @@ public class File : IncomingHTTP //IncomingHTTP? request = JsonSerializer.Deserialize(web.GetAsync($"https://{Server.Domain}/{Server.API_Ver}/SocketMessage/GetFile").Result.Content.ReadAsStringAsync().Result, IncomingHTTPContext.Default.IncomingHTTP); string path = Path.GetTempFileName(); - await Server.GetFromServer($"SocketMessage/GetFile/{Id}", path); - string Key = (key == 0 ? Encryption.MyPublicKey : Encryption.File.Channels.GetKey(key))!; - Encryption.AES.Decrypt(System.IO.File.ReadAllBytes(path), Key, Loc); + await Server.GetFromServer($"SocketMessage/GetFile/{Id}", path, CancellationToken); + string Key = (key == 0 ? ClientEncryption.MyPublicKey : ClientEncryption.File.Channels.GetKey(key))!; + Encryption.AES.DecryptToFile(System.IO.File.ReadAllBytes(path), Key, Loc); /* if (request is not null && request.Error is not null) { @@ -78,25 +82,29 @@ public class File : IncomingHTTP loc = path; } - internal async Task Upload(string keyy) + private bool Uploaded = false; + + internal async Task Upload(string keyy, CancellationToken CancellationToken) { - if (Name != null) Name = Convert.ToBase64String(Encryption.Encrypt(Name, keyy)); - Debug.WriteLine("uploading"); - string NPath = Encryption.AES.Encrypt(loc, keyy); - File sf = await Server.SendServer( + if (Uploaded) return Id; + if (Name != null) Name = Convert.ToBase64String(Encryption.RSA.Encrypt(Encoding.UTF8.GetBytes(Name), keyy)); + string NPath = Encryption.AES.EncryptFile(loc, keyy); + File sf = await Server.SendServer( "SocketMessage/UploadFile", NPath, FileContext.Default.File, + CancellationToken, new KeyValuePair("name", Name)); try { System.IO.File.Delete(NPath); } catch { } - Debug.WriteLine("done uploading"); if (sf.Error is not null) throw new Exception(sf.ErrorMessage); + Id = sf.Id; + Uploaded = true; return sf.Id; } internal void decrypt() { - if (Name is not null) Name = Encryption.Encoder.GetString(Encryption.Decrypt(Convert.FromBase64String(Name), key)); + if (Name is not null) Name = Encoding.UTF8.GetString(Encryption.RSA.Decrypt(Convert.FromBase64String(Name), key)); } } diff --git a/Luski.net/Structures/Main/MainSocketAppUser.cs b/Luski.net/Structures/Main/MainSocketAppUser.cs new file mode 100755 index 0000000..7d3dc8d --- /dev/null +++ b/Luski.net/Structures/Main/MainSocketAppUser.cs @@ -0,0 +1,194 @@ +using System; +using Luski.net.Interfaces; +using Luski.net.JsonTypes.BaseTypes; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; +using JacobTechEncryption; +using Luski.net.Enums; +using Luski.net.Enums.Main; +using Luski.net.JsonTypes; + +namespace Luski.net.Structures.Main; + +public class MainSocketAppUser : SocketUserBase, IAppUser +{ + [JsonPropertyName("username")] + [JsonInclude] + public string Username { get; internal set; } = default!; + [JsonPropertyName("flags")] + [JsonInclude] + public UserFlag Flags { get; internal set; } = default!; + + [JsonIgnore] + public IReadOnlyList Channels + { + get + { + if (_Channels is null || ChannelIdList is not null) + { + if (ChannelIdList.Length != 0) + { + _Channels = new List(); + foreach (long channel in ChannelIdList) + { + MainSocketChannel s = (Server as Server).GetChannel(channel, + MainSocketChannelContext.Default.MainSocketChannel, CancellationToken.None).Result; + (Server as Server)!.chans.Remove(s); + switch (s.Type) + { + case ChannelType.GROUP: + _Channels.Add((Server as Server).GetChannel(channel, + MainSocketGroupChannelContext.Default.MainSocketGroupChannel, CancellationToken.None).Result); + break; + case ChannelType.DM: + _Channels.Add((Server as Server).GetChannel(channel, + MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken.None).Result); + break; + } + } + } + else _Channels = new List(); + } + return _Channels.AsReadOnly(); + } + } + + [JsonIgnore] + public IReadOnlyList FriendRequests + { + get + { + if (_FriendRequests is null || FriendRequestsRaw is not null) + { + _FriendRequests = new(); + if (ChannelIdList.Length != 0 && FriendRequestsRaw is not null) + { + foreach (FR person in FriendRequestsRaw) + { + //_Friends.Add(SocketRemoteUser.GetUser(person)); + long id = person.user_id == Id ? person.from : person.user_id; + MainSocketRemoteUser frq = Server.GetUser(id, CancellationToken.None).Result; + _FriendRequests.Add(frq); + } + } + else _FriendRequests = new(); + } + return _FriendRequests.AsReadOnly(); + } + } + [JsonIgnore] + public IReadOnlyList Friends + { + get + { + if (_Friends is null || FriendIdList is not null) + { + if (ChannelIdList.Length != 0) + { + _Friends = new List(); + foreach (long person in FriendIdList) + { + _Friends.Add(Server.GetUser(person, CancellationToken.None).Result); + } + } + else _Friends = new List(); + } + return _Friends.AsReadOnly(); + } + } + [JsonPropertyName("selected_channel")] + [JsonInclude] + public long SelectedChannel { get; internal set; } = default!; + [JsonPropertyName("channels")] + [JsonInclude] + public long[] ChannelIdList { get; internal set; } = default!; + [JsonPropertyName("friends")] + [JsonInclude] + public long[] FriendIdList { get; internal set; } = default!; + [JsonPropertyName("friend_requests")] + [JsonInclude] + public FR[] FriendRequestsRaw { get; internal set; } = default!; + [JsonIgnore] + private List _Channels = default!; + [JsonIgnore] + private List _Friends = default!; + [JsonIgnore] + private List _FriendRequests = default!; + + public class FR + { + public long from { get; set; } = default!; + public long user_id { get; set; } = default!; + } + + internal void AddFriend(MainSocketRemoteUser User) + { + if ((Server as Server)!.poeople.Any(s => s.Id == User.Id)) + { + IEnumerable b = (Server as Server)!.poeople.Where(s => s.Id == User.Id); + foreach (IUser item in b) + { + (Server as Server)!.poeople.Remove(item); + } + (Server as Server)!.poeople.Add(User); + } + else + { + (Server as Server)!.poeople.Add(User); + } + _Friends.Add(User); + } + + internal void RemoveFriendRequest(MainSocketRemoteUser User) + { + if ((Server as Server)!.poeople.Any(s => s.Id == User.Id)) + { + IEnumerable b = (Server as Server)!.poeople.Where(s => s.Id == User.Id); + foreach (IUser item in b) + { + (Server as Server)!.poeople.Remove(item); + } + } + (Server as Server)!.poeople.Add(User); + foreach (MainSocketRemoteUser user in _FriendRequests) + { + if (User.Id == user.Id) + { + _FriendRequests.Remove(User); + } + } + } + + internal void AddFriendRequest(MainSocketRemoteUser User) + { + if ((Server as Server)!.poeople.Any(s => s.Id == User.Id)) + { + IEnumerable b = (Server as Server)!.poeople.Where(s => s.Id == User.Id); + foreach (IUser item in b) + { + (Server as Server)!.poeople.Remove(item); + } + (Server as Server)!.poeople.Add(User); + } + else + { + (Server as Server)!.poeople.Add(User); + } + _FriendRequests.Add(User); + } +} + +[JsonSerializable(typeof(MainSocketAppUser))] +[JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Default, + PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never)] +internal partial class MainSocketAppUserContext : JsonSerializerContext +{ + +} diff --git a/Luski.net/JsonTypes/SocketChannel.cs b/Luski.net/Structures/Main/MainSocketChannel.cs similarity index 51% rename from Luski.net/JsonTypes/SocketChannel.cs rename to Luski.net/Structures/Main/MainSocketChannel.cs index 95af482..a46b6e1 100755 --- a/Luski.net/JsonTypes/SocketChannel.cs +++ b/Luski.net/Structures/Main/MainSocketChannel.cs @@ -9,10 +9,15 @@ using System.Net.Http; using System.Threading.Tasks; using Luski.net.JsonTypes.WSS; using System.Text.Json.Serialization.Metadata; +using System.Threading; +using JacobTechEncryption; +using JacobTechEncryption.Enums; +using Luski.net.Enums.Main; +using Luski.net.JsonTypes; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures.Main; -public class SocketChannel : IncomingHTTP +public class MainSocketChannel : IncomingHTTP { [JsonInclude] [JsonPropertyName("id")] @@ -29,6 +34,7 @@ public class SocketChannel : IncomingHTTP [JsonPropertyName("type")] [JsonInclude] public ChannelType Type { get; internal set; } = default!; + public IServer Server { get; internal set; } [JsonPropertyName("members")] [JsonInclude] public long[] MemberIdList { get; internal set; } = default!; @@ -43,8 +49,8 @@ public class SocketChannel : IncomingHTTP _members = new(); foreach (long member in MemberIdList) { - if (member != Server._user!.Id) _members.Add(SocketUserBase.GetUser(member, SocketRemoteUserContext.Default.SocketRemoteUser).Result); - else _members.Add(Server._user); + if (member != Server.IAppUser!.Id) _members.Add(Server.GetUser(member, CancellationToken.None).Result); + else _members.Add(Server.IAppUser); } } return _members.AsReadOnly(); @@ -53,31 +59,31 @@ public class SocketChannel : IncomingHTTP [JsonIgnore] private List _members = new(); - public async Task SendKeysToUsers() + public Task SendKeysToUsers(CancellationToken CancellationToken) { if (Key is null) { - StartKeyProcessAsync().Wait(); + StartKeyProcessAsync(CancellationToken).Wait(); return Task.CompletedTask; } - int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Server.Percent) * 2.0)); + int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 50) * 2.0)); if (num == 0) num = 1; - string? lkey = Encryption.File.Channels.GetKey(Id); + string? lkey = ClientEncryption.File.Channels.GetKey(Id); Parallel.ForEach(Members, new ParallelOptions() { MaxDegreeOfParallelism = num - }, async i => + }, i => { - if (i.Id != Server._user?.Id) + if (i.Id != (Server as Server).User?.Id) { - string key = await i.GetUserKey(); - if (!string.IsNullOrEmpty(key)) + long key = i.GetUserKey(CancellationToken).Result; + if (true) { WSSKeyExchange send = new() { to = i.Id, channel = Id, - key = Convert.ToBase64String(Encryption.Encrypt(lkey, key)) + key = Convert.ToBase64String(Encryption.RSA.Encrypt(lkey, key.ToString(), EncoderType.UTF8)) }; Server.SendServer(send, WSSKeyExchangeContext.Default.WSSKeyExchange); } @@ -86,17 +92,17 @@ public class SocketChannel : IncomingHTTP return Task.CompletedTask; } - internal async Task StartKeyProcessAsync() - { - Encryption.GenerateNewKeys(out string Public, out string Private); + internal Task StartKeyProcessAsync(CancellationToken CancellationToken) + {/* + ClientEncryption.GenerateNewKeys(out string Public, out string Private); Key = Public; HttpResponseMessage b; using (HttpClient web = new()) { - web.DefaultRequestHeaders.Add("token", Server.Token); - b = web.PostAsync($"https://{Server.InternalDomain}/{Server.API_Ver}/SocketChannel/SetKey/{Id}", new StringContent(Key)).Result; + web.DefaultRequestHeaders.Add("token", Luski.net.Server.Token); + b = web.PostAsync($"https://{Server.Domain}/{Server.ApiVersion}/SocketChannel/SetKey/{Id}", new StringContent(Key), CancellationToken).Result; } - int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Server.Percent) * 2.0)); + int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Luski.net.Server.Percent) * 2.0)); if (num == 0) num = 1; Encryption.File.Channels.AddKey(Id, Private); Parallel.ForEach(Members, new ParallelOptions() @@ -104,9 +110,9 @@ public class SocketChannel : IncomingHTTP MaxDegreeOfParallelism = num }, i => { - if (i.Id != Server._user?.Id) + if (i.Id != Luski.net.Server._user?.Id) { - string key = i.GetUserKey().Result; + string key = i.GetUserKey(CancellationToken, Server).Result; if (!string.IsNullOrEmpty(key)) { WSSKeyExchange send = new() @@ -115,59 +121,20 @@ public class SocketChannel : IncomingHTTP channel = Id, key = Convert.ToBase64String(Encryption.Encrypt(Private, key)) }; - Server.SendServer(send, WSSKeyExchangeContext.Default.WSSKeyExchange); + Luski.net.Server.SendServer(send, WSSKeyExchangeContext.Default.WSSKeyExchange); } } - }); - } - - internal static async Task GetChannel(long id, JsonTypeInfo Json) where TChannel : SocketChannel, new() - { - TChannel request; - if (Server.chans is null) Server.chans = new(); - if (Server.chans.Count > 0 && Server.chans.Any(s => s.Id == id)) - { - return Server.chans.Where(s => s is TChannel && s.Id == id).Cast().FirstOrDefault()!; - } - while (true) - { - if (Server.CanRequest) - { - request = await Server.GetFromServer($"SocketChannel/Get/{id}", Json); - break; - } - } - if (request is null) throw new Exception("Something was wrong with the server responce"); - if (request.Error is null) - { - if (Server.chans is null) Server.chans = new(); - if (Server.chans.Count > 0 && Server.chans.Any(s => s.Id == request.Id)) - { - foreach (SocketChannel? p in Server.chans.Where(s => s.Id == request.Id)) - { - Server.chans.Remove(p); - } - } - Server.chans.Add(request); - return request; - } - throw request.Error switch - { - ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"), - ErrorCode.Forbidden => new Exception("The server rejected your request"), - ErrorCode.ServerError => new Exception("Error from server: " + request.ErrorMessage), - ErrorCode.InvalidURL or ErrorCode.MissingHeader => new Exception(request.ErrorMessage), - _ => new Exception($"Unknown data: '{request.ErrorMessage}'"), - }; + });*/ + return Task.CompletedTask; } } -[JsonSerializable(typeof(SocketChannel))] +[JsonSerializable(typeof(MainSocketChannel))] [JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, WriteIndented = false)] -internal partial class SocketChannelContext : JsonSerializerContext +internal partial class MainSocketChannelContext : JsonSerializerContext { } \ No newline at end of file diff --git a/Luski.net/Structures/Main/MainSocketDMChannel.cs b/Luski.net/Structures/Main/MainSocketDMChannel.cs new file mode 100755 index 0000000..c330a3d --- /dev/null +++ b/Luski.net/Structures/Main/MainSocketDMChannel.cs @@ -0,0 +1,34 @@ +using Luski.net.JsonTypes.BaseTypes; +using System.Linq; +using System.Text.Json.Serialization; +using System.Threading; + +namespace Luski.net.Structures.Main; + +public class MainSocketDMChannel : MainSocketTextChannel +{ + public MainSocketRemoteUser User + { + get + { + if (_user is null) + { + var list = MemberIdList.ToList(); + list.Remove(Server.IAppUser.Id); + _user = Server.GetUser(list.FirstOrDefault(), CancellationToken.None).Result; + } + return _user; + } + } + public MainSocketRemoteUser _user = null!; +} + +[JsonSerializable(typeof(MainSocketDMChannel))] +[JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Default, + PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, + WriteIndented = false)] +internal partial class MainSocketDMChannelContext : JsonSerializerContext +{ + +} diff --git a/Luski.net/JsonTypes/SocketGroupChannel.cs b/Luski.net/Structures/Main/MainSocketGroupChannel.cs similarity index 59% rename from Luski.net/JsonTypes/SocketGroupChannel.cs rename to Luski.net/Structures/Main/MainSocketGroupChannel.cs index f7a3300..1e865d2 100755 --- a/Luski.net/JsonTypes/SocketGroupChannel.cs +++ b/Luski.net/Structures/Main/MainSocketGroupChannel.cs @@ -1,20 +1,20 @@ using System.Text.Json.Serialization; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures.Main; -public class SocketGroupChannel : SocketTextChannel +public class MainSocketGroupChannel : MainSocketTextChannel { [JsonPropertyName("owner")] [JsonInclude] public long Owner { get; internal set; } = default!; } -[JsonSerializable(typeof(SocketGroupChannel))] +[JsonSerializable(typeof(MainSocketGroupChannel))] [JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, WriteIndented = false)] -internal partial class SocketGroupChannelContext : JsonSerializerContext +internal partial class MainSocketGroupChannelContext : JsonSerializerContext { } diff --git a/Luski.net/JsonTypes/SocketRemoteUser.cs b/Luski.net/Structures/Main/MainSocketRemoteUser.cs similarity index 60% rename from Luski.net/JsonTypes/SocketRemoteUser.cs rename to Luski.net/Structures/Main/MainSocketRemoteUser.cs index 11277b4..9ac8862 100755 --- a/Luski.net/JsonTypes/SocketRemoteUser.cs +++ b/Luski.net/Structures/Main/MainSocketRemoteUser.cs @@ -7,29 +7,29 @@ using System.Net.Http; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; +using Luski.net.Enums.Main; +using Luski.net.Structures; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures; -public class SocketRemoteUser : SocketUserBase +public class MainSocketRemoteUser : SocketUserBase { [JsonPropertyName("friend_status")] [JsonInclude] public FriendStatus FriendStatus { get; internal set; } = default!; - [JsonIgnore] - public SocketDMChannel Channel { get; internal set; } = default!; - internal SocketRemoteUser Clone() + internal MainSocketRemoteUser Clone() { - return (SocketRemoteUser)MemberwiseClone(); + return (MainSocketRemoteUser)MemberwiseClone(); } } -[JsonSerializable(typeof(SocketRemoteUser))] +[JsonSerializable(typeof(MainSocketRemoteUser))] [JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, WriteIndented = false)] -internal partial class SocketRemoteUserContext : JsonSerializerContext +internal partial class MainSocketRemoteUserContext : JsonSerializerContext { } diff --git a/Luski.net/JsonTypes/SocketTextChannel.cs b/Luski.net/Structures/Main/MainSocketTextChannel.cs similarity index 71% rename from Luski.net/JsonTypes/SocketTextChannel.cs rename to Luski.net/Structures/Main/MainSocketTextChannel.cs index 5b61339..ce83d2e 100755 --- a/Luski.net/JsonTypes/SocketTextChannel.cs +++ b/Luski.net/Structures/Main/MainSocketTextChannel.cs @@ -7,32 +7,36 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; +using JacobTechEncryption; +using JacobTechEncryption.Enums; +using Luski.net.Enums.Main; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures.Main; -public class SocketTextChannel : SocketChannel, ITextChannel +public class MainSocketTextChannel : MainSocketChannel { - public async Task GetMessage(long ID) + public async Task GetMessage(long ID, CancellationToken CancellationToken) { - return await SocketMessage.GetMessage(ID); + return await (Server as Server)!.GetMessage(ID, CancellationToken); } - public async Task GetPicture() + public async Task GetPicture(CancellationToken CancellationToken) { - if (Type == ChannelType.DM) return Members.First().GetAvatar().Result; + if (Type == ChannelType.DM) return Members.First().GetAvatar(CancellationToken).Result; else { if (Server.Cache != null) { bool isc = System.IO.File.Exists($"{Server.Cache}/channels/{Id}"); - if (!isc) await Server.GetFromServer($"SocketChannel/GetPicture/{Id}", $"{Server.Cache}/channels/{Id}"); + if (!isc) await Server.GetFromServer($"SocketChannel/GetPicture/{Id}", $"{Server.Cache}/channels/{Id}", CancellationToken); } return System.IO.File.ReadAllBytes($"{Server.Cache}/channels/{Id}"); } } - public async Task> GetMessages(long Message_Id, int count = 50) + public async Task> GetMessages(long Message_Id, CancellationToken CancellationToken, int count = 50) { if (count > 200) { @@ -46,15 +50,16 @@ public class SocketTextChannel : SocketChannel, ITextChannel { SocketBulkMessage data = await Server.GetFromServer("SocketBulkMessage", SocketBulkMessageContext.Default.SocketBulkMessage, + CancellationToken, new KeyValuePair("channel_id", Id.ToString()), new KeyValuePair("messages", count.ToString()), new KeyValuePair("mostrecentid", Message_Id.ToString())); if (data.Error is null) { - int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Server.Percent) * 2.0)); + int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 5) * 2.0)); if (num == 0) num = 1; - string? key = Encryption.File.Channels.GetKey(Id); + string? key = ClientEncryption.File.Channels.GetKey(Id); if (data is null) throw new Exception("Invalid data from server"); if (data.Messages is null) data.Messages = Array.Empty(); Parallel.ForEach(data.Messages, new ParallelOptions() @@ -62,7 +67,7 @@ public class SocketTextChannel : SocketChannel, ITextChannel MaxDegreeOfParallelism = num }, i => { - i.decrypt(key); + i.decrypt(key, CancellationToken); }); key = null; return await Task.FromResult(data.Messages.ToList().AsReadOnly() as IReadOnlyList); @@ -74,7 +79,7 @@ public class SocketTextChannel : SocketChannel, ITextChannel } } - public async Task> GetMessages(int count = 50) + public async Task> GetMessages(CancellationToken CancellationToken, int count = 50) { try { @@ -88,24 +93,29 @@ public class SocketTextChannel : SocketChannel, ITextChannel } else { + DateTime start = DateTime.Now; SocketBulkMessage data = await Server.GetFromServer("SocketBulkMessage", SocketBulkMessageContext.Default.SocketBulkMessage, + CancellationToken, new KeyValuePair("id", Id.ToString()), new KeyValuePair("messages", count.ToString())); + Console.WriteLine($"Messages downloaded in {(DateTime.Now - start).TotalSeconds}"); + start = DateTime.Now; if (data is not null && !data.Error.HasValue) { - int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Server.Percent) * 2.0)); + int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 5) * 2.0)); if (num == 0) num = 1; - string? key = Encryption.File.Channels.GetKey(Id); + string? key = ClientEncryption.File.Channels.GetKey(Id); if (data.Messages is null) data.Messages = Array.Empty(); Parallel.ForEach(data.Messages, new ParallelOptions() { MaxDegreeOfParallelism = num }, i => { - i.decrypt(key); + i.decrypt(key, CancellationToken); }); key = null; + Console.WriteLine($"Messages decrypted in {(DateTime.Now - start).TotalSeconds}"); return await Task.FromResult(data.Messages.ToList().AsReadOnly() as IReadOnlyList); } else @@ -128,13 +138,13 @@ public class SocketTextChannel : SocketChannel, ITextChannel } } - public async Task SendMessage(string Message, params File?[] Files) + public async Task SendMessage(string Message, CancellationToken CancellationToken, params File?[] Files) { - string key = Encryption.File.Channels.GetKey(Id); - if (Id == 0) key = Encryption.ServerPublicKey; - HTTP.Message m = new() + string key = ClientEncryption.File.Channels.GetKey(Id); + if (Id == 0) key = "";//ClientEncryption.ServerPublicKey; + JsonTypes.HTTP.Message m = new() { - Context = Convert.ToBase64String(Encryption.Encrypt(Message, key)), + Context = Convert.ToBase64String(Encryption.RSA.Encrypt(Message, key, EncoderType.UTF8)), Channel = Id, }; if (Files is not null && Files.Length > 0) @@ -145,24 +155,24 @@ public class SocketTextChannel : SocketChannel, ITextChannel File? ff = Files[i]; if (ff is not null) { - bb.Add(await ff.Upload(key)); + bb.Add(await ff.Upload(key, CancellationToken)); Files[i] = null; } } m.Files = bb.ToArray(); } - IncomingHTTP data = await Server.SendServer("socketmessage", m, HTTP.MessageContext.Default.Message, IncomingHTTPContext.Default.IncomingHTTP); + IncomingHTTP data = await Server.SendServer("socketmessage", m, net.JsonTypes.HTTP.MessageContext.Default.Message, IncomingHTTPContext.Default.IncomingHTTP, CancellationToken); if (data.Error is not null && data.ErrorMessage != "Server responded with empty data") throw new Exception(data.ErrorMessage); return Task.CompletedTask; } } -[JsonSerializable(typeof(SocketTextChannel))] +[JsonSerializable(typeof(MainSocketTextChannel))] [JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, WriteIndented = false)] -internal partial class SocketTextChannelContext : JsonSerializerContext +internal partial class MainSocketTextChannelContext : JsonSerializerContext { } diff --git a/Luski.net/Structures/Public/PublicSocketAppUser.cs b/Luski.net/Structures/Public/PublicSocketAppUser.cs new file mode 100755 index 0000000..0b7250b --- /dev/null +++ b/Luski.net/Structures/Public/PublicSocketAppUser.cs @@ -0,0 +1,35 @@ +using System; +using Luski.net.Interfaces; +using Luski.net.JsonTypes.BaseTypes; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using System.Threading; +using System.Threading.Tasks; +using JacobTechEncryption; +using Luski.net.Enums; +using Luski.net.Enums.Main; + +namespace Luski.net.Structures.Public; + +public class PublicSocketAppUser : SocketUserBase, IAppUser +{ + [JsonPropertyName("selected_channel")] + [JsonInclude] + public long SelectedChannel { get; internal set; } = default!; + [JsonPropertyName("username")] + [JsonInclude] + public string Username { get; internal set; } = default!; +} + +[JsonSerializable(typeof(PublicSocketAppUser))] +[JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Default, + PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never)] +internal partial class PublicSocketAppUserContext : JsonSerializerContext +{ + +} diff --git a/Luski.net/JsonTypes/SocketBulkMessage.cs b/Luski.net/Structures/SocketBulkMessage.cs similarity index 89% rename from Luski.net/JsonTypes/SocketBulkMessage.cs rename to Luski.net/Structures/SocketBulkMessage.cs index 7ca8518..3ec44d4 100755 --- a/Luski.net/JsonTypes/SocketBulkMessage.cs +++ b/Luski.net/Structures/SocketBulkMessage.cs @@ -1,7 +1,7 @@ using Luski.net.JsonTypes.BaseTypes; using System.Text.Json.Serialization; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures; internal class SocketBulkMessage : IncomingHTTP { @@ -11,7 +11,6 @@ internal class SocketBulkMessage : IncomingHTTP } [JsonSerializable(typeof(SocketBulkMessage))] -[JsonSerializable(typeof(SocketAppUser))] [JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Default, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, diff --git a/Luski.net/JsonTypes/SocketMessage.cs b/Luski.net/Structures/SocketMessage.cs similarity index 50% rename from Luski.net/JsonTypes/SocketMessage.cs rename to Luski.net/Structures/SocketMessage.cs index aa4c948..5e41bda 100755 --- a/Luski.net/JsonTypes/SocketMessage.cs +++ b/Luski.net/Structures/SocketMessage.cs @@ -3,14 +3,18 @@ using Luski.net.JsonTypes.BaseTypes; using System; using System.Linq; using System.Net.Http; +using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; +using JacobTechEncryption; -namespace Luski.net.JsonTypes; +namespace Luski.net.Structures; public class SocketMessage : IncomingHTTP { + public IServer Server { get; } [JsonPropertyName("id")] [JsonInclude] public long Id { get; internal set; } = default!; @@ -26,29 +30,16 @@ public class SocketMessage : IncomingHTTP [JsonPropertyName("files")] [JsonInclude] public File[]? Files { get; internal set; } = default!; - public async Task GetChannel() + public async Task GetAuthor(CancellationToken CancellationToken) { - if (Server.chans.Any(s => s.Id == ChannelID)) - { - return (SocketTextChannel)Server.chans.Where(s => s.Id == ChannelID).First(); - } - else - { - SocketTextChannel ch = await SocketChannel.GetChannel(ChannelID, SocketTextChannelContext.Default.SocketTextChannel); - Server.chans.Add(ch); - return ch; - } - } - public async Task GetAuthor() - { - if (Server._user!.Id != AuthorID) return await SocketUserBase.GetUser(AuthorID, SocketRemoteUserContext.Default.SocketRemoteUser); - else return Server._user; + if (Server.IAppUser!.Id != AuthorID) return await Server.GetUser(AuthorID, CancellationToken); + else return Server.IAppUser; } - internal void decrypt(string? key) + internal void decrypt(string? key, CancellationToken CancellationToken) { if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key)); - Context = Encryption.Encoder.GetString(Encryption.Decrypt(Convert.FromBase64String(Context), key)); + Context = Encoding.UTF8.GetString(Encryption.AES.Decrypt(Convert.FromBase64String(Context), key)); if (Files is not null && Files.Length > 0) { for (int i = 0; i < Files.Length; i++) @@ -58,22 +49,6 @@ public class SocketMessage : IncomingHTTP } } } - internal static async Task GetMessage(long id) - { - SocketMessage message; - while (true) - { - if (Server.CanRequest) - { - message = await Server.GetFromServer("socketmessage", - SocketMessageContext.Default.SocketMessage, - new System.Collections.Generic.KeyValuePair("msg_id", id.ToString())); - break; - } - } - if (message is not null) return message; - throw new Exception("Server did not return a message"); - } } [JsonSerializable(typeof(SocketMessage))] diff --git a/Luski.net/Structures/SocketUserBase.cs b/Luski.net/Structures/SocketUserBase.cs new file mode 100644 index 0000000..f29c9ec --- /dev/null +++ b/Luski.net/Structures/SocketUserBase.cs @@ -0,0 +1,53 @@ +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Luski.net.Enums; +using Luski.net.Interfaces; +using Luski.net.JsonTypes.BaseTypes; + +namespace Luski.net.Structures; + +public class SocketUserBase : IncomingHTTP, IUser +{ + [JsonPropertyName("id")] + [JsonInclude] + public long Id { get; internal set; } = default!; + [JsonPropertyName("username")] + [JsonInclude] + public string DisplayName { get; internal set; } = default!; + [JsonPropertyName("status")] + [JsonInclude] + public UserStatus Status { get; internal set; } = default!; + [JsonPropertyName("picture_type")] + [JsonInclude] + public PictureType PictureType { get; internal set; } = default!; + [JsonIgnore] + public IServer Server { get; internal set; } = default!; + + public async Task GetAvatar(CancellationToken CancellationToken) + { + if (Server.Cache != null) + { + bool isc = System.IO.File.Exists($"{Server.Cache}/avatars/{Id}"); + if (!isc) await Server.GetFromServer($"socketuserprofile/Avatar/{Id}", $"{Server.Cache}/avatars/{Id}", CancellationToken); + } + return System.IO.File.ReadAllBytes($"{Server.Cache}/avatars/{Id}"); + } + + public Task GetUserKey(CancellationToken CancellationToken) + { + string data = Server.GetFromServer($"Keys/GetUserKey/{Id}", CancellationToken).Content.ReadAsStringAsync().Result; + return Task.FromResult(long.Parse(data)); + } +} + +[JsonSerializable(typeof(SocketUserBase))] +[JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Default, + PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never)] +internal partial class SocketUserBaseContext : JsonSerializerContext +{ + +} \ No newline at end of file