diff options
Diffstat (limited to 'includes/process.js')
-rw-r--r-- | includes/process.js | 230 |
1 files changed, 215 insertions, 15 deletions
diff --git a/includes/process.js b/includes/process.js index 0a1798f..88a477b 100644 --- a/includes/process.js +++ b/includes/process.js @@ -4,22 +4,44 @@ const path = require('path'); const uuid = require('crypto').randomUUID; const substitutes = [ - ["illenium", "ILLENIUM"] + ["illenium", "ILLENIUM"], + ["SueCo", "Sueco"], + ["Illenium", "ILLENIUM"], + ["Princewhateverer", "PrinceWhateverer"], + ["Kennyoung", "kennyoung"], + ["4EverfreeBrony", "4everfreebrony"], + ["4Everfreebrony", "4everfreebrony"] ]; +if (!fs.existsSync("../assets/content/_")) fs.mkdirSync("../assets/content/_"); +if (!fs.existsSync("../assets/content/songs.json")) fs.writeFileSync("../assets/content/songs.json", "{}"); +if (!fs.existsSync("../assets/content/albums.json")) fs.writeFileSync("../assets/content/albums.json", "{}"); + const songs = require('../assets/content/songs.json'); const albums = require('../assets/content/albums.json'); function scandir(dir) { + let count = 0; + + function updateScandirDisplay() { + process.stdout.clearLine(null); + process.stdout.cursorTo(0); + process.stdout.write("Scanning... " + count); + } + return new Promise((res, rej) => { const walk = (dir, done) => { let results = []; fs.readdir(dir, function(err, list) { + count++; + updateScandirDisplay(); if (err) return done(err); let pending = list.length; if (!pending) return done(null, results); list.forEach(function(file) { + count++; + updateScandirDisplay(); file = path.resolve(dir, file); fs.stat(file, function(err, stat) { if (stat && stat.isDirectory()) { @@ -48,25 +70,77 @@ function scandir(dir) { function substitute(text) { for (let sub of substitutes) { - if (text.trim() === sub[0].trim()) { - return sub[1].trim(); - } + text = text.replaceAll(sub[0], sub[1]); + } + + return text; +} + +function timeToString(time) { + if (!isNaN(parseInt(time))) { + time = new Date(time).getTime(); } + + let periods = ["second", "minute", "hour", "day", "week", "month", "year", "age"]; + + let lengths = ["60", "60", "24", "7", "4.35", "12", "100"]; + + let now = new Date().getTime(); + + let difference = time / 1000; + let period; + + let j; + + for (j = 0; difference >= lengths[j] && j < lengths.length - 1; j++) { + difference /= lengths[j]; + } + + difference = Math.round(difference); + + period = periods[j]; + + return `${difference} ${period}${difference > 1 ? "s" : ""}`; } (async () => { - for (let file of (await scandir("../assets/content/_")).filter(i => i.endsWith(".flac"))) { + let timePerOp = []; + let list = (await scandir("../assets/content/_")).filter(i => i.endsWith(".flac")); + process.stdout.write(" files found, " + list.length + " to process\n"); + let index = 0; + + function updateETA() { + if (timePerOp.length > 5) { + process.stdout.write("(" + timeToString((list.length - index) * (timePerOp.reduce((a, b) => a + b) / timePerOp.length)) + ")"); + } else { + process.stdout.write(""); + } + } + + for (let file of list) { + let start = new Date().getTime(); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(file); + updateETA(); let id = uuid(); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Gathering metadata..."); + updateETA(); let metadata = JSON.parse(cp.execFileSync("ffprobe", ["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", file]).toString()); + if (!metadata['format']['tags']) continue; songs[id] = { - title: substitute(metadata['format']['tags']['TITLE'] ?? path.basename(file, ".flac")), + title: substitute(metadata['format']['tags']['TITLE'] ?? metadata['format']['tags']['title'] ?? path.basename(file, ".flac")), length: parseInt(metadata['format']['duration']), - album: substitute(metadata['format']['tags']['ALBUM'] ?? "Unknown album"), - artist: substitute(metadata['format']['tags']['ARTIST'] ?? "Unknown artist"), - albumArtist: substitute(metadata['format']['tags']['album_artist'] ?? metadata['format']['tags']['ARTIST'] ?? "Unknown artist"), - date: parseInt(metadata['format']['tags']['DATE']) ?? 0, + album: substitute(metadata['format']['tags']['ALBUM'] ?? metadata['format']['tags']['album'] ?? "Unknown album"), + artist: (substitute(metadata['format']['tags']['ARTIST'] ?? metadata['format']['tags']['artist'] ?? "Unknown artist")).replaceAll(";", ", ").replaceAll(" & ", ", ").replaceAll("&", ", ").replaceAll(", and ", ", "), + albumArtist: (substitute(metadata['format']['tags']['album_artist'] ?? metadata['format']['tags']['ARTIST'] ?? metadata['format']['tags']['artist'] ?? "Unknown artist")).replaceAll(";", ", ").replaceAll("&", ", ").replaceAll(", and ", ", "), + date: parseInt(((metadata['format']['tags']['DATE'] ?? metadata['format']['tags']['date']).split("-")[0]).substring(0, 4)) ?? 0, track: parseInt(metadata['format']['tags']['track']) ?? 0, + disc: parseInt(metadata['format']['tags']['disc']) ?? 1, + copyright: metadata['format']['tags']['COPYRIGHT'] ?? metadata['format']['tags']['copyright'] ?? "", size: parseInt(metadata['format']['size']), bitRate: parseInt(metadata['format']['bit_rate']), bitDepth: parseInt(metadata['streams'][0]['bits_per_raw_sample']), @@ -75,37 +149,163 @@ function substitute(text) { channels: parseInt(metadata['streams'][0]['channels']), } + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Writing songs list..."); + updateETA(); fs.writeFileSync("../assets/content/songs.json", JSON.stringify(songs)); - cp.execFileSync("ffmpeg", ["-i", file, "-map", "0", "-map", "-0:v?", "-b:a", "256k", "../assets/content/" + id + ".m4a"]); - cp.execFileSync("ffmpeg", ["-i", file, "-map", "0", "-map", "-0:v?", "../assets/content/" + id + ".flac"]); - cp.execFileSync("ffmpeg", ["-i", file, "-an", "../assets/content/" + id + ".jpg"]); + + if (fs.existsSync("/opt/mist")) { + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Encoding AAC version..."); + updateETA(); + cp.execFileSync("ffmpeg", ["-i", file, "-map", "0", "-map", "-0:v?", "-b:a", "256k", "/opt/mist/aac/" + id + ".m4a"], { stdio: "ignore" }); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Encoding FLAC version..."); + updateETA(); + cp.execFileSync("ffmpeg", ["-i", file, "-map", "0", "-map", "-0:v?", "-c:a", "copy", "/opt/mist/flac/" + id + ".flac"], { stdio: "ignore" }); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Extracting album art..."); + updateETA(); + cp.execFileSync("ffmpeg", ["-i", file, "-an", "/opt/mist/jpeg/" + id + ".jpg"], { stdio: "ignore" }); + } else { + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Encoding AAC version..."); + updateETA(); + cp.execFileSync("ffmpeg", ["-i", file, "-map", "0", "-map", "-0:v?", "-b:a", "256k", "../assets/content/" + id + ".m4a"], { stdio: "ignore" }); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Encoding FLAC version..."); + updateETA(); + cp.execFileSync("ffmpeg", ["-i", file, "-map", "0", "-map", "-0:v?", "-c:a", "copy", "../assets/content/" + id + ".flac"], { stdio: "ignore" }); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Extracting album art..."); + updateETA(); + cp.execFileSync("ffmpeg", ["-i", file, "-an", "../assets/content/" + id + ".jpg"], { stdio: "ignore" }); + } + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Removing original file..."); + updateETA(); fs.unlinkSync(file); + + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log(" Done: " + id); + updateETA(); + + timePerOp.push(new Date().getTime() - start); + index++; } + process.stdout.clearLine(null); process.stdout.cursorTo(0); + console.log("Collecting albums..."); + for (let song of Object.keys(songs)) { if (Object.values(albums).filter(i => i.title === songs[song].album).length > 0) { Object.values(albums).filter(i => i.title === songs[song].album)[0].tracks.push(song); Object.values(albums).filter(i => i.title === songs[song].album)[0].hiRes = Object.values(albums).filter(i => i.title === songs[song].album)[0].hiRes || songs[song].hiRes; } else { let albumID = uuid(); - fs.copyFileSync("../assets/content/" + song + ".jpg", "../assets/content/" + albumID + ".jpg") + + if (fs.existsSync("/opt/mist")) { + fs.copyFileSync("/opt/mist/jpeg/" + song + ".jpg", "/opt/mist/jpeg/" + albumID + ".jpg") + } else { + fs.copyFileSync("../assets/content/" + song + ".jpg", "../assets/content/" + albumID + ".jpg") + } albums[albumID] = { title: songs[song].album, artist: songs[song].albumArtist, date: songs[song].date, hiRes: songs[song].hiRes, + copyright: songs[song].copyright, tracks: [song] } } } + console.log("Cleaning up..."); + + for (let songID of Object.keys(songs)) { + if (fs.existsSync("/opt/mist")) { + if (!fs.existsSync("/opt/mist/flac/" + songID + ".flac") || !fs.existsSync("/opt/mist/aac/" + songID + ".m4a") || !fs.existsSync("/opt/mist/jpeg/" + songID + ".jpg")) { + delete songs[songID]; + } + } else { + if (!fs.existsSync("../assets/content/" + songID + ".flac") || !fs.existsSync("../assets/content/" + songID + ".m4a") || !fs.existsSync("../assets/content/" + songID + ".jpg")) { + delete songs[songID]; + } + } + } + + let idList = [...Object.keys(songs), ...Object.keys(albums)]; + + if (fs.existsSync("/opt/mist")) { + for (let file of fs.readdirSync("/opt/mist/flac")) { + if (fs.lstatSync("/opt/mist/flac/" + file).isFile()) { + let id = path.basename(file, path.extname(file)); + + if (!idList.includes(id) && !file.endsWith(".json")) { + fs.unlinkSync("/opt/mist/flac/" + file); + if (fs.existsSync("../assets/content/" + file)) fs.unlinkSync("../assets/content/" + file); + } else { + if (!fs.existsSync("../assets/content/" + file)) fs.symlinkSync("/opt/mist/flac/" + file, "../assets/content/" + file); + } + } + } + + for (let file of fs.readdirSync("/opt/mist/aac")) { + if (fs.lstatSync("/opt/mist/aac/" + file).isFile()) { + let id = path.basename(file, path.extname(file)); + + if (!idList.includes(id) && !file.endsWith(".json")) { + fs.unlinkSync("/opt/mist/aac/" + file); + if (fs.existsSync("../assets/content/" + file)) fs.unlinkSync("../assets/content/" + file); + } else { + if (!fs.existsSync("../assets/content/" + file)) fs.symlinkSync("/opt/mist/aac/" + file, "../assets/content/" + file); + } + } + } + + for (let file of fs.readdirSync("/opt/mist/jpeg")) { + if (fs.lstatSync("/opt/mist/jpeg/" + file).isFile()) { + let id = path.basename(file, path.extname(file)); + + if (!idList.includes(id) && !file.endsWith(".json")) { + fs.unlinkSync("/opt/mist/jpeg/" + file); + if (fs.existsSync("../assets/content/" + file)) fs.unlinkSync("../assets/content/" + file); + } else { + if (!fs.existsSync("../assets/content/" + file)) fs.symlinkSync("/opt/mist/jpeg/" + file, "../assets/content/" + file); + } + } + } + } else { + for (let file of fs.readdirSync("../assets/content")) { + if (fs.lstatSync("../assets/content/" + file).isFile()) { + let id = path.basename(file, path.extname(file)); + + if (!idList.includes(id) && !file.endsWith(".json")) { + fs.unlinkSync("../assets/content/" + file); + } + } + } + } + + console.log("Adding tracks to albums..."); + for (let albumID of Object.keys(albums)) { let album = albums[albumID]; - album["tracks"] = album["tracks"].sort((a, b) => { + album["tracks"] = [...new Set(album["tracks"])].filter(i => songs[i]).sort((a, b) => { return songs[a]['track'] - songs[b]['track']; }); } + console.log("Writing metadata..."); + + fs.writeFileSync("../assets/content/songs.json", JSON.stringify(songs)); fs.writeFileSync("../assets/content/albums.json", JSON.stringify(albums)); + + console.log("Done!"); })()
\ No newline at end of file |