mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-06-01 04:34:13 -04:00
Remove unused old model functions
This commit is contained in:
parent
4a5f534a65
commit
920ddf43d7
@ -153,7 +153,6 @@ class Server {
|
|||||||
// Static folder
|
// Static folder
|
||||||
router.use(express.static(Path.join(global.appRoot, 'static')))
|
router.use(express.static(Path.join(global.appRoot, 'static')))
|
||||||
|
|
||||||
// router.use('/api/v1', routes) // TODO: New routes
|
|
||||||
router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router)
|
router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router)
|
||||||
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
|
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
const itemDb = require('../db/item.db')
|
|
||||||
|
|
||||||
const getLibraryItem = async (req, res) => {
|
|
||||||
let libraryItem = null
|
|
||||||
if (req.query.expanded == 1) {
|
|
||||||
libraryItem = await itemDb.getLibraryItemExpanded(req.params.id)
|
|
||||||
} else {
|
|
||||||
libraryItem = await itemDb.getLibraryItemMinified(req.params.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
res.json(libraryItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getLibraryItem
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* TODO: Unused for testing
|
|
||||||
*/
|
|
||||||
const { Sequelize } = require('sequelize')
|
|
||||||
const Database = require('../Database')
|
|
||||||
|
|
||||||
const getLibraryItemMinified = (libraryItemId) => {
|
|
||||||
return Database.libraryItemModel.findByPk(libraryItemId, {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: Database.bookModel,
|
|
||||||
attributes: [
|
|
||||||
'id', 'title', 'subtitle', 'publishedYear', 'publishedDate', 'publisher', 'description', 'isbn', 'asin', 'language', 'explicit', 'narrators', 'coverPath', 'genres', 'tags'
|
|
||||||
],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: Database.authorModel,
|
|
||||||
attributes: ['id', 'name'],
|
|
||||||
through: {
|
|
||||||
attributes: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: Database.seriesModel,
|
|
||||||
attributes: ['id', 'name'],
|
|
||||||
through: {
|
|
||||||
attributes: ['sequence']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: Database.podcastModel,
|
|
||||||
attributes: [
|
|
||||||
'id', 'title', 'author', 'releaseDate', 'feedURL', 'imageURL', 'description', 'itunesPageURL', 'itunesId', 'itunesArtistId', 'language', 'podcastType', 'explicit', 'autoDownloadEpisodes', 'genres', 'tags',
|
|
||||||
[Sequelize.literal('(SELECT COUNT(*) FROM "podcastEpisodes" WHERE "podcastEpisodes"."podcastId" = podcast.id)'), 'numPodcastEpisodes']
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getLibraryItemExpanded = (libraryItemId) => {
|
|
||||||
return Database.libraryItemModel.findByPk(libraryItemId, {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: Database.bookModel,
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: Database.authorModel,
|
|
||||||
through: {
|
|
||||||
attributes: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: Database.seriesModel,
|
|
||||||
through: {
|
|
||||||
attributes: ['sequence']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: Database.podcastModel,
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: Database.podcastEpisodeModel
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'libraryFolder',
|
|
||||||
'library'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getLibraryItemMinified,
|
|
||||||
getLibraryItemExpanded
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
const uuidv4 = require("uuid").v4
|
const uuidv4 = require("uuid").v4
|
||||||
const fs = require('../libs/fsExtra')
|
const fs = require('../libs/fsExtra')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const { version } = require('../../package.json')
|
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const abmetadataGenerator = require('../utils/generators/abmetadataGenerator')
|
const abmetadataGenerator = require('../utils/generators/abmetadataGenerator')
|
||||||
const LibraryFile = require('./files/LibraryFile')
|
const LibraryFile = require('./files/LibraryFile')
|
||||||
@ -9,7 +8,7 @@ const Book = require('./mediaTypes/Book')
|
|||||||
const Podcast = require('./mediaTypes/Podcast')
|
const Podcast = require('./mediaTypes/Podcast')
|
||||||
const Video = require('./mediaTypes/Video')
|
const Video = require('./mediaTypes/Video')
|
||||||
const Music = require('./mediaTypes/Music')
|
const Music = require('./mediaTypes/Music')
|
||||||
const { areEquivalent, copyValue, cleanStringForSearch } = require('../utils/index')
|
const { areEquivalent, copyValue } = require('../utils/index')
|
||||||
const { filePathToPOSIX, getFileTimestampsWithIno } = require('../utils/fileUtils')
|
const { filePathToPOSIX, getFileTimestampsWithIno } = require('../utils/fileUtils')
|
||||||
|
|
||||||
class LibraryItem {
|
class LibraryItem {
|
||||||
@ -180,34 +179,23 @@ class LibraryItem {
|
|||||||
this.libraryFiles.forEach((lf) => total += lf.metadata.size)
|
this.libraryFiles.forEach((lf) => total += lf.metadata.size)
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
get audioFileTotalSize() {
|
|
||||||
let total = 0
|
|
||||||
this.libraryFiles.filter(lf => lf.fileType == 'audio').forEach((lf) => total += lf.metadata.size)
|
|
||||||
return total
|
|
||||||
}
|
|
||||||
get hasAudioFiles() {
|
get hasAudioFiles() {
|
||||||
return this.libraryFiles.some(lf => lf.fileType === 'audio')
|
return this.libraryFiles.some(lf => lf.fileType === 'audio')
|
||||||
}
|
}
|
||||||
get hasMediaEntities() {
|
get hasMediaEntities() {
|
||||||
return this.media.hasMediaEntities
|
return this.media.hasMediaEntities
|
||||||
}
|
}
|
||||||
get hasIssues() {
|
|
||||||
if (this.isMissing || this.isInvalid) return true
|
|
||||||
return this.media.hasIssues
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data comes from scandir library item data
|
// Data comes from scandir library item data
|
||||||
|
// TODO: Remove this function. Only used when creating a new podcast now
|
||||||
setData(libraryMediaType, payload) {
|
setData(libraryMediaType, payload) {
|
||||||
this.id = uuidv4()
|
this.id = uuidv4()
|
||||||
this.mediaType = libraryMediaType
|
this.mediaType = libraryMediaType
|
||||||
if (libraryMediaType === 'video') {
|
if (libraryMediaType === 'podcast') {
|
||||||
this.media = new Video()
|
|
||||||
} else if (libraryMediaType === 'podcast') {
|
|
||||||
this.media = new Podcast()
|
this.media = new Podcast()
|
||||||
} else if (libraryMediaType === 'book') {
|
} else {
|
||||||
this.media = new Book()
|
Logger.error(`[LibraryItem] setData called with unsupported media type "${libraryMediaType}"`)
|
||||||
} else if (libraryMediaType === 'music') {
|
return
|
||||||
this.media = new Music()
|
|
||||||
}
|
}
|
||||||
this.media.id = uuidv4()
|
this.media.id = uuidv4()
|
||||||
this.media.libraryItemId = this.id
|
this.media.libraryItemId = this.id
|
||||||
@ -270,85 +258,13 @@ class LibraryItem {
|
|||||||
this.updatedAt = Date.now()
|
this.updatedAt = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
setInvalid() {
|
|
||||||
this.isInvalid = true
|
|
||||||
this.updatedAt = Date.now()
|
|
||||||
}
|
|
||||||
|
|
||||||
setLastScan() {
|
|
||||||
this.lastScan = Date.now()
|
|
||||||
this.updatedAt = Date.now()
|
|
||||||
this.scanVersion = version
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns null if file not found, true if file was updated, false if up to date
|
|
||||||
// updates existing LibraryFile, AudioFile, EBookFile's
|
|
||||||
checkFileFound(fileFound) {
|
|
||||||
let hasUpdated = false
|
|
||||||
|
|
||||||
let existingFile = this.libraryFiles.find(lf => lf.ino === fileFound.ino)
|
|
||||||
let mediaFile = null
|
|
||||||
if (!existingFile) {
|
|
||||||
existingFile = this.libraryFiles.find(lf => lf.metadata.path === fileFound.metadata.path)
|
|
||||||
if (existingFile) {
|
|
||||||
// Update media file ino
|
|
||||||
mediaFile = this.media.findFileWithInode(existingFile.ino)
|
|
||||||
if (mediaFile) {
|
|
||||||
mediaFile.ino = fileFound.ino
|
|
||||||
}
|
|
||||||
|
|
||||||
// file inode was updated
|
|
||||||
existingFile.ino = fileFound.ino
|
|
||||||
hasUpdated = true
|
|
||||||
} else {
|
|
||||||
// file not found
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mediaFile = this.media.findFileWithInode(existingFile.ino)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existingFile.metadata.path !== fileFound.metadata.path) {
|
|
||||||
existingFile.metadata.path = fileFound.metadata.path
|
|
||||||
existingFile.metadata.relPath = fileFound.metadata.relPath
|
|
||||||
if (mediaFile) {
|
|
||||||
mediaFile.metadata.path = fileFound.metadata.path
|
|
||||||
mediaFile.metadata.relPath = fileFound.metadata.relPath
|
|
||||||
}
|
|
||||||
hasUpdated = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileMetadata keys
|
|
||||||
['filename', 'ext', 'mtimeMs', 'ctimeMs', 'birthtimeMs', 'size'].forEach((key) => {
|
|
||||||
if (existingFile.metadata[key] !== fileFound.metadata[key]) {
|
|
||||||
// Add modified flag on file data object if exists and was changed
|
|
||||||
if (key === 'mtimeMs' && existingFile.metadata[key]) {
|
|
||||||
fileFound.metadata.wasModified = true
|
|
||||||
}
|
|
||||||
|
|
||||||
existingFile.metadata[key] = fileFound.metadata[key]
|
|
||||||
if (mediaFile) {
|
|
||||||
if (key === 'mtimeMs') mediaFile.metadata.wasModified = true
|
|
||||||
mediaFile.metadata[key] = fileFound.metadata[key]
|
|
||||||
}
|
|
||||||
hasUpdated = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return hasUpdated
|
|
||||||
}
|
|
||||||
|
|
||||||
searchQuery(query) {
|
|
||||||
query = cleanStringForSearch(query)
|
|
||||||
return this.media.searchQuery(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
getDirectPlayTracklist(episodeId) {
|
getDirectPlayTracklist(episodeId) {
|
||||||
return this.media.getDirectPlayTracklist(episodeId)
|
return this.media.getDirectPlayTracklist(episodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save metadata.json/metadata.abs file
|
* Save metadata.json/metadata.abs file
|
||||||
|
* TODO: Move to new LibraryItem model
|
||||||
* @returns {Promise<LibraryFile>} null if not saved
|
* @returns {Promise<LibraryFile>} null if not saved
|
||||||
*/
|
*/
|
||||||
async saveMetadata() {
|
async saveMetadata() {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
const uuidv4 = require("uuid").v4
|
const uuidv4 = require("uuid").v4
|
||||||
const Path = require('path')
|
const { areEquivalent, copyValue } = require('../../utils/index')
|
||||||
const Logger = require('../../Logger')
|
|
||||||
const { cleanStringForSearch, areEquivalent, copyValue } = require('../../utils/index')
|
|
||||||
const AudioFile = require('../files/AudioFile')
|
const AudioFile = require('../files/AudioFile')
|
||||||
const AudioTrack = require('../files/AudioTrack')
|
const AudioTrack = require('../files/AudioTrack')
|
||||||
|
|
||||||
@ -146,19 +144,6 @@ class PodcastEpisode {
|
|||||||
this.updatedAt = Date.now()
|
this.updatedAt = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
setDataFromAudioFile(audioFile, index) {
|
|
||||||
this.id = uuidv4()
|
|
||||||
this.audioFile = audioFile
|
|
||||||
this.title = Path.basename(audioFile.metadata.filename, Path.extname(audioFile.metadata.filename))
|
|
||||||
this.index = index
|
|
||||||
|
|
||||||
this.setDataFromAudioMetaTags(audioFile.metaTags, true)
|
|
||||||
|
|
||||||
this.chapters = audioFile.chapters?.map((c) => ({ ...c }))
|
|
||||||
this.addedAt = Date.now()
|
|
||||||
this.updatedAt = Date.now()
|
|
||||||
}
|
|
||||||
|
|
||||||
update(payload) {
|
update(payload) {
|
||||||
let hasUpdates = false
|
let hasUpdates = false
|
||||||
for (const key in this.toJSON()) {
|
for (const key in this.toJSON()) {
|
||||||
@ -192,80 +177,5 @@ class PodcastEpisode {
|
|||||||
if (!this.enclosure || !this.enclosure.url) return false
|
if (!this.enclosure || !this.enclosure.url) return false
|
||||||
return this.enclosure.url == url
|
return this.enclosure.url == url
|
||||||
}
|
}
|
||||||
|
|
||||||
searchQuery(query) {
|
|
||||||
return cleanStringForSearch(this.title).includes(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
setDataFromAudioMetaTags(audioFileMetaTags, overrideExistingDetails = false) {
|
|
||||||
if (!audioFileMetaTags) return false
|
|
||||||
|
|
||||||
const MetadataMapArray = [
|
|
||||||
{
|
|
||||||
tag: 'tagComment',
|
|
||||||
altTag: 'tagSubtitle',
|
|
||||||
key: 'description'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagSubtitle',
|
|
||||||
key: 'subtitle'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagDate',
|
|
||||||
key: 'pubDate'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagDisc',
|
|
||||||
key: 'season',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagTrack',
|
|
||||||
altTag: 'tagSeriesPart',
|
|
||||||
key: 'episode'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagTitle',
|
|
||||||
key: 'title'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagEpisodeType',
|
|
||||||
key: 'episodeType'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
MetadataMapArray.forEach((mapping) => {
|
|
||||||
let value = audioFileMetaTags[mapping.tag]
|
|
||||||
let tagToUse = mapping.tag
|
|
||||||
if (!value && mapping.altTag) {
|
|
||||||
tagToUse = mapping.altTag
|
|
||||||
value = audioFileMetaTags[mapping.altTag]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value && typeof value === 'string') {
|
|
||||||
value = value.trim() // Trim whitespace
|
|
||||||
|
|
||||||
if (mapping.key === 'pubDate' && (!this.pubDate || overrideExistingDetails)) {
|
|
||||||
const pubJsDate = new Date(value)
|
|
||||||
if (pubJsDate && !isNaN(pubJsDate)) {
|
|
||||||
this.publishedAt = pubJsDate.valueOf()
|
|
||||||
this.pubDate = value
|
|
||||||
Logger.debug(`[PodcastEpisode] Mapping metadata to key ${tagToUse} => ${mapping.key}: ${this[mapping.key]}`)
|
|
||||||
} else {
|
|
||||||
Logger.warn(`[PodcastEpisode] Mapping pubDate with tag ${tagToUse} has invalid date "${value}"`)
|
|
||||||
}
|
|
||||||
} else if (mapping.key === 'episodeType' && (!this.episodeType || overrideExistingDetails)) {
|
|
||||||
if (['full', 'trailer', 'bonus'].includes(value)) {
|
|
||||||
this.episodeType = value
|
|
||||||
Logger.debug(`[PodcastEpisode] Mapping metadata to key ${tagToUse} => ${mapping.key}: ${this[mapping.key]}`)
|
|
||||||
} else {
|
|
||||||
Logger.warn(`[PodcastEpisode] Mapping episodeType with invalid value "${value}". Must be one of [full, trailer, bonus].`)
|
|
||||||
}
|
|
||||||
} else if (!this[mapping.key] || overrideExistingDetails) {
|
|
||||||
this[mapping.key] = value
|
|
||||||
Logger.debug(`[PodcastEpisode] Mapping metadata to key ${tagToUse} => ${mapping.key}: ${this[mapping.key]}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
module.exports = PodcastEpisode
|
module.exports = PodcastEpisode
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
const Logger = require('../../Logger')
|
const Logger = require('../../Logger')
|
||||||
const BookMetadata = require('../metadata/BookMetadata')
|
const BookMetadata = require('../metadata/BookMetadata')
|
||||||
const { areEquivalent, copyValue, cleanStringForSearch } = require('../../utils/index')
|
const { areEquivalent, copyValue } = require('../../utils/index')
|
||||||
const { parseOpfMetadataXML } = require('../../utils/parsers/parseOpfMetadata')
|
const { filePathToPOSIX } = require('../../utils/fileUtils')
|
||||||
const abmetadataGenerator = require('../../utils/generators/abmetadataGenerator')
|
|
||||||
const { readTextFile, filePathToPOSIX } = require('../../utils/fileUtils')
|
|
||||||
const AudioFile = require('../files/AudioFile')
|
const AudioFile = require('../files/AudioFile')
|
||||||
const AudioTrack = require('../files/AudioTrack')
|
const AudioTrack = require('../files/AudioTrack')
|
||||||
const EBookFile = require('../files/EBookFile')
|
const EBookFile = require('../files/EBookFile')
|
||||||
@ -111,23 +109,12 @@ class Book {
|
|||||||
get hasMediaEntities() {
|
get hasMediaEntities() {
|
||||||
return !!this.tracks.length || this.ebookFile
|
return !!this.tracks.length || this.ebookFile
|
||||||
}
|
}
|
||||||
get shouldSearchForCover() {
|
|
||||||
if (this.coverPath) return false
|
|
||||||
if (!this.lastCoverSearch || this.metadata.coverSearchQuery !== this.lastCoverSearchQuery) return true
|
|
||||||
return (Date.now() - this.lastCoverSearch) > 1000 * 60 * 60 * 24 * 7 // 7 day
|
|
||||||
}
|
|
||||||
get hasEmbeddedCoverArt() {
|
|
||||||
return this.audioFiles.some(af => af.embeddedCoverArt)
|
|
||||||
}
|
|
||||||
get invalidAudioFiles() {
|
get invalidAudioFiles() {
|
||||||
return this.audioFiles.filter(af => af.invalid)
|
return this.audioFiles.filter(af => af.invalid)
|
||||||
}
|
}
|
||||||
get includedAudioFiles() {
|
get includedAudioFiles() {
|
||||||
return this.audioFiles.filter(af => !af.exclude && !af.invalid)
|
return this.audioFiles.filter(af => !af.exclude && !af.invalid)
|
||||||
}
|
}
|
||||||
get hasIssues() {
|
|
||||||
return this.missingParts.length || this.invalidAudioFiles.length
|
|
||||||
}
|
|
||||||
get tracks() {
|
get tracks() {
|
||||||
let startOffset = 0
|
let startOffset = 0
|
||||||
return this.includedAudioFiles.map((af) => {
|
return this.includedAudioFiles.map((af) => {
|
||||||
@ -226,57 +213,6 @@ class Book {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLastCoverSearch(coverWasFound) {
|
|
||||||
this.lastCoverSearch = coverWasFound ? null : Date.now()
|
|
||||||
this.lastCoverSearchQuery = coverWasFound ? null : this.metadata.coverSearchQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio file metadata tags map to book details (will not overwrite)
|
|
||||||
setMetadataFromAudioFile(overrideExistingDetails = false) {
|
|
||||||
if (!this.audioFiles.length) return false
|
|
||||||
var audioFile = this.audioFiles[0]
|
|
||||||
if (!audioFile.metaTags) return false
|
|
||||||
return this.metadata.setDataFromAudioMetaTags(audioFile.metaTags, overrideExistingDetails)
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(mediaPayload) {
|
|
||||||
this.metadata = new BookMetadata()
|
|
||||||
if (mediaPayload.metadata) {
|
|
||||||
this.metadata.setData(mediaPayload.metadata)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
searchQuery(query) {
|
|
||||||
const payload = {
|
|
||||||
tags: this.tags.filter(t => cleanStringForSearch(t).includes(query)),
|
|
||||||
series: this.metadata.searchSeries(query),
|
|
||||||
authors: this.metadata.searchAuthors(query),
|
|
||||||
narrators: this.metadata.searchNarrators(query),
|
|
||||||
matchKey: null,
|
|
||||||
matchText: null
|
|
||||||
}
|
|
||||||
const metadataMatch = this.metadata.searchQuery(query)
|
|
||||||
if (metadataMatch) {
|
|
||||||
payload.matchKey = metadataMatch.matchKey
|
|
||||||
payload.matchText = metadataMatch.matchText
|
|
||||||
} else {
|
|
||||||
if (payload.authors.length) {
|
|
||||||
payload.matchKey = 'authors'
|
|
||||||
payload.matchText = this.metadata.authorName
|
|
||||||
} else if (payload.series.length) {
|
|
||||||
payload.matchKey = 'series'
|
|
||||||
payload.matchText = this.metadata.seriesName
|
|
||||||
} else if (payload.tags.length) {
|
|
||||||
payload.matchKey = 'tags'
|
|
||||||
payload.matchText = this.tags.join(', ')
|
|
||||||
} else if (payload.narrators.length) {
|
|
||||||
payload.matchKey = 'narrators'
|
|
||||||
payload.matchText = this.metadata.narratorName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return payload
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the EBookFile from a LibraryFile
|
* Set the EBookFile from a LibraryFile
|
||||||
* If null then ebookFile will be removed from the book
|
* If null then ebookFile will be removed from the book
|
||||||
|
@ -65,15 +65,6 @@ class Music {
|
|||||||
get hasMediaEntities() {
|
get hasMediaEntities() {
|
||||||
return !!this.audioFile
|
return !!this.audioFile
|
||||||
}
|
}
|
||||||
get shouldSearchForCover() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get hasEmbeddedCoverArt() {
|
|
||||||
return this.audioFile.embeddedCoverArt
|
|
||||||
}
|
|
||||||
get hasIssues() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get duration() {
|
get duration() {
|
||||||
return this.audioFile.duration || 0
|
return this.audioFile.duration || 0
|
||||||
}
|
}
|
||||||
@ -134,16 +125,6 @@ class Music {
|
|||||||
this.audioFile = audioFile
|
this.audioFile = audioFile
|
||||||
}
|
}
|
||||||
|
|
||||||
setMetadataFromAudioFile(overrideExistingDetails = false) {
|
|
||||||
if (!this.audioFile) return false
|
|
||||||
if (!this.audioFile.metaTags) return false
|
|
||||||
return this.metadata.setDataFromAudioMetaTags(this.audioFile.metaTags, overrideExistingDetails)
|
|
||||||
}
|
|
||||||
|
|
||||||
searchQuery(query) {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only checks container format
|
// Only checks container format
|
||||||
checkCanDirectPlay(payload) {
|
checkCanDirectPlay(payload) {
|
||||||
return true
|
return true
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
const Logger = require('../../Logger')
|
const Logger = require('../../Logger')
|
||||||
const PodcastEpisode = require('../entities/PodcastEpisode')
|
const PodcastEpisode = require('../entities/PodcastEpisode')
|
||||||
const PodcastMetadata = require('../metadata/PodcastMetadata')
|
const PodcastMetadata = require('../metadata/PodcastMetadata')
|
||||||
const { areEquivalent, copyValue, cleanStringForSearch } = require('../../utils/index')
|
const { areEquivalent, copyValue } = require('../../utils/index')
|
||||||
const abmetadataGenerator = require('../../utils/generators/abmetadataGenerator')
|
const { filePathToPOSIX } = require('../../utils/fileUtils')
|
||||||
const { readTextFile, filePathToPOSIX } = require('../../utils/fileUtils')
|
|
||||||
|
|
||||||
class Podcast {
|
class Podcast {
|
||||||
constructor(podcast) {
|
constructor(podcast) {
|
||||||
@ -110,15 +109,6 @@ class Podcast {
|
|||||||
get hasMediaEntities() {
|
get hasMediaEntities() {
|
||||||
return !!this.episodes.length
|
return !!this.episodes.length
|
||||||
}
|
}
|
||||||
get shouldSearchForCover() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get hasEmbeddedCoverArt() {
|
|
||||||
return this.episodes.some(ep => ep.audioFile.embeddedCoverArt)
|
|
||||||
}
|
|
||||||
get hasIssues() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get duration() {
|
get duration() {
|
||||||
let total = 0
|
let total = 0
|
||||||
this.episodes.forEach((ep) => total += ep.duration)
|
this.episodes.forEach((ep) => total += ep.duration)
|
||||||
@ -187,10 +177,6 @@ class Podcast {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
findEpisodeWithInode(inode) {
|
|
||||||
return this.episodes.find(ep => ep.audioFile.ino === inode)
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(mediaData) {
|
setData(mediaData) {
|
||||||
this.metadata = new PodcastMetadata()
|
this.metadata = new PodcastMetadata()
|
||||||
if (mediaData.metadata) {
|
if (mediaData.metadata) {
|
||||||
@ -203,31 +189,6 @@ class Podcast {
|
|||||||
this.lastEpisodeCheck = Date.now() // Makes sure new episodes are after this
|
this.lastEpisodeCheck = Date.now() // Makes sure new episodes are after this
|
||||||
}
|
}
|
||||||
|
|
||||||
searchEpisodes(query) {
|
|
||||||
return this.episodes.filter(ep => ep.searchQuery(query))
|
|
||||||
}
|
|
||||||
|
|
||||||
searchQuery(query) {
|
|
||||||
const payload = {
|
|
||||||
tags: this.tags.filter(t => cleanStringForSearch(t).includes(query)),
|
|
||||||
matchKey: null,
|
|
||||||
matchText: null
|
|
||||||
}
|
|
||||||
const metadataMatch = this.metadata.searchQuery(query)
|
|
||||||
if (metadataMatch) {
|
|
||||||
payload.matchKey = metadataMatch.matchKey
|
|
||||||
payload.matchText = metadataMatch.matchText
|
|
||||||
} else {
|
|
||||||
const matchingEpisodes = this.searchEpisodes(query)
|
|
||||||
if (matchingEpisodes.length) {
|
|
||||||
payload.matchKey = 'episode'
|
|
||||||
payload.matchText = matchingEpisodes[0].title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return payload
|
|
||||||
}
|
|
||||||
|
|
||||||
checkHasEpisode(episodeId) {
|
checkHasEpisode(episodeId) {
|
||||||
return this.episodes.some(ep => ep.id === episodeId)
|
return this.episodes.some(ep => ep.id === episodeId)
|
||||||
}
|
}
|
||||||
@ -294,14 +255,6 @@ class Podcast {
|
|||||||
return this.episodes.find(ep => ep.id == episodeId)
|
return this.episodes.find(ep => ep.id == episodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio file metadata tags map to podcast details
|
|
||||||
setMetadataFromAudioFile(overrideExistingDetails = false) {
|
|
||||||
if (!this.episodes.length) return false
|
|
||||||
const audioFile = this.episodes[0].audioFile
|
|
||||||
if (!audioFile?.metaTags) return false
|
|
||||||
return this.metadata.setDataFromAudioMetaTags(audioFile.metaTags, overrideExistingDetails)
|
|
||||||
}
|
|
||||||
|
|
||||||
getChapters(episodeId) {
|
getChapters(episodeId) {
|
||||||
return this.getEpisode(episodeId)?.chapters?.map(ch => ({ ...ch })) || []
|
return this.getEpisode(episodeId)?.chapters?.map(ch => ({ ...ch })) || []
|
||||||
}
|
}
|
||||||
|
@ -69,15 +69,6 @@ class Video {
|
|||||||
get hasMediaEntities() {
|
get hasMediaEntities() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
get shouldSearchForCover() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get hasEmbeddedCoverArt() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get hasIssues() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
get duration() {
|
get duration() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const Logger = require('../../Logger')
|
const Logger = require('../../Logger')
|
||||||
const { areEquivalent, copyValue, cleanStringForSearch, getTitleIgnorePrefix, getTitlePrefixAtEnd } = require('../../utils/index')
|
const { areEquivalent, copyValue, getTitleIgnorePrefix, getTitlePrefixAtEnd } = require('../../utils/index')
|
||||||
const parseNameString = require('../../utils/parsers/parseNameString')
|
const parseNameString = require('../../utils/parsers/parseNameString')
|
||||||
class BookMetadata {
|
class BookMetadata {
|
||||||
constructor(metadata) {
|
constructor(metadata) {
|
||||||
@ -144,20 +144,6 @@ class BookMetadata {
|
|||||||
return `${se.name} #${se.sequence}`
|
return `${se.name} #${se.sequence}`
|
||||||
}).join(', ')
|
}).join(', ')
|
||||||
}
|
}
|
||||||
get seriesNameIgnorePrefix() {
|
|
||||||
if (!this.series.length) return ''
|
|
||||||
return this.series.map(se => {
|
|
||||||
if (!se.sequence) return getTitleIgnorePrefix(se.name)
|
|
||||||
return `${getTitleIgnorePrefix(se.name)} #${se.sequence}`
|
|
||||||
}).join(', ')
|
|
||||||
}
|
|
||||||
get seriesNamePrefixAtEnd() {
|
|
||||||
if (!this.series.length) return ''
|
|
||||||
return this.series.map(se => {
|
|
||||||
if (!se.sequence) return getTitlePrefixAtEnd(se.name)
|
|
||||||
return `${getTitlePrefixAtEnd(se.name)} #${se.sequence}`
|
|
||||||
}).join(', ')
|
|
||||||
}
|
|
||||||
get firstSeriesName() {
|
get firstSeriesName() {
|
||||||
if (!this.series.length) return ''
|
if (!this.series.length) return ''
|
||||||
return this.series[0].name
|
return this.series[0].name
|
||||||
@ -169,36 +155,15 @@ class BookMetadata {
|
|||||||
get narratorName() {
|
get narratorName() {
|
||||||
return this.narrators.join(', ')
|
return this.narrators.join(', ')
|
||||||
}
|
}
|
||||||
get coverSearchQuery() {
|
|
||||||
if (!this.authorName) return this.title
|
|
||||||
return this.title + '&' + this.authorName
|
|
||||||
}
|
|
||||||
|
|
||||||
hasAuthor(id) {
|
|
||||||
return !!this.authors.find(au => au.id == id)
|
|
||||||
}
|
|
||||||
hasSeries(seriesId) {
|
|
||||||
return !!this.series.find(se => se.id == seriesId)
|
|
||||||
}
|
|
||||||
hasNarrator(narratorName) {
|
|
||||||
return this.narrators.includes(narratorName)
|
|
||||||
}
|
|
||||||
getSeries(seriesId) {
|
getSeries(seriesId) {
|
||||||
return this.series.find(se => se.id == seriesId)
|
return this.series.find(se => se.id == seriesId)
|
||||||
}
|
}
|
||||||
getFirstSeries() {
|
|
||||||
return this.series.length ? this.series[0] : null
|
|
||||||
}
|
|
||||||
getSeriesSequence(seriesId) {
|
getSeriesSequence(seriesId) {
|
||||||
const series = this.series.find(se => se.id == seriesId)
|
const series = this.series.find(se => se.id == seriesId)
|
||||||
if (!series) return null
|
if (!series) return null
|
||||||
return series.sequence || ''
|
return series.sequence || ''
|
||||||
}
|
}
|
||||||
getSeriesSortTitle(series) {
|
|
||||||
if (!series) return ''
|
|
||||||
if (!series.sequence) return series.name
|
|
||||||
return `${series.name} #${series.sequence}`
|
|
||||||
}
|
|
||||||
|
|
||||||
update(payload) {
|
update(payload) {
|
||||||
const json = this.toJSON()
|
const json = this.toJSON()
|
||||||
@ -231,205 +196,5 @@ class BookMetadata {
|
|||||||
name: newAuthor.name
|
name: newAuthor.name
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update narrator name if narrator is in book
|
|
||||||
* @param {String} oldNarratorName - Narrator name to get updated
|
|
||||||
* @param {String} newNarratorName - Updated narrator name
|
|
||||||
* @return {Boolean} True if narrator was updated
|
|
||||||
*/
|
|
||||||
updateNarrator(oldNarratorName, newNarratorName) {
|
|
||||||
if (!this.hasNarrator(oldNarratorName)) return false
|
|
||||||
this.narrators = this.narrators.filter(n => n !== oldNarratorName)
|
|
||||||
if (newNarratorName && !this.hasNarrator(newNarratorName)) {
|
|
||||||
this.narrators.push(newNarratorName)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove narrator name if narrator is in book
|
|
||||||
* @param {String} narratorName - Narrator name to remove
|
|
||||||
* @return {Boolean} True if narrator was updated
|
|
||||||
*/
|
|
||||||
removeNarrator(narratorName) {
|
|
||||||
if (!this.hasNarrator(narratorName)) return false
|
|
||||||
this.narrators = this.narrators.filter(n => n !== narratorName)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(scanMediaData = {}) {
|
|
||||||
this.title = scanMediaData.title || null
|
|
||||||
this.subtitle = scanMediaData.subtitle || null
|
|
||||||
this.narrators = this.parseNarratorsTag(scanMediaData.narrators)
|
|
||||||
this.publishedYear = scanMediaData.publishedYear || null
|
|
||||||
this.description = scanMediaData.description || null
|
|
||||||
this.isbn = scanMediaData.isbn || null
|
|
||||||
this.asin = scanMediaData.asin || null
|
|
||||||
this.language = scanMediaData.language || null
|
|
||||||
this.genres = []
|
|
||||||
this.explicit = !!scanMediaData.explicit
|
|
||||||
|
|
||||||
if (scanMediaData.author) {
|
|
||||||
this.authors = this.parseAuthorsTag(scanMediaData.author)
|
|
||||||
}
|
|
||||||
if (scanMediaData.series) {
|
|
||||||
this.series = this.parseSeriesTag(scanMediaData.series, scanMediaData.sequence)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setDataFromAudioMetaTags(audioFileMetaTags, overrideExistingDetails = false) {
|
|
||||||
const MetadataMapArray = [
|
|
||||||
{
|
|
||||||
tag: 'tagComposer',
|
|
||||||
key: 'narrators'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagDescription',
|
|
||||||
altTag: 'tagComment',
|
|
||||||
key: 'description'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagPublisher',
|
|
||||||
key: 'publisher'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagDate',
|
|
||||||
key: 'publishedYear'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagSubtitle',
|
|
||||||
key: 'subtitle'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagAlbum',
|
|
||||||
altTag: 'tagTitle',
|
|
||||||
key: 'title',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagArtist',
|
|
||||||
altTag: 'tagAlbumArtist',
|
|
||||||
key: 'authors'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagGenre',
|
|
||||||
key: 'genres'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagSeries',
|
|
||||||
key: 'series'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagIsbn',
|
|
||||||
key: 'isbn'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagLanguage',
|
|
||||||
key: 'language'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagASIN',
|
|
||||||
key: 'asin'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const updatePayload = {}
|
|
||||||
|
|
||||||
// Metadata is only mapped to the book if it is empty
|
|
||||||
MetadataMapArray.forEach((mapping) => {
|
|
||||||
let value = audioFileMetaTags[mapping.tag]
|
|
||||||
// let tagToUse = mapping.tag
|
|
||||||
if (!value && mapping.altTag) {
|
|
||||||
value = audioFileMetaTags[mapping.altTag]
|
|
||||||
// tagToUse = mapping.altTag
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value && typeof value === 'string') {
|
|
||||||
value = value.trim() // Trim whitespace
|
|
||||||
|
|
||||||
if (mapping.key === 'narrators' && (!this.narrators.length || overrideExistingDetails)) {
|
|
||||||
updatePayload.narrators = this.parseNarratorsTag(value)
|
|
||||||
} else if (mapping.key === 'authors' && (!this.authors.length || overrideExistingDetails)) {
|
|
||||||
updatePayload.authors = this.parseAuthorsTag(value)
|
|
||||||
} else if (mapping.key === 'genres' && (!this.genres.length || overrideExistingDetails)) {
|
|
||||||
updatePayload.genres = this.parseGenresTag(value)
|
|
||||||
} else if (mapping.key === 'series' && (!this.series.length || overrideExistingDetails)) {
|
|
||||||
const sequenceTag = audioFileMetaTags.tagSeriesPart || null
|
|
||||||
updatePayload.series = this.parseSeriesTag(value, sequenceTag)
|
|
||||||
} else if (!this[mapping.key] || overrideExistingDetails) {
|
|
||||||
updatePayload[mapping.key] = value
|
|
||||||
// Logger.debug(`[Book] Mapping metadata to key ${tagToUse} => ${mapping.key}: ${updatePayload[mapping.key]}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Object.keys(updatePayload).length) {
|
|
||||||
return this.update(updatePayload)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns array of names in First Last format
|
|
||||||
parseNarratorsTag(narratorsTag) {
|
|
||||||
const parsed = parseNameString.parse(narratorsTag)
|
|
||||||
return parsed ? parsed.names : []
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return array of authors minified with placeholder id
|
|
||||||
parseAuthorsTag(authorsTag) {
|
|
||||||
const parsed = parseNameString.parse(authorsTag)
|
|
||||||
if (!parsed) return []
|
|
||||||
return (parsed.names || []).map((au) => {
|
|
||||||
const findAuthor = this.authors.find(_au => _au.name == au)
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: findAuthor?.id || `new-${Math.floor(Math.random() * 1000000)}`,
|
|
||||||
name: au
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
parseGenresTag(genreTag) {
|
|
||||||
if (!genreTag || !genreTag.length) return []
|
|
||||||
const separators = ['/', '//', ';']
|
|
||||||
for (let i = 0; i < separators.length; i++) {
|
|
||||||
if (genreTag.includes(separators[i])) {
|
|
||||||
return genreTag.split(separators[i]).map(genre => genre.trim()).filter(g => !!g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [genreTag]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return array with series with placeholder id
|
|
||||||
parseSeriesTag(seriesTag, sequenceTag) {
|
|
||||||
if (!seriesTag) return []
|
|
||||||
return [{
|
|
||||||
id: `new-${Math.floor(Math.random() * 1000000)}`,
|
|
||||||
name: seriesTag,
|
|
||||||
sequence: sequenceTag || ''
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
searchSeries(query) {
|
|
||||||
return this.series.filter(se => cleanStringForSearch(se.name).includes(query))
|
|
||||||
}
|
|
||||||
searchAuthors(query) {
|
|
||||||
return this.authors.filter(au => cleanStringForSearch(au.name).includes(query))
|
|
||||||
}
|
|
||||||
searchNarrators(query) {
|
|
||||||
return this.narrators.filter(n => cleanStringForSearch(n).includes(query))
|
|
||||||
}
|
|
||||||
searchQuery(query) { // Returns key if match is found
|
|
||||||
const keysToCheck = ['title', 'asin', 'isbn', 'subtitle']
|
|
||||||
for (const key of keysToCheck) {
|
|
||||||
if (this[key] && cleanStringForSearch(String(this[key])).includes(query)) {
|
|
||||||
return {
|
|
||||||
matchKey: key,
|
|
||||||
matchText: this[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
module.exports = BookMetadata
|
module.exports = BookMetadata
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const Logger = require('../../Logger')
|
const Logger = require('../../Logger')
|
||||||
const { areEquivalent, copyValue, cleanStringForSearch, getTitleIgnorePrefix, getTitlePrefixAtEnd } = require('../../utils/index')
|
const { areEquivalent, copyValue, getTitleIgnorePrefix, getTitlePrefixAtEnd } = require('../../utils/index')
|
||||||
|
|
||||||
class MusicMetadata {
|
class MusicMetadata {
|
||||||
constructor(metadata) {
|
constructor(metadata) {
|
||||||
@ -133,19 +133,6 @@ class MusicMetadata {
|
|||||||
return getTitlePrefixAtEnd(this.title)
|
return getTitlePrefixAtEnd(this.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchQuery(query) { // Returns key if match is found
|
|
||||||
const keysToCheck = ['title', 'album']
|
|
||||||
for (const key of keysToCheck) {
|
|
||||||
if (this[key] && cleanStringForSearch(String(this[key])).includes(query)) {
|
|
||||||
return {
|
|
||||||
matchKey: key,
|
|
||||||
matchText: this[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(mediaMetadata = {}) {
|
setData(mediaMetadata = {}) {
|
||||||
this.title = mediaMetadata.title || null
|
this.title = mediaMetadata.title || null
|
||||||
this.artist = mediaMetadata.artist || null
|
this.artist = mediaMetadata.artist || null
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const Logger = require('../../Logger')
|
const Logger = require('../../Logger')
|
||||||
const { areEquivalent, copyValue, cleanStringForSearch, getTitleIgnorePrefix, getTitlePrefixAtEnd } = require('../../utils/index')
|
const { areEquivalent, copyValue, getTitleIgnorePrefix, getTitlePrefixAtEnd } = require('../../utils/index')
|
||||||
|
|
||||||
class PodcastMetadata {
|
class PodcastMetadata {
|
||||||
constructor(metadata) {
|
constructor(metadata) {
|
||||||
@ -91,19 +91,6 @@ class PodcastMetadata {
|
|||||||
return getTitlePrefixAtEnd(this.title)
|
return getTitlePrefixAtEnd(this.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchQuery(query) { // Returns key if match is found
|
|
||||||
const keysToCheck = ['title', 'author', 'itunesId', 'itunesArtistId']
|
|
||||||
for (const key of keysToCheck) {
|
|
||||||
if (this[key] && cleanStringForSearch(String(this[key])).includes(query)) {
|
|
||||||
return {
|
|
||||||
matchKey: key,
|
|
||||||
matchText: this[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(mediaMetadata = {}) {
|
setData(mediaMetadata = {}) {
|
||||||
this.title = mediaMetadata.title || null
|
this.title = mediaMetadata.title || null
|
||||||
this.author = mediaMetadata.author || null
|
this.author = mediaMetadata.author || null
|
||||||
@ -136,74 +123,5 @@ class PodcastMetadata {
|
|||||||
}
|
}
|
||||||
return hasUpdates
|
return hasUpdates
|
||||||
}
|
}
|
||||||
|
|
||||||
setDataFromAudioMetaTags(audioFileMetaTags, overrideExistingDetails = false) {
|
|
||||||
const MetadataMapArray = [
|
|
||||||
{
|
|
||||||
tag: 'tagAlbum',
|
|
||||||
altTag: 'tagSeries',
|
|
||||||
key: 'title'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagArtist',
|
|
||||||
key: 'author'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagGenre',
|
|
||||||
key: 'genres'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagLanguage',
|
|
||||||
key: 'language'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagItunesId',
|
|
||||||
key: 'itunesId'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: 'tagPodcastType',
|
|
||||||
key: 'type',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const updatePayload = {}
|
|
||||||
|
|
||||||
MetadataMapArray.forEach((mapping) => {
|
|
||||||
let value = audioFileMetaTags[mapping.tag]
|
|
||||||
let tagToUse = mapping.tag
|
|
||||||
if (!value && mapping.altTag) {
|
|
||||||
value = audioFileMetaTags[mapping.altTag]
|
|
||||||
tagToUse = mapping.altTag
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value && typeof value === 'string') {
|
|
||||||
value = value.trim() // Trim whitespace
|
|
||||||
|
|
||||||
if (mapping.key === 'genres' && (!this.genres.length || overrideExistingDetails)) {
|
|
||||||
updatePayload.genres = this.parseGenresTag(value)
|
|
||||||
Logger.debug(`[Podcast] Mapping metadata to key ${tagToUse} => ${mapping.key}: ${updatePayload.genres.join(', ')}`)
|
|
||||||
} else if (!this[mapping.key] || overrideExistingDetails) {
|
|
||||||
updatePayload[mapping.key] = value
|
|
||||||
Logger.debug(`[Podcast] Mapping metadata to key ${tagToUse} => ${mapping.key}: ${updatePayload[mapping.key]}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Object.keys(updatePayload).length) {
|
|
||||||
return this.update(updatePayload)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
parseGenresTag(genreTag) {
|
|
||||||
if (!genreTag || !genreTag.length) return []
|
|
||||||
const separators = ['/', '//', ';']
|
|
||||||
for (let i = 0; i < separators.length; i++) {
|
|
||||||
if (genreTag.includes(separators[i])) {
|
|
||||||
return genreTag.split(separators[i]).map(genre => genre.trim()).filter(g => !!g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [genreTag]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
module.exports = PodcastMetadata
|
module.exports = PodcastMetadata
|
||||||
|
@ -55,19 +55,6 @@ class VideoMetadata {
|
|||||||
return getTitlePrefixAtEnd(this.title)
|
return getTitlePrefixAtEnd(this.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchQuery(query) { // Returns key if match is found
|
|
||||||
var keysToCheck = ['title']
|
|
||||||
for (var key of keysToCheck) {
|
|
||||||
if (this[key] && String(this[key]).toLowerCase().includes(query)) {
|
|
||||||
return {
|
|
||||||
matchKey: key,
|
|
||||||
matchText: this[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(mediaMetadata = {}) {
|
setData(mediaMetadata = {}) {
|
||||||
this.title = mediaMetadata.title || null
|
this.title = mediaMetadata.title || null
|
||||||
this.description = mediaMetadata.description || null
|
this.description = mediaMetadata.description || null
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
const sequelize = require('sequelize')
|
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
const express = require('express')
|
|
||||||
const libraries = require('./libraries')
|
|
||||||
|
|
||||||
const router = express.Router()
|
|
||||||
|
|
||||||
router.use('/libraries', libraries)
|
|
||||||
|
|
||||||
module.exports = router
|
|
@ -1,7 +0,0 @@
|
|||||||
const express = require('express')
|
|
||||||
|
|
||||||
const router = express.Router()
|
|
||||||
|
|
||||||
// TODO: Add library routes
|
|
||||||
|
|
||||||
module.exports = router
|
|
Loading…
x
Reference in New Issue
Block a user