namespace Producer.Extensions; public static class ServiceCollectionExtensions { internal static IServiceCollection AddCrawlers(this IServiceCollection services) { services.AddHttpClient("Scraper"); services .AddKeyedTransient(nameof(EzTvCrawler)) .AddKeyedTransient(nameof(NyaaCrawler)) .AddKeyedTransient(nameof(YtsCrawler)) .AddKeyedTransient(nameof(TpbCrawler)) .AddKeyedTransient(nameof(TgxCrawler)) .AddKeyedTransient(nameof(DebridMediaManagerCrawler)) .AddSingleton() .AddTransient(); return services; } internal static IServiceCollection AddDataStorage(this IServiceCollection services) { services.LoadConfigurationFromEnv(); services.AddTransient(); services.AddTransient(); return services; } internal static IServiceCollection RegisterMassTransit(this IServiceCollection services) { var rabbitConfig = services.LoadConfigurationFromEnv(); services.AddMassTransit(busConfigurator => { busConfigurator.SetKebabCaseEndpointNameFormatter(); busConfigurator.UsingRabbitMq((_, busFactoryConfigurator) => { busFactoryConfigurator.Host(rabbitConfig.Host, hostConfigurator => { hostConfigurator.Username(rabbitConfig.Username); hostConfigurator.Password(rabbitConfig.Password); }); }); }); return services; } internal static IServiceCollection AddQuartz(this IServiceCollection services, IConfiguration configuration) { var scrapeConfiguration = services.LoadConfigurationFromConfig(configuration, ScrapeConfiguration.SectionName); var githubConfiguration = services.LoadConfigurationFromEnv(); var rabbitConfig = services.LoadConfigurationFromEnv(); services .AddTransient() .AddTransient() .AddTransient() .AddTransient() .AddTransient() .AddTransient() .AddTransient(); if (!string.IsNullOrEmpty(githubConfiguration.PAT)) { services.AddTransient(); } services.AddQuartz( quartz => { AddJobWithTrigger(quartz, SyncEzTvJob.Key, SyncEzTvJob.Trigger, scrapeConfiguration); AddJobWithTrigger(quartz, SyncNyaaJob.Key, SyncNyaaJob.Trigger, scrapeConfiguration); AddJobWithTrigger(quartz, SyncTpbJob.Key, SyncTpbJob.Trigger, scrapeConfiguration); AddJobWithTrigger(quartz, SyncYtsJob.Key, SyncYtsJob.Trigger, scrapeConfiguration); AddJobWithTrigger(quartz, SyncTgxJob.Key, SyncTgxJob.Trigger, scrapeConfiguration); AddJobWithTrigger(quartz, IPJob.Key, IPJob.Trigger, 60 * 5); AddJobWithTrigger(quartz, PublisherJob.Key, PublisherJob.Trigger, rabbitConfig.PublishIntervalInSeconds); if (!string.IsNullOrEmpty(githubConfiguration.PAT)) { AddJobWithTrigger(quartz, SyncDmmJob.Key, SyncDmmJob.Trigger, scrapeConfiguration); } }); services.AddQuartzHostedService( options => { options.WaitForJobsToComplete = true; }); return services; } private static TConfiguration LoadConfigurationFromConfig(this IServiceCollection services, IConfiguration configuration, string sectionName) where TConfiguration : class { var instance = configuration.GetSection(sectionName).Get(); ArgumentNullException.ThrowIfNull(instance, nameof(instance)); services.TryAddSingleton(instance); return instance; } private static TConfiguration LoadConfigurationFromEnv(this IServiceCollection services) where TConfiguration : class { var instance = Activator.CreateInstance(); ArgumentNullException.ThrowIfNull(instance, nameof(instance)); services.TryAddSingleton(instance); return instance; } private static void AddJobWithTrigger( IServiceCollectionQuartzConfigurator quartz, JobKey key, TriggerKey trigger, ScrapeConfiguration scrapeConfiguration) where TJobType : IJob { var scraper = scrapeConfiguration.Scrapers .FirstOrDefault(x => x.Name != null && x.Name.Equals(typeof(TJobType).Name, StringComparison.OrdinalIgnoreCase)); if (scraper is null || !scraper.Enabled) { return; } quartz.AddJob(opts => opts.WithIdentity(key).StoreDurably()); quartz.AddTrigger( opts => opts .ForJob(key) .WithIdentity(trigger) .StartAt(DateTimeOffset.Now.AddSeconds(20)) .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(scraper.IntervalSeconds)).RepeatForever())); } private static void AddJobWithTrigger( IServiceCollectionQuartzConfigurator quartz, JobKey key, TriggerKey trigger, int interval) where TJobType : IJob { quartz.AddJob(opts => opts.WithIdentity(key).StoreDurably()); quartz.AddTrigger( opts => opts .ForJob(key) .WithIdentity(trigger) .StartAt(DateTimeOffset.Now.AddSeconds(20)) .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(interval)).RepeatForever())); } }