Public Servers.
Added a bunch of API calls to use in public servers.
This commit is contained in:
parent
ea39d93cf5
commit
9f641e7429
@ -1,8 +1,9 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Luski.net.Enums;
|
using Luski.net.Enums;
|
||||||
using Luski.net.Structures.Main;
|
|
||||||
using Luski.net.Structures.Public;
|
|
||||||
|
|
||||||
namespace Luski.net;
|
namespace Luski.net;
|
||||||
|
|
||||||
@ -12,24 +13,63 @@ public class API
|
|||||||
internal List<PublicServer> InternalServers { get; } = new();
|
internal List<PublicServer> InternalServers { get; } = new();
|
||||||
public IReadOnlyList<PublicServer> LoadedServers => InternalServers.AsReadOnly();
|
public IReadOnlyList<PublicServer> LoadedServers => InternalServers.AsReadOnly();
|
||||||
|
|
||||||
public PublicServer GetPublicServer(string Domain, string Version = "v1")
|
public async Task<PublicServer> GetPublicServer(string Domain, string Version = "v1", bool Secure = true)
|
||||||
{
|
{
|
||||||
IEnumerable<PublicServer> isl = InternalServers.Where(a => (a.Domain == Domain && a.ApiVersion == Version));
|
DateTime dt = DateTime.UtcNow;
|
||||||
if (isl.Any()) return isl.First();
|
Console.WriteLine("Connecting to public server '{0}' using API {1}.", Domain, Version);
|
||||||
PublicServer s = new(Domain, Version)
|
PublicServer s;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
ServerType = ServerType.Public
|
IEnumerable<PublicServer> isl = InternalServers.Where(a => (a.Domain == Domain && a.ApiVersion == Version));
|
||||||
};
|
if (isl.Any()) return isl.First();
|
||||||
|
s = new(Domain, Version, Secure)
|
||||||
|
{
|
||||||
|
ServerType = ServerType.Public
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Failed to connect to public server '{0}' using API {1}.", Domain, Version);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
Console.WriteLine("Connected to public server '{0}' using API {1} in {4}.\nServer Name: {2}\nServer Description: {3}", Domain, Version, s.Name, s.Description, DateTime.UtcNow.Subtract(dt).ToString("g"));
|
||||||
|
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) Console.WriteLine("Auto Login Successful");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.Token = null;
|
||||||
|
s.Error = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
InternalServers.Add(s);
|
InternalServers.Add(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainServer GetMainServer(string Domain, string Version = "v1")
|
public MainServer GetMainServer(string Domain, string Version = "v1")
|
||||||
{
|
{
|
||||||
|
DateTime dt = DateTime.UtcNow;
|
||||||
|
Console.WriteLine("Conecting to main server '{0}' using API {1}.", Domain, Version);
|
||||||
MainServer = new(Domain, Version)
|
MainServer = new(Domain, Version)
|
||||||
{
|
{
|
||||||
ServerType = ServerType.Main
|
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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
8
Luski.net/Converters.cs
Normal file
8
Luski.net/Converters.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using Luski.net.JsonTypes.Public;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
namespace Luski.net;
|
||||||
|
|
||||||
|
public static class Converters
|
||||||
|
{
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
public enum PictureType : short
|
public enum PictureType : short
|
||||||
{
|
{
|
||||||
|
none,
|
||||||
png,
|
png,
|
||||||
jpeg,
|
jpeg,
|
||||||
bmp,
|
bmp,
|
||||||
|
7
Luski.net/Enums/Public/DataType.cs
Normal file
7
Luski.net/Enums/Public/DataType.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Luski.net.Enums.Public;
|
||||||
|
|
||||||
|
public enum DataType
|
||||||
|
{
|
||||||
|
Token,
|
||||||
|
MessageCreate
|
||||||
|
}
|
38
Luski.net/Enums/Public/ServerPermission.cs
Normal file
38
Luski.net/Enums/Public/ServerPermission.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
namespace Luski.net.Enums.Public;
|
||||||
|
|
||||||
|
public enum ServerPermission : long
|
||||||
|
{
|
||||||
|
ViewChannels,
|
||||||
|
MoveChannels,
|
||||||
|
EditChannels,
|
||||||
|
EditChannelPermissions,
|
||||||
|
CreateChannels,
|
||||||
|
DeleteChannels,
|
||||||
|
ViewCategories,
|
||||||
|
MoveCategories,
|
||||||
|
EditCategories,
|
||||||
|
EditCategoryPermissions,
|
||||||
|
CreateCategories,
|
||||||
|
DeleteCategories,
|
||||||
|
DeleteKeys,
|
||||||
|
ManageRoles,
|
||||||
|
ViewLogs,
|
||||||
|
ManageServer,
|
||||||
|
Invite,
|
||||||
|
Nickname,
|
||||||
|
ManageNacknames,
|
||||||
|
Kick,
|
||||||
|
Ban,
|
||||||
|
SendMessages,
|
||||||
|
SendFiles,
|
||||||
|
ChannelAndServerPings,
|
||||||
|
PingSomeone,
|
||||||
|
ManageMessages,
|
||||||
|
ReadMessageHistory,
|
||||||
|
UseServerCommands,
|
||||||
|
JoinVoice,
|
||||||
|
SpeakInVoice,
|
||||||
|
MuteMembers,
|
||||||
|
DeafenMembers,
|
||||||
|
MoveMembers
|
||||||
|
}
|
@ -8,5 +8,7 @@ public enum StorageDirectory : byte
|
|||||||
ServerKeys,
|
ServerKeys,
|
||||||
Avatars,
|
Avatars,
|
||||||
ChannelIcons,
|
ChannelIcons,
|
||||||
Messages
|
Messages,
|
||||||
|
StorageInfo,
|
||||||
|
Files
|
||||||
}
|
}
|
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
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
using System.Threading;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
using Luski.net.Enums;
|
using Luski.net.Enums;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Luski.net.JsonTypes;
|
using Luski.net.JsonTypes;
|
||||||
|
using Luski.net.Structures;
|
||||||
|
|
||||||
namespace Luski.net.Interfaces;
|
namespace Luski.net.Interfaces;
|
||||||
|
|
||||||
@ -29,11 +31,11 @@ public interface IUser
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current avatar of the user
|
/// Gets the current avatar of the user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<byte[]> GetAvatar(CancellationToken CancellationToken);
|
Task<Stream> GetAvatar(CancellationToken CancellationToken);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current user key
|
/// Gets the current user keys
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<long> GetUserKey(CancellationToken CancellationToken);
|
Task<PublicKeyInfo[]> GetUserKeys(CancellationToken CancellationToken);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ public class IncomingWSS
|
|||||||
{
|
{
|
||||||
[JsonPropertyName("type")]
|
[JsonPropertyName("type")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public DataType? Type { get; set; } = default!;
|
public DataType? Type { get; set; } = DataType.Login!;
|
||||||
[JsonPropertyName("error")]
|
[JsonPropertyName("error")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public string Error { get; set; } = default!;
|
public string Error { get; set; } = default!;
|
||||||
|
@ -7,6 +7,7 @@ internal class Login : IncomingHTTP
|
|||||||
{
|
{
|
||||||
[JsonPropertyName("login_token")]
|
[JsonPropertyName("login_token")]
|
||||||
public string? Token { get; set; } = default!;
|
public string? Token { get; set; } = default!;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonSerializable(typeof(Login))]
|
[JsonSerializable(typeof(Login))]
|
||||||
|
63
Luski.net/JsonTypes/Public/Category.cs
Normal file
63
Luski.net/JsonTypes/Public/Category.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class Category : IncomingHTTP
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long ID { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("picture_type")]
|
||||||
|
public PictureType PictureType { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("color")]
|
||||||
|
public string Color { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("parent")]
|
||||||
|
public long Parent { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("inner_categories")]
|
||||||
|
public long[] InnerCategories { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("channels")]
|
||||||
|
public long[] Channels { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("role_overides")]
|
||||||
|
public long[] RoleOverides { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("member_overides")]
|
||||||
|
public long[] UserOverides { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("title_encryption_key")]
|
||||||
|
public long TitleEncryptionKey { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description_encryption_key")]
|
||||||
|
public long DescriptionEncryptionKey { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("title_encoder_type")]
|
||||||
|
public EncoderType TitleEncoderType { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description_encoder_type")]
|
||||||
|
public EncoderType DescriptionEncoderType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(Category))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class PublicCategoryContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
71
Luski.net/JsonTypes/Public/Channel.cs
Normal file
71
Luski.net/JsonTypes/Public/Channel.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.Enums.Public;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class Channel : IncomingHTTP
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long ID { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("parent")]
|
||||||
|
public long Parent { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("color")]
|
||||||
|
public string Color { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("type")]
|
||||||
|
public ChannelType Type { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("epoch")]
|
||||||
|
public DateTime Epoch { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("role_overides")]
|
||||||
|
public long[] RoleOverides { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("member_overides")]
|
||||||
|
public long[] UserOverides { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("title_encryption_key")]
|
||||||
|
public long TitleEncryptionKey { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description_encryption_key")]
|
||||||
|
public long DescriptionEncryptionKey { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("encryption_keys")]
|
||||||
|
public long[] EncryptionKeys { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("title_encoder_type")]
|
||||||
|
public EncoderType TitleEncoderType { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("description_encoder_type")]
|
||||||
|
public EncoderType DescriptionEncoderType { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("encoder_types")]
|
||||||
|
public EncoderType[] EncoderTypes { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("picture_type")]
|
||||||
|
public PictureType PictureType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(Channel))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class PublicChannelContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
32
Luski.net/JsonTypes/Public/PublicMessage.cs
Normal file
32
Luski.net/JsonTypes/Public/PublicMessage.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class PublicMessage
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long ID { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("channel_id")]
|
||||||
|
public long ChannelID { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("author_id")]
|
||||||
|
public long AuthorID { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("ts")]
|
||||||
|
public long TimeStamp { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("context")]
|
||||||
|
public string Context { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("encryption_key")]
|
||||||
|
public long EncryptionKey { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("files")]
|
||||||
|
public pFile[] Files { get; internal set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("encoder_type")]
|
||||||
|
public EncoderType EncoderType { get; internal set; }
|
||||||
|
}
|
22
Luski.net/JsonTypes/Public/PublicSocketBulkMessage.cs
Normal file
22
Luski.net/JsonTypes/Public/PublicSocketBulkMessage.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class PublicSocketBulkMessage : IncomingHTTP
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("messages")]
|
||||||
|
public PublicMessage[]? Messages { get; set; } = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(PublicSocketBulkMessage))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class PublicSocketBulkMessageContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
28
Luski.net/JsonTypes/Public/Role.cs
Normal file
28
Luski.net/JsonTypes/Public/Role.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Enums.Public;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class Role : IncomingHTTP
|
||||||
|
{
|
||||||
|
public long id { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string display_name { get; set; }
|
||||||
|
public int index { get; set; }
|
||||||
|
public string color { get; set; }
|
||||||
|
public string description { get; set; }
|
||||||
|
public ServerPermission[] server_permissions { get; set; }
|
||||||
|
public long[] members_list { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(Role))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class RoleContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
41
Luski.net/JsonTypes/Public/SocketUser.cs
Normal file
41
Luski.net/JsonTypes/Public/SocketUser.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class SocketUser : IncomingHTTP
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long ID { get; internal set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("displayname")]
|
||||||
|
public string DisplayName { get; internal set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("selected_channel")]
|
||||||
|
public long SelectedChannel { get; internal set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("status")]
|
||||||
|
public UserStatus Status { get; internal set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("picture_type")]
|
||||||
|
public PictureType PictureType { get; internal set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("roles")]
|
||||||
|
public long[] RoleIds { get; internal set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("username")]
|
||||||
|
public string Username { get; internal set; } = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(SocketUser))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
||||||
|
internal partial class PublicSocketUserContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
32
Luski.net/JsonTypes/Public/pFile.cs
Normal file
32
Luski.net/JsonTypes/Public/pFile.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
public class pFile
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long ID { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("channel")]
|
||||||
|
public long Channel { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("encoder_type")]
|
||||||
|
public EncoderType Encoder { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name_encoder_type")]
|
||||||
|
public EncoderType NameEncoder { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("encryption_key")]
|
||||||
|
public long Key { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("name_encryption_key")]
|
||||||
|
public long NameKey { get; set; }
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("size")]
|
||||||
|
public long Size { get; set; }
|
||||||
|
}
|
22
Luski.net/JsonTypes/ServerInfo.cs
Normal file
22
Luski.net/JsonTypes/ServerInfo.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes;
|
||||||
|
|
||||||
|
public class ServerInfo : IncomingHTTP
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
public string wssv4 { get; set; }
|
||||||
|
public string description { get; set; }
|
||||||
|
public long owner { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ServerInfo))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = false)]
|
||||||
|
internal partial class ServerInfoContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,9 @@ public class ServerStorageInfo
|
|||||||
[JsonPropertyName("cache_mode")]
|
[JsonPropertyName("cache_mode")]
|
||||||
public CacheMode CacheMode { get; set; } = CacheMode.Encrypted;
|
public CacheMode CacheMode { get; set; } = CacheMode.Encrypted;
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("storage_id")]
|
||||||
|
public long StorageID { get; set; } = default!;
|
||||||
|
[JsonInclude]
|
||||||
[JsonPropertyName("prevent_deletion")]
|
[JsonPropertyName("prevent_deletion")]
|
||||||
public bool DontDelete { get; set; } = false;
|
public bool DontDelete { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
22
Luski.net/JsonTypes/StorageInfoJSON.cs
Normal file
22
Luski.net/JsonTypes/StorageInfoJSON.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes;
|
||||||
|
|
||||||
|
public class StorageInfoJSON : IncomingHTTP, IWebRequest
|
||||||
|
{
|
||||||
|
public long id { get; set; }
|
||||||
|
public string password { get; set; }
|
||||||
|
public bool update { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(StorageInfoJSON))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = true)]
|
||||||
|
internal partial class StorageInfoJSONContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
23
Luski.net/JsonTypes/UserKeyGetRequest.cs
Normal file
23
Luski.net/JsonTypes/UserKeyGetRequest.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes;
|
||||||
|
|
||||||
|
public class UserKeyGetRequest : IWebRequest
|
||||||
|
{
|
||||||
|
public long id { get; set; }
|
||||||
|
public long owner { get; set; }
|
||||||
|
public EncryptionType encryption_type { get; set; }
|
||||||
|
public string key_data { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(UserKeyGetRequest))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = false)]
|
||||||
|
internal partial class UserKeyGetRequestContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
19
Luski.net/JsonTypes/UserKeysGetRequest.cs
Normal file
19
Luski.net/JsonTypes/UserKeysGetRequest.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes;
|
||||||
|
|
||||||
|
public class UserKeysGetRequest : IncomingHTTP
|
||||||
|
{
|
||||||
|
public UserKeyGetRequest[] keys { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(UserKeysGetRequest))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = true)]
|
||||||
|
internal partial class UserKeysGetRequestContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
24
Luski.net/JsonTypes/WSS/IncomingWSS.cs
Executable file
24
Luski.net/JsonTypes/WSS/IncomingWSS.cs
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
using Luski.net.Enums.Public;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
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!;
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(BetterIncomingWSS))]
|
||||||
|
[JsonSourceGenerationOptions(
|
||||||
|
GenerationMode = JsonSourceGenerationMode.Default,
|
||||||
|
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
||||||
|
WriteIndented = false)]
|
||||||
|
public partial class BetterIncomingWSSContext : JsonSerializerContext
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
16
Luski.net/JsonTypes/WSS/ServerEvent.cs
Normal file
16
Luski.net/JsonTypes/WSS/ServerEvent.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Enums.Public;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
|
||||||
|
namespace Luski.net.JsonTypes.WSS;
|
||||||
|
|
||||||
|
public class ServerEvent
|
||||||
|
{
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("type")]
|
||||||
|
public DataType Type { get; set; }
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("data")]
|
||||||
|
public object Data { get; set; }
|
||||||
|
}
|
@ -1,14 +1,18 @@
|
|||||||
using Luski.net.Enums;
|
using Luski.net.Enums;
|
||||||
using Luski.net.JsonTypes.BaseTypes;
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
|
||||||
namespace Luski.net.JsonTypes.WSS;
|
namespace Luski.net.JsonTypes.WSS;
|
||||||
|
|
||||||
internal class WSSLogin : IncomingWSS
|
internal class WSSLogin : IncomingWSS, IServerEvent
|
||||||
{
|
{
|
||||||
[JsonPropertyName("token")]
|
[JsonPropertyName("token")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public string Token { get; set; } = default!;
|
public string Token { get; set; } = default!;
|
||||||
|
[JsonPropertyName("session_token")]
|
||||||
|
[JsonInclude]
|
||||||
|
public string? SessionToken { get; set; } = default!;
|
||||||
[JsonPropertyName("type")]
|
[JsonPropertyName("type")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
new public DataType? Type { get; set; } = DataType.Login;
|
new public DataType? Type { get; set; } = DataType.Login;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
@ -13,14 +13,15 @@
|
|||||||
<RepositoryUrl>https://github.com/JacobTech-com/Luski.net</RepositoryUrl>
|
<RepositoryUrl>https://github.com/JacobTech-com/Luski.net</RepositoryUrl>
|
||||||
<IncludeSymbols>True</IncludeSymbols>
|
<IncludeSymbols>True</IncludeSymbols>
|
||||||
<FileVersion>1.0.0</FileVersion>
|
<FileVersion>1.0.0</FileVersion>
|
||||||
<Version>1.1.3-alpha25</Version>
|
<Version>2.0.0-alpha12</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JacobTechEncryption" Version="1.0.1" />
|
<PackageReference Include="JacobTechEncryption" Version="1.0.2" />
|
||||||
<PackageReference Include="websocketsharp.core" Version="1.0.0" />
|
<PackageReference Include="websocketsharp.core" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<Target Name="CustomActionsAfterPublish" AfterTargets="Pack">
|
<Target Name="CustomActionsAfterPublish" AfterTargets="Pack">
|
||||||
<Message Text="Actions AfterPublish: $(PackageId).$(PackageVersion).nupkg" Importance="high" />
|
<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" />
|
<Exec Command="nuget push -Source https://nuget.jacobtech.com/v3/index.json bin/Release/$(PackageId).$(PackageVersion).nupkg" />
|
||||||
|
@ -42,12 +42,12 @@ public partial class MainServer
|
|||||||
List<KeyValuePair<string, string?>> heads = new()
|
List<KeyValuePair<string, string?>> heads = new()
|
||||||
{
|
{
|
||||||
new("key", EncryptionHandler.MyPublicKey),
|
new("key", EncryptionHandler.MyPublicKey),
|
||||||
new("username", Convert.ToBase64String(Encryption.RSA.Encrypt(Username, EncryptionHandler.MyPublicKey, EncoderType.UTF8))),
|
new("email", Convert.ToBase64String(Encryption.RSA.Encrypt(Username, EncryptionHandler.ServerPublicKey, EncoderType.UTF16))),
|
||||||
new("password", EncryptionHandler.RemotePasswordEncrypt(Encoding.UTF8.GetBytes(Password)))
|
new("password", EncryptionHandler.RemotePasswordEncrypt(Encoding.Unicode.GetBytes(Password)))
|
||||||
};
|
};
|
||||||
if (File.Exists("LastPassVer.txt") && int.TryParse(File.ReadAllText("LastPassVer.txt"), out int lpv) && lpv < EncryptionHandler.PasswordVersion && lpv >= 0)
|
if (File.Exists("LastPassVer.txt") && int.TryParse(File.ReadAllText("LastPassVer.txt"), out int lpv) && lpv < EncryptionHandler.PasswordVersion && lpv >= 0)
|
||||||
{
|
{
|
||||||
heads.Add(new("old_password", EncryptionHandler.RemotePasswordEncrypt(Encoding.UTF8.GetBytes(Password), lpv)));
|
heads.Add(new("old_password", EncryptionHandler.RemotePasswordEncrypt(Encoding.Unicode.GetBytes(Password), lpv)));
|
||||||
heads.Add(new("old_version", lpv.ToString()));
|
heads.Add(new("old_version", lpv.ToString()));
|
||||||
}
|
}
|
||||||
if (pfp is not null)
|
if (pfp is not null)
|
||||||
@ -73,16 +73,16 @@ public partial class MainServer
|
|||||||
login = false;
|
login = false;
|
||||||
if (json is not null && json.Error is null)
|
if (json is not null && json.Error is null)
|
||||||
{
|
{
|
||||||
ServerOut = new WebSocket($"wss://{Domain}/WSS/{ApiVersion}");
|
ServerOut = new WebSocket($"{(Secure ? "wss" : "ws" )}://{Domain}/WSS/{ApiVersion}");
|
||||||
ServerOut.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12;
|
if (Secure) ServerOut.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12;
|
||||||
ServerOut.OnMessage += DataFromServer;
|
ServerOut.OnMessage += DataFromServer;
|
||||||
ServerOut.WaitTime = new TimeSpan(0, 0, 5);
|
ServerOut.WaitTime = new TimeSpan(0, 0, 5);
|
||||||
ServerOut.OnError += ServerOut_OnError;
|
ServerOut.OnError += ServerOut_OnError;
|
||||||
ServerOut.Connect();
|
ServerOut.Connect();
|
||||||
SendServer(new WSSLogin() { Token = json.Token! }, WSSLoginContext.Default.WSSLogin);
|
SendServerOld(new WSSLogin() { Token = json.Token! }, WSSLoginContext.Default.WSSLogin);
|
||||||
while (Token is null && Error is null)
|
while (Token is null && Error is null)
|
||||||
{
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
}
|
}
|
||||||
if (Error is not null)
|
if (Error is not null)
|
||||||
{
|
{
|
||||||
@ -103,33 +103,32 @@ public partial class MainServer
|
|||||||
if (User is not null && User.Error is not null) error = $"{User.Error}: {User.ErrorMessage}";
|
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}");
|
throw new Exception($"Something went wrong getting your user infermation\n{error}");
|
||||||
}
|
}
|
||||||
Console.WriteLine("User got");
|
|
||||||
Console.WriteLine("Insert");
|
|
||||||
_ = UpdateStatus(UserStatus.Online, CancellationToken);
|
_ = UpdateStatus(UserStatus.Online, CancellationToken);
|
||||||
Console.WriteLine("stat");
|
if (pfp is not null)
|
||||||
EncryptionHandler.Hash = EncryptionHandler.LocalPasswordEncrypt(Encoding.UTF8.GetBytes(Username.ToLower() + Password));
|
{
|
||||||
Console.WriteLine("req offline");
|
//post
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
EncryptionHandler.Hash = EncryptionHandler.LocalPasswordEncrypt(Encoding.Unicode.GetBytes(Username.ToLower() + Password));
|
||||||
OfflineData offlinedata = GetFromServer("Keys/GetOfflineData", OfflineDataContext.Default.OfflineData, CancellationToken).Result;
|
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)
|
if (offlinedata is not null && offlinedata.Error is null && offlinedata.Data is not null && offlinedata.Data.Length > 0)
|
||||||
{
|
{
|
||||||
foreach (string keyex in offlinedata.Data)
|
foreach (string keyex in offlinedata.Data)
|
||||||
{
|
{
|
||||||
Console.WriteLine(keyex);
|
|
||||||
KeyExchange? okd = JsonSerializer.Deserialize<KeyExchange>(keyex);
|
KeyExchange? okd = JsonSerializer.Deserialize<KeyExchange>(keyex);
|
||||||
Console.WriteLine(okd);
|
|
||||||
if (okd is not null && !string.IsNullOrEmpty(okd.key))
|
if (okd is not null && !string.IsNullOrEmpty(okd.key))
|
||||||
{
|
{
|
||||||
Console.WriteLine(okd.channel);
|
|
||||||
Console.WriteLine(okd.key);
|
|
||||||
Storage.SetResourceKey(
|
Storage.SetResourceKey(
|
||||||
StorageDirectory.ChannelKeys,
|
StorageDirectory.ChannelKeys,
|
||||||
okd.channel.ToString(),
|
okd.channel.ToString(),
|
||||||
EncryptionHandler.Hash,
|
EncryptionHandler.Hash,
|
||||||
Encoding.UTF8.GetString(
|
Encoding.Unicode.GetString(
|
||||||
Encryption.RSA.Decrypt(
|
Encryption.RSA.Decrypt(
|
||||||
Convert.FromBase64String(okd.key),
|
Convert.FromBase64String(okd.key),
|
||||||
Storage.GetResourceKey(
|
Storage.GetResourceKeyRaw(
|
||||||
StorageDirectory.ServerKeys,
|
StorageDirectory.ServerKeys,
|
||||||
"pkey",
|
"pkey",
|
||||||
EncryptionHandler.Hash
|
EncryptionHandler.Hash
|
||||||
@ -140,13 +139,11 @@ public partial class MainServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine("lpv");
|
|
||||||
System.IO.File.WriteAllText("LastPassVer.txt", EncryptionHandler.PasswordVersion.ToString());
|
System.IO.File.WriteAllText("LastPassVer.txt", EncryptionHandler.PasswordVersion.ToString());
|
||||||
Storage.SetResourceKey(StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash, EncryptionHandler.OfflinePrivateKey);
|
Storage.SetResourceKey(StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash, EncryptionHandler.OfflinePrivateKey);
|
||||||
using HttpClient setkey = new();
|
using HttpClient setkey = new();
|
||||||
setkey.DefaultRequestHeaders.Add("token", Token);
|
setkey.DefaultRequestHeaders.Add("token", Token);
|
||||||
_ = setkey.PostAsync($"https://{Domain}/{ApiVersion}/Keys/SetOfflineKey", new StringContent(EncryptionHandler.OfflinePublicKey)).Result;
|
_ = setkey.PostAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/Keys/SetOfflineKey", new StringContent(EncryptionHandler.OfflinePublicKey)).Result;
|
||||||
//_ = User.Channels;
|
|
||||||
foreach (var ch in chans)
|
foreach (var ch in chans)
|
||||||
{
|
{
|
||||||
_ = ch.Members;
|
_ = ch.Members;
|
||||||
|
@ -27,6 +27,8 @@ public partial class MainServer : Server
|
|||||||
|
|
||||||
public MainSocketAppUser User { get; internal set; } = default!;
|
public MainSocketAppUser User { get; internal set; } = default!;
|
||||||
|
|
||||||
|
public List<MainSocketChannel> chans { get; } = new();
|
||||||
|
|
||||||
public async Task<MainSocketRemoteUser> SendFriendResult(long user, bool answer, CancellationToken CancellationToken)
|
public async Task<MainSocketRemoteUser> SendFriendResult(long user, bool answer, CancellationToken CancellationToken)
|
||||||
{
|
{
|
||||||
FriendRequestResult json = await SendServer("FriendRequestResult",
|
FriendRequestResult json = await SendServer("FriendRequestResult",
|
||||||
@ -120,7 +122,7 @@ public partial class MainServer : Server
|
|||||||
TChannel request;
|
TChannel request;
|
||||||
if (chans.Count > 0 && chans.Any(s => s.Id == id))
|
if (chans.Count > 0 && chans.Any(s => s.Id == id))
|
||||||
{
|
{
|
||||||
return chans.Where(s => s is TChannel && s.Id == id).Cast<TChannel>().FirstOrDefault()!;
|
return (chans.Where(s => s is TChannel && s.Id == id).First() as TChannel)!;
|
||||||
}
|
}
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -140,7 +142,6 @@ public partial class MainServer : Server
|
|||||||
chans.Remove(p);
|
chans.Remove(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Server = this;
|
request.Server = this;
|
||||||
chans.Add(request);
|
chans.Add(request);
|
||||||
return request;
|
return request;
|
||||||
|
353
Luski.net/PublicServer.Account.cs
Normal file
353
Luski.net/PublicServer.Account.cs
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JacobTechEncryption;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.JsonTypes;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
using Luski.net.JsonTypes.WSS;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using WebSocketSharp;
|
||||||
|
using DataType = Luski.net.Enums.Public.DataType;
|
||||||
|
|
||||||
|
namespace Luski.net;
|
||||||
|
|
||||||
|
public partial class PublicServer
|
||||||
|
{
|
||||||
|
public async Task<bool> Login(string Username, string Password, CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
return await Both(Username, Password, CancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> CreateAccount(string Username, string Password, string Displayname, string PFP, CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
return await Both(Username, Password, CancellationToken, Displayname, PFP);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<bool> LoginViaToken(string t)
|
||||||
|
{
|
||||||
|
CancellationToken CancellationToken = CancellationToken.None;
|
||||||
|
if (!EncryptionHandler.Generating)
|
||||||
|
{
|
||||||
|
EncryptionHandler.GenerateKeys();
|
||||||
|
}
|
||||||
|
while (!EncryptionHandler.Generated) { }
|
||||||
|
|
||||||
|
login = true;
|
||||||
|
Login json;
|
||||||
|
List<KeyValuePair<string, string?>> heads = new()
|
||||||
|
{
|
||||||
|
new("key", EncryptionHandler.MyPublicKey),
|
||||||
|
new("token", Convert.ToBase64String(Encryption.RSA.Encrypt(t, EncryptionHandler.ServerPublicKey, EncoderType.UTF16))),
|
||||||
|
};
|
||||||
|
|
||||||
|
json = await GetFromServer(
|
||||||
|
"SocketAccount/AccessToken",
|
||||||
|
LoginContext.Default.Login,
|
||||||
|
CancellationToken,
|
||||||
|
heads.ToArray());
|
||||||
|
if (json.Error is not null) throw new Exception($"Luski appears to be down at the current moment: {json.ErrorMessage}");
|
||||||
|
if (EncryptionHandler.OfflinePrivateKey is null || EncryptionHandler.OfflinePublicKey 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(wssurl);
|
||||||
|
ServerOut.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12;
|
||||||
|
ServerOut.OnMessage += DataFromServer;
|
||||||
|
ServerOut.EmitOnPing = true;
|
||||||
|
ServerOut.WaitTime = new TimeSpan(0, 0, 5);
|
||||||
|
ServerOut.OnError += ServerOut_OnError;
|
||||||
|
ServerOut.Connect();
|
||||||
|
SendServer(DataType.Token, new WSSLogin() { Token = json.Token! });
|
||||||
|
while (Token is null && Error is null)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
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]
|
||||||
|
)));
|
||||||
|
User = await GetUser<SocketAppUser>(id, CancellationToken);
|
||||||
|
StorageInfoJSON data;
|
||||||
|
if (Storage.StorageID == 0)
|
||||||
|
{
|
||||||
|
EncryptionHandler.Hash = Storage.GenerateStorage();
|
||||||
|
data = await SendServer("OfflineData/Info",
|
||||||
|
new StorageInfoJSON()
|
||||||
|
{
|
||||||
|
id = 0,
|
||||||
|
update = false,
|
||||||
|
password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk")))
|
||||||
|
},
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON,
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("storage_id", Storage.StorageID.ToString()));
|
||||||
|
Storage.setid(data.id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = await GetFromServer("OfflineData/Info", StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair<string, string?>("storage_id", Storage.StorageID.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.update)
|
||||||
|
{
|
||||||
|
EncryptionHandler.Hash = Storage.UpdateStorage(Convert.FromBase64String(data.password));
|
||||||
|
_ = await SendServerPatch("OfflineData/Info",
|
||||||
|
new StorageInfoJSON()
|
||||||
|
{
|
||||||
|
id = 0,
|
||||||
|
update = false,
|
||||||
|
password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk")))
|
||||||
|
},
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON,
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("storage_id", Storage.StorageID.ToString()));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = EncryptionHandler.GetKey(0);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
EncryptionHandler.SetKey(0, new()
|
||||||
|
{
|
||||||
|
EncryptionType = EncryptionType.None,
|
||||||
|
Key = string.Empty
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ = await UpdateStatus(UserStatus.Online, CancellationToken);
|
||||||
|
KeyValuePair<string, string?> stor = new("storage_id", Storage.StorageID.ToString());
|
||||||
|
OfflineData offlinedata = await GetFromServer("OfflineData", OfflineDataContext.Default.OfflineData, CancellationToken, stor);
|
||||||
|
if (offlinedata is not null && offlinedata.Error is null && offlinedata.Data is not null && offlinedata.Data.Length > 0)
|
||||||
|
{
|
||||||
|
string pkey = Storage.GetResourceKeyRaw(
|
||||||
|
StorageDirectory.ServerKeys,
|
||||||
|
"pkey",
|
||||||
|
EncryptionHandler.Hash
|
||||||
|
);
|
||||||
|
foreach (string keyexx in offlinedata.Data)
|
||||||
|
{
|
||||||
|
string keyex = Encoding.UTF8.GetString(Convert.FromBase64String(keyexx));
|
||||||
|
KeyExchange? okd = JsonSerializer.Deserialize<KeyExchange>(keyex);
|
||||||
|
if (okd is not null && !string.IsNullOrEmpty(okd.key))
|
||||||
|
{
|
||||||
|
Storage.SetResourceKey(
|
||||||
|
StorageDirectory.ChannelKeys,
|
||||||
|
okd.channel.ToString(),
|
||||||
|
EncryptionHandler.Hash,
|
||||||
|
Encoding.Unicode.GetString(
|
||||||
|
Encryption.RSA.Decrypt(
|
||||||
|
Convert.FromBase64String(okd.key),
|
||||||
|
pkey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Storage.SetResourceKey(StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash, EncryptionHandler.OfflinePrivateKey);
|
||||||
|
UserKeyGetRequest OfflineKeySetRequest = new()
|
||||||
|
{
|
||||||
|
key_data = Convert.ToBase64String(Encoding.UTF8.GetBytes(EncryptionHandler.OfflinePublicKey)),
|
||||||
|
encryption_type = EncryptionType.RSA
|
||||||
|
};
|
||||||
|
_ = await SendServer("Keys/SetOfflineKey",
|
||||||
|
OfflineKeySetRequest,
|
||||||
|
UserKeyGetRequestContext.Default.UserKeyGetRequest,
|
||||||
|
IncomingHTTPContext.Default.IncomingHTTP,
|
||||||
|
CancellationToken.None,
|
||||||
|
stor);
|
||||||
|
EncryptionHandler.OfflinePublicKey = null!;
|
||||||
|
EncryptionHandler.OfflinePrivateKey = null!;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception(json?.ErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> Both(string Username, string Password, CancellationToken CancellationToken, string? Displayname = null, string? pfp = null)
|
||||||
|
{
|
||||||
|
if (!EncryptionHandler.Generating)
|
||||||
|
{
|
||||||
|
EncryptionHandler.GenerateKeys();
|
||||||
|
}
|
||||||
|
while (!EncryptionHandler.Generated) { }
|
||||||
|
|
||||||
|
login = true;
|
||||||
|
Login json;
|
||||||
|
List<KeyValuePair<string, string?>> heads = new()
|
||||||
|
{
|
||||||
|
new("key", EncryptionHandler.MyPublicKey),
|
||||||
|
new("username", Convert.ToBase64String(Encryption.RSA.Encrypt(Username, EncryptionHandler.ServerPublicKey, EncoderType.UTF16))),
|
||||||
|
new("password", EncryptionHandler.RemotePasswordEncrypt(Encryption.Generic.Encoders[(int)EncoderType.UTF16].GetBytes(Password)))
|
||||||
|
};
|
||||||
|
if (File.Exists("LastPassVer.txt") && int.TryParse(File.ReadAllText("LastPassVer.txt"), out int lpv) && lpv < EncryptionHandler.PasswordVersion && lpv >= 0)
|
||||||
|
{
|
||||||
|
heads.Add(new("old_password", EncryptionHandler.RemotePasswordEncrypt(Encoding.Unicode.GetBytes(Password), lpv)));
|
||||||
|
heads.Add(new("old_version", lpv.ToString()));
|
||||||
|
}
|
||||||
|
if (pfp is not null)
|
||||||
|
{
|
||||||
|
heads.Add(new("displayname", Displayname));
|
||||||
|
json = await SendServer(
|
||||||
|
"SocketAccount",
|
||||||
|
pfp,
|
||||||
|
LoginContext.Default.Login,
|
||||||
|
CancellationToken,
|
||||||
|
heads.ToArray());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
json = await GetFromServer(
|
||||||
|
"SocketAccount",
|
||||||
|
LoginContext.Default.Login,
|
||||||
|
CancellationToken,
|
||||||
|
heads.ToArray());
|
||||||
|
}
|
||||||
|
if (json.Error is not null) throw new Exception($"Luski appears to be down at the current moment: {json.ErrorMessage}");
|
||||||
|
if (EncryptionHandler.OfflinePrivateKey is null || EncryptionHandler.OfflinePublicKey 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(wssurl);
|
||||||
|
ServerOut.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12;
|
||||||
|
ServerOut.OnMessage += DataFromServer;
|
||||||
|
ServerOut.WaitTime = new TimeSpan(0, 0, 5);
|
||||||
|
ServerOut.EmitOnPing = true;
|
||||||
|
ServerOut.OnError += ServerOut_OnError;
|
||||||
|
ServerOut.Connect();
|
||||||
|
SendServer(DataType.Token, new WSSLogin() { Token = json.Token! });
|
||||||
|
while (Token is null && Error is null)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
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]
|
||||||
|
)));
|
||||||
|
User = await GetUser<SocketAppUser>(id, CancellationToken);
|
||||||
|
StorageInfoJSON data;
|
||||||
|
if (Storage.StorageID == 0)
|
||||||
|
{
|
||||||
|
EncryptionHandler.Hash = Storage.GenerateStorage();
|
||||||
|
data = await SendServer("OfflineData/Info",
|
||||||
|
new StorageInfoJSON()
|
||||||
|
{
|
||||||
|
id = 0,
|
||||||
|
update = false,
|
||||||
|
password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk")))
|
||||||
|
},
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON,
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("storage_id", Storage.StorageID.ToString()));
|
||||||
|
Storage.setid(data.id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = await GetFromServer("OfflineData/Info", StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken, new KeyValuePair<string, string?>("storage_id", Storage.StorageID.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.update)
|
||||||
|
{
|
||||||
|
EncryptionHandler.Hash = Storage.UpdateStorage(Convert.FromBase64String(data.password));
|
||||||
|
_ = await SendServerPatch("OfflineData/Info",
|
||||||
|
new StorageInfoJSON()
|
||||||
|
{
|
||||||
|
id = 0,
|
||||||
|
update = false,
|
||||||
|
password = Convert.ToBase64String(Encryption.AES.Encrypt(EncryptionHandler.Hash, Storage.GetResourceBytes(StorageDirectory.StorageInfo, "lpk")))
|
||||||
|
},
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON,
|
||||||
|
StorageInfoJSONContext.Default.StorageInfoJSON, CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("storage_id", Storage.StorageID.ToString()));
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = EncryptionHandler.GetKey(0);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
EncryptionHandler.SetKey(0, new()
|
||||||
|
{
|
||||||
|
EncryptionType = EncryptionType.None,
|
||||||
|
Key = string.Empty
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ = await UpdateStatus(UserStatus.Online, CancellationToken);
|
||||||
|
//EncryptionHandler.Hash = EncryptionHandler.LocalPasswordEncrypt(Encoding.Unicode.GetBytes(Username.ToLower() + Password));
|
||||||
|
KeyValuePair<string, string?> stor = new("storage_id", Storage.StorageID.ToString());
|
||||||
|
OfflineData offlinedata = await GetFromServer("OfflineData", OfflineDataContext.Default.OfflineData, CancellationToken, stor);
|
||||||
|
if (offlinedata is not null && offlinedata.Error is null && offlinedata.Data is not null && offlinedata.Data.Length > 0)
|
||||||
|
{
|
||||||
|
string pkey = Storage.GetResourceKeyRaw(
|
||||||
|
StorageDirectory.ServerKeys,
|
||||||
|
"pkey",
|
||||||
|
EncryptionHandler.Hash
|
||||||
|
);
|
||||||
|
foreach (string keyexx in offlinedata.Data)
|
||||||
|
{
|
||||||
|
string keyex = Encoding.UTF8.GetString(Convert.FromBase64String(keyexx));
|
||||||
|
KeyExchange? okd = JsonSerializer.Deserialize<KeyExchange>(keyex);
|
||||||
|
if (okd is not null && !string.IsNullOrEmpty(okd.key))
|
||||||
|
{
|
||||||
|
Storage.SetResourceKey(
|
||||||
|
StorageDirectory.ChannelKeys,
|
||||||
|
okd.channel.ToString(),
|
||||||
|
EncryptionHandler.Hash,
|
||||||
|
Encoding.Unicode.GetString(
|
||||||
|
Encryption.RSA.Decrypt(
|
||||||
|
Convert.FromBase64String(okd.key),
|
||||||
|
pkey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.IO.File.WriteAllText("LastPassVer.txt", EncryptionHandler.PasswordVersion.ToString());
|
||||||
|
Storage.SetResourceKey(StorageDirectory.ServerKeys, "pkey", EncryptionHandler.Hash, EncryptionHandler.OfflinePrivateKey);
|
||||||
|
UserKeyGetRequest OfflineKeySetRequest = new()
|
||||||
|
{
|
||||||
|
key_data = Convert.ToBase64String(Encoding.UTF8.GetBytes(EncryptionHandler.OfflinePublicKey)),
|
||||||
|
encryption_type = EncryptionType.RSA
|
||||||
|
};
|
||||||
|
_ = await SendServer("Keys/SetOfflineKey",
|
||||||
|
OfflineKeySetRequest,
|
||||||
|
UserKeyGetRequestContext.Default.UserKeyGetRequest,
|
||||||
|
IncomingHTTPContext.Default.IncomingHTTP,
|
||||||
|
CancellationToken.None,
|
||||||
|
stor);
|
||||||
|
// using HttpClient setkey = new();
|
||||||
|
// setkey.DefaultRequestHeaders.Add("token", Token);
|
||||||
|
// _ = await setkey.PostAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/Keys/SetOfflineKey", new StringContent(EncryptionHandler.OfflinePublicKey));
|
||||||
|
EncryptionHandler.OfflinePublicKey = null!;
|
||||||
|
EncryptionHandler.OfflinePrivateKey = null!;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else throw new Exception(json?.ErrorMessage);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
38
Luski.net/PublicServer.Incoming.cs
Normal file
38
Luski.net/PublicServer.Incoming.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
using Luski.net.JsonTypes.WSS;
|
||||||
|
using WebSocketSharp;
|
||||||
|
using DataType = Luski.net.Enums.Public.DataType;
|
||||||
|
|
||||||
|
namespace Luski.net;
|
||||||
|
|
||||||
|
public partial class PublicServer
|
||||||
|
{
|
||||||
|
private void DataFromServer(object? sender, MessageEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.IsPing) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BetterIncomingWSS? data = JsonSerializer.Deserialize(e.Data, BetterIncomingWSSContext.Default.BetterIncomingWSS);
|
||||||
|
switch (data?.Type)
|
||||||
|
{
|
||||||
|
case DataType.Token:
|
||||||
|
WSSLogin n = JsonSerializer.Deserialize(e.Data, WSSLoginContext.Default.WSSLogin)!;
|
||||||
|
File.WriteAllText(Storage.GetStorageDirectory(StorageDirectory.StorageInfo) + "token",
|
||||||
|
n.SessionToken);
|
||||||
|
Token = n.Token;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Exception(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,300 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json.Serialization.Metadata;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JacobTechEncryption;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.Enums.Main;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
using Luski.net.JsonTypes;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
using Luski.net.JsonTypes.HTTP;
|
||||||
|
using Luski.net.JsonTypes.Public;
|
||||||
|
using Luski.net.Structures;
|
||||||
|
using Luski.net.Structures.Public;
|
||||||
|
using Channel = Luski.net.JsonTypes.Public.Channel;
|
||||||
|
using Role = Luski.net.Structures.Public.Role;
|
||||||
|
using SocketUser = Luski.net.Structures.Public.SocketUser;
|
||||||
|
|
||||||
namespace Luski.net;
|
namespace Luski.net;
|
||||||
|
|
||||||
public class PublicServer : Server
|
public partial class PublicServer : Server
|
||||||
{
|
{
|
||||||
internal PublicServer(string Domain, string API_Version):
|
public List<SocketChannel> chans { get; } = new();
|
||||||
base(Domain, API_Version)
|
public List<SocketCategory> cats { get; } = new();
|
||||||
|
public List<Role> roles { get; } = new();
|
||||||
|
|
||||||
|
public SocketAppUser User { get; private set; } = null!;
|
||||||
|
|
||||||
|
internal PublicServer(string Domain, string API_Version, bool Secure = true):
|
||||||
|
base(Domain, API_Version, Secure)
|
||||||
{
|
{
|
||||||
|
ServerInfo si = GetFromServer("socketserver", ServerInfoContext.Default.ServerInfo, CancellationToken.None).Result;
|
||||||
|
Name = si.name;
|
||||||
|
Description = si.description;
|
||||||
|
wssurl = si.wssv4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<TCategory> GetCategory<TCategory>(long id, CancellationToken CancellationToken) where TCategory : SocketCategory, new()
|
||||||
|
{
|
||||||
|
Category request;
|
||||||
|
if (cats.Count > 0 && cats.Any(s => s.ID == id))
|
||||||
|
{
|
||||||
|
return (cats.Where(s => s is TCategory && s.ID == id).First() as TCategory)!;
|
||||||
|
}
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (CanRequest)
|
||||||
|
{
|
||||||
|
request = await GetFromServer($"SocketCategory", PublicCategoryContext.Default.Category, CancellationToken, new KeyValuePair<string, string?>("id", id.ToString()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request is null) throw new Exception("Something was wrong with the server responce");
|
||||||
|
if (request.Error is null)
|
||||||
|
{
|
||||||
|
if (cats.Count > 0 && cats.Any(s => s.ID == request.ID))
|
||||||
|
{
|
||||||
|
foreach (SocketCategory? p in cats.Where(s => s.ID == request.ID))
|
||||||
|
{
|
||||||
|
cats.Remove(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalKeyInfo deckey = EncryptionHandler.GetKey(request.DescriptionEncryptionKey);
|
||||||
|
string dec = deckey.EncryptionType switch
|
||||||
|
{
|
||||||
|
EncryptionType.RSA => Encryption.RSA.Decrypt(Convert.FromBase64String(request.Description), deckey.Key, request.DescriptionEncoderType),
|
||||||
|
EncryptionType.AES => Encryption.Generic.Encoders[(short)request.DescriptionEncoderType].GetString(
|
||||||
|
Encryption.AES.Decrypt(Convert.FromBase64String(request.Description), deckey.Key)),
|
||||||
|
_ => Encryption.Generic.Encoders[(short)request.DescriptionEncoderType].GetString(Convert.FromBase64String(request.Description))
|
||||||
|
};
|
||||||
|
LocalKeyInfo nkey = EncryptionHandler.GetKey(request.TitleEncryptionKey);
|
||||||
|
string n = nkey.EncryptionType switch
|
||||||
|
{
|
||||||
|
EncryptionType.RSA => Encryption.RSA.Decrypt(Convert.FromBase64String(request.Name), nkey.Key, request.TitleEncoderType),
|
||||||
|
EncryptionType.AES => Encryption.Generic.Encoders[(short)request.TitleEncoderType].GetString(
|
||||||
|
Encryption.AES.Decrypt(Convert.FromBase64String(request.Name), nkey.Key)),
|
||||||
|
_ => Encryption.Generic.Encoders[(short)request.TitleEncoderType].GetString(Convert.FromBase64String(request.Name))
|
||||||
|
};
|
||||||
|
|
||||||
|
TCategory bob = new()
|
||||||
|
{
|
||||||
|
ID = request.ID,
|
||||||
|
ParentID = request.Parent,
|
||||||
|
Description = dec,
|
||||||
|
DescriptionEncoderType = request.DescriptionEncoderType,
|
||||||
|
DescriptionEncryptionKey = request.DescriptionEncryptionKey,
|
||||||
|
Channels = request.Channels,
|
||||||
|
Categories = request.InnerCategories,
|
||||||
|
Name = n,
|
||||||
|
RoleOverides = request.RoleOverides,
|
||||||
|
UserOverides = request.UserOverides,
|
||||||
|
TitleEncoderType = request.TitleEncoderType,
|
||||||
|
TitleEncryptionKey = request.TitleEncryptionKey,
|
||||||
|
Server = this,
|
||||||
|
Color = new(request.Color)
|
||||||
|
};
|
||||||
|
cats.Add(bob);
|
||||||
|
return bob;
|
||||||
|
}
|
||||||
|
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}'"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Role> GetRole(long id)
|
||||||
|
{
|
||||||
|
Role[] r = roles.Where(s => s.ID == id).ToArray();
|
||||||
|
if (r.Length > 0) return r[0];
|
||||||
|
JsonTypes.Public.Role s = await GetFromServer("SocketRole?id=" + id.ToString(), RoleContext.Default.Role, CancellationToken.None);
|
||||||
|
|
||||||
|
Role role = new()
|
||||||
|
{
|
||||||
|
Server = this,
|
||||||
|
ID = s.id,
|
||||||
|
Color = new(s.color),
|
||||||
|
Description = s.description,
|
||||||
|
DisplayName = s.display_name,
|
||||||
|
MembersListID = s.members_list,
|
||||||
|
Name = s.name,
|
||||||
|
Index = s.index,
|
||||||
|
ServerPermissions = s.server_permissions
|
||||||
|
};
|
||||||
|
roles.Add(role);
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TChannel> GetChannel<TChannel>(long id, CancellationToken CancellationToken) where TChannel : SocketChannel, new()
|
||||||
|
{
|
||||||
|
Channel request;
|
||||||
|
if (chans.Count > 0 && chans.Any(s => s.ID == id))
|
||||||
|
{
|
||||||
|
return (chans.Where(s => s is TChannel && s.ID == id).First() as TChannel)!;
|
||||||
|
}
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (CanRequest)
|
||||||
|
{
|
||||||
|
request = await GetFromServer($"SocketChannel", PublicChannelContext.Default.Channel, CancellationToken, new KeyValuePair<string, string?>("id", id.ToString()));
|
||||||
|
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 (SocketChannel? p in chans.Where(s => s.ID == request.ID))
|
||||||
|
{
|
||||||
|
chans.Remove(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalKeyInfo deckey = EncryptionHandler.GetKey(request.DescriptionEncryptionKey);
|
||||||
|
string dec = deckey.EncryptionType switch
|
||||||
|
{
|
||||||
|
EncryptionType.RSA => Encryption.RSA.Decrypt(Convert.FromBase64String(request.Description), deckey.Key, request.DescriptionEncoderType),
|
||||||
|
EncryptionType.AES => Encryption.Generic.Encoders[(short)request.DescriptionEncoderType].GetString(
|
||||||
|
Encryption.AES.Decrypt(Convert.FromBase64String(request.Description), deckey.Key)),
|
||||||
|
_ => Encryption.Generic.Encoders[(short)request.DescriptionEncoderType].GetString(Convert.FromBase64String(request.Description))
|
||||||
|
};
|
||||||
|
LocalKeyInfo nkey = EncryptionHandler.GetKey(request.TitleEncryptionKey);
|
||||||
|
string n = nkey.EncryptionType switch
|
||||||
|
{
|
||||||
|
EncryptionType.RSA => Encryption.RSA.Decrypt(Convert.FromBase64String(request.Name), nkey.Key, request.TitleEncoderType),
|
||||||
|
EncryptionType.AES => Encryption.Generic.Encoders[(short)request.TitleEncoderType].GetString(
|
||||||
|
Encryption.AES.Decrypt(Convert.FromBase64String(request.Name), nkey.Key)),
|
||||||
|
_ => Encryption.Generic.Encoders[(short)request.TitleEncoderType].GetString(Convert.FromBase64String(request.Name))
|
||||||
|
};
|
||||||
|
|
||||||
|
TChannel bob = new()
|
||||||
|
{
|
||||||
|
ID = request.ID,
|
||||||
|
CategoryID = request.Parent,
|
||||||
|
Description = dec,
|
||||||
|
DescriptionEncoderType = request.DescriptionEncoderType,
|
||||||
|
DescriptionEncryptionKey = request.DescriptionEncryptionKey,
|
||||||
|
EncoderTypes = request.EncoderTypes,
|
||||||
|
EncryptionKeys = request.EncryptionKeys,
|
||||||
|
Epoch = request.Epoch,
|
||||||
|
Name = n,
|
||||||
|
RoleOverides = request.RoleOverides,
|
||||||
|
UserOverides = request.UserOverides,
|
||||||
|
Type = request.Type,
|
||||||
|
TitleEncoderType = request.TitleEncoderType,
|
||||||
|
TitleEncryptionKey = request.TitleEncryptionKey,
|
||||||
|
PictureType = request.PictureType,
|
||||||
|
Server = this,
|
||||||
|
Color = new(request.Color)
|
||||||
|
};
|
||||||
|
chans.Add(bob);
|
||||||
|
return bob;
|
||||||
|
}
|
||||||
|
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}'"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Tuser> GetUser<Tuser>(long UserId, CancellationToken CancellationToken) where Tuser : SocketUser, new()
|
||||||
|
{
|
||||||
|
JsonTypes.Public.SocketUser user;
|
||||||
|
if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId))
|
||||||
|
{
|
||||||
|
Tuser temp = poeople.Where(s => s is Tuser && s.Id == UserId).Cast<Tuser>().FirstOrDefault()!;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (CanRequest)
|
||||||
|
{
|
||||||
|
user = await GetFromServer("socketuser",
|
||||||
|
PublicSocketUserContext.Default.SocketUser,
|
||||||
|
CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 information\n{error}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuser u = new();
|
||||||
|
if (u is SocketUser)
|
||||||
|
{
|
||||||
|
u = new()
|
||||||
|
{
|
||||||
|
Server = this,
|
||||||
|
Id = user.ID,
|
||||||
|
DisplayName = user.DisplayName,
|
||||||
|
PictureType = user.PictureType,
|
||||||
|
RoleIds = user.RoleIds,
|
||||||
|
Status = user.Status
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u = (new SocketAppUser()
|
||||||
|
{
|
||||||
|
Server = this,
|
||||||
|
Id = user.ID,
|
||||||
|
DisplayName = user.DisplayName,
|
||||||
|
SelectedChannel = user.SelectedChannel,
|
||||||
|
PictureType = user.PictureType,
|
||||||
|
RoleIds = user.RoleIds,
|
||||||
|
Status = user.Status,
|
||||||
|
Username = user.Username
|
||||||
|
} as Tuser)!;
|
||||||
|
}
|
||||||
|
poeople.Add(u);
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the server a request to update the <paramref name="Status"/> of you account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Status">The <see cref="UserStatus"/> you want to set your status to</param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public async Task<Task> UpdateStatus(UserStatus Status, CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
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.Status = Status;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
public string Description { get; }
|
||||||
}
|
}
|
@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using JacobTechEncryption;
|
using JacobTechEncryption;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
using Luski.net.Enums;
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.Structures;
|
||||||
|
|
||||||
namespace Luski.net;
|
namespace Luski.net;
|
||||||
|
|
||||||
@ -10,15 +13,26 @@ public class ServerEncryption
|
|||||||
internal bool Generating, Generated;
|
internal bool Generating, Generated;
|
||||||
internal string ServerPublicKey = "", MyPublicKey = "", myPrivateKey = "", OfflinePrivateKey = "", OfflinePublicKey = "";
|
internal string ServerPublicKey = "", MyPublicKey = "", myPrivateKey = "", OfflinePrivateKey = "", OfflinePublicKey = "";
|
||||||
internal byte[] Hash = default!;
|
internal byte[] Hash = default!;
|
||||||
internal ServerEncryption(string Domain, string API_Version, ServerStorage Storage)
|
internal ServerEncryption(string Domain, string API_Version, ServerStorage Storage, bool Secure)
|
||||||
{
|
{
|
||||||
this.Storage = Storage;
|
this.Storage = Storage;
|
||||||
//TODO Get server p key
|
ServerPublicKey = new HttpClient().GetAsync($"{(Secure ? "https" : "http" )}://{Domain}/{API_Version}/Keys/PublicKey").Result.Content
|
||||||
|
.ReadAsStringAsync().Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetChannelKey(long Channel)
|
public string GetChannelKey(long Channel)
|
||||||
{
|
{
|
||||||
return Storage.GetResourceKey(StorageDirectory.ChannelKeys, Channel.ToString(), Hash);
|
return Storage.GetResourceKeyRaw(StorageDirectory.ChannelKeys, Channel.ToString(), Hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalKeyInfo GetKey(long Key)
|
||||||
|
{
|
||||||
|
return Storage.GetResourceKey(StorageDirectory.ServerKeys, Key.ToString(), Hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetKey(long Key, LocalKeyInfo Info)
|
||||||
|
{
|
||||||
|
Storage.SetResourceKey(StorageDirectory.ServerKeys, Key.ToString(), Info, Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetChannelKey(long Channel, string Key)
|
public void SetChannelKey(long Channel, string Key)
|
@ -18,7 +18,7 @@ public partial class Server
|
|||||||
public string ApiVersion { get; } = "v1";
|
public string ApiVersion { get; } = "v1";
|
||||||
internal WebSocket? ServerOut;
|
internal WebSocket? ServerOut;
|
||||||
internal string? Token = null, Error = null, gen = null;
|
internal string? Token = null, Error = null, gen = null;
|
||||||
|
public bool IsLogedIn => Token is not null;
|
||||||
internal bool CanRequest = false, login = false;
|
internal bool CanRequest = false, login = false;
|
||||||
internal List<IUser> poeople = new();
|
internal List<IUser> poeople = new();
|
||||||
internal List<MainSocketChannel> chans { get; set; } = new();
|
|
||||||
}
|
}
|
306
Luski.net/Server.Storage.cs
Normal file
306
Luski.net/Server.Storage.cs
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using JacobTechEncryption;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.JsonTypes;
|
||||||
|
using Luski.net.Structures;
|
||||||
|
using File = System.IO.File;
|
||||||
|
|
||||||
|
namespace Luski.net;
|
||||||
|
|
||||||
|
public class ServerStorage
|
||||||
|
{
|
||||||
|
public static readonly string[] Directories = new[]
|
||||||
|
{
|
||||||
|
"Info",
|
||||||
|
"Assets",
|
||||||
|
"Channels/Keys",
|
||||||
|
"Keys",
|
||||||
|
"Avatars",
|
||||||
|
"Channels/Icons",
|
||||||
|
"Channels/Messages",
|
||||||
|
"StorageInfo",
|
||||||
|
"Channels/Files"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly int[] CantDelete = new[]
|
||||||
|
{
|
||||||
|
(int)StorageDirectory.ChannelKeys,
|
||||||
|
(int)StorageDirectory.ServerKeys,
|
||||||
|
(int)StorageDirectory.StorageInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
internal ServerStorage(string Domain)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(JT)) Directory.CreateDirectory(JT);
|
||||||
|
Location = JT + "/Luski/";
|
||||||
|
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
||||||
|
Location += "Storage/";
|
||||||
|
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
||||||
|
Location += "Servers/";
|
||||||
|
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
||||||
|
Location += Domain.ToLower() + "/";
|
||||||
|
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
||||||
|
if (!File.Exists(Location + "storage.json")) File.WriteAllText(Location + "storage.json", JsonSerializer.Serialize(new ServerStorageInfo(),ServerStorageInfoContext.Default.ServerStorageInfo));
|
||||||
|
RawInfo = JsonSerializer.Deserialize(File.ReadAllText(Location + "storage.json"),
|
||||||
|
ServerStorageInfoContext.Default.ServerStorageInfo)!;
|
||||||
|
CacheMode = RawInfo.CacheMode;
|
||||||
|
StorageID = RawInfo.StorageID;
|
||||||
|
|
||||||
|
for (int i = 0; i < Directories.Length; i++)
|
||||||
|
{
|
||||||
|
string full = Location;
|
||||||
|
string[] spl = Directories[i].Split('/');
|
||||||
|
foreach (string d in spl)
|
||||||
|
{
|
||||||
|
full += d + "/";
|
||||||
|
if (!Directory.Exists(full)) Directory.CreateDirectory(full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void setid(long id)
|
||||||
|
{
|
||||||
|
StorageID = id;
|
||||||
|
RawInfo.StorageID = id;
|
||||||
|
File.WriteAllText(Location + "storage.json", JsonSerializer.Serialize(RawInfo,ServerStorageInfoContext.Default.ServerStorageInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ServerStorageInfo RawInfo { get; }
|
||||||
|
|
||||||
|
public byte[] UpdateStorage(byte[] OldPassword)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] NewPassword = new byte[100];
|
||||||
|
byte[] lpk = GetResourceBytes(StorageDirectory.StorageInfo, "lpk");
|
||||||
|
OldPassword = Encryption.AES.Decrypt(OldPassword, lpk);
|
||||||
|
using (RandomNumberGenerator provider = RandomNumberGenerator.Create())
|
||||||
|
{
|
||||||
|
provider.GetBytes(NewPassword);
|
||||||
|
}
|
||||||
|
void UpdateDir(string Dir)
|
||||||
|
{
|
||||||
|
DirectoryInfo DI = new(Dir);
|
||||||
|
foreach (DirectoryInfo DIR in DI.GetDirectories())
|
||||||
|
{
|
||||||
|
UpdateDir(DIR.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (FileInfo FI in DI.GetFiles())
|
||||||
|
{
|
||||||
|
byte[] raw = Array.Empty<byte>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
raw = Encryption.AES.Decrypt(
|
||||||
|
File.ReadAllBytes(FI.FullName),
|
||||||
|
OldPassword
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Failed to decrypt file: '{0}'\nError: {1}", FI.FullName, e.ToString());
|
||||||
|
FI.Delete();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
raw = Encryption.AES.Encrypt(raw,
|
||||||
|
NewPassword
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Failed to encrypt file data: '{0}'\nError: {1}", FI.FullName, e.ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(FI.FullName, raw);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Failed to write file data: '{0}'\nError: {1}", FI.FullName, e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateDir(GetStorageDirectory(StorageDirectory.ServerKeys));
|
||||||
|
UpdateDir(GetStorageDirectory(StorageDirectory.ChannelKeys));
|
||||||
|
|
||||||
|
for (int i = 0; i < Directories.Length; i++)
|
||||||
|
{
|
||||||
|
string full = Location;
|
||||||
|
string[] spl = Directories[i].Split('/');
|
||||||
|
if (!RawInfo.DontDelete && !CantDelete.Contains(i))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(full + Directories[i])) Directory.Delete(full + Directories[i], true);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string d in spl)
|
||||||
|
{
|
||||||
|
full += d + "/";
|
||||||
|
if (!Directory.Exists(full)) Directory.CreateDirectory(full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetResourceBytes(StorageDirectory.StorageInfo, "lpk", OldPassword);
|
||||||
|
|
||||||
|
return NewPassword;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GenerateStorage()
|
||||||
|
{
|
||||||
|
byte[] NewPassword = new byte[100];
|
||||||
|
byte[] OldPassword = new byte[100];
|
||||||
|
using (RandomNumberGenerator provider = RandomNumberGenerator.Create())
|
||||||
|
{
|
||||||
|
provider.GetBytes(OldPassword);
|
||||||
|
}
|
||||||
|
using (RandomNumberGenerator provider = RandomNumberGenerator.Create())
|
||||||
|
{
|
||||||
|
provider.GetBytes(NewPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Directories.Length; i++)
|
||||||
|
{
|
||||||
|
string full = Location;
|
||||||
|
string[] spl = Directories[i].Split('/');
|
||||||
|
if (!RawInfo.DontDelete && !CantDelete.Contains(i))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(full + Directories[i])) Directory.Delete(full + Directories[i], true);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string d in spl)
|
||||||
|
{
|
||||||
|
full += d + "/";
|
||||||
|
if (!Directory.Exists(full)) Directory.CreateDirectory(full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetResourceBytes(StorageDirectory.StorageInfo, "lpk", OldPassword);
|
||||||
|
|
||||||
|
return NewPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long StorageID { get; internal set; }
|
||||||
|
|
||||||
|
public string Location { get; internal set; }
|
||||||
|
|
||||||
|
public string GetStorageDirectory(StorageDirectory Directory)
|
||||||
|
{
|
||||||
|
return Location + Directories[(byte)Directory] + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetResourceKey(StorageDirectory Directory, string Resource, string Key)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetString(Encryption.AES.Decrypt(GetResourceBytes(Directory, Resource), Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetResourceKeyRaw(StorageDirectory Directory, string Resource, byte[] Key)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetString(Encryption.AES.Decrypt(GetResourceBytes(Directory, Resource), Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalKeyInfo GetResourceKey(StorageDirectory Directory, string Resource, byte[] Key)
|
||||||
|
{
|
||||||
|
string str =
|
||||||
|
Encoding.UTF8.GetString(Encryption.AES.Decrypt(GetResourceBytes(Directory, Resource),
|
||||||
|
Key));
|
||||||
|
string b = str.Split(':')[0];
|
||||||
|
str = str.Remove(0, b.Length + 1);
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Key = str,
|
||||||
|
EncryptionType = (EncryptionType)short.Parse(b)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetResourceKey(StorageDirectory Directory, string Resource, LocalKeyInfo Info, byte[] Key)
|
||||||
|
{
|
||||||
|
SetResourceKey(Directory, Resource, Key, $"{(int)Info.EncryptionType}:{Info.Key}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetResourceKey(StorageDirectory Directory, string Resource, string Key, string value)
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(GetStorageDirectory(Directory) + Resource, Encryption.AES.Encrypt(Encoding.UTF8.GetBytes(value), Key));
|
||||||
|
}
|
||||||
|
public void SetResourceKey(StorageDirectory Directory, string Resource, byte[] Key, string value)
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(GetStorageDirectory(Directory) + Resource, Encryption.AES.Encrypt(Encoding.UTF8.GetBytes(value), Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetResourceKey(StorageDirectory Directory, string Resource, byte[] Key, byte[] value)
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(GetStorageDirectory(Directory) + Resource, Encryption.AES.Encrypt(value, Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetResourceBytes(StorageDirectory Directory, string Resource)
|
||||||
|
{
|
||||||
|
return File.ReadAllBytes(Location + Directories[(byte)Directory] + "/" + Resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream GetResourceStream(StorageDirectory Directory, string Resource)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[16 * 1024];
|
||||||
|
MemoryStream ms = new();
|
||||||
|
using (FileStream r = File.OpenRead(Location + Directories[(byte)Directory] + "/" + Resource))
|
||||||
|
{
|
||||||
|
int readBytes;
|
||||||
|
while ((readBytes = r.Read(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
ms.Write(buffer, 0, readBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.Position = 0;
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetResourceBytes(StorageDirectory Directory, string Resource, byte[] data)
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(Location + Directories[(byte)Directory] + "/" + Resource, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheMode CacheMode { get; internal set; }
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Net.Mime;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization.Metadata;
|
using System.Text.Json.Serialization.Metadata;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -11,42 +12,60 @@ using System.Threading.Tasks;
|
|||||||
using Luski.net.Enums;
|
using Luski.net.Enums;
|
||||||
using Luski.net.Interfaces;
|
using Luski.net.Interfaces;
|
||||||
using Luski.net.JsonTypes.BaseTypes;
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
using Luski.net.JsonTypes.WSS;
|
||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
|
|
||||||
namespace Luski.net;
|
namespace Luski.net;
|
||||||
|
|
||||||
public partial class Server
|
public partial class Server
|
||||||
{
|
{
|
||||||
internal Server(string Domain, string API_Version)
|
internal Server(string Domain, string API_Version, bool Secure = true)
|
||||||
{
|
{
|
||||||
this.Domain = Domain;
|
this.Domain = Domain;
|
||||||
this.ApiVersion = API_Version;
|
this.ApiVersion = API_Version;
|
||||||
|
this.Secure = Secure;
|
||||||
Storage = new(Domain);
|
Storage = new(Domain);
|
||||||
EncryptionHandler = new(Domain, API_Version, Storage);
|
EncryptionHandler = new(Domain, API_Version, Storage, this.Secure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool Secure = true;
|
||||||
|
internal string wssurl;
|
||||||
|
|
||||||
public ServerEncryption EncryptionHandler { get; }
|
public ServerEncryption EncryptionHandler { get; }
|
||||||
public ServerStorage Storage { get; }
|
public ServerStorage Storage { get; }
|
||||||
|
|
||||||
public async Task<byte[]> GetAvatar(CancellationToken CancellationToken)
|
public async Task<Stream> GetAvatar(CancellationToken CancellationToken)
|
||||||
{
|
{
|
||||||
bool isc = File.Exists(Storage.GetStorageDirectory(StorageDirectory.ServerAssets) + "Icon");
|
bool isc = File.Exists(Storage.GetStorageDirectory(StorageDirectory.ServerAssets) + "Icon");
|
||||||
if (!isc) await GetFromServer($"socketserver/Avatar/", Storage.GetStorageDirectory(StorageDirectory.ServerAssets) + "Icon", CancellationToken);
|
if (!isc) await GetFromServer($"socketserver/Icon/", Storage.GetStorageDirectory(StorageDirectory.ServerAssets) + "Icon", CancellationToken);
|
||||||
return Storage.GetResourceBytes(StorageDirectory.ServerAssets, "Icon");
|
return Storage.GetResourceStream(StorageDirectory.ServerAssets, "Icon");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendServer<Tvalue>(Tvalue Payload, JsonTypeInfo<Tvalue> jsonTypeInfo) where Tvalue : IncomingWSS
|
public void SendServerOld<Tvalue>(Tvalue Payload, JsonTypeInfo<Tvalue> jsonTypeInfo) where Tvalue : IncomingWSS
|
||||||
{
|
{
|
||||||
ServerOut?.Send(JsonSerializer.Serialize(Payload, jsonTypeInfo));
|
ServerOut?.Send(JsonSerializer.Serialize(Payload, jsonTypeInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendServer(Enums.Public.DataType Type, IServerEvent Payload)
|
||||||
|
{
|
||||||
|
ServerOut?.Send(JsonSerializer.Serialize(new WSSOut()
|
||||||
|
{
|
||||||
|
Data = new()
|
||||||
|
{
|
||||||
|
Type = Type,
|
||||||
|
Data = Payload
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpResponseMessage GetFromServer(string Path, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
public HttpResponseMessage GetFromServer(string Path, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
||||||
{
|
{
|
||||||
using HttpClient web = new();
|
using HttpClient web = new();
|
||||||
web.Timeout = TimeSpan.FromSeconds(10);
|
web.Timeout = TimeSpan.FromSeconds(10);
|
||||||
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
||||||
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
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($"https://{Domain}/{ApiVersion}/{Path}", cancellationToken: CancellationToken).Result;
|
return web.GetAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", cancellationToken: CancellationToken).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task GetFromServer(string Path, string File, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
public Task GetFromServer(string Path, string File, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
|
||||||
@ -55,7 +74,7 @@ public partial class Server
|
|||||||
web.Timeout = TimeSpan.FromMinutes(10);
|
web.Timeout = TimeSpan.FromMinutes(10);
|
||||||
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
||||||
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
||||||
HttpResponseMessage Response = web.GetAsync($"https://{Domain}/{ApiVersion}/{Path}", CancellationToken).Result;
|
HttpResponseMessage Response = web.GetAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", CancellationToken).Result;
|
||||||
Stream stream = Response.Content.ReadAsStreamAsync(CancellationToken).Result;
|
Stream stream = Response.Content.ReadAsStreamAsync(CancellationToken).Result;
|
||||||
using FileStream fs = System.IO.File.Create(File);
|
using FileStream fs = System.IO.File.Create(File);
|
||||||
stream.CopyTo(fs);
|
stream.CopyTo(fs);
|
||||||
@ -65,8 +84,17 @@ public partial class Server
|
|||||||
public async Task<Tresult> GetFromServer<Tresult>(string Path, JsonTypeInfo<Tresult> Type, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers) where Tresult : IncomingHTTP, new()
|
public async Task<Tresult> GetFromServer<Tresult>(string Path, JsonTypeInfo<Tresult> Type, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers) where Tresult : IncomingHTTP, new()
|
||||||
{
|
{
|
||||||
HttpResponseMessage ServerResponce = GetFromServer(Path, CancellationToken, 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}" };
|
//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);
|
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 new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" };
|
if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" };
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
@ -76,9 +104,29 @@ public partial class Server
|
|||||||
using HttpClient web = new();
|
using HttpClient web = new();
|
||||||
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
||||||
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
||||||
HttpResponseMessage ServerResponce = web.PostAsJsonAsync($"https://{Domain}/{ApiVersion}/{Path}", Payload, jsonTypeInfo, CancellationToken).Result;
|
HttpResponseMessage ServerResponce = web.PostAsJsonAsync($"{(Secure ? "https" : "http" )}://{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}" };
|
//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" };
|
Tresult error = new() { StatusCode = ServerResponce.StatusCode, Error = null, 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; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Tresult> SendServerPatch<Tvalue, Tresult>(string Path, Tvalue Payload, JsonTypeInfo<Tvalue> jsonTypeInfo, JsonTypeInfo<Tresult> ReturnjsonTypeInfo, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] 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<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
||||||
|
HttpResponseMessage ServerResponce = await web.PatchAsJsonAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", Payload, jsonTypeInfo, CancellationToken);
|
||||||
|
// HttpResponseMessage ServerResponce = await web.PatchAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", new StringContent(JsonSerializer.Serialize(Payload, jsonTypeInfo)),
|
||||||
|
// CancellationToken);
|
||||||
|
//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 = null, ErrorMessage = $"Server responded with empty data" };
|
||||||
if (string.IsNullOrWhiteSpace(ServerResponce.Content.ReadAsStringAsync(CancellationToken).Result)) return error;
|
if (string.IsNullOrWhiteSpace(ServerResponce.Content.ReadAsStringAsync(CancellationToken).Result)) return error;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -98,12 +146,12 @@ public partial class Server
|
|||||||
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
if (!login) web.DefaultRequestHeaders.Add("token", Token);
|
||||||
web.Timeout = new TimeSpan(0, 10, 0);
|
web.Timeout = new TimeSpan(0, 10, 0);
|
||||||
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair<string, string?> header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value);
|
||||||
HttpResponseMessage ServerResponce = web.PostAsync($"https://{Domain}/{ApiVersion}/{Path}", new StreamContent(fs), CancellationToken).Result;
|
//web.DefaultRequestHeaders.Add("Content-Type", MediaTypeNames.Application.Octet);
|
||||||
if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" };
|
HttpResponseMessage ServerResponce = web.PostAsync($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", new StreamContent(fs), CancellationToken).Result;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync(CancellationToken).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" };
|
if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = null, ErrorMessage = $"Server responded with empty data" };
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
catch { return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; }
|
catch { return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; }
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using JacobTechEncryption;
|
|
||||||
using Luski.net.Enums;
|
|
||||||
using Luski.net.JsonTypes;
|
|
||||||
|
|
||||||
namespace Luski.net;
|
|
||||||
|
|
||||||
public class ServerStorage
|
|
||||||
{
|
|
||||||
public static readonly string[] Directories = new[]
|
|
||||||
{
|
|
||||||
"Info",
|
|
||||||
"Assets",
|
|
||||||
"Channels/Keys",
|
|
||||||
"Keys",
|
|
||||||
"Avatars",
|
|
||||||
"Channels/Icons",
|
|
||||||
"Channels/Messages"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly int[] CantDelete = new[]
|
|
||||||
{
|
|
||||||
(int)StorageDirectory.ChannelKeys,
|
|
||||||
(int)StorageDirectory.ServerKeys
|
|
||||||
};
|
|
||||||
|
|
||||||
internal ServerStorage(string Domain)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(JT)) Directory.CreateDirectory(JT);
|
|
||||||
Location = JT + "/Luski/";
|
|
||||||
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
|
||||||
Location += "Storage/";
|
|
||||||
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
|
||||||
Location += "Servers/";
|
|
||||||
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
|
||||||
Location += Domain+ "/";
|
|
||||||
if (!Directory.Exists(Location)) Directory.CreateDirectory(Location);
|
|
||||||
if (!File.Exists(Location + "storage.json")) File.WriteAllText(Location + "storage.json", JsonSerializer.Serialize(new ServerStorageInfo(),ServerStorageInfoContext.Default.ServerStorageInfo));
|
|
||||||
ServerStorageInfo info = JsonSerializer.Deserialize(File.ReadAllText(Location + "storage.json"),
|
|
||||||
ServerStorageInfoContext.Default.ServerStorageInfo)!;
|
|
||||||
CacheMode = info.CacheMode;
|
|
||||||
for (int i = 0; i < Directories.Length; i++)
|
|
||||||
{
|
|
||||||
string full = Location;
|
|
||||||
string[] spl = Directories[i].Split('/');
|
|
||||||
if (!info.DontDelete && !CantDelete.Contains(i))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Directory.Exists(full + spl[0])) Directory.Delete(full + spl[0], true);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string d in spl)
|
|
||||||
{
|
|
||||||
full += d + "/";
|
|
||||||
if (!Directory.Exists(full)) Directory.CreateDirectory(full);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Location { get; internal set; }
|
|
||||||
|
|
||||||
public string GetStorageDirectory(StorageDirectory Directory)
|
|
||||||
{
|
|
||||||
return Location + Directories[(byte)Directory] + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetResourceKey(StorageDirectory Directory, string Resource, string Key)
|
|
||||||
{
|
|
||||||
return Encoding.UTF8.GetString(Encryption.AES.Decrypt(GetResourceBytes(Directory, Resource), Key));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetResourceKey(StorageDirectory Directory, string Resource, byte[] Key)
|
|
||||||
{
|
|
||||||
return Encoding.UTF8.GetString(Encryption.AES.Decrypt(GetResourceBytes(Directory, Resource), Encoding.UTF8.GetString(Key)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetResourceKey(StorageDirectory Directory, string Resource, string Key, string value)
|
|
||||||
{
|
|
||||||
File.WriteAllBytes(GetStorageDirectory(Directory) + Resource, Encryption.AES.Encrypt(Encoding.UTF8.GetBytes(value), Key));
|
|
||||||
}
|
|
||||||
public void SetResourceKey(StorageDirectory Directory, string Resource, byte[] Key, string value)
|
|
||||||
{
|
|
||||||
File.WriteAllBytes(GetStorageDirectory(Directory) + Resource, Encryption.AES.Encrypt(Encoding.UTF8.GetBytes(value), Encoding.UTF8.GetString(Key)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] GetResourceBytes(StorageDirectory Directory, string Resource)
|
|
||||||
{
|
|
||||||
return File.ReadAllBytes(Location + Directories[(byte)Directory] + "/" + Resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CacheMode CacheMode { get; internal set; }
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
9
Luski.net/Structures/LocalKeyInfo.cs
Normal file
9
Luski.net/Structures/LocalKeyInfo.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures;
|
||||||
|
|
||||||
|
public class LocalKeyInfo
|
||||||
|
{
|
||||||
|
public string Key { get; init; } = default!;
|
||||||
|
public EncryptionType EncryptionType { get; init; } = default!;
|
||||||
|
}
|
@ -19,40 +19,45 @@ public class MainSocketAppUser : MainSocketUserBase, IAppUser
|
|||||||
[JsonPropertyName("selected_channel")]
|
[JsonPropertyName("selected_channel")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public long SelectedChannel { get; internal set; } = default!;
|
public long SelectedChannel { get; internal set; } = default!;
|
||||||
[JsonPropertyName("username")]
|
[JsonPropertyName("email")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public string Username { get; internal set; } = default!;
|
public string Username { get; internal set; } = default!;
|
||||||
[JsonPropertyName("flags")]
|
[JsonPropertyName("flags")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public UserFlag Flags { get; internal set; } = default!;
|
public UserFlag Flags { get; internal set; } = default!;
|
||||||
|
|
||||||
public MainServer Server { get; internal set; } = default!;
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IReadOnlyList<MainSocketChannel> Channels
|
public IReadOnlyList<MainSocketChannel> Channels
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_Channels is null || ChannelIdList is not null)
|
if (_Channels is null && ChannelIdList is not null)
|
||||||
{
|
{
|
||||||
if (ChannelIdList.Length != 0)
|
if (ChannelIdList.Length != 0)
|
||||||
{
|
{
|
||||||
_Channels = new List<MainSocketChannel>();
|
_Channels = new List<MainSocketChannel>();
|
||||||
foreach (long channel in ChannelIdList)
|
foreach (long channel in ChannelIdList)
|
||||||
{
|
{
|
||||||
MainSocketChannel s = Server.GetChannel(channel,
|
try
|
||||||
MainSocketChannelContext.Default.MainSocketChannel, CancellationToken.None).Result;
|
|
||||||
Server.chans.Remove(s);
|
|
||||||
switch (s.Type)
|
|
||||||
{
|
{
|
||||||
case ChannelType.GROUP:
|
MainSocketChannel s = Server.GetChannel(channel,
|
||||||
_Channels.Add(Server.GetChannel(channel,
|
MainSocketChannelContext.Default.MainSocketChannel, CancellationToken.None).Result;
|
||||||
MainSocketGroupChannelContext.Default.MainSocketGroupChannel, CancellationToken.None).Result);
|
Server.chans.Remove(s);
|
||||||
break;
|
switch (s.Type)
|
||||||
case ChannelType.DM:
|
{
|
||||||
_Channels.Add(Server.GetChannel(channel,
|
case ChannelType.GROUP:
|
||||||
MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken.None).Result);
|
_Channels.Add(Server.GetChannel(channel,
|
||||||
break;
|
MainSocketGroupChannelContext.Default.MainSocketGroupChannel, CancellationToken.None).Result);
|
||||||
|
break;
|
||||||
|
case ChannelType.DM:
|
||||||
|
_Channels.Add(Server.GetChannel(channel,
|
||||||
|
MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken.None).Result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +120,7 @@ public class MainSocketAppUser : MainSocketUserBase, IAppUser
|
|||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public FR[] FriendRequestsRaw { get; internal set; } = default!;
|
public FR[] FriendRequestsRaw { get; internal set; } = default!;
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private List<MainSocketChannel> _Channels = default!;
|
private List<MainSocketChannel> _Channels = null!;
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private List<MainSocketRemoteUser> _Friends = default!;
|
private List<MainSocketRemoteUser> _Friends = default!;
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
@ -78,7 +78,7 @@ public class MainSocketChannel : IncomingHTTP
|
|||||||
{
|
{
|
||||||
if (i.Id != Server.User.Id)
|
if (i.Id != Server.User.Id)
|
||||||
{
|
{
|
||||||
long key = i.GetUserKey(CancellationToken).Result;
|
long key = i.GetUserKeys(CancellationToken).Result.First().Id;
|
||||||
if (true)
|
if (true)
|
||||||
{
|
{
|
||||||
WSSKeyExchange send = new()
|
WSSKeyExchange send = new()
|
||||||
@ -87,7 +87,7 @@ public class MainSocketChannel : IncomingHTTP
|
|||||||
channel = Id,
|
channel = Id,
|
||||||
key = Convert.ToBase64String(Encryption.RSA.Encrypt(lkey, key.ToString(), EncoderType.UTF8))
|
key = Convert.ToBase64String(Encryption.RSA.Encrypt(lkey, key.ToString(), EncoderType.UTF8))
|
||||||
};
|
};
|
||||||
Server.SendServer(send, WSSKeyExchangeContext.Default.WSSKeyExchange);
|
Server.SendServerOld(send, WSSKeyExchangeContext.Default.WSSKeyExchange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -22,14 +22,14 @@ public class MainSocketTextChannel : MainSocketChannel
|
|||||||
return await Server.GetMessage(ID, CancellationToken);
|
return await Server.GetMessage(ID, CancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<byte[]> GetPicture(CancellationToken CancellationToken)
|
public async Task<Stream> GetPicture(CancellationToken CancellationToken)
|
||||||
{
|
{
|
||||||
if (Type == ChannelType.DM) return Members.First().GetAvatar(CancellationToken).Result;
|
if (Type == ChannelType.DM) return Members.First().GetAvatar(CancellationToken).Result;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.ChannelIcons) + Id.ToString());
|
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.ChannelIcons) + Id.ToString());
|
||||||
if (!isc) await Server.GetFromServer($"SocketChannel/GetPicture/{Id}", Server.Storage.GetStorageDirectory(StorageDirectory.ChannelIcons) + Id.ToString(), CancellationToken);
|
if (!isc) await Server.GetFromServer($"SocketChannel/GetPicture/{Id}", Server.Storage.GetStorageDirectory(StorageDirectory.ChannelIcons) + Id.ToString(), CancellationToken);
|
||||||
return Server.Storage.GetResourceBytes(StorageDirectory.ChannelIcons, Id.ToString());
|
return Server.Storage.GetResourceStream(StorageDirectory.ChannelIcons, Id.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.IO;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -22,17 +23,18 @@ public class MainSocketUserBase : IncomingHTTP, IUser
|
|||||||
[JsonPropertyName("picture_type")]
|
[JsonPropertyName("picture_type")]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public PictureType PictureType { get; internal set; } = default!;
|
public PictureType PictureType { get; internal set; } = default!;
|
||||||
public async Task<byte[]> GetAvatar(CancellationToken CancellationToken)
|
public async Task<Stream> GetAvatar(CancellationToken CancellationToken)
|
||||||
{
|
{
|
||||||
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString());
|
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString());
|
||||||
if (!isc) await Server.GetFromServer($"socketuserprofile/Avatar/{Id}", Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString(), CancellationToken);
|
if (!isc) await Server.GetFromServer($"socketuserprofile/Avatar/{Id}", Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString(), CancellationToken);
|
||||||
return Server.Storage.GetResourceBytes(StorageDirectory.Avatars, Id.ToString());
|
return Server.Storage.GetResourceStream(StorageDirectory.Avatars, Id.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<long> GetUserKey(CancellationToken CancellationToken)
|
public Task<PublicKeyInfo[]> GetUserKeys(CancellationToken CancellationToken)
|
||||||
{
|
{
|
||||||
string data = Server.GetFromServer($"Keys/GetUserKey/{Id}", CancellationToken).Content.ReadAsStringAsync().Result;
|
string data = Server.GetFromServer($"Keys/GetUserKey/{Id}", CancellationToken).Content.ReadAsStringAsync().Result;
|
||||||
return Task.FromResult(long.Parse(data));
|
//return Task.FromResult(new long[] {long.Parse(data)});
|
||||||
|
return Task.FromResult(new[] { new PublicKeyInfo() { Id = long.Parse(data) }});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
Luski.net/Structures/Public/Color.cs
Normal file
40
Luski.net/Structures/Public/Color.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class Color
|
||||||
|
{
|
||||||
|
public Color(string servercol)
|
||||||
|
{
|
||||||
|
Bytes = servercol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color(byte R, byte G, byte B, byte A)
|
||||||
|
{
|
||||||
|
Bytes = $"{Convert.ToChar(R)}{Convert.ToChar(G)}{Convert.ToChar(B)}{Convert.ToChar(A)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Bytes;
|
||||||
|
|
||||||
|
public string ToDB()
|
||||||
|
{
|
||||||
|
return Bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte A
|
||||||
|
{
|
||||||
|
get => (byte)(Bytes[3]);
|
||||||
|
}
|
||||||
|
public byte R
|
||||||
|
{
|
||||||
|
get => (byte)(Bytes[0]);
|
||||||
|
}
|
||||||
|
public byte G
|
||||||
|
{
|
||||||
|
get => (byte)(Bytes[1]);
|
||||||
|
}
|
||||||
|
public byte B
|
||||||
|
{
|
||||||
|
get => (byte)(Bytes[2]);
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
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.Structures.Main;
|
|
||||||
|
|
||||||
namespace Luski.net.Structures.Public;
|
|
||||||
|
|
||||||
public class PublicSocketAppUser : PublicSocketUserBase, 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
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
public class PublicSocketUserBase : IncomingHTTP, IUser
|
|
||||||
{
|
|
||||||
public PublicServer Server { get; internal set; } = default!;
|
|
||||||
[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!;
|
|
||||||
public async Task<byte[]> GetAvatar(CancellationToken CancellationToken)
|
|
||||||
{
|
|
||||||
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString());
|
|
||||||
if (!isc) await Server.GetFromServer($"socketuserprofile/Avatar/{Id}", Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString(), CancellationToken);
|
|
||||||
return Server.Storage.GetResourceBytes(StorageDirectory.Avatars, Id.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<long> GetUserKey(CancellationToken CancellationToken)
|
|
||||||
{
|
|
||||||
string data = Server.GetFromServer($"Keys/GetUserKey/{Id}", CancellationToken).Content.ReadAsStringAsync().Result;
|
|
||||||
return Task.FromResult(long.Parse(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonSerializable(typeof(PublicSocketUserBase))]
|
|
||||||
[JsonSourceGenerationOptions(
|
|
||||||
GenerationMode = JsonSourceGenerationMode.Default,
|
|
||||||
PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified,
|
|
||||||
WriteIndented = false,
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.Never)]
|
|
||||||
internal partial class PublicSocketUserBaseContext : JsonSerializerContext
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
29
Luski.net/Structures/Public/Role.cs
Normal file
29
Luski.net/Structures/Public/Role.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Luski.net.Enums.Public;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class Role
|
||||||
|
{
|
||||||
|
public required PublicServer Server { get; init; } = default!;
|
||||||
|
public required long ID { get; init; } = default!;
|
||||||
|
public required string Name { get; init; } = default!;
|
||||||
|
public required int Index { get; init; } = default!;
|
||||||
|
public required Color Color { get; init; } = default!;
|
||||||
|
public required string Description { get; init; } = default!;
|
||||||
|
public required string DisplayName { get; init; } = default!;
|
||||||
|
public required ServerPermission[] ServerPermissions { get; init; } = default!;
|
||||||
|
public required long[] MembersListID { get; init; } = default!;
|
||||||
|
private List<SocketUser>? RawUsers = null;
|
||||||
|
|
||||||
|
public Task<SocketUser[]> GetMembers()
|
||||||
|
{
|
||||||
|
if (RawUsers is null)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(RawUsers!.ToArray());
|
||||||
|
}
|
||||||
|
}
|
21
Luski.net/Structures/Public/RoleOveride.cs
Normal file
21
Luski.net/Structures/Public/RoleOveride.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class RoleOveride
|
||||||
|
{
|
||||||
|
public long ID { get; init; }
|
||||||
|
public long ParentRoleID { get; init; }
|
||||||
|
internal string[] RawOverides { get; init; }
|
||||||
|
private Role? Parent = null;
|
||||||
|
|
||||||
|
public Task<Role> GetRole()
|
||||||
|
{
|
||||||
|
if (Parent is null)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(Parent)!;
|
||||||
|
}
|
||||||
|
}
|
17
Luski.net/Structures/Public/SocketAppUser.cs
Executable file
17
Luski.net/Structures/Public/SocketAppUser.cs
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class SocketAppUser : SocketUser
|
||||||
|
{
|
||||||
|
public long SelectedChannel { get; init; } = default!;
|
||||||
|
|
||||||
|
public async Task<SocketChannel> GetSelectedChannel(CancellationToken Token)
|
||||||
|
{
|
||||||
|
return await Server.GetChannel<SocketChannel>(SelectedChannel, Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Username { get; init; } = default!;
|
||||||
|
}
|
106
Luski.net/Structures/Public/SocketCategory.cs
Normal file
106
Luski.net/Structures/Public/SocketCategory.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums.Public;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class SocketCategory
|
||||||
|
{
|
||||||
|
public PublicServer Server { get; init; } = default!;
|
||||||
|
public long ID { get; init; }
|
||||||
|
public Color Color { get; init; }
|
||||||
|
internal long ParentID { get; set; }
|
||||||
|
internal long[] RoleOverides { get; set; }
|
||||||
|
internal long[] UserOverides { get; set; }
|
||||||
|
internal long[] Channels { get; set; }
|
||||||
|
internal long[] Categories { get; set; }
|
||||||
|
SocketCategory? RawParent = null;
|
||||||
|
List<RoleOveride>? RawRoleOverides = null;
|
||||||
|
List<UserOveride>? RawUserOverides = null;
|
||||||
|
List<SocketChannel>? RawChan = null;
|
||||||
|
List<SocketCategory>? RawCat = null;
|
||||||
|
|
||||||
|
public async Task<SocketCategory?> GetParent()
|
||||||
|
{
|
||||||
|
if (ParentID != -1 && RawParent is null)
|
||||||
|
{
|
||||||
|
RawParent = await Server.GetCategory<SocketCategory>(ParentID, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SocketChannel[]> GetChannels()
|
||||||
|
{
|
||||||
|
if (RawChan is null)
|
||||||
|
{
|
||||||
|
RawChan = new();
|
||||||
|
foreach (long chan in Channels)
|
||||||
|
{
|
||||||
|
RawChan.Add(await Server.GetChannel<SocketChannel>(chan, CancellationToken.None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RawChan.Count != Channels.Length)
|
||||||
|
{
|
||||||
|
foreach (long chan in Channels)
|
||||||
|
{
|
||||||
|
if (RawChan.Any(s => s.ID == chan)) continue;
|
||||||
|
RawChan.Add(await Server.GetChannel<SocketChannel>(chan, CancellationToken.None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawChan.ToArray();
|
||||||
|
}
|
||||||
|
public async Task<SocketCategory[]> GetCategories()
|
||||||
|
{
|
||||||
|
if (RawCat is null)
|
||||||
|
{
|
||||||
|
RawCat = new();
|
||||||
|
foreach (long chan in Categories)
|
||||||
|
{
|
||||||
|
RawCat.Add(await Server.GetCategory<SocketCategory>(chan, CancellationToken.None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RawCat.Count != Channels.Length)
|
||||||
|
{
|
||||||
|
foreach (long chan in Categories)
|
||||||
|
{
|
||||||
|
if (RawCat.Any(s => s.ID == chan)) continue;
|
||||||
|
RawCat.Add(await Server.GetCategory<SocketCategory>(chan, CancellationToken.None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawCat.ToArray();
|
||||||
|
}
|
||||||
|
public string Name { get; internal set; }
|
||||||
|
public string Description { get; internal set; }
|
||||||
|
|
||||||
|
public Task<RoleOveride[]> GetRoleOverides()
|
||||||
|
{
|
||||||
|
if (RawRoleOverides is null)
|
||||||
|
{
|
||||||
|
RawRoleOverides = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(RawRoleOverides!.ToArray());
|
||||||
|
}
|
||||||
|
public Task<UserOveride[]> GetUserOveride()
|
||||||
|
{
|
||||||
|
if (RawUserOverides is null)
|
||||||
|
{
|
||||||
|
RawUserOverides = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(RawUserOverides!.ToArray());
|
||||||
|
}
|
||||||
|
public long TitleEncryptionKey { get; internal set; }
|
||||||
|
public long DescriptionEncryptionKey { get; internal set; }
|
||||||
|
public EncoderType TitleEncoderType { get; internal set; }
|
||||||
|
public EncoderType DescriptionEncoderType { get; internal set; }
|
||||||
|
}
|
217
Luski.net/Structures/Public/SocketChannel.cs
Normal file
217
Luski.net/Structures/Public/SocketChannel.cs
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JacobTechEncryption;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.Enums.Public;
|
||||||
|
using Luski.net.JsonTypes.Public;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class SocketChannel
|
||||||
|
{
|
||||||
|
public PublicServer Server { get; init; } = default!;
|
||||||
|
public Color Color { get; init; }
|
||||||
|
public long ID { get; internal set; }
|
||||||
|
internal long CategoryID { get; set; }
|
||||||
|
internal long[] RoleOverides { get; set; }
|
||||||
|
internal long[] UserOverides { get; set; }
|
||||||
|
SocketCategory? RawParent = null;
|
||||||
|
List<RoleOveride>? RawRoleOverides = null;
|
||||||
|
List<UserOveride>? RawUserOverides = null;
|
||||||
|
public PictureType PictureType { get; internal set; }
|
||||||
|
|
||||||
|
public async Task<IReadOnlyList<SocketMessage>> GetMessages(CancellationToken CancellationToken, int count = 50)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (count > 200)
|
||||||
|
{
|
||||||
|
throw new Exception("You can not request more than 200 messages at a time");
|
||||||
|
}
|
||||||
|
else if (count < 1)
|
||||||
|
{
|
||||||
|
throw new Exception("You must request at least 1 message");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PublicSocketBulkMessage data = await Server.GetFromServer("SocketBulkMessage",
|
||||||
|
PublicSocketBulkMessageContext.Default.PublicSocketBulkMessage,
|
||||||
|
CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("id", ID.ToString()),
|
||||||
|
new KeyValuePair<string, string?>("messages", count.ToString()));
|
||||||
|
if (data is not null && !data.Error.HasValue)
|
||||||
|
{
|
||||||
|
int num = Convert.ToInt32(6);
|
||||||
|
if (num == 0) num = 1;
|
||||||
|
//string key = Server.EncryptionHandler.GetKey(enc)
|
||||||
|
//string key = Server.EncryptionHandler.GetChannelKey(ID);
|
||||||
|
if (data.Messages is null) data.Messages = Array.Empty<PublicMessage>();
|
||||||
|
List<SocketMessage> mmmm = new();
|
||||||
|
ParallelLoopResult p = Parallel.ForEach(data.Messages, new ParallelOptions()
|
||||||
|
{
|
||||||
|
MaxDegreeOfParallelism = num
|
||||||
|
}, i =>
|
||||||
|
{
|
||||||
|
if (i.EncryptionKey == 0)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(i.Context))
|
||||||
|
{
|
||||||
|
i.Context = "";
|
||||||
|
}
|
||||||
|
else i.Context = Encryption.Generic.Encoders[(int)i.EncoderType]
|
||||||
|
.GetString(Convert.FromBase64String(i.Context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LocalKeyInfo key = Server.EncryptionHandler.GetKey(i.EncryptionKey);
|
||||||
|
switch (key.EncryptionType)
|
||||||
|
{
|
||||||
|
case EncryptionType.RSA:
|
||||||
|
i.Context = Encryption.RSA.Decrypt(Convert.FromBase64String(i.Context), key.Key,
|
||||||
|
i.EncoderType);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
i.Context = Encryption.Generic.Encoders[(int)i.EncoderType]
|
||||||
|
.GetString(Convert.FromBase64String(i.Context));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.Files.Length > 0)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < i.Files.Length; j++)
|
||||||
|
{
|
||||||
|
if (i.Files[j].Key == 0)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(i.Files[j].Name))
|
||||||
|
{
|
||||||
|
i.Files[j].Name = "";
|
||||||
|
}
|
||||||
|
else i.Files[j].Name = Encryption.Generic.Encoders[(int)i.Files[j].NameEncoder]
|
||||||
|
.GetString(Convert.FromBase64String(i.Files[j].Name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LocalKeyInfo key = Server.EncryptionHandler.GetKey(i.Files[j].NameKey);
|
||||||
|
switch (key.EncryptionType)
|
||||||
|
{
|
||||||
|
case EncryptionType.RSA:
|
||||||
|
i.Files[j].Name = Encryption.RSA.Decrypt(Convert.FromBase64String(i.Context), key.Key,
|
||||||
|
i.Files[j].NameEncoder);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
i.Files[j].Name = Encryption.Generic.Encoders[(int)i.Files[j].NameEncoder]
|
||||||
|
.GetString(Convert.FromBase64String(i.Context));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (PublicMessage i in data.Messages)
|
||||||
|
{
|
||||||
|
var ff = new List<long>();
|
||||||
|
List<SocketFile> sf = new();
|
||||||
|
foreach (pFile v in i.Files)
|
||||||
|
{
|
||||||
|
sf.Add(new()
|
||||||
|
{
|
||||||
|
ID = v.ID,
|
||||||
|
Size = v.Size,
|
||||||
|
Name = v.Name,
|
||||||
|
Encoder = v.Encoder,
|
||||||
|
NameEncoder = v.NameEncoder,
|
||||||
|
Key = v.Key,
|
||||||
|
NameKey = v.NameKey,
|
||||||
|
Channel = v.Channel,
|
||||||
|
Server = Server
|
||||||
|
});
|
||||||
|
ff.Add(v.ID);
|
||||||
|
}
|
||||||
|
mmmm.Add(new()
|
||||||
|
{
|
||||||
|
Server = Server,
|
||||||
|
ID = i.ID,
|
||||||
|
ChannelID = ID,
|
||||||
|
AuthorID = i.AuthorID,
|
||||||
|
TimeStamp = i.TimeStamp,
|
||||||
|
Context = i.Context,
|
||||||
|
EncryptionKey = i.EncryptionKey,
|
||||||
|
EncoderType = i.EncoderType,
|
||||||
|
FileIDs = ff.ToArray(),
|
||||||
|
_Files = sf
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return await Task.FromResult(mmmm.AsReadOnly());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw data?.Error switch
|
||||||
|
{
|
||||||
|
ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"),
|
||||||
|
ErrorCode.ServerError => new Exception($"Error from server: {data.ErrorMessage}"),
|
||||||
|
ErrorCode.InvalidHeader => new Exception(data.ErrorMessage),
|
||||||
|
ErrorCode.MissingHeader => new Exception("The header sent to the server was not found. This may be because you app is couropt or you are using the wron API version"),
|
||||||
|
ErrorCode.Forbidden => new Exception("You are not allowed to do this request"),
|
||||||
|
_ => new Exception(data?.Error.ToString()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Stream> GetPicture(CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.ChannelIcons) + ID.ToString());
|
||||||
|
if (!isc) await Server.GetFromServer($"SocketChannel/GetPicture", Server.Storage.GetStorageDirectory(StorageDirectory.ChannelIcons) + ID.ToString(), CancellationToken,
|
||||||
|
new KeyValuePair<string, string?>("id", ID.ToString()));
|
||||||
|
return Server.Storage.GetResourceStream(StorageDirectory.ChannelIcons, ID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SocketCategory> GetParent()
|
||||||
|
{
|
||||||
|
if (CategoryID != -1 && RawParent is null)
|
||||||
|
{
|
||||||
|
RawParent = await Server.GetCategory<SocketCategory>(CategoryID, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawParent!;
|
||||||
|
}
|
||||||
|
public ChannelType Type { get; internal set; }
|
||||||
|
public DateTime Epoch { get; internal set; }
|
||||||
|
public string Name { get; internal set; }
|
||||||
|
public string Description { get; internal set; }
|
||||||
|
public Task<RoleOveride[]> GetRoleOverides()
|
||||||
|
{
|
||||||
|
if (RawRoleOverides is null)
|
||||||
|
{
|
||||||
|
RawRoleOverides = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(RawRoleOverides!.ToArray());
|
||||||
|
}
|
||||||
|
public Task<UserOveride[]> GetUserOveride()
|
||||||
|
{
|
||||||
|
if (RawUserOverides is null)
|
||||||
|
{
|
||||||
|
RawUserOverides = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(RawUserOverides!.ToArray());
|
||||||
|
}
|
||||||
|
public long TitleEncryptionKey { get; internal set; }
|
||||||
|
public long DescriptionEncryptionKey { get; internal set; }
|
||||||
|
public long[] EncryptionKeys { get; internal set; }
|
||||||
|
public EncoderType TitleEncoderType { get; internal set; }
|
||||||
|
public EncoderType DescriptionEncoderType { get; internal set; }
|
||||||
|
public EncoderType[] EncoderTypes { get; internal set; }
|
||||||
|
}
|
28
Luski.net/Structures/Public/SocketFile.cs
Normal file
28
Luski.net/Structures/Public/SocketFile.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class SocketFile
|
||||||
|
{
|
||||||
|
public required PublicServer Server { get; init; }
|
||||||
|
public required long ID { get; init; }
|
||||||
|
public required long Channel { get; init; }
|
||||||
|
public required string Name { get; init; }
|
||||||
|
public required EncoderType Encoder { get; init; }
|
||||||
|
public required EncoderType NameEncoder { get; init; }
|
||||||
|
public required long Key { get; init; }
|
||||||
|
public required long NameKey { get; init; }
|
||||||
|
public required long Size { get; init; }
|
||||||
|
|
||||||
|
public async Task<Stream> GetCache(CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
string d = Server.Storage.GetStorageDirectory(StorageDirectory.Files) + Channel.ToString() + "-" + ID.ToString();
|
||||||
|
bool isc = System.IO.File.Exists(d);
|
||||||
|
if (!isc) await Server.GetFromServer($"socketfile?id={ID}&channel={Channel}", d, CancellationToken);
|
||||||
|
return Server.Storage.GetResourceStream(StorageDirectory.Files, Channel.ToString() + "-" + ID.ToString());
|
||||||
|
}
|
||||||
|
}
|
49
Luski.net/Structures/Public/SocketMessage.cs
Normal file
49
Luski.net/Structures/Public/SocketMessage.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class SocketMessage
|
||||||
|
{
|
||||||
|
public PublicServer Server { get; init; } = default!;
|
||||||
|
public long ID { get; internal set; }
|
||||||
|
public long ChannelID { get; internal set; }
|
||||||
|
public long AuthorID { get; internal set; }
|
||||||
|
public long TimeStamp { get; internal set; }
|
||||||
|
public string Context { get; internal set; }
|
||||||
|
public long EncryptionKey { get; internal set; }
|
||||||
|
public long[] FileIDs { get; internal set; }
|
||||||
|
public EncoderType EncoderType { get; internal set; }
|
||||||
|
private SocketChannel? RawParent;
|
||||||
|
private IUser? au;
|
||||||
|
internal List<SocketFile> _Files = new();
|
||||||
|
|
||||||
|
public IReadOnlyList<SocketFile> Files
|
||||||
|
{
|
||||||
|
get => _Files.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SocketChannel> GetParent(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (RawParent is null)
|
||||||
|
{
|
||||||
|
RawParent = await Server.GetChannel<SocketChannel>(ChannelID, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IUser> GetAuthor(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (au is null)
|
||||||
|
{
|
||||||
|
if (AuthorID == Server.User.Id) au = Server.User;
|
||||||
|
else au = await Server.GetUser<SocketUser>(ChannelID, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return au;
|
||||||
|
}
|
||||||
|
}
|
64
Luski.net/Structures/Public/SocketUser.cs
Normal file
64
Luski.net/Structures/Public/SocketUser.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Luski.net.Classes;
|
||||||
|
using Luski.net.Enums;
|
||||||
|
using Luski.net.Interfaces;
|
||||||
|
using Luski.net.JsonTypes;
|
||||||
|
using Luski.net.JsonTypes.BaseTypes;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class SocketUser : IUser
|
||||||
|
{
|
||||||
|
public PublicServer Server { get; init; } = default!;
|
||||||
|
public long Id { get; init; } = default!;
|
||||||
|
public string DisplayName { get; init; } = default!;
|
||||||
|
public virtual UserStatus Status { get; internal set; } = default!;
|
||||||
|
public PictureType PictureType { get; init; } = default!;
|
||||||
|
public long[] RoleIds { get; init; } = default!;
|
||||||
|
private List<Role>? RawRoles = null;
|
||||||
|
|
||||||
|
public async Task<Role[]> GetRoles()
|
||||||
|
{
|
||||||
|
if (RawRoles is null)
|
||||||
|
{
|
||||||
|
RawRoles = new();
|
||||||
|
foreach (long r in RoleIds)
|
||||||
|
{
|
||||||
|
Role f = await Server.GetRole(r);
|
||||||
|
RawRoles.Add(f);
|
||||||
|
}
|
||||||
|
RawRoles.Sort(new RoleComparer());
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawRoles.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Stream> GetAvatar(CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
bool isc = System.IO.File.Exists(Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString());
|
||||||
|
if (!isc) await Server.GetFromServer($"socketuserprofile/Avatar/{Id}", Server.Storage.GetStorageDirectory(StorageDirectory.Avatars) + Id.ToString(), CancellationToken);
|
||||||
|
return Server.Storage.GetResourceStream(StorageDirectory.Avatars, Id.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<PublicKeyInfo[]> GetUserKeys(CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
UserKeysGetRequest data = Server.GetFromServer($"Keys/UserKeys/{Id}", UserKeysGetRequestContext.Default.UserKeysGetRequest, CancellationToken).Result;
|
||||||
|
List<PublicKeyInfo> pki = new();
|
||||||
|
foreach (UserKeyGetRequest key in data.keys)
|
||||||
|
{
|
||||||
|
pki.Add(new()
|
||||||
|
{
|
||||||
|
Id = key.id,
|
||||||
|
Owner = key.owner,
|
||||||
|
EncryptionType = key.encryption_type,
|
||||||
|
Data = Convert.FromBase64String(key.key_data)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Task.FromResult(pki.ToArray());
|
||||||
|
}
|
||||||
|
}
|
6
Luski.net/Structures/Public/UserOveride.cs
Normal file
6
Luski.net/Structures/Public/UserOveride.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace Luski.net.Structures.Public;
|
||||||
|
|
||||||
|
public class UserOveride
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
11
Luski.net/Structures/PublicKeyInfo.cs
Normal file
11
Luski.net/Structures/PublicKeyInfo.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using JacobTechEncryption.Enums;
|
||||||
|
|
||||||
|
namespace Luski.net.Structures;
|
||||||
|
|
||||||
|
public class PublicKeyInfo
|
||||||
|
{
|
||||||
|
public long Id { get; init; }
|
||||||
|
public byte[] Data { get; init; }
|
||||||
|
public long Owner { get; init; }
|
||||||
|
public EncryptionType EncryptionType { get; init; }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user