commit
34633ad2e4
25
Luski.net.sln
Executable file
25
Luski.net.sln
Executable file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
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
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3DF9B870-51B3-4338-84EC-75E4B8802F0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{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
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {49AFEA24-10EC-4D2C-B99C-C3E70124E443}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
163
Luski.net/API.cs
Normal file
163
Luski.net/API.cs
Normal file
@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Luski.net.Enums;
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
|
||||
|
||||
namespace Luski.net;
|
||||
|
||||
public class API
|
||||
{
|
||||
[JsonIgnore]
|
||||
public MainServer MainServer { get; internal set; }
|
||||
|
||||
public bool IsAnyServerLoggedin { get; internal set; }
|
||||
|
||||
public const string DefaultVersion = "v1";
|
||||
|
||||
internal List<string> Versions = new()
|
||||
{
|
||||
DefaultVersion
|
||||
};
|
||||
|
||||
public IReadOnlyList<string> SupportedVersions => Versions.AsReadOnly();
|
||||
internal List<PublicServer> InternalServers { get; } = new();
|
||||
public IReadOnlyList<PublicServer> LoadedServers => InternalServers.AsReadOnly();
|
||||
|
||||
internal List<PublicServer> InternalFailedServers { get; } = new();
|
||||
public IReadOnlyList<PublicServer> FailedServers => InternalFailedServers.AsReadOnly();
|
||||
|
||||
private static HttpResponseMessage GetFromServer(string Domain, string ApiVersion, bool Secure, string Path, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
||||
{
|
||||
using HttpClient web = new();
|
||||
web.Timeout = TimeSpan.FromSeconds(10);
|
||||
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
||||
return web.GetAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", cancellationToken: CancellationToken).Result;
|
||||
}
|
||||
private static Task<Tresult> GetFromServer<Tresult>(string Domain, string ApiVersion, bool Secure, string Path, JsonTypeInfo<Tresult> Type, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers) where Tresult : STC, new()
|
||||
{
|
||||
HttpResponseMessage ServerResponce = GetFromServer(Domain, ApiVersion, Secure, Path, CancellationToken, Headers);
|
||||
Tresult temp = new();
|
||||
string raw = ServerResponce.Content.ReadAsStringAsync(CancellationToken).Result;
|
||||
try
|
||||
{
|
||||
temp = JsonSerializer.Deserialize(raw, Type)!;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("JSON parse failed for the following data as type {0}\n{1}", temp.GetType(), raw);
|
||||
}
|
||||
if (temp is null) return Task.FromResult(new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" });
|
||||
return Task.FromResult(temp);
|
||||
}
|
||||
|
||||
public Task<ServerInfoSTC> GetServerInfo(string Domain, string Version = DefaultVersion,
|
||||
bool Secure = true)
|
||||
{
|
||||
ServerInfoSTC? si = GetFromServer(Domain, Version, Secure, "socketserver", ServerInfoSTCContext.Default.ServerInfoSTC, CancellationToken.None).Result;
|
||||
if (si is null) throw new Exception("Bad Response");
|
||||
return Task.FromResult(si);
|
||||
}
|
||||
|
||||
public Task<bool> TryGetServerInfo([NotNullWhen(true)]out ServerInfoSTC? si, string Domain, string Version = DefaultVersion,
|
||||
bool Secure = true)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
si = GetServerInfo(Domain, Version, Secure).Result;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
si = null;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<bool> TryGetPublicServer(out PublicServer Server, string Domain, string Version = DefaultVersion,
|
||||
bool Secure = true, bool GenerateEncryption = true, bool LogConsole = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
Task<PublicServer> result = GetPublicServer(Domain, Version, Secure, GenerateEncryption, LogConsole);
|
||||
Task.WaitAll(result);
|
||||
Server = result.Result;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!e.Message.Contains("Connection refused")) Console.WriteLine(e);
|
||||
Server = null!;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<PublicServer> GetPublicServer(string Domain, string Version = DefaultVersion, bool Secure = true, bool GenerateEncryption = true, bool LogConsole = false)
|
||||
{
|
||||
PublicServer s;
|
||||
try
|
||||
{
|
||||
IEnumerable<PublicServer> isl = InternalServers.Where(a => (a.Domain == Domain && a.ApiVersion == Version));
|
||||
if (isl.Any()) return isl.First();
|
||||
s = await PublicServer.GetServer(InternalFailedServers, Domain, Version, Secure, GenerateEncryption, LogConsole);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Failed to connect to public server '{0}' using API {1}. No alternate server was found.", Domain, Version);
|
||||
throw;
|
||||
}
|
||||
|
||||
string? f = s.Storage.GetStorageDirectory(StorageDirectory.StorageInfo) + "token";
|
||||
if (File.Exists(f))
|
||||
{
|
||||
f = File.ReadAllText(f);
|
||||
}
|
||||
else f = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (f is not null)
|
||||
{
|
||||
bool b = await s.LoginViaToken(f);
|
||||
if (b)
|
||||
{
|
||||
IsAnyServerLoggedin = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.Token = null;
|
||||
s.Error = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
InternalServers.Add(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public MainServer GetMainServer(string Domain, string Version = DefaultVersion)
|
||||
{
|
||||
DateTime dt = DateTime.UtcNow;
|
||||
Console.WriteLine("Conecting to main server '{0}' using API {1}.", Domain, Version);
|
||||
MainServer = new(Domain, Version)
|
||||
{
|
||||
ServerType = ServerType.Main
|
||||
};
|
||||
Console.WriteLine("Connected to main server '{0}' using API {1} in {2}.", Domain, Version, DateTime.UtcNow.Subtract(dt).ToString("g"));
|
||||
return MainServer;
|
||||
}
|
||||
}
|
13
Luski.net/Classes/RoleComparer.cs
Normal file
13
Luski.net/Classes/RoleComparer.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Luski.net.Structures.Public;
|
||||
|
||||
namespace Luski.net.Classes;
|
||||
|
||||
public class RoleComparer : IComparer<Role>
|
||||
{
|
||||
public int Compare(Role x, Role y)
|
||||
{
|
||||
return y.Index - x.Index;
|
||||
}
|
||||
}
|
458
Luski.net/ClientEncryption.cs
Executable file
458
Luski.net/ClientEncryption.cs
Executable file
@ -0,0 +1,458 @@
|
||||
/*using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Luski.net
|
||||
{
|
||||
public static class ClientEncryption
|
||||
{
|
||||
internal static string pw = "";
|
||||
|
||||
public static class File
|
||||
{/*
|
||||
internal static void SetOfflineKey(string key)
|
||||
{
|
||||
MakeFile("Server.GetKeyFilePath", pw);
|
||||
LuskiDataFile? fileLayout = JsonSerializer.Deserialize<LuskiDataFile>(FileString("Server.GetKeyFilePath", pw));
|
||||
fileLayout.OfflineKey = key;
|
||||
fileLayout.Save("Server.GetKeyFilePath", pw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal static string? GetOfflineKey()
|
||||
{
|
||||
MakeFile("Server.GetKeyFilePath", pw);
|
||||
LuskiDataFile? fileLayout = JsonSerializer.Deserialize<LuskiDataFile>(FileString("Server.GetKeyFilePath", pw));
|
||||
return fileLayout?.OfflineKey;
|
||||
}
|
||||
|
||||
public static LuskiDataFile GetFile()
|
||||
{
|
||||
MakeFile("Server.GetKeyFilePath", pw);
|
||||
return JsonSerializer.Deserialize<LuskiDataFile>(FileString("Server.GetKeyFilePath", pw))!;
|
||||
}
|
||||
|
||||
private static string FileString(string path, string password)
|
||||
{
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
|
||||
byte[] salt = new byte[100];
|
||||
FileStream fsCrypt = new(path, FileMode.Open);
|
||||
fsCrypt.Read(salt, 0, salt.Length);
|
||||
RijndaelManaged AES = new()
|
||||
{
|
||||
KeySize = 256,
|
||||
BlockSize = 128
|
||||
};
|
||||
Rfc2898DeriveBytes key = new(passwordBytes, salt, 50000);
|
||||
AES.Key = key.GetBytes(AES.KeySize / 8);
|
||||
AES.IV = key.GetBytes(AES.BlockSize / 8);
|
||||
AES.Padding = PaddingMode.PKCS7;
|
||||
AES.Mode = CipherMode.CFB;
|
||||
CryptoStream cs = new(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);
|
||||
MemoryStream fsOut = new();
|
||||
int read;
|
||||
byte[] buffer = new byte[1048576];
|
||||
try
|
||||
{
|
||||
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
fsOut.Write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
catch (CryptographicException ex_CryptographicException)
|
||||
{
|
||||
Console.WriteLine("CryptographicException error: " + ex_CryptographicException.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error: " + ex.Message);
|
||||
}
|
||||
fsOut.Seek(0, SeekOrigin.Begin);
|
||||
using BinaryReader reader = new(fsOut);
|
||||
byte[] by = reader.ReadBytes((int)fsOut.Length);
|
||||
fsOut.Close();
|
||||
fsCrypt.Close();
|
||||
return Encoding.UTF8.GetString(by);
|
||||
}
|
||||
|
||||
public static class Channels
|
||||
{
|
||||
private static string GetKey(long channel)
|
||||
{
|
||||
LuskiDataFile? fileLayout;
|
||||
IEnumerable<ChannelLayout>? lis;
|
||||
try
|
||||
{
|
||||
#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<LuskiDataFile>(FileString("Server.GetKeyFilePath", pw));
|
||||
lis = fileLayout?.channels?.Where(s => s.id == channel);
|
||||
if (lis?.Count() > 0)
|
||||
{
|
||||
return lis.First().key;
|
||||
}
|
||||
throw new Exception("You dont have a key for that channel");
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLayout = null;
|
||||
lis = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GetKeyBranch(long channel)
|
||||
{
|
||||
LuskiDataFile? fileLayout;
|
||||
IEnumerable<ChannelLayout>? lis;
|
||||
try
|
||||
{
|
||||
#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<LuskiDataFile>(FileString("", pw));
|
||||
lis = fileLayout?.channels?.Where(s => s.id == channel);
|
||||
if (lis?.Count() > 0)
|
||||
{
|
||||
return lis.First().key;
|
||||
}
|
||||
throw new Exception("You dont have a key for that channel");
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileLayout = null;
|
||||
lis = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddKey(long channel, string key)
|
||||
{
|
||||
MakeFile("Server.GetKeyFilePath", pw);
|
||||
LuskiDataFile? fileLayout = JsonSerializer.Deserialize<LuskiDataFile>(FileString("Server.GetKeyFilePath", pw));
|
||||
fileLayout?.Addchannelkey(channel, key);
|
||||
fileLayout?.Save("Server.GetKeyFilePath", pw);
|
||||
}
|
||||
}
|
||||
|
||||
private static void MakeFile(string dir, string password)
|
||||
{
|
||||
if (!System.IO.File.Exists(dir))
|
||||
{
|
||||
LuskiDataFile? l = JsonSerializer.Deserialize<LuskiDataFile>("{\"channels\":[]}");
|
||||
l?.Save(dir, password);
|
||||
}
|
||||
}
|
||||
|
||||
public class LuskiDataFile
|
||||
{
|
||||
public static LuskiDataFile GetDataFile(string path, string password)
|
||||
{
|
||||
MakeFile(path, password);
|
||||
return JsonSerializer.Deserialize<LuskiDataFile>(FileString(path, password));
|
||||
}
|
||||
|
||||
internal static LuskiDataFile GetDefualtDataFile()
|
||||
{
|
||||
return GetDataFile("Server.GetKeyFilePath", pw);
|
||||
}
|
||||
|
||||
public ChannelLayout[]? channels { get; set; } = default!;
|
||||
|
||||
public string? OfflineKey { get; set; } = default!;
|
||||
|
||||
public void Save(string file, string password)
|
||||
{
|
||||
byte[] salt = new byte[100];
|
||||
RandomNumberGenerator? provider = RandomNumberGenerator.Create();
|
||||
provider.GetBytes(salt);
|
||||
FileStream fsCrypt = new(file, FileMode.Create);
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
|
||||
RijndaelManaged AES = new()
|
||||
{
|
||||
KeySize = 256,
|
||||
BlockSize = 128,
|
||||
Padding = PaddingMode.PKCS7
|
||||
};
|
||||
Rfc2898DeriveBytes key = new(passwordBytes, salt, 50000);
|
||||
AES.Key = key.GetBytes(AES.KeySize / 8);
|
||||
AES.IV = key.GetBytes(AES.BlockSize / 8);
|
||||
AES.Mode = CipherMode.CFB;
|
||||
fsCrypt.Write(salt, 0, salt.Length);
|
||||
CryptoStream cs = new(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
|
||||
string tempp = JsonSerializer.Serialize(this);
|
||||
MemoryStream fsIn = new(Encoding.UTF8.GetBytes(tempp));
|
||||
byte[] buffer = new byte[1048576];
|
||||
int read;
|
||||
try
|
||||
{
|
||||
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
cs.Write(buffer, 0, read);
|
||||
}
|
||||
fsIn.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error: " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cs.Close();
|
||||
fsCrypt.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void Addchannelkey(long chan, string Key)
|
||||
{
|
||||
List<ChannelLayout>? chans = channels?.ToList();
|
||||
if (chans is null) chans = new();
|
||||
if (!(chans?.Where(s => s.id == chan).Count() > 0))
|
||||
{
|
||||
ChannelLayout l = new()
|
||||
{
|
||||
id = chan,
|
||||
key = Key
|
||||
};
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ChannelLayout
|
||||
{
|
||||
public long id { get; set; } = default!;
|
||||
public string key { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
public class AES
|
||||
{
|
||||
public static string Encrypt(string path, string Password)
|
||||
{
|
||||
string p = Path.GetTempFileName();
|
||||
byte[] salt = RandomNumberGenerator.GetBytes(100);
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(Password);
|
||||
Rfc2898DeriveBytes key = new(passwordBytes, salt, 50000);
|
||||
byte[] data = System.IO.File.ReadAllBytes(path);
|
||||
|
||||
using Aes aesAlg = Aes.Create();
|
||||
aesAlg.KeySize = 256;
|
||||
aesAlg.BlockSize = 128;
|
||||
aesAlg.Padding = PaddingMode.PKCS7;
|
||||
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
|
||||
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
|
||||
|
||||
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
|
||||
|
||||
using FileStream msEncrypt = new(p, FileMode.Open);
|
||||
msEncrypt.Write(salt, 0, salt.Length);
|
||||
using CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write);
|
||||
csEncrypt.Write(data, 0, data.Length);
|
||||
csEncrypt.Dispose();
|
||||
msEncrypt.Dispose();
|
||||
return p;
|
||||
|
||||
|
||||
|
||||
|
||||
string p = Path.GetTempFileName();
|
||||
byte[] salt = new byte[100];
|
||||
RNGCryptoServiceProvider provider = new();
|
||||
provider.GetBytes(salt);
|
||||
FileStream fsCrypt = new(p, FileMode.Open);
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(Password);
|
||||
Aes AES = Aes.Create();
|
||||
AES.KeySize = 256;
|
||||
AES.BlockSize = 128;
|
||||
AES.Padding = PaddingMode.PKCS7;
|
||||
Rfc2898DeriveBytes key = new(passwordBytes, salt, 50000);
|
||||
AES.Key = key.GetBytes(AES.KeySize / 8);
|
||||
AES.IV = key.GetBytes(AES.BlockSize / 8);
|
||||
AES.Mode = CipherMode.CFB;
|
||||
fsCrypt.Write(salt, 0, salt.Length);
|
||||
key.Dispose();
|
||||
CryptoStream cs = new(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
|
||||
FileStream fsIn = new(path, FileMode.Open);
|
||||
try
|
||||
{
|
||||
FileInfo FI = new(path);
|
||||
byte[] buffer = new byte[FI.Length];
|
||||
int read;
|
||||
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
cs.Write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
catch (OutOfMemoryException ex)
|
||||
{
|
||||
throw new Exception("Buffer", ex);
|
||||
}
|
||||
fsIn.Close();
|
||||
fsIn.Dispose();
|
||||
cs.Close();
|
||||
cs.Dispose();
|
||||
fsCrypt.Close();
|
||||
fsCrypt.Dispose();
|
||||
NewPath = p;
|
||||
}
|
||||
|
||||
public static void Decrypt(byte[] data, string Password, string File)
|
||||
{
|
||||
byte[] salt = new byte[100];
|
||||
using MemoryStream fsCrypt = new(data);
|
||||
fsCrypt.Read(salt, 0, salt.Length);
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(Password);
|
||||
Rfc2898DeriveBytes key = new(passwordBytes, salt, 50000);
|
||||
byte[] decrypted = new byte[data.Length - salt.Length];
|
||||
|
||||
using Aes aesAlg = Aes.Create();
|
||||
aesAlg.KeySize = 256;
|
||||
aesAlg.BlockSize = 128;
|
||||
aesAlg.Padding = PaddingMode.PKCS7;
|
||||
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
|
||||
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
|
||||
|
||||
ICryptoTransform encryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
|
||||
|
||||
using CryptoStream csEncrypt = new(fsCrypt, encryptor, CryptoStreamMode.Read);
|
||||
FileStream fsOut = new(File, FileMode.Create);
|
||||
int read;
|
||||
byte[] buffer = new byte[data.Length];
|
||||
while ((read = csEncrypt.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
fsOut.Write(buffer, 0, read);
|
||||
}
|
||||
csEncrypt.Dispose();
|
||||
fsCrypt.Dispose();
|
||||
fsOut.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Hash(byte[] data)
|
||||
{
|
||||
return SHA256.Create().ComputeHash(data);
|
||||
}
|
||||
|
||||
internal static byte[] Encrypt(string data)
|
||||
{
|
||||
return Encrypt(data, ServerPublicKey);
|
||||
}
|
||||
|
||||
internal static byte[] Encrypt(byte[] data)
|
||||
{
|
||||
return Encrypt(data, ServerPublicKey);
|
||||
}
|
||||
|
||||
internal static byte[] Encrypt(string data, string key, bool multithread = false)
|
||||
{
|
||||
return Encrypt(Encoder.GetBytes(data), key, multithread);
|
||||
}
|
||||
|
||||
internal static byte[] Encrypt(byte[] data, string key, bool multithread = false)
|
||||
{
|
||||
using RSACryptoServiceProvider rsa = new();
|
||||
rsa.FromXmlString(key);
|
||||
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++;
|
||||
byte[]? datasplitout = Array.Empty<byte>();
|
||||
if (multithread)
|
||||
{
|
||||
byte[][]? decccc = Array.Empty<byte[]>();
|
||||
Array.Resize(ref decccc, bbb);
|
||||
int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Server.Percent) * 2.0));
|
||||
if (num == 0) num = 1;
|
||||
Parallel.For(0, bbb, new ParallelOptions()
|
||||
{
|
||||
MaxDegreeOfParallelism = num
|
||||
}, i =>
|
||||
{
|
||||
decccc[i] = rsa.Encrypt(data.Skip(i * size).Take(size).ToArray(), true);
|
||||
});
|
||||
foreach (byte[] dataa in decccc)
|
||||
{
|
||||
datasplitout = Combine(datasplitout, dataa);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < bbb; i++)
|
||||
{
|
||||
datasplitout = Combine(datasplitout, rsa.Encrypt(data.Skip(i * size).Take(size).ToArray(), false));
|
||||
}
|
||||
}
|
||||
return datasplitout;
|
||||
}
|
||||
|
||||
private static byte[] Combine(byte[] first, byte[] second)
|
||||
{
|
||||
byte[]? bytes = new byte[first.Length + second.Length];
|
||||
Buffer.BlockCopy(first, 0, bytes, 0, first.Length);
|
||||
Buffer.BlockCopy(second, 0, bytes, first.Length, second.Length);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
internal static byte[] Decrypt(byte[] EncryptedText, bool multithread = false)
|
||||
{
|
||||
return Decrypt(EncryptedText, myPrivateKey, multithread);
|
||||
}
|
||||
|
||||
internal static byte[] Decrypt(byte[]? EncryptedText, string? key, bool multithread = false)
|
||||
{
|
||||
if (key is null) throw new ArgumentNullException(nameof(key));
|
||||
if (EncryptedText is null) throw new ArgumentNullException(nameof(EncryptedText));
|
||||
using RSACryptoServiceProvider rsa = new();
|
||||
rsa.FromXmlString(key);
|
||||
int size = rsa.KeySize / 8;
|
||||
double x = EncryptedText.Length / (double)size;
|
||||
int bbb = int.Parse(x.ToString().Split('.')[0]);
|
||||
if (x.ToString().Contains('.')) bbb++;
|
||||
byte[]? datasplitout = Array.Empty<byte>();
|
||||
if (multithread)
|
||||
{
|
||||
byte[][]? decccc = Array.Empty<byte[]>();
|
||||
Array.Resize(ref decccc, bbb);
|
||||
int num = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * Server.Percent) * 2.0));
|
||||
if (num == 0) num = 1;
|
||||
Parallel.For(0, bbb, new ParallelOptions()
|
||||
{
|
||||
MaxDegreeOfParallelism = num
|
||||
}, i =>
|
||||
{
|
||||
decccc[i] = rsa.Decrypt(EncryptedText.Skip(i * size).Take(size).ToArray(), true);
|
||||
});
|
||||
foreach (byte[] data in decccc)
|
||||
{
|
||||
datasplitout = Combine(datasplitout, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < bbb; i++)
|
||||
{
|
||||
datasplitout = Combine(datasplitout, rsa.Decrypt(EncryptedText.Skip(i * size).Take(size).ToArray(), false));
|
||||
}
|
||||
}
|
||||
return datasplitout;
|
||||
}
|
||||
}
|
||||
}*/
|
5
Luski.net/Converters.cs
Normal file
5
Luski.net/Converters.cs
Normal file
@ -0,0 +1,5 @@
|
||||
namespace Luski.net;
|
||||
|
||||
public static class Converters
|
||||
{
|
||||
}
|
8
Luski.net/Enums/CacheMode.cs
Normal file
8
Luski.net/Enums/CacheMode.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Luski.net.Enums;
|
||||
|
||||
public enum CacheMode : byte
|
||||
{
|
||||
None,
|
||||
Encrypted,
|
||||
Unencrypted
|
||||
}
|
10
Luski.net/Enums/ConnectionStatus.cs
Normal file
10
Luski.net/Enums/ConnectionStatus.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Luski.net.Enums;
|
||||
|
||||
public enum ConnectionStatus
|
||||
{
|
||||
FailedToConnect,
|
||||
CommunicationError,
|
||||
FailedToLogin,
|
||||
ConnectedNotLoggedIn,
|
||||
LoggedIn,
|
||||
}
|
18
Luski.net/Enums/DataType.cs
Normal file
18
Luski.net/Enums/DataType.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace Luski.net.Enums;
|
||||
|
||||
public enum DataType
|
||||
{
|
||||
Message_Create,
|
||||
Status_Update,
|
||||
Friend_Request_Result,
|
||||
Friend_Request,
|
||||
Change_Channel,
|
||||
Join_Call,
|
||||
Leave_Call,
|
||||
Call_Info,
|
||||
Call_Data,
|
||||
Login,
|
||||
Error,
|
||||
Key_Exchange,
|
||||
MAX
|
||||
}
|
7
Luski.net/Enums/Main/ChannelType.cs
Executable file
7
Luski.net/Enums/Main/ChannelType.cs
Executable file
@ -0,0 +1,7 @@
|
||||
namespace Luski.net.Enums.Main;
|
||||
|
||||
public enum ChannelType : short
|
||||
{
|
||||
DM,
|
||||
GROUP,
|
||||
}
|
9
Luski.net/Enums/Main/FriendStatus.cs
Executable file
9
Luski.net/Enums/Main/FriendStatus.cs
Executable file
@ -0,0 +1,9 @@
|
||||
namespace Luski.net.Enums.Main;
|
||||
|
||||
public enum FriendStatus
|
||||
{
|
||||
NotFriends,
|
||||
Friends,
|
||||
PendingOut,
|
||||
PendingIn
|
||||
}
|
11
Luski.net/Enums/Main/UserFlag.cs
Executable file
11
Luski.net/Enums/Main/UserFlag.cs
Executable file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Luski.net.Enums.Main;
|
||||
|
||||
[Flags]
|
||||
public enum UserFlag : short
|
||||
{
|
||||
Dev = 0b_001,
|
||||
Early = 0b_010,
|
||||
Tester = 0b_100
|
||||
}
|
9
Luski.net/Enums/ServerType.cs
Normal file
9
Luski.net/Enums/ServerType.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Luski.net.Enums;
|
||||
|
||||
public enum ServerType : byte
|
||||
{
|
||||
Public = 0,
|
||||
Main = 1,
|
||||
PublicSub = 2,
|
||||
MainSub = 3
|
||||
}
|
15
Luski.net/Enums/StorageDirectory.cs
Normal file
15
Luski.net/Enums/StorageDirectory.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Luski.net.Enums;
|
||||
|
||||
public enum StorageDirectory : byte
|
||||
{
|
||||
ServerInfo,
|
||||
ServerAssets,
|
||||
ChannelKeys,
|
||||
ServerKeys,
|
||||
Avatars,
|
||||
ChannelIcons,
|
||||
Messages,
|
||||
StorageInfo,
|
||||
Files,
|
||||
ProfileAvatars
|
||||
}
|
30
Luski.net/Exceptions.cs
Executable file
30
Luski.net/Exceptions.cs
Executable file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace Luski.net
|
||||
{
|
||||
public class Exceptions
|
||||
{
|
||||
|
||||
[Serializable]
|
||||
public class MissingEventException : Exception
|
||||
{
|
||||
public string EventName;
|
||||
public MissingEventException(string Event) : base(Event)
|
||||
{
|
||||
EventName = Event;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class NotConnectedException : Exception
|
||||
{
|
||||
public NotConnectedException(object sender, string message) : base(message)
|
||||
{
|
||||
Sender = sender;
|
||||
}
|
||||
|
||||
public object Sender { get; }
|
||||
}
|
||||
}
|
||||
}
|
10
Luski.net/Interfaces/IAppUser.cs
Normal file
10
Luski.net/Interfaces/IAppUser.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
|
||||
namespace Luski.net.Interfaces;
|
||||
|
||||
public interface IAppUser : IUser
|
||||
{
|
||||
public ErrorCode? Error { get; }
|
||||
public string? ErrorMessage { get; }
|
||||
public string Username { get; }
|
||||
}
|
38
Luski.net/Interfaces/IServer.cs
Normal file
38
Luski.net/Interfaces/IServer.cs
Normal file
@ -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;
|
||||
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
|
||||
|
||||
namespace Luski.net.Interfaces;
|
||||
|
||||
public interface IServer
|
||||
{
|
||||
public IAppUser IAppUser { get; }
|
||||
public string Cache { get; }
|
||||
public void SendServer<Tvalue>(Tvalue Payload, JsonTypeInfo<Tvalue> jsonTypeInfo) where Tvalue : IncomingWSS;
|
||||
|
||||
public HttpResponseMessage GetFromServer(string Path, CancellationToken CancellationToken,
|
||||
params KeyValuePair<string, string?>[] Headers);
|
||||
|
||||
public Task GetFromServer(string Path, string File, CancellationToken CancellationToken,
|
||||
params KeyValuePair<string, string?>[] Headers);
|
||||
|
||||
public Task<Tresult> GetFromServer<Tresult>(string Path, JsonTypeInfo<Tresult> Type,
|
||||
CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
||||
where Tresult : STC, new();
|
||||
|
||||
public Task<Tresult> SendServer<Tvalue, Tresult>(string Path, Tvalue Payload,
|
||||
JsonTypeInfo<Tvalue> jsonTypeInfo, JsonTypeInfo<Tresult> ReturnjsonTypeInfo,
|
||||
CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
||||
where Tvalue : IWebRequest where Tresult : STC, new();
|
||||
|
||||
public Task<Tresult> SendServer<Tresult>(string Path, string File, JsonTypeInfo<Tresult> ReturnjsonTypeInfo,
|
||||
CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
||||
where Tresult : STC, new();
|
||||
|
||||
}
|
6
Luski.net/Interfaces/IServerEvent.cs
Normal file
6
Luski.net/Interfaces/IServerEvent.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Luski.net.Interfaces;
|
||||
|
||||
public interface IServerEvent
|
||||
{
|
||||
|
||||
}
|
29
Luski.net/Interfaces/IUser.cs
Executable file
29
Luski.net/Interfaces/IUser.cs
Executable file
@ -0,0 +1,29 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Luski.net.Structures;
|
||||
using Luski.net.Structures.Public;
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
|
||||
namespace Luski.net.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the curent user
|
||||
/// </summary>
|
||||
public interface IUser
|
||||
{
|
||||
/// <summary>
|
||||
/// The current Id of the user
|
||||
/// </summary>
|
||||
long Id { get; }
|
||||
/// <summary>
|
||||
/// The current status of the user
|
||||
/// </summary>
|
||||
UserStatus Status { get; }
|
||||
/// <summary>
|
||||
/// Gets the current user keys
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<PublicKeyInfo[]> GetUserKeys(CancellationToken CancellationToken);
|
||||
|
||||
}
|
6
Luski.net/Interfaces/IWebRequest.cs
Normal file
6
Luski.net/Interfaces/IWebRequest.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Luski.net.Interfaces;
|
||||
|
||||
public interface IWebRequest
|
||||
{
|
||||
|
||||
}
|
28
Luski.net/JsonRequest.cs
Executable file
28
Luski.net/JsonRequest.cs
Executable file
@ -0,0 +1,28 @@
|
||||
using Luski.net.Enums;
|
||||
using System;
|
||||
|
||||
namespace Luski.net
|
||||
{
|
||||
internal static class JsonRequest
|
||||
{
|
||||
internal static string SendCallData(byte[] Data, long channel)
|
||||
{
|
||||
return $"{{\"data\": \"{Convert.ToBase64String(Data)}\", \"id\": {channel}}}";
|
||||
}
|
||||
|
||||
internal static string JoinCall(long Channel)
|
||||
{
|
||||
return $"{{\"id\": {Channel}}}";
|
||||
}
|
||||
|
||||
internal static string Send(DataType Request, string Data)
|
||||
{
|
||||
return $"{{\"type\": {(int)Request}, \"data\": {Data}}}";
|
||||
}
|
||||
|
||||
internal static string FriendRequestResult(long User, bool Result)
|
||||
{
|
||||
return $"{{\"id\": {User},\"result\": {Result.ToString().ToLower()}}}";
|
||||
}
|
||||
}
|
||||
}
|
12
Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs
Executable file
12
Luski.net/JsonTypes/BaseTypes/HTTPRequest.cs
Executable file
@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.net.Enums;
|
||||
using Luski.net.Interfaces;
|
||||
|
||||
namespace Luski.net.JsonTypes.BaseTypes;
|
||||
|
||||
internal class HTTPRequest : IWebRequest
|
||||
{
|
||||
[JsonPropertyName("data_type")]
|
||||
[JsonInclude]
|
||||
public DataType Type { get; set; } = default!;
|
||||
}
|
24
Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs
Executable file
24
Luski.net/JsonTypes/BaseTypes/IncomingWSS.cs
Executable file
@ -0,0 +1,24 @@
|
||||
using Luski.net.Enums;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Luski.net.JsonTypes.BaseTypes;
|
||||
|
||||
public class IncomingWSS
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
[JsonInclude]
|
||||
public DataType? Type { get; set; } = DataType.Login!;
|
||||
[JsonPropertyName("error")]
|
||||
[JsonInclude]
|
||||
public string Error { get; set; } = default!;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(IncomingWSS))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||
WriteIndented = false)]
|
||||
public partial class IncomingWSSContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
28
Luski.net/JsonTypes/FriendRequestResult.cs
Executable file
28
Luski.net/JsonTypes/FriendRequestResult.cs
Executable file
@ -0,0 +1,28 @@
|
||||
using Luski.net.JsonTypes.BaseTypes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
|
||||
|
||||
namespace Luski.net.JsonTypes;
|
||||
|
||||
internal class FriendRequestResult : STC
|
||||
{
|
||||
[JsonPropertyName("channel")]
|
||||
[JsonInclude]
|
||||
public long? Channel { get; set; }
|
||||
[JsonPropertyName("id")]
|
||||
[JsonInclude]
|
||||
public long? Id { get; set; }
|
||||
[JsonPropertyName("result")]
|
||||
[JsonInclude]
|
||||
public bool? Result { get; set; }
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(FriendRequestResult))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class FriendRequestResultContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
25
Luski.net/JsonTypes/HTTP/FriendRequest.cs
Executable file
25
Luski.net/JsonTypes/HTTP/FriendRequest.cs
Executable file
@ -0,0 +1,25 @@
|
||||
using Luski.net.JsonTypes.BaseTypes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.ClientToServer.HTTP;
|
||||
|
||||
namespace Luski.net.JsonTypes.HTTP;
|
||||
|
||||
internal class FriendRequest : CTS
|
||||
{
|
||||
[JsonPropertyName("code")]
|
||||
[JsonInclude]
|
||||
public string code { get; set; } = default!;
|
||||
[JsonPropertyName("id")]
|
||||
[JsonInclude]
|
||||
public long Id { get; set; } = default!;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(FriendRequest))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class FriendRequestContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
25
Luski.net/JsonTypes/HTTP/FriendRequestResultOut.cs
Executable file
25
Luski.net/JsonTypes/HTTP/FriendRequestResultOut.cs
Executable file
@ -0,0 +1,25 @@
|
||||
using Luski.net.JsonTypes.BaseTypes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.ClientToServer.HTTP;
|
||||
|
||||
namespace Luski.net.JsonTypes.HTTP;
|
||||
|
||||
internal class FriendRequestResultOut : CTS
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
[JsonInclude]
|
||||
public long? Id { get; set; }
|
||||
[JsonPropertyName("result")]
|
||||
[JsonInclude]
|
||||
public bool? Result { get; set; }
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(FriendRequestResultOut))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class FriendRequestResultOutContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
11
Luski.net/JsonTypes/KeyExchange.cs
Executable file
11
Luski.net/JsonTypes/KeyExchange.cs
Executable file
@ -0,0 +1,11 @@
|
||||
namespace Luski.net.JsonTypes
|
||||
{
|
||||
internal class KeyExchange
|
||||
{
|
||||
public long channel { get; set; } = default!;
|
||||
public long id { get; set; } = default!;
|
||||
public string key { get; set; } = default!;
|
||||
|
||||
public long? to { get; set; } = default!;
|
||||
}
|
||||
}
|
29
Luski.net/JsonTypes/LocalServerInfo.cs
Normal file
29
Luski.net/JsonTypes/LocalServerInfo.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
using Luski.Shared.PublicServers.V1.Shared;
|
||||
|
||||
namespace Luski.net.JsonTypes;
|
||||
|
||||
public class LocalServerInfo
|
||||
{
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("alternate_servers")]
|
||||
public ServerData[] AlternateServers { get; set; } = Array.Empty<ServerData>();
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("picture_type")]
|
||||
public PictureType PictureType { get; set; }
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = default!;
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = default!;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(LocalServerInfo))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class LocalServerInfoContext : JsonSerializerContext;
|
20
Luski.net/JsonTypes/OfflineKeyData.cs
Executable file
20
Luski.net/JsonTypes/OfflineKeyData.cs
Executable file
@ -0,0 +1,20 @@
|
||||
using Luski.net.JsonTypes.BaseTypes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
|
||||
|
||||
namespace Luski.net.JsonTypes;
|
||||
|
||||
internal class OfflineKeyData : STC
|
||||
{
|
||||
public KeyExchange[]? keys { get; internal set; } = default!;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(OfflineKeyData))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class OfflineKeyDataContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
27
Luski.net/JsonTypes/ServerStorageInfo.cs
Normal file
27
Luski.net/JsonTypes/ServerStorageInfo.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.net.Enums;
|
||||
|
||||
namespace Luski.net.JsonTypes;
|
||||
|
||||
public class ServerStorageInfo
|
||||
{
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("cache_mode")]
|
||||
public CacheMode CacheMode { get; set; } = CacheMode.Encrypted;
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("storage_id")]
|
||||
public long StorageID { get; set; } = default!;
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("prevent_deletion")]
|
||||
public bool DontDelete { get; set; } = false;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(ServerStorageInfo))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = true)]
|
||||
internal partial class ServerStorageInfoContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
17
Luski.net/JsonTypes/StatusUpdate.cs
Executable file
17
Luski.net/JsonTypes/StatusUpdate.cs
Executable file
@ -0,0 +1,17 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
|
||||
namespace Luski.net.JsonTypes;
|
||||
|
||||
internal class StatusUpdate
|
||||
{
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("id")]
|
||||
public long id { get; set; } = default!;
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("before")]
|
||||
public UserStatus before { get; set; } = default!;
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("after")]
|
||||
public UserStatus after { get; set; } = default!;
|
||||
}
|
27
Luski.net/JsonTypes/WSS/IncomingWSS.cs
Executable file
27
Luski.net/JsonTypes/WSS/IncomingWSS.cs
Executable file
@ -0,0 +1,27 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
|
||||
namespace Luski.net.JsonTypes.BaseTypes;
|
||||
|
||||
public class BetterIncomingWSS
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
[JsonInclude]
|
||||
public DataType? Type { get; set; } = DataType.Token!;
|
||||
[JsonPropertyName("error")]
|
||||
[JsonInclude]
|
||||
public string Error { get; set; } = default!;
|
||||
[JsonPropertyName("data")]
|
||||
[JsonInclude]
|
||||
public object? Data { get; set; }
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(BetterIncomingWSS))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||
WriteIndented = false)]
|
||||
public partial class BetterIncomingWSSContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
15
Luski.net/JsonTypes/WSS/ServerEvent.cs
Normal file
15
Luski.net/JsonTypes/WSS/ServerEvent.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.Shared.PublicServers.V1.Enums;
|
||||
|
||||
namespace Luski.net.JsonTypes.WSS;
|
||||
|
||||
public class ServerEvent
|
||||
{
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("type")]
|
||||
public DataType Type { get; set; }
|
||||
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("data")]
|
||||
public object Data { get; set; }
|
||||
}
|
31
Luski.net/JsonTypes/WSS/WSSKeyExchange.cs
Executable file
31
Luski.net/JsonTypes/WSS/WSSKeyExchange.cs
Executable file
@ -0,0 +1,31 @@
|
||||
using Luski.net.Enums;
|
||||
using Luski.net.JsonTypes.BaseTypes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Luski.net.JsonTypes.WSS;
|
||||
|
||||
internal class WSSKeyExchange : IncomingWSS
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
[JsonInclude]
|
||||
new public DataType? Type { get; set; } = DataType.Key_Exchange;
|
||||
[JsonPropertyName("channel")]
|
||||
[JsonInclude]
|
||||
public long channel { get; set; } = default!;
|
||||
[JsonPropertyName("key")]
|
||||
[JsonInclude]
|
||||
public string key { get; set; } = default!;
|
||||
[JsonPropertyName("to")]
|
||||
[JsonInclude]
|
||||
public long? to { get; set; } = default!;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(WSSKeyExchange))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class WSSKeyExchangeContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
29
Luski.net/JsonTypes/WSS/WSSLogin.cs
Executable file
29
Luski.net/JsonTypes/WSS/WSSLogin.cs
Executable file
@ -0,0 +1,29 @@
|
||||
using Luski.net.Enums;
|
||||
using Luski.net.JsonTypes.BaseTypes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Luski.net.Interfaces;
|
||||
|
||||
namespace Luski.net.JsonTypes.WSS;
|
||||
|
||||
internal class WSSLogin : IncomingWSS, IServerEvent
|
||||
{
|
||||
[JsonPropertyName("token")]
|
||||
[JsonInclude]
|
||||
public string Token { get; set; } = default!;
|
||||
[JsonPropertyName("session_token")]
|
||||
[JsonInclude]
|
||||
public string? SessionToken { get; set; } = default!;
|
||||
[JsonPropertyName("type")]
|
||||
[JsonInclude]
|
||||
new public DataType? Type { get; set; } = DataType.Login;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(WSSLogin))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class WSSLoginContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
23
Luski.net/JsonTypes/WSS/WSSOut.cs
Normal file
23
Luski.net/JsonTypes/WSS/WSSOut.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Luski.net.JsonTypes.WSS;
|
||||
|
||||
public class WSSOut
|
||||
{
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("data")]
|
||||
public ServerEvent Data { get; set; }
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("send_type")]
|
||||
public int SendType { get; set; } = 1;
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(WSSOut))]
|
||||
[JsonSourceGenerationOptions(
|
||||
GenerationMode = JsonSourceGenerationMode.Default,
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
WriteIndented = false)]
|
||||
internal partial class WSSOutContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
30
Luski.net/Luski.net.csproj
Executable file
30
Luski.net/Luski.net.csproj
Executable file
@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Title>Luski.net</Title>
|
||||
<Authors>JacobTech</Authors>
|
||||
<Company>JacobTech, LLC</Company>
|
||||
<Description>A wrapper for the luski API</Description>
|
||||
<PackageProjectUrl>https://www.jacobtech.com/Luski/Documentation</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/JacobTech-com/Luski.net</RepositoryUrl>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<FileVersion>1.0.0</FileVersion>
|
||||
<Version>2.0.1-alpha18</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Luski.Shared" Version="1.1.0-alpha48" />
|
||||
<PackageReference Include="websocketsharp.core" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Target Name="CustomActionsAfterPublish" AfterTargets="Pack">
|
||||
<Message Text="Actions AfterPublish: $(PackageId).$(PackageVersion).nupkg" Importance="high" />
|
||||
<Exec Command="nuget push -Source https://nuget.jacobtech.com/v3/index.json bin/Release/$(PackageId).$(PackageVersion).nupkg" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
6
Luski.net/Luski.net.csproj.user
Executable file
6
Luski.net/Luski.net.csproj.user
Executable file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_LastSelectedProfileId>C:\Users\techn\source\repos\JacobTech-com\Luski.net\Luski.net\Luski.net\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
157
Luski.net/MainServer.Account.cs
Normal file
157
Luski.net/MainServer.Account.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
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.Shared.PublicServers.V1.Enums;
|
||||