diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs index 027979fa4..aed406a32 100644 --- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs @@ -50,7 +50,7 @@ internal sealed class ExamplePlugin : IASF, IBot, IBotCommand2, IBotConnection, // Please note that this property can have direct dependencies only on structures that were initialized by the constructor, as it's possible to be called before OnLoaded() takes place [JsonInclude] [Required] - public string Name => typeof(ExamplePlugin).Assembly.GetName().Name ?? throw new InvalidOperationException(nameof(Name)); + public string Name => nameof(ExamplePlugin); // This will be displayed to the user and written in the log file, typically you should point it to the version of your library, but alternatively you can do some more advanced logic if you'd like to // Please note that this property can have direct dependencies only on structures that were initialized by the constructor, as it's possible to be called before OnLoaded() takes place diff --git a/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs b/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs index cea7ad517..863c0f7c3 100644 --- a/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.PeriodicGC/PeriodicGCPlugin.cs @@ -44,7 +44,7 @@ internal sealed class PeriodicGCPlugin : IPlugin { [JsonInclude] [Required] - public string Name => typeof(PeriodicGCPlugin).Assembly.GetName().Name ?? throw new InvalidOperationException(nameof(Name)); + public string Name => nameof(PeriodicGCPlugin); [JsonInclude] [Required] diff --git a/ArchiSteamFarm.CustomPlugins.SignInWithSteam/SignInWithSteamPlugin.cs b/ArchiSteamFarm.CustomPlugins.SignInWithSteam/SignInWithSteamPlugin.cs index ecbff8c5e..8ddf027bd 100644 --- a/ArchiSteamFarm.CustomPlugins.SignInWithSteam/SignInWithSteamPlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.SignInWithSteam/SignInWithSteamPlugin.cs @@ -37,7 +37,7 @@ namespace ArchiSteamFarm.CustomPlugins.SignInWithSteam; internal sealed class SignInWithSteamPlugin : IPlugin { [JsonInclude] [Required] - public string Name => typeof(SignInWithSteamPlugin).Assembly.GetName().Name ?? throw new InvalidOperationException(nameof(Name)); + public string Name => nameof(SignInWithSteamPlugin); [JsonInclude] [Required] diff --git a/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/ItemsMatcherPlugin.cs b/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/ItemsMatcherPlugin.cs index c4cf5af98..680ece5c7 100644 --- a/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/ItemsMatcherPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/ItemsMatcherPlugin.cs @@ -48,7 +48,7 @@ internal sealed class ItemsMatcherPlugin : OfficialPlugin, IBot, IBotCommand2, I [JsonInclude] [Required] - public override string Name => typeof(ItemsMatcherPlugin).Assembly.GetName().Name ?? throw new InvalidOperationException(nameof(Name)); + public override string Name => nameof(ItemsMatcherPlugin); [JsonInclude] [Required] diff --git a/ArchiSteamFarm.OfficialPlugins.MobileAuthenticator/MobileAuthenticatorPlugin.cs b/ArchiSteamFarm.OfficialPlugins.MobileAuthenticator/MobileAuthenticatorPlugin.cs index bd9a1da35..d8f720d08 100644 --- a/ArchiSteamFarm.OfficialPlugins.MobileAuthenticator/MobileAuthenticatorPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.MobileAuthenticator/MobileAuthenticatorPlugin.cs @@ -43,7 +43,7 @@ namespace ArchiSteamFarm.OfficialPlugins.MobileAuthenticator; internal sealed class MobileAuthenticatorPlugin : OfficialPlugin, IBotCommand2, IBotSteamClient { [JsonInclude] [Required] - public override string Name => typeof(MobileAuthenticatorPlugin).Assembly.GetName().Name ?? throw new InvalidOperationException(nameof(Name)); + public override string Name => nameof(MobileAuthenticatorPlugin); [JsonInclude] [Required] diff --git a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs index 6ee393030..d64caf32f 100644 --- a/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.Monitoring/MonitoringPlugin.cs @@ -54,7 +54,7 @@ internal sealed class MonitoringPlugin : OfficialPlugin, IWebServiceProvider, IG [JsonInclude] [Required] - public override string Name => typeof(MonitoringPlugin).Assembly.GetName().Name ?? throw new InvalidOperationException(nameof(Name)); + public override string Name => nameof(MonitoringPlugin); public string RepositoryName => SharedInfo.GithubRepo; diff --git a/ArchiSteamFarm/Plugins/Interfaces/IGitHubPluginUpdates.cs b/ArchiSteamFarm/Plugins/Interfaces/IGitHubPluginUpdates.cs index fe5a6befd..227fa63f6 100644 --- a/ArchiSteamFarm/Plugins/Interfaces/IGitHubPluginUpdates.cs +++ b/ArchiSteamFarm/Plugins/Interfaces/IGitHubPluginUpdates.cs @@ -78,26 +78,31 @@ public interface IGitHubPluginUpdates : IPluginUpdates { /// Available release assets for auto-update. Those come directly from your release on GitHub. /// /// Default implementation will select release asset in following order: - /// - {PluginName}-V{Major}-{Minor}-{Build}-{Revision}.zip - /// - {PluginName}-V{Major}-{Minor}-{Build}.zip - /// - {PluginName}-V{Major}-{Minor}.zip - /// - {PluginName}-V{Major}.zip - /// - {PluginName}.zip + /// - {Name}-V{Major}-{Minor}-{Build}-{Revision}.zip + /// - {Name}-V{Major}-{Minor}-{Build}.zip + /// - {Name}-V{Major}-{Minor}.zip + /// - {Name}-V{Major}.zip + /// - {Name}.zip /// - *.zip, if exactly 1 release asset matching in the release /// Where: - /// - {PluginName} is + /// - {Name} will be tried out of and assembly name that provides your plugin type /// - {Major} is target major ASF version (A from A.B.C.D) /// - {Minor} is target minor ASF version (B from A.B.C.D) /// - {Build} is target build (patch) ASF version (C from A.B.C.D) /// - {Revision} is target revision ASF version (D from A.B.C.D) /// - * is a wildcard matching any string value - /// For example, when updating MyAwesomePlugin with ASF version V6.0.1.3, it will select first zip file from available ones in the following order: + /// For example, when updating MyAwesomePlugin declared in JustArchiNET.MyAwesomePlugin assembly with ASF version V6.0.1.3, it will select the first zip file available from those below: /// - MyAwesomePlugin-V6.0.1.3.zip /// - MyAwesomePlugin-V6.0.1.zip /// - MyAwesomePlugin-V6.0.zip /// - MyAwesomePlugin-V6.zip /// - MyAwesomePlugin.zip - /// - *.zip + /// - JustArchiNET.MyAwesomePlugin-V6.0.1.3.zip + /// - JustArchiNET.MyAwesomePlugin-V6.0.1.zip + /// - JustArchiNET.MyAwesomePlugin-V6.0.zip + /// - JustArchiNET.MyAwesomePlugin-V6.zip + /// - JustArchiNET.MyAwesomePlugin.zip + /// - *.zip, if exactly one match is found /// /// Target release asset from those provided that should be used for auto-update. You may return null if the update is unavailable, for example, because ASF version/variant is determined unsupported, or due to any other reason. Task GetTargetReleaseAsset(Version asfVersion, string asfVariant, Version newPluginVersion, IReadOnlyCollection releaseAssets) { @@ -111,16 +116,8 @@ public interface IGitHubPluginUpdates : IPluginUpdates { Dictionary assetsByName = releaseAssets.ToDictionary(static asset => asset.Name, StringComparer.OrdinalIgnoreCase); - List matches = [ - $"{Name}-V{asfVersion.Major}-{asfVersion.Minor}-{asfVersion.Build}-{asfVersion.Revision}.zip", - $"{Name}-V{asfVersion.Major}-{asfVersion.Minor}-{asfVersion.Build}.zip", - $"{Name}-V{asfVersion.Major}-{asfVersion.Minor}.zip", - $"{Name}-V{asfVersion.Major}.zip", - $"{Name}.zip" - ]; - - foreach (string match in matches) { - if (assetsByName.TryGetValue(match, out ReleaseAsset? targetAsset)) { + foreach (string possibleMatch in GetPossibleMatches(asfVersion)) { + if (assetsByName.TryGetValue(possibleMatch, out ReleaseAsset? targetAsset)) { return Task.FromResult(targetAsset); } } @@ -183,4 +180,35 @@ public interface IGitHubPluginUpdates : IPluginUpdates { return asset.DownloadURL; } + + private IEnumerable GetPossibleMatches(Version version) { + ArgumentNullException.ThrowIfNull(version); + + string pluginName = Name; + + if (!string.IsNullOrEmpty(pluginName)) { + foreach (string possibleMatch in GetPossibleMatchesByName(version, pluginName)) { + yield return possibleMatch; + } + } + + string? assemblyName = GetType().Assembly.GetName().Name; + + if (!string.IsNullOrEmpty(assemblyName)) { + foreach (string possibleMatch in GetPossibleMatchesByName(version, assemblyName)) { + yield return possibleMatch; + } + } + } + + private static IEnumerable GetPossibleMatchesByName(Version version, string name) { + ArgumentNullException.ThrowIfNull(version); + ArgumentException.ThrowIfNullOrEmpty(name); + + yield return $"{name}-V{version.Major}-{version.Minor}-{version.Build}-{version.Revision}.zip"; + yield return $"{name}-V{version.Major}-{version.Minor}-{version.Build}.zip"; + yield return $"{name}-V{version.Major}-{version.Minor}.zip"; + yield return $"{name}-V{version.Major}.zip"; + yield return $"{name}.zip"; + } }