diff --git a/server/ApiController.js b/server/ApiController.js index 96cef619..45969c75 100644 --- a/server/ApiController.js +++ b/server/ApiController.js @@ -18,7 +18,7 @@ const AuthorFinder = require('./AuthorFinder') const FileSystemController = require('./controllers/FileSystemController') class ApiController { - constructor(MetadataPath, db, auth, scanner, streamManager, rssFeeds, downloadManager, coverController, backupManager, watcher, cacheManager, emitter, clientEmitter) { + constructor(db, auth, scanner, streamManager, rssFeeds, downloadManager, coverController, backupManager, watcher, cacheManager, emitter, clientEmitter) { this.db = db this.auth = auth this.scanner = scanner @@ -31,10 +31,9 @@ class ApiController { this.cacheManager = cacheManager this.emitter = emitter this.clientEmitter = clientEmitter - this.MetadataPath = MetadataPath this.bookFinder = new BookFinder() - this.authorFinder = new AuthorFinder(this.MetadataPath) + this.authorFinder = new AuthorFinder() this.router = express() this.init() @@ -287,7 +286,7 @@ class ApiController { this.backupManager.updateCronSchedule() } - await this.db.updateEntity('settings', this.db.serverSettings) + await this.db.updateServerSettings() } return res.json({ success: true, diff --git a/server/AuthorFinder.js b/server/AuthorFinder.js index fe0f3b51..ba3f3a83 100644 --- a/server/AuthorFinder.js +++ b/server/AuthorFinder.js @@ -7,9 +7,8 @@ const Audnexus = require('./providers/Audnexus') const { downloadFile } = require('./utils/fileUtils') class AuthorFinder { - constructor(MetadataPath) { - this.MetadataPath = MetadataPath - this.AuthorPath = Path.join(MetadataPath, 'authors') + constructor() { + this.AuthorPath = Path.join(global.MetadataPath, 'authors') this.audnexus = new Audnexus() } diff --git a/server/BackupManager.js b/server/BackupManager.js index b59ffe01..22be4278 100644 --- a/server/BackupManager.js +++ b/server/BackupManager.js @@ -13,9 +13,9 @@ const Logger = require('./Logger') const Backup = require('./objects/Backup') class BackupManager { - constructor(MetadataPath, Uid, Gid, db) { - this.MetadataPath = MetadataPath - this.BackupPath = Path.join(this.MetadataPath, 'backups') + constructor(Uid, Gid, db) { + this.BackupPath = Path.join(global.MetadataPath, 'backups') + this.MetadataBooksPath = Path.join(global.MetadataPath, 'books') this.Uid = Uid this.Gid = Gid @@ -142,10 +142,9 @@ class BackupManager { return } const zip = new StreamZip.async({ file: backup.fullPath }) - await zip.extract('config/', this.db.ConfigPath) + await zip.extract('config/', global.ConfigPath) if (backup.backupMetadataCovers) { - var metadataBooksPath = Path.join(this.MetadataPath, 'books') - await zip.extract('metadata-books/', metadataBooksPath) + await zip.extract('metadata-books/', this.MetadataBooksPath) } await this.db.reinit() socket.emit('apply_backup_complete', true) @@ -157,7 +156,7 @@ class BackupManager { var lastBackup = this.backups.shift() const zip = new StreamZip.async({ file: lastBackup.fullPath }) - await zip.extract('config/', this.db.ConfigPath) + await zip.extract('config/', global.ConfigPath) console.log('Set Last Backup') await this.db.reinit() } @@ -196,7 +195,7 @@ class BackupManager { async runBackup() { // Check if Metadata Path is inside Config Path (otherwise there will be an infinite loop as the archiver tries to zip itself) Logger.info(`[BackupManager] Running Backup`) - var metadataBooksPath = this.serverSettings.backupMetadataCovers ? Path.join(this.MetadataPath, 'books') : null + var metadataBooksPath = this.serverSettings.backupMetadataCovers ? this.MetadataBooksPath : null var newBackup = new Backup() diff --git a/server/CacheManager.js b/server/CacheManager.js index 29ba4cca..bece235f 100644 --- a/server/CacheManager.js +++ b/server/CacheManager.js @@ -5,9 +5,8 @@ const Logger = require('./Logger') const { resizeImage } = require('./utils/ffmpegHelpers') class CacheManager { - constructor(MetadataPath) { - this.MetadataPath = MetadataPath - this.CachePath = Path.join(this.MetadataPath, 'cache') + constructor() { + this.CachePath = Path.join(global.MetadataPath, 'cache') this.CoverCachePath = Path.join(this.CachePath, 'covers') } diff --git a/server/CoverController.js b/server/CoverController.js index 187b5a10..fc8de935 100644 --- a/server/CoverController.js +++ b/server/CoverController.js @@ -9,13 +9,11 @@ const globals = require('./utils/globals') const { downloadFile } = require('./utils/fileUtils') class CoverController { - constructor(db, cacheManager, MetadataPath, AudiobookPath) { + constructor(db, cacheManager) { this.db = db this.cacheManager = cacheManager - this.MetadataPath = MetadataPath.replace(/\\/g, '/') - this.BookMetadataPath = Path.posix.join(this.MetadataPath, 'books') - this.AudiobookPath = AudiobookPath + this.BookMetadataPath = Path.posix.join(global.MetadataPath, 'books') } getCoverDirectory(audiobook) { diff --git a/server/Db.js b/server/Db.js index 2c550cf1..75868ccf 100644 --- a/server/Db.js +++ b/server/Db.js @@ -12,17 +12,14 @@ const Author = require('./objects/Author') const ServerSettings = require('./objects/ServerSettings') class Db { - constructor(ConfigPath, AudiobookPath) { - this.ConfigPath = ConfigPath - this.AudiobookPath = AudiobookPath - - this.AudiobooksPath = Path.join(ConfigPath, 'audiobooks') - this.UsersPath = Path.join(ConfigPath, 'users') - this.SessionsPath = Path.join(ConfigPath, 'sessions') - this.LibrariesPath = Path.join(ConfigPath, 'libraries') - this.SettingsPath = Path.join(ConfigPath, 'settings') - this.CollectionsPath = Path.join(ConfigPath, 'collections') - this.AuthorsPath = Path.join(ConfigPath, 'authors') + constructor() { + this.AudiobooksPath = Path.join(global.ConfigPath, 'audiobooks') + this.UsersPath = Path.join(global.ConfigPath, 'users') + this.SessionsPath = Path.join(global.ConfigPath, 'sessions') + this.LibrariesPath = Path.join(global.ConfigPath, 'libraries') + this.SettingsPath = Path.join(global.ConfigPath, 'settings') + this.CollectionsPath = Path.join(global.ConfigPath, 'collections') + this.AuthorsPath = Path.join(global.ConfigPath, 'authors') this.audiobooksDb = new njodb.Database(this.AudiobooksPath) this.usersDb = new njodb.Database(this.UsersPath) @@ -88,7 +85,7 @@ class Db { name: 'Main', folder: { // Generates default folder id: 'audiobooks', - fullPath: this.AudiobookPath, + fullPath: global.AudiobookPath, libraryId: 'main' } }) @@ -127,6 +124,7 @@ class Db { if (!this.serverSettings) { this.serverSettings = new ServerSettings() await this.insertEntity('settings', this.serverSettings) + global.ServerSettings = this.serverSettings.toJSON() } } @@ -170,7 +168,7 @@ class Db { // Update server version in server settings if (this.previousVersion) { this.serverSettings.version = version - await this.updateEntity('settings', this.serverSettings) + await this.updateServerSettings() } } @@ -201,6 +199,11 @@ class Db { }) } + updateServerSettings() { + global.ServerSettings = this.serverSettings.toJSON() + return this.updateEntity('settings', this.serverSettings) + } + insertEntities(entityName, entities) { var entityDb = this.getEntityDb(entityName) return entityDb.insert(entities).then((results) => { diff --git a/server/DownloadManager.js b/server/DownloadManager.js index 45a0213d..dce93901 100644 --- a/server/DownloadManager.js +++ b/server/DownloadManager.js @@ -11,14 +11,12 @@ const { writeConcatFile, writeMetadataFile } = require('./utils/ffmpegHelpers') const { getFileSize } = require('./utils/fileUtils') const TAG = 'DownloadManager' class DownloadManager { - constructor(db, MetadataPath, AudiobookPath, Uid, Gid) { + constructor(db, Uid, Gid) { this.Uid = Uid this.Gid = Gid this.db = db - this.MetadataPath = MetadataPath - this.AudiobookPath = AudiobookPath - this.downloadDirPath = Path.join(this.MetadataPath, 'downloads') + this.downloadDirPath = Path.join(global.MetadataPath, 'downloads') this.pendingDownloads = [] this.downloads = [] @@ -248,7 +246,7 @@ class DownloadManager { // Supporting old local file prefix var bookCoverPath = audiobook.book.cover ? audiobook.book.cover.replace(/\\/g, '/') : null if (!_cover && bookCoverPath && bookCoverPath.startsWith('/local')) { - _cover = Path.posix.join(this.AudiobookPath.replace(/\\/g, '/'), _cover.replace('/local', '')) + _cover = Path.posix.join(global.AudiobookPath, _cover.replace('/local', '')) Logger.debug('Local cover url', _cover) } diff --git a/server/HlsController.js b/server/HlsController.js index ed44c84f..35e80f52 100644 --- a/server/HlsController.js +++ b/server/HlsController.js @@ -4,12 +4,11 @@ const fs = require('fs-extra') const Logger = require('./Logger') class HlsController { - constructor(db, auth, streamManager, emitter, StreamsPath) { + constructor(db, auth, streamManager, emitter) { this.db = db this.auth = auth this.streamManager = streamManager this.emitter = emitter - this.StreamsPath = StreamsPath this.router = express() this.init() @@ -27,7 +26,7 @@ class HlsController { async streamFileRequest(req, res) { var streamId = req.params.stream - var fullFilePath = Path.join(this.StreamsPath, streamId, req.params.file) + var fullFilePath = Path.join(this.streamManager.StreamsPath, streamId, req.params.file) // development test stream - ignore if (streamId === 'test') { diff --git a/server/LogManager.js b/server/LogManager.js index fe684f45..0b7d6604 100644 --- a/server/LogManager.js +++ b/server/LogManager.js @@ -8,11 +8,10 @@ const Logger = require('./Logger') const TAG = '[LogManager]' class LogManager { - constructor(MetadataPath, db) { + constructor(db) { this.db = db - this.MetadataPath = MetadataPath - this.logDirPath = Path.join(this.MetadataPath, 'logs') + this.logDirPath = Path.join(global.MetadataPath, 'logs') this.dailyLogDirPath = Path.join(this.logDirPath, 'daily') this.currentDailyLog = null diff --git a/server/Server.js b/server/Server.js index fd5e19db..90a78422 100644 --- a/server/Server.js +++ b/server/Server.js @@ -35,27 +35,33 @@ class Server { this.Uid = isNaN(UID) ? 0 : Number(UID) this.Gid = isNaN(GID) ? 0 : Number(GID) this.Host = '0.0.0.0' - this.ConfigPath = Path.normalize(CONFIG_PATH) - this.AudiobookPath = Path.normalize(AUDIOBOOK_PATH) - this.MetadataPath = Path.normalize(METADATA_PATH) + global.ConfigPath = Path.normalize(CONFIG_PATH) + global.AudiobookPath = Path.normalize(AUDIOBOOK_PATH) + global.MetadataPath = Path.normalize(METADATA_PATH) + // Fix backslash if not on Windows + if (process.platform !== 'win32') { + global.ConfigPath = global.ConfigPath.replace(/\\/g, '/') + global.AudiobookPath = global.AudiobookPath.replace(/\\/g, '/') + global.MetadataPath = global.MetadataPath.replace(/\\/g, '/') + } - fs.ensureDirSync(CONFIG_PATH, 0o774) - fs.ensureDirSync(METADATA_PATH, 0o774) - fs.ensureDirSync(AUDIOBOOK_PATH, 0o774) + fs.ensureDirSync(global.ConfigPath, 0o774) + fs.ensureDirSync(global.MetadataPath, 0o774) + fs.ensureDirSync(global.AudiobookPath, 0o774) - this.db = new Db(this.ConfigPath, this.AudiobookPath) + this.db = new Db() this.auth = new Auth(this.db) - this.backupManager = new BackupManager(this.MetadataPath, this.Uid, this.Gid, this.db) - this.logManager = new LogManager(this.MetadataPath, this.db) - this.cacheManager = new CacheManager(this.MetadataPath) - this.watcher = new Watcher(this.AudiobookPath) - this.coverController = new CoverController(this.db, this.cacheManager, this.MetadataPath, this.AudiobookPath) - this.scanner = new Scanner(this.AudiobookPath, this.MetadataPath, this.db, this.coverController, this.emitter.bind(this)) + this.backupManager = new BackupManager(this.Uid, this.Gid, this.db) + this.logManager = new LogManager(this.db) + this.cacheManager = new CacheManager() + this.watcher = new Watcher() + this.coverController = new CoverController(this.db, this.cacheManager) + this.scanner = new Scanner(this.db, this.coverController, this.emitter.bind(this)) - this.streamManager = new StreamManager(this.db, this.MetadataPath, this.emitter.bind(this), this.clientEmitter.bind(this)) + this.streamManager = new StreamManager(this.db, this.emitter.bind(this), this.clientEmitter.bind(this)) this.rssFeeds = new RssFeeds(this.Port, this.db) - this.downloadManager = new DownloadManager(this.db, this.MetadataPath, this.AudiobookPath, this.Uid, this.Gid) - this.apiController = new ApiController(this.MetadataPath, this.db, this.auth, this.scanner, this.streamManager, this.rssFeeds, this.downloadManager, this.coverController, this.backupManager, this.watcher, this.cacheManager, this.emitter.bind(this), this.clientEmitter.bind(this)) + this.downloadManager = new DownloadManager(this.db, this.Uid, this.Gid) + this.apiController = new ApiController(this.db, this.auth, this.scanner, this.streamManager, this.rssFeeds, this.downloadManager, this.coverController, this.backupManager, this.watcher, this.cacheManager, this.emitter.bind(this), this.clientEmitter.bind(this)) this.hlsController = new HlsController(this.db, this.auth, this.streamManager, this.emitter.bind(this), this.streamManager.StreamsPath) Logger.logManager = this.logManager @@ -155,10 +161,10 @@ class Server { app.use(express.static(distPath)) // Old static path for covers - app.use('/local', this.authMiddleware.bind(this), express.static(this.AudiobookPath)) + app.use('/local', this.authMiddleware.bind(this), express.static(global.AudiobookPath)) // Metadata folder static path - app.use('/metadata', this.authMiddleware.bind(this), express.static(this.MetadataPath)) + app.use('/metadata', this.authMiddleware.bind(this), express.static(global.MetadataPath)) // Downloads folder static path app.use('/downloads', this.authMiddleware.bind(this), express.static(this.downloadManager.downloadDirPath)) @@ -349,7 +355,7 @@ class Server { // Remove unused /metadata/books/{id} folders async purgeMetadata() { - var booksMetadata = Path.join(this.MetadataPath, 'books') + var booksMetadata = Path.join(global.MetadataPath, 'books') var booksMetadataExists = await fs.pathExists(booksMetadata) if (!booksMetadataExists) return var foldersInBooksMetadata = await fs.readdir(booksMetadata) @@ -622,9 +628,9 @@ class Server { const initialPayload = { serverSettings: this.serverSettings.toJSON(), - audiobookPath: this.AudiobookPath, - metadataPath: this.MetadataPath, - configPath: this.ConfigPath, + audiobookPath: global.AudiobookPath, + metadataPath: global.MetadataPath, + configPath: global.ConfigPath, user: client.user.toJSONForBrowser(), stream: client.stream || null, librariesScanning: this.scanner.librariesScanning, diff --git a/server/StreamManager.js b/server/StreamManager.js index 0ed1e2e1..22fa1bc1 100644 --- a/server/StreamManager.js +++ b/server/StreamManager.js @@ -5,15 +5,14 @@ const fs = require('fs-extra') const Path = require('path') class StreamManager { - constructor(db, MetadataPath, emitter, clientEmitter) { + constructor(db, emitter, clientEmitter) { this.db = db this.emitter = emitter this.clientEmitter = clientEmitter - this.MetadataPath = MetadataPath this.streams = [] - this.StreamsPath = Path.join(this.MetadataPath, 'streams') + this.StreamsPath = Path.join(global.MetadataPath, 'streams') } get audiobooks() { @@ -68,12 +67,12 @@ class StreamManager { async tempCheckStrayStreams() { try { - var dirs = await fs.readdir(this.MetadataPath) + var dirs = await fs.readdir(global.MetadataPath) if (!dirs || !dirs.length) return true await Promise.all(dirs.map(async (dirname) => { if (dirname !== 'streams' && dirname !== 'books' && dirname !== 'downloads' && dirname !== 'backups' && dirname !== 'logs' && dirname !== 'cache') { - var fullPath = Path.join(this.MetadataPath, dirname) + var fullPath = Path.join(global.MetadataPath, dirname) Logger.warn(`Removing OLD Orphan Stream ${dirname}`) return fs.remove(fullPath) } diff --git a/server/objects/Audiobook.js b/server/objects/Audiobook.js index 3b39c2c6..a7e41262 100644 --- a/server/objects/Audiobook.js +++ b/server/objects/Audiobook.js @@ -422,13 +422,8 @@ class Audiobook { hasUpdates = true } - if (payload.book) { - if (!this.book) { - this.setBook(payload.book) - hasUpdates = true - } else if (this.book.update(payload.book)) { - hasUpdates = true - } + if (payload.book && this.book.update(payload.book)) { + hasUpdates = true } if (hasUpdates) { @@ -523,7 +518,7 @@ class Audiobook { } // On scan check other files found with other files saved - async syncOtherFiles(newOtherFiles, metadataPath, opfMetadataOverrideDetails, forceRescan = false) { + async syncOtherFiles(newOtherFiles, opfMetadataOverrideDetails, forceRescan = false) { var hasUpdates = false var currOtherFileNum = this.otherFiles.length @@ -640,7 +635,7 @@ class Audiobook { if (bookCoverPath && bookCoverPath.startsWith('/metadata')) { // Fixing old cover paths if (!this.book.coverFullPath) { - this.book.coverFullPath = Path.join(metadataPath, this.book.cover.substr('/metadata/'.length)).replace(/\\/g, '/').replace(/\/\//g, '/') + this.book.coverFullPath = Path.join(global.MetadataPath, this.book.cover.substr('/metadata/'.length)).replace(/\\/g, '/').replace(/\/\//g, '/') Logger.debug(`[Audiobook] Metadata cover full path set "${this.book.coverFullPath}" for "${this.title}"`) hasUpdates = true } @@ -1014,14 +1009,14 @@ class Audiobook { } // Temp fix for cover is set but coverFullPath is not set - fixFullCoverPath(metadataPath) { + fixFullCoverPath() { if (!this.book.cover) return var bookCoverPath = this.book.cover.replace(/\\/g, '/') var newFullCoverPath = null if (bookCoverPath.startsWith('/s/book/')) { newFullCoverPath = Path.join(this.fullPath, bookCoverPath.substr(`/s/book/${this.id}`.length)).replace(/\/\//g, '/') } else if (bookCoverPath.startsWith('/metadata/')) { - newFullCoverPath = Path.join(metadataPath, bookCoverPath.substr('/metadata/'.length)).replace(/\/\//g, '/') + newFullCoverPath = Path.join(global.MetadataPath, bookCoverPath.substr('/metadata/'.length)).replace(/\/\//g, '/') } if (newFullCoverPath) { Logger.debug(`[Audiobook] "${this.title}" fixing full cover path "${this.book.cover}" => "${newFullCoverPath}"`) diff --git a/server/scanner/AuthorScanner.js b/server/scanner/AuthorScanner.js index b1e525c3..3c3be497 100644 --- a/server/scanner/AuthorScanner.js +++ b/server/scanner/AuthorScanner.js @@ -1,10 +1,9 @@ const AuthorFinder = require('../AuthorFinder') class AuthorScanner { - constructor(db, MetadataPath) { + constructor(db) { this.db = db - this.MetadataPath = MetadataPath - this.authorFinder = new AuthorFinder(MetadataPath) + this.authorFinder = new AuthorFinder() } getUniqueAuthors() { diff --git a/server/scanner/Scanner.js b/server/scanner/Scanner.js index cf3ee485..b5dcaf9c 100644 --- a/server/scanner/Scanner.js +++ b/server/scanner/Scanner.js @@ -15,12 +15,9 @@ const LibraryScan = require('./LibraryScan') const ScanOptions = require('./ScanOptions') class Scanner { - constructor(AUDIOBOOK_PATH, METADATA_PATH, db, coverController, emitter) { - this.AudiobookPath = AUDIOBOOK_PATH - this.MetadataPath = METADATA_PATH - this.BookMetadataPath = Path.posix.join(this.MetadataPath.replace(/\\/g, '/'), 'books') - var LogDirPath = Path.join(this.MetadataPath, 'logs') - this.ScanLogPath = Path.join(LogDirPath, 'scans') + constructor(db, coverController, emitter) { + this.BookMetadataPath = Path.posix.join(global.MetadataPath, 'books') + this.ScanLogPath = Path.posix.join(global.MetadataPath, 'logs', 'scans') this.db = db this.coverController = coverController @@ -89,7 +86,7 @@ class Scanner { // Sync other files first so that local images are used as cover art // TODO: Cleanup other file sync var allOtherFiles = checkRes.newOtherFileData.concat(audiobook._otherFiles) - if (await audiobook.syncOtherFiles(allOtherFiles, this.MetadataPath, this.db.serverSettings.scannerPreferOpfMetadata)) { + if (await audiobook.syncOtherFiles(allOtherFiles, this.db.serverSettings.scannerPreferOpfMetadata)) { hasUpdated = true } @@ -330,7 +327,7 @@ class Scanner { if (newOtherFileData.length || libraryScan.scanOptions.forceRescan) { // TODO: Cleanup other file sync var allOtherFiles = newOtherFileData.concat(existingOtherFileData) - if (await audiobook.syncOtherFiles(allOtherFiles, this.MetadataPath, libraryScan.preferOpfMetadata)) { + if (await audiobook.syncOtherFiles(allOtherFiles, libraryScan.preferOpfMetadata)) { hasUpdated = true } }