Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //For browsers, it takes the URL from the address bar.
- //If you select some text and draw a gesture, it will pass the selected text to yt-dlp.
- //If nothing is selected and it's not a browser, it simply opens menu from a file.
- (function() {
- const ytdlpPath = 'c:\\test\\'; // The path should end with (\\)
- const ytdlpFileName = 'yt-dlp.exe';
- const ffmpegFileName = 'ffmpeg.exe';
- const menuFileName = 'menu.bat';
- const originalDirectory = System.Environment.CurrentDirectory;
- const keepCmdOpen = true;
- //false: starts in minimized mode, closes if there are no errors, and remains minimized with a sound signal if there are errors.
- //true: launches in normal mode
- //0 in the menu: does not depend on false/true, always true.
- function checkFile(filePath, fileName) {
- return System.IO.File.Exists(`${filePath}\\${fileName}`)
- || !!(sp.MessageBox(`File ${fileName} not found in the directory: ${filePath}`, "Error") && false);
- }
- function safeGetClipboardText() {
- try {
- return clip.GetText() || '';
- } catch (e) {
- sp.MessageBox("Failed to access clipboard", "Error");
- return '';
- }
- }
- function safeSetClipboardText(text) {
- try {
- if (text === '') {
- clip.Clear();
- } else {
- clip.SetText(text);
- }
- } catch (e) {
- sp.MessageBox("Failed to set clipboard", "Error");
- }
- }
- if (!checkFile(ytdlpPath, ytdlpFileName) || !checkFile(ytdlpPath, ffmpegFileName) || !checkFile(ytdlpPath, menuFileName)) {
- return;
- }
- const originalClipboard = safeGetClipboardText();
- try {
- System.Environment.CurrentDirectory = ytdlpPath;
- // Check if the foreground window is a browser
- var fgWnd = sp.ForegroundWindow();
- var exeName = fgWnd.Process.MainModule.ModuleName.toLowerCase();
- var isBrowser = exeName.includes("chrome") || exeName.includes("firefox") || exeName.includes("msedge") ||
- exeName.includes("opera") || exeName.includes("brave") || exeName.includes("vivaldi");
- let url = '';
- let isTextSelected = false;
- // First, we check if any text is selected (for both browsers and non-browsers)
- const originalClipboardContent = safeGetClipboardText();
- sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_C]);
- sp.Sleep(50);
- const newClipboardContent = safeGetClipboardText();
- if (newClipboardContent !== originalClipboardContent) {
- url = newClipboardContent;
- isTextSelected = true;
- }
- if (isBrowser && !isTextSelected) {
- // If it's a browser and no text is selected, we get the URL from the address bar
- sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_L]);
- sp.Sleep(50);
- sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_C]);
- sp.Sleep(50);
- sp.SendVKey(vk.ESCAPE);
- url = safeGetClipboardText();
- }
- const menuOptions = readMenuOptions(ytdlpPath + menuFileName);
- if (isTextSelected || (isBrowser && url)) {
- // Show all options
- showCustomMenu(menuOptions.filter(option => option.number >= 0 && option.number <= 20), ytdlpPath, url, ytdlpFileName, keepCmdOpen, true);
- } else {
- // Show only options 8 and 9 if not browser or url
- showCustomMenu(menuOptions.filter(option => option.number === 8 || option.number === 9), ytdlpPath, '', ytdlpFileName, keepCmdOpen, false);
- }
- } catch (error) {
- sp.ConsoleLog("Failed to execute command. Error: " + error.message, "Error");
- } finally {
- System.Environment.CurrentDirectory = originalDirectory;
- safeSetClipboardText(originalClipboard);
- }
- })();
- // Function to read and parse menu options from menu
- function readMenuOptions(filePath) {
- const content = System.IO.File.ReadAllText(filePath);
- const options = [];
- const menuRegex = /if\s+%%i==(\d+)\s+\(\s*set\s+"menu\[%%i\]=([^"]+)"/g;
- const optionRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"option\[%%i\]=([^"]+)"/g;
- const outputTemplateRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"output_template\[%%i\]=([^"]+)"/g;
- const skipUrlPromptRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"skip_url_prompt\[%%i\]=(\d+)"/g;
- const separatorRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"separator\[%%i\]=(\d+)"/g;
- let match;
- const menuMap = {};
- while ((match = menuRegex.exec(content)) !== null) {
- const [, number, menuName] = match;
- menuMap[number] = { number: parseInt(number), name: menuName.trim() };
- }
- while ((match = optionRegex.exec(content)) !== null) {
- const [, number, option] = match;
- if (menuMap[number]) {
- menuMap[number].option = option.trim();
- }
- }
- while ((match = outputTemplateRegex.exec(content)) !== null) {
- const [, number, outputTemplate] = match;
- if (menuMap[number]) {
- menuMap[number].outputTemplate = outputTemplate.trim();
- }
- }
- while ((match = skipUrlPromptRegex.exec(content)) !== null) {
- const [, number, skipUrlPrompt] = match;
- if (menuMap[number]) {
- menuMap[number].skipUrlPrompt = skipUrlPrompt === '1';
- }
- }
- while ((match = separatorRegex.exec(content)) !== null) {
- const [, number, separator] = match;
- if (menuMap[number]) {
- menuMap[number].separator = separator === '1';
- }
- }
- for (const key in menuMap) {
- options.push(menuMap[key]);
- }
- return options.sort((a, b) => a.number - b.number);
- }
- function showCustomMenu(menuOptions, ytdlpPath, url, ytdlpFileName, keepCmdOpen, isBrowser) {
- const items = [];
- const subMenus = {
- 9: { label: "From file >", items: [8, 9] }
- };
- const separator = ["--", ""];
- menuOptions.forEach((option, index) => {
- if (option.isSeparator) {
- if (items.length > 0 && items[items.length - 1][0] !== separator[0]) {
- items.push(separator);
- }
- } else if (isBrowser || url || option.skipUrlPrompt || (!isBrowser && !url && (option.number === 8 || option.number === 9))) {
- if (subMenus[option.number] && (isBrowser || url)) {
- // Submenu only if it is a browser or URL is provided
- const subMenu = subMenus[option.number];
- const subItems = subMenu.items.map((subItemNumber) => {
- const subOption = menuOptions.find(opt => opt.number === subItemNumber);
- if (subOption) {
- const itemUrl = subOption.skipUrlPrompt ? '' : url;
- return [
- `${subOption.number}. ${subOption.name}`,
- `executeYtDlp(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(itemUrl)}, ${JSON.stringify(ytdlpFileName)}, ${subItemNumber}, ${keepCmdOpen});`
- ];
- }
- return null;
- }).filter(item => item !== null);
- subItems.push(separator);
- subItems.push([
- "Save to list_video.txt",
- `saveToList(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(url)}, 'list_video.txt');`
- ]);
- subItems.push([
- "Save to list_audio.txt",
- `saveToList(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(url)}, 'list_audio.txt');`
- ]);
- //separator
- subItems.push(separator);
- subItems.push([
- "Open list_video.txt",
- `openList(${JSON.stringify(ytdlpPath)}, 'list_video.txt');`
- ]);
- subItems.push([
- "Open list_audio.txt",
- `openList(${JSON.stringify(ytdlpPath)}, 'list_audio.txt');`
- ]);
- items.push([`${option.number}. ${subMenu.label}`, "", false, subItems]);
- } else if (!Object.values(subMenus).some(subMenu => subMenu.items.includes(option.number)) || (!isBrowser && !url)) {
- const label = `${option.number}. ${option.name}`;
- const itemUrl = option.skipUrlPrompt ? '' : url;
- const action = `executeYtDlp(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(itemUrl)}, ${JSON.stringify(ytdlpFileName)}, ${option.number}, ${keepCmdOpen});`;
- items.push([label, action]);
- }
- }
- // Separator after specific menu items
- if ((option.number === 4 || option.number === 7 || option.number === 9) && index < menuOptions.length - 1) {
- items.push(separator);
- }
- });
- // if not a browser and no text is selected
- if (!isBrowser && !url) {
- items.push(separator);
- items.push([
- "Open list_video.txt",
- `openList(${JSON.stringify(ytdlpPath)}, 'list_video.txt');`
- ]);
- items.push([
- "Open list_audio.txt",
- `openList(${JSON.stringify(ytdlpPath)}, 'list_audio.txt');`
- ]);
- }
- const currentPoint = sp.GetCurrentMousePoint();
- const contentFont = new Font(new FontFamily("Tahoma"), 11, FontStyle.Regular, GraphicsUnit.Point);
- if (typeof sp.PopupList === 'function') {
- sp.PopupList(
- items,
- currentPoint,
- contentFont,
- Color.FromName("White"),
- Color.FromArgb(200, 160, 180, 255),
- Color.FromArgb(255, 0, 0, 0)
- );
- } else {
- sp.MessageBox("PopupList function is not available", "Error");
- }
- }
- // Function to save a URL to a file
- function saveToList(ytdlpPath, url, fileName) {
- const filePath = `${ytdlpPath}\\${fileName}`;
- try {
- // Trim the URL and check if it's not empty
- const trimmedUrl = url.trim();
- if (trimmedUrl) {
- System.IO.File.AppendAllText(filePath, trimmedUrl + '\n');
- //sp.MessageBox(`URL saved to ${fileName}`, "Success");
- } else {
- sp.MessageBox(`Cannot save empty URL to ${fileName}`, "Warning");
- }
- } catch (error) {
- sp.MessageBox(`Failed to save URL to ${fileName}. Error: ${error.message}`, "Error");
- }
- }
- // Function to open a file in Notepad
- function openList(ytdlpPath, fileName) {
- const filePath = `${ytdlpPath}\\${fileName}`;
- try {
- // Check if the file exists
- if (System.IO.File.Exists(filePath)) {
- sp.RunProgram('notepad', filePath, '', 'normal', true, false, false);
- } else {
- sp.MessageBox(`File ${fileName} does not exist.`, "Error");
- }
- } catch (error) {
- sp.MessageBox(`Failed to open ${fileName}. Error: ${error.message}`, "Error");
- }
- }
- function executeYtDlp(ytdlpPath, url, ytdlpFileName, optionNumber, keepCmdOpen) {
- ytdlpPath = ytdlpPath.replace(/\\+$/, '');
- let actualKeepCmdOpen = optionNumber === 0 ? true : keepCmdOpen;
- let command = `cd /d "${ytdlpPath}" && `;
- command += `call menu.bat "${ytdlpPath}" "${url}" "${ytdlpFileName}" ${optionNumber} ${actualKeepCmdOpen}`;
- try {
- sp.RunProgram(
- 'cmd.exe',
- `/c "cd /d ${ytdlpPath} && menu.bat "${ytdlpPath}" "${url}" "${ytdlpFileName}" ${optionNumber} ${actualKeepCmdOpen}"`,
- '',
- actualKeepCmdOpen ? 'normal' : 'minimized',
- true,
- false,
- false
- );
- } catch (error) {
- sp.ConsoleLog(`Failed to execute command. Error: ${error.message}`, "Error");
- }
- }
Advertisement