264 lines
11 KiB
C#
264 lines
11 KiB
C#
using FictionArchive.Common.Enums;
|
|
using FictionArchive.Service.NovelService.Models.DTOs;
|
|
using FictionArchive.Service.NovelService.Services;
|
|
using HotChocolate.Authorization;
|
|
using HotChocolate.Data;
|
|
using HotChocolate.Types;
|
|
|
|
namespace FictionArchive.Service.NovelService.GraphQL;
|
|
|
|
public class Query
|
|
{
|
|
[Authorize]
|
|
[UsePaging]
|
|
[UseProjection]
|
|
[UseFiltering]
|
|
[UseSorting]
|
|
public IQueryable<NovelDto> GetNovels(
|
|
NovelServiceDbContext dbContext,
|
|
Language preferredLanguage = Language.En)
|
|
{
|
|
return dbContext.Novels.Select(novel => new NovelDto
|
|
{
|
|
Id = novel.Id,
|
|
CreatedTime = novel.CreatedTime,
|
|
LastUpdatedTime = novel.LastUpdatedTime,
|
|
Url = novel.Url,
|
|
RawLanguage = novel.RawLanguage,
|
|
RawStatus = novel.RawStatus,
|
|
StatusOverride = novel.StatusOverride,
|
|
ExternalId = novel.ExternalId,
|
|
|
|
Name = novel.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? novel.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
|
|
Description = novel.Description.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? novel.Description.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
|
|
Author = new PersonDto
|
|
{
|
|
Id = novel.Author.Id,
|
|
CreatedTime = novel.Author.CreatedTime,
|
|
LastUpdatedTime = novel.Author.LastUpdatedTime,
|
|
Name = novel.Author.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? novel.Author.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
ExternalUrl = novel.Author.ExternalUrl
|
|
},
|
|
|
|
Source = new SourceDto
|
|
{
|
|
Id = novel.Source.Id,
|
|
CreatedTime = novel.Source.CreatedTime,
|
|
LastUpdatedTime = novel.Source.LastUpdatedTime,
|
|
Name = novel.Source.Name,
|
|
Key = novel.Source.Key,
|
|
Url = novel.Source.Url
|
|
},
|
|
|
|
CoverImage = novel.CoverImage != null
|
|
? new ImageDto
|
|
{
|
|
Id = novel.CoverImage.Id,
|
|
CreatedTime = novel.CoverImage.CreatedTime,
|
|
LastUpdatedTime = novel.CoverImage.LastUpdatedTime,
|
|
NewPath = novel.CoverImage.NewPath
|
|
}
|
|
: null,
|
|
|
|
Volumes = novel.Volumes.OrderBy(v => v.Order).Select(volume => new VolumeDto
|
|
{
|
|
Id = volume.Id,
|
|
CreatedTime = volume.CreatedTime,
|
|
LastUpdatedTime = volume.LastUpdatedTime,
|
|
Order = volume.Order,
|
|
Name = volume.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? volume.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
Chapters = volume.Chapters.OrderBy(c => c.Order).Select(chapter => new ChapterDto
|
|
{
|
|
Id = chapter.Id,
|
|
CreatedTime = chapter.CreatedTime,
|
|
LastUpdatedTime = chapter.LastUpdatedTime,
|
|
Revision = chapter.Revision,
|
|
Order = chapter.Order,
|
|
Url = chapter.Url,
|
|
Name = chapter.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? chapter.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
Body = chapter.Body.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? chapter.Body.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
Images = chapter.Images.Select(image => new ImageDto
|
|
{
|
|
Id = image.Id,
|
|
CreatedTime = image.CreatedTime,
|
|
LastUpdatedTime = image.LastUpdatedTime,
|
|
NewPath = image.NewPath
|
|
}).ToList()
|
|
}).ToList()
|
|
}).ToList(),
|
|
|
|
Tags = novel.Tags.Select(tag => new NovelTagDto
|
|
{
|
|
Id = tag.Id,
|
|
CreatedTime = tag.CreatedTime,
|
|
LastUpdatedTime = tag.LastUpdatedTime,
|
|
Key = tag.Key,
|
|
TagType = tag.TagType,
|
|
DisplayName = tag.DisplayName.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? tag.DisplayName.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
Source = tag.Source != null
|
|
? new SourceDto
|
|
{
|
|
Id = tag.Source.Id,
|
|
CreatedTime = tag.Source.CreatedTime,
|
|
LastUpdatedTime = tag.Source.LastUpdatedTime,
|
|
Name = tag.Source.Name,
|
|
Key = tag.Source.Key,
|
|
Url = tag.Source.Url
|
|
}
|
|
: null
|
|
}).ToList()
|
|
});
|
|
}
|
|
|
|
[Authorize]
|
|
[UseFirstOrDefault]
|
|
[UseProjection]
|
|
public IQueryable<ChapterReaderDto> GetChapter(
|
|
NovelServiceDbContext dbContext,
|
|
uint novelId,
|
|
uint volumeId,
|
|
uint chapterOrder,
|
|
Language preferredLanguage = Language.En)
|
|
{
|
|
return dbContext.Chapters
|
|
.Where(c => c.Volume.Novel.Id == novelId && c.Volume.Id == volumeId && c.Order == chapterOrder)
|
|
.Select(chapter => new ChapterReaderDto
|
|
{
|
|
Id = chapter.Id,
|
|
CreatedTime = chapter.CreatedTime,
|
|
LastUpdatedTime = chapter.LastUpdatedTime,
|
|
Revision = chapter.Revision,
|
|
Order = chapter.Order,
|
|
Url = chapter.Url,
|
|
|
|
Name = chapter.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? chapter.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
|
|
Body = chapter.Body.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? chapter.Body.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
|
|
Images = chapter.Images.Select(image => new ImageDto
|
|
{
|
|
Id = image.Id,
|
|
CreatedTime = image.CreatedTime,
|
|
LastUpdatedTime = image.LastUpdatedTime,
|
|
NewPath = image.NewPath
|
|
}).ToList(),
|
|
|
|
NovelId = chapter.Volume.Novel.Id,
|
|
NovelName = chapter.Volume.Novel.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? chapter.Volume.Novel.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
|
|
// Volume context
|
|
VolumeId = chapter.Volume.Id,
|
|
VolumeName = chapter.Volume.Name.Texts
|
|
.Where(t => t.Language == preferredLanguage)
|
|
.Select(t => t.Text)
|
|
.FirstOrDefault()
|
|
?? chapter.Volume.Name.Texts.Select(t => t.Text).FirstOrDefault()
|
|
?? "",
|
|
VolumeOrder = chapter.Volume.Order,
|
|
TotalChaptersInVolume = chapter.Volume.Chapters.Count,
|
|
|
|
// Previous chapter: first try same volume, then last chapter of previous volume
|
|
PrevChapterVolumeId = chapter.Volume.Chapters
|
|
.Where(c => c.Order < chapterOrder)
|
|
.OrderByDescending(c => c.Order)
|
|
.Select(c => (uint?)chapter.Volume.Id)
|
|
.FirstOrDefault()
|
|
?? chapter.Volume.Novel.Volumes
|
|
.Where(v => v.Order < chapter.Volume.Order)
|
|
.OrderByDescending(v => v.Order)
|
|
.SelectMany(v => v.Chapters.OrderByDescending(c => c.Order).Take(1))
|
|
.Select(c => (uint?)c.Volume.Id)
|
|
.FirstOrDefault(),
|
|
|
|
PrevChapterOrder = chapter.Volume.Chapters
|
|
.Where(c => c.Order < chapterOrder)
|
|
.OrderByDescending(c => c.Order)
|
|
.Select(c => (uint?)c.Order)
|
|
.FirstOrDefault()
|
|
?? chapter.Volume.Novel.Volumes
|
|
.Where(v => v.Order < chapter.Volume.Order)
|
|
.OrderByDescending(v => v.Order)
|
|
.SelectMany(v => v.Chapters.OrderByDescending(c => c.Order).Take(1))
|
|
.Select(c => (uint?)c.Order)
|
|
.FirstOrDefault(),
|
|
|
|
// Next chapter: first try same volume, then first chapter of next volume
|
|
NextChapterVolumeId = chapter.Volume.Chapters
|
|
.Where(c => c.Order > chapterOrder)
|
|
.OrderBy(c => c.Order)
|
|
.Select(c => (uint?)chapter.Volume.Id)
|
|
.FirstOrDefault()
|
|
?? chapter.Volume.Novel.Volumes
|
|
.Where(v => v.Order > chapter.Volume.Order)
|
|
.OrderBy(v => v.Order)
|
|
.SelectMany(v => v.Chapters.OrderBy(c => c.Order).Take(1))
|
|
.Select(c => (uint?)c.Volume.Id)
|
|
.FirstOrDefault(),
|
|
|
|
NextChapterOrder = chapter.Volume.Chapters
|
|
.Where(c => c.Order > chapterOrder)
|
|
.OrderBy(c => c.Order)
|
|
.Select(c => (uint?)c.Order)
|
|
.FirstOrDefault()
|
|
?? chapter.Volume.Novel.Volumes
|
|
.Where(v => v.Order > chapter.Volume.Order)
|
|
.OrderBy(v => v.Order)
|
|
.SelectMany(v => v.Chapters.OrderBy(c => c.Order).Take(1))
|
|
.Select(c => (uint?)c.Order)
|
|
.FirstOrDefault()
|
|
});
|
|
}
|
|
}
|