JD2022-TU1/main/tools/services/JD.LocalizationExport.Service/Implementation/Server/GameServerClient.cs

147 lines
7.3 KiB
C#

using System;
using System.Threading.Tasks;
using JD.LocalizationExport.Service.Implementation.Server.AmazonS3;
using JD.LocalizationExport.Service.Implementation.Server.Exceptions;
using JD.LocalizationExport.Service.Implementation.Server.JmcsClasses.Resources;
using JD.LocalizationExport.Service.Implementation.Server.JsonAnswers;
using JD.LocalizationExport.Service.Implementation.Server.Metafiles;
using JD.LocalizationExport.Service.Implementation.Server.Utility;
using RestSharp;
using RestSharp.Authenticators;
namespace JD.LocalizationExport.Service.Implementation.Server
{
public class GameServerClient
{
private readonly ResourceProvider _resourceProvider = new ResourceProvider();
private readonly StreamUploader _streamUploader = new StreamUploader();
private JmcsClasses.JmcsClient _jmcsClient;
public bool IsInitialized => _jmcsClient != null;
/// <summary>
/// Initialize the client with the given server.
/// </summary>
public async Task InitializeAsync(ServerName serverName, Action<string> logInfo, OnlineConfiguration onlineConfiguration)
{
_jmcsClient = null;
logInfo?.Invoke($"Initializing {nameof(GameServerClient)} with {serverName} server...");
// get ticket
logInfo?.Invoke("Retrieving ticket...");
var restClientForTicket = new RestClient(serverName.TicketAddress() ?? onlineConfiguration.AuthenticationEndpoint)
{
Authenticator = new HttpBasicAuthenticator(onlineConfiguration.ApplicationId, onlineConfiguration.Password)
};
var requestExecutorForTicket = new JmcsClasses.RequestExecutor(restClientForTicket);
var request = new RestRequest(Method.POST) { RequestFormat = DataFormat.Json };
request.AddHeader(Headers.UbiAppId, onlineConfiguration.ApplicationId);
request.AddHeader(Headers.ContentType, "application/json");
var authenticationTicket = await requestExecutorForTicket.ExecuteAndGetResponseAsync<AuthenticationTicket>(request);
if (string.IsNullOrEmpty(authenticationTicket?.Ticket))
{
throw new ArgumentException($"Unable to get a valid ticket for AppId \"{onlineConfiguration.ApplicationId}\".");
}
var ticket = authenticationTicket.Ticket;
logInfo?.Invoke("Ticket successfully retrieved.");
// create client
var serverAddress = serverName.Address();
if (string.IsNullOrEmpty(serverAddress))
{
throw new ArgumentException($"Unable to get a server address from \"{serverName}\". You should check the attributes on the {nameof(ServerName)} enum value.");
}
var restClient = new RestClient(serverAddress)
{
Timeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds
};
_jmcsClient = new JmcsClasses.JmcsClient(restClient, ticket);
logInfo?.Invoke($"{nameof(GameServerClient)} successfully initialized to {serverName} ({serverAddress}).");
}
/// <summary>
/// Upload the given localization file on the given environment.
/// </summary>
public async Task UploadLocalizationAsync(string localizationFilePath, ServiceContentEnvironment environment, bool forceUpload, Action<string> logInfo, IProgress<double> progress, Action onLocalizationUploadComplete)
{
if (!IsInitialized)
{
throw new GameServerClientNotInitializedException();
}
var fileDetails = new FileDetails(localizationFilePath);
var resourceUrl = _resourceProvider.GetServiceContentResource(environment, fileDetails.FileName);
await ExecuteUploadAsync(resourceUrl, fileDetails, (Platform)0, forceUpload, logInfo, progress, onLocalizationUploadComplete);
}
/// <summary>
/// Execute the full upload process at the given resource for the given file on the given platform.
/// </summary>
private async Task ExecuteUploadAsync(string resourceUrl, FileDetails fileDetails, Platform platform, bool forceUpload, Action<string> logInfo, IProgress<double> progress, Action onUploadComplete = null)
{
// retrieve where to upload the file
logInfo?.Invoke((int)platform == 0
? "Retrieving signed urls..."
: $"Retrieving signed urls for {platform.ToString()}...");
var signedUploadRoutes = await _jmcsClient.RetrieveSignedUrlsAsync(resourceUrl, fileDetails, platform);
logInfo?.Invoke("Signed urls successfully retrieved.");
if (string.IsNullOrEmpty(signedUploadRoutes.HeadUrl)
|| forceUpload
|| !(await _jmcsClient.ResourceExistsAsync(signedUploadRoutes.HeadUrl)))
{
// Upload the file itself
logInfo?.Invoke((int)platform == 0
? $"Uploading {fileDetails.FileName} (file hash: {fileDetails.Md5Hash})..."
: $"Uploading {fileDetails.FileName} for {platform.ToString()} (file hash: {fileDetails.Md5Hash})...");
await _streamUploader.UploadAsync(fileDetails, signedUploadRoutes.UploadUrl, progress);
logInfo?.Invoke($"{fileDetails.FileName} successfully uploaded.");
onUploadComplete?.Invoke();
// Useless for this export, so I let it commented
//if (!string.IsNullOrEmpty(signedUploadRoutes.MetadataUrl))
//{
// // generate metadata
// logInfo?.Invoke($"Generating details about {fileDetails.FileName} in a temporary file...");
// string metafilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Ubisoft", "UploadMetafiles", $"{fileDetails.FileName}.meta.json");
// MetafileSerializer.WriteToMetafile(fileDetails, metafilePath, force: true);
// var metaFileDetails = new FileDetails(metafilePath);
// logInfo?.Invoke($"Details about {fileDetails.FileName} were generated at \"{metafilePath}\".");
// logInfo?.Invoke($"Uploading details about {fileDetails.FileName}...");
// _streamUploader.Upload(metaFileDetails, signedUploadRoutes.MetadataUrl, reporter.Progress);
// logInfo?.Invoke($"Details about {fileDetails.FileName} successfully uploaded.");
// logInfo?.Invoke($"Deleting details temporary file at {metafilePath}...");
// System.IO.File.Delete(metafilePath);
// logInfo?.Invoke("Details temporary file deleted.");
//}
}
else
{
logInfo?.Invoke($"Upload skipped because file {fileDetails.FileName} is already present on the server (file hash: {fileDetails.Md5Hash}).");
}
logInfo?.Invoke((int)platform == 0
? "Validating upload..."
: $"Validating upload for {platform.ToString()}...");
await _jmcsClient.ValidateFileUploadAsync(resourceUrl, fileDetails, platform);
logInfo?.Invoke("Upload successfully validated.");
}
}
}