mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Update author API endpoints to load library items from DB
This commit is contained in:
		
							parent
							
								
									56e3449db6
								
							
						
					
					
						commit
						345ff1aa66
					
				@ -15,18 +15,13 @@ class AuthorController {
 | 
				
			|||||||
  constructor() { }
 | 
					  constructor() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async findOne(req, res) {
 | 
					  async findOne(req, res) {
 | 
				
			||||||
    const libraryId = req.query.library
 | 
					 | 
				
			||||||
    const include = (req.query.include || '').split(',')
 | 
					    const include = (req.query.include || '').split(',')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const authorJson = req.author.toJSON()
 | 
					    const authorJson = req.author.toJSON()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Used on author landing page to include library items and items grouped in series
 | 
					    // Used on author landing page to include library items and items grouped in series
 | 
				
			||||||
    if (include.includes('items')) {
 | 
					    if (include.includes('items')) {
 | 
				
			||||||
      authorJson.libraryItems = Database.libraryItems.filter(li => {
 | 
					      authorJson.libraryItems = await Database.models.libraryItem.getForAuthor(req.author, req.user)
 | 
				
			||||||
        if (libraryId && li.libraryId !== libraryId) return false
 | 
					 | 
				
			||||||
        if (!req.user.checkCanAccessLibraryItem(li)) return false // filter out library items user cannot access
 | 
					 | 
				
			||||||
        return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(req.author.id)
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (include.includes('series')) {
 | 
					      if (include.includes('series')) {
 | 
				
			||||||
        const seriesMap = {}
 | 
					        const seriesMap = {}
 | 
				
			||||||
@ -101,7 +96,7 @@ class AuthorController {
 | 
				
			|||||||
    const existingAuthor = authorNameUpdate ? Database.authors.find(au => au.id !== req.author.id && payload.name === au.name) : false
 | 
					    const existingAuthor = authorNameUpdate ? Database.authors.find(au => au.id !== req.author.id && payload.name === au.name) : false
 | 
				
			||||||
    if (existingAuthor) {
 | 
					    if (existingAuthor) {
 | 
				
			||||||
      const bookAuthorsToCreate = []
 | 
					      const bookAuthorsToCreate = []
 | 
				
			||||||
      const itemsWithAuthor = Database.libraryItems.filter(li => li.mediaType === 'book' && li.media.metadata.hasAuthor(req.author.id))
 | 
					      const itemsWithAuthor = await Database.models.libraryItem.getForAuthor(req.author)
 | 
				
			||||||
      itemsWithAuthor.forEach(libraryItem => { // Replace old author with merging author for each book
 | 
					      itemsWithAuthor.forEach(libraryItem => { // Replace old author with merging author for each book
 | 
				
			||||||
        libraryItem.media.metadata.replaceAuthor(req.author, existingAuthor)
 | 
					        libraryItem.media.metadata.replaceAuthor(req.author, existingAuthor)
 | 
				
			||||||
        bookAuthorsToCreate.push({
 | 
					        bookAuthorsToCreate.push({
 | 
				
			||||||
@ -120,9 +115,7 @@ class AuthorController {
 | 
				
			|||||||
      SocketAuthority.emitter('author_removed', req.author.toJSON())
 | 
					      SocketAuthority.emitter('author_removed', req.author.toJSON())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Send updated num books for merged author
 | 
					      // Send updated num books for merged author
 | 
				
			||||||
      const numBooks = Database.libraryItems.filter(li => {
 | 
					      const numBooks = await Database.models.libraryItem.getForAuthor(existingAuthor).length
 | 
				
			||||||
        return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(existingAuthor.id)
 | 
					 | 
				
			||||||
      }).length
 | 
					 | 
				
			||||||
      SocketAuthority.emitter('author_updated', existingAuthor.toJSONExpanded(numBooks))
 | 
					      SocketAuthority.emitter('author_updated', existingAuthor.toJSONExpanded(numBooks))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      res.json({
 | 
					      res.json({
 | 
				
			||||||
@ -137,8 +130,8 @@ class AuthorController {
 | 
				
			|||||||
      if (hasUpdated) {
 | 
					      if (hasUpdated) {
 | 
				
			||||||
        req.author.updatedAt = Date.now()
 | 
					        req.author.updatedAt = Date.now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const itemsWithAuthor = await Database.models.libraryItem.getForAuthor(req.author)
 | 
				
			||||||
        if (authorNameUpdate) { // Update author name on all books
 | 
					        if (authorNameUpdate) { // Update author name on all books
 | 
				
			||||||
          const itemsWithAuthor = Database.libraryItems.filter(li => li.mediaType === 'book' && li.media.metadata.hasAuthor(req.author.id))
 | 
					 | 
				
			||||||
          itemsWithAuthor.forEach(libraryItem => {
 | 
					          itemsWithAuthor.forEach(libraryItem => {
 | 
				
			||||||
            libraryItem.media.metadata.updateAuthor(req.author)
 | 
					            libraryItem.media.metadata.updateAuthor(req.author)
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
@ -148,10 +141,7 @@ class AuthorController {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await Database.updateAuthor(req.author)
 | 
					        await Database.updateAuthor(req.author)
 | 
				
			||||||
        const numBooks = Database.libraryItems.filter(li => {
 | 
					        SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(itemsWithAuthor.length))
 | 
				
			||||||
          return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(req.author.id)
 | 
					 | 
				
			||||||
        }).length
 | 
					 | 
				
			||||||
        SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(numBooks))
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      res.json({
 | 
					      res.json({
 | 
				
			||||||
@ -211,9 +201,8 @@ class AuthorController {
 | 
				
			|||||||
      req.author.updatedAt = Date.now()
 | 
					      req.author.updatedAt = Date.now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await Database.updateAuthor(req.author)
 | 
					      await Database.updateAuthor(req.author)
 | 
				
			||||||
      const numBooks = Database.libraryItems.filter(li => {
 | 
					
 | 
				
			||||||
        return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(req.author.id)
 | 
					      const numBooks = await Database.models.libraryItem.getForAuthor(req.author).length
 | 
				
			||||||
      }).length
 | 
					 | 
				
			||||||
      SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(numBooks))
 | 
					      SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(numBooks))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -679,8 +679,8 @@ class LibraryItemController {
 | 
				
			|||||||
    res.sendStatus(200)
 | 
					    res.sendStatus(200)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  middleware(req, res, next) {
 | 
					  async middleware(req, res, next) {
 | 
				
			||||||
    req.libraryItem = Database.libraryItems.find(li => li.id === req.params.id)
 | 
					    req.libraryItem = await Database.models.libraryItem.getOldById(req.params.id)
 | 
				
			||||||
    if (!req.libraryItem?.media) return res.sendStatus(404)
 | 
					    if (!req.libraryItem?.media) return res.sendStatus(404)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check user can access this library item
 | 
					    // Check user can access this library item
 | 
				
			||||||
 | 
				
			|||||||
@ -400,6 +400,46 @@ module.exports = (sequelize) => {
 | 
				
			|||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get old library item by id
 | 
				
			||||||
 | 
					     * @param {string} libraryItemId 
 | 
				
			||||||
 | 
					     * @returns {oldLibraryItem}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static async getOldById(libraryItemId) {
 | 
				
			||||||
 | 
					      if (!libraryItemId) return null
 | 
				
			||||||
 | 
					      const libraryItem = await this.findByPk(libraryItemId, {
 | 
				
			||||||
 | 
					        include: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            model: sequelize.models.book,
 | 
				
			||||||
 | 
					            include: [
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                model: sequelize.models.author,
 | 
				
			||||||
 | 
					                through: {
 | 
				
			||||||
 | 
					                  attributes: []
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                model: sequelize.models.series,
 | 
				
			||||||
 | 
					                through: {
 | 
				
			||||||
 | 
					                  attributes: ['sequence']
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            model: sequelize.models.podcast,
 | 
				
			||||||
 | 
					            include: [
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                model: sequelize.models.podcastEpisode
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      if (!libraryItem) return null
 | 
				
			||||||
 | 
					      return this.getOldLibraryItem(libraryItem)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get library items using filter and sort
 | 
					     * Get library items using filter and sort
 | 
				
			||||||
     * @param {oldLibrary} library 
 | 
					     * @param {oldLibrary} library 
 | 
				
			||||||
@ -609,6 +649,17 @@ module.exports = (sequelize) => {
 | 
				
			|||||||
      return shelves
 | 
					      return shelves
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get book library items for author, optional use user permissions
 | 
				
			||||||
 | 
					     * @param {oldAuthor} author
 | 
				
			||||||
 | 
					     * @param {[oldUser]} user 
 | 
				
			||||||
 | 
					     * @returns {oldLibraryItem[]}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static async getForAuthor(author, user = null) {
 | 
				
			||||||
 | 
					      const { libraryItems } = await libraryFilters.getLibraryItemsForAuthor(author, user, undefined, undefined)
 | 
				
			||||||
 | 
					      return libraryItems.map(li => this.getOldLibraryItem(li))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getMedia(options) {
 | 
					    getMedia(options) {
 | 
				
			||||||
      if (!this.mediaType) return Promise.resolve(null)
 | 
					      if (!this.mediaType) return Promise.resolve(null)
 | 
				
			||||||
      const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaType)}`
 | 
					      const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaType)}`
 | 
				
			||||||
 | 
				
			|||||||
@ -357,5 +357,21 @@ module.exports = {
 | 
				
			|||||||
        return oldLibraryItem
 | 
					        return oldLibraryItem
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Get library items for an author, optional use user permissions
 | 
				
			||||||
 | 
					   * @param {oldAuthor} author 
 | 
				
			||||||
 | 
					   * @param {[oldUser]} user 
 | 
				
			||||||
 | 
					   * @param {number} limit 
 | 
				
			||||||
 | 
					   * @param {number} offset 
 | 
				
			||||||
 | 
					   * @returns {object} { libraryItems:LibraryItem[], count:number }
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  async getLibraryItemsForAuthor(author, user, limit, offset) {
 | 
				
			||||||
 | 
					    const { libraryItems, count } = await libraryItemsBookFilters.getFilteredLibraryItems(author.libraryId, user, 'authors', author.id, 'addedAt', true, false, [], limit, offset)
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      count,
 | 
				
			||||||
 | 
					      libraryItems
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -11,6 +11,8 @@ module.exports = {
 | 
				
			|||||||
  getUserPermissionBookWhereQuery(user) {
 | 
					  getUserPermissionBookWhereQuery(user) {
 | 
				
			||||||
    const bookWhere = []
 | 
					    const bookWhere = []
 | 
				
			||||||
    const replacements = {}
 | 
					    const replacements = {}
 | 
				
			||||||
 | 
					    if (!user) return { bookWhere, replacements }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!user.canAccessExplicitContent) {
 | 
					    if (!user.canAccessExplicitContent) {
 | 
				
			||||||
      bookWhere.push({
 | 
					      bookWhere.push({
 | 
				
			||||||
        explicit: false
 | 
					        explicit: false
 | 
				
			||||||
@ -325,7 +327,7 @@ module.exports = {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Get library items for book media type using filter and sort
 | 
					   * Get library items for book media type using filter and sort
 | 
				
			||||||
   * @param {string} libraryId 
 | 
					   * @param {string} libraryId 
 | 
				
			||||||
   * @param {oldUser} user
 | 
					   * @param {[oldUser]} user
 | 
				
			||||||
   * @param {[string]} filterGroup 
 | 
					   * @param {[string]} filterGroup 
 | 
				
			||||||
   * @param {[string]} filterValue 
 | 
					   * @param {[string]} filterValue 
 | 
				
			||||||
   * @param {string} sortBy 
 | 
					   * @param {string} sortBy 
 | 
				
			||||||
@ -467,7 +469,7 @@ module.exports = {
 | 
				
			|||||||
          isInvalid: true
 | 
					          isInvalid: true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    } else if (filterGroup === 'progress') {
 | 
					    } else if (filterGroup === 'progress' && user) {
 | 
				
			||||||
      bookIncludes.push({
 | 
					      bookIncludes.push({
 | 
				
			||||||
        model: Database.models.mediaProgress,
 | 
					        model: Database.models.mediaProgress,
 | 
				
			||||||
        attributes: ['id', 'isFinished', 'currentTime', 'ebookProgress', 'updatedAt'],
 | 
					        attributes: ['id', 'isFinished', 'currentTime', 'ebookProgress', 'updatedAt'],
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user