diff --git a/server/controllers/MiscController.js b/server/controllers/MiscController.js index ffa4e2c2..f4f1703d 100644 --- a/server/controllers/MiscController.js +++ b/server/controllers/MiscController.js @@ -527,6 +527,54 @@ class MiscController { }) } + /** + * POST: /api/watcher/update + * Update a watch path + * Req.body { libraryId, path, type, [oldPath] } + * type = add, unlink, rename + * oldPath = required only for rename + * @this import('../routers/ApiRouter') + * + * @param {import('express').Request} req + * @param {import('express').Response} res + */ + updateWatchedPath(req, res) { + if (!req.user.isAdminOrUp) { + Logger.error(`[MiscController] Non-admin user attempted to updateWatchedPath`) + return res.sendStatus(404) + } + + const libraryId = req.body.libraryId + const path = req.body.path + const type = req.body.type + if (!libraryId || !path || !type) { + Logger.error(`[MiscController] Invalid request body for updateWatchedPath. libraryId: "${libraryId}", path: "${path}", type: "${type}"`) + return res.sendStatus(400) + } + + switch (type) { + case 'add': + this.watcher.onFileAdded(libraryId, path) + break; + case 'unlink': + this.watcher.onFileRemoved(libraryId, path) + break; + case 'rename': + const oldPath = req.body.oldPath + if (!oldPath) { + Logger.error(`[MiscController] Invalid request body for updateWatchedPath. oldPath is required for rename.`) + return res.sendStatus(400) + } + this.watcher.onFileRename(libraryId, oldPath, path) + break; + default: + Logger.error(`[MiscController] Invalid type for updateWatchedPath. type: "${type}"`) + return res.sendStatus(400) + } + + res.sendStatus(200) + } + validateCronExpression(req, res) { const expression = req.body.expression if (!expression) { diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index b40c3d80..41b24716 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -39,6 +39,7 @@ class ApiRouter { this.playbackSessionManager = Server.playbackSessionManager this.abMergeManager = Server.abMergeManager this.backupManager = Server.backupManager + /** @type {import('../Watcher')} */ this.watcher = Server.watcher this.podcastManager = Server.podcastManager this.audioMetadataManager = Server.audioMetadataManager @@ -308,6 +309,7 @@ class ApiRouter { this.router.post('/genres/rename', MiscController.renameGenre.bind(this)) this.router.delete('/genres/:genre', MiscController.deleteGenre.bind(this)) this.router.post('/validate-cron', MiscController.validateCronExpression.bind(this)) + this.router.post('/watcher/update', MiscController.updateWatchedPath.bind(this)) } async getDirectories(dir, relpath, excludedDirs, level = 0) {