📄 src/Domain/Uploader.cs
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace Slopper.Domain;

public sealed class Uploader(IServiceProvider serviceProvider, IClipRepository clipRepository)
{
    public async Task<Upload?> Upload(string platform, CancellationToken cancellationToken)
    {
        var uploader = serviceProvider.GetRequiredKeyedService<IUploader>(platform);

        var clip = await clipRepository
            .GetLatest(limit: 1, cancellationToken: cancellationToken)
            .FirstOrDefaultAsync(cancellationToken);

        if (clip is null)
            return null;

        var upload = await uploader.Upload(clip, cancellationToken);

        clip.Uploads.Add(upload);
        await clipRepository.Save(clip, cancellationToken);

        return upload;
    }
}

public static class UploaderServiceCollectionExtensions
{
    extension(IServiceCollection services)
    {
        public IServiceCollection AddUploader()
        {
            services.AddTransient<Uploader>();
            return services;
        }
    }
}