using FictionArchive.Service.NovelService.Models.Enums; using FictionArchive.Service.NovelService.Models.Localization; using FictionArchive.Service.NovelService.Models.Novels; using FictionArchive.Service.NovelService.Models.SourceAdapters; using FictionArchive.Service.NovelService.Services; using FictionArchive.Service.NovelService.Services.SourceAdapters; using Microsoft.EntityFrameworkCore; namespace FictionArchive.Service.NovelService.GraphQL; public class Mutation { // TODO Make this kick off a job in the background somehow. Probably want to think of how jobs will work across services // Also of course need to make it a proper 'upsert' public async Task ImportNovel(string novelUrl, NovelServiceDbContext dbContext, IEnumerable adapters) { NovelMetadata? metadata = null; foreach (ISourceAdapter sourceAdapter in adapters) { if (await sourceAdapter.CanProcessNovel(novelUrl)) { metadata = await sourceAdapter.GetMetadata(novelUrl); } } if (metadata == null) { throw new NotSupportedException("The provided novel url is currently unsupported."); } var systemTags = metadata.SystemTags.Select(tag => new NovelTag() { Key = tag, DisplayName = LocalizationKey.CreateFromText(tag, metadata.RawLanguage), TagType = TagType.System }); var sourceTags = metadata.SourceTags.Select(tag => new NovelTag() { Key = tag, DisplayName = LocalizationKey.CreateFromText(tag, metadata.RawLanguage), TagType = TagType.External }); var addedNovel = dbContext.Novels.Add(new Novel() { Author = new Person() { Name = metadata.AuthorName, ExternalUrl = metadata.AuthorUrl, }, RawLanguage = metadata.RawLanguage, Url = metadata.Url, ExternalId = metadata.ExternalId, Chapters = metadata.Chapters.Select(chapter => { return new Chapter() { Order = chapter.Order, Url = chapter.Url, Revision = chapter.Revision, Name = LocalizationKey.CreateFromText(chapter.Name, metadata.RawLanguage), Body = new LocalizationKey() { Texts = new List() } }; }).ToList(), Description = LocalizationKey.CreateFromText(metadata.Description, metadata.RawLanguage), Name = LocalizationKey.CreateFromText(metadata.Name, metadata.RawLanguage), RawStatus = metadata.RawStatus, Tags = sourceTags.Concat(systemTags).ToList(), Source = new Source() { Name = metadata.SourceDescriptor.Name, Url = metadata.SourceDescriptor.Url, Key = metadata.SourceDescriptor.Key, } }); await dbContext.SaveChangesAsync(); return addedNovel.Entity; } public async Task FetchChapterContents(uint novelId, uint chapterNumber, NovelServiceDbContext dbContext, IEnumerable sourceAdapters) { var novel = await dbContext.Novels.Where(novel => novel.Id == novelId) .Include(novel => novel.Chapters) .ThenInclude(chapter => chapter.Body) .ThenInclude(body => body.Texts) .Include(novel => novel.Source) .FirstOrDefaultAsync(); var chapter = novel.Chapters.Where(chapter => chapter.Order == chapterNumber).FirstOrDefault(); var adapter = sourceAdapters.FirstOrDefault(adapter => adapter.SourceDescriptor.Key == novel.Source.Key); var rawChapter = await adapter.GetRawChapter(chapter.Url); chapter.Body.Texts.Add(new LocalizationText() { Text = rawChapter, Language = novel.RawLanguage }); await dbContext.SaveChangesAsync(); return chapter; } }