diff --git a/GandiDynamicDns/DynamicDnsService.cs b/GandiDynamicDns/DynamicDnsService.cs index f53c0f5..655de94 100644 --- a/GandiDynamicDns/DynamicDnsService.cs +++ b/GandiDynamicDns/DynamicDnsService.cs @@ -1,86 +1,86 @@ -using GandiDynamicDns.Net.Dns; -using GandiDynamicDns.Net.Stun; -using GandiDynamicDns.Unfucked.Tasks; -using Microsoft.Extensions.Options; -using System.Diagnostics; -using System.Net; - -namespace GandiDynamicDns; - -public interface DynamicDnsService: IDisposable { - - IPAddress? selfWanAddress { get; } - -} - -public class DynamicDnsServiceImpl(DnsManager dns, SelfWanAddressClient stun, IOptions configuration, ILogger logger, IHostApplicationLifetime lifetime) - : BackgroundService, DynamicDnsService { - - private const string DNS_A_RECORD = "A"; - - public IPAddress? selfWanAddress { get; private set; } - - private readonly EventLog? eventLog = -#if WINDOWS - new("Application") { Source = "GandiDynamicDns" }; -#else - null; -#endif - - protected override async Task ExecuteAsync(CancellationToken ct) { - if ((await dns.fetchDnsRecords(configuration.Value.subdomain, configuration.Value.domain, DnsRecordType.A, ct)).FirstOrDefault() is { } existingIpAddress) { - try { - selfWanAddress = IPAddress.Parse(existingIpAddress); - } catch (FormatException) { } - } - logger.LogInformation("On startup, the {fqdn} DNS A record was pointing to {address}", configuration.Value.fqdn, selfWanAddress?.ToString() ?? "(nothing)"); - - while (!ct.IsCancellationRequested) { - await updateDnsRecordIfNecessary(ct); - - if (configuration.Value.updateInterval > TimeSpan.Zero) { - await Task2.Delay(configuration.Value.updateInterval, ct); - } else { - lifetime.StopApplication(); - break; - } - } - } - - private async Task updateDnsRecordIfNecessary(CancellationToken ct = default) { - SelfWanAddressResponse stunResponse = await stun.getSelfWanAddress(ct); - if (stunResponse.selfWanAddress != null && !stunResponse.selfWanAddress.Equals(selfWanAddress)) { - logger.LogInformation("This computer's public IP address changed from {old} to {new} according to {server} ({serverAddr}), updating {fqdn} A record in DNS server", selfWanAddress, - stunResponse.selfWanAddress, stunResponse.server.Host, stunResponse.serverAddress.ToString(), configuration.Value.fqdn); -#if WINDOWS - eventLog?.WriteEntry( - $"This computer's public IP address changed from {selfWanAddress} to {stunResponse.selfWanAddress}, according to {stunResponse.server.Host} ({stunResponse.serverAddress}), updating {configuration.Value.fqdn} A record in DNS server", - EventLogEntryType.Information, 1); -#endif - - selfWanAddress = stunResponse.selfWanAddress; - await updateDnsRecord(stunResponse.selfWanAddress, ct); - } else { - logger.LogDebug("Not updating DNS {type} record for {fqdn} because it is already set to {value}", DNS_A_RECORD, configuration.Value.fqdn, selfWanAddress); - } - } - - private async Task updateDnsRecord(IPAddress currentIPAddress, CancellationToken ct = default) { - if (!configuration.Value.dryRun) { - await dns.setDnsRecord(configuration.Value.subdomain, configuration.Value.domain, DnsRecordType.A, configuration.Value.dnsRecordTimeToLive, [currentIPAddress.ToString()], ct); - } - } - - protected virtual void Dispose(bool disposing) { - if (disposing) { - eventLog?.Dispose(); - } - } - - public sealed override void Dispose() { - Dispose(true); - base.Dispose(); - GC.SuppressFinalize(this); - } - +using GandiDynamicDns.Net.Dns; +using Microsoft.Extensions.Options; +using System.Diagnostics; +using System.Net; +using Unfucked; +using Unfucked.STUN; + +namespace GandiDynamicDns; + +public interface DynamicDnsService: IDisposable { + + IPAddress? selfWanAddress { get; } + +} + +public class DynamicDnsServiceImpl(DnsManager dns, ISelfWanAddressClient stun, IOptions configuration, ILogger logger, IHostApplicationLifetime lifetime) + : BackgroundService, DynamicDnsService { + + private const string DNS_A_RECORD = "A"; + + public IPAddress? selfWanAddress { get; private set; } + + private readonly EventLog? eventLog = +#if WINDOWS + new("Application") { Source = "GandiDynamicDns" }; +#else + null; +#endif + + protected override async Task ExecuteAsync(CancellationToken ct) { + if ((await dns.fetchDnsRecords(configuration.Value.subdomain, configuration.Value.domain, DnsRecordType.A, ct)).FirstOrDefault() is { } existingIpAddress) { + try { + selfWanAddress = IPAddress.Parse(existingIpAddress); + } catch (FormatException) { } + } + logger.LogInformation("On startup, the {fqdn} DNS A record was pointing to {address}", configuration.Value.fqdn, selfWanAddress?.ToString() ?? "(nothing)"); + + while (!ct.IsCancellationRequested) { + await updateDnsRecordIfNecessary(ct); + + if (configuration.Value.updateInterval > TimeSpan.Zero) { + await Tasks.Delay(configuration.Value.updateInterval, ct); + } else { + lifetime.StopApplication(); + break; + } + } + } + + private async Task updateDnsRecordIfNecessary(CancellationToken ct = default) { + SelfWanAddressResponse stunResponse = await stun.GetSelfWanAddress(ct); + if (stunResponse.SelfWanAddress != null && !stunResponse.SelfWanAddress.Equals(selfWanAddress)) { + logger.LogInformation("This computer's public IP address changed from {old} to {new} according to {server} ({serverAddr}), updating {fqdn} A record in DNS server", selfWanAddress, + stunResponse.SelfWanAddress, stunResponse.Server.Host, stunResponse.ServerAddress.ToString(), configuration.Value.fqdn); +#if WINDOWS + eventLog?.WriteEntry( + $"This computer's public IP address changed from {selfWanAddress} to {stunResponse.SelfWanAddress}, according to {stunResponse.Server.Host} ({stunResponse.ServerAddress}), updating {configuration.Value.fqdn} A record in DNS server", + EventLogEntryType.Information, 1); +#endif + + selfWanAddress = stunResponse.SelfWanAddress; + await updateDnsRecord(stunResponse.SelfWanAddress, ct); + } else { + logger.LogDebug("Not updating DNS {type} record for {fqdn} because it is already set to {value}", DNS_A_RECORD, configuration.Value.fqdn, selfWanAddress); + } + } + + private async Task updateDnsRecord(IPAddress currentIPAddress, CancellationToken ct = default) { + if (!configuration.Value.dryRun) { + await dns.setDnsRecord(configuration.Value.subdomain, configuration.Value.domain, DnsRecordType.A, configuration.Value.dnsRecordTimeToLive, [currentIPAddress.ToString()], ct); + } + } + + protected virtual void Dispose(bool disposing) { + if (disposing) { + eventLog?.Dispose(); + } + } + + public sealed override void Dispose() { + Dispose(true); + base.Dispose(); + GC.SuppressFinalize(this); + } + } \ No newline at end of file diff --git a/GandiDynamicDns/GandiDynamicDns.csproj b/GandiDynamicDns/GandiDynamicDns.csproj index 95c5956..07e62a4 100644 --- a/GandiDynamicDns/GandiDynamicDns.csproj +++ b/GandiDynamicDns/GandiDynamicDns.csproj @@ -1,52 +1,69 @@ - - - - Exe - net8.0;net8.0-windows - win-x64;win-arm64;linux-x64;linux-arm;linux-arm64 - enable - enable - latestMajor - latest - $(NoWarn);8524;VSTHRD200 - 0.2.0 - Ben Hutchison - © 2024 $(Authors) - $(Authors) - Gandi Dynamic DNS - true - favicon.ico - app.manifest - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - PreserveNewest - - - - - - - + + + + Exe + net8.0;net8.0-windows + win-x64;win-arm64;linux-x64;linux-arm;linux-arm64 + enable + enable + latestMajor + latest + $(NoWarn);8524;VSTHRD200 + 0.2.1 + Ben Hutchison + © 2024 $(Authors) + $(Authors) + Gandi Dynamic DNS + true + favicon.ico + app.manifest + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + PreserveNewest + + + + + + + + + + ..\..\Unfucked\Unfucked\bin\Debug\net8.0\Unfucked.dll + + + ..\..\Unfucked\Caching\bin\Debug\netstandard2.0\Unfucked.Caching.dll + + + ..\..\Unfucked\DI\bin\Debug\net6.0\Unfucked.DI.dll + + + ..\..\Unfucked\DNS\bin\Debug\net6.0\Unfucked.DNS.dll + + + ..\..\Unfucked\STUN\bin\Debug\net8.0\Unfucked.STUN.dll + + + \ No newline at end of file diff --git a/GandiDynamicDns/Net/Dns/GandiDnsManager.cs b/GandiDynamicDns/Net/Dns/GandiDnsManager.cs index 01f829d..0cb2e29 100644 --- a/GandiDynamicDns/Net/Dns/GandiDnsManager.cs +++ b/GandiDynamicDns/Net/Dns/GandiDnsManager.cs @@ -1,31 +1,38 @@ -using GandiDynamicDns.Unfucked.Dns; - -namespace GandiDynamicDns.Net.Dns; - -public interface DnsManager { - - Task> fetchDnsRecords(string subdomain, string domain, DnsRecordType type = DnsRecordType.A, CancellationToken ct = default); - - Task setDnsRecord(string subdomain, string domain, DnsRecordType type, TimeSpan timeToLive, IEnumerable values, CancellationToken ct = default); - -} - -public class GandiDnsManager(IGandiLiveDns gandi): DnsManager { - - public static readonly TimeSpan MINIMUM_TIME_TO_LIVE = TimeSpan.FromSeconds(300); // 5 minutes - private static readonly TimeSpan MAXIMUM_TIME_TO_LIVE = TimeSpan.FromSeconds(2_592_000); // 30 days - - public async Task> fetchDnsRecords(string subdomain, string domain, DnsRecordType type = DnsRecordType.A, CancellationToken ct = default) => - from record in await gandi.GetDomainRecords(domain, ct) - where record.rrset_type == type.ToString() && record.rrset_name == subdomain && record.rrset_values.LongLength != 0 - select record.rrset_values[0]; - - public async Task setDnsRecord(string subdomain, string domain, DnsRecordType type, TimeSpan timeToLive, IEnumerable values, CancellationToken ct = default) => - await gandi.PutDomainRecord(domain: domain, - name: subdomain, - type: type.ToString(), - values: values.ToArray(), - ttl: (int) (timeToLive > MINIMUM_TIME_TO_LIVE ? timeToLive < MAXIMUM_TIME_TO_LIVE ? timeToLive : MAXIMUM_TIME_TO_LIVE : MINIMUM_TIME_TO_LIVE).TotalSeconds, - cancellationToken: ct); - +using Unfucked.DNS; + +namespace GandiDynamicDns.Net.Dns; + +public interface DnsManager { + + Task> fetchDnsRecords(string subdomain, string domain, DnsRecordType type = DnsRecordType.A, CancellationToken ct = default); + + Task setDnsRecord(string subdomain, string domain, DnsRecordType type, TimeSpan timeToLive, IEnumerable values, CancellationToken ct = default); + +} + +public class GandiDnsManager(IGandiLiveDns gandi): DnsManager { + + /// + /// 5 minutes + /// + public static readonly TimeSpan MINIMUM_TIME_TO_LIVE = TimeSpan.FromSeconds(300); + + /// + /// 30 days + /// + private static readonly TimeSpan MAXIMUM_TIME_TO_LIVE = TimeSpan.FromSeconds(2_592_000); + + public async Task> fetchDnsRecords(string subdomain, string domain, DnsRecordType type = DnsRecordType.A, CancellationToken ct = default) => + from record in await gandi.GetDomainRecords(domain, ct) + where record.rrset_type == type.ToString() && record.rrset_name == subdomain && record.rrset_values.LongLength != 0 + select record.rrset_values[0]; + + public async Task setDnsRecord(string subdomain, string domain, DnsRecordType type, TimeSpan timeToLive, IEnumerable values, CancellationToken ct = default) => + await gandi.PutDomainRecord(domain: domain, + name: subdomain, + type: type.ToString(), + values: values.ToArray(), + ttl: (int) (timeToLive > MINIMUM_TIME_TO_LIVE ? timeToLive < MAXIMUM_TIME_TO_LIVE ? timeToLive : MAXIMUM_TIME_TO_LIVE : MINIMUM_TIME_TO_LIVE).TotalSeconds, + cancellationToken: ct); + } \ No newline at end of file diff --git a/GandiDynamicDns/Net/Stun/MultiServerStunClient.cs b/GandiDynamicDns/Net/Stun/MultiServerStunClient.cs deleted file mode 100644 index c9dfb79..0000000 --- a/GandiDynamicDns/Net/Stun/MultiServerStunClient.cs +++ /dev/null @@ -1,155 +0,0 @@ -using GandiDynamicDns.Unfucked.Caching; -using GandiDynamicDns.Unfucked.Stun; -using GandiDynamicDns.Util; -using Microsoft.Extensions.Options; -using STUN.Enums; -using STUN.StunResult; -using System.Collections.Frozen; -using System.Net; -using System.Runtime.CompilerServices; - -namespace GandiDynamicDns.Net.Stun; - -public class MultiServerStunClient(HttpClient http, StunClientFactory stunClientFactory, ILogger logger, IOptions config): IStunClient5389 { - - private static readonly Random RANDOM = new(); - private static readonly TimeSpan STUN_LIST_CACHE_DURATION = TimeSpan.FromDays(1); - - // ExceptionAdjustment: M:System.Uri.#ctor(System.String) -T:System.UriFormatException - private static readonly Uri STUN_SERVER_LIST_URL = new("https://raw.githubusercontent.com/pradt2/always-online-stun/master/valid_hosts.txt"); - - internal static readonly IMemoryCache> SERVERS_CACHE = new MemoryCache>($"{nameof(MultiServerStunClient)}.{nameof(SERVERS_CACHE)}"); - - private static readonly IList FALLBACK_SERVERS = [ - new DnsEndPoint("stun.ekiga.net", 3478), - new DnsEndPoint("stun.freeswitch.org", 3478), - new DnsEndPoint("stun1.l.google.com", 19302), - new DnsEndPoint("stun2.l.google.com", 19302), - new DnsEndPoint("stun3.l.google.com", 19302), - new DnsEndPoint("stun4.l.google.com", 19302) - ]; - - private readonly IReadOnlySet blacklistedServers = config.Value.stunServerBlacklist.Concat([ - "stun.bergophor.de", // Some German agriculture company. 87.129.12.229 incorrectly told me that my IP address was 192.168.80.67 - "stun.usfamily.net" // Some small-town Minnesota ISP. 64.131.63.216 and 64.131.63.217 told me that my IP address was a wide variety of incorrect values, including 107.12.198.224, 121.5.32.247, 136.249.128.168, 151.70.235.94, 170.87.255.116, 189.172.15.230, 199.225.99.231, 237.120.242.186, 25.32.55.201, 54.65.6.154, 55.204.238.254, 79.244.154.201, 8.144.106.11, 87.46.19.57, and 99.93.120.192 - ]).Select(s => s.ToLowerInvariant()).ToFrozenSet(); - - public StunResult5389 State { get; private set; } = new(); - public DnsEndPoint Server { get; private set; } = null!; - public IPEndPoint ServerAddress { get; private set; } = null!; - - private async IAsyncEnumerable getStunClients([EnumeratorCancellation] CancellationToken ct = default) { - const string STUN_LIST_CACHE_KEY = "always-on-stun"; - DnsEndPoint[] servers = []; - try { - servers = (await SERVERS_CACHE.GetOrAdd(STUN_LIST_CACHE_KEY, async () => await fetchStunServers(ct), STUN_LIST_CACHE_DURATION)).ToArray(); - } catch (HttpRequestException) { } catch (TaskCanceledException) { /* timeout */ - } catch (Exception e) when (e is not OutOfMemoryException) { } - - RANDOM.Shuffle(servers); - - foreach (DnsEndPoint host in servers.Concat(FALLBACK_SERVERS)) { - if (await stunClientFactory.createStunClient(host) is { } stunClient) { - yield return stunClient; - } - } - } - - /// - /// - private async Task> fetchStunServers(CancellationToken ct) { - logger.LogDebug("Fetching list of STUN servers from pradt2/always-online-stun"); - ICollection servers = (await http.GetStringAsync(STUN_SERVER_LIST_URL, ct)) - .TrimEnd() - .Split('\n') - .Select(line => { - string[] columns = line.Split(':', 2); - try { - return new DnsEndPoint(columns[0], columns.ElementAtOrDefault(1) is { } port ? ushort.Parse(port) : 3478); - } catch (FormatException) { - return null; - } - }) - .Compact() - .ExceptBy(blacklistedServers, host => host.Host) - .ToList(); - - logger.LogDebug("Fetched {count:N0} STUN servers", servers.Count); - return servers; - } - - public async ValueTask QueryAsync(CancellationToken cancellationToken = default) { - await foreach (IStunClient5389 stun in getStunClients(cancellationToken)) { - using (stun) { - Server = stun.Server; - ServerAddress = stun.ServerAddress; - await stun.QueryAsync(cancellationToken); - State = stun.State; - if (isSuccessfulResponse(State)) { - break; - } else { - logger.LogWarning("STUN request to {host} ({addr}:{port}) failed, trying another server", stun.Server.Host, stun.ServerAddress.Address, stun.ServerAddress.Port); - } - } - } - } - - public async ValueTask BindingTestAsync(CancellationToken cancellationToken = default) { - await foreach (IStunClient5389 stun in getStunClients(cancellationToken)) { - using (stun) { - Server = stun.Server; - ServerAddress = stun.ServerAddress; - logger.LogDebug("Sending UDP STUN request to {host} ({addr}:{port})", stun.Server.Host, stun.ServerAddress.Address, stun.ServerAddress.Port); - State = await stun.BindingTestAsync(cancellationToken); - if (isSuccessfulResponse(State)) { - break; - } else { - logger.LogWarning("STUN request to {host} ({addr}:{port}) failed, trying another server", stun.Server.Host, stun.ServerAddress.Address, stun.ServerAddress.Port); - } - } - } - return State; - } - - public async ValueTask MappingBehaviorTestAsync(CancellationToken cancellationToken = default) { - await foreach (IStunClient5389 stun in getStunClients(cancellationToken)) { - using (stun) { - Server = stun.Server; - ServerAddress = stun.ServerAddress; - await stun.MappingBehaviorTestAsync(cancellationToken); - State = stun.State; - if (isSuccessfulResponse(State)) { - break; - } else { - logger.LogWarning("STUN request to {host} ({addr}:{port}) failed, trying another server", stun.Server.Host, stun.ServerAddress.Address, stun.ServerAddress.Port); - } - } - } - } - - public async ValueTask FilteringBehaviorTestAsync(CancellationToken cancellationToken = default) { - await foreach (IStunClient5389 stun in getStunClients(cancellationToken)) { - using (stun) { - Server = stun.Server; - ServerAddress = stun.ServerAddress; - await stun.FilteringBehaviorTestAsync(cancellationToken); - State = stun.State; - if (isSuccessfulResponse(State)) { - break; - } else { - logger.LogWarning("STUN request to {host} ({addr}:{port}) failed, trying another server", stun.Server.Host, stun.ServerAddress.Address, stun.ServerAddress.Port); - } - } - } - } - - private static bool isSuccessfulResponse(StunResult5389 response) => - response.BindingTestResult != BindingTestResult.Fail && - response.BindingTestResult != BindingTestResult.UnsupportedServer && - response.FilteringBehavior != FilteringBehavior.UnsupportedServer && - response.MappingBehavior != MappingBehavior.Fail && - response.MappingBehavior != MappingBehavior.UnsupportedServer; - - public void Dispose() => GC.SuppressFinalize(this); - -} \ No newline at end of file diff --git a/GandiDynamicDns/Net/Stun/ThreadSafeMultiServerStunClient.cs b/GandiDynamicDns/Net/Stun/ThreadSafeMultiServerStunClient.cs deleted file mode 100644 index ae31415..0000000 --- a/GandiDynamicDns/Net/Stun/ThreadSafeMultiServerStunClient.cs +++ /dev/null @@ -1,25 +0,0 @@ -using GandiDynamicDns.Unfucked.DependencyInjection; -using GandiDynamicDns.Unfucked.Stun; -using STUN.Enums; -using STUN.StunResult; -using System.Net; - -namespace GandiDynamicDns.Net.Stun; - -public interface SelfWanAddressClient { - - Task getSelfWanAddress(CancellationToken ct = default); - -} - -public record SelfWanAddressResponse(IPAddress? selfWanAddress, DnsEndPoint server, IPEndPoint serverAddress); - -public class ThreadSafeMultiServerStunClient(Provider stunProvider): SelfWanAddressClient { - - public async Task getSelfWanAddress(CancellationToken ct = default) { - using IStunClient5389 stun = stunProvider.get(); - StunResult5389 response = await stun.BindingTestAsync(ct); - return new SelfWanAddressResponse(response.BindingTestResult == BindingTestResult.Success ? response.PublicEndPoint?.Address : null, stun.Server, stun.ServerAddress); - } - -} \ No newline at end of file diff --git a/GandiDynamicDns/Program.cs b/GandiDynamicDns/Program.cs index 4d485ff..9906fb3 100644 --- a/GandiDynamicDns/Program.cs +++ b/GandiDynamicDns/Program.cs @@ -1,48 +1,45 @@ -using GandiDynamicDns; -using GandiDynamicDns.Net.Dns; -using GandiDynamicDns.Net.Stun; -using GandiDynamicDns.Unfucked.Dns; -using GandiDynamicDns.Unfucked.Stun; -using GandiDynamicDns.Util; -using Microsoft.Extensions.Options; -using System.Net.Security; -using System.Security.Authentication; - -HostApplicationBuilder appConfig = Host.CreateApplicationBuilder(args); - -appConfig.Logging.AddConsole(options => options.FormatterName = MyConsoleFormatter.NAME).AddConsoleFormatter(options => { - options.includeNamespaces = false; -}); - -appConfig.Configuration.AlsoSearchForJsonFilesInExecutableDirectory(); - -appConfig.Services - .AddLogging() - .AddInjectableProviders() - .AddSystemd() - .AddWindowsService(WindowsService.configure) - .Configure(appConfig.Configuration) - .AddSingleton(_ => new HttpClient(new SocketsHttpHandler { - AllowAutoRedirect = true, - ConnectTimeout = TimeSpan.FromSeconds(10), - PooledConnectionLifetime = TimeSpan.FromMinutes(15), - MaxConnectionsPerServer = 8, - SslOptions = new SslClientAuthenticationOptions { - EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13 - } - })) - .AddHostedService() - .AddSingleton(provider => { - string apiKey = provider.GetRequiredService>().Value.gandiApiKey; - if (string.IsNullOrWhiteSpace(apiKey) || apiKey == "") { - throw new ArgumentException($"Missing configuration option {nameof(Configuration.gandiApiKey)} in appsettings.json"); - } - return new GandiLiveDns { ApiKey = apiKey }; - }) - .AddSingleton() - .AddTransient() - .AddSingleton() - .AddSingleton(); - -using IHost app = appConfig.Build(); +using GandiDynamicDns; +using GandiDynamicDns.Net.Dns; +using GandiDynamicDns.Util; +using Microsoft.Extensions.Options; +using System.Net.Security; +using System.Security.Authentication; +using Unfucked; +using Unfucked.DNS; +using Unfucked.STUN; + +HostApplicationBuilder appConfig = Host.CreateApplicationBuilder(args); + +appConfig.Logging.AddUnfuckedConsole(); + +appConfig.Configuration.AlsoSearchForJsonFilesInExecutableDirectory(); + +appConfig.Services + .AddLogging() + .AddSystemd() + .AddWindowsService(WindowsService.configure) + .Configure(appConfig.Configuration) + .AddSingleton(_ => new HttpClient(new SocketsHttpHandler { + AllowAutoRedirect = true, + ConnectTimeout = TimeSpan.FromSeconds(10), + PooledConnectionLifetime = TimeSpan.FromMinutes(15), + MaxConnectionsPerServer = 8, + SslOptions = new SslClientAuthenticationOptions { + EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13 + } + }) { Timeout = TimeSpan.FromSeconds(20) }) + .AddHostedService() + .SetExitCodeOnBackgroundServiceException() + .AddSingleton(provider => { + string apiKey = provider.GetRequiredService>().Value.gandiApiKey; + if (string.IsNullOrWhiteSpace(apiKey) || apiKey == "") { + throw new ArgumentException($"Missing configuration option {nameof(Configuration.gandiApiKey)} in appsettings.json"); + } + return new GandiLiveDns { ApiKey = apiKey }; + }) + .AddSingleton() + .AddStunClient(ctx => new StunOptions { serverHostnameBlacklist = ctx.GetRequiredService>().Value.stunServerBlacklist }); + +using IHost app = appConfig.Build(); + await app.RunAsync(); \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Caching/IMemoryCache.cs b/GandiDynamicDns/Unfucked/Caching/IMemoryCache.cs deleted file mode 100644 index f3cb842..0000000 --- a/GandiDynamicDns/Unfucked/Caching/IMemoryCache.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System.Runtime.Caching; - -// ReSharper disable InconsistentNaming - -namespace GandiDynamicDns.Unfucked.Caching; - -/// -/// Like , but strongly typed -/// -/// The type of the value to cache -public interface IMemoryCache: IDisposable where T: notnull { - - #region New Methods - - /// - /// Lazy/deferred synchronous upsert with custom cache item policy - /// - /// Cache key - /// Function that creates the value, will be called (possibly multiple times) if the key is not present in the cache, but 0 times if it is present - /// custom cache item policy - /// The old cached value if it already existed, or the new value returned and cached from otherwise - T GetOrAdd(string key, Func valueCreator, CacheItemPolicy? policy = default); - - /// - /// Lazy/deferred synchronous upsert with custom cache item policy - /// - /// Cache key - /// Function that creates the value, will be called (possibly multiple times) if the key is not present in the cache, but 0 times if it is present - /// cache item lifetime after write - /// The old cached value if it already existed, or the new value returned and cached from otherwise - T GetOrAdd(string key, Func valueCreator, TimeSpan evictAfterCreation); - - /// - /// Lazy/deferred asynchronous upsert with custom cache item policy - /// - /// Cache key - /// Function that asynchronously creates the value, will be called (possibly multiple times) if the key is not present in the cache, but 0 times if it is present - /// custom cache item policy - /// The old cached value if it already existed, or the new value returned and cached from otherwise - Task GetOrAdd(string key, Func> valueCreator, CacheItemPolicy? policy = null); - - /// - /// Lazy/deferred asynchronous upsert with custom cache item policy - /// - /// Cache key - /// Function that asynchronously creates the value, will be called (possibly multiple times) if the key is not present in the cache, but 0 times if it is present - /// cache item lifetime after write - /// The old cached value if it already existed, or the new value returned and cached from otherwise - Task GetOrAdd(string key, Func> valueCreator, TimeSpan evictAfterCreation); - - /// - /// Remove all entries from the cache - /// - void Clear(); - - #endregion - - #region Delegated - - /// - IEnumerator GetEnumerator(); - - /// - bool Add(string key, T value, DateTimeOffset absoluteExpiration); - - /// - bool Add(string key, T value, CacheItemPolicy policy); - - /// - bool Add(CacheItem item, CacheItemPolicy policy); - - /// - IDictionary? GetValues(params string[] keys); - - /// - IDictionary GetValues(IEnumerable keys); - - /// - CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(IEnumerable keys); - - /// - long Trim(int percent); - - /// - bool Contains(string key); - - /// - T AddOrGetExisting(string key, T value, DateTimeOffset absoluteExpiration); - - /// - CacheItem AddOrGetExisting(CacheItem item, CacheItemPolicy policy); - - /// - T AddOrGetExisting(string key, T value, CacheItemPolicy policy); - - /// When overridden in a derived class, gets the specified cache entry from the cache as an object. - /// A unique identifier for the cache entry to get. - /// The cache entry that is identified by . - T? Get(string key); - - /// - CacheItem? GetCacheItem(string key); - - /// - void Set(string key, T value, DateTimeOffset absoluteExpiration); - - /// - void Set(CacheItem item, CacheItemPolicy policy); - - /// - void Set(string key, T value, CacheItemPolicy policy); - - /// - T? Remove(string key); - - /// - T? Remove(string key, CacheEntryRemovedReason reason); - - /// - long GetCount(string? regionName = null); - - /// - long GetLastSize(string? regionName = null); - - /// - long CacheMemoryLimit { get; } - - /// - DefaultCacheCapabilities DefaultCacheCapabilities { get; } - - /// - string Name { get; } - - /// - long PhysicalMemoryLimit { get; } - - /// - TimeSpan PollingInterval { get; } - - /// - T? this[string key] { get; set; } - - #endregion - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Caching/MemoryCache.cs b/GandiDynamicDns/Unfucked/Caching/MemoryCache.cs deleted file mode 100644 index 5ac5a7d..0000000 --- a/GandiDynamicDns/Unfucked/Caching/MemoryCache.cs +++ /dev/null @@ -1,181 +0,0 @@ -using JetBrains.Annotations; -using System.Collections.Specialized; -using System.Runtime.Caching; -using MemoryCache = System.Runtime.Caching.MemoryCache; - -// ReSharper disable InconsistentNaming - -namespace GandiDynamicDns.Unfucked.Caching; - -/// -public class MemoryCache(string name = "", NameValueCollection? config = null, bool ignoreConfigSection = false): IMemoryCache where T: notnull { - - private readonly MemoryCache cache = new(name, config, ignoreConfigSection); - - #region New Methods - - /// - public T GetOrAdd(string key, Func valueCreator, CacheItemPolicy? policy = null) { - return Get(key) ?? AddOrGetExisting(key, valueCreator(), policy ?? new CacheItemPolicy()); - } - - /// - public T GetOrAdd(string key, Func valueCreator, TimeSpan evictAfterCreation) { - return GetOrAdd(key, valueCreator, new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now + evictAfterCreation }); - } - - /// - public async Task GetOrAdd(string key, Func> valueCreator, CacheItemPolicy? policy = null) { - return Get(key) ?? AddOrGetExisting(key, await valueCreator(), policy ?? new CacheItemPolicy()); - } - - /// - public async Task GetOrAdd(string key, Func> valueCreator, TimeSpan evictAfterCreation) { - return await GetOrAdd(key, valueCreator, new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now + evictAfterCreation }); - } - - public void Clear() { - Trim(100); - } - - #endregion - - #region Delegated - - /// - [MustDisposeResource] - public IEnumerator GetEnumerator() { - return ((IEnumerable) cache).GetEnumerator(); - } - - /// - public bool Add(string key, T value, DateTimeOffset absoluteExpiration) { - return cache.Add(key, value, absoluteExpiration); - } - - /// - public bool Add(string key, T value, CacheItemPolicy policy) { - return cache.Add(key, value, policy); - } - - /// - public IDictionary? GetValues(params string[] keys) { - return cache.GetValues(null, keys) as IDictionary; - } - - /// - public CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(IEnumerable keys) { - return cache.CreateCacheEntryChangeMonitor(keys); - } - - /// - public void Dispose() { - cache.Dispose(); - GC.SuppressFinalize(this); - } - - /// - public long Trim(int percent) { - return cache.Trim(percent); - } - - /// - public bool Contains(string key) { - return cache.Contains(key); - } - - /// - public bool Add(CacheItem item, CacheItemPolicy policy) { - return cache.Add(item, policy); - } - - /// - public T AddOrGetExisting(string key, T value, DateTimeOffset absoluteExpiration) { - return (T) cache.AddOrGetExisting(key, value, absoluteExpiration) ?? value; - } - - /// - public CacheItem AddOrGetExisting(CacheItem item, CacheItemPolicy policy) { - return cache.AddOrGetExisting(item, policy); - } - - /// - public T AddOrGetExisting(string key, T value, CacheItemPolicy policy) { - return (T) cache.AddOrGetExisting(key, value, policy) ?? value; - } - - /// - // ExceptionAdjustment: M:System.Runtime.Caching.MemoryCache.Get(System.String,System.String) -T:System.NotSupportedException - public T? Get(string key) { - return (T?) cache.Get(key); - } - - /// - public CacheItem? GetCacheItem(string key) { - return cache.GetCacheItem(key); - } - - /// - public void Set(string key, T value, DateTimeOffset absoluteExpiration) { - cache.Set(key, value, absoluteExpiration); - } - - /// - public void Set(CacheItem item, CacheItemPolicy policy) { - cache.Set(item, policy); - } - - /// - public void Set(string key, T value, CacheItemPolicy policy) { - cache.Set(key, value, policy); - } - - /// - public T? Remove(string key) { - return (T?) cache.Remove(key); - } - - /// - public T? Remove(string key, CacheEntryRemovedReason reason) { - return (T?) cache.Remove(key, reason); - } - - /// - public long GetCount(string? regionName = null) { - return cache.GetCount(regionName); - } - - /// - public long GetLastSize(string? regionName = null) { - return cache.GetLastSize(regionName); - } - - /// - public IDictionary GetValues(IEnumerable keys) { - return (IDictionary) cache.GetValues(keys); - } - - /// - public long CacheMemoryLimit => cache.CacheMemoryLimit; - - /// - public DefaultCacheCapabilities DefaultCacheCapabilities => cache.DefaultCacheCapabilities; - - /// - public string Name => cache.Name; - - /// - public long PhysicalMemoryLimit => cache.PhysicalMemoryLimit; - - /// - public TimeSpan PollingInterval => cache.PollingInterval; - - /// - public T? this[string key] { - get => (T?) cache[key]; - set => cache[key] = value; - } - - #endregion - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/DependencyInjection/Provider.cs b/GandiDynamicDns/Unfucked/DependencyInjection/Provider.cs deleted file mode 100644 index f4d720d..0000000 --- a/GandiDynamicDns/Unfucked/DependencyInjection/Provider.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace GandiDynamicDns.Unfucked.DependencyInjection; - -/// -/// Declarative injection of dependencies with shorter lifetimes into dependents with longer lifetimes, like javax.inject.Provider<T>, without the complication of creating scopes, so you don't have a inject an and imperatively request everything, which isn't very DI-like. -/// -/// Type to request from IoC container -public interface OptionalProvider { - - T? get(); - -} - -/// -public interface Provider: OptionalProvider where T: notnull { - - new T get(); - -} - -/// -public class MicrosoftDependencyInjectionServiceProvider(IServiceProvider services): Provider where T: notnull { - - public T get() => services.GetRequiredService(); - - T? OptionalProvider.get() => services.GetService(); - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Dns/GandiLiveDns.cs b/GandiDynamicDns/Unfucked/Dns/GandiLiveDns.cs deleted file mode 100644 index 6f34423..0000000 --- a/GandiDynamicDns/Unfucked/Dns/GandiLiveDns.cs +++ /dev/null @@ -1,75 +0,0 @@ -using G6.GandiLiveDns; -using System.CodeDom.Compiler; -using System.Diagnostics; -using System.Reflection; - -// ReSharper disable InconsistentNaming - these names must match a third-party library - -namespace GandiDynamicDns.Unfucked.Dns; - -[GeneratedCode("G6.GandiLiveDns", "1.0.0")] -public class GandiLiveDns: IGandiLiveDns { - - #region New - - private readonly G6.GandiLiveDns.GandiLiveDns gandi; - - private readonly bool shouldDisposeHttpClient; - - private GandiLiveDns(G6.GandiLiveDns.GandiLiveDns gandi, bool shouldDisposeHttpClient) { - this.gandi = gandi; - this.shouldDisposeHttpClient = shouldDisposeHttpClient; - } - - public GandiLiveDns(): this(new G6.GandiLiveDns.GandiLiveDns(), true) { } - - public GandiLiveDns(string baseUrl, HttpClient httpClient): this(new G6.GandiLiveDns.GandiLiveDns(baseUrl, httpClient), false) { } - - public void Dispose() { - if (shouldDisposeHttpClient) { - ((HttpClient) typeof(G6.GandiLiveDns.GandiLiveDns).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).First(f => f.FieldType == typeof(HttpClient)).GetValue(gandi)!).Dispose(); - } - } - - #endregion - - #region Delegated - - public string BaseUrl { - [DebuggerStepThrough] get => gandi.BaseUrl; - [DebuggerStepThrough] set => gandi.BaseUrl = value; - } - - public string ApiKey { - [DebuggerStepThrough] get => gandi.Apikey; - [DebuggerStepThrough] set => gandi.Apikey = value; - } - - public bool ReadResponseAsString { - [DebuggerStepThrough] get => gandi.ReadResponseAsString; - [DebuggerStepThrough] set => gandi.ReadResponseAsString = value; - } - - [DebuggerStepThrough] - public async Task> GetDomainRecords(string domain, CancellationToken cancellationToken) { - return await gandi.GetDomainRecords(domain, cancellationToken); - } - - [DebuggerStepThrough] - public async Task PostDomainRecord(string domain, string name, string type, string[] values, int ttl, CancellationToken cancellationToken) { - return await gandi.PostDomainRecord(domain, name, type, values, ttl, cancellationToken); - } - - [DebuggerStepThrough] - public async Task PutDomainRecord(string domain, string name, string type, string[] values, int ttl, CancellationToken cancellationToken) { - return await gandi.PutDomainRecord(domain, name, type, values, ttl, cancellationToken); - } - - [DebuggerStepThrough] - public async Task DeleteDomainRecord(string domain, string name, string type, CancellationToken cancellationToken) { - return await gandi.DeleteDomainRecord(domain, name, type, cancellationToken); - } - - #endregion - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Dns/IGandiLiveDns.cs b/GandiDynamicDns/Unfucked/Dns/IGandiLiveDns.cs deleted file mode 100644 index 0acfcf9..0000000 --- a/GandiDynamicDns/Unfucked/Dns/IGandiLiveDns.cs +++ /dev/null @@ -1,79 +0,0 @@ -using G6.GandiLiveDns; -using System.CodeDom.Compiler; - -// ReSharper disable InconsistentNaming - these names must match a third-party library - -namespace GandiDynamicDns.Unfucked.Dns; - -/// -/// Gandi LiveDNS Management API -/// Documentation: -/// Marketing page: -/// -[GeneratedCode("G6.GandiLiveDns", "1.0.0")] -public interface IGandiLiveDns: IDisposable { - - /// - /// Defaults to https://api.gandi.net/v5/livedns for production. - /// To use the Gandi Public API Sandbox, set this to https://api.sandbox.gandi.net/v5/livedns, create a sandbox account at , and create a sandbox API key at to set in . - /// - string BaseUrl { get; set; } - - /// - /// The API Key is the previous mechanism used to do public api calls. They cannot be scoped, they have the same set of permission than the owner of the API Key and users can't have two api keys at the same time. - /// You can generate or delete your production API key from the API Key Page (, in the Security section). - /// Documentation: - /// - string ApiKey { get; set; } - - /// - /// Documentation: - /// List records associated with a domain - /// - /// Domain name - /// Allows the request can be canceled - /// List of DNS records for the given - /// if the request was unauthorized (401) or forbidden (403) - Task> GetDomainRecords(string domain, CancellationToken cancellationToken); - - /// - /// Creates a new record. Will raise a 409 conflict if the record already exists, and return a 200 OK if the record already exists WITH THE SAME VALUES. - /// Documentation: - /// - /// Domain name - /// Name of the record - /// One of: A, AAAA, ALIAS, CAA, CDS, CNAME, DNAME, DS, KEY, LOC, MX, NAPTR, NS, OPENPGPKEY, PTR, RP, SPF, SRV, SSHFP, TLSA, TXT, WKS - /// A list of values for this record - /// Minimum: 300, maximum: 2592000. The time in seconds that DNS resolvers should cache this record. - /// Allows the request can be canceled - /// true if the record was created (otherwise, an is thrown, false is never returned) - /// if the request was unauthorized (401), or forbidden (403), or the DNS record already existed (409) - Task PostDomainRecord(string domain, string name, string type, string[] values, int ttl, CancellationToken cancellationToken); - - /// - /// Overwrites a single record with and - /// Documentation: - /// - /// Domain name - /// Name of the record - /// One of: A, AAAA, ALIAS, CAA, CDS, CNAME, DNAME, DS, KEY, LOC, MX, NAPTR, NS, OPENPGPKEY, PTR, RP, SPF, SRV, SSHFP, TLSA, TXT, WKS - /// A list of values for this record - /// Minimum: 300, maximum: 2592000. The time in seconds that DNS resolvers should cache this record. - /// Allows the request can be canceled - /// true if the record was created (otherwise, an is thrown, false is never returned) - /// if the request was unauthorized (401) or forbidden (403) - Task PutDomainRecord(string domain, string name, string type, string[] values, int ttl, CancellationToken cancellationToken); - - /// - /// Delete record with and - /// Documentation: - /// - /// Domain name - /// Name of the record - /// One of: A, AAAA, ALIAS, CAA, CDS, CNAME, DNAME, DS, KEY, LOC, MX, NAPTR, NS, OPENPGPKEY, PTR, RP, SPF, SRV, SSHFP, TLSA, TXT, WKS - /// Allows the request can be canceled - /// true if the record was deleted or could not be found (otherwise, an is thrown, false is never returned) - /// if the request was unauthorized (401) or forbidden (403) - Task DeleteDomainRecord(string domain, string name, string type, CancellationToken cancellationToken); - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Stun/StunClient5389UDP.cs b/GandiDynamicDns/Unfucked/Stun/StunClient5389UDP.cs deleted file mode 100644 index 714bb7b..0000000 --- a/GandiDynamicDns/Unfucked/Stun/StunClient5389UDP.cs +++ /dev/null @@ -1,34 +0,0 @@ -using STUN.Proxy; -using System.Net; - -// ReSharper disable InconsistentNaming - -namespace GandiDynamicDns.Unfucked.Stun; - -/// -/// Like but it allows consumers to introspect the STUN server that the instance was configured with, without restoring to reflection on private fields. -/// -public interface IStunClient5389: STUN.Client.IStunClient5389 { - - /// - /// The STUN server IP address and port that this instance was configured with. - /// - IPEndPoint ServerAddress { get; } - - /// - /// The STUN server hostname and port that this instance was configured with. - /// - DnsEndPoint Server { get; } - -} - -/// -public class StunClient5389UDP(IPEndPoint server, string serverName, IPEndPoint local, IUdpProxy? proxy = null): STUN.Client.StunClient5389UDP(server, local, proxy), IStunClient5389 { - - /// - public IPEndPoint ServerAddress { get; } = server; - - /// - public DnsEndPoint Server { get; } = new(serverName, server.Port); - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Stun/StunClientFactory.cs b/GandiDynamicDns/Unfucked/Stun/StunClientFactory.cs deleted file mode 100644 index 6fec770..0000000 --- a/GandiDynamicDns/Unfucked/Stun/StunClientFactory.cs +++ /dev/null @@ -1,18 +0,0 @@ -using GandiDynamicDns.Util; -using System.Net; - -namespace GandiDynamicDns.Unfucked.Stun; - -public interface StunClientFactory { - - Task createStunClient(DnsEndPoint server); - -} - -public class StunClient5389Factory: StunClientFactory { - - private static readonly IPEndPoint LOCAL_HOST = new(IPAddress.Any, 0); - - public async Task createStunClient(DnsEndPoint server) => await server.Resolve() is { } addr ? new StunClient5389UDP(addr, server.Host, LOCAL_HOST) : null; - -} \ No newline at end of file diff --git a/GandiDynamicDns/Unfucked/Tasks/Task2.cs b/GandiDynamicDns/Unfucked/Tasks/Task2.cs deleted file mode 100644 index 1108b54..0000000 --- a/GandiDynamicDns/Unfucked/Tasks/Task2.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace GandiDynamicDns.Unfucked.Tasks; - -// ReSharper disable InconsistentNaming -public static class Task2 { - - private static readonly TimeSpan MAX_SHORT_DELAY; - - // ExceptionAdjustment: M:System.TimeSpan.FromMilliseconds(System.Double) -T:System.OverflowException - // ExceptionAdjustment: M:System.Threading.Tasks.Task.Delay(System.TimeSpan,System.Threading.CancellationToken) -T:System.Threading.Tasks.TaskCanceledException - // ExceptionAdjustment: M:System.Threading.CancellationTokenSource.Cancel -T:System.AggregateException - static Task2() { - // max duration of Task.Delay with .NET 6 and later - MAX_SHORT_DELAY = TimeSpan.FromMilliseconds(uint.MaxValue - 1); - try { - CancellationTokenSource testCts = new(); - _ = Task.Delay(MAX_SHORT_DELAY, testCts.Token); - testCts.Cancel(); - } catch (ArgumentOutOfRangeException) { - // max duration of Task.Delay with .NET 5 and earlier - MAX_SHORT_DELAY = TimeSpan.FromMilliseconds(int.MaxValue); - } - } - - /// - /// Like , except this supports arbitrarily long delays. - /// - /// how long to wait - /// to stop waiting before has elapsed - /// useful for mocking - // ExceptionAdjustment: M:System.TimeSpan.Subtract(System.TimeSpan) -T:System.OverflowException - public static Task Delay(TimeSpan duration, CancellationToken cancellationToken = default, TimeProvider? timeProvider = default) { - timeProvider ??= TimeProvider.System; - Task result = Task.CompletedTask; - - for (TimeSpan remaining = duration; remaining > TimeSpan.Zero; remaining = remaining.Subtract(MAX_SHORT_DELAY)) { - TimeSpan shortDelay = remaining > MAX_SHORT_DELAY ? MAX_SHORT_DELAY : remaining; - result = result.ContinueWith(_ => Task.Delay(shortDelay, timeProvider, cancellationToken), cancellationToken, - TaskContinuationOptions.LongRunning | TaskContinuationOptions.NotOnCanceled, TaskScheduler.Current).Unwrap(); - } - - return result; - } - -} \ No newline at end of file diff --git a/GandiDynamicDns/Util/Extensions.cs b/GandiDynamicDns/Util/Extensions.cs deleted file mode 100644 index 458596e..0000000 --- a/GandiDynamicDns/Util/Extensions.cs +++ /dev/null @@ -1,111 +0,0 @@ -using GandiDynamicDns.Unfucked.DependencyInjection; -using Microsoft.Extensions.Configuration.Json; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.FileProviders; -using System.Diagnostics.CodeAnalysis; -using System.Net; -using System.Net.Sockets; - -namespace GandiDynamicDns.Util; - -public static class Extensions { - - /// - /// By default, the .NET host only looks for configuration files in the working directory, not the installation directory, which breaks when you run the program from any other directory. - /// Fix this by also looking for JSON configuration files in the same directory as this executable. - /// - /// - /// the same for chaining - // ExceptionAdjustment: M:System.Collections.Generic.IList`1.Insert(System.Int32,`0) -T:System.NotSupportedException - [ExcludeFromCodeCoverage] - public static IConfigurationBuilder AlsoSearchForJsonFilesInExecutableDirectory(this IConfigurationBuilder builder) { - string? installationDir; - try { - installationDir = Path.GetDirectoryName(Environment.ProcessPath); - } catch (PathTooLongException) { - return builder; - } - - if (installationDir != null) { - PhysicalFileProvider fileProvider = new(installationDir); - - IEnumerable<(int index, IConfigurationSource source)> sourcesToAdd = builder.Sources.SelectMany((src, oldIndex) => - src is JsonConfigurationSource { Path: { } path } source - ? [ - (oldIndex, new JsonConfigurationSource { - FileProvider = fileProvider, - Path = path, - Optional = true, - ReloadOnChange = source.ReloadOnChange, - ReloadDelay = source.ReloadDelay - }) - ] - : []).ToList(); - - int sourcesAdded = 0; - foreach ((int index, IConfigurationSource? source) in sourcesToAdd) { - // this list instance is not read-only - builder.Sources.Insert(index + sourcesAdded++, source); - } - } - - return builder; - } - - [ExcludeFromCodeCoverage] - public static IEnumerable Compact(this IEnumerable source) where T: class { - return source.Where(item => item != null)!; - } - - [ExcludeFromCodeCoverage] - public static IEnumerable Compact(this IEnumerable source) where T: struct { - return source.Where(item => item != null).Cast(); - } - - public static async Task Resolve(this DnsEndPoint host, CancellationToken ct = default) { - try { - return await Dns.GetHostAddressesAsync(host.Host, host.AddressFamily, ct) is [var firstAddress, ..] ? new IPEndPoint(firstAddress, host.Port) : null; - } catch (SocketException) { - return null; - } - } - - /*public static IServiceCollection AddTransientProviders(this IServiceCollection services) { - services.Add(services.Select(descriptor => { - if (descriptor.Lifetime == ServiceLifetime.Transient /*&& descriptor.ServiceType == typeof(IStunClient5389)#1#) { - Type serviceType = descriptor.ServiceType; - Type providerReturnType = typeof(Func<>).MakeGenericType(serviceType); - - DynamicMethod transientProviderMethod = new("TransientProvider", providerReturnType, [typeof(IServiceProvider)], typeof(Extensions).Module); - ILGenerator byteCode = transientProviderMethod.GetILGenerator(); - - // push method parameter 0 "provider" onto stack - byteCode.Emit(OpCodes.Ldarg_0); - - // push ServiceProviderServiceExtensions.GetRequiredService() - byteCode.Emit(OpCodes.Ldftn, typeof(ServiceProviderServiceExtensions) - .GetMethod(nameof(ServiceProviderServiceExtensions.GetRequiredService), 1, BindingFlags.Public | BindingFlags.Static, null, [typeof(IServiceProvider)], [])! - .MakeGenericMethod(serviceType)); - - // create new function that calls GetRequiredService() - byteCode.Emit(OpCodes.Newobj, providerReturnType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, [typeof(object), typeof(IntPtr)])!); - - // return the new function - byteCode.Emit(OpCodes.Ret); - - var transientProvider = (Func>) transientProviderMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(typeof(IServiceProvider), providerReturnType)); - return new ServiceDescriptor(providerReturnType, transientProvider, ServiceLifetime.Transient); - } else { - return null; - } - }).Compact().ToList()); - return services; - }*/ - - public static IServiceCollection AddInjectableProviders(this IServiceCollection services) { - services.TryAddSingleton(typeof(Provider<>), typeof(MicrosoftDependencyInjectionServiceProvider<>)); - services.TryAddSingleton(typeof(OptionalProvider<>), typeof(MicrosoftDependencyInjectionServiceProvider<>)); - return services; - } - -} \ No newline at end of file diff --git a/GandiDynamicDns/Util/MyConsoleFormatter.cs b/GandiDynamicDns/Util/MyConsoleFormatter.cs deleted file mode 100644 index 91c28b4..0000000 --- a/GandiDynamicDns/Util/MyConsoleFormatter.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Logging.Console; -using Microsoft.Extensions.Options; -using System.Diagnostics.CodeAnalysis; - -namespace GandiDynamicDns.Util; - -[ExcludeFromCodeCoverage] -public class MyConsoleFormatter(IOptions options): ConsoleFormatter(NAME) { - - public const string NAME = "myConsoleFormatter"; - private const string DEFAULT_DATE_FORMAT = "yyyy'-'MM'-'dd' 'HH':'mm':'ss.fff"; - private const string PADDING = " "; - private const string ANSI_RESET = "\u001b[0m"; - - private static readonly int MAX_PADDED_CATEGORY_LENGTH = PADDING.Length; - - private readonly MyConsoleOptions options = options.Value; - - private int maxCategoryLength; - - public override void Write(in LogEntry logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter) { - DateTimeOffset now = DateTimeOffset.Now; - string? message = logEntry.State?.ToString(); - Exception? exception = logEntry.Exception; - if (message is not null || exception is not null) { - - textWriter.Write(formatLevel(logEntry.LogLevel)); - textWriter.Write(options.columnSeparator); - textWriter.Write(formatTime(now)); - textWriter.Write(options.columnSeparator); - writeCategory(logEntry, textWriter); - textWriter.Write(options.columnSeparator); - - if (message is not null) { - textWriter.Write(message); - } - - if (message is not null && exception is not null) { - textWriter.Write("\n "); - } - - if (exception is not null) { - textWriter.Write(exception.ToString().Replace("\n", "\n ")); - } - - textWriter.WriteLine(ANSI_RESET); - } - } - - private void writeCategory(LogEntry logEntry, TextWriter textWriter) { - int lastSeparatorPosition = options.includeNamespaces ? -1 : logEntry.Category.LastIndexOf('.', logEntry.Category.Length - 2); - - ReadOnlySpan category = lastSeparatorPosition != -1 ? logEntry.Category.AsSpan(lastSeparatorPosition + 1) : logEntry.Category.AsSpan(); - - int categoryLength = category.Length; - maxCategoryLength = Math.Max(maxCategoryLength, categoryLength); - textWriter.Write(category); - - if (categoryLength >= maxCategoryLength) { - maxCategoryLength = categoryLength; - } else { - textWriter.Write(PADDING.AsSpan(0, Math.Max(0, Math.Min(maxCategoryLength, MAX_PADDED_CATEGORY_LENGTH) - categoryLength))); - } - } - - private string formatTime(DateTimeOffset now) => now.ToString(options.TimestampFormat ?? DEFAULT_DATE_FORMAT); - - private static string formatLevel(LogLevel level) => level switch { - LogLevel.Trace => "\u001b[0;90m t", - LogLevel.Debug => " d", - LogLevel.Information => "\u001b[0;36m i", - LogLevel.Warning => "\u001b[30;43m W", - LogLevel.Error => "\u001b[97;41m E", - LogLevel.Critical => "\u001b[97;41m C", - _ => " " - }; - - public class MyConsoleOptions: ConsoleFormatterOptions { - - public bool includeNamespaces { get; set; } - public string columnSeparator { get; set; } = " | "; - - } - -} \ No newline at end of file diff --git a/GandiDynamicDns/packages.lock.json b/GandiDynamicDns/packages.lock.json index 24bd122..26f1a39 100644 --- a/GandiDynamicDns/packages.lock.json +++ b/GandiDynamicDns/packages.lock.json @@ -10,28 +10,28 @@ }, "JetBrains.Annotations": { "type": "Direct", - "requested": "[2023.3.0, )", - "resolved": "2023.3.0", - "contentHash": "PHfnvdBUdGaTVG9bR/GEfxgTwWM0Z97Y6X3710wiljELBISipSfF5okn/vz+C2gfO+ihoEyVPjaJwn8ZalVukA==" + "requested": "[2024.2.0, )", + "resolved": "2024.2.0", + "contentHash": "GNnqCFW/163p1fOehKx0CnAqjmpPrUSqrgfHM6qca+P+RN39C9rhlfZHQpJhxmQG/dkOYe/b3Z0P8b6Kv5m1qw==" }, "Microsoft.Extensions.Hosting.Systemd": { "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "z69pnSzenLkMYqho8lcNtu2RoEBFucBgCWaBkgWraGNGGMD42L3VRDq8qrEBB/gNdtcPCFKZdfyaXLAaH2T0+g==", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "URto937K9+hiTUMt6mIj/cfILi0YbI4MbNKBUvE0quE1Hx84GeOK9rIG2kYkp2R5SpQqMAxHJ89xrv50oAuc6A==", "dependencies": { - "Microsoft.Extensions.Hosting": "8.0.0" + "Microsoft.Extensions.Hosting": "8.0.1" } }, "Microsoft.Extensions.Hosting.WindowsServices": { "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "8JIvU6R9fejZj/p6QATeDaNEPtIvLuwE5Uh7qyPx7tp+Fc9FqYaAe6ylU2dM839IUpmsU4ZVev956slZyrYEhQ==", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "5p0tjMDpr8tgzjBdu9Rzk8lUU/PaR1D3Us52XZypl85QTxfAjthR1+YywB3GsGc+FOZWdpuEDsV8kZisEC2Hng==", "dependencies": { - "Microsoft.Extensions.Hosting": "8.0.0", - "Microsoft.Extensions.Logging.EventLog": "8.0.0", - "System.ServiceProcess.ServiceController": "8.0.0" + "Microsoft.Extensions.Hosting": "8.0.1", + "Microsoft.Extensions.Logging.EventLog": "8.0.1", + "System.ServiceProcess.ServiceController": "8.0.1" } }, "Stun.Net": { @@ -43,15 +43,6 @@ "Socks5": "1.0.2" } }, - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "7.0.0", @@ -76,8 +67,8 @@ }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "mBMoXLsr5s1y2zOHWmKsE9veDcx8h1x/c3rz4baEdQKTeDcmQAPNbB54Pi/lhFO3K431eEq6PFbMgLaa6PHFfA==", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", "dependencies": { "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" } @@ -102,8 +93,8 @@ }, "Microsoft.Extensions.Configuration.FileExtensions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", @@ -114,58 +105,56 @@ }, "Microsoft.Extensions.Configuration.Json": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "System.Text.Json": "8.0.0" + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" } }, "Microsoft.Extensions.Configuration.UserSecrets": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ihDHu2dJYQird9pl2CbdwuNDfvCZdOS0S7SPlNfhPt0B81UTT+yyZKz2pimFZGUp3AfuBRnqUCxB2SjsZKHVUw==", + "resolved": "8.0.1", + "contentHash": "7tYqdPPpAK+3jO9d5LTuCK2VxrEdf85Ol4trUr6ds4jclBecadWZ/RyPCbNjfbN5iGTfUnD/h65TOQuqQv2c+A==", "dependencies": { "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Configuration.Json": "8.0.1", "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", "Microsoft.Extensions.FileProviders.Physical": "8.0.0" } }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" }, "Microsoft.Extensions.Diagnostics": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3PZp/YSkIXrF7QK7PfC1bkyRYwqOHpWFad8Qx+4wkuumAeXo1NHaxpS9LboNA9OvNSAu+QOVlXbMyoY+pHSqcw==", + "resolved": "8.0.1", + "contentHash": "doVPCUUCY7c6LhBsEfiy3W1bvS7Mi6LkfQMS8nlC22jZWNxBv8VO8bdfeyvpYFst6Kxqk7HBC6lytmEoBssvSQ==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" } }, "Microsoft.Extensions.Diagnostics.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==", + "resolved": "8.0.1", + "contentHash": "elH2vmwNmsXuKmUeMQ4YW9ldXiF+gSGDgg1vORksob5POnpaI6caj1Hu8zaYbEuibhqCoWg0YRWDazBY3zjBfg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Diagnostics.DiagnosticSource": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.FileProviders.Abstractions": { @@ -193,130 +182,128 @@ }, "Microsoft.Extensions.Hosting": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ItYHpdqVp5/oFLT5QqbopnkKlyFG9EW/9nhM6/yfObeKt6Su0wkBio6AizgRHGNwhJuAtlE5VIjow5JOTrip6w==", + "resolved": "8.0.1", + "contentHash": "bP9EEkHBEfjgYiG8nUaXqMk/ujwJrffOkNPP7onpRMO8R+OUSESSP4xHkCAXgYZ1COP2Q9lXlU5gkMFh20gRuw==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", "Microsoft.Extensions.Configuration.CommandLine": "8.0.0", "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", - "Microsoft.Extensions.Configuration.Json": "8.0.0", - "Microsoft.Extensions.Configuration.UserSecrets": "8.0.0", - "Microsoft.Extensions.DependencyInjection": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Diagnostics": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Configuration.UserSecrets": "8.0.1", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics": "8.0.1", "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", "Microsoft.Extensions.FileProviders.Physical": "8.0.0", - "Microsoft.Extensions.Hosting.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Configuration": "8.0.0", - "Microsoft.Extensions.Logging.Console": "8.0.0", - "Microsoft.Extensions.Logging.Debug": "8.0.0", - "Microsoft.Extensions.Logging.EventLog": "8.0.0", - "Microsoft.Extensions.Logging.EventSource": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0" + "Microsoft.Extensions.Hosting.Abstractions": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging.Configuration": "8.0.1", + "Microsoft.Extensions.Logging.Console": "8.0.1", + "Microsoft.Extensions.Logging.Debug": "8.0.1", + "Microsoft.Extensions.Logging.EventLog": "8.0.1", + "Microsoft.Extensions.Logging.EventSource": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "AG7HWwVRdCHlaA++1oKDxLsXIBxmDpMPb3VoyOoAghEWnkUvEAdYQUwnV4jJbAaa/nMYNiEh5ByoLauZBEiovg==", + "resolved": "8.0.1", + "contentHash": "nHwq9aPBdBPYXPti6wYEEfgXddfBrYC+CQLn+qISiwQq5tpfaqDZSKOJNxoe9rfQxGf1c+2wC/qWFe1QYJPYqw==", "dependencies": { "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" } }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0" + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" } }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ixXXV0G/12g6MXK65TLngYN9V5hQQRuV+fZi882WIoVJT7h5JvoYoxTEwCgdqwLjSneqh1O+66gM8sMr9z/rsQ==", + "resolved": "8.0.1", + "contentHash": "QWwTrsgOnJMmn+XUslm8D2H1n3PkP/u/v52FODtyBc/k4W9r3i2vcXXeeX/upnzllJYRRbrzVzT0OclfNJtBJA==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" } }, "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "e+48o7DztoYog+PY430lPxrM4mm3PbA6qucvQtUDDwVo4MO+ejMw7YGc/o2rnxbxj4isPxdfKFzTxvXMwAz83A==", + "resolved": "8.0.1", + "contentHash": "uzcg/5U2eLyn5LIKlERkdSxw6VPC1yydnOSQiRRWGBGN3kphq3iL4emORzrojScDmxRhv49gp5BI8U3Dz7y4iA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Configuration": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Text.Json": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging.Configuration": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Logging.Debug": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dt0x21qBdudHLW/bjMJpkixv858RRr8eSomgVbU8qljOyfrfDGi1JQvpF9w8S7ziRPtRKisuWaOwFxJM82GxeA==", + "resolved": "8.0.1", + "contentHash": "B8hqNuYudC2RB+L/DI33uO4rf5by41fZVdcVL2oZj0UyoAZqnwTwYHp1KafoH4nkl1/23piNeybFFASaV2HkFg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" } }, "Microsoft.Extensions.Logging.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3X9D3sl7EmOu7vQp5MJrmIJBl5XSdOhZPYXUeFfYa6Nnm9+tok8x3t3IVPLhm7UJtPOU61ohFchw8rNm9tIYOQ==", + "resolved": "8.0.1", + "contentHash": "ZD1m4GXoxcZeDJIq8qePKj+QAWeQNO/OG8skvrOG8RQfxLp9MAKRoliTc27xanoNUzeqvX5HhS/I7c0BvwAYUg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Diagnostics.EventLog": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "System.Diagnostics.EventLog": "8.0.1" } }, "Microsoft.Extensions.Logging.EventSource": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "oKcPMrw+luz2DUAKhwFXrmFikZWnyc8l2RKoQwqU3KIZZjcfoJE0zRHAnqATfhRZhtcbjl/QkiY2Xjxp0xu+6w==", + "resolved": "8.0.1", + "contentHash": "YMXMAla6B6sEf/SnfZYTty633Ool3AH7KOw2LOaaEqwSo2piK4f7HMtzyc3CNiipDnq1fsUSuG5Oc7ZzpVy8WQ==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0", - "System.Text.Json": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "Microsoft.Extensions.Primitives": "8.0.0" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.Primitives": "8.0.0" @@ -392,24 +379,10 @@ "Pipelines.Extensions": "1.0.2" } }, - "System.Configuration.ConfigurationManager": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==", - "dependencies": { - "System.Diagnostics.EventLog": "8.0.0", - "System.Security.Cryptography.ProtectedData": "8.0.0" - } - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ==" - }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.IO.Pipelines": { "type": "Transitive", @@ -425,11 +398,6 @@ "System.Security.Principal.Windows": "5.0.0" } }, - "System.Security.Cryptography.ProtectedData": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==" - }, "System.Security.Principal.Windows": { "type": "Transitive", "resolved": "5.0.0", @@ -437,23 +405,10 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" - } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" - }, - "System.Text.Json": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", - "dependencies": { - "System.Text.Encodings.Web": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } }, "System.Threading.Tasks.Extensions": { @@ -463,15 +418,6 @@ } }, "net8.0/linux-arm": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -483,8 +429,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -502,28 +448,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0/linux-arm64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -535,8 +467,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -554,28 +486,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0/linux-x64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -587,8 +505,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -606,28 +524,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0/win-arm64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -639,8 +543,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -658,28 +562,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0/win-x64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -691,8 +581,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -710,16 +600,11 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0-windows7.0": { @@ -731,28 +616,28 @@ }, "JetBrains.Annotations": { "type": "Direct", - "requested": "[2023.3.0, )", - "resolved": "2023.3.0", - "contentHash": "PHfnvdBUdGaTVG9bR/GEfxgTwWM0Z97Y6X3710wiljELBISipSfF5okn/vz+C2gfO+ihoEyVPjaJwn8ZalVukA==" + "requested": "[2024.2.0, )", + "resolved": "2024.2.0", + "contentHash": "GNnqCFW/163p1fOehKx0CnAqjmpPrUSqrgfHM6qca+P+RN39C9rhlfZHQpJhxmQG/dkOYe/b3Z0P8b6Kv5m1qw==" }, "Microsoft.Extensions.Hosting.Systemd": { "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "z69pnSzenLkMYqho8lcNtu2RoEBFucBgCWaBkgWraGNGGMD42L3VRDq8qrEBB/gNdtcPCFKZdfyaXLAaH2T0+g==", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "URto937K9+hiTUMt6mIj/cfILi0YbI4MbNKBUvE0quE1Hx84GeOK9rIG2kYkp2R5SpQqMAxHJ89xrv50oAuc6A==", "dependencies": { - "Microsoft.Extensions.Hosting": "8.0.0" + "Microsoft.Extensions.Hosting": "8.0.1" } }, "Microsoft.Extensions.Hosting.WindowsServices": { "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "8JIvU6R9fejZj/p6QATeDaNEPtIvLuwE5Uh7qyPx7tp+Fc9FqYaAe6ylU2dM839IUpmsU4ZVev956slZyrYEhQ==", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "5p0tjMDpr8tgzjBdu9Rzk8lUU/PaR1D3Us52XZypl85QTxfAjthR1+YywB3GsGc+FOZWdpuEDsV8kZisEC2Hng==", "dependencies": { - "Microsoft.Extensions.Hosting": "8.0.0", - "Microsoft.Extensions.Logging.EventLog": "8.0.0", - "System.ServiceProcess.ServiceController": "8.0.0" + "Microsoft.Extensions.Hosting": "8.0.1", + "Microsoft.Extensions.Logging.EventLog": "8.0.1", + "System.ServiceProcess.ServiceController": "8.0.1" } }, "Stun.Net": { @@ -764,15 +649,6 @@ "Socks5": "1.0.2" } }, - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "7.0.0", @@ -797,8 +673,8 @@ }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "mBMoXLsr5s1y2zOHWmKsE9veDcx8h1x/c3rz4baEdQKTeDcmQAPNbB54Pi/lhFO3K431eEq6PFbMgLaa6PHFfA==", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", "dependencies": { "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" } @@ -823,8 +699,8 @@ }, "Microsoft.Extensions.Configuration.FileExtensions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "McP+Lz/EKwvtCv48z0YImw+L1gi1gy5rHhNaNIY2CrjloV+XY8gydT8DjMR6zWeL13AFK+DioVpppwAuO1Gi1w==", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", @@ -835,58 +711,56 @@ }, "Microsoft.Extensions.Configuration.Json": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "C2wqUoh9OmRL1akaCcKSTmRU8z0kckfImG7zLNI8uyi47Lp+zd5LWAD17waPQEqCz3ioWOCrFUo+JJuoeZLOBw==", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", - "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "System.Text.Json": "8.0.0" + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" } }, "Microsoft.Extensions.Configuration.UserSecrets": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ihDHu2dJYQird9pl2CbdwuNDfvCZdOS0S7SPlNfhPt0B81UTT+yyZKz2pimFZGUp3AfuBRnqUCxB2SjsZKHVUw==", + "resolved": "8.0.1", + "contentHash": "7tYqdPPpAK+3jO9d5LTuCK2VxrEdf85Ol4trUr6ds4jclBecadWZ/RyPCbNjfbN5iGTfUnD/h65TOQuqQv2c+A==", "dependencies": { "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Json": "8.0.0", + "Microsoft.Extensions.Configuration.Json": "8.0.1", "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", "Microsoft.Extensions.FileProviders.Physical": "8.0.0" } }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" }, "Microsoft.Extensions.Diagnostics": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3PZp/YSkIXrF7QK7PfC1bkyRYwqOHpWFad8Qx+4wkuumAeXo1NHaxpS9LboNA9OvNSAu+QOVlXbMyoY+pHSqcw==", + "resolved": "8.0.1", + "contentHash": "doVPCUUCY7c6LhBsEfiy3W1bvS7Mi6LkfQMS8nlC22jZWNxBv8VO8bdfeyvpYFst6Kxqk7HBC6lytmEoBssvSQ==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" } }, "Microsoft.Extensions.Diagnostics.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==", + "resolved": "8.0.1", + "contentHash": "elH2vmwNmsXuKmUeMQ4YW9ldXiF+gSGDgg1vORksob5POnpaI6caj1Hu8zaYbEuibhqCoWg0YRWDazBY3zjBfg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Diagnostics.DiagnosticSource": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.FileProviders.Abstractions": { @@ -914,130 +788,128 @@ }, "Microsoft.Extensions.Hosting": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ItYHpdqVp5/oFLT5QqbopnkKlyFG9EW/9nhM6/yfObeKt6Su0wkBio6AizgRHGNwhJuAtlE5VIjow5JOTrip6w==", + "resolved": "8.0.1", + "contentHash": "bP9EEkHBEfjgYiG8nUaXqMk/ujwJrffOkNPP7onpRMO8R+OUSESSP4xHkCAXgYZ1COP2Q9lXlU5gkMFh20gRuw==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", "Microsoft.Extensions.Configuration.CommandLine": "8.0.0", "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "8.0.0", - "Microsoft.Extensions.Configuration.Json": "8.0.0", - "Microsoft.Extensions.Configuration.UserSecrets": "8.0.0", - "Microsoft.Extensions.DependencyInjection": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Diagnostics": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Configuration.UserSecrets": "8.0.1", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics": "8.0.1", "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", "Microsoft.Extensions.FileProviders.Physical": "8.0.0", - "Microsoft.Extensions.Hosting.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Configuration": "8.0.0", - "Microsoft.Extensions.Logging.Console": "8.0.0", - "Microsoft.Extensions.Logging.Debug": "8.0.0", - "Microsoft.Extensions.Logging.EventLog": "8.0.0", - "Microsoft.Extensions.Logging.EventSource": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0" + "Microsoft.Extensions.Hosting.Abstractions": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging.Configuration": "8.0.1", + "Microsoft.Extensions.Logging.Console": "8.0.1", + "Microsoft.Extensions.Logging.Debug": "8.0.1", + "Microsoft.Extensions.Logging.EventLog": "8.0.1", + "Microsoft.Extensions.Logging.EventSource": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "AG7HWwVRdCHlaA++1oKDxLsXIBxmDpMPb3VoyOoAghEWnkUvEAdYQUwnV4jJbAaa/nMYNiEh5ByoLauZBEiovg==", + "resolved": "8.0.1", + "contentHash": "nHwq9aPBdBPYXPti6wYEEfgXddfBrYC+CQLn+qISiwQq5tpfaqDZSKOJNxoe9rfQxGf1c+2wC/qWFe1QYJPYqw==", "dependencies": { "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" } }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0" + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" } }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ixXXV0G/12g6MXK65TLngYN9V5hQQRuV+fZi882WIoVJT7h5JvoYoxTEwCgdqwLjSneqh1O+66gM8sMr9z/rsQ==", + "resolved": "8.0.1", + "contentHash": "QWwTrsgOnJMmn+XUslm8D2H1n3PkP/u/v52FODtyBc/k4W9r3i2vcXXeeX/upnzllJYRRbrzVzT0OclfNJtBJA==", "dependencies": { "Microsoft.Extensions.Configuration": "8.0.0", "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" } }, "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "e+48o7DztoYog+PY430lPxrM4mm3PbA6qucvQtUDDwVo4MO+ejMw7YGc/o2rnxbxj4isPxdfKFzTxvXMwAz83A==", + "resolved": "8.0.1", + "contentHash": "uzcg/5U2eLyn5LIKlERkdSxw6VPC1yydnOSQiRRWGBGN3kphq3iL4emORzrojScDmxRhv49gp5BI8U3Dz7y4iA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Configuration": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Text.Json": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging.Configuration": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Logging.Debug": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dt0x21qBdudHLW/bjMJpkixv858RRr8eSomgVbU8qljOyfrfDGi1JQvpF9w8S7ziRPtRKisuWaOwFxJM82GxeA==", + "resolved": "8.0.1", + "contentHash": "B8hqNuYudC2RB+L/DI33uO4rf5by41fZVdcVL2oZj0UyoAZqnwTwYHp1KafoH4nkl1/23piNeybFFASaV2HkFg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" } }, "Microsoft.Extensions.Logging.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3X9D3sl7EmOu7vQp5MJrmIJBl5XSdOhZPYXUeFfYa6Nnm9+tok8x3t3IVPLhm7UJtPOU61ohFchw8rNm9tIYOQ==", + "resolved": "8.0.1", + "contentHash": "ZD1m4GXoxcZeDJIq8qePKj+QAWeQNO/OG8skvrOG8RQfxLp9MAKRoliTc27xanoNUzeqvX5HhS/I7c0BvwAYUg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Diagnostics.EventLog": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "System.Diagnostics.EventLog": "8.0.1" } }, "Microsoft.Extensions.Logging.EventSource": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "oKcPMrw+luz2DUAKhwFXrmFikZWnyc8l2RKoQwqU3KIZZjcfoJE0zRHAnqATfhRZhtcbjl/QkiY2Xjxp0xu+6w==", + "resolved": "8.0.1", + "contentHash": "YMXMAla6B6sEf/SnfZYTty633Ool3AH7KOw2LOaaEqwSo2piK4f7HMtzyc3CNiipDnq1fsUSuG5Oc7ZzpVy8WQ==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0", - "System.Text.Json": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "Microsoft.Extensions.Primitives": "8.0.0" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.Primitives": "8.0.0" @@ -1113,24 +985,10 @@ "Pipelines.Extensions": "1.0.2" } }, - "System.Configuration.ConfigurationManager": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==", - "dependencies": { - "System.Diagnostics.EventLog": "8.0.0", - "System.Security.Cryptography.ProtectedData": "8.0.0" - } - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ==" - }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.IO.Pipelines": { "type": "Transitive", @@ -1146,11 +1004,6 @@ "System.Security.Principal.Windows": "5.0.0" } }, - "System.Security.Cryptography.ProtectedData": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==" - }, "System.Security.Principal.Windows": { "type": "Transitive", "resolved": "5.0.0", @@ -1158,23 +1011,10 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" - } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" - }, - "System.Text.Json": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", - "dependencies": { - "System.Text.Encodings.Web": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } }, "System.Threading.Tasks.Extensions": { @@ -1184,15 +1024,6 @@ } }, "net8.0-windows7.0/linux-arm": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -1204,8 +1035,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -1223,28 +1054,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0-windows7.0/linux-arm64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -1256,8 +1073,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -1275,28 +1092,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0-windows7.0/linux-x64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -1308,8 +1111,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -1327,28 +1130,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0-windows7.0/win-arm64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -1360,8 +1149,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -1379,28 +1168,14 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } }, "net8.0-windows7.0/win-x64": { - "System.Runtime.Caching": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "4TmlmvGp4kzZomm7J2HJn6IIx0UUrQyhBDyb5O1XiunZlQImXW+B8b7W/sTPcXhSf9rp5NR5aDtQllwbB5elOQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "8.0.0" - } - }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -1412,8 +1187,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "fdYxcRjQqTTacKId/2IECojlDSFvp7LP5N78+0z/xH7v/Tuw5ZAxu23Y6PTCRinqyu2ePx+Gn1098NC6jM6d+A==" + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" }, "System.Security.AccessControl": { "type": "Transitive", @@ -1431,16 +1206,11 @@ }, "System.ServiceProcess.ServiceController": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "jtYVG3bpw2n/NvNnP2g/JLri0D4UtfusTvLeH6cZPNAEjJXJVGspS3wLgVvjNbm+wjaYkFgsXejMTocV1T5DIQ==", + "resolved": "8.0.1", + "contentHash": "02I0BXo1kmMBgw03E8Hu4K6nTqur4wpQdcDZrndczPzY2fEoGvlinE35AWbyzLZ2h2IksEZ6an4tVt3hi9j1oA==", "dependencies": { - "System.Diagnostics.EventLog": "8.0.0" + "System.Diagnostics.EventLog": "8.0.1" } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==" } } } diff --git a/Readme.md b/Readme.md index f25863c..49d55c7 100644 --- a/Readme.md +++ b/Readme.md @@ -43,7 +43,7 @@ Open `appsettings.json` in a text editor and fill in the following values. Keys |Key|Type|Examples|Description| |-|-|-|-| -|`gandiApiKey` ✴|`string`|`abcdefg`|Generate an API key under [Developer access](https://account.gandi.net/en/users/_/security) in your [Gandi Account](https://account.gandi.net/en). Personal Access Tokens are unfortunately not supported by [G6.GandiLiveDns](https://github.com/gaylord-roger/G6.GandiLiveDns).| +|`gandiApiKey` ✴|`string`|`abcdefg`|Generate an API key under [Developer access](https://account.gandi.net/en/users/_/security) in your [Gandi Account](https://account.gandi.net/en). Does not accept Personal Access Tokens because they expire after a finite duration and can't be refreshed, and they're incompatible with the underlying third-party API client anyway.| |`domain` ✴|`string`|`example.com`
`example.co.uk`|The second-level domain name that you registered, including the TLD.| |`subdomain` ✴|`string`|`www`
`@`
`api.stage`|The subdomain whose DNS record you want to update, not including `domain` or a trailing period. To update `domain` itself, set this to `@` (default). Can also be a multi-level subdomain.| |`updateInterval`|`TimeSpan`|`0.00:05:00`|How frequently this program will check if your public IP address has changed and update DNS. Format is `d.hh:mm:ss`. Defaults to 5 minutes.
**One-shot mode:** if set to `0:0:0` or negative, this program will exit after the first update attempt, instead of remaining running and updating periodically; useful if you want to trigger it yourself, like with `cron`.|