merge source (#2)

* Added Discord timeout

* Add getOptions in plugin util

* Mutex in ffmpeg conversion (only supports one command at a time)

* Add menu customization in plugin system

* Add ytpl package (playlist info)

* Handle ffmpeg metadata flags when metadata is not present

* Only use artist in file name if present

* Export sendError method

* Handle image not present in metadata util

* Add downloader utils (getFolder and default menu label)

* Pass (optional) existing metadata and subfolder in mp3 converter

* Add listener to download playlist

* Add custom menu in downloader plugin ("download playlist" item)

* nit: fix main CSS style

* Only set the "enable" item in menu if plugin not enabled

* Navigation plugin: inject HTML once CSS is loaded

Co-authored-by: Sem Visscher <semvisscher10@gmail.com>
Co-authored-by: TC <th-ch@users.noreply.github.com>
This commit is contained in:
Araxeus
2021-03-25 01:02:42 +02:00
committed by GitHub
parent 2fb4cbcf02
commit 9a95f435ad
15 changed files with 248 additions and 61 deletions

View File

@ -1,7 +1,8 @@
const { randomBytes } = require("crypto");
const { writeFileSync } = require("fs");
const { join } = require("path");
const downloadsFolder = require("downloads-folder");
const Mutex = require("async-mutex").Mutex;
const { ipcRenderer } = require("electron");
const is = require("electron-is");
const filenamify = require("filenamify");
@ -12,8 +13,9 @@ const filenamify = require("filenamify");
const FFmpeg = require("@ffmpeg/ffmpeg/dist/ffmpeg.min");
const ytdl = require("ytdl-core");
const { triggerActionSync } = require("../utils");
const { triggerAction, triggerActionSync } = require("../utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { defaultMenuDownloadLabel, getFolder } = require("./utils");
const { createFFmpeg } = FFmpeg;
const ffmpeg = createFFmpeg({
@ -21,13 +23,16 @@ const ffmpeg = createFFmpeg({
logger: () => {}, // console.log,
progress: () => {}, // console.log,
});
const ffmpegMutex = new Mutex();
const downloadVideoToMP3 = (
videoUrl,
sendFeedback,
sendError,
reinit,
options
options,
metadata = undefined,
subfolder = ""
) => {
sendFeedback("Downloading…");
@ -66,9 +71,18 @@ const downloadVideoToMP3 = (
}
})
.on("error", sendError)
.on("end", () => {
.on("end", async () => {
const buffer = Buffer.concat(chunks);
toMP3(videoName, buffer, sendFeedback, sendError, reinit, options);
await toMP3(
videoName,
buffer,
sendFeedback,
sendError,
reinit,
options,
metadata,
subfolder
);
});
};
@ -78,10 +92,13 @@ const toMP3 = async (
sendFeedback,
sendError,
reinit,
options
options,
existingMetadata = undefined,
subfolder = ""
) => {
const safeVideoName = randomBytes(32).toString("hex");
const extension = options.extension || "mp3";
const releaseFFmpegMutex = await ffmpegMutex.acquire();
try {
if (!ffmpeg.isLoaded()) {
@ -93,7 +110,7 @@ const toMP3 = async (
ffmpeg.FS("writeFile", safeVideoName, buffer);
sendFeedback("Converting…");
const metadata = getMetadata();
const metadata = existingMetadata || getMetadata();
await ffmpeg.run(
"-i",
safeVideoName,
@ -102,24 +119,31 @@ const toMP3 = async (
safeVideoName + "." + extension
);
const folder = options.downloadFolder || downloadsFolder();
const folder = getFolder(options.downloadFolder);
const name = metadata
? `${metadata.artist} - ${metadata.title}`
? `${metadata.artist ? `${metadata.artist} - ` : ""}${metadata.title}`
: videoName;
const filename = filenamify(name + "." + extension, {
replacement: "_",
});
// Add the metadata
sendFeedback("Adding metadata…");
ipcRenderer.send(
"add-metadata",
join(folder, filename),
ffmpeg.FS("readFile", safeVideoName + "." + extension)
);
ipcRenderer.once("add-metadata-done", reinit);
const filePath = join(folder, subfolder, filename);
const fileBuffer = ffmpeg.FS("readFile", safeVideoName + "." + extension);
if (existingMetadata) {
writeFileSync(filePath, fileBuffer);
reinit();
} else {
// Add the metadata
sendFeedback("Adding metadata…");
ipcRenderer.send("add-metadata", filePath, fileBuffer);
ipcRenderer.once("add-metadata-done", reinit);
sendFeedback("Finished converting", metadata);
}
} catch (e) {
sendError(e);
} finally {
releaseFFmpegMutex();
}
};
@ -133,13 +157,34 @@ const getFFmpegMetadataArgs = (metadata) => {
}
return [
"-metadata",
`title=${metadata.title}`,
"-metadata",
`artist=${metadata.artist}`,
...(metadata.title ? ["-metadata", `title=${metadata.title}`] : []),
...(metadata.artist ? ["-metadata", `artist=${metadata.artist}`] : []),
];
};
module.exports = {
downloadVideoToMP3,
};
ipcRenderer.on(
"downloader-download-playlist",
(_, songMetadata, playlistFolder, options) => {
const reinit = () =>
ipcRenderer.send("downloader-feedback", defaultMenuDownloadLabel);
downloadVideoToMP3(
songMetadata.url,
(feedback) => {
ipcRenderer.send("downloader-feedback", feedback);
},
(error) => {
triggerAction(CHANNEL, ACTIONS.ERROR, error);
reinit();
},
reinit,
options,
songMetadata,
playlistFolder
);
}
);