From 651865f28a9347747cdac0a55820a269c5678b98 Mon Sep 17 00:00:00 2001 From: Brant Martin Date: Sat, 2 Mar 2019 11:42:08 -0500 Subject: [PATCH] Implement plugin browser and downloader --- Torch.API/Torch.API.csproj | 5 + Torch.API/WebAPI/PluginQuery.cs | 159 ++++++++++++++++++++++ Torch.API/packages.config | 1 + Torch.Server/Torch.Server.csproj | 12 +- Torch.Server/Views/PluginBrowser.xaml | 124 +++++++++++++++++ Torch.Server/Views/PluginBrowser.xaml.cs | 90 ++++++++++++ Torch.Server/Views/PluginsControl.xaml | 9 +- Torch.Server/Views/PluginsControl.xaml.cs | 6 + Torch.Server/packages.config | 1 + 9 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 Torch.API/WebAPI/PluginQuery.cs create mode 100644 Torch.Server/Views/PluginBrowser.xaml create mode 100644 Torch.Server/Views/PluginBrowser.xaml.cs diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj index 10bedc2..987b979 100644 --- a/Torch.API/Torch.API.csproj +++ b/Torch.API/Torch.API.csproj @@ -39,6 +39,10 @@ ..\GameBinaries\HavokWrapper.dll False + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + True + ..\packages\NLog.4.4.12\lib\net45\NLog.dll True @@ -189,6 +193,7 @@ + diff --git a/Torch.API/WebAPI/PluginQuery.cs b/Torch.API/WebAPI/PluginQuery.cs new file mode 100644 index 0000000..74da68f --- /dev/null +++ b/Torch.API/WebAPI/PluginQuery.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using NLog; + +namespace Torch.API.WebAPI +{ + public class PluginQuery + { + private const string ALL_QUERY = "https://torchapi.net/api/plugins"; + private const string PLUGIN_QUERY = "https://torchapi.net/api/plugins/{0}"; + private readonly HttpClient _client; + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + private static PluginQuery _instance; + public static PluginQuery Instance => _instance ?? (_instance = new PluginQuery()); + + private PluginQuery() + { + _client = new HttpClient(); + } + + public async Task QueryAll() + { + var h = await _client.GetAsync(ALL_QUERY); + if (!h.IsSuccessStatusCode) + { + Log.Error($"Plugin query returned response {h.StatusCode}"); + return null; + } + + var r = await h.Content.ReadAsStringAsync(); + + PluginResponse response; + try + { + response = JsonConvert.DeserializeObject(r); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to deserialize plugin query response!"); + return null; + } + return response; + } + + public async Task QueryOne(Guid guid) + { + return await QueryOne(guid.ToString()); + } + + public async Task QueryOne(string guid) + { + + var h = await _client.GetAsync(string.Format(PLUGIN_QUERY, guid)); + if (!h.IsSuccessStatusCode) + { + Log.Error($"Plugin query returned response {h.StatusCode}"); + return null; + } + + var r = await h.Content.ReadAsStringAsync(); + + PluginFullItem response; + try + { + response = JsonConvert.DeserializeObject(r); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to deserialize plugin query response!"); + return null; + } + return response; + } + + public async Task DownloadPlugin(Guid guid) + { + return await DownloadPlugin(guid.ToString()); + } + + public async Task DownloadPlugin(string guid) + { + var item = await QueryOne(guid); + return await DownloadPlugin(item); + } + + public async Task DownloadPlugin(PluginFullItem item) + { + try + { + var h = await _client.GetAsync(string.Format(PLUGIN_QUERY, item.ID)); + string res = await h.Content.ReadAsStringAsync(); + var response = JsonConvert.DeserializeObject(res); + if (response.Versions.Length == 0) + { + Log.Error($"Selected plugin {item.Name} does not have any versions to download!"); + return false; + } + var version = response.Versions.FirstOrDefault(v => v.Version == response.LatestVersion); + if (version == null) + { + Log.Error($"Could not find latest version for selected plugin {item.Name}"); + return false; + } + var s = await _client.GetStreamAsync(version.URL); + using (var f = new FileStream($"Plugins\\{item.Name}.zip", FileMode.Create)) + { + await s.CopyToAsync(f); + await f.FlushAsync(); + } + } + catch (Exception ex) + { + Log.Error(ex, "Failed to download plugin!"); + } + + return true; + } + } + + public class PluginResponse + { + public PluginItem[] Plugins; + public int Count; + } + + public class PluginItem + { + public string ID; + public string Name; + public string Author; + public string Description; + public string LatestVersion; + + public override string ToString() + { + return Name; + } + } + + public class PluginFullItem : PluginItem + { + public VersionItem[] Versions; + } + + public class VersionItem + { + public string Version; + public string Note; + public bool IsBeta; + public string URL; + } +} diff --git a/Torch.API/packages.config b/Torch.API/packages.config index 9d88a31..5221eb5 100644 --- a/Torch.API/packages.config +++ b/Torch.API/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj index ec1c672..506686b 100644 --- a/Torch.Server/Torch.Server.csproj +++ b/Torch.Server/Torch.Server.csproj @@ -51,7 +51,6 @@ MinimumRecommendedRules.ruleset true $(SolutionDir)\bin\x64\Release\Torch.Server.xml - 1591 Torch.Server.Program @@ -71,6 +70,9 @@ ..\packages\MahApps.Metro.1.6.1\lib\net45\MahApps.Metro.dll + + ..\packages\Markdown.Xaml.1.0.0\lib\net45\Markdown.Xaml.dll + False ..\GameBinaries\Microsoft.CodeAnalysis.dll @@ -273,6 +275,9 @@ ModListControl.xaml + + PluginBrowser.xaml + ThemeControl.xaml @@ -437,6 +442,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -492,6 +501,7 @@ false + diff --git a/Torch.Server/Views/PluginBrowser.xaml b/Torch.Server/Views/PluginBrowser.xaml new file mode 100644 index 0000000..e4cd24f --- /dev/null +++ b/Torch.Server/Views/PluginBrowser.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +