From 33d4fb5db93d26152f4017e7b62e7f3ff422553b Mon Sep 17 00:00:00 2001 From: VPKSoft Date: Wed, 24 Aug 2022 17:46:36 +0300 Subject: [PATCH] Move common utils to separate project. --- .../EventArgs/ExceptionOccurredEventArgs.cs | 66 ++++++++ .../Interfaces/IExceptionReporter.cs | 49 ++++++ .../UpdateCheck/UpdateChecker.cs | 158 ++++++++++++++++++ .../UpdateCheck/VersionData.cs | 111 ++++++++++++ .../VPKSoft.Utils.Common.csproj | 22 +++ 5 files changed, 406 insertions(+) create mode 100644 VPKSoft.Utils.Common/EventArgs/ExceptionOccurredEventArgs.cs create mode 100644 VPKSoft.Utils.Common/Interfaces/IExceptionReporter.cs create mode 100644 VPKSoft.Utils.Common/UpdateCheck/UpdateChecker.cs create mode 100644 VPKSoft.Utils.Common/UpdateCheck/VersionData.cs create mode 100644 VPKSoft.Utils.Common/VPKSoft.Utils.Common.csproj diff --git a/VPKSoft.Utils.Common/EventArgs/ExceptionOccurredEventArgs.cs b/VPKSoft.Utils.Common/EventArgs/ExceptionOccurredEventArgs.cs new file mode 100644 index 00000000..0978010d --- /dev/null +++ b/VPKSoft.Utils.Common/EventArgs/ExceptionOccurredEventArgs.cs @@ -0,0 +1,66 @@ +#region License +/* +MIT License + +Copyright(c) 2022 Petteri Kautonen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#endregion + +namespace VPKSoft.Utils.Common.EventArgs; + +/// +/// Event arguments for reporting an . +/// Implements the . +/// +/// +public class ExceptionOccurredEventArgs : System.EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The exception which occurred. + /// The class in which the exception occurred. + /// The method in which the exception occurred. + public ExceptionOccurredEventArgs(Exception exception, string @class, string method) + { + Exception = exception; + Class = @class; + Method = method; + } + + /// + /// Gets the exception which occurred. + /// + /// The exception which occurred. + public Exception Exception { get; } + + /// + /// Gets the class in which the exception occurred. + /// + /// The class in which the exception occurred. + public string Class { get; } + + /// + /// Gets the method in which the exception occurred. + /// + /// The method in which the exception occurred. + public string Method { get; } +} \ No newline at end of file diff --git a/VPKSoft.Utils.Common/Interfaces/IExceptionReporter.cs b/VPKSoft.Utils.Common/Interfaces/IExceptionReporter.cs new file mode 100644 index 00000000..517c8b20 --- /dev/null +++ b/VPKSoft.Utils.Common/Interfaces/IExceptionReporter.cs @@ -0,0 +1,49 @@ +#region License +/* +MIT License + +Copyright(c) 2022 Petteri Kautonen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#endregion + + +using VPKSoft.Utils.Common.EventArgs; + +namespace VPKSoft.Utils.Common.Interfaces; + +/// +/// A simple interface to report exception without any specific dependencies. +/// +public interface IExceptionReporter +{ + /// + /// Occurs when an exception occurred somewhere. + /// + public event EventHandler? ExceptionOccurred; + + /// + /// Initializes a new instance of the class. + /// + /// The exception which occurred. + /// The class in which the exception occurred. + /// The method in which the exception occurred. + public void RaiseExceptionOccurred(Exception exception, string @class, string method); +} \ No newline at end of file diff --git a/VPKSoft.Utils.Common/UpdateCheck/UpdateChecker.cs b/VPKSoft.Utils.Common/UpdateCheck/UpdateChecker.cs new file mode 100644 index 00000000..059b2dcb --- /dev/null +++ b/VPKSoft.Utils.Common/UpdateCheck/UpdateChecker.cs @@ -0,0 +1,158 @@ +#region License +/* +MIT License + +Copyright(c) 2022 Petteri Kautonen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#endregion + + +using System.Text.Json; +using VPKSoft.Utils.Common.EventArgs; +using VPKSoft.Utils.Common.Interfaces; + +namespace VPKSoft.Utils.Common.UpdateCheck; + +/// +/// An application update checker class. +/// +public class UpdateChecker : IExceptionReporter +{ + /// + /// Initializes a new instance of the class. + /// + /// The check URI. + /// The version. + /// The version tag. + public UpdateChecker(string checkUri, Version version, string? versionTag = null) + { + this.checkUri = checkUri; + this.version = version; + this.versionTag = versionTag; + } + + /// + /// Generates a file from the specified collection as JSON. + /// + /// The data to deserialize into a JSON file. + /// Name of the JSON file. + public static void GenerateFile(IEnumerable data, string fileName) + { + var jsonText = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true, }); + File.WriteAllText(fileName, jsonText); + } + + /// + /// Gets or sets a version to not to check for again. + /// + public static string SkipVersion { get; set; } = string.Empty; + + /// + /// Checks the updates and returns the array of version data larger than the version specified in the constructor. + /// + /// IEnumerable<VersionData>. + public async Task> CheckUpdates() + { + var result = new List(); + + try + { + using var client = new HttpClient(); + var bytes = await client.GetByteArrayAsync(checkUri); + + var options = new JsonDocumentOptions + { + AllowTrailingCommas = true, + }; + + var document = JsonDocument.Parse(bytes, options); + var items = document.Deserialize>()?.ToList() ?? new List(); + + var larger = items.Where(f => + new Version(f.Version) > version || new Version(f.Version) == version && + string.CompareOrdinal(f.VersionTag, versionTag) > 0) + .ToList(); + + result.AddRange(larger); + + var check = result.OrderByDescending(f => f.ReleaseDateTime).FirstOrDefault(); + + if (check != null && $"{check.Version}|{check.VersionTag ?? string.Empty}" == SkipVersion) + { + result.Clear(); + } + + return result; + } + catch (Exception ex) + { + RaiseExceptionOccurred(ex, string.Empty, nameof(CheckUpdates)); + return result; + } + } + + /// + /// Generates a string representation of the version string and optional tag with the specified string delimiter. + /// + /// The version string. + /// The version tag delimiter. + /// The version tag. + /// An optional version prefix. E.g. 'v.'. + /// A string representation of the application version. + public static string VersionAndTagToString(string? version, string versionTagDelimiter, string? versionTag, string versionPrefix = "") + { + version = version == null ? versionPrefix + "1.0.0.0" : versionPrefix + version; + + if (!string.IsNullOrWhiteSpace(versionTag)) + { + return $"{version} {versionTagDelimiter} {versionTag}"; + } + + return $"{version}"; + } + + /// + /// Generates a string representation of the value and optional tag with the specified string delimiter. + /// + /// The version. + /// The version tag delimiter. + /// The version tag. + /// The number of components to take from the . The fieldCount ranges from 0 to 4. + /// An optional version prefix. E.g. 'v.'. + /// A string representation of the application version. + public static string VersionAndTagToString(Version version, string versionTagDelimiter, string? versionTag, int versionFieldCount = 3, string versionPrefix = "") + { + return VersionAndTagToString(version.ToString(versionFieldCount), versionTagDelimiter, versionTag, versionPrefix); + } + + private readonly string checkUri; + private readonly Version version; + private readonly string? versionTag; + + /// + public event EventHandler? ExceptionOccurred; + + /// + public void RaiseExceptionOccurred(Exception exception, string _, string method) + { + ExceptionOccurred?.Invoke(this, new ExceptionOccurredEventArgs(exception, nameof(UpdateChecker), method)); + } +} \ No newline at end of file diff --git a/VPKSoft.Utils.Common/UpdateCheck/VersionData.cs b/VPKSoft.Utils.Common/UpdateCheck/VersionData.cs new file mode 100644 index 00000000..a7deff8e --- /dev/null +++ b/VPKSoft.Utils.Common/UpdateCheck/VersionData.cs @@ -0,0 +1,111 @@ +#region License +/* +MIT License + +Copyright(c) 2022 Petteri Kautonen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#endregion + +namespace VPKSoft.Utils.Common.UpdateCheck; + +/// +/// A class for single version Json data. +/// +public class VersionData +{ + /// + /// Initializes a new instance of the class. + /// + /// The version. + /// The download URL. + /// The change log. + /// The release date time. + /// if set to true the links to a file. + /// The version tag. E.g. beta-2 + public VersionData(string version, string downloadUrl, string changeLog, DateTimeOffset releaseDateTime, bool isDirectDownload, string? versionTag = null) + { + Version = version; + DownloadUrl = downloadUrl; + ChangeLog = changeLog; + VersionTag = versionTag; + ReleaseDateTime = releaseDateTime; + IsDirectDownload = isDirectDownload; + } + + /// + /// Initializes a new instance of the class. + /// + /// Default constructor for Json deserialization. + public VersionData() + { + Version = "1.0.0"; + DownloadUrl = string.Empty; + ChangeLog = string.Empty; + } + + private string version = string.Empty; + + /// + /// Gets or sets the version. + /// + /// The version. + public string Version + { + get => version; + + set + { + _ = System.Version.Parse(value); + version = value; + } + } + + /// + /// Gets or sets the version tag. + /// + /// The version tag. + public string? VersionTag { get; set; } + + /// + /// Gets or sets the download URL. + /// + /// The download URL. + public string DownloadUrl { get; set; } + + /// + /// Gets or sets the change log. + /// + /// The change log. + public string ChangeLog { get; set; } + + /// + /// Gets or sets the release date time. + /// + /// The release date time. + public DateTimeOffset ReleaseDateTime { get; set; } + + /// + /// Gets or sets a value indicating whether the links to a file. + /// + /// true if the links to a file; otherwise, false. + // ReSharper disable once UnusedAutoPropertyAccessor.Global + public bool IsDirectDownload { get; set; } +} \ No newline at end of file diff --git a/VPKSoft.Utils.Common/VPKSoft.Utils.Common.csproj b/VPKSoft.Utils.Common/VPKSoft.Utils.Common.csproj new file mode 100644 index 00000000..7afa7345 --- /dev/null +++ b/VPKSoft.Utils.Common/VPKSoft.Utils.Common.csproj @@ -0,0 +1,22 @@ + + + + netstandard2.1 + enable + bin\$(Configuration)\VPKSoft.Utils.Common.xml + latest + Library + Copyright © VPKSoft 2022 + Basic utility classes and interfaces. + https://github.com/VPKSoft + True + utils;utilities;vpksoft + MIT + True + enable + + + + + +