163 lines
6.0 KiB
C#
163 lines
6.0 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();
|
|
|
|
internal List<PublicServer> InternalFailedServers { get; } = new();
|
|
public IReadOnlyList<PublicServer> FailedServers => InternalFailedServers.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(InternalFailedServers, 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;
|
|
}
|
|
} |