using Bugsnag; using Bugsnag.Payload; using ErsatzTV.Core; using ErsatzTV.Core.Emby; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.Emby; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Images; using ErsatzTV.Core.Interfaces.Jellyfin; using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Plex; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Interfaces.Repositories.Caching; using ErsatzTV.Core.Interfaces.Search; using ErsatzTV.Core.Jellyfin; using ErsatzTV.Core.Metadata; using ErsatzTV.Core.Plex; using ErsatzTV.FFmpeg.Runtime; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Data.Repositories; using ErsatzTV.Infrastructure.Data.Repositories.Caching; using ErsatzTV.Infrastructure.Emby; using ErsatzTV.Infrastructure.Images; using ErsatzTV.Infrastructure.Jellyfin; using ErsatzTV.Infrastructure.Plex; using ErsatzTV.Infrastructure.Runtime; using ErsatzTV.Infrastructure.Search; using ErsatzTV.Scanner.Core.Emby; using ErsatzTV.Scanner.Core.FFmpeg; using ErsatzTV.Scanner.Core.Interfaces.FFmpeg; using ErsatzTV.Scanner.Core.Interfaces.Metadata; using ErsatzTV.Scanner.Core.Interfaces.Metadata.Nfo; using ErsatzTV.Scanner.Core.Jellyfin; using ErsatzTV.Scanner.Core.Metadata; using ErsatzTV.Scanner.Core.Metadata.Nfo; using ErsatzTV.Scanner.Core.Plex; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.IO; using Serilog; using Serilog.Events; using Serilog.Formatting.Compact; using Exception = System.Exception; namespace ErsatzTV.Scanner; public class Program { public static async Task Main(string[] args) { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .MinimumLevel.Override("Microsoft", LogEventLevel.Error) .Enrich.FromLogContext() .WriteTo.Console(new CompactJsonFormatter(), standardErrorFromLevel: LogEventLevel.Debug) .CreateLogger(); try { await CreateHostBuilder(args).Build().RunAsync(); return 0; } catch (Exception ex) { Log.Fatal(ex, "ErsatzTV.Scanner host terminated unexpectedly"); return 1; } finally { await Log.CloseAndFlushAsync(); } } private static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices( (_, services) => { var connectionString = $"Data Source={FileSystemLayout.DatabasePath};foreign keys=true;"; services.AddDbContext( options => options.UseSqlite( connectionString, o => { o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); o.MigrationsAssembly("ErsatzTV.Infrastructure"); }), ServiceLifetime.Scoped, ServiceLifetime.Singleton); services.AddDbContextFactory( options => options.UseSqlite( connectionString, o => { o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); o.MigrationsAssembly("ErsatzTV.Infrastructure"); })); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); // TODO: real bugsnag? services.AddSingleton(_ => new BugsnagNoopClient()); services.AddMediatR(config => config.RegisterServicesFromAssemblyContaining()); services.AddMemoryCache(); services.AddHostedService(); }) .UseSerilog(); private class BugsnagNoopClient : IClient { public void Notify(Exception exception) { } public void Notify(Exception exception, Middleware callback) { } public void Notify(Exception exception, Severity severity) { } public void Notify(Exception exception, Severity severity, Middleware callback) { } public void Notify(Exception exception, HandledState handledState) { } public void Notify(Exception exception, HandledState handledState, Middleware callback) { } public void Notify(Report report, Middleware callback) { } public void BeforeNotify(Middleware middleware) { } public IBreadcrumbs Breadcrumbs => new Breadcrumbs(Configuration); public ISessionTracker SessionTracking => new SessionTracker(Configuration); public IConfiguration Configuration => new Configuration(); } }