"use strict"; const Promise = require("bluebird"), fs = require("fs"), config = require("config"), moment = require("moment"), crypto = require("crypto"); let photoDB = null; const picturesPath = config.get("picturesPath").replace(/\/$/, "") + "/"; const stat = function (_path) { if (_path.indexOf(picturesPath.replace(/\/$/, "")) == 0) { _path = _path.substring(picturesPath.length); } let path = picturesPath + _path; return new Promise(function (resolve, reject) { fs.stat(path, function (error, stats) { if (error) { return reject(error); } return resolve(stats); }); }); } const rawExtension = /\.nef$/i, extensions = [ "jpg", "jpeg", "png", "gif", "nef" ]; function scanDir(parent, path) { let re = new RegExp("\.((" + extensions.join(")|(") + "))$", "i"), album = { path: path.slice(picturesPath.length), /* path already ends in '/' */ parent: parent, }, albums = [ album ], assets = []; console.log("Scanning for date fixes: " + (path || "/")); return new Promise(function(resolve, reject) { fs.readdir(path, function(error, files) { if (error) { console.warn("Could not readdir: " + path); return resolve([]); } /* Remove 'thumbs' and 'raw' directories from being processed */ files = files.filter(function(file) { for (var i = 0; i < files.length; i++) { /* If this file has an original NEF/ORF on the system, don't add the JPG to the DB */ if (rawExtension.exec(files[i]) && file == files[i].replace(rawExtension, ".jpg")) { return false; } /* If there is a different CASE (eg. JPG vs jpg) don't add it, and remove the 'lower case' * version from disk. */ if (file != files[i] && file.toUpperCase() == files[i]) { removeNewerFile(path, file, files[i]); console.log("Duplicate file in " + path + ": ", file, files[i]); return false; } } return file != "raw" && file != "thumbs" && file != ".git" && file != "corrupt"; }); return resolve(files); }); }).then(function(files) { return Promise.map(files, function(file) { let filepath = path + file; return stat(filepath).then(function(stats) { if (stats.isDirectory()) { return scanDir(album, filepath + "/") .then(([ _albums, _assets ]) => { albums = albums.concat(_albums); assets = assets.concat(_assets); }); } /* Check file extensions */ if (!re.exec(file)) { return; } return photoDB.sequelize.query("SELECT photos.id,photos.added FROM photos,albums " + "WHERE albums.id=photos.albumId AND albums.path=:path AND photos.filename=:filename " + "AND photos.added>:mtime", { replacements: { mtime: stats.mtime, filename: file.replace(rawExtension, ".jpg"), path: album.path }, type: photoDB.sequelize.QueryTypes.SELECT }).then(function(results) { if (results.length == 1) { assets.push({ id: results[0].id, mtime: stats.mtime }); } }); }); }); }).then(function() { return [ albums, assets ]; }); } require("./server/db/photos").then(function(db) { photoDB = db; return scanDir(null, picturesPath) .then(([ albums, assets ]) => { console.log(assets.length + " assets have incorrect dates."); let toProcess = assets.length, lastMessage = moment(), started = moment(); return photoDB.sequelize.transaction(function (t) { return Promise.map(assets, function(asset) { return photoDB.sequelize.query( "UPDATE photos SET added=:mtime,taken=:mtime,modified=:mtime WHERE id=:id", { replacements: asset, transaction: t, }).then(function(results) { toProcess--; if (moment().add(-1, 'seconds') > lastMessage) { console.log("Items to be processed: " + toProcess); lastMessage = moment(); } }); }, { concurrency: 5 }); }).then(function(result) { console.log("Update transaction completed: " + started.toNow()); }) }); });