Luski.Net/Luski.net/API.cs

160 lines
5.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Threading;
using System.Threading.Tasks;
using Luski.net.Enums;
using Luski.Shared.PublicServers.V1.Enums;
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP;
namespace Luski.net;
public class API
{
[JsonIgnore]
public MainServer MainServer { get; internal set; }
public bool IsAnyServerLoggedin { get; internal set; }
public const string DefaultVersion = "v1";
internal List<string> Versions = new()
{
DefaultVersion
};
public IReadOnlyList<string> SupportedVersions => Versions.AsReadOnly();
internal List<PublicServer> InternalServers { get; } = new();
public IReadOnlyList<PublicServer> LoadedServers => InternalServers.AsReadOnly();
private static HttpResponseMessage GetFromServer(string Domain, string ApiVersion, bool Secure, string Path, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers)
{
using HttpClient web = new();
web.Timeout = TimeSpan.FromSeconds(10);
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($"{(Secure ? "https" : "http" )}://{Domain}/{ApiVersion}/{Path}", cancellationToken: CancellationToken).Result;
}
private static Task<Tresult> GetFromServer<Tresult>(string Domain, string ApiVersion, bool Secure, string Path, JsonTypeInfo<Tresult> Type, CancellationToken CancellationToken, params KeyValuePair<string, string?>[] Headers) where Tresult : STC, new()
{
HttpResponseMessage ServerResponce = GetFromServer(Domain, ApiVersion, Secure, Path, CancellationToken, Headers);
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 Task.FromResult(new Tresult() { StatusCode = ServerResponce.StatusCode, Error = ErrorCode.ServerError, ErrorMessage = $"Server responded with empty data" });
return Task.FromResult(temp);
}
public Task<ServerInfoSTC> GetServerInfo(string Domain, string Version = DefaultVersion,
bool Secure = true)
{
ServerInfoSTC? si = GetFromServer(Domain, Version, Secure, "socketserver", ServerInfoSTCContext.Default.ServerInfoSTC, CancellationToken.None).Result;
if (si is null) throw new Exception("Bad Response");
return Task.FromResult(si);
}
public Task<bool> TryGetServerInfo([NotNullWhen(true)]out ServerInfoSTC? si, string Domain, string Version = DefaultVersion,
bool Secure = true)
{
try
{
si = GetServerInfo(Domain, Version, Secure).Result;
return Task.FromResult(true);
}
catch (Exception e)
{
si = null;
return Task.FromResult(false);
}
}
public Task<bool> TryGetPublicServer(out PublicServer Server, string Domain, string Version = DefaultVersion,
bool Secure = true, bool GenerateEncryption = true, bool LogConsole = false)
{
try
{
Task<PublicServer> result = GetPublicServer(Domain, Version, Secure, GenerateEncryption, LogConsole);
Task.WaitAll(result);
Server = result.Result;
return Task.FromResult(true);
}
catch (Exception e)
{
if (!e.Message.Contains("Connection refused")) Console.WriteLine(e);
Server = null!;
return Task.FromResult(false);
}
}
public async Task<PublicServer> GetPublicServer(string Domain, string Version = DefaultVersion, bool Secure = true, bool GenerateEncryption = true, bool LogConsole = false)
{
PublicServer s;
try
{
IEnumerable<PublicServer> isl = InternalServers.Where(a => (a.Domain == Domain && a.ApiVersion == Version));
if (isl.Any()) return isl.First();
s = await PublicServer.GetServer(Domain, Version, Secure, GenerateEncryption, LogConsole);
}
catch (Exception e)
{
Console.WriteLine("Failed to connect to public server '{0}' using API {1}. No alternate server was found.", Domain, Version);
throw;
}
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)
{
IsAnyServerLoggedin = true;
}
else
{
s.Token = null;
s.Error = null;
}
}
}
catch
{
}
InternalServers.Add(s);
return s;
}
public MainServer GetMainServer(string Domain, string Version = DefaultVersion)
{
DateTime dt = DateTime.UtcNow;
Console.WriteLine("Conecting to main server '{0}' using API {1}.", Domain, Version);
MainServer = new(Domain, Version)
{
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;
}
}