mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-08 00:08:14 +01:00
Update updateMedia endpoint to use new model
This commit is contained in:
parent
5cd14108f9
commit
12c6f2e9a5
@ -234,32 +234,27 @@ class LibraryItemController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(req.libraryItem)
|
|
||||||
|
|
||||||
// Book specific - Get all series being removed from this item
|
// Book specific - Get all series being removed from this item
|
||||||
let seriesRemoved = []
|
let seriesRemoved = []
|
||||||
if (req.libraryItem.isBook && mediaPayload.metadata?.series) {
|
if (req.libraryItem.isBook && mediaPayload.metadata?.series) {
|
||||||
const seriesIdsInUpdate = mediaPayload.metadata.series?.map((se) => se.id) || []
|
const seriesIdsInUpdate = mediaPayload.metadata.series?.map((se) => se.id) || []
|
||||||
seriesRemoved = oldLibraryItem.media.metadata.series.filter((se) => !seriesIdsInUpdate.includes(se.id))
|
seriesRemoved = req.libraryItem.media.series.filter((se) => !seriesIdsInUpdate.includes(se.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
let authorsRemoved = []
|
let authorsRemoved = []
|
||||||
if (req.libraryItem.isBook && mediaPayload.metadata?.authors) {
|
if (req.libraryItem.isBook && mediaPayload.metadata?.authors) {
|
||||||
const authorIdsInUpdate = mediaPayload.metadata.authors.map((au) => au.id)
|
const authorIdsInUpdate = mediaPayload.metadata.authors.map((au) => au.id)
|
||||||
authorsRemoved = oldLibraryItem.media.metadata.authors.filter((au) => !authorIdsInUpdate.includes(au.id))
|
authorsRemoved = req.libraryItem.media.authors.filter((au) => !authorIdsInUpdate.includes(au.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasUpdates = oldLibraryItem.media.update(mediaPayload) || mediaPayload.url
|
const hasUpdates = (await req.libraryItem.media.updateFromRequest(mediaPayload)) || mediaPayload.url
|
||||||
if (hasUpdates) {
|
if (hasUpdates) {
|
||||||
oldLibraryItem.updatedAt = Date.now()
|
|
||||||
|
|
||||||
if (isPodcastAutoDownloadUpdated) {
|
if (isPodcastAutoDownloadUpdated) {
|
||||||
this.cronManager.checkUpdatePodcastCron(oldLibraryItem)
|
this.cronManager.checkUpdatePodcastCron(req.libraryItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.debug(`[LibraryItemController] Updated library item media ${oldLibraryItem.media.metadata.title}`)
|
Logger.debug(`[LibraryItemController] Updated library item media ${req.libraryItem.media.title}`)
|
||||||
await Database.updateLibraryItem(oldLibraryItem)
|
SocketAuthority.emitter('item_updated', req.libraryItem.toOldJSONExpanded())
|
||||||
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
|
|
||||||
|
|
||||||
if (authorsRemoved.length) {
|
if (authorsRemoved.length) {
|
||||||
// Check remove empty authors
|
// Check remove empty authors
|
||||||
@ -274,7 +269,7 @@ class LibraryItemController {
|
|||||||
}
|
}
|
||||||
res.json({
|
res.json({
|
||||||
updated: hasUpdates,
|
updated: hasUpdates,
|
||||||
libraryItem: oldLibraryItem
|
libraryItem: req.libraryItem.toOldJSON()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +215,10 @@ class CronManager {
|
|||||||
this.podcastCrons = this.podcastCrons.filter((pc) => pc.expression !== podcastCron.expression)
|
this.podcastCrons = this.podcastCrons.filter((pc) => pc.expression !== podcastCron.expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import('../models/LibraryItem')} libraryItem - this can be the old model
|
||||||
|
*/
|
||||||
checkUpdatePodcastCron(libraryItem) {
|
checkUpdatePodcastCron(libraryItem) {
|
||||||
// Remove from old cron by library item id
|
// Remove from old cron by library item id
|
||||||
const existingCron = this.podcastCrons.find((pc) => pc.libraryItemIds.includes(libraryItem.id))
|
const existingCron = this.podcastCrons.find((pc) => pc.libraryItemIds.includes(libraryItem.id))
|
||||||
@ -230,7 +234,10 @@ class CronManager {
|
|||||||
const cronMatchingExpression = this.podcastCrons.find((pc) => pc.expression === libraryItem.media.autoDownloadSchedule)
|
const cronMatchingExpression = this.podcastCrons.find((pc) => pc.expression === libraryItem.media.autoDownloadSchedule)
|
||||||
if (cronMatchingExpression) {
|
if (cronMatchingExpression) {
|
||||||
cronMatchingExpression.libraryItemIds.push(libraryItem.id)
|
cronMatchingExpression.libraryItemIds.push(libraryItem.id)
|
||||||
Logger.info(`[CronManager] Added podcast "${libraryItem.media.metadata.title}" to auto dl episode cron "${cronMatchingExpression.expression}"`)
|
|
||||||
|
// TODO: Update after old model removed
|
||||||
|
const podcastTitle = libraryItem.media.title || libraryItem.media.metadata?.title
|
||||||
|
Logger.info(`[CronManager] Added podcast "${podcastTitle}" to auto dl episode cron "${cronMatchingExpression.expression}"`)
|
||||||
} else {
|
} else {
|
||||||
this.startPodcastCron(libraryItem.media.autoDownloadSchedule, [libraryItem.id])
|
this.startPodcastCron(libraryItem.media.autoDownloadSchedule, [libraryItem.id])
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const { DataTypes, Model } = require('sequelize')
|
const { DataTypes, Model } = require('sequelize')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const { getTitlePrefixAtEnd } = require('../utils')
|
const { getTitlePrefixAtEnd, getTitleIgnorePrefix } = require('../utils')
|
||||||
const parseNameString = require('../utils/parsers/parseNameString')
|
const parseNameString = require('../utils/parsers/parseNameString')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -425,6 +425,116 @@ class Book extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} payload - old book object
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async updateFromRequest(payload) {
|
||||||
|
if (!payload) return false
|
||||||
|
|
||||||
|
let hasUpdates = false
|
||||||
|
|
||||||
|
if (payload.metadata) {
|
||||||
|
const metadataStringKeys = ['title', 'subtitle', 'publishedYear', 'publishedDate', 'publisher', 'description', 'isbn', 'asin', 'language']
|
||||||
|
metadataStringKeys.forEach((key) => {
|
||||||
|
if (typeof payload.metadata[key] === 'string' && this[key] !== payload.metadata[key]) {
|
||||||
|
this[key] = payload.metadata[key] || null
|
||||||
|
|
||||||
|
if (key === 'title') {
|
||||||
|
this.titleIgnorePrefix = getTitleIgnorePrefix(this.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (payload.metadata.explicit !== undefined && this.explicit !== !!payload.metadata.explicit) {
|
||||||
|
this.explicit = !!payload.metadata.explicit
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
if (payload.metadata.abridged !== undefined && this.abridged !== !!payload.metadata.abridged) {
|
||||||
|
this.abridged = !!payload.metadata.abridged
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
const arrayOfStringsKeys = ['narrators', 'genres']
|
||||||
|
arrayOfStringsKeys.forEach((key) => {
|
||||||
|
if (Array.isArray(payload.metadata[key]) && !payload.metadata[key].some((item) => typeof item !== 'string') && JSON.stringify(this[key]) !== JSON.stringify(payload.metadata[key])) {
|
||||||
|
this[key] = payload.metadata[key]
|
||||||
|
this.changed(key, true)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(payload.tags) && !payload.tags.some((tag) => typeof tag !== 'string') && JSON.stringify(this.tags) !== JSON.stringify(payload.tags)) {
|
||||||
|
this.tags = payload.tags
|
||||||
|
this.changed('tags', true)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove support for updating audioFiles, chapters and ebookFile here
|
||||||
|
const arrayOfObjectsKeys = ['audioFiles', 'chapters']
|
||||||
|
arrayOfObjectsKeys.forEach((key) => {
|
||||||
|
if (Array.isArray(payload[key]) && !payload[key].some((item) => typeof item !== 'object') && JSON.stringify(this[key]) !== JSON.stringify(payload[key])) {
|
||||||
|
this[key] = payload[key]
|
||||||
|
this.changed(key, true)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (payload.ebookFile && JSON.stringify(this.ebookFile) !== JSON.stringify(payload.ebookFile)) {
|
||||||
|
this.ebookFile = payload.ebookFile
|
||||||
|
this.changed('ebookFile', true)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUpdates) {
|
||||||
|
Logger.debug(`[Book] "${this.title}" changed keys:`, this.changed())
|
||||||
|
await this.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(payload.metadata?.authors)) {
|
||||||
|
const authorsRemoved = this.authors.filter((au) => !payload.metadata.authors.some((a) => a.id === au.id))
|
||||||
|
const newAuthors = payload.metadata.authors.filter((a) => !this.authors.some((au) => au.id === a.id))
|
||||||
|
|
||||||
|
for (const author of authorsRemoved) {
|
||||||
|
await this.sequelize.models.bookAuthor.removeByIds(author.id, this.id)
|
||||||
|
Logger.debug(`[Book] "${this.title}" Removed author ${author.id}`)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
for (const author of newAuthors) {
|
||||||
|
await this.sequelize.models.bookAuthor.create({ bookId: this.id, authorId: author.id })
|
||||||
|
Logger.debug(`[Book] "${this.title}" Added author ${author.id}`)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(payload.metadata?.series)) {
|
||||||
|
const seriesRemoved = this.series.filter((se) => !payload.metadata.series.some((s) => s.id === se.id))
|
||||||
|
const newSeries = payload.metadata.series.filter((s) => !this.series.some((se) => se.id === s.id))
|
||||||
|
|
||||||
|
for (const series of seriesRemoved) {
|
||||||
|
await this.sequelize.models.bookSeries.removeByIds(series.id, this.id)
|
||||||
|
Logger.debug(`[Book] "${this.title}" Removed series ${series.id}`)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
for (const series of newSeries) {
|
||||||
|
await this.sequelize.models.bookSeries.create({ bookId: this.id, seriesId: series.id, sequence: series.sequence })
|
||||||
|
Logger.debug(`[Book] "${this.title}" Added series ${series.id}`)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
for (const series of payload.metadata.series) {
|
||||||
|
const existingSeries = this.series.find((se) => se.id === series.id)
|
||||||
|
if (existingSeries && existingSeries.bookSeries.sequence !== series.sequence) {
|
||||||
|
await existingSeries.bookSeries.update({ sequence: series.sequence })
|
||||||
|
Logger.debug(`[Book] "${this.title}" Updated series ${series.id} sequence ${series.sequence}`)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasUpdates
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Old model kept metadata in a separate object
|
* Old model kept metadata in a separate object
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const { DataTypes, Model } = require('sequelize')
|
const { DataTypes, Model } = require('sequelize')
|
||||||
const { getTitlePrefixAtEnd } = require('../utils')
|
const { getTitlePrefixAtEnd, getTitleIgnorePrefix } = require('../utils')
|
||||||
|
const Logger = require('../Logger')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef PodcastExpandedProperties
|
* @typedef PodcastExpandedProperties
|
||||||
@ -199,6 +200,82 @@ class Podcast extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} payload - Old podcast object
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async updateFromRequest(payload) {
|
||||||
|
if (!payload) return false
|
||||||
|
|
||||||
|
let hasUpdates = false
|
||||||
|
|
||||||
|
if (payload.metadata) {
|
||||||
|
const stringKeys = ['title', 'author', 'releaseDate', 'feedUrl', 'imageUrl', 'description', 'itunesPageUrl', 'itunesId', 'itunesArtistId', 'language', 'type']
|
||||||
|
stringKeys.forEach((key) => {
|
||||||
|
let newKey = key
|
||||||
|
if (key === 'type') {
|
||||||
|
newKey = 'podcastType'
|
||||||
|
} else if (key === 'feedUrl') {
|
||||||
|
newKey = 'feedURL'
|
||||||
|
} else if (key === 'imageUrl') {
|
||||||
|
newKey = 'imageURL'
|
||||||
|
} else if (key === 'itunesPageUrl') {
|
||||||
|
newKey = 'itunesPageURL'
|
||||||
|
}
|
||||||
|
if (typeof payload.metadata[key] === 'string' && payload.metadata[key] !== this[newKey]) {
|
||||||
|
this[newKey] = payload.metadata[key]
|
||||||
|
if (key === 'title') {
|
||||||
|
this.titleIgnorePrefix = getTitleIgnorePrefix(this.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (payload.metadata.explicit !== undefined && payload.metadata.explicit !== this.explicit) {
|
||||||
|
this.explicit = !!payload.metadata.explicit
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(payload.metadata.genres) && !payload.metadata.genres.some((item) => typeof item !== 'string') && JSON.stringify(this.genres) !== JSON.stringify(payload.metadata.genres)) {
|
||||||
|
this.genres = payload.metadata.genres
|
||||||
|
this.changed('genres', true)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(payload.tags) && !payload.tags.some((item) => typeof item !== 'string') && JSON.stringify(this.tags) !== JSON.stringify(payload.tags)) {
|
||||||
|
this.tags = payload.tags
|
||||||
|
this.changed('tags', true)
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.autoDownloadEpisodes !== undefined && payload.autoDownloadEpisodes !== this.autoDownloadEpisodes) {
|
||||||
|
this.autoDownloadEpisodes = !!payload.autoDownloadEpisodes
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
if (typeof payload.autoDownloadSchedule === 'string' && payload.autoDownloadSchedule !== this.autoDownloadSchedule) {
|
||||||
|
this.autoDownloadSchedule = payload.autoDownloadSchedule
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberKeys = ['maxEpisodesToKeep', 'maxNewEpisodesToDownload']
|
||||||
|
numberKeys.forEach((key) => {
|
||||||
|
if (typeof payload[key] === 'number' && payload[key] !== this[key]) {
|
||||||
|
this[key] = payload[key]
|
||||||
|
hasUpdates = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (hasUpdates) {
|
||||||
|
Logger.debug(`[Podcast] changed keys:`, this.changed())
|
||||||
|
await this.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasUpdates
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Old model kept metadata in a separate object
|
* Old model kept metadata in a separate object
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user