From 018c0ab15ca37446dfb561cd5a593bb0aebac275 Mon Sep 17 00:00:00 2001 From: Joe Milazzo Date: Sat, 10 Dec 2022 08:00:36 -0600 Subject: [PATCH] Hooked up the API layer to be able to extract images from PDF again for Tachiyomi explicitly (#1686) --- API/Controllers/ReaderController.cs | 14 ++++++++------ API/Services/BookService.cs | 2 +- API/Services/CacheService.cs | 19 +++++++++++++------ API/Services/ReadingItemService.cs | 2 ++ openapi.json | 24 +++++++++++++++++++++--- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/API/Controllers/ReaderController.cs b/API/Controllers/ReaderController.cs index cff8c24d4..c92f4398d 100644 --- a/API/Controllers/ReaderController.cs +++ b/API/Controllers/ReaderController.cs @@ -87,16 +87,17 @@ public class ReaderController : BaseApiController /// Returns an image for a given chapter. Will perform bounding checks /// /// This will cache the chapter images for reading - /// - /// + /// Chapter Id + /// Page in question + /// Should Kavita extract pdf into images. Defaults to false. /// [HttpGet("image")] [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour)] [AllowAnonymous] - public async Task GetImage(int chapterId, int page) + public async Task GetImage(int chapterId, int page, bool extractPdf = false) { if (page < 0) page = 0; - var chapter = await _cacheService.Ensure(chapterId); + var chapter = await _cacheService.Ensure(chapterId, extractPdf); if (chapter == null) return BadRequest("There was an issue finding image file for reading"); try @@ -155,12 +156,13 @@ public class ReaderController : BaseApiController /// Returns various information about a Chapter. Side effect: This will cache the chapter images for reading. /// /// + /// Should Kavita extract pdf into images. Defaults to false. /// [HttpGet("chapter-info")] - public async Task> GetChapterInfo(int chapterId) + public async Task> GetChapterInfo(int chapterId, bool extractPdf = false) { if (chapterId <= 0) return null; // This can happen occasionally from UI, we should just ignore - var chapter = await _cacheService.Ensure(chapterId); + var chapter = await _cacheService.Ensure(chapterId, extractPdf); if (chapter == null) return BadRequest("Could not find Chapter"); var dto = await _unitOfWork.ChapterRepository.GetChapterInfoDtoAsync(chapterId); diff --git a/API/Services/BookService.cs b/API/Services/BookService.cs index e358a46e2..3244ce07f 100644 --- a/API/Services/BookService.cs +++ b/API/Services/BookService.cs @@ -49,9 +49,9 @@ public interface IBookService /// /// Extracts a PDF file's pages as images to an target directory /// + /// This method relies on Docnet which has explict patches from Kavita for ARM support. This should only be used with Tachiyomi /// /// Where the files will be extracted to. If doesn't exist, will be created. - [Obsolete("This method of reading is no longer supported. Please use native pdf reader")] void ExtractPdfImages(string fileFilePath, string targetDirectory); Task ScopePage(HtmlDocument doc, EpubBookRef book, string apiBase, HtmlNode body, Dictionary mappings, int page); diff --git a/API/Services/CacheService.cs b/API/Services/CacheService.cs index 7cf00bf57..95a9a646e 100644 --- a/API/Services/CacheService.cs +++ b/API/Services/CacheService.cs @@ -20,8 +20,9 @@ public interface ICacheService /// cache operations (except cleanup). /// /// + /// Extracts a PDF into images for a different reading experience /// Chapter for the passed chapterId. Side-effect from ensuring cache. - Task Ensure(int chapterId); + Task Ensure(int chapterId, bool extractPdfToImages = false); /// /// Clears cache directory of all volumes. This can be invoked from deleting a library or a series. /// @@ -31,7 +32,7 @@ public interface ICacheService string GetCachedPagePath(Chapter chapter, int page); string GetCachedBookmarkPagePath(int seriesId, int page); string GetCachedFile(Chapter chapter); - public void ExtractChapterFiles(string extractPath, IReadOnlyList files); + public void ExtractChapterFiles(string extractPath, IReadOnlyList files, bool extractPdfImages = false); Task CacheBookmarkForSeries(int userId, int seriesId); void CleanupBookmarkCache(int seriesId); } @@ -95,7 +96,7 @@ public class CacheService : ICacheService /// /// /// This will always return the Chapter for the chapterId - public async Task Ensure(int chapterId) + public async Task Ensure(int chapterId, bool extractPdfToImages = false) { _directoryService.ExistOrCreate(_directoryService.CacheDirectory); var chapter = await _unitOfWork.ChapterRepository.GetChapterAsync(chapterId); @@ -103,7 +104,7 @@ public class CacheService : ICacheService if (_directoryService.Exists(extractPath)) return chapter; var files = chapter?.Files.ToList(); - ExtractChapterFiles(extractPath, files); + ExtractChapterFiles(extractPath, files, extractPdfToImages); return chapter; } @@ -114,8 +115,9 @@ public class CacheService : ICacheService /// /// /// + /// Defaults to false, if true, will extract the images from the PDF renderer and not move the pdf file /// - public void ExtractChapterFiles(string extractPath, IReadOnlyList files) + public void ExtractChapterFiles(string extractPath, IReadOnlyList files, bool extractPdfImages = false) { var removeNonImages = true; var fileCount = files.Count; @@ -143,12 +145,17 @@ public class CacheService : ICacheService case MangaFormat.Epub: case MangaFormat.Pdf: { - removeNonImages = false; if (!_directoryService.FileSystem.File.Exists(files[0].FilePath)) { _logger.LogError("{File} does not exist on disk", files[0].FilePath); throw new KavitaException($"{files[0].FilePath} does not exist on disk"); } + if (extractPdfImages) + { + _readingItemService.Extract(file.FilePath, Path.Join(extractPath, extraPath), file.Format); + break; + } + removeNonImages = false; _directoryService.ExistOrCreate(extractPath); _directoryService.CopyFileToDirectory(files[0].FilePath, extractPath); diff --git a/API/Services/ReadingItemService.cs b/API/Services/ReadingItemService.cs index a70f7f38e..14ced8674 100644 --- a/API/Services/ReadingItemService.cs +++ b/API/Services/ReadingItemService.cs @@ -199,6 +199,8 @@ public class ReadingItemService : IReadingItemService _imageService.ExtractImages(fileFilePath, targetDirectory, imageCount); break; case MangaFormat.Pdf: + _bookService.ExtractPdfImages(fileFilePath, targetDirectory); + break; case MangaFormat.Unknown: case MangaFormat.Epub: break; diff --git a/openapi.json b/openapi.json index 3e4194f53..13a9800e7 100644 --- a/openapi.json +++ b/openapi.json @@ -7,7 +7,7 @@ "name": "GPL-3.0", "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" }, - "version": "0.6.1.7" + "version": "0.6.1.8" }, "servers": [ { @@ -3411,7 +3411,7 @@ { "name": "chapterId", "in": "query", - "description": "", + "description": "Chapter Id", "schema": { "type": "integer", "format": "int32" @@ -3420,11 +3420,20 @@ { "name": "page", "in": "query", - "description": "", + "description": "Page in question", "schema": { "type": "integer", "format": "int32" } + }, + { + "name": "extractPdf", + "in": "query", + "description": "Should Kavita extract pdf into images. Defaults to false.", + "schema": { + "type": "boolean", + "default": false + } } ], "responses": { @@ -3491,6 +3500,15 @@ "type": "integer", "format": "int32" } + }, + { + "name": "extractPdf", + "in": "query", + "description": "Should Kavita extract pdf into images. Defaults to false.", + "schema": { + "type": "boolean", + "default": false + } } ], "responses": {