Luski.Net/Luski.net/Server.cs

299 lines
15 KiB
C#
Executable File

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
/// <summary>
/// Creates an audio client for the <paramref name="channel_id"/> you want to talk on
/// </summary>
/// <param name="ID">The channel <see cref="ITextChannel.ID"/> you want to talk on</param>
/// <returns><seealso cref="IAudioClient"/></returns>
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<SocketRemoteUser> 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<SocketRemoteUser> 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<SocketDMChannel>)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<SocketRemoteUser> 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<SocketDMChannel>)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");
}
/// <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)
{
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<Task> SendMessage(string Message, long Channel, params JsonTypes.File[] Files) => (await GetChannel<SocketTextChannel>(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<SocketMessage> GetMessage(long MessageId) => await SocketMessage.GetMessage(MessageId);
public async Task<SocketRemoteUser> GetUser(long UserID) => await SocketUserBase.GetUser(UserID, SocketRemoteUserContext.Default.SocketRemoteUser);
public async Task<TChannel> GetChannel<TChannel>(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>(Tvalue Payload, JsonTypeInfo<Tvalue> jsonTypeInfo) where Tvalue : IncomingWSS
{
ServerOut?.Send(JsonSerializer.Serialize(Payload, jsonTypeInfo));
}
internal static HttpResponseMessage GetFromServer(string Path, params KeyValuePair<string, string?>[] 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<string, string?> 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<string, string?>[] 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<string, string?> 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<Tresult> GetFromServer<Tresult>(string Path, JsonTypeInfo<Tresult> Type, params KeyValuePair<string, string?>[] 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<Tresult> SendServer<Tvalue, Tresult>(string Path, Tvalue Payload, JsonTypeInfo<Tvalue> jsonTypeInfo, JsonTypeInfo<Tresult> ReturnjsonTypeInfo, params KeyValuePair<string, string?>[] 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<string, string?> 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<Tresult> SendServer<Tresult>(string Path, string File, JsonTypeInfo<Tresult> ReturnjsonTypeInfo, params KeyValuePair<string, string?>[] 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<string, string?> 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();
}
}
}