// ==UserScript== // @name Youtube Downloader // @author Cyka // @match https://www.youtube.com/* // @version 1.19 // @run-at document-idle // @noframes // ==/UserScript== const URL = `https://youtube-download-ws-server.site.quack-lab.dev/download`; function waitForElement(element, selector) { return new Promise((resolve) => { if (element.querySelector(selector)) { return resolve(element.querySelector(selector)); } const observer = new MutationObserver((mutations) => { if (element.querySelector(selector)) { resolve(element.querySelector(selector)); observer.disconnect(); } }); observer.observe(element, { childList: true, subtree: true, }); }); } function parseVideo(videoElement) { hookVideo(videoElement); } function hookVideo(videoElement) { videoElement.addEventListener( "mousedown", function (e) { if (e.button === 1) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); const link = videoElement.querySelector("a#video-title-link").href; console.log(link); fetch(URL, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ link: link, }), }).then((res) => { console.log(res); res.json().then((data) => console.log(data)); }); } }, false ); } async function main() { const videosContainer = await waitForElement(document, "ytd-rich-grid-renderer > div#contents"); for (const video of videosContainer.querySelectorAll("ytd-rich-item-renderer")) { parseVideo(video); } new MutationObserver((mutations) => { mutations = mutations.filter((mutation) => mutation.addedNodes.length > 0); for (const mutation of mutations) { if (mutation.target.tagName == "YTD-RICH-ITEM-RENDERER") { parseVideo(mutation.target); } } }).observe(videosContainer, { childList: true, subtree: true, }); } main();