Random Cleanup + OPDS Base Url Support (#1926)
* Updated a ton of dependencies. PDFs reader got a big update from PDF.js 2.6 -> 3.x * Rolled back fontawesome update * Updated to latest angular patch. Fixed search being too long instead of just to the end of the browser screen. * Fixed alignment on download icon for download indicator in cards * Include progress information on Want To Read API and when marking something as Read, perform cleanup service on want to read. * Removed mark-read updating want to read. As there are series restrictions and it could be misleading. * Tweaked login page spacing when form is dirty * Replaced an object instantiation * Commented out a few tests that always break when updating NetVips (but always work) * Updated ngx-toastr * Added styles for alerts to Kavita. They were somehow missing. Fixed an issue where when OPDS was disabled, user preferences wouldn't tell them. * Wired up a reset base url button to match Ip Addresses * Disable ipAddress and port for docker users * Removed cache dir since it's kinda pointless currently * Started the update for OPDS BaseUrl support * Fixed OPDS url not reflecting base url on localhost * Added extra plumbing to allow sending a real email when testing a custom service. * Implemented OPDS support under Base Url. Added pagination to all APIs where applicable. * Added a swallowing of permission denied on Updating baseurl in index.html for inapplicable users. * Fixed a bad test
This commit is contained in:
parent
1bf4fde58f
commit
21a9f28923
39 changed files with 2519 additions and 1219 deletions
|
@ -38,7 +38,6 @@ public class OpdsController : BaseApiController
|
|||
|
||||
private readonly XmlSerializer _xmlSerializer;
|
||||
private readonly XmlSerializer _xmlOpenSearchSerializer;
|
||||
private const string Prefix = "/api/opds/";
|
||||
private readonly FilterDto _filterDto = new FilterDto()
|
||||
{
|
||||
Formats = new List<MangaFormat>(),
|
||||
|
@ -63,7 +62,8 @@ public class OpdsController : BaseApiController
|
|||
SortOptions = null,
|
||||
PublicationStatus = new List<PublicationStatus>()
|
||||
};
|
||||
private readonly ChapterSortComparer _chapterSortComparer = new ChapterSortComparer();
|
||||
private readonly ChapterSortComparer _chapterSortComparer = ChapterSortComparer.Default;
|
||||
private const int PageSize = 20;
|
||||
|
||||
public OpdsController(IUnitOfWork unitOfWork, IDownloadService downloadService,
|
||||
IDirectoryService directoryService, ICacheService cacheService,
|
||||
|
@ -80,7 +80,6 @@ public class OpdsController : BaseApiController
|
|||
|
||||
_xmlSerializer = new XmlSerializer(typeof(Feed));
|
||||
_xmlOpenSearchSerializer = new XmlSerializer(typeof(OpenSearchDescription));
|
||||
|
||||
}
|
||||
|
||||
[HttpPost("{apiKey}")]
|
||||
|
@ -90,7 +89,10 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var feed = CreateFeed("Kavita", string.Empty, apiKey);
|
||||
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
|
||||
var feed = CreateFeed("Kavita", string.Empty, apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "root");
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
{
|
||||
|
@ -102,7 +104,7 @@ public class OpdsController : BaseApiController
|
|||
},
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/on-deck"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/on-deck"),
|
||||
}
|
||||
});
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
|
@ -115,7 +117,7 @@ public class OpdsController : BaseApiController
|
|||
},
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/recently-added"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/recently-added"),
|
||||
}
|
||||
});
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
|
@ -128,7 +130,7 @@ public class OpdsController : BaseApiController
|
|||
},
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/reading-list"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/reading-list"),
|
||||
}
|
||||
});
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
|
@ -141,7 +143,7 @@ public class OpdsController : BaseApiController
|
|||
},
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/libraries"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/libraries"),
|
||||
}
|
||||
});
|
||||
feed.Entries.Add(new FeedEntry()
|
||||
|
@ -154,12 +156,25 @@ public class OpdsController : BaseApiController
|
|||
},
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/collections"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/collections"),
|
||||
}
|
||||
});
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
||||
private async Task<Tuple<string, string>> GetPrefix()
|
||||
{
|
||||
var baseUrl = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BaseUrl)).Value;
|
||||
var prefix = "/api/opds/";
|
||||
if (!Configuration.DefaultBaseUrl.Equals(baseUrl))
|
||||
{
|
||||
// We need to update the Prefix to account for baseUrl
|
||||
prefix = baseUrl + "api/opds/";
|
||||
}
|
||||
|
||||
return new Tuple<string, string>(baseUrl, prefix);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("{apiKey}/libraries")]
|
||||
[Produces("application/xml")]
|
||||
|
@ -167,9 +182,10 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var libraries = await _unitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(userId);
|
||||
var feed = CreateFeed("All Libraries", $"{apiKey}/libraries", apiKey);
|
||||
var feed = CreateFeed("All Libraries", $"{prefix}{apiKey}/libraries", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "libraries");
|
||||
foreach (var library in libraries)
|
||||
{
|
||||
|
@ -179,7 +195,7 @@ public class OpdsController : BaseApiController
|
|||
Title = library.Name,
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/libraries/{library.Id}"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/libraries/{library.Id}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -193,16 +209,17 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
if (user == null) return Unauthorized();
|
||||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
||||
|
||||
IEnumerable<CollectionTagDto> tags = isAdmin ? (await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync())
|
||||
var tags = isAdmin ? (await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync())
|
||||
: (await _unitOfWork.CollectionTagRepository.GetAllPromotedTagDtosAsync(userId));
|
||||
|
||||
|
||||
var feed = CreateFeed("All Collections", $"{apiKey}/collections", apiKey);
|
||||
var feed = CreateFeed("All Collections", $"{prefix}{apiKey}/collections", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "collections");
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
|
@ -213,9 +230,9 @@ public class OpdsController : BaseApiController
|
|||
Summary = tag.Summary,
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/collections/{tag.Id}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/collection-cover?collectionId={tag.Id}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/collection-cover?collectionId={tag.Id}")
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/collections/{tag.Id}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/collection-cover?collectionId={tag.Id}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"{baseUrl}api/image/collection-cover?collectionId={tag.Id}")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -230,6 +247,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
if (user == null) return Unauthorized();
|
||||
|
@ -251,20 +269,16 @@ public class OpdsController : BaseApiController
|
|||
return BadRequest("Collection does not exist or you don't have access");
|
||||
}
|
||||
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoForCollectionAsync(collectionId, userId, new UserParams()
|
||||
{
|
||||
PageNumber = pageNumber,
|
||||
PageSize = 20
|
||||
});
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoForCollectionAsync(collectionId, userId, GetUserParams(pageNumber));
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(series.Select(s => s.Id));
|
||||
|
||||
var feed = CreateFeed(tag.Title + " Collection", $"{apiKey}/collections/{collectionId}", apiKey);
|
||||
var feed = CreateFeed(tag.Title + " Collection", $"{prefix}{apiKey}/collections/{collectionId}", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, $"collections-{collectionId}");
|
||||
AddPagination(feed, series, $"{Prefix}{apiKey}/collections/{collectionId}");
|
||||
AddPagination(feed, series, $"{prefix}{apiKey}/collections/{collectionId}");
|
||||
|
||||
foreach (var seriesDto in series)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey, prefix, baseUrl));
|
||||
}
|
||||
|
||||
|
||||
|
@ -277,15 +291,13 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
|
||||
var readingLists = await _unitOfWork.ReadingListRepository.GetReadingListDtosForUserAsync(userId, true, new UserParams()
|
||||
{
|
||||
PageNumber = pageNumber
|
||||
});
|
||||
var readingLists = await _unitOfWork.ReadingListRepository.GetReadingListDtosForUserAsync(userId, true, GetUserParams(pageNumber));
|
||||
|
||||
|
||||
var feed = CreateFeed("All Reading Lists", $"{apiKey}/reading-list", apiKey);
|
||||
var feed = CreateFeed("All Reading Lists", $"{prefix}{apiKey}/reading-list", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "reading-list");
|
||||
foreach (var readingListDto in readingLists)
|
||||
{
|
||||
|
@ -296,7 +308,7 @@ public class OpdsController : BaseApiController
|
|||
Summary = readingListDto.Summary,
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/reading-list/{readingListDto.Id}"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/reading-list/{readingListDto.Id}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -304,12 +316,22 @@ public class OpdsController : BaseApiController
|
|||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
||||
private static UserParams GetUserParams(int pageNumber)
|
||||
{
|
||||
return new UserParams()
|
||||
{
|
||||
PageNumber = pageNumber,
|
||||
PageSize = PageSize
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("{apiKey}/reading-list/{readingListId}")]
|
||||
[Produces("application/xml")]
|
||||
public async Task<IActionResult> GetReadingListItems(int readingListId, string apiKey)
|
||||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
|
||||
|
@ -321,13 +343,15 @@ public class OpdsController : BaseApiController
|
|||
return BadRequest("Reading list does not exist or you don't have access");
|
||||
}
|
||||
|
||||
var feed = CreateFeed(readingList.Title + " Reading List", $"{apiKey}/reading-list/{readingListId}", apiKey);
|
||||
var feed = CreateFeed(readingList.Title + " Reading List", $"{prefix}{apiKey}/reading-list/{readingListId}", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, $"reading-list-{readingListId}");
|
||||
|
||||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId)).ToList();
|
||||
foreach (var item in items)
|
||||
{
|
||||
feed.Entries.Add(CreateChapter(apiKey, $"{item.Order} - {item.SeriesName}: {item.Title}", string.Empty, 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, prefix, baseUrl));
|
||||
}
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
}
|
||||
|
@ -338,6 +362,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var library =
|
||||
(await _unitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(userId)).SingleOrDefault(l =>
|
||||
|
@ -347,20 +372,16 @@ public class OpdsController : BaseApiController
|
|||
return BadRequest("User does not have access to this library");
|
||||
}
|
||||
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoForLibraryIdAsync(libraryId, userId, new UserParams()
|
||||
{
|
||||
PageNumber = pageNumber,
|
||||
PageSize = 20
|
||||
}, _filterDto);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoForLibraryIdAsync(libraryId, userId, GetUserParams(pageNumber), _filterDto);
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(series.Select(s => s.Id));
|
||||
|
||||
var feed = CreateFeed(library.Name, $"{apiKey}/libraries/{libraryId}", apiKey);
|
||||
var feed = CreateFeed(library.Name, $"{apiKey}/libraries/{libraryId}", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, $"library-{library.Name}");
|
||||
AddPagination(feed, series, $"{Prefix}{apiKey}/libraries/{libraryId}");
|
||||
AddPagination(feed, series, $"{prefix}{apiKey}/libraries/{libraryId}");
|
||||
|
||||
foreach (var seriesDto in series)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey, prefix, baseUrl));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -372,21 +393,18 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var recentlyAdded = await _unitOfWork.SeriesRepository.GetRecentlyAdded(0, userId, new UserParams()
|
||||
{
|
||||
PageNumber = pageNumber,
|
||||
PageSize = 20
|
||||
}, _filterDto);
|
||||
var recentlyAdded = await _unitOfWork.SeriesRepository.GetRecentlyAdded(0, userId, GetUserParams(pageNumber), _filterDto);
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIds(recentlyAdded.Select(s => s.Id));
|
||||
|
||||
var feed = CreateFeed("Recently Added", $"{apiKey}/recently-added", apiKey);
|
||||
var feed = CreateFeed("Recently Added", $"{prefix}{apiKey}/recently-added", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "recently-added");
|
||||
AddPagination(feed, recentlyAdded, $"{Prefix}{apiKey}/recently-added");
|
||||
AddPagination(feed, recentlyAdded, $"{prefix}{apiKey}/recently-added");
|
||||
|
||||
foreach (var seriesDto in recentlyAdded)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey, prefix, baseUrl));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -398,23 +416,23 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
|
||||
var userId = await GetUser(apiKey);
|
||||
var userParams = new UserParams()
|
||||
{
|
||||
PageNumber = pageNumber,
|
||||
};
|
||||
var userParams = GetUserParams(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);
|
||||
|
||||
var feed = CreateFeed("On Deck", $"{apiKey}/on-deck", apiKey);
|
||||
var feed = CreateFeed("On Deck", $"{prefix}{apiKey}/on-deck", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "on-deck");
|
||||
AddPagination(feed, pagedList, $"{Prefix}{apiKey}/on-deck");
|
||||
AddPagination(feed, pagedList, $"{prefix}{apiKey}/on-deck");
|
||||
|
||||
foreach (var seriesDto in pagedList)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, seriesMetadatas.First(s => s.SeriesId == seriesDto.Id), apiKey, prefix, baseUrl));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -426,6 +444,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
|
||||
|
@ -442,11 +461,11 @@ public class OpdsController : BaseApiController
|
|||
|
||||
var series = await _unitOfWork.SeriesRepository.SearchSeries(userId, isAdmin, libraries.Select(l => l.Id).ToArray(), query);
|
||||
|
||||
var feed = CreateFeed(query, $"{apiKey}/series?query=" + query, apiKey);
|
||||
var feed = CreateFeed(query, $"{prefix}{apiKey}/series?query=" + query, apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, "search-series");
|
||||
foreach (var seriesDto in series.Series)
|
||||
{
|
||||
feed.Entries.Add(CreateSeries(seriesDto, apiKey));
|
||||
feed.Entries.Add(CreateSeries(seriesDto, apiKey, prefix, baseUrl));
|
||||
}
|
||||
|
||||
foreach (var collection in series.Collections)
|
||||
|
@ -459,11 +478,11 @@ public class OpdsController : BaseApiController
|
|||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||
Prefix + $"{apiKey}/collections/{collection.Id}"),
|
||||
$"{prefix}{apiKey}/collections/{collection.Id}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
||||
$"/api/image/collection-cover?collectionId={collection.Id}"),
|
||||
$"{baseUrl}api/image/collection-cover?collectionId={collection.Id}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image,
|
||||
$"/api/image/collection-cover?collectionId={collection.Id}")
|
||||
$"{baseUrl}api/image/collection-cover?collectionId={collection.Id}")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -477,7 +496,7 @@ public class OpdsController : BaseApiController
|
|||
Summary = readingListDto.Summary,
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/reading-list/{readingListDto.Id}"),
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/reading-list/{readingListDto.Id}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -497,6 +516,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var feed = new OpenSearchDescription()
|
||||
{
|
||||
ShortName = "Search",
|
||||
|
@ -504,7 +524,7 @@ public class OpdsController : BaseApiController
|
|||
Url = new SearchLink()
|
||||
{
|
||||
Type = FeedLinkType.AtomAcquisition,
|
||||
Template = $"{Prefix}{apiKey}/series?query=" + "{searchTerms}"
|
||||
Template = $"{prefix}{apiKey}/series?query=" + "{searchTerms}"
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -520,12 +540,13 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||
|
||||
var feed = CreateFeed(series.Name + " - Storyline", $"{apiKey}/series/{series.Id}", apiKey);
|
||||
var feed = CreateFeed(series.Name + " - Storyline", $"{prefix}{apiKey}/series/{series.Id}", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, $"series-{series.Id}");
|
||||
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesId}"));
|
||||
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/series-cover?seriesId={seriesId}"));
|
||||
|
||||
var seriesDetail = await _seriesService.GetSeriesDetail(seriesId, userId);
|
||||
foreach (var volume in seriesDetail.Volumes)
|
||||
|
@ -539,7 +560,7 @@ public class OpdsController : BaseApiController
|
|||
var chapterTest = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapter.Id);
|
||||
foreach (var mangaFile in files)
|
||||
{
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, volume.Id, chapter.Id, mangaFile, series, chapterTest, apiKey));
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, volume.Id, chapter.Id, mangaFile, series, chapterTest, apiKey, prefix, baseUrl));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +572,7 @@ public class OpdsController : BaseApiController
|
|||
var chapterTest = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(storylineChapter.Id);
|
||||
foreach (var mangaFile in files)
|
||||
{
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, storylineChapter.VolumeId, storylineChapter.Id, mangaFile, series, chapterTest, apiKey));
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, storylineChapter.VolumeId, storylineChapter.Id, mangaFile, series, chapterTest, apiKey, prefix, baseUrl));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,7 +582,7 @@ public class OpdsController : BaseApiController
|
|||
var chapterTest = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(special.Id);
|
||||
foreach (var mangaFile in files)
|
||||
{
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, special.VolumeId, special.Id, mangaFile, series, chapterTest, apiKey));
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, special.VolumeId, special.Id, mangaFile, series, chapterTest, apiKey, prefix, baseUrl));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,6 +595,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
||||
|
@ -582,7 +604,7 @@ public class OpdsController : BaseApiController
|
|||
(await _unitOfWork.ChapterRepository.GetChaptersAsync(volumeId)).OrderBy(x => double.Parse(x.Number),
|
||||
_chapterSortComparer);
|
||||
var feed = CreateFeed(series.Name + " - Volume " + volume!.Name + $" - {SeriesService.FormatChapterName(libraryType)}s ",
|
||||
$"{apiKey}/series/{seriesId}/volume/{volumeId}", apiKey);
|
||||
$"{prefix}{apiKey}/series/{seriesId}/volume/{volumeId}", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, $"series-{series.Id}-volume-{volume.Id}-{SeriesService.FormatChapterName(libraryType)}s");
|
||||
foreach (var chapter in chapters)
|
||||
{
|
||||
|
@ -590,7 +612,7 @@ public class OpdsController : BaseApiController
|
|||
var chapterTest = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapter.Id);
|
||||
foreach (var mangaFile in files)
|
||||
{
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, volumeId, chapter.Id, mangaFile, series, chapterTest, apiKey));
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, volumeId, chapter.Id, mangaFile, series, chapterTest, apiKey, prefix, baseUrl));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,6 +625,7 @@ public class OpdsController : BaseApiController
|
|||
{
|
||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||
return BadRequest("OPDS is not enabled on this server");
|
||||
var (baseUrl, prefix) = await GetPrefix();
|
||||
var userId = await GetUser(apiKey);
|
||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
||||
|
@ -612,11 +635,11 @@ public class OpdsController : BaseApiController
|
|||
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
||||
|
||||
var feed = CreateFeed(series.Name + " - Volume " + volume!.Name + $" - {SeriesService.FormatChapterName(libraryType)}s",
|
||||
$"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}", apiKey);
|
||||
$"{prefix}{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}", apiKey, prefix, baseUrl);
|
||||
SetFeedId(feed, $"series-{series.Id}-volume-{volumeId}-{SeriesService.FormatChapterName(libraryType)}-{chapterId}-files");
|
||||
foreach (var mangaFile in files)
|
||||
{
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, volumeId, chapterId, mangaFile, series, chapter, apiKey));
|
||||
feed.Entries.Add(await CreateChapterWithFile(seriesId, volumeId, chapterId, mangaFile, series, chapter, apiKey, prefix, baseUrl));
|
||||
}
|
||||
|
||||
return CreateXmlResult(SerializeXml(feed));
|
||||
|
@ -694,7 +717,7 @@ public class OpdsController : BaseApiController
|
|||
feed.StartIndex = (Math.Max(list.CurrentPage - 1, 0) * list.PageSize) + 1;
|
||||
}
|
||||
|
||||
private static FeedEntry CreateSeries(SeriesDto seriesDto, SeriesMetadataDto metadata, string apiKey)
|
||||
private static FeedEntry CreateSeries(SeriesDto seriesDto, SeriesMetadataDto metadata, string apiKey, string prefix, string baseUrl)
|
||||
{
|
||||
return new FeedEntry()
|
||||
{
|
||||
|
@ -704,7 +727,7 @@ public class OpdsController : BaseApiController
|
|||
Authors = metadata.Writers.Select(p => new FeedAuthor()
|
||||
{
|
||||
Name = p.Name,
|
||||
Uri = "http://opds-spec.org/author"
|
||||
Uri = "http://opds-spec.org/author/" + p.Id
|
||||
}).ToList(),
|
||||
Categories = metadata.Genres.Select(g => new FeedCategory()
|
||||
{
|
||||
|
@ -713,14 +736,14 @@ public class OpdsController : BaseApiController
|
|||
}).ToList(),
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{seriesDto.Id}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesDto.Id}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesDto.Id}")
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/series/{seriesDto.Id}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/series-cover?seriesId={seriesDto.Id}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"{baseUrl}api/image/series-cover?seriesId={seriesDto.Id}")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static FeedEntry CreateSeries(SearchResultDto searchResultDto, string apiKey)
|
||||
private static FeedEntry CreateSeries(SearchResultDto searchResultDto, string apiKey, string prefix, string baseUrl)
|
||||
{
|
||||
return new FeedEntry()
|
||||
{
|
||||
|
@ -728,14 +751,14 @@ public class OpdsController : BaseApiController
|
|||
Title = $"{searchResultDto.Name} ({searchResultDto.Format})",
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{searchResultDto.SeriesId}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={searchResultDto.SeriesId}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/series-cover?seriesId={searchResultDto.SeriesId}")
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/series/{searchResultDto.SeriesId}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/series-cover?seriesId={searchResultDto.SeriesId}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"{baseUrl}api/image/series-cover?seriesId={searchResultDto.SeriesId}")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static FeedEntry CreateChapter(string apiKey, string title, string summary, int chapterId, int volumeId, int seriesId)
|
||||
private static FeedEntry CreateChapter(string apiKey, string title, string summary, int chapterId, int volumeId, int seriesId, string prefix, string baseUrl)
|
||||
{
|
||||
return new FeedEntry()
|
||||
{
|
||||
|
@ -745,16 +768,16 @@ public class OpdsController : BaseApiController
|
|||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||
Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}"),
|
||||
$"{prefix}{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
||||
$"/api/image/chapter-cover?chapterId={chapterId}"),
|
||||
$"{baseUrl}api/image/chapter-cover?chapterId={chapterId}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image,
|
||||
$"/api/image/chapter-cover?chapterId={chapterId}")
|
||||
$"{baseUrl}api/image/chapter-cover?chapterId={chapterId}")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<FeedEntry> CreateChapterWithFile(int seriesId, int volumeId, int chapterId, MangaFile mangaFile, SeriesDto series, ChapterDto chapter, string apiKey)
|
||||
private async Task<FeedEntry> CreateChapterWithFile(int seriesId, int volumeId, int chapterId, MangaFile mangaFile, SeriesDto series, ChapterDto chapter, string apiKey, string prefix, string baseUrl)
|
||||
{
|
||||
var fileSize =
|
||||
mangaFile.Bytes > 0 ? DirectoryService.GetHumanReadableBytes(mangaFile.Bytes) :
|
||||
|
@ -787,7 +810,7 @@ public class OpdsController : BaseApiController
|
|||
// Chunky requires a file at the end. Our API ignores this
|
||||
var accLink =
|
||||
CreateLink(FeedLinkRelation.Acquisition, fileType,
|
||||
$"{Prefix}{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}/download/{filename}",
|
||||
$"{prefix}{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}/download/{filename}",
|
||||
filename);
|
||||
accLink.TotalPages = chapter.Pages;
|
||||
|
||||
|
@ -800,11 +823,11 @@ public class OpdsController : BaseApiController
|
|||
Format = mangaFile.Format.ToString(),
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={chapterId}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={chapterId}"),
|
||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/chapter-cover?chapterId={chapterId}"),
|
||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"{baseUrl}api/image/chapter-cover?chapterId={chapterId}"),
|
||||
// We can't not include acc link in the feed, panels doesn't work with just page streaming option. We have to block download directly
|
||||
accLink,
|
||||
await CreatePageStreamLink(series.LibraryId, seriesId, volumeId, chapterId, mangaFile, apiKey)
|
||||
await CreatePageStreamLink(series.LibraryId, seriesId, volumeId, chapterId, mangaFile, apiKey, prefix)
|
||||
},
|
||||
Content = new FeedEntryContent()
|
||||
{
|
||||
|
@ -894,13 +917,14 @@ public class OpdsController : BaseApiController
|
|||
throw new KavitaException("User does not exist");
|
||||
}
|
||||
|
||||
private async Task<FeedLink> CreatePageStreamLink(int libraryId, int seriesId, int volumeId, int chapterId, MangaFile mangaFile, string apiKey)
|
||||
private async Task<FeedLink> CreatePageStreamLink(int libraryId, int seriesId, int volumeId, int chapterId, MangaFile mangaFile, string apiKey, string prefix)
|
||||
{
|
||||
var userId = await GetUser(apiKey);
|
||||
var progress = await _unitOfWork.AppUserProgressRepository.GetUserProgressDtoAsync(chapterId, userId);
|
||||
|
||||
// TODO: Type could be wrong
|
||||
var link = CreateLink(FeedLinkRelation.Stream, "image/jpeg",
|
||||
$"{Prefix}{apiKey}/image?libraryId={libraryId}&seriesId={seriesId}&volumeId={volumeId}&chapterId={chapterId}&pageNumber=" + "{pageNumber}");
|
||||
$"{prefix}{apiKey}/image?libraryId={libraryId}&seriesId={seriesId}&volumeId={volumeId}&chapterId={chapterId}&pageNumber=" + "{pageNumber}");
|
||||
link.TotalPages = mangaFile.Pages;
|
||||
if (progress != null)
|
||||
{
|
||||
|
@ -922,21 +946,21 @@ public class OpdsController : BaseApiController
|
|||
};
|
||||
}
|
||||
|
||||
private static Feed CreateFeed(string title, string href, string apiKey)
|
||||
private static Feed CreateFeed(string title, string href, string apiKey, string prefix, string baseUrl)
|
||||
{
|
||||
var link = CreateLink(FeedLinkRelation.Self, string.IsNullOrEmpty(href) ?
|
||||
FeedLinkType.AtomNavigation :
|
||||
FeedLinkType.AtomAcquisition, Prefix + href);
|
||||
FeedLinkType.AtomAcquisition, prefix + href);
|
||||
|
||||
return new Feed()
|
||||
{
|
||||
Title = title,
|
||||
Icon = Prefix + $"{apiKey}/favicon",
|
||||
Icon = $"{prefix}{apiKey}/favicon",
|
||||
Links = new List<FeedLink>()
|
||||
{
|
||||
link,
|
||||
CreateLink(FeedLinkRelation.Start, FeedLinkType.AtomNavigation, Prefix + apiKey),
|
||||
CreateLink(FeedLinkRelation.Search, FeedLinkType.AtomSearch, Prefix + $"{apiKey}/search")
|
||||
CreateLink(FeedLinkRelation.Start, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}"),
|
||||
CreateLink(FeedLinkRelation.Search, FeedLinkType.AtomSearch, $"{prefix}{apiKey}/search")
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class SettingsController : BaseApiController
|
|||
/// <returns></returns>
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
[HttpPost("reset-ip-addresses")]
|
||||
public async Task<ActionResult<ServerSettingDto>> ResetIPAddressesSettings()
|
||||
public async Task<ActionResult<ServerSettingDto>> ResetIpAddressesSettings()
|
||||
{
|
||||
_logger.LogInformation("{UserName} is resetting IP Addresses Setting", User.GetUsername());
|
||||
var ipAddresses = await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.IpAddresses);
|
||||
|
@ -91,6 +91,28 @@ public class SettingsController : BaseApiController
|
|||
return Ok(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the Base url
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
[HttpPost("reset-base-url")]
|
||||
public async Task<ActionResult<ServerSettingDto>> ResetBaseUrlSettings()
|
||||
{
|
||||
_logger.LogInformation("{UserName} is resetting Base Url Setting", User.GetUsername());
|
||||
var baseUrl = await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BaseUrl);
|
||||
baseUrl.Value = Configuration.DefaultBaseUrl;
|
||||
_unitOfWork.SettingsRepository.Update(baseUrl);
|
||||
|
||||
if (!await _unitOfWork.CommitAsync())
|
||||
{
|
||||
await _unitOfWork.RollbackAsync();
|
||||
}
|
||||
|
||||
Configuration.BaseUrl = baseUrl.Value;
|
||||
return Ok(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the email service url
|
||||
/// </summary>
|
||||
|
@ -116,7 +138,9 @@ public class SettingsController : BaseApiController
|
|||
[HttpPost("test-email-url")]
|
||||
public async Task<ActionResult<EmailTestResultDto>> TestEmailServiceUrl(TestEmailDto dto)
|
||||
{
|
||||
return Ok(await _emailService.TestConnectivity(dto.Url));
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId());
|
||||
var emailService = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.EmailServiceUrl)).Value;
|
||||
return Ok(await _emailService.TestConnectivity(dto.Url, user!.Email, !emailService.Equals(EmailService.DefaultApiUrl)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,7 +201,7 @@ public class SettingsController : BaseApiController
|
|||
}
|
||||
|
||||
setting.Value = updateSettingsDto.IpAddresses;
|
||||
// IpAddesses is managed in appSetting.json
|
||||
// IpAddresses is managed in appSetting.json
|
||||
Configuration.IpAddresses = updateSettingsDto.IpAddresses;
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ public class WantToReadController : BaseApiController
|
|||
userParams ??= new UserParams();
|
||||
var pagedList = await _unitOfWork.SeriesRepository.GetWantToReadForUserAsync(User.GetUserId(), userParams, filterDto);
|
||||
Response.AddPaginationHeader(pagedList.CurrentPage, pagedList.PageSize, pagedList.TotalCount, pagedList.TotalPages);
|
||||
|
||||
await _unitOfWork.SeriesRepository.AddSeriesModifiers(User.GetUserId(), pagedList);
|
||||
|
||||
return Ok(pagedList);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue