📄 src/Api/YouTubeApiEndpoints.cs
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.AspNetCore3;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Quartz;
using Slopper.Api.YouTubeAuth;

namespace Slopper.Api;

public static class YouTubeApiEndpoints
{
    extension(IEndpointRouteBuilder endpoints)
    {
        public IEndpointConventionBuilder MapYouTubeApi()
        {
            var youtube = endpoints.MapGroup("/youtube").RequireYouTubeAuthorization();

            youtube.MapGet("/login", Login).WithDisplayName("YouTube Login");

            youtube.MapGet("/upload", GetUploadJobStatus).WithDisplayName("Get YouTube upload job status.");
            youtube.MapPut("/upload", StartUploadJob).WithDisplayName("Triggers a job uploading clips to YouTube.");

            return youtube;
        }
    }

    private static RedirectHttpResult Login() => TypedResults.Redirect("/admin/youtube");

    private static async Task<Ok<JobStatus>> GetUploadJobStatus(
        [FromServices] ISchedulerFactory schedulerFactory,
        CancellationToken cancellationToken
    )
    {
        var scheduler = await schedulerFactory.GetScheduler(cancellationToken);

        if (await IsUploadJobRunning(scheduler, cancellationToken))
        {
            return TypedResults.Ok(new JobStatus(true));
        }

        return TypedResults.Ok(new JobStatus(false));
    }

    private static async Task<Accepted> StartUploadJob(
        [FromServices] YouTubeCredentialsProvider credentialsProvider,
        [FromServices] IGoogleAuthProvider googleAuthProvider,
        [FromServices] ISchedulerFactory schedulerFactory,
        CancellationToken cancellationToken
    )
    {
        var scheduler = await schedulerFactory.GetScheduler(cancellationToken);

        if (await IsUploadJobRunning(scheduler, cancellationToken))
        {
            return TypedResults.Accepted("/api/youtube/upload");
        }

        credentialsProvider.Credential = await googleAuthProvider.GetCredentialAsync(
            cancellationToken: cancellationToken
        );
        await scheduler.TriggerJob(UploadJob.Key, new JobDataMap { ["platform"] = "YouTube" }, cancellationToken);
        return TypedResults.Accepted("/api/youtube/upload");
    }

    private static async Task<bool> IsUploadJobRunning(IScheduler scheduler, CancellationToken cancellationToken)
    {
        var currentlyExecutingJobs = await scheduler.GetCurrentlyExecutingJobs(cancellationToken);
        return currentlyExecutingJobs.Any(j =>
            j.JobDetail.Key == UploadJob.Key && j.MergedJobDataMap.GetString("platform") is "YouTube"
        );
    }
}