const { clipboard, shell, ipcRenderer } = require("electron");
const { default: YTDlpWrap } = require("yt-dlp-wrap-extended");
const path = require("path");
const os = require("os");
let url;
const ytDlp = localStorage.getItem("ytdlp");
const ytdlp = new YTDlpWrap(ytDlp);
const downloadDir = localStorage.getItem("downloadPath");
const i18n = new (require("../translations/i18n"))();
let cookieArg = "";
let browser = "";
let ffmpeg;
if (os.platform() === "win32") {
ffmpeg = `"${__dirname}\\..\\ffmpeg.exe"`;
} else {
ffmpeg = `"${__dirname}/../ffmpeg"`;
}
let foldernameFormat = "%(playlist_title)s";
let filenameFormat = "%(playlist_index)s.%(title)s.%(ext)s";
let playlistIndex = 1;
let playlistEnd = "";
function getId(id) {
return document.getElementById(id);
}
function pasteLink() {
url = clipboard.readText();
getId("link").textContent = " " + url;
getId("options").style.display = "block";
getId("incorrectMsg").textContent = "";
}
getId("pasteLink").addEventListener("click", () => {
pasteLink();
});
document.addEventListener("keydown", (event) => {
if (event.ctrlKey && event.key == "v") {
pasteLink();
}
});
// Patterns
const playlistTxt = "Downloading playlist: ";
const videoIndex = "Downloading video ";
function download(type) {
// Config file
let configArg = "";
let configTxt = "";
if (localStorage.getItem("configPath")){
configArg = "--config-location"
configTxt = `"${localStorage.getItem("configPath")}"`
}
nameFormatting();
// Playlist download range
managePlaylistRange()
// Whether to use browser cookies or not
if (localStorage.getItem("browser")) {
browser = localStorage.getItem("browser");
}
if (browser) {
cookieArg = "--cookies-from-browser";
} else {
cookieArg = "";
}
let count = 0;
let playlistName;
hideOptions();
let quality, format, downloadProcess;
if (type === "video") {
quality = getId("select").value;
if (quality === "best") {
format = "bv*+ba/best";
} else {
format = `"mp4[height<=${quality}]+m4a/mp4[height<=${quality}]/bv[height<=${quality}]+ba/best[height<=${quality}]/best"`;
}
} else {
format = getId("audioSelect").value;
}
const controller = new AbortController();
if (type === "video") {
downloadProcess = ytdlp.exec(
[
"-f",
format,
"--yes-playlist",
"-o",
`"${path.join(downloadDir, foldernameFormat, filenameFormat)}"`,
"-I",
`"${playlistIndex}:${playlistEnd}"`,
"--ffmpeg-location",
ffmpeg,
cookieArg,
browser,
configArg,
configTxt,
`"${url}"`,
],
{ shell: true, detached: false },
controller.signal
);
} else {
downloadProcess = ytdlp.exec(
[
"--yes-playlist",
"--no-warnings",
"-x",
"--audio-format",
format,
"-o",
`"${path.join(downloadDir, foldernameFormat, filenameFormat)}"`,
"-I",
`"${playlistIndex}:${playlistEnd}"`,
"--ffmpeg-location",
ffmpeg,
cookieArg,
browser,
configArg,
configTxt,
`"${url}"`,
],
{ shell: true, detached: false },
controller.signal
);
}
downloadProcess.on("ytDlpEvent", (eventType, eventData) => {
// console.log(eventData);
if (eventData.includes(playlistTxt)) {
playlistName = eventData.split(":")[1].slice(1);
getId("playlistName").textContent =
i18n.__("Downloading playlist:") + " " + playlistName;
console.log(playlistName);
}
if (
eventData.includes(videoIndex) &&
!eventData.includes("thumbnail")
) {
count += 1;
let itemTitle;
if (type === "video") {
itemTitle = i18n.__("Video") + " " + eventData.split(" ")[3];
} else {
itemTitle = i18n.__("Audio") + " " + eventData.split(" ")[3];
}
if (count > 1) {
getId(`p${count - 1}`).textContent = i18n.__("File saved.");
}
const item = `
${itemTitle}
${i18n.__("Downloading...")}
`;
getId("list").innerHTML += item;
window.scrollTo(0, document.body.scrollHeight);
}
});
downloadProcess.on("progress", (progress) => {
if (getId(`p${count}`)) {
getId(`p${count}`).textContent = `${i18n.__("Progress")} ${
progress.percent
}% | ${i18n.__("Speed")} ${progress.currentSpeed || 0}`;
}
});
downloadProcess.on("error", (error) => {
showErrorTxt(error);
});
downloadProcess.on("close", () => {
afterClose(count);
});
}
function managePlaylistRange(){
if (getId("playlistIndex").value) {
playlistIndex = Number(getId("playlistIndex").value);
}
if (getId("playlistEnd").value) {
playlistEnd = Number(getId("playlistEnd").value);
}
console.log(`Range: ${playlistIndex}:${playlistEnd}`);
}
function afterClose(count) {
getId(`p${count}`).textContent = i18n.__("File saved.");
getId("pasteLink").style.display = "inline-block";
const notify = new Notification("ytDownloader", {
body: i18n.__("Playlist downloaded"),
icon: "../assets/images/icon.png",
});
notify.onclick = () => {
openFolder(downloadDir);
};
}
// Error handling
function showErrorTxt(error) {
console.log("Error " + error);
getId("pasteLink").style.display = "inline-block";
getId("openDownloads").style.display = "none";
getId("options").style.display = "block";
getId("playlistName").textContent = "";
getId("incorrectMsg").textContent = i18n.__(
"Some error has occurred. Check your network and use correct URL"
);
getId("incorrectMsg").title = error;
}
// File and folder name patterns
function nameFormatting() {
// Handling folder and file names
if (localStorage.getItem("foldernameFormat")) {
foldernameFormat = localStorage.getItem("foldernameFormat");
}
if (localStorage.getItem("filenameFormat")) {
filenameFormat = localStorage.getItem("filenameFormat");
}
}
function hideOptions() {
getId("options").style.display = "none";
getId("openDownloads").style.display = "inline-block";
getId("pasteLink").style.display = "none";
getId("playlistName").textContent = i18n.__("Processing") + "...";
getId("list").innerHTML = "";
}
function downloadThumbnails() {
let count = 0;
hideOptions();
nameFormatting();
managePlaylistRange()
const downloadProcess = ytdlp.exec(
[
"--yes-playlist",
"--no-warnings",
"-o",
`"${path.join(downloadDir, foldernameFormat, filenameFormat)}"`,
cookieArg,
browser,
"--write-thumbnail",
"--convert-thumbnails png",
"--skip-download",
"-I",
`"${playlistIndex}:${playlistEnd}"`,
`"${url}"`,
],
{ shell: true, detached: false }
);
downloadProcess.on("ytDlpEvent", (eventType, eventData) => {
// console.log(eventData);
if (eventData.includes(playlistTxt)) {
playlistName = eventData.split(":")[1].slice(1);
getId("playlistName").textContent =
i18n.__("Downloading playlist:") + " " + playlistName;
console.log(playlistName);
}
if (
eventData.includes(videoIndex) &&
!eventData.includes("thumbnail")
) {
count += 1;
let itemTitle;
itemTitle = i18n.__("Thumbnail") + " " + eventData.split(" ")[3];
if (count > 1) {
getId(`p${count - 1}`).textContent = i18n.__("File saved.");
}
const item = `
${itemTitle}
${i18n.__("Downloading...")}
`;
getId("list").innerHTML += item;
window.scrollTo(0, document.body.scrollHeight);
}
});
downloadProcess.on("error", (error) => {
showErrorTxt(error);
});
downloadProcess.on("close", () => {
afterClose(count);
});
}
// Download video links
function saveLinks() {
let count = 0;
hideOptions();
nameFormatting();
managePlaylistRange()
const downloadProcess = ytdlp.exec(
[
"--yes-playlist",
"--no-warnings",
cookieArg,
browser,
"--skip-download",
"--print-to-file",
"webpage_url",
`"${path.join(downloadDir, foldernameFormat, "links.txt")}"`,
"--skip-download",
"-I",
`"${playlistIndex}:${playlistEnd}"`,
`"${url}"`,
],
{ shell: true, detached: false }
);
downloadProcess.on("ytDlpEvent", (eventType, eventData) => {
// console.log(eventData);
if (eventData.includes(playlistTxt)) {
playlistName = eventData.split(":")[1].slice(1);
getId("playlistName").textContent =
i18n.__("Downloading playlist:") + " " + playlistName;
console.log(playlistName);
}
if (
eventData.includes(videoIndex) &&
!eventData.includes("thumbnail")
) {
count += 1;
let itemTitle;
itemTitle = i18n.__("Link") + " " + eventData.split(" ")[3];
if (count > 1) {
getId(`p${count - 1}`).textContent = i18n.__("Link added");
}
const item = `
${itemTitle}
${i18n.__("Downloading...")}
`;
getId("list").innerHTML += item;
window.scrollTo(0, document.body.scrollHeight);
}
});
downloadProcess.on("close", () => {
afterClose(count);
});
downloadProcess.on("error", (error) => {
showErrorTxt(error);
});
}
// Downloading video
getId("download").addEventListener("click", () => {
download("video");
});
// Downloading audio
getId("audioDownload").addEventListener("click", () => {
download("audio");
});
// Downloading thumbnails
getId("downloadThumbnails").addEventListener("click", () => {
downloadThumbnails();
});
// Saving video links to a text file
getId("saveLinks").addEventListener("click", () => {
saveLinks();
});
function openFolder(location) {
shell.openPath(location);
}
function closeMenu() {
getId("menuIcon").style.transform = "rotate(0deg)";
menuIsOpen = false;
let count = 0;
let opacity = 1;
const fade = setInterval(() => {
if (count >= 10) {
clearInterval(fade);
} else {
opacity -= 0.1;
getId("menu").style.opacity = opacity;
count++;
}
}, 50);
}
// Video and audio toggle
const videoToggle = getId("videoToggle");
const audioToggle = getId("audioToggle");
videoToggle.style.backgroundColor = "var(--box-toggleOn)";
videoToggle.addEventListener("click", (event) => {
videoToggle.style.backgroundColor = "var(--box-toggleOn)";
audioToggle.style.backgroundColor = "var(--box-toggle)";
getId("audioBox").style.display = "none";
getId("videoBox").style.display = "block";
});
audioToggle.addEventListener("click", (event) => {
audioToggle.style.backgroundColor = "var(--box-toggleOn)";
videoToggle.style.backgroundColor = "var(--box-toggle)";
getId("videoBox").style.display = "none";
getId("audioBox").style.display = "block";
});
// More options
let moreOptions = true;
getId("advancedToggle").addEventListener("click", () => {
if (moreOptions) {
getId("advancedMenu").style.display = "block";
moreOptions = false;
} else {
getId("advancedMenu").style.display = "none";
moreOptions = true;
}
});
// Menu
getId("openDownloads").addEventListener("click", () => {
openFolder(downloadDir);
});
getId("preferenceWin").addEventListener("click", () => {
closeMenu();
ipcRenderer.send("load-page", __dirname + "/preferences.html");
});
getId("aboutWin").addEventListener("click", () => {
closeMenu();
ipcRenderer.send("load-page", __dirname + "/about.html");
});
getId("homeWin").addEventListener("click", () => {
closeMenu();
ipcRenderer.send("load-win", __dirname + "/index.html");
});
// Translations
getId("pasteLink").textContent = i18n.__(
"Click to paste playlist link from clipboard [Ctrl + V]"
);
getId("preferenceWin").textContent = i18n.__("Preferences");
getId("aboutWin").textContent = i18n.__("About");
getId("homeWin").textContent = i18n.__("Homepage");
getId("linkTitle").textContent = i18n.__("Link:");
getId("videoFormat").textContent = i18n.__("Select Video Format ");
getId("audioFormat").textContent = i18n.__("Select Audio Format ");
getId("download").textContent = i18n.__("Download");
getId("audioDownload").textContent = i18n.__("Download");
getId("bestVideoOption").textContent = i18n.__("Best");
getId("openDownloads").textContent = i18n.__("Open download folder");
getId("videoToggle").textContent = i18n.__("Video");
getId("audioToggle").textContent = i18n.__("Audio");
getId("advancedToggle").textContent = i18n.__("More options");
getId("rangeTxt").textContent = i18n.__("Playlist range");
getId("playlistIndex").placeholder = i18n.__("Start");
getId("playlistEnd").placeholder = i18n.__("End");
getId("downloadThumbnails").textContent = i18n.__("Download thumbnails");
getId("saveLinks").textContent = i18n.__("Save video links to a file");