From 0aedb04736a9a4d7f8526e11be1d9b91b535375c Mon Sep 17 00:00:00 2001 From: SimplyBoo Date: Sat, 6 Oct 2018 16:06:24 +0100 Subject: [PATCH] Various bugfixes (see below) * Deprecated decoding paths from legacy versions and added tool to fix paths. * Fixed null hash on corrupted media. * Made a verbose getStatus that will show new files. * Fixed unable to delete rated media. --- index.js | 54 +++++++++++++++++++++++++++-------- src/database/manager.js | 4 +-- src/database/mysql/index.js | 4 ++- src/database/sqlite3/index.js | 2 ++ utils/fix_paths.js | 24 ++++++++++++++++ 5 files changed, 73 insertions(+), 15 deletions(-) create mode 100755 utils/fix_paths.js diff --git a/index.js b/index.js index 3b4b208..29c0bf2 100755 --- a/index.js +++ b/index.js @@ -23,6 +23,19 @@ const configCheckConnector = async function (req, res, next) { next(); }; +function deleteMedia(media) { + const hash = media.hash; + fs.unlink(media.absolutePath, function() { + console.log(`${media.absolutePath} removed`); + }); + fs.unlink(`${utils.config.cachePath}/thumbnails/${hash}.png`, function() { + console.log(`${utils.config.cachePath}/thumbnails/${hash}.png removed`); + }); + rimraf(`${utils.config.cachePath}/${hash}/`, function () { + console.log(`${utils.config.cachePath}/${hash}/ removed`); + }); +} + class Scanner { constructor(callback) { this.state = "IDLE"; @@ -121,7 +134,7 @@ class Scanner { }; } - getStatus() { + getStatus(verbose) { const status = { state: this.state, libraryPath: utils.config.libraryPath, @@ -131,6 +144,10 @@ class Scanner { } if (this.scanStatus) { status.scanStatus = utils.slimScannerStatus(this.scanStatus); + if (verbose) { + status.scanStatus.newFiles = this.scanStatus.newFiles; + status.scanStatus.missingFiles = this.scanStatus.missingFiles; + } } return status; } @@ -154,6 +171,22 @@ class Scanner { } } } + + async deleteCorrupted() { + const map = global.db.getDefaultMap(); + for (let i = 0; i < map.length; i++) { + const media = global.db.getMedia(map[i]); + if (media.corrupted) { + console.log(`Deleting corrupted media ${media.path}`); + if (await global.db.removeMedia(media.hash)) { + deleteMedia(media); + console.log(`${media.hash} deleted.`); + } else { + console.log(`Failed to delete ${media.hash}`); + } + } + } + } } const scanner = new Scanner(function(status) { @@ -204,7 +237,7 @@ function wrapReq(func) { } app.get('/api/scanner/status', configCheckConnector, function (req, res) { - res.json(scanner.getStatus()); + res.json(scanner.getStatus(req.query.verbose)); }); app.get('/api/scanner/index', configCheckConnector, function (req, res) { @@ -233,7 +266,7 @@ app.get('/api/scanner/import', configCheckConnector, function (req, res) { } (async function() { await scanner.scan(); - await scanner.index(); + await scanner.index(deleteClones); await scanner.cache(); await global.db.search.rebuildIndex(); })(); @@ -246,6 +279,11 @@ app.get('/api/scanner/deleteMissing', configCheckConnector, wrapReq(async functi res.json(scanner.getStatus()); })); +app.get('/api/scanner/deleteCorrupted', configCheckConnector, wrapReq(async function (req, res) { + await scanner.deleteCorrupted(); + res.json(scanner.getStatus()); +})); + app.get('/api/tags', configCheckConnector, function (req, res) { res.json(global.db.getTags()); }); @@ -318,15 +356,7 @@ app.get('/api/images/:hash/delete', configCheckConnector, wrapReq(async function const media = global.db.getMedia(hash); if (media) { if (await global.db.removeMedia(hash)) { - fs.unlink(media.absolutePath, function() { - console.log(`${media.absolutePath} removed`); - }); - fs.unlink(`${utils.config.cachePath}/thumbnails/${hash}.png`, function() { - console.log(`${utils.config.cachePath}/thumbnails/${hash}.png removed`); - }); - rimraf(`${utils.config.cachePath}/${hash}/`, function () { - console.log(`${utils.config.cachePath}/${hash}/ removed`); - }); + deleteMedia(media); console.log(`${hash} deleted.`); res.json({message: `${hash} deleted.`}); } else { diff --git a/src/database/manager.js b/src/database/manager.js index 1263272..cc6015c 100755 --- a/src/database/manager.js +++ b/src/database/manager.js @@ -22,7 +22,7 @@ class MediaManager { addMedia(hash, path, rotation, type, hashDate) { if (!hash) { - console.log('Skipping file. Hash not set'); + console.log(`Skipping file. Hash not set: ${path}`); return false; } if (!path) { @@ -42,7 +42,7 @@ class MediaManager { // Hash date can be null. It's not crucial. const media = { hash: hash, - path: decodeURIComponent((path + '').replace(/\+/g, '%20')).replace(/\\/g, '/'), + path: path, rotation: rotation, type: type, tags: [], diff --git a/src/database/mysql/index.js b/src/database/mysql/index.js index d29a6c8..f3e2362 100755 --- a/src/database/mysql/index.js +++ b/src/database/mysql/index.js @@ -163,7 +163,7 @@ class MySQLDatabase extends MediaManager { IF(corrupted.hash IS NULL, FALSE, TRUE) AS corrupted, IF(priority_transcode.hash IS NULL, FALSE, TRUE) AS priority_transcode, IF(cached.hash IS NULL, FALSE, TRUE) AS cached, - cached.*, + cached.width, cached.height, cached.length, cached.artist, cached.album, cached.title, ratings.rating from images LEFT JOIN corrupted ON (corrupted.hash = images.hash) @@ -272,6 +272,8 @@ class MySQLDatabase extends MediaManager { await this.query("DELETE FROM priority_transcode WHERE hash=?", [hash]); await this.query("DELETE FROM corrupted WHERE hash=?", [hash]); await this.query("DELETE FROM collection_data WHERE hash=?", [hash]); + await this.query("DELETE FROM ratings WHERE hash=?", [hash]); + await this.query("DELETE FROM media_actors WHERE hash=?", [hash]); await this.query('DELETE FROM images WHERE hash=?', [hash]); return true; } diff --git a/src/database/sqlite3/index.js b/src/database/sqlite3/index.js index df48442..957b086 100755 --- a/src/database/sqlite3/index.js +++ b/src/database/sqlite3/index.js @@ -270,6 +270,8 @@ class SQLiteDatabase extends MediaManager { await this.query("DELETE FROM priority_transcode WHERE hash=?", [hash]); await this.query("DELETE FROM corrupted WHERE hash=?", [hash]); await this.query("DELETE FROM collection_data WHERE hash=?", [hash]); + await this.query("DELETE FROM ratings WHERE hash=?", [hash]); + await this.query("DELETE FROM media_actors WHERE hash=?", [hash]); await this.query('DELETE FROM images WHERE hash=?', [hash]); return true; } diff --git a/utils/fix_paths.js b/utils/fix_paths.js new file mode 100755 index 0000000..e26a4ff --- /dev/null +++ b/utils/fix_paths.js @@ -0,0 +1,24 @@ +const Database = require('../src/database'); +const utils = require('../src/utils.js'); +const path = require('path'); + +(async function() { + await utils.setup(); + global.db = await Database.setup(utils.config); + console.log('Decoding all paths'); + const map = global.db.getDefaultMap(); + // Convert from hashmap to array. + let updated = 0; + for (let i = 0; i < map.length; i++) { + const media = global.db.getMedia(map[i]); + const newPath = decodeURIComponent((media.path + '').replace(/\+/g, '%20')).replace(/\\/g, '/'); + if (media.path !== newPath) { + console.log(`Updated ${media.path} to ${newPath}`); + await global.db.updateMedia(media.hash, {path: newPath}); + updated++; + } + } + console.log(`Updated ${updated} paths`); + + await global.db.close(); +})();