Moved to Json Database for online plugins

This commit is contained in:
2024-02-26 23:36:19 +02:00
parent 196fb6d3d1
commit 14f280baef
16 changed files with 376 additions and 299 deletions

View File

@@ -30,6 +30,8 @@ public class Config
AppSettings = new SettingsDictionary<string, string>("./Data/Resources/config.json");
AppSettings["LogFolder"] = "./Data/Logs";
AppSettings["PluginFolder"] = "./Data/Plugins";
AppSettings["ArchiveFolder"] = "./Data/Archives";
if (OperatingSystem.IsLinux())
{

View File

@@ -0,0 +1,14 @@
namespace PluginManager.Interfaces.Updater;
public interface IVersion
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public bool IsNewerThan(IVersion version);
public bool IsOlderThan(IVersion version);
public bool IsEqualTo(IVersion version);
public string ToShortString();
}

View File

@@ -0,0 +1,71 @@
using System;
namespace PluginManager.Interfaces.Updater;
public abstract class Version : IVersion
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
protected readonly char _Separator = '.';
protected Version(int major, int minor, int patch)
{
this.Major = major;
this.Minor = minor;
this.Patch = patch;
}
protected Version(string versionAsString)
{
string[] versionParts = versionAsString.Split(_Separator);
if (versionParts.Length != 3)
{
throw new ArgumentException("Invalid version string");
}
this.Major = int.Parse(versionParts[0]);
this.Minor = int.Parse(versionParts[1]);
this.Patch = int.Parse(versionParts[2]);
}
public bool IsNewerThan(IVersion version)
{
if (this.Major > version.Major)
return true;
if (this.Major == version.Major && this.Minor > version.Minor)
return true;
if (this.Major == version.Major && this.Minor == version.Minor && this.Patch > version.Patch)
return true;
return false;
}
public bool IsOlderThan(IVersion version)
{
if (this.Major < version.Major)
return true;
if (this.Major == version.Major && this.Minor < version.Minor)
return true;
if (this.Major == version.Major && this.Minor == version.Minor && this.Patch < version.Patch)
return true;
return false;
}
public bool IsEqualTo(IVersion version)
{
return this.Major == version.Major && this.Minor == version.Minor && this.Patch == version.Patch;
}
public string ToShortString()
{
return $"{Major}.{Minor}.{Patch}";
}
}

View File

@@ -0,0 +1,16 @@
using PluginManager.Interfaces.Updater;
namespace PluginManager.Online.Helpers;
public class ApplicationVersion : Version
{
public ApplicationVersion(int major, int minor, int patch): base(major, minor, patch)
{
}
public ApplicationVersion(string versionAsString): base(versionAsString)
{
}
}

View File

@@ -0,0 +1,20 @@
using System.Text.Json.Serialization;
using PluginManager.Interfaces.Updater;
namespace PluginManager.Online.Helpers;
public class PluginVersion : Version
{
[JsonConstructor]
public PluginVersion(int major, int minor, int patch): base(major, minor, patch)
{
}
public PluginVersion(string versionAsString): base(versionAsString)
{
}
public override string ToString()
{
return ToShortString();
}
}

View File

@@ -1,117 +0,0 @@
using System;
namespace PluginManager.Online.Helpers;
public class VersionString
{
public int PackageCheckVersion;
public int PackageMainVersion;
public int PackageVersionID;
public VersionString(string version)
{
var data = version.Split('.');
try
{
if (data.Length == 3)
{
PackageVersionID = int.Parse(data[0]);
PackageMainVersion = int.Parse(data[1]);
PackageCheckVersion = int.Parse(data[2]);
}
else if (data.Length == 4)
{
// ignore the first item data[0]
PackageVersionID = int.Parse(data[1]);
PackageMainVersion = int.Parse(data[2]);
PackageCheckVersion = int.Parse(data[3]);
}
else
{
throw new Exception("Invalid version string");
}
}
catch (Exception ex)
{
Console.WriteLine(version);
throw new Exception("Failed to write Version", ex);
}
}
private bool Equals(VersionString other)
{
return PackageCheckVersion == other.PackageCheckVersion && PackageMainVersion == other.PackageMainVersion &&
PackageVersionID == other.PackageVersionID;
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((VersionString)obj);
}
public override int GetHashCode()
{
return HashCode.Combine(PackageCheckVersion, PackageMainVersion, PackageVersionID);
}
public override string ToString()
{
return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion +
", PackageCheckVersion: " + PackageCheckVersion + "}";
}
public string ToShortString()
{
if (PackageVersionID == 0 && PackageCheckVersion == 0 && PackageMainVersion == 0)
return "Unknown";
return $"{PackageVersionID}.{PackageMainVersion}.{PackageCheckVersion}";
}
#region operators
public static bool operator >(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID > s2.PackageVersionID) return true;
if (s1.PackageVersionID == s2.PackageVersionID)
{
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion &&
s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
}
return false;
}
public static bool operator <(VersionString s1, VersionString s2)
{
return !(s1 > s2) && s1 != s2;
}
public static bool operator ==(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID == s2.PackageVersionID && s1.PackageMainVersion == s2.PackageMainVersion &&
s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false;
}
public static bool operator !=(VersionString s1, VersionString s2)
{
return !(s1 == s2);
}
public static bool operator <=(VersionString s1, VersionString s2)
{
return s1 < s2 || s1 == s2;
}
public static bool operator >=(VersionString s1, VersionString s2)
{
return s1 > s2 || s1 == s2;
}
#endregion
}

View File

@@ -3,161 +3,59 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using PluginManager.Online.Helpers;
using PluginManager.Others;
using PluginManager.Plugin;
namespace PluginManager.Online;
public class PluginsManager
{
/// <summary>
/// The Plugin Manager constructor. It uses the default links and the default branch.
/// </summary>
/// <param name="branch">The main branch from where the plugin manager gets its info</param>
public PluginsManager(string? branch)
private static readonly string _DefaultBranch = "releases";
private static readonly string _DefaultBaseUrl = "https://raw.githubusercontent.com/andreitdr/SethPlugins";
private static readonly string _DefaultPluginsLink = "PluginsList.json";
public string Branch { get; init; }
public string BaseUrl { get; init; }
private string PluginsLink => $"{BaseUrl}/{Branch}/{_DefaultPluginsLink}";
public PluginsManager(Uri baseUrl, string branch)
{
PluginsLink = $"https://raw.githubusercontent.com/andreitdr/SethPlugins/{branch}/PluginsList";
VersionsLink = $"https://raw.githubusercontent.com/andreitdr/SethPlugins/{branch}/Versions";
this.BaseUrl = baseUrl.ToString();
this.Branch = branch;
}
public PluginsManager(string branch)
{
this.BaseUrl = _DefaultBaseUrl;
this.Branch = branch;
}
public PluginsManager()
{
this.BaseUrl = _DefaultBaseUrl;
this.Branch = _DefaultBranch;
}
/// <summary>
/// The URL of the server
/// </summary>
public string PluginsLink { get; }
public string VersionsLink { get; }
/// <summary>
/// The method to load all plugins
/// </summary>
/// <returns></returns>
public async Task<List<string[]>> GetAvailablePlugins()
public async Task<List<PluginOnlineInfo?>> GetPluginsList()
{
// Config.Logger.Log("Got data from " + VersionsLink, this, LogLevel.INFO);
try
{
var list = await ServerCom.ReadTextFromURL(PluginsLink);
var lines = list.ToArray();
string jsonText = await ServerCom.GetAllTextFromUrl(PluginsLink);
List<PluginOnlineInfo?> result = await JsonManager.ConvertFromJson<List<PluginOnlineInfo?>>(jsonText);
OSType currentOS = OperatingSystem.IsWindows() ? OSType.WINDOWS : OperatingSystem.IsLinux() ? OSType.LINUX : OSType.MACOSX;
var data = new List<string[]>();
var len = lines.Length;
for (var i = 0; i < len; i++)
{
if (lines[i].Length <= 2)
continue;
var content = lines[i].Split(',');
var display = new string[4]; // 4 columns
if (System.OperatingSystem.IsWindows())
{
if (content[4].Contains("Windows"))
{
display[0] = content[0];
display[1] = content[1];
display[2] = content[2];
display[3] =
(await GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
.ToShortString();
data.Add(display);
}
}
else if (System.OperatingSystem.IsLinux())
{
if (content[4].Contains("Linux"))
{
display[0] = content[0];
display[1] = content[1];
display[2] = content[2];
display[3] =
(await GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
.ToShortString();
data.Add(display);
}
}
}
return data;
}
catch (Exception exception)
{
Config.Logger.Log(message: "Failed to execute command: listplugs\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR);
}
return null;
return result.FindAll(pl => (pl.SupportedOS & currentOS) != 0);
}
private async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName)
public async Task<PluginOnlineInfo?> GetPluginDataByName(string pluginName)
{
var data = await ServerCom.ReadTextFromURL(VersionsLink);
foreach (var item in data)
{
if (item.StartsWith("#"))
continue;
List<PluginOnlineInfo?> plugins = await GetPluginsList();
PluginOnlineInfo? result = plugins.Find(p => p.Name == pluginName);
var split = item.Split(',');
if (split[0] == pakName)
{
// Config.Logger.Log("Searched for " + pakName + " and found " + split[1] + " as version.", LogLevel.INFO);
return new VersionString(split[1]);
}
}
return null;
return result;
}
/// <summary>
/// The method to get plugin information by its name
/// </summary>
/// <param name="name">The plugin name</param>
/// <returns></returns>
public async Task<string[]> GetPluginLinkByName(string name)
{
try
{
var list = await ServerCom.ReadTextFromURL(PluginsLink);
var lines = list.ToArray();
var len = lines.Length;
for (var i = 0; i < len; i++)
{
var contents = lines[i].Split(',');
if (contents[0].ToLowerInvariant() == name.ToLowerInvariant())
{
if (System.OperatingSystem.IsWindows() && contents[4].Contains("Windows"))
{
if (contents.Length == 6)
return new[]
{
contents[2], contents[3], contents[5]
};
if (contents.Length == 5)
return new[]
{
contents[2], contents[3], string.Empty
};
throw new Exception("Failed to download plugin. Invalid Argument Length");
}
if (System.OperatingSystem.IsLinux() && contents[4].Contains("Linux"))
{
if (contents.Length == 6)
return new[]
{
contents[2], contents[3], contents[5]
};
if (contents.Length == 5)
return new[]
{
contents[2], contents[3], string.Empty
};
throw new Exception("Failed to download plugin. Invalid Argument Length");
}
}
}
}
catch (Exception exception)
{
Config.Logger.Log("Failed to execute command: plugin list\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR);
}
return null;
}
}

View File

@@ -21,6 +21,17 @@ public static class ServerCom
var lines = response.Split('\n');
return lines.ToList();
}
/// <summary>
/// Get all text from a file async
/// </summary>
/// <param name="link">The link of the file</param>
/// <returns></returns>
public static async Task<string> GetAllTextFromUrl(string link)
{
var response = await OnlineFunctions.DownloadStringAsync(link);
return response;
}
/// <summary>
/// Download file from url

View File

@@ -1,4 +1,6 @@
namespace PluginManager.Others;
using System;
namespace PluginManager.Others;
/// <summary>
/// The output log type
@@ -28,3 +30,12 @@ public enum InternalActionRunType
ON_STARTUP,
ON_CALL
}
[Flags]
public enum OSType : byte
{
NONE = 0,
WINDOWS = 1 << 0,
LINUX = 2 << 1,
MACOSX = 3 << 2,
}

View File

@@ -0,0 +1,13 @@
namespace PluginManager.Plugin;
public class OnlineDependencyInfo
{
public string DownloadLink { get; private set; }
public string DownloadLocation { get; private set; }
public OnlineDependencyInfo(string downloadLink, string downloadLocation)
{
DownloadLink = downloadLink;
DownloadLocation = downloadLocation;
}
}

View File

@@ -0,0 +1,24 @@
using System.IO;
using PluginManager.Interfaces.Updater;
namespace PluginManager.Plugin;
public class PluginInfo
{
public string PluginName { get; private set; }
public IVersion PluginVersion { get; private set; }
public FileInfo FileData { get; private set; }
public PluginInfo(string pluginName, IVersion pluginVersion)
{
PluginName = pluginName;
PluginVersion = pluginVersion;
FileData = new FileInfo($"{Config.AppSettings["PluginFolder"]}/{pluginName}.dll");
}
public static PluginInfo FromOnlineInfo(PluginOnlineInfo onlineInfo)
{
return new PluginInfo(onlineInfo.Name, onlineInfo.Version);
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using PluginManager.Online.Helpers;
using PluginManager.Others;
namespace PluginManager.Plugin;
public class PluginOnlineInfo
{
public string Name { get; private set; }
public PluginVersion Version { get; private set; }
public string DownLoadLink { get; private set; }
public string Description { get; private set; }
public List<OnlineDependencyInfo> Dependencies { get; private set; }
public OSType SupportedOS { get; private set; }
public bool HasDependencies { get; init; }
[JsonConstructor]
public PluginOnlineInfo(string name, PluginVersion version, string description, string downLoadLink, OSType supportedOS, List<OnlineDependencyInfo> dependencies)
{
Name = name;
Version = version;
Description = description;
DownLoadLink = downLoadLink;
SupportedOS = supportedOS;
Dependencies = dependencies;
HasDependencies = dependencies.Count > 0;
}
public PluginOnlineInfo(string name, PluginVersion version, string description, string downLoadLink, OSType supportedOS)
{
Name = name;
Version = version;
Description = description;
DownLoadLink = downLoadLink;
SupportedOS = supportedOS;
Dependencies = new List<OnlineDependencyInfo>();
HasDependencies = false;
}
public static async Task<PluginOnlineInfo> FromRawData(string jsonText)
{
return await JsonManager.ConvertFromJson<PluginOnlineInfo>(jsonText);
}
public override string ToString()
{
return $"{Name} - {Version} ({Description})";
}
}