using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; 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; public partial class PublicServer : Server { public List chans { get; } = new(); public List cats { get; } = new(); public List roles { 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 GetServer(string Domain, string API_Version, bool Secure = true) { DateTime dt = DateTime.UtcNow; Console.WriteLine("Connecting to public server '{0}' using API {1}.", Domain, API_Version); PublicServer s = new(Domain, API_Version, Secure); ServerInfo? si = null; try { si = await s.GetFromServer("socketserver", ServerInfoContext.Default.ServerInfo, 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, "Servers.json", true, LocalServerInfoContext.Default.LocalServerInfo); 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", ServerInfoContext.Default.ServerInfo, 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) throw; } s.Name = si.name; s.Description = si.description; s.wssurl = si.wssv4; s.ServerType = ServerType.Public; 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 async Task GetCategory(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("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 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 GetChannel(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("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 GetUser(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().FirstOrDefault()!; return temp; } while (true) { if (CanRequest) { user = await GetFromServer("socketuser", PublicSocketUserContext.Default.SocketUser, CancellationToken, new KeyValuePair("id", UserId.ToString())); break; } } if (user is null) throw new Exception("Server did not return a user"); if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId)) { foreach (IUser? p in poeople.Where(s => s.Id == UserId)) { poeople.Remove(p); } } 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; } /// /// Sends the server a request to update the of you account /// /// The you want to set your status to /// public async Task UpdateStatus(UserStatus Status, CancellationToken CancellationToken) { 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; private set; } public string Description { get; private set; } }