diff --git a/LANCommander.Playnite.Extension/InstallController.cs b/LANCommander.Playnite.Extension/InstallController.cs
new file mode 100644
index 00000000..6ef7cee8
--- /dev/null
+++ b/LANCommander.Playnite.Extension/InstallController.cs
@@ -0,0 +1,124 @@
+using Playnite.SDK;
+using Playnite.SDK.Models;
+using Playnite.SDK.Plugins;
+using LANCommander.SDK.Extensions;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using ICSharpCode.SharpZipLib.Zip;
+using ICSharpCode.SharpZipLib.Core;
+
+namespace LANCommander.Playnite.Extension
+{
+ public class LANCommanderInstallController : InstallController
+ {
+ private PlayniteLibraryPlugin Plugin;
+
+ public LANCommanderInstallController(PlayniteLibraryPlugin plugin, Game game) : base(game)
+ {
+ Name = "Install using LANCommander";
+ Plugin = plugin;
+
+ }
+
+ public override void Install(InstallActionArgs args)
+ {
+ var tempPath = System.IO.Path.GetTempFileName();
+ var gameId = Guid.Parse(Game.GameId);
+
+ var game = Plugin.LANCommander.GetGame(gameId);
+
+ var tempFile = Download(game);
+
+ Extract(game, tempFile);
+ }
+
+ private string Download(LANCommander.SDK.Models.Game game)
+ {
+ string tempFile = String.Empty;
+
+ var archive = game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault();
+
+ if (archive != null)
+ {
+ var result = Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
+ {
+ progress.ProgressMaxValue = 100;
+ progress.CurrentProgressValue = 0;
+
+ var destination = Plugin.LANCommander.DownloadArchive(archive.Id, (changed) =>
+ {
+ progress.CurrentProgressValue = changed.ProgressPercentage;
+ }, (complete) =>
+ {
+ progress.CurrentProgressValue = 100;
+ });
+
+ while (progress.CurrentProgressValue != 100)
+ {
+
+ }
+
+ tempFile = destination;
+ },
+ new GlobalProgressOptions($"Downloading {game.Title}")
+ {
+ IsIndeterminate = false,
+ Cancelable = false,
+ });
+
+ return tempFile;
+ }
+ else
+ throw new Exception("Game failed to download");
+ }
+
+ private void Extract(LANCommander.SDK.Models.Game game, string archivePath)
+ {
+ var destination = $"C:\\Games\\{game.Title.SanitizeFilename()}";
+
+ ZipFile file = null;
+
+ try
+ {
+ FileStream fs = File.OpenRead(archivePath);
+
+ file = new ZipFile(fs);
+
+ foreach (ZipEntry entry in file)
+ {
+ if (!entry.IsFile)
+ continue;
+
+ byte[] buffer = new byte[4096];
+ var zipStream = file.GetInputStream(entry);
+
+ var entryDestination = Path.Combine(destination, entry.Name);
+ var entryDirectory = Path.GetDirectoryName(entryDestination);
+
+ if (!String.IsNullOrWhiteSpace(entryDirectory))
+ Directory.CreateDirectory(entryDirectory);
+
+ using (FileStream streamWriter = File.Create(entryDestination))
+ {
+ StreamUtils.Copy(zipStream, streamWriter, buffer);
+ }
+ }
+ }
+ finally
+ {
+ if (file != null)
+ {
+ file.IsStreamOwner = true;
+ file.Close();
+ }
+
+ File.Delete(archivePath);
+ }
+ }
+ }
+}
diff --git a/LANCommander.Playnite.Extension/LANCommander.Playnite.Extension.csproj b/LANCommander.Playnite.Extension/LANCommander.Playnite.Extension.csproj
index cd35c593..49dc42c6 100644
--- a/LANCommander.Playnite.Extension/LANCommander.Playnite.Extension.csproj
+++ b/LANCommander.Playnite.Extension/LANCommander.Playnite.Extension.csproj
@@ -31,6 +31,9 @@
4
+
+ ..\packages\SharpZipLib.1.4.1\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll
+
..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
@@ -47,6 +50,7 @@
..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
@@ -80,6 +84,7 @@
+
diff --git a/LANCommander.Playnite.Extension/LANCommanderClient.cs b/LANCommander.Playnite.Extension/LANCommanderClient.cs
index 8ccd7b02..805db6bc 100644
--- a/LANCommander.Playnite.Extension/LANCommanderClient.cs
+++ b/LANCommander.Playnite.Extension/LANCommanderClient.cs
@@ -1,7 +1,10 @@
using LANCommander.SDK.Models;
using RestSharp;
+using RestSharp.Extensions;
using System;
using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
using System.Linq;
using System.Net;
using System.Text;
@@ -40,6 +43,23 @@ namespace LANCommander.Playnite.Extension
return response.Data;
}
+ private string DownloadRequest(string route, Action progressHandler, Action completeHandler)
+ {
+ 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);
+
+ var request = new RestRequest(route)
+ .AddHeader("Authorization", $"Bearer {Token.AccessToken}");
+
+ client.DownloadFileAsync(new Uri($"{Client.BaseUrl}{route}"), tempFile);
+
+ return tempFile;
+ }
+
public AuthResponse Authenticate(string username, string password)
{
var response = Client.Post(new RestRequest("/api/Auth").AddJsonBody(new AuthRequest()
@@ -86,5 +106,15 @@ namespace LANCommander.Playnite.Extension
{
return GetRequest>("/api/Games");
}
+
+ public Game GetGame(Guid id)
+ {
+ return GetRequest($"/api/Games/{id}");
+ }
+
+ public string DownloadArchive(Guid id, Action progressHandler, Action completeHandler)
+ {
+ return DownloadRequest($"api/Archives/Download/{id}", progressHandler, completeHandler);
+ }
}
}
diff --git a/LANCommander.Playnite.Extension/PlayniteLibraryPlugin.cs b/LANCommander.Playnite.Extension/PlayniteLibraryPlugin.cs
index d2d028fa..02621005 100644
--- a/LANCommander.Playnite.Extension/PlayniteLibraryPlugin.cs
+++ b/LANCommander.Playnite.Extension/PlayniteLibraryPlugin.cs
@@ -77,12 +77,20 @@ namespace LANCommander.Playnite.Extension
return games;
}
- catch
+ catch (Exception ex)
{
return new List();
}
}
+ public override IEnumerable GetInstallActions(GetInstallActionsArgs args)
+ {
+ if (args.Game.PluginId != Id)
+ yield break;
+
+ yield return new LANCommanderInstallController(this, args.Game);
+ }
+
public override ISettings GetSettings(bool firstRunSettings)
{
return Settings;
diff --git a/LANCommander.Playnite.Extension/app.config b/LANCommander.Playnite.Extension/app.config
index 7d2aa9e8..b9fa866e 100644
--- a/LANCommander.Playnite.Extension/app.config
+++ b/LANCommander.Playnite.Extension/app.config
@@ -10,6 +10,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LANCommander.Playnite.Extension/packages.config b/LANCommander.Playnite.Extension/packages.config
index f991b70d..168f677e 100644
--- a/LANCommander.Playnite.Extension/packages.config
+++ b/LANCommander.Playnite.Extension/packages.config
@@ -3,6 +3,7 @@
+
diff --git a/LANCommander.SDK/Extensions/StringExtensions.cs b/LANCommander.SDK/Extensions/StringExtensions.cs
new file mode 100644
index 00000000..9771b96d
--- /dev/null
+++ b/LANCommander.SDK/Extensions/StringExtensions.cs
@@ -0,0 +1,15 @@
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace LANCommander.SDK.Extensions
+{
+ public static class StringExtensions
+ {
+ public static string SanitizeFilename(this string filename, string replacement = "")
+ {
+ var removeInvalidChars = new Regex($"[{Regex.Escape(new string(Path.GetInvalidFileNameChars()))}]", RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant);
+
+ return removeInvalidChars.Replace(filename, replacement);
+ }
+ }
+}
diff --git a/LANCommander/Controllers/Api/ArchivesController.cs b/LANCommander/Controllers/Api/ArchivesController.cs
index c43cdd49..a69f60e3 100644
--- a/LANCommander/Controllers/Api/ArchivesController.cs
+++ b/LANCommander/Controllers/Api/ArchivesController.cs
@@ -19,6 +19,24 @@ namespace LANCommander.Controllers.Api
}
[HttpGet]
+ public IEnumerable Get()
+ {
+ using (var repo = new Repository(Context, HttpContext))
+ {
+ return repo.Get(a => true).ToList();
+ }
+ }
+
+ [HttpGet("{id}")]
+ public async Task Get(Guid id)
+ {
+ using (var repo = new Repository(Context, HttpContext))
+ {
+ return await repo.Find(id);
+ }
+ }
+
+ [HttpGet("Download/{id}")]
public async Task Download(Guid id)
{
using (var repo = new Repository(Context, HttpContext))