NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==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ả~ // @namespace PeterParker_X_Y_NameScope // @version 1.1.7 // @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:\/\/((ko|fr|es|ja|pt|it|th|ar|tr|de|he|nl|pl|www|best)+\.)?aliexpress\.(ru|us|com)\/*/ // @include /^https:\/\/(www\.)?lazada\.(co\.id|vn|com\.my|co\.th|sg|com\.ph)/.*/ // @include *://www.ebay.*/* // @include *://www.bestbuy.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 // @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, 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 commonLanguage = { "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 ecommerceLanguage = { "zh": { "operat": { "copied": "Ohhhh!已复制!" }, "dialog": { "title": "设置", "contentPieceMax": "最大浏览记录数(最小: {min},最大:{max},改变的值自动保存):", "contentPieceClear": "清除所有浏览历史记录。注意:清除后历史记录不可恢复,请谨慎操作。", "contentPieceClearBtn": "清除", "clearConfirmContent": "是否要清除所有浏览记录?一旦被清除,将无法恢复~" }, "historyToolbar": { "boxTitle": "浏览记录", "expandTipText": "记录" }, "menuCommand": { "settings": "设置", "buttonClose": "关闭", "goodsHistories": { "clear": "清空所有商品浏览记录" } } }, "en": { "operat": { "copied": "Ohhhh, Copied!" }, "dialog": { "title": "Ohhhh! I'm settings", "contentPieceMax": "Maximum number of browsing histories(min:{min}, max:{max}, Changed values are automatically saved):", "contentPieceClear": "Clear all browsing history. Note: The history cannot be restored after clearing. Please operate with caution.", "contentPieceClearBtn": "Clear", "clearConfirmContent": "Do you want to clear all browsing history? Once cleared, it cannot be restored" }, "historyToolbar": { "boxTitle": "Browsing history", "expandTipText": "History" }, "menuCommand": { "settings": "Settings", "buttonClose": "Close", "goodsHistories": { "clear": "Clear all product browsing history" } } }, "ja": { "operat": { "copied": "Ohhhh, コピーされました" }, "dialog": { "title": "設定", "contentPieceMax": "閲覧レコードの最大数(最小値:{min}、最大値:{max}、変更された値は自動的に保存されます):", "contentPieceClear": "すべての閲覧履歴を消去します。 ※クリア後の履歴は元に戻せませんので、慎重に操作してください。", "contentPieceClearBtn": "クリア", "clearConfirmContent": "すべての閲覧履歴を消去しますか?一度クリアすると元に戻せませんよ~" }, "historyToolbar": { "boxTitle": "閲覧履歴", "expandTipText": "記録" }, "menuCommand": { "settings": "設定", "buttonClose": "閉鎖", "goodsHistories": { "clear": "製品の閲覧履歴をすべて消去する" } } }, "fr": { "operat": { "copied": "Ohhhh, Copié!" }, "dialog": { "title": "installation", "contentPieceMax": "Nombre maximum d'enregistrements de navigation (minimum : {min}, maximum : {max}, les valeurs modifiées sont automatiquement enregistrées) :", "contentPieceClear": "Effacez tout l’historique de navigation. Remarque : L'historique ne peut pas être récupéré après l'effacement, veuillez agir avec prudence.", "contentPieceClearBtn": "Clair", "clearConfirmContent": "Voulez-vous effacer tout l’historique de navigation ? Une fois effacé, il ne peut pas être restauré ~" }, "historyToolbar": { "boxTitle": "Historique de navigation", "expandTipText": "Enregistrer" }, "menuCommand": { "settings": "installation", "buttonClose": "fermeture", "goodsHistories": { "clear": "Effacer tout l'historique de navigation des produits" } } }, "de": { "operat": { "copied": "Ohhhh, Kopiert!" }, "dialog": { "title": "aufstellen", "contentPieceMax": "Maximale Anzahl an Browsing-Datensätzen (Minimum: {min}, Maximum: {max}, geänderte Werte werden automatisch gespeichert):", "contentPieceClear": "Löschen Sie den gesamten Browserverlauf. Hinweis: Der Verlauf kann nach dem Löschen nicht wiederhergestellt werden. Bitte gehen Sie vorsichtig vor.", "contentPieceClearBtn": "Klar", "clearConfirmContent": "Möchten Sie den gesamten Browserverlauf löschen? Nach dem Löschen kann es nicht wiederhergestellt werden~" }, "historyToolbar": { "boxTitle": "Browser-Verlauf", "expandTipText": "Aufzeichnen" }, "menuCommand": { "settings": "aufstellen", "buttonClose": "Schließung", "goodsHistories": { "clear": "Löschen Sie den gesamten Browserverlauf des Produkts" } } }, "it": { "operat": { "copied": "Ohhhh, Copiato!" }, "dialog": { "title": "impostare", "contentPieceMax": "Numero massimo di record di navigazione (minimo: {min}, massimo: {max}, i valori modificati vengono salvati automaticamente):", "contentPieceClear": "Cancella tutta la cronologia di navigazione. Nota: la cronologia non può essere recuperata dopo la cancellazione, si prega di operare con cautela.", "contentPieceClearBtn": "Chiaro", "clearConfirmContent": "Vuoi cancellare tutta la cronologia di navigazione? Una volta cancellato, non può essere ripristinato~" }, "historyToolbar": { "boxTitle": "Cronologia di navigazione", "expandTipText": "Documentazione" }, "menuCommand": { "settings": "impostare", "buttonClose": "chiusura", "goodsHistories": { "clear": "Cancella tutta la cronologia di navigazione del prodotto" } } }, "ko": { "operat": { "copied": "Ohhhh, 복사됨!" }, "dialog": { "title": "설정", "contentPieceMax": "최대 검색 기록 수(최소: {min}, 최대: {max}, 변경된 값은 자동으로 저장됩니다):", "contentPieceClear": "모든 검색 기록을 지웁니다. 참고: 삭제 후에는 기록을 복구할 수 없으므로 주의해서 조작하시기 바랍니다.", "contentPieceClearBtn": "분명한", "clearConfirmContent": "모든 검색 기록을 삭제하시겠습니까? 한번 삭제하면 복원이 불가능해요~" }, "historyToolbar": { "boxTitle": "검색 기록", "expandTipText": "기록" }, "menuCommand": { "settings": "설정", "buttonClose": "폐쇄", "goodsHistories": { "clear": "모든 제품 검색 기록 지우기" } } }, "ru": { "operat": { "copied": "Ohhhh, Скопировано!" }, "dialog": { "title": "настраивать", "contentPieceMax": "Максимальное количество записей просмотра (минимум: {min}, максимум: {max}, измененные значения сохраняются автоматически):", "contentPieceClear": "Очистить всю историю просмотров. Примечание. После очистки историю невозможно восстановить, действуйте осторожно.", "contentPieceClearBtn": "Прозрачный", "clearConfirmContent": "Хотите очистить всю историю просмотров? После очистки его невозможно восстановить~" }, "historyToolbar": { "boxTitle": "История браузера", "expandTipText": "Записывать" }, "menuCommand": { "settings": "настраивать", "buttonClose": "закрытие", "goodsHistories": { "clear": "Очистить всю историю просмотра товаров" } } }, "pt": { "operat": { "copied": "Ohhhh, Copiado!" }, "dialog": { "title": "configurar", "contentPieceMax": "Número máximo de registos de navegação (mínimo: {min}, máximo: {max}, os valores alterados são guardados automaticamente):", "contentPieceClear": "Limpe todo o histórico de navegação. Nota: O histórico não pode ser recuperado após a limpeza, opere com cuidado.", "contentPieceClearBtn": "Claro", "clearConfirmContent": "Quer limpar todo o histórico de navegação? Uma vez limpo, não pode ser restaurado ~" }, "historyToolbar": { "boxTitle": "Histórico de navegação", "expandTipText": "Registo" }, "menuCommand": { "settings": "configuración", "buttonClose": "cierre", "goodsHistories": { "clear": "Quer limpar todo o histórico de navegação do produto? Uma vez limpo, não será recuperável" } } }, "es": { "operat": { "copied": "Ohhhh, Copiado!" }, "dialog": { "title": "configuración", "contentPieceMax": "Número máximo de registros de navegación (mínimo: {min}, máximo: {max}, los valores modificados se guardan automáticamente):", "contentPieceClear": "Borrar todo el historial de navegación. Nota: El historial no se puede recuperar después de borrarlo; opere con precaución.", "contentPieceClearBtn": "Claro", "clearConfirmContent": "¿Quieres borrar todo el historial de navegación? Una vez borrado, no se puede restaurar ~" }, "historyToolbar": { "boxTitle": "Historial de navegación", "expandTipText": "Registro" }, "menuCommand": { "settings": "configuración", "buttonClose": "cierre", "goodsHistories": { "clear": "Borrar todo el historial de navegación de productos" } } }, "th": { "operat": { "copied": "Ohhhh!โอ้! คัดลอก!" }, "dialog": { "title": "ตั้งค่า", "contentPieceMax": "จำนวนบันทึกการสืบค้นสูงสุด (ขั้นต่ำ: {min}, สูงสุด: {max}, ค่าที่เปลี่ยนแปลงจะถูกบันทึกโดยอัตโนมัติ):", "contentPieceClear": "ล้างประวัติการเข้าชมทั้งหมด หมายเหตุ: ไม่สามารถกู้คืนประวัติได้หลังจากเคลียร์แล้ว โปรดดำเนินการด้วยความระมัดระวัง", "contentPieceClearBtn": "ชัดเจน", "clearConfirmContent": "คุณต้องการล้างประวัติการเข้าชมทั้งหมดหรือไม่? เมื่อเคลียร์แล้วจะไม่สามารถกู้คืนได้~" }, "historyToolbar": { "boxTitle": "ประวัติการเรียกดู", "expandTipText": "บันทึก" }, "menuCommand": { "settings": "ตั้งค่า", "buttonClose": "ปิด", "goodsHistories": { "clear": "ล้างประวัติการเรียกดูผลิตภัณฑ์ทั้งหมด" } } }, "tr": { "operat": { "copied": "Ohhhh,Kopyalandı!" }, "dialog": { "title": "kurmak", "contentPieceMax": "Maksimum tarama kaydı sayısı (minimum: {min}, maksimum: {max}, değiştirilen değerler otomatik olarak kaydedilir):", "contentPieceClear": "Tüm tarama geçmişini temizleyin. Not: Geçmiş temizlendikten sonra kurtarılamaz, lütfen dikkatli çalışın.", "contentPieceClearBtn": "Temizlemek", "clearConfirmContent": "Tüm tarama geçmişini temizlemek istiyor musunuz? Bir kez temizlendiğinde geri yüklenemez~" }, "historyToolbar": { "boxTitle": "Tarama geçmişi", "expandTipText": "Kayıt" }, "menuCommand": { "settings": "kurmak", "buttonClose": "kapatma", "goodsHistories": { "clear": "Tüm ürün tarama geçmişini temizle" } } }, "nl": { "operat": { "copied": "Ohhhh, Gekopieerd!" }, "dialog": { "title": "opgezet", "contentPieceMax": "Maximaal aantal browserecords (minimaal: {min}, maximaal: {max}, gewijzigde waarden worden automatisch opgeslagen):", "contentPieceClear": "Wis alle browsegeschiedenis. Opmerking: de geschiedenis kan na het wissen niet worden hersteld. Wees voorzichtig.", "contentPieceClearBtn": "Duidelijk", "clearConfirmContent": "Wilt u de hele browsegeschiedenis wissen? Eenmaal gewist, kan het niet meer worden hersteld~" }, "historyToolbar": { "boxTitle": "Geschiedenis doorbladeren", "expandTipText": "Dossier" }, "menuCommand": { "settings": "opgezet", "buttonClose": "sluiting", "goodsHistories": { "clear": "Wis de volledige browsegeschiedenis van producten" } } } }; var _a, _b; const isDev = false, isDebug = false; const currentHost = window.location.host; const currentUrl = window.location.href; const lang = (navigator.language.indexOf("-") != -1 ? navigator.language.split("-")[0] : navigator.language).toLocaleLowerCase(); const ScriptConst = { "lang": lang, "isDev": isDev, "isDebug": isDebug, "currentHost": currentHost, "currentUrl": currentUrl }; const language = (_a = commonLanguage[lang]) != null ? _a : commonLanguage["en"]; const eLanguage = (_b = ecommerceLanguage[lang]) != null ? _b : ecommerceLanguage["en"]; var __async$b = (__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 = (level = "log", ...messages) => { { return; } }; const Tools = { decryptStr: function(str) { let result = atob(str); return result.split("").reverse().join(""); }, encryptStr: function(str) { let result = str.split("").reverse().join(""); return btoa(result); }, platform: function() { let platform = "unknown"; const currentHost = window.location.host; if (/twitter|x\.com$/.test(currentHost)) { platform = "x"; } else if (/aliexpress/.test(currentHost)) { platform = "aliexpress"; } else if (/youtube\.com$/.test(currentHost)) { platform = "youtube"; } else if (/www\.amazon\.com$/.test(currentHost)) { platform = "amazon"; } else if (/www\.ebay\./.test(currentHost)) { platform = "ebay"; } else if (/www\.lazada\./.test(currentHost)) { platform = "lazada"; } else if (/www\.tiktok\.com/.test(currentHost)) { platform = "tiktok"; } else if (/cobalt\.tools/.test(currentHost)) { platform = "cobalt"; } else if (/www\.bestbuy\./.test(currentHost)) { platform = "bestbuy"; } return platform; }, removeAliexpressAnchors: 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.removeAliexpressAnchors(node.childNodes[i]); } } }, 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, method: mothed, data: param, 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 }); } }); }); }, crossRequest: function(method, url, param) { if (!method) { method = "get"; } if (!url) { return new Promise(function(resolve, reject) { reject({ "code": "error", "result": null }); }); } if (!param) { param = {}; } method = method.toUpperCase(); let config = { method }; if (method === "POST") { config.headers["Content-Type"] = "application/json"; config.body = JSON.stringify(param); } return new Promise(function(resolve, reject) { fetch(url, config).then((response) => response.text()).then((text) => { resolve({ "code": "success", "result": text }); }).catch((error) => { reject({ "code": "error", "result": null }); }); }); }, 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$b(this, null, function* () { const getElements = (handler2) => __async$b(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(); } } }; 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; let defaultMarginValue = 50; if (time == void 0 || time == "") { time = 1500; } if (position == void 0 || position == "") { position = "center-bottom"; } 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); 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); } }; var __async$a = (__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;">` + language.menuCommand.titleDateFormat + `</div> <div>` + formatsHtml + `</div> <div style="margin-top:15px;text-align:center;"> <button name="closex">` + language.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(language.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 = language.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+)(&|&)(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 ? language.download.completed : language.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) { } 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 ? language.download.completed : language.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$a(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$a(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) + ": " : "") + language.download.completed); this.status(btn, null, tasks_result.sort().join("\n")); if (tasks === 0) { this.status(btn, "completed", language.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$a(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$9 = (__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$9(this, null, function* () { Toast.show({ "message": language.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$9(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 = language.download.tip; cloneNode.addEventListener("click", () => { Tiktok.download(window.location.href, cloneNode); }); } } }, 1500); }); } }; const dialog = function() { class Dialog { constructor() { this.mask = document.createElement("div"); this.dialogStyle = document.createElement("style"); this.setStyle(this.mask, { "width": "100%", "height": "100%", "backgroundColor": "rgba(0, 0, 0, .6)", "position": "fixed", "left": "0px", "top": "0px", "bottom": "0px", "right": "0px", "z-index": "9999999999999" }); this.content = document.createElement("div"); this.setStyle(this.content, { "max-width": "450px", "width": "100%", "max-height": "600px", "backgroundColor": "#fff", "boxShadow": "0 0 2px #999", "position": "absolute", "left": "50%", "top": "50%", "transform": "translate(-50%,-50%)", "borderRadius": "5px" }); this.mask.appendChild(this.content); } middleBox(param) { this.content.innerHTML = ""; let title = ""; if ({}.toString.call(param) === "[object String]") { title = param; } else if ({}.toString.call(param) === "[object Object]") { title = param.title; } document.body.appendChild(this.mask); this.title = document.createElement("div"); this.setStyle(this.title, { "width": "100%", "height": "40px", "lineHeight": "40px", "boxSizing": "border-box", "background-color": "#dedede", "color": "#000", "text-align": "center", "font-weight": "700", "font-size": "17px", "border-radius": "4px 4px 0px 0px" }); this.title.innerText = title; this.content.appendChild(this.title); this.closeBtn = document.createElement("div"); this.closeBtn.innerText = "×"; this.setStyle(this.closeBtn, { "textDecoration": "none", "color": "#000", "position": "absolute", "right": "10px", "top": "0px", "fontSize": "25px", "display": "inline-block", "cursor": "pointer" }); this.title.appendChild(this.closeBtn); this.closeBtn.onclick = () => this.close(); } showMake(param) { if (param.hasOwnProperty("styleSheet")) { this.dialogStyle.textContent = param.styleSheet; } document.querySelector("head").appendChild(this.dialogStyle); this.middleBox(param); this.dialogContent = document.createElement("div"); this.setStyle(this.dialogContent, { "padding": "15px", "max-height": "400px" }); this.dialogContent.innerHTML = param.content; this.content.appendChild(this.dialogContent); param.onContentReady(this); } close() { document.body.removeChild(this.mask); document.querySelector("head").removeChild(this.dialogStyle); } setStyle(ele, styleObj) { for (let attr in styleObj) { ele.style[attr] = styleObj[attr]; } } } let dialog2 = null; return function() { if (!dialog2) { dialog2 = new Dialog(); } return dialog2; }(); }(); const GoodsHistroy = { storageKeys: { goodsHistory: "goooods_history_key", offset: "goooods_wrapper_key", maximumRecordsKey: "goooods_max_records_key" }, defaultValue: { historyStorage: { "aliexpress": [], "amazon": [], "shein": [], "shopee": [], "lazada": [], "ebay": [], "bestbuy": [] }, offsetWrapper: { right: 10, bottom: 0 }, records: { min: 10, max: 500, default: 100 }, toolbarGoodsNum: 4 }, push: function(platform, obj) { var _a; try { const storageObj = GM_getValue(this.storageKeys.goodsHistory, this.defaultValue.historyStorage); const maximumRecords = GM_getValue(this.storageKeys.maximumRecordsKey, this.defaultValue.records.default); const histories = (_a = storageObj[platform]) != null ? _a : []; if (histories.length >= maximumRecords) { histories.splice(0, parseInt(maximumRecords / 5)); } const newArr = histories.filter((item, index) => item.id != obj.id); newArr.push(obj); storageObj[platform] = newArr; GM_setValue(this.storageKeys.goodsHistory, storageObj); } catch (e) { } }, get: function(platform, num = -1) { var _a; const storageObj = GM_getValue(this.storageKeys.goodsHistory, this.defaultValue.historyStorage); const histories = (_a = storageObj[platform]) != null ? _a : []; if (num > 0) { const showHistories = []; for (let i = histories.length - 1; i >= 0; i--) { if (showHistories.length >= num) break; showHistories.push(histories[i]); } return showHistories; } return histories; }, remove: function(platform, id) { const storageObj = GM_getValue(this.storageKeys.goodsHistory, this.defaultValue.historyStorage); const histories = storageObj[platform]; let newArr = histories.filter((item, index) => item.id != id); storageObj[platform] = newArr; GM_setValue(this.storageKeys.goodsHistory, storageObj); }, removeAll: function() { GM_setValue(this.storageKeys.goodsHistory, this.defaultValue.historyStorage); document.querySelector(".peter99032j-xyz-panel-aside-body .goods_____review").innerHTML = ""; document.querySelector(".peter99032j-xyz-panel-aside-main .panel-aside-main_____content").innerHTML = ""; }, removeAllConfirm: function() { if (confirm(eLanguage.dialog.clearConfirmContent)) { this.removeAll(); } }, registerMenuCommand: function() { GM_registerMenuCommand(eLanguage.menuCommand.settings, () => { this.showSettingDialog(); }); }, getGoodsByDateGroup: function(platform) { const histories = this.get(platform).reverse(); const group = []; const today = new Date(); const yesterday = new Date(today); const format = "dd/MM"; yesterday.setDate(today.getDate() - 1); const todayStr = this.dateFormat(today, format); const yesterdayStr = this.dateFormat(yesterday, format); const showDateFormat = (todayStr2, yesterdayStr2, current) => { return current === todayStr2 ? "Today" : current === yesterdayStr2 ? "Yesterday" : current; }; let items = [], cacheDateStr = null, currentDateStr = null; for (let i = 0; i < histories.length; i++) { today.setTime(histories[i].date); currentDateStr = this.dateFormat(today, format); if (!!cacheDateStr) { if (cacheDateStr != currentDateStr) { group.push({ "str": showDateFormat(todayStr, yesterdayStr, cacheDateStr), "items": items }); items = []; cacheDateStr = currentDateStr; } } else { cacheDateStr = currentDateStr; } items.push(histories[i]); } if (items.length != 0) { group.push({ "str": showDateFormat(todayStr, yesterdayStr, cacheDateStr), "items": items }); } return group; }, dateFormat: function(date, format) { var showDate = { "M+": date.getMonth() + 1, "d+": date.getDate(), "h+": date.getHours(), "m+": date.getMinutes(), "s+": date.getSeconds(), "q+": Math.floor((date.getMonth() + 3) / 3), "S+": date.getMilliseconds() }; if (/(y+)/i.test(format)) { format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); } for (var k in showDate) { if (new RegExp("(" + k + ")").test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? showDate[k] : ("00" + showDate[k]).substr(("" + showDate[k]).length)); } } return format; }, showSettingDialog: function() { const outerId = "dialog_x_" + Tools.randomNumber(); const self = this; const { min, max } = this.defaultValue.records; const maximumRecords = GM_getValue(this.storageKeys.maximumRecordsKey, this.defaultValue.records.default); const styleSheet = ` #` + outerId + `{ padding:15px; } #` + outerId + ` .d_____piece{ margin-bottom:15px; font-size:15px; } #` + outerId + ` .d_____input{ padding: 5px 10px !important; background-color: #fafafa !important; color: #000 !important; border: 1px solid #ccc !important; font-size: 14px !important; border-radius: 4px !important; width: 80px !important; text-align: center !important; } #` + outerId + ` .d_____btn{ padding: 3px 10px !important; background-color: #edf2fa !important; color: #000 !important; border-radius: 4px!important; font-size: 14px!important; } #` + outerId + ` .d_____btn:hover{ background-color: #cdd1da !important; } `; var tips = eLanguage.dialog.contentPieceMax; tips = tips.replace("{min}", min); tips = tips.replace("{max}", max); const content = ` <div id="` + outerId + `"> <div class="d_____piece"> ` + tips + `<input class="d_____input" number="number" min="` + min + `" max="` + max + `" step="1" value="` + maximumRecords + `" name="maximum-records"/> </div> <div class="d_____piece"> <p>` + eLanguage.dialog.contentPieceClear + `</p> <button class="d_____btn" name="clear">` + eLanguage.dialog.contentPieceClearBtn + `</button> </div> </div> `; dialog.showMake({ title: eLanguage.dialog.title, content, styleSheet, onContentReady: function($that) { $that.dialogContent.querySelector("button[name='clear']").addEventListener("click", function() { self.removeAllConfirm(); }); $that.dialogContent.querySelector("input[name='maximum-records']").onchange = function(e) { const value = this.value; if (value >= min && value <= max) { GM_setValue(self.storageKeys.maximumRecordsKey, value); } }; } }); }, showOrHideHistoryBox: function(platform) { const self = this; const group = this.getGoodsByDateGroup(platform); const contentElement = document.querySelector(".peter99032j-xyz-panel-aside-main .panel-aside-main_____content"); contentElement.innerHTML = ""; let historiesBoxHtml = "", jumpUrl = "", imgUrl = ""; for (let i = 0; i < group.length; i++) { historiesBoxHtml += `<div class="panel-aside-main_____item">`; historiesBoxHtml += `<div class="item_____title"> —— ` + group[i].str + ` —— </div>`; historiesBoxHtml += `<div class="item_____container">`; for (let j = 0; j < group[i].items.length; j++) { jumpUrl = this.pretreatmentJumpUrl(group[i].items[j].url, platform); imgUrl = this.pretreatmentImageUrl(group[i].items[j].pic, platform); historiesBoxHtml += ` <div class="histories-box-review_item"> <a title="` + group[i].items[j].title + `" jump-tag="true" href="javascript:void(0);" jump-url="` + jumpUrl + `" target="_blank"> <div class="review___shadow"> <div class="delete_____btn" data-id="` + group[i].items[j].id + `">×</div> </div> <div class="review___img"><img src="` + imgUrl + `" /></div> <div class="review___text">` + group[i].items[j].price + `</div> </a> </div> `; } historiesBoxHtml += `</div>`; historiesBoxHtml += `</div>`; } contentElement.innerHTML = historiesBoxHtml; document.querySelectorAll(".peter99032j-xyz-panel-aside-main .delete_____btn").forEach((ele) => { ele.addEventListener("click", function(e) { e.stopPropagation(); e.preventDefault(); const id = this.getAttribute("data-id"); this.parentNode.parentNode.parentNode.remove(); self.remove(platform, id); }); }); const items = document.querySelectorAll(".peter99032j-xyz-panel-aside-main .histories-box-review_item > a"); items.forEach((ele) => { ele.addEventListener("mouseover", function() { this.querySelector(".review___shadow").style.display = "block"; }); ele.addEventListener("mouseout", function() { this.querySelector(".review___shadow").style.display = "none"; }); }); document.querySelectorAll(".peter99032j-xyz-panel-aside-main a[jump-tag='true']").forEach((ele) => { ele.addEventListener("click", function(e) { e.stopPropagation(); e.preventDefault(); const href = this.getAttribute("jump-url"); Tools.openInTab(Tools.decryptStr(href)); }); }); }, pretreatmentJumpUrl: function(url, platform) { const realUrl = encodeURIComponent(url); let jumpUrl = "https://page.mimixiaoke.com/api/product/redirect?url=" + realUrl; if (platform == "ebay" || platform == "bestbuy") { jumpUrl = "https://www.jtm.pub/api/product/redirect?url=" + realUrl; } return Tools.encryptStr(jumpUrl); }, pretreatmentImageUrl: function(imgUrl, platform) { let dealImgUrl = ""; if (platform == "aliexpress") { dealImgUrl = imgUrl.split("_")[0]; } else { dealImgUrl = imgUrl; } return dealImgUrl; }, createHistoryBox: function(platform) { const wrapperOffset = GM_getValue(this.storageKeys.offset, this.defaultValue.offsetWrapper); let css = ` .peter99032j-xyz-panel-wrapper{ position: fixed; bottom: ` + wrapperOffset.bottom + `px; right: ` + wrapperOffset.right + `px; z-index: 999999999; box-sizing: border-box; } .peter99032j-xyz-panel-wrapper svg.icon-svg path{ fill: #bfbfbf; } .peter99032j-xyz-panel-wrapper svg.icon-svg:hover path{ fill: #6a7a9b; } /*** 历史记录大box ***/ .peter99032j-xyz-panel-wrapper >.peter99032j-xyz-panel-aside-main{ width: 400px; height: 400px; position: absolute; right: 0px; bottom: 70px; border-radius: 5px; border: 1px solid #ebebeb; background-color: #fafafa; overflow-y: auto; overflow-x: hidden; background-color:#fafafa; display:none; -moz-box-shadow:2px 2px 5px #b6bdc5; -webkit-box-shadow:2px 2px 5px #b6bdc5; box-shadow:2px 2px 5px #b6bdc5; } .peter99032j-xyz-panel-wrapper >.peter99032j-xyz-panel-aside-main >.panel-aside-main_____inner{ display: flex; flex-direction: column; width: 100%; height: 100%; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____header{ display: flex; align-items: center; flex-direction: row; height:40px; background: #dedede; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____header >.header_____title{ align-items: center; display: flex; flex: 1; margin-left: 15px; font-size: 15px; font-weight: bold; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____header >.header_____title >svg{ margin-right:5px; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____header >.header_____close, .peter99032j-xyz-panel-aside-main .panel-aside-main_____header >.header_____setting{ display: flex; justify-content: center; align-items: center; cursor:pointer; width:35px; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____content{ flex: 1; overflow: auto; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____item{ padding: 5px; margin:5px 0px; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____item .item_____title{ font-size: 13px; font-weight: 500; text-align: center; color: #b6b6b6; padding: 5px 0px; } .peter99032j-xyz-panel-aside-main .panel-aside-main_____item .item_____container{ display: flex; flex-flow: wrap; flex-direction: row; justify-content: flex-start; } /**** 历史记录展示 ****/ .peter99032j-xyz-panel-aside-main .histories-box-review_item{ width:33.3333%; margin: 5px 0px; overflow: hidden; } .peter99032j-xyz-panel-aside-main .histories-box-review_item >a{ display: block !important; position: relative !important; margin: 0px auto !important; background-color: #fff !important; width: 110px !important; border-radius: 5px !important; border: 1px solid #ccc !important; box-sizing: content-box !important; } .peter99032j-xyz-panel-aside-main .histories-box-review_item > a >.review___shadow{ position:absolute; left:0px; right:0px; top:0px; bottom:0px; z-index:99; text-align: center; border:2px solid red; border-radius: 5px; display:none; } .peter99032j-xyz-panel-aside-main .histories-box-review_item > a >.review___shadow .delete_____btn{ position: absolute; top: 0px; right: 0px; width: 15px; height: 15px; text-align: center; line-height: 10px; background-color:red; color:#FFF; font-size:13px; border-radius:3px; } .peter99032j-xyz-panel-aside-main .histories-box-review_item > a >.review___img{ width:110px; height: 110px; border-radius: 5px 5px 0px 0px; overflow: hidden; } .peter99032j-xyz-panel-aside-main .histories-box-review_item > a >.review___img >img{ width:100%; } .peter99032j-xyz-panel-aside-main .histories-box-review_item > a >.review___text{ text-align: center!important; font-size: 13px !important; color: #000 !important; text-decoration: underline !important; padding: 5px!important; white-space: nowrap!important; overflow: hidden!important; text-overflow: ellipsis!important; } /*** 横向小卡片 ***/ .peter99032j-xyz-panel-wrapper >.peter99032j-xyz-panel-aside-body{ display: flex; border-radius:5px; overflow: hidden; background-color: #fafafa; -moz-box-shadow:2px 2px 5px #b6bdc5; -webkit-box-shadow:2px 2px 5px #b6bdc5; box-shadow:2px 2px 5px #b6bdc5; height:60px; } .peter99032j-xyz-panel-wrapper >.peter99032j-xyz-panel-aside-body >div{ display: flex; justify-content: center; align-items: center; } .peter99032j-xyz-panel-aside-body .goods_____expand{ cursor: pointer; width: 20px !important; } .peter99032j-xyz-panel-aside-body .goods_____expand svg{ transition: transform 0.3s; } /**** goods展示 ****/ .peter99032j-xyz-panel-aside-body .goods_____review{ flex-direction: row; width:auto; transition: all 0.5s ease-in-out; } .peter99032j-xyz-panel-aside-body .goods-review_____item{ width:45px; height:45px; line-height:45px; margin:0px 5px; position:relative; border-radius: 4px; overflow: hidden; cursor:pointer; } .peter99032j-xyz-panel-aside-body .goods-review_____item >a{ display:block; width: 100%; height: 100%; } .peter99032j-xyz-panel-aside-body .goods-review_____item > a>.review___shadow{ position:absolute; left:0px; right:0px; top:0px; bottom:0px; z-index:99; text-align: center; background-color:rgb(61 155 164 / 20%); display:none; } .peter99032j-xyz-panel-aside-body .goods-review_____item > a>.review___shadow img{ width:15px; } .peter99032j-xyz-panel-aside-body .goods-review_____item img{ width:100%; } /** 展开历史记录BOX **/ .peter99032j-xyz-panel-aside-body .history-box_____expand{ flex-direction: column; text-align: center; margin:0px 10px; cursor: pointer; } .peter99032j-xyz-panel-aside-body .history-box_____expand img{ width:26px; } .peter99032j-xyz-panel-aside-body .history-box_____expand label{ font-size:12px; font-weight: bold; } .peter99032j-xyz-panel-aside-body .wrapper_____drag-handle{ width: 20px !important; cursor: grab; box-shadow: rgba(0, 0, 0, 0.2) 0px 3px 3px -2px, rgba(0, 0, 0, 0.14) 0px 3px 4px 0px, rgba(0, 0, 0, 0.12) 0px 1px 8px 0px; } `; const histories = this.get(platform, this.defaultValue.toolbarGoodsNum); const historySVG = ` <svg t="1722328287419" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14202" width="25" height="25"><path d="M757.9648 948.1216H271.6672c-107.264 0-194.2016-86.9376-194.2016-194.2016V267.6736c0-107.264 86.9376-194.2016 194.2016-194.2016h486.2464c107.264 0 194.2016 86.9376 194.2016 194.2016v486.2464c0.0512 107.264-86.8864 194.2016-194.1504 194.2016z" fill="#F6CC4F" p-id="14203"></path><path d="M823.3472 441.6512c-38.9632-171.5712-210.2784-279.4496-381.8496-240.5376-47.7696 10.8544-91.4944 32.0512-128.9216 62.1568l0.2048-44.3904a25.61024 25.61024 0 0 0-25.4976-25.7024h-0.1024c-14.08 0-25.5488 11.3664-25.6 25.4976l-0.512 111.8208c-0.0512 6.8096 2.6624 13.312 7.424 18.1248 4.7616 4.8128 11.3152 7.5264 18.0736 7.5776l119.296 0.3584h0.1024c14.08 0 25.5488-11.4176 25.6-25.4976a25.61024 25.61024 0 0 0-25.4976-25.7024l-63.7952-0.2048c31.9488-26.2656 69.5296-44.7488 110.6432-54.0672 144.0256-32.7168 287.8976 57.856 320.6144 201.9328 32.7168 144.0768-57.9072 287.8976-201.9328 320.6144-144.128 32.7168-287.8976-57.9072-320.6144-201.9328-4.9152-21.6576-7.168-43.8272-6.656-65.8432a25.6512 25.6512 0 0 0-24.9856-26.2144 25.61536 25.61536 0 0 0-26.2144 24.9856c-0.6144 26.2144 2.048 52.5824 7.8848 78.3872 33.5872 147.9168 165.4784 248.5248 311.1424 248.5248 23.3472 0 47.0016-2.56 70.7072-7.936 171.52-39.0656 279.4496-210.3296 240.4864-381.952z" fill="#F7F8F8" p-id="14204"></path><path d="M512.1536 382.3104c-14.1312 0-25.6 11.4688-25.6 25.6v106.7008c0 6.3488 2.3552 12.4416 6.6048 17.152l91.5968 101.6832c5.0688 5.632 12.032 8.448 19.0464 8.448 6.0928 0 12.2368-2.1504 17.1008-6.6048a25.58976 25.58976 0 0 0 1.8944-36.1472l-85.0432-94.3616V407.9104c0-14.1824-11.4688-25.6-25.6-25.6z" fill="#F7F8F8" p-id="14205"></path></svg> `; let goodsHtml = ``, jumpUrl = ""; histories.forEach((h) => { jumpUrl = this.pretreatmentJumpUrl(h.url, platform); goodsHtml += ` <div class="goods-review_____item"> <a title="` + h.title + `" jump-tag="true" jump-url="` + jumpUrl + `" target="_blank"> <div class="review___shadow"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAVlJREFUWEftlsGRgzAMRS26wBQTUtluKltSDKYLlJUHMY6xZMGFi7lkCObr6cuWAHfzBTfHdw2gOdAcOOXAPM+/fGwB4OGcG7f7iX4R8d113dT3fby3XCYACgwAPxZBBiKYYRh2YOldFUAKjIivNNNlWUZEJEB2ZI9HazUQEUALLgluIH95thpEESCEQCKHbADgyfXNACcAeNEzpVyT9/6Zwx0ApOD/QFFAypKEvfdR74x7XwCaOGevANIpiPXWNm1eji8ATZyzCyGgdhos63gN6eQAorhFmMugOcml3PtJmo3FukpPqO6TdCMfHLBuIKkMiUvFU5RnXwSgP6W9kG6gbQ0tpya0NxvFftsx5JJIVucWWkp4uhHVIMhKajy0jptPtLMwLy634kJm6fSrzqVa4OIpqKlSfdd1HbdRHOufTj9+3zIFLwHUAK88N30PXBG2vtMAmgPNgQ/i7v8h6Um2jAAAAABJRU5ErkJggg==" /> </div> <img src="` + h.pic + `" /> </a> </div> `; }); let html = ` <div class="peter99032j-xyz-panel-wrapper"> <div class="peter99032j-xyz-panel-aside-main"> <div class="panel-aside-main_____inner"> <div class="panel-aside-main_____header"> <div class="header_____title"> ` + historySVG + ` ` + eLanguage.historyToolbar.boxTitle + ` </div> <div class="header_____setting"> <svg class="icon-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1770" width="30" height="30"><path d="M811.04 468.728a39.72 39.72 0 0 0-27.672-30.36l-10.2-2.28a100.872 100.872 0 0 1-68.856-120.24l3.12-9.552a41.592 41.592 0 0 0-11.424-40.368 281.64 281.64 0 0 0-36.816-24.336c-12.36-7.2-25.224-13.536-38.496-18.912a41.592 41.592 0 0 0-41.592 9.984l-7.08 7.488a100.248 100.248 0 0 1-69.264 27.456 100.464 100.464 0 0 1-68.64-27.672l-6.864-7.272a41.592 41.592 0 0 0-41.592-9.984 294.96 294.96 0 0 0-37.848 18.912c-12.696 7.152-24.792 15.288-36.192 24.336a41.592 41.592 0 0 0-10.824 40.368l2.904 9.552a101.088 101.088 0 0 1-10.8 74.064 96.72 96.72 0 0 1-57.408 45.552l-9.792 2.28a35.352 35.352 0 0 0-26.616 28.488c-1.872 14.352-2.64 28.8-2.28 43.272-0.408 14.736 0.36 29.472 2.28 44.088a39.936 39.936 0 0 0 25.8 31.2l9.552 2.304a99 99 0 0 1 57.624 46.992c12.984 22.392 16.848 48.912 10.8 74.064l-2.064 9.36a41.592 41.592 0 0 0 11.856 40.344c11.136 9.072 22.968 17.28 35.352 24.552 12.312 7.488 25.176 14.016 38.496 19.536 14.64 4.608 30.624 0.768 41.592-9.984l6.648-7.272a101.088 101.088 0 0 1 139.152 0l6.672 7.272a41.592 41.592 0 0 0 41.592 9.984 295.152 295.152 0 0 0 37.224-19.536 271.848 271.848 0 0 0 36.624-24.336c10.944-10.32 15.48-25.752 11.856-40.368l-2.928-9.768a100.872 100.872 0 0 1 69.48-120l9.576-2.304a39.72 39.72 0 0 0 27.648-30.36c1.68-14.376 2.232-28.824 1.68-43.272a291.192 291.192 0 0 0-2.304-43.272z m-307.44 190.944a147.672 147.672 0 1 1 0-295.344 147.672 147.672 0 0 1 0 295.344z" fill="#8a8a8a" p-id="1771"></path></svg> </div> <div class="header_____close"> <svg class="icon-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1609" width="30" height="30"><path d="M673.5644448 281.66826667L512 447.82933333 351.16373333 281.71377813a44.6464 44.6464 0 0 0-63.6700448-0.50062293 46.1027552 46.1027552 0 0 0-0.50062186 64.6712896L447.82933333 512l-160.83626666 165.84248853c-17.52177813 18.06791147-17.29422187 46.8764448 0.50062186 64.6712896a44.69191147 44.69191147 0 0 0 63.71555627-0.45511146L512 576.17066667l161.5644448 165.93351146a44.78293333 44.78293333 0 0 0 63.7155552 0.4096 45.96622187 45.96622187 0 0 0 0.45511147-64.62577813L576.17066667 512l161.5644448-166.16106667a46.01173333 46.01173333 0 0 0-0.45511147-64.62577813 44.73742187 44.73742187 0 0 0-63.7155552 0.45511147z" fill="#5D6E7F" p-id="1610"></path></svg> </div> </div> <div class="panel-aside-main_____content"></div> </div> </div> <div class="peter99032j-xyz-panel-aside-body"> <div class="goods_____expand"> <svg focusable="false" class="icon-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1365" width="20" height="20"><path d="M317.84959998 926.1056a46.08 46.08 0 0 1 10.8544-29.9008L643.68639998 521.216a13.312 13.312 0 0 0 0-18.432l-3.6864-3.072L328.70399998 127.7952a46.4896 46.4896 0 0 1 71.0656-59.8016l311.0912 370.68799999a105.8816 105.8816 0 0 1 0 146.63680002l-311.0912 370.68799999a46.2848 46.2848 0 0 1-81.92-29.9008z" fill="#bfbfbf" p-id="1366"></path></svg> </div> <div class="goods_____review"> ` + goodsHtml + ` </div> <div class="history-box_____expand"> ` + historySVG + ` <label>` + eLanguage.historyToolbar.expandTipText + `</label> </div> <div class="wrapper_____drag-handle"> <svg focusable="false" class="icon-svg" viewBox="0 0 24 24" data-testid="DragIndicatorIcon"><path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2m-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2m0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2" fill="#bfbfbf"></path></svg> </div> </div> </div> `; GM_addStyle(css); document.querySelector("body").insertAdjacentHTML("afterend", html); this.addEventListener(platform); }, addEventListener: function(platform) { const self = this; const items = document.querySelectorAll(".goods_____review >.goods-review_____item >a"); items.forEach((ele) => { ele.addEventListener("mouseover", function() { this.querySelector(".review___shadow").style.display = "block"; }); ele.addEventListener("mouseout", function() { this.querySelector(".review___shadow").style.display = "none"; }); }); const goodsExpandEle = document.querySelector(".peter99032j-xyz-panel-wrapper .goods_____expand"); if (goodsExpandEle) { goodsExpandEle.addEventListener("click", function() { const goodsReviewEle = this.nextElementSibling; const svgEle = this.querySelector("svg"); svgEle.style.transition = "transform 0.3s"; if (goodsReviewEle.style.width == "0px") { goodsReviewEle.style.width = "auto"; svgEle.style.transform = "rotate(0deg)"; } else { goodsReviewEle.style.width = "0px"; svgEle.style.transform = "rotate(180deg)"; } }); } const historyBoxExpandEles = [ document.querySelector(".peter99032j-xyz-panel-wrapper .history-box_____expand"), document.querySelector(".peter99032j-xyz-panel-wrapper .header_____close") ]; const asideMainEle = document.querySelector(".peter99032j-xyz-panel-wrapper >.peter99032j-xyz-panel-aside-main"); if (asideMainEle) { historyBoxExpandEles.forEach((ele) => { if (ele) { ele.addEventListener("click", function() { if (!asideMainEle.style.display || asideMainEle.style.display === "none") { self.showOrHideHistoryBox(platform); asideMainEle.style.display = "block"; } else { asideMainEle.style.display = "none"; } }); } }); } document.body.addEventListener("click", function(e) { if (asideMainEle.style.display && asideMainEle.style.display !== "none") { asideMainEle.style.display = "none"; } }); const headerSettingElement = document.querySelector(".peter99032j-xyz-panel-wrapper .header_____setting"); if (headerSettingElement) { headerSettingElement.addEventListener("click", () => { self.showSettingDialog(); }); } document.querySelectorAll(".peter99032j-xyz-panel-aside-body a[jump-tag='true']").forEach((ele) => { ele.addEventListener("click", function(e) { e.stopPropagation(); e.preventDefault(); const href = this.getAttribute("jump-url"); Tools.openInTab(Tools.decryptStr(href)); }); }); const draggable = document.querySelector(".peter99032j-xyz-panel-wrapper .wrapper_____drag-handle"); const wrapper = document.querySelector(".peter99032j-xyz-panel-wrapper"); let offsetX, offsetY; const padding = 0; const { width, height } = wrapper.getBoundingClientRect(); const offsetWrapper = Object.assign({}, this.defaultValue.offsetWrapper); const move = (e) => { const { innerWidth, innerHeight } = window; innerWidth - (e.clientX - offsetX) - width; let y = innerHeight - (e.clientY - offsetY) - height; if (y < padding) { y = padding; } else if (y > innerHeight - height) { y = innerHeight - height - padding; } wrapper.style.bottom = y + "px"; offsetWrapper.bottom = y; GM_setValue(this.storageKeys.offset, offsetWrapper); }; if (draggable && wrapper) { draggable.addEventListener("mousedown", function(e) { offsetX = e.clientX - wrapper.offsetLeft - 10; offsetY = e.clientY - wrapper.offsetTop - 10; draggable.style.cursor = "grabbing"; wrapper.style.userSelect = "none"; document.addEventListener("mousemove", move); }); document.addEventListener("mouseup", function() { draggable.style.cursor = "grab"; wrapper.style.userSelect = "default"; document.removeEventListener("mousemove", move); }); } }, removeAnchor: function() { if (/aliexpress\./.test(window.location.host)) { setInterval(() => { const anchors = document.querySelectorAll("div[class='peter99032j-xyz-panel-wrapper']"); anchors.forEach((ele) => { Tools.removeAliexpressAnchors(ele); }); }, 1500); } }, start: function(platform) { try { if (!/aliexpress\.ru/.test(window.location.host) && window.self == window.top) { this.createHistoryBox(platform); this.registerMenuCommand(); } this.removeAnchor(); } catch (e) { } } }; var __async$8 = (__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 Aliexpress = { languageStoageKey: "language-stoage-key", currencyStoageKey: "language-currency-key", baseUrl: "https://oversea.mimixiaoke.com", checkDomInsertRs: true, getLang: function() { const host = window.location.host; let lang = "en"; if (/^(us|ko|uk|fr|de|it|ca|au|jp|ja|he|kr|ru|br|in|es|mx|pl|tr|ar|id|th|vn|sg|my|ph|be|nl|se|ch|no|dk|at|ie|fi|pt|gr|hu|cz|bg|ro|ua|il|sa|eg|ir|pk|iq|af|ly|et|gh|ke|ng|za|tz|mg|mw|zm|bw|sn|cm|ci|gh|ma|tn|mr|mu|om|kw|qa|bh|ae|lb|jo|sy|lb|il|ps|kr|cl|pe|uy|ec|ve|bo|gt|pa|hn|ni|cr|sv|gt|sl|lr|sd|er|dj|et|mw|mz|ao|tz|zm|zw|mw|na|bw|ls|mg|km)\.aliexpress\.com$/.test(host)) { lang = host.split(".")[0]; } else if (/^www\.aliexpress\.com$/.test(host)) { lang = "en"; } else if (/^aliexpress\.ru$/.test(host)) { lang = "ru"; } GM_setValue(this.languageStoageKey, lang); return lang; }, getCurrency: function() { const host = window.location.host; return new Promise((resolve, reject) => { if (host.indexOf("aliexpress.ru") != -1) { resolve("unknown"); } else { const element = document.querySelector("div[class^='ship-to--menuItem--']") || document.querySelector("div[class^='countryFlag--']"); if (element) { let currency = element.textContent; if (currency) { currency = encodeURIComponent(currency); GM_setValue(this.currencyStoageKey, currency); resolve(currency); } else { resolve("unknown"); } } else { resolve("unknown"); } } }); }, detail: function() { return __async$8(this, null, function* () { const visitUrl = window.location.href; const validate = [/\/item\/[^\/]*?\.html\?/, /\/item\/[^\/]*?\.html$/].map((reg) => reg.test(visitUrl)).some((rs) => rs == true); if (!validate) return; const language = this.getLang(); const currency = yield this.getCurrency(); const id = Tools.getParamterBySuffix(visitUrl, "html"); const url = this.baseUrl + "/api/coupon/query?ids=" + id + "&qu=&p=aliexpress&no=9&v=1.0.1&lang=" + language + "&mul=false¤cy=" + currency; const data = yield Tools.crossRequest("GET", url, null); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); yield this.detailAnalyze(json, language, currency); } if (!/aliexpress\.ru/.test(window.location.host)) { const priceValueElement = document.querySelector("span.product-price-value, div[class*='ProductPrice_SnowPrice']"); const sliderImgElement = document.querySelector("div[class*='slider--img'] >img, picture[class*='Picture__container'] >img"); const priceTitleElement = document.querySelector("h1[data-pl='product-title'], h1[class*='HazeProductDescription_HazeProductDescription__smallText_']"); if (sliderImgElement) { const imgSrc = sliderImgElement.getAttribute("src"); const price = priceValueElement ? priceValueElement.innerText : "Unknown"; const title = priceTitleElement ? priceTitleElement.innerText : "--"; const goods = { "id": id, "url": visitUrl, "pic": imgSrc, "date": new Date().getTime(), "price": price, "title": title }; GoodsHistroy.push("aliexpress", goods); } } }); }, detailAnalyze: function(json, language, currency) { return __async$8(this, null, function* () { this.checkDomInsertRs = false; try { if (!json) return; let couponResult = null; let qrcodeResult = null; if (!!json.data && !!json.data.css && !!json.data.html && !!json.data.handler) { const { handler, css, html, templateId, distinguish } = json.data; GM_addStyle(css); const element = yield Tools.mustGetElement(handler); logger("info", "coupon insert:element", element); if (element) { couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish }; } } if (!!json.id && !!json.mscan && !!json.mscan.html && !!json.mscan.mount) { const { iden, html, mount, distinguish } = json.mscan; const id = json.id; const promiseResultArray = []; const elementPromise = Tools.mustGetElement(mount); const reqUrl = this.baseUrl + "/api/coupon/change?id=" + id + "&lang=" + language + "&platform=aliexpress¤cy=" + currency; logger("info", "coupon change >>>>>>>>>>>>>", reqUrl); const reqPromise = Tools.crossRequest("GET", reqUrl, null); promiseResultArray.push(elementPromise, reqPromise); const allResult = yield Promise.all(promiseResultArray); let element = null, qrcodeData = null; for (let i = 0; i < allResult.length; i++) { if (allResult[i]) { if (allResult[i].hasOwnProperty("code")) { qrcodeData = allResult[i]; } else { element = allResult[i]; } } } logger("info", "qrcocd insert:element", element); if (element && qrcodeData) { qrcodeResult = { "element": element, "html": html, "iden": iden, "qrcodeData": qrcodeData, "distinguish": distinguish }; } } Tools.loopTask(() => { if (couponResult) { Tools.distinguishRemoveAndTry(couponResult.distinguish, () => { this.detailCouponAnalyze(couponResult); }); } if (qrcodeResult) { Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => { this.detailMscanAnalyze(qrcodeResult); }); } }); } catch (error) { } finally { this.checkDomInsertRs = true; } }); }, detailCouponAnalyze: function(result) { const { element, html, templateId } = result; element.insertAdjacentHTML("afterend", html); const templateIdEle = document.querySelector("div[id='" + templateId + "']"); if (templateIdEle) { const couponCodeElement = templateIdEle.querySelector(".coupon-code"); const promoCode = Tools.decryptStr(couponCodeElement.getAttribute("data-encryptcode")); templateIdEle.addEventListener("click", () => { GM_setClipboard(promoCode, "txt", () => { Toast.show({ "message": eLanguage.operat.copied, "background": "#D3031C" }); }); }); } }, detailMscanAnalyze: function(result) { const { element, html, qrcodeData, iden } = result; element.insertAdjacentHTML("afterend", html); if (!!qrcodeData && qrcodeData.code === "success" && !!qrcodeData.result) { const mscanImg = JSON.parse(qrcodeData.result).mscanImg; if (!!mscanImg) { const canvasElement = document.getElementById("mscan" + iden); if (canvasElement) { var cxt = canvasElement.getContext("2d"); var imgData = new Image(); imgData.src = mscanImg; imgData.onload = function() { cxt.drawImage(imgData, 0, 0, imgData.width, imgData.height); }; } } } }, trade: function() { return __async$8(this, null, function* () { const visitUrl = window.location.href; const validate = [ /\/trade\/confirm\.html/, /\/checkout\?/ ].map((reg) => reg.test(visitUrl)).some((rs) => rs == true); if (!validate) return; const language = yield GM_getValue(this.languageStoageKey, navigator.language); const currency = yield GM_getValue(this.currencyStoageKey, "USD"); const ids = Tools.getParamterBySearch(window.location.search, "objectId") || Tools.getParamterBySearch(window.location.search, "availableProductShopcartIds") || Tools.getParamterBySearch(window.location.search, "itemId"); const confirmUrl = this.baseUrl + "/api/coupon/query?ids=" + ids + "&qu=&p=aliexpress&no=9&v=1.0.1&lang=" + language + "&mul=true¤cy=" + currency; const res = yield Tools.crossRequest("GET", confirmUrl, null); if (res.code == "success" && !!res.result) { const json = JSON.parse(res.result); yield this.tradeAnalyze(json, language); } }); }, tradeAnalyze: function(json, language) { return __async$8(this, null, function* () { if (!json || !json.handler || !json.css || !json.templateId) { return; } const { handler, css, html, templateId, distinguish } = json; GM_addStyle(css); let element = yield Tools.mustGetElement(handler); Tools.loopTask(() => { if (!element) { return; } Tools.distinguishRemoveAndTry(distinguish, () => { element.insertAdjacentHTML("afterend", html); const templateIdEle = document.querySelector("#" + templateId + ">.item"); if (templateIdEle) { const promoCode = Tools.decryptStr(templateIdEle.querySelector(".copy").getAttribute("data-encryptcode")); templateIdEle.addEventListener("click", () => { GM_setClipboard(promoCode, "txt", () => { Toast.show({ "message": eLanguage.operat.copied, "background": "#D3031C" }); }); }); const arrowElement = document.querySelector(".pl-summary__item-arrow-pc"); if (arrowElement) { arrowElement.click(); } } }); }); }); }, isRun: function() { return window.location.host.indexOf("aliexpress.") != -1; }, removeAnchor: function() { Tools.loopTask(() => { const anchors = document.querySelectorAll("div[name^='ali-gogo-coupon-']"); anchors.forEach((ele) => Tools.removeAliexpressAnchors(ele)); }, 2500); }, start: function() { return __async$8(this, null, function* () { if (this.isRun()) { this.detail(); this.trade(); this.removeAnchor(); } }); } }; const ItemSearchBaseObj = { visitUrl: window.location.href, searchAttribute: "loop-task-i9v---search", baseUrl: "https://oversea.mimixiaoke.com", cacheRequestMap: {}, requestAndSaveSate: function(method, url, param) { return new Promise((resolve, reject) => { const key = "key_" + new Date().getTime(); const xhr = new XMLHttpRequest(); this.cacheRequestMap[key] = xhr; if (method === "GET") { let queryString = ""; if (param) { const params = new URLSearchParams(param); queryString = "?" + params.toString(); } xhr.open(method, url + queryString); xhr.send(); } else if (method === "POST") { xhr.open(method, url); xhr.setRequestHeader("Content - Type", "application/json"); xhr.send(JSON.stringify(param)); } else { resolve({ "code": "error", "requestKey": key, "result": null }); return; } xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { try { resolve({ "code": "success", "requestKey": key, "result": xhr.responseText }); } catch (e) { resolve({ "code": "error", "requestKey": key, "result": null }); } } else { resolve({ "code": "error", "requestKey": key, "result": null }); } } }; }); }, requestConf: function() { return new Promise((resolve, reject) => { Tools.crossRequest("GET", this.baseUrl + "/api/load/conf", null).then((data) => { if (data.code == "success" && !!data.result) { resolve(data.result); } else { resolve(null); } }); }); }, pickupGoodsItem: function(platform, confString) { const visitHref = window.location.href; const selectorElementList = new Array(); let confFilter = confString; try { confFilter = confFilter.replace(/\\\\/g, "\\"); } catch (e) { } const confJson = JSON.parse(confFilter)[platform]; for (let i = 0; i < confJson.length; i++) { const itemJson = confJson[i]; if (!itemJson.hasOwnProperty("elements") || !itemJson.hasOwnProperty("matches")) { continue; } const { elements, matches } = itemJson; const isMatch = matches.map((reg) => new RegExp(reg, "i").test(visitHref)).some((res) => res); if (isMatch) { for (let j = 0; j < elements.length; j++) { selectorElementList.push({ "element": elements[j]["element"], "findA": elements[j]["findA"], "page": elements[j]["page"] }); } } } return selectorElementList; }, getGoodsLinkByElement: function(element, findTag) { let searchElement = null; if (findTag == "this") { searchElement = element; } else if (/^child@/.test(findTag)) { searchElement = element.querySelector(findTag.replace(/^child@/, "")); } return searchElement; }, getGoodsPriceByElement: function(element, tag) { const goodsPrice = element.querySelector(tag); let price = goodsPrice == null ? "" : goodsPrice.innerText; if (price) { price = price.replace(/\s/g, ""); } return price; }, getGoodsPrice: function(content) { content = content.replace(/[,]/g, ""); const amount = content.match(/(?:₱|\$|฿|₫|Rp|RM|¥)\n?\d+(?:(?:\.\d{1,3})*)?/); let price = amount ? amount[0] : ""; if (price && price.indexOf("Rp") != -1) { price = price.replace(/\./g, ""); } price = price.replace(/\n/g, ""); return price; }, isElementDisplayed: function(element) { if (element.offsetParent !== null) { return true; } const style = window.getComputedStyle(element); return style.display !== "none"; }, getGoodsIdByUrl: function(href, suffix) { if (!href) return null; href = href.indexOf("http") == -1 ? location.protocol + href : href; const id = Tools.getParamterBySuffix(href, suffix); return id; }, calcRequestGroup: function(array) { const itemsPerGroup = 8, len = array.length; let groups = []; for (let i = 0; i < len; i++) { const groupIndex = Math.floor(i / itemsPerGroup); if (!groups[groupIndex]) { groups[groupIndex] = []; } groups[groupIndex].push(array[i]); } return groups; } }; var __async$7 = (__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 AliexpressSearch = { loopIsComplete: true, currentPlatform: "aliexpress", isInbusinessPage: function() { return /inbusiness\.aliexpress\.com\/web\/search-products/.test(ItemSearchBaseObj.visitUrl); }, isItemLink: function(url) { return /aliexpress/.test(url) && /\/item\/[^\/]*?\.html/.test(url); }, pickUpWholesale: function(selectors, language, currency) { return __async$7(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); logger("info", "search coupon elements======>", elements.length); const findA = elementObj.findA; elements.forEach((element) => { if (element && ItemSearchBaseObj.isElementDisplayed(element) && !element.getAttribute(ItemSearchBaseObj.searchAttribute)) { const goodsLink = ItemSearchBaseObj.getGoodsLinkByElement(element, findA); let id = null; if (this.isItemLink(goodsLink)) { id = ItemSearchBaseObj.getGoodsIdByUrl(goodsLink.getAttribute("href")); } if (id) { items.push({ "id": id, "platform": this.currentPlatform, "handler": element, "findA": findA, "from": "wholesale" }); } } }); } }); if (items.length > 0) { yield this.search(items, language, currency); } } catch (e) { } }); }, pickUpInbusiness: function(language, currency) { return __async$7(this, null, function* () { const validate = this.isInbusinessPage(); if (!validate) return; try { const iceContainerElement = document.querySelector("#ice-container"); const loadMoreElement = yield Tools.waitForElementByInterval("#loadMore", iceContainerElement); if (loadMoreElement) { const array = new Array(); const containerElement = loadMoreElement.previousElementSibling; if (containerElement && containerElement.tagName === "DIV") { const childNodes = containerElement.childNodes; childNodes.forEach((child) => { if (child.tagName === "A" && ItemSearchBaseObj.isElementDisplayed(child) && !child.getAttribute(ItemSearchBaseObj.searchAttribute)) { const id = ItemSearchBaseObj.getGoodsIdByUrl(child.getAttribute("href")); if (id) { array.push({ "id": id, "platform": this.currentPlatform, "handler": child, "from": "inbusiness" }); } } }); } yield this.search(array, language, currency); } } catch (e) { } }); }, search: function(array, language, currency) { const groups = ItemSearchBaseObj.calcRequestGroup(array); const len = groups.length; return new Promise((resolve, reject) => { if (len <= 0) { resolve("complete"); return; } const promises = []; for (let i = 0; i < groups.length; i++) { promises.push(this.createItemHtml(groups[i], language, currency)); } Promise.all(promises).then((data) => { resolve("complete"); }); }); }, createItemHtml: function(group, language, currency) { return new Promise((resolve, reject) => { try { if (Array.isArray(group) && group.length === 0) { resolve("exception"); return; } let reqId = ""; const platform = group[0].platform; for (var i = 0; i < group.length; i++) { if (group[i].handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { continue; } reqId += group[i].id + ","; } if (reqId.endsWith(",")) { reqId = reqId.slice(0, -1); } logger("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&lang=" + language + "&no=9&v=1.0.1¤cy=" + currency; logger("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { logger("info", "request finish >>>>>>>>>>>>>"); delete ItemSearchBaseObj.cacheRequestMap[data.requestKey]; if (data.code != "success" || !data.result) { resolve("exception"); return; } const json = JSON.parse(data.result); logger("info", "json", json); let isBroken = false; for (let key in json) { const { encryptLink, tip } = json[key]; const item = group.find((obj) => obj.id === key); if (!item) { continue; } let handler = null, findA = null; if (item.hasOwnProperty("handler") && item.hasOwnProperty("findA")) { handler = item.handler; findA = item.findA; } if (!handler || !findA) { continue; } let decryptUrl = null; if (encryptLink) { try { const decryptLink = atob(encryptLink); decryptUrl = decryptLink.split("").reverse().join(""); } catch (e) { } } const elementA = ItemSearchBaseObj.getGoodsLinkByElement(handler, findA); const currentId = elementA ? ItemSearchBaseObj.getGoodsIdByUrl(elementA.getAttribute("href")) : ""; if (currentId != key) { group.forEach((gItem) => { const ele = gItem.handler; ele.removeAttribute(ItemSearchBaseObj.searchAttribute); const tipElement = ele.querySelector("div[name^='ali-gogo-coupon-']"); if (tipElement) { tipElement.remove(); } }); logger("info", "exception currentGoodsId != request id"); isBroken = true; break; } else { if (!handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true"); if (tip) { handler.style.position = "relative"; handler.insertAdjacentHTML("beforeend", tip); logger("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); logger("info", "good job >>>>>>>>>>>>>", key); } } } } resolve(isBroken ? "broken" : "complete"); }); } catch (e) { resolve("exception"); } }); }, relativeJ: function(handler, decryptUrl) { const clickTipAttribute = "tip-vjd1jd89fcv-i"; let elements = null; if (handler.tagName == "A") { elements = [handler]; } else { elements = handler.querySelectorAll("a"); } elements.forEach((elementA) => { const href = elementA.getAttribute("href"); if (this.isItemLink(href)) { if (elementA.getAttribute(clickTipAttribute)) { return; } elementA.setAttribute(clickTipAttribute, "true"); elementA.addEventListener("click", function(e) { let isPreventDefault = true; const target = e.target; const tagName = target.tagName.toUpperCase(); if (tagName == "A") { const href2 = target.getAttribute("href"); if (!this.isItemLink(href2)) { isPreventDefault = false; } } if (isPreventDefault) { Array.from(target.classList).forEach((className) => { const iscontains = ["icon", "-btn-"].map((name) => className.indexOf(name) != -1).some((result) => result); if (iscontains) { isPreventDefault = false; } }); } if (isPreventDefault) { e.preventDefault(); e.stopPropagation(); Tools.openInTab(decryptUrl); } }); } }); }, isRun: function() { let run = false; if (window.location.host.indexOf("aliexpress.") != -1) { run = !/\/(item|trade|checkout)\//.test(window.location.pathname); } return run; }, start: function() { return __async$7(this, null, function* () { if (!this.isRun()) return; let removeTagIsComplete = true; const language = Aliexpress.getLang(); const currency = yield Aliexpress.getCurrency(); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(this.currentPlatform, confString); setInterval(() => __async$7(this, null, function* () { if (removeTagIsComplete && this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpInbusiness(language, currency); yield this.pickUpWholesale(selectors, language, currency); this.loopIsComplete = true; } }), 1700); if (selectors.length != 0 && window.location.pathname != "/") { let oldUrl = window.location.href; setInterval(() => { if (oldUrl != window.location.href && removeTagIsComplete) { removeTagIsComplete = false; Object.keys(ItemSearchBaseObj.cacheRequestMap).forEach((key) => { ItemSearchBaseObj.cacheRequestMap[key].abort(); }); ItemSearchBaseObj.cacheRequestMap = {}; document.querySelectorAll("*[" + ItemSearchBaseObj.searchAttribute + "='true']").forEach((element) => { const tipElement = element.querySelector("*[name^='ali-gogo-coupon-']"); if (tipElement) { tipElement.remove(); } }); oldUrl = window.location.href; } removeTagIsComplete = true; }, 777); const promises = []; selectors.forEach((selector) => { promises.push(Tools.waitForElementByInterval(selector.element, document.body, true, 50, 3e3)); }); const observerElement = yield Promise.race(promises); if (observerElement) { const observer = new MutationObserver((mutationsList) => { if (mutationsList.length == 1) { const mutation = mutationsList[0]; if (mutation.type === "attributes" && mutation.attributeName === "href") { if (removeTagIsComplete) { removeTagIsComplete = false; document.querySelectorAll("*[" + ItemSearchBaseObj.searchAttribute + "='true']").forEach((element) => { element.removeAttribute(ItemSearchBaseObj.searchAttribute); const tipElement = element.querySelector("*[name^='ali-gogo-coupon-']"); if (tipElement) { tipElement.remove(); } }); removeTagIsComplete = true; } } } }); observer.observe(observerElement, { attributes: true }); } } }); } }; var __async$6 = (__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 Ebay = { baseUrl: "https://oversea.mimixiaoke.com", getGoodsId: function(url) { const regex = /https?:\/\/www\.ebay\.[a-z.]+\/itm\/(\d+)/; const match = url.match(regex); return match ? match[1] : null; }, isDetail: function() { const visitUrl = window.location.href; return [/https?:\/\/www\.ebay\.[a-z.]+\/itm\/\d+/].map((rs) => rs.test(visitUrl)).some((rs) => rs); }, getMarketplace: function(url) { try { const urlObj = new URL(url); const hostname = urlObj.hostname; if (hostname) { return hostname.split(".").slice(-1)[0]; } } catch (error) { } return null; }, detail: function() { return __async$6(this, null, function* () { const validate = this.isDetail(); if (!validate) return; const visitUrl = window.location.href; const id = this.getGoodsId(visitUrl); if (!id) { return; } const titleElement = document.querySelector(".x-item-title__mainTitle"); const priceElement = document.querySelector(".x-price-primary >span"); const imgElement = document.querySelector(".ux-image-grid-item >img") || document.querySelector(".ux-image-carousel-item >img"); if (imgElement) { const imgSrc = imgElement.getAttribute("src"); const title = titleElement ? titleElement.innerText : "--"; const price = priceElement ? priceElement.innerText : "Unknown"; const goods = { "id": id, "url": visitUrl, "pic": imgSrc, "date": new Date().getTime(), "price": price, "title": title }; GoodsHistroy.push("ebay", goods); } const marketplace = this.getMarketplace(visitUrl); const url = this.baseUrl + "/api/coupon/query?ids=" + id + "&qu=&p=ebay&no=9&v=1.0.1&marketplace=" + marketplace + "&mul=false"; const data = yield Tools.crossRequest("GET", url, null); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); yield this.detailAnalyze(json, marketplace); } }); }, detailAnalyze: function(json, marketplace) { return __async$6(this, null, function* () { let couponResult = null; let qrcodeResult = null; if (!!json.data && !!json.data.css && !!json.data.html && !!json.data.handler) { const { handler, css, html, templateId, distinguish } = json.data; GM_addStyle(css); const element = yield Tools.mustGetElement(handler); if (element) { couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish }; } } if (!!json.id && !!json.mscan && !!json.mscan.html && !!json.mscan.mount) { const { iden, html, mount, distinguish } = json.mscan; const id = json.id; const promiseResultArray = []; const elementPromise = Tools.mustGetElement(mount); const reqUrl = this.baseUrl + "/api/coupon/change?id=" + id + "&marketplace=" + marketplace + "&platform=ebay"; const reqPromise = Tools.crossRequest("GET", reqUrl, null); promiseResultArray.push(elementPromise, reqPromise); const allResult = yield Promise.all(promiseResultArray); let element = null, qrcodeData = null; for (let i = 0; i < allResult.length; i++) { if (allResult[i]) { if (allResult[i].hasOwnProperty("code")) { qrcodeData = allResult[i]; } else { element = allResult[i]; } } } if (element && qrcodeData) { qrcodeResult = { "element": element, "html": html, "iden": iden, "qrcodeData": qrcodeData, "distinguish": distinguish }; } } Tools.loopTask(() => { if (couponResult) { Tools.distinguishRemoveAndTry(couponResult.distinguish, () => { this.detailCouponAnalyze(couponResult); }); } if (qrcodeResult) { Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => { this.detailMscanAnalyze(qrcodeResult); }); } }); }); }, detailCouponAnalyze: function(result) { const { element, html, templateId } = result; element.insertAdjacentHTML("afterend", html); const templateIdEle = document.querySelector("div[id='" + templateId + "']"); if (templateIdEle) { const couponCodeElement = templateIdEle.querySelector(".coupon-code"); const promoCode = Tools.decryptStr(couponCodeElement.getAttribute("data-encryptcode")); templateIdEle.addEventListener("click", () => { GM_setClipboard(promoCode, "txt", () => { Toast.show({ "message": eLanguage.operat.copied, "background": "#D3031C" }); }); }); } }, detailMscanAnalyze: function(result) { const { element, html, qrcodeData, iden } = result; element.insertAdjacentHTML("afterend", html); if (!!qrcodeData && qrcodeData.code === "success" && !!qrcodeData.result) { const mscanImg = JSON.parse(qrcodeData.result).mscanImg; if (!!mscanImg) { const canvasElement = document.getElementById("mscan" + iden); if (canvasElement) { var cxt = canvasElement.getContext("2d"); var imgData = new Image(); imgData.src = mscanImg; imgData.onload = function() { cxt.drawImage(imgData, 0, 0, imgData.width, imgData.height); }; } } } }, start: function() { return __async$6(this, null, function* () { this.detail(); }); } }; var __async$5 = (__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 EbaySearch = { loopIsComplete: true, currentPlatform: "ebay", isRun: function() { let run = false; if (window.location.host.indexOf("ebay.") != -1) { run = !/\/(item|trade|checkout|rxo)\//.test(window.location.pathname); } return run; }, isItemLink: function(url) { return /ebay/.test(url) && /\/itm\/[^\/]*?/.test(url); }, pickUpItems: function(selectors, marketplace) { return __async$5(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); logger("info", "search coupon elements======>", elements); const findA = elementObj.findA; elements.forEach((element) => { if (element && ItemSearchBaseObj.isElementDisplayed(element) && !element.getAttribute(ItemSearchBaseObj.searchAttribute)) { const goodsLink = ItemSearchBaseObj.getGoodsLinkByElement(element, findA); const priceQuery = [ "*[class*='detail'] >*[class*='price']", "*[class*='merch-price'] >span" ].join(","); const price = ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery); let id = null; if (this.isItemLink(goodsLink)) { id = ItemSearchBaseObj.getGoodsIdByUrl(goodsLink.getAttribute("href")); } if (id) { items.push({ "id": id, "price": price, "platform": this.currentPlatform, "handler": element, "findA": findA, "from": "search" }); } } }); } }); logger("info", items); if (items.length > 0) { yield this.search(items, marketplace); } } catch (e) { } }); }, search: function(array, marketplace) { return __async$5(this, null, function* () { const groups = ItemSearchBaseObj.calcRequestGroup(array); const len = groups.length; return new Promise((resolve, reject) => { if (len <= 0) { resolve("complete"); return; } const promises = []; for (let i = 0; i < groups.length; i++) { promises.push(this.createItemHtml(groups[i], marketplace)); } Promise.all(promises).then((data) => { resolve("complete"); }); }); }); }, createItemHtml: function(group, marketplace) { return new Promise((resolve, reject) => { try { if (Array.isArray(group) && group.length === 0) { resolve("exception"); return; } let reqId = ""; const platform = group[0].platform; for (var i = 0; i < group.length; i++) { if (group[i].handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { continue; } reqId += group[i].id + ":" + group[i].price + ","; } if (reqId.endsWith(",")) { reqId = reqId.slice(0, -1); } logger("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=9&v=1.0.1"; logger("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { logger("info", "request finish >>>>>>>>>>>>>", data); delete ItemSearchBaseObj.cacheRequestMap[data.requestKey]; if (data.code != "success" || !data.result) { resolve("exception"); return; } const json = JSON.parse(data.result); for (let key in json) { const { encryptLink, tip } = json[key]; const item = group.find((obj) => obj.id === key); if (!item) { continue; } let handler = null, findA = null; if (item.hasOwnProperty("handler") && item.hasOwnProperty("findA")) { handler = item.handler; findA = item.findA; } if (!handler || !findA) { continue; } let decryptUrl = null; if (encryptLink) { try { const decryptLink = atob(encryptLink); decryptUrl = decryptLink.split("").reverse().join(""); } catch (e) { } } const elementA = ItemSearchBaseObj.getGoodsLinkByElement(handler, findA); if (!handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true"); if (tip) { handler.style.position = "relative"; handler.insertAdjacentHTML("beforeend", tip); logger("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); logger("info", "good job >>>>>>>>>>>>>", key); } } } resolve("complete"); }); } catch (e) { resolve("exception"); } }); }, relativeJ: function(handler, decryptUrl) { const clickTipAttribute = "tip-vjd1jd89fcv-i", self = this; let elements = null; if (handler.tagName == "A") { elements = [handler]; } else { elements = handler.querySelectorAll("a"); } elements.forEach((elementA) => { const href = elementA.getAttribute("href"); if (self.isItemLink(href)) { if (elementA.getAttribute(clickTipAttribute)) { return; } elementA.setAttribute(clickTipAttribute, "true"); elementA.addEventListener("click", function(e) { let isPreventDefault = true; const target = e.target; const tagName = target.tagName.toUpperCase(); if (tagName == "A") { const href2 = target.getAttribute("href"); if (!self.isItemLink(href2)) { isPreventDefault = false; } } if (isPreventDefault) { Array.from(target.classList).forEach((className) => { const iscontains = ["btn", "icon"].map((name) => className.indexOf(name) != -1).some((result) => result); if (iscontains) { isPreventDefault = false; } }); } if (isPreventDefault) { e.preventDefault(); e.stopPropagation(); Tools.openInTab(decryptUrl); } }); } }); }, start: function() { return __async$5(this, null, function* () { if (!this.isRun()) return; const marketplace = Ebay.getMarketplace(window.location.href); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(this.currentPlatform, confString); setInterval(() => __async$5(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpItems(selectors, marketplace); this.loopIsComplete = true; } }), 1700); }); } }; var __async$4 = (__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 Lazada = { baseUrl: "https://oversea.mimixiaoke.com", visitUrl: window.location.href, getMarketplace: function(url) { try { const domainParts = new URL(url).hostname.split("."); const countryCode = domainParts[domainParts.length - 1]; return countryCode; } catch (error) { console.log(error); } return null; }, isRun: function() { return /.*\.lazada\..*\/products\/.*-i\d+.*\.html/.test(this.visitUrl); }, detailMyMscanAnalyze: function(result) { return __async$4(this, null, function* () { const { id, iden, marketplace, platform, mount, html, cmd } = result; if (!mount || !html) { return; } if (cmd && cmd.do && cmd.ele) { const cmdElement = yield Tools.waitForElementByInterval(cmd.ele); if (cmdElement) { if (cmd.do == "empty") { cmdElement.innerHTML = ""; } } } const element = yield Tools.mustGetElement(mount); if (!element) { return; } element.insertAdjacentHTML("beforeend", html); const reqImageUrl = this.baseUrl + "/api/coupon/change?id={id}&marketplace={marketplace}&platform={platform}".replace("{id}", id).replace("{marketplace}", marketplace).replace("{platform}", platform); const qrcodeData = yield Tools.crossRequest("GET", reqImageUrl, null); if (!!qrcodeData && qrcodeData.code === "success" && !!qrcodeData.result) { let mscanImg = JSON.parse(qrcodeData.result).mscanImg; if (!!mscanImg) { var canvasElement = document.getElementById("mscan" + iden); if (!!canvasElement) { var cxt = canvasElement.getContext("2d"); var imgData = new Image(); imgData.src = mscanImg; imgData.onload = function() { cxt.drawImage(imgData, 0, 0, imgData.width, imgData.height); }; } } } }); }, detail: function() { return __async$4(this, null, function* () { const marketplace = this.getMarketplace(window.location.href), platform = "lazada"; const ids = Tools.getParamterBySuffix(this.visitUrl); if (!ids) { return; } const reqUrl = this.baseUrl + "/api/coupon/query?ids=" + ids + "&qu=&p=" + platform + "&no=9&v=1.0.1&marketplace=" + marketplace + "&mul=false"; const data = yield Tools.crossRequest("GET", reqUrl, null); if (!!data && data.code === "success" && !!data.result) { const json = JSON.parse(data.result); if (json && json.mscan) { const { distinguish, iden, html, cmd, mount } = json.mscan; const mscanResult = { "id": json.id, "iden": iden, "marketplace": marketplace, "platform": platform, "mount": mount, "html": html, "cmd": cmd }; Tools.loopTask(() => { Tools.distinguishRemoveAndTry(distinguish, () => { this.detailMyMscanAnalyze(mscanResult); }); }); } } const titleElement = document.querySelector(".pdp-mod-product-badge-title"); const priceElement = yield Tools.waitForElementByInterval(".pdp-product-price >span", document.body, false); const imgElement = document.querySelector(".gallery-preview-panel__content >img:last-child"); if (imgElement && priceElement) { const imgSrc = imgElement.getAttribute("src"); const title = titleElement ? titleElement.innerText : "--"; const price = priceElement ? priceElement.innerText : "Unknown"; const goods = { "id": ids, "url": this.visitUrl, "pic": imgSrc, "date": new Date().getTime(), "price": price, "title": title }; GoodsHistroy.push("lazada", goods); } }); }, start: function() { return __async$4(this, null, function* () { if (this.isRun()) { this.detail(); } }); } }; 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 LazadaSearch = { loopIsComplete: true, currentPlatform: "lazada", isRun: function() { let run = false; if (window.location.host.indexOf("lazada.") != -1) { run = !this.isItemLink(window.location.href) && !/\/(\/shipping\\?)\//.test(window.location.pathname); } return run; }, isItemLink: function(url) { return /.*\.lazada\..*\/products\/.*-i\d+.*\.html/.test(url); }, pickUpItems: function(selectors, marketplace) { return __async$3(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); logger("info", "search coupon elements======>", elements); const findA = elementObj.findA; elements.forEach((element) => { if (element && ItemSearchBaseObj.isElementDisplayed(element) && !element.getAttribute(ItemSearchBaseObj.searchAttribute)) { const goodsLink = ItemSearchBaseObj.getGoodsLinkByElement(element, findA); const price = ItemSearchBaseObj.getGoodsPrice(element.innerText); let id = null; if (this.isItemLink(goodsLink)) { id = ItemSearchBaseObj.getGoodsIdByUrl(goodsLink.getAttribute("href")); } if (id) { items.push({ "id": id, "price": price, "platform": this.currentPlatform, "handler": element, "findA": findA, "from": "search" }); } } }); } }); logger("info", items); if (items.length > 0) { yield this.search(items, marketplace); } } catch (e) { } }); }, search: function(array, marketplace) { return __async$3(this, null, function* () { const groups = ItemSearchBaseObj.calcRequestGroup(array); const len = groups.length; return new Promise((resolve, reject) => { if (len <= 0) { resolve("complete"); return; } const promises = []; for (let i = 0; i < groups.length; i++) { promises.push(this.createItemHtml(groups[i], marketplace)); } Promise.all(promises).then((data) => { resolve("complete"); }); }); }); }, createItemHtml: function(group, marketplace) { return new Promise((resolve, reject) => { try { if (Array.isArray(group) && group.length === 0) { resolve("exception"); return; } let reqId = ""; const platform = group[0].platform; for (var i = 0; i < group.length; i++) { if (group[i].handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { continue; } reqId += group[i].id + ":" + group[i].price + ","; } if (reqId.endsWith(",")) { reqId = reqId.slice(0, -1); } logger("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=9&v=1.0.1"; logger("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { logger("info", "request finish >>>>>>>>>>>>>", data); delete ItemSearchBaseObj.cacheRequestMap[data.requestKey]; if (data.code != "success" || !data.result) { resolve("exception"); return; } const json = JSON.parse(data.result); for (let key in json) { const { encryptLink, tip } = json[key]; const { handler, findA } = group.find((obj) => obj.id === key); let decryptUrl = null; if (encryptLink) { try { const decryptLink = atob(encryptLink); decryptUrl = decryptLink.split("").reverse().join(""); } catch (e) { } } const elementA = ItemSearchBaseObj.getGoodsLinkByElement(handler, findA); if (!handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true"); if (tip) { handler.style.position = "relative"; handler.insertAdjacentHTML("beforeend", tip); logger("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); logger("info", "good job >>>>>>>>>>>>>", key); } } } resolve("complete"); }); } catch (e) { resolve("exception"); } }); }, relativeJ: function(handler, decryptUrl) { let selectorA = null; if (handler.tagName == "A") { selectorA = [handler]; } else { selectorA = handler.querySelectorAll("a"); } selectorA.forEach((element_a) => { if (this.isItemLink(element_a.getAttribute("href"))) { element_a.addEventListener("click", function(e) { e.preventDefault(); e.stopPropagation(); Tools.openInTab(decryptUrl); }); } }); }, start: function() { return __async$3(this, null, function* () { if (!this.isRun()) return; const marketplace = Lazada.getMarketplace(window.location.href); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(this.currentPlatform, confString); setInterval(() => __async$3(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpItems(selectors, marketplace); this.loopIsComplete = true; } }), 1700); }); } }; 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 Bestbuy = { baseUrl: "https://oversea.mimixiaoke.com", currentPlatform: "bestbuy", isDetail: function() { const visitUrl = window.location.href; return [/www\.bestbuy\.com\/site\/.*\/\d+\.p/].map((rs) => rs.test(visitUrl)).some((rs) => rs); }, getMarketplace: function(url) { try { const urlObj = new URL(url); const hostname = urlObj.hostname; if (hostname) { return hostname.split(".").slice(-1)[0]; } } catch (error) { } return null; }, detail: function() { return __async$2(this, null, function* () { const validate = this.isDetail(); if (!validate) return; const visitUrl = window.location.href; const id = ItemSearchBaseObj.getGoodsIdByUrl(visitUrl, "p"); if (!id) { return; } const titleElement = document.querySelector(".sku-title"); const priceElement = document.querySelector(".priceView-customer-price >span"); const imgElement = document.querySelector(".thumbnail-list img"); if (imgElement) { const imgSrc = imgElement.getAttribute("src"); const title = titleElement ? titleElement.innerText : "--"; const price = priceElement ? priceElement.innerText : "Unknown"; const goods = { "id": id, "url": visitUrl, "pic": imgSrc, "date": new Date().getTime(), "price": price, "title": title }; GoodsHistroy.push(this.currentPlatform, goods); } const marketplace = this.getMarketplace(visitUrl); const url = this.baseUrl + "/api/coupon/query?ids=" + id + "&qu=&p=" + this.currentPlatform + "&no=9&v=1.0.1&marketplace=" + marketplace + "&mul=false"; const data = yield Tools.crossRequest("GET", url, null); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); yield this.detailAnalyze(json, marketplace); } }); }, detailAnalyze: function(json, marketplace) { return __async$2(this, null, function* () { let couponResult = null; let qrcodeResult = null; if (!!json.data && !!json.data.css && !!json.data.html && !!json.data.handler) { const { handler, css, html, templateId, distinguish } = json.data; GM_addStyle(css); const element = yield Tools.mustGetElement(handler); if (element) { couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish }; } } if (!!json.id && !!json.mscan && !!json.mscan.html && !!json.mscan.mount) { const { iden, html, mount, distinguish } = json.mscan; const id = json.id; const promiseResultArray = []; const elementPromise = Tools.mustGetElement(mount); const reqUrl = this.baseUrl + "/api/coupon/change?id=" + id + "&marketplace=" + marketplace + "&platform=" + this.currentPlatform; const reqPromise = Tools.crossRequest("GET", reqUrl, null); promiseResultArray.push(elementPromise, reqPromise); const allResult = yield Promise.all(promiseResultArray); let element = null, qrcodeData = null; for (let i = 0; i < allResult.length; i++) { if (allResult[i]) { if (allResult[i].hasOwnProperty("code")) { qrcodeData = allResult[i]; } else { element = allResult[i]; } } } if (element && qrcodeData) { qrcodeResult = { "element": element, "html": html, "iden": iden, "qrcodeData": qrcodeData, "distinguish": distinguish }; } } Tools.loopTask(() => { if (couponResult) { Tools.distinguishRemoveAndTry(couponResult.distinguish, () => { this.detailCouponAnalyze(couponResult); }); } if (qrcodeResult) { Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => { this.detailMscanAnalyze(qrcodeResult); }); } }); }); }, detailCouponAnalyze: function(result) { const { element, html, templateId } = result; element.insertAdjacentHTML("afterend", html); const templateIdEle = document.querySelector("div[id='" + templateId + "']"); if (templateIdEle) { const couponCodeElement = templateIdEle.querySelector(".coupon-code"); const promoCode = Tools.decryptStr(couponCodeElement.getAttribute("data-encryptcode")); templateIdEle.addEventListener("click", () => { GM_setClipboard(promoCode, "txt", () => { Toast.show({ "message": eLanguage.operat.copied, "background": "#D3031C" }); }); }); } }, detailMscanAnalyze: function(result) { const { element, html, qrcodeData, iden } = result; element.insertAdjacentHTML("afterend", html); if (!!qrcodeData && qrcodeData.code === "success" && !!qrcodeData.result) { const mscanImg = JSON.parse(qrcodeData.result).mscanImg; if (!!mscanImg) { const canvasElement = document.getElementById("mscan" + iden); if (canvasElement) { var cxt = canvasElement.getContext("2d"); var imgData = new Image(); imgData.src = mscanImg; imgData.onload = function() { cxt.drawImage(imgData, 0, 0, imgData.width, imgData.height); }; } } } }, start: function() { return __async$2(this, null, function* () { this.detail(); }); } }; 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 BestbuySearch = { loopIsComplete: true, currentPlatform: "bestbuy", isRun: function() { return /https:\/\/www\.bestbuy\.com\/site\/searchpage\.jsp/.test(window.location.href); }, isItemLink: function(url) { return /\/site\/.*\/\d+\.p/.test(url); }, pickUpItems: function(selectors, marketplace) { return __async$1(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); logger("info", "search coupon elements======>", elements); const findA = elementObj.findA; elements.forEach((element) => { if (element && ItemSearchBaseObj.isElementDisplayed(element) && !element.getAttribute(ItemSearchBaseObj.searchAttribute)) { const goodsLink = ItemSearchBaseObj.getGoodsLinkByElement(element, findA); const priceQuery = [ "div[id*='pricing-price-']" ].join(","); const price = ItemSearchBaseObj.getGoodsPrice( ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery) ); let id = null; if (this.isItemLink(goodsLink)) { id = ItemSearchBaseObj.getGoodsIdByUrl(goodsLink.getAttribute("href"), "p"); } if (id) { items.push({ "id": id, "price": price, "platform": this.currentPlatform, "handler": element, "findA": findA, "from": "search" }); } } }); } }); logger("info", items); if (items.length > 0) { yield this.search(items, marketplace); } } catch (e) { } }); }, search: function(array, marketplace) { return __async$1(this, null, function* () { const groups = ItemSearchBaseObj.calcRequestGroup(array); const len = groups.length; return new Promise((resolve, reject) => { if (len <= 0) { resolve("complete"); return; } const promises = []; for (let i = 0; i < groups.length; i++) { promises.push(this.createItemHtml(groups[i], marketplace)); } Promise.all(promises).then((data) => { resolve("complete"); }); }); }); }, createItemHtml: function(group, marketplace) { return new Promise((resolve, reject) => { try { if (Array.isArray(group) && group.length === 0) { resolve("exception"); return; } let reqId = ""; const platform = group[0].platform; for (var i = 0; i < group.length; i++) { if (group[i].handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { continue; } reqId += group[i].id + ":" + group[i].price + ","; } if (reqId.endsWith(",")) { reqId = reqId.slice(0, -1); } logger("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=9&v=1.0.1"; logger("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { logger("info", "request finish >>>>>>>>>>>>>", data); delete ItemSearchBaseObj.cacheRequestMap[data.requestKey]; if (data.code != "success" || !data.result) { resolve("exception"); return; } const json = JSON.parse(data.result); for (let key in json) { const { encryptLink, tip } = json[key]; const item = group.find((obj) => obj.id === key); if (!item) { continue; } let handler = null, findA = null; if (item.hasOwnProperty("handler") && item.hasOwnProperty("findA")) { handler = item.handler; findA = item.findA; } if (!handler || !findA) { continue; } let decryptUrl = null; if (encryptLink) { try { const decryptLink = atob(encryptLink); decryptUrl = decryptLink.split("").reverse().join(""); } catch (e) { } } const elementA = ItemSearchBaseObj.getGoodsLinkByElement(handler, findA); if (!handler.getAttribute(ItemSearchBaseObj.searchAttribute)) { handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true"); if (tip) { handler.style.position = "relative"; handler.insertAdjacentHTML("beforeend", tip); logger("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); logger("info", "good job >>>>>>>>>>>>>", key); } } } resolve("complete"); }); } catch (e) { resolve("exception"); } }); }, relativeJ: function(handler, decryptUrl) { const clickTipAttribute = "tip-vjd1jd89fcv-i", self = this; let elements = null; if (handler.tagName == "A") { elements = [handler]; } else { elements = handler.querySelectorAll("a"); } elements.forEach((elementA) => { const href = elementA.getAttribute("href"); if (self.isItemLink(href)) { if (elementA.getAttribute(clickTipAttribute)) { return; } elementA.setAttribute(clickTipAttribute, "true"); elementA.addEventListener("click", function(e) { let isPreventDefault = true; const target = e.target; const tagName = target.tagName.toUpperCase(); if (tagName == "A") { const href2 = target.getAttribute("href"); if (!self.isItemLink(href2)) { isPreventDefault = false; } } if (isPreventDefault) { Array.from(target.classList).forEach((className) => { const iscontains = ["btn", "icon"].map((name) => className.indexOf(name) != -1).some((result) => result); if (iscontains) { isPreventDefault = false; } }); } if (isPreventDefault) { e.preventDefault(); e.stopPropagation(); Tools.openInTab(decryptUrl); } }); } }); }, start: function() { return __async$1(this, null, function* () { if (!this.isRun()) return; const marketplace = Bestbuy.getMarketplace(window.location.href); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(this.currentPlatform, confString); setInterval(() => __async$1(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpItems(selectors, marketplace); this.loopIsComplete = true; } }), 1700); }); } }; 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) { } 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, "<") }); const downloadButton = document.createElement("button"); downloadButton.id = "ytdl-download-button"; downloadButton.classList.add("ytp-button", markName); downloadButton.title = language.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) { } 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": language.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, GoodsHistroy, Aliexpress: { Aliexpress, AliexpressSearch }, Ebay: { Ebay, EbaySearch }, Lazada: { Lazada, LazadaSearch }, Bestbuy: { Bestbuy, BestbuySearch } }; 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 }); }, aliexpress: function() { AllModules.Aliexpress.Aliexpress.start(); AllModules.Aliexpress.AliexpressSearch.start(); AllModules.GoodsHistroy.start("aliexpress"); }, ebay: function() { AllModules.Ebay.Ebay.start(); AllModules.Ebay.EbaySearch.start(); AllModules.GoodsHistroy.start("ebay"); }, lazada: function() { AllModules.Lazada.Lazada.start(); AllModules.Lazada.LazadaSearch.start(); AllModules.GoodsHistroy.start("lazada"); }, bestbuy: function() { AllModules.Bestbuy.Bestbuy.start(); AllModules.Bestbuy.BestbuySearch.start(); AllModules.GoodsHistroy.start("bestbuy"); }, youtube: function() { AllModules.Youtube.YoutubeDownload.start(); }, tiktok: function() { AllModules.Tiktok.start(); }, cobalt: function() { AllModules.CobaltDownloader.start(); }, unknown: function() { }, start: function() { Toast.initStyle(); const platform = Tools.platform(); this[platform](); } }; Init.start(); }());