Add metadata management for shows: implement metadata retrieval, application, and updates in the API and UI. Enhance Show and ShowDto models to include metadata fields, and update the database schema accordingly. Introduce new endpoints for metadata operations and integrate metadata display in the ShowDetail component.

This commit is contained in:
Leonid Pershin
2026-07-25 09:07:55 +03:00
parent ba023bc416
commit 0d2dee815e
42 changed files with 2271 additions and 4 deletions
@@ -18,6 +18,7 @@ public sealed class MediaPathResolver
OriginalsDir = Path.Combine(_root, "originals");
AssetsDir = Path.Combine(_root, "assets");
BumpersDir = Path.Combine(_root, "bumpers");
MetadataDir = Path.Combine(_root, "metadata");
}
public string InboxDir { get; }
@@ -28,6 +29,9 @@ public sealed class MediaPathResolver
/// <summary>Сырые файлы шаблонов заставок (фон/музыка) по каналам — не режутся на HLS.</summary>
public string BumpersDir { get; }
/// <summary>Картинки метаданных (постеры/кадры), скачанные локально.</summary>
public string MetadataDir { get; }
public void EnsureDirectories()
{
Directory.CreateDirectory(InboxDir);
@@ -35,6 +39,33 @@ public sealed class MediaPathResolver
Directory.CreateDirectory(OriginalsDir);
Directory.CreateDirectory(AssetsDir);
Directory.CreateDirectory(BumpersDir);
Directory.CreateDirectory(MetadataDir);
}
public string MetadataShowDir(Guid showId) =>
EnsureWithinRoot(Path.Combine(MetadataDir, "shows", showId.ToString("N")));
/// <summary>Абсолютный путь к файлу постера шоу (extension — с точкой).</summary>
public string MetadataShowPosterPath(Guid showId, string extension) =>
EnsureWithinRoot(
Path.Combine(MetadataDir, "shows", showId.ToString("N"), "poster" + extension)
);
/// <summary>Относительный путь постера от корня (для хранения в БД и отдачи).</summary>
public string MetadataShowPosterRelative(Guid showId, string extension) =>
$"metadata/shows/{showId:N}/poster{extension}";
/// <summary>Абсолютный путь по относительному (с защитой от traversal) или null, если вне корня.</summary>
public string? ResolveRelative(string relativePath)
{
try
{
return EnsureWithinRoot(Path.Combine(_root, relativePath));
}
catch (UnauthorizedAccessException)
{
return null;
}
}
public string BumperChannelDir(Guid channelId) =>