YouTube 會員徽章及自訂表情符號圖標下載器

下載最佳畫質的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);
        });
    }
})();