using Luski.net.Enums; using Luski.net.Interfaces; using Luski.net.JsonTypes; using Luski.net.JsonTypes.BaseTypes; using Luski.net.JsonTypes.HTTP; using Luski.net.Sockets; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; namespace Luski.net; public sealed partial class Server { #pragma warning disable CA1822 // Mark members as static /// /// Creates an audio client for the you want to talk on /// /// The channel you want to talk on /// public IAudioClient CreateAudioClient(long channel_id) { // if (AudioClient != null) throw new Exception("audio client alread created"); SocketAudioClient client = new(channel_id, OnError); AudioClient = client; return client; } public async Task SendFriendResult(long user, bool answer) { FriendRequestResult json = await SendServer("FriendRequestResult", new FriendRequestResultOut() { Id = user, Result = answer }, FriendRequestResultOutContext.Default.FriendRequestResultOut, FriendRequestResultContext.Default.FriendRequestResult); if (json is not null && json.Error is null && json.ErrorMessage is null && answer && json.Channel is not null) { SocketDMChannel chan = await SocketChannel.GetChannel((long)json.Channel, SocketDMChannelContext.Default.SocketDMChannel); _ = chan.StartKeyProcessAsync(); chans.Add(chan); } else { throw new Exception(json?.Error.ToString()); } return SocketUserBase.GetUser(user, SocketRemoteUserContext.Default.SocketRemoteUser).Result; } public async Task SendFriendRequest(long user) { FriendRequestResult? json = await SendServer("FriendRequest", new FriendRequest() { Id = user, SubType = 0 }, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult); if (json.StatusCode != HttpStatusCode.Accepted) { if (json is not null && json.Error is not null) { switch ((ErrorCode)(int)json.Error) { case ErrorCode.InvalidToken: throw new Exception("Your current token is no longer valid"); case ErrorCode.ServerError: throw new Exception($"Error from server: {json.ErrorMessage}"); case ErrorCode.InvalidPostData: throw new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version"); case ErrorCode.Forbidden: throw new Exception("You already have an outgoing request or the persone is not real"); } } if (json is not null && json.Channel is not null) { SocketDMChannel chan = await SocketChannel.GetChannel((long)json.Channel, (JsonTypeInfo)SocketDMChannelContext.Default.SocketDMChannel); _ = chan.StartKeyProcessAsync(); chans.Add(chan); } } SocketRemoteUser b = await SocketUserBase.GetUser(user, SocketRemoteUserContext.Default.SocketRemoteUser); b.FriendStatus = FriendStatus.PendingOut; return b; } public async Task SendFriendRequest(string username, short tag) { FriendRequestResult json = await SendServer("FriendRequest", new FriendRequest() { Username = username, Tag = tag, SubType = 1 }, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult); if (json is not null && json.Error is not null) { throw (ErrorCode)(int)json.Error switch { ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"), ErrorCode.ServerError => new Exception("Error from server: " + json.ErrorMessage), ErrorCode.InvalidPostData => new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version"), ErrorCode.Forbidden => new Exception("You already have an outgoing request or the persone is not real"), _ => new Exception(JsonSerializer.Serialize(json)), }; } else if (json is not null && json.Channel is not null && json.Id is not null) { SocketDMChannel chan = await SocketChannel.GetChannel(json.Channel.Value, (JsonTypeInfo)SocketDMChannelContext.Default.SocketDMChannel); _ = chan.StartKeyProcessAsync(); chans.Add(chan); return await SocketUserBase.GetUser((long)json.Id, SocketRemoteUserContext.Default.SocketRemoteUser); } else throw new Exception("missing data from server"); } /// /// Sends the server a request to update the of you account /// /// The you want to set your status to /// public async Task UpdateStatus(UserStatus Status) { if (_user is null) throw new Exception("You must login to make a request"); IncomingHTTP? data = await SendServer("SocketUserProfile/Status", new Status() { UserStatus = Status }, StatusContext.Default.Status, IncomingHTTPContext.Default.IncomingHTTP); if (data.Error is not null && ((int)data.StatusCode < 200 || (int)data.StatusCode > 299)) { if (data?.ErrorMessage is not null) throw new Exception(data.ErrorMessage); if (data?.Error is not null) throw new Exception(((int)data.Error).ToString()); else throw new Exception("Something went worng"); } _user.Status = Status; return Task.CompletedTask; } public async Task ChangeChannel(long Channel) { if (_user is null) throw new Exception("You must login to make a request"); IncomingHTTP? data = await SendServer("ChangeChannel", new Channel() { Id = Channel }, ChannelContext.Default.Channel, IncomingHTTPContext.Default.IncomingHTTP); if (data.StatusCode != HttpStatusCode.Accepted) { if (data?.Error is not null) { switch (data.Error) { case ErrorCode.InvalidToken: throw new Exception("Your current token is no longer valid"); case ErrorCode.ServerError: throw new Exception("Error from server: " + data.ErrorMessage); } } else throw new Exception("Something went worng"); } _user.SelectedChannel = Channel; } public async Task SendMessage(string Message, long Channel, params JsonTypes.File[] Files) => (await GetChannel(Channel)).SendMessage(Message, Files); public void SetMultiThreadPercent(double num) { if (num < 1 || num > 100) throw new Exception("Number must be from 1 - 100"); Percent = num / 100; } public async Task GetMessage(long MessageId) => await SocketMessage.GetMessage(MessageId); public async Task GetUser(long UserID) => await SocketUserBase.GetUser(UserID, SocketRemoteUserContext.Default.SocketRemoteUser); public async Task GetChannel(long Channel) where TChannel : SocketChannel, new() { TChannel Return = new(); switch (Return) { case SocketDMChannel: Return = (await SocketChannel.GetChannel(Channel, SocketDMChannelContext.Default.SocketDMChannel) as TChannel)!; break; case SocketGroupChannel: Return = (await SocketChannel.GetChannel(Channel, SocketGroupChannelContext.Default.SocketGroupChannel) as TChannel)!; break; case SocketTextChannel: Return = (await SocketChannel.GetChannel(Channel, SocketTextChannelContext.Default.SocketTextChannel) as TChannel)!; break; case SocketChannel: Return = (await SocketChannel.GetChannel(Channel, SocketChannelContext.Default.SocketChannel) as TChannel)!; break; case null: throw new NullReferenceException(nameof(TChannel)); default: throw new Exception("Unknown channel type"); } return Return; } public SocketAppUser CurrentUser { get { if (_user is null) throw new Exception("You must Login first"); return _user; } } #pragma warning restore CA1822 // Mark members as static private void ServerOut_OnError(object? sender, WebSocketSharp.ErrorEventArgs e) { if (OnError is not null) OnError.Invoke(new Exception(e.Message)); } [Obsolete("Move to new Data layout")] internal static void SendServer(string data) { ServerOut?.Send(data); } internal static void SendServer(Tvalue Payload, JsonTypeInfo jsonTypeInfo) where Tvalue : IncomingWSS { ServerOut?.Send(JsonSerializer.Serialize(Payload, jsonTypeInfo)); } internal static HttpResponseMessage GetFromServer(string Path, params KeyValuePair[] Headers) { using HttpClient web = new(); web.Timeout = TimeSpan.FromSeconds(10); if (!login) web.DefaultRequestHeaders.Add("token", Token); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); return web.GetAsync($"https://{InternalDomain}/{API_Ver}/{Path}").Result; } internal static Task GetFromServer(string Path, string File, params KeyValuePair[] Headers) { using HttpClient web = new(); web.Timeout = TimeSpan.FromMinutes(10); if (!login) web.DefaultRequestHeaders.Add("token", Token); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); HttpResponseMessage Response = web.GetAsync($"https://{InternalDomain}/{API_Ver}/{Path}").Result; Stream stream = Response.Content.ReadAsStreamAsync().Result; using FileStream fs = System.IO.File.Create(File); stream.CopyTo(fs); return Task.CompletedTask; } internal static async Task GetFromServer(string Path, JsonTypeInfo Type, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() { HttpResponseMessage ServerResponce = GetFromServer(Path, Headers); if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync().Result, Type); if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; return temp; } internal static async Task SendServer(string Path, Tvalue Payload, JsonTypeInfo jsonTypeInfo, JsonTypeInfo ReturnjsonTypeInfo, params KeyValuePair[] Headers) where Tvalue : HTTPRequest where Tresult : IncomingHTTP, new() { using HttpClient web = new(); if (!login) web.DefaultRequestHeaders.Add("token", Token); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); HttpResponseMessage ServerResponce = web.PostAsJsonAsync($"https://{InternalDomain}/{API_Ver}/{Path}", Payload, jsonTypeInfo).Result; if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; Tresult error = new() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; if (string.IsNullOrWhiteSpace(ServerResponce.Content.ReadAsStringAsync().Result)) return error; try { Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync().Result, ReturnjsonTypeInfo); if (temp is null) return error; return temp; } catch { return error; } } internal static async Task SendServer(string Path, string File, JsonTypeInfo ReturnjsonTypeInfo, params KeyValuePair[] Headers) where Tresult : IncomingHTTP, new() { var fs = System.IO.File.OpenRead(File); try { using HttpClient web = new(); if (!login) web.DefaultRequestHeaders.Add("token", Token); web.Timeout = new TimeSpan(0, 10, 0); if (Headers is not null && Headers.Length > 0) foreach (KeyValuePair header in Headers) web.DefaultRequestHeaders.Add(header.Key, header.Value); HttpResponseMessage ServerResponce = web.PostAsync($"https://{InternalDomain}/{API_Ver}/{Path}", new StreamContent(fs)).Result; if (!ServerResponce.IsSuccessStatusCode) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with status code {(int)ServerResponce.StatusCode}:{ServerResponce.StatusCode}" }; try { Tresult? temp = JsonSerializer.Deserialize(ServerResponce.Content.ReadAsStreamAsync().Result, ReturnjsonTypeInfo); if (temp is null) return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; return temp; } catch { return new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" }; } } finally { fs.Close(); } } }