OPDS Enhancements (#1687)
* Bump express from 4.17.2 to 4.18.2 in /UI/Web Bumps [express](https://github.com/expressjs/express) from 4.17.2 to 4.18.2. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.17.2...4.18.2) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> * Bump decode-uri-component from 0.2.0 to 0.2.2 in /UI/Web Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2. - [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases) - [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2) --- updated-dependencies: - dependency-name: decode-uri-component dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> * Bump qs and express in /UI/Web Bumps [qs](https://github.com/ljharb/qs) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `qs` from 6.5.3 to 6.11.0 - [Release notes](https://github.com/ljharb/qs/releases) - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/qs/compare/v6.5.3...v6.11.0) Updates `express` from 4.17.2 to 4.18.2 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.17.2...4.18.2) --- updated-dependencies: - dependency-name: qs dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> * Added genre and authors to Series level, added summary to volume and chapter level. Force order on reading list title as Chunky enforces their own sort order and doesn't respect the spec. * Moved all the reading list formatting logic to the backend. This allows us to re-use the UI logic for OPDS streams. * Fixed a broken unit test * Code smells Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
fbd9b36e35
commit
1a729adf40
15 changed files with 369 additions and 344 deletions
|
@ -253,6 +253,7 @@ public class OpdsController : BaseApiController
|
|||
PageNumber = pageNumber,
|
||||
PageSize = 20
|
||||
});
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(series.Select(s => s.Id));
|
||||
|
||||
var feed = CreateFeed(tag.Title + " Collection", $"{apiKey}/collections/{collectionId}", apiKey);
|
||||
SetFeedId(feed, $"collections-{collectionId}");
|
||||
|
@ -260,7 +261,7 @@ public class OpdsController : BaseApiController
|
|||
|
||||
foreach (var seriesDto in series)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
}
|
||||
|
||||
|
||||
|
@ -322,7 +323,7 @@ public class OpdsController : BaseApiController
|
|||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId)).ToList();
|
||||
foreach (var item in items)
|
||||
{
|
||||
feed.Entries.Add(CreateChapter(apiKey, $"{item.SeriesName} Chapter {item.ChapterNumber}", item.ChapterId, item.VolumeId, item.SeriesId));
|
||||
feed.Entries.Add(CreateChapter(apiKey, $"{item.Order} - {item.SeriesName}: {item.Title}", string.Empty, item.ChapterId, item.VolumeId, item.SeriesId));
|
||||
}
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
@ -347,6 +348,7 @@ public class OpdsController : BaseApiController
|
|||
PageNumber = pageNumber,
|
||||
PageSize = 20
|
||||
}, _filterDto);
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(series.Select(s => s.Id));
|
||||
|
||||
var feed = CreateFeed(library.Name, $"{apiKey}/libraries/{libraryId}", apiKey);
|
||||
SetFeedId(feed, $"library-{library.Name}");
|
||||
|
@ -354,7 +356,7 @@ public class OpdsController : BaseApiController
|
|||
|
||||
foreach (var seriesDto in series)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -372,6 +374,7 @@ public class OpdsController : BaseApiController
|
|||
PageNumber = pageNumber,
|
||||
PageSize = 20
|
||||
}, _filterDto);
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(recentlyAdded.Select(s => s.Id));
|
||||
|
||||
var feed = CreateFeed("Recently Added", $"{apiKey}/recently-added", apiKey);
|
||||
SetFeedId(feed, "recently-added");
|
||||
|
@ -379,7 +382,7 @@ public class OpdsController : BaseApiController
|
|||
|
||||
foreach (var seriesDto in recentlyAdded)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -397,6 +400,7 @@ public class OpdsController : BaseApiController
|
|||
PageNumber = pageNumber,
|
||||
};
|
||||
var pagedList = await _unitOfWork.SeriesRepository.GetOnDeck(userId, 0, userParams, _filterDto);
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(pagedList.Select(s => s.Id));
|
||||
|
||||
Response.AddPaginationHeader(pagedList.CurrentPage, pagedList.PageSize, pagedList.TotalCount, pagedList.TotalPages);
|
||||
|
||||
|
@ -406,7 +410,7 @@ public class OpdsController : BaseApiController
|
|||
|
||||
foreach (var seriesDto in pagedList)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -527,7 +531,7 @@ public class OpdsController : BaseApiController
|
|||
if (volume.Chapters.Count == 1)
|
||||
{
|
||||
var firstChapter = volume.Chapters.First();
|
||||
var chapter = CreateChapter(apiKey, volume.Name, firstChapter.Id, volume.Id, seriesId);
|
||||
var chapter = CreateChapter(apiKey, volume.Name, firstChapter.Summary, firstChapter.Id, volume.Id, seriesId);
|
||||
chapter.Id = firstChapter.Id.ToString();
|
||||
feed.Entries.Add(chapter);
|
||||
}
|
||||
|
@ -540,12 +544,12 @@ public class OpdsController : BaseApiController
|
|||
|
||||
foreach (var storylineChapter in seriesDetail.StorylineChapters.Where(c => !c.IsSpecial))
|
||||
{
|
||||
feed.Entries.Add(CreateChapter(apiKey, storylineChapter.Title, storylineChapter.Id, storylineChapter.VolumeId, seriesId));
|
||||
feed.Entries.Add(CreateChapter(apiKey, storylineChapter.Title, storylineChapter.Summary, storylineChapter.Id, storylineChapter.VolumeId, seriesId));
|
||||
}
|
||||
|
||||
foreach (var special in seriesDetail.Specials)
|
||||
{
|
||||
feed.Entries.Add(CreateChapter(apiKey, special.Title, special.Id, special.VolumeId, seriesId));
|
||||
feed.Entries.Add(CreateChapter(apiKey, special.Title, special.Summary, special.Id, special.VolumeId, seriesId));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -679,13 +683,23 @@ public class OpdsController : BaseApiController
|
|||
feed.StartIndex = (Math.Max(list.CurrentPage - 1, 0) * list.PageSize) + 1;
|
||||
}
|
||||
|
||||
private static FeedEntry CreateSeries(SeriesDto seriesDto, string apiKey)
|
||||
private static FeedEntry CreateSeries(SeriesDto seriesDto, SeriesMetadataDto metadata, string apiKey)
|
||||
{
|
||||
return new FeedEntry()
|
||||
{
|
||||
Id = seriesDto.Id.ToString(),
|
||||
Title = $"{seriesDto.Name} ({seriesDto.Format})",
|
||||
Summary = seriesDto.Summary,
|
||||
Authors = metadata.Writers.Select(p => new FeedAuthor()
|
||||
{
|
||||
Name = p.Name,
|
||||
Uri = "http://opds-spec.org/author"
|
||||
}).ToList(),
|
||||
Categories = metadata.Genres.Select(g => new FeedCategory()
|
||||
{
|
||||
Label = g.Title,
|
||||
Term = string.Empty
|
||||
}).ToList(),
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{seriesDto.Id}"),
|
||||
|
@ -716,6 +730,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
Id = volumeDto.Id.ToString(),
|
||||
Title = volumeDto.Name,
|
||||
Summary = volumeDto.Chapters.First().Summary ?? string.Empty,
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||
|
@ -728,12 +743,13 @@ public class OpdsController : BaseApiController
|
|||
};
|
||||
}
|
||||
|
||||
private static FeedEntry CreateChapter(string apiKey, string title, int chapterId, int volumeId, int seriesId)
|
||||
private static FeedEntry CreateChapter(string apiKey, string title, string summary, int chapterId, int volumeId, int seriesId)
|
||||
{
|
||||
return new FeedEntry()
|
||||
{
|
||||
Id = chapterId.ToString(),
|
||||
Title = title,
|
||||
Summary = summary ?? string.Empty,
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue