您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a button to download emojis and badges!
// ==UserScript== // @name Download Youtube Custom Emojis // @namespace https://greasyfork.org/en/scripts/502239-download-youtube-custom-emojis // @version 0.9 // @description Add a button to download emojis and badges! // @author ATPPP3 // @match https://www.youtube.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @grant none // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @license MIT // ==/UserScript== (function () { function dlBadges(name, elems) { downloadImages(getImagesForNotMembership(elems, false), name, 'Badge'); } //Download emojis function dlEmojis(name, elems) { downloadImages(getImagesForNotMembership(elems, false), name, 'Emoji'); } function dlBadgesMem(name, elems) { downloadImages(getImagesForMembershipBadges(elems, false), name, 'Badge'); } //Download emojis function dlEmojisMem(name, elems) { downloadImages(getImagesForMembershipEmojis(elems, false), name, 'Emoji'); } function notMembership() { console.log("nonMembership"); let Channel = document.querySelectorAll('#page-header h1 > span')[0].textContent; let PerksContainer = document.querySelectorAll('#perks_section #perks ytd-sponsorships-perk-renderer #container #images-line'); let Badges = PerksContainer[0]; //Badges element selector let Emojis = PerksContainer[1]; //Emojis element selector if (!Badges || !Emojis) return; //download button style let btnStyle = "margin-bottom:5px; border-radius: 15px; background-color: #3ea6ff; color: #000000; font-size: 16px; border: none; height: 32px; cursor: pointer;"; //Insert Download Button Badges.insertAdjacentHTML("beforebegin", "<button id=\"badges-dl\" style=\"" + btnStyle + "\">Download</button>"); Emojis.insertAdjacentHTML("beforebegin", "<button id=\"emojis-dl\" style=\"" + btnStyle + "\">Download</button>"); //Handle Button Click document.getElementById('badges-dl').addEventListener('click', dlBadges.bind(null, Channel, Badges)); document.getElementById('emojis-dl').addEventListener('click', dlEmojis.bind(null, Channel, Emojis)); } function isMembership() { console.log("isMembership"); let Channel = document.querySelectorAll('#page-header h1 > span')[0].textContent; let Badges = document.querySelectorAll('#container .badge-container .badge-icon'); //Badges element selector let Emojis = document.querySelectorAll('#container #images-line')[0].getElementsByTagName('img') //Emojis element selector //download button style let btnStyle = "margin-bottom:5px; border-radius: 15px; background-color: #3ea6ff; color: #000000; font-size: 16px; border: none; height: 32px; cursor: pointer;"; //Insert Download Button document.querySelectorAll('#container .badge-container')[0].insertAdjacentHTML("afterend", "<button id=\"badges-dl\" style=\"" + btnStyle + "\">Download</button>") document.querySelectorAll('#container #images-line')[0].insertAdjacentHTML("beforebegin", "<button id=\"emojis-dl\" style=\"" + btnStyle + "\">Download</button>") //Handle Button Click document.getElementById('badges-dl').addEventListener('click', dlBadgesMem.bind(null, Channel, Badges)); document.getElementById('emojis-dl').addEventListener('click', dlEmojisMem.bind(null, Channel, Emojis)); } setInterval(function () { console.log("started") try { //Check if membership join button clicked let PerksPopupHidden = document.querySelectorAll('ytd-popup-container > tp-yt-paper-dialog')[0].getAttribute('aria-hidden'); if (PerksPopupHidden) { document.getElementById('badges-dl').remove(); document.getElementById('emojis-dl').remove(); return; } } catch (err) { try { let PerksButtonStatus = !!document.querySelectorAll('#contents .expand-collapse-button button[aria-label="Show perks info"]')[0]; if (PerksButtonStatus) { document.getElementById('badges-dl').remove(); document.getElementById('emojis-dl').remove(); return; } } catch (err) { return; } } console.log("check end"); //Create a download Button if not exists let perksShowed = !!0; if (!document.getElementById('badges-dl') && !document.getElementById('emojis-dl')) { let membership = document.querySelectorAll('#tabsContent .yt-tab-shape-wiz[tab-identifier="TAB_ID_SPONSORSHIPS"]'); if (membership) { perksShowed = !!document.querySelectorAll('#contents .expand-collapse-button button[aria-label="Hide perks info"]')[0]; } if (perksShowed) { isMembership(); } else { notMembership(); } } }, 1000); //get all emojis/badges image url const getImagesForNotMembership = (el, includeDuplicates = false) => { console.log("getImg non"); let eles = [...el.getElementsByTagName('img')]; let srcs = eles.map(img =>img.getAttribute('src')); let images = [...srcs].map(src=>src.split('=')[0]); return includeDuplicates ? images : [...new Set(images)]; }; //get all emojis/badges image url const getImagesForMembershipBadges = (el, includeDuplicates = false) => { console.log("get badges ismem"); let Badges = [...el].map(el => el.getElementsByTagName('img')[0]).map(img => img.getAttribute('src').split('=')[0]); return includeDuplicates ? Badges : [...new Set(Badges)]; }; const getImagesForMembershipEmojis = (el, includeDuplicates = false) => { console.log("get emojis ismem"); let Emojis = [...el].map(el => el.getAttribute('src').split('=')[0]); //Emojis element selector return includeDuplicates ? Emojis : [...new Set(Emojis)]; }; function downloadImages(urls, name, type) { let filename = name + '.zip'; try{ JSZipDownload(urls, filename, type); }catch(err){ let delay = 100; let target = document.querySelectorAll('ytd-popup-container > tp-yt-paper-dialog')[0]; if(!target){target = document.body;} downloadImagesWithDelay(urls, name, type, delay, target); } } function JSZipDownload(urls, filename, type) { console.log("jszip"); let zip = new JSZip(); let interval = 500; urls.forEach(function (url, i) { const name = `${type}_${i}.png`; JSZipUtils.getBinaryContent(url, function (err, data) { if (err) { throw err; // or handle the error } zip.file(name, data, {binary: true}); if (i === urls.length - 1) { setTimeout(() => { zip.generateAsync({type: 'blob'}).then(function (content) { saveAs(content, filename); }) }, interval); } else { clearInterval(interval); // Stop interval when done } }) }) } function backupDownloadImage(url, filename, target) { return fetch(url) .then(response => response.blob()) .then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = filename; target.appendChild(a); a.click(); window.URL.revokeObjectURL(url); target.removeChild(a); }) .catch(() => console.error('An error occurred while downloading the image.')); } function downloadImagesWithDelay(urls, name, type, delay, target) { let index = 0; function downloadNext() { if (index < urls.length) { const url = urls[index]; const filename = `${name}_${type}_${index + 1}.png`; backupDownloadImage(url, filename, target); index++; setTimeout(downloadNext, delay); // Schedule next download } } downloadNext(); // Start the process } })();