Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++

Ĉ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~

// ==UserScript==
// @name              Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ar           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:bg           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:cs           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:da           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:de           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:el           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:en           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:eo           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:es           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:fi           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:fr           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:fr-CA        Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:he           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:hr           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:hu           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:id           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:it           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ja           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ka           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ko           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:nb           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:nl           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:pl           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:pt-BR        Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ro           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ru           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:sk           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:sr           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:sv           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:th           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:tr           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:uk           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:ug           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @name:vi           Twitter(X)ᴾˡᵘˢ+++ ; Youtubeᴾˡᵘˢ+++
// @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ả~
// @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=
// @namespace         PeterParker_X_Y_NameScope
// @version           1.0.7
// @author            PeterParker
// @include           *://x.com/*
// @include           *://twitter.com/*
// @include           *://mobile.x.com/*
// @include           *://www.youtube.com/watch**
// @include           *://www.youtube.com/shorts**
// @include           *://www.tiktok.com/@*
// @exclude           *://accounts.youtube.com/*
// @exclude           *://www.youtube.com/live_chat_replay*
// @exclude           *://www.youtube.com/persist_identity*
// @exclude           *://x.com/i/flow/*
// @grant             GM_registerMenuCommand
// @grant             GM_openInTab
// @grant             GM.openInTab
// @grant             GM_addStyle
// @grant             GM_setValue
// @grant             GM_getValue
// @grant             GM_xmlhttpRequest
// @grant             GM_download
// @connect           api.cobalt.tools
// @connect           tikdownloader.io
// @license           MIT
// @charset		      UTF-8
// @run-at            document-idle
// ==/UserScript==
(function(){
	'use strict';
	
	/**
	 * Copyright (c) 2024, 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 host = window.location.host;
	const lang = (navigator.language.indexOf("-")!=-1 ? navigator.language.split("-")[0] : navigator.language).toLocaleLowerCase();
 
	const language={
		"zh":{
			"dateFormat":{
				"week":['日', '一', '二', '三', '四', '五', '六']
			},
			"download":{
				"download": '下载', "completed": '下载完成', "tip":"点击下载视频"
				,"preparing":"正在准备下载,请稍后..."
			},
			"menuCommand":{
				"command":"设置", "titleDateFormat":"时间格式设置:","buttonClose":"关闭"
			}
		},
		"en":{
			"dateFormat":{
				"week":['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] 
			},
			"download":{
				"download": 'Download', "completed": 'Download Completed', "tip":"Click to download video"
				,"preparing":"Preparing to download, please wait..."
			},
			"menuCommand":{
				"command":"Settings", "titleDateFormat":"Time format settings:", "buttonClose":"Close"
			}
		},
		"ja":{
			"dateFormat":{
				"week":['日', '月', '火', '水', '木', '金', '土']
			},
			"download":{
				"download": 'ダウンロード', "completed": 'ダウンロード完了',"tip":"クリックしてビデオをダウンロード"
				,"preparing":"ダウンロードの準備をしています。お待ちください..."
			},
			"menuCommand":{
				"command":"設定", "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":"Vous êtes en train de télécharger, veuillez patienter..."
			},
			"menuCommand":{
				"command":"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":"Der Download wird vorbereitet, bitte warten..."
			},
			"menuCommand":{
				"command":"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 al download, attendere..."
			},
			"menuCommand":{
				"command":"impostare", "titleDateFormat":"Impostazioni del formato dell'ora:","buttonClose":"chiusura"
			}
		},
		"ko":{
			"dateFormat":{
				"week":['일', '월', '화', '수', '목', '금', '토']
			},
			"download":{
				"download": '다운로드', "completed": '다운로드 완료',"tip":"비디오를 다운로드하려면 클릭하세요"
				,"preparing":"다운로드 준비 중입니다. 잠시 기다려 주세요..."
			},
			"menuCommand":{
				"command":"설정", "titleDateFormat":"시간 형식 설정:","buttonClose":"폐쇄"
			}
		},
		"ru":{
			"dateFormat":{
				"week":['ВС', 'ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ']
			},
			"download":{
				"download": 'скачать', "completed": 'Загрузка завершена',"tip":"Нажмите, чтобы скачать видео"
				,"preparing":"Подготовка к загрузке, пожалуйста, подождите..."
			},
			"menuCommand":{
				"command":"настраивать", "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":"Preparando o download, aguarde..."
			},
			"menuCommand":{
				"command":"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 descargar, espere..."
			},
			"menuCommand":{
				"command":"configuración", "titleDateFormat":"Configuración de formato de hora:","buttonClose":"cierre"
			}
		}
	}
	
	const selectLanguage=()=>{
		return language[lang] ?? language["en"];
	}
		
	const Toast={
		initStyle:function(){
			GM_addStyle(`
				@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;
				}
			`);
		},
		show:function(params){
			let time = params.time;
			let background = params.background;
			let color = params.color;
			let position = params.position;  //center-top, center-bottom
			let defaultMarginValue = 50;
			if(time == undefined || time == ''){
				time = 1500;
			}
			if(position==undefined || position==''){
				position = "center-bottom";
			}
			
			const el = document.createElement("div");
			if(background!=undefined && background!=''){
				el.style.backgroundColor=background;
			}
			if(color!=undefined && 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);
			el.classList.add("fadeIn");
			
			setTimeout(function () {
				el.classList.remove("fadeIn");
				el.classList.add("fadeOut");
				el.addEventListener("animationend", function () {
					document.body.removeChild(el);
				});
				el.addEventListener("webkitAnimationEnd", function () {
					document.body.removeChild(el);
				});
			}, time);
		}
	}
	
	/**
	 *  Variable & Constant
	 */
	const FMT = 7; // 70/12/31(Th) 23:59
	let fmt = FMT;
	
	/**
	 * script value init
	 */
	const ScriptValue={
		init:function(){
			Toast.initStyle();
			fmt = GM_getValue("fmt", FMT);
		}
	}
		
	const SettingsDialog={
		number:Math.ceil(Math.random()*100000000),
		formats:[
			"Do nothing",
			"31.12.70 23:59",
			"31.12.70 23:59:59",
			"31.12.70(Th) 23:59",
			"31.12.70(Th) 23:59:59",
			"70/12/31 23:59",
			"70/12/31 23:59:59",
			"70/12/31(Th) 23:59",
			"70/12/31(Th) 23:59:59 [ye/mo/da(we) ho:mi:se]",
			"70-12/31 23:59",
			"70-12/31 23:59'59",
			"70-12/31(Th) 23:59",
			"70-12/31(Th) 23:59'59",
			"M59-12-31 23:59",
			"M59-12-31 23:59:59",
			"M59-12-31(Th) 23:59",
			"M59-12-31(Th) 23:59:59"
		],
		make:function(){
			let dialog = document.createElement('div');
			dialog.className = 'dialog_u_'+this.number;
			dialog.style.all = 'initial';
			dialog.style.backgroundColor = 'rgb(235, 235, 235)';
			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 border="0" style="width:100%;padding:5px;">`;
			for(var i=1; i<=this.formats.length;i++){
				if(i%2!=0){
					formatsHtml += `<tr style="width:100%;">`;
				}
				formatsHtml += `<td width="50"><input type="radio" name="fmt" value="`+(i-1)+`" class="top_r" />`+(i+"."+this.formats[i-1])+`</td>`;
				if(i%2==0){
					formatsHtml += `</tr>`;
				}
			}
			formatsHtml += `</table>`;
			
			let html=`
				<div style="font-size:15px;font-weight:bold;margin-bottom:5px;">`+selectLanguage().menuCommand.titleDateFormat+`</div>
				<div>`+formatsHtml+`</div>
				<div style="margin-top:15px;text-align:center;">
					<button name="closex">`+selectLanguage().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(selectLanguage().menuCommand.command, function () {
				if (dialog.style.display == 'none') {
					dialog.querySelector('input[name="fmt"][value="' + fmt + '"]').checked = true;
					dialog.style.display = 'block';
				}
			});
		}
	}
	
	const Tools = {
		platform:function(){
			const isX = /twitter|x\.com$/.test(host);
			const isAliexpress = /([a-zA-Z0-9]+\.)?aliexpress\.[a-zA-Z]+/.test(host);
			const isYoutube = /youtube\.com$/.test(host);
			const isAmazon = /www\.amazon\.com$/.test(host);
			const isEbay = /www\.ebay\.[a-zA-Z]+/.test(host);
			const isTiktok = /www\.tiktok\.com/.test(host);

			if(isX) return "x";
			if(isAliexpress) return "aliexpress";
			if(isYoutube) return "youtube";
			if(isAmazon) return "amazon";
			if(isEbay) return "ebay";
			if(isTiktok) return "tiktok";
			return "unknown";
		},
		waitForElementByInterval: function(selector, target=document.body, allowEmpty = true, delay=10, maxDelay=10 * 1000){
			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()*100000000);
		},
		elementInContainer:function(container, element) {
		    return container.contains(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(mothed, url, param, headers={"Content-Type": "application/json;charset=UTF-8"}){
			return new Promise(function(resolve, reject){
				GM_xmlhttpRequest({
					url: url,
					method: mothed,
					data:param,
					headers:headers,
					onload: function(response) {
						const status = response.status;
						if(status==200 || status=='200'){
							var responseText = response.responseText;
							resolve({"code":"success", "result":responseText});
						}else{
							resolve({"code":"error", "result":null});
						}
					},
					onabort:function(){
						resolve({"code":"error", "result":null});
					},
					onerror:function(){
						resolve({"code":"error", "result":null});
					}
				});
			})
		}
	}
	
	/**
	 * The code here is referenced from:
	 * https://qiita.com/libraplanet/items/0bdd7ef1a13e7af8f48f
	 * https://greasyfork.org/zh-CN/scripts/462064-show-date-normally-on-twitter
	 * 
	 * Optimization was made based on the source code and some bugs were modified.
	 * Include Fun XDateFormat、XOrigimg,XHidepromo
	 * 
	 * Author:@PeterParker & @AeamaN & @libraplanet
	 */
	const XDateFormat = {
		df:function(date, f){
			const WEEK = selectLanguage().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, // 0=1
				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,
				'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,
				YE+'/'+MO+'/'+DA+'('+WE+') '+HO+':'+MI+':'+SE
			];
			return F[f - 1] ?? F[16];
		},
		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]'; // DM list
			document.querySelectorAll(SEL + ', ' + SEL_2 + ', ' + SEL_3 + ', ' + SEL_4 + ', ' + SEL_5).forEach((e)=>{
				const SEL_ADD = 'span.us-' + MYNAME;
				let d = e.getAttribute('datetime');
				let df = this.df(new Date(d), fmt);
				
				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;
				}
			})
		}
	}
	
	/**
	 * Display the original size of the picture, which is clearer, but also consumes more traffic.
	 */
	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+)([")]*)$/;
			let ss; // Temp.
			
			if (/div/i.test(e.tagName)) {
				let r = regex.exec(e.style.backgroundImage);
				if (r && r[4] != 'orig') {
					e.style.backgroundImage = r[1] + r[2] + r[3] + 'orig' + r[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;
			}
		}
	}
	
	/**
	 * Hide promotional posts
	 */
	const XHidepromo=()=>{
		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'; // def-ja, def-en, ble-ja, ble-en
		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';
		// Lone label def-ja, def-en, ble-ja, ble-en
		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 ' // Add your language
		};
		const PROMO_L = PROMO[lang] ?? 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' // Add your language
		};
		const PROMO_L_2 = PROMO_2[lang] ?? PROMO_2['en'];
		
		let ss; // Temp.
		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'); // def-ja, def-en, ble-ja, ble-en
			if (!xpe) xpe = e.closest('div.css-175oi2r.r-1ny4l3l[data-testid="UserCell"]'); // def-ja, def-en, ?, ble-en
			if (xpe) xpe.style.setProperty('display', 'none'); // Right column のおすすめユーザー'
		}
		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');
		}
	}
	
	/**
	 * The code here is referenced from:
	 * https://github.com/ne0lith/random-userscripts/blob/main/twitter-media-downloader.user.js
	 * 
	 * The code adopts the MIT open source license. Please note that it is appreciated!
	 * Author:@PeterParker & @ne0lith
	 */
	const XDownload={
		history:[],
		show_sensitive:true,
		is_tweetdeck:host.indexOf('tweetdeck') >= 0,
		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>
		`,
		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"]', //hidden content
				'div.media-image-container', // for tweetdeck
				'div.media-preview-container', // for tweetdeck
				'div[aria-labelledby]>div:first-child>div[role="button"][tabindex="0"]' //for audio (experimental)
			];
			
			const media = article.querySelector(media_selector.join(','));
			if(media){
				let status_id = 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.is_tweetdeck) {
					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_id) >= 0;
				this.status(btn_down, 'tmd-down');
				this.status(btn_down, is_exist ? 'completed': 'download', is_exist ? selectLanguage().download.completed: selectLanguage().download.download);
				btn_group.insertBefore(btn_down, btn_share.nextSibling);
				btn_down.onclick = () =>{
					this.click(btn_down, status_id, 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_id = article.querySelector('a[href*="/status/"]').href.split('/status/').pop().split('/').shift();
				let btn_group = article.querySelector('div[role="group"]:last-of-type');
				let btn_share = 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_id) >= 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_id, is_exist, index);
					}
				});
			}
		},
		addButtonToMedia: function(listitems) {
			listitems.forEach(li =>{
				if (li.dataset.detected) return;
				li.dataset.detected = 'true';
				let status_id = li.querySelector('a[href*="/status/"]').href.split('/status/').pop().split('/').shift();
				let is_exist = this.history.indexOf(status_id) >= 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-media');
				this.status(btn_down, is_exist ? 'completed': 'download', is_exist ? selectLanguage().download.completed: selectLanguage().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:async function(status_id){
			const base_url = `https://${host}/i/api/graphql/NmCeCgkVlsRGS1cAwqtgmw/TweetDetail`;
			const variables = {
				"focalTweetId":status_id,
				"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 = await fetch(url, {headers: 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_id}`);
			let tweet_result = tweet_entrie.content.itemContent.tweet_results.result;
			return tweet_result.tweet || tweet_result;
		},
		click:async function(btn, status_id, is_exist, index){
			if (btn.classList.contains('loading')) return;
			this.status(btn, 'loading');
			let save_history = await GM_getValue('save_history', true);
			let json = await this.fetchJson(status_id);
			let tweet = json.legacy;
			let user = json.core.user_results.result.legacy;
			let invalid_chars = {
				'\\': '\',
				'\/': '/',
				'\|': '|',
				'<': '<',
				'>': '>',
				':': ':',
				'*': '*',
				'?': '?',
				'"': '"',
				'\u200b': '',
				'\u200c': '',
				'\u200d': '',
				'\u2060': '',
				'\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_id;
			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 == undefined){
				medias = JSON.parse(json.card.legacy.binding_values[0].value.string_value).media_entities;
				medias = Object.values(medias);
			}
			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) + ': ' : '') + selectLanguage().download.completed);
							this.status(btn, null, tasks_result.sort().join('\n'));
							if (tasks === 0) {
								this.status(btn, 'completed', selectLanguage().download.completed);
								if (save_history && !is_exist) {
									this.history.push(status_id);
								}
							}
						},
						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: async function () {
				let task = tasks.shift();
				await 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>');
		}
	}
	
	/**
	 * youtube function plus
	 * Author:@PeterParker
	 */
	const YoutubeDownload={
		markName:`script-download-----iux998htt`,
		isComplete:true,
		download:async function(btn){
			try{
				Toast.show({"message":selectLanguage().download.preparing, "background":"#000"});
				btn.classList.add("download-loadding");
				
				const downloadUl = await this.getDownloadUrl(window.location.href.replace('music.youtube.com', 'www.youtube.com') );
				window.open(downloadUl,'_blank');
			}
			catch(ex){
				logger("error", ex);
			}
			finally{
				btn.classList.remove("download-loadding");
			}
		},
		getDownloadUrl:function(videoUrl, audioOnly = false) {
			return new Promise((resolve, reject) => {
				// https://github.com/imputnet/cobalt/blob/current/docs/api.md
				GM_xmlhttpRequest({
					method: 'POST',
					url: 'https://api.cobalt.tools/api/json',
					headers: {
						'Cache-Control': 'no-cache',
						Accept: 'application/json',
						'Content-Type': 'application/json',
					},
					data: JSON.stringify({
						url: encodeURI(videoUrl),
						vQuality:  'max',
						filenamePattern: 'basic', // file name = video title
						isAudioOnly: audioOnly,
						disableMetadata: true, // privacy
					}),
					onload: (response) => {
						const data = JSON.parse(response.responseText);
						if (data?.url) resolve(data.url);
						else reject(data);
					},
					onerror: (err) => reject(err),
				});
			});
		},
		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:async 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:async function(e){
			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 = selectLanguage().download.tip;
				downloadButton.style.borderRadius="50%";
				downloadButton.appendChild(img);
				switch (this.detectYoutubeService()) {
					case 'watch':
						const ytCont = await 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 = await 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("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 = 1000*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);
		}
	}
	
	/**
	 * Tiktok download no watermark video
	 */
	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:async function(url, element){
			Toast.show({"message":selectLanguage().download.preparing, "background":"#000"});
			element.classList.add("download-loadding");
			const data = await 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 data = result.data;
					const downloadUrls = this.extractHref(data);
					if(downloadUrls.length>=2){
						Tools.openInTab(downloadUrls.at(-2));
					}
				}
			}
			element.classList.remove("download-loadding");
		},
		start:async 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 = selectLanguage().download.tip;
						cloneNode.addEventListener("click",()=>{
							Tiktok.download(window.location.href,cloneNode);
						});
					}
				}
			}, 2000);
		}
	}
	
	const Init = {
		x:function(){
			XDownload.init();
			SettingsDialog.init();
			
			const observer = new MutationObserver(ms => ms.forEach(m =>{
				m.addedNodes.forEach(node =>{
					XDownload.detect(node); //download
					XDateFormat.repldatetime(); //date formats
					XOrigimg(); //Pictures are automatically the highest resolution
					XHidepromo(); //hide AD.
				});
			}));
			observer.observe(document.body, {
				childList: true,
				subtree: true
			});
		},
		youtube:function(){
			YoutubeDownload.start();
		},
		tiktok:function(){
			Tiktok.start();
		},
		unknown:function(){
			console.log("Hoooo,This method was not found");
		},
		start:function(){
			ScriptValue.init();
			const platform = Tools.platform();
			this[platform]();
		}
	}
	
	Init.start();
})();