mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-24 15:48:50 +01:00
Update logger to support dev only log, remove old model docs
This commit is contained in:
parent
c5a4f63670
commit
89aa4a8bdc
@ -1,171 +0,0 @@
|
||||
/*
|
||||
This is an example of a fully expanded book library item
|
||||
*/
|
||||
|
||||
const LibraryItem = require('../server/objects/LibraryItem')
|
||||
|
||||
new LibraryItem({
|
||||
id: 'li_abai123wir',
|
||||
ino: "55450570412017066",
|
||||
libraryId: 'lib_1239p1d8',
|
||||
folderId: 'fol_192ab8901',
|
||||
path: '/audiobooks/Terry Goodkind/Sword of Truth/1 - Wizards First Rule',
|
||||
relPath: '/Terry Goodkind/Sword of Truth/1 - Wizards First Rule',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127,
|
||||
lastScan: 1646784672127,
|
||||
scanVersion: 1.72,
|
||||
isMissing: false,
|
||||
isInvalid: false,
|
||||
mediaType: 'book',
|
||||
media: { // Book.js
|
||||
coverPath: '/metadata/items/li_abai123wir/cover.webp',
|
||||
tags: ['favorites'],
|
||||
lastCoverSearch: null,
|
||||
lastCoverSearchQuery: null,
|
||||
metadata: { // BookMetadata.js
|
||||
title: 'Wizards First Rule',
|
||||
subtitle: null,
|
||||
authors: [
|
||||
{
|
||||
id: 'au_42908lkajsfdk',
|
||||
name: 'Terry Goodkind'
|
||||
}
|
||||
],
|
||||
narrators: ['Sam Tsoutsouvas'],
|
||||
series: [
|
||||
{
|
||||
id: 'se_902384lansf',
|
||||
name: 'Sword of Truth',
|
||||
sequence: 1
|
||||
}
|
||||
],
|
||||
genres: ['Fantasy', 'Adventure'],
|
||||
publishedYear: '1994',
|
||||
publishedDate: '1994-01-01',
|
||||
publisher: 'Brilliance Audio',
|
||||
description: 'In the aftermath of the brutal murder of his father, a mysterious woman...',
|
||||
isbn: '289374092834',
|
||||
asin: '19023819203',
|
||||
language: 'english',
|
||||
explicit: false
|
||||
},
|
||||
audioFiles: [
|
||||
{ // AudioFile.js
|
||||
ino: "55450570412017066",
|
||||
index: 1,
|
||||
metadata: { // FileMetadata.js
|
||||
filename: 'audiofile.mp3',
|
||||
ext: '.mp3',
|
||||
path: '/audiobooks/Terry Goodkind/Sword of Truth/1 - Wizards First Rule/CD01/audiofile.mp3',
|
||||
relPath: '/CD01/audiofile.mp3',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
size: 1197449516
|
||||
},
|
||||
trackNumFromMeta: 1,
|
||||
discNumFromMeta: null,
|
||||
trackNumFromFilename: null,
|
||||
discNumFromFilename: 1,
|
||||
manuallyVerified: false,
|
||||
exclude: false,
|
||||
invalid: false,
|
||||
format: "MP2/3 (MPEG audio layer 2/3)",
|
||||
duration: 2342342,
|
||||
bitRate: 324234,
|
||||
language: null,
|
||||
codec: 'mp3',
|
||||
timeBase: "1/14112000",
|
||||
channels: 1,
|
||||
channelLayout: "mono",
|
||||
chapters: [],
|
||||
embeddedCoverArt: 'jpeg', // Video stream codec ['mjpeg', 'jpeg', 'png'] or null
|
||||
metaTags: { // AudioMetaTags.js
|
||||
tagAlbum: '',
|
||||
tagArtist: '',
|
||||
tagGenre: '',
|
||||
tagTitle: '',
|
||||
tagSeries: '',
|
||||
tagSeriesPart: '',
|
||||
tagTrack: '',
|
||||
tagDisc: '',
|
||||
tagSubtitle: '',
|
||||
tagAlbumArtist: '',
|
||||
tagDate: '',
|
||||
tagComposer: '',
|
||||
tagPublisher: '',
|
||||
tagComment: '',
|
||||
tagDescription: '',
|
||||
tagEncoder: '',
|
||||
tagEncodedBy: '',
|
||||
tagIsbn: '',
|
||||
tagLanguage: '',
|
||||
tagASIN: ''
|
||||
},
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
}
|
||||
],
|
||||
chapters: [
|
||||
{
|
||||
id: 0,
|
||||
title: 'Chapter 01',
|
||||
start: 0,
|
||||
end: 2467.753
|
||||
}
|
||||
],
|
||||
missingParts: [4, 10], // Array of missing parts in tracklist
|
||||
ebookFile: { // EBookFile.js
|
||||
ino: "55450570412017066",
|
||||
metadata: { // FileMetadata.js
|
||||
filename: 'ebookfile.mobi',
|
||||
ext: '.mobi',
|
||||
path: '/audiobooks/Terry Goodkind/Sword of Truth/1 - Wizards First Rule/ebookfile.mobi',
|
||||
relPath: '/ebookfile.mobi',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
size: 1197449516
|
||||
},
|
||||
ebookFormat: 'mobi',
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
}
|
||||
},
|
||||
libraryFiles: [
|
||||
{ // LibraryFile.js
|
||||
ino: "55450570412017066",
|
||||
metadata: { // FileMetadata.js
|
||||
filename: 'cover.png',
|
||||
ext: '.png',
|
||||
path: '/audiobooks/Terry Goodkind/Sword of Truth/1 - Wizards First Rule/subfolder/cover.png',
|
||||
relPath: '/subfolder/cover.png',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
size: 1197449516
|
||||
},
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
},
|
||||
{ // LibraryFile.js
|
||||
ino: "55450570412017066",
|
||||
metadata: { // FileMetadata.js
|
||||
filename: 'cover.png',
|
||||
ext: '.mobi',
|
||||
path: '/audiobooks/Terry Goodkind/Sword of Truth/1 - Wizards First Rule/ebookfile.mobi',
|
||||
relPath: '/ebookfile.mobi',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
size: 1197449516
|
||||
},
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
}
|
||||
]
|
||||
})
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
This is an example of a fully expanded podcast library item (under construction)
|
||||
*/
|
||||
|
||||
const LibraryItem = require('../server/objects/LibraryItem')
|
||||
|
||||
new LibraryItem({
|
||||
id: 'li_abai123wir',
|
||||
ino: "55450570412017066",
|
||||
libraryId: 'lib_1239p1d8',
|
||||
folderId: 'fol_192ab8901',
|
||||
path: '/podcasts/Great Podcast Name',
|
||||
relPath: '/Great Podcast Name',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127,
|
||||
lastScan: 1646784672127,
|
||||
scanVersion: 1.72,
|
||||
isMissing: false,
|
||||
isInvalid: false,
|
||||
mediaType: 'podcast',
|
||||
media: { // Podcast.js
|
||||
coverPath: '/metadata/items/li_abai123wir/cover.webp',
|
||||
tags: ['favorites'],
|
||||
lastCoverSearch: null,
|
||||
lastCoverSearchQuery: null,
|
||||
metadata: { // PodcastMetadata.js
|
||||
title: 'Great Podcast Name',
|
||||
artist: 'Some Artist Name',
|
||||
genres: ['Fantasy', 'Adventure'],
|
||||
publishedDate: '1994-01-01',
|
||||
description: 'In the aftermath of the brutal murder of his father, a mysterious woman...',
|
||||
feedUrl: '',
|
||||
itunesPageUrl: '',
|
||||
itunesId: '',
|
||||
itunesArtistId: '',
|
||||
explicit: false
|
||||
},
|
||||
episodes: [
|
||||
{ // PodcastEpisode.js
|
||||
id: 'ep_289374asf0a98',
|
||||
index: 1,
|
||||
// TODO: podcast episode data and PodcastEpisodeMetadata
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
}
|
||||
]
|
||||
},
|
||||
libraryFiles: [
|
||||
{ // LibraryFile.js
|
||||
ino: "55450570412017066",
|
||||
metadata: { // FileMetadata.js
|
||||
filename: 'cover.png',
|
||||
ext: '.png',
|
||||
path: '/podcasts/Great Podcast Name/cover.png',
|
||||
relPath: '/cover.png',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
size: 1197449516
|
||||
},
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
},
|
||||
{ // LibraryFile.js
|
||||
ino: "55450570412017066",
|
||||
metadata: { // FileMetadata.js
|
||||
filename: 'episode_1.mp3',
|
||||
ext: '.mp3',
|
||||
path: '/podcasts/Great Podcast Name/episode_1.mp3',
|
||||
relPath: '/episode_1.mp3',
|
||||
mtimeMs: 1646784672127,
|
||||
ctimeMs: 1646784672127,
|
||||
birthtimeMs: 1646784672127,
|
||||
size: 1197449516
|
||||
},
|
||||
addedAt: 1646784672127,
|
||||
updatedAt: 1646784672127
|
||||
}
|
||||
]
|
||||
})
|
@ -57,7 +57,7 @@ class Database {
|
||||
}
|
||||
|
||||
await this.buildModels(force)
|
||||
Logger.info(`[Database] Db initialized`, Object.keys(this.sequelize.models))
|
||||
Logger.info(`[Database] Db initialized with models:`, Object.keys(this.sequelize.models).join(', '))
|
||||
|
||||
await this.loadData()
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ const { LogLevel } = require('./utils/constants')
|
||||
|
||||
class Logger {
|
||||
constructor() {
|
||||
this.logLevel = process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.TRACE
|
||||
this.isDev = process.env.NODE_ENV !== 'production'
|
||||
this.logLevel = !this.isDev ? LogLevel.INFO : LogLevel.TRACE
|
||||
this.socketListeners = []
|
||||
|
||||
this.logManager = null
|
||||
@ -86,6 +87,15 @@ class Logger {
|
||||
this.debug(`Set Log Level to ${this.levelString}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Only to console and only for development
|
||||
* @param {...any} args
|
||||
*/
|
||||
dev(...args) {
|
||||
if (!this.isDev) return
|
||||
console.log(`[${this.timestamp}] DEV:`, ...args)
|
||||
}
|
||||
|
||||
trace(...args) {
|
||||
if (this.logLevel > LogLevel.TRACE) return
|
||||
console.trace(`[${this.timestamp}] TRACE:`, ...args)
|
||||
|
@ -1,6 +1,5 @@
|
||||
const Logger = require('../Logger')
|
||||
const { DataTypes, Model } = require('sequelize')
|
||||
|
||||
const Logger = require('../Logger')
|
||||
const oldLibrary = require('../objects/Library')
|
||||
|
||||
module.exports = (sequelize) => {
|
||||
|
@ -149,7 +149,7 @@ module.exports = (sequelize) => {
|
||||
for (const existingPodcastEpisode of existingPodcastEpisodes) {
|
||||
// Episode was removed
|
||||
if (!updatedPodcastEpisodes.some(ep => ep.id === existingPodcastEpisode.id)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${existingPodcastEpisode.title}" was removed`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${existingPodcastEpisode.title}" was removed`)
|
||||
await existingPodcastEpisode.destroy()
|
||||
hasUpdates = true
|
||||
}
|
||||
@ -157,7 +157,7 @@ module.exports = (sequelize) => {
|
||||
for (const updatedPodcastEpisode of updatedPodcastEpisodes) {
|
||||
const existingEpisodeMatch = existingPodcastEpisodes.find(ep => ep.id === updatedPodcastEpisode.id)
|
||||
if (!existingEpisodeMatch) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${updatedPodcastEpisode.title}" was added`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${updatedPodcastEpisode.title}" was added`)
|
||||
await sequelize.models.podcastEpisode.createFromOld(updatedPodcastEpisode)
|
||||
hasUpdates = true
|
||||
} else {
|
||||
@ -168,7 +168,7 @@ module.exports = (sequelize) => {
|
||||
if (existingValue instanceof Date) existingValue = existingValue.valueOf()
|
||||
|
||||
if (!areEquivalent(updatedEpisodeCleaned[key], existingValue, true)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${existingEpisodeMatch.title}" ${key} was updated from "${existingValue}" to "${updatedEpisodeCleaned[key]}"`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" episode "${existingEpisodeMatch.title}" ${key} was updated from "${existingValue}" to "${updatedEpisodeCleaned[key]}"`)
|
||||
episodeHasUpdates = true
|
||||
}
|
||||
}
|
||||
@ -189,7 +189,7 @@ module.exports = (sequelize) => {
|
||||
for (const existingAuthor of existingAuthors) {
|
||||
// Author was removed from Book
|
||||
if (!updatedAuthors.some(au => au.id === existingAuthor.id)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${existingAuthor.name}" was removed`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${existingAuthor.name}" was removed`)
|
||||
await sequelize.models.bookAuthor.removeByIds(existingAuthor.id, libraryItemExpanded.media.id)
|
||||
hasUpdates = true
|
||||
}
|
||||
@ -197,7 +197,7 @@ module.exports = (sequelize) => {
|
||||
for (const updatedAuthor of updatedAuthors) {
|
||||
// Author was added
|
||||
if (!existingAuthors.some(au => au.id === updatedAuthor.id)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${updatedAuthor.name}" was added`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" author "${updatedAuthor.name}" was added`)
|
||||
await sequelize.models.bookAuthor.create({ authorId: updatedAuthor.id, bookId: libraryItemExpanded.media.id })
|
||||
hasUpdates = true
|
||||
}
|
||||
@ -205,7 +205,7 @@ module.exports = (sequelize) => {
|
||||
for (const existingSeries of existingSeriesAll) {
|
||||
// Series was removed
|
||||
if (!updatedSeriesAll.some(se => se.id === existingSeries.id)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${existingSeries.name}" was removed`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${existingSeries.name}" was removed`)
|
||||
await sequelize.models.bookSeries.removeByIds(existingSeries.id, libraryItemExpanded.media.id)
|
||||
hasUpdates = true
|
||||
}
|
||||
@ -214,11 +214,11 @@ module.exports = (sequelize) => {
|
||||
// Series was added/updated
|
||||
const existingSeriesMatch = existingSeriesAll.find(se => se.id === updatedSeries.id)
|
||||
if (!existingSeriesMatch) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" was added`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" was added`)
|
||||
await sequelize.models.bookSeries.create({ seriesId: updatedSeries.id, bookId: libraryItemExpanded.media.id, sequence: updatedSeries.sequence })
|
||||
hasUpdates = true
|
||||
} else if (existingSeriesMatch.bookSeries.sequence !== updatedSeries.sequence) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" sequence was updated from "${existingSeriesMatch.bookSeries.sequence}" to "${updatedSeries.sequence}"`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" series "${updatedSeries.name}" sequence was updated from "${existingSeriesMatch.bookSeries.sequence}" to "${updatedSeries.sequence}"`)
|
||||
await existingSeriesMatch.bookSeries.update({ sequence: updatedSeries.sequence })
|
||||
hasUpdates = true
|
||||
}
|
||||
@ -231,7 +231,7 @@ module.exports = (sequelize) => {
|
||||
if (existingValue instanceof Date) existingValue = existingValue.valueOf()
|
||||
|
||||
if (!areEquivalent(updatedMedia[key], existingValue, true)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" ${libraryItemExpanded.mediaType}.${key} updated from ${existingValue} to ${updatedMedia[key]}`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" ${libraryItemExpanded.mediaType}.${key} updated from ${existingValue} to ${updatedMedia[key]}`)
|
||||
hasMediaUpdates = true
|
||||
}
|
||||
}
|
||||
@ -248,29 +248,18 @@ module.exports = (sequelize) => {
|
||||
if (existingValue instanceof Date) existingValue = existingValue.valueOf()
|
||||
|
||||
if (!areEquivalent(updatedLibraryItem[key], existingValue, true)) {
|
||||
Logger.debug(`[LibraryItem] "${libraryItemExpanded.media.title}" ${key} updated from ${existingValue} to ${updatedLibraryItem[key]}`)
|
||||
Logger.dev(`[LibraryItem] "${libraryItemExpanded.media.title}" ${key} updated from ${existingValue} to ${updatedLibraryItem[key]}`)
|
||||
hasLibraryItemUpdates = true
|
||||
}
|
||||
}
|
||||
if (hasLibraryItemUpdates) {
|
||||
await libraryItemExpanded.update(updatedLibraryItem)
|
||||
Logger.info(`[LibraryItem] Library item "${libraryItemExpanded.id}" updated`)
|
||||
hasUpdates = true
|
||||
}
|
||||
return hasUpdates
|
||||
}
|
||||
|
||||
static updateFromOld(oldLibraryItem) {
|
||||
const libraryItem = this.getFromOld(oldLibraryItem)
|
||||
return this.update(libraryItem, {
|
||||
where: {
|
||||
id: libraryItem.id
|
||||
}
|
||||
}).then((result) => result[0] > 0).catch((error) => {
|
||||
Logger.error(`[LibraryItem] Failed to update libraryItem ${libraryItem.id}`, error)
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
static getFromOld(oldLibraryItem) {
|
||||
return {
|
||||
id: oldLibraryItem.id,
|
||||
|
@ -1,4 +1,5 @@
|
||||
const { DataTypes, Model } = require('sequelize')
|
||||
const Logger = require('../Logger')
|
||||
|
||||
const oldPlaylist = require('../objects/Playlist')
|
||||
const { areEquivalent } = require('../utils/index')
|
||||
@ -32,14 +33,15 @@ module.exports = (sequelize) => {
|
||||
const items = playlistExpanded.playlistMediaItems.map(pmi => {
|
||||
const libraryItemId = pmi.mediaItem?.podcast?.libraryItem?.id || pmi.mediaItem?.libraryItem?.id || null
|
||||
if (!libraryItemId) {
|
||||
console.log(JSON.stringify(pmi, null, 2))
|
||||
throw new Error('No library item id')
|
||||
Logger.error(`[Playlist] Invalid playlist media item - No library item id found`, JSON.stringify(pmi, null, 2))
|
||||
return null
|
||||
}
|
||||
return {
|
||||
episodeId: pmi.mediaItemType === 'podcastEpisode' ? pmi.mediaItemId : '',
|
||||
libraryItemId: libraryItemId
|
||||
libraryItemId
|
||||
}
|
||||
})
|
||||
}).filter(pmi => pmi)
|
||||
|
||||
return new oldPlaylist({
|
||||
id: playlistExpanded.id,
|
||||
libraryId: playlistExpanded.libraryId,
|
||||
|
@ -447,7 +447,7 @@ class ApiRouter {
|
||||
if (!otherLibraryItemsInSeries.length) {
|
||||
// Close open RSS feed for series
|
||||
await this.rssFeedManager.closeFeedForEntityId(series.id)
|
||||
Logger.debug(`[ApiRouter] Series "${series.name}" is now empty. Removing series`)
|
||||
Logger.info(`[ApiRouter] Series "${series.name}" is now empty. Removing series`)
|
||||
await Database.removeSeries(series.id)
|
||||
// TODO: Socket events for series?
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ function migrateSessions(oldSessions) {
|
||||
for (const oldSession of oldSessions) {
|
||||
const userId = oldDbIdMap.users[oldSession.userId]
|
||||
if (!userId) {
|
||||
Logger.debug(`[dbMigration] Not migrating playback session ${oldSession.id} because user was not found`)
|
||||
Logger.info(`[dbMigration] Not migrating playback session ${oldSession.id} because user was not found`)
|
||||
continue
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user