new scanner

This commit is contained in:
IrosTheBeggar 2021-03-09 18:45:13 -05:00
parent f9e5984280
commit 00a1d38167
2 changed files with 90 additions and 16 deletions

View File

@ -160,8 +160,8 @@ async function recursiveScan(dir) {
// put in new entry
await insertEntries(songInfo);
// update users db
// TODO: update users db
} catch(err) {
console.error(`Warning: failed to add file ${thisSong} to database: ${err.message}`);
}
@ -216,6 +216,7 @@ function calculateHash(filepath) {
async function getAlbumArt(songInfo) {
if (loadJson.skipImg === true) { return; }
// picture is stored in song metadata
if (songInfo.picture && songInfo.picture[0]) {
// Generate unique name based off hash of album art and metadata
const picHashString = crypto.createHash('md5').update(songInfo.picture[0].data.toString('utf-8')).digest('hex');
@ -225,9 +226,84 @@ async function getAlbumArt(songInfo) {
// Save file sync
fs.writeFileSync(path.join(loadJson.albumArtDirectory, songInfo.aaFile), songInfo.picture[0].data);
}
} else {
await checkDirectoryForAlbumArt(songInfo);
}
}
const mapOfDirectoryAlbumArt = {};
async function checkDirectoryForAlbumArt(songInfo) {
const directory = path.join(loadJson.directory, path.dirname(songInfo.filePath));
// album art has already been found
if (mapOfDirectoryAlbumArt[directory]) {
return songInfo.aaFile = mapOfDirectoryAlbumArt[directory];
}
// directory was already scanned and nothing was found
if (mapOfDirectoryAlbumArt[directory] === false) { return; }
const imageArray = [];
try {
var files = fs.readdirSync(directory);
} catch (err) {
return;
}
for (const file of files) {
const filepath = path.join(directory, file);
try {
var stat = fs.statSync(filepath);
} catch (error) {
// Bad file, ignore and continue
continue;
}
if (!stat.isFile()) {
continue;
}
if (["png", "jpg"].indexOf(getFileType(file)) === -1) {
continue;
}
imageArray.push(file);
}
if (imageArray.length === 0) {
return mapOfDirectoryAlbumArt[directory] = false;
}
let imageBuffer;
let picFormat;
// Search for a named file
for (var i = 0; i < imageArray.length; i++) {
const imgMod = imageArray[i].toLowerCase();
if (imgMod === 'folder.jpg' || imgMod === 'cover.jpg' || imgMod === 'album.jpg' || imgMod === 'folder.png' || imgMod === 'cover.png' || imgMod === 'album.png') {
imageBuffer = fs.readFileSync(path.join(directory, imageArray[i]));
picFormat = getFileType(imageArray[i]);
break;
}
}
// default to first file if none are named
if (!imageBuffer) {
imageBuffer = fs.readFileSync(path.join(directory, imageArray[0]));
picFormat = getFileType(imageArray[0]);
}
const picHashString = crypto.createHash('md5').update(imageBuffer.toString('utf8')).digest('hex');
songInfo.aaFile = picHashString + '.' + picFormat;
// Check image-cache folder for filename and save if doesn't exist
if (!fs.existsSync(path.join(loadJson.albumArtDirectory, songInfo.aaFile))) {
// Save file sync
fs.writeFileSync(path.join(loadJson.albumArtDirectory, songInfo.aaFile), imageBuffer);
}
mapOfDirectoryAlbumArt[directory] = songInfo.aaFile;
}
function getFileType(filename) {
return filename.split(".").pop();
}

View File

@ -11,10 +11,11 @@ const vpathLimiter = new Set();
let scanIntervalTimer = null; // This gets set after the server boots
function addScanTask(vpath) {
const scanObj = { task: 'scan', vpath: vpath, id: nanoid.nanoid(8) };
if (runningTasks.size < config.program.scanOptions.maxConcurrentTasks) {
runScan(vpath);
runScan(scanObj);
} else {
taskQueue.push({ task: 'scan', vpath: vpath, id: nanoid.nanoid(8) });
taskQueue.push(scanObj);
}
}
@ -34,28 +35,29 @@ function nextTask() {
&& runningTasks.size < config.program.scanOptions.maxConcurrentTasks
&& !vpathLimiter.has(taskQueue[taskQueue.length - 1].vpath))
{
runScan(taskQueue.pop().vpath);
runScan(taskQueue.pop());
}
}
function runScan(vpath) {
function runScan(scanObj) {
let parseFlag = false;
const jsonLoad = {
directory: config.program.folders[vpath].root,
vpath: vpath,
directory: config.program.folders[scanObj.vpath].root,
vpath: scanObj.vpath,
dbPath: path.join(config.program.storage.dbDirectory, db.getFileDbName()),
albumArtDirectory: config.program.storage.albumArtDirectory,
skipImg: config.program.scanOptions.skipImg,
saveInterval: config.program.scanOptions.saveInterval,
pause: config.program.scanOptions.pause,
supportedFiles: config.program.supportedAudioFiles
supportedFiles: config.program.supportedAudioFiles,
scanId: scanObj.id
};
const forkedScan = child.fork(path.join(__dirname, './scanner.js'), [JSON.stringify(jsonLoad)], { silent: true });
const forkedScan = child.fork(path.join(__dirname, './scanner-alpha.js'), [JSON.stringify(jsonLoad)], { silent: true });
winston.info(`File scan started on ${jsonLoad.directory}`);
runningTasks.add(forkedScan);
vpathLimiter.add(vpath);
vpathLimiter.add(scanObj.vpath);
forkedScan.stdout.on('data', (data) => {
try {
@ -80,7 +82,7 @@ function runScan(vpath) {
db.loadDB();
}
runningTasks.delete(forkedScan);
vpathLimiter.delete(vpath);
vpathLimiter.delete(scanObj.vpath);
nextTask();
winston.info(`File scan completed with code ${code}`);
});
@ -99,10 +101,6 @@ exports.isScanning = () => {
}
exports.getAdminStats = () => {
console.log(taskQueue);
console.log(vpathLimiter);
console.log(runningTasks);
return {
taskQueue,
vpaths: [...vpathLimiter]