[#8] Add auto update checker

This commit is contained in:
2024-03-04 21:19:08 +01:00
parent ac4026571e
commit 7e1843a1b3
11 changed files with 231 additions and 4 deletions

View File

@ -31,14 +31,19 @@ namespace Elwig.Helpers {
public class Config {
private static readonly string[] TrueValues = ["1", "true", "yes", "on"];
private readonly string FileName;
public bool Debug;
public string DatabaseFile = App.DataPath + "database.sqlite3";
public string? DatabaseLog = null;
public string? Branch = null;
public string? UpdateUrl = null;
public bool UpdateAuto = false;
public IList<ScaleConfig> Scales;
private readonly List<ScaleConfig> ScaleList = [];
private static readonly string[] trueValues = ["1", "true", "yes", "on"];
public Config(string filename) {
FileName = filename;
@ -53,7 +58,9 @@ namespace Elwig.Helpers {
var log = config["database:log"];
DatabaseLog = log != null ? Path.Combine(App.DataPath, log) : null;
Branch = config["general:branch"];
Debug = trueValues.Contains(config["general:debug"]?.ToLower());
Debug = TrueValues.Contains(config["general:debug"]?.ToLower());
UpdateUrl = config["update:url"];
UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
var scales = config.AsEnumerable().Where(i => i.Key.StartsWith("scale.")).GroupBy(i => i.Key.Split(':')[0][6..]).Select(i => i.Key);
ScaleList.Clear();
@ -73,6 +80,10 @@ namespace Elwig.Helpers {
if (Debug) file.Write("debug = true\r\n");
file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n");
if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n");
file.Write($"\r\n[update]\r\n");
if (UpdateUrl != null) file.Write($"url = {UpdateUrl}\r\n");
if (UpdateAuto) file.Write($"auto = true\r\n");
foreach (var s in ScaleList) {
file.Write($"\r\n[scale.{s.Id}]\r\ntype = {s.Type}\r\nmodel = {s.Model}\r\nconnection = {s.Connection}\r\n");
if (s.Empty != null) file.Write($"empty = {s.Empty}\r\n");

View File

@ -0,0 +1,24 @@
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace Elwig.Helpers {
public static class HttpClientExtensions {
public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, IProgress<double>? progress = null, CancellationToken cancellationToken = default) {
using var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
var contentLength = response.Content.Headers.ContentLength;
using var download = await response.Content.ReadAsStreamAsync(cancellationToken);
if (progress == null || !contentLength.HasValue) {
await download.CopyToAsync(destination, cancellationToken);
return;
}
var relativeProgress = new Progress<long>(totalBytes => progress.Report((double)totalBytes / contentLength.Value));
await download.CopyToAsync(destination, 81920, relativeProgress, cancellationToken);
progress.Report(100.0);
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Elwig.Helpers {
public static class StreamExtensions {
public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long>? progress = null, CancellationToken cancellationToken = default) {
ArgumentNullException.ThrowIfNull(source);
if (!source.CanRead) throw new ArgumentException("Has to be readable", nameof(source));
ArgumentNullException.ThrowIfNull(destination);
if (!destination.CanWrite) throw new ArgumentException("Has to be writable", nameof(destination));
ArgumentOutOfRangeException.ThrowIfNegative(bufferSize);
var buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0) {
await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
}
}
}

View File

@ -12,6 +12,10 @@ using System.Text;
using System.Numerics;
using Elwig.Models.Entities;
using Elwig.Helpers.Billing;
using System.Runtime.InteropServices;
using System.Net.Http;
using System.Text.Json.Nodes;
using System.IO;
namespace Elwig.Helpers {
public static partial class Utils {
@ -61,6 +65,8 @@ namespace Elwig.Helpers {
return PhoneNrTypes.Where(t => t.Key == type).Select(t => t.Value).FirstOrDefault(type);
}
private static readonly string[] TempWildcards = ["*.html", "*.pdf", "*.exe"];
private static readonly ushort[] Crc16ModbusTable = [
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
@ -302,7 +308,7 @@ namespace Elwig.Helpers {
public static string GetSign<T>(T number) where T : INumber<T>
=> T.Sign(number) switch {
< 0 => "\u2212", // minus
0 => "\u00b1", // plus minus
0 => "\u00b1", // plus minus
> 0 => "+",
};
@ -378,5 +384,33 @@ namespace Elwig.Helpers {
.Select(s => new Varibute(s, varieties, attributes, cultivations))
.ToList();
}
[LibraryImport("wininet.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool InternetGetConnectedState(out int description, int reservedValue);
public static bool HasInternetConnectivity() {
return InternetGetConnectedState(out var _, 0);
}
public static async Task<(string Version, string Url, long Size)?> GetLatestInstallerUrl(string url) {
try {
using var client = new HttpClient() {
Timeout = TimeSpan.FromSeconds(5),
};
var res = JsonNode.Parse(await client.GetStringAsync(url));
var data = res!["data"]![0]!;
return ((string)data["version"]!, (string)data["url"]!, (int)data["size"]!);
} catch {
return null;
}
}
public static void CleanupTempFiles() {
var dir = new DirectoryInfo(App.TempPath);
foreach (var file in TempWildcards.SelectMany(dir.EnumerateFiles)) {
file.Delete();
}
}
}
}