您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
下載最佳畫質的YouTube在留言和聊天室中,顯示頻道的會員徽章及自訂表情符號。
// ==UserScript== // @name YouTube 會員徽章及自訂表情符號圖標下載器 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 下載最佳畫質的YouTube在留言和聊天室中,顯示頻道的會員徽章及自訂表情符號。 // @author ChatGPT, kkom kbro // @license MIT // @match https://youtube.com/* // @match https://www.youtube.com/* // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @grant none // ==/UserScript== (function() { 'use strict'; window.addEventListener("load", main, false); const replacementNames = [ "新規メンバー", "1か月", "2か月", "6か月", "1年", "2年", "3年", "4年", "5年" ]; const labels = { "af-ZA": { prefix: "Voorvoegsel", suffix: "Achtervoegsel", capitalize: "Kapitaliseer die eerste letter as dit met 'n letter begin", download: "Ikone aflaai!" }, "az-Latn-AZ": { prefix: "Ön əlavə", suffix: "Arxa əlavə", capitalize: "Əgər hərf ilə başlayırsa, ilk hərfi böyük edin", download: "İkonu yükləyin!" }, "id-ID": { prefix: "Awalan", suffix: "Akhiran", capitalize: "Jika dimulai dengan huruf, kapitalisasi huruf pertama", download: "Unduh ikon!" }, "ms-MY": { prefix: "Awalan", suffix: "Akhiran", capitalize: "Jika bermula dengan huruf, besar huruf pertama", download: "Muat turun ikon!" }, "bs-Latn-BA": { prefix: "Prefiks", suffix: "Sufiks", capitalize: "Ako počinje sa slovom, kapitalizuj prvo slovo", download: "Preuzmi ikonu!" }, "ca-ES": { prefix: "Prefix", suffix: "Sufix", capitalize: "Si comença per una lletra, posa en majúscula la primera lletra", download: "Descarrega la icona!" }, "cs-CZ": { prefix: "Předpona", suffix: "Přípona", capitalize: "Pokud začíná písmenem, velké první písmeno", download: "Stáhnout ikonu!" }, "da-DK": { prefix: "Præfiks", suffix: "Suffiks", capitalize: "Hvis det starter med et bogstav, skal det første bogstav skrives med stort", download: "Hent ikon!" }, "de-DE": { prefix: "Präfix", suffix: "Suffix", capitalize: "Wenn es mit einem Buchstaben beginnt, den ersten Buchstaben großschreiben", download: "Symbol herunterladen!" }, "et-EE": { prefix: "Eesliide", suffix: "Tagae liide", capitalize: "Kui see algab tähega, siis suurtäht esimese tähega", download: "Laadi ikoon alla!" }, "en-IN": { prefix: "Prefix", suffix: "Suffix", capitalize: "If it starts with a letter, capitalize the first letter", download: "Download icon!" }, "en-GB": { prefix: "Prefix", suffix: "Suffix", capitalize: "If it starts with a letter, capitalize the first letter", download: "Download icon!" }, "en": { prefix: "Prefix", suffix: "Suffix", capitalize: "If it starts with a letter, capitalize the first letter", download: "Download icon!" }, "es-ES": { prefix: "Prefijo", suffix: "Sufijo", capitalize: "Si empieza con una letra, pon en mayúscula la primera letra", download: "¡Descargar ícono!" }, "es-419": { prefix: "Prefijo", suffix: "Sufijo", capitalize: "Si empieza con una letra, pon en mayúscula la primera letra", download: "¡Descargar ícono!" }, "es-US": { prefix: "Prefijo", suffix: "Sufijo", capitalize: "Si empieza con una letra, pon en mayúscula la primera letra", download: "¡Descargar ícono!" }, "eu-ES": { prefix: "Aurkeztu", suffix: "Atzizkia", capitalize: "Letra batekin hasten bada, idatzi lehen letra nagusian", download: "Ikonoa jaitsi!" }, "fil-PH": { prefix: "Paunang salita", suffix: "Sugnay", capitalize: "Kung nagsisimula ito sa isang titik, i-capitalize ang unang titik", download: "I-download ang icon!" }, "fr-FR": { prefix: "Préfixe", suffix: "Suffixe", capitalize: "S'il commence par une lettre, mettre la première lettre en majuscule", download: "Télécharger l'icône !" }, "fr-CA": { prefix: "Préfixe", suffix: "Suffixe", capitalize: "S'il commence par une lettre, mettre la première lettre en majuscule", download: "Télécharger l'icône !" }, "gl-ES": { prefix: "Prefixo", suffix: "Sufixo", capitalize: "Se comeza cunha letra, escribe a primeira letra en maiúscula", download: "Descargar o ícono!" }, "hr-HR": { prefix: "Prefiks", suffix: "Sufiks", capitalize: "Ako počinje slovom, kapitaliziraj prvo slovo", download: "Preuzmi ikonu!" }, "zu-ZA": { prefix: "Isithako", suffix: "Isiphetho", capitalize: "Uma iqala ngeleta, khuphula ileta yokuqala", download: "Landa isithonjana!" }, "is-IS": { prefix: "Forskeyti", suffix: "Eftirskeyti", capitalize: "Ef það byrjar á staf, skaltu stórskrifa fyrsta stafinn", download: "Sækið táknið!" }, "it-IT": { prefix: "Prefisso", suffix: "Suffisso", capitalize: "Se inizia con una lettera, maiuscola la prima lettera", download: "Scarica l'icona!" }, "sw-TZ": { prefix: "Kichwa", suffix: "Kiambatanishi", capitalize: "Ikiwa inaanza na herufi, inua herufi ya kwanza", download: "Pakua ikoni!" }, "lv-LV": { prefix: "Priekšmets", suffix: "Pielikums", capitalize: "Ja tas sākas ar burtu, lielais pirmais burts", download: "Lejupielādēt ikonu!" }, "lt-LT": { prefix: "Priešdėlis", suffix: "Priedas", capitalize: "Jei prasideda su raide, didžiuoju pirmą raide", download: "Atsisiųsti ikoną!" }, "hu-HU": { prefix: "Előtag", suffix: "Utótag", capitalize: "Ha betűvel kezdődik, a nagybetűt az első betűvel", download: "Ikont letölteni!" }, "nl-NL": { prefix: "Voorvoegsel", suffix: "Achtervoegsel", capitalize: "Als het begint met een letter, maak de eerste letter hoofdletter", download: "Pictogram downloaden!" }, "nb-NO": { prefix: "Prefiks", suffix: "Suffiks", capitalize: "Hvis det begynner med en bokstav, kapitaliser den første bokstaven", download: "Last ned ikonet!" }, "uz-Latn-UZ": { prefix: "Oldingi qo'shimcha", suffix: "Yana qo'shimcha", capitalize: "Agar harf bilan boshlangan bo'lsa, birinchi harfni katta qilib qo'ying", download: "Ikonni yuklab oling!" }, "pl-PL": { prefix: "Prefiks", suffix: "Sufiks", capitalize: "Jeśli zaczyna się od litery, użyj wielkiej litery na pierwszej literze", download: "Pobierz ikonę!" }, "pt-PT": { prefix: "Prefixo", suffix: "Sufixo", capitalize: "Se começar com uma letra, capitaliza a primeira letra", download: "Baixar ícone!" }, "pt-BR": { prefix: "Prefixo", suffix: "Sufixo", capitalize: "Se começar com uma letra, capitaliza a primeira letra", download: "Baixar ícone!" }, "ro-RO": { prefix: "Prefix", suffix: "Sufix", capitalize: "Dacă începe cu o literă, pune prima literă cu majuscule", download: "Descarcă pictograma!" }, "sq-AL": { prefix: "Prefiks", suffix: "Shtesë", capitalize: "Nëse fillon me një shkronjë, shkruaj me shkronjë të madhe shkronjën e parë", download: "Shkarko ikonën!" }, "sk-SK": { prefix: "Predpona", suffix: "Prípona", capitalize: "Ak začína písmenom, veľké prvé písmeno", download: "Stiahnuť ikonu!" }, "sl-SI": { prefix: "Predpona", suffix: "Pripona", capitalize: "Če se začne z črko, z velikimi začetnicami", download: "Prenesi ikono!" }, "sr-Latn-RS": { prefix: "Prefiks", suffix: "Sufiks", capitalize: "Ako počinje slovom, kapitalizuj prvo slovo", download: "Preuzmi ikonu!" }, "fi-FI": { prefix: "Etuliite", suffix: "Loppuliite", capitalize: "Jos se alkaa kirjaimella, isolla ensimmäisellä kirjaimella", download: "Lataa ikoni!" }, "sv-SE": { prefix: "Prefix", suffix: "Suffix", capitalize: "Om det börjar med en bokstav, skriv första bokstaven med stort", download: "Ladda ner ikon!" }, "vi-VN": { prefix: "Tiền tố", suffix: "Hậu tố", capitalize: "Nếu bắt đầu bằng chữ cái, viết hoa chữ cái đầu tiên", download: "Tải xuống biểu tượng!" }, "tr-TR": { prefix: "Önek", suffix: "Sonek", capitalize: "Eğer bir harfle başlıyorsa, ilk harfi büyük yaz", download: "İkonu indir!" }, "be-BY": { prefix: "Префікс", suffix: "Суфікс", capitalize: "Калі пачынаецца з літары, напішыце першую літару з вялікай", download: "Спампаваць значок!" }, "bg-BG": { prefix: "Префикс", suffix: "Суфикс", capitalize: "Ако започва с буква, направете първата буква главна", download: "Изтеглете иконата!" }, "ky-KG": { prefix: "Префикс", suffix: "Суфикс", capitalize: "Эгер ал бугаардан башталса, биринчи харфин чоң кыл", download: "Иконканы жүктөө!" }, "kk-KZ": { prefix: "Префикс", suffix: "Суфикс", capitalize: "Егер әріптен басталса, бірінші әріпті бас әріппен жазыңыз", download: "Иконканы жүктеңіз!" }, "mk-MK": { prefix: "Префикс", suffix: "Суфикс", capitalize: "Ако започнува со буква, напиши го првото слово со голема буква", download: "Преземи икона!" }, "mn-MN": { prefix: "Урьдчилсан", suffix: "Дүгнэлт", capitalize: "Хэрвээ үсэгтэй эхэлж байвал, анхны үсгийг томоор бич", download: "Икон хуулах!" }, "ru-RU": { prefix: "Префикс", suffix: "Суффикс", capitalize: "Если оно начинается с буквы, сделайте первую букву заглавной", download: "Скачать иконку!" }, "sr-Cyrl-RS": { prefix: "Префикс", suffix: "Суфикс", capitalize: "Ако почиње словом, капитализуј прво слово", download: "Преузми иконку!" }, "uk-UA": { prefix: "Префікс", suffix: "Суфікс", capitalize: "Якщо починається з літери, напишіть першу літеру з великої", download: "Завантажити іконку!" }, "el-GR": { prefix: "Πρόθεμα", suffix: "Επίθημα", capitalize: "Αν αρχίζει με γράμμα, κεφαλαιοποιήστε το πρώτο γράμμα", download: "Κατεβάστε το εικονίδιο!" }, "hy-AM": { prefix: "Առաջադիմություն", suffix: "Վերջաբան", capitalize: "Եթե սկսվում է տառով, մեծացրեք առաջին տառը", download: "Բեռնել սիմվոլը!" }, "he-IL": { prefix: "קידומת", suffix: "סופית", capitalize: "אם זה מתחיל באות, הכנס אות גדולה ראשונה", download: "הורד סמל!" }, "ur-PK": { prefix: "پیش لفظ", suffix: "لاحقہ", capitalize: "اگر یہ کسی حرف سے شروع ہوتا ہے تو پہلے حرف کو بڑے حروف میں لکھیں", download: "آئیکن ڈاؤن لوڈ کریں!" }, "ar": { prefix: "بادئة", suffix: "لاحقة", capitalize: "إذا بدأت بحرف، اجعل الحرف الأول كبيرًا", download: "تنزيل الأيقونة!" }, "fa-IR": { prefix: "پیشوند", suffix: "پسوند", capitalize: "اگر با حرف شروع میشود، حرف اول را بزرگ کنید", download: "دانلود آیکون!" }, "ne-NP": { prefix: "प्रीफिक्स", suffix: "सफिक्स", capitalize: "यदि यो अक्षरले सुरु हुन्छ भने, पहिलो अक्षरलाई ठूलो बनाउनुहोस्", download: "आइकन डाउनलोड गर्नुहोस्!" }, "mr-IN": { prefix: "पूर्वसूचक", suffix: "अंतसूचक", capitalize: "जर तुमच्या अक्षराने सुरूवात केली, तर पहिल्या अक्षराला मोठा करा", download: "आइकन डाउनलोड करा!" }, "hi-IN": { prefix: "पूर्ववर्ती", suffix: "उपसर्ग", capitalize: "यदि यह एक अक्षर से शुरू होता है, तो पहले अक्षर को बड़े अक्षर में करें", download: "आइकन डाउनलोड करें!" }, "as-IN": { prefix: "পূৰ্বৰ অংশ", suffix: "অংশ", capitalize: "যদি এটি এখন অক্ষৰে আৰম্ভ হয়, তেনেহ'লে প্ৰথম অক্ষৰখন বৃহৎ কৰক", download: "আইকন ডাউনলোড কৰক!" }, "bn-BD": { prefix: "প্রিফিক্স", suffix: "সাফিক্স", capitalize: "যদি এটি একটি অক্ষর দিয়ে শুরু হয় তবে প্রথম অক্ষরকে বড় করুন", download: "আইকন ডাউনলোড করুন!" }, "pa-Guru-IN": { prefix: "ਪੂਰਵਲੇਖ", suffix: "ਲਾਗੂ", capitalize: "ਜੇ ਇਹ ਅੱਖਰ ਨਾਲ ਸ਼ੁਰੂ ਹੁੰਦਾ ਹੈ, ਤਾਂ ਪਹਿਲੇ ਅੱਖਰ ਨੂੰ ਵੱਡਾ ਕਰੋ", download: "ਆਈਕਨ ਡਾਊਨਲੋਡ ਕਰੋ!" }, "gu-IN": { prefix: "પૂર્વવાહી", suffix: "અર્થશાસ્ત્ર", capitalize: "જો તે અક્ષરથી શરૂ થાય તો પ્રથમ અક્ષરને મોટા બનાવો", download: "આઇકન ડાઉનલોડ કરો!" }, "or-IN": { prefix: "ପ୍ରିଫିକ୍ସ", suffix: "ସୁଫିକ୍ସ", capitalize: "ଯଦି ଏହା ଏକ ଅକ୍ଷରରୁ ଆରମ୍ଭ ହୁଏ, ତେବେ ପ୍ରଥମ ଅକ୍ଷରକୁ ବଡ ରଖନ୍ତୁ", download: "ଆଇକନ୍ ଡାଉନଲୋଡ୍ କରନ୍ତୁ!" }, "ta-IN": { prefix: "முன்சொல்", suffix: "இணைப்பு", capitalize: "அது எழுத்தில் தொடங்கின், முதல் எழுத்தை பெரிய எழுத்தில் மாற்றவும்", download: "அச்சொல்லை பதிவிறக்கம் செய்க!" }, "te-IN": { prefix: "ప్రీఫిక్స్", suffix: "సఫిక్స్", capitalize: "అది అక్షరంతో ప్రారంభం అయితే, మొదటి అక్షరాన్ని పెద్దదిగా చేయండి", download: "ఐకాన్ డౌన్లోడ్ చేయండి!" }, "kn-IN": { prefix: "ಮೂರು", suffix: "ಅನುಕ್ರಮ", capitalize: "ಅದು ಅಕ್ಷರದಿಂದ ಪ್ರಾರಂಭವಾದರೆ, ಮೊದಲ ಅಕ್ಷರವನ್ನು ದೊಡ್ಡದಾಗಿ ಮಾಡಿ", download: "ಐಕಾನ್ ಡೌನ್ಲೋಡ್ ಮಾಡಿ!" }, "ml-IN": { prefix: "മുൻപറഞ്ഞത്", suffix: "ശേഷം", capitalize: "അത് അക്ഷരത്തിൽ തുടങ്ങുകയാണെങ്കിൽ, ആദ്യ അക്ഷരം വലിയയാക്കി", download: "അയോൺ ഡൗൺലോഡ് ചെയ്യുക!" }, "si-LK": { prefix: "පෙරපදය", suffix: "අනුපදය", capitalize: "එය අක්ෂරයකින් ආරම්භ කළහොත්, පළමු අක්ෂරය විශාල කරන්න", download: "ලොාකීකරණය කරන්න!" }, "th-TH": { prefix: "คำนำ", suffix: "คำต่อท้าย", capitalize: "ถ้าเริ่มด้วยตัวอักษรให้ตัวอักษรตัวแรกเป็นตัวพิมพ์ใหญ่", download: "ดาวน์โหลดไอคอน!" }, "lo-LA": { prefix: "ເຄື່ອນຄົນ", suffix: "ປ່ອນອັນ", capitalize: "ໂດຍຖ້າເລີ່ມດ້ວຍອັກສອນ ຂອງເລີ່ມສຽງດິບໃນຂອບໃນ", download: "ດາວເລີ່ອຄອນ!" }, "my-MM": { prefix: "အကြောင်းအရာ", suffix: "အဆုံးသတ်", capitalize: "အက္ခရာဖြင့်စလွှတ်သည့်အခါ၊ ပထမဆုံးအက္ခရာကို အကြီးစီးရေးပါ", download: "အိုင်ကွန်းဒေါင်းလုပ်လုပ်ပါ!" }, "ka-GE": { prefix: "წინადადება", suffix: "საფუძველი", capitalize: "თუ ის იწყება ასოზე, გააკეთეთ პირველი ასო დიდი", download: "დაამატეთ აიკონი!" }, "am-ET": { prefix: "ቅድመ ቃል", suffix: "መደብ", capitalize: "እንደ የዕለት አይደለም፣ የመጀመሪያ ፊደል ይትወዳድር", download: "መልዕክት ይላኩ!" }, "km-KH": { prefix: "គម្រូ", suffix: "សរុប", capitalize: "បើវាលើកឡើងដោយអក្សរ សូមធ្វើអក្សរដំបូងអោយធំបំផុត", download: "ទាញយកស្លាក!" }, "zh-Hans-CN": { prefix: "前缀", suffix: "后缀", capitalize: "如果以字母开头则大写第一个字母", download: "下载图标!" }, "zh-Hant-TW": { prefix: "前綴", suffix: "後綴", capitalize: "如果以字母開頭則大寫第一個字母", download: "下載圖標!" }, "zh-Hant-HK": { prefix: "前綴", suffix: "後綴", capitalize: "如果以字母開頭則大寫第一個字母", download: "下載圖標!" }, "ja-JP": { prefix: "接頭辞", suffix: "接尾辞", capitalize: "文字で始まる場合は最初の文字を大文字にする", download: "アイコンをダウンロード!" }, "ko-KR": { prefix: "접두사", suffix: "접미사", capitalize: "문자로 시작하면 첫 글자를 대문자로 작성하세요", download: "아이콘 다운로드!" } }; let jsInitChecktimer = null; function main() { jsInitChecktimer = setInterval(addDownloadButtons, 1000); } function getFullSizeImgUrl(url) { return url.split("=").slice(0, -1).join("=") + "=s0"; } function getIconNameFromAlt(alttext, index) { if (alttext === "Custom badge for members") { alttext = null; } return alttext || "Icon_" + (index + 1); } async function getExtensionFromURL(url) { try { let response = await fetch(url, { method: 'HEAD' }); if (response.ok) { let contentType = response.headers.get('Content-Type'); if (contentType) { return contentTypeToExtension(contentType); } } return 'png'; } catch (error) { console.error("Failed to fetch Content-Type for URL:", url, error); return 'png'; } } function contentTypeToExtension(contentType) { const mapping = { 'image/jpeg': 'jpg', 'image/png': 'png', 'image/gif': 'gif', 'image/webp': 'webp', }; return mapping[contentType] || 'png'; } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function applyPrefixSuffix(filename, prefix, suffix, capitalize) { if (capitalize && /[a-zA-Z]/.test(filename.charAt(0))) { filename = capitalizeFirstLetter(filename); } return (prefix || '') + filename + (suffix || ''); } function extractUrls(imgs, prefix, suffix, capitalize) { const urls = []; const metadata = []; // 用來保存alt文本、url和filename的metadata const filenameCount = {}; // 用來記錄每個名稱出現的次數 const firstAppearanceMap = {}; // 用來記錄每個文件名第一次出現的index和對應的url信息 for (let i = 0; i < imgs.snapshotLength; i++) { const img = imgs.snapshotItem(i); let originalFilename = getIconNameFromAlt(img.alt, i); // 使用原始名稱 let finalFilename; // 初始化計數器 if (!filenameCount[originalFilename]) { filenameCount[originalFilename] = 0; // 初始化名稱計數為 0 } // 獲取當前計數 const count = filenameCount[originalFilename]; if (count === 0) { // 第一次出現,保留原始名稱,但記錄它的位置以便後續修改 finalFilename = applyPrefixSuffix(originalFilename, prefix, suffix, capitalize); // 記錄第一次出現的位置和相關信息 firstAppearanceMap[originalFilename] = { index: i, // 記錄第一次出現的 index url: getFullSizeImgUrl(img.src) // 記錄對應的圖片URL }; } else { // 重複出現,則根據計數獲取 replacementNames const replacementIndex = Math.min(count, replacementNames.length - 1); // 確保索引不超過範圍 finalFilename = applyPrefixSuffix(replacementNames[replacementIndex], prefix, suffix, capitalize); // 使用替換名稱 // 如果是第二次出現,修改第一次的文件名 if (count === 1) { const firstAppearance = firstAppearanceMap[originalFilename]; if (firstAppearance) { // 將第一次的文件名更新為替換名稱的第一個 urls[firstAppearance.index].filename = applyPrefixSuffix(replacementNames[0], prefix, suffix, capitalize); metadata[firstAppearance.index].altText = applyPrefixSuffix(replacementNames[0], prefix, suffix, capitalize); // 同步更新metadata的altText } } } // 增加計數 filenameCount[originalFilename]++; // 將網址和檔名推入數組 urls.push({ "url": getFullSizeImgUrl(img.src), "filename": finalFilename }); // 保存metadata信息,包括最終的文件名 metadata.push({ "altText": finalFilename, "url": getFullSizeImgUrl(img.src) }); } return { urls, metadata }; // 返回圖片數據與metadata } function addDownloadButtons() { const iconContainerXPath = "//ytd-sponsorships-perk-renderer[descendant::img]"; const iconContainers = document.evaluate(iconContainerXPath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (iconContainers.snapshotLength !== 0) { clearInterval(jsInitChecktimer); jsInitChecktimer = null; } // 獲取 YouTube 的介面語言 const lang = document.documentElement.lang || 'en'; // 默認為英文 const currentLabels = labels[lang] || labels['en']; // 如果沒有對應的語言則使用英文 for (let i = 0; i < iconContainers.snapshotLength; i++) { const container = iconContainers.snapshotItem(i); const titleResult = document.evaluate(".//yt-formatted-string[@id=\"title\"]/text()", container, null, XPathResult.STRING_TYPE, null); const sectionTitle = titleResult.stringValue || ""; const header = sectionTitle.split(" ").slice(0, 2).join(" ") || "unknown"; if (container.querySelector('.download-icons-button')) continue; // 創建前綴、後綴的輸入框和大寫切換 const prefixInput = document.createElement("input"); prefixInput.placeholder = currentLabels.prefix; // 設置前綴的佔位符 prefixInput.style.marginRight = "5px"; prefixInput.style.display = "block"; const capitalizeLabel = document.createElement("label"); capitalizeLabel.style.marginRight = "5px"; capitalizeLabel.style.display = "block"; const capitalizeCheckbox = document.createElement("input"); capitalizeCheckbox.type = "checkbox"; // 創建描述文本並設置綠色字體 const descriptionText = document.createElement("span"); descriptionText.textContent = currentLabels.capitalize; // 設置描述文本 // 定義函數來找到背景色 function getBackgroundColor(element) { let bgColor = window.getComputedStyle(element).backgroundColor; // 當背景顏色是透明或者無法檢測時,繼續查找父元素 while (element && (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent')) { element = element.parentElement; if (element) { bgColor = window.getComputedStyle(element).backgroundColor; } else { break; } } return bgColor; } // 獲取背景色(從 body 開始檢測) const backgroundColor = getBackgroundColor(document.body); // 將背景顏色轉換為 RGB 格式 function getRGBValues(color) { if (color.startsWith('rgb')) { // 如果是 rgb/rgba 顏色,解析 RGB 數值 return color.match(/\d+/g).map(Number); } else if (color.startsWith('#')) { // 如果是 hex 顏色,將 hex 轉換為 RGB let hex = color.replace('#', ''); if (hex.length === 3) { hex = hex.split('').map(h => h + h).join(''); } const bigint = parseInt(hex, 16); return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255]; } return [255, 255, 255]; // 默認為白色(避免異常情況) } const rgb = getRGBValues(backgroundColor); const brightness = (0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]); // 計算亮度 // 根據亮度設置文本顏色 descriptionText.style.color = brightness > 186 ? "black" : "white"; capitalizeLabel.appendChild(capitalizeCheckbox); capitalizeLabel.appendChild(descriptionText); // 添加描述文本 const suffixInput = document.createElement("input"); suffixInput.placeholder = currentLabels.suffix; // 設置後綴的佔位符 suffixInput.style.marginRight = "5px"; const btnDownload = document.createElement("button"); btnDownload.innerText = currentLabels.download; // 設置按鈕文本 btnDownload.className = 'download-icons-button'; btnDownload.style.marginTop = '10px'; btnDownload.addEventListener("click", (e) => { const prefix = prefixInput.value; const suffix = suffixInput.value; const capitalize = capitalizeCheckbox.checked; downloadIcons(container, header, prefix, suffix, capitalize); }); container.appendChild(prefixInput); container.appendChild(capitalizeLabel); // 把大寫選項移到前綴後面並包含描述 container.appendChild(suffixInput); container.appendChild(btnDownload); } } async function downloadIcons(container, header, prefix, suffix, capitalize) { const channelHandleXPath = "//*[@id=\"page-header\"]/yt-page-header-renderer/yt-page-header-view-model/div/div[1]/div/yt-content-metadata-view-model/div[1]/span"; const channelHandleNode = document.evaluate(channelHandleXPath, document, null, XPathResult.STRING_TYPE, null); let channelHandle; if (!channelHandleNode || !channelHandleNode.stringValue) { channelHandle = "unknown_channel"; console.log("YouTube updated the DOM again--needs update"); } else { channelHandle = channelHandleNode.stringValue; } const folderName = channelHandle + "-" + header; const imgsContainer = document.evaluate(".//img", container, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); const { urls, metadata } = extractUrls(imgsContainer, prefix, suffix, capitalize); const zip = new JSZip(); const iconZip = zip.folder(folderName); const promises = []; // 生成 metadata.json,保留原始的冒號 ':' const metadataJson = JSON.stringify(metadata, null, 2); iconZip.file("metadata.json", metadataJson); for (let i = 0; i < urls.length; i++) { const iconObj = urls[i]; const url = iconObj.url; const filename = iconObj.filename; // 保留原始文件名 const promise = new Promise(async (resolve, reject) => { try { const extension = await getExtensionFromURL(url); // 將文件名中的特殊字符替換為可顯示字符 const sanitizedFilename = filename .replace(/\//g, '⧸') .replace(/\\/g, '\') .replace(/\?/g, '?') .replace(/%/g, '%') .replace(/\*/g, '*') .replace(/:/g, ':') .replace(/\|/g, '|') .replace(/</g, '<') .replace(/>/g, '>'); const fullFilename = sanitizedFilename + "." + extension; // 最終文件名 JSZipUtils.getBinaryContent(url, function (err, data) { if (err) { reject(err); } else { iconZip.file(fullFilename, data); resolve(); } }); } catch (error) { reject(error); } }); promises.push(promise); } Promise.all(promises).then(function () { zip.generateAsync({ type: "blob", compression: "DEFLATE" }).then(function (blob) { saveAs(blob, folderName + ".zip"); }, function (err) { alert("Failed. See the log for details."); console.log(err); }); }).catch(function(error) { alert("An error occurred during the download process. See the log for details."); console.error(error); }); } })();