using System.Security.Claims; using MaxMind.GeoIP2; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization.Infrastructure; using Microsoft.AspNetCore.DataProtection; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using Nostr.Client.Client; using NostrServices.Client; using NostrStreamer.Database; using NostrStreamer.Services; using NostrStreamer.Services.Background; using NostrStreamer.Services.Clips; using NostrStreamer.Services.Dvr; using NostrStreamer.Services.StreamManager; using NostrStreamer.Services.Thumbnail; using Prometheus; using StackExchange.Redis; namespace NostrStreamer; internal static class Program { private static void ConfigureSerializer(JsonSerializerSettings s) { s.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; s.Formatting = Formatting.None; s.NullValueHandling = NullValueHandling.Ignore; s.ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor; s.Converters = new List() { new UnixDateTimeConverter() }; s.ContractResolver = new CamelCasePropertyNamesContractResolver(); } public static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); var services = builder.Services; var config = builder.Configuration.GetSection("Config").Get(); if (config == default) { throw new Exception("Config is missing!"); } ConfigureDb(services, builder.Configuration); services.AddCors(); services.AddMemoryCache(); services.AddHttpClient(); services.AddRazorPages(); services.AddControllers().AddNewtonsoftJson(opt => { ConfigureSerializer(opt.SerializerSettings); }); services.AddSwaggerGen(); services.AddSingleton(config); // Redis var cx = await ConnectionMultiplexer.ConnectAsync(config.Redis); services.AddSingleton(cx); services.AddTransient(svc => svc.GetRequiredService().GetDatabase()); // GeoIP services.AddSingleton(_ => new DatabaseReader(config.GeoIpDatabase)); services.AddTransient(); // nostr auth services.AddTransient(); services.AddAuthentication(o => { o.DefaultChallengeScheme = NostrAuth.Scheme; o.AddScheme(NostrAuth.Scheme, "Nostr"); }); services.AddAuthorization(o => { o.DefaultPolicy = new AuthorizationPolicy(new[] { new ClaimsAuthorizationRequirement(ClaimTypes.Name, null) }, new[] { NostrAuth.Scheme }); }); services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(config.DataProtectionKeyPath)); // nostr services services.AddSingleton(); services.AddSingleton(s => s.GetRequiredService()); services.AddSingleton(); services.AddHostedService(); services.AddTransient(); // streaming services services.AddTransient(); services.AddHostedService(); services.AddSingleton(); services.AddHostedService(); services.AddTransient(); services.AddTransient(); services.AddTransient(); // dvr services services.AddTransient(); services.AddHostedService(); // thumbnail services services.AddTransient(); services.AddHostedService(); // lnd services services.AddSingleton(); services.AddHostedService(); // game services services.AddSingleton(); // clip services services.AddTransient(); services.AddTransient(); // notifications services services.AddSingleton(); services.AddHostedService(); services.AddHostedService(); // webhooks services.AddTransient(); // snort api services.AddTransient(); var app = builder.Build(); using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); await db.Database.MigrateAsync(); } app.UseRouting(); app.UseCors(o => o.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); app.UseHttpMetrics(); app.UseAuthorization(); app.MapRazorPages(); app.MapControllers(); app.MapMetrics(); app.UseSwagger(); app.UseSwaggerUI(); await app.RunAsync(); } private static void ConfigureDb(IServiceCollection services, IConfiguration configuration) { services.AddDbContext(o => o.UseNpgsql(configuration.GetConnectionString("Database"))); } /// /// Dummy method for EF core migrations /// /// /// // ReSharper disable once UnusedMember.Global public static IHostBuilder CreateHostBuilder(string[] args) { var dummyHost = Host.CreateDefaultBuilder(args); dummyHost.ConfigureServices((ctx, svc) => { ConfigureDb(svc, ctx.Configuration); }); return dummyHost; } }