diff --git a/API/DTOs/KavitaPlus/Metadata/ExternalChapterDto.cs b/API/DTOs/KavitaPlus/Metadata/ExternalChapterDto.cs index 83b0fcd94..6b711513c 100644 --- a/API/DTOs/KavitaPlus/Metadata/ExternalChapterDto.cs +++ b/API/DTOs/KavitaPlus/Metadata/ExternalChapterDto.cs @@ -19,9 +19,9 @@ public class ExternalChapterDto public string? Summary { get; set; } - public string? Writer { get; set; } + public IList? Writers { get; set; } - public string? Artist { get; set; } + public IList? Artists { get; set; } public DateTime? ReleaseDate { get; set; } diff --git a/API/DTOs/KavitaPlus/Metadata/ExternalSeriesDetailDto.cs b/API/DTOs/KavitaPlus/Metadata/ExternalSeriesDetailDto.cs index bee228f37..2ea746214 100644 --- a/API/DTOs/KavitaPlus/Metadata/ExternalSeriesDetailDto.cs +++ b/API/DTOs/KavitaPlus/Metadata/ExternalSeriesDetailDto.cs @@ -35,11 +35,11 @@ public class ExternalSeriesDetailDto public IList? Characters { get; set; } = []; #region Comic Only - public string Publisher { get; set; } + public string? Publisher { get; set; } /// /// Only from CBR for . Full metadata about issues /// - public IList ChapterDtos { get; set; } + public IList? ChapterDtos { get; set; } #endregion diff --git a/API/Data/Repositories/ChapterRepository.cs b/API/Data/Repositories/ChapterRepository.cs index 52ded9e94..376592a71 100644 --- a/API/Data/Repositories/ChapterRepository.cs +++ b/API/Data/Repositories/ChapterRepository.cs @@ -47,6 +47,7 @@ public interface IChapterRepository Task> GetCoverImagesForLockedChaptersAsync(); Task AddChapterModifiers(int userId, ChapterDto chapter); IEnumerable GetChaptersForSeries(int seriesId); + Task> GetAllChaptersForSeries(int seriesId); } public class ChapterRepository : IChapterRepository { @@ -298,4 +299,13 @@ public class ChapterRepository : IChapterRepository .Include(c => c.Volume) .AsEnumerable(); } + + public async Task> GetAllChaptersForSeries(int seriesId) + { + return await _context.Chapter + .Where(c => c.Volume.SeriesId == seriesId) + .OrderBy(c => c.SortOrder) + .Include(c => c.Volume) + .ToListAsync(); + } } diff --git a/API/Services/Plus/ExternalMetadataService.cs b/API/Services/Plus/ExternalMetadataService.cs index b198d2fa7..0c66ed97e 100644 --- a/API/Services/Plus/ExternalMetadataService.cs +++ b/API/Services/Plus/ExternalMetadataService.cs @@ -836,7 +836,6 @@ public class ExternalMetadataService : IExternalMetadataService } } - // Download the image and save it _unitOfWork.SeriesRepository.Update(series); await _unitOfWork.CommitAsync(); @@ -1038,8 +1037,71 @@ public class ExternalMetadataService : IExternalMetadataService { if (externalMetadata.PlusMediaFormat != PlusMediaFormat.Comic) return false; - var chapters = await _unitOfWork.ChapterRepository.GetChaptersAsync(1); - return false; + if (externalMetadata.ChapterDtos == null || externalMetadata.ChapterDtos.Count == 0) return false; + + // Get all volumes and chapters + var madeModification = false; + var allChapters = await _unitOfWork.ChapterRepository.GetAllChaptersForSeries(series.Id); + + var matchedChapters = allChapters + .Join( + externalMetadata.ChapterDtos, + chapter => chapter.Range, + dto => dto.IssueNumber, + (chapter, dto) => (chapter, dto) // Create a tuple of matched pairs + ) + .ToList(); + + foreach (var (chapter, potentialMatch) in matchedChapters) + { + _logger.LogDebug("Updating {ChapterNumber} with metadata", chapter.Range); + + // Write the metadata + if (!string.IsNullOrEmpty(potentialMatch.Title) && !potentialMatch.Title.Contains(series.Name)) + { + chapter.Title = potentialMatch.Title; + _unitOfWork.ChapterRepository.Update(chapter); + madeModification = true; + } + + if (!chapter.SummaryLocked && string.IsNullOrEmpty(chapter.Summary) & !string.IsNullOrEmpty(potentialMatch.Summary)) + { + chapter.Summary = potentialMatch.Summary; + _unitOfWork.ChapterRepository.Update(chapter); + madeModification = true; + } + + // ReleaseDate + // Cover Image + + + // Update People (Writer/Artist/Publisher) + if (!chapter.PublisherLocked) + { + // Update publisher + } + + //var artists = potentialMatch.Artists.Select(p => new PersonDto()) + + // await SeriesService.HandlePeopleUpdateAsync(series.Metadata, artists, PersonRole.CoverArtist, _unitOfWork); + // + // foreach (var person in series.Metadata.People.Where(p => p.Role == PersonRole.CoverArtist)) + // { + // var meta = upstreamArtists.FirstOrDefault(c => c.Name == person.Person.Name); + // person.OrderWeight = 0; + // if (meta != null) + // { + // person.KavitaPlusConnection = true; + // } + // } + } + + + + _unitOfWork.SeriesRepository.Update(series); + await _unitOfWork.CommitAsync(); + + return madeModification; } private async Task UpdateCoverImage(Series series, MetadataSettingsDto settings, ExternalSeriesDetailDto externalMetadata)