📄 src/Api/Program.cs
using System.Linq;
using System.Threading;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Quartz;
using Quartz.AspNetCore;
using Slopper.Api;
using Slopper.Api.YouTubeAuth;
using Slopper.Domain;
using Slopper.Infrastructure.Ai;
using Slopper.Infrastructure.Database;
using Slopper.Infrastructure.Ffmpeg;
using Slopper.Infrastructure.YouTube;

// using Winton.Extensions.Configuration.Consul;

var builder = WebApplication.CreateBuilder(args);

// builder.Configuration.AddConsul(
//     "slopper",
//     options =>
//     {
//         options.ConsulConfigurationOptions = options => options.Address = new(builder.Configuration["Consul:Address"]!);
//         options.ReloadOnChange = true;
//     }
// );

builder.ConfigureOpenTelemetry();

builder.Services.AddOpenApi();

builder.Services.AddClipSelector().AddClipGenerator().AddCleaner();

builder.Services.AddJellyfinDatabase().AddSlopperDatabase().AddFfmpegServices().AddAi().AddYouTubeUploader();

builder
    .Services.AddClipGenerationJobOptions()
    .AddQuartz() //quartz => quartz.AddClipGenerationJob().AddCleanupJob())
    .AddQuartzServer();

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie().AddYouTube();

builder.Services.AddAuthorizationBuilder().AddYouTubePolicy();

using var app = builder.Build();

if (builder.Environment.IsDevelopment())
{
    app.UseCookiePolicy(new() { MinimumSameSitePolicy = SameSiteMode.Lax });
}

app.UseAuthentication();
app.UseAuthorization();

app.MapOpenApi();

app.MapApi();

app.UseDefaultFiles();
app.UseStaticFiles();

app.MapGet(
        "/admin/youtube",
        async (
            [FromServices] IClipRepository clipRepository,
            [FromKeyedServices("YouTube")] IUploader uploader,
            HttpContext httpContext,
            CancellationToken cancellationToken
        ) =>
        {
            var clip = await clipRepository
                .GetLatest(limit: 1, cancellationToken: cancellationToken)
                .FirstOrDefaultAsync(cancellationToken);
            if (clip is null)
            {
                return Results.NotFound();
            }
            var result = await uploader.Upload(clip, cancellationToken);
            return Results.Ok(result.CanonicalUrl);
        }
    )
    .RequireAuthorization("YouTube");

app.Run();