Basic download and extract of games
parent
1e63813cd6
commit
ffc51f4e0d
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,6 +31,9 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=1.4.1.12, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.1.4.1\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -47,6 +50,7 @@
|
|||
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -80,6 +84,7 @@
|
|||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="InstallController.cs" />
|
||||
<Compile Include="LANCommanderClient.cs" />
|
||||
<Compile Include="PlayniteClient.cs" />
|
||||
<Compile Include="PlayniteLibraryPlugin.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<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> 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<AuthResponse>(new RestRequest("/api/Auth").AddJsonBody(new AuthRequest()
|
||||
|
@ -86,5 +106,15 @@ namespace LANCommander.Playnite.Extension
|
|||
{
|
||||
return GetRequest<IEnumerable<Game>>("/api/Games");
|
||||
}
|
||||
|
||||
public Game GetGame(Guid id)
|
||||
{
|
||||
return GetRequest<Game>($"/api/Games/{id}");
|
||||
}
|
||||
|
||||
public string DownloadArchive(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
|
||||
{
|
||||
return DownloadRequest($"api/Archives/Download/{id}", progressHandler, completeHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,12 +77,20 @@ namespace LANCommander.Playnite.Extension
|
|||
|
||||
return games;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new List<GameMetadata>();
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<InstallController> 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;
|
||||
|
|
|
@ -10,6 +10,14 @@
|
|||
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.1" newVersion="5.0.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -3,6 +3,7 @@
|
|||
<package id="Microsoft.Bcl.AsyncInterfaces" version="5.0.0" targetFramework="net462" />
|
||||
<package id="PlayniteSDK" version="6.8.0" targetFramework="net462" />
|
||||
<package id="RestSharp" version="106.15.0" targetFramework="net462" />
|
||||
<package id="SharpZipLib" version="1.4.1" targetFramework="net462" />
|
||||
<package id="System.Buffers" version="4.5.1" targetFramework="net462" />
|
||||
<package id="System.Memory" version="4.5.4" targetFramework="net462" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net462" />
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,24 @@ namespace LANCommander.Controllers.Api
|
|||
}
|
||||
|
||||
[HttpGet]
|
||||
public IEnumerable<Archive> Get()
|
||||
{
|
||||
using (var repo = new Repository<Archive>(Context, HttpContext))
|
||||
{
|
||||
return repo.Get(a => true).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public async Task<Archive> Get(Guid id)
|
||||
{
|
||||
using (var repo = new Repository<Archive>(Context, HttpContext))
|
||||
{
|
||||
return await repo.Find(id);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("Download/{id}")]
|
||||
public async Task<IActionResult> Download(Guid id)
|
||||
{
|
||||
using (var repo = new Repository<Archive>(Context, HttpContext))
|
||||
|
|
Loading…
Reference in New Issue