diff --git a/UmlautAdaptarr/Program.cs b/UmlautAdaptarr/Program.cs index c6e42f4..5df6506 100644 --- a/UmlautAdaptarr/Program.cs +++ b/UmlautAdaptarr/Program.cs @@ -8,10 +8,12 @@ using UmlautAdaptarr.Utilities; internal class Program { - private static void Main(string[] args) + private static void Main(string[] args) { + MainAsync(args).Wait(); + } + + private static async Task MainAsync(string[] args) { - Helper.ShowLogo(); - Helper.ShowInformation(); // TODO: // add option to sort by nzb age var builder = WebApplication.CreateBuilder(args); @@ -43,9 +45,9 @@ internal class Program builder.AddTitleLookupService(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.AddSonarrSupport(); - builder.AddLidarrSupport(); - builder.AddReadarrSupport(); + await builder.AddSonarrSupport(); + await builder.AddLidarrSupport(); + await builder.AddReadarrSupport(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -54,6 +56,13 @@ internal class Program var app = builder.Build(); + Helper.ShowLogo(); + + if (app.Configuration.GetValue("IpLeakTest:Enabled")) + { + await Helper.ShowInformation(); + } + GlobalStaticLogger.Initialize(app.Services.GetService()!); app.UseHttpsRedirection(); app.UseAuthorization(); @@ -109,4 +118,4 @@ internal class Program //.Enrich.With(new ApiKeyMaskingEnricher("appsettings.json")) // TODO - Not working currently .CreateLogger(); } -} \ No newline at end of file +} diff --git a/UmlautAdaptarr/Services/Factory/ArrApplicationFactory.cs b/UmlautAdaptarr/Services/Factory/ArrApplicationFactory.cs index 2fe4ddc..98f2b5c 100644 --- a/UmlautAdaptarr/Services/Factory/ArrApplicationFactory.cs +++ b/UmlautAdaptarr/Services/Factory/ArrApplicationFactory.cs @@ -4,7 +4,7 @@ using UmlautAdaptarr.Providers; namespace UmlautAdaptarr.Services.Factory { /// - /// Factory for creating RrApplication instances. + /// Factory for creating ArrApplication instances. /// public class ArrApplicationFactory { @@ -33,21 +33,21 @@ namespace UmlautAdaptarr.Services.Factory /// /// Constructor for the ArrApplicationFactory. /// - /// A dictionary of IArrApplication instances. + /// A dictionary of IArrApplication instances. /// Logger Instanz - public ArrApplicationFactory(IDictionary rrArrApplications, ILogger logger) + public ArrApplicationFactory(IDictionary arrApplications, ILogger logger) { _logger = logger; try { - SonarrInstances = rrArrApplications.Values.OfType(); - LidarrInstances = rrArrApplications.Values.OfType(); - ReadarrInstances = rrArrApplications.Values.OfType(); - AllInstances = rrArrApplications; + SonarrInstances = arrApplications.Values.OfType(); + LidarrInstances = arrApplications.Values.OfType(); + ReadarrInstances = arrApplications.Values.OfType(); + AllInstances = arrApplications; - if (!AllInstances.Values.Any()) + if (AllInstances.Values.Count == 0) { - throw new Exception("No RrApplication could be successfully initialized. This could be due to a faulty configuration"); + throw new Exception("No ArrApplication could be successfully initialized. This could be due to a faulty configuration"); } } catch (Exception e) diff --git a/UmlautAdaptarr/Utilities/Helper.cs b/UmlautAdaptarr/Utilities/Helper.cs index 002310e..ff6a26c 100644 --- a/UmlautAdaptarr/Utilities/Helper.cs +++ b/UmlautAdaptarr/Utilities/Helper.cs @@ -11,10 +11,10 @@ public static class Helper "\r\n _ _ _ _ ___ _ _ \r\n| | | | | | | | / _ \\ | | | | \r\n| | | |_ __ ___ | | __ _ _ _| |_/ /_\\ \\ __| | __ _ _ __ | |_ __ _ _ __ _ __ \r\n| | | | '_ ` _ \\| |/ _` | | | | __| _ |/ _` |/ _` | '_ \\| __/ _` | '__| '__|\r\n| |_| | | | | | | | (_| | |_| | |_| | | | (_| | (_| | |_) | || (_| | | | | \r\n \\___/|_| |_| |_|_|\\__,_|\\__,_|\\__\\_| |_/\\__,_|\\__,_| .__/ \\__\\__,_|_| |_| \r\n | | \r\n |_| \r\n"); } - public static void ShowInformation() + public static async Task ShowInformation() { Console.WriteLine("--------------------------[IP Leak Test]-----------------------------"); - var ipInfo = GetPublicIpAddressInfoAsync().GetAwaiter().GetResult(); + var ipInfo = await GetPublicIpAddressInfoAsync(); if (ipInfo != null) { diff --git a/UmlautAdaptarr/Utilities/ServicesExtensions.cs b/UmlautAdaptarr/Utilities/ServicesExtensions.cs index 7037172..808906a 100644 --- a/UmlautAdaptarr/Utilities/ServicesExtensions.cs +++ b/UmlautAdaptarr/Utilities/ServicesExtensions.cs @@ -29,7 +29,7 @@ public static class ServicesExtensions /// The to configure the service collection. /// The name of the configuration section containing service options. /// The configured . - private static WebApplicationBuilder AddServicesWithOptions( + private static async Task AddServicesWithOptions( this WebApplicationBuilder builder, string sectionName) where TOptions : class, new() where TService : class, TInterface @@ -57,9 +57,9 @@ public static class ServicesExtensions foreach (var option in optionsArray) { - GlobalInstanceOptionsValidator validator = new GlobalInstanceOptionsValidator(); + GlobalInstanceOptionsValidator validator = new(); - var results = validator.Validate(option as GlobalInstanceOptions); + var results = await validator.ValidateAsync(option as GlobalInstanceOptions); if (!results.IsValid) { @@ -68,7 +68,7 @@ public static class ServicesExtensions Console.WriteLine(($"Property {failure.PropertyName } failed validation. Error was: {failure.ErrorMessage}")); } - throw new Exception("Please fix first you config and then Start UmlautAdaptarr again"); + throw new Exception("Please fix cour environment variables and then Start UmlautAdaptarr again"); } var instanceState = (bool)(typeof(TOptions).GetProperty("Enabled")?.GetValue(option, null) ?? false); @@ -143,7 +143,7 @@ public static class ServicesExtensions /// /// The to configure the service collection. /// The configured . - public static WebApplicationBuilder AddSonarrSupport(this WebApplicationBuilder builder) + public static Task AddSonarrSupport(this WebApplicationBuilder builder) { // builder.Serviceses.AddSingleton, OptionsMonitoSonarrInstanceOptionsns>>(); return builder.AddServicesWithOptions("Sonarr"); @@ -154,7 +154,7 @@ public static class ServicesExtensions /// /// The to configure the service collection. /// The configured . - public static WebApplicationBuilder AddLidarrSupport(this WebApplicationBuilder builder) + public static Task AddLidarrSupport(this WebApplicationBuilder builder) { return builder.AddServicesWithOptions("Lidarr"); } @@ -164,7 +164,7 @@ public static class ServicesExtensions /// /// The to configure the service collection. /// The configured . - public static WebApplicationBuilder AddReadarrSupport(this WebApplicationBuilder builder) + public static Task AddReadarrSupport(this WebApplicationBuilder builder) { return builder.AddServicesWithOptions("Readarr"); } diff --git a/UmlautAdaptarr/Validator/GlobalInstanceOptionsValidator.cs b/UmlautAdaptarr/Validator/GlobalInstanceOptionsValidator.cs index eca7e94..de6d087 100644 --- a/UmlautAdaptarr/Validator/GlobalInstanceOptionsValidator.cs +++ b/UmlautAdaptarr/Validator/GlobalInstanceOptionsValidator.cs @@ -6,6 +6,10 @@ namespace UmlautAdaptarr.Validator; public class GlobalInstanceOptionsValidator : AbstractValidator { + private readonly static HttpClient httpClient = new() { + Timeout = TimeSpan.FromSeconds(3) + }; + public GlobalInstanceOptionsValidator() { RuleFor(x => x.Enabled).NotNull(); @@ -14,12 +18,14 @@ public class GlobalInstanceOptionsValidator : AbstractValidator x.Host) .NotEmpty().WithMessage("Host is required when Enabled is true.") - .Must(BeAValidUrl).WithMessage("Host/Url must start with http:// or https:// and be a valid address.") - .Must(BeReachable) - .WithMessage("Host/Url is not reachable. Please check your Host or your UmlautAdaptrr Settings"); + .Must(BeAValidUrl).WithMessage("Host/Url must start with http:// or https:// and be a valid address."); RuleFor(x => x.ApiKey) .NotEmpty().WithMessage("ApiKey is required when Enabled is true."); + + RuleFor(x => x) + .MustAsync(BeReachable) + .WithMessage("Host/Url is not reachable. Please check your Host or your UmlautAdaptrr Settings"); }); } @@ -29,42 +35,22 @@ public class GlobalInstanceOptionsValidator : AbstractValidator BeReachable(GlobalInstanceOptions opts, CancellationToken cancellationToken) { var endTime = DateTime.Now.AddMinutes(3); var reachable = false; + var url = $"{opts.Host}/api?apikey={opts.ApiKey}"; while (DateTime.Now < endTime) { try { - // TODO use HttpClient here - var request = (HttpWebRequest)WebRequest.Create(url); - request.AllowAutoRedirect = false; - request.Timeout = 3000; - using var response = (HttpWebResponse)request.GetResponse(); + using var response = await httpClient.GetAsync(url, cancellationToken); reachable = response.StatusCode == HttpStatusCode.OK; - if (reachable) + if (response.IsSuccessStatusCode) { break; } - // If status is 301/302 (Found), follow the redirect manually - else if (response.StatusCode == HttpStatusCode.MovedPermanently || response.StatusCode == HttpStatusCode.Found) - { - var redirectUrl = response.Headers["Location"]; // Get the redirect URL - if (!string.IsNullOrEmpty(redirectUrl)) - { - // Create a new request for the redirected URL - var redirectRequest = (HttpWebRequest)WebRequest.Create(redirectUrl); - redirectRequest.Timeout = 3000; - using var redirectResponse = (HttpWebResponse)redirectRequest.GetResponse(); - reachable = redirectResponse.StatusCode == HttpStatusCode.OK; - if (reachable) - { - break; - } - } - } } catch { @@ -72,7 +58,7 @@ public class GlobalInstanceOptionsValidator : AbstractValidator