feat(ingestion): implement hybrid metadata verification form in ingestion modal #34
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using FluentResults;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
using NexusReader.Application.Abstractions.Services;
|
||||
using NexusReader.Data.Persistence;
|
||||
using NexusReader.Domain.Entities;
|
||||
|
||||
namespace NexusReader.Application.Commands.Library;
|
||||
|
||||
public class IngestEbookCommandHandler : IRequestHandler<IngestEbookCommand, Result<Guid>>
|
||||
{
|
||||
private readonly IDbContextFactory<AppDbContext> _dbContextFactory;
|
||||
private readonly IBookStorageService _storageService;
|
||||
|
||||
public IngestEbookCommandHandler(
|
||||
IDbContextFactory<AppDbContext> dbContextFactory,
|
||||
IBookStorageService storageService)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_storageService = storageService;
|
||||
}
|
||||
|
||||
public async Task<Result<Guid>> Handle(IngestEbookCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
// 1. Save Files
|
||||
var epubPath = await _storageService.SaveEbookAsync(request.EpubData, $"{request.Title}.epub");
|
||||
var coverUrl = request.CoverImage != null && request.CoverImage.Length > 0
|
||||
? await _storageService.SaveCoverAsync(request.CoverImage, $"{request.Title}_cover.jpg")
|
||||
: null;
|
||||
|
||||
// 2. Resolve Author
|
||||
var authorName = string.IsNullOrWhiteSpace(request.AuthorName) ? "Unknown Author" : request.AuthorName.Trim();
|
||||
var author = await context.Authors
|
||||
.FirstOrDefaultAsync(a => a.Name.ToLower() == authorName.ToLower(), cancellationToken);
|
||||
|
||||
if (author == null)
|
||||
{
|
||||
author = new Author { Name = authorName };
|
||||
context.Authors.Add(author);
|
||||
// We need to save to get the Author ID if we want to use it,
|
||||
// but EF will handle it if we assign the object.
|
||||
}
|
||||
|
||||
// 3. Create Ebook
|
||||
var ebook = new Ebook
|
||||
{
|
||||
Title = request.Title,
|
||||
Author = author,
|
||||
FilePath = epubPath,
|
||||
CoverUrl = coverUrl,
|
||||
UserId = request.UserId,
|
||||
TenantId = request.TenantId,
|
||||
AddedDate = DateTime.UtcNow
|
||||
};
|
||||
|
||||
context.Ebooks.Add(ebook);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return Result.Ok(ebook.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(new Error("Failed to ingest ebook").CausedBy(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user