mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-04-20 01:17:45 +02:00
Update:New EBook API endpoint
This commit is contained in:
parent
b3f19ef628
commit
4f75a89633
@ -57,7 +57,6 @@ Archive.init({
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
url: String,
|
|
||||||
libraryItem: {
|
libraryItem: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
@ -88,6 +87,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
userToken() {
|
||||||
|
return this.$store.getters['user/getToken']
|
||||||
|
},
|
||||||
|
libraryItemId() {
|
||||||
|
return this.libraryItem?.id
|
||||||
|
},
|
||||||
|
ebookUrl() {
|
||||||
|
return `/api/items/${this.libraryItemId}/ebook`
|
||||||
|
},
|
||||||
comicMetadataKeys() {
|
comicMetadataKeys() {
|
||||||
return this.comicMetadata ? Object.keys(this.comicMetadata) : []
|
return this.comicMetadata ? Object.keys(this.comicMetadata) : []
|
||||||
},
|
},
|
||||||
@ -146,10 +154,11 @@ export default {
|
|||||||
},
|
},
|
||||||
async extract() {
|
async extract() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
console.log('Extracting', this.url)
|
var buff = await this.$axios.$get(this.ebookUrl, {
|
||||||
|
responseType: 'blob',
|
||||||
var buff = await this.$axios.$get(this.url, {
|
headers: {
|
||||||
responseType: 'blob'
|
Authorization: `Bearer ${this.userToken}`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const archive = await Archive.open(buff)
|
const archive = await Archive.open(buff)
|
||||||
const originalFilesObject = await archive.getFilesObject()
|
const originalFilesObject = await archive.getFilesObject()
|
||||||
|
@ -24,7 +24,6 @@ import ePub from 'epubjs'
|
|||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
url: String,
|
|
||||||
libraryItem: {
|
libraryItem: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
@ -47,6 +46,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
userToken() {
|
||||||
|
return this.$store.getters['user/getToken']
|
||||||
|
},
|
||||||
/** @returns {string} */
|
/** @returns {string} */
|
||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem?.id
|
return this.libraryItem?.id
|
||||||
@ -75,6 +77,9 @@ export default {
|
|||||||
readerHeight() {
|
readerHeight() {
|
||||||
if (this.windowHeight < 400 || !this.playerOpen) return this.windowHeight
|
if (this.windowHeight < 400 || !this.playerOpen) return this.windowHeight
|
||||||
return this.windowHeight - 164
|
return this.windowHeight - 164
|
||||||
|
},
|
||||||
|
epubUrl() {
|
||||||
|
return `/api/items/${this.libraryItemId}/ebook`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -212,9 +217,13 @@ export default {
|
|||||||
const reader = this
|
const reader = this
|
||||||
|
|
||||||
/** @type {ePub.Book} */
|
/** @type {ePub.Book} */
|
||||||
reader.book = new ePub(reader.url, {
|
reader.book = new ePub(reader.epubUrl, {
|
||||||
width: this.readerWidth,
|
width: this.readerWidth,
|
||||||
height: this.readerHeight - 50
|
height: this.readerHeight - 50,
|
||||||
|
openAs: 'epub',
|
||||||
|
requestHeaders: {
|
||||||
|
Authorization: `Bearer ${this.userToken}`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/** @type {ePub.Rendition} */
|
/** @type {ePub.Rendition} */
|
||||||
|
@ -15,7 +15,6 @@ import defaultCss from '@/assets/ebooks/basic.js'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
url: String,
|
|
||||||
libraryItem: {
|
libraryItem: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
@ -25,7 +24,17 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {
|
||||||
|
userToken() {
|
||||||
|
return this.$store.getters['user/getToken']
|
||||||
|
},
|
||||||
|
libraryItemId() {
|
||||||
|
return this.libraryItem?.id
|
||||||
|
},
|
||||||
|
ebookUrl() {
|
||||||
|
return `/api/items/${this.libraryItemId}/ebook`
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addHtmlCss() {
|
addHtmlCss() {
|
||||||
let iframe = document.getElementsByTagName('iframe')[0]
|
let iframe = document.getElementsByTagName('iframe')[0]
|
||||||
@ -83,8 +92,11 @@ export default {
|
|||||||
},
|
},
|
||||||
async initMobi() {
|
async initMobi() {
|
||||||
// Fetch mobi file as blob
|
// Fetch mobi file as blob
|
||||||
var buff = await this.$axios.$get(this.url, {
|
var buff = await this.$axios.$get(this.ebookUrl, {
|
||||||
responseType: 'blob'
|
responseType: 'blob',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.userToken}`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
var reader = new FileReader()
|
var reader = new FileReader()
|
||||||
reader.onload = async (event) => {
|
reader.onload = async (event) => {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<div :style="{ width: pdfWidth + 'px', height: pdfHeight + 'px' }" class="overflow-auto">
|
<div :style="{ width: pdfWidth + 'px', height: pdfHeight + 'px' }" class="overflow-auto">
|
||||||
<div v-if="loadedRatio > 0 && loadedRatio < 1" style="background-color: green; color: white; text-align: center" :style="{ width: loadedRatio * 100 + '%' }">{{ Math.floor(loadedRatio * 100) }}%</div>
|
<div v-if="loadedRatio > 0 && loadedRatio < 1" style="background-color: green; color: white; text-align: center" :style="{ width: loadedRatio * 100 + '%' }">{{ Math.floor(loadedRatio * 100) }}%</div>
|
||||||
<pdf ref="pdf" class="m-auto z-10 border border-black border-opacity-20 shadow-md" :src="url" :page="page" :rotate="rotate" @progress="progressEvt" @error="error" @num-pages="numPagesLoaded" @link-clicked="page = $event" @loaded="loadedEvt"></pdf>
|
<pdf ref="pdf" class="m-auto z-10 border border-black border-opacity-20 shadow-md" :src="pdfDocInitParams" :page="page" :rotate="rotate" @progress="progressEvt" @error="error" @num-pages="numPagesLoaded" @link-clicked="page = $event" @loaded="loadedEvt"></pdf>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +41,6 @@ export default {
|
|||||||
pdf
|
pdf
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
url: String,
|
|
||||||
libraryItem: {
|
libraryItem: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
@ -60,6 +59,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
userToken() {
|
||||||
|
return this.$store.getters['user/getToken']
|
||||||
|
},
|
||||||
libraryItemId() {
|
libraryItemId() {
|
||||||
return this.libraryItem?.id
|
return this.libraryItem?.id
|
||||||
},
|
},
|
||||||
@ -94,6 +96,14 @@ export default {
|
|||||||
},
|
},
|
||||||
savedPage() {
|
savedPage() {
|
||||||
return Number(this.userMediaProgress?.ebookLocation || 0)
|
return Number(this.userMediaProgress?.ebookLocation || 0)
|
||||||
|
},
|
||||||
|
pdfDocInitParams() {
|
||||||
|
return {
|
||||||
|
url: `/api/items/${this.libraryItemId}/ebook`,
|
||||||
|
httpHeaders: {
|
||||||
|
Authorization: `Bearer ${this.userToken}`
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<span class="material-icons cursor-pointer text-2xl" @click="close">close</span>
|
<span class="material-icons cursor-pointer text-2xl" @click="close">close</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<component v-if="componentName" ref="readerComponent" :is="componentName" :url="ebookUrl" :library-item="selectedLibraryItem" :player-open="!!streamLibraryItem" />
|
<component v-if="componentName" ref="readerComponent" :is="componentName" :library-item="selectedLibraryItem" :player-open="!!streamLibraryItem" />
|
||||||
|
|
||||||
<!-- TOC side nav -->
|
<!-- TOC side nav -->
|
||||||
<div v-if="tocOpen" class="w-full h-full fixed inset-0 bg-black/20 z-20" @click.stop.prevent="toggleToC"></div>
|
<div v-if="tocOpen" class="w-full h-full fixed inset-0 bg-black/20 z-20" @click.stop.prevent="toggleToC"></div>
|
||||||
@ -128,21 +128,6 @@ export default {
|
|||||||
isComic() {
|
isComic() {
|
||||||
return this.ebookFormat == 'cbz' || this.ebookFormat == 'cbr'
|
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() {
|
userToken() {
|
||||||
return this.$store.getters['user/getToken']
|
return this.$store.getters['user/getToken']
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,8 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
|
|
||||||
proxy: {
|
proxy: {
|
||||||
'/dev/': { target: 'http://localhost:3333', pathRewrite: { '^/dev/': '' } },
|
'/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' },
|
||||||
'/ebook/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' },
|
'/api/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' }
|
||||||
'/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' + process.env : '/' },
|
|
||||||
},
|
},
|
||||||
|
|
||||||
io: {
|
io: {
|
||||||
|
@ -7,15 +7,10 @@ export default function ({ $axios, store, $config }) {
|
|||||||
if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
|
if (config.url.startsWith('http:') || config.url.startsWith('https:')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var bearerToken = store.state.user.user ? store.state.user.user.token : null
|
const bearerToken = store.state.user.user?.token || null
|
||||||
if (bearerToken) {
|
if (bearerToken) {
|
||||||
config.headers.common['Authorization'] = `Bearer ${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 => {
|
$axios.onError(error => {
|
||||||
|
@ -19,7 +19,7 @@ export const getters = {
|
|||||||
getIsRoot: (state) => state.user && state.user.type === 'root',
|
getIsRoot: (state) => state.user && state.user.type === 'root',
|
||||||
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
|
getIsAdminOrUp: (state) => state.user && (state.user.type === 'admin' || state.user.type === 'root'),
|
||||||
getToken: (state) => {
|
getToken: (state) => {
|
||||||
return state.user ? state.user.token : null
|
return state.user?.token || null
|
||||||
},
|
},
|
||||||
getUserMediaProgress: (state) => (libraryItemId, episodeId = null) => {
|
getUserMediaProgress: (state) => (libraryItemId, episodeId = null) => {
|
||||||
if (!state.user.mediaProgress) return null
|
if (!state.user.mediaProgress) return null
|
||||||
|
@ -165,6 +165,7 @@ class Server {
|
|||||||
router.use('/s', this.authMiddleware.bind(this), this.staticRouter.router)
|
router.use('/s', this.authMiddleware.bind(this), this.staticRouter.router)
|
||||||
|
|
||||||
// EBook static file routes
|
// EBook static file routes
|
||||||
|
// TODO: Deprecated as of 2.2.21 edge
|
||||||
router.get('/ebook/:library/:folder/*', (req, res) => {
|
router.get('/ebook/:library/:folder/*', (req, res) => {
|
||||||
const library = this.db.libraries.find(lib => lib.id === req.params.library)
|
const library = this.db.libraries.find(lib => lib.id === req.params.library)
|
||||||
if (!library) return res.sendStatus(404)
|
if (!library) return res.sendStatus(404)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const Path = require('path')
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const SocketAuthority = require('../SocketAuthority')
|
const SocketAuthority = require('../SocketAuthority')
|
||||||
@ -552,6 +553,16 @@ class LibraryItemController {
|
|||||||
res.sendStatus(200)
|
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) {
|
middleware(req, res, next) {
|
||||||
const item = this.db.libraryItems.find(li => li.id === req.params.id)
|
const item = this.db.libraryItems.find(li => li.id === req.params.id)
|
||||||
if (!item || !item.media) return res.sendStatus(404)
|
if (!item || !item.media) return res.sendStatus(404)
|
||||||
|
@ -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/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.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.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
|
// User Routes
|
||||||
|
Loading…
Reference in New Issue
Block a user