mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-07-14 19:34:57 +02:00
Fix:Remove authors with no books when a books is removed #3668
- Handles bulk delete, single delete, deleting library folder, and removing items with issues - Also handles bulk editing and removing authors
This commit is contained in:
parent
ea4d5ff665
commit
c496db7c95
3 changed files with 177 additions and 83 deletions
|
@ -348,11 +348,10 @@ class ApiRouter {
|
|||
//
|
||||
/**
|
||||
* Remove library item and associated entities
|
||||
* @param {string} mediaType
|
||||
* @param {string} libraryItemId
|
||||
* @param {string[]} mediaItemIds array of bookId or podcastEpisodeId
|
||||
*/
|
||||
async handleDeleteLibraryItem(mediaType, libraryItemId, mediaItemIds) {
|
||||
async handleDeleteLibraryItem(libraryItemId, mediaItemIds) {
|
||||
const numProgressRemoved = await Database.mediaProgressModel.destroy({
|
||||
where: {
|
||||
mediaItemId: mediaItemIds
|
||||
|
@ -362,29 +361,6 @@ class ApiRouter {
|
|||
Logger.info(`[ApiRouter] Removed ${numProgressRemoved} media progress entries for library item "${libraryItemId}"`)
|
||||
}
|
||||
|
||||
// TODO: Remove open sessions for library item
|
||||
|
||||
// Remove series if empty
|
||||
if (mediaType === 'book') {
|
||||
// TODO: update filter data
|
||||
const bookSeries = await Database.bookSeriesModel.findAll({
|
||||
where: {
|
||||
bookId: mediaItemIds[0]
|
||||
},
|
||||
include: {
|
||||
model: Database.seriesModel,
|
||||
include: {
|
||||
model: Database.bookModel
|
||||
}
|
||||
}
|
||||
})
|
||||
for (const bs of bookSeries) {
|
||||
if (bs.series.books.length === 1) {
|
||||
await this.removeEmptySeries(bs.series)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove item from playlists
|
||||
const playlistsWithItem = await Database.playlistModel.getPlaylistsForMediaItemIds(mediaItemIds)
|
||||
for (const playlist of playlistsWithItem) {
|
||||
|
@ -423,6 +399,7 @@ class ApiRouter {
|
|||
// purge cover cache
|
||||
await CacheManager.purgeCoverCache(libraryItemId)
|
||||
|
||||
// Remove metadata file if in /metadata/items dir
|
||||
const itemMetadataPath = Path.join(global.MetadataPath, 'items', libraryItemId)
|
||||
if (await fs.pathExists(itemMetadataPath)) {
|
||||
Logger.info(`[ApiRouter] Removing item metadata at "${itemMetadataPath}"`)
|
||||
|
@ -437,32 +414,27 @@ class ApiRouter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Used when a series is removed from a book
|
||||
* Series is removed if it only has 1 book
|
||||
* After deleting book(s), remove empty series
|
||||
*
|
||||
* @param {string} bookId
|
||||
* @param {string[]} seriesIds
|
||||
*/
|
||||
async checkRemoveEmptySeries(bookId, seriesIds) {
|
||||
async checkRemoveEmptySeries(seriesIds) {
|
||||
if (!seriesIds?.length) return
|
||||
|
||||
const bookSeries = await Database.bookSeriesModel.findAll({
|
||||
const series = await Database.seriesModel.findAll({
|
||||
where: {
|
||||
bookId,
|
||||
seriesId: seriesIds
|
||||
id: seriesIds
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Database.seriesModel,
|
||||
include: {
|
||||
model: Database.bookModel
|
||||
}
|
||||
}
|
||||
]
|
||||
attributes: ['id', 'name', 'libraryId'],
|
||||
include: {
|
||||
model: Database.bookModel,
|
||||
attributes: ['id']
|
||||
}
|
||||
})
|
||||
for (const bs of bookSeries) {
|
||||
if (bs.series.books.length === 1) {
|
||||
await this.removeEmptySeries(bs.series)
|
||||
|
||||
for (const s of series) {
|
||||
if (!s.books.length) {
|
||||
await this.removeEmptySeries(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -471,11 +443,10 @@ class ApiRouter {
|
|||
* Remove authors with no books and unset asin, description and imagePath
|
||||
* Note: Other implementation is in BookScanner.checkAuthorsRemovedFromBooks (can be merged)
|
||||
*
|
||||
* @param {string} libraryId
|
||||
* @param {string[]} authorIds
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async checkRemoveAuthorsWithNoBooks(libraryId, authorIds) {
|
||||
async checkRemoveAuthorsWithNoBooks(authorIds) {
|
||||
if (!authorIds?.length) return
|
||||
|
||||
const bookAuthorsToRemove = (
|
||||
|
@ -495,10 +466,10 @@ class ApiRouter {
|
|||
},
|
||||
sequelize.where(sequelize.literal('(SELECT count(*) FROM bookAuthors ba WHERE ba.authorId = author.id)'), 0)
|
||||
],
|
||||
attributes: ['id', 'name'],
|
||||
attributes: ['id', 'name', 'libraryId'],
|
||||
raw: true
|
||||
})
|
||||
).map((au) => ({ id: au.id, name: au.name }))
|
||||
).map((au) => ({ id: au.id, name: au.name, libraryId: au.libraryId }))
|
||||
|
||||
if (bookAuthorsToRemove.length) {
|
||||
await Database.authorModel.destroy({
|
||||
|
@ -506,7 +477,7 @@ class ApiRouter {
|
|||
id: bookAuthorsToRemove.map((au) => au.id)
|
||||
}
|
||||
})
|
||||
bookAuthorsToRemove.forEach(({ id, name }) => {
|
||||
bookAuthorsToRemove.forEach(({ id, name, libraryId }) => {
|
||||
Database.removeAuthorFromFilterData(libraryId, id)
|
||||
// TODO: Clients were expecting full author in payload but its unnecessary
|
||||
SocketAuthority.emitter('author_removed', { id, libraryId })
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue