mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-26 00:29:53 +01:00
Update filterData for authors/series when added/removed
This commit is contained in:
parent
7222171c5b
commit
9d7d4c6902
@ -343,6 +343,10 @@ export default {
|
||||
}
|
||||
this.$store.commit('libraries/removeCollection', collection)
|
||||
},
|
||||
seriesRemoved({ id, libraryId }) {
|
||||
if (this.currentLibraryId !== libraryId) return
|
||||
this.$store.commit('libraries/removeSeriesFromFilterData', id)
|
||||
},
|
||||
playlistAdded(playlist) {
|
||||
if (playlist.userId !== this.user.id || this.currentLibraryId !== playlist.libraryId) return
|
||||
this.$store.commit('libraries/addUpdateUserPlaylist', playlist)
|
||||
@ -442,6 +446,9 @@ export default {
|
||||
this.socket.on('collection_updated', this.collectionUpdated)
|
||||
this.socket.on('collection_removed', this.collectionRemoved)
|
||||
|
||||
// Series Listeners
|
||||
this.socket.on('series_removed', this.seriesRemoved)
|
||||
|
||||
// User Playlist Listeners
|
||||
this.socket.on('playlist_added', this.playlistAdded)
|
||||
this.socket.on('playlist_updated', this.playlistUpdated)
|
||||
|
@ -234,6 +234,10 @@ export const mutations = {
|
||||
setNumUserPlaylists(state, numUserPlaylists) {
|
||||
state.numUserPlaylists = numUserPlaylists
|
||||
},
|
||||
removeSeriesFromFilterData(state, seriesId) {
|
||||
if (!seriesId || !state.filterData) return
|
||||
state.filterData.series = state.filterData.series.filter(se => se.id !== seriesId)
|
||||
},
|
||||
updateFilterDataWithItem(state, libraryItem) {
|
||||
if (!libraryItem || !state.filterData) return
|
||||
if (state.currentLibraryId !== libraryItem.libraryId) return
|
||||
|
@ -34,6 +34,16 @@ class Database {
|
||||
return this.sequelize?.models || {}
|
||||
}
|
||||
|
||||
/** @type {typeof import('./models/Author')} */
|
||||
get authorModel() {
|
||||
return this.models.author
|
||||
}
|
||||
|
||||
/** @type {typeof import('./models/Series')} */
|
||||
get seriesModel() {
|
||||
return this.models.series
|
||||
}
|
||||
|
||||
async checkHasDb() {
|
||||
if (!await fs.pathExists(this.dbPath)) {
|
||||
Logger.info(`[Database] absdatabase.sqlite not found at ${this.dbPath}`)
|
||||
@ -481,6 +491,66 @@ class Database {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeSeriesFromFilterData(libraryId, seriesId) {
|
||||
if (!this.libraryFilterData[libraryId]) return
|
||||
this.libraryFilterData[libraryId].series = this.libraryFilterData[libraryId].series.filter(se => se.id !== seriesId)
|
||||
}
|
||||
|
||||
addSeriesToFilterData(libraryId, seriesName, seriesId) {
|
||||
if (!this.libraryFilterData[libraryId]) return
|
||||
// Check if series is already added
|
||||
if (this.libraryFilterData[libraryId].series.some(se => se.id === seriesId)) return
|
||||
this.libraryFilterData[libraryId].series.push({
|
||||
id: seriesId,
|
||||
name: seriesName
|
||||
})
|
||||
}
|
||||
|
||||
removeAuthorFromFilterData(libraryId, authorId) {
|
||||
if (!this.libraryFilterData[libraryId]) return
|
||||
this.libraryFilterData[libraryId].authors = this.libraryFilterData[libraryId].authors.filter(au => au.id !== authorId)
|
||||
}
|
||||
|
||||
addAuthorToFilterData(libraryId, authorName, authorId) {
|
||||
if (!this.libraryFilterData[libraryId]) return
|
||||
// Check if author is already added
|
||||
if (this.libraryFilterData[libraryId].authors.some(au => au.id === authorId)) return
|
||||
this.libraryFilterData[libraryId].authors.push({
|
||||
id: authorId,
|
||||
name: authorName
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when updating items to make sure author id exists
|
||||
* If library filter data is set then use that for check
|
||||
* otherwise lookup in db
|
||||
* @param {string} libraryId
|
||||
* @param {string} authorId
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async checkAuthorExists(libraryId, authorId) {
|
||||
if (!this.libraryFilterData[libraryId]) {
|
||||
return this.authorModel.checkExistsById(authorId)
|
||||
}
|
||||
return this.libraryFilterData[libraryId].authors.some(au => au.id === authorId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when updating items to make sure series id exists
|
||||
* If library filter data is set then use that for check
|
||||
* otherwise lookup in db
|
||||
* @param {string} libraryId
|
||||
* @param {string} seriesId
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async checkSeriesExists(libraryId, seriesId) {
|
||||
if (!this.libraryFilterData[libraryId]) {
|
||||
return this.seriesModel.checkExistsById(seriesId)
|
||||
}
|
||||
return this.libraryFilterData[libraryId].series.some(se => se.id === seriesId)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Database()
|
@ -113,6 +113,8 @@ class AuthorController {
|
||||
// Remove old author
|
||||
await Database.removeAuthor(req.author.id)
|
||||
SocketAuthority.emitter('author_removed', req.author.toJSON())
|
||||
// Update filter data
|
||||
Database.removeAuthorFromFilterData(req.author.libraryId, req.author.id)
|
||||
|
||||
// Send updated num books for merged author
|
||||
const numBooks = await Database.models.libraryItem.getForAuthor(existingAuthor).length
|
||||
|
@ -859,12 +859,12 @@ class LibraryController {
|
||||
/**
|
||||
* GET: /api/libraries/:id/authors
|
||||
* Get authors for library
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getAuthors(req, res) {
|
||||
const { bookWhere, replacements } = libraryItemsBookFilters.getUserPermissionBookWhereQuery(req.user)
|
||||
const authors = await Database.models.author.findAll({
|
||||
const authors = await Database.authorModel.findAll({
|
||||
where: {
|
||||
libraryId: req.library.id
|
||||
},
|
||||
|
@ -124,7 +124,7 @@ class LibraryItemController {
|
||||
// Book specific - Get all series being removed from this item
|
||||
let seriesRemoved = []
|
||||
if (libraryItem.isBook && mediaPayload.metadata?.series) {
|
||||
const seriesIdsInUpdate = (mediaPayload.metadata?.series || []).map(se => se.id)
|
||||
const seriesIdsInUpdate = mediaPayload.metadata.series?.map(se => se.id) || []
|
||||
seriesRemoved = libraryItem.media.metadata.series.filter(se => !seriesIdsInUpdate.includes(se.id))
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,15 @@ class Author extends Model {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if author exists
|
||||
* @param {string} authorId
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
static async checkExistsById(authorId) {
|
||||
return (await this.count({ where: { id: authorId } })) > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize model
|
||||
* @param {import('../Database').sequelize} sequelize
|
||||
|
@ -75,6 +75,15 @@ class Series extends Model {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if series exists
|
||||
* @param {string} seriesId
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
static async checkExistsById(seriesId) {
|
||||
return (await this.count({ where: { id: seriesId } })) > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize model
|
||||
* @param {import('../Database').sequelize} sequelize
|
||||
|
@ -472,10 +472,20 @@ class ApiRouter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty series & close an open RSS feed
|
||||
* @param {import('../models/Series')} series
|
||||
*/
|
||||
async removeEmptySeries(series) {
|
||||
await this.rssFeedManager.closeFeedForEntityId(series.id)
|
||||
Logger.info(`[ApiRouter] Series "${series.name}" is now empty. Removing series`)
|
||||
await Database.removeSeries(series.id)
|
||||
// Remove series from library filter data
|
||||
Database.removeSeriesFromFilterData(series.libraryId, series.id)
|
||||
SocketAuthority.emitter('series_removed', {
|
||||
id: series.id,
|
||||
libraryId: series.libraryId
|
||||
})
|
||||
}
|
||||
|
||||
async getUserListeningSessionsHelper(userId) {
|
||||
@ -546,7 +556,7 @@ class ApiRouter {
|
||||
const mediaMetadata = mediaPayload.metadata
|
||||
|
||||
// Create new authors if in payload
|
||||
if (mediaMetadata.authors && mediaMetadata.authors.length) {
|
||||
if (mediaMetadata.authors?.length) {
|
||||
const newAuthors = []
|
||||
for (let i = 0; i < mediaMetadata.authors.length; i++) {
|
||||
const authorName = (mediaMetadata.authors[i].name || '').trim()
|
||||
@ -555,6 +565,12 @@ class ApiRouter {
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the ID for the author exists
|
||||
if (mediaMetadata.authors[i].id && !(await Database.checkAuthorExists(libraryId, mediaMetadata.authors[i].id))) {
|
||||
Logger.warn(`[ApiRouter] Author id "${mediaMetadata.authors[i].id}" does not exist`)
|
||||
mediaMetadata.authors[i].id = null
|
||||
}
|
||||
|
||||
if (!mediaMetadata.authors[i].id || mediaMetadata.authors[i].id.startsWith('new')) {
|
||||
let author = Database.authors.find(au => au.libraryId === libraryId && au.checkNameEquals(authorName))
|
||||
if (!author) {
|
||||
@ -562,6 +578,8 @@ class ApiRouter {
|
||||
author.setData(mediaMetadata.authors[i], libraryId)
|
||||
Logger.debug(`[ApiRouter] Created new author "${author.name}"`)
|
||||
newAuthors.push(author)
|
||||
// Update filter data
|
||||
Database.addAuthorToFilterData(libraryId, author.name, author.id)
|
||||
}
|
||||
|
||||
// Update ID in original payload
|
||||
@ -584,6 +602,12 @@ class ApiRouter {
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the ID for the series exists
|
||||
if (mediaMetadata.series[i].id && !(await Database.checkSeriesExists(libraryId, mediaMetadata.series[i].id))) {
|
||||
Logger.warn(`[ApiRouter] Series id "${mediaMetadata.series[i].id}" does not exist`)
|
||||
mediaMetadata.series[i].id = null
|
||||
}
|
||||
|
||||
if (!mediaMetadata.series[i].id || mediaMetadata.series[i].id.startsWith('new')) {
|
||||
let seriesItem = Database.series.find(se => se.libraryId === libraryId && se.checkNameEquals(seriesName))
|
||||
if (!seriesItem) {
|
||||
@ -591,6 +615,8 @@ class ApiRouter {
|
||||
seriesItem.setData(mediaMetadata.series[i], libraryId)
|
||||
Logger.debug(`[ApiRouter] Created new series "${seriesItem.name}"`)
|
||||
newSeries.push(seriesItem)
|
||||
// Update filter data
|
||||
Database.addSeriesToFilterData(libraryId, seriesItem.name, seriesItem.id)
|
||||
}
|
||||
|
||||
// Update ID in original payload
|
||||
|
@ -486,6 +486,8 @@ class Scanner {
|
||||
_author = new Author()
|
||||
_author.setData(tempMinAuthor, libraryItem.libraryId)
|
||||
newAuthors.push(_author)
|
||||
// Update filter data
|
||||
Database.addAuthorToFilterData(libraryItem.libraryId, _author.name, _author.id)
|
||||
}
|
||||
|
||||
return {
|
||||
@ -502,11 +504,17 @@ class Scanner {
|
||||
const newSeries = []
|
||||
libraryItem.media.metadata.series = libraryItem.media.metadata.series.map((tempMinSeries) => {
|
||||
let _series = Database.series.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(tempMinSeries.name))
|
||||
if (!_series) _series = newSeries.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(tempMinSeries.name)) // Check new unsaved series
|
||||
if (!_series) {
|
||||
// Check new unsaved series
|
||||
_series = newSeries.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(tempMinSeries.name))
|
||||
}
|
||||
|
||||
if (!_series) { // Must create new series
|
||||
_series = new Series()
|
||||
_series.setData(tempMinSeries, libraryItem.libraryId)
|
||||
newSeries.push(_series)
|
||||
// Update filter data
|
||||
Database.addSeriesToFilterData(libraryItem.libraryId, _series.name, _series.id)
|
||||
}
|
||||
return {
|
||||
id: _series.id,
|
||||
@ -924,6 +932,8 @@ class Scanner {
|
||||
author.setData({ name: authorName }, libraryItem.libraryId)
|
||||
await Database.createAuthor(author)
|
||||
SocketAuthority.emitter('author_added', author.toJSON())
|
||||
// Update filter data
|
||||
Database.addAuthorToFilterData(libraryItem.libraryId, author.name, author.id)
|
||||
}
|
||||
authorPayload.push(author.toJSONMinimal())
|
||||
}
|
||||
@ -940,6 +950,8 @@ class Scanner {
|
||||
seriesItem = new Series()
|
||||
seriesItem.setData({ name: seriesMatchItem.series }, libraryItem.libraryId)
|
||||
await Database.createSeries(seriesItem)
|
||||
// Update filter data
|
||||
Database.addSeriesToFilterData(libraryItem.libraryId, seriesItem.name, seriesItem.id)
|
||||
SocketAuthority.emitter('series_added', seriesItem.toJSON())
|
||||
}
|
||||
seriesPayload.push(seriesItem.toJSONMinimal(seriesMatchItem.sequence))
|
||||
|
@ -221,7 +221,7 @@ module.exports = {
|
||||
}))
|
||||
}
|
||||
|
||||
const { rows: series, count } = await Database.models.series.findAndCountAll({
|
||||
const { rows: series, count } = await Database.seriesModel.findAndCountAll({
|
||||
where: seriesWhere,
|
||||
limit,
|
||||
offset: 0,
|
||||
@ -291,7 +291,7 @@ module.exports = {
|
||||
async getNewestAuthors(library, user, limit) {
|
||||
if (library.mediaType !== 'book') return { authors: [], count: 0 }
|
||||
|
||||
const { rows: authors, count } = await Database.models.author.findAndCountAll({
|
||||
const { rows: authors, count } = await Database.authorModel.findAndCountAll({
|
||||
where: {
|
||||
libraryId: library.id,
|
||||
createdAt: {
|
||||
@ -461,7 +461,7 @@ module.exports = {
|
||||
if (book.language) data.languages.add(book.language)
|
||||
}
|
||||
|
||||
const series = await Database.models.series.findAll({
|
||||
const series = await Database.seriesModel.findAll({
|
||||
where: {
|
||||
libraryId: oldLibrary.id
|
||||
},
|
||||
@ -469,7 +469,7 @@ module.exports = {
|
||||
})
|
||||
series.forEach((s) => data.series.push({ id: s.id, name: s.name }))
|
||||
|
||||
const authors = await Database.models.author.findAll({
|
||||
const authors = await Database.authorModel.findAll({
|
||||
where: {
|
||||
libraryId: oldLibrary.id
|
||||
},
|
||||
|
@ -278,7 +278,7 @@ module.exports = {
|
||||
* @returns {object} { booksToExclude, bookSeriesToInclude }
|
||||
*/
|
||||
async getCollapseSeriesBooksToExclude(bookFindOptions, seriesWhere) {
|
||||
const allSeries = await Database.models.series.findAll({
|
||||
const allSeries = await Database.seriesModel.findAll({
|
||||
attributes: [
|
||||
'id',
|
||||
'name',
|
||||
@ -642,7 +642,7 @@ module.exports = {
|
||||
const userPermissionBookWhere = this.getUserPermissionBookWhereQuery(user)
|
||||
bookWhere.push(...userPermissionBookWhere.bookWhere)
|
||||
|
||||
const { rows: series, count } = await Database.models.series.findAndCountAll({
|
||||
const { rows: series, count } = await Database.seriesModel.findAndCountAll({
|
||||
where: [
|
||||
{
|
||||
libraryId
|
||||
@ -751,7 +751,7 @@ module.exports = {
|
||||
const userPermissionBookWhere = this.getUserPermissionBookWhereQuery(user)
|
||||
|
||||
// Step 1: Get the first book of every series that hasnt been started yet
|
||||
const seriesNotStarted = await Database.models.series.findAll({
|
||||
const seriesNotStarted = await Database.seriesModel.findAll({
|
||||
where: [
|
||||
{
|
||||
libraryId
|
||||
|
Loading…
Reference in New Issue
Block a user