namespace Producer.Extensions; public static class ServiceCollectionExtensions { internal static IServiceCollection AddCrawlers(this IServiceCollection services) { services.AddHttpClient("Scraper"); services .AddKeyedTransient(nameof(EzTvCrawler)) .AddKeyedTransient(nameof(YtsCrawler)) .AddKeyedTransient(nameof(TpbCrawler)) .AddKeyedTransient(nameof(TgxCrawler)) .AddKeyedTransient(nameof(DebridMediaManagerCrawler)) .AddSingleton() .AddTransient(); return services; } internal static IServiceCollection AddDataStorage(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); return services; } internal static IServiceCollection RegisterMassTransit(this IServiceCollection services, IConfiguration configuration) { var rabbitConfig = configuration.GetSection(RabbitMqConfiguration.SectionName).Get(); ArgumentNullException.ThrowIfNull(rabbitConfig, nameof(rabbitConfig)); services.AddSingleton(rabbitConfig); services.AddMassTransit(busConfigurator => { busConfigurator.SetKebabCaseEndpointNameFormatter(); busConfigurator.UsingRabbitMq((context, 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 = LoadScrapeConfiguration(services, configuration); var githubConfiguration = LoadGithubConfiguration(services, configuration); var rabbitConfig = LoadRabbitMQConfiguration(services, configuration); services .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, 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 GithubConfiguration LoadGithubConfiguration(IServiceCollection services, IConfiguration configuration) { var githubConfiguration = configuration.GetSection(GithubConfiguration.SectionName).Get(); ArgumentNullException.ThrowIfNull(githubConfiguration, nameof(githubConfiguration)); services.TryAddSingleton(githubConfiguration); return githubConfiguration; } private static RabbitMqConfiguration LoadRabbitMQConfiguration(IServiceCollection services, IConfiguration configuration) { var rabbitConfiguration = configuration.GetSection(RabbitMqConfiguration.SectionName).Get(); ArgumentNullException.ThrowIfNull(rabbitConfiguration, nameof(rabbitConfiguration)); services.TryAddSingleton(rabbitConfiguration); return rabbitConfiguration; } private static ScrapeConfiguration LoadScrapeConfiguration(IServiceCollection services, IConfiguration configuration) { var scrapeConfiguration = configuration.GetSection(ScrapeConfiguration.SectionName).Get(); ArgumentNullException.ThrowIfNull(scrapeConfiguration, nameof(scrapeConfiguration)); services.TryAddSingleton(scrapeConfiguration); return scrapeConfiguration; } 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())); } }