Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.

Този скрипт ще предостави подобрения на някои уебсайтове. 🔥Twitter(X): Добавяне на дисплей за форматиране на време, показване на HD картина, изтегляне на снимки и видео и т.н. 🔥Youtube: Добавяне на изтегляне на видео, премахване на реклами и т.н. 🔥Tiktok: Предоставяне на изтегляне на HD видео без воден знак и т.н. За повече функции , моля, проверете описанието~

// ==UserScript==
// @name       Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ar    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:bg    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:cs    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:da    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:de    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:el    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:en    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:eo    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:es    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:fi    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:fr    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:fr-CA Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:he    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:hr    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:hu    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:id    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:it    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ja    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ka    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ko    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:nb    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:nl    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:pl    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:pt-BR Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ro    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ru    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:sk    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:sr    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:sv    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:th    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:tr    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:uk    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:ug    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @name:vi    Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++,etc.
// @description       This script will provide enhancements to some websites. 🔥Twitter(X): Add time formatting display, HD picture display, picture and video downloading, etc. 🔥Youtube: Add video downloading, ad removal, etc. 🔥Tiktok: Provide HD watermark-free video downloading, etc. For more features, please check the description~
// @description:ar    سيوفر هذا البرنامج النصي تحسينات لبعض المواقع الإلكترونية. 🔥Twitter(X): إضافة عرض تنسيق الوقت، وعرض الصور عالية الدقة، وتنزيل الصور والفيديو، وما إلى ذلك. 🔥Youtube: إضافة تنزيل الفيديو، وإزالة الإعلانات، وما إلى ذلك. 🔥Tiktok: توفير تنزيل فيديو عالي الدقة بدون علامة مائية، وما إلى ذلك. لمزيد من الميزات، يرجى التحقق من الوصف~
// @description:bg    Този скрипт ще предостави подобрения на някои уебсайтове. 🔥Twitter(X): Добавяне на дисплей за форматиране на време, показване на HD картина, изтегляне на снимки и видео и т.н. 🔥Youtube: Добавяне на изтегляне на видео, премахване на реклами и т.н. 🔥Tiktok: Предоставяне на изтегляне на HD видео без воден знак и т.н. За повече функции , моля, проверете описанието~
// @description:cs    Tento skript poskytne vylepšení některých webových stránek. 🔥Twitter(X): Přidejte zobrazení formátování času, zobrazení obrázků HD, stahování obrázků a videí atd. 🔥Youtube: Přidejte stahování videa, odstraňování reklam atd. 🔥Tiktok: Poskytujte stahování videa HD bez vodoznaku atd. Další funkce , zkontrolujte prosím popis~
// @description:da    Dette script vil give forbedringer til nogle websteder. 🔥Twitter(X): Tilføj tidsformateringsvisning, HD-billedvisning, billed- og videodownload osv. 🔥Youtube: Tilføj videodownload, annoncefjernelse osv. 🔥Tiktok: Giver HD vandmærkefri videodownload osv. For flere funktioner , tjek venligst beskrivelsen~
// @description:de    Dieses Skript verbessert einige Websites. 🔥Twitter(X): Fügt Zeitformatanzeige, HD-Bildanzeige, Bild- und Video-Downloads usw. hinzu. 🔥Youtube: Fügt Video-Downloads, Anzeigenentfernung usw. hinzu. 🔥Tiktok: Bietet HD-Video-Downloads ohne Wasserzeichen usw. Weitere Funktionen finden Sie in der Beschreibung~
// @description:el    Αυτό το σενάριο θα παρέχει βελτιώσεις σε ορισμένους ιστότοπους. 🔥Twitter(X): Προσθήκη εμφάνισης μορφοποίησης ώρας, προβολής εικόνων HD, λήψης εικόνων και βίντεο κ.λπ. 🔥Youtube: Προσθήκη λήψης βίντεο, αφαίρεση διαφημίσεων κ.λπ. 🔥Tiktok: Παρέχετε λήψη βίντεο HD χωρίς υδατογράφημα κ.λπ. Για περισσότερες δυνατότητες , ελέγξτε την περιγραφή~
// @description:en    This script will provide enhancements to some websites. 🔥Twitter(X): Add time formatting display, HD picture display, picture and video downloading, etc. 🔥Youtube: Add video downloading, ad removal, etc. 🔥Tiktok: Provide HD watermark-free video downloading, etc. For more features, please check the description~
// @description:eo    Ĉi tiu skripto provizos plibonigojn al iuj retejoj. 🔥Twitter(X): Aldonu horformatan ekranon, HD-bildon, elŝuton de bildoj kaj filmetojn ktp. 🔥Youtube: Aldonu video-elŝutadon, forigon de reklamoj ktp. 🔥Tiktok: Provizu HD-senpagan video-elŝutadon, ktp. Por pliaj funkcioj , bonvolu kontroli la priskribon~
// @description:es    Este script proporcionará mejoras a algunos sitios web.🔥twitter (x): agregue la pantalla de formato de tiempo, visualización de imágenes HD, descarga de imágenes y videos, etc. 🔥Youtube: Agregue la descarga de video, eliminación de anuncios, etc. 🔥tiktok: proporcione descarga de video sin marca de agua HD, etc. para obtener más funciones, por favor verifique la descripción ~
// @description:fi    Tämä komentosarja tarjoaa parannuksia joihinkin verkkosivustoihin. 🔥Twitter(X): Lisää ajan muotoilun näyttö, HD-kuvanäyttö, kuvien ja videoiden lataus jne. 🔥Youtube: Lisää videoiden lataus, mainosten poisto jne. 🔥Tiktok: Tarjoa HD-vesileimatonta videoiden latausta jne. Lisää ominaisuuksia , tarkista kuvaus~
// @description:fr    Ce script apportera des améliorations à certains sites Web. 🔥Twitter(X) : Ajout de l'affichage du formatage de l'heure, de l'affichage d'images HD, du téléchargement d'images et de vidéos, etc. 🔥Youtube : Ajout du téléchargement de vidéos, de la suppression des publicités, etc. 🔥Tiktok : Fournit un téléchargement de vidéos HD sans filigrane, etc. Pour plus de fonctionnalités, veuillez consulter la description~
// @description:fr-CA Ce script apportera des améliorations à certains sites Web. 🔥Twitter(X) : Ajout de l'affichage du formatage de l'heure, de l'affichage d'images HD, du téléchargement d'images et de vidéos, etc. 🔥Youtube : Ajout du téléchargement de vidéos, de la suppression des publicités, etc. 🔥Tiktok : Fournit un téléchargement de vidéos HD sans filigrane, etc. Pour plus de fonctionnalités, veuillez consulter la description~
// @description:he    סקריפט זה יספק שיפורים לאתרים מסוימים. 🔥Twitter(X): הוסף תצוגת עיצוב זמן, תצוגת תמונות HD, הורדת תמונות ווידאו וכו'. 🔥YouTube: הוסף הורדת וידאו, הסרת מודעות וכו'. , אנא בדוק את התיאור~
// @description:hr    Ova skripta će poboljšati neke web stranice. 🔥Twitter(X): Dodajte prikaz formatiranja vremena, HD prikaz slike, preuzimanje slika i videa itd. 🔥Youtube: Dodajte preuzimanje videa, uklanjanje oglasa itd. 🔥Tiktok: Omogućite preuzimanje HD videa bez vodenog žiga itd. Za više značajki , provjerite opis~
// @description:hu    Ez a szkript fejlesztéseket biztosít bizonyos webhelyeken. 🔥Twitter(X): Időformázási megjelenítés hozzáadása, HD képmegjelenítés, kép- és videóletöltés stb. 🔥Youtube: Videó letöltése, hirdetések eltávolítása stb. , ellenőrizze a leírást~
// @description:id    Skrip ini akan memberikan peningkatan pada beberapa situs web. 🔥Twitter(X): Menambahkan tampilan format waktu, tampilan gambar HD, pengunduhan gambar dan video, dll. 🔥Youtube: Menambahkan pengunduhan video, penghapusan iklan, dll. 🔥Tiktok: Menyediakan pengunduhan video HD tanpa tanda air, dll. Untuk fitur lainnya, silakan periksa deskripsi~
// @description:it    Questo script migliorerà alcuni siti web. 🔥Twitter(X): aggiunge la visualizzazione della formattazione dell'ora, la visualizzazione delle immagini HD, il download di immagini e video, ecc. 🔥Youtube: aggiunge il download di video, la rimozione degli annunci, ecc. 🔥Tiktok: fornisce il download di video HD senza filigrana, ecc. Per altre funzionalità, controlla la descrizione~
// @description:ja    このスクリプトは、いくつかのウェブサイトの機能強化を提供します。🔥Twitter(X): 時間フォーマット表示、HD画像表示、画像とビデオのダウンロードなどを追加します。🔥Youtube: ビデオのダウンロード、広告の削除などを追加します。🔥Tiktok: HDウォーターマークのないビデオのダウンロードなどを提供します。その他の機能については、説明を確認してください~
// @description:ka    This script will provide enhancements to some websites. 🔥Twitter(X): Add time formatting display, HD picture display, picture and video downloading, etc. 🔥Youtube: Add video downloading, ad removal, etc. 🔥Tiktok: Provide HD watermark-free video downloading, etc. For more features, please check the description~
// @description:ko    이 스크립트는 일부 웹사이트에 개선 사항을 제공합니다. 🔥Twitter(X): 시간 형식 표시, HD 사진 표시, 사진 및 비디오 다운로드 등을 추가합니다. 🔥Youtube: 비디오 다운로드, 광고 제거 등을 추가합니다. 🔥Tiktok: HD 워터마크 없는 비디오 다운로드 등을 제공합니다. 자세한 내용은 설명을 확인하세요~
// @description:nb    Dette skriptet vil gi forbedringer til enkelte nettsteder. 🔥Twitter(X): Legg til tidsformateringsvisning, HD-bildevisning, bilde- og videonedlasting osv. 🔥Youtube: Legg til videonedlasting, annonsefjerning osv. 🔥Tiktok: Gi HD vannmerkefri videonedlasting osv. For flere funksjoner , sjekk beskrivelsen~
// @description:nl    Dit script zal verbeteringen aan sommige websites bieden. 🔥Twitter(X): Voeg weergave van tijdsopmaak, HD-afbeeldingsweergave, downloaden van afbeeldingen en video's, enz. toe. 🔥Youtube: Voeg videodownloads, advertentieverwijdering, enz. toe. 🔥Tiktok: Biedt HD-watermerkvrije videodownloads, enz. Voor meer functies, bekijk de beschrijving~
// @description:pl    Ten skrypt wprowadzi ulepszenia do niektórych witryn internetowych. 🔥Twitter(X): Dodaj wyświetlanie formatu czasu, wyświetlanie obrazów HD, pobieranie obrazów i filmów itp. 🔥Youtube: Dodaj pobieranie filmów, usuwanie reklam itp. 🔥Tiktok: Zapewnij pobieranie filmów HD bez znaku wodnego itp. Aby uzyskać więcej funkcji, sprawdź opis~
// @description:pt-BR Este script fornecerá melhorias para alguns sites. 🔥Twitter(X): Adicione exibição de formatação de hora, exibição de imagem em HD, download de imagem e vídeo, etc. 🔥Youtube: Adicione download de vídeo, remoção de anúncios, etc. 🔥Tiktok: Forneça download de vídeo em HD sem marca d'água, etc. Para mais recursos, verifique a descrição~
// @description:ro    Acest script va oferi îmbunătățiri unor site-uri web. 🔥Twitter(X): Adăugați afișaj de formatare a orei, afișare a imaginii HD, descărcare de imagini și videoclipuri etc. 🔥Youtube: Adăugați descărcare video, eliminare a reclamelor etc. 🔥Tiktok: Oferiți descărcare video HD fără filigran etc. Pentru mai multe funcții , vă rugăm să verificați descrierea~
// @description:ru    Этот скрипт улучшит работу некоторых веб-сайтов. 🔥Twitter(X): Добавить отображение форматирования времени, отображение HD-изображений, загрузку изображений и видео и т. д. 🔥Youtube: Добавить загрузку видео, удалить рекламу и т. д. 🔥TikTok: Обеспечить загрузку HD-видео без водяных знаков и т. д. Для получения дополнительных функций, пожалуйста, проверьте описание~
// @description:sk    Tento skript poskytne vylepšenia niektorých webových stránok. 🔥Twitter(X): Pridajte zobrazenie formátovania času, zobrazenie HD obrázkov, sťahovanie obrázkov a videí atď. 🔥Youtube: Pridajte sťahovanie videa, odstraňovanie reklám atď. 🔥Tiktok: Poskytnite sťahovanie videa HD bez vodoznaku atď. Ďalšie funkcie , prosím skontrolujte popis ~
// @description:sr    Ова скрипта ће пружити побољшања неким веб локацијама. 🔥Твиттер(Кс): Додајте приказ форматирања времена, приказ ХД слике, преузимање слика и видео записа итд. 🔥Иоутубе: Додајте преузимање видео записа, уклањање огласа итд. 🔥Тикток: Омогућите преузимање видео записа у ХД-у без воденог жига итд. За више функција , молимо проверите опис~
// @description:sv    Detta skript kommer att ge förbättringar till vissa webbplatser. 🔥Twitter(X): Lägg till tidsformateringsvisning, HD-bildvisning, bild- och videonedladdning, etc. 🔥Youtube: Lägg till videonedladdning, annonsborttagning etc. 🔥Tiktok: Tillhandahåller HD vattenstämpelfri videonedladdning, etc. För fler funktioner , kontrollera beskrivningen~
// @description:th    สคริปต์นี้จะให้การปรับปรุงแก่บางเว็บไซต์🔥twitter (x): เพิ่มการจัดรูปแบบการจัดรูปแบบการจัดรูปแบบการแสดงภาพ HD รูปภาพและวิดีโอการดาวน์โหลด ฯลฯ 🔥youtube: เพิ่มการดาวน์โหลดวิดีโอการลบโฆษณา ฯลฯ 🔥tiktok: ให้การดาวน์โหลดวิดีโอที่ปราศจากลายน้ำ HD ฯลฯ สำหรับคุณสมบัติเพิ่มเติมโปรดตรวจสอบคำอธิบาย ~
// @description:tr    Bu script bazı web sitelerine geliştirmeler sağlayacaktır. 🔥Twitter(X): Zaman biçimlendirme gösterimi, HD resim gösterimi, resim ve video indirme vb. ekleyin. 🔥Youtube: Video indirme, reklam kaldırma vb. ekleyin. 🔥Tiktok: HD filigransız video indirme vb. sağlayın. Daha fazla özellik için lütfen açıklamayı kontrol edin~
// @description:uk    Цей сценарій покращить роботу деяких веб-сайтів. 🔥Twitter(X): додайте відображення форматування часу, відображення HD-зображення, завантаження зображень і відео тощо. 🔥Youtube: додайте завантаження відео, видалення реклами тощо. 🔥Tiktok: забезпечте завантаження відео HD без водяних знаків тощо. Для додаткових функцій , будь ласка, перевірте опис~
// @description:ug    بۇ قوليازما بەزى تور بېكەتلەرنى ياخشىلاش بىلەن تەمىنلەيدۇ. 🔥Twitter (X): ۋاقىت فورماتلاش ئېكرانى ، HD رەسىم كۆرسىتىش ، رەسىم ۋە سىن چۈشۈرۈش قاتارلىقلارنى قوشۇڭ outYoutube: سىن چۈشۈرۈش ، ئېلان ئۆچۈرۈش قاتارلىقلارنى قوشۇڭ ikTiktok: HD سۇ ماركىسىسىز سىن چۈشۈرۈش قاتارلىقلار بىلەن تەمىنلەڭ. ، چۈشەندۈرۈشنى تەكشۈرۈپ بېقىڭ ~
// @description:vi    Tập lệnh này sẽ cung cấp các cải tiến cho một số trang web. 🔥Twitter(X): Thêm hiển thị định dạng thời gian, hiển thị hình ảnh HD, tải xuống hình ảnh và video, v.v. 🔥Youtube: Thêm tải xuống video, xóa quảng cáo, v.v. 🔥Tiktok: Cung cấp tải xuống video HD không có hình mờ, v.v. Để biết thêm các tính năng, vui lòng kiểm tra phần mô tả~
// @namespace   PeterParker_X_Y_NameScope
// @version     2.0.1
// @author      PeterParker
// @icon        data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABhxJREFUeF7lm09oHUUcx3/7nm0aWou2CtL2kFLbREXFRPBU+tJb8Gb1Yg8VhIhHb6U86HvwKKWCR8WAx3qRipfYW7rBk2Iq2EvTKkUspRhbJTRpm/p25TdvZ3d2dmb2N7vzNnnJQMhLdnZ2vp/5/dvdeR5s8eZtcf1QHYDmL40EdhB99o4BhPPpRaj50HnDr2ph+guAiQ7PRmIEAFR5YZv17Ey0qGfY9nMPIBEdCz56/xab19F70e/ob/zfD3sOxnM+d/i4Yf79geEOgCSciz5zcw74Z8rqIBD2s7f3O9vcgigPQCHcVrQOzLkXj4PeKtyAKAegudAC8JiP4yq7Ei4DyQVRIkYUB9C8egUAmJ+j+Ms/fkWx8FJ9pt76UOMW4ENnfLLI4PYAeiaP4lnDVT/z21yRaxc6x2wN3qRtCrUDIJj8eojnxFy6BB3ABhHvGgINgGT2Vfl8no8YYgIA0NyBCOBqKE7mweVm3twqO75rqqO/Vmc8V19uBxCi/Xr6vU4lFktoCZqWmx3MACS/x4tspNXnos2uELZN9xJ6AArxVac8FFifeBW6C9eMLpVjBcZ4YAXAZvV3fHk+nvSTmYtKEShu2/TJuN+jj07Hn/EYH+PJzNewNnPRCMFsBfpCSQ2g5OqLk8dZozDVKqJA7IsNj4sAxGN4fOXNt8sA0FpBJQB0k9/582wsygRAPqYike8GaivIAlCsvm3wM62sOHkRgGwl3D2ChWvQXfg1Nw7guMaUyC6crQ1IAGwLHwoAqpvYFBQ5cQCHyqRFBYB00VMk94srqwtg26dPwrbp92N9opvIwRGtIC8I4kDme4ToUlJxlAagMX+b9CevLAJAE5YbRn9dACxqHSQAkhv0HQDFhOUgJ1uHLovIYxMCYcYNJABZ88cz8GEH9bmenL4oAGQ3sU2B/Bp9A2DjAvLkdVUcN39VnWBKjyagNBdIZ4PEAqRbXvFCNgBcBMB0FZlfBfK5lgSQPOCUKVPTIDV4mdIkdQyVJWwKAEUDIDkNMnLJHaLgAnoLoFaC1OBlchPqGCoLyK8E+VkFAFAygYsKsGgAJGYATiCuCAULSJ7zq+hS4gBl8iYTVxVRlArQzvwLugDFDVAcb7obGBRZn3gt7icKLBMA6eZfAgDFDSiFj+s+9OhvjAHpNz66Sdo8FXItVDee3eprLYAGwKYoqgKA/eoXqARlIRvJFexXH3ecJO8L5Juh+I2vafUoGaGK1cdrrAsAvDAVQv1IgqJ+mI6lezPp272hP88eQPo9gWQBtDjAp8PjAYpEcTVBoCicLtvck4MIIjgIafiQ4dWYcjgTADyhqX4mgIcae3ubnBrP3YJj/HP025XIouO0b/Q2WPl/HwT/nmpvUTSy8ZFYD4AyDrRG5+Dskeo2QhQFgechjNaiasdZ9jUZc4Hwm7FGUOttd1lYHRmZXR4/JU+gse8u4M8gNP/OC4A/cnt5x+35d5/5iW3CrAXge+9d92MAYS3Z9qIS6e3eA7D72UHQD7D8D4TL941z9QJvMgaAPbuXxlpesqsze/LQMHjP79sUALh4FJPKAkYIAwQgXLoD8PihOgeA166fuB5vvc28GAkujaZ2g8SjbAYAHvi1dxZT2+kyADAgKuPBJgAgmj5fWOXbYaUrDBKA279nzF8lPhMD+Fk6K/AOHBqIIBgqANROLCoXW/nP4NvRKxD26gKxDTKAUAp+RhfQBUJbAGJJOh+Vp1iqqhqW13LDcpuX3zamp7IAVvworIAeBDFnalyAC21H5aexFrdRIvVFGByUtix//BBYGlQ0lRVk06DG/FnAwEJoaBi6q6vw5901+O6vV+CTpY9LSCp/6uzYZ/D68B+w/8DTvcHKANCmwGiej4KnYHnpX1hdWYOVB2vwRXgKPg8+KK+ixAgXhj6Fqf++h527trNRRl7ary2CVG6QsgAEQJ0L1tGg2VBBHcNNv94dHnXubN5Cy98qmzdLBoE5CP92WN4Zro77AF7b9vsB8sXLA+AjVgfCiXA+bXcA+g/CqfD+ARBtrJxVRL5a3sxNPufeAkxXY7tQ+Ndm4zUQvj5bSwJURV+frRaAq/DncJwtD+B/6XGfbp4XQ5oAAAAASUVORK5CYII=
// @include     https://x.com/*
// @include     https://twitter.com/*
// @include     https://mobile.x.com/*
// @include     https://www.youtube.com/**
// @include     https://music.youtube.com/watch**
// @include     https://www.tiktok.com/@*
// @include     https://cobalt.tools/**
// @exclude     *://accounts.youtube.com/*
// @exclude     *://www.youtube.com/live_chat_replay*
// @exclude     *://www.youtube.com/persist_identity*
// @exclude     *://x.com/i/flow/*
// @connect     tikdownloader.io
// @license     MIT
// @run-at      document-idle
// @antifeature referral-link
// @noframes
// @grant       GM_registerMenuCommand
// @grant       GM_openInTab
// @grant       GM.openInTab
// @grant       GM_addStyle
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_xmlhttpRequest
// @grant       GM_download
// @grant       GM_setClipboard
// ==/UserScript==
(function () {
  'use strict';

  
  /*!
  * Copyright (c) 2024 - 2025, PeterParker. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
  *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  *
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */


  const ScriptConst = {
    "lang": (navigator.language || navigator.userLanguage).slice(0, 2).toLowerCase(),
    "isDev": false,
    "isDebug": true,
    "currentHost": window.location.host,
    "currentUrl": window.location.href
  };
  const PlatformConst = {
    "aliexpress": "aliexpress",
    "amazon": "amazon",
    "shopee": "shopee",
    "lazada": "lazada",
    "ebay": "ebay",
    "bestbuy": "bestbuy",
    "banggood": "banggood",
    "wish": "wish",
    "airbaltic": "airbaltic",
    "edureka": "edureka",
    "ranavat": "ranavat",
    "alibaba": "alibaba",
    "ticketmaster": "ticketmaster",
    "wilson": "wilson",
    "wilsonsleather": "wilsonsleather",
    "pictarine": "pictarine",
    "suiteness": "suiteness",
    "trip": "trip",
    "treatwell": "treatwell",
    "samsung": "samsung",
    "x": "x",
    "youtube": "youtube",
    "tiktok": "tiktok",
    "cobalt": "cobalt"
  };

  var __async$3 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const Logger = {
    log: function(level = "info", ...messages) {
      {
        if (level.toLowerCase() === "info") {
          console.info(...messages);
        } else if (level.toLowerCase() === "error") {
          console.error(...messages);
        } else {
          console.log(...messages);
        }
      }
    }
  };
  const Tools = {
    decryptStr: function(str) {
      if (!str)
        return str;
      let result = atob(str);
      return result.split("").reverse().join("");
    },
    encryptStr: function(str) {
      if (!str)
        return str;
      let result = str.split("").reverse().join("");
      return btoa(result);
    },
    getEcommercePlatform: function() {
      let platform = null;
      const currentHost = window.location.host;
      if (/amazon\./.test(currentHost)) {
        platform = PlatformConst.amazon;
      } else if (/ebay\./.test(currentHost)) {
        platform = PlatformConst.ebay;
      } else if (/lazada\./.test(currentHost)) {
        platform = PlatformConst.lazada;
      } else if (/aliexpress./.test(currentHost)) {
        platform = PlatformConst.aliexpress;
      } else if (/bestbuy\./.test(currentHost)) {
        platform = PlatformConst.bestbuy;
      } else if (/banggood\./.test(currentHost)) {
        platform = PlatformConst.banggood;
      } else if (/wish\./.test(currentHost)) {
        platform = PlatformConst.wish;
      } else if (/airbaltic\./.test(currentHost)) {
        platform = PlatformConst.airbaltic;
      } else if (/edureka\./.test(currentHost)) {
        platform = PlatformConst.edureka;
      } else if (/ranavat\./.test(currentHost)) {
        platform = PlatformConst.ranavat;
      } else if (/alibaba\./.test(currentHost)) {
        platform = PlatformConst.alibaba;
      } else if (/ticketmaster\./.test(currentHost)) {
        platform = PlatformConst.ticketmaster;
      } else if (/wilson\./.test(currentHost)) {
        platform = PlatformConst.wilson;
      } else if (/wilsonsleather\./.test(currentHost)) {
        platform = PlatformConst.wilsonsleather;
      } else if (/pictarine\./.test(currentHost)) {
        platform = PlatformConst.pictarine;
      } else if (/suiteness\./.test(currentHost)) {
        platform = PlatformConst.suiteness;
      } else if (/trip\./.test(currentHost)) {
        platform = PlatformConst.trip;
      } else if (/treatwell\./.test(currentHost)) {
        platform = PlatformConst.treatwell;
      } else if (/samsung\./.test(currentHost)) {
        platform = PlatformConst.samsung;
      }
      return platform;
    },
    getOtherPlatform: function() {
      let platform = null;
      const currentHost = window.location.host;
      if (/twitter|x\.com$/.test(currentHost)) {
        platform = PlatformConst.x;
      } else if (/youtube\.com$/.test(currentHost)) {
        platform = PlatformConst.youtube;
      } else if (/www\.tiktok\.com/.test(currentHost)) {
        platform = PlatformConst.tiktok;
      } else if (/cobalt\.tools/.test(currentHost)) {
        platform = PlatformConst.cobalt;
      }
      return platform;
    },
    getAllMatchPlatform: function() {
      var _a;
      return (_a = this.getEcommercePlatform()) != null ? _a : this.getOtherPlatform();
    },
    removeAnchorsByNode: function(node) {
      const tagName = node.tagName;
      if (!tagName)
        return;
      const exist = ["A", "IMG", "DIV", "SPAN", "LABEL", "TABLE", "TR", "TD", "CANVAS"].some((name) => name === tagName);
      if (exist) {
        node.removeAttribute("data-spm-anchor-id");
        for (let i = 0; i < node.childNodes.length; i++) {
          this.removeAnchorsByNode(node.childNodes[i]);
        }
      }
    },
    removeAnchorsBySeletor: function() {
      document.querySelectorAll("*[data-re-mark-tag='aliexpress']").forEach((element) => {
        this.removeAnchorsByNode(element);
      });
    },
    openInTab: function(url, options = { "active": true, "insert": true, "setParent": true }) {
      if (typeof GM_openInTab === "function") {
        GM_openInTab(url, options);
      } else {
        GM.openInTab(url, options);
      }
    },
    request: function(method, url, param, headers = { "Content-Type": "application/json;charset=UTF-8" }, timeout = 20 * 1e3) {
      if (!url) {
        return Promise.reject({ "code": "exception", "result": null });
      }
      return new Promise((resolve, reject) => {
        const config = {
          method: method.toUpperCase(),
          url,
          timeout,
          onload: function(response) {
            if (response.status >= 200 && response.status < 300) {
              resolve({ "code": "success", "result": response.responseText });
            } else {
              reject({ "code": "error", "result": response.statusText });
            }
          },
          ontimeout: function(error) {
            reject({ "code": "error", "result": error });
          },
          onerror: function(error) {
            reject({ "code": "error", "result": error });
          }
        };
        if (config.method === "POST") {
          config.headers = headers != null ? headers : { "Content-Type": "application/json" };
          config.data = JSON.stringify(param);
        } else if (config.method === "GET") {
          config.headers = headers != null ? headers : { "Content-Type": "application/json" };
          config.data = param;
        }
        GM_xmlhttpRequest(config);
      });
    },
    crossRequest: function(method = "GET", url, param = {}, headers = { "Content-Type": "application/json;charset=UTF-8" }, timeout = 20 * 1e3) {
      if (!url) {
        return Promise.reject({ "code": "exception", "result": null });
      }
      const config = { method: method.toUpperCase(), headers };
      const controller = new AbortController();
      const signal = controller.signal;
      config.signal = signal;
      if (config.method === "POST") {
        config.headers = headers != null ? headers : { "Content-Type": "application/json" };
        config.body = JSON.stringify(param);
      }
      const timeoutId = setTimeout(() => controller.abort(), timeout);
      return fetch(url, config).then((response) => response.ok ? response.text() : Promise.reject(response.statusText)).then((result) => {
        clearTimeout(timeoutId);
        return { "code": "success", "result": result };
      }).catch((error) => {
        clearTimeout(timeoutId);
        if (error.name === "AbortError") {
          return { "code": "error", "result": "Request timeout" };
        }
        return { "code": "error", "result": error };
      });
    },
    getParamterBySuffix: function(url = window.location.href, suffix = "html") {
      if (url.indexOf("?") != -1) {
        url = url.split("?")[0];
      }
      if (url.indexOf("#") != -1) {
        url = url.split("#")[0];
      }
      let regex = new RegExp("\\/([^\\/]*?)\\." + suffix);
      if (/lazada/.test(url)) {
        regex = new RegExp("-i(\\d+)(?:-s(\\d+))?\\.html");
      } else if (/www\.ebay/.test(url)) {
        regex = new RegExp("\\/itm\\/(\\d+)");
      }
      const match = url.match(regex);
      return match ? match[1] : null;
    },
    getParamterBySearch: function(paramsString = window.location.href, tag) {
      if (paramsString.indexOf("?") != -1) {
        paramsString = paramsString.split("?")[1];
      }
      const params = new URLSearchParams(paramsString);
      return params.get(tag);
    },
    waitForElementByInterval: function(selector, target = document.body, allowEmpty = true, delay = 10, maxDelay = 10 * 1e3) {
      return new Promise((resolve, reject) => {
        let totalDelay = 0;
        let element = target.querySelector(selector);
        let result = allowEmpty ? !!element : !!element && !!element.innerHTML;
        if (result) {
          resolve(element);
        }
        const elementInterval = setInterval(() => {
          if (totalDelay >= maxDelay) {
            clearInterval(elementInterval);
            resolve(null);
          }
          element = target.querySelector(selector);
          result = allowEmpty ? !!element : !!element && !!element.innerHTML;
          if (result) {
            clearInterval(elementInterval);
            resolve(element);
          } else {
            totalDelay += delay;
          }
        }, delay);
      });
    },
    randomNumber: function() {
      return Math.ceil(Math.random() * 1e8);
    },
    elementInContainer: function(container, element) {
      return container.contains(element);
    },
    mustGetElement: function(handler) {
      return __async$3(this, null, function* () {
        const getElements = (handler2) => __async$3(this, null, function* () {
          const promiseArray = [];
          const handlers = handler2.split("@");
          for (let i = 0; i < handlers.length; i++) {
            const eleName = handlers[i];
            if (!eleName) {
              continue;
            }
            if (eleName == "body") {
              promiseArray.push(
                new Promise((resolve, reject) => {
                  resolve(document.body);
                })
              );
            } else if (eleName == "html") {
              promiseArray.push(
                new Promise((resolve, reject) => {
                  resolve(document.html);
                })
              );
            } else {
              promiseArray.push(this.waitForElementByInterval(eleName, document.body, true, 10, 1500));
            }
          }
          let element2 = yield Promise.race(promiseArray);
          return element2;
        });
        let element = yield getElements(handler);
        return new Promise((resolve, reject) => {
          if (element) {
            resolve(element);
            return;
          }
          const waitInterval = setInterval(() => {
            element = getElements(handler);
            if (element) {
              clearInterval(waitInterval);
              resolve(element);
              return;
            }
          }, 2e3);
        });
      });
    },
    loopTask: function(callback, delay = 1500) {
      callback();
      setInterval(() => {
        callback();
      }, delay);
    },
    distinguishRemoveAndTry: function(distinguish, callback) {
      const distinguishElements = distinguish.map((name) => document.querySelector("*[name='" + name + "']"));
      const validateRs = distinguishElements.some((ele) => ele === null || ele === void 0);
      if (validateRs) {
        distinguishElements.reverse().forEach((element) => {
          if (element) {
            element.remove();
          }
        });
        callback();
      }
    },
    getDomain: function(url) {
      try {
        const hostname = new URL(url).hostname;
        const parts = hostname.split(".");
        if (parts.length > 2) {
          return `${parts[parts.length - 2]}.${parts[parts.length - 1]}`;
        }
        return hostname;
      } catch (error) {
        console.error("Invalid URL:", error);
        return null;
      }
    }
  };

  const Toast = {
    show: function(params) {
      let time = params.time;
      let background = params.background;
      let color = params.color;
      let position = params.position;
      let defaultMarginValue = 50;
      if (time == void 0 || time == "") {
        time = 1500;
      }
      if (position == void 0 || position == "") {
        position = "center-bottom";
      }
      const style = document.createElement("style");
      style.textContent = `@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-o-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-ms-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-o-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-ms-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.toast-style-kk998y{position:fixed;background:rgba(0,0,0,0.7);color:#fff;font-size:14px;line-height:1;padding:10px;border-radius:3px;left:50%;transform:translateX(-50%);-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-o-transform:translateX(-50%);-ms-transform:translateX(-50%);z-index:999999999999999999999999999;white-space:nowrap}.fadeOut{animation:fadeOut .5s}.fadeIn{animation:fadeIn .5s}`;
      const el = document.createElement("div");
      if (background != void 0 && background != "") {
        el.style.backgroundColor = background;
      }
      if (color != void 0 && color != "") {
        el.style.color = color;
      }
      el.setAttribute("class", "toast-style-kk998y");
      el.innerText = params.message;
      el.style.zIndex = 999999999;
      if (position === "center-bottom") {
        el.style.bottom = defaultMarginValue + "px";
      } else {
        el.style.top = defaultMarginValue + "px";
      }
      document.body.appendChild(el);
      document.head.appendChild(style);
      el.classList.add("fadeIn");
      setTimeout(function() {
        el.classList.remove("fadeIn");
        el.classList.add("fadeOut");
        el.addEventListener("animationend", function() {
          document.body.removeChild(el);
          document.head.removeChild(style);
        });
        el.addEventListener("webkitAnimationEnd", function() {
          document.body.removeChild(el);
          document.head.removeChild(style);
        });
      }, time);
    }
  };

  var _a;
  const language = {
    "zh": {
      "dateFormat": {
        "week": ["日", "一", "二", "三", "四", "五", "六"]
      },
      "download": {
        "download": "下载",
        "completed": "下载完成",
        "tip": "点击下载视频",
        "preparing": "正在准备下载(如果失败,请手动操作)"
      },
      "menuCommand": {
        "settings": "设置",
        "titleDateFormat": "时间格式设置:",
        "buttonClose": "关闭"
      }
    },
    "en": {
      "dateFormat": {
        "week": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
      },
      "download": {
        "download": "Download",
        "completed": "Download Completed",
        "tip": "Click to download video",
        "preparing": "Preparing to download (if failed, please do it manually)"
      },
      "menuCommand": {
        "settings": "Settings",
        "titleDateFormat": "Time format settings:",
        "buttonClose": "Close"
      }
    },
    "ja": {
      "dateFormat": {
        "week": ["日", "月", "火", "水", "木", "金", "土"]
      },
      "download": {
        "download": "ダウンロード",
        "completed": "ダウンロード完了",
        "tip": "クリックしてビデオをダウンロード",
        "preparing": "ダウンロードの準備中(失敗する場合は手動で行ってください)"
      },
      "menuCommand": {
        "settings": "設定",
        "titleDateFormat": "時刻形式の設定:",
        "buttonClose": "閉鎖"
      }
    },
    "fr": {
      "dateFormat": {
        "week": ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"]
      },
      "download": {
        "download": "télécharger",
        "completed": "éléchargement terminé",
        "tip": "Cliquez pour télécharger la vidéo",
        "preparing": "Préparation du téléchargement (en cas d'échec, veuillez le faire manuellement)"
      },
      "menuCommand": {
        "settings": "installation",
        "titleDateFormat": "Paramètres du format de l'heure :",
        "buttonClose": "fermeture"
      }
    },
    "de": {
      "dateFormat": {
        "week": ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam"]
      },
      "download": {
        "download": "herunterladen",
        "completed": "Download abgeschlossen",
        "tip": "Klicken Sie hier, um das Video herunterzuladen",
        "preparing": "Vorbereitung für den Download (falls der Download fehlschlägt, führen Sie ihn bitte manuell durch)"
      },
      "menuCommand": {
        "settings": "aufstellen",
        "titleDateFormat": "Einstellungen für das Zeitformat:",
        "buttonClose": "Schließung"
      }
    },
    "it": {
      "dateFormat": {
        "week": ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"]
      },
      "download": {
        "download": "scaricamento",
        "completed": "Download completato",
        "tip": "Fare clic per scaricare il video",
        "preparing": "Preparazione per il download (se fallisce, eseguilo manualmente)"
      },
      "menuCommand": {
        "settings": "impostare",
        "titleDateFormat": "Impostazioni del formato dell'ora:",
        "buttonClose": "chiusura"
      }
    },
    "ko": {
      "dateFormat": {
        "week": ["일", "월", "화", "수", "목", "금", "토"]
      },
      "download": {
        "download": "다운로드",
        "completed": "다운로드 완료",
        "tip": "비디오를 다운로드하려면 클릭하세요",
        "preparing": "다운로드 준비 중 (실패할 경우 수동으로 진행해주세요)"
      },
      "menuCommand": {
        "settings": "설정",
        "titleDateFormat": "시간 형식 설정:",
        "buttonClose": "폐쇄"
      }
    },
    "ru": {
      "dateFormat": {
        "week": ["ВС", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"]
      },
      "download": {
        "download": "скачать",
        "completed": "Загрузка завершена",
        "tip": "Нажмите, чтобы скачать видео",
        "preparing": "Подготовка к загрузке (если не получается, сделайте это вручную)"
      },
      "menuCommand": {
        "settings": "настраивать",
        "titleDateFormat": "Настройки формата времени:",
        "buttonClose": "закрытие"
      }
    },
    "pt": {
      "dateFormat": {
        "week": ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"]
      },
      "download": {
        "download": "descargar",
        "completed": "Descarga completa",
        "tip": "Clique para baixar o vídeo",
        "preparing": "Preparação para download (se falhar, faça-o manualmente)"
      },
      "menuCommand": {
        "settings": "configuración",
        "titleDateFormat": "Configuración de formato de hora:",
        "buttonClose": "cierre"
      }
    },
    "es": {
      "dateFormat": {
        "week": ["DOM", "LUN", "MAR", "MIER", "JUE", "VIE", "SÁB"]
      },
      "download": {
        "download": "descargar",
        "completed": "Descarga completa",
        "tip": "Haga clic para descargar el vídeo",
        "preparing": "Preparándose para la descarga (si falla, hágalo manualmente)"
      },
      "menuCommand": {
        "settings": "configuración",
        "titleDateFormat": "Configuración de formato de hora:",
        "buttonClose": "cierre"
      }
    },
    "th": {
      "dateFormat": {
        "week": ["วันอาทิตย์", "วันจันทร์", "วันอังคาร", "วันพุธ", " วันพฤหัสบดี", "วันศุกร์ ", "วันเสาร์ "]
      },
      "download": {
        "download": "ดาวน์โหลด",
        "completed": "ดาวน์โหลดเสร็จสมบูรณ์",
        "tip": "คลิกเพื่อดาวน์โหลดวิดีโอ",
        "preparing": "กำลังเตรียมการดาวน์โหลด (หากล้มเหลว กรุณาดำเนินการด้วยตนเอง)"
      },
      "menuCommand": {
        "settings": "ตั้งค่า",
        "titleDateFormat": "การตั้งค่ารูปแบบเวลา:",
        "buttonClose": "ปิด"
      }
    },
    "tr": {
      "dateFormat": {
        "week": ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"]
      },
      "download": {
        "download": "indirmek",
        "completed": "İndirme tamamlandı",
        "tip": "Videoyu indirmek için tıklayın",
        "preparing": "İndirmeye hazırlanıyor (başarısız olursa lütfen manuel olarak yapın)"
      },
      "menuCommand": {
        "settings": "kurmak",
        "titleDateFormat": "Saat formatı ayarları:",
        "buttonClose": "kapatma"
      }
    },
    "nl": {
      "dateFormat": {
        "week": ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"]
      },
      "download": {
        "download": "downloaden",
        "completed": "Downloaden voltooid",
        "tip": "Klik om video te downloaden",
        "preparing": "Voorbereiden voor downloaden (als dit mislukt, doe dit dan handmatig)"
      },
      "menuCommand": {
        "settings": "opgezet",
        "titleDateFormat": "Instellingen tijdformaat:",
        "buttonClose": "sluiting"
      }
    }
  };
  const Commonlanguage = (_a = language[ScriptConst["lang"]]) != null ? _a : language["en"];

  var __async$2 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const FMT = 7;
  let fmt = GM_getValue("fmt", FMT);
  const XSettingsDialog = {
    number: Math.ceil(Math.random() * 1e8),
    formats: [
      { "format": "Do nothing", "example": "N/A" },
      { "format": "dd.MM.yy HH:mm", "example": "22.10.24 03:12" },
      { "format": "dd.MM.yy HH:mm:ss", "example": "22.10.24 03:12:56" },
      { "format": "dd.MM.yy(W) HH:mm", "example": "22.10.24(Mon) 03:12" },
      { "format": "dd.MM.yy(W) HH:mm:ss", "example": "22.10.24(Mon) 03:12:56" },
      { "format": "yy/MM/dd HH:mm", "example": "24/10/22 03:12" },
      { "format": "yy/MM/dd HH:mm:ss", "example": "24/10/22 03:12:56" },
      { "format": "yy/MM/dd(W) HH:mm", "example": "24/10/22(Mon) 03:12" },
      { "format": "yy/MM/dd(W) HH:mm:ss [ye/mo/da(we) ho:mi:se]", "example": "24/10/22(Mon) 03:12:56 [ye/mo/da(we) ho:mi:se]" },
      { "format": "yy-MM/dd HH:mm", "example": "24-10/22 03:12" },
      { "format": "yy-MM/dd HH:mm'ss", "example": "24-10/22 03:12'56" },
      { "format": "yy-MM/dd(W) HH:mm", "example": "24-10/22(Mon) 03:12" },
      { "format": "yy-MM/dd(W) HH:mm'ss", "example": "24-10/22(Mon) 03:12'56" },
      { "format": "MM/dd/yy HH:mm", "example": "10/22/24 03:12" },
      { "format": "MM/dd/yy HH:mm:ss", "example": "10/22/24 03:12:56" },
      { "format": "W, MM/dd/yy HH:mm", "example": "Mon, 10/22/24 03:12" },
      { "format": "W, MM/dd/yy HH:mm:ss", "example": "Mon, 10/22/24 03:12:56" },
      { "format": "M59-MM-dd HH:mm", "example": "M59-10-22 03:12" },
      { "format": "M59-MM-dd HH:mm:ss", "example": "M59-10-22 03:12:56" },
      { "format": "M59-MM-dd(W) HH:mm", "example": "M59-10-22(Mon) 03:12" },
      { "format": "M59-MM-dd(W) HH:mm:ss", "example": "M59-10-22(Mon) 03:12:56" }
    ],
    make: function() {
      let dialog = document.createElement("div");
      dialog.className = "dialog_u_" + this.number;
      dialog.style.all = "initial";
      dialog.style.backgroundColor = "rgb(255, 255, 255)";
      dialog.style.border = "1px solid #ccc";
      dialog.style.borderRadius = "2px";
      dialog.style.display = "none";
      dialog.style.fontFamily = "monospace";
      dialog.style.fontSize = "12px";
      dialog.style.width = "480px";
      dialog.style.paddingLeft = "5px";
      dialog.style.paddingRight = "5px";
      dialog.style.paddingTop = "5px";
      dialog.style.paddingBottom = "5px";
      dialog.style.position = "fixed";
      dialog.style.right = "8px";
      dialog.style.top = "8px";
      dialog.style.zIndex = "2147483647";
      dialog.style.overflow = "auto";
      let formatsHtml = `<table style="width:100%;border: 1px solid #c0bfbf;border-collapse: collapse;">`;
      for (var i = 1; i <= this.formats.length; i++) {
        if (i % 2 != 0) {
          formatsHtml += `<tr style="width:100%;border: 1px solid #c0bfbf;">`;
        }
        formatsHtml += `<td width="50" style="border: 1px solid #c0bfbf;padding: 5px 0px;" title="` + this.formats[i - 1].example + `"><input type="radio" name="fmt" value="` + (i - 1) + `" class="top_r" />` + ("【" + i + "】" + this.formats[i - 1].format) + `</td>`;
        if (i % 2 == 0) {
          formatsHtml += `</tr>`;
        }
      }
      formatsHtml += `</table>`;
      let html = `
        <div style="font-size:15px;font-weight:bold;margin-bottom:5px;">` + Commonlanguage.menuCommand.titleDateFormat + `</div>
        <div>` + formatsHtml + `</div>
        <div style="margin-top:15px;text-align:center;">
          <button name="closex">` + Commonlanguage.menuCommand.buttonClose + `</button>
        </div>
      `;
      dialog.innerHTML = html;
      return dialog;
    },
    addEvent: function(dialog) {
      dialog.querySelector("button[name='closex']").addEventListener("click", function(event) {
        for (let e of dialog.querySelectorAll('input[name="fmt"]')) {
          if (e.checked) {
            fmt = e.value;
            break;
          }
        }
        GM_setValue("fmt", fmt);
        dialog.style.display = "none";
      }, false);
    },
    init: function() {
      let dialog = this.make();
      this.addEvent(dialog);
      document.body.appendChild(dialog);
      GM_registerMenuCommand(Commonlanguage.menuCommand.settings, function() {
        if (dialog.style.display == "none") {
          dialog.querySelector('input[name="fmt"][value="' + fmt + '"]').checked = true;
          dialog.style.display = "block";
        }
      });
    }
  };
  const XDateFormat = {
    df: function(date, f) {
      var _a;
      const WEEK = Commonlanguage.dateFormat.week;
      const YE = date.getFullYear().toString().slice(-2);
      const YM = date.getFullYear() - 1911;
      const MO = ("0" + (date.getMonth() + 1)).slice(-2);
      const DA = ("0" + date.getDate()).slice(-2);
      const WE = WEEK[date.getDay()];
      const HO = ("0" + date.getHours()).slice(-2);
      const MI = ("0" + date.getMinutes()).slice(-2);
      const SE = ("0" + date.getSeconds()).slice(-2);
      const F = [
        DA + "." + MO + "." + YE + " " + HO + ":" + MI,
        DA + "." + MO + "." + YE + " " + HO + ":" + MI + ":" + SE,
        DA + "." + MO + "." + YE + "(" + WE + ") " + HO + ":" + MI,
        DA + "." + MO + "." + YE + "(" + WE + ") " + HO + ":" + MI + ":" + SE,
        YE + "/" + MO + "/" + DA + " " + HO + ":" + MI,
        YE + "/" + MO + "/" + DA + " " + HO + ":" + MI + ":" + SE,
        YE + "/" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI,
        YE + "/" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI + ":" + SE,
        YE + "-" + MO + "/" + DA + " " + HO + ":" + MI,
        YE + "-" + MO + "/" + DA + " " + HO + ":" + MI + "'" + SE,
        YE + "-" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI,
        YE + "-" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI + "'" + SE,
        MO + "/" + DA + "/" + YE + " " + HO + ":" + MI,
        MO + "/" + DA + "/" + YE + " " + HO + ":" + MI + ":" + SE,
        WE + ", " + MO + "/" + DA + "/" + YE + " " + HO + ":" + MI,
        WE + ", " + MO + "/" + DA + "/" + YE + " " + HO + ":" + MI + ":" + SE,
        "M" + YM + "-" + MO + "-" + DA + " " + HO + ":" + MI,
        "M" + YM + "-" + MO + "-" + DA + " " + HO + ":" + MI + ":" + SE,
        "M" + YM + "-" + MO + "-" + DA + "(" + WE + ") " + HO + ":" + MI,
        "M" + YM + "-" + MO + "-" + DA + "(" + WE + ") " + HO + ":" + MI + ":" + SE
      ];
      return (_a = F[f]) != null ? _a : F[0];
    },
    repldatetime: function() {
      const MYNAME = "peter_parker_x1190";
      const SEL = 'main div[data-testid="primaryColumn"] section article time[datetime*=":"]';
      const SEL_2 = 'div[aria-labelledby="modal-header"] div[data-testid^="User-Name"] time[datetime]';
      const SEL_3 = 'div[aria-labelledby="modal-header"] div[aria-label] time[datetime]';
      const SEL_4 = 'main section[aria-labelledby="detail-header"] article div[data-testid^="User-Name"] time[datetime]';
      const SEL_5 = 'main section div[data-testid="conversation"] div[aria-label] time[datetime]';
      document.querySelectorAll(SEL + ", " + SEL_2 + ", " + SEL_3 + ", " + SEL_4 + ", " + SEL_5).forEach((e) => {
        if (fmt != 0) {
          const SEL_ADD = "span.us-" + MYNAME;
          let d = e.getAttribute("datetime");
          let df = this.df(new Date(d), fmt - 1);
          let pe = e.parentNode;
          let old = pe.querySelectorAll(SEL_ADD);
          if (!old.length) {
            let span = document.createElement("span");
            span.className = "us-" + MYNAME;
            span.setAttribute("datetime", d);
            span.setAttribute("local-datetime", df);
            span.textContent = df;
            span.style = e.style;
            e.style.setProperty("display", "none");
            pe.appendChild(span);
          } else if (old[0].getAttribute("local-datetime") != df) {
            old[0].setAttribute("local-datetime", df);
            old[0].textContent = df;
            old[0].style = e.style;
          }
        }
      });
    }
  };
  const XOrigimg = () => {
    const SEL_D = 'div[style*="background-image:"]';
    const SEL_I = "img";
    let elms = document.querySelectorAll(SEL_D + ", " + SEL_I);
    for (let e of elms) {
      let regex = /^(.+pbs\.twimg\.com\/[^?]+\?format=\w+)(&|&amp;)(name=)(\w+)([")]*)$/;
      if (/div/i.test(e.tagName)) {
        let r2 = regex.exec(e.style.backgroundImage);
        if (r2 && r2[4] != "orig") {
          e.style.backgroundImage = r2[1] + r2[2] + r2[3] + "orig" + r2[5];
          continue;
        }
        continue;
      }
      let r = regex.exec(e.getAttribute("src"));
      if (r && r[4] != "orig") {
        e.setAttribute("src", r[1] + r[2] + r[3] + "orig" + r[5]);
        continue;
      }
    }
  };
  const XHidepromo = () => {
    var _a, _b;
    const SEL = 'path[d^="M19.498 3h-15c-1.381 0-2.5 1.12-2.5 2.5v13c0 1.38 1.119 2.5"]';
    const SEL_2 = 'main div[data-testid="sidebarColumn"] section div[data-testid="trend"] div.r-14gqq1x span.css-1qaijid.r-bcqeeo.r-qvutc0';
    const SEL_3 = 'main div[data-testid="primaryColumn"] section article span.css-1jxf684.r-bcqeeo.r-qvutc0.r-poiln3';
    const SEL_4 = 'main div[data-testid="primaryColumn"] section span.css-901oao.css-16my406.r-bcqeeo.r-qvutc0';
    let elms = document.querySelectorAll(SEL);
    let elms_2 = document.querySelectorAll(SEL_2);
    let elms_3 = document.querySelectorAll(SEL_3);
    let elms_4 = document.querySelectorAll(SEL_4);
    const PROMO = {
      "ja": "によるプロモーション$",
      "ko": " 님이 프로모션함$",
      "zh": "^由 .+ 推广$",
      "ru": "^Реклама от ",
      "de": "^Gesponsert von ",
      "it": "^Sponsorizzato da ",
      "fr": "^Sponsorisé par ",
      "pt": "^Promovido por ",
      "en": "^Promoted by "
    };
    const PROMO_L = (_a = PROMO[ScriptConst.lang]) != null ? _a : PROMO["en"];
    const PROMO_2 = {
      "ja": "プロモポスト",
      "ko": "Promoted Post",
      "zh": "推广帖",
      "ru": "Promoted Post",
      "de": "Gesponserter Post",
      "it": "Promoted Post",
      "fr": "Promoted Post",
      "pt": "Post promovido",
      "en": "Promoted Post"
    };
    const PROMO_L_2 = (_b = PROMO_2[ScriptConst.lang]) != null ? _b : PROMO_2["en"];
    for (let e of elms) {
      let xpe = e.closest('div[data-testid="cellInnerDiv"]');
      if (!xpe)
        xpe = e.closest("div.css-175oi2r.r-1adg3ll.r-1ny4l3l");
      if (!xpe)
        xpe = e.closest('div.css-175oi2r.r-1ny4l3l[data-testid="UserCell"]');
      if (xpe)
        xpe.style.setProperty("display", "none");
    }
    for (let e of elms_2) {
      const REGEX = new RegExp(PROMO_L, "i");
      if (!REGEX.test(e.textContent))
        continue;
      let xpe = e.closest("div.css-175oi2r.r-1adg3ll.r-1ny4l3l");
      xpe.style.setProperty("display", "none");
    }
    for (let e of elms_3) {
      if (e.textContent != "Ad")
        continue;
      let xpe = e.closest('div[data-testid="cellInnerDiv"]');
      xpe.style.setProperty("display", "none");
    }
    for (let e of elms_4) {
      if (e.textContent != PROMO_2["en"] && e.textContent != PROMO_L_2)
        continue;
      let xpe = e.closest('div[data-testid="cellInnerDiv"]');
      xpe.style.setProperty("display", "none");
    }
  };
  const XDownload = {
    history: [],
    show_sensitive: true,
    filename: "twitter_{user-name}(@{user-id})_{date-time}_{status-id}_{file-type}",
    css: `
    .tmd-down {margin-left: 12px; order: 99;}
    .tmd-down:hover > div > div > div > div {color: rgba(29, 161, 242, 1.0);}
    .tmd-down:hover > div > div > div > div > div {background-color: rgba(29, 161, 242, 0.1);}
    .tmd-down:active > div > div > div > div > div {background-color: rgba(29, 161, 242, 0.2);}
    .tmd-down:hover svg {color: rgba(29, 161, 242, 1.0);}
    .tmd-down:hover div:first-child:not(:last-child) {background-color: rgba(29, 161, 242, 0.1);}
    .tmd-down:active div:first-child:not(:last-child) {background-color: rgba(29, 161, 242, 0.2);}
    .tmd-down.tmd-media {position: absolute; right: 0;}
    .tmd-down.tmd-media > div {display: flex; border-radius: 99px; margin: 2px;}
    .tmd-down.tmd-media > div > div {display: flex; margin: 6px; color: #fff;}
    .tmd-down.tmd-media:hover > div {background-color: rgba(255,255,255, 0.6);}
    .tmd-down.tmd-media:hover > div > div {color: rgba(29, 161, 242, 1.0);}
    .tmd-down.tmd-media:not(:hover) > div > div {filter: drop-shadow(0 0 1px #000);}
    .tmd-down g {display: none;}
    .tmd-down.download g.download, .tmd-down.completed g.completed, .tmd-down.loading g.loading,.tmd-down.failed g.failed {display: unset;}
    .tmd-down.loading svg {animation: spin 1s linear infinite;}
    @keyframes spin {0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}}
    .tmd-btn {display: inline-block; background-color: #1DA1F2; color: #FFFFFF; padding: 0 20px; border-radius: 99px;}
    .tmd-tag {display: inline-block; background-color: #FFFFFF; color: #1DA1F2; padding: 0 10px; border-radius: 10px; border: 1px solid #1DA1F2;  font-weight: bold; margin: 5px;}
    .tmd-btn:hover {background-color: rgba(29, 161, 242, 0.9);}
    .tmd-tag:hover {background-color: rgba(29, 161, 242, 0.1);}
    .tmd-notifier {display: none; position: fixed; left: 16px; bottom: 16px; color: #000; background: #fff; border: 1px solid #ccc; border-radius: 8px; padding: 4px;}
    .tmd-notifier.running {display: flex; align-items: center;}
    .tmd-notifier label {display: inline-flex; align-items: center; margin: 0 8px;}
    .tmd-notifier label:before {content: " "; width: 32px; height: 16px; background-position: center; background-repeat: no-repeat;}
    .tmd-notifier label:nth-child(1):before {background-image:url("data:image/svg+xml;charset=utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2216%22 height=%2216%22 viewBox=%220 0 24 24%22><path d=%22M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l4,4 q1,1 2,0 l4,-4 M12,3 v11%22 fill=%22none%22 stroke=%22%23666%22 stroke-width=%222%22 stroke-linecap=%22round%22 /></svg>");}
    .tmd-notifier label:nth-child(2):before {background-image:url("data:image/svg+xml;charset=utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2216%22 height=%2216%22 viewBox=%220 0 24 24%22><path d=%22M12,2 a1,1 0 0 1 0,20 a1,1 0 0 1 0,-20 M12,5 v7 h6%22 fill=%22none%22 stroke=%22%23999%22 stroke-width=%222%22 stroke-linejoin=%22round%22 stroke-linecap=%22round%22 /></svg>");}
    .tmd-notifier label:nth-child(3):before {background-image:url("data:image/svg+xml;charset=utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2216%22 height=%2216%22 viewBox=%220 0 24 24%22><path d=%22M12,0 a2,2 0 0 0 0,24 a2,2 0 0 0 0,-24%22 fill=%22%23f66%22 stroke=%22none%22 /><path d=%22M14.5,5 a1,1 0 0 0 -5,0 l0.5,9 a1,1 0 0 0 4,0 z M12,17 a2,2 0 0 0 0,5 a2,2 0 0 0 0,-5%22 fill=%22%23fff%22 stroke=%22none%22 /></svg>");}
    .tmd-down.tmd-img {position: absolute; right: 0; bottom: 0; display: none !important;}
    .tmd-down.tmd-img > div {display: flex; border-radius: 99px; margin: 2px; background-color: rgba(255,255,255, 0.6);}
    .tmd-down.tmd-img > div > div {display: flex; margin: 6px; color: #fff !important;}
    .tmd-down.tmd-img:not(:hover) > div > div {filter: drop-shadow(0 0 1px #000);}
    .tmd-down.tmd-img:hover > div > div {color: rgba(29, 161, 242, 1.0);}
    :hover > .tmd-down.tmd-img, .tmd-img.loading, .tmd-img.completed, .tmd-img.failed {display: block !important;}
    .tweet-detail-action-item {width: 20% !important;}
    `,
    css_ss: `
    /* show sensitive in media tab */
    li[role="listitem"]>div>div>div>div:not(:last-child) {filter: none;}
    li[role="listitem"]>div>div>div>div+div:last-child {display: none;}
    `,
    svg: `
    <g class="download"><path d="M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l4,4 q1,1 2,0 l4,-4 M12,3 v11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></g>
    <g class="completed"><path d="M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l3,4 q1,1 2,0 l8,-11" fill="none" stroke="#1DA1F2" stroke-width="2" stroke-linecap="round" /></g>
    <g class="loading"><circle cx="12" cy="12" r="10" fill="none" stroke="#1DA1F2" stroke-width="4" opacity="0.4" /><path d="M12,2 a10,10 0 0 1 10,10" fill="none" stroke="#1DA1F2" stroke-width="4" stroke-linecap="round" /></g>
    <g class="failed"><circle cx="12" cy="12" r="11" fill="#f33" stroke="currentColor" stroke-width="2" opacity="0.8" /><path d="M14,5 a1,1 0 0 0 -4,0 l0.5,9.5 a1.5,1.5 0 0 0 3,0 z M12,17 a2,2 0 0 0 0,4 a2,2 0 0 0 0,-4" fill="#fff" stroke="none" /></g>
    `,
    isTweetdeck: function() {
      return ScriptConst.currentHost.indexOf("tweetdeck") >= 0;
    },
    getCookie: function() {
      const cookieString = document.cookie;
      const cookiePairs = cookieString.split(";");
      const cookiesObject = {};
      for (const pair of cookiePairs) {
        const [key, value] = pair.split("=");
        cookiesObject[key.trim()] = value.trim();
      }
      return cookiesObject;
    },
    formatDate: function(i, o, tz) {
      let d = new Date(i);
      if (tz) {
        d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
      }
      let m = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
      let v = {
        YYYY: d.getUTCFullYear().toString(),
        YY: d.getUTCFullYear().toString(),
        MM: d.getUTCMonth() + 1,
        MMM: m[d.getUTCMonth()],
        DD: d.getUTCDate(),
        hh: d.getUTCHours(),
        mm: d.getUTCMinutes(),
        ss: d.getUTCSeconds(),
        h2: d.getUTCHours() % 12,
        ap: d.getUTCHours() < 12 ? "AM" : "PM"
      };
      return o.replace(/(YY(YY)?|MMM?|DD|hh|mm|ss|h2|ap)/g, (n) => ("0" + v[n]).substr(-n.length));
    },
    detect: function(node) {
      let article = node.tagName == "ARTICLE" && node || node.tagName == "DIV" && (node.querySelector("article") || node.closest("article"));
      if (article) {
        this.addButtonTo(article);
      }
      let listitems = node.tagName == "LI" && node.getAttribute("role") == "listitem" && [node] || node.tagName == "DIV" && node.querySelectorAll('li[role="listitem"]');
      if (listitems) {
        this.addButtonToMedia(listitems);
      }
    },
    addButtonTo: function(article) {
      if (article.dataset.detected) {
        return;
      }
      article.dataset.detected = "true";
      const media_selector = [
        'a[href*="/photo/1"]',
        'div[role="progressbar"]',
        'button[data-testid="playButton"]',
        'a[href="/settings/content_you_see"]',
        "div.media-image-container",
        "div.media-preview-container",
        'div[aria-labelledby]>div:first-child>div[role="button"][tabindex="0"]'
      ];
      const media = article.querySelector(media_selector.join(","));
      if (media) {
        let status_id2 = article.querySelector('a[href*="/status/"]').href.split("/status/").pop().split("/").shift();
        let btn_group = article.querySelector('div[role="group"]:last-of-type, ul.tweet-actions, ul.tweet-detail-actions');
        let btn_share = Array.from(btn_group.querySelectorAll(":scope>div>div, li.tweet-action-item>a, li.tweet-detail-action-item>a")).pop().parentNode;
        let btn_down = btn_share.cloneNode(true);
        btn_down.querySelector("button").removeAttribute("disabled");
        if (this.isTweetdeck()) {
          btn_down.firstElementChild.innerHTML = '<svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">' + this.svg + "</svg>";
          btn_down.firstElementChild.removeAttribute("rel");
          btn_down.classList.replace("pull-left", "pull-right");
        } else {
          btn_down.querySelector("svg").innerHTML = this.svg;
        }
        let is_exist = this.history.indexOf(status_id2) >= 0;
        this.status(btn_down, "tmd-down");
        this.status(btn_down, is_exist ? "completed" : "download", is_exist ? Commonlanguage.download.completed : Commonlanguage.download.download);
        btn_group.insertBefore(btn_down, btn_share.nextSibling);
        btn_down.onclick = () => {
          this.click(btn_down, status_id2, is_exist);
        };
        if (this.show_sensitive) {
          let btn_show = article.querySelector('div[aria-labelledby] div[role="button"][tabindex="0"]:not([data-testid]) > div[dir] > span > span');
          if (btn_show) {
            btn_show.click();
          }
        }
      }
      const imgs = article.querySelectorAll('a[href*="/photo/"]');
      if (imgs.length > 1) {
        let status_id2 = article.querySelector('a[href*="/status/"]').href.split("/status/").pop().split("/").shift();
        let btn_group = article.querySelector('div[role="group"]:last-of-type');
        Array.from(btn_group.querySelectorAll(":scope>div>div")).pop().parentNode;
        imgs.forEach((img) => {
          let index = img.href.split("/status/").pop().split("/").pop();
          let is_exist = this.history.indexOf(status_id2) >= 0;
          let btn_down = document.createElement("div");
          btn_down.innerHTML = '<div><div><svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">' + this.svg + "</svg></div></div>";
          btn_down.classList.add("tmd-down", "tmd-img");
          this.status(btn_down, "download");
          img.parentNode.appendChild(btn_down);
          btn_down.onclick = (e) => {
            e.preventDefault();
            this.click(btn_down, status_id2, is_exist, index);
          };
        });
      }
    },
    addButtonToMedia: function(listitems) {
      listitems.forEach((li) => {
        if (li.dataset.detected)
          return;
        li.dataset.detected = "true";
        let is_exist = false;
        try {
          let status_id2 = li.querySelector('a[href*="/status/"]').href.split("/status/").pop().split("/").shift();
          is_exist = this.history.indexOf(status_id2) >= 0;
        } catch (e) {
          Logger.log("error", "get status_id error:", e);
        }
        let btn_down = document.createElement("div");
        btn_down.innerHTML = '<div><div><svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">' + this.svg + "</svg></div></div>";
        btn_down.classList.add("tmd-down", "tmd-media");
        this.status(btn_down, is_exist ? "completed" : "download", is_exist ? Commonlanguage.download.completed : Commonlanguage.download.download);
        li.appendChild(btn_down);
        btn_down.onclick = () => {
          this.click(btn_down, status_id, is_exist);
        };
      });
    },
    status: function(btn, css, title, style) {
      if (css) {
        btn.classList.remove("download", "completed", "loading", "failed");
        btn.classList.add(css);
      }
      if (title)
        btn.title = title;
      if (style)
        btn.style.cssText = style;
    },
    fetchJson: function(status_id2) {
      return __async$2(this, null, function* () {
        const base_url = `https://${ScriptConst.currentHost}/i/api/graphql/NmCeCgkVlsRGS1cAwqtgmw/TweetDetail`;
        const variables = {
          "focalTweetId": status_id2,
          "with_rux_injections": false,
          "includePromotedContent": true,
          "withCommunity": true,
          "withQuickPromoteEligibilityTweetFields": true,
          "withBirdwatchNotes": true,
          "withVoice": true,
          "withV2Timeline": true
        };
        const features = {
          "rweb_lists_timeline_redesign_enabled": true,
          "responsive_web_graphql_exclude_directive_enabled": true,
          "verified_phone_label_enabled": false,
          "creator_subscriptions_tweet_preview_api_enabled": true,
          "responsive_web_graphql_timeline_navigation_enabled": true,
          "responsive_web_graphql_skip_user_profile_image_extensions_enabled": false,
          "tweetypie_unmention_optimization_enabled": true,
          "responsive_web_edit_tweet_api_enabled": true,
          "graphql_is_translatable_rweb_tweet_is_translatable_enabled": true,
          "view_counts_everywhere_api_enabled": true,
          "longform_notetweets_consumption_enabled": true,
          "responsive_web_twitter_article_tweet_consumption_enabled": false,
          "tweet_awards_web_tipping_enabled": false,
          "freedom_of_speech_not_reach_fetch_enabled": true,
          "standardized_nudges_misinfo": true,
          "tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
          "longform_notetweets_rich_text_read_enabled": true,
          "longform_notetweets_inline_media_enabled": true,
          "responsive_web_media_download_video_enabled": false,
          "responsive_web_enhance_cards_enabled": false
        };
        const url = encodeURI(`${base_url}?variables=${JSON.stringify(variables)}&features=${JSON.stringify(features)}`);
        const cookies = this.getCookie();
        const headers = {
          "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA",
          "x-twitter-active-user": "yes",
          "x-twitter-client-language": cookies.lang,
          "x-csrf-token": cookies.ct0
        };
        if (cookies.ct0.length == 32)
          headers["x-guest-token"] = cookies.gt;
        let tweet_detail = yield fetch(url, { headers }).then((result) => result.json());
        let tweet_entrie = tweet_detail.data.threaded_conversation_with_injections_v2.instructions[0].entries.find((n) => n.entryId == `tweet-${status_id2}`);
        let tweet_result = tweet_entrie.content.itemContent.tweet_results.result;
        return tweet_result.tweet || tweet_result;
      });
    },
    click: function(btn, status_id2, is_exist, index) {
      return __async$2(this, null, function* () {
        if (btn.classList.contains("loading"))
          return;
        this.status(btn, "loading");
        let save_history = yield GM_getValue("save_history", true);
        let json = yield this.fetchJson(status_id2);
        let tweet = json.legacy;
        let user = json.core.user_results.result.legacy;
        let invalid_chars = {
          "\\": "\",
          "/": "/",
          "|": "|",
          "<": "<",
          ">": ">",
          ":": ":",
          "*": "*",
          "?": "?",
          '"': """,
          "​": "",
          "‌": "",
          "‍": "",
          "⁠": "",
          "\uFEFF": "",
          "🔞": ""
        };
        let datetime = this.filename.match(/{date-time(-local)?:[^{}]+}/) ? this.filename.match(/{date-time(?:-local)?:([^{}]+)}/)[1].replace(/[\\/ | <>*?:"]/g, (v) => invalid_chars[v]) : "YYYYMMDD-hhmmss";
        let info = {};
        info["status-id"] = status_id2;
        info["user-name"] = user.name.replace(/([\\/|*?:"] | [\u200b - \u200d\u2060\ufeff] | 🔞) /g, (v) => invalid_chars[v]);
        info["user-id"] = user.screen_name;
        info["date-time"] = this.formatDate(tweet.created_at, datetime);
        info["date-time-local"] = this.formatDate(tweet.created_at, datetime, true);
        info["full-text"] = tweet.full_text.split("\n").join(" ").replace(/\s*https:\/\/t\.co\/\w+/g, "").replace(/[\\/ | <>*?:"]|[\u200b-\u200d\u2060\ufeff]/g, (v) => invalid_chars[v]);
        let medias = tweet.extended_entities && tweet.extended_entities.media;
        if (!medias || medias.length == 0) {
          try {
            medias = JSON.parse(json.card.legacy.binding_values[0].value.string_value).media_entities;
            medias = Object.values(medias);
          } catch (e) {
          }
        }
        if (!medias || medias.length == 0) {
          this.status(btn, "failed", "MEDIA_NOT_FOUND");
          return;
        }
        if (index) {
          medias = [medias[index - 1]];
        }
        if (medias.length > 0) {
          let tasks = medias.length;
          let tasks_result = [];
          medias.forEach((media, i) => {
            info.url = media.type == "photo" ? media.media_url_https + ":orig" : media.video_info.variants.filter((n) => n.content_type == "video/mp4").sort((a, b) => b.bitrate - a.bitrate)[0].url;
            info.file = info.url.split("/").pop().split(/[:?]/).shift();
            info["file-name"] = info.file.split(".").shift();
            info["file-ext"] = info.file.split(".").pop();
            info["file-type"] = media.type.replace("animated_", "");
            info.out = (this.filename.replace(/\.?{file-ext}/, "") + ((medias.length > 1 || index) && !this.filename.match("{file-name}") ? "-" + (index ? index - 1 : i) : "") + ".{file-ext}").replace(/{([^{}:]+)(:[^{}]+)?}/g, (match, name) => info[name]);
            this.downloader.add({
              url: info.url,
              name: info.out,
              onload: () => {
                tasks -= 1;
                tasks_result.push((medias.length > 1 || index ? (index ? index : i + 1) + ": " : "") + Commonlanguage.download.completed);
                this.status(btn, null, tasks_result.sort().join("\n"));
                if (tasks === 0) {
                  this.status(btn, "completed", Commonlanguage.download.completed);
                  if (save_history && !is_exist) {
                    this.history.push(status_id2);
                  }
                }
              },
              onerror: (result) => {
                tasks = -1;
                tasks_result.push((medias.length > 1 ? i + 1 + ": " : "") + result.details.current);
                this.status(btn, "failed", tasks_result.sort().join("\n"));
              }
            });
          });
        } else {
          this.status(btn, "failed", "MEDIA_NOT_FOUND");
        }
      });
    },
    downloader: function() {
      let tasks = [], thread = 0, max_thread = 2, retry = 0, max_retry = 2, failed = 0, notifier, has_failed = false;
      return {
        add: function(task) {
          tasks.push(task);
          if (thread < max_thread) {
            thread += 1;
            this.next();
          } else {
            this.update();
          }
        },
        next: function() {
          return __async$2(this, null, function* () {
            let task = tasks.shift();
            yield this.start(task);
            if (tasks.length > 0 && thread <= max_thread) {
              this.next();
            } else {
              thread -= 1;
            }
            this.update();
          });
        },
        start: function(task) {
          this.update();
          return new Promise((resolve) => {
            GM_download({
              url: task.url,
              name: task.name,
              onload: (result) => {
                task.onload();
                resolve();
              },
              onerror: (result) => {
                this.retry(task, result);
                resolve();
              },
              ontimeout: (result) => {
                this.retry(task, result);
                resolve();
              }
            });
          });
        },
        retry: function(task, result) {
          retry += 1;
          if (retry == 3)
            max_thread = 1;
          if (task.retry && task.retry >= max_retry || result.details && result.details.current == "USER_CANCELED") {
            task.onerror(result);
            failed += 1;
          } else {
            if (max_thread == 1)
              task.retry = (task.retry || 0) + 1;
            this.add(task);
          }
        },
        update: function() {
          if (!notifier) {
            notifier = document.createElement("div");
            notifier.title = "Twitter Media Downloader";
            notifier.classList.add("tmd-notifier");
            notifier.innerHTML = "<label>0</label>|<label>0</label>";
            document.body.appendChild(notifier);
          }
          if (failed > 0 && !has_failed) {
            has_failed = true;
            notifier.innerHTML += "|";
            let clear = document.createElement("label");
            notifier.appendChild(clear);
            clear.onclick = () => {
              notifier.innerHTML = "<label>0</label>|<label>0</label>";
              failed = 0;
              has_failed = false;
              this.update();
            };
          }
          notifier.firstChild.innerText = thread;
          notifier.firstChild.nextElementSibling.innerText = tasks.length;
          if (failed > 0) {
            notifier.lastChild.innerText = failed;
          }
          if (thread > 0 || tasks.length > 0 || failed > 0) {
            notifier.classList.add("running");
          } else {
            notifier.classList.remove("running");
          }
        }
      };
    }(),
    init: function() {
      document.head.insertAdjacentHTML("beforeend", "<style>" + this.css + (this.show_sensitive ? this.css_ss : "") + "</style>");
    }
  };
  const X = {
    XSettingsDialog,
    XDateFormat,
    XOrigimg,
    XHidepromo,
    XDownload
  };

  var __async$1 = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const Tiktok = {
    extractHref: function(html) {
      const regex = /<a\s+(?:[^>]*?\s+)?href=(['"])(.*?)\1/gi;
      const hrefs = [];
      let match;
      while ((match = regex.exec(html)) !== null) {
        hrefs.push(match[2]);
      }
      return hrefs.filter((href) => href.indexOf("snapcdn.app") != -1);
    },
    download: function(url, element) {
      return __async$1(this, null, function* () {
        Toast.show({ "message": Commonlanguage.download.preparing, "background": "#000" });
        element.classList.add("download-loadding");
        const data = yield Tools.request(
          "POST",
          "https://tikdownloader.io/api/ajaxSearch",
          "q=" + url + "&lang=en",
          { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" }
        );
        if (data.code === "success") {
          const result = JSON.parse(data.result);
          if (result.status == "ok" && result.hasOwnProperty("data")) {
            const data2 = result.data;
            const downloadUrls = this.extractHref(data2);
            if (downloadUrls.length >= 2) {
              Tools.openInTab(downloadUrls.at(-2));
            }
          }
        }
        element.classList.remove("download-loadding");
      });
    },
    start: function() {
      return __async$1(this, null, function* () {
        if (!/www\.tiktok\.com/.test(window.location.host)) {
          return;
        }
        GM_addStyle(`
      @keyframes scriptspin {0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}}
      .download-loadding{
        animation: scriptspin 1s linear infinite;
      }
    `);
        setInterval(() => {
          if (!document.querySelector("#tiktok-download-990i")) {
            const container = document.querySelector("#main-content-video_detail") || document.body;
            if (!container) {
              return;
            }
            const divs = container.querySelectorAll("div");
            const regex = /-DivRightControlsWrapper|-DivMiniPlayerContainer/;
            const matchedDiv = Array.from(divs).find((div) => {
              return div.classList.value.split(" ").some((className) => {
                return regex.test(className);
              });
            });
            if (matchedDiv) {
              let cloneNode = null;
              let isDetail = matchedDiv.children.length != 1;
              if (isDetail) {
                cloneNode = matchedDiv.children[0].cloneNode(true);
              } else {
                cloneNode = matchedDiv.cloneNode(true);
              }
              cloneNode.id = "tiktok-download-990i";
              cloneNode.querySelector("div").innerHTML = `<svg t="1724300009050" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5307" width="35" height="35"><path d="M298.666667 554.666667v85.333333H256v128h512v-128h-42.666667v-85.333333h128v213.333333a85.333333 85.333333 0 0 1-78.933333 85.077333L768 853.333333H256a85.333333 85.333333 0 0 1-85.12-78.933333L170.666667 768v-213.333333h128z" fill="#ffffff" p-id="5308"></path><path d="M512 627.498667l219.477333-219.477334h-120.704L512 506.88 413.141333 408.021333H292.522667L512 627.498667z" fill="#ffffff" p-id="5309"></path><path d="M554.666667 528V167.978667h-85.333334v360.021333h85.333334z" fill="#ffffff" p-id="5310"></path></svg>`;
              if (isDetail) {
                matchedDiv.insertBefore(cloneNode, matchedDiv.children[0]);
              } else {
                cloneNode.style.right = 166 + "px";
                matchedDiv.parentNode.insertBefore(cloneNode, matchedDiv);
              }
              cloneNode.title = Commonlanguage.download.tip;
              cloneNode.addEventListener("click", () => {
                Tiktok.download(window.location.href, cloneNode);
              });
            }
          }
        }, 1500);
      });
    }
  };

  var __async = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };
  const YoutubeDownload = {
    markName: `script-download-----iux998htt`,
    isComplete: true,
    download: function(btn) {
      return __async(this, null, function* () {
        try {
          btn.classList.add("download-loadding");
          const downloadUl = yield this.getDownloadUrl(window.location.href.replace("music.youtube.com", "www.youtube.com"));
          window.open(downloadUl, "_blank");
        } catch (ex) {
          Logger.log("error", ex);
        } finally {
          btn.classList.remove("download-loadding");
        }
      });
    },
    getDownloadUrl: function(videoUrl, audioOnly = false) {
      return new Promise((resolve, reject) => {
        resolve("https://cobalt.tools/?url=" + videoUrl);
      });
    },
    elementInContainer: function(container, element) {
      return container.contains(element);
    },
    detectYoutubeService: function() {
      if (window.location.hostname === "www.youtube.com" && window.location.pathname.startsWith("/shorts"))
        return "shorts";
      if (window.location.hostname === "www.youtube.com" && window.location.pathname.startsWith("/watch"))
        return "watch";
      else if (window.location.hostname === "music.youtube.com")
        return "music";
      else if (window.location.hostname === "www.youtube.com")
        return "youtube";
      else
        return null;
    },
    hookNavigationEvents: function() {
      return __async(this, null, function* () {
        ["yt-navigate", "yt-navigate-finish", "yt-navigate-finish", "yt-page-data-updated"].forEach((evName) => {
          if (evName) {
            document.addEventListener(evName, (e) => {
              this.appendDownloadButton(e);
            });
          }
        });
      });
    },
    appendDownloadButton: function(e) {
      return __async(this, null, function* () {
        try {
          this.isComplete = false;
          const ytContainerSelector = "#movie_player > div.ytp-chrome-bottom > div.ytp-chrome-controls > div.ytp-right-controls";
          const ytmContainerSelector = "#layout > ytmusic-player-bar > div.middle-controls.style-scope.ytmusic-player-bar > div.middle-controls-buttons.style-scope.ytmusic-player-bar";
          const img = document.createElement("img");
          img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAepJREFUaEPtmEFygzAMRQ3dsm2mx0kOkfO0OQ+HCL1Np91m29ARtgM0gPUluZ3MmE0miSH//S8Jk8o9+FE9uH5XAP47wZJASUDpQCkhpYHq00sCSxY27ct+/Py6d67u6P3l+DG8Wh5mCXjR369eXDUBuJN78jCfbxYgaoBR+KboJa0nCwgVgBd/PSudVIGIAZp2RyUQSkaJ4JwYQgRgLD7SiyCkAD3P8z5MHW5/1Ad0UsEAgPs3R5v2+ZyYTMGPvrscvw48c8K8QxYD4umyEwCkX7AUoAT+BgBLAQVg1v6QqzCB4SbH1sVeKJj5YgDn+GVkDEBTp3r3fVV3caIE+On2InH/yALAasTkLOf1URYA9rZhFYInft4/qSlpXELx5+4dBMRT+bFvaJkA5pMEHwAZAMhb/h2VVo/zvGl3yPjNM0ZxAA/B20LMKj05CKar2SXkAbYamcQ+DU9b6YMeM1e34vkAtlJA7p7+OotlBYmn60AJJFJg//jaREJNEAEE9yyfxmLFsQ0Q98D0RGyuJ7tCJF6cQJRjBCEWrwbQgfiphT5C/s4SbuK1Yghp0NcbO834jKwXHnWYAcz7I/61OP6tSN9r3V4yLwtAsmUNFxQAQzNFlyoJiGwzPKkkYGim6FIlAZFthic9fAI/mIfoMZ8JBO0AAAAASUVORK5CYII=";
          img.style.width = "44px";
          img.style.height = "44px";
          const markName = this.markName;
          if (document.querySelector("." + markName))
            return;
          const escapeHTMLPolicy = trustedTypes.createPolicy("conardEscapePolicy", {
            createHTML: (string) => string.replace(/\</g, "&lt;")
          });
          const downloadButton = document.createElement("button");
          downloadButton.id = "ytdl-download-button";
          downloadButton.classList.add("ytp-button", markName);
          downloadButton.title = Commonlanguage.download.tip;
          downloadButton.style.borderRadius = "50%";
          downloadButton.appendChild(img);
          switch (this.detectYoutubeService()) {
            case "watch":
              const ytCont = yield Tools.waitForElementByInterval(ytContainerSelector);
              if (this.elementInContainer(ytCont, ytCont.querySelector("#ytdl-download-button"))) {
                break;
              }
              const ytDlBtnClone = downloadButton.cloneNode(true);
              ytDlBtnClone.classList.add("YT");
              ytDlBtnClone.addEventListener("click", () => {
                this.download(ytDlBtnClone);
              });
              ytCont.insertBefore(ytDlBtnClone, ytCont.firstChild);
              break;
            case "shorts":
              if (!document.querySelector("#navigation-button-download-----iux998htt")) {
                const navigationButtonDown = document.querySelector("#navigation-button-down");
                const navigationButtonDownload = navigationButtonDown.cloneNode(false);
                navigationButtonDownload.id = "navigation-button-download-----iux998htt";
                navigationButtonDownload.style.textAlign = "center";
                navigationButtonDownload.appendChild(img);
                document.querySelector(".navigation-container").appendChild(navigationButtonDownload);
                navigationButtonDownload.addEventListener("click", () => {
                  this.download(img);
                });
              }
              break;
            case "music":
              const ytmCont = yield Tools.waitForElementByInterval(ytmContainerSelector);
              if (this.elementInContainer(ytmCont, ytmCont.querySelector("#ytdl-download-button"))) {
                break;
              }
              const ytmDlBtnClone = downloadButton.cloneNode(true);
              ytmDlBtnClone.classList.add("YTM");
              ytmDlBtnClone.addEventListener("click", () => {
                this.download(ytmDlBtnClone);
              });
              ytmCont.insertBefore(ytmDlBtnClone, ytmCont.firstChild);
              break;
            default:
              return;
          }
        } catch (error) {
          Logger.log("error", "youtube download", error);
        } finally {
          this.isComplete = true;
        }
      });
    },
    initStyle: function() {
      GM_addStyle(`
      @keyframes scriptspin {0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}}
      .download-loadding{
        animation: scriptspin 1s linear infinite;
      }
    `);
    },
    asyncAppendDownloadButton: function() {
      let allDelay = 1e3 * 30, delay = 250;
      const interval = setInterval(() => {
        if (document.querySelector("." + this.markName) || allDelay <= 0) {
          clearInterval(interval);
        } else {
          if (this.isComplete)
            this.appendDownloadButton();
        }
        allDelay -= delay;
      }, delay);
    },
    start: function() {
      this.initStyle();
      let currentUrl = null;
      setInterval(() => {
        const visitUrl = window.location.href;
        if (currentUrl !== window.location.href) {
          currentUrl = window.location.href;
          const watch = /www\.youtube\.com\/watch\?v=/.test(visitUrl);
          const shorts = /www\.youtube\.com\/shorts\//.test(visitUrl);
          const music = /music\.youtube\.com\/watch\?v=/.test(visitUrl);
          if (watch || shorts || music) {
            this.hookNavigationEvents();
            this.asyncAppendDownloadButton();
          }
        }
      }, 500);
    }
  };

  const CobaltDownloader = {
    start: function() {
      const params = new URLSearchParams(window.location.search);
      const url = params.get("url");
      if (url) {
        GM_setClipboard(url, "txt", () => {
          Toast.show({ "message": Commonlanguage.download.preparing, "background": "#000", "time": 3e3 });
          setTimeout(() => {
            const buttonPaste = document.querySelector("#button-paste");
            if (buttonPaste) {
              buttonPaste.click();
              document.querySelector("#link-area").value = url;
              const downloadButton = document.querySelector("#download-button");
              if (downloadButton) {
                setTimeout(() => {
                  downloadButton.click();
                }, 2e3);
              }
            }
          }, 2e3);
        });
      }
    }
  };

  const AllModules = {
    CobaltDownloader,
    X,
    Youtube: {
      YoutubeDownload
    },
    Tiktok
  };

  const Init = {
    x: function() {
      AllModules.X.XDownload.init();
      AllModules.X.XSettingsDialog.init();
      const observer = new MutationObserver((ms) => ms.forEach((m) => {
        m.addedNodes.forEach((node) => {
          AllModules.X.XDownload.detect(node);
          AllModules.X.XDateFormat.repldatetime();
          AllModules.X.XOrigimg();
          AllModules.X.XHidepromo();
        });
      }));
      observer.observe(document.body, {
        childList: true,
        subtree: true
      });
    },
    youtube: function() {
      AllModules.Youtube.YoutubeDownload.start();
    },
    tiktok: function() {
      AllModules.Tiktok.start();
    },
    cobalt: function() {
      AllModules.CobaltDownloader.start();
    },
    unknown: function() {
      Logger.log("error", "Hoooo,This method was not found");
    },
    start: function() {
      const otherPlatform = Tools.getOtherPlatform();
      if (otherPlatform) {
        try {
          this[otherPlatform]();
        } catch (e) {
          console.log("error", "Hoooo,catch", e);
        }
      }
    }
  };
  Init.start();

}());