diff --git a/Torch.API/WebAPI/Plugin/IPluginQuery.cs b/Torch.API/WebAPI/Plugin/IPluginQuery.cs new file mode 100644 index 0000000..b63db2a --- /dev/null +++ b/Torch.API/WebAPI/Plugin/IPluginQuery.cs @@ -0,0 +1,12 @@ +using System; +using System.Threading.Tasks; + +namespace Torch.API.WebAPI.Plugin; + +public interface IPluginQuery +{ + Task QueryAll(); + Task QueryOne(Guid guid); + Task DownloadPlugin(Guid guid, string path = null); + Task DownloadPlugin(PluginItem item, string path = null); +} \ No newline at end of file diff --git a/Torch.API/WebAPI/Plugin/LegacyPluginQuery.cs b/Torch.API/WebAPI/Plugin/LegacyPluginQuery.cs new file mode 100644 index 0000000..fd2a544 --- /dev/null +++ b/Torch.API/WebAPI/Plugin/LegacyPluginQuery.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading; +using System.Threading.Tasks; +using NLog; + +namespace Torch.API.WebAPI.Plugin; + +public class LegacyPluginQuery : IPluginQuery +{ + private const string BASE_URL = "https://torchapi.com/api/plugins/"; + private readonly HttpClient _client; + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + private LegacyPluginQuery() + { + _client = new() + { + BaseAddress = new(BASE_URL) + }; + } + + public static LegacyPluginQuery Instance { get; } = new(); + + public async Task QueryAll() + { + return await _client.GetFromJsonAsync("/", CancellationToken.None); + } + + public async Task QueryOne(Guid guid) + { + using var res = await _client.GetAsync($"/search/{guid}"); + if (!res.IsSuccessStatusCode) + return null; + return await res.Content.ReadFromJsonAsync(); + } + + public async Task DownloadPlugin(Guid guid, string path = null) + { + var item = await QueryOne(guid); + if (item is null) return false; + return await DownloadPlugin(item, path); + } + + public async Task DownloadPlugin(PluginItem item, string path = null) + { + try + { + path ??= Path.Combine(AppContext.BaseDirectory, "Plugins", $"{item.Name}.zip"); + + if (item.Versions.Length == 0) + { + Log.Error($"Selected plugin {item.Name} does not have any versions to download!"); + return false; + } + var version = item.Versions.FirstOrDefault(v => v.Version == item.LatestVersion); + if (version is null) + { + Log.Error($"Could not find latest version for selected plugin {item.Name}"); + return false; + } + var s = await _client.GetStreamAsync(version.Url); + + if(File.Exists(path)) + File.Delete(path); + + await using var f = File.Create(path); + await s.CopyToAsync(f); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to download plugin!"); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/Torch.API/WebAPI/Plugin/PluginItem.cs b/Torch.API/WebAPI/Plugin/PluginItem.cs new file mode 100644 index 0000000..cadf0c5 --- /dev/null +++ b/Torch.API/WebAPI/Plugin/PluginItem.cs @@ -0,0 +1,11 @@ +using System; +using System.Text.Json.Serialization; + +namespace Torch.API.WebAPI.Plugin; + +public record PluginItem(Guid Id, string Name, string Author, string Description, string LatestVersion, + VersionItem[] Versions) +{ + [JsonIgnore] + public bool Installed { get; set; } +} \ No newline at end of file diff --git a/Torch.API/WebAPI/Plugin/PluginsResponse.cs b/Torch.API/WebAPI/Plugin/PluginsResponse.cs new file mode 100644 index 0000000..bb34f25 --- /dev/null +++ b/Torch.API/WebAPI/Plugin/PluginsResponse.cs @@ -0,0 +1,3 @@ +namespace Torch.API.WebAPI.Plugin; + +public record PluginsResponse(PluginItem[] Plugins); \ No newline at end of file diff --git a/Torch.API/WebAPI/Plugin/VersionItem.cs b/Torch.API/WebAPI/Plugin/VersionItem.cs new file mode 100644 index 0000000..d74c51d --- /dev/null +++ b/Torch.API/WebAPI/Plugin/VersionItem.cs @@ -0,0 +1,6 @@ +using System.Text.Json.Serialization; + +namespace Torch.API.WebAPI.Plugin; + +public record VersionItem(string Version, string Note, [property: JsonPropertyName("is_beta")] bool IsBeta, + string Url); \ No newline at end of file diff --git a/Torch.API/WebAPI/PluginQuery.cs b/Torch.API/WebAPI/PluginQuery.cs deleted file mode 100644 index d120c11..0000000 --- a/Torch.API/WebAPI/PluginQuery.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Json; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; -using NLog; - -namespace Torch.API.WebAPI -{ - public class PluginQuery - { - private const string ALL_QUERY = "https://torchapi.com/api/plugins/"; - private const string PLUGIN_QUERY = "https://torchapi.com/api/plugins/search/{0}"; - private readonly HttpClient _client; - private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - - private static PluginQuery _instance; - public static PluginQuery Instance => _instance ??= new(); - - private PluginQuery() - { - _client = new(); - } - - public async Task QueryAll() - { - return (PluginsResponse) await _client.GetFromJsonAsync(ALL_QUERY, typeof(PluginsResponse), CancellationToken.None); - } - - public Task QueryOne(Guid guid) - { - return QueryOne(guid.ToString()); - } - - public async Task QueryOne(string guid) - { - using var res = await _client.GetAsync(string.Format(PLUGIN_QUERY, guid)); - if (!res.IsSuccessStatusCode) - return null; - return await res.Content.ReadFromJsonAsync(); - } - - public Task DownloadPlugin(Guid guid, string path = null) - { - return DownloadPlugin(guid.ToString(), path); - } - - public async Task DownloadPlugin(string guid, string path = null) - { - var item = await QueryOne(guid); - if (item is null) return false; - return await DownloadPlugin(item, path); - } - - public async Task DownloadPlugin(PluginItem item, string path = null) - { - try - { - path ??= Path.Combine(AppContext.BaseDirectory, "Plugins", $"{item.Name}.zip"); - - if (item.Versions.Length == 0) - { - Log.Error($"Selected plugin {item.Name} does not have any versions to download!"); - return false; - } - var version = item.Versions.FirstOrDefault(v => v.Version == item.LatestVersion); - if (version is null) - { - Log.Error($"Could not find latest version for selected plugin {item.Name}"); - return false; - } - var s = await _client.GetStreamAsync(version.Url); - - if(File.Exists(path)) - File.Delete(path); - - await using var f = File.Create(path); - await s.CopyToAsync(f); - } - catch (Exception ex) - { - Log.Error(ex, "Failed to download plugin!"); - } - - return true; - } - } - - public record PluginsResponse(PluginItem[] Plugins); - - public record PluginItem(Guid Id, string Name, string Author, string Description, string LatestVersion, - VersionItem[] Versions) - { - [JsonIgnore] - public bool Installed { get; set; } - } - - public record VersionItem(string Version, string Note, [property: JsonPropertyName("is_beta")] bool IsBeta, - string Url); -} diff --git a/Torch.API/WebAPI/GithubQuery.cs b/Torch.API/WebAPI/Update/GithubQuery.cs similarity index 98% rename from Torch.API/WebAPI/GithubQuery.cs rename to Torch.API/WebAPI/Update/GithubQuery.cs index 1769bb1..3cdb167 100644 --- a/Torch.API/WebAPI/GithubQuery.cs +++ b/Torch.API/WebAPI/Update/GithubQuery.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using JorgeSerrano.Json; using Version = SemanticVersioning.Version; -namespace Torch.API.WebAPI; +namespace Torch.API.WebAPI.Update; public class GithubQuery : IUpdateQuery { diff --git a/Torch.API/WebAPI/IUpdateQuery.cs b/Torch.API/WebAPI/Update/IUpdateQuery.cs similarity index 84% rename from Torch.API/WebAPI/IUpdateQuery.cs rename to Torch.API/WebAPI/Update/IUpdateQuery.cs index 60647f1..3f6a7ef 100644 --- a/Torch.API/WebAPI/IUpdateQuery.cs +++ b/Torch.API/WebAPI/Update/IUpdateQuery.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; -namespace Torch.API.WebAPI; +namespace Torch.API.WebAPI.Update; public interface IUpdateQuery : IDisposable { diff --git a/Torch.API/WebAPI/JenkinsQuery.cs b/Torch.API/WebAPI/Update/JenkinsQuery.cs similarity index 98% rename from Torch.API/WebAPI/JenkinsQuery.cs rename to Torch.API/WebAPI/Update/JenkinsQuery.cs index 62baaa5..906c388 100644 --- a/Torch.API/WebAPI/JenkinsQuery.cs +++ b/Torch.API/WebAPI/Update/JenkinsQuery.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using Torch.API.Utils; using Version = SemanticVersioning.Version; -namespace Torch.API.WebAPI +namespace Torch.API.WebAPI.Update { public class JenkinsQuery : IUpdateQuery { diff --git a/Torch.API/WebAPI/UpdateRelease.cs b/Torch.API/WebAPI/Update/UpdateRelease.cs similarity index 73% rename from Torch.API/WebAPI/UpdateRelease.cs rename to Torch.API/WebAPI/Update/UpdateRelease.cs index 33a7db2..211c40e 100644 --- a/Torch.API/WebAPI/UpdateRelease.cs +++ b/Torch.API/WebAPI/Update/UpdateRelease.cs @@ -1,5 +1,5 @@ using SemanticVersioning; -namespace Torch.API.WebAPI; +namespace Torch.API.WebAPI.Update; public record UpdateRelease(Version Version, string ArtifactUrl); \ No newline at end of file diff --git a/Torch.Server/Views/PluginBrowser.xaml.cs b/Torch.Server/Views/PluginBrowser.xaml.cs index 315e37a..2e06bc4 100644 --- a/Torch.Server/Views/PluginBrowser.xaml.cs +++ b/Torch.Server/Views/PluginBrowser.xaml.cs @@ -22,6 +22,7 @@ using Torch.Collections; using Torch.Server.Annotations; using Torch.Managers; using Torch.API.Managers; +using Torch.API.WebAPI.Plugin; namespace Torch.Server.Views { @@ -60,7 +61,7 @@ namespace Torch.Server.Views { try { - var res = await PluginQuery.Instance.QueryAll(); + var res = await LegacyPluginQuery.Instance.QueryAll(); foreach (var item in res.Plugins.OrderBy(i => i.Name)) { lock (_syncLock) { diff --git a/Torch.Server/Views/PluginDownloader.xaml.cs b/Torch.Server/Views/PluginDownloader.xaml.cs index 00faac3..a4614d3 100644 --- a/Torch.Server/Views/PluginDownloader.xaml.cs +++ b/Torch.Server/Views/PluginDownloader.xaml.cs @@ -14,6 +14,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.ComponentModel; +using Torch.API.WebAPI.Plugin; namespace Torch.Server.Views { @@ -50,7 +51,7 @@ namespace Torch.Server.Views var PercentChangeOnDownload = 100 / PluginsToDownload.Count; foreach (PluginItem PluginItem in PluginsToDownload) { - if (!PluginQuery.Instance.DownloadPlugin(PluginItem.Id).Result) { + if (!LegacyPluginQuery.Instance.DownloadPlugin(PluginItem.Id).Result) { failedDownloads++; DownloadProgress += PercentChangeOnDownload; (sender as BackgroundWorker).ReportProgress(DownloadProgress); diff --git a/Torch/Managers/UpdateManager.cs b/Torch/Managers/UpdateManager.cs index 4793157..a9d1bab 100644 --- a/Torch/Managers/UpdateManager.cs +++ b/Torch/Managers/UpdateManager.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using NLog; using Torch.API; using Torch.API.WebAPI; +using Torch.API.WebAPI.Update; namespace Torch.Managers { diff --git a/Torch/Plugins/PluginManager.cs b/Torch/Plugins/PluginManager.cs index 3c2f6e6..02d4add 100644 --- a/Torch/Plugins/PluginManager.cs +++ b/Torch/Plugins/PluginManager.cs @@ -16,6 +16,7 @@ using Torch.API.Managers; using Torch.API.Plugins; using Torch.API.Session; using Torch.API.WebAPI; +using Torch.API.WebAPI.Plugin; using Torch.Collections; using Torch.Commands; using Torch.Plugins; @@ -306,7 +307,7 @@ namespace Torch.Managers return; } item.Manifest.Version.TryExtractVersion(out Version currentVersion); - var latest = await PluginQuery.Instance.QueryOne(item.Manifest.Guid); + var latest = await LegacyPluginQuery.Instance.QueryOne(item.Manifest.Guid); if (latest?.LatestVersion == null) { @@ -329,7 +330,7 @@ namespace Torch.Managers } _log.Info($"Updating plugin '{item.Manifest.Name}' from {currentVersion} to {newVersion}."); - await PluginQuery.Instance.DownloadPlugin(latest, item.Path); + await LegacyPluginQuery.Instance.DownloadPlugin(latest, item.Path); Interlocked.Increment(ref count); } catch (Exception e)