2023-07-05 01:14:44 +02:00
|
|
|
const Path = require('path')
|
|
|
|
const { Sequelize } = require('sequelize')
|
|
|
|
|
|
|
|
const packageJson = require('../package.json')
|
|
|
|
const fs = require('./libs/fsExtra')
|
|
|
|
const Logger = require('./Logger')
|
|
|
|
|
|
|
|
const dbMigration = require('./utils/migrations/dbMigration')
|
2023-07-22 22:32:20 +02:00
|
|
|
const Auth = require('./Auth')
|
2023-07-05 01:14:44 +02:00
|
|
|
|
|
|
|
class Database {
|
|
|
|
constructor() {
|
|
|
|
this.sequelize = null
|
|
|
|
this.dbPath = null
|
2023-07-08 21:40:49 +02:00
|
|
|
this.isNew = false // New absdatabase.sqlite created
|
2023-07-22 22:32:20 +02:00
|
|
|
this.hasRootUser = false // Used to show initialization page in web ui
|
2023-07-05 01:14:44 +02:00
|
|
|
|
|
|
|
// Temporarily using format of old DB
|
2023-07-09 21:22:30 +02:00
|
|
|
// TODO: below data should be loaded from the DB as needed
|
2023-07-05 01:14:44 +02:00
|
|
|
this.libraryItems = []
|
|
|
|
this.settings = []
|
|
|
|
this.authors = []
|
|
|
|
this.series = []
|
|
|
|
|
2023-08-13 22:10:26 +02:00
|
|
|
// Cached library filter data
|
|
|
|
this.libraryFilterData = {}
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
this.serverSettings = null
|
|
|
|
this.notificationSettings = null
|
|
|
|
this.emailSettings = null
|
|
|
|
}
|
|
|
|
|
|
|
|
get models() {
|
|
|
|
return this.sequelize?.models || {}
|
|
|
|
}
|
|
|
|
|
2023-08-18 21:40:36 +02:00
|
|
|
/** @type {typeof import('./models/Author')} */
|
|
|
|
get authorModel() {
|
|
|
|
return this.models.author
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @type {typeof import('./models/Series')} */
|
|
|
|
get seriesModel() {
|
|
|
|
return this.models.series
|
|
|
|
}
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
async checkHasDb() {
|
|
|
|
if (!await fs.pathExists(this.dbPath)) {
|
2023-07-08 21:40:49 +02:00
|
|
|
Logger.info(`[Database] absdatabase.sqlite not found at ${this.dbPath}`)
|
2023-07-05 01:14:44 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
async init(force = false) {
|
2023-07-08 21:40:49 +02:00
|
|
|
this.dbPath = Path.join(global.ConfigPath, 'absdatabase.sqlite')
|
2023-07-05 01:14:44 +02:00
|
|
|
|
|
|
|
// First check if this is a new database
|
|
|
|
this.isNew = !(await this.checkHasDb()) || force
|
|
|
|
|
|
|
|
if (!await this.connect()) {
|
|
|
|
throw new Error('Database connection failed')
|
|
|
|
}
|
|
|
|
|
|
|
|
await this.buildModels(force)
|
2023-07-14 21:50:37 +02:00
|
|
|
Logger.info(`[Database] Db initialized with models:`, Object.keys(this.sequelize.models).join(', '))
|
2023-07-05 01:14:44 +02:00
|
|
|
|
2023-07-08 21:40:49 +02:00
|
|
|
await this.loadData()
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async connect() {
|
|
|
|
Logger.info(`[Database] Initializing db at "${this.dbPath}"`)
|
|
|
|
this.sequelize = new Sequelize({
|
|
|
|
dialect: 'sqlite',
|
|
|
|
storage: this.dbPath,
|
2023-07-22 18:30:29 +02:00
|
|
|
logging: false,
|
|
|
|
transactionType: 'IMMEDIATE'
|
2023-07-05 01:14:44 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
// Helper function
|
|
|
|
this.sequelize.uppercaseFirst = str => str ? `${str[0].toUpperCase()}${str.substr(1)}` : ''
|
|
|
|
|
|
|
|
try {
|
|
|
|
await this.sequelize.authenticate()
|
|
|
|
Logger.info(`[Database] Db connection was successful`)
|
|
|
|
return true
|
|
|
|
} catch (error) {
|
|
|
|
Logger.error(`[Database] Failed to connect to db`, error)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-08 21:40:49 +02:00
|
|
|
async disconnect() {
|
|
|
|
Logger.info(`[Database] Disconnecting sqlite db`)
|
|
|
|
await this.sequelize.close()
|
|
|
|
this.sequelize = null
|
|
|
|
}
|
|
|
|
|
|
|
|
async reconnect() {
|
|
|
|
Logger.info(`[Database] Reconnecting sqlite db`)
|
|
|
|
await this.init()
|
|
|
|
}
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
buildModels(force = false) {
|
2023-08-16 23:38:48 +02:00
|
|
|
require('./models/User').init(this.sequelize)
|
2023-08-16 01:03:43 +02:00
|
|
|
require('./models/Library').init(this.sequelize)
|
|
|
|
require('./models/LibraryFolder').init(this.sequelize)
|
|
|
|
require('./models/Book').init(this.sequelize)
|
2023-08-16 23:38:48 +02:00
|
|
|
require('./models/Podcast').init(this.sequelize)
|
|
|
|
require('./models/PodcastEpisode').init(this.sequelize)
|
|
|
|
require('./models/LibraryItem').init(this.sequelize)
|
|
|
|
require('./models/MediaProgress').init(this.sequelize)
|
|
|
|
require('./models/Series').init(this.sequelize)
|
2023-08-16 01:03:43 +02:00
|
|
|
require('./models/BookSeries').init(this.sequelize)
|
2023-08-15 01:22:38 +02:00
|
|
|
require('./models/Author').init(this.sequelize)
|
2023-08-16 01:03:43 +02:00
|
|
|
require('./models/BookAuthor').init(this.sequelize)
|
|
|
|
require('./models/Collection').init(this.sequelize)
|
|
|
|
require('./models/CollectionBook').init(this.sequelize)
|
2023-08-16 23:38:48 +02:00
|
|
|
require('./models/Playlist').init(this.sequelize)
|
|
|
|
require('./models/PlaylistMediaItem').init(this.sequelize)
|
2023-08-16 01:03:43 +02:00
|
|
|
require('./models/Device').init(this.sequelize)
|
2023-08-16 23:38:48 +02:00
|
|
|
require('./models/PlaybackSession').init(this.sequelize)
|
2023-08-16 01:03:43 +02:00
|
|
|
require('./models/Feed').init(this.sequelize)
|
|
|
|
require('./models/FeedEpisode').init(this.sequelize)
|
2023-08-16 23:38:48 +02:00
|
|
|
require('./models/Setting').init(this.sequelize)
|
2023-07-05 01:14:44 +02:00
|
|
|
|
2023-07-06 01:18:37 +02:00
|
|
|
return this.sequelize.sync({ force, alter: false })
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
|
2023-07-21 23:59:00 +02:00
|
|
|
/**
|
|
|
|
* Compare two server versions
|
|
|
|
* @param {string} v1
|
|
|
|
* @param {string} v2
|
|
|
|
* @returns {-1|0|1} 1 if v1 > v2
|
|
|
|
*/
|
|
|
|
compareVersions(v1, v2) {
|
|
|
|
if (!v1 || !v2) return 0
|
|
|
|
return v1.localeCompare(v2, undefined, { numeric: true, sensitivity: "case", caseFirst: "upper" })
|
|
|
|
}
|
|
|
|
|
2023-07-19 22:36:18 +02:00
|
|
|
/**
|
|
|
|
* Checks if migration to sqlite db is necessary & runs migration.
|
|
|
|
*
|
|
|
|
* Check if version was upgraded and run any version specific migrations.
|
|
|
|
*
|
|
|
|
* Loads most of the data from the database. This is a temporary solution.
|
|
|
|
*/
|
2023-07-08 21:40:49 +02:00
|
|
|
async loadData() {
|
|
|
|
if (this.isNew && await dbMigration.checkShouldMigrate()) {
|
2023-07-05 01:14:44 +02:00
|
|
|
Logger.info(`[Database] New database was created and old database was detected - migrating old to new`)
|
|
|
|
await dbMigration.migrate(this.models)
|
|
|
|
}
|
|
|
|
|
|
|
|
const startTime = Date.now()
|
|
|
|
|
2023-07-16 22:05:51 +02:00
|
|
|
const settingsData = await this.models.setting.getOldSettings()
|
|
|
|
this.settings = settingsData.settings
|
|
|
|
this.emailSettings = settingsData.emailSettings
|
|
|
|
this.serverSettings = settingsData.serverSettings
|
|
|
|
this.notificationSettings = settingsData.notificationSettings
|
|
|
|
global.ServerSettings = this.serverSettings.toJSON()
|
|
|
|
|
|
|
|
// Version specific migrations
|
2023-07-30 18:09:49 +02:00
|
|
|
if (this.serverSettings.version === '2.3.0' && this.compareVersions(packageJson.version, '2.3.0') == 1) {
|
2023-07-16 22:05:51 +02:00
|
|
|
await dbMigration.migrationPatch(this)
|
2023-07-29 01:03:31 +02:00
|
|
|
}
|
2023-07-30 18:09:49 +02:00
|
|
|
if (['2.3.0', '2.3.1', '2.3.2', '2.3.3'].includes(this.serverSettings.version) && this.compareVersions(packageJson.version, '2.3.3') >= 0) {
|
2023-07-21 23:59:00 +02:00
|
|
|
await dbMigration.migrationPatch2(this)
|
2023-07-16 22:05:51 +02:00
|
|
|
}
|
|
|
|
|
2023-07-19 22:36:18 +02:00
|
|
|
Logger.info(`[Database] Loading db data...`)
|
|
|
|
|
|
|
|
this.libraryItems = await this.models.libraryItem.loadAllLibraryItems()
|
|
|
|
Logger.info(`[Database] Loaded ${this.libraryItems.length} library items`)
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
this.authors = await this.models.author.getOldAuthors()
|
2023-07-19 22:36:18 +02:00
|
|
|
Logger.info(`[Database] Loaded ${this.authors.length} authors`)
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
this.series = await this.models.series.getAllOldSeries()
|
2023-07-19 22:36:18 +02:00
|
|
|
Logger.info(`[Database] Loaded ${this.series.length} series`)
|
2023-07-05 01:14:44 +02:00
|
|
|
|
2023-07-22 22:32:20 +02:00
|
|
|
// Set if root user has been created
|
|
|
|
this.hasRootUser = await this.models.user.getHasRootUser()
|
|
|
|
|
2023-07-19 22:36:18 +02:00
|
|
|
Logger.info(`[Database] Db data loaded in ${((Date.now() - startTime) / 1000).toFixed(2)}s`)
|
2023-07-05 01:14:44 +02:00
|
|
|
|
|
|
|
if (packageJson.version !== this.serverSettings.version) {
|
|
|
|
Logger.info(`[Database] Server upgrade detected from ${this.serverSettings.version} to ${packageJson.version}`)
|
|
|
|
this.serverSettings.version = packageJson.version
|
|
|
|
await this.updateServerSettings()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-22 22:32:20 +02:00
|
|
|
/**
|
|
|
|
* Create root user
|
|
|
|
* @param {string} username
|
|
|
|
* @param {string} pash
|
|
|
|
* @param {Auth} auth
|
|
|
|
* @returns {boolean} true if created
|
|
|
|
*/
|
|
|
|
async createRootUser(username, pash, auth) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-22 22:32:20 +02:00
|
|
|
await this.models.user.createRootUser(username, pash, auth)
|
|
|
|
this.hasRootUser = true
|
|
|
|
return true
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
updateServerSettings() {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
global.ServerSettings = this.serverSettings.toJSON()
|
|
|
|
return this.updateSetting(this.serverSettings)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateSetting(settings) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.setting.updateSettingObj(settings.toJSON())
|
|
|
|
}
|
|
|
|
|
|
|
|
async createUser(oldUser) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.user.createFromOld(oldUser)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
updateUser(oldUser) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.user.updateFromOld(oldUser)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateBulkUsers(oldUsers) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return Promise.all(oldUsers.map(u => this.updateUser(u)))
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeUser(userId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.user.removeById(userId)
|
|
|
|
}
|
|
|
|
|
|
|
|
upsertMediaProgress(oldMediaProgress) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.mediaProgress.upsertFromOld(oldMediaProgress)
|
|
|
|
}
|
|
|
|
|
|
|
|
removeMediaProgress(mediaProgressId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.mediaProgress.removeById(mediaProgressId)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateBulkBooks(oldBooks) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return Promise.all(oldBooks.map(oldBook => this.models.book.saveFromOld(oldBook)))
|
|
|
|
}
|
|
|
|
|
|
|
|
async createLibrary(oldLibrary) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.library.createFromOld(oldLibrary)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateLibrary(oldLibrary) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.library.updateFromOld(oldLibrary)
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeLibrary(libraryId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.library.removeById(libraryId)
|
|
|
|
}
|
|
|
|
|
|
|
|
createBulkCollectionBooks(collectionBooks) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.collectionBook.bulkCreate(collectionBooks)
|
|
|
|
}
|
|
|
|
|
|
|
|
createPlaylistMediaItem(playlistMediaItem) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playlistMediaItem.create(playlistMediaItem)
|
|
|
|
}
|
|
|
|
|
|
|
|
createBulkPlaylistMediaItems(playlistMediaItems) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playlistMediaItem.bulkCreate(playlistMediaItems)
|
|
|
|
}
|
|
|
|
|
|
|
|
getLibraryItem(libraryItemId) {
|
2023-07-16 22:05:51 +02:00
|
|
|
if (!this.sequelize || !libraryItemId) return false
|
|
|
|
|
|
|
|
// Temp support for old library item ids from mobile
|
|
|
|
if (libraryItemId.startsWith('li_')) return this.libraryItems.find(li => li.oldLibraryItemId === libraryItemId)
|
|
|
|
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.libraryItems.find(li => li.id === libraryItemId)
|
|
|
|
}
|
|
|
|
|
|
|
|
async createLibraryItem(oldLibraryItem) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-22 14:50:47 +02:00
|
|
|
await oldLibraryItem.saveMetadata()
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.libraryItem.fullCreateFromOld(oldLibraryItem)
|
|
|
|
this.libraryItems.push(oldLibraryItem)
|
|
|
|
}
|
|
|
|
|
2023-07-22 14:50:47 +02:00
|
|
|
async updateLibraryItem(oldLibraryItem) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-22 14:50:47 +02:00
|
|
|
await oldLibraryItem.saveMetadata()
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.libraryItem.fullUpdateFromOld(oldLibraryItem)
|
|
|
|
}
|
|
|
|
|
|
|
|
async updateBulkLibraryItems(oldLibraryItems) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
let updatesMade = 0
|
|
|
|
for (const oldLibraryItem of oldLibraryItems) {
|
2023-07-22 14:50:47 +02:00
|
|
|
await oldLibraryItem.saveMetadata()
|
2023-07-05 01:14:44 +02:00
|
|
|
const hasUpdates = await this.models.libraryItem.fullUpdateFromOld(oldLibraryItem)
|
2023-07-22 14:50:47 +02:00
|
|
|
if (hasUpdates) {
|
|
|
|
updatesMade++
|
|
|
|
}
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
return updatesMade
|
|
|
|
}
|
|
|
|
|
|
|
|
async createBulkLibraryItems(oldLibraryItems) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
for (const oldLibraryItem of oldLibraryItems) {
|
2023-07-22 14:50:47 +02:00
|
|
|
await oldLibraryItem.saveMetadata()
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.libraryItem.fullCreateFromOld(oldLibraryItem)
|
|
|
|
this.libraryItems.push(oldLibraryItem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeLibraryItem(libraryItemId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.libraryItem.removeById(libraryItemId)
|
|
|
|
this.libraryItems = this.libraryItems.filter(li => li.id !== libraryItemId)
|
|
|
|
}
|
|
|
|
|
2023-07-06 01:18:37 +02:00
|
|
|
async createFeed(oldFeed) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-06 01:18:37 +02:00
|
|
|
await this.models.feed.fullCreateFromOld(oldFeed)
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
updateFeed(oldFeed) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-06 01:18:37 +02:00
|
|
|
return this.models.feed.fullUpdateFromOld(oldFeed)
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async removeFeed(feedId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.feed.removeById(feedId)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateSeries(oldSeries) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.series.updateFromOld(oldSeries)
|
|
|
|
}
|
|
|
|
|
|
|
|
async createSeries(oldSeries) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.series.createFromOld(oldSeries)
|
|
|
|
this.series.push(oldSeries)
|
|
|
|
}
|
|
|
|
|
|
|
|
async createBulkSeries(oldSeriesObjs) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.series.createBulkFromOld(oldSeriesObjs)
|
|
|
|
this.series.push(...oldSeriesObjs)
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeSeries(seriesId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.series.removeById(seriesId)
|
|
|
|
this.series = this.series.filter(se => se.id !== seriesId)
|
|
|
|
}
|
|
|
|
|
|
|
|
async createAuthor(oldAuthor) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-16 22:29:43 +02:00
|
|
|
await this.models.author.createFromOld(oldAuthor)
|
2023-07-05 01:14:44 +02:00
|
|
|
this.authors.push(oldAuthor)
|
|
|
|
}
|
|
|
|
|
|
|
|
async createBulkAuthors(oldAuthors) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.author.createBulkFromOld(oldAuthors)
|
|
|
|
this.authors.push(...oldAuthors)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateAuthor(oldAuthor) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.author.updateFromOld(oldAuthor)
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeAuthor(authorId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.author.removeById(authorId)
|
|
|
|
this.authors = this.authors.filter(au => au.id !== authorId)
|
|
|
|
}
|
|
|
|
|
|
|
|
async createBulkBookAuthors(bookAuthors) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
await this.models.bookAuthor.bulkCreate(bookAuthors)
|
|
|
|
this.authors.push(...bookAuthors)
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeBulkBookAuthors(authorId = null, bookId = null) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
if (!authorId && !bookId) return
|
|
|
|
await this.models.bookAuthor.removeByIds(authorId, bookId)
|
|
|
|
this.authors = this.authors.filter(au => {
|
|
|
|
if (authorId && au.authorId !== authorId) return true
|
|
|
|
if (bookId && au.bookId !== bookId) return true
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
getPlaybackSessions(where = null) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playbackSession.getOldPlaybackSessions(where)
|
|
|
|
}
|
|
|
|
|
|
|
|
getPlaybackSession(sessionId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playbackSession.getById(sessionId)
|
|
|
|
}
|
|
|
|
|
|
|
|
createPlaybackSession(oldSession) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playbackSession.createFromOld(oldSession)
|
|
|
|
}
|
|
|
|
|
|
|
|
updatePlaybackSession(oldSession) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playbackSession.updateFromOld(oldSession)
|
|
|
|
}
|
|
|
|
|
|
|
|
removePlaybackSession(sessionId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.playbackSession.removeById(sessionId)
|
|
|
|
}
|
|
|
|
|
|
|
|
getDeviceByDeviceId(deviceId) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.device.getOldDeviceByDeviceId(deviceId)
|
|
|
|
}
|
|
|
|
|
|
|
|
updateDevice(oldDevice) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.device.updateFromOld(oldDevice)
|
|
|
|
}
|
|
|
|
|
|
|
|
createDevice(oldDevice) {
|
2023-07-08 21:40:49 +02:00
|
|
|
if (!this.sequelize) return false
|
2023-07-05 01:14:44 +02:00
|
|
|
return this.models.device.createFromOld(oldDevice)
|
|
|
|
}
|
2023-08-13 22:10:26 +02:00
|
|
|
|
|
|
|
removeTagFromFilterData(tag) {
|
|
|
|
for (const libraryId in this.libraryFilterData) {
|
|
|
|
this.libraryFilterData[libraryId].tags = this.libraryFilterData[libraryId].tags.filter(t => t !== tag)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addTagToFilterData(tag) {
|
|
|
|
for (const libraryId in this.libraryFilterData) {
|
|
|
|
if (!this.libraryFilterData[libraryId].tags.includes(tag)) {
|
|
|
|
this.libraryFilterData[libraryId].tags.push(tag)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
removeGenreFromFilterData(genre) {
|
|
|
|
for (const libraryId in this.libraryFilterData) {
|
|
|
|
this.libraryFilterData[libraryId].genres = this.libraryFilterData[libraryId].genres.filter(g => g !== genre)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addGenreToFilterData(genre) {
|
|
|
|
for (const libraryId in this.libraryFilterData) {
|
|
|
|
if (!this.libraryFilterData[libraryId].genres.includes(genre)) {
|
|
|
|
this.libraryFilterData[libraryId].genres.push(genre)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-14 00:45:53 +02:00
|
|
|
|
|
|
|
removeNarratorFromFilterData(narrator) {
|
|
|
|
for (const libraryId in this.libraryFilterData) {
|
|
|
|
this.libraryFilterData[libraryId].narrators = this.libraryFilterData[libraryId].narrators.filter(n => n !== narrator)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addNarratorToFilterData(narrator) {
|
|
|
|
for (const libraryId in this.libraryFilterData) {
|
|
|
|
if (!this.libraryFilterData[libraryId].narrators.includes(narrator)) {
|
|
|
|
this.libraryFilterData[libraryId].narrators.push(narrator)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-18 21:40:36 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2023-07-05 01:14:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = new Database()
|