Update Series and Author model to be library specific

This commit is contained in:
advplyr 2023-07-08 09:57:32 -05:00
parent 1d13d0a553
commit 0ac63b2678
10 changed files with 119 additions and 61 deletions

View File

@ -271,12 +271,16 @@ export default {
let filterValue = null
if (parts.length > 1) {
const decoded = this.$decode(parts[1])
if (decoded.startsWith('aut_')) {
if (parts[0] === 'authors') {
const author = this.authors.find((au) => au.id == decoded)
if (author) filterValue = author.name
} else if (decoded.startsWith('ser_')) {
} else if (parts[0] === 'series') {
if (decoded === 'no-series') {
filterValue = this.$strings.MessageNoSeries
} else {
const series = this.series.find((se) => se.id == decoded)
if (series) filterValue = series.name
}
} else {
filterValue = decoded
}

View File

@ -105,7 +105,7 @@ class LibraryItemController {
// Book specific
if (libraryItem.isBook) {
await this.createAuthorsAndSeriesForItemUpdate(mediaPayload)
await this.createAuthorsAndSeriesForItemUpdate(mediaPayload, libraryItem.libraryId)
}
// Podcast specific
@ -342,7 +342,7 @@ class LibraryItemController {
var libraryItem = Database.libraryItems.find(_li => _li.id === updatePayloads[i].id)
if (!libraryItem) return null
await this.createAuthorsAndSeriesForItemUpdate(mediaPayload)
await this.createAuthorsAndSeriesForItemUpdate(mediaPayload, libraryItem.libraryId)
var hasUpdates = libraryItem.media.update(mediaPayload)
if (hasUpdates) {

View File

@ -74,5 +74,9 @@ module.exports = (sequelize) => {
modelName: 'author'
})
const { library } = sequelize.models
library.hasMany(Author)
Author.belongsTo(library)
return Author
}

View File

@ -68,5 +68,9 @@ module.exports = (sequelize) => {
modelName: 'series'
})
const { library } = sequelize.models
library.hasMany(Series)
Series.belongsTo(library)
return Series
}

View File

@ -11,6 +11,7 @@ class Author {
this.imagePath = null
this.addedAt = null
this.updatedAt = null
this.libraryId = null
if (author) {
this.construct(author)
@ -25,6 +26,7 @@ class Author {
this.imagePath = author.imagePath
this.addedAt = author.addedAt
this.updatedAt = author.updatedAt
this.libraryId = author.libraryId
}
toJSON() {
@ -35,7 +37,8 @@ class Author {
description: this.description,
imagePath: this.imagePath,
addedAt: this.addedAt,
updatedAt: this.updatedAt
updatedAt: this.updatedAt,
libraryId: this.libraryId
}
}
@ -52,7 +55,7 @@ class Author {
}
}
setData(data) {
setData(data, libraryId) {
this.id = uuidv4()
this.name = data.name
this.description = data.description || null
@ -60,6 +63,7 @@ class Author {
this.imagePath = data.imagePath || null
this.addedAt = Date.now()
this.updatedAt = Date.now()
this.libraryId = libraryId
}
update(payload) {

View File

@ -7,6 +7,7 @@ class Series {
this.description = null
this.addedAt = null
this.updatedAt = null
this.libraryId = null
if (series) {
this.construct(series)
@ -19,6 +20,7 @@ class Series {
this.description = series.description || null
this.addedAt = series.addedAt
this.updatedAt = series.updatedAt
this.libraryId = series.libraryId
}
toJSON() {
@ -27,7 +29,8 @@ class Series {
name: this.name,
description: this.description,
addedAt: this.addedAt,
updatedAt: this.updatedAt
updatedAt: this.updatedAt,
libraryId: this.libraryId
}
}
@ -39,12 +42,13 @@ class Series {
}
}
setData(data) {
setData(data, libraryId) {
this.id = uuidv4()
this.name = data.name
this.description = data.description || null
this.addedAt = Date.now()
this.updatedAt = Date.now()
this.libraryId = libraryId
}
update(series) {

View File

@ -519,7 +519,7 @@ class ApiRouter {
return listeningStats
}
async createAuthorsAndSeriesForItemUpdate(mediaPayload) {
async createAuthorsAndSeriesForItemUpdate(mediaPayload, libraryId) {
if (mediaPayload.metadata) {
const mediaMetadata = mediaPayload.metadata
@ -534,10 +534,10 @@ class ApiRouter {
}
if (!mediaMetadata.authors[i].id || mediaMetadata.authors[i].id.startsWith('new')) {
let author = Database.authors.find(au => au.checkNameEquals(authorName))
let author = Database.authors.find(au => au.libraryId === libraryId && au.checkNameEquals(authorName))
if (!author) {
author = new Author()
author.setData(mediaMetadata.authors[i])
author.setData(mediaMetadata.authors[i], libraryId)
Logger.debug(`[ApiRouter] Created new author "${author.name}"`)
newAuthors.push(author)
}
@ -563,10 +563,10 @@ class ApiRouter {
}
if (!mediaMetadata.series[i].id || mediaMetadata.series[i].id.startsWith('new')) {
let seriesItem = Database.series.find(se => se.checkNameEquals(seriesName))
let seriesItem = Database.series.find(se => se.libraryId === libraryId && se.checkNameEquals(seriesName))
if (!seriesItem) {
seriesItem = new Series()
seriesItem.setData(mediaMetadata.series[i])
seriesItem.setData(mediaMetadata.series[i], libraryId)
Logger.debug(`[ApiRouter] Created new series "${seriesItem.name}"`)
newSeries.push(seriesItem)
}

View File

@ -477,13 +477,13 @@ class Scanner {
// Create or match all new authors and series
if (libraryItem.media.metadata.authors.some(au => au.id.startsWith('new'))) {
var newAuthors = []
const newAuthors = []
libraryItem.media.metadata.authors = libraryItem.media.metadata.authors.map((tempMinAuthor) => {
var _author = Database.authors.find(au => au.checkNameEquals(tempMinAuthor.name))
if (!_author) _author = newAuthors.find(au => au.checkNameEquals(tempMinAuthor.name)) // Check new unsaved authors
let _author = Database.authors.find(au => au.libraryId === libraryItem.libraryId && au.checkNameEquals(tempMinAuthor.name))
if (!_author) _author = newAuthors.find(au => au.libraryId === libraryItem.libraryId && au.checkNameEquals(tempMinAuthor.name)) // Check new unsaved authors
if (!_author) { // Must create new author
_author = new Author()
_author.setData(tempMinAuthor)
_author.setData(tempMinAuthor, libraryItem.libraryId)
newAuthors.push(_author)
}
@ -498,13 +498,13 @@ class Scanner {
}
}
if (libraryItem.media.metadata.series.some(se => se.id.startsWith('new'))) {
var newSeries = []
const newSeries = []
libraryItem.media.metadata.series = libraryItem.media.metadata.series.map((tempMinSeries) => {
var _series = Database.series.find(se => se.checkNameEquals(tempMinSeries.name))
if (!_series) _series = newSeries.find(se => se.checkNameEquals(tempMinSeries.name)) // Check new unsaved series
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) { // Must create new series
_series = new Series()
_series.setData(tempMinSeries)
_series.setData(tempMinSeries, libraryItem.libraryId)
newSeries.push(_series)
}
return {
@ -877,12 +877,11 @@ class Scanner {
matchData.author = matchData.author.split(',').map(au => au.trim()).filter(au => !!au)
}
const authorPayload = []
for (let index = 0; index < matchData.author.length; index++) {
const authorName = matchData.author[index]
var author = Database.authors.find(au => au.checkNameEquals(authorName))
for (const authorName of matchData.author) {
let author = Database.authors.find(au => au.libraryId === libraryItem.libraryId && au.checkNameEquals(authorName))
if (!author) {
author = new Author()
author.setData({ name: authorName })
author.setData({ name: authorName }, libraryItem.libraryId)
await Database.createAuthor(author)
SocketAuthority.emitter('author_added', author.toJSON())
}
@ -895,12 +894,11 @@ class Scanner {
if (matchData.series && (!libraryItem.media.metadata.seriesName || options.overrideDetails)) {
if (!Array.isArray(matchData.series)) matchData.series = [{ series: matchData.series, sequence: matchData.sequence }]
const seriesPayload = []
for (let index = 0; index < matchData.series.length; index++) {
const seriesMatchItem = matchData.series[index]
var seriesItem = Database.series.find(au => au.checkNameEquals(seriesMatchItem.series))
for (const seriesMatchItem of matchData.series) {
let seriesItem = Database.series.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(seriesMatchItem.series))
if (!seriesItem) {
seriesItem = new Series()
seriesItem.setData({ name: seriesMatchItem.series })
seriesItem.setData({ name: seriesMatchItem.series }, libraryItem.libraryId)
await Database.createSeries(seriesItem)
SocketAuthority.emitter('series_added', seriesItem.toJSON())
}

View File

@ -9,8 +9,8 @@ const oldDbIdMap = {
libraries: {},
libraryFolders: {},
libraryItems: {},
authors: {},
series: {},
authors: {}, // key is (new) library id with another map of author ids
series: {}, // key is (new) library id with another map of series ids
collections: {},
podcastEpisodes: {},
books: {}, // key is library item id
@ -98,10 +98,10 @@ function migrateBook(oldLibraryItem, LibraryItem) {
// Migrate BookAuthors
//
for (const oldBookAuthor of oldBook.metadata.authors) {
if (oldDbIdMap.authors[oldBookAuthor.id]) {
if (oldDbIdMap.authors[LibraryItem.libraryId][oldBookAuthor.id]) {
newRecords.bookAuthor.push({
id: uuidv4(),
authorId: oldDbIdMap.authors[oldBookAuthor.id],
authorId: oldDbIdMap.authors[LibraryItem.libraryId][oldBookAuthor.id],
bookId: Book.id
})
} else {
@ -113,11 +113,11 @@ function migrateBook(oldLibraryItem, LibraryItem) {
// Migrate BookSeries
//
for (const oldBookSeries of oldBook.metadata.series) {
if (oldDbIdMap.series[oldBookSeries.id]) {
if (oldDbIdMap.series[LibraryItem.libraryId][oldBookSeries.id]) {
const BookSeries = {
id: uuidv4(),
sequence: oldBookSeries.sequence,
seriesId: oldDbIdMap.series[oldBookSeries.id],
seriesId: oldDbIdMap.series[LibraryItem.libraryId][oldBookSeries.id],
bookId: Book.id
}
newRecords.bookSeries.push(BookSeries)
@ -297,8 +297,22 @@ function migrateLibraries(oldLibraries) {
}
}
function migrateAuthors(oldAuthors) {
function migrateAuthors(oldAuthors, oldLibraryItems) {
for (const oldAuthor of oldAuthors) {
// Get an array of NEW library ids that have this author
const librariesWithThisAuthor = [...new Set(oldLibraryItems.map(li => {
if (!li.media.metadata.authors?.some(au => au.id === oldAuthor.id)) return null
if (!oldDbIdMap.libraries[li.libraryId]) {
Logger.warn(`[dbMigration] Authors library id ${li.libraryId} was not migrated`)
}
return oldDbIdMap.libraries[li.libraryId]
}).filter(lid => lid))]
if (!librariesWithThisAuthor.length) {
Logger.error(`[dbMigration] Author ${oldAuthor.name} was not found in any libraries`)
}
for (const libraryId of librariesWithThisAuthor) {
const Author = {
id: uuidv4(),
name: oldAuthor.name,
@ -306,25 +320,44 @@ function migrateAuthors(oldAuthors) {
description: oldAuthor.description,
imagePath: oldAuthor.imagePath,
createdAt: oldAuthor.addedAt || Date.now(),
updatedAt: oldAuthor.updatedAt || Date.now()
updatedAt: oldAuthor.updatedAt || Date.now(),
libraryId
}
oldDbIdMap.authors[oldAuthor.id] = Author.id
if (!oldDbIdMap.authors[libraryId]) oldDbIdMap.authors[libraryId] = {}
oldDbIdMap.authors[libraryId][oldAuthor.id] = Author.id
newRecords.author.push(Author)
}
}
}
function migrateSeries(oldSerieses) {
function migrateSeries(oldSerieses, oldLibraryItems) {
// Originaly series were shared between libraries if they had the same name
// Series will be separate between libraries
for (const oldSeries of oldSerieses) {
// Get an array of NEW library ids that have this series
const librariesWithThisSeries = [...new Set(oldLibraryItems.map(li => {
if (!li.media.metadata.series?.some(se => se.id === oldSeries.id)) return null
return oldDbIdMap.libraries[li.libraryId]
}).filter(lid => lid))]
if (!librariesWithThisSeries.length) {
Logger.error(`[dbMigration] Series ${oldSeries.name} was not found in any libraries`)
}
for (const libraryId of librariesWithThisSeries) {
const Series = {
id: uuidv4(),
name: oldSeries.name,
description: oldSeries.description || null,
createdAt: oldSeries.addedAt || Date.now(),
updatedAt: oldSeries.updatedAt || Date.now()
updatedAt: oldSeries.updatedAt || Date.now(),
libraryId
}
oldDbIdMap.series[oldSeries.id] = Series.id
if (!oldDbIdMap.series[libraryId]) oldDbIdMap.series[libraryId] = {}
oldDbIdMap.series[libraryId][oldSeries.id] = Series.id
newRecords.series.push(Series)
}
}
}
function migrateUsers(oldUsers) {
@ -615,7 +648,14 @@ function migrateFeeds(oldFeeds) {
} else if (oldFeed.entityType === 'libraryItem') {
entityId = oldDbIdMap.libraryItems[oldFeed.entityId]
} else if (oldFeed.entityType === 'series') {
entityId = oldDbIdMap.series[oldFeed.entityId]
// Series were split to be per library
// This will use the first series it finds
for (const libraryId in oldDbIdMap.series) {
if (oldDbIdMap.series[libraryId][oldFeed.entityId]) {
entityId = oldDbIdMap.series[libraryId][oldFeed.entityId]
break
}
}
}
if (!entityId) {
@ -719,9 +759,9 @@ module.exports.migrate = async (DatabaseModels) => {
const start = Date.now()
migrateSettings(data.settings)
migrateAuthors(data.authors)
migrateSeries(data.series)
migrateLibraries(data.libraries)
migrateAuthors(data.authors, data.libraryItems)
migrateSeries(data.series, data.libraryItems)
migrateLibraryItems(data.libraryItems)
migrateUsers(data.users)
migrateSessions(data.sessions)