Add DownloadAndExtract

This commit is contained in:
Daniel 2023-04-07 20:08:03 -05:00
parent 127f0cbb08
commit cb770f8dab
3 changed files with 79 additions and 19 deletions

View file

@ -39,19 +39,9 @@ namespace LANCommander.PlaynitePlugin
var gameId = Guid.Parse(Game.GameId); var gameId = Guid.Parse(Game.GameId);
var game = Plugin.LANCommander.GetGame(gameId); var game = Plugin.LANCommander.GetGame(gameId);
string tempDownloadLocation;
if (Plugin.DownloadCache.ContainsKey(gameId))
tempDownloadLocation = Plugin.DownloadCache[gameId];
else
{
tempDownloadLocation = Download(game);
Plugin.DownloadCache[gameId] = tempDownloadLocation;
}
var installDirectory = RetryHelper.RetryOnException(10, TimeSpan.FromMilliseconds(500), "", () => var installDirectory = RetryHelper.RetryOnException(10, TimeSpan.FromMilliseconds(500), "", () =>
{ {
return Extract(game, tempDownloadLocation); return DownloadAndExtract(game);
}); });
if (installDirectory == "") if (installDirectory == "")
@ -97,11 +87,51 @@ namespace LANCommander.PlaynitePlugin
Plugin.UpdateGame(manifest, gameId); Plugin.UpdateGame(manifest, gameId);
Plugin.DownloadCache.Remove(gameId); Plugin.DownloadCache.Remove(gameId);
File.Delete(tempDownloadLocation);
InvokeOnInstalled(new GameInstalledEventArgs(installInfo)); InvokeOnInstalled(new GameInstalledEventArgs(installInfo));
} }
private string DownloadAndExtract(LANCommander.SDK.Models.Game game)
{
if (game == null)
{
throw new Exception("Game failed to download!");
}
var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename());
Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
{
Directory.CreateDirectory(destination);
progress.ProgressMaxValue = 100;
progress.CurrentProgressValue = 0;
using (var gameStream = Plugin.LANCommander.StreamGame(game.Id))
using (var reader = ReaderFactory.Open(gameStream))
{
progress.ProgressMaxValue = gameStream.Length;
gameStream.OnProgress += (pos, len) =>
{
progress.CurrentProgressValue = pos;
};
reader.WriteAllToDirectory(destination, new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
},
new GlobalProgressOptions($"Downloading {game.Title}...")
{
IsIndeterminate = false,
Cancelable = false,
});
return destination;
}
private string Download(LANCommander.SDK.Models.Game game) private string Download(LANCommander.SDK.Models.Game game)
{ {
string tempFile = String.Empty; string tempFile = String.Empty;

View file

@ -1,7 +1,6 @@
using LANCommander.SDK; using LANCommander.SDK;
using LANCommander.SDK.Models; using LANCommander.SDK.Models;
using RestSharp; using RestSharp;
using RestSharp.Extensions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@ -9,10 +8,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media.Converters;
using YamlDotNet.Core;
namespace LANCommander.PlaynitePlugin namespace LANCommander.PlaynitePlugin
{ {
@ -64,6 +60,20 @@ namespace LANCommander.PlaynitePlugin
return tempFile; return tempFile;
} }
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($"{Client.BaseUrl}{route}"));
return new TrackableStream(ws, true, Convert.ToInt64(client.ResponseHeaders["Content-Length"]));
}
public async Task<AuthResponse> AuthenticateAsync(string username, string password) public async Task<AuthResponse> AuthenticateAsync(string username, string password)
{ {
var response = await Client.ExecuteAsync<AuthResponse>(new RestRequest("/api/Auth", Method.POST).AddJsonBody(new AuthRequest() var response = await Client.ExecuteAsync<AuthResponse>(new RestRequest("/api/Auth", Method.POST).AddJsonBody(new AuthRequest()
@ -166,6 +176,11 @@ namespace LANCommander.PlaynitePlugin
return DownloadRequest($"/api/Games/{id}/Download", progressHandler, completeHandler); return DownloadRequest($"/api/Games/{id}/Download", progressHandler, completeHandler);
} }
public TrackableStream StreamGame(Guid id)
{
return StreamRequest($"/api/Games/{id}/Download");
}
public string DownloadArchive(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler) public string DownloadArchive(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
{ {
return DownloadRequest($"/api/Archives/Download/{id}", progressHandler, completeHandler); return DownloadRequest($"/api/Archives/Download/{id}", progressHandler, completeHandler);

View file

@ -1,13 +1,16 @@
using System.IO; using System;
using System.IO;
namespace LANCommander.PlaynitePlugin namespace LANCommander.PlaynitePlugin
{ {
internal class TrackableStream : MemoryStream internal class TrackableStream : MemoryStream, IDisposable
{ {
public delegate void OnProgressDelegate(long Position, long Length); public delegate void OnProgressDelegate(long Position, long Length);
public event OnProgressDelegate OnProgress = delegate { }; public event OnProgressDelegate OnProgress = delegate { };
private long internalStreamProgress = 0; private long internalStreamProgress = 0;
private Stream internalStream; private Stream internalStream;
private bool disposeStream = false;
private long? streamLength;
// //
// Summary: // Summary:
@ -19,9 +22,11 @@ namespace LANCommander.PlaynitePlugin
// Summary: // Summary:
// Initializes a new instance of the TrackableStream class with the contents of stream. // Initializes a new instance of the TrackableStream class with the contents of stream.
// capacity initialized to zero. // capacity initialized to zero.
public TrackableStream(Stream stream) : base() public TrackableStream(Stream stream, bool disposeStream = false, long? streamLength = null) : base()
{ {
internalStream = stream; internalStream = stream;
this.disposeStream = disposeStream;
this.streamLength = streamLength;
} }
// //
@ -321,5 +326,15 @@ namespace LANCommander.PlaynitePlugin
} }
return r; return r;
} }
public void Dispose()
{
if (disposeStream)
{
internalStream.Dispose();
}
}
public long Length => streamLength ?? internalStream.Length;
} }
} }