Luski.Net/Luski.net/PublicServer.cs

920 lines
34 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JacobTechEncryption;
using JacobTechEncryption.Enums;
using Luski.net.Enums;
using Luski.net.Interfaces;
using Luski.net.JsonTypes;
using Luski.net.JsonTypes.HTTP;
using Luski.net.Structures;
using Luski.net.Structures.Public;
using Luski.Shared.PublicServers.V1.ClientToServer.HTTP;
using Luski.Shared.PublicServers.V1.Enums;
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
using Luski.Shared.PublicServers.V1.Shared;
using Role = Luski.net.Structures.Public.Role;
using SocketUser = Luski.net.Structures.Public.SocketUser;
namespace Luski.net;
public partial class PublicServer : Server
{
public event Func<SocketMessage, Task>? MessageReceived;
public event Func<UserStatus, SocketUser, Task>? StatusUpdate;
public event Func<bool, Role, Task>? RoleEvent;
public event Func<Role, Task>? RoleDeleted;
public event Func<Role, IUser[], IUser[], Task>? RoleMemberEvent;
public PictureType PictureType { get; private set; }
public List<SocketChannel> chans { get; } = new();
public List<SocketCategory> cats { get; } = new();
public List<Role> roles { get; } = new();
public List<RoleOverride> roleso { get; } = new();
public SocketAppUser User { get; private set; } = null!;
private PublicServer(string Domain, string API_Version, bool Secure = true) :
base(Domain, API_Version, Secure)
{ }
internal static async Task<PublicServer> GetServer(List<PublicServer> Failed, string Domain, string API_Version, bool Secure = true, bool GenerateEncryption = true, bool LogConsole = false)
{
DateTime dt = DateTime.UtcNow;
Console.WriteLine("Connecting to public server '{0}' using API {1}.", Domain, API_Version);
PublicServer s = new(Domain, API_Version, Secure);
s.PrintServerMessages = LogConsole;
if (GenerateEncryption)
{
Thread t = new(_ =>
{
s.EncryptionHandler.GenerateKeys();
});
t.Start();
}
ServerInfoSTC? si = null;
try
{
si = await s.GetFromServer("socketserver", ServerInfoSTCContext.Default.ServerInfoSTC, CancellationToken.None);
s.EncryptionHandler.ServerPublicKey = await (await new HttpClient()
.GetAsync($"{(s.Secure ? "https" : "http")}://{s.Domain}/{s.ApiVersion}/Keys/PublicKey"))
.Content
.ReadAsStringAsync();
}
catch (Exception e)
{
LocalServerInfo ServerListing = s.Storage.GetJson(StorageDirectory.ServerInfo, "server.json", true,
LocalServerInfoContext.Default.LocalServerInfo);
s.Name = ServerListing.Name;
s.Description = ServerListing.Description;
s.PictureType = ServerListing.PictureType;
if (ServerListing.AlternateServers.Length > 0)
{
Console.WriteLine("Failed to connect to public server '{0}' using API {1}. Attempting to connect to alternate servers.", Domain, API_Version);
foreach (ServerData Server in ServerListing.AlternateServers)
{
s.Secure = Server.Secure;
s.Domain = Server.DomainAndPort;
try
{
si = await s.GetFromServer("socketserver", ServerInfoSTCContext.Default.ServerInfoSTC, CancellationToken.None);
s.EncryptionHandler.ServerPublicKey = await (await new HttpClient()
.GetAsync($"{(s.Secure ? "https" : "http")}://{s.Domain}/{s.ApiVersion}/Keys/PublicKey"))
.Content
.ReadAsStringAsync();
Console.WriteLine("Public server '{0}' connection restored by alternate server '{1}' using API {2}.", Domain, s.Domain, API_Version);
break;
}
catch
{
// ignored
}
}
}
if (si is null)
{
Failed.Add(s);
throw;
}
}
s.Storage.SetJson(StorageDirectory.ServerInfo, "server.json", new()
{
AlternateServers = Array.Empty<ServerData>(),
PictureType = si.PictureType,
Name = si.Name,
Description = si.Description
},
LocalServerInfoContext.Default.LocalServerInfo);
s.Name = si.Name;
s.PictureType = si.PictureType;
s.Description = si.Description;
s.wssurl = si.WSSv4Address;
s.ServerType = ServerType.Public;
s.OwnerID = si.Owner;
Console.WriteLine("Connected to public server '{0}' using API {1} in {4}.\nServer Name: {2}\nServer Description: {3}", Domain, API_Version, s.Name, s.Description, DateTime.UtcNow.Subtract(dt).ToString("g"));
return s;
}
public long OwnerID { get; private set; } = 0;
public async Task<TCategory> GetCategory<TCategory>(long id, CancellationToken CancellationToken) where TCategory : SocketCategory, new()
{
CategorySTC 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", CategorySTCContext.Default.CategorySTC, 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;
if (request.DescriptionEncryptionKey != 0)
deckey = EncryptionHandler.GetKey(request.DescriptionEncryptionKey);
else deckey = new()
{
EncryptionType = EncryptionType.None,
Key = string.Empty
};
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;
if (request.TitleEncryptionKey != 0)
nkey = EncryptionHandler.GetKey(request.TitleEncryptionKey);
else nkey = new()
{
EncryptionType = EncryptionType.None,
Key = string.Empty
};
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))
};
List<Color> cols = new();
if (request.ColorType == ColorType.Full)
{
Color nc = new(request.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < request.Color.Length - 7; i+=8)
{
cols.Add(new(request.Color[i..(i+8)]));
}
}
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.RoleOverrides,
UserOverides = request.UserOverrides,
TitleEncoderType = request.TitleEncoderType,
TitleEncryptionKey = request.TitleEncryptionKey,
Server = this,
ColorType = request.ColorType,
Colors = cols.ToArray()
};
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];
RoleSTC s = await GetFromServer("SocketRole?id=" + id.ToString(), RoleSTCContext.Default.RoleSTC, CancellationToken.None);
List<Color> cols = new();
if (s.ColorType == ColorType.Full)
{
Color nc = new(s.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < s.Color.Length - 7; i+=8)
{
cols.Add(new(s.Color[i..(i+8)]));
}
}
Role role = new()
{
Server = this,
ID = s.ID,
ColorType = s.ColorType,
Colors = cols.ToArray(),
Description = s.Description,
DisplayName = s.DisplayName,
MembersListID = s.Members,
Index = s.Index,
ServerPermissions = s.ServerPermissions
};
roles.Add(role);
return role;
}
public async Task<Role[]> GetRoles()
{
RolesSTC s = await GetFromServer("SocketRole/GetAll", RolesSTCContext.Default.RolesSTC, CancellationToken.None);
roles.Clear();
foreach (var ServerRole in s.Roles)
{
List<Color> cols = new();
if (ServerRole.ColorType == ColorType.Full)
{
Color nc = new(ServerRole.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < ServerRole.Color.Length - 7; i+=8)
{
cols.Add(new(ServerRole.Color[i..(i+8)]));
}
}
roles.Add(new Role()
{
Server = this,
ID = ServerRole.ID,
ColorType = ServerRole.ColorType,
Colors = cols.ToArray(),
Description = ServerRole.Description,
DisplayName = ServerRole.DisplayName,
MembersListID = ServerRole.Members,
Index = ServerRole.Index,
ServerPermissions = ServerRole.ServerPermissions
});
}
return roles.ToArray();
}
public async Task<SocketMessage> SendMessage<TChannel>(TChannel channel, string msg, SocketMessage? ReplyTo = null,
ServerProfile? FakeProfile = null, params string[] files) where TChannel : SocketChannel, new()
{
List<SocketFile> lll = new();
foreach (var f in files)
{
lll.Add(await UploadFile(f));
}
return await SendMessage(channel, msg, ReplyTo, FakeProfile, lll.ToArray());
}
public async Task<SocketFile> UploadFile(string File)
{
FileInfo FI = new FileInfo(File);
ServerFileInfoSTC res = await SendServer("SocketFile", File, ServerFileInfoSTCContext.Default.ServerFileInfoSTC,
CancellationToken.None,
new("name_encoder", "0"),
new("encoder", "0"),
new("name_encryption", "0"),
new("encryption", "0"),
new("name", Convert.ToBase64String(Encoding.UTF8.GetBytes(FI.Name))));
if (res.ErrorMessage is not null || res.Error is not null)
{
Console.WriteLine("Error {0}: {1}", (res.Error is null ? "Unknown" : res.Error.Value), res.ErrorMessage);
}
return new SocketFile()
{
ID = res.ID,
Encoder = EncoderType.UTF8,
Key = 0,
Name = FI.Name,
NameEncoder = EncoderType.UTF8,
NameKey = 0,
Server = this,
Size = FI.Length
};
}
public async Task<SocketMessage> SendMessage<TChannel>(TChannel channel, string msg, SocketMessage? ReplyTo = null,
ServerProfile? FakeProfile = null, params SocketFile[] files) where TChannel : SocketChannel, new()
{
string bc = "";
if (channel.EncryptionKeys[0] == 0)
{
if (!string.IsNullOrEmpty(msg))
bc = Convert.ToBase64String(Encryption.Generic.Encoders[(int)channel.EncoderTypes[0]].GetBytes(msg));
}
else
{
LocalKeyInfo key = channel.Server.EncryptionHandler.GetKey(channel.EncryptionKeys[0]);
bc = Convert.ToBase64String(key.EncryptionType switch
{
EncryptionType.RSA => Encryption.RSA.Encrypt(msg, key.Key, channel.EncoderTypes[0]),
_ => Encryption.AES.Encrypt(Encryption.Generic.Encoders[(int)channel.EncoderTypes[0]].GetBytes(msg), key.Key)
});
}
List<long> lll = new();
foreach (var f in files)
{
lll.Add(f.ID);
}
MessageCTS pcsm = new()
{
Files = lll.ToArray(),
ChannelID = channel.ID,
EncryptionKey = channel.EncryptionKeys[0],
Encoding = channel.EncoderTypes[0],
Base64Context = bc,
};
if (FakeProfile is not null)
{
pcsm.Profile = FakeProfile.ID;
}
MessageSTC smsg = await channel.Server.SendServer("socketmessage", pcsm,
MessageCTSContext.Default.MessageCTS, MessageSTCContext.Default.MessageSTC,
CancellationToken.None);
List<long> fl = new();
foreach (var VARIABLE in smsg.Files)
{
fl.Add(VARIABLE.ID);
}
SocketMessage sm = new()
{
ID = smsg.ID,
AuthorID = smsg.AuthorID,
ProfileID = smsg.ProfileID,
ChannelID = channel.ID,
TimeStamp = smsg.Timestamp,
Context = msg,
EncoderType = smsg.EncoderType,
EncryptionKey = smsg.EncryptionKey,
FileIDs = fl.ToArray(),
Server = channel.Server,
_Files = files.ToList()
};
return sm;
}
public async Task<Role> CreateRole(RolePostCTS Req)
{
RoleSTC res = await SendServer("SocketRole",
Req,
RolePostCTSContext.Default.RolePostCTS,
RoleSTCContext.Default.RoleSTC,
CancellationToken.None);
List<Color> cols = new();
if (res.ColorType == ColorType.Full)
{
Color nc = new(res.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < res.Color.Length - 7; i+=8)
{
cols.Add(new(res.Color[i..(i+8)]));
}
}
Role role = new Role()
{
DisplayName = res.DisplayName,
ServerPermissions = res.ServerPermissions,
Description = res.Description,
Index = res.Index,
MembersListID = res.Members,
ColorType = res.ColorType,
Colors = cols.ToArray(),
Server = this,
ID = res.ID
};
roles.Add(role);
return role;
}
public async Task<Role> EditRole(Role role, string? Name = null, string? Description = null, int? Index = null, ServerPermission? Permissions = null, string? Color = null, ColorType? colorType = null)
{
RoleSTC res = await SendServerPatch("SocketRole",
new()
{
ID = role.ID,
Description = Description,
DisplayName = Name,
Index = Index,
ColorType = colorType,
Color = Color,
ServerPermissions = Permissions
},
RolePatchCTSContext.Default.RolePatchCTS,
RoleSTCContext.Default.RoleSTC,
CancellationToken.None);
if (Permissions is not null) role.ServerPermissions = res.ServerPermissions;
if (Description is not null) role.Description = res.Description;
if (Index is not null) role.Index = res.Index;
if (Name is not null) role.DisplayName = res.DisplayName;
if (Color is not null) role.Colors = new []{new Color(res.Color)};
if (colorType is not null) role.ColorType = res.ColorType;
return role;
}
public async Task<Role> EditRoleMembers(Role r)
{
return r;
}
public async Task<TChannel> GetChannel<TChannel>(long id, CancellationToken CancellationToken) where TChannel : SocketChannel, new()
{
ChannelSTC 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", ChannelSTCContext.Default.ChannelSTC, 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;
if (request.DescriptionEncryptionKey != 0)
deckey = EncryptionHandler.GetKey(request.DescriptionEncryptionKey);
else deckey = new()
{
EncryptionType = EncryptionType.None,
Key = string.Empty
};
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;
if (request.TitleEncryptionKey != 0)
nkey = EncryptionHandler.GetKey(request.TitleEncryptionKey);
else nkey = new()
{
EncryptionType = EncryptionType.None,
Key = string.Empty
};
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))
};
List<Color> cols = new();
if (request.ColorType == ColorType.Full)
{
Color nc = new(request.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < request.Color.Length - 7; i+=8)
{
cols.Add(new(request.Color[i..(i+8)]));
}
}
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,
RoleOverrides = request.RoleOverrides,
UserOverrides = request.UserOverrides,
Type = request.Type,
TitleEncoderType = request.TitleEncoderType,
TitleEncryptionKey = request.TitleEncryptionKey,
PictureType = request.PictureType,
Server = this,
ColorType = request.ColorType,
Colors = cols.ToArray()
};
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<SocketChannel> MakeChannel(SocketCategory parent, string Name, string Decription)
{
ChannelSTC res = await SendServer(
"SocketChannel",
new ChannelPostCTS()
{
Name = Convert.ToBase64String(Encoding.UTF8.GetBytes(Name)),
Description = Convert.ToBase64String(Encoding.UTF8.GetBytes(Decription)),
EncoderTypes = new[] { EncoderType.UTF16 },
EncryptionKeys = new long[] { 0 },
DescriptionEncoderType = EncoderType.UTF8,
TitleEncoderType = EncoderType.UTF8,
Parent = parent.ID,
DescriptionEncryptionKey = 0,
TitleEncryptionKey = 0,
RoleOverrides = Array.Empty<RoleOverrideCTS>(),
UserOverrides = Array.Empty<UserOverrideCTS>(),
Type = ChannelType.TextAndVoice,
Color = "FFFFFFFF",
PictureType = PictureType.none
},
ChannelPostCTSContext.Default.ChannelPostCTS,
ChannelSTCContext.Default.ChannelSTC,
CancellationToken.None);
List<Color> cols = new();
if (res.ColorType == ColorType.Full)
{
Color nc = new(res.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < res.Color.Length - 7; i+=8)
{
cols.Add(new(res.Color[i..(i+8)]));
}
}
return new SocketChannel()
{
ID = res.ID,
CategoryID = res.Parent,
Description = Decription,
DescriptionEncoderType = res.DescriptionEncoderType,
DescriptionEncryptionKey = res.DescriptionEncryptionKey,
EncoderTypes = res.EncoderTypes,
EncryptionKeys = res.EncryptionKeys,
Epoch = res.Epoch,
Name = Name,
RoleOverrides = res.RoleOverrides,
UserOverrides = res.UserOverrides,
Type = res.Type,
TitleEncoderType = res.TitleEncoderType,
TitleEncryptionKey = res.TitleEncryptionKey,
PictureType = res.PictureType,
Server = this,
ColorType = res.ColorType,
Colors = cols.ToArray()
};
}
public async Task<Tuser> GetUser<Tuser>(long UserId, CancellationToken CancellationToken) where Tuser : SocketUser, new()
{
SocketUserSTC 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",
SocketUserSTCContext.Default.SocketUserSTC,
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 (typeof(Tuser).FullName == typeof(SocketUser).FullName)
{
u = new()
{
Server = this,
Id = user.ID,
ServerProfile = user.ServerProfile,
RoleIds = user.RoleIds,
Status = user.Status
};
}
else
{
u = (new SocketAppUser()
{
Server = this,
Id = user.ID,
ServerProfile = user.ServerProfile,
SelectedChannel = user.SelectedChannel,
RoleIds = user.RoleIds,
Status = user.Status,
} as Tuser)!;
}
poeople.Add(u);
return u;
}
public Tuser GetUser<Tuser>(long UserId) where Tuser : SocketUser, new()
{
SocketUserSTC 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 = GetFromServerRaw("socketuser",
SocketUserSTCContext.Default.SocketUserSTC,
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 (typeof(Tuser).FullName == typeof(SocketUser).FullName)
{
u = new()
{
Server = this,
Id = user.ID,
ServerProfile = user.ServerProfile,
RoleIds = user.RoleIds,
Status = user.Status
};
}
else
{
u = (new SocketAppUser()
{
Server = this,
Id = user.ID,
ServerProfile = user.ServerProfile,
SelectedChannel = user.SelectedChannel,
RoleIds = user.RoleIds,
Status = user.Status,
} as Tuser)!;
}
poeople.Add(u);
return u;
}
public async Task<ServerProfile> GetProfile(long ProfileId, CancellationToken CancellationToken)
{
ProfileSTC user;
if (profiles.Count > 0 && profiles.Any(s => s.ID == ProfileId))
{
ServerProfile temp = profiles.Where(s => s.ID == ProfileId).FirstOrDefault()!;
return temp;
}
while (true)
{
if (CanRequest)
{
user = await GetFromServer("socketprofile",
ChannelProfileSTCContext.Default.ProfileSTC,
CancellationToken,
new KeyValuePair<string, string?>("id", ProfileId.ToString()));
break;
}
}
if (user is null) throw new Exception("Server did not return a user");
if (profiles.Count > 0 && profiles.Any(s => s.ID == ProfileId))
{
_ = profiles.RemoveAll(s => s.ID == ProfileId);
}
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}");
}
Color[]? colss = null;
if (user.Color is not null)
{
List<Color> cols = new();
if (user.ColorType == ColorType.Full)
{
Color nc = new(user.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < user.Color.Length - 7; i+=8)
{
cols.Add(new(user.Color[i..(i+8)]));
}
}
colss = cols.ToArray();
}
ServerProfile u = new()
{
Server = this,
ID = user.ID,
DisplayName = user.DisplayName,
PictureType = user.PictureType,
Controllers = user.Controllers,
RoleControllers = user.RoleControllers,
ColorType = user.ColorType,
Color = colss
};
profiles.Add(u);
return u;
}
public async Task<ServerProfile[]> GetMyProfiles(CancellationToken CancellationToken)
{
ProfileListSTC Prof;
while (true)
{
if (CanRequest)
{
Prof = await GetFromServer("socketprofile/myprofiles",
ProfileListSTCContext.Default.ProfileListSTC,
CancellationToken);
break;
}
}
if (Prof is null) throw new Exception("Server did not return a Profile List");
List<ServerProfile> profiles_ = new();
foreach (ProfileSTC user in Prof.Profiles)
{
if (profiles.Count > 0 && profiles.Any(s => s.ID == user.ID))
{
_ = profiles.RemoveAll(s => s.ID == user.ID);
}
if (user is null || user.Error is not null)
{
string error = "Profile 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 profile information\n{error}");
}
Color[]? colss = null;
if (user.Color is not null)
{
List<Color> cols = new();
if (user.ColorType == ColorType.Full)
{
Color nc = new(user.Color);
cols.Add(nc);
}
else
{
for (int i = 0; i < user.Color.Length - 7; i+=8)
{
cols.Add(new(user.Color[i..(i+8)]));
}
}
colss = cols.ToArray();
}
ServerProfile u = new()
{
Server = this,
ID = user.ID,
DisplayName = user.DisplayName,
PictureType = user.PictureType,
Controllers = user.Controllers,
RoleControllers = user.RoleControllers,
ColorType = user.ColorType,
Color = colss
};
profiles_.Add(u);
profiles.Add(u);
}
return profiles_.ToArray();
}
/// <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)
{
STC? data = await SendServer("SocketUserProfile/Status", new StatusUpdateCTS() { Status = Status }, StatusUpdateCTSContext.Default.StatusUpdateCTS, STCContext.Default.STC, 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; private set; }
public string Description { get; private set; }
}