mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-06-04 01:40:40 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b816c0e7c4 | |||
| a8b92819d1 | |||
| 54a4b09592 | |||
| f13283b950 | |||
| 78994b3589 | |||
| 6745efc4d6 | |||
| 6c540ad789 |
@@ -5,7 +5,7 @@
|
|||||||
@import './absicons.css';
|
@import './absicons.css';
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bookshelf-texture-img: url(/textures/wood_default.jpg);
|
--bookshelf-texture-img: url(~static/textures/wood_default.jpg);
|
||||||
--bookshelf-divider-bg: linear-gradient(180deg, rgba(149, 119, 90, 1) 0%, rgba(103, 70, 37, 1) 17%, rgba(103, 70, 37, 1) 88%, rgba(71, 48, 25, 1) 100%);
|
--bookshelf-divider-bg: linear-gradient(180deg, rgba(149, 119, 90, 1) 0%, rgba(103, 70, 37, 1) 17%, rgba(103, 70, 37, 1) 88%, rgba(71, 48, 25, 1) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,4 +247,4 @@ Bookshelf Label
|
|||||||
|
|
||||||
.abs-btn:disabled::before {
|
.abs-btn:disabled::before {
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ export default {
|
|||||||
},
|
},
|
||||||
ebookUrl() {
|
ebookUrl() {
|
||||||
if (this.fileId) {
|
if (this.fileId) {
|
||||||
return `/api/items/${this.libraryItemId}/ebook/${this.fileId}`
|
return `${this.$config.routerBasePath}/api/items/${this.libraryItemId}/ebook/${this.fileId}`
|
||||||
}
|
}
|
||||||
return `/api/items/${this.libraryItemId}/ebook`
|
return `${this.$config.routerBasePath}/api/items/${this.libraryItemId}/ebook`
|
||||||
},
|
},
|
||||||
themeRules() {
|
themeRules() {
|
||||||
const isDark = this.ereaderSettings.theme === 'dark'
|
const isDark = this.ereaderSettings.theme === 'dark'
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ class ApiCacheManager {
|
|||||||
Logger.debug(`[ApiCacheManager] Skipping cache for random sort`)
|
Logger.debug(`[ApiCacheManager] Skipping cache for random sort`)
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
// Force URL to be lower case for matching against routes
|
|
||||||
req.url = req.url.toLowerCase()
|
|
||||||
const key = { user: req.user.username, url: req.url }
|
const key = { user: req.user.username, url: req.url }
|
||||||
const stringifiedKey = JSON.stringify(key)
|
const stringifiedKey = JSON.stringify(key)
|
||||||
Logger.debug(`[ApiCacheManager] count: ${this.cache.size} size: ${this.cache.calculatedSize}`)
|
Logger.debug(`[ApiCacheManager] count: ${this.cache.size} size: ${this.cache.calculatedSize}`)
|
||||||
|
|||||||
+37
-21
@@ -561,7 +561,42 @@ class Feed extends Model {
|
|||||||
* @param {string} hostPrefix
|
* @param {string} hostPrefix
|
||||||
*/
|
*/
|
||||||
buildXml(hostPrefix) {
|
buildXml(hostPrefix) {
|
||||||
const blockTags = [{ 'itunes:block': 'yes' }, { 'googleplay:block': 'yes' }]
|
const customElements = [
|
||||||
|
{ language: this.language || 'en' },
|
||||||
|
{ author: this.author || 'advplyr' },
|
||||||
|
{ 'itunes:author': this.author || 'advplyr' },
|
||||||
|
{ 'itunes:type': this.podcastType || 'serial' },
|
||||||
|
{
|
||||||
|
'itunes:image': {
|
||||||
|
_attr: {
|
||||||
|
href: `${hostPrefix}${this.imageURL}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ 'itunes:explicit': !!this.explicit }
|
||||||
|
]
|
||||||
|
|
||||||
|
if (this.description) {
|
||||||
|
customElements.push({ 'itunes:summary': { _cdata: this.description } })
|
||||||
|
}
|
||||||
|
|
||||||
|
const itunesOwnersData = []
|
||||||
|
if (this.ownerName || this.author) {
|
||||||
|
itunesOwnersData.push({ 'itunes:name': this.ownerName || this.author })
|
||||||
|
}
|
||||||
|
if (this.ownerEmail) {
|
||||||
|
itunesOwnersData.push({ 'itunes:email': this.ownerEmail })
|
||||||
|
}
|
||||||
|
if (itunesOwnersData.length) {
|
||||||
|
customElements.push({
|
||||||
|
'itunes:owner': itunesOwnersData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.preventIndexing) {
|
||||||
|
customElements.push({ 'itunes:block': 'yes' }, { 'googleplay:block': 'yes' })
|
||||||
|
}
|
||||||
|
|
||||||
const rssData = {
|
const rssData = {
|
||||||
title: this.title,
|
title: this.title,
|
||||||
description: this.description || '',
|
description: this.description || '',
|
||||||
@@ -571,29 +606,10 @@ class Feed extends Model {
|
|||||||
image_url: `${hostPrefix}${this.imageURL}`,
|
image_url: `${hostPrefix}${this.imageURL}`,
|
||||||
custom_namespaces: {
|
custom_namespaces: {
|
||||||
itunes: 'http://www.itunes.com/dtds/podcast-1.0.dtd',
|
itunes: 'http://www.itunes.com/dtds/podcast-1.0.dtd',
|
||||||
psc: 'http://podlove.org/simple-chapters',
|
|
||||||
podcast: 'https://podcastindex.org/namespace/1.0',
|
podcast: 'https://podcastindex.org/namespace/1.0',
|
||||||
googleplay: 'http://www.google.com/schemas/play-podcasts/1.0'
|
googleplay: 'http://www.google.com/schemas/play-podcasts/1.0'
|
||||||
},
|
},
|
||||||
custom_elements: [
|
custom_elements: customElements
|
||||||
{ language: this.language || 'en' },
|
|
||||||
{ author: this.author || 'advplyr' },
|
|
||||||
{ 'itunes:author': this.author || 'advplyr' },
|
|
||||||
{ 'itunes:summary': this.description || '' },
|
|
||||||
{ 'itunes:type': this.podcastType },
|
|
||||||
{
|
|
||||||
'itunes:image': {
|
|
||||||
_attr: {
|
|
||||||
href: `${hostPrefix}${this.imageURL}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'itunes:owner': [{ 'itunes:name': this.ownerName || this.author || '' }, { 'itunes:email': this.ownerEmail || '' }]
|
|
||||||
},
|
|
||||||
{ 'itunes:explicit': !!this.explicit },
|
|
||||||
...(this.preventIndexing ? blockTags : [])
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rssfeed = new RSS(rssData)
|
const rssfeed = new RSS(rssData)
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ class FeedEpisode extends Model {
|
|||||||
const feedEpisodeObjs = []
|
const feedEpisodeObjs = []
|
||||||
let numExisting = 0
|
let numExisting = 0
|
||||||
for (const book of books) {
|
for (const book of books) {
|
||||||
const trackList = book.libraryItem.getTrackList()
|
const trackList = book.getTracklist(book.libraryItem.id)
|
||||||
const useChapterTitles = this.checkUseChapterTitlesForEpisodes(trackList, book)
|
const useChapterTitles = this.checkUseChapterTitlesForEpisodes(trackList, book)
|
||||||
for (const track of trackList) {
|
for (const track of trackList) {
|
||||||
// Check for existing episode by filepath
|
// Check for existing episode by filepath
|
||||||
@@ -305,6 +305,23 @@ class FeedEpisode extends Model {
|
|||||||
* @param {string} hostPrefix
|
* @param {string} hostPrefix
|
||||||
*/
|
*/
|
||||||
getRSSData(hostPrefix) {
|
getRSSData(hostPrefix) {
|
||||||
|
const customElements = [
|
||||||
|
{ 'itunes:author': this.author || null },
|
||||||
|
{ 'itunes:duration': Math.round(Number(this.duration)) },
|
||||||
|
{
|
||||||
|
'itunes:explicit': !!this.explicit
|
||||||
|
},
|
||||||
|
{ 'itunes:episodeType': this.episodeType || null },
|
||||||
|
{ 'itunes:season': this.season || null },
|
||||||
|
{ 'itunes:episode': this.episode || null }
|
||||||
|
].filter((element) => {
|
||||||
|
// Remove empty custom elements
|
||||||
|
return Object.values(element)[0] !== null
|
||||||
|
})
|
||||||
|
if (this.description) {
|
||||||
|
customElements.push({ 'itunes:summary': { _cdata: this.description } })
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: this.title,
|
title: this.title,
|
||||||
description: this.description || '',
|
description: this.description || '',
|
||||||
@@ -317,17 +334,7 @@ class FeedEpisode extends Model {
|
|||||||
type: this.enclosureType,
|
type: this.enclosureType,
|
||||||
size: this.enclosureSize
|
size: this.enclosureSize
|
||||||
},
|
},
|
||||||
custom_elements: [
|
custom_elements: customElements
|
||||||
{ 'itunes:author': this.author },
|
|
||||||
{ 'itunes:duration': secondsToTimestamp(this.duration) },
|
|
||||||
{ 'itunes:summary': this.description || '' },
|
|
||||||
{
|
|
||||||
'itunes:explicit': !!this.explicit
|
|
||||||
},
|
|
||||||
{ 'itunes:episodeType': this.episodeType },
|
|
||||||
{ 'itunes:season': this.season },
|
|
||||||
{ 'itunes:episode': this.episode }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class ApiRouter {
|
|||||||
//
|
//
|
||||||
// Library Routes
|
// Library Routes
|
||||||
//
|
//
|
||||||
this.router.get(/^\/libraries/i, this.apiCacheManager.middleware)
|
this.router.get(/^\/libraries/, this.apiCacheManager.middleware)
|
||||||
this.router.post('/libraries', LibraryController.create.bind(this))
|
this.router.post('/libraries', LibraryController.create.bind(this))
|
||||||
this.router.get('/libraries', LibraryController.findAll.bind(this))
|
this.router.get('/libraries', LibraryController.findAll.bind(this))
|
||||||
this.router.get('/libraries/:id', LibraryController.middleware.bind(this), LibraryController.findOne.bind(this))
|
this.router.get('/libraries/:id', LibraryController.middleware.bind(this), LibraryController.findOne.bind(this))
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ function secondsToTimestamp(seconds, includeMs = false, alwaysIncludeHours = fal
|
|||||||
var ms = _seconds - Math.floor(seconds)
|
var ms = _seconds - Math.floor(seconds)
|
||||||
_seconds = Math.floor(_seconds)
|
_seconds = Math.floor(_seconds)
|
||||||
|
|
||||||
var msString = '.' + (includeMs ? ms.toFixed(3) : '0.0').split('.')[1]
|
const msString = includeMs ? '.' + ms.toFixed(3).split('.')[1] : ''
|
||||||
if (alwaysIncludeHours) {
|
if (alwaysIncludeHours) {
|
||||||
return `${_hours.toString().padStart(2, '0')}:${_minutes.toString().padStart(2, '0')}:${_seconds.toString().padStart(2, '0')}${msString}`
|
return `${_hours.toString().padStart(2, '0')}:${_minutes.toString().padStart(2, '0')}:${_seconds.toString().padStart(2, '0')}${msString}`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user