Refactor manual inbox handling: update ImportManualInboxCommand to accept ManualImportItem objects, enhancing file import functionality with explicit season and episode numbers. Implement CleanupManualLeftoversAsync in IMediaStorage to remove unnecessary files after import. Update frontend components to support new import structure and improve user experience in manual media management.
build / backend (push) Successful in 1m11s
build / frontend (push) Successful in 34s
tests / backend-tests (push) Successful in 1m38s

This commit is contained in:
Leonid Pershin
2026-07-26 15:41:31 +03:00
parent 74bca20a3c
commit a95c0540d9
13 changed files with 585 additions and 90 deletions
@@ -42,7 +42,10 @@ public sealed class ManualInboxIntegrationTests(PostgresFixture fixture)
storage,
Substitute.For<IMediaProcessingQueue>()
).Handle(
new ImportManualInboxCommand([$"Сериал/{first}", $"Сериал/{second}"], showId),
new ImportManualInboxCommand(
[Item($"Сериал/{first}"), Item($"Сериал/{second}")],
showId
),
default
);
@@ -111,7 +114,10 @@ public sealed class ManualInboxIntegrationTests(PostgresFixture fixture)
storage,
Substitute.For<IMediaProcessingQueue>()
).Handle(
new ImportManualInboxCommand([good, "readme.txt", "ушёл.mkv"], showId),
new ImportManualInboxCommand(
[Item(good), Item("readme.txt"), Item("ушёл.mkv")],
showId
),
default
);
@@ -123,6 +129,44 @@ public sealed class ManualInboxIntegrationTests(PostgresFixture fixture)
Assert.Contains(result.Value.Failed, f => f.RelativePath == "ушёл.mkv");
}
[SkippableFact]
public async Task Import_WithExplicitNumbers_UsesThemInsteadOfFileName()
{
Skip.IfNot(fixture.Available, "Docker недоступен");
await using var seedDb = fixture.CreateContext();
var showId = await SeedShowAsync(seedDb);
var name = $"{Guid.NewGuid():N}"[..8] + "-без-номеров.mkv";
var storage = Substitute.For<IMediaStorage>();
storage
.ListManualInbox(Arg.Any<int>())
.Returns([new IMediaStorage.ManualInboxFile(name, name, 1000)]);
await using var db = fixture.CreateContext();
var result = await new ImportManualInboxCommandHandler(
db,
storage,
Substitute.For<IMediaProcessingQueue>()
).Handle(new ImportManualInboxCommand([new ManualImportItem(name, 4, 12)], showId), default);
Assert.True(result.IsSuccess);
await db.SaveChangesAsync();
await using var verify = fixture.CreateContext();
var episode = verify.Shows.Where(s => s.Id == showId).SelectMany(s => s.Episodes).Single();
// Из имени номера не вытащить — значит сохранилось ровно то, что видел пользователь.
Assert.Equal(4, episode.Season);
Assert.Equal(12, episode.Episode);
// И спутники рядом с забранным файлом убираются.
await storage.Received(1).CleanupManualLeftoversAsync(name, Arg.Any<CancellationToken>());
}
/// <summary>Файл без явных номеров — сервер разбирает имя сам, как при обычном добавлении.</summary>
private static ManualImportItem Item(string relativePath) => new(relativePath, null, null);
private static async Task<Guid> SeedShowAsync(AppDbContext db)
{
var show = Show.Create($"Сериал {Guid.NewGuid():N}"[..20], ShowKind.Series);