feat: Add validation for YouTube URL and enhance image upload experience in creator's album editor
This commit is contained in:
64
backend/src/Web/Common/YouTube/YouTubeUrlHelper.cs
Normal file
64
backend/src/Web/Common/YouTube/YouTubeUrlHelper.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Hutopy.Web.Common.YouTube;
|
||||
|
||||
public static class YouTubeUrlHelper
|
||||
{
|
||||
private static readonly Regex VideoIdRegex = new(
|
||||
@"(?:youtube\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^""&?/\s]{11})",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private static readonly Regex ShortUrlRegex = new(
|
||||
@"^[a-zA-Z0-9_-]{11}$",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the video ID from a YouTube URL or returns the input if it's already a video ID.
|
||||
/// </summary>
|
||||
/// <param name="input">The YouTube URL or video ID</param>
|
||||
/// <returns>The extracted video ID or null if invalid</returns>
|
||||
public static string? ExtractVideoId(string? input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return null;
|
||||
|
||||
// If it's already a valid video ID, return it
|
||||
if (IsValidVideoId(input))
|
||||
return input;
|
||||
|
||||
// Try to extract video ID from URL
|
||||
var match = VideoIdRegex.Match(input);
|
||||
return match.Success ? match.Groups[1].Value : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if the input is a valid YouTube video ID.
|
||||
/// </summary>
|
||||
/// <param name="input">The video ID to validate</param>
|
||||
/// <returns>True if the input is a valid video ID</returns>
|
||||
public static bool IsValidVideoId(string? input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return false;
|
||||
|
||||
return ShortUrlRegex.IsMatch(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if the input is a valid YouTube URL or video ID.
|
||||
/// </summary>
|
||||
/// <param name="input">The URL or video ID to validate</param>
|
||||
/// <returns>True if the input is a valid YouTube URL or video ID</returns>
|
||||
public static bool IsValidYouTubeUrlOrId(string? input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return false;
|
||||
|
||||
// Check if it's a valid video ID
|
||||
if (IsValidVideoId(input))
|
||||
return true;
|
||||
|
||||
// Check if it's a valid YouTube URL
|
||||
return VideoIdRegex.IsMatch(input);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using Hutopy.Web.Common.BlobStorage;
|
||||
using Hutopy.Web.Common.YouTube;
|
||||
using Hutopy.Web.Features.Contents.Data;
|
||||
|
||||
namespace Hutopy.Web.Features.Contents.Handlers;
|
||||
@@ -11,10 +11,36 @@ public record ChangePresentationInfosRequest(
|
||||
string? PhoneNumber,
|
||||
string? Email);
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class ChangePresentationInfosRequestValidator : Validator<ChangePresentationInfosRequest>
|
||||
{
|
||||
public ChangePresentationInfosRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.CreatorId)
|
||||
.NotEmpty()
|
||||
.WithMessage("Creator ID is required");
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.NotEmpty()
|
||||
.WithMessage("Description is required");
|
||||
|
||||
RuleFor(x => x.VideoUrl)
|
||||
.Must(url => url == null || YouTubeUrlHelper.IsValidYouTubeUrlOrId(url))
|
||||
.WithMessage("Invalid YouTube URL or video ID format");
|
||||
|
||||
RuleFor(x => x.PhoneNumber)
|
||||
.Must(phone => phone == null || !string.IsNullOrWhiteSpace(phone))
|
||||
.WithMessage("Phone number cannot be empty if provided");
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.Must(email => email == null || !string.IsNullOrWhiteSpace(email))
|
||||
.WithMessage("Email cannot be empty if provided");
|
||||
}
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public class ChangePresentationInfosHandler(
|
||||
ContentDbContext context,
|
||||
AzureBlobStorage blobStorage)
|
||||
ContentDbContext context)
|
||||
: Endpoint<ChangePresentationInfosRequest>
|
||||
{
|
||||
public override void Configure()
|
||||
@@ -42,11 +68,14 @@ public class ChangePresentationInfosHandler(
|
||||
|
||||
// Update the presentation info with the new values
|
||||
creator.Presentation.Description = request.Description.Trim();
|
||||
creator.Presentation.VideoUrl = request.VideoUrl?.Trim();
|
||||
creator.Presentation.VideoUrl = request.VideoUrl != null
|
||||
? YouTubeUrlHelper.ExtractVideoId(request.VideoUrl.Trim())
|
||||
: null;
|
||||
creator.Presentation.PhoneNumber = request.PhoneNumber?.Trim();
|
||||
creator.Presentation.Email = request.Email?.Trim();
|
||||
|
||||
await context.SaveChangesAsync(ct);
|
||||
|
||||
await SendOkAsync(ct);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user