const youtubedl = require('youtube-dl-exec'); const got = require("got"); const { createWriteStream, existsSync, unlinkSync } = require("fs"); const fs = require('fs').promises; const { getFiles } = require('./../file-utils'); const { exec } = require('child_process'); async function downloadThumbnail(youtubeid, downloadDir, overlayImg) { const dlLoc = `${downloadDir}/${youtubeid}.jpg` if(existsSync(dlLoc)) { console.log(` -- SKIPPING ${youtubeid}: already downloaded.`) return } console.log(` -- downloading YouTube ${youtubeid} thumb...`) const fStream = createWriteStream(dlLoc) const done = new Promise(function(resolve, reject) { fStream.on('finish', () => { const child = exec(`convert -resize 700x400 -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -format jpg -colorspace sRGB ${dlLoc} +repage +page ${overlayImg} -flatten ${dlLoc}`) child.on('exit', code => { if(code != 0) reject(`Mogrify returned non-zero exit code: ${code}`) resolve() }) }) youtubedl(`https://www.youtube.com/watch?v=${youtubeid}`, { getThumb: true, noWarnings: true }) .then(url => { got.stream(url).pipe(fStream) }) .catch(err => { // What the fuck. destroy() does not release: https://github.com/nodejs/node/issues/31776 fStream.end() fStream.destroy() fStream.on('close', () => { if(existsSync(dlLoc)) unlinkSync(dlLoc) reject(err) }) }) }) return done } async function loadPostsWithVideos(postsDirectoryPath) { const postNames = await getFiles(postsDirectoryPath); const posts = await Promise.all( postNames.filter(name => name.endsWith('.md')).map(async fileName => { const fileContent = await fs.readFile(fileName, 'utf8'); return { file: fileName, content: fileContent } }) ); return posts } async function run(options) { const { postDir, downloadDir, overlayImg } = options console.log(`-- Scanning for YouTube embeds in ${postDir}... --`) const posts = await loadPostsWithVideos(postDir) for(let post of posts) { const matches = post.content.matchAll(/\{\{\<\syoutube\s\"?(.+)\"?\s\>\}\}/gi) for(let youtubeid of matches) { try { await downloadThumbnail(youtubeid[1].replace(/\"/g, ""), downloadDir, overlayImg) } catch(e) { console.log(`-- error while processing: ${e}`) } } } console.log("-- DONE scanning for YouTube embeds --") } module.exports = { thumbify: run }