ozhegovvv

yt-dlp

Sep 7th, 2024 (edited)
55
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.56 KB | None | 0 0
  1. //For browsers, it takes the URL from the address bar.
  2. //If you select some text and draw a gesture, it will pass the selected text to yt-dlp.
  3. //If nothing is selected and it's not a browser, it simply opens menu from a file.
  4. (function() {
  5. const ytdlpPath = 'c:\\test\\'; // The path should end with (\\)
  6. const ytdlpFileName = 'yt-dlp.exe';
  7. const ffmpegFileName = 'ffmpeg.exe';
  8. const menuFileName = 'menu.bat';
  9. const originalDirectory = System.Environment.CurrentDirectory;
  10. const keepCmdOpen = true;
  11. //false: starts in minimized mode, closes if there are no errors, and remains minimized with a sound signal if there are errors.
  12. //true: launches in normal mode
  13. //0 in the menu: does not depend on false/true, always true.
  14.  
  15. function checkFile(filePath, fileName) {
  16. return System.IO.File.Exists(`${filePath}\\${fileName}`)
  17. || !!(sp.MessageBox(`File ${fileName} not found in the directory: ${filePath}`, "Error") && false);
  18. }
  19. function safeGetClipboardText() {
  20. try {
  21. return clip.GetText() || '';
  22. } catch (e) {
  23. sp.MessageBox("Failed to access clipboard", "Error");
  24. return '';
  25. }
  26. }
  27.  
  28. function safeSetClipboardText(text) {
  29. try {
  30. if (text === '') {
  31. clip.Clear();
  32. } else {
  33. clip.SetText(text);
  34. }
  35. } catch (e) {
  36. sp.MessageBox("Failed to set clipboard", "Error");
  37. }
  38. }
  39.  
  40. if (!checkFile(ytdlpPath, ytdlpFileName) || !checkFile(ytdlpPath, ffmpegFileName) || !checkFile(ytdlpPath, menuFileName)) {
  41. return;
  42. }
  43.  
  44. const originalClipboard = safeGetClipboardText();
  45.  
  46. try {
  47. System.Environment.CurrentDirectory = ytdlpPath;
  48.  
  49. // Check if the foreground window is a browser
  50. var fgWnd = sp.ForegroundWindow();
  51. var exeName = fgWnd.Process.MainModule.ModuleName.toLowerCase();
  52. var isBrowser = exeName.includes("chrome") || exeName.includes("firefox") || exeName.includes("msedge") ||
  53. exeName.includes("opera") || exeName.includes("brave") || exeName.includes("vivaldi");
  54.  
  55. let url = '';
  56. let isTextSelected = false;
  57.  
  58. // First, we check if any text is selected (for both browsers and non-browsers)
  59. const originalClipboardContent = safeGetClipboardText();
  60. sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_C]);
  61. sp.Sleep(50);
  62. const newClipboardContent = safeGetClipboardText();
  63. if (newClipboardContent !== originalClipboardContent) {
  64. url = newClipboardContent;
  65. isTextSelected = true;
  66. }
  67.  
  68. if (isBrowser && !isTextSelected) {
  69. // If it's a browser and no text is selected, we get the URL from the address bar
  70. sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_L]);
  71. sp.Sleep(50);
  72. sp.SendModifiedVKeys([vk.LCONTROL], [vk.VK_C]);
  73. sp.Sleep(50);
  74. sp.SendVKey(vk.ESCAPE);
  75. url = safeGetClipboardText();
  76. }
  77.  
  78. const menuOptions = readMenuOptions(ytdlpPath + menuFileName);
  79.  
  80. if (isTextSelected || (isBrowser && url)) {
  81. // Show all options
  82. showCustomMenu(menuOptions.filter(option => option.number >= 0 && option.number <= 20), ytdlpPath, url, ytdlpFileName, keepCmdOpen, true);
  83. } else {
  84. // Show only options 8 and 9 if not browser or url
  85. showCustomMenu(menuOptions.filter(option => option.number === 8 || option.number === 9), ytdlpPath, '', ytdlpFileName, keepCmdOpen, false);
  86. }
  87. } catch (error) {
  88. sp.ConsoleLog("Failed to execute command. Error: " + error.message, "Error");
  89. } finally {
  90. System.Environment.CurrentDirectory = originalDirectory;
  91. safeSetClipboardText(originalClipboard);
  92. }
  93. })();
  94.  
  95. // Function to read and parse menu options from menu
  96. function readMenuOptions(filePath) {
  97. const content = System.IO.File.ReadAllText(filePath);
  98.  
  99. const options = [];
  100. const menuRegex = /if\s+%%i==(\d+)\s+\(\s*set\s+"menu\[%%i\]=([^"]+)"/g;
  101. const optionRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"option\[%%i\]=([^"]+)"/g;
  102. const outputTemplateRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"output_template\[%%i\]=([^"]+)"/g;
  103. const skipUrlPromptRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"skip_url_prompt\[%%i\]=(\d+)"/g;
  104. const separatorRegex = /if\s+%%i==(\d+)\s+\(\s*.*set\s+"separator\[%%i\]=(\d+)"/g;
  105.  
  106. let match;
  107. const menuMap = {};
  108. while ((match = menuRegex.exec(content)) !== null) {
  109. const [, number, menuName] = match;
  110. menuMap[number] = { number: parseInt(number), name: menuName.trim() };
  111. }
  112. while ((match = optionRegex.exec(content)) !== null) {
  113. const [, number, option] = match;
  114. if (menuMap[number]) {
  115. menuMap[number].option = option.trim();
  116. }
  117. }
  118.  
  119. while ((match = outputTemplateRegex.exec(content)) !== null) {
  120. const [, number, outputTemplate] = match;
  121. if (menuMap[number]) {
  122. menuMap[number].outputTemplate = outputTemplate.trim();
  123. }
  124. }
  125. while ((match = skipUrlPromptRegex.exec(content)) !== null) {
  126. const [, number, skipUrlPrompt] = match;
  127. if (menuMap[number]) {
  128. menuMap[number].skipUrlPrompt = skipUrlPrompt === '1';
  129. }
  130. }
  131. while ((match = separatorRegex.exec(content)) !== null) {
  132. const [, number, separator] = match;
  133. if (menuMap[number]) {
  134. menuMap[number].separator = separator === '1';
  135. }
  136. }
  137. for (const key in menuMap) {
  138. options.push(menuMap[key]);
  139. }
  140. return options.sort((a, b) => a.number - b.number);
  141. }
  142. function showCustomMenu(menuOptions, ytdlpPath, url, ytdlpFileName, keepCmdOpen, isBrowser) {
  143. const items = [];
  144. const subMenus = {
  145. 9: { label: "From file >", items: [8, 9] }
  146. };
  147. const separator = ["--", ""];
  148.  
  149. menuOptions.forEach((option, index) => {
  150. if (option.isSeparator) {
  151. if (items.length > 0 && items[items.length - 1][0] !== separator[0]) {
  152. items.push(separator);
  153. }
  154. } else if (isBrowser || url || option.skipUrlPrompt || (!isBrowser && !url && (option.number === 8 || option.number === 9))) {
  155. if (subMenus[option.number] && (isBrowser || url)) {
  156. // Submenu only if it is a browser or URL is provided
  157. const subMenu = subMenus[option.number];
  158. const subItems = subMenu.items.map((subItemNumber) => {
  159. const subOption = menuOptions.find(opt => opt.number === subItemNumber);
  160. if (subOption) {
  161. const itemUrl = subOption.skipUrlPrompt ? '' : url;
  162. return [
  163. `${subOption.number}. ${subOption.name}`,
  164. `executeYtDlp(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(itemUrl)}, ${JSON.stringify(ytdlpFileName)}, ${subItemNumber}, ${keepCmdOpen});`
  165. ];
  166. }
  167. return null;
  168. }).filter(item => item !== null);
  169. subItems.push(separator);
  170. subItems.push([
  171. "Save to list_video.txt",
  172. `saveToList(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(url)}, 'list_video.txt');`
  173. ]);
  174. subItems.push([
  175. "Save to list_audio.txt",
  176. `saveToList(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(url)}, 'list_audio.txt');`
  177. ]);
  178. //separator
  179. subItems.push(separator);
  180. subItems.push([
  181. "Open list_video.txt",
  182. `openList(${JSON.stringify(ytdlpPath)}, 'list_video.txt');`
  183. ]);
  184. subItems.push([
  185. "Open list_audio.txt",
  186. `openList(${JSON.stringify(ytdlpPath)}, 'list_audio.txt');`
  187. ]);
  188. items.push([`${option.number}. ${subMenu.label}`, "", false, subItems]);
  189. } else if (!Object.values(subMenus).some(subMenu => subMenu.items.includes(option.number)) || (!isBrowser && !url)) {
  190. const label = `${option.number}. ${option.name}`;
  191. const itemUrl = option.skipUrlPrompt ? '' : url;
  192. const action = `executeYtDlp(${JSON.stringify(ytdlpPath)}, ${JSON.stringify(itemUrl)}, ${JSON.stringify(ytdlpFileName)}, ${option.number}, ${keepCmdOpen});`;
  193. items.push([label, action]);
  194. }
  195. }
  196. // Separator after specific menu items
  197. if ((option.number === 4 || option.number === 7 || option.number === 9) && index < menuOptions.length - 1) {
  198. items.push(separator);
  199. }
  200. });
  201.  
  202. // if not a browser and no text is selected
  203. if (!isBrowser && !url) {
  204. items.push(separator);
  205. items.push([
  206. "Open list_video.txt",
  207. `openList(${JSON.stringify(ytdlpPath)}, 'list_video.txt');`
  208. ]);
  209. items.push([
  210. "Open list_audio.txt",
  211. `openList(${JSON.stringify(ytdlpPath)}, 'list_audio.txt');`
  212. ]);
  213. }
  214.  
  215. const currentPoint = sp.GetCurrentMousePoint();
  216. const contentFont = new Font(new FontFamily("Tahoma"), 11, FontStyle.Regular, GraphicsUnit.Point);
  217.  
  218. if (typeof sp.PopupList === 'function') {
  219. sp.PopupList(
  220. items,
  221. currentPoint,
  222. contentFont,
  223. Color.FromName("White"),
  224. Color.FromArgb(200, 160, 180, 255),
  225. Color.FromArgb(255, 0, 0, 0)
  226. );
  227. } else {
  228. sp.MessageBox("PopupList function is not available", "Error");
  229. }
  230. }
  231. // Function to save a URL to a file
  232. function saveToList(ytdlpPath, url, fileName) {
  233. const filePath = `${ytdlpPath}\\${fileName}`;
  234. try {
  235. // Trim the URL and check if it's not empty
  236. const trimmedUrl = url.trim();
  237. if (trimmedUrl) {
  238. System.IO.File.AppendAllText(filePath, trimmedUrl + '\n');
  239. //sp.MessageBox(`URL saved to ${fileName}`, "Success");
  240. } else {
  241. sp.MessageBox(`Cannot save empty URL to ${fileName}`, "Warning");
  242. }
  243. } catch (error) {
  244. sp.MessageBox(`Failed to save URL to ${fileName}. Error: ${error.message}`, "Error");
  245. }
  246. }
  247. // Function to open a file in Notepad
  248. function openList(ytdlpPath, fileName) {
  249. const filePath = `${ytdlpPath}\\${fileName}`;
  250. try {
  251. // Check if the file exists
  252. if (System.IO.File.Exists(filePath)) {
  253. sp.RunProgram('notepad', filePath, '', 'normal', true, false, false);
  254. } else {
  255. sp.MessageBox(`File ${fileName} does not exist.`, "Error");
  256. }
  257. } catch (error) {
  258. sp.MessageBox(`Failed to open ${fileName}. Error: ${error.message}`, "Error");
  259. }
  260. }
  261.  
  262. function executeYtDlp(ytdlpPath, url, ytdlpFileName, optionNumber, keepCmdOpen) {
  263. ytdlpPath = ytdlpPath.replace(/\\+$/, '');
  264. let actualKeepCmdOpen = optionNumber === 0 ? true : keepCmdOpen;
  265. let command = `cd /d "${ytdlpPath}" && `;
  266. command += `call menu.bat "${ytdlpPath}" "${url}" "${ytdlpFileName}" ${optionNumber} ${actualKeepCmdOpen}`;
  267.  
  268. try {
  269. sp.RunProgram(
  270. 'cmd.exe',
  271. `/c "cd /d ${ytdlpPath} && menu.bat "${ytdlpPath}" "${url}" "${ytdlpFileName}" ${optionNumber} ${actualKeepCmdOpen}"`,
  272. '',
  273. actualKeepCmdOpen ? 'normal' : 'minimized',
  274. true,
  275. false,
  276. false
  277. );
  278. } catch (error) {
  279. sp.ConsoleLog(`Failed to execute command. Error: ${error.message}`, "Error");
  280. }
  281. }
Tags: strokeplus
Advertisement
Comments
Add Comment
Please, Sign In to add comment