src/Api/ApiEndpoints.cs
+8
-0
diff --git a/src/Api/ApiEndpoints.cs b/src/Api/ApiEndpoints.cs
index 06bc105..a3dc4e6 100644
@@ -33,6 +33,8 @@ public static class ApiEndpoints
.WithDisplayName("Create New Clip")
.WithSummary("Triggers a job generating a new clip.");
api.MapYouTubeApi();
return api;
}
}
@@ -116,6 +118,12 @@ public static class ApiEndpoints
}
}
public sealed record Clip(Guid Id, TimeSpan Duration, DateTimeOffset CreatedAt, string? Caption, string[] Tags)
{
public static Clip FromDomain(Domain.Clip clip) =>
new(clip.Id, clip.Duration, clip.CreatedAt, clip.Caption, [.. clip.Tags.Select(t => t.Value)]);
}
public sealed record JobStatus(
bool IsRunning,
[property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] DateTimeOffset? NextScheduledRun = null
src/Api/Clip.cs
+0
-10
diff --git a/src/Api/Clip.cs b/src/Api/Clip.cs
deleted file mode 100644
index b458aa7..0000000
@@ -1,10 +0,0 @@
using System;
using System.Linq;
namespace Slopper.Api;
public sealed record Clip(Guid Id, TimeSpan Duration, DateTimeOffset CreatedAt, string? Caption, string[] Tags)
{
public static Clip FromDomain(Domain.Clip clip) =>
new(clip.Id, clip.Duration, clip.CreatedAt, clip.Caption, [.. clip.Tags.Select(t => t.Value)]);
}
src/Api/Program.cs
+0
-3
diff --git a/src/Api/Program.cs b/src/Api/Program.cs
index 32069b4..88962c3 100644
@@ -60,7 +60,4 @@ app.MapApi();
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapGet("/admin/youtube", (HttpContext httpContext) => httpContext.User.Identity?.Name)
.RequireYouTubeAuthorization();
app.Run();
src/Api/YouTubeApiEndpoints.cs
+57
-0
diff --git a/src/Api/YouTubeApiEndpoints.cs b/src/Api/YouTubeApiEndpoints.cs
new file mode 100644
index 0000000..8ff365f
@@ -0,0 +1,57 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Slopper.Api.YouTubeAuth;
using Slopper.Domain;
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.MapPost("/upload", Upload).WithDisplayName("Upload Latest Clip to YouTube");
return youtube;
}
}
private static RedirectHttpResult Login() => TypedResults.Redirect("/admin/youtube");
private static async Task<Results<Ok<UploadResult>, NotFound>> Upload(
[FromKeyedServices("YouTube")] IUploader uploader,
[FromServices] IClipRepository clipRepository,
CancellationToken cancellationToken
)
{
var clip = await clipRepository
.GetLatest(limit: 1, cancellationToken: cancellationToken)
.FirstOrDefaultAsync(cancellationToken);
if (clip is null)
{
return TypedResults.NotFound();
}
var result = await uploader.Upload(clip, cancellationToken);
return TypedResults.Ok(UploadResult.FromDomain(result));
}
}
public sealed record UploadResult(Uri CanonicalUrl)
{
public static UploadResult FromDomain(Domain.UploadResult uploadResult) => new(uploadResult.CanonicalUrl);
}