using Hutopy.Infrastructure.YouTube; using Hutopy.Modules.Creators.Data; namespace Hutopy.Modules.Creators.Features; [PublicAPI] public record ChangePresentationInfosRequest( Guid CreatorId, string Description, string? VideoUrl); [PublicAPI] public sealed class ChangePresentationInfosRequestValidator : Validator { public ChangePresentationInfosRequestValidator() { RuleFor(x => x.CreatorId) .NotEmpty() .WithMessage("Creator ID is required"); RuleFor(x => x.Description) .NotEmpty() .WithMessage("Description is required") .MaximumLength(2000) .WithMessage("Description cannot exceed 2000 characters"); RuleFor(x => x.VideoUrl) .Must(url => url == null || YouTubeUrlHelper.IsValidYouTubeUrlOrId(url)) .WithMessage("Invalid YouTube URL or video ID format"); } } [PublicAPI] public class ChangePresentationInfosHandler( CreatorsDbContext context) : Endpoint { public override void Configure() { Post("/api/creators/{CreatorId}/presentation-infos"); Options(o => o.WithTags("Creators")); } public override async Task HandleAsync( ChangePresentationInfosRequest request, CancellationToken ct) { Creator? creator = await context .Creators .Include(c => c.Presentation) .SingleOrDefaultAsync( c => c.Id == request.CreatorId, ct); if (creator is null) { await SendNotFoundAsync(ct); return; } // Update the presentation info with the new values creator.Presentation.Description = request.Description.Trim(); creator.Presentation.VideoUrl = request.VideoUrl != null ? YouTubeUrlHelper.ExtractVideoId(request.VideoUrl.Trim()) : null; await context.SaveChangesAsync(ct); await SendOkAsync(ct); } }