const cp = require("child_process");
const os = require("os");
let ffmpeg;
if (os.platform() === "win32") {
ffmpeg = `"${__dirname}\\..\\ffmpeg.exe"`;
} else {
ffmpeg = `"${__dirname}/../ffmpeg"`;
}
const fs = require("fs");
/////////////////////////////////////
// Do not change the lines at the top
/////////////////////////////////////
const path = require("path");
const { shell, ipcRenderer, clipboard } = require("electron");
const { default: YTDlpWrap } = require("yt-dlp-wrap-plus");
// Directories
const homedir = os.homedir();
const appdir = path.join(homedir, "Downloads");
const hiddenDir = path.join(homedir, ".ytDownloader");
const i18n = new (require("../translations/i18n"))();
fs.mkdir(hiddenDir, { recursive: true }, () => {});
// System tray
const trayEnabled = localStorage.getItem("closeToTray");
if (trayEnabled == "true") {
console.log("Tray is Enabled");
ipcRenderer.send("useTray", true);
}
// Ignore Python warnings
process.env.PYTHONWARNINGS = "error";
// Download directory
let downloadDir = "";
// Global variables
let title, onlyvideo, id, thumbnail, ytdlp, duration;
let audioExtensionList = [];
let rangeCmd = "";
let subs = "";
let subLangs;
let rangeOption = "--download-sections";
let cookieArg = "";
let browser = "";
let maxActiveDownloads = 5;
function checkMaxDownloads() {
if (localStorage.getItem("maxActiveDownloads")) {
const number = Number(localStorage.getItem("maxActiveDownloads"));
if (number < 1) {
maxActiveDownloads = 1;
} else {
maxActiveDownloads = number;
}
}
}
checkMaxDownloads();
// Check for auto updates
let autoUpdate = true;
const autoUpdateStatus = localStorage.getItem("autoUpdate");
if (autoUpdateStatus) {
if (autoUpdateStatus == "false") {
autoUpdate = false;
}
}
ipcRenderer.send("autoUpdate", autoUpdate);
let currentDownloads = 0;
let controllers = new Object();
// Video and audio preferences
let preferredVideoQuality = "";
let preferredAudioQuality = "";
function getId(id) {
return document.getElementById(id);
}
function downloadPathSelection() {
let localPath = localStorage.getItem("downloadPath");
if (localPath) {
downloadDir = localPath;
} else {
downloadDir = appdir;
localStorage.setItem("downloadPath", appdir);
}
getId("path").textContent = downloadDir;
fs.mkdir(downloadDir, { recursive: true }, () => {});
}
downloadPathSelection();
// Checking for yt-dlp
let ytDlp;
let ytdlpPath = path.join(os.homedir(), ".ytDownloader", "ytdlp");
// ytdlp download path
let ytdlpDownloadPath;
if (os.platform() == "win32") {
ytdlpDownloadPath = path.join(os.homedir(), ".ytDownloader", "ytdlp.exe");
} else {
ytdlpDownloadPath = path.join(os.homedir(), ".ytDownloader", "ytdlp");
}
// Downloading yt-dlp
async function downloadYtdlp() {
document.querySelector("#popupBox p").textContent = i18n.__(
"Please wait, necessary files are being downloaded"
);
getId("popupSvg").style.display = "inline";
// Downloading appropriate version of yt-dlp
if (os.platform() == "linux") {
// Checking python version
try {
const result = cp.execSync("python3 --version", {
encoding: "utf-8",
});
const minorVersion = Number(result.split(" ")[1].split(".")[1]);
if (minorVersion >= 7) {
await YTDlpWrap.downloadFromGithub(ytdlpDownloadPath);
} else {
// Downloading full binary if python version is less than 3.7
await YTDlpWrap.downloadFromGithub(
ytdlpDownloadPath,
"",
"linux",
true
);
}
} catch (error) {
// Downloading full binary of python3 is not there
await YTDlpWrap.downloadFromGithub(
ytdlpDownloadPath,
"",
"linux",
true
);
}
} else {
// In case of windows/mac
await YTDlpWrap.downloadFromGithub(ytdlpDownloadPath);
}
getId("popupBox").style.display = "none";
ytDlp = ytdlpPath;
ytdlp = new YTDlpWrap(ytDlp);
localStorage.setItem("ytdlp", ytDlp);
getId("pasteUrl").style.display = "inline-block";
console.log("yt-dlp bin Path: " + ytDlp);
}
// Checking if yt-dlp has been installed by user
cp.exec("yt-dlp --version", (error, stdout, stderr) => {
if (error) {
// Checking if yt-dlp has been installed by program
cp.exec(`${ytdlpPath} --version`, (error, stdout, stderr) => {
if (error) {
getId("popupBox").style.display = "block";
process.on("uncaughtException", (reason, promise) => {
document.querySelector("#popupBox p").textContent = i18n.__(
"Failed to download necessary files. Please check your network and try again"
);
getId("popupSvg").style.display = "none";
getId("popup").innerHTML += ``;
console.log("Failed to download yt-dlp");
getId("tryBtn").addEventListener("click", () => {
getId("popup").removeChild(getId("popup").lastChild);
downloadYtdlp();
});
});
downloadYtdlp();
} else {
console.log("yt-dlp binary is present in PATH");
ytDlp = ytdlpPath;
ytdlp = new YTDlpWrap(ytDlp);
localStorage.setItem("ytdlp", ytDlp);
cp.spawn(`${ytDlp}`, ["-U"]).stdout.on("data", (data) =>
console.log(data.toString("utf8"))
);
getId("pasteUrl").style.display = "inline-block";
console.log("yt-dlp bin Path: " + ytDlp);
ipcRenderer.send("ready-for-links");
}
});
} else {
console.log("yt-dlp binary is present in PATH");
ytDlp = "yt-dlp";
ytdlp = new YTDlpWrap(ytDlp);
localStorage.setItem("ytdlp", ytDlp);
getId("pasteUrl").style.display = "inline-block";
console.log("yt-dlp bin Path: " + ytDlp);
ipcRenderer.send("ready-for-links");
}
});
function defaultVideoToggle() {
let defaultWindow = "video";
if (localStorage.getItem("defaultWindow")) {
defaultWindow = localStorage.getItem("defaultWindow");
}
if (defaultWindow == "video") {
selectVideo();
} else {
selectAudio();
}
}
// Pasting url from clipboard
function pasteUrl() {
defaultVideoToggle();
hideHidden()
getId("loadingWrapper").style.display = "flex";
getId("incorrectMsg").textContent = "";
const url = clipboard.readText();
getInfo(url);
}
function pasteFromTray(url) {
defaultVideoToggle();
hideHidden()
getId("loadingWrapper").style.display = "flex";
getId("incorrectMsg").textContent = "";
getInfo(url);
}
getId("closeHidden").addEventListener("click", () => {
hideHidden()
getId("loadingWrapper").style.display = "none";
});
document.addEventListener("keydown", (event) => {
if (event.ctrlKey && event.key == "v") {
pasteUrl();
}
});
getId("pasteUrl").addEventListener("click", () => {
pasteUrl();
});
// Getting video info
async function getInfo(url) {
audioExtensionList = [];
let selected = false;
onlyvideo = false;
let audioIsPresent = false;
downloadPathSelection();
// Cleaning text
getId("videoFormatSelect").innerHTML = "";
getId("audioFormatSelect").innerHTML = "";
getId("startTime").value = "";
getId("endTime").value = "";
getId("errorBtn").style.display = "none";
getId("errorDetails").style.display = "none";
getId("errorDetails").textContent = "";
if (localStorage.getItem("preferredVideoQuality")) {
preferredVideoQuality = localStorage.getItem("preferredVideoQuality");
}
if (localStorage.getItem("preferredAudioQuality")) {
preferredAudioQuality = localStorage.getItem("preferredAudioQuality");
getId("extractSelection").value = preferredAudioQuality;
}
// Whether to use browser cookies or not
if (localStorage.getItem("browser")) {
browser = localStorage.getItem("browser");
}
if (browser) {
cookieArg = "--cookies-from-browser";
} else {
cookieArg = "";
}
let validInfo = true;
let info = "";
const infoProcess = cp.spawn(
ytDlp,
[
"-j",
"--no-playlist",
"--no-warnings",
cookieArg,
browser,
`"${url}"`,
],
{
shell: true,
}
);
infoProcess.stdout.on("data", (data) => {
info += data;
});
infoProcess.stderr.on("data", (error) => {
validInfo = false;
// Error message handling
console.log(error.toString("utf8"));
getId("loadingWrapper").style.display = "none";
getId("incorrectMsg").textContent = i18n.__(
"Some error has occurred. Check your network and use correct URL"
);
getId("errorBtn").style.display = "inline-block";
getId("errorDetails").innerHTML = `
URL: ${url}
${error.toString("utf8")}
`;
getId("errorDetails").title = i18n.__("Click to copy");
});
infoProcess.on("close", () => {
if (validInfo) {
info = JSON.parse(info);
console.log(info);
title = info.title;
id = info.id;
thumbnail = info.thumbnail;
duration = info.duration;
const formats = info.formats;
console.log(formats);
const urlElements = document.querySelectorAll(".url");
urlElements.forEach((element) => {
element.value = url;
});
getId("loadingWrapper").style.display = "none";
getId("hidden").style.display = "inline-block";
getId("hidden").classList.add("scaleUp")
getId("title").innerHTML =
`${i18n.__("Title ")}: ` +
``;
let audioSize = 0;
let defaultVideoFormat = 0;
// Getting approx size of audio file and checking if audio is present
for (let format of formats) {
// Find the item with the preferred video format
if (
format.height <= preferredVideoQuality &&
format.height > defaultVideoFormat &&
format.video_ext !== "none"
) {
defaultVideoFormat = format.height;
}
// Going through audio list
if (
format.audio_ext !== "none" ||
(format.acodec !== "none" && format.video_ext === "none")
) {
audioIsPresent = true;
onlyvideo = true;
audioSize =
Number(format.filesize || format.filesize_approx) /
1000000;
if (!audioExtensionList.includes(format.audio_ext)) {
audioExtensionList.push(format.audio_ext);
}
}
}
for (let format of formats) {
let size;
let selectedText = "";
if (format.height == defaultVideoFormat && !selected) {
selectedText = " selected ";
selected = true;
}
if (format.filesize || format.filesize_approx) {
size = (
Number(format.filesize || format.filesize_approx) /
1000000
).toFixed(2);
} else {
size = i18n.__("Unknown size");
}
// For videos
if (
format.video_ext !== "none" &&
format.audio_ext === "none"
) {
if (size !== "Unknown size") {
size = (Number(size) + 0 || Number(audioSize)).toFixed(
2
);
size = size + " " + i18n.__("MB");
}
const format_id =
format.format_id +
"|" +
format.ext +
"|" +
(format.height || "NO");
const element =
"";
getId("videoFormatSelect").innerHTML += element;
}
// For audios
else if (
format.audio_ext !== "none" ||
(format.acodec !== "none" && format.video_ext === "none")
) {
size = size + " MB";
let audio_ext;
if (format.audio_ext === "webm") {
audio_ext = "opus";
} else {
audio_ext = format.audio_ext;
}
const format_id = format.format_id + "|" + audio_ext;
const element =
"";
getId("audioFormatSelect").innerHTML += element;
}
// Both audio and video available
else if (
format.audio_ext !== "none" ||
(format.acodec !== "none" && format.video_ext !== "none")
) {
let size;
if (format.filesize || format.filesize_approx) {
size = (
Number(format.filesize || format.filesize_approx) /
1000000
).toFixed(2);
} else {
size = i18n.__("Unknown size");
}
const element =
"";
getId("videoFormatSelect").innerHTML += element;
}
// When there is no audio
if (audioIsPresent === false) {
getId("audioPresent").style.display = "none";
} else {
getId("audioPresent").style.display = "block";
}
}
}
});
}
// Video download event
getId("videoDownload").addEventListener("click", (event) => {
checkMaxDownloads();
hideHidden()
console.log(`Current:${currentDownloads} Max:${maxActiveDownloads}`);
if (currentDownloads < maxActiveDownloads) {
manageAdvanced(duration);
download("video");
currentDownloads++;
} else {
// Handling active downloads for video
manageAdvanced(duration);
const range1 = rangeOption;
const range2 = rangeCmd;
const subs1 = subs;
const subs2 = subLangs;
const url1 = getId("url").value;
const thumb1 = thumbnail;
const title1 = title;
const randId = Math.random().toFixed(10).toString().slice(2);
const item = `
${i18n.__("Download pending")}
${i18n.__("Download pending")}
${i18n.__("Download pending")}