LANCommander/LANCommander.SDK/Client.cs

367 lines
12 KiB
C#
Raw Normal View History

using LANCommander.SDK;
using LANCommander.SDK.Models;
using Microsoft.Extensions.Logging;
2023-01-05 02:31:02 +00:00
using RestSharp;
using System;
using System.Collections.Generic;
2023-01-07 04:12:03 +00:00
using System.ComponentModel;
using System.IO;
2023-01-05 02:31:02 +00:00
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
2023-01-05 02:31:02 +00:00
using System.Threading.Tasks;
namespace LANCommander.SDK
2023-01-05 02:31:02 +00:00
{
public class Client
2023-01-05 02:31:02 +00:00
{
private static readonly ILogger Logger;
2023-08-21 23:44:20 +00:00
private readonly RestClient ApiClient;
private AuthToken Token;
2023-01-05 02:31:02 +00:00
public Client(string baseUrl)
2023-01-05 02:31:02 +00:00
{
if (!String.IsNullOrWhiteSpace(baseUrl))
ApiClient = new RestClient(baseUrl);
2023-01-05 02:31:02 +00:00
}
private T PostRequest<T>(string route, object body)
{
var request = new RestRequest(route)
.AddJsonBody(body)
.AddHeader("Authorization", $"Bearer {Token.AccessToken}");
var response = ApiClient.Post<T>(request);
return response.Data;
}
private T GetRequest<T>(string route)
{
var request = new RestRequest(route)
.AddHeader("Authorization", $"Bearer {Token.AccessToken}");
var response = ApiClient.Get<T>(request);
return response.Data;
}
2023-01-07 04:12:03 +00:00
private string DownloadRequest(string route, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
{
route = route.TrimStart('/');
2023-01-07 04:12:03 +00:00
var client = new WebClient();
var tempFile = Path.GetTempFileName();
client.Headers.Add("Authorization", $"Bearer {Token.AccessToken}");
client.DownloadProgressChanged += (s, e) => progressHandler(e);
client.DownloadFileCompleted += (s, e) => completeHandler(e);
client.DownloadFileAsync(new Uri($"{ApiClient.BaseUrl}{route}"), tempFile);
2023-01-07 04:12:03 +00:00
return tempFile;
}
2023-04-08 01:08:03 +00:00
private TrackableStream StreamRequest(string route)
{
route = route.TrimStart('/');
var client = new WebClient();
var tempFile = Path.GetTempFileName();
client.Headers.Add("Authorization", $"Bearer {Token.AccessToken}");
var ws = client.OpenRead(new Uri($"{ApiClient.BaseUrl}{route}"));
2023-04-08 01:08:03 +00:00
return new TrackableStream(ws, true, Convert.ToInt64(client.ResponseHeaders["Content-Length"]));
}
public async Task<AuthToken> AuthenticateAsync(string username, string password)
{
var response = await ApiClient.ExecuteAsync<AuthResponse>(new RestRequest("/api/Auth", Method.POST).AddJsonBody(new AuthRequest()
{
UserName = username,
Password = password
}));
2023-01-06 00:35:58 +00:00
switch (response.StatusCode)
{
case HttpStatusCode.OK:
Token = new AuthToken
{
AccessToken = response.Data.AccessToken,
RefreshToken = response.Data.RefreshToken,
Expiration = response.Data.Expiration
};
return Token;
2023-01-06 00:35:58 +00:00
case HttpStatusCode.Forbidden:
case HttpStatusCode.BadRequest:
2023-03-14 06:10:02 +00:00
case HttpStatusCode.Unauthorized:
2023-01-06 00:35:58 +00:00
throw new WebException("Invalid username or password");
default:
throw new WebException("Could not communicate with the server");
}
}
public async Task<AuthToken> RegisterAsync(string username, string password)
{
var response = await ApiClient.ExecuteAsync<AuthResponse>(new RestRequest("/api/auth/register", Method.POST).AddJsonBody(new AuthRequest()
{
UserName = username,
Password = password
}));
switch (response.StatusCode)
{
case HttpStatusCode.OK:
Token = new AuthToken
{
AccessToken = response.Data.AccessToken,
RefreshToken = response.Data.RefreshToken,
Expiration = response.Data.Expiration
};
return Token;
case HttpStatusCode.BadRequest:
case HttpStatusCode.Forbidden:
case HttpStatusCode.Unauthorized:
throw new WebException(response.Data.Message);
default:
throw new WebException("Could not communicate with the server");
}
}
public async Task<bool> PingAsync()
{
var response = await ApiClient.ExecuteAsync(new RestRequest("/api/Ping", Method.GET));
return response.StatusCode == HttpStatusCode.OK;
}
public AuthToken RefreshToken(AuthToken token)
{
Logger.LogTrace("Refreshing token...");
2023-08-22 23:59:10 +00:00
var request = new RestRequest("/api/Auth/Refresh")
.AddJsonBody(token);
var response = ApiClient.Post<AuthResponse>(request);
if (response.StatusCode != HttpStatusCode.OK)
throw new WebException(response.ErrorMessage);
Token = new AuthToken
{
AccessToken = response.Data.AccessToken,
RefreshToken = response.Data.RefreshToken,
Expiration = response.Data.Expiration
};
return Token;
}
public bool ValidateToken()
{
return ValidateToken(Token);
}
public bool ValidateToken(AuthToken token)
{
Logger.LogTrace("Validating token...");
2023-08-21 23:44:20 +00:00
if (token == null)
2023-08-21 23:44:20 +00:00
{
Logger.LogTrace("Token is null!");
return false;
2023-08-21 23:44:20 +00:00
}
var request = new RestRequest("/api/Auth/Validate")
.AddHeader("Authorization", $"Bearer {token.AccessToken}");
if (String.IsNullOrEmpty(token.AccessToken) || String.IsNullOrEmpty(token.RefreshToken))
2023-08-21 23:44:20 +00:00
{
Logger.LogTrace("Token is empty!");
return false;
2023-08-21 23:44:20 +00:00
}
var response = ApiClient.Post(request);
2023-08-21 23:44:20 +00:00
var valid = response.StatusCode == HttpStatusCode.OK;
if (valid)
Logger.LogTrace("Token is valid!");
2023-08-21 23:44:20 +00:00
else
Logger.LogTrace("Token is invalid!");
2023-08-21 23:44:20 +00:00
return response.StatusCode == HttpStatusCode.OK;
}
public void UseToken(AuthToken token)
{
Token = token;
}
2023-01-05 02:31:02 +00:00
public IEnumerable<Game> GetGames()
{
return GetRequest<IEnumerable<Game>>("/api/Games");
}
2023-01-07 04:12:03 +00:00
public Game GetGame(Guid id)
{
return GetRequest<Game>($"/api/Games/{id}");
}
public GameManifest GetGameManifest(Guid id)
{
return GetRequest<GameManifest>($"/api/Games/{id}/Manifest");
}
public string DownloadGame(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
{
return DownloadRequest($"/api/Games/{id}/Download", progressHandler, completeHandler);
}
2023-04-08 01:08:03 +00:00
public TrackableStream StreamGame(Guid id)
{
return StreamRequest($"/api/Games/{id}/Download");
}
2023-01-07 04:12:03 +00:00
public string DownloadArchive(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
{
return DownloadRequest($"/api/Archives/Download/{id}", progressHandler, completeHandler);
2023-01-07 04:12:03 +00:00
}
public TrackableStream StreamRedistributable(Guid id)
{
return StreamRequest($"/api/Redistributables/{id}/Download");
}
2023-03-29 02:30:29 +00:00
public string DownloadSave(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
{
return DownloadRequest($"/api/Saves/Download/{id}", progressHandler, completeHandler);
}
public string DownloadLatestSave(Guid gameId, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
{
return DownloadRequest($"/api/Saves/DownloadLatest/{gameId}", progressHandler, completeHandler);
}
public GameSave UploadSave(string gameId, byte[] data)
{
Logger.LogTrace("Uploading save...");
2023-08-21 23:44:20 +00:00
2023-03-29 02:30:29 +00:00
var request = new RestRequest($"/api/Saves/Upload/{gameId}", Method.POST)
.AddHeader("Authorization", $"Bearer {Token.AccessToken}");
request.AddFile(gameId, data, gameId);
var response = ApiClient.Post<GameSave>(request);
2023-03-29 02:30:29 +00:00
return response.Data;
}
public string GetMediaUrl(Media media)
{
return (new Uri(ApiClient.BaseUrl, $"/api/Media/{media.Id}/Download?fileId={media.FileId}").ToString());
}
public string GetKey(Guid id)
{
Logger.LogTrace("Requesting key allocation...");
2023-08-21 23:44:20 +00:00
var macAddress = GetMacAddress();
var request = new KeyRequest()
{
GameId = id,
MacAddress = macAddress,
ComputerName = Environment.MachineName,
IpAddress = GetIpAddress(),
};
var response = PostRequest<Key>($"/api/Keys/Get", request);
return response.Value;
}
2023-01-28 23:18:41 +00:00
public string GetAllocatedKey(Guid id)
{
Logger.LogTrace("Requesting allocated key...");
2023-08-21 23:44:20 +00:00
2023-01-28 23:18:41 +00:00
var macAddress = GetMacAddress();
var request = new KeyRequest()
{
GameId = id,
MacAddress = macAddress,
ComputerName = Environment.MachineName,
IpAddress = GetIpAddress(),
};
var response = PostRequest<Key>($"/api/Keys/GetAllocated/{id}", request);
if (response == null)
return String.Empty;
return response.Value;
}
public string GetNewKey(Guid id)
{
Logger.LogTrace("Requesting new key allocation...");
2023-08-21 23:44:20 +00:00
var macAddress = GetMacAddress();
var request = new KeyRequest()
{
GameId = id,
MacAddress = macAddress,
ComputerName = Environment.MachineName,
IpAddress = GetIpAddress(),
};
var response = PostRequest<Key>($"/api/Keys/Allocate/{id}", request);
if (response == null)
return String.Empty;
return response.Value;
}
public User GetProfile()
{
Logger.LogTrace("Requesting player's profile...");
return GetRequest<User>("/api/Profile");
}
public string ChangeAlias(string alias)
{
Logger.LogTrace("Requesting to change player alias...");
var response = PostRequest<object>("/api/Profile/ChangeAlias", alias);
return alias;
}
private string GetMacAddress()
{
return NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)
.Select(nic => nic.GetPhysicalAddress().ToString())
.FirstOrDefault();
}
private string GetIpAddress()
{
return Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();
}
2023-01-05 02:31:02 +00:00
}
}