Added Source Chapter and Source Page entities.

This commit is contained in:
2025-06-12 02:34:26 -04:00
parent 000a20bb0f
commit a82eab0ecb
18 changed files with 232 additions and 79 deletions

View File

@@ -2,5 +2,6 @@
public interface IMangaPipeline
{
Task RunAsync(MangaPipelineRequest request);
Task RunMetadataAsync(MangaMetadataPipelineRequest request);
Task RunPagesAsync(MangaPagePipelineRequest request);
}

View File

@@ -2,8 +2,9 @@
namespace MangaReader.Core.Pipeline;
public class MangaPipelineRequest
public class MangaMetadataPipelineRequest
{
public int? MangaId { get; init; }
public required string SourceName { get; init; }
public required string SourceUrl { get; init; }
public required SourceManga SourceManga { get; init; }

View File

@@ -0,0 +1,7 @@
namespace MangaReader.Core.Pipeline;
public class MangaPagePipelineRequest
{
public required int SourceChapterId { get; init; }
public required IReadOnlyList<string> PageImageUrls { get; init; }
}

View File

@@ -13,7 +13,7 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
Secondary
}
public async Task RunAsync(MangaPipelineRequest request)
public async Task RunMetadataAsync(MangaMetadataPipelineRequest request)
{
string sourceName = request.SourceName;
string sourceUrl = request.SourceUrl;
@@ -21,8 +21,8 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
Source source = await GetOrAddSourceAsync(sourceName);
Manga manga = await GetOrAddMangaAsync(sourceManga);
MangaSource mangaSource = await AddMangaSourceAsync(sourceUrl, manga, source);
await AddMangaSourceAsync(sourceUrl, manga, source);
await AddTitleAsync(manga, sourceManga.Title, TitleType.Primary);
await AddDescriptionAsync(manga, sourceManga.Description);
@@ -38,7 +38,7 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
foreach (SourceMangaChapter chapter in sourceManga.Chapters)
{
await AddChapterAsync(manga, chapter);
await AddChapterAsync(mangaSource, chapter);
}
context.SaveChanges();
@@ -94,13 +94,13 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
[GeneratedRegex(@"\s+")]
private static partial Regex RemoveSpacesWithDashRegex();
private async Task AddMangaSourceAsync(string sourceUrl, Manga manga, Source source)
private async Task<MangaSource> AddMangaSourceAsync(string sourceUrl, Manga manga, Source source)
{
MangaSource? mangaSource = await context.MangaSources.FirstOrDefaultAsync(ms =>
ms.Manga == manga && ms.Source == source && ms.Url == sourceUrl);
if (mangaSource != null)
return;
return mangaSource;
mangaSource = new()
{
@@ -110,6 +110,8 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
};
context.MangaSources.Add(mangaSource);
return mangaSource;
}
private async Task AddTitleAsync(Manga manga, SourceMangaTitle sourceMangaTitle, TitleType titleType)
@@ -187,32 +189,76 @@ public partial class MangaPipeline(MangaContext context) : IMangaPipeline
return genre;
}
private async Task AddChapterAsync(Manga manga, SourceMangaChapter sourceMangaChapter)
private async Task AddChapterAsync(MangaSource mangaSource, SourceMangaChapter sourceMangaChapter)
{
MangaChapter mangaChapter = await context.MangaChapters.FirstOrDefaultAsync(x => x.ChapterNumber == sourceMangaChapter.Number)
?? AddMangaChapter(manga, sourceMangaChapter);
SourceChapter sourceChapter = await GetSourceChapter(mangaSource, sourceMangaChapter)
?? AddSourceChapter(mangaSource, sourceMangaChapter);
if (mangaChapter.VolumeNumber is null && sourceMangaChapter.Volume is not null)
if (sourceChapter.VolumeNumber is null && sourceMangaChapter.Volume is not null)
{
mangaChapter.VolumeNumber = sourceMangaChapter.Volume;
sourceChapter.VolumeNumber = sourceMangaChapter.Volume;
}
if (mangaChapter.Title is null && sourceMangaChapter.Title is not null)
if (sourceChapter.Title is null && sourceMangaChapter.Title is not null)
{
mangaChapter.Title = sourceMangaChapter.Title;
sourceChapter.Title = sourceMangaChapter.Title;
}
}
private MangaChapter AddMangaChapter(Manga manga, SourceMangaChapter sourceMangaChapter)
private async Task<SourceChapter?> GetSourceChapter(MangaSource mangaSource, SourceMangaChapter sourceMangaChapter)
{
MangaChapter mangaChapter = new()
return await context.SourceChapters.FirstOrDefaultAsync(x =>
x.MangaSource == mangaSource && x.ChapterNumber == sourceMangaChapter.Number);
}
private SourceChapter AddSourceChapter(MangaSource mangaSource, SourceMangaChapter sourceMangaChapter)
{
SourceChapter sourceChapter = new()
{
Manga = manga,
ChapterNumber = sourceMangaChapter.Number
MangaSource = mangaSource,
ChapterNumber = sourceMangaChapter.Number,
Url = sourceMangaChapter.Url
};
context.MangaChapters.Add(mangaChapter);
context.SourceChapters.Add(sourceChapter);
return mangaChapter;
return sourceChapter;
}
public async Task RunPagesAsync(MangaPagePipelineRequest request)
{
SourceChapter? sourceChapter = await context.SourceChapters.FirstOrDefaultAsync(x => x.SourceChapterId == request.SourceChapterId);
if (sourceChapter == null)
return;
int currentPageNumber = 1;
foreach (string pageImageUrl in request.PageImageUrls)
{
await AddOrUpdateSourcePageAsync(sourceChapter, currentPageNumber++, pageImageUrl);
}
}
private async Task AddOrUpdateSourcePageAsync(SourceChapter sourceChapter, int pageNumber, string pageImageUrl)
{
SourcePage? sourcePage = await context.SourcePages.FirstOrDefaultAsync(x =>
x.Chapter == sourceChapter && x.PageNumber == pageNumber);
if (sourcePage == null)
{
sourcePage = new()
{
Chapter = sourceChapter,
PageNumber = pageNumber,
Url = pageImageUrl
};
context.SourcePages.Add(sourcePage);
}
else
{
sourcePage.Url = pageImageUrl;
}
}
}