Implement image management enhancements: add functionality to relocate legacy images during startup, update image handling in show metadata, and refactor related API endpoints to utilize the new image storage system. Adjust database schema to support image references and update UI components for improved image selection and display.

This commit is contained in:
Leonid Pershin
2026-07-25 11:43:17 +03:00
parent 149cd153b9
commit a970eae7d2
30 changed files with 1231 additions and 172 deletions
@@ -7,43 +7,6 @@ namespace TeleWave.Infrastructure.Metadata;
public sealed class MetadataImageStore(MediaPathResolver paths, IHttpClientFactory httpFactory)
: IMetadataImageStore
{
public async Task<string?> DownloadShowPosterAsync(
Guid showId,
string url,
CancellationToken cancellationToken
)
{
try
{
var client = httpFactory.CreateClient("metadata");
using var response = await client.GetAsync(url, cancellationToken);
if (!response.IsSuccessStatusCode)
return null;
var ext = ExtensionFor(url, response.Content.Headers.ContentType?.MediaType);
await using var content = await response.Content.ReadAsStreamAsync(cancellationToken);
return await WritePosterAsync(showId, ext, content, cancellationToken);
}
catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException or IOException)
{
return null;
}
}
public Task<string> SaveShowPosterAsync(
Guid showId,
string extension,
Stream content,
CancellationToken cancellationToken
) => WritePosterAsync(showId, NormalizeExtension(extension), content, cancellationToken);
public void DeleteShowImages(Guid showId)
{
var dir = paths.MetadataShowDir(showId);
if (Directory.Exists(dir))
Directory.Delete(dir, recursive: true);
}
public async Task<string?> DownloadEpisodeStillAsync(
Guid episodeId,
string url,
@@ -87,24 +50,6 @@ public sealed class MetadataImageStore(MediaPathResolver paths, IHttpClientFacto
return abs is not null && File.Exists(abs) ? abs : null;
}
private async Task<string> WritePosterAsync(
Guid showId,
string ext,
Stream content,
CancellationToken cancellationToken
)
{
var dir = paths.MetadataShowDir(showId);
Directory.CreateDirectory(dir);
RemoveExisting(dir, "poster");
var abs = paths.MetadataShowPosterPath(showId, ext);
await using (var fs = File.Create(abs))
await content.CopyToAsync(fs, cancellationToken);
return paths.MetadataShowPosterRelative(showId, ext);
}
private static void RemoveExisting(string dir, string baseName)
{
foreach (var file in Directory.EnumerateFiles(dir, baseName + ".*"))
@@ -119,7 +64,4 @@ public sealed class MetadataImageStore(MediaPathResolver paths, IHttpClientFacto
"image/jpeg" => ".jpg",
_ => Path.GetExtension(new Uri(url).AbsolutePath) is { Length: > 1 } e ? e.ToLowerInvariant() : ".jpg",
};
private static string NormalizeExtension(string extension) =>
extension.StartsWith('.') ? extension.ToLowerInvariant() : "." + extension.ToLowerInvariant();
}