Add DownloadAndExtract

pull/19/head
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 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), "", () =>
{
return Extract(game, tempDownloadLocation);
return DownloadAndExtract(game);
});
if (installDirectory == "")
@ -97,11 +87,51 @@ namespace LANCommander.PlaynitePlugin
Plugin.UpdateGame(manifest, gameId);
Plugin.DownloadCache.Remove(gameId);
File.Delete(tempDownloadLocation);
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)
{
string tempFile = String.Empty;

View File

@ -1,7 +1,6 @@
using LANCommander.SDK;
using LANCommander.SDK.Models;
using RestSharp;
using RestSharp.Extensions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -9,10 +8,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Converters;
using YamlDotNet.Core;
namespace LANCommander.PlaynitePlugin
{
@ -64,6 +60,20 @@ namespace LANCommander.PlaynitePlugin
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)
{
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);
}
public TrackableStream StreamGame(Guid id)
{
return StreamRequest($"/api/Games/{id}/Download");
}
public string DownloadArchive(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> 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
{
internal class TrackableStream : MemoryStream
internal class TrackableStream : MemoryStream, IDisposable
{
public delegate void OnProgressDelegate(long Position, long Length);
public event OnProgressDelegate OnProgress = delegate { };
private long internalStreamProgress = 0;
private Stream internalStream;
private bool disposeStream = false;
private long? streamLength;
//
// Summary:
@ -19,9 +22,11 @@ namespace LANCommander.PlaynitePlugin
// Summary:
// Initializes a new instance of the TrackableStream class with the contents of stream.
// capacity initialized to zero.
public TrackableStream(Stream stream) : base()
public TrackableStream(Stream stream, bool disposeStream = false, long? streamLength = null) : base()
{
internalStream = stream;
this.disposeStream = disposeStream;
this.streamLength = streamLength;
}
//
@ -321,5 +326,15 @@ namespace LANCommander.PlaynitePlugin
}
return r;
}
public void Dispose()
{
if (disposeStream)
{
internalStream.Dispose();
}
}
public long Length => streamLength ?? internalStream.Length;
}
}