From 4f75a89633beaee6db9cbbc78237795b02bf49f4 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sun, 28 May 2023 10:47:28 -0500 Subject: [PATCH] Update:New EBook API endpoint --- client/components/readers/ComicReader.vue | 19 ++++++++++++++----- client/components/readers/EpubReader.vue | 15 ++++++++++++--- client/components/readers/MobiReader.vue | 20 ++++++++++++++++---- client/components/readers/PdfReader.vue | 14 ++++++++++++-- client/components/readers/Reader.vue | 17 +---------------- client/nuxt.config.js | 5 ++--- client/plugins/axios.js | 7 +------ client/store/user.js | 2 +- server/Server.js | 1 + server/controllers/LibraryItemController.js | 11 +++++++++++ server/routers/ApiRouter.js | 1 + 11 files changed, 72 insertions(+), 40 deletions(-) diff --git a/client/components/readers/ComicReader.vue b/client/components/readers/ComicReader.vue index 31b058fa..e0ab42f3 100644 --- a/client/components/readers/ComicReader.vue +++ b/client/components/readers/ComicReader.vue @@ -57,7 +57,6 @@ Archive.init({ export default { props: { - url: String, libraryItem: { type: Object, default: () => {} @@ -88,6 +87,15 @@ export default { } }, computed: { + userToken() { + return this.$store.getters['user/getToken'] + }, + libraryItemId() { + return this.libraryItem?.id + }, + ebookUrl() { + return `/api/items/${this.libraryItemId}/ebook` + }, comicMetadataKeys() { return this.comicMetadata ? Object.keys(this.comicMetadata) : [] }, @@ -146,10 +154,11 @@ export default { }, async extract() { this.loading = true - console.log('Extracting', this.url) - - var buff = await this.$axios.$get(this.url, { - responseType: 'blob' + var buff = await this.$axios.$get(this.ebookUrl, { + responseType: 'blob', + headers: { + Authorization: `Bearer ${this.userToken}` + } }) const archive = await Archive.open(buff) const originalFilesObject = await archive.getFilesObject() diff --git a/client/components/readers/EpubReader.vue b/client/components/readers/EpubReader.vue index 90cf4328..fa80d3c5 100644 --- a/client/components/readers/EpubReader.vue +++ b/client/components/readers/EpubReader.vue @@ -24,7 +24,6 @@ import ePub from 'epubjs' */ export default { props: { - url: String, libraryItem: { type: Object, default: () => {} @@ -47,6 +46,9 @@ export default { } }, computed: { + userToken() { + return this.$store.getters['user/getToken'] + }, /** @returns {string} */ libraryItemId() { return this.libraryItem?.id @@ -75,6 +77,9 @@ export default { readerHeight() { if (this.windowHeight < 400 || !this.playerOpen) return this.windowHeight return this.windowHeight - 164 + }, + epubUrl() { + return `/api/items/${this.libraryItemId}/ebook` } }, methods: { @@ -212,9 +217,13 @@ export default { const reader = this /** @type {ePub.Book} */ - reader.book = new ePub(reader.url, { + reader.book = new ePub(reader.epubUrl, { width: this.readerWidth, - height: this.readerHeight - 50 + height: this.readerHeight - 50, + openAs: 'epub', + requestHeaders: { + Authorization: `Bearer ${this.userToken}` + } }) /** @type {ePub.Rendition} */ diff --git a/client/components/readers/MobiReader.vue b/client/components/readers/MobiReader.vue index c432ff7d..01689aa9 100644 --- a/client/components/readers/MobiReader.vue +++ b/client/components/readers/MobiReader.vue @@ -15,7 +15,6 @@ import defaultCss from '@/assets/ebooks/basic.js' export default { props: { - url: String, libraryItem: { type: Object, default: () => {} @@ -25,7 +24,17 @@ export default { data() { return {} }, - computed: {}, + computed: { + userToken() { + return this.$store.getters['user/getToken'] + }, + libraryItemId() { + return this.libraryItem?.id + }, + ebookUrl() { + return `/api/items/${this.libraryItemId}/ebook` + } + }, methods: { addHtmlCss() { let iframe = document.getElementsByTagName('iframe')[0] @@ -83,8 +92,11 @@ export default { }, async initMobi() { // Fetch mobi file as blob - var buff = await this.$axios.$get(this.url, { - responseType: 'blob' + var buff = await this.$axios.$get(this.ebookUrl, { + responseType: 'blob', + headers: { + Authorization: `Bearer ${this.userToken}` + } }) var reader = new FileReader() reader.onload = async (event) => { diff --git a/client/components/readers/PdfReader.vue b/client/components/readers/PdfReader.vue index 486fce4d..d67a2229 100644 --- a/client/components/readers/PdfReader.vue +++ b/client/components/readers/PdfReader.vue @@ -23,7 +23,7 @@
{{ Math.floor(loadedRatio * 100) }}%
- +
@@ -41,7 +41,6 @@ export default { pdf }, props: { - url: String, libraryItem: { type: Object, default: () => {} @@ -60,6 +59,9 @@ export default { } }, computed: { + userToken() { + return this.$store.getters['user/getToken'] + }, libraryItemId() { return this.libraryItem?.id }, @@ -94,6 +96,14 @@ export default { }, savedPage() { return Number(this.userMediaProgress?.ebookLocation || 0) + }, + pdfDocInitParams() { + return { + url: `/api/items/${this.libraryItemId}/ebook`, + httpHeaders: { + Authorization: `Bearer ${this.userToken}` + } + } } }, methods: { diff --git a/client/components/readers/Reader.vue b/client/components/readers/Reader.vue index 82e03473..df1d6630 100644 --- a/client/components/readers/Reader.vue +++ b/client/components/readers/Reader.vue @@ -17,7 +17,7 @@ close - +
@@ -128,21 +128,6 @@ export default { isComic() { return this.ebookFormat == 'cbz' || this.ebookFormat == 'cbr' }, - ebookUrl() { - if (!this.ebookFile) return null - let filepath = '' - if (this.selectedLibraryItem.isFile) { - filepath = this.$encodeUriPath(this.ebookFile.metadata.filename) - } else { - const itemRelPath = this.selectedLibraryItem.relPath - if (itemRelPath.startsWith('/')) itemRelPath = itemRelPath.slice(1) - const relPath = this.ebookFile.metadata.relPath - if (relPath.startsWith('/')) relPath = relPath.slice(1) - - filepath = this.$encodeUriPath(`${itemRelPath}/${relPath}`) - } - return `/ebook/${this.libraryId}/${this.folderId}/${filepath}` - }, userToken() { return this.$store.getters['user/getToken'] } diff --git a/client/nuxt.config.js b/client/nuxt.config.js index d768fa41..6e06589e 100644 --- a/client/nuxt.config.js +++ b/client/nuxt.config.js @@ -71,9 +71,8 @@ module.exports = { ], proxy: { - '/dev/': { target: 'http://localhost:3333', pathRewrite: { '^/dev/': '' } }, - '/ebook/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' }, - '/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' + process.env : '/' }, + '/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' }, + '/api/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' } }, io: { diff --git a/client/plugins/axios.js b/client/plugins/axios.js index e839e382..f212429c 100644 --- a/client/plugins/axios.js +++ b/client/plugins/axios.js @@ -7,15 +7,10 @@ export default function ({ $axios, store, $config }) { if (config.url.startsWith('http:') || config.url.startsWith('https:')) { return } - var bearerToken = store.state.user.user ? store.state.user.user.token : null + const bearerToken = store.state.user.user?.token || null if (bearerToken) { config.headers.common['Authorization'] = `Bearer ${bearerToken}` } - - if (process.env.NODE_ENV === 'development') { - config.url = `/dev${config.url}` - console.log('Making request to ' + config.url) - } }) $axios.onError(error => { diff --git a/client/store/user.js b/client/store/user.js index 95bf2249..d90c911e 100644 --- a/client/store/user.js +++ b/client/store/user.js @@ -19,7 +19,7 @@ export const getters = { getIsRoot: (state) => state.user && state.user.type === 'root', getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'), getToken: (state) => { - return state.user ? state.user.token : null + return state.user?.token || null }, getUserMediaProgress: (state) => (libraryItemId, episodeId = null) => { if (!state.user.mediaProgress) return null diff --git a/server/Server.js b/server/Server.js index 858ffd56..86559149 100644 --- a/server/Server.js +++ b/server/Server.js @@ -165,6 +165,7 @@ class Server { router.use('/s', this.authMiddleware.bind(this), this.staticRouter.router) // EBook static file routes + // TODO: Deprecated as of 2.2.21 edge router.get('/ebook/:library/:folder/*', (req, res) => { const library = this.db.libraries.find(lib => lib.id === req.params.library) if (!library) return res.sendStatus(404) diff --git a/server/controllers/LibraryItemController.js b/server/controllers/LibraryItemController.js index 5c151246..fd01a806 100644 --- a/server/controllers/LibraryItemController.js +++ b/server/controllers/LibraryItemController.js @@ -1,3 +1,4 @@ +const Path = require('path') const fs = require('../libs/fsExtra') const Logger = require('../Logger') const SocketAuthority = require('../SocketAuthority') @@ -552,6 +553,16 @@ class LibraryItemController { res.sendStatus(200) } + async getEBookFile(req, res) { + const ebookFile = req.libraryItem.media.ebookFile + if (!ebookFile) { + Logger.error(`[LibraryItemController] No ebookFile for library item "${req.libraryItem.media.metadata.title}"`) + return res.sendStatus(404) + } + const ebookFilePath = ebookFile.metadata.path + res.sendFile(ebookFilePath) + } + middleware(req, res, next) { const item = this.db.libraryItems.find(li => li.id === req.params.id) if (!item || !item.media) return res.sendStatus(404) diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index 36fcf734..aec30aa4 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -121,6 +121,7 @@ class ApiRouter { this.router.post('/items/:id/chapters', LibraryItemController.middleware.bind(this), LibraryItemController.updateMediaChapters.bind(this)) this.router.post('/items/:id/tone-scan/:index?', LibraryItemController.middleware.bind(this), LibraryItemController.toneScan.bind(this)) this.router.delete('/items/:id/file/:ino', LibraryItemController.middleware.bind(this), LibraryItemController.deleteLibraryFile.bind(this)) + this.router.get('/items/:id/ebook', LibraryItemController.middleware.bind(this), LibraryItemController.getEBookFile.bind(this)) // // User Routes