mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Update controllers to use toOldJSON functions
This commit is contained in:
		
							parent
							
								
									7fae25a726
								
							
						
					
					
						commit
						6d52f88a96
					
				@ -665,7 +665,7 @@ class Database {
 | 
			
		||||
  /**
 | 
			
		||||
   * Clean invalid records in database
 | 
			
		||||
   * Series should have atleast one Book
 | 
			
		||||
   * Book and Podcast must have an associated LibraryItem
 | 
			
		||||
   * Book and Podcast must have an associated LibraryItem (and vice versa)
 | 
			
		||||
   * Remove playback sessions that are 3 seconds or less
 | 
			
		||||
   */
 | 
			
		||||
  async cleanDatabase() {
 | 
			
		||||
@ -695,6 +695,28 @@ class Database {
 | 
			
		||||
      await book.destroy()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Remove invalid LibraryItem records
 | 
			
		||||
    const libraryItemsWithNoMedia = await this.libraryItemModel.findAll({
 | 
			
		||||
      include: [
 | 
			
		||||
        {
 | 
			
		||||
          model: this.bookModel,
 | 
			
		||||
          attributes: ['id']
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          model: this.podcastModel,
 | 
			
		||||
          attributes: ['id']
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      where: {
 | 
			
		||||
        '$book.id$': null,
 | 
			
		||||
        '$podcast.id$': null
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    for (const libraryItem of libraryItemsWithNoMedia) {
 | 
			
		||||
      Logger.warn(`Found libraryItem "${libraryItem.id}" with no media - removing it`)
 | 
			
		||||
      await libraryItem.destroy()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const playlistMediaItemsWithNoMediaItem = await this.playlistMediaItemModel.findAll({
 | 
			
		||||
      include: [
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
@ -125,7 +125,7 @@ class AuthorController {
 | 
			
		||||
      const bookAuthorsToCreate = []
 | 
			
		||||
      const allItemsWithAuthor = await Database.authorModel.getAllLibraryItemsForAuthor(req.author.id)
 | 
			
		||||
 | 
			
		||||
      const oldLibraryItems = []
 | 
			
		||||
      const libraryItems = []
 | 
			
		||||
      allItemsWithAuthor.forEach((libraryItem) => {
 | 
			
		||||
        // Replace old author with merging author for each book
 | 
			
		||||
        libraryItem.media.authors = libraryItem.media.authors.filter((au) => au.id !== req.author.id)
 | 
			
		||||
@ -134,23 +134,22 @@ class AuthorController {
 | 
			
		||||
          name: existingAuthor.name
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
        oldLibraryItems.push(oldLibraryItem)
 | 
			
		||||
        libraryItems.push(libraryItem)
 | 
			
		||||
 | 
			
		||||
        bookAuthorsToCreate.push({
 | 
			
		||||
          bookId: libraryItem.media.id,
 | 
			
		||||
          authorId: existingAuthor.id
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      if (oldLibraryItems.length) {
 | 
			
		||||
      if (libraryItems.length) {
 | 
			
		||||
        await Database.removeBulkBookAuthors(req.author.id) // Remove all old BookAuthor
 | 
			
		||||
        await Database.createBulkBookAuthors(bookAuthorsToCreate) // Create all new BookAuthor
 | 
			
		||||
        for (const libraryItem of allItemsWithAuthor) {
 | 
			
		||||
        for (const libraryItem of libraryItems) {
 | 
			
		||||
          await libraryItem.saveMetadataFile()
 | 
			
		||||
        }
 | 
			
		||||
        SocketAuthority.emitter(
 | 
			
		||||
          'items_updated',
 | 
			
		||||
          oldLibraryItems.map((li) => li.toJSONExpanded())
 | 
			
		||||
          libraryItems.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -190,7 +189,7 @@ class AuthorController {
 | 
			
		||||
        const allItemsWithAuthor = await Database.authorModel.getAllLibraryItemsForAuthor(req.author.id)
 | 
			
		||||
 | 
			
		||||
        numBooksForAuthor = allItemsWithAuthor.length
 | 
			
		||||
        const oldLibraryItems = []
 | 
			
		||||
        const libraryItems = []
 | 
			
		||||
        // Update author name on all books
 | 
			
		||||
        for (const libraryItem of allItemsWithAuthor) {
 | 
			
		||||
          libraryItem.media.authors = libraryItem.media.authors.map((au) => {
 | 
			
		||||
@ -199,16 +198,16 @@ class AuthorController {
 | 
			
		||||
            }
 | 
			
		||||
            return au
 | 
			
		||||
          })
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
          oldLibraryItems.push(oldLibraryItem)
 | 
			
		||||
 | 
			
		||||
          libraryItems.push(libraryItem)
 | 
			
		||||
 | 
			
		||||
          await libraryItem.saveMetadataFile()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (oldLibraryItems.length) {
 | 
			
		||||
        if (libraryItems.length) {
 | 
			
		||||
          SocketAuthority.emitter(
 | 
			
		||||
            'items_updated',
 | 
			
		||||
            oldLibraryItems.map((li) => li.toJSONExpanded())
 | 
			
		||||
            libraryItems.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
 | 
			
		||||
@ -221,7 +221,9 @@ class CollectionController {
 | 
			
		||||
   * @param {Response} res
 | 
			
		||||
   */
 | 
			
		||||
  async addBook(req, res) {
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.getOldById(req.body.id)
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.findByPk(req.body.id, {
 | 
			
		||||
      attributes: ['libraryId', 'mediaId']
 | 
			
		||||
    })
 | 
			
		||||
    if (!libraryItem) {
 | 
			
		||||
      return res.status(404).send('Book not found')
 | 
			
		||||
    }
 | 
			
		||||
@ -231,14 +233,14 @@ class CollectionController {
 | 
			
		||||
 | 
			
		||||
    // Check if book is already in collection
 | 
			
		||||
    const collectionBooks = await req.collection.getCollectionBooks()
 | 
			
		||||
    if (collectionBooks.some((cb) => cb.bookId === libraryItem.media.id)) {
 | 
			
		||||
    if (collectionBooks.some((cb) => cb.bookId === libraryItem.mediaId)) {
 | 
			
		||||
      return res.status(400).send('Book already in collection')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create collectionBook record
 | 
			
		||||
    await Database.collectionBookModel.create({
 | 
			
		||||
      collectionId: req.collection.id,
 | 
			
		||||
      bookId: libraryItem.media.id,
 | 
			
		||||
      bookId: libraryItem.mediaId,
 | 
			
		||||
      order: collectionBooks.length + 1
 | 
			
		||||
    })
 | 
			
		||||
    const jsonExpanded = await req.collection.getOldJsonExpanded()
 | 
			
		||||
@ -255,7 +257,9 @@ class CollectionController {
 | 
			
		||||
   * @param {Response} res
 | 
			
		||||
   */
 | 
			
		||||
  async removeBook(req, res) {
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.getOldById(req.params.bookId)
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.findByPk(req.params.bookId, {
 | 
			
		||||
      attributes: ['mediaId']
 | 
			
		||||
    })
 | 
			
		||||
    if (!libraryItem) {
 | 
			
		||||
      return res.sendStatus(404)
 | 
			
		||||
    }
 | 
			
		||||
@ -266,7 +270,7 @@ class CollectionController {
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    let jsonExpanded = null
 | 
			
		||||
    const collectionBookToRemove = collectionBooks.find((cb) => cb.bookId === libraryItem.media.id)
 | 
			
		||||
    const collectionBookToRemove = collectionBooks.find((cb) => cb.bookId === libraryItem.mediaId)
 | 
			
		||||
    if (collectionBookToRemove) {
 | 
			
		||||
      // Remove collection book record
 | 
			
		||||
      await collectionBookToRemove.destroy()
 | 
			
		||||
@ -274,7 +278,7 @@ class CollectionController {
 | 
			
		||||
      // Update order on collection books
 | 
			
		||||
      let order = 1
 | 
			
		||||
      for (const collectionBook of collectionBooks) {
 | 
			
		||||
        if (collectionBook.bookId === libraryItem.media.id) continue
 | 
			
		||||
        if (collectionBook.bookId === libraryItem.mediaId) continue
 | 
			
		||||
        if (collectionBook.order !== order) {
 | 
			
		||||
          await collectionBook.update({
 | 
			
		||||
            order
 | 
			
		||||
 | 
			
		||||
@ -1145,14 +1145,14 @@ class LibraryController {
 | 
			
		||||
      await libraryItem.media.update({
 | 
			
		||||
        narrators: libraryItem.media.narrators
 | 
			
		||||
      })
 | 
			
		||||
      const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
      itemsUpdated.push(oldLibraryItem)
 | 
			
		||||
 | 
			
		||||
      itemsUpdated.push(libraryItem)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (itemsUpdated.length) {
 | 
			
		||||
      SocketAuthority.emitter(
 | 
			
		||||
        'items_updated',
 | 
			
		||||
        itemsUpdated.map((li) => li.toJSONExpanded())
 | 
			
		||||
        itemsUpdated.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1189,14 +1189,14 @@ class LibraryController {
 | 
			
		||||
      await libraryItem.media.update({
 | 
			
		||||
        narrators: libraryItem.media.narrators
 | 
			
		||||
      })
 | 
			
		||||
      const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
      itemsUpdated.push(oldLibraryItem)
 | 
			
		||||
 | 
			
		||||
      itemsUpdated.push(libraryItem)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (itemsUpdated.length) {
 | 
			
		||||
      SocketAuthority.emitter(
 | 
			
		||||
        'items_updated',
 | 
			
		||||
        itemsUpdated.map((li) => li.toJSONExpanded())
 | 
			
		||||
        itemsUpdated.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -551,11 +551,11 @@ class LibraryItemController {
 | 
			
		||||
    const hardDelete = req.query.hard == 1 // Delete files from filesystem
 | 
			
		||||
 | 
			
		||||
    const { libraryItemIds } = req.body
 | 
			
		||||
    if (!libraryItemIds?.length) {
 | 
			
		||||
    if (!libraryItemIds?.length || !Array.isArray(libraryItemIds)) {
 | 
			
		||||
      return res.status(400).send('Invalid request body')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const itemsToDelete = await Database.libraryItemModel.getAllOldLibraryItems({
 | 
			
		||||
    const itemsToDelete = await Database.libraryItemModel.findAllExpandedWhere({
 | 
			
		||||
      id: libraryItemIds
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
@ -566,19 +566,19 @@ class LibraryItemController {
 | 
			
		||||
    const libraryId = itemsToDelete[0].libraryId
 | 
			
		||||
    for (const libraryItem of itemsToDelete) {
 | 
			
		||||
      const libraryItemPath = libraryItem.path
 | 
			
		||||
      Logger.info(`[LibraryItemController] (${hardDelete ? 'Hard' : 'Soft'}) deleting Library Item "${libraryItem.media.metadata.title}" with id "${libraryItem.id}"`)
 | 
			
		||||
      Logger.info(`[LibraryItemController] (${hardDelete ? 'Hard' : 'Soft'}) deleting Library Item "${libraryItem.media.title}" with id "${libraryItem.id}"`)
 | 
			
		||||
      const mediaItemIds = []
 | 
			
		||||
      const seriesIds = []
 | 
			
		||||
      const authorIds = []
 | 
			
		||||
      if (libraryItem.isPodcast) {
 | 
			
		||||
        mediaItemIds.push(...libraryItem.media.episodes.map((ep) => ep.id))
 | 
			
		||||
        mediaItemIds.push(...libraryItem.media.podcastEpisodes.map((ep) => ep.id))
 | 
			
		||||
      } else {
 | 
			
		||||
        mediaItemIds.push(libraryItem.media.id)
 | 
			
		||||
        if (libraryItem.media.metadata.series?.length) {
 | 
			
		||||
          seriesIds.push(...libraryItem.media.metadata.series.map((se) => se.id))
 | 
			
		||||
        if (libraryItem.media.series?.length) {
 | 
			
		||||
          seriesIds.push(...libraryItem.media.series.map((se) => se.id))
 | 
			
		||||
        }
 | 
			
		||||
        if (libraryItem.media.metadata.authors?.length) {
 | 
			
		||||
          authorIds.push(...libraryItem.media.metadata.authors.map((au) => au.id))
 | 
			
		||||
        if (libraryItem.media.authors?.length) {
 | 
			
		||||
          authorIds.push(...libraryItem.media.authors.map((au) => au.id))
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      await this.handleDeleteLibraryItem(libraryItem.id, mediaItemIds)
 | 
			
		||||
@ -623,7 +623,7 @@ class LibraryItemController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get all library items to update
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.getAllOldLibraryItems({
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.findAllExpandedWhere({
 | 
			
		||||
      id: libraryItemIds
 | 
			
		||||
    })
 | 
			
		||||
    if (updatePayloads.length !== libraryItems.length) {
 | 
			
		||||
@ -645,21 +645,23 @@ class LibraryItemController {
 | 
			
		||||
      if (libraryItem.isBook) {
 | 
			
		||||
        if (Array.isArray(mediaPayload.metadata?.series)) {
 | 
			
		||||
          const seriesIdsInUpdate = mediaPayload.metadata.series.map((se) => se.id)
 | 
			
		||||
          const seriesRemoved = libraryItem.media.metadata.series.filter((se) => !seriesIdsInUpdate.includes(se.id))
 | 
			
		||||
          const seriesRemoved = libraryItem.media.series.filter((se) => !seriesIdsInUpdate.includes(se.id))
 | 
			
		||||
          seriesIdsRemoved.push(...seriesRemoved.map((se) => se.id))
 | 
			
		||||
        }
 | 
			
		||||
        if (Array.isArray(mediaPayload.metadata?.authors)) {
 | 
			
		||||
          const authorIdsInUpdate = mediaPayload.metadata.authors.map((au) => au.id)
 | 
			
		||||
          const authorsRemoved = libraryItem.media.metadata.authors.filter((au) => !authorIdsInUpdate.includes(au.id))
 | 
			
		||||
          const authorsRemoved = libraryItem.media.authors.filter((au) => !authorIdsInUpdate.includes(au.id))
 | 
			
		||||
          authorIdsRemoved.push(...authorsRemoved.map((au) => au.id))
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (libraryItem.media.update(mediaPayload)) {
 | 
			
		||||
        Logger.debug(`[LibraryItemController] Updated library item media ${libraryItem.media.metadata.title}`)
 | 
			
		||||
      const hasUpdates = await libraryItem.media.updateFromRequest(mediaPayload)
 | 
			
		||||
      if (hasUpdates) {
 | 
			
		||||
        libraryItem.changed('updatedAt', true)
 | 
			
		||||
        await libraryItem.save()
 | 
			
		||||
 | 
			
		||||
        await Database.updateLibraryItem(libraryItem)
 | 
			
		||||
        SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
 | 
			
		||||
        Logger.debug(`[LibraryItemController] Updated library item media "${libraryItem.media.title}"`)
 | 
			
		||||
        SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
 | 
			
		||||
        itemsUpdated++
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -688,11 +690,11 @@ class LibraryItemController {
 | 
			
		||||
    if (!libraryItemIds.length) {
 | 
			
		||||
      return res.status(403).send('Invalid payload')
 | 
			
		||||
    }
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.getAllOldLibraryItems({
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.findAllExpandedWhere({
 | 
			
		||||
      id: libraryItemIds
 | 
			
		||||
    })
 | 
			
		||||
    res.json({
 | 
			
		||||
      libraryItems: libraryItems.map((li) => li.toJSONExpanded())
 | 
			
		||||
      libraryItems: libraryItems.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -715,7 +717,7 @@ class LibraryItemController {
 | 
			
		||||
      return res.sendStatus(400)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.getAllOldLibraryItems({
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.findAllExpandedWhere({
 | 
			
		||||
      id: req.body.libraryItemIds
 | 
			
		||||
    })
 | 
			
		||||
    if (!libraryItems?.length) {
 | 
			
		||||
@ -737,7 +739,8 @@ class LibraryItemController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (const libraryItem of libraryItems) {
 | 
			
		||||
      const matchResult = await Scanner.quickMatchLibraryItem(this, libraryItem, options)
 | 
			
		||||
      const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
      const matchResult = await Scanner.quickMatchLibraryItem(this, oldLibraryItem, options)
 | 
			
		||||
      if (matchResult.updated) {
 | 
			
		||||
        itemsUpdated++
 | 
			
		||||
      } else if (matchResult.warning) {
 | 
			
		||||
 | 
			
		||||
@ -66,7 +66,7 @@ class MeController {
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.findByPk(req.params.libraryItemId)
 | 
			
		||||
    const episode = await Database.podcastEpisodeModel.findByPk(req.params.episodeId)
 | 
			
		||||
 | 
			
		||||
    if (!libraryItem || (libraryItem.mediaType === 'podcast' && !episode)) {
 | 
			
		||||
    if (!libraryItem || (libraryItem.isPodcast && !episode)) {
 | 
			
		||||
      Logger.error(`[MeController] Media item not found for library item id "${req.params.libraryItemId}"`)
 | 
			
		||||
      return res.sendStatus(404)
 | 
			
		||||
    }
 | 
			
		||||
@ -296,7 +296,7 @@ class MeController {
 | 
			
		||||
    const mediaProgressesInProgress = req.user.mediaProgresses.filter((mp) => !mp.isFinished && (mp.currentTime > 0 || mp.ebookProgress > 0))
 | 
			
		||||
 | 
			
		||||
    const libraryItemsIds = [...new Set(mediaProgressesInProgress.map((mp) => mp.extraData?.libraryItemId).filter((id) => id))]
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.getAllOldLibraryItems({ id: libraryItemsIds })
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.findAllExpandedWhere({ id: libraryItemsIds })
 | 
			
		||||
 | 
			
		||||
    let itemsInProgress = []
 | 
			
		||||
 | 
			
		||||
@ -304,19 +304,19 @@ class MeController {
 | 
			
		||||
      const oldMediaProgress = mediaProgress.getOldMediaProgress()
 | 
			
		||||
      const libraryItem = libraryItems.find((li) => li.id === oldMediaProgress.libraryItemId)
 | 
			
		||||
      if (libraryItem) {
 | 
			
		||||
        if (oldMediaProgress.episodeId && libraryItem.mediaType === 'podcast') {
 | 
			
		||||
          const episode = libraryItem.media.episodes.find((ep) => ep.id === oldMediaProgress.episodeId)
 | 
			
		||||
        if (oldMediaProgress.episodeId && libraryItem.isPodcast) {
 | 
			
		||||
          const episode = libraryItem.media.podcastEpisodes.find((ep) => ep.id === oldMediaProgress.episodeId)
 | 
			
		||||
          if (episode) {
 | 
			
		||||
            const libraryItemWithEpisode = {
 | 
			
		||||
              ...libraryItem.toJSONMinified(),
 | 
			
		||||
              recentEpisode: episode.toJSON(),
 | 
			
		||||
              ...libraryItem.toOldJSONMinified(),
 | 
			
		||||
              recentEpisode: episode.toOldJSON(libraryItem.id),
 | 
			
		||||
              progressLastUpdate: oldMediaProgress.lastUpdate
 | 
			
		||||
            }
 | 
			
		||||
            itemsInProgress.push(libraryItemWithEpisode)
 | 
			
		||||
          }
 | 
			
		||||
        } else if (!oldMediaProgress.episodeId) {
 | 
			
		||||
          itemsInProgress.push({
 | 
			
		||||
            ...libraryItem.toJSONMinified(),
 | 
			
		||||
            ...libraryItem.toOldJSONMinified(),
 | 
			
		||||
            progressLastUpdate: oldMediaProgress.lastUpdate
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -342,8 +342,8 @@ class MiscController {
 | 
			
		||||
          tags: libraryItem.media.tags
 | 
			
		||||
        })
 | 
			
		||||
        await libraryItem.saveMetadataFile()
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
        SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
 | 
			
		||||
 | 
			
		||||
        SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
 | 
			
		||||
        numItemsUpdated++
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -385,8 +385,8 @@ class MiscController {
 | 
			
		||||
        tags: libraryItem.media.tags
 | 
			
		||||
      })
 | 
			
		||||
      await libraryItem.saveMetadataFile()
 | 
			
		||||
      const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
      SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
 | 
			
		||||
 | 
			
		||||
      SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
 | 
			
		||||
      numItemsUpdated++
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -480,8 +480,8 @@ class MiscController {
 | 
			
		||||
          genres: libraryItem.media.genres
 | 
			
		||||
        })
 | 
			
		||||
        await libraryItem.saveMetadataFile()
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
        SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
 | 
			
		||||
 | 
			
		||||
        SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
 | 
			
		||||
        numItemsUpdated++
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -523,8 +523,8 @@ class MiscController {
 | 
			
		||||
        genres: libraryItem.media.genres
 | 
			
		||||
      })
 | 
			
		||||
      await libraryItem.saveMetadataFile()
 | 
			
		||||
      const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
      SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
 | 
			
		||||
 | 
			
		||||
      SocketAuthority.emitter('item_updated', libraryItem.toOldJSONExpanded())
 | 
			
		||||
      numItemsUpdated++
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -276,7 +276,7 @@ class PlaylistController {
 | 
			
		||||
      return res.status(400).send('Request body has no libraryItemId')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.getOldById(itemToAdd.libraryItemId)
 | 
			
		||||
    const libraryItem = await Database.libraryItemModel.getExpandedById(itemToAdd.libraryItemId)
 | 
			
		||||
    if (!libraryItem) {
 | 
			
		||||
      return res.status(400).send('Library item not found')
 | 
			
		||||
    }
 | 
			
		||||
@ -286,7 +286,7 @@ class PlaylistController {
 | 
			
		||||
    if ((itemToAdd.episodeId && !libraryItem.isPodcast) || (libraryItem.isPodcast && !itemToAdd.episodeId)) {
 | 
			
		||||
      return res.status(400).send('Invalid item to add for this library type')
 | 
			
		||||
    }
 | 
			
		||||
    if (itemToAdd.episodeId && !libraryItem.media.checkHasEpisode(itemToAdd.episodeId)) {
 | 
			
		||||
    if (itemToAdd.episodeId && !libraryItem.media.podcastEpisodes.some((pe) => pe.id === itemToAdd.episodeId)) {
 | 
			
		||||
      return res.status(400).send('Episode not found in library item')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -308,17 +308,17 @@ class PlaylistController {
 | 
			
		||||
 | 
			
		||||
    // Add the new item to to the old json expanded to prevent having to fully reload the playlist media items
 | 
			
		||||
    if (itemToAdd.episodeId) {
 | 
			
		||||
      const episode = libraryItem.media.episodes.find((ep) => ep.id === itemToAdd.episodeId)
 | 
			
		||||
      const episode = libraryItem.media.podcastEpisodes.find((ep) => ep.id === itemToAdd.episodeId)
 | 
			
		||||
      jsonExpanded.items.push({
 | 
			
		||||
        episodeId: itemToAdd.episodeId,
 | 
			
		||||
        episode: episode.toJSONExpanded(),
 | 
			
		||||
        episode: episode.toOldJSONExpanded(libraryItem.id),
 | 
			
		||||
        libraryItemId: libraryItem.id,
 | 
			
		||||
        libraryItem: libraryItem.toJSONMinified()
 | 
			
		||||
        libraryItem: libraryItem.toOldJSONMinified()
 | 
			
		||||
      })
 | 
			
		||||
    } else {
 | 
			
		||||
      jsonExpanded.items.push({
 | 
			
		||||
        libraryItemId: libraryItem.id,
 | 
			
		||||
        libraryItem: libraryItem.toJSONExpanded()
 | 
			
		||||
        libraryItem: libraryItem.toOldJSONExpanded()
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -388,8 +388,8 @@ class PlaylistController {
 | 
			
		||||
    // Find all library items
 | 
			
		||||
    const libraryItemIds = new Set(req.body.items.map((i) => i.libraryItemId).filter((i) => i))
 | 
			
		||||
 | 
			
		||||
    const oldLibraryItems = await Database.libraryItemModel.getAllOldLibraryItems({ id: Array.from(libraryItemIds) })
 | 
			
		||||
    if (oldLibraryItems.length !== libraryItemIds.size) {
 | 
			
		||||
    const libraryItems = await Database.libraryItemModel.findAllExpandedWhere({ id: Array.from(libraryItemIds) })
 | 
			
		||||
    if (libraryItems.length !== libraryItemIds.size) {
 | 
			
		||||
      return res.status(400).send('Invalid request body items')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -401,7 +401,7 @@ class PlaylistController {
 | 
			
		||||
    // Setup array of playlistMediaItem records to add
 | 
			
		||||
    let order = req.playlist.playlistMediaItems.length + 1
 | 
			
		||||
    for (const item of req.body.items) {
 | 
			
		||||
      const libraryItem = oldLibraryItems.find((li) => li.id === item.libraryItemId)
 | 
			
		||||
      const libraryItem = libraryItems.find((li) => li.id === item.libraryItemId)
 | 
			
		||||
 | 
			
		||||
      const mediaItemId = item.episodeId || libraryItem.media.id
 | 
			
		||||
      if (req.playlist.playlistMediaItems.some((pmi) => pmi.mediaItemId === mediaItemId)) {
 | 
			
		||||
@ -417,17 +417,17 @@ class PlaylistController {
 | 
			
		||||
 | 
			
		||||
        // Add the new item to to the old json expanded to prevent having to fully reload the playlist media items
 | 
			
		||||
        if (item.episodeId) {
 | 
			
		||||
          const episode = libraryItem.media.episodes.find((ep) => ep.id === item.episodeId)
 | 
			
		||||
          const episode = libraryItem.media.podcastEpisodes.find((ep) => ep.id === item.episodeId)
 | 
			
		||||
          jsonExpanded.items.push({
 | 
			
		||||
            episodeId: item.episodeId,
 | 
			
		||||
            episode: episode.toJSONExpanded(),
 | 
			
		||||
            episode: episode.toOldJSONExpanded(libraryItem.id),
 | 
			
		||||
            libraryItemId: libraryItem.id,
 | 
			
		||||
            libraryItem: libraryItem.toJSONMinified()
 | 
			
		||||
            libraryItem: libraryItem.toOldJSONMinified()
 | 
			
		||||
          })
 | 
			
		||||
        } else {
 | 
			
		||||
          jsonExpanded.items.push({
 | 
			
		||||
            libraryItemId: libraryItem.id,
 | 
			
		||||
            libraryItem: libraryItem.toJSONExpanded()
 | 
			
		||||
            libraryItem: libraryItem.toOldJSONExpanded()
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -296,9 +296,9 @@ class PodcastManager {
 | 
			
		||||
 | 
			
		||||
    Logger.info(`[PodcastManager] runEpisodeCheck: "${libraryItem.media.title}" | Last check: ${new Date(lastEpisodeCheck)} | ${latestEpisodePublishedAt ? `Latest episode pubDate: ${new Date(latestEpisodePublishedAt)}` : 'No latest episode'}`)
 | 
			
		||||
 | 
			
		||||
    // Use latest episode pubDate if exists OR fallback to using lastEpisodeCheckDate
 | 
			
		||||
    //    lastEpisodeCheckDate will be the current time when adding a new podcast
 | 
			
		||||
    const dateToCheckForEpisodesAfter = latestEpisodePublishedAt || lastEpisodeCheckDate
 | 
			
		||||
    // Use latest episode pubDate if exists OR fallback to using lastEpisodeCheck
 | 
			
		||||
    //    lastEpisodeCheck will be the current time when adding a new podcast
 | 
			
		||||
    const dateToCheckForEpisodesAfter = latestEpisodePublishedAt || lastEpisodeCheck
 | 
			
		||||
    Logger.debug(`[PodcastManager] runEpisodeCheck: "${libraryItem.media.title}" checking for episodes after ${new Date(dateToCheckForEpisodesAfter)}`)
 | 
			
		||||
 | 
			
		||||
    const newEpisodes = await this.checkPodcastForNewEpisodes(libraryItem, dateToCheckForEpisodesAfter, libraryItem.media.maxNewEpisodesToDownload)
 | 
			
		||||
 | 
			
		||||
@ -282,7 +282,7 @@ class Collection extends Model {
 | 
			
		||||
      const libraryItem = book.libraryItem
 | 
			
		||||
      delete book.libraryItem
 | 
			
		||||
      libraryItem.media = book
 | 
			
		||||
      return this.sequelize.models.libraryItem.getOldLibraryItem(libraryItem).toJSONExpanded()
 | 
			
		||||
      return libraryItem.toOldJSONExpanded()
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return json
 | 
			
		||||
 | 
			
		||||
@ -122,45 +122,6 @@ class LibraryItem extends Model {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @param {import('sequelize').WhereOptions} [where]
 | 
			
		||||
   * @returns {Array<objects.LibraryItem>} old library items
 | 
			
		||||
   */
 | 
			
		||||
  static async getAllOldLibraryItems(where = null) {
 | 
			
		||||
    let libraryItems = await this.findAll({
 | 
			
		||||
      where,
 | 
			
		||||
      include: [
 | 
			
		||||
        {
 | 
			
		||||
          model: this.sequelize.models.book,
 | 
			
		||||
          include: [
 | 
			
		||||
            {
 | 
			
		||||
              model: this.sequelize.models.author,
 | 
			
		||||
              through: {
 | 
			
		||||
                attributes: []
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              model: this.sequelize.models.series,
 | 
			
		||||
              through: {
 | 
			
		||||
                attributes: ['sequence']
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          model: this.sequelize.models.podcast,
 | 
			
		||||
          include: [
 | 
			
		||||
            {
 | 
			
		||||
              model: this.sequelize.models.podcastEpisode
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    })
 | 
			
		||||
    return libraryItems.map((ti) => this.getOldLibraryItem(ti))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Convert an expanded LibraryItem into an old library item
 | 
			
		||||
   *
 | 
			
		||||
@ -448,6 +409,47 @@ class LibraryItem extends Model {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @param {import('sequelize').WhereOptions} where
 | 
			
		||||
   * @returns {Promise<LibraryItemExpanded[]>}
 | 
			
		||||
   */
 | 
			
		||||
  static async findAllExpandedWhere(where = null) {
 | 
			
		||||
    return this.findAll({
 | 
			
		||||
      where,
 | 
			
		||||
      include: [
 | 
			
		||||
        {
 | 
			
		||||
          model: this.sequelize.models.book,
 | 
			
		||||
          include: [
 | 
			
		||||
            {
 | 
			
		||||
              model: this.sequelize.models.author,
 | 
			
		||||
              through: {
 | 
			
		||||
                attributes: []
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              model: this.sequelize.models.series,
 | 
			
		||||
              through: {
 | 
			
		||||
                attributes: ['sequence']
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          model: this.sequelize.models.podcast,
 | 
			
		||||
          include: {
 | 
			
		||||
            model: this.sequelize.models.podcastEpisode
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      order: [
 | 
			
		||||
        // Ensure author & series stay in the same order
 | 
			
		||||
        [this.sequelize.models.book, this.sequelize.models.author, this.sequelize.models.bookAuthor, 'createdAt', 'ASC'],
 | 
			
		||||
        [this.sequelize.models.book, this.sequelize.models.series, 'bookSeries', 'createdAt', 'ASC']
 | 
			
		||||
      ]
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string} libraryItemId
 | 
			
		||||
@ -611,7 +613,7 @@ class LibraryItem extends Model {
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      libraryItems: libraryItems.map((li) => {
 | 
			
		||||
        const oldLibraryItem = this.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
        const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
        if (li.collapsedSeries) {
 | 
			
		||||
          oldLibraryItem.collapsedSeries = li.collapsedSeries
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -357,7 +357,7 @@ class Playlist extends Model {
 | 
			
		||||
        libraryItem.media = pmi.mediaItem
 | 
			
		||||
        return {
 | 
			
		||||
          libraryItemId: libraryItem.id,
 | 
			
		||||
          libraryItem: this.sequelize.models.libraryItem.getOldLibraryItem(libraryItem).toJSONExpanded()
 | 
			
		||||
          libraryItem: libraryItem.toOldJSONExpanded()
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -368,7 +368,7 @@ class Playlist extends Model {
 | 
			
		||||
        episodeId: pmi.mediaItemId,
 | 
			
		||||
        episode: pmi.mediaItem.toOldJSONExpanded(libraryItem.id),
 | 
			
		||||
        libraryItemId: libraryItem.id,
 | 
			
		||||
        libraryItem: this.sequelize.models.libraryItem.getOldLibraryItem(libraryItem).toJSONMinified()
 | 
			
		||||
        libraryItem: libraryItem.toOldJSONMinified()
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -166,10 +166,6 @@ class Podcast {
 | 
			
		||||
    return true
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  checkHasEpisode(episodeId) {
 | 
			
		||||
    return this.episodes.some((ep) => ep.id === episodeId)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getEpisode(episodeId) {
 | 
			
		||||
    if (!episodeId) return null
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,7 @@ class LibraryItemScanner {
 | 
			
		||||
 | 
			
		||||
    const { libraryItem: expandedLibraryItem, wasUpdated } = await this.rescanLibraryItemMedia(libraryItem, libraryItemScanData, library.settings, scanLogger)
 | 
			
		||||
    if (libraryItemDataUpdated || wasUpdated) {
 | 
			
		||||
      const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(expandedLibraryItem)
 | 
			
		||||
      SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
 | 
			
		||||
      SocketAuthority.emitter('item_updated', expandedLibraryItem.toOldJSONExpanded())
 | 
			
		||||
 | 
			
		||||
      await this.checkAuthorsAndSeriesRemovedFromBooks(library.id, scanLogger)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -167,7 +167,7 @@ class LibraryScanner {
 | 
			
		||||
    if (this.shouldCancelScan(libraryScan)) return true
 | 
			
		||||
 | 
			
		||||
    const libraryItemIdsMissing = []
 | 
			
		||||
    let oldLibraryItemsUpdated = []
 | 
			
		||||
    let libraryItemsUpdated = []
 | 
			
		||||
    for (const existingLibraryItem of existingLibraryItems) {
 | 
			
		||||
      // First try to find matching library item with exact file path
 | 
			
		||||
      let libraryItemData = libraryItemDataFound.find((lid) => lid.path === existingLibraryItem.path)
 | 
			
		||||
@ -190,11 +190,11 @@ class LibraryScanner {
 | 
			
		||||
            libraryItemIdsMissing.push(existingLibraryItem.id)
 | 
			
		||||
 | 
			
		||||
            // TODO: Temporary while using old model to socket emit
 | 
			
		||||
            const oldLibraryItem = await Database.libraryItemModel.getOldById(existingLibraryItem.id)
 | 
			
		||||
            if (oldLibraryItem) {
 | 
			
		||||
              oldLibraryItem.isMissing = true
 | 
			
		||||
              oldLibraryItem.updatedAt = Date.now()
 | 
			
		||||
              oldLibraryItemsUpdated.push(oldLibraryItem)
 | 
			
		||||
            const libraryItem = await Database.libraryItemModel.getExpandedById(existingLibraryItem.id)
 | 
			
		||||
            if (libraryItem) {
 | 
			
		||||
              libraryItem.isMissing = true
 | 
			
		||||
              await libraryItem.save()
 | 
			
		||||
              libraryItemsUpdated.push(libraryItem)
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
@ -206,16 +206,15 @@ class LibraryScanner {
 | 
			
		||||
            const { libraryItem, wasUpdated } = await LibraryItemScanner.rescanLibraryItemMedia(existingLibraryItem, libraryItemData, libraryScan.library.settings, libraryScan)
 | 
			
		||||
            if (!forceRescan || wasUpdated) {
 | 
			
		||||
              libraryScan.resultsUpdated++
 | 
			
		||||
              const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
 | 
			
		||||
              oldLibraryItemsUpdated.push(oldLibraryItem)
 | 
			
		||||
              libraryItemsUpdated.push(libraryItem)
 | 
			
		||||
            } else {
 | 
			
		||||
              libraryScan.addLog(LogLevel.DEBUG, `Library item "${existingLibraryItem.relPath}" is up-to-date`)
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            libraryScan.resultsUpdated++
 | 
			
		||||
            // TODO: Temporary while using old model to socket emit
 | 
			
		||||
            const oldLibraryItem = await Database.libraryItemModel.getOldById(existingLibraryItem.id)
 | 
			
		||||
            oldLibraryItemsUpdated.push(oldLibraryItem)
 | 
			
		||||
            const libraryItem = await Database.libraryItemModel.getExpandedById(existingLibraryItem.id)
 | 
			
		||||
            libraryItemsUpdated.push(libraryItem)
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          libraryScan.addLog(LogLevel.DEBUG, `Library item "${existingLibraryItem.relPath}" is up-to-date`)
 | 
			
		||||
@ -223,23 +222,23 @@ class LibraryScanner {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Emit item updates in chunks of 10 to client
 | 
			
		||||
      if (oldLibraryItemsUpdated.length === 10) {
 | 
			
		||||
      if (libraryItemsUpdated.length === 10) {
 | 
			
		||||
        // TODO: Should only emit to clients where library item is accessible
 | 
			
		||||
        SocketAuthority.emitter(
 | 
			
		||||
          'items_updated',
 | 
			
		||||
          oldLibraryItemsUpdated.map((li) => li.toJSONExpanded())
 | 
			
		||||
          libraryItemsUpdated.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
        )
 | 
			
		||||
        oldLibraryItemsUpdated = []
 | 
			
		||||
        libraryItemsUpdated = []
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this.shouldCancelScan(libraryScan)) return true
 | 
			
		||||
    }
 | 
			
		||||
    // Emit item updates to client
 | 
			
		||||
    if (oldLibraryItemsUpdated.length) {
 | 
			
		||||
    if (libraryItemsUpdated.length) {
 | 
			
		||||
      // TODO: Should only emit to clients where library item is accessible
 | 
			
		||||
      SocketAuthority.emitter(
 | 
			
		||||
        'items_updated',
 | 
			
		||||
        oldLibraryItemsUpdated.map((li) => li.toJSONExpanded())
 | 
			
		||||
        libraryItemsUpdated.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -267,34 +266,33 @@ class LibraryScanner {
 | 
			
		||||
 | 
			
		||||
    // Add new library items
 | 
			
		||||
    if (libraryItemDataFound.length) {
 | 
			
		||||
      let newOldLibraryItems = []
 | 
			
		||||
      let newLibraryItems = []
 | 
			
		||||
      for (const libraryItemData of libraryItemDataFound) {
 | 
			
		||||
        const newLibraryItem = await LibraryItemScanner.scanNewLibraryItem(libraryItemData, libraryScan.library.settings, libraryScan)
 | 
			
		||||
        if (newLibraryItem) {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(newLibraryItem)
 | 
			
		||||
          newOldLibraryItems.push(oldLibraryItem)
 | 
			
		||||
          newLibraryItems.push(newLibraryItem)
 | 
			
		||||
 | 
			
		||||
          libraryScan.resultsAdded++
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Emit new items in chunks of 10 to client
 | 
			
		||||
        if (newOldLibraryItems.length === 10) {
 | 
			
		||||
        if (newLibraryItems.length === 10) {
 | 
			
		||||
          // TODO: Should only emit to clients where library item is accessible
 | 
			
		||||
          SocketAuthority.emitter(
 | 
			
		||||
            'items_added',
 | 
			
		||||
            newOldLibraryItems.map((li) => li.toJSONExpanded())
 | 
			
		||||
            newLibraryItems.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
          )
 | 
			
		||||
          newOldLibraryItems = []
 | 
			
		||||
          newLibraryItems = []
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.shouldCancelScan(libraryScan)) return true
 | 
			
		||||
      }
 | 
			
		||||
      // Emit new items to client
 | 
			
		||||
      if (newOldLibraryItems.length) {
 | 
			
		||||
      if (newLibraryItems.length) {
 | 
			
		||||
        // TODO: Should only emit to clients where library item is accessible
 | 
			
		||||
        SocketAuthority.emitter(
 | 
			
		||||
          'items_added',
 | 
			
		||||
          newOldLibraryItems.map((li) => li.toJSONExpanded())
 | 
			
		||||
          newLibraryItems.map((li) => li.toOldJSONExpanded())
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -645,8 +643,7 @@ class LibraryScanner {
 | 
			
		||||
      const isSingleMediaItem = isSingleMediaFile(fileUpdateGroup, itemDir)
 | 
			
		||||
      const newLibraryItem = await LibraryItemScanner.scanPotentialNewLibraryItem(fullPath, library, folder, isSingleMediaItem)
 | 
			
		||||
      if (newLibraryItem) {
 | 
			
		||||
        const oldNewLibraryItem = Database.libraryItemModel.getOldLibraryItem(newLibraryItem)
 | 
			
		||||
        SocketAuthority.emitter('item_added', oldNewLibraryItem.toJSONExpanded())
 | 
			
		||||
        SocketAuthority.emitter('item_added', newLibraryItem.toOldJSONExpanded())
 | 
			
		||||
      }
 | 
			
		||||
      itemGroupingResults[itemDir] = newLibraryItem ? ScanResult.ADDED : ScanResult.NOTHING
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1200,7 +1200,7 @@ async function migrationPatchNewColumns(queryInterface) {
 | 
			
		||||
 */
 | 
			
		||||
async function handleOldLibraryItems(ctx) {
 | 
			
		||||
  const oldLibraryItems = await oldDbFiles.loadOldData('libraryItems')
 | 
			
		||||
  const libraryItems = await ctx.models.libraryItem.getAllOldLibraryItems()
 | 
			
		||||
  const libraryItems = (await ctx.models.libraryItem.findAllExpandedWhere()).map((li) => ctx.models.libraryItem.getOldLibraryItem(li))
 | 
			
		||||
 | 
			
		||||
  const bulkUpdateItems = []
 | 
			
		||||
  const bulkUpdateEpisodes = []
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ module.exports = {
 | 
			
		||||
   * @param {string} libraryId
 | 
			
		||||
   * @param {import('../../models/User')} user
 | 
			
		||||
   * @param {object} options
 | 
			
		||||
   * @returns {object} { libraryItems:LibraryItem[], count:number }
 | 
			
		||||
   * @returns {Promise<{ libraryItems:import('../../models/LibraryItem')[], count:number }>}
 | 
			
		||||
   */
 | 
			
		||||
  async getFilteredLibraryItems(libraryId, user, options) {
 | 
			
		||||
    const { filterBy, sortBy, sortDesc, limit, offset, collapseseries, include, mediaType } = options
 | 
			
		||||
@ -52,7 +52,7 @@ module.exports = {
 | 
			
		||||
      const { libraryItems, count } = await libraryItemsBookFilters.getFilteredLibraryItems(library.id, user, 'progress', 'in-progress', 'progress', true, false, include, limit, 0, true)
 | 
			
		||||
      return {
 | 
			
		||||
        items: libraryItems.map((li) => {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
          if (li.rssFeed) {
 | 
			
		||||
            oldLibraryItem.rssFeed = li.rssFeed.toOldJSONMinified()
 | 
			
		||||
          }
 | 
			
		||||
@ -68,7 +68,7 @@ module.exports = {
 | 
			
		||||
      return {
 | 
			
		||||
        count,
 | 
			
		||||
        items: libraryItems.map((li) => {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
          oldLibraryItem.recentEpisode = li.recentEpisode
 | 
			
		||||
          return oldLibraryItem
 | 
			
		||||
        })
 | 
			
		||||
@ -89,7 +89,7 @@ module.exports = {
 | 
			
		||||
      const { libraryItems, count } = await libraryItemsBookFilters.getFilteredLibraryItems(library.id, user, 'recent', null, 'addedAt', true, false, include, limit, 0)
 | 
			
		||||
      return {
 | 
			
		||||
        libraryItems: libraryItems.map((li) => {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
          if (li.rssFeed) {
 | 
			
		||||
            oldLibraryItem.rssFeed = li.rssFeed.toOldJSONMinified()
 | 
			
		||||
          }
 | 
			
		||||
@ -107,7 +107,7 @@ module.exports = {
 | 
			
		||||
      const { libraryItems, count } = await libraryItemsPodcastFilters.getFilteredLibraryItems(library.id, user, 'recent', null, 'addedAt', true, include, limit, 0)
 | 
			
		||||
      return {
 | 
			
		||||
        libraryItems: libraryItems.map((li) => {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
          if (li.rssFeed) {
 | 
			
		||||
            oldLibraryItem.rssFeed = li.rssFeed.toOldJSONMinified()
 | 
			
		||||
          }
 | 
			
		||||
@ -136,7 +136,7 @@ module.exports = {
 | 
			
		||||
    const { libraryItems, count } = await libraryItemsBookFilters.getContinueSeriesLibraryItems(library, user, include, limit, 0)
 | 
			
		||||
    return {
 | 
			
		||||
      libraryItems: libraryItems.map((li) => {
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
        const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
        if (li.rssFeed) {
 | 
			
		||||
          oldLibraryItem.rssFeed = li.rssFeed.toOldJSONMinified()
 | 
			
		||||
        }
 | 
			
		||||
@ -166,7 +166,7 @@ module.exports = {
 | 
			
		||||
      const { libraryItems, count } = await libraryItemsBookFilters.getFilteredLibraryItems(library.id, user, 'progress', 'finished', 'progress', true, false, include, limit, 0)
 | 
			
		||||
      return {
 | 
			
		||||
        items: libraryItems.map((li) => {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
          if (li.rssFeed) {
 | 
			
		||||
            oldLibraryItem.rssFeed = li.rssFeed.toOldJSONMinified()
 | 
			
		||||
          }
 | 
			
		||||
@ -182,7 +182,7 @@ module.exports = {
 | 
			
		||||
      return {
 | 
			
		||||
        count,
 | 
			
		||||
        items: libraryItems.map((li) => {
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
          oldLibraryItem.recentEpisode = li.recentEpisode
 | 
			
		||||
          return oldLibraryItem
 | 
			
		||||
        })
 | 
			
		||||
@ -293,15 +293,17 @@ module.exports = {
 | 
			
		||||
      })
 | 
			
		||||
      oldSeries.books = s.bookSeries
 | 
			
		||||
        .map((bs) => {
 | 
			
		||||
          const libraryItem = bs.book.libraryItem?.toJSON()
 | 
			
		||||
          const libraryItem = bs.book.libraryItem
 | 
			
		||||
          if (!libraryItem) {
 | 
			
		||||
            Logger.warn(`Book series book has no libraryItem`, bs, bs.book, 'series=', series)
 | 
			
		||||
            return null
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          delete bs.book.libraryItem
 | 
			
		||||
          bs.book.authors = [] // Not needed
 | 
			
		||||
          bs.book.series = [] // Not needed
 | 
			
		||||
          libraryItem.media = bs.book
 | 
			
		||||
          const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem).toJSONMinified()
 | 
			
		||||
          const oldLibraryItem = libraryItem.toOldJSONMinified()
 | 
			
		||||
          return oldLibraryItem
 | 
			
		||||
        })
 | 
			
		||||
        .filter((b) => b)
 | 
			
		||||
@ -373,7 +375,7 @@ module.exports = {
 | 
			
		||||
    const { libraryItems, count } = await libraryItemsBookFilters.getDiscoverLibraryItems(library.id, user, include, limit)
 | 
			
		||||
    return {
 | 
			
		||||
      libraryItems: libraryItems.map((li) => {
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
        const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
        if (li.rssFeed) {
 | 
			
		||||
          oldLibraryItem.rssFeed = li.rssFeed.toOldJSONMinified()
 | 
			
		||||
        }
 | 
			
		||||
@ -400,7 +402,7 @@ module.exports = {
 | 
			
		||||
    return {
 | 
			
		||||
      count,
 | 
			
		||||
      libraryItems: libraryItems.map((li) => {
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(li).toJSONMinified()
 | 
			
		||||
        const oldLibraryItem = li.toOldJSONMinified()
 | 
			
		||||
        oldLibraryItem.recentEpisode = li.recentEpisode
 | 
			
		||||
        return oldLibraryItem
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
@ -349,7 +349,7 @@ module.exports = {
 | 
			
		||||
   * @param {number} limit
 | 
			
		||||
   * @param {number} offset
 | 
			
		||||
   * @param {boolean} isHomePage for home page shelves
 | 
			
		||||
   * @returns {object} { libraryItems:LibraryItem[], count:number }
 | 
			
		||||
   * @returns {{ libraryItems: import('../../models/LibraryItem')[], count: number }}
 | 
			
		||||
   */
 | 
			
		||||
  async getFilteredLibraryItems(libraryId, user, filterGroup, filterValue, sortBy, sortDesc, collapseseries, include, limit, offset, isHomePage = false) {
 | 
			
		||||
    // TODO: Handle collapse sub-series
 | 
			
		||||
@ -583,8 +583,8 @@ module.exports = {
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const libraryItems = books.map((bookExpanded) => {
 | 
			
		||||
      const libraryItem = bookExpanded.libraryItem.toJSON()
 | 
			
		||||
      const book = bookExpanded.toJSON()
 | 
			
		||||
      const libraryItem = bookExpanded.libraryItem
 | 
			
		||||
      const book = bookExpanded
 | 
			
		||||
 | 
			
		||||
      if (filterGroup === 'series' && book.series?.length) {
 | 
			
		||||
        // For showing sequence on book cover when filtering for series
 | 
			
		||||
@ -596,27 +596,37 @@ module.exports = {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      delete book.libraryItem
 | 
			
		||||
      delete book.authors
 | 
			
		||||
      delete book.series
 | 
			
		||||
 | 
			
		||||
      book.series =
 | 
			
		||||
        book.bookSeries?.map((bs) => {
 | 
			
		||||
          const series = bs.series
 | 
			
		||||
          delete bs.series
 | 
			
		||||
          series.bookSeries = bs
 | 
			
		||||
          return series
 | 
			
		||||
        }) || []
 | 
			
		||||
      delete book.bookSeries
 | 
			
		||||
 | 
			
		||||
      book.authors = book.bookAuthors?.map((ba) => ba.author) || []
 | 
			
		||||
      delete book.bookAuthors
 | 
			
		||||
 | 
			
		||||
      // For showing details of collapsed series
 | 
			
		||||
      if (collapseseries && book.bookSeries?.length) {
 | 
			
		||||
        const collapsedSeries = book.bookSeries.find((bs) => collapseSeriesBookSeries.some((cbs) => cbs.id === bs.id))
 | 
			
		||||
      if (collapseseries && book.series?.length) {
 | 
			
		||||
        const collapsedSeries = book.series.find((bs) => collapseSeriesBookSeries.some((cbs) => cbs.id === bs.bookSeries.id))
 | 
			
		||||
        if (collapsedSeries) {
 | 
			
		||||
          const collapseSeriesObj = collapseSeriesBookSeries.find((csbs) => csbs.id === collapsedSeries.id)
 | 
			
		||||
          const collapseSeriesObj = collapseSeriesBookSeries.find((csbs) => csbs.id === collapsedSeries.bookSeries.id)
 | 
			
		||||
          libraryItem.collapsedSeries = {
 | 
			
		||||
            id: collapsedSeries.series.id,
 | 
			
		||||
            name: collapsedSeries.series.name,
 | 
			
		||||
            nameIgnorePrefix: collapsedSeries.series.nameIgnorePrefix,
 | 
			
		||||
            sequence: collapsedSeries.sequence,
 | 
			
		||||
            id: collapsedSeries.id,
 | 
			
		||||
            name: collapsedSeries.name,
 | 
			
		||||
            nameIgnorePrefix: collapsedSeries.nameIgnorePrefix,
 | 
			
		||||
            sequence: collapsedSeries.bookSeries.sequence,
 | 
			
		||||
            numBooks: collapseSeriesObj?.numBooks || 0,
 | 
			
		||||
            libraryItemIds: collapseSeriesObj?.libraryItemIds || []
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (bookExpanded.libraryItem.feeds?.length) {
 | 
			
		||||
        libraryItem.rssFeed = bookExpanded.libraryItem.feeds[0]
 | 
			
		||||
      if (libraryItem.feeds?.length) {
 | 
			
		||||
        libraryItem.rssFeed = libraryItem.feeds[0]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (includeMediaItemShare) {
 | 
			
		||||
@ -646,7 +656,7 @@ module.exports = {
 | 
			
		||||
   * @param {string[]} include
 | 
			
		||||
   * @param {number} limit
 | 
			
		||||
   * @param {number} offset
 | 
			
		||||
   * @returns {{ libraryItems:import('../../models/LibraryItem')[], count:number }}
 | 
			
		||||
   * @returns {Promise<{ libraryItems:import('../../models/LibraryItem')[], count:number }>}
 | 
			
		||||
   */
 | 
			
		||||
  async getContinueSeriesLibraryItems(library, user, include, limit, offset) {
 | 
			
		||||
    const libraryId = library.id
 | 
			
		||||
@ -758,16 +768,19 @@ module.exports = {
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const libraryItem = s.bookSeries[bookIndex].book.libraryItem.toJSON()
 | 
			
		||||
        const book = s.bookSeries[bookIndex].book.toJSON()
 | 
			
		||||
        const libraryItem = s.bookSeries[bookIndex].book.libraryItem
 | 
			
		||||
        const book = s.bookSeries[bookIndex].book
 | 
			
		||||
        delete book.libraryItem
 | 
			
		||||
 | 
			
		||||
        book.series = []
 | 
			
		||||
 | 
			
		||||
        libraryItem.series = {
 | 
			
		||||
          id: s.id,
 | 
			
		||||
          name: s.name,
 | 
			
		||||
          sequence: s.bookSeries[bookIndex].sequence
 | 
			
		||||
        }
 | 
			
		||||
        if (s.bookSeries[bookIndex].book.libraryItem.feeds?.length) {
 | 
			
		||||
          libraryItem.rssFeed = s.bookSeries[bookIndex].book.libraryItem.feeds[0]
 | 
			
		||||
        if (libraryItem.feeds?.length) {
 | 
			
		||||
          libraryItem.rssFeed = libraryItem.feeds[0]
 | 
			
		||||
        }
 | 
			
		||||
        libraryItem.media = book
 | 
			
		||||
        return libraryItem
 | 
			
		||||
@ -788,7 +801,7 @@ module.exports = {
 | 
			
		||||
   * @param {import('../../models/User')} user
 | 
			
		||||
   * @param {string[]} include
 | 
			
		||||
   * @param {number} limit
 | 
			
		||||
   * @returns {object} {libraryItems:LibraryItem, count:number}
 | 
			
		||||
   * @returns {Promise<{ libraryItems: import('../../models/LibraryItem')[], count: number }>}
 | 
			
		||||
   */
 | 
			
		||||
  async getDiscoverLibraryItems(libraryId, user, include, limit) {
 | 
			
		||||
    const userPermissionBookWhere = this.getUserPermissionBookWhereQuery(user)
 | 
			
		||||
@ -895,13 +908,26 @@ module.exports = {
 | 
			
		||||
 | 
			
		||||
    // Step 3: Map books to library items
 | 
			
		||||
    const libraryItems = books.map((bookExpanded) => {
 | 
			
		||||
      const libraryItem = bookExpanded.libraryItem.toJSON()
 | 
			
		||||
      const book = bookExpanded.toJSON()
 | 
			
		||||
      const libraryItem = bookExpanded.libraryItem
 | 
			
		||||
      const book = bookExpanded
 | 
			
		||||
      delete book.libraryItem
 | 
			
		||||
 | 
			
		||||
      book.series =
 | 
			
		||||
        book.bookSeries?.map((bs) => {
 | 
			
		||||
          const series = bs.series
 | 
			
		||||
          delete bs.series
 | 
			
		||||
          series.bookSeries = bs
 | 
			
		||||
          return series
 | 
			
		||||
        }) || []
 | 
			
		||||
      delete book.bookSeries
 | 
			
		||||
 | 
			
		||||
      book.authors = book.bookAuthors?.map((ba) => ba.author) || []
 | 
			
		||||
      delete book.bookAuthors
 | 
			
		||||
 | 
			
		||||
      libraryItem.media = book
 | 
			
		||||
 | 
			
		||||
      if (bookExpanded.libraryItem.feeds?.length) {
 | 
			
		||||
        libraryItem.rssFeed = bookExpanded.libraryItem.feeds[0]
 | 
			
		||||
      if (libraryItem.feeds?.length) {
 | 
			
		||||
        libraryItem.rssFeed = libraryItem.feeds[0]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return libraryItem
 | 
			
		||||
@ -961,11 +987,11 @@ module.exports = {
 | 
			
		||||
   * Get library items for series
 | 
			
		||||
   * @param {import('../../models/Series')} series
 | 
			
		||||
   * @param {import('../../models/User')} [user]
 | 
			
		||||
   * @returns {Promise<import('../../objects/LibraryItem')[]>}
 | 
			
		||||
   * @returns {Promise<import('../../models/LibraryItem')[]>}
 | 
			
		||||
   */
 | 
			
		||||
  async getLibraryItemsForSeries(series, user) {
 | 
			
		||||
    const { libraryItems } = await this.getFilteredLibraryItems(series.libraryId, user, 'series', series.id, null, null, false, [], null, null)
 | 
			
		||||
    return libraryItems.map((li) => Database.libraryItemModel.getOldLibraryItem(li))
 | 
			
		||||
    return libraryItems
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@ -1040,9 +1066,21 @@ module.exports = {
 | 
			
		||||
    for (const book of books) {
 | 
			
		||||
      const libraryItem = book.libraryItem
 | 
			
		||||
      delete book.libraryItem
 | 
			
		||||
 | 
			
		||||
      book.series = book.bookSeries.map((bs) => {
 | 
			
		||||
        const series = bs.series
 | 
			
		||||
        delete bs.series
 | 
			
		||||
        series.bookSeries = bs
 | 
			
		||||
        return series
 | 
			
		||||
      })
 | 
			
		||||
      delete book.bookSeries
 | 
			
		||||
 | 
			
		||||
      book.authors = book.bookAuthors.map((ba) => ba.author)
 | 
			
		||||
      delete book.bookAuthors
 | 
			
		||||
 | 
			
		||||
      libraryItem.media = book
 | 
			
		||||
      itemMatches.push({
 | 
			
		||||
        libraryItem: Database.libraryItemModel.getOldLibraryItem(libraryItem).toJSONExpanded()
 | 
			
		||||
        libraryItem: libraryItem.toOldJSONExpanded()
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1132,7 +1170,9 @@ module.exports = {
 | 
			
		||||
      const books = series.bookSeries.map((bs) => {
 | 
			
		||||
        const libraryItem = bs.book.libraryItem
 | 
			
		||||
        libraryItem.media = bs.book
 | 
			
		||||
        return Database.libraryItemModel.getOldLibraryItem(libraryItem).toJSON()
 | 
			
		||||
        libraryItem.media.authors = []
 | 
			
		||||
        libraryItem.media.series = []
 | 
			
		||||
        return libraryItem.toOldJSON()
 | 
			
		||||
      })
 | 
			
		||||
      seriesMatches.push({
 | 
			
		||||
        series: series.toOldJSON(),
 | 
			
		||||
 | 
			
		||||
@ -107,7 +107,7 @@ module.exports = {
 | 
			
		||||
   * @param {string[]} include
 | 
			
		||||
   * @param {number} limit
 | 
			
		||||
   * @param {number} offset
 | 
			
		||||
   * @returns {object} { libraryItems:LibraryItem[], count:number }
 | 
			
		||||
   * @returns {Promise<{ libraryItems: import('../../models/LibraryItem')[], count: number }>}
 | 
			
		||||
   */
 | 
			
		||||
  async getFilteredLibraryItems(libraryId, user, filterGroup, filterValue, sortBy, sortDesc, include, limit, offset) {
 | 
			
		||||
    const includeRSSFeed = include.includes('rssfeed')
 | 
			
		||||
@ -175,16 +175,19 @@ module.exports = {
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const libraryItems = podcasts.map((podcastExpanded) => {
 | 
			
		||||
      const libraryItem = podcastExpanded.libraryItem.toJSON()
 | 
			
		||||
      const podcast = podcastExpanded.toJSON()
 | 
			
		||||
      const libraryItem = podcastExpanded.libraryItem
 | 
			
		||||
      const podcast = podcastExpanded
 | 
			
		||||
 | 
			
		||||
      delete podcast.libraryItem
 | 
			
		||||
 | 
			
		||||
      if (podcastExpanded.libraryItem.feeds?.length) {
 | 
			
		||||
        libraryItem.rssFeed = podcastExpanded.libraryItem.feeds[0]
 | 
			
		||||
      if (libraryItem.feeds?.length) {
 | 
			
		||||
        libraryItem.rssFeed = libraryItem.feeds[0]
 | 
			
		||||
      }
 | 
			
		||||
      if (podcast.numEpisodesIncomplete) {
 | 
			
		||||
        libraryItem.numEpisodesIncomplete = podcast.numEpisodesIncomplete
 | 
			
		||||
      if (podcast.dataValues.numEpisodesIncomplete) {
 | 
			
		||||
        libraryItem.numEpisodesIncomplete = podcast.dataValues.numEpisodesIncomplete
 | 
			
		||||
      }
 | 
			
		||||
      if (podcast.dataValues.numEpisodes) {
 | 
			
		||||
        podcast.numEpisodes = podcast.dataValues.numEpisodes
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      libraryItem.media = podcast
 | 
			
		||||
@ -209,7 +212,7 @@ module.exports = {
 | 
			
		||||
   * @param {number} limit
 | 
			
		||||
   * @param {number} offset
 | 
			
		||||
   * @param {boolean} isHomePage for home page shelves
 | 
			
		||||
   * @returns {object} {libraryItems:LibraryItem[], count:number}
 | 
			
		||||
   * @returns {Promise<{ libraryItems: import('../../models/LibraryItem')[], count: number }>}
 | 
			
		||||
   */
 | 
			
		||||
  async getFilteredPodcastEpisodes(libraryId, user, filterGroup, filterValue, sortBy, sortDesc, limit, offset, isHomePage = false) {
 | 
			
		||||
    if (sortBy === 'progress' && filterGroup !== 'progress') {
 | 
			
		||||
@ -289,10 +292,11 @@ module.exports = {
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const libraryItems = podcastEpisodes.map((ep) => {
 | 
			
		||||
      const libraryItem = ep.podcast.libraryItem.toJSON()
 | 
			
		||||
      const podcast = ep.podcast.toJSON()
 | 
			
		||||
      const libraryItem = ep.podcast.libraryItem
 | 
			
		||||
      const podcast = ep.podcast
 | 
			
		||||
      delete podcast.libraryItem
 | 
			
		||||
      libraryItem.media = podcast
 | 
			
		||||
 | 
			
		||||
      libraryItem.recentEpisode = ep.getOldPodcastEpisode(libraryItem.id).toJSON()
 | 
			
		||||
      return libraryItem
 | 
			
		||||
    })
 | 
			
		||||
@ -362,8 +366,9 @@ module.exports = {
 | 
			
		||||
      const libraryItem = podcast.libraryItem
 | 
			
		||||
      delete podcast.libraryItem
 | 
			
		||||
      libraryItem.media = podcast
 | 
			
		||||
      libraryItem.media.podcastEpisodes = []
 | 
			
		||||
      itemMatches.push({
 | 
			
		||||
        libraryItem: Database.libraryItemModel.getOldLibraryItem(libraryItem).toJSONExpanded()
 | 
			
		||||
        libraryItem: libraryItem.toOldJSONExpanded()
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -162,6 +162,12 @@ module.exports = {
 | 
			
		||||
            include: [
 | 
			
		||||
              {
 | 
			
		||||
                model: Database.libraryItemModel
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                model: Database.authorModel
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                model: Database.seriesModel
 | 
			
		||||
              }
 | 
			
		||||
            ]
 | 
			
		||||
          },
 | 
			
		||||
@ -195,10 +201,10 @@ module.exports = {
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      oldSeries.books = s.bookSeries.map((bs) => {
 | 
			
		||||
        const libraryItem = bs.book.libraryItem.toJSON()
 | 
			
		||||
        const libraryItem = bs.book.libraryItem
 | 
			
		||||
        delete bs.book.libraryItem
 | 
			
		||||
        libraryItem.media = bs.book
 | 
			
		||||
        const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem).toJSONMinified()
 | 
			
		||||
        const oldLibraryItem = libraryItem.toOldJSONMinified()
 | 
			
		||||
        return oldLibraryItem
 | 
			
		||||
      })
 | 
			
		||||
      allOldSeries.push(oldSeries)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user