mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-06-03 13:44:36 -04:00
Update model casing & associations
This commit is contained in:
parent
2131a65299
commit
54ca58e610
@ -12,12 +12,12 @@ class Database {
|
|||||||
return this.sequelize?.models || {}
|
return this.sequelize?.models || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init(force = false) {
|
||||||
if (!await this.connect()) {
|
if (!await this.connect()) {
|
||||||
throw new Error('Database connection failed')
|
throw new Error('Database connection failed')
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.buildModels()
|
await this.buildModels(force)
|
||||||
Logger.info(`[Database] Db initialized`, Object.keys(this.sequelize.models))
|
Logger.info(`[Database] Db initialized`, Object.keys(this.sequelize.models))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +30,9 @@ class Database {
|
|||||||
logging: false
|
logging: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Helper function
|
||||||
|
this.sequelize.uppercaseFirst = str => str ? `${str[0].toUpperCase()}${str.substr(1)}` : ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.sequelize.authenticate()
|
await this.sequelize.authenticate()
|
||||||
Logger.info(`[Database] Db connection was successful`)
|
Logger.info(`[Database] Db connection was successful`)
|
||||||
@ -40,15 +43,15 @@ class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildModels() {
|
buildModels(force = false) {
|
||||||
require('./models/User')(this.sequelize)
|
require('./models/User')(this.sequelize)
|
||||||
require('./models/FileMetadata')(this.sequelize)
|
require('./models/FileMetadata')(this.sequelize)
|
||||||
require('./models/Library')(this.sequelize)
|
|
||||||
require('./models/LibraryFolder')(this.sequelize)
|
|
||||||
require('./models/LibraryItem')(this.sequelize)
|
|
||||||
require('./models/EBookFile')(this.sequelize)
|
require('./models/EBookFile')(this.sequelize)
|
||||||
require('./models/Book')(this.sequelize)
|
require('./models/Book')(this.sequelize)
|
||||||
require('./models/Podcast')(this.sequelize)
|
require('./models/Podcast')(this.sequelize)
|
||||||
|
require('./models/Library')(this.sequelize)
|
||||||
|
require('./models/LibraryFolder')(this.sequelize)
|
||||||
|
require('./models/LibraryItem')(this.sequelize)
|
||||||
require('./models/PodcastEpisode')(this.sequelize)
|
require('./models/PodcastEpisode')(this.sequelize)
|
||||||
require('./models/MediaProgress')(this.sequelize)
|
require('./models/MediaProgress')(this.sequelize)
|
||||||
require('./models/LibraryFile')(this.sequelize)
|
require('./models/LibraryFile')(this.sequelize)
|
||||||
@ -82,24 +85,7 @@ class Database {
|
|||||||
require('./models/Notification')(this.sequelize)
|
require('./models/Notification')(this.sequelize)
|
||||||
require('./models/UserPermission')(this.sequelize)
|
require('./models/UserPermission')(this.sequelize)
|
||||||
|
|
||||||
return this.sequelize.sync({ force: true })
|
return this.sequelize.sync({ force })
|
||||||
}
|
|
||||||
|
|
||||||
async createTestUser() {
|
|
||||||
const User = this.sequelize.models.User
|
|
||||||
|
|
||||||
let user = await User.findOne({
|
|
||||||
where: {
|
|
||||||
username: 'Tester'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
Logger.info(`[Database] Tester user was found`, user.toJSON())
|
|
||||||
} else {
|
|
||||||
user = await User.create({ username: 'Tester' })
|
|
||||||
Logger.info(`[Database] Created Tester user`, user.toJSON())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const Database = require('./Database')
|
|||||||
const SocketAuthority = require('./SocketAuthority')
|
const SocketAuthority = require('./SocketAuthority')
|
||||||
|
|
||||||
const ApiRouter = require('./routers/ApiRouter')
|
const ApiRouter = require('./routers/ApiRouter')
|
||||||
|
const ApiRouter2 = require('./routers/ApiRouter2')
|
||||||
const HlsRouter = require('./routers/HlsRouter')
|
const HlsRouter = require('./routers/HlsRouter')
|
||||||
const StaticRouter = require('./routers/StaticRouter')
|
const StaticRouter = require('./routers/StaticRouter')
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ class Server {
|
|||||||
|
|
||||||
// Routers
|
// Routers
|
||||||
this.apiRouter = new ApiRouter(this)
|
this.apiRouter = new ApiRouter(this)
|
||||||
|
|
||||||
this.hlsRouter = new HlsRouter(this.db, this.auth, this.playbackSessionManager)
|
this.hlsRouter = new HlsRouter(this.db, this.auth, this.playbackSessionManager)
|
||||||
this.staticRouter = new StaticRouter(this.db)
|
this.staticRouter = new StaticRouter(this.db)
|
||||||
|
|
||||||
@ -102,9 +104,9 @@ class Server {
|
|||||||
await this.playbackSessionManager.removeOrphanStreams()
|
await this.playbackSessionManager.removeOrphanStreams()
|
||||||
|
|
||||||
// TODO: Test new db connection
|
// TODO: Test new db connection
|
||||||
await Database.init()
|
const force = true
|
||||||
// await Database.createTestUser()
|
await Database.init(force)
|
||||||
await dbMigration3.migrate()
|
if (force) await dbMigration3.migrate()
|
||||||
|
|
||||||
const previousVersion = await this.db.checkPreviousVersion() // Returns null if same server version
|
const previousVersion = await this.db.checkPreviousVersion() // Returns null if same server version
|
||||||
if (previousVersion) {
|
if (previousVersion) {
|
||||||
@ -169,6 +171,7 @@ class Server {
|
|||||||
// Static folder
|
// Static folder
|
||||||
router.use(express.static(Path.join(global.appRoot, 'static')))
|
router.use(express.static(Path.join(global.appRoot, 'static')))
|
||||||
|
|
||||||
|
router.use('/api/v1', new ApiRouter2(this).router)
|
||||||
router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router)
|
router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router)
|
||||||
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
|
router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router)
|
||||||
router.use('/s', this.authMiddleware.bind(this), this.staticRouter.router)
|
router.use('/s', this.authMiddleware.bind(this), this.staticRouter.router)
|
||||||
|
192
server/controllers2/LibraryItemController.js
Normal file
192
server/controllers2/LibraryItemController.js
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
const Database = require('../Database')
|
||||||
|
|
||||||
|
class LibraryItemController {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
// Example get library item fully expanded or minified
|
||||||
|
async get(req, res) {
|
||||||
|
const key = req.query.minified == 1 ? 'minified' : 'full'
|
||||||
|
const include = {
|
||||||
|
minified: [
|
||||||
|
{
|
||||||
|
model: Database.models.book,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.models.audioTrack
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.genre,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.tag,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.person,
|
||||||
|
as: 'authors',
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.person,
|
||||||
|
as: 'narrators',
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.series,
|
||||||
|
through: {
|
||||||
|
attributes: ['sequence']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.bookChapter
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.eBookFile,
|
||||||
|
include: 'fileMetadata'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.podcast,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.models.podcastEpisode,
|
||||||
|
include: {
|
||||||
|
model: Database.models.audioTrack
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.genre,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.tag,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
full: [
|
||||||
|
{
|
||||||
|
model: Database.models.book,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.models.fileMetadata,
|
||||||
|
as: 'imageFile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.audioTrack,
|
||||||
|
include: {
|
||||||
|
model: Database.models.mediaFile,
|
||||||
|
include: [
|
||||||
|
'fileMetadata',
|
||||||
|
'mediaStreams'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.genre,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.tag,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.person,
|
||||||
|
as: 'authors',
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.person,
|
||||||
|
as: 'narrators',
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.series,
|
||||||
|
through: {
|
||||||
|
attributes: ['sequence']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.bookChapter
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.eBookFile,
|
||||||
|
include: 'fileMetadata'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.podcast,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.models.fileMetadata,
|
||||||
|
as: 'imageFile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.podcastEpisode,
|
||||||
|
include: {
|
||||||
|
model: Database.models.audioTrack,
|
||||||
|
include: {
|
||||||
|
model: Database.models.mediaFile,
|
||||||
|
include: [
|
||||||
|
'fileMetadata',
|
||||||
|
'mediaStreams'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.genre,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.tag,
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.libraryFile,
|
||||||
|
include: 'fileMetadata'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.models.libraryFolder,
|
||||||
|
include: 'library'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const LibraryItem = await Database.models.libraryItem.findByPk(req.params.id, {
|
||||||
|
include: include[key]
|
||||||
|
})
|
||||||
|
|
||||||
|
res.json(LibraryItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = new LibraryItemController()
|
@ -8,7 +8,7 @@ module.exports = (sequelize) => {
|
|||||||
class AudioBookmark extends Model {
|
class AudioBookmark extends Model {
|
||||||
getMediaItem(options) {
|
getMediaItem(options) {
|
||||||
if (!this.mediaItemType) return Promise.resolve(null)
|
if (!this.mediaItemType) return Promise.resolve(null)
|
||||||
const mixinMethodName = `get${this.mediaItemType}`
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}`
|
||||||
return this[mixinMethodName](options)
|
return this[mixinMethodName](options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,52 +19,57 @@ module.exports = (sequelize) => {
|
|||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
MediaItemId: DataTypes.UUIDV4,
|
mediaItemId: DataTypes.UUIDV4,
|
||||||
mediaItemType: DataTypes.STRING,
|
mediaItemType: DataTypes.STRING,
|
||||||
title: DataTypes.STRING,
|
title: DataTypes.STRING,
|
||||||
time: DataTypes.INTEGER
|
time: DataTypes.INTEGER
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'AudioBookmark'
|
modelName: 'audioBookmark'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { User, Book, PodcastEpisode } = sequelize.models
|
const { user, book, podcastEpisode } = sequelize.models
|
||||||
Book.hasMany(AudioBookmark, {
|
book.hasMany(AudioBookmark, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'Book'
|
mediaItemType: 'book'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
AudioBookmark.belongsTo(Book, { foreignKey: 'MediaItemId', constraints: false })
|
AudioBookmark.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
PodcastEpisode.hasMany(AudioBookmark, {
|
podcastEpisode.hasMany(AudioBookmark, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'PodcastEpisode'
|
mediaItemType: 'podcastEpisode'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
AudioBookmark.belongsTo(PodcastEpisode, { foreignKey: 'MediaItemId', constraints: false })
|
AudioBookmark.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
AudioBookmark.addHook('afterFind', findResult => {
|
AudioBookmark.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
if (!Array.isArray(findResult)) findResult = [findResult]
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
|
|
||||||
for (const instance of findResult) {
|
for (const instance of findResult) {
|
||||||
if (instance.mediaItemType === 'Book' && instance.Book !== undefined) {
|
if (instance.mediaItemType === 'book' && instance.book !== undefined) {
|
||||||
instance.MediaItem = instance.Book
|
instance.mediaItem = instance.book
|
||||||
} else if (instance.mediaItemType === 'PodcastEpisode' && instance.PodcastEpisode !== undefined) {
|
instance.dataValues.mediaItem = instance.dataValues.book
|
||||||
instance.MediaItem = instance.PodcastEpisode
|
} else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) {
|
||||||
|
instance.mediaItem = instance.podcastEpisode
|
||||||
|
instance.dataValues.mediaItem = instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
// To prevent mistakes:
|
// To prevent mistakes:
|
||||||
delete instance.Book
|
delete instance.book
|
||||||
delete instance.dataValues.Book
|
delete instance.dataValues.book
|
||||||
delete instance.PodcastEpisode
|
delete instance.podcastEpisode
|
||||||
delete instance.dataValues.PodcastEpisode
|
delete instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
User.hasMany(AudioBookmark)
|
user.hasMany(AudioBookmark)
|
||||||
AudioBookmark.belongsTo(User)
|
AudioBookmark.belongsTo(user)
|
||||||
|
|
||||||
return AudioBookmark
|
return AudioBookmark
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ module.exports = (sequelize) => {
|
|||||||
class AudioTrack extends Model {
|
class AudioTrack extends Model {
|
||||||
getMediaItem(options) {
|
getMediaItem(options) {
|
||||||
if (!this.mediaItemType) return Promise.resolve(null)
|
if (!this.mediaItemType) return Promise.resolve(null)
|
||||||
const mixinMethodName = `get${this.mediaItemType}`
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}`
|
||||||
return this[mixinMethodName](options)
|
return this[mixinMethodName](options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ module.exports = (sequelize) => {
|
|||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
MediaItemId: DataTypes.UUIDV4,
|
mediaItemId: DataTypes.UUIDV4,
|
||||||
mediaItemType: DataTypes.STRING,
|
mediaItemType: DataTypes.STRING,
|
||||||
index: DataTypes.INTEGER,
|
index: DataTypes.INTEGER,
|
||||||
startOffset: DataTypes.FLOAT,
|
startOffset: DataTypes.FLOAT,
|
||||||
@ -31,45 +31,50 @@ module.exports = (sequelize) => {
|
|||||||
discNumber: DataTypes.INTEGER
|
discNumber: DataTypes.INTEGER
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'AudioTrack'
|
modelName: 'audioTrack'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Book, PodcastEpisode, MediaFile } = sequelize.models
|
const { book, podcastEpisode, mediaFile } = sequelize.models
|
||||||
|
|
||||||
MediaFile.hasOne(AudioTrack)
|
mediaFile.hasOne(AudioTrack)
|
||||||
AudioTrack.belongsTo(MediaFile)
|
AudioTrack.belongsTo(mediaFile)
|
||||||
|
|
||||||
Book.hasMany(AudioTrack, {
|
book.hasMany(AudioTrack, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'Book'
|
mediaItemType: 'book'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
AudioTrack.belongsTo(Book, { foreignKey: 'MediaItemId', constraints: false })
|
AudioTrack.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
PodcastEpisode.hasOne(AudioTrack, {
|
podcastEpisode.hasOne(AudioTrack, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'PodcastEpisode'
|
mediaItemType: 'podcastEpisode'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
AudioTrack.belongsTo(PodcastEpisode, { foreignKey: 'MediaItemId', constraints: false })
|
AudioTrack.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
AudioTrack.addHook('afterFind', findResult => {
|
AudioTrack.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
if (!Array.isArray(findResult)) findResult = [findResult]
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
|
|
||||||
for (const instance of findResult) {
|
for (const instance of findResult) {
|
||||||
if (instance.mediaItemType === 'Book' && instance.Book !== undefined) {
|
if (instance.mediaItemType === 'book' && instance.book !== undefined) {
|
||||||
instance.MediaItem = instance.Book
|
instance.mediaItem = instance.book
|
||||||
} else if (instance.mediaItemType === 'PodcastEpisode' && instance.PodcastEpisode !== undefined) {
|
instance.dataValues.mediaItem = instance.dataValues.book
|
||||||
instance.MediaItem = instance.PodcastEpisode
|
} else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) {
|
||||||
|
instance.mediaItem = instance.podcastEpisode
|
||||||
|
instance.dataValues.mediaItem = instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
// To prevent mistakes:
|
// To prevent mistakes:
|
||||||
delete instance.Book
|
delete instance.book
|
||||||
delete instance.dataValues.Book
|
delete instance.dataValues.book
|
||||||
delete instance.PodcastEpisode
|
delete instance.podcastEpisode
|
||||||
delete instance.dataValues.PodcastEpisode
|
delete instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -23,18 +23,16 @@ module.exports = (sequelize) => {
|
|||||||
lastCoverSearch: DataTypes.DATE
|
lastCoverSearch: DataTypes.DATE
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Book'
|
modelName: 'book'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { LibraryItem, FileMetadata, EBookFile } = sequelize.models
|
const { fileMetadata, eBookFile } = sequelize.models
|
||||||
LibraryItem.hasOne(Book)
|
|
||||||
Book.belongsTo(LibraryItem)
|
|
||||||
|
|
||||||
FileMetadata.hasOne(Book, { foreignKey: 'ImageFileId ' })
|
fileMetadata.hasOne(Book, { foreignKey: 'imageFileId' })
|
||||||
Book.belongsTo(FileMetadata, { as: 'ImageFile', foreignKey: 'ImageFileId' }) // Ref: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-an-alias
|
Book.belongsTo(fileMetadata, { as: 'imageFile', foreignKey: 'imageFileId' }) // Ref: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-an-alias
|
||||||
|
|
||||||
EBookFile.hasOne(Book)
|
eBookFile.hasOne(Book)
|
||||||
Book.belongsTo(EBookFile)
|
Book.belongsTo(eBookFile)
|
||||||
|
|
||||||
return Book
|
return Book
|
||||||
}
|
}
|
@ -11,21 +11,21 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'BookAuthor',
|
modelName: 'bookAuthor',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Book, Person } = sequelize.models
|
const { book, person } = sequelize.models
|
||||||
Book.belongsToMany(Person, { through: BookAuthor })
|
book.belongsToMany(person, { through: BookAuthor, as: 'authors', otherKey: 'authorId' })
|
||||||
Person.belongsToMany(Book, { through: BookAuthor })
|
person.belongsToMany(book, { through: BookAuthor, foreignKey: 'authorId' })
|
||||||
|
|
||||||
Book.hasMany(BookAuthor)
|
book.hasMany(BookAuthor)
|
||||||
BookAuthor.belongsTo(Book)
|
BookAuthor.belongsTo(book)
|
||||||
|
|
||||||
Person.hasMany(BookAuthor)
|
person.hasMany(BookAuthor, { foreignKey: 'authorId' })
|
||||||
BookAuthor.belongsTo(Person)
|
BookAuthor.belongsTo(person, { as: 'author', foreignKey: 'authorId' })
|
||||||
|
|
||||||
return BookAuthor
|
return BookAuthor
|
||||||
}
|
}
|
@ -15,13 +15,13 @@ module.exports = (sequelize) => {
|
|||||||
end: DataTypes.FLOAT
|
end: DataTypes.FLOAT
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'BookChapter'
|
modelName: 'bookChapter'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Book } = sequelize.models
|
const { book } = sequelize.models
|
||||||
|
|
||||||
Book.hasMany(BookChapter)
|
book.hasMany(BookChapter)
|
||||||
BookChapter.belongsTo(Book)
|
BookChapter.belongsTo(book)
|
||||||
|
|
||||||
return BookChapter
|
return BookChapter
|
||||||
}
|
}
|
@ -11,21 +11,21 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'BookGenre',
|
modelName: 'bookGenre',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Book, Genre } = sequelize.models
|
const { book, genre } = sequelize.models
|
||||||
Book.belongsToMany(Genre, { through: BookGenre })
|
book.belongsToMany(genre, { through: BookGenre })
|
||||||
Genre.belongsToMany(Book, { through: BookGenre })
|
genre.belongsToMany(book, { through: BookGenre })
|
||||||
|
|
||||||
Book.hasMany(BookGenre)
|
book.hasMany(BookGenre)
|
||||||
BookGenre.belongsTo(Book)
|
BookGenre.belongsTo(book)
|
||||||
|
|
||||||
Genre.hasMany(BookGenre)
|
genre.hasMany(BookGenre)
|
||||||
BookGenre.belongsTo(Genre)
|
BookGenre.belongsTo(genre)
|
||||||
|
|
||||||
return BookGenre
|
return BookGenre
|
||||||
}
|
}
|
@ -11,21 +11,21 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'BookNarrator',
|
modelName: 'bookNarrator',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Book, Person } = sequelize.models
|
const { book, person } = sequelize.models
|
||||||
Book.belongsToMany(Person, { through: BookNarrator })
|
book.belongsToMany(person, { through: BookNarrator, as: 'narrators', otherKey: 'narratorId' })
|
||||||
Person.belongsToMany(Book, { through: BookNarrator })
|
person.belongsToMany(book, { through: BookNarrator, foreignKey: 'narratorId' })
|
||||||
|
|
||||||
Book.hasMany(BookNarrator)
|
book.hasMany(BookNarrator)
|
||||||
BookNarrator.belongsTo(Book)
|
BookNarrator.belongsTo(book)
|
||||||
|
|
||||||
Person.hasMany(BookNarrator)
|
person.hasMany(BookNarrator, { foreignKey: 'narratorId' })
|
||||||
BookNarrator.belongsTo(Person)
|
BookNarrator.belongsTo(person, { as: 'narrator', foreignKey: 'narratorId' })
|
||||||
|
|
||||||
return BookNarrator
|
return BookNarrator
|
||||||
}
|
}
|
@ -12,21 +12,21 @@ module.exports = (sequelize) => {
|
|||||||
sequence: DataTypes.STRING
|
sequence: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'BookSeries',
|
modelName: 'bookSeries',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Book, Series } = sequelize.models
|
const { book, series } = sequelize.models
|
||||||
Book.belongsToMany(Series, { through: BookSeries })
|
book.belongsToMany(series, { through: BookSeries })
|
||||||
Series.belongsToMany(Book, { through: BookSeries })
|
series.belongsToMany(book, { through: BookSeries })
|
||||||
|
|
||||||
Book.hasMany(BookSeries)
|
book.hasMany(BookSeries)
|
||||||
BookSeries.belongsTo(Book)
|
BookSeries.belongsTo(book)
|
||||||
|
|
||||||
Series.hasMany(BookSeries)
|
series.hasMany(BookSeries)
|
||||||
BookSeries.belongsTo(Series)
|
BookSeries.belongsTo(series)
|
||||||
|
|
||||||
return BookSeries
|
return BookSeries
|
||||||
}
|
}
|
@ -11,21 +11,21 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'BookTag',
|
modelName: 'bookTag',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Book, Tag } = sequelize.models
|
const { book, tag } = sequelize.models
|
||||||
Book.belongsToMany(Tag, { through: BookTag })
|
book.belongsToMany(tag, { through: BookTag })
|
||||||
Tag.belongsToMany(Book, { through: BookTag })
|
tag.belongsToMany(book, { through: BookTag })
|
||||||
|
|
||||||
Book.hasMany(BookTag)
|
book.hasMany(BookTag)
|
||||||
BookTag.belongsTo(Book)
|
BookTag.belongsTo(book)
|
||||||
|
|
||||||
Tag.hasMany(BookTag)
|
tag.hasMany(BookTag)
|
||||||
BookTag.belongsTo(Tag)
|
BookTag.belongsTo(tag)
|
||||||
|
|
||||||
return BookTag
|
return BookTag
|
||||||
}
|
}
|
@ -13,13 +13,13 @@ module.exports = (sequelize) => {
|
|||||||
description: DataTypes.TEXT
|
description: DataTypes.TEXT
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Collection'
|
modelName: 'collection'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Library } = sequelize.models
|
const { library } = sequelize.models
|
||||||
|
|
||||||
Library.hasMany(Collection)
|
library.hasMany(Collection)
|
||||||
Collection.belongsTo(Library)
|
Collection.belongsTo(library)
|
||||||
|
|
||||||
return Collection
|
return Collection
|
||||||
}
|
}
|
@ -13,20 +13,20 @@ module.exports = (sequelize) => {
|
|||||||
sequelize,
|
sequelize,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
updatedAt: false,
|
updatedAt: false,
|
||||||
modelName: 'CollectionBook'
|
modelName: 'collectionBook'
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Book, Collection } = sequelize.models
|
const { book, collection } = sequelize.models
|
||||||
Book.belongsToMany(Collection, { through: CollectionBook })
|
book.belongsToMany(collection, { through: CollectionBook })
|
||||||
Collection.belongsToMany(Book, { through: CollectionBook })
|
collection.belongsToMany(book, { through: CollectionBook })
|
||||||
|
|
||||||
Book.hasMany(CollectionBook)
|
book.hasMany(CollectionBook)
|
||||||
CollectionBook.belongsTo(Book)
|
CollectionBook.belongsTo(book)
|
||||||
|
|
||||||
Collection.hasMany(CollectionBook)
|
collection.hasMany(CollectionBook)
|
||||||
CollectionBook.belongsTo(Collection)
|
CollectionBook.belongsTo(collection)
|
||||||
|
|
||||||
return CollectionBook
|
return CollectionBook
|
||||||
}
|
}
|
@ -17,13 +17,13 @@ module.exports = (sequelize) => {
|
|||||||
deviceVersion: DataTypes.STRING // e.g. Browser version or Android SDK
|
deviceVersion: DataTypes.STRING // e.g. Browser version or Android SDK
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Device'
|
modelName: 'device'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { User } = sequelize.models
|
const { user } = sequelize.models
|
||||||
|
|
||||||
User.hasMany(Device)
|
user.hasMany(Device)
|
||||||
Device.belongsTo(User)
|
Device.belongsTo(user)
|
||||||
|
|
||||||
return Device
|
return Device
|
||||||
}
|
}
|
@ -8,16 +8,17 @@ module.exports = (sequelize) => {
|
|||||||
type: DataTypes.UUID,
|
type: DataTypes.UUID,
|
||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
}
|
},
|
||||||
|
format: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'EBookFile'
|
modelName: 'eBookFile'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { FileMetadata } = sequelize.models
|
const { fileMetadata } = sequelize.models
|
||||||
|
|
||||||
FileMetadata.hasOne(EBookFile, { foreignKey: 'FileMetadataId' })
|
fileMetadata.hasOne(EBookFile, { foreignKey: 'fileMetadataId' })
|
||||||
EBookFile.belongsTo(FileMetadata, { as: 'FileMetadata', foreignKey: 'FileMetadataId' })
|
EBookFile.belongsTo(fileMetadata, { as: 'fileMetadata', foreignKey: 'fileMetadataId' })
|
||||||
|
|
||||||
return EBookFile
|
return EBookFile
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ module.exports = (sequelize) => {
|
|||||||
class Feed extends Model {
|
class Feed extends Model {
|
||||||
getEntity(options) {
|
getEntity(options) {
|
||||||
if (!this.entityType) return Promise.resolve(null)
|
if (!this.entityType) return Promise.resolve(null)
|
||||||
const mixinMethodName = `get${this.entityType}`
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.entityType)}`
|
||||||
return this[mixinMethodName](options)
|
return this[mixinMethodName](options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ module.exports = (sequelize) => {
|
|||||||
},
|
},
|
||||||
slug: DataTypes.STRING,
|
slug: DataTypes.STRING,
|
||||||
entityType: DataTypes.STRING,
|
entityType: DataTypes.STRING,
|
||||||
EntityId: DataTypes.UUIDV4,
|
entityId: DataTypes.UUIDV4,
|
||||||
entityUpdatedAt: DataTypes.DATE,
|
entityUpdatedAt: DataTypes.DATE,
|
||||||
serverAddress: DataTypes.STRING,
|
serverAddress: DataTypes.STRING,
|
||||||
feedURL: DataTypes.STRING,
|
feedURL: DataTypes.STRING,
|
||||||
@ -38,72 +38,78 @@ module.exports = (sequelize) => {
|
|||||||
preventIndexing: DataTypes.BOOLEAN
|
preventIndexing: DataTypes.BOOLEAN
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Feed'
|
modelName: 'feed'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { User, LibraryItem, Collection, Series, Playlist } = sequelize.models
|
const { user, libraryItem, collection, series, playlist } = sequelize.models
|
||||||
|
|
||||||
User.hasMany(Feed)
|
user.hasMany(Feed)
|
||||||
Feed.belongsTo(User)
|
Feed.belongsTo(user)
|
||||||
|
|
||||||
LibraryItem.hasMany(Feed, {
|
libraryItem.hasMany(Feed, {
|
||||||
foreignKey: 'EntityId',
|
foreignKey: 'entityId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
entityType: 'LibraryItem'
|
entityType: 'libraryItem'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Feed.belongsTo(LibraryItem, { foreignKey: 'EntityId', constraints: false })
|
Feed.belongsTo(libraryItem, { foreignKey: 'entityId', constraints: false })
|
||||||
|
|
||||||
Collection.hasMany(Feed, {
|
collection.hasMany(Feed, {
|
||||||
foreignKey: 'EntityId',
|
foreignKey: 'entityId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
entityType: 'Collection'
|
entityType: 'collection'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Feed.belongsTo(Collection, { foreignKey: 'EntityId', constraints: false })
|
Feed.belongsTo(collection, { foreignKey: 'entityId', constraints: false })
|
||||||
|
|
||||||
Series.hasMany(Feed, {
|
series.hasMany(Feed, {
|
||||||
foreignKey: 'EntityId',
|
foreignKey: 'entityId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
entityType: 'Series'
|
entityType: 'series'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Feed.belongsTo(Series, { foreignKey: 'EntityId', constraints: false })
|
Feed.belongsTo(series, { foreignKey: 'entityId', constraints: false })
|
||||||
|
|
||||||
Playlist.hasMany(Feed, {
|
playlist.hasMany(Feed, {
|
||||||
foreignKey: 'EntityId',
|
foreignKey: 'entityId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
entityType: 'Playlist'
|
entityType: 'playlist'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Feed.belongsTo(Playlist, { foreignKey: 'EntityId', constraints: false })
|
Feed.belongsTo(playlist, { foreignKey: 'entityId', constraints: false })
|
||||||
|
|
||||||
Feed.addHook('afterFind', findResult => {
|
Feed.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
if (!Array.isArray(findResult)) findResult = [findResult]
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
for (const instance of findResult) {
|
for (const instance of findResult) {
|
||||||
if (instance.entityType === 'LibraryItem' && instance.LibraryItem !== undefined) {
|
if (instance.entityType === 'libraryItem' && instance.libraryItem !== undefined) {
|
||||||
instance.Entity = instance.LibraryItem
|
instance.entity = instance.libraryItem
|
||||||
} else if (instance.mediaItemType === 'Collection' && instance.Collection !== undefined) {
|
instance.dataValues.entity = instance.dataValues.libraryItem
|
||||||
instance.Entity = instance.Collection
|
} else if (instance.entityType === 'collection' && instance.collection !== undefined) {
|
||||||
} else if (instance.mediaItemType === 'Series' && instance.Series !== undefined) {
|
instance.entity = instance.collection
|
||||||
instance.Entity = instance.Series
|
instance.dataValues.entity = instance.dataValues.collection
|
||||||
} else if (instance.mediaItemType === 'Playlist' && instance.Playlist !== undefined) {
|
} else if (instance.entityType === 'series' && instance.series !== undefined) {
|
||||||
instance.Entity = instance.Playlist
|
instance.entity = instance.series
|
||||||
|
instance.dataValues.entity = instance.dataValues.series
|
||||||
|
} else if (instance.entityType === 'playlist' && instance.playlist !== undefined) {
|
||||||
|
instance.entity = instance.playlist
|
||||||
|
instance.dataValues.entity = instance.dataValues.playlist
|
||||||
}
|
}
|
||||||
|
|
||||||
// To prevent mistakes:
|
// To prevent mistakes:
|
||||||
delete instance.LibraryItem
|
delete instance.libraryItem
|
||||||
delete instance.dataValues.LibraryItem
|
delete instance.dataValues.libraryItem
|
||||||
delete instance.Collection
|
delete instance.collection
|
||||||
delete instance.dataValues.Collection
|
delete instance.dataValues.collection
|
||||||
delete instance.Series
|
delete instance.series
|
||||||
delete instance.dataValues.Series
|
delete instance.dataValues.series
|
||||||
delete instance.Playlist
|
delete instance.playlist
|
||||||
delete instance.dataValues.Playlist
|
delete instance.dataValues.playlist
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -25,13 +25,13 @@ module.exports = (sequelize) => {
|
|||||||
explicit: DataTypes.BOOLEAN
|
explicit: DataTypes.BOOLEAN
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'FeedEpisode'
|
modelName: 'feedEpisode'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Feed } = sequelize.models
|
const { feed } = sequelize.models
|
||||||
|
|
||||||
Feed.hasMany(FeedEpisode)
|
feed.hasMany(FeedEpisode)
|
||||||
FeedEpisode.belongsTo(Feed)
|
FeedEpisode.belongsTo(feed)
|
||||||
|
|
||||||
return FeedEpisode
|
return FeedEpisode
|
||||||
}
|
}
|
@ -21,10 +21,10 @@ module.exports = (sequelize) => {
|
|||||||
sequelize,
|
sequelize,
|
||||||
freezeTableName: true, // sequelize uses datum as singular of data
|
freezeTableName: true, // sequelize uses datum as singular of data
|
||||||
name: {
|
name: {
|
||||||
singular: 'FileMetadata',
|
singular: 'fileMetadata',
|
||||||
plural: 'FileMetadata'
|
plural: 'fileMetadata'
|
||||||
},
|
},
|
||||||
modelName: 'FileMetadata'
|
modelName: 'fileMetadata'
|
||||||
})
|
})
|
||||||
|
|
||||||
return FileMetadata
|
return FileMetadata
|
||||||
|
@ -13,7 +13,7 @@ module.exports = (sequelize) => {
|
|||||||
cleanName: DataTypes.STRING
|
cleanName: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Genre'
|
modelName: 'genre'
|
||||||
})
|
})
|
||||||
|
|
||||||
return Genre
|
return Genre
|
||||||
|
@ -18,7 +18,7 @@ module.exports = (sequelize) => {
|
|||||||
lastScanVersion: DataTypes.STRING
|
lastScanVersion: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Library'
|
modelName: 'library'
|
||||||
})
|
})
|
||||||
|
|
||||||
return Library
|
return Library
|
||||||
|
@ -11,15 +11,15 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'LibraryFile'
|
modelName: 'libraryFile'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { LibraryItem, FileMetadata } = sequelize.models
|
const { libraryItem, fileMetadata } = sequelize.models
|
||||||
LibraryItem.hasMany(LibraryFile)
|
libraryItem.hasMany(LibraryFile)
|
||||||
LibraryFile.belongsTo(LibraryItem)
|
LibraryFile.belongsTo(libraryItem)
|
||||||
|
|
||||||
FileMetadata.hasOne(LibraryFile, { foreignKey: 'FileMetadataId' })
|
fileMetadata.hasOne(LibraryFile, { foreignKey: 'fileMetadataId' })
|
||||||
LibraryFile.belongsTo(FileMetadata, { as: 'FileMetadata', foreignKey: 'FileMetadataId' })
|
LibraryFile.belongsTo(fileMetadata, { as: 'fileMetadata', foreignKey: 'fileMetadataId' })
|
||||||
|
|
||||||
return LibraryFile
|
return LibraryFile
|
||||||
}
|
}
|
@ -12,12 +12,12 @@ module.exports = (sequelize) => {
|
|||||||
path: DataTypes.STRING
|
path: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'LibraryFolder'
|
modelName: 'libraryFolder'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Library } = sequelize.models
|
const { library } = sequelize.models
|
||||||
Library.hasMany(LibraryFolder)
|
library.hasMany(LibraryFolder)
|
||||||
LibraryFolder.belongsTo(Library)
|
LibraryFolder.belongsTo(library)
|
||||||
|
|
||||||
return LibraryFolder
|
return LibraryFolder
|
||||||
}
|
}
|
@ -1,7 +1,13 @@
|
|||||||
const { DataTypes, Model } = require('sequelize')
|
const { DataTypes, Model } = require('sequelize')
|
||||||
|
|
||||||
module.exports = (sequelize) => {
|
module.exports = (sequelize) => {
|
||||||
class LibraryItem extends Model { }
|
class LibraryItem extends Model {
|
||||||
|
getMedia(options) {
|
||||||
|
if (!this.mediaType) return Promise.resolve(null)
|
||||||
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaType)}`
|
||||||
|
return this[mixinMethodName](options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LibraryItem.init({
|
LibraryItem.init({
|
||||||
id: {
|
id: {
|
||||||
@ -12,6 +18,7 @@ module.exports = (sequelize) => {
|
|||||||
ino: DataTypes.STRING,
|
ino: DataTypes.STRING,
|
||||||
path: DataTypes.STRING,
|
path: DataTypes.STRING,
|
||||||
relPath: DataTypes.STRING,
|
relPath: DataTypes.STRING,
|
||||||
|
mediaId: DataTypes.UUIDV4,
|
||||||
mediaType: DataTypes.STRING,
|
mediaType: DataTypes.STRING,
|
||||||
isFile: DataTypes.BOOLEAN,
|
isFile: DataTypes.BOOLEAN,
|
||||||
isMissing: DataTypes.BOOLEAN,
|
isMissing: DataTypes.BOOLEAN,
|
||||||
@ -23,12 +30,50 @@ module.exports = (sequelize) => {
|
|||||||
lastScanVersion: DataTypes.STRING
|
lastScanVersion: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'LibraryItem'
|
modelName: 'libraryItem'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { LibraryFolder } = sequelize.models
|
const { libraryFolder, book, podcast } = sequelize.models
|
||||||
LibraryFolder.hasMany(LibraryItem)
|
libraryFolder.hasMany(LibraryItem)
|
||||||
LibraryItem.belongsTo(LibraryFolder)
|
LibraryItem.belongsTo(libraryFolder)
|
||||||
|
|
||||||
|
book.hasOne(LibraryItem, {
|
||||||
|
foreignKey: 'mediaId',
|
||||||
|
constraints: false,
|
||||||
|
scope: {
|
||||||
|
mediaType: 'book'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
LibraryItem.belongsTo(book, { foreignKey: 'mediaId', constraints: false })
|
||||||
|
|
||||||
|
podcast.hasOne(LibraryItem, {
|
||||||
|
foreignKey: 'mediaId',
|
||||||
|
constraints: false,
|
||||||
|
scope: {
|
||||||
|
mediaType: 'podcast'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
LibraryItem.belongsTo(podcast, { foreignKey: 'mediaId', constraints: false })
|
||||||
|
|
||||||
|
LibraryItem.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
|
for (const instance of findResult) {
|
||||||
|
if (instance.mediaType === 'book' && instance.book !== undefined) {
|
||||||
|
instance.media = instance.book
|
||||||
|
instance.dataValues.media = instance.dataValues.book
|
||||||
|
} else if (instance.mediaType === 'podcast' && instance.podcast !== undefined) {
|
||||||
|
instance.media = instance.podcast
|
||||||
|
instance.dataValues.media = instance.dataValues.podcast
|
||||||
|
}
|
||||||
|
// To prevent mistakes:
|
||||||
|
delete instance.book
|
||||||
|
delete instance.dataValues.book
|
||||||
|
delete instance.podcast
|
||||||
|
delete instance.dataValues.podcast
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return LibraryItem
|
return LibraryItem
|
||||||
}
|
}
|
@ -13,13 +13,13 @@ module.exports = (sequelize) => {
|
|||||||
value: DataTypes.STRING
|
value: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'LibrarySetting'
|
modelName: 'librarySetting'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Library } = sequelize.models
|
const { library } = sequelize.models
|
||||||
|
|
||||||
Library.hasMany(LibrarySetting)
|
library.hasMany(LibrarySetting)
|
||||||
LibrarySetting.belongsTo(Library)
|
LibrarySetting.belongsTo(library)
|
||||||
|
|
||||||
return LibrarySetting
|
return LibrarySetting
|
||||||
}
|
}
|
@ -17,13 +17,13 @@ module.exports = (sequelize) => {
|
|||||||
tags: DataTypes.JSON
|
tags: DataTypes.JSON
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'MediaFile'
|
modelName: 'mediaFile'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { FileMetadata } = sequelize.models
|
const { fileMetadata } = sequelize.models
|
||||||
|
|
||||||
FileMetadata.hasOne(MediaFile, { foreignKey: 'FileMetadataId' })
|
fileMetadata.hasOne(MediaFile, { foreignKey: 'fileMetadataId' })
|
||||||
MediaFile.belongsTo(FileMetadata, { as: 'FileMetadata', foreignKey: 'FileMetadataId' })
|
MediaFile.belongsTo(fileMetadata, { as: 'fileMetadata', foreignKey: 'fileMetadataId' })
|
||||||
|
|
||||||
return MediaFile
|
return MediaFile
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ module.exports = (sequelize) => {
|
|||||||
class MediaProgress extends Model {
|
class MediaProgress extends Model {
|
||||||
getMediaItem(options) {
|
getMediaItem(options) {
|
||||||
if (!this.mediaItemType) return Promise.resolve(null)
|
if (!this.mediaItemType) return Promise.resolve(null)
|
||||||
const mixinMethodName = `get${this.mediaItemType}`
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}`
|
||||||
return this[mixinMethodName](options)
|
return this[mixinMethodName](options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ module.exports = (sequelize) => {
|
|||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
MediaItemId: DataTypes.UUIDV4,
|
mediaItemId: DataTypes.UUIDV4,
|
||||||
mediaItemType: DataTypes.STRING,
|
mediaItemType: DataTypes.STRING,
|
||||||
duration: DataTypes.FLOAT,
|
duration: DataTypes.FLOAT,
|
||||||
currentTime: DataTypes.FLOAT,
|
currentTime: DataTypes.FLOAT,
|
||||||
@ -28,46 +28,52 @@ module.exports = (sequelize) => {
|
|||||||
finishedAt: DataTypes.DATE
|
finishedAt: DataTypes.DATE
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'MediaProgress'
|
modelName: 'mediaProgress'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Book, PodcastEpisode, User } = sequelize.models
|
const { book, podcastEpisode, user } = sequelize.models
|
||||||
Book.hasMany(MediaProgress, {
|
|
||||||
foreignKey: 'MediaItemId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
mediaItemType: 'Book'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
MediaProgress.belongsTo(Book, { foreignKey: 'MediaItemId', constraints: false })
|
|
||||||
|
|
||||||
PodcastEpisode.hasMany(MediaProgress, {
|
book.hasMany(MediaProgress, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'PodcastEpisode'
|
mediaItemType: 'book'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
MediaProgress.belongsTo(PodcastEpisode, { foreignKey: 'MediaItemId', constraints: false })
|
MediaProgress.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
|
podcastEpisode.hasMany(MediaProgress, {
|
||||||
|
foreignKey: 'mediaItemId',
|
||||||
|
constraints: false,
|
||||||
|
scope: {
|
||||||
|
mediaItemType: 'podcastEpisode'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
MediaProgress.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
MediaProgress.addHook('afterFind', findResult => {
|
MediaProgress.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
if (!Array.isArray(findResult)) findResult = [findResult]
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
|
|
||||||
for (const instance of findResult) {
|
for (const instance of findResult) {
|
||||||
if (instance.mediaItemType === 'Book' && instance.Book !== undefined) {
|
if (instance.mediaItemType === 'book' && instance.book !== undefined) {
|
||||||
instance.MediaItem = instance.Book
|
instance.mediaItem = instance.book
|
||||||
} else if (instance.mediaItemType === 'PodcastEpisode' && instance.PodcastEpisode !== undefined) {
|
instance.dataValues.mediaItem = instance.dataValues.book
|
||||||
instance.MediaItem = instance.PodcastEpisode
|
} else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) {
|
||||||
|
instance.mediaItem = instance.podcastEpisode
|
||||||
|
instance.dataValues.mediaItem = instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
// To prevent mistakes:
|
// To prevent mistakes:
|
||||||
delete instance.Book
|
delete instance.book
|
||||||
delete instance.dataValues.Book
|
delete instance.dataValues.book
|
||||||
delete instance.PodcastEpisode
|
delete instance.podcastEpisode
|
||||||
delete instance.dataValues.PodcastEpisode
|
delete instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
User.hasMany(MediaProgress)
|
user.hasMany(MediaProgress)
|
||||||
MediaProgress.belongsTo(User)
|
MediaProgress.belongsTo(user)
|
||||||
|
|
||||||
return MediaProgress
|
return MediaProgress
|
||||||
}
|
}
|
@ -37,13 +37,13 @@ module.exports = (sequelize) => {
|
|||||||
chapters: DataTypes.JSON
|
chapters: DataTypes.JSON
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'MediaStream'
|
modelName: 'mediaStream'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { MediaFile } = sequelize.models
|
const { mediaFile } = sequelize.models
|
||||||
|
|
||||||
MediaFile.hasMany(MediaStream)
|
mediaFile.hasMany(MediaStream)
|
||||||
MediaStream.belongsTo(MediaFile)
|
MediaStream.belongsTo(mediaFile)
|
||||||
|
|
||||||
return MediaStream
|
return MediaStream
|
||||||
}
|
}
|
@ -22,7 +22,7 @@ module.exports = (sequelize) => {
|
|||||||
extraData: DataTypes.JSON
|
extraData: DataTypes.JSON
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Notification'
|
modelName: 'notification'
|
||||||
})
|
})
|
||||||
|
|
||||||
return Notification
|
return Notification
|
||||||
|
@ -15,12 +15,12 @@ module.exports = (sequelize) => {
|
|||||||
description: DataTypes.TEXT
|
description: DataTypes.TEXT
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Person'
|
modelName: 'person'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { FileMetadata } = sequelize.models
|
const { fileMetadata } = sequelize.models
|
||||||
FileMetadata.hasMany(Person, { foreignKey: 'ImageFileId' })
|
fileMetadata.hasMany(Person, { foreignKey: 'imageFileId' })
|
||||||
Person.belongsTo(FileMetadata, { as: 'ImageFile', foreignKey: 'ImageFileId' }) // Ref: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-an-alias
|
Person.belongsTo(fileMetadata, { as: 'imageFile', foreignKey: 'imageFileId' }) // Ref: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-an-alias
|
||||||
|
|
||||||
return Person
|
return Person
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ module.exports = (sequelize) => {
|
|||||||
class PlaybackSession extends Model {
|
class PlaybackSession extends Model {
|
||||||
getMediaItem(options) {
|
getMediaItem(options) {
|
||||||
if (!this.mediaItemType) return Promise.resolve(null)
|
if (!this.mediaItemType) return Promise.resolve(null)
|
||||||
const mixinMethodName = `get${this.mediaItemType}`
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}`
|
||||||
return this[mixinMethodName](options)
|
return this[mixinMethodName](options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -15,7 +15,7 @@ module.exports = (sequelize) => {
|
|||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
MediaItemId: DataTypes.UUIDV4,
|
mediaItemId: DataTypes.UUIDV4,
|
||||||
mediaItemType: DataTypes.STRING,
|
mediaItemType: DataTypes.STRING,
|
||||||
displayTitle: DataTypes.STRING,
|
displayTitle: DataTypes.STRING,
|
||||||
displayAuthor: DataTypes.STRING,
|
displayAuthor: DataTypes.STRING,
|
||||||
@ -27,48 +27,53 @@ module.exports = (sequelize) => {
|
|||||||
serverVersion: DataTypes.STRING
|
serverVersion: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'PlaybackSession'
|
modelName: 'playbackSession'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Book, PodcastEpisode, User, Device } = sequelize.models
|
const { book, podcastEpisode, user, device } = sequelize.models
|
||||||
|
|
||||||
User.hasMany(PlaybackSession)
|
user.hasMany(PlaybackSession)
|
||||||
PlaybackSession.belongsTo(User)
|
PlaybackSession.belongsTo(user)
|
||||||
|
|
||||||
Device.hasMany(PlaybackSession)
|
device.hasMany(PlaybackSession)
|
||||||
PlaybackSession.belongsTo(Device)
|
PlaybackSession.belongsTo(device)
|
||||||
|
|
||||||
Book.hasMany(PlaybackSession, {
|
book.hasMany(PlaybackSession, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'Book'
|
mediaItemType: 'book'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
PlaybackSession.belongsTo(Book, { foreignKey: 'MediaItemId', constraints: false })
|
PlaybackSession.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
PodcastEpisode.hasOne(PlaybackSession, {
|
podcastEpisode.hasOne(PlaybackSession, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'PodcastEpisode'
|
mediaItemType: 'podcastEpisode'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
PlaybackSession.belongsTo(PodcastEpisode, { foreignKey: 'MediaItemId', constraints: false })
|
PlaybackSession.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
PlaybackSession.addHook('afterFind', findResult => {
|
PlaybackSession.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
if (!Array.isArray(findResult)) findResult = [findResult]
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
|
|
||||||
for (const instance of findResult) {
|
for (const instance of findResult) {
|
||||||
if (instance.mediaItemType === 'Book' && instance.Book !== undefined) {
|
if (instance.mediaItemType === 'book' && instance.book !== undefined) {
|
||||||
instance.MediaItem = instance.Book
|
instance.mediaItem = instance.book
|
||||||
} else if (instance.mediaItemType === 'PodcastEpisode' && instance.PodcastEpisode !== undefined) {
|
instance.dataValues.mediaItem = instance.dataValues.book
|
||||||
instance.MediaItem = instance.PodcastEpisode
|
} else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) {
|
||||||
|
instance.mediaItem = instance.podcastEpisode
|
||||||
|
instance.dataValues.mediaItem = instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
// To prevent mistakes:
|
// To prevent mistakes:
|
||||||
delete instance.Book
|
delete instance.book
|
||||||
delete instance.dataValues.Book
|
delete instance.dataValues.book
|
||||||
delete instance.PodcastEpisode
|
delete instance.podcastEpisode
|
||||||
delete instance.dataValues.PodcastEpisode
|
delete instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ module.exports = (sequelize) => {
|
|||||||
date: DataTypes.STRING
|
date: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'PlaybackSessionListenTime'
|
modelName: 'playbackSessionListenTime'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { PlaybackSession } = sequelize.models
|
const { playbackSession } = sequelize.models
|
||||||
|
|
||||||
PlaybackSession.hasMany(PlaybackSessionListenTime)
|
playbackSession.hasMany(PlaybackSessionListenTime)
|
||||||
PlaybackSessionListenTime.belongsTo(PlaybackSession)
|
PlaybackSessionListenTime.belongsTo(playbackSession)
|
||||||
|
|
||||||
return PlaybackSessionListenTime
|
return PlaybackSessionListenTime
|
||||||
}
|
}
|
@ -13,15 +13,15 @@ module.exports = (sequelize) => {
|
|||||||
description: DataTypes.TEXT
|
description: DataTypes.TEXT
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Playlist'
|
modelName: 'playlist'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Library, User } = sequelize.models
|
const { library, user } = sequelize.models
|
||||||
Library.hasMany(Playlist)
|
library.hasMany(Playlist)
|
||||||
Playlist.belongsTo(Library)
|
Playlist.belongsTo(library)
|
||||||
|
|
||||||
User.hasMany(Playlist)
|
user.hasMany(Playlist)
|
||||||
Playlist.belongsTo(User)
|
Playlist.belongsTo(user)
|
||||||
|
|
||||||
return Playlist
|
return Playlist
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ module.exports = (sequelize) => {
|
|||||||
class PlaylistMediaItem extends Model {
|
class PlaylistMediaItem extends Model {
|
||||||
getMediaItem(options) {
|
getMediaItem(options) {
|
||||||
if (!this.mediaItemType) return Promise.resolve(null)
|
if (!this.mediaItemType) return Promise.resolve(null)
|
||||||
const mixinMethodName = `get${this.mediaItemType}`
|
const mixinMethodName = `get${sequelize.uppercaseFirst(this.mediaItemType)}`
|
||||||
return this[mixinMethodName](options)
|
return this[mixinMethodName](options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -15,53 +15,58 @@ module.exports = (sequelize) => {
|
|||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
MediaItemId: DataTypes.UUIDV4,
|
mediaItemId: DataTypes.UUIDV4,
|
||||||
mediaItemType: DataTypes.STRING
|
mediaItemType: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
updatedAt: false,
|
updatedAt: false,
|
||||||
modelName: 'PlaylistMediaItem'
|
modelName: 'playlistMediaItem'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Book, PodcastEpisode, Playlist } = sequelize.models
|
const { book, podcastEpisode, playlist } = sequelize.models
|
||||||
|
|
||||||
Book.hasMany(PlaylistMediaItem, {
|
book.hasMany(PlaylistMediaItem, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'Book'
|
mediaItemType: 'book'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
PlaylistMediaItem.belongsTo(Book, { foreignKey: 'MediaItemId', constraints: false })
|
PlaylistMediaItem.belongsTo(book, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
PodcastEpisode.hasOne(PlaylistMediaItem, {
|
podcastEpisode.hasOne(PlaylistMediaItem, {
|
||||||
foreignKey: 'MediaItemId',
|
foreignKey: 'mediaItemId',
|
||||||
constraints: false,
|
constraints: false,
|
||||||
scope: {
|
scope: {
|
||||||
mediaItemType: 'PodcastEpisode'
|
mediaItemType: 'podcastEpisode'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
PlaylistMediaItem.belongsTo(PodcastEpisode, { foreignKey: 'MediaItemId', constraints: false })
|
PlaylistMediaItem.belongsTo(podcastEpisode, { foreignKey: 'mediaItemId', constraints: false })
|
||||||
|
|
||||||
PlaylistMediaItem.addHook('afterFind', findResult => {
|
PlaylistMediaItem.addHook('afterFind', findResult => {
|
||||||
|
if (!findResult) return
|
||||||
|
|
||||||
if (!Array.isArray(findResult)) findResult = [findResult]
|
if (!Array.isArray(findResult)) findResult = [findResult]
|
||||||
|
|
||||||
for (const instance of findResult) {
|
for (const instance of findResult) {
|
||||||
if (instance.mediaItemType === 'Book' && instance.Book !== undefined) {
|
if (instance.mediaItemType === 'book' && instance.book !== undefined) {
|
||||||
instance.MediaItem = instance.Book
|
instance.mediaItem = instance.book
|
||||||
} else if (instance.mediaItemType === 'PodcastEpisode' && instance.PodcastEpisode !== undefined) {
|
instance.dataValues.mediaItem = instance.dataValues.book
|
||||||
instance.MediaItem = instance.PodcastEpisode
|
} else if (instance.mediaItemType === 'podcastEpisode' && instance.podcastEpisode !== undefined) {
|
||||||
|
instance.mediaItem = instance.podcastEpisode
|
||||||
|
instance.dataValues.mediaItem = instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
// To prevent mistakes:
|
// To prevent mistakes:
|
||||||
delete instance.Book
|
delete instance.book
|
||||||
delete instance.dataValues.Book
|
delete instance.dataValues.book
|
||||||
delete instance.PodcastEpisode
|
delete instance.podcastEpisode
|
||||||
delete instance.dataValues.PodcastEpisode
|
delete instance.dataValues.podcastEpisode
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Playlist.hasMany(PlaylistMediaItem)
|
playlist.hasMany(PlaylistMediaItem)
|
||||||
PlaylistMediaItem.belongsTo(Playlist)
|
PlaylistMediaItem.belongsTo(playlist)
|
||||||
|
|
||||||
return PlaylistMediaItem
|
return PlaylistMediaItem
|
||||||
}
|
}
|
@ -9,7 +9,6 @@ module.exports = (sequelize) => {
|
|||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: DataTypes.UUIDV4,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
// Metadata
|
|
||||||
title: DataTypes.STRING,
|
title: DataTypes.STRING,
|
||||||
author: DataTypes.STRING,
|
author: DataTypes.STRING,
|
||||||
releaseDate: DataTypes.STRING,
|
releaseDate: DataTypes.STRING,
|
||||||
@ -32,15 +31,13 @@ module.exports = (sequelize) => {
|
|||||||
lastCoverSearch: DataTypes.DATE
|
lastCoverSearch: DataTypes.DATE
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Podcast'
|
modelName: 'podcast'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { LibraryItem, FileMetadata } = sequelize.models
|
const { fileMetadata } = sequelize.models
|
||||||
LibraryItem.hasOne(Podcast)
|
|
||||||
Podcast.belongsTo(LibraryItem)
|
|
||||||
|
|
||||||
FileMetadata.hasOne(Podcast, { foreignKey: 'ImageFileId' })
|
fileMetadata.hasOne(Podcast, { foreignKey: 'imageFileId' })
|
||||||
Podcast.belongsTo(FileMetadata, { as: 'ImageFile', foreignKey: 'ImageFileId' }) // Ref: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-an-alias
|
Podcast.belongsTo(fileMetadata, { as: 'imageFile', foreignKey: 'imageFileId' }) // Ref: https://sequelize.org/docs/v6/core-concepts/assocs/#defining-an-alias
|
||||||
|
|
||||||
return Podcast
|
return Podcast
|
||||||
}
|
}
|
@ -23,12 +23,12 @@ module.exports = (sequelize) => {
|
|||||||
publishedAt: DataTypes.DATE
|
publishedAt: DataTypes.DATE
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'PodcastEpisode'
|
modelName: 'podcastEpisode'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { Podcast } = sequelize.models
|
const { podcast } = sequelize.models
|
||||||
Podcast.hasMany(PodcastEpisode)
|
podcast.hasMany(PodcastEpisode)
|
||||||
PodcastEpisode.belongsTo(Podcast)
|
PodcastEpisode.belongsTo(podcast)
|
||||||
|
|
||||||
return PodcastEpisode
|
return PodcastEpisode
|
||||||
}
|
}
|
@ -11,21 +11,21 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'PodcastGenre',
|
modelName: 'podcastGenre',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Podcast, Genre } = sequelize.models
|
const { podcast, genre } = sequelize.models
|
||||||
Podcast.belongsToMany(Genre, { through: PodcastGenre })
|
podcast.belongsToMany(genre, { through: PodcastGenre })
|
||||||
Genre.belongsToMany(Podcast, { through: PodcastGenre })
|
genre.belongsToMany(podcast, { through: PodcastGenre })
|
||||||
|
|
||||||
Podcast.hasMany(PodcastGenre)
|
podcast.hasMany(PodcastGenre)
|
||||||
PodcastGenre.belongsTo(Podcast)
|
PodcastGenre.belongsTo(podcast)
|
||||||
|
|
||||||
Genre.hasMany(PodcastGenre)
|
genre.hasMany(PodcastGenre)
|
||||||
PodcastGenre.belongsTo(Genre)
|
PodcastGenre.belongsTo(genre)
|
||||||
|
|
||||||
return PodcastGenre
|
return PodcastGenre
|
||||||
}
|
}
|
@ -11,21 +11,21 @@ module.exports = (sequelize) => {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'PodcastTag',
|
modelName: 'podcastTag',
|
||||||
timestamps: false
|
timestamps: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Super Many-to-Many
|
// Super Many-to-Many
|
||||||
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
// ref: https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#the-best-of-both-worlds-the-super-many-to-many-relationship
|
||||||
const { Podcast, Tag } = sequelize.models
|
const { podcast, tag } = sequelize.models
|
||||||
Podcast.belongsToMany(Tag, { through: PodcastTag })
|
podcast.belongsToMany(tag, { through: PodcastTag })
|
||||||
Tag.belongsToMany(Podcast, { through: PodcastTag })
|
tag.belongsToMany(podcast, { through: PodcastTag })
|
||||||
|
|
||||||
Podcast.hasMany(PodcastTag)
|
podcast.hasMany(PodcastTag)
|
||||||
PodcastTag.belongsTo(Podcast)
|
PodcastTag.belongsTo(podcast)
|
||||||
|
|
||||||
Tag.hasMany(PodcastTag)
|
tag.hasMany(PodcastTag)
|
||||||
PodcastTag.belongsTo(Tag)
|
PodcastTag.belongsTo(tag)
|
||||||
|
|
||||||
return PodcastTag
|
return PodcastTag
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ module.exports = (sequelize) => {
|
|||||||
description: DataTypes.TEXT
|
description: DataTypes.TEXT
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Series'
|
modelName: 'series'
|
||||||
})
|
})
|
||||||
|
|
||||||
return Series
|
return Series
|
||||||
|
@ -12,7 +12,7 @@ module.exports = (sequelize) => {
|
|||||||
type: DataTypes.INTEGER
|
type: DataTypes.INTEGER
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Setting'
|
modelName: 'setting'
|
||||||
})
|
})
|
||||||
|
|
||||||
return Setting
|
return Setting
|
||||||
|
@ -13,7 +13,7 @@ module.exports = (sequelize) => {
|
|||||||
cleanName: DataTypes.STRING
|
cleanName: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'Tag'
|
modelName: 'tag'
|
||||||
})
|
})
|
||||||
|
|
||||||
return Tag
|
return Tag
|
||||||
|
@ -26,7 +26,7 @@ module.exports = (sequelize) => {
|
|||||||
extraData: DataTypes.JSON
|
extraData: DataTypes.JSON
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'User'
|
modelName: 'user'
|
||||||
})
|
})
|
||||||
|
|
||||||
return User
|
return User
|
||||||
|
@ -13,13 +13,13 @@ module.exports = (sequelize) => {
|
|||||||
value: DataTypes.STRING
|
value: DataTypes.STRING
|
||||||
}, {
|
}, {
|
||||||
sequelize,
|
sequelize,
|
||||||
modelName: 'UserPermission'
|
modelName: 'userPermission'
|
||||||
})
|
})
|
||||||
|
|
||||||
const { User } = sequelize.models
|
const { user } = sequelize.models
|
||||||
|
|
||||||
User.hasMany(UserPermission)
|
user.hasMany(UserPermission)
|
||||||
UserPermission.belongsTo(User)
|
UserPermission.belongsTo(user)
|
||||||
|
|
||||||
return UserPermission
|
return UserPermission
|
||||||
}
|
}
|
15
server/routers/ApiRouter2.js
Normal file
15
server/routers/ApiRouter2.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const express = require('express')
|
||||||
|
const LibraryItemController = require('../controllers2/LibraryItemController')
|
||||||
|
|
||||||
|
class ApiRouter2 {
|
||||||
|
constructor(Server) {
|
||||||
|
this.router = express()
|
||||||
|
this.router.disable('x-powered-by')
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.router.get('/items/:id', LibraryItemController.get.bind(this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = ApiRouter2
|
@ -1,6 +1,5 @@
|
|||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const uuidv4 = require("uuid").v4
|
const uuidv4 = require("uuid").v4
|
||||||
const package = require('../../../package.json')
|
|
||||||
const { AudioMimeType } = require('../constants')
|
const { AudioMimeType } = require('../constants')
|
||||||
const Logger = require('../../Logger')
|
const Logger = require('../../Logger')
|
||||||
const Database = require('../../Database')
|
const Database = require('../../Database')
|
||||||
@ -20,49 +19,50 @@ const oldDbIdMap = {
|
|||||||
files: {}, // key is fullpath
|
files: {}, // key is fullpath
|
||||||
podcastEpisodes: {},
|
podcastEpisodes: {},
|
||||||
books: {}, // key is library item id
|
books: {}, // key is library item id
|
||||||
|
podcasts: {}, // key is library item id
|
||||||
devices: {} // key is a json stringify of the old DeviceInfo data
|
devices: {} // key is a json stringify of the old DeviceInfo data
|
||||||
}
|
}
|
||||||
const newRecords = {
|
const newRecords = {
|
||||||
User: [],
|
user: [],
|
||||||
UserPermission: [],
|
userPermission: [],
|
||||||
Library: [],
|
library: [],
|
||||||
LibraryFolder: [],
|
libraryFolder: [],
|
||||||
LibrarySetting: [],
|
librarySetting: [],
|
||||||
FileMetadata: [],
|
fileMetadata: [],
|
||||||
Person: [],
|
person: [],
|
||||||
LibraryItem: [],
|
eBookFile: [],
|
||||||
LibraryFile: [],
|
book: [],
|
||||||
EBookFile: [],
|
podcast: [],
|
||||||
Book: [],
|
libraryItem: [],
|
||||||
BookAuthor: [],
|
libraryFile: [],
|
||||||
BookNarrator: [],
|
bookAuthor: [],
|
||||||
BookChapter: [],
|
bookNarrator: [],
|
||||||
Tag: [],
|
bookChapter: [],
|
||||||
BookTag: [],
|
tag: [],
|
||||||
Genre: [],
|
bookTag: [],
|
||||||
BookGenre: [],
|
genre: [],
|
||||||
Series: [],
|
bookGenre: [],
|
||||||
BookSeries: [],
|
series: [],
|
||||||
Podcast: [],
|
bookSeries: [],
|
||||||
PodcastTag: [],
|
podcastTag: [],
|
||||||
PodcastGenre: [],
|
podcastGenre: [],
|
||||||
PodcastEpisode: [],
|
podcastEpisode: [],
|
||||||
MediaProgress: [],
|
mediaProgress: [],
|
||||||
AudioBookmark: [],
|
audioBookmark: [],
|
||||||
MediaFile: [],
|
mediaFile: [],
|
||||||
MediaStream: [],
|
mediaStream: [],
|
||||||
AudioTrack: [],
|
audioTrack: [],
|
||||||
Device: [],
|
device: [],
|
||||||
PlaybackSession: [],
|
playbackSession: [],
|
||||||
PlaybackSessionListenTime: [],
|
playbackSessionListenTime: [],
|
||||||
Collection: [],
|
collection: [],
|
||||||
CollectionBook: [],
|
collectionBook: [],
|
||||||
Playlist: [],
|
playlist: [],
|
||||||
PlaylistMediaItem: [],
|
playlistMediaItem: [],
|
||||||
Feed: [],
|
feed: [],
|
||||||
FeedEpisode: [],
|
feedEpisode: [],
|
||||||
Setting: [],
|
setting: [],
|
||||||
Notification: []
|
notification: []
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDeviceInfoString(deviceInfo, UserId) {
|
function getDeviceInfoString(deviceInfo, UserId) {
|
||||||
@ -102,10 +102,10 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
//
|
//
|
||||||
// Migrate ImageFile
|
// Migrate ImageFile
|
||||||
//
|
//
|
||||||
let ImageFileId = null
|
let imageFileId = null
|
||||||
if (oldBook.coverPath) {
|
if (oldBook.coverPath) {
|
||||||
ImageFileId = oldDbIdMap.files[oldBook.coverPath] || null
|
imageFileId = oldDbIdMap.files[oldBook.coverPath] || null
|
||||||
if (!ImageFileId) {
|
if (!imageFileId) {
|
||||||
const FileMetadata = {
|
const FileMetadata = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
filename: Path.basename(oldBook.coverPath),
|
filename: Path.basename(oldBook.coverPath),
|
||||||
@ -114,26 +114,28 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
newRecords.FileMetadata.push(FileMetadata)
|
newRecords.fileMetadata.push(FileMetadata)
|
||||||
oldDbIdMap.files[oldBook.coverPath] = FileMetadata.id
|
oldDbIdMap.files[oldBook.coverPath] = FileMetadata.id
|
||||||
ImageFileId = FileMetadata.id
|
imageFileId = FileMetadata.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate EBookFile
|
// Migrate EBookFile
|
||||||
//
|
//
|
||||||
let EBookFileId = null
|
let eBookFileId = null
|
||||||
if (oldBook.ebookFile) {
|
if (oldBook.ebookFile) {
|
||||||
if (oldDbIdMap.files[oldBook.ebookFile.metadata?.path]) {
|
if (oldDbIdMap.files[oldBook.ebookFile.metadata?.path]) {
|
||||||
|
const ext = oldBook.ebookFile.metadata.ext || ''
|
||||||
const EBookFile = {
|
const EBookFile = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
FileMetadataId: oldDbIdMap.files[oldBook.ebookFile.metadata?.path]
|
format: ext.toLowerCase().slice(1),
|
||||||
|
fileMetadataId: oldDbIdMap.files[oldBook.ebookFile.metadata.path]
|
||||||
}
|
}
|
||||||
newRecords.EBookFile.push(EBookFile)
|
newRecords.eBookFile.push(EBookFile)
|
||||||
EBookFileId = EBookFile.id
|
eBookFileId = EBookFile.id
|
||||||
} else {
|
} else {
|
||||||
Logger.warn(`[dbMigration] migrateBook: `)
|
Logger.warn(`[dbMigration] migrateBook: Unable to find ebook file`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,11 +158,10 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
lastCoverSearch: oldBook.lastCoverSearch,
|
lastCoverSearch: oldBook.lastCoverSearch,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
ImageFileId,
|
imageFileId,
|
||||||
EBookFileId,
|
eBookFileId
|
||||||
LibraryItemId: LibraryItem.id,
|
|
||||||
}
|
}
|
||||||
newRecords.Book.push(Book)
|
newRecords.book.push(Book)
|
||||||
oldDbIdMap.books[oldLibraryItem.id] = Book.id
|
oldDbIdMap.books[oldLibraryItem.id] = Book.id
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -169,8 +170,8 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
const oldAudioFiles = oldBook.audioFiles
|
const oldAudioFiles = oldBook.audioFiles
|
||||||
let startOffset = 0
|
let startOffset = 0
|
||||||
for (const oldAudioFile of oldAudioFiles) {
|
for (const oldAudioFile of oldAudioFiles) {
|
||||||
const FileMetadataId = oldDbIdMap.files[oldAudioFile.metadata.path]
|
const fileMetadataId = oldDbIdMap.files[oldAudioFile.metadata.path]
|
||||||
if (!FileMetadataId) {
|
if (!fileMetadataId) {
|
||||||
Logger.warn(`[dbMigration] migrateBook: File metadata not found for audio file "${oldAudioFile.metadata.path}"`)
|
Logger.warn(`[dbMigration] migrateBook: File metadata not found for audio file "${oldAudioFile.metadata.path}"`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -187,9 +188,9 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
tags: cleanAudioFileMetaTags(oldAudioFile.metaTags),
|
tags: cleanAudioFileMetaTags(oldAudioFile.metaTags),
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
FileMetadataId
|
fileMetadataId
|
||||||
}
|
}
|
||||||
newRecords.MediaFile.push(MediaFile)
|
newRecords.mediaFile.push(MediaFile)
|
||||||
|
|
||||||
const MediaStream = {
|
const MediaStream = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
@ -207,9 +208,9 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
chapters: oldAudioFile.chapters,
|
chapters: oldAudioFile.chapters,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
MediaFileId: MediaFile.id
|
mediaFileId: MediaFile.id
|
||||||
}
|
}
|
||||||
newRecords.MediaStream.push(MediaStream)
|
newRecords.mediaStream.push(MediaStream)
|
||||||
|
|
||||||
if (oldAudioFile.embeddedCoverArt) {
|
if (oldAudioFile.embeddedCoverArt) {
|
||||||
const CoverMediaStream = {
|
const CoverMediaStream = {
|
||||||
@ -220,17 +221,17 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
default: true,
|
default: true,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
MediaFileId: MediaFile.id
|
mediaFileId: MediaFile.id
|
||||||
}
|
}
|
||||||
newRecords.MediaStream.push(CoverMediaStream)
|
newRecords.mediaStream.push(CoverMediaStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
const include = !oldAudioFile.exclude && !oldAudioFile.invalid
|
const include = !oldAudioFile.exclude && !oldAudioFile.invalid
|
||||||
|
|
||||||
const AudioTrack = {
|
const AudioTrack = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
MediaItemId: Book.id,
|
mediaItemId: Book.id,
|
||||||
mediaItemType: 'Book',
|
mediaItemType: 'book',
|
||||||
index: oldAudioFile.index,
|
index: oldAudioFile.index,
|
||||||
startOffset: include ? startOffset : null,
|
startOffset: include ? startOffset : null,
|
||||||
duration: oldAudioFile.duration,
|
duration: oldAudioFile.duration,
|
||||||
@ -241,9 +242,9 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
discNumber: oldAudioFile.discNumFromMeta || oldAudioFile.discNumFromFilename,
|
discNumber: oldAudioFile.discNumFromMeta || oldAudioFile.discNumFromFilename,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
MediaFileId: MediaFile.id
|
mediaFileId: MediaFile.id
|
||||||
}
|
}
|
||||||
newRecords.AudioTrack.push(AudioTrack)
|
newRecords.audioTrack.push(AudioTrack)
|
||||||
|
|
||||||
if (include) {
|
if (include) {
|
||||||
startOffset += AudioTrack.duration
|
startOffset += AudioTrack.duration
|
||||||
@ -267,13 +268,13 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
tagId = Tag.id
|
tagId = Tag.id
|
||||||
newRecords.Tag.push(Tag)
|
newRecords.tag.push(Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
newRecords.BookTag.push({
|
newRecords.bookTag.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
BookId: Book.id,
|
bookId: Book.id,
|
||||||
TagId: tagId
|
tagId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +282,7 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
// Migrate BookChapters
|
// Migrate BookChapters
|
||||||
//
|
//
|
||||||
for (const oldChapter of oldBook.chapters) {
|
for (const oldChapter of oldBook.chapters) {
|
||||||
newRecords.BookChapter.push({
|
newRecords.bookChapter.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
index: oldChapter.id,
|
index: oldChapter.id,
|
||||||
start: oldChapter.start,
|
start: oldChapter.start,
|
||||||
@ -289,7 +290,7 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
title: oldChapter.title,
|
title: oldChapter.title,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
BookId: Book.id
|
bookId: Book.id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,13 +312,13 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
genreId = Genre.id
|
genreId = Genre.id
|
||||||
newRecords.Genre.push(Genre)
|
newRecords.genre.push(Genre)
|
||||||
}
|
}
|
||||||
|
|
||||||
newRecords.BookGenre.push({
|
newRecords.bookGenre.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
BookId: Book.id,
|
bookId: Book.id,
|
||||||
GenreId: genreId
|
genreId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,10 +327,10 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
//
|
//
|
||||||
for (const oldBookAuthor of oldBook.metadata.authors) {
|
for (const oldBookAuthor of oldBook.metadata.authors) {
|
||||||
if (oldDbIdMap.people[oldBookAuthor.id]) {
|
if (oldDbIdMap.people[oldBookAuthor.id]) {
|
||||||
newRecords.BookAuthor.push({
|
newRecords.bookAuthor.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
PersonId: oldDbIdMap.people[oldBookAuthor.id],
|
authorId: oldDbIdMap.people[oldBookAuthor.id],
|
||||||
BookId: Book.id
|
bookId: Book.id
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Logger.warn(`[dbMigration] migrateBook: Book author not found "${oldBookAuthor.name}"`)
|
Logger.warn(`[dbMigration] migrateBook: Book author not found "${oldBookAuthor.name}"`)
|
||||||
@ -340,23 +341,23 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
// Migrate BookNarrators
|
// Migrate BookNarrators
|
||||||
//
|
//
|
||||||
for (const oldBookNarrator of oldBook.metadata.narrators) {
|
for (const oldBookNarrator of oldBook.metadata.narrators) {
|
||||||
let PersonId = oldDbIdMap.people[oldBookNarrator]
|
let personId = oldDbIdMap.people[oldBookNarrator]
|
||||||
if (!PersonId) {
|
if (!personId) {
|
||||||
const Person = {
|
const Person = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
type: 'Narrator',
|
type: 'narrator',
|
||||||
name: oldBookNarrator,
|
name: oldBookNarrator,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
newRecords.Person.push(Person)
|
newRecords.person.push(Person)
|
||||||
PersonId = Person.id
|
personId = Person.id
|
||||||
}
|
}
|
||||||
|
|
||||||
newRecords.BookNarrator.push({
|
newRecords.bookNarrator.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
PersonId,
|
narratorId: personId,
|
||||||
BookId: Book.id
|
bookId: Book.id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,10 +369,10 @@ function migrateBook(oldLibraryItem, LibraryItem) {
|
|||||||
const BookSeries = {
|
const BookSeries = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
sequence: oldBookSeries.sequence,
|
sequence: oldBookSeries.sequence,
|
||||||
SeriesId: oldDbIdMap.series[oldBookSeries.id],
|
seriesId: oldDbIdMap.series[oldBookSeries.id],
|
||||||
BookId: Book.id
|
bookId: Book.id
|
||||||
}
|
}
|
||||||
newRecords.BookSeries.push(BookSeries)
|
newRecords.bookSeries.push(BookSeries)
|
||||||
} else {
|
} else {
|
||||||
Logger.warn(`[dbMigration] migrateBook: Series not found "${oldBookSeries.name}"`)
|
Logger.warn(`[dbMigration] migrateBook: Series not found "${oldBookSeries.name}"`)
|
||||||
}
|
}
|
||||||
@ -385,10 +386,10 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
//
|
//
|
||||||
// Migrate ImageFile
|
// Migrate ImageFile
|
||||||
//
|
//
|
||||||
let ImageFileId = null
|
let imageFileId = null
|
||||||
if (oldPodcast.coverPath) {
|
if (oldPodcast.coverPath) {
|
||||||
ImageFileId = oldDbIdMap.files[oldPodcast.coverPath] || null
|
imageFileId = oldDbIdMap.files[oldPodcast.coverPath] || null
|
||||||
if (!ImageFileId) {
|
if (!imageFileId) {
|
||||||
const FileMetadata = {
|
const FileMetadata = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
filename: Path.basename(oldPodcast.coverPath),
|
filename: Path.basename(oldPodcast.coverPath),
|
||||||
@ -397,9 +398,9 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
newRecords.FileMetadata.push(FileMetadata)
|
newRecords.fileMetadata.push(FileMetadata)
|
||||||
oldDbIdMap.files[oldPodcast.coverPath] = FileMetadata.id
|
oldDbIdMap.files[oldPodcast.coverPath] = FileMetadata.id
|
||||||
ImageFileId = FileMetadata.id
|
imageFileId = FileMetadata.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,10 +430,10 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
lastCoverSearch: oldPodcast.lastCoverSearch,
|
lastCoverSearch: oldPodcast.lastCoverSearch,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
ImageFileId,
|
imageFileId,
|
||||||
LibraryItemId: LibraryItem.id
|
|
||||||
}
|
}
|
||||||
newRecords.Podcast.push(Podcast)
|
newRecords.podcast.push(Podcast)
|
||||||
|
oldDbIdMap.podcasts[oldLibraryItem.id] = Podcast.id
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate Tags
|
// Migrate Tags
|
||||||
@ -451,13 +452,13 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
tagId = Tag.id
|
tagId = Tag.id
|
||||||
newRecords.Tag.push(Tag)
|
newRecords.tag.push(Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
newRecords.PodcastTag.push({
|
newRecords.podcastTag.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
PodcastId: Podcast.id,
|
podcastId: Podcast.id,
|
||||||
TagId: tagId
|
tagId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,13 +479,13 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
updatedAt: LibraryItem.updatedAt
|
updatedAt: LibraryItem.updatedAt
|
||||||
}
|
}
|
||||||
genreId = Genre.id
|
genreId = Genre.id
|
||||||
newRecords.Genre.push(Genre)
|
newRecords.genre.push(Genre)
|
||||||
}
|
}
|
||||||
|
|
||||||
newRecords.PodcastGenre.push({
|
newRecords.podcastGenre.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
PodcastId: Podcast.id,
|
podcastId: Podcast.id,
|
||||||
GenreId: genreId
|
genreId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,8 +495,8 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
const oldEpisodes = oldPodcast.episodes || []
|
const oldEpisodes = oldPodcast.episodes || []
|
||||||
for (const oldEpisode of oldEpisodes) {
|
for (const oldEpisode of oldEpisodes) {
|
||||||
const oldAudioFile = oldEpisode.audioFile
|
const oldAudioFile = oldEpisode.audioFile
|
||||||
const FileMetadataId = oldDbIdMap.files[oldAudioFile.metadata.path]
|
const fileMetadataId = oldDbIdMap.files[oldAudioFile.metadata.path]
|
||||||
if (!FileMetadataId) {
|
if (!fileMetadataId) {
|
||||||
Logger.warn(`[dbMigration] migratePodcast: File metadata not found for audio file "${oldAudioFile.metadata.path}"`)
|
Logger.warn(`[dbMigration] migratePodcast: File metadata not found for audio file "${oldAudioFile.metadata.path}"`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -516,9 +517,9 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
publishedAt: oldEpisode.publishedAt,
|
publishedAt: oldEpisode.publishedAt,
|
||||||
createdAt: oldEpisode.addedAt,
|
createdAt: oldEpisode.addedAt,
|
||||||
updatedAt: oldEpisode.updatedAt,
|
updatedAt: oldEpisode.updatedAt,
|
||||||
PodcastId: Podcast.id
|
podcastId: Podcast.id
|
||||||
}
|
}
|
||||||
newRecords.PodcastEpisode.push(PodcastEpisode)
|
newRecords.podcastEpisode.push(PodcastEpisode)
|
||||||
oldDbIdMap.podcastEpisodes[oldEpisode.id] = PodcastEpisode.id
|
oldDbIdMap.podcastEpisodes[oldEpisode.id] = PodcastEpisode.id
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -535,9 +536,9 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
tags: cleanAudioFileMetaTags(oldAudioFile.metaTags),
|
tags: cleanAudioFileMetaTags(oldAudioFile.metaTags),
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
FileMetadataId
|
fileMetadataId
|
||||||
}
|
}
|
||||||
newRecords.MediaFile.push(MediaFile)
|
newRecords.mediaFile.push(MediaFile)
|
||||||
|
|
||||||
const MediaStream = {
|
const MediaStream = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
@ -555,9 +556,9 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
chapters: oldAudioFile.chapters,
|
chapters: oldAudioFile.chapters,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
MediaFileId: MediaFile.id
|
mediaFileId: MediaFile.id
|
||||||
}
|
}
|
||||||
newRecords.MediaStream.push(MediaStream)
|
newRecords.mediaStream.push(MediaStream)
|
||||||
|
|
||||||
if (oldAudioFile.embeddedCoverArt) {
|
if (oldAudioFile.embeddedCoverArt) {
|
||||||
const CoverMediaStream = {
|
const CoverMediaStream = {
|
||||||
@ -568,15 +569,15 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
default: true,
|
default: true,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
MediaFileId: MediaFile.id
|
mediaFileId: MediaFile.id
|
||||||
}
|
}
|
||||||
newRecords.MediaStream.push(CoverMediaStream)
|
newRecords.mediaStream.push(CoverMediaStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
const AudioTrack = {
|
const AudioTrack = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
MediaItemId: Podcast.id,
|
mediaItemId: PodcastEpisode.id,
|
||||||
mediaItemType: 'Podcast',
|
mediaItemType: 'podcastEpisode',
|
||||||
index: oldAudioFile.index,
|
index: oldAudioFile.index,
|
||||||
startOffset: 0,
|
startOffset: 0,
|
||||||
duration: oldAudioFile.duration,
|
duration: oldAudioFile.duration,
|
||||||
@ -587,16 +588,16 @@ function migratePodcast(oldLibraryItem, LibraryItem) {
|
|||||||
discNumber: oldAudioFile.discNumFromMeta || oldAudioFile.discNumFromFilename,
|
discNumber: oldAudioFile.discNumFromMeta || oldAudioFile.discNumFromFilename,
|
||||||
createdAt: LibraryItem.createdAt,
|
createdAt: LibraryItem.createdAt,
|
||||||
updatedAt: LibraryItem.updatedAt,
|
updatedAt: LibraryItem.updatedAt,
|
||||||
MediaFileId: MediaFile.id
|
mediaFileId: MediaFile.id
|
||||||
}
|
}
|
||||||
newRecords.AudioTrack.push(AudioTrack)
|
newRecords.audioTrack.push(AudioTrack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrateLibraryItems(oldLibraryItems) {
|
function migrateLibraryItems(oldLibraryItems) {
|
||||||
for (const oldLibraryItem of oldLibraryItems) {
|
for (const oldLibraryItem of oldLibraryItems) {
|
||||||
const LibraryId = oldDbIdMap.libraryFolders[oldLibraryItem.folderId]
|
const libraryFolderId = oldDbIdMap.libraryFolders[oldLibraryItem.folderId]
|
||||||
if (!LibraryId) {
|
if (!libraryFolderId) {
|
||||||
Logger.error(`[dbMigration] migrateLibraryItems: Old library folder id not found "${oldLibraryItem.folderId}"`)
|
Logger.error(`[dbMigration] migrateLibraryItems: Old library folder id not found "${oldLibraryItem.folderId}"`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -609,6 +610,7 @@ function migrateLibraryItems(oldLibraryItems) {
|
|||||||
ino: oldLibraryItem.ino,
|
ino: oldLibraryItem.ino,
|
||||||
path: oldLibraryItem.path,
|
path: oldLibraryItem.path,
|
||||||
relPath: oldLibraryItem.relPath,
|
relPath: oldLibraryItem.relPath,
|
||||||
|
mediaId: null, // set below
|
||||||
mediaType: oldLibraryItem.mediaType,
|
mediaType: oldLibraryItem.mediaType,
|
||||||
isFile: !!oldLibraryItem.isFile,
|
isFile: !!oldLibraryItem.isFile,
|
||||||
isMissing: !!oldLibraryItem.isMissing,
|
isMissing: !!oldLibraryItem.isMissing,
|
||||||
@ -620,10 +622,10 @@ function migrateLibraryItems(oldLibraryItems) {
|
|||||||
lastScanVersion: oldLibraryItem.scanVersion,
|
lastScanVersion: oldLibraryItem.scanVersion,
|
||||||
createdAt: oldLibraryItem.addedAt,
|
createdAt: oldLibraryItem.addedAt,
|
||||||
updatedAt: oldLibraryItem.updatedAt,
|
updatedAt: oldLibraryItem.updatedAt,
|
||||||
LibraryId
|
libraryFolderId
|
||||||
}
|
}
|
||||||
oldDbIdMap.libraryItems[oldLibraryItem.id] = LibraryItem.id
|
oldDbIdMap.libraryItems[oldLibraryItem.id] = LibraryItem.id
|
||||||
newRecords.LibraryItem.push(LibraryItem)
|
newRecords.libraryItem.push(LibraryItem)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate LibraryFiles
|
// Migrate LibraryFiles
|
||||||
@ -642,17 +644,17 @@ function migrateLibraryItems(oldLibraryItems) {
|
|||||||
createdAt: oldLibraryFile.addedAt || Date.now(),
|
createdAt: oldLibraryFile.addedAt || Date.now(),
|
||||||
updatedAt: oldLibraryFile.updatedAt || Date.now()
|
updatedAt: oldLibraryFile.updatedAt || Date.now()
|
||||||
}
|
}
|
||||||
newRecords.FileMetadata.push(FileMetadata)
|
newRecords.fileMetadata.push(FileMetadata)
|
||||||
oldDbIdMap.files[FileMetadata.path] = FileMetadata.id
|
oldDbIdMap.files[FileMetadata.path] = FileMetadata.id
|
||||||
|
|
||||||
const LibraryFile = {
|
const LibraryFile = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
createdAt: FileMetadata.createdAt,
|
createdAt: FileMetadata.createdAt,
|
||||||
updatedAt: FileMetadata.updatedAt,
|
updatedAt: FileMetadata.updatedAt,
|
||||||
FileMetadataId: FileMetadata.id,
|
fileMetadataId: FileMetadata.id,
|
||||||
LibraryItemId: LibraryItem.id
|
libraryItemId: LibraryItem.id
|
||||||
}
|
}
|
||||||
newRecords.LibraryFile.push(LibraryFile)
|
newRecords.libraryFile.push(LibraryFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -660,8 +662,10 @@ function migrateLibraryItems(oldLibraryItems) {
|
|||||||
//
|
//
|
||||||
if (oldLibraryItem.mediaType === 'book') {
|
if (oldLibraryItem.mediaType === 'book') {
|
||||||
migrateBook(oldLibraryItem, LibraryItem)
|
migrateBook(oldLibraryItem, LibraryItem)
|
||||||
|
LibraryItem.mediaId = oldDbIdMap.books[oldLibraryItem.id]
|
||||||
} else if (oldLibraryItem.mediaType === 'podcast') {
|
} else if (oldLibraryItem.mediaType === 'podcast') {
|
||||||
migratePodcast(oldLibraryItem, LibraryItem)
|
migratePodcast(oldLibraryItem, LibraryItem)
|
||||||
|
LibraryItem.mediaId = oldDbIdMap.podcasts[oldLibraryItem.id]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -682,20 +686,20 @@ function migrateLibraries(oldLibraries) {
|
|||||||
updatedAt: oldLibrary.lastUpdate
|
updatedAt: oldLibrary.lastUpdate
|
||||||
}
|
}
|
||||||
oldDbIdMap.libraries[oldLibrary.id] = Library.id
|
oldDbIdMap.libraries[oldLibrary.id] = Library.id
|
||||||
newRecords.Library.push(Library)
|
newRecords.library.push(Library)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate LibrarySettings
|
// Migrate LibrarySettings
|
||||||
//
|
//
|
||||||
const oldLibrarySettings = oldLibrary.settings || {}
|
const oldLibrarySettings = oldLibrary.settings || {}
|
||||||
for (const oldSettingsKey in oldLibrarySettings) {
|
for (const oldSettingsKey in oldLibrarySettings) {
|
||||||
newRecords.LibrarySetting.push({
|
newRecords.librarySetting.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
key: oldSettingsKey,
|
key: oldSettingsKey,
|
||||||
value: oldLibrarySettings[oldSettingsKey],
|
value: oldLibrarySettings[oldSettingsKey],
|
||||||
createdAt: oldLibrary.createdAt,
|
createdAt: oldLibrary.createdAt,
|
||||||
updatedAt: oldLibrary.lastUpdate,
|
updatedAt: oldLibrary.lastUpdate,
|
||||||
LibraryId: Library.id
|
libraryId: Library.id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,10 +712,10 @@ function migrateLibraries(oldLibraries) {
|
|||||||
path: oldFolder.fullPath,
|
path: oldFolder.fullPath,
|
||||||
createdAt: oldFolder.addedAt,
|
createdAt: oldFolder.addedAt,
|
||||||
updatedAt: oldLibrary.lastUpdate,
|
updatedAt: oldLibrary.lastUpdate,
|
||||||
LibraryId: Library.id
|
libraryId: Library.id
|
||||||
}
|
}
|
||||||
oldDbIdMap.libraryFolders[oldFolder.id] = LibraryFolder.id
|
oldDbIdMap.libraryFolders[oldFolder.id] = LibraryFolder.id
|
||||||
newRecords.LibraryFolder.push(LibraryFolder)
|
newRecords.libraryFolder.push(LibraryFolder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -728,22 +732,22 @@ function migrateAuthors(oldAuthors) {
|
|||||||
createdAt: oldAuthor.addedAt || Date.now(),
|
createdAt: oldAuthor.addedAt || Date.now(),
|
||||||
updatedAt: oldAuthor.updatedAt || Date.now()
|
updatedAt: oldAuthor.updatedAt || Date.now()
|
||||||
}
|
}
|
||||||
newRecords.FileMetadata.push(FileMetadata)
|
newRecords.fileMetadata.push(FileMetadata)
|
||||||
imageFileId = FileMetadata.id
|
imageFileId = FileMetadata.id
|
||||||
}
|
}
|
||||||
|
|
||||||
const Person = {
|
const Person = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
type: 'Author',
|
type: 'author',
|
||||||
name: oldAuthor.name,
|
name: oldAuthor.name,
|
||||||
asin: oldAuthor.asin || null,
|
asin: oldAuthor.asin || null,
|
||||||
description: oldAuthor.description,
|
description: oldAuthor.description,
|
||||||
createdAt: oldAuthor.addedAt || Date.now(),
|
createdAt: oldAuthor.addedAt || Date.now(),
|
||||||
updatedAt: oldAuthor.updatedAt || Date.now(),
|
updatedAt: oldAuthor.updatedAt || Date.now(),
|
||||||
ImageFileId: imageFileId
|
imageFileId
|
||||||
}
|
}
|
||||||
oldDbIdMap.people[oldAuthor.id] = Person.id
|
oldDbIdMap.people[oldAuthor.id] = Person.id
|
||||||
newRecords.Person.push(Person)
|
newRecords.person.push(Person)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +761,7 @@ function migrateSeries(oldSerieses) {
|
|||||||
updatedAt: oldSeries.updatedAt || Date.now()
|
updatedAt: oldSeries.updatedAt || Date.now()
|
||||||
}
|
}
|
||||||
oldDbIdMap.series[oldSeries.id] = Series.id
|
oldDbIdMap.series[oldSeries.id] = Series.id
|
||||||
newRecords.Series.push(Series)
|
newRecords.series.push(Series)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +784,7 @@ function migrateUsers(oldUsers) {
|
|||||||
createdAt: oldUser.createdAt || Date.now()
|
createdAt: oldUser.createdAt || Date.now()
|
||||||
}
|
}
|
||||||
oldDbIdMap.users[oldUser.id] = User.id
|
oldDbIdMap.users[oldUser.id] = User.id
|
||||||
newRecords.User.push(User)
|
newRecords.user.push(User)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate UserPermissions
|
// Migrate UserPermissions
|
||||||
@ -792,9 +796,9 @@ function migrateUsers(oldUsers) {
|
|||||||
key: oldUserPermission,
|
key: oldUserPermission,
|
||||||
value: !!oldUser.permissions[oldUserPermission],
|
value: !!oldUser.permissions[oldUserPermission],
|
||||||
createdAt: User.createdAt,
|
createdAt: User.createdAt,
|
||||||
UserId: User.id
|
userId: User.id
|
||||||
}
|
}
|
||||||
newRecords.UserPermission.push(UserPermission)
|
newRecords.userPermission.push(UserPermission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (oldUser.librariesAccessible?.length) {
|
if (oldUser.librariesAccessible?.length) {
|
||||||
@ -803,9 +807,9 @@ function migrateUsers(oldUsers) {
|
|||||||
key: 'librariesAccessible',
|
key: 'librariesAccessible',
|
||||||
value: JSON.stringify(oldUser.librariesAccessible),
|
value: JSON.stringify(oldUser.librariesAccessible),
|
||||||
createdAt: User.createdAt,
|
createdAt: User.createdAt,
|
||||||
UserId: User.id
|
userId: User.id
|
||||||
}
|
}
|
||||||
newRecords.UserPermission.push(UserPermission)
|
newRecords.userPermission.push(UserPermission)
|
||||||
}
|
}
|
||||||
if (oldUser.itemTagsAccessible?.length) {
|
if (oldUser.itemTagsAccessible?.length) {
|
||||||
const UserPermission = {
|
const UserPermission = {
|
||||||
@ -813,32 +817,32 @@ function migrateUsers(oldUsers) {
|
|||||||
key: 'itemTagsAccessible',
|
key: 'itemTagsAccessible',
|
||||||
value: JSON.stringify(oldUser.itemTagsAccessible),
|
value: JSON.stringify(oldUser.itemTagsAccessible),
|
||||||
createdAt: User.createdAt,
|
createdAt: User.createdAt,
|
||||||
UserId: User.id
|
userId: User.id
|
||||||
}
|
}
|
||||||
newRecords.UserPermission.push(UserPermission)
|
newRecords.userPermission.push(UserPermission)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate MediaProgress
|
// Migrate MediaProgress
|
||||||
//
|
//
|
||||||
for (const oldMediaProgress of oldUser.mediaProgress) {
|
for (const oldMediaProgress of oldUser.mediaProgress) {
|
||||||
let mediaItemType = 'Book'
|
let mediaItemType = 'book'
|
||||||
let MediaItemId = null
|
let mediaItemId = null
|
||||||
if (oldMediaProgress.episodeId) {
|
if (oldMediaProgress.episodeId) {
|
||||||
mediaItemType = 'PodcastEpisode'
|
mediaItemType = 'podcastEpisode'
|
||||||
MediaItemId = oldDbIdMap.podcastEpisodes[oldMediaProgress.episodeId]
|
mediaItemId = oldDbIdMap.podcastEpisodes[oldMediaProgress.episodeId]
|
||||||
} else {
|
} else {
|
||||||
MediaItemId = oldDbIdMap.books[oldMediaProgress.libraryItemId]
|
mediaItemId = oldDbIdMap.books[oldMediaProgress.libraryItemId]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MediaItemId) {
|
if (!mediaItemId) {
|
||||||
Logger.warn(`[dbMigration] migrateUsers: Unable to find media item for media progress "${oldMediaProgress.id}"`)
|
Logger.warn(`[dbMigration] migrateUsers: Unable to find media item for media progress "${oldMediaProgress.id}"`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const MediaProgress = {
|
const MediaProgress = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
MediaItemId,
|
mediaItemId,
|
||||||
mediaItemType,
|
mediaItemType,
|
||||||
duration: oldMediaProgress.duration,
|
duration: oldMediaProgress.duration,
|
||||||
currentTime: oldMediaProgress.currentTime,
|
currentTime: oldMediaProgress.currentTime,
|
||||||
@ -847,49 +851,49 @@ function migrateUsers(oldUsers) {
|
|||||||
finishedAt: oldMediaProgress.finishedAt,
|
finishedAt: oldMediaProgress.finishedAt,
|
||||||
createdAt: oldMediaProgress.startedAt || oldMediaProgress.lastUpdate,
|
createdAt: oldMediaProgress.startedAt || oldMediaProgress.lastUpdate,
|
||||||
updatedAt: oldMediaProgress.lastUpdate,
|
updatedAt: oldMediaProgress.lastUpdate,
|
||||||
UserId: User.id
|
userId: User.id
|
||||||
}
|
}
|
||||||
newRecords.MediaProgress.push(MediaProgress)
|
newRecords.mediaProgress.push(MediaProgress)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate AudioBookmarks
|
// Migrate AudioBookmarks
|
||||||
//
|
//
|
||||||
for (const oldBookmark of oldUser.bookmarks) {
|
for (const oldBookmark of oldUser.bookmarks) {
|
||||||
const MediaItemId = oldDbIdMap.books[oldBookmark.libraryItemId]
|
const mediaItemId = oldDbIdMap.books[oldBookmark.libraryItemId]
|
||||||
if (!MediaItemId) {
|
if (!mediaItemId) {
|
||||||
Logger.warn(`[dbMigration] migrateUsers: Unable to find media item for audio bookmark "${oldBookmark.id}"`)
|
Logger.warn(`[dbMigration] migrateUsers: Unable to find media item for audio bookmark "${oldBookmark.id}"`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const AudioBookmark = {
|
const AudioBookmark = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
MediaItemId,
|
mediaItemId,
|
||||||
mediaItemType: 'Book',
|
mediaItemType: 'book',
|
||||||
title: oldBookmark.title,
|
title: oldBookmark.title,
|
||||||
time: oldBookmark.time,
|
time: oldBookmark.time,
|
||||||
createdAt: oldBookmark.createdAt,
|
createdAt: oldBookmark.createdAt,
|
||||||
updatedAt: oldBookmark.createdAt,
|
updatedAt: oldBookmark.createdAt,
|
||||||
UserId: User.id
|
userId: User.id
|
||||||
}
|
}
|
||||||
newRecords.AudioBookmark.push(AudioBookmark)
|
newRecords.audioBookmark.push(AudioBookmark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrateSessions(oldSessions) {
|
function migrateSessions(oldSessions) {
|
||||||
for (const oldSession of oldSessions) {
|
for (const oldSession of oldSessions) {
|
||||||
const UserId = oldDbIdMap.users[oldSession.userId] || null // Can be null
|
const userId = oldDbIdMap.users[oldSession.userId] || null // Can be null
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate Device
|
// Migrate Device
|
||||||
//
|
//
|
||||||
let DeviceId = null
|
let deviceId = null
|
||||||
if (oldSession.deviceInfo) {
|
if (oldSession.deviceInfo) {
|
||||||
const oldDeviceInfo = oldSession.deviceInfo
|
const oldDeviceInfo = oldSession.deviceInfo
|
||||||
const deviceInfoStr = getDeviceInfoString(oldDeviceInfo, UserId)
|
const deviceInfoStr = getDeviceInfoString(oldDeviceInfo, userId)
|
||||||
DeviceId = oldDbIdMap.devices[deviceInfoStr]
|
deviceId = oldDbIdMap.devices[deviceInfoStr]
|
||||||
if (!DeviceId) {
|
if (!deviceId) {
|
||||||
let clientName = 'Unknown'
|
let clientName = 'Unknown'
|
||||||
let clientVersion = null
|
let clientVersion = null
|
||||||
let deviceName = null
|
let deviceName = null
|
||||||
@ -918,9 +922,9 @@ function migrateSessions(oldSessions) {
|
|||||||
ipAddress: oldDeviceInfo.ipAddress,
|
ipAddress: oldDeviceInfo.ipAddress,
|
||||||
deviceName, // e.g. Windows 10 Chrome, Google Pixel 6, Apple iPhone 10,3
|
deviceName, // e.g. Windows 10 Chrome, Google Pixel 6, Apple iPhone 10,3
|
||||||
deviceVersion,
|
deviceVersion,
|
||||||
UserId
|
userId
|
||||||
}
|
}
|
||||||
newRecords.Device.push(Device)
|
newRecords.device.push(Device)
|
||||||
oldDbIdMap.devices[deviceInfoStr] = Device.id
|
oldDbIdMap.devices[deviceInfoStr] = Device.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -929,18 +933,18 @@ function migrateSessions(oldSessions) {
|
|||||||
//
|
//
|
||||||
// Migrate PlaybackSession
|
// Migrate PlaybackSession
|
||||||
//
|
//
|
||||||
let MediaItemId = null
|
let mediaItemId = null
|
||||||
let mediaItemType = 'Book'
|
let mediaItemType = 'book'
|
||||||
if (oldSession.mediaType === 'podcast') {
|
if (oldSession.mediaType === 'podcast') {
|
||||||
MediaItemId = oldDbIdMap.podcastEpisodes[oldSession.episodeId] || null
|
mediaItemId = oldDbIdMap.podcastEpisodes[oldSession.episodeId] || null
|
||||||
mediaItemType = 'PodcastEpisode'
|
mediaItemType = 'podcastEpisode'
|
||||||
} else {
|
} else {
|
||||||
MediaItemId = oldDbIdMap.books[oldSession.libraryItemId] || null
|
mediaItemId = oldDbIdMap.books[oldSession.libraryItemId] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlaybackSession = {
|
const PlaybackSession = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
MediaItemId, // Can be null
|
mediaItemId, // Can be null
|
||||||
mediaItemType,
|
mediaItemType,
|
||||||
displayTitle: oldSession.displayTitle,
|
displayTitle: oldSession.displayTitle,
|
||||||
displayAuthor: oldSession.displayAuthor,
|
displayAuthor: oldSession.displayAuthor,
|
||||||
@ -952,10 +956,10 @@ function migrateSessions(oldSessions) {
|
|||||||
serverVersion: oldSession.deviceInfo?.serverVersion || null,
|
serverVersion: oldSession.deviceInfo?.serverVersion || null,
|
||||||
createdAt: oldSession.startedAt,
|
createdAt: oldSession.startedAt,
|
||||||
updatedAt: oldSession.updatedAt,
|
updatedAt: oldSession.updatedAt,
|
||||||
UserId, // Can be null
|
userId, // Can be null
|
||||||
DeviceId
|
deviceId
|
||||||
}
|
}
|
||||||
newRecords.PlaybackSession.push(PlaybackSession)
|
newRecords.playbackSession.push(PlaybackSession)
|
||||||
|
|
||||||
if (oldSession.timeListening) {
|
if (oldSession.timeListening) {
|
||||||
const PlaybackSessionListenTime = {
|
const PlaybackSessionListenTime = {
|
||||||
@ -964,17 +968,17 @@ function migrateSessions(oldSessions) {
|
|||||||
date: oldSession.date || dateAndTime.format(new Date(PlaybackSession.createdAt), 'YYYY-MM-DD'),
|
date: oldSession.date || dateAndTime.format(new Date(PlaybackSession.createdAt), 'YYYY-MM-DD'),
|
||||||
createdAt: PlaybackSession.createdAt,
|
createdAt: PlaybackSession.createdAt,
|
||||||
updatedAt: PlaybackSession.updatedAt,
|
updatedAt: PlaybackSession.updatedAt,
|
||||||
PlaybackSessionId: PlaybackSession.id
|
playbackSessionId: PlaybackSession.id
|
||||||
}
|
}
|
||||||
newRecords.PlaybackSessionListenTime.push(PlaybackSessionListenTime)
|
newRecords.playbackSessionListenTime.push(PlaybackSessionListenTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrateCollections(oldCollections) {
|
function migrateCollections(oldCollections) {
|
||||||
for (const oldCollection of oldCollections) {
|
for (const oldCollection of oldCollections) {
|
||||||
const LibraryId = oldDbIdMap.libraries[oldCollection.libraryId]
|
const libraryId = oldDbIdMap.libraries[oldCollection.libraryId]
|
||||||
if (!LibraryId) {
|
if (!libraryId) {
|
||||||
Logger.warn(`[dbMigration] migrateCollections: Library not found for collection "${oldCollection.name}" (id:${oldCollection.libraryId})`)
|
Logger.warn(`[dbMigration] migrateCollections: Library not found for collection "${oldCollection.name}" (id:${oldCollection.libraryId})`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -991,42 +995,42 @@ function migrateCollections(oldCollections) {
|
|||||||
description: oldCollection.description,
|
description: oldCollection.description,
|
||||||
createdAt: oldCollection.createdAt,
|
createdAt: oldCollection.createdAt,
|
||||||
updatedAt: oldCollection.lastUpdate,
|
updatedAt: oldCollection.lastUpdate,
|
||||||
LibraryId
|
libraryId
|
||||||
}
|
}
|
||||||
oldDbIdMap.collections[oldCollection.id] = Collection.id
|
oldDbIdMap.collections[oldCollection.id] = Collection.id
|
||||||
newRecords.Collection.push(Collection)
|
newRecords.collection.push(Collection)
|
||||||
|
|
||||||
BookIds.forEach((BookId) => {
|
BookIds.forEach((bookId) => {
|
||||||
const CollectionBook = {
|
const CollectionBook = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
createdAt: Collection.createdAt,
|
createdAt: Collection.createdAt,
|
||||||
BookId,
|
bookId,
|
||||||
CollectionId: Collection.id
|
collectionId: Collection.id
|
||||||
}
|
}
|
||||||
newRecords.CollectionBook.push(CollectionBook)
|
newRecords.collectionBook.push(CollectionBook)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function migratePlaylists(oldPlaylists) {
|
function migratePlaylists(oldPlaylists) {
|
||||||
for (const oldPlaylist of oldPlaylists) {
|
for (const oldPlaylist of oldPlaylists) {
|
||||||
const LibraryId = oldDbIdMap.libraries[oldPlaylist.libraryId]
|
const libraryId = oldDbIdMap.libraries[oldPlaylist.libraryId]
|
||||||
if (!LibraryId) {
|
if (!libraryId) {
|
||||||
Logger.warn(`[dbMigration] migratePlaylists: Library not found for playlist "${oldPlaylist.name}" (id:${oldPlaylist.libraryId})`)
|
Logger.warn(`[dbMigration] migratePlaylists: Library not found for playlist "${oldPlaylist.name}" (id:${oldPlaylist.libraryId})`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserId = oldDbIdMap.users[oldPlaylist.userId]
|
const userId = oldDbIdMap.users[oldPlaylist.userId]
|
||||||
if (!UserId) {
|
if (!userId) {
|
||||||
Logger.warn(`[dbMigration] migratePlaylists: User not found for playlist "${oldPlaylist.name}" (id:${oldPlaylist.userId})`)
|
Logger.warn(`[dbMigration] migratePlaylists: User not found for playlist "${oldPlaylist.name}" (id:${oldPlaylist.userId})`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let mediaItemType = 'Book'
|
let mediaItemType = 'book'
|
||||||
let MediaItemIds = []
|
let MediaItemIds = []
|
||||||
oldPlaylist.items.forEach((itemObj) => {
|
oldPlaylist.items.forEach((itemObj) => {
|
||||||
if (itemObj.episodeId) {
|
if (itemObj.episodeId) {
|
||||||
mediaItemType = 'PodcastEpisode'
|
mediaItemType = 'podcastEpisode'
|
||||||
if (oldDbIdMap.podcastEpisodes[itemObj.episodeId]) {
|
if (oldDbIdMap.podcastEpisodes[itemObj.episodeId]) {
|
||||||
MediaItemIds.push(oldDbIdMap.podcastEpisodes[itemObj.episodeId])
|
MediaItemIds.push(oldDbIdMap.podcastEpisodes[itemObj.episodeId])
|
||||||
}
|
}
|
||||||
@ -1045,20 +1049,20 @@ function migratePlaylists(oldPlaylists) {
|
|||||||
description: oldPlaylist.description,
|
description: oldPlaylist.description,
|
||||||
createdAt: oldPlaylist.createdAt,
|
createdAt: oldPlaylist.createdAt,
|
||||||
updatedAt: oldPlaylist.lastUpdate,
|
updatedAt: oldPlaylist.lastUpdate,
|
||||||
UserId,
|
userId,
|
||||||
LibraryId
|
libraryId
|
||||||
}
|
}
|
||||||
newRecords.Playlist.push(Playlist)
|
newRecords.playlist.push(Playlist)
|
||||||
|
|
||||||
MediaItemIds.forEach((MediaItemId) => {
|
MediaItemIds.forEach((mediaItemId) => {
|
||||||
const PlaylistMediaItem = {
|
const PlaylistMediaItem = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
MediaItemId,
|
mediaItemId,
|
||||||
mediaItemType,
|
mediaItemType,
|
||||||
createdAt: Playlist.createdAt,
|
createdAt: Playlist.createdAt,
|
||||||
PlaylistId: Playlist.id
|
playlistId: Playlist.id
|
||||||
}
|
}
|
||||||
newRecords.PlaylistMediaItem.push(PlaylistMediaItem)
|
newRecords.playlistMediaItem.push(PlaylistMediaItem)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1069,27 +1073,23 @@ function migrateFeeds(oldFeeds) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let entityType = null
|
let entityId = null
|
||||||
let EntityId = null
|
|
||||||
|
|
||||||
if (oldFeed.entityType === 'collection') {
|
if (oldFeed.entityType === 'collection') {
|
||||||
entityType = 'Collection'
|
entityId = oldDbIdMap.collections[oldFeed.entityId]
|
||||||
EntityId = oldDbIdMap.collections[oldFeed.entityId]
|
|
||||||
} else if (oldFeed.entityType === 'libraryItem') {
|
} else if (oldFeed.entityType === 'libraryItem') {
|
||||||
entityType = 'LibraryItem'
|
entityId = oldDbIdMap.libraryItems[oldFeed.entityId]
|
||||||
EntityId = oldDbIdMap.libraryItems[oldFeed.entityId]
|
|
||||||
} else if (oldFeed.entityType === 'series') {
|
} else if (oldFeed.entityType === 'series') {
|
||||||
entityType = 'Series'
|
entityId = oldDbIdMap.series[oldFeed.entityId]
|
||||||
EntityId = oldDbIdMap.series[oldFeed.entityId]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntityId) {
|
if (!entityId) {
|
||||||
Logger.warn(`[dbMigration] migrateFeeds: Entity not found for feed "${entityType}" (id:${oldFeed.entityId})`)
|
Logger.warn(`[dbMigration] migrateFeeds: Entity not found for feed "${oldFeed.entityType}" (id:${oldFeed.entityId})`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserId = oldDbIdMap.users[oldFeed.userId]
|
const userId = oldDbIdMap.users[oldFeed.userId]
|
||||||
if (!UserId) {
|
if (!userId) {
|
||||||
Logger.warn(`[dbMigration] migrateFeeds: User not found for feed (id:${oldFeed.userId})`)
|
Logger.warn(`[dbMigration] migrateFeeds: User not found for feed (id:${oldFeed.userId})`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1099,8 +1099,8 @@ function migrateFeeds(oldFeeds) {
|
|||||||
const Feed = {
|
const Feed = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
slug: oldFeed.slug,
|
slug: oldFeed.slug,
|
||||||
entityType,
|
entityType: oldFeed.entityType,
|
||||||
EntityId,
|
entityId,
|
||||||
entityUpdatedAt: oldFeed.entityUpdatedAt,
|
entityUpdatedAt: oldFeed.entityUpdatedAt,
|
||||||
serverAddress: oldFeed.serverAddress,
|
serverAddress: oldFeed.serverAddress,
|
||||||
feedURL: oldFeed.feedUrl,
|
feedURL: oldFeed.feedUrl,
|
||||||
@ -1117,9 +1117,9 @@ function migrateFeeds(oldFeeds) {
|
|||||||
preventIndexing: !!oldFeedMeta.preventIndexing,
|
preventIndexing: !!oldFeedMeta.preventIndexing,
|
||||||
createdAt: oldFeed.createdAt,
|
createdAt: oldFeed.createdAt,
|
||||||
updatedAt: oldFeed.updatedAt,
|
updatedAt: oldFeed.updatedAt,
|
||||||
UserId
|
userId
|
||||||
}
|
}
|
||||||
newRecords.Feed.push(Feed)
|
newRecords.feed.push(Feed)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate FeedEpisodes
|
// Migrate FeedEpisodes
|
||||||
@ -1143,9 +1143,9 @@ function migrateFeeds(oldFeeds) {
|
|||||||
explicit: !!oldFeedEpisode.explicit,
|
explicit: !!oldFeedEpisode.explicit,
|
||||||
createdAt: oldFeed.createdAt,
|
createdAt: oldFeed.createdAt,
|
||||||
updatedAt: oldFeed.updatedAt,
|
updatedAt: oldFeed.updatedAt,
|
||||||
FeedId: Feed.id
|
feedId: Feed.id
|
||||||
}
|
}
|
||||||
newRecords.FeedEpisode.push(FeedEpisode)
|
newRecords.feedEpisode.push(FeedEpisode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1162,7 +1162,7 @@ function migrateSettings(oldSettings) {
|
|||||||
if (value === undefined) value = null
|
if (value === undefined) value = null
|
||||||
else if (serverSettingsKey === 'sortingPrefixes') value = JSON.stringify(value)
|
else if (serverSettingsKey === 'sortingPrefixes') value = JSON.stringify(value)
|
||||||
|
|
||||||
newRecords.Setting.push({
|
newRecords.setting.push({
|
||||||
key: serverSettingsKey,
|
key: serverSettingsKey,
|
||||||
value,
|
value,
|
||||||
type: 0
|
type: 0
|
||||||
@ -1178,7 +1178,7 @@ function migrateSettings(oldSettings) {
|
|||||||
notificationDelay: notificationSettings.notificationDelay ?? 1000 // ms delay between firing notifications
|
notificationDelay: notificationSettings.notificationDelay ?? 1000 // ms delay between firing notifications
|
||||||
}
|
}
|
||||||
for (const notificationSettingKey in cleanedCopy) {
|
for (const notificationSettingKey in cleanedCopy) {
|
||||||
newRecords.Setting.push({
|
newRecords.setting.push({
|
||||||
key: notificationSettingKey,
|
key: notificationSettingKey,
|
||||||
value: cleanedCopy[notificationSettingKey],
|
value: cleanedCopy[notificationSettingKey],
|
||||||
type: 1
|
type: 1
|
||||||
@ -1206,7 +1206,7 @@ function migrateSettings(oldSettings) {
|
|||||||
createdAt: oldNotification.createdAt,
|
createdAt: oldNotification.createdAt,
|
||||||
updatedAt: oldNotification.createdAt
|
updatedAt: oldNotification.createdAt
|
||||||
}
|
}
|
||||||
newRecords.Notification.push(Notification)
|
newRecords.notification.push(Notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user