// ==UserScript== // @name Online shopping assistant & Automatically query coupons & Save money // @name:ar مساعد التسوق عبر الإنترنت & الاستعلام عن القسائم تلقائيًا & توفير المال // @name:bg Онлайн асистент за пазаруване & Автоматично търсене на купони & Спестяване на пари // @name:ckb یارمەتی کڕینی ئۆنلاین & داواکاری خۆکارانەی کوپۆنەکان & پارە پاشەکەوتکردن // @name:cs Online nákupní asistent & Automatické vyhledávání kupónů & Šetřete peníze // @name:da Online shoppingassistent & Automatisk søgning efter kuponer & Spar penge // @name:de Online-Shopping-Assistent & Automatische Gutscheinsuche & Geld sparen // @name:el Βοηθός διαδικτυακών αγορών & Αυτόματη αναζήτηση κουπονιών & Εξοικονόμηση χρημάτων // @name:en Online shopping assistant & Automatically query coupons & Save money // @name:eo Reta aĉethelpilo & Aŭtomata kuponserĉado & Ŝparu monon // @name:es Asistente de compras online & Búsqueda automática de cupones & Ahorrar dinero // @name:es-419 Asistente de compras en línea & Consulta automática de cupones & Ahorra dinero // @name:fi Verkkokauppa-avustaja & Automaattinen kuponkihaku & Säästä rahaa // @name:fr Assistant de shopping en ligne & Recherche automatique de coupons & Économiser de l'argent // @name:fr-CA Assistant d'achat en ligne & Recherche automatique de coupons & Économiser de l'argent // @name:he עוזר קניות אונליין & חיפוש קופונים אוטומטי & לחסוך כסף // @name:hr Internetski asistent za kupovinu & Automatsko pretraživanje kupona & Uštedite novac // @name:hu Online vásárlási asszisztens & Kuponok automatikus lekérdezése & Pénzmegtakarítás // @name:id Asisten belanja online & Pencarian kupon otomatis & Hemat uang // @name:it Assistente per lo shopping online & Ricerca automatica di coupon & Risparmiare denaro // @name:ja オンラインショッピングアシスタント & クーポンの自動検索 & 節約 // @name:ka ონლაინ შოპინგ ასისტენტი & ავტომატური კუპონის ძიება & დაზოგეთ ფული // @name:ko 온라인 쇼핑 도우미 & 쿠폰 자동 검색 & 돈 절약 // @name:nb Online shoppingassistent & Automatisk kupongsøk & Spar penger // @name:nl Online winkelassistent & Automatisch coupons opzoeken & Geld besparen // @name:pl Asystent zakupów online & Automatyczne wyszukiwanie kuponów & Oszczędzaj pieniądze // @name:pt-BR Assistente de compras online & Pesquisa automática de cupons & Economize dinheiro // @name:ro Asistent de cumpărături online & Căutare automată de cupoane & Economisiți bani // @name:ru Помощник для онлайн-покупок & Автоматический поиск купонов & Экономия денег // @name:sk Online nákupný asistent & Automatické vyhľadávanie kupónov & Šetrite peniaze // @name:sr Асистент за онлајн куповину & Аутоматско претраживање купона & Уштедите новац // @name:sv Online shoppingassistent & Automatisk kupongsökning & Spara pengar // @name:th ผู้ช่วยช้อปปิ้งออนไลน์ & ค้นหาคูปองอัตโนมัติ & ประหยัดเงิน // @name:tr Çevrimiçi alışveriş asistanı & Otomatik kupon sorgulama & Para tasarrufu // @name:uk Помічник для онлайн-шопінгу & Автоматичний пошук купонів & Економія грошей // @name:ug تور سودا سېتىۋېلىش ياردەمچىسى & ئاپتوماتىك كۇپون ئىزدەش & پۇل تېجەش // @name:vi Trợ lý mua sắm trực tuyến & Tự động tìm kiếm mã giảm giá & Tiết kiệm tiền // @description Automatically search for coupons on popular shopping platforms to help you find the best deals on the products you need, without overspending. Currently supports: Aliexpress, Lazada, eBay, Amazon, and more. // @description:ar البحث التلقائي عن القسائم على منصات التسوق الشهيرة لمساعدتك في العثور على أفضل العروض للمنتجات التي تحتاجها، دون إنفاق مبالغ زائدة. يدعم حاليًا: علي إكسبرس، لازادا، إيباي، أمازون والمزيد. // @description:bg Автоматично търсене на купони на популярни търговски платформи, за да ви помогне да намерите най-добрите оферти за продуктите, от които се нуждаете, без да харчите прекалено много. В момента поддържа: Aliexpress, Lazada, eBay, Amazon и други. // @description:ckb داواکاری خۆکارانەی کوپۆنەکان لە سەردەمی فەرەشەکانەوە بۆ یارمەتی کردنی تۆ لە دۆزینەوەی باشترین بەرهەمهاتەکان بۆ بەرهەمی پێویستەکانت، بێ گەورە کردنی ھەزەرەکان. ئیشکراوی ئێستا: Aliexpress، Lazada، eBay، Amazon و زۆرتر. // @description:cs Automatické vyhledávání kupónů na populárních nákupních platformách, které vám pomohou najít nejlepší nabídky pro produkty, které potřebujete, aniž byste přeplatili. Momentálně podporuje: Aliexpress, Lazada, eBay, Amazon a další. // @description:da Automatisk søgning efter kuponer på populære shoppingplatforme, der hjælper dig med at finde de bedste tilbud på de produkter, du har brug for, uden at bruge for meget. Understøtter i øjeblikket: Aliexpress, Lazada, eBay, Amazon og mere. // @description:de Automatisches Suchen nach Gutscheinen auf beliebten Shopping-Plattformen, um Ihnen zu helfen, die besten Angebote für die Produkte zu finden, die Sie benötigen, ohne zu viel auszugeben. Unterstützt derzeit: Aliexpress, Lazada, eBay, Amazon und mehr. // @description:el Αυτόματη αναζήτηση κουπονιών σε δημοφιλείς πλατφόρμες αγορών για να σας βοηθήσει να βρείτε τις καλύτερες προσφορές για τα προϊόντα που χρειάζεστε, χωρίς να ξοδέψετε υπερβολικά. Υποστηρίζει αυτή τη στιγμή: Aliexpress, Lazada, eBay, Amazon και άλλα. // @description:en Automatically search for coupons on popular shopping platforms to help you find the best deals on the products you need, without overspending. Currently supports: Aliexpress, Lazada, eBay, Amazon, and more. // @description:eo Aŭtomate serĉi kuponojn en popularaj aĉetplatformoj por helpi vin trovi la plej bonajn oferton por la produktoj, kiujn vi bezonas, sen tro elspezi. Nuntempe subtenas: Aliexpress, Lazada, eBay, Amazon kaj aliaj. // @description:es Buscar automáticamente cupones en plataformas de compras populares para ayudarte a encontrar las mejores ofertas de los productos que necesitas, sin gastar de más. Actualmente es compatible con: Aliexpress, Lazada, eBay, Amazon y más. // @description:es-419 Buscar automáticamente cupones en plataformas de compras populares para ayudarte a encontrar las mejores ofertas de los productos que necesitas, sin gastar de más. Actualmente es compatible con: Aliexpress, Lazada, eBay, Amazon y más. // @description:fi Automaattinen kuponkien haku suosituilla ostosalustoilla auttaaksesi löytämään parhaat tarjoukset tarvitsemasi tuotteista ilman, että käytät liikaa rahaa. Tällä hetkellä tuetaan: Aliexpress, Lazada, eBay, Amazon ja muita. // @description:fr Recherche automatique de coupons sur des plateformes de shopping populaires pour vous aider à trouver les meilleures offres sur les produits dont vous avez besoin, sans trop dépenser. Actuellement pris en charge : Aliexpress, Lazada, eBay, Amazon et plus. // @description:fr-CA Recherche automatique de coupons sur des plateformes de shopping populaires pour vous aider à trouver les meilleures offres sur les produits dont vous avez besoin, sans trop dépenser. Actuellement pris en charge : Aliexpress, Lazada, eBay, Amazon et plus. // @description:he חיפוש אוטומטי של קופונים בפלטפורמות קניות פופולריות כדי לעזור לך למצוא את ההצעות הטובות ביותר למוצרים שאתה צריך, מבלי להוציא יותר מדי. כרגע תומך ב: Aliexpress, Lazada, eBay, Amazon ועוד. // @description:hr Automatsko pretraživanje kupona na popularnim shopping platformama kako bi vam pomoglo da pronađete najbolje ponude za proizvode koje trebate, bez prekomjernog trošenja. Trenutno podržava: Aliexpress, Lazada, eBay, Amazon i još mnogo toga. // @description:hu Automatikus kupon keresés népszerű vásárlási platformokon, hogy segítsen megtalálni a legjobb ajánlatokat a szükséges termékekhez, anélkül, hogy túl sokat költene. Jelenleg támogatja: Aliexpress, Lazada, eBay, Amazon és mások. // @description:id Cari kupon secara otomatis di platform belanja populer untuk membantu Anda menemukan penawaran terbaik untuk produk yang Anda butuhkan, tanpa membelanjakan terlalu banyak. Saat ini mendukung: Aliexpress, Lazada, eBay, Amazon, dan lainnya. // @description:it Cerca automaticamente i coupon su piattaforme di shopping popolari per aiutarti a trovare le migliori offerte sui prodotti di cui hai bisogno, senza spendere troppo. Attualmente supporta: Aliexpress, Lazada, eBay, Amazon e altro. // @description:ja 人気のショッピングプラットフォームでクーポンを自動的に検索し、必要な製品の最良の取引を見つけるのに役立ちます。無駄遣いを防ぎます。現在対応しているプラットフォーム: Aliexpress、Lazada、eBay、Amazon など。 // @description:ka პოპულარული შოპინგ პლატფორმებზე ავტომატური კუპონის ძიება, რათა დაგეხმაროთ საუკეთესო შეთავაზებების პოვნაში თქვენთვის საჭირო პროდუქციისთვის, ზედმეტი ხარჯების გარეშე. ამჟამად მხარდაჭერილია: Aliexpress, Lazada, eBay, Amazon და სხვა. // @description:ko 인기 쇼핑 플랫폼에서 자동으로 쿠폰을 검색하여 필요한 제품에 대한 최상의 거래를 찾는 데 도움을 줍니다. 과도한 지출 없이. 현재 지원되는 플랫폼: Aliexpress, Lazada, eBay, Amazon 등. // @description:nb Automatisk søk etter kuponger på populære shoppingplattformer for å hjelpe deg med å finne de beste tilbudene på produktene du trenger, uten å bruke for mye. Støtter for øyeblikket: Aliexpress, Lazada, eBay, Amazon og mer. // @description:nl Automatisch zoeken naar coupons op populaire winkelplatforms om je te helpen de beste aanbiedingen te vinden voor de producten die je nodig hebt, zonder te veel uit te geven. Ondersteunt momenteel: Aliexpress, Lazada, eBay, Amazon en meer. // @description:pl Automatyczne wyszukiwanie kuponów na popularnych platformach zakupowych, które pomogą Ci znaleźć najlepsze oferty na produkty, których potrzebujesz, bez przepłacania. Obecnie obsługiwane: Aliexpress, Lazada, eBay, Amazon i inne. // @description:pt-BR Buscar automaticamente cupons nas plataformas de compras populares para ajudá-lo a encontrar as melhores ofertas nos produtos que você precisa, sem gastar demais. Atualmente suporta: Aliexpress, Lazada, eBay, Amazon e mais. // @description:ro Căutare automată de cupoane pe platformele populare de cumpărături pentru a te ajuta să găsești cele mai bune oferte la produsele de care ai nevoie, fără a cheltui prea mult. În prezent suportă: Aliexpress, Lazada, eBay, Amazon și altele. // @description:ru Автоматический поиск купонов на популярных торговых платформах, чтобы помочь вам найти лучшие предложения на необходимые товары, не переплачивая. В настоящее время поддерживает: Aliexpress, Lazada, eBay, Amazon и другие. // @description:sk Automatické vyhľadávanie kupónov na populárnych nákupných platformách, ktoré vám pomôžu nájsť najlepšie ponuky na produkty, ktoré potrebujete, bez zbytočných výdavkov. Momentálne podporuje: Aliexpress, Lazada, eBay, Amazon a ďalšie. // @description:sr Аутоматско претраживање купона на популарним платформама за куповину како би вам помогло да пронађете најбоље понуде за производе који су вам потребни, без претераног трошења. Тренутно подржава: Aliexpress, Lazada, eBay, Amazon и остало. // @description:sv Automatiskt söka efter kuponger på populära shoppingplattformar för att hjälpa dig att hitta de bästa erbjudandena på de produkter du behöver, utan att överskrida budgeten. För närvarande stöds: Aliexpress, Lazada, eBay, Amazon och fler. // @description:th ค้นหาคูปองอัตโนมัติในแพลตฟอร์มช็อปปิ้งยอดนิยมเพื่อช่วยให้คุณค้นหาข้อเสนอที่ดีที่สุดสำหรับสินค้าที่คุณต้องการโดยไม่ต้องใช้จ่ายเกินไป ขณะนี้รองรับ: Aliexpress, Lazada, eBay, Amazon และอื่นๆ // @description:tr Popüler alışveriş platformlarında otomatik olarak kupon arayarak, ihtiyacınız olan ürünler için en iyi fırsatları bulmanıza yardımcı olur, fazla harcama yapmadan. Şu anda desteklenenler: Aliexpress, Lazada, eBay, Amazon ve daha fazlası. // @description:uk Автоматичний пошук купонів на популярних торгових платформах, щоб допомогти вам знайти найкращі пропозиції на товари, які вам потрібні, без зайвих витрат. Наразі підтримується: Aliexpress, Lazada, eBay, Amazon та інші. // @description:ug پاپۇلار سودا سېتىش پلاتفورمالىرىدا ئاپتوماتىك كۇپون ئىزدەش ئارقىلىق، پەقەت مۇھتاج بولغان مەھسۇلاتلارغا ئەڭ ياخشى پەقەتلەرنى تاپشۇرۇشقا ياردەم بېرىدۇ، ھىچ بىر ئاشىق پۇل چىقارماي. ھازىر كۆرسىتىلىدىغان: Aliexpress، Lazada، eBay، Amazon ۋە باشقا. // @description:vi Tìm kiếm tự động mã giảm giá trên các nền tảng mua sắm phổ biến để giúp bạn tìm được những ưu đãi tốt nhất cho sản phẩm bạn cần, mà không phải chi tiêu quá mức. Hiện tại hỗ trợ: Aliexpress, Lazada, eBay, Amazon và nhiều hơn nữa. // @namespace Thaddeus_ecommerce_NameScope // @version 1.1.3 // @author Thaddeus310 // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAABAZJREFUWEetl1lME1EUhv+htbaISamoVTC0WrcgASOSlFCpuEfRmPigicaghgeXRI2JiTy4xVfikzExLvhkJGpiTYi4FUQeDMEG3CXp4FpQaEW0LKWjd2Camemdxep96EzSc+/5zn/PPecOg78Ypb7LXgbccdEU7/i7nzwZcI3k2VSx+4TeZRk9hst8F09wYMSONacx4E7qAVEFSMWxnEwLRBHA47v0CIAgMb+uPT0DoV8DmtEvnmLHs96Q2M7/uGLXctrEJADRPic5X5czF/Uf36lCEOd2Swae9YWS7Dgwy5srKvl8EUYSgMd3iVMKUUkBvcr8UTRJCQkATXYtvUnEZMgkV5smgUgApJpwJPoZRHLpnqtyixMzAaAmvZYKqfz/uGIX75v/oUVfVlMN49QpMGTZUllfMmfo1Tt0ucvBuleIkm+sTvAAtOgPtlVjQiSOaPck5M+0pAwxOO0reuNRXO3fKAEgCxIVGKW933bjGKZO5jASNiPPNillgLqOMIqLR1BnWJMEQI4lFcD6IYgt7bUozIsi0GTGHFPqCnSZf2B69ih8g0Vo82yRB+JnaEdvU9s5zI6+hyE+CoNRsSzoUmU0NpbnwR4LHhRXIjLLKamQVICq9lPYup7V5UCPEWNyIPjyMw73HKUC8CGKq9l/B8jwIhhooQGAKMAJzoWnHOD+DRvYThP2HJU0GMXgie1Q2IKJmVE4XMNgNAD4rqekAFmsoW4uvvT0Yee+Xn5BrVFfa0dsxIV5BR2Yv/Q75Fsg8kVPQrkC9dc9WLB6B5zWKi3f/P+NDxchO/8IjN+rxhQQ5YCz0C3uHfoAGm67YbS5UV5aowug9sISxAbN2H3gCW8v3gLz/PxE7yA9gRnv/2QbEkOuwJuADd04Bq7vCsrKn2tCBEP70Rn4hlVrryUBiI8hD0ArxbRTcPfOdpizbMjNOq+aB43NGxBPcyErfgv5pV2qAHwpJhbyckwD6GOdCHzcDAPeItfeQIUgzoncQ6HWRPTyLRAUEFoytR0r1YGO5lx8jnhgySkENzB+sxpmAZODT7TRmBE/2RcoKemEzRFMbBXtGErasVwFtUJElHjdOg0/M5xIM8aQlp6DWH8IsYEvKHD1I9MRhMUakeSJHIB6IRnPBb4m6KmEBISMwYgVZmsEFms4ybFAIQOgX8kEY9KcqtpPef9rLxBVQt/e05J7KPVaXj1w5tHKhZ2ax02vgVCIzrRsOHSl5uZZ8TzFD5MXTx3heSbWqteJmt3bYUckr5jNpNmofprdaynye9Nby/4Fwv+rqHFVSavkI0eXAmKjVEA+xaaz2YbuygmLIfkSkgej6+tYmERAyPtM47cC8hS2iEgs2HQMu05uLb0v2Wc1BX8DMGUKxDW5sRoAAAAASUVORK5CYII= // @match *://*/* // @include /^https:\/\/([\w-]+\.)?aliexpress\.(ru|us|com)\/*/ // @include /^https:\/\/([\w-]+\.)?lazada\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?shopee\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?banggood\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?amazon\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?ebay\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?bestbuy\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?airbaltic\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?edureka\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?ranavat\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?alibaba\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wish\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?ticketmaster\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wilson\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wilsonsleather\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?pictarine\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?suiteness\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?treatwell\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?trip\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?samsung\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?daraz\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wildberries\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?shopee\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?walmart\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?temu\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?noon\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?ozon\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?allegro\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?rakuten\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?zalando\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?shein\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?expedia\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?booking\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?agoda\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?hotels\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?hoteis\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?hoteles\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?tripadvisor\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?skyscanner\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?target\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?etsy\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?nike\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?adidas\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?meesho\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?abritel\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?bookabach\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?fewo-direkt\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?stayz\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?mercadolibre\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?magazineluiza\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wildberries\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?zalando\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?daraz\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?advertiser\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?namshi\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?sivvi\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?vrbo\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wotif\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?ajio\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?flipkart\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?myntra\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?cex\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?changelly\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?kucoin\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?paxful\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?htx\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?mexc\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?coinmama\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?gate\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?bitget\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?freebitco\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?bybit\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?crypto\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?okx\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?coinbase\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?binance\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?wazirx\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?coindcx\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?zebpay\.[\w.-]+([/?#].*)?$/ // @include /^https:\/\/([\w-]+\.)?bitbns\.[\w.-]+([/?#].*)?$/ // @include /^https?:\/\/(www\.)?google\.[a-z]{2,3}(\.[a-z]{2})?\/search\?/ // @include /^https?:\/\/(?:www|cn)?\.?bing\.com\/search\?.*/ // @include *://www.jtmate.com/mid/merge** // @exclude *://www.lazada.com/* // @exclude *://shopee.com/* // @connect oversea.mimixiaoke.com // @connect jtmate.com // @license MIT // @run-at document-idle // @antifeature referral-link // @noframes // @grant GM_registerMenuCommand // @grant GM_openInTab // @grant GM.openInTab // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_setClipboard // @downloadURL none // ==/UserScript== (function () { 'use strict'; /*! * Copyright (c) 2024 - 2025, Thaddeus310 & PeterParker. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ const ScriptConst = { "lang": (navigator.language || navigator.userLanguage || "").slice(0, 2).toLowerCase() || "en", "isDev": false, "isDebug": false, "version": "1.0.1", "number": "10", "currentHost": window.location.host, "currentUrl": window.location.href }; const PlatformConst = { "x": { "p": "x", "match": /twitter|x\.com$/ }, "youtube": { "p": "youtube", "match": /youtube\.com$/ }, "tiktok": { "p": "tiktok", "match": /www\.tiktok\.com/ }, "cobalt": { "p": "cobalt", "match": /cobalt\.tools/ } }; var __async$o = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; const Logger = { log: function(level = "info", ...messages) { } }; const Tools = { decryptStr: function(str) { try { if (!str) { return str; } let result = atob(str); return result.split("").reverse().join(""); } catch (e) { } return null; }, encryptStr: function(str) { try { if (!str) { return str; } let result = str.split("").reverse().join(""); return btoa(result); } catch (e) { } return null; }, getOtherPlatform: function() { let platform = null; const currentHost = window.location.host; for (let key in PlatformConst) { if (PlatformConst[key].match.test(currentHost)) { platform = PlatformConst[key].p; break; } } return platform; }, removeAnchorsByNode: function(node) { const tagName = node.tagName; if (!tagName) return; const exist = ["A", "IMG", "DIV", "SPAN", "LABEL", "TABLE", "TR", "TD", "CANVAS"].some((name) => name === tagName); if (exist) { node.removeAttribute("data-spm-anchor-id"); for (let i = 0; i < node.childNodes.length; i++) { this.removeAnchorsByNode(node.childNodes[i]); } } }, openInTab: function(url, options = { "active": true, "insert": true, "setParent": true }) { if (typeof GM_openInTab === "function") { GM_openInTab(url, options); } else { GM.openInTab(url, options); } }, onPageLoad: function(callback) { if (document.readyState === "complete") { callback(); } else { window.addEventListener("DOMContentLoaded", callback, { once: true }); window.addEventListener("load", callback, { once: true }); } }, request: function(method, url, param, headers = { "Content-Type": "application/json;charset=UTF-8" }, timeout = 20 * 1e3) { if (!url) { return Promise.reject({ "code": "exception", "result": null }); } return new Promise((resolve, reject) => { const config = { method: method.toUpperCase(), url, timeout, onload: function(response) { if (response.status >= 200 && response.status < 300) { resolve({ "code": "success", "result": response.responseText }); } else { reject({ "code": "error", "result": response.statusText }); } }, ontimeout: function(error) { reject({ "code": "error", "result": error }); }, onerror: function(error) { reject({ "code": "error", "result": error }); } }; if (config.method === "POST") { config.headers = headers != null ? headers : { "Content-Type": "application/json" }; if (JSON.stringify(config.headers).indexOf("application/json") != -1) { config.data = JSON.stringify(param); } else { config.data = param; } } else if (config.method === "GET") { config.headers = headers != null ? headers : { "Content-Type": "application/json" }; config.data = param; } GM_xmlhttpRequest(config); }); }, crossRequest: function(method = "GET", url, param = {}, headers = { "Content-Type": "application/json;charset=UTF-8" }, timeout = 20 * 1e3) { if (!url) { return Promise.reject({ "code": "exception", "result": null }); } const config = { method: method.toUpperCase(), headers }; const controller = new AbortController(); const signal = controller.signal; config.signal = signal; if (config.method === "POST") { config.headers = headers != null ? headers : { "Content-Type": "application/json" }; config.body = JSON.stringify(param); } const timeoutId = setTimeout(() => controller.abort(), timeout); return fetch(url, config).then((response) => response.ok ? response.text() : Promise.reject(response.statusText)).then((result) => { clearTimeout(timeoutId); return { "code": "success", "result": result }; }).catch((error) => { clearTimeout(timeoutId); if (error.name === "AbortError") { return { "code": "error", "result": "Request timeout" }; } return { "code": "error", "result": error }; }); }, getGoodsIdByLink: function(url = window.location.href) { if (url.indexOf("?") != -1) { url = url.split("?")[0]; } if (url.indexOf("#") != -1) { url = url.split("#")[0]; } const suffix = "html|htm|id|p"; let regex = new RegExp("\\/([^\\/]*?)\\.(" + suffix + ")"); if (/lazada\./.test(url)) { regex = new RegExp("-i(\\d+)(?:-s(\\d+))?\\.html"); } else if (/ebay\./.test(url)) { regex = new RegExp("\\/itm\\/(\\d+)"); } else if (/banggood\./.test(url)) { regex = new RegExp("-p-(\\d+)\\.html"); } 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$o(this, null, function* () { const getElements = (handler2) => __async$o(this, null, function* () { const promiseArray = []; const handlers = handler2.split("@"); for (let i = 0; i < handlers.length; i++) { const eleName = handlers[i]; if (!eleName) { continue; } if (eleName == "body") { promiseArray.push( new Promise((resolve, reject) => { resolve(document.body); }) ); } else if (eleName == "html") { promiseArray.push( new Promise((resolve, reject) => { resolve(document.html); }) ); } else { promiseArray.push(this.waitForElementByInterval(eleName, document.body, true, 10, 1500)); } } let element2 = yield Promise.race(promiseArray); return element2; }); let element = yield getElements(handler); return new Promise((resolve, reject) => { if (element) { resolve(element); return; } const waitInterval = setInterval(() => { element = getElements(handler); if (element) { clearInterval(waitInterval); resolve(element); return; } }, 2e3); }); }); }, loopTask: function(callback, delay = 1500) { callback(); setInterval(() => { callback(); }, delay); }, distinguishRemoveAndTry: function(distinguish, callback) { const distinguishElements = distinguish.map((name) => document.querySelector("*[name='" + name + "']")); const validateRs = distinguishElements.some((ele) => ele === null || ele === void 0); if (validateRs) { distinguishElements.reverse().forEach((element) => { if (element) { element.remove(); } }); callback(); } }, getDomain: function(url) { try { const hostname = new URL(url).hostname; const parts = hostname.split("."); if (parts.length > 2) { return `${parts[parts.length - 2]}.${parts[parts.length - 1]}`; } return hostname; } catch (error) { return null; } }, getCommonMarketplace: function(url = window.location.href) { try { const domainParts = new URL(url).hostname.split("."); const countryCode = domainParts[domainParts.length - 1]; return countryCode; } catch (error) { } return null; } }; const Toast = { show: function(params) { let time = params.time; let background = params.background; let color = params.color; let position = params.position; let defaultMarginValue = 50; if (time == void 0 || time == "") { time = 1500; } if (position == void 0 || position == "") { position = "center-bottom"; } const style = document.createElement("style"); style.textContent = `@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-o-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-ms-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-o-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-ms-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.toast-style-kk998y{position:fixed;background:rgba(0,0,0,0.7);color:#fff;font-size:14px;line-height:1;padding:10px;border-radius:3px;left:50%;transform:translateX(-50%);-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-o-transform:translateX(-50%);-ms-transform:translateX(-50%);z-index:999999999999999999999999999;white-space:nowrap}.fadeOut{animation:fadeOut .5s}.fadeIn{animation:fadeIn .5s}`; const el = document.createElement("div"); if (background != void 0 && background != "") { el.style.backgroundColor = background; } if (color != void 0 && color != "") { el.style.color = color; } el.setAttribute("class", "toast-style-kk998y"); el.innerText = params.message; el.style.zIndex = 999999999; if (position === "center-bottom") { el.style.bottom = defaultMarginValue + "px"; } else { el.style.top = defaultMarginValue + "px"; } document.body.appendChild(el); document.head.appendChild(style); el.classList.add("fadeIn"); setTimeout(function() { el.classList.remove("fadeIn"); el.classList.add("fadeOut"); el.addEventListener("animationend", function() { document.body.removeChild(el); document.head.removeChild(style); }); el.addEventListener("webkitAnimationEnd", function() { document.body.removeChild(el); document.head.removeChild(style); }); }, time); } }; const SupportData = { supports: null, support: null }; const StorageKeys = { activatePositionTop: "inspect_activate_position_top", token: "inspect_token", exchangeInfo: "exchange_info", supports: "supports_key", featureControl: { windowShow: "window_show" }, history: { goodsHistory: "goooods_history_key", offset: "goooods_wrapper_key", maximumRecordsKey: "goooods_max_records_key" }, langue: { custom: "custom_langue_key", objects: "langue_data_objects_key" } }; const DefaultValue = { lang: ScriptConst.lang, history: { historyStorage: { "aliexpress": [], "amazon": [], "shein": [], "shopee": [], "lazada": [], "ebay": [], "bestbuy": [], "banggood": [], "wish": [] }, offsetWrapper: { right: 10, bottom: 10 }, records: { min: 10, max: 500, default: 100 }, toolbarGoodsNum: 4 }, exchangeInfoLocal: { certificate: "https://www.jtmate.com/api/certificate", redirect: "https://www.jtmate.com/mid/redirect?url=" }, updateSupportsDelay: 1e3 * 60 * 5, updateExchangeInfoDelay: 1e3 * 60 * 10 }; const getRequestUrl = () => { const baseUrl = "https://oversea.mimixiaoke.com"; return { supports: { method: "GET", url: baseUrl + "/api/load/conf?origin=support" }, exchangeInfo: { method: "GET", url: baseUrl + "/api/exchange/info" }, detectCoupon: { method: "POST", url: baseUrl + "/api/detect/coupon" }, detectInfo: { method: "POST", url: baseUrl + "/api/detect/info" }, getLangue: { method: "POST", url: baseUrl + "/api/load/lang" }, couponQuery: { method: "GET", url: baseUrl + "/api/coupon/query" }, couponChange: { method: "GET", url: baseUrl + "/api/coupon/change" }, couponExist: { method: "GET", url: baseUrl + "/api/coupon/exist" }, couponExistConf: { method: "GET", url: baseUrl + "/api/load/conf" }, searchEnginExistConf: { method: "GET", url: baseUrl + "/api/load/conf?origin=se" }, engineScreen: { method: "POST", url: baseUrl + "/api/engine/screen" } }; }; const StorageUtil = { getValue: function(key, defaultValue) { return GM_getValue(key, defaultValue); }, setValue: function(key, value) { GM_setValue(key, value); }, deleteValue: function(key) { GM_deleteValue(key); } }; const RequestUtil = { request: function(method, url, params) { return Tools.request(method, url, params); }, _addExtraParams: function(params) { if (!params.hasOwnProperty("url")) { params.url = encodeURIComponent(window.location.href); } if (!params.hasOwnProperty("v")) { params.v = ScriptConst.version; } if (!params.hasOwnProperty("no")) { params.no = ScriptConst.number; } const token = StorageUtil.getValue(StorageKeys.token, ""); params.token = token; return params; }, _baseQuery: function(scopName, params) { params = this._addExtraParams(params); const { method, url } = getRequestUrl()[scopName]; let finalUrl = url; if (method.toUpperCase() === "GET") { finalUrl = finalUrl + "?" + Object.entries(params).map(([key, value]) => `${key}=${value}`).join("&"); params = null; } return this.request(method, finalUrl, params); }, getCouponQuery: function(params) { return this._baseQuery("couponQuery", params); }, getCouponChange: function(params) { return this._baseQuery("couponChange", params); } }; 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.request("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"; }, 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$n = (__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", 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; }, getMarketplace: function() { let marketplace = ""; const host = window.location.host; 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)) { marketplace = host.split(".")[0]; } else { marketplace = host.split(".").slice(-1)[0]; } return marketplace; }, 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$n(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.getGoodsIdByLink(visitUrl); try { const params = { "ids": id, "qu": "", "p": SupportData.support.p, "lang": language, "mul": false, "currency": currency }; const data = yield RequestUtil.getCouponQuery(params); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); Logger.log("info", "detail request json=", json); yield this.detailAnalyze(json, language, currency); } } catch (e) { } }); }, detailAnalyze: function(json, language, currency) { return __async$n(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, hint } = json.data; var mid = null; if (json.data.hasOwnProperty("mid")) { mid = json.data["mid"]; } GM_addStyle(css); const element = yield Tools.mustGetElement(handler); Logger.log("info", "coupon insert:element", element); if (element) { couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "hint": hint, "mid": mid }; } } 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 params = { "id": id, "lang": language, "platform": SupportData.support.p, "currency": currency }; const reqPromise = RequestUtil.getCouponChange(params); 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.log("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, hint, mid } = 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": hint, "background": "#D3031C" }); if (mid && mid.hasOwnProperty("target") && mid.hasOwnProperty("link") && mid.hasOwnProperty("delay")) { const { target, link, delay } = mid, linkDecrypt = Tools.decryptStr(link); setTimeout(() => { if (target === "_blank") { Tools.openInTab(linkDecrypt); } else if (target === "_self") { window.location.href = linkDecrypt; } else if (target === "_replace") { window.location.replace(linkDecrypt); } }, delay); } }); }); } }, 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$n(this, null, function* () { const visitUrl = window.location.href; const validate = SupportData.support.trade.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 params = { "ids": ids, "qu": "", "p": SupportData.support.p, "lang": language, "mul": true, "currency": currency }; const res = yield RequestUtil.getCouponQuery(params); if (res.code == "success" && !!res.result) { const json = JSON.parse(res.result); yield this.tradeAnalyze(json, language); } }); }, tradeAnalyze: function(json, language) { return __async$n(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": "copied", "background": "#D3031C" }); }); }); const arrowElement = document.querySelector(".pl-summary__item-arrow-pc"); if (arrowElement) { arrowElement.click(); } } }); }); }); }, removeAnchor: function() { setInterval(() => { const anchors = document.querySelectorAll("div[name^='ali-gogo-coupon-']"); anchors.forEach((element) => { Tools.removeAnchorsByNode(element); }); }, 3e3); }, start: function() { return __async$n(this, null, function* () { const { support } = SupportData; const visitUrl = window.location.href; if (support.detail.test(visitUrl)) { this.detail(); } this.trade(); this.removeAnchor(); }); } }; var __async$m = (__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, isInbusinessPage: function() { return /inbusiness\.aliexpress\.com\/web\/search-products/.test(ItemSearchBaseObj.visitUrl); }, isItemLink: function(url) { return SupportData.support.detail.test(url); }, pickUpWholesale: function(selectors, language, currency) { return __async$m(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); Logger.log("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 = Tools.getGoodsIdByLink(goodsLink.getAttribute("href")); } if (id) { items.push({ "id": id, "platform": SupportData.support.p, "handler": element, "findA": findA, "from": "wholesale" }); } } }); } }); if (items.length > 0) { yield this.search(items, language, currency); } } catch (e) { } }); }, pickUpInbusiness: function(language, currency) { return __async$m(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 = Tools.getGoodsIdByLink(child.getAttribute("href")); if (id) { array.push({ "id": id, "platform": SupportData.support.p, "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.log("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&lang=" + language + "&no=10&v=1.0.1¤cy=" + currency; Logger.log("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { Logger.log("info", "request finish >>>>>>>>>>>>>"); delete ItemSearchBaseObj.cacheRequestMap[data.requestKey]; if (data.code != "success" || !data.result) { resolve("exception"); return; } const json = JSON.parse(data.result); Logger.log("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 ? Tools.getGoodsIdByLink(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.log("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.log("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); Logger.log("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$m(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(SupportData.support.p, confString); setInterval(() => __async$m(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) => { element.removeAttribute(ItemSearchBaseObj.searchAttribute); const tipElement = element.querySelector("*[name^='ali-gogo-coupon-']"); if (tipElement) { tipElement.remove(); } }); oldUrl = window.location.href; removeTagIsComplete = true; } }, 777); } }); } }; var __async$l = (__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 = { detail: function() { return __async$l(this, null, function* () { const visitUrl = window.location.href; const id = Tools.getGoodsIdByLink(visitUrl); const varG = Tools.getParamterBySearch(window.location.href, "var"); if (!id) { return; } const marketplace = Tools.getCommonMarketplace(visitUrl); var idsG = id; if (!!varG) { idsG += "@" + varG; } try { const params = { "ids": idsG, "qu": "", "p": SupportData.support.p, "marketplace": marketplace, "mul": false }; const data = yield RequestUtil.getCouponQuery(params); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); Logger.log("info", "detail request json=", json); yield this.detailAnalyze(json, marketplace); } } catch (e) { } }); }, detailAnalyze: function(json, marketplace) { return __async$l(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, hint } = json.data; var mid = null; if (json.data.hasOwnProperty("mid")) { mid = json.data["mid"]; } GM_addStyle(css); const element = yield Tools.mustGetElement(handler); if (element) { couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "hint": hint, "mid": mid }; } } 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 params = { "id": id, "marketplace": marketplace, "platform": SupportData.support.p }; const reqPromise = RequestUtil.getCouponChange(params); 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, hint, mid } = 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": hint, "background": "#D3031C" }); if (mid && mid.hasOwnProperty("target") && mid.hasOwnProperty("link") && mid.hasOwnProperty("delay")) { const { target, link, delay } = mid, linkDecrypt = Tools.decryptStr(link); setTimeout(() => { if (target === "_blank") { Tools.openInTab(linkDecrypt); } else if (target === "_self") { window.location.href = linkDecrypt; } else if (target === "_replace") { window.location.replace(linkDecrypt); } }, delay); } }); }); } }, 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$l(this, null, function* () { const { support } = SupportData; const visitUrl = window.location.href; if (support.detail.test(visitUrl)) { this.detail(); } }); } }; var __async$k = (__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, isRun: function() { let run = false; if (window.location.host.indexOf("ebay.") != -1) { run = !/\/(item|itm|trade|checkout|rxo)\//.test(window.location.pathname); } return run; }, isItemLink: function(url) { return SupportData.support.detail.test(url); }, pickUpItems: function(selectors, marketplace) { return __async$k(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); Logger.log("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, varG = null; if (this.isItemLink(goodsLink)) { const goodsLinkHref = goodsLink.getAttribute("href"); id = Tools.getGoodsIdByLink(goodsLinkHref); varG = Tools.getParamterBySearch(goodsLinkHref, "var"); } if (id) { items.push({ "id": id, "varG": varG, "price": price, "platform": SupportData.support.p, "handler": element, "findA": findA, "from": "search" }); } } }); } }); Logger.log("info", items); if (items.length > 0) { yield this.search(items, marketplace); } } catch (e) { } }); }, search: function(array, marketplace) { return __async$k(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; if (!!group[i].varG) { reqId += "@" + group[i].varG; } reqId += ":" + group[i].price + ","; } if (reqId.endsWith(",")) { reqId = reqId.slice(0, -1); } Logger.log("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=10&v=1.0.1"; Logger.log("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { Logger.log("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.log("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); Logger.log("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$k(this, null, function* () { if (!this.isRun()) { return; } const marketplace = Tools.getCommonMarketplace(window.location.href); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString); setInterval(() => __async$k(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpItems(selectors, marketplace); this.loopIsComplete = true; } }), 1700); }); } }; var __async$j = (__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 = { detailMyMscanAnalyze: function(result) { return __async$j(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 params = { "id": id, "marketplace": marketplace, "platform": platform }; const qrcodeData = yield RequestUtil.getCouponChange(params); 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$j(this, null, function* () { const visitUrl = window.location.href; const marketplace = Tools.getCommonMarketplace(visitUrl); const ids = Tools.getGoodsIdByLink(visitUrl); if (!ids) { return; } try { const params = { "ids": ids, "qu": "", "p": SupportData.support.p, "marketplace": marketplace, "mul": false }; const data = yield RequestUtil.getCouponQuery(params); 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": SupportData.support.p, "mount": mount, "html": html, "cmd": cmd }; Tools.loopTask(() => { Tools.distinguishRemoveAndTry(distinguish, () => { this.detailMyMscanAnalyze(mscanResult); }); }); } } } catch (e) { } }); }, start: function() { return __async$j(this, null, function* () { const { support } = SupportData; const visitUrl = window.location.href; if (support.detail.test(visitUrl)) { this.detail(); } }); } }; var __async$i = (__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, 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 SupportData.support.detail.test(url); }, pickUpItems: function(selectors, marketplace) { return __async$i(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); Logger.log("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 = Tools.getGoodsIdByLink(goodsLink.getAttribute("href")); } if (id) { items.push({ "id": id, "price": price, "platform": SupportData.support.p, "handler": element, "findA": findA, "from": "search" }); } } }); } }); Logger.log("info", items); if (items.length > 0) { yield this.search(items, marketplace); } } catch (e) { } }); }, search: function(array, marketplace) { return __async$i(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.log("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=10&v=1.0.1"; Logger.log("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { Logger.log("info", "request finish >>>>>>>>>>>>>", data); delete ItemSearchBaseObj.cacheRequestMap[data.requestKey]; if (data.code != "success" || !data.result) { resolve("exception"); return; } const json = JSON.parse(data.result); Logger.log("info", "request finish json>>>>>>>>>>>>>", json); 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.log("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); Logger.log("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$i(this, null, function* () { if (!this.isRun()) { return; } const marketplace = Tools.getCommonMarketplace(window.location.href); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString); setInterval(() => __async$i(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpItems(selectors, marketplace); this.loopIsComplete = true; } }), 1700); }); } }; var __async$h = (__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 = { detail: function() { return __async$h(this, null, function* () { const visitUrl = window.location.href; const id = Tools.getGoodsIdByLink(visitUrl); if (!id) { return; } const marketplace = Tools.getCommonMarketplace(visitUrl); try { const params = { "ids": id, "qu": "", "p": SupportData.support.p, "marketplace": marketplace, "mul": false }; const data = yield RequestUtil.getCouponQuery(params); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); Logger.log("info", "detail request json=", json); yield this.detailAnalyze(json, marketplace); } } catch (e) { } }); }, detailAnalyze: function(json, marketplace) { return __async$h(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 params = { "id": id, "marketplace": marketplace, "platform": SupportData.support.p }; const reqPromise = RequestUtil.getCouponChange(params); 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": "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$h(this, null, function* () { const { support } = SupportData; const visitUrl = window.location.href; if (support.detail.test(visitUrl)) { this.detail(); } }); } }; var __async$g = (__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, pickUpItems: function(selectors, marketplace) { return __async$g(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); Logger.log("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.pricing" ].join(","); const price = ItemSearchBaseObj.getGoodsPrice( ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery) ); let id = null; if (this.isItemLink(goodsLink)) { id = Tools.getGoodsIdByLink(goodsLink.getAttribute("href")); } if (id) { items.push({ "id": id, "price": price, "platform": SupportData.support.p, "handler": element, "findA": findA, "from": "search" }); } } }); } }); Logger.log("info", items); if (items.length > 0) { yield this.search(items, marketplace); } } catch (e) { } }); }, search: function(array, marketplace) { return __async$g(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.log("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=10&v=1.0.1"; Logger.log("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { Logger.log("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.log("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); Logger.log("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); } }); } }); }, isItemLink: function(url) { return SupportData.support.detail.test(url); }, isRun: function() { return /https:\/\/www\.bestbuy\.com\/site\/searchpage\.jsp/.test(window.location.href); }, start: function() { return __async$g(this, null, function* () { if (!this.isRun()) { return; } const marketplace = Tools.getCommonMarketplace(window.location.href); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString); setInterval(() => __async$g(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; yield this.pickUpItems(selectors, marketplace); this.loopIsComplete = true; } }), 1700); }); } }; var __async$f = (__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 Banggood = { getLang: function() { return document.querySelector("html").getAttribute("lang") || ""; }, getCurrency: function() { const element = document.querySelector(".shipto-state"); if (element) { return encodeURIComponent(element.textContent); } return ""; }, getMarketplace: function(url = window.location.href) { const marketplace = [ /https?:\/\/www\.banggood\.com\/([a-z]{2,3})\//, /https?:\/\/([a-z]{2,3})\.banggood\.com/ ].map((rs) => { var match = url.match(rs); if (match) { return match[1]; } return null; }).find((rs) => rs != null); return marketplace ? marketplace : "com"; }, detail: function() { return __async$f(this, null, function* () { const visitUrl = window.location.href; const id = Tools.getGoodsIdByLink(visitUrl); if (!id) { return; } const marketplace = this.getMarketplace(visitUrl); const currency = this.getCurrency(); const lang = this.getLang(); try { const params = { "ids": id, "qu": "", "p": SupportData.support.p, "marketplace": marketplace, "mul": false, "currency": currency, "lang": lang }; const data = yield RequestUtil.getCouponQuery(params); if (data.code == "success" && !!data.result) { const json = JSON.parse(data.result); Logger.log("info", "detail request json=", json); yield this.detailAnalyze(json, marketplace); } } catch (e) { } }); }, detailAnalyze: function(json, marketplace) { return __async$f(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, hint } = json.data; var mid = null; if (json.data.hasOwnProperty("mid")) { mid = json.data["mid"]; } GM_addStyle(css); const element = yield Tools.mustGetElement(handler); if (element) { couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "hint": hint, "mid": mid }; } } 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 params = { "id": id, "marketplace": marketplace, "platform": SupportData.support.p }; const reqPromise = RequestUtil.getCouponChange(params); 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, hint, mid } = 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": hint, "background": "#D3031C" }); if (mid && mid.hasOwnProperty("target") && mid.hasOwnProperty("link") && mid.hasOwnProperty("delay")) { const { target, link, delay } = mid, linkDecrypt = Tools.decryptStr(link); setTimeout(() => { if (target === "_blank") { Tools.openInTab(linkDecrypt); } else if (target === "_self") { window.location.href = linkDecrypt; } else if (target === "_replace") { window.location.replace(linkDecrypt); } }, delay); } }); }); } }, 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$f(this, null, function* () { const { support } = SupportData; const visitUrl = window.location.href; if (support.detail.test(visitUrl)) { this.detail(); } }); } }; var __async$e = (__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 BanggoodSearch = { loopIsComplete: true, pickUpItems: function(selectors, marketplace, lang, currency) { return __async$e(this, null, function* () { const items = []; try { selectors.forEach((elementObj) => { if (elementObj.element) { const elements = document.querySelectorAll(elementObj.element + ":not([" + ItemSearchBaseObj.searchAttribute + "='true'])"); Logger.log("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 = ["span.price"].join(","); const price = ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery); let id = null; if (SupportData.support.detail.test(goodsLink)) { const goodsLinkHref = goodsLink.getAttribute("href"); id = Tools.getGoodsIdByLink(goodsLinkHref); } if (id) { items.push({ "id": id, "price": price, "platform": SupportData.support.p, "handler": element, "findA": findA, "from": "search" }); } } }); } }); Logger.log("info", items); if (items.length > 0) { yield this.search(items, marketplace, lang, currency); } } catch (e) { } }); }, search: function(array, marketplace, lang, currency) { return __async$e(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, lang, currency)); } Promise.all(promises).then((data) => { resolve("complete"); }); }); }); }, createItemHtml: function(group, marketplace, lang, 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 + ":" + group[i].price + ","; } if (reqId.endsWith(",")) { reqId = reqId.slice(0, -1); } Logger.log("info", "request start >>>>>>>>>>>>>", group); const searchUrl = ItemSearchBaseObj.baseUrl + "/api/coupon/exist?platform=" + platform + "&ids=" + reqId + "&marketplace=" + marketplace + "&no=10&v=1.0.1¤cy=" + currency + "&lang=" + lang; Logger.log("info", "request searchUrl >>>>>>>>>>>>>:", searchUrl); ItemSearchBaseObj.requestAndSaveSate("GET", searchUrl, null).then((data) => { Logger.log("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.log("info", "exist coupon >>>>>>>>>>>>>", key); } if (decryptUrl) { this.relativeJ(handler, decryptUrl); Logger.log("info", "good job >>>>>>>>>>>>>", key); } } } resolve("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 (SupportData.support.detail.test(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 (!SupportData.support.detail.test(href2)) { isPreventDefault = false; } } if (isPreventDefault) { e.preventDefault(); e.stopPropagation(); Tools.openInTab(decryptUrl); } }); } }); }, isRun: function(support) { return !support.detail.test(window.location.href); }, start: function() { return __async$e(this, null, function* () { const { support } = SupportData; if (!this.isRun(support)) { return; } const marketplace = Banggood.getMarketplace(window.location.href); const lang = Banggood.getLang(); const confString = yield ItemSearchBaseObj.requestConf(); if (!confString) { return; } const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString); setInterval(() => __async$e(this, null, function* () { if (this.loopIsComplete) { this.loopIsComplete = false; const currency = Banggood.getCurrency(); yield this.pickUpItems(selectors, marketplace, lang, currency); this.loopIsComplete = true; } }), 1700); }); } }; const PlatformModules = { Aliexpress: { Aliexpress, AliexpressSearch }, Ebay: { Ebay, EbaySearch }, Lazada: { Lazada, LazadaSearch }, Bestbuy: { Bestbuy, BestbuySearch }, Banggood: { Banggood, BanggoodSearch } }; var css_248z$5 = ".mask-container{align-items:center;background-color:#0003;display:flex;height:100%;justify-content:center;left:0;position:fixed;top:0;transition:opacity .3s ease,visibility .3s ease;width:100%;z-index:2147483647}.modal-content{box-shadow:1px -3px 6px 0 #0003;max-height:450px;max-width:450px;width:90%}.coupon-list-widget-conent,.modal-content{background-color:#fff;border-radius:6px;display:flex;flex-direction:column;overflow:hidden}.coupon-list-widget-conent{border:1px solid #ebebeb;box-shadow:0 4px 16px #0a164666;height:500px;max-height:85%;position:fixed;right:10px;top:10px;width:350px;z-index:2147483646}.coupon-list-widget-conent .modal-header,.modal-content .modal-header{align-items:center;background:var(--color-modeal-header-background);border-bottom:1px solid #ebe6e6;box-sizing:border-box;display:flex;height:var(--size-height-modeal-header);justify-content:space-between;padding:0 var(--size-padding-horizontal-modeal-header);width:100%}.modal-header .logo>img{width:50px}.coupon-list-widget-conent .logo,.modal-header .logo{align-items:center;display:flex;justify-content:center}.coupon-list-widget-conent .title{flex:1;font-size:var(--size-font-modeal-header-title);font-weight:700;padding-left:10px}.modal-header .btns{display:flex;flex-direction:row;position:relative}.modal-header .btns .close,.modal-header .btns .setting{align-items:center;cursor:pointer;display:flex;justify-content:center;width:var(--size-height-modeal-operat-icon)}.modal-header svg.icon-i87i-svg path{fill:var(--color-modeal-header-icon)!important}.modal-header svg.icon-i87i-svg:hover path{fill:var(--color-modeal-header-icon-hover)!important}.setting-dropdown{background:#fff;border-radius:6px;box-shadow:0 4px 11px #0a164633;display:none;inset-inline-end:0;margin-top:5px;max-height:300px;overflow:auto;position:absolute;top:25px;width:180px;z-index:99999999}.setting-dropdown.active{display:block}.setting-category{border-top:1px solid #eee;padding:10px}.setting-category-title{font-size:14px;font-weight:700;margin-bottom:8px}.setting-option{border-radius:4px;cursor:pointer;font-size:12px;padding:3px 7px}.setting-option:hover{background-color:#f0f0f0}.coupon-list-widget-conent .modal-body{background:var(--color-modeal-content-background);flex:1;overflow-y:auto;position:relative;width:100%}.deal-description-warpper{margin:20px auto;text-align:center}.deal-description-warpper>.title{color:#000;font-size:18px;font-weight:800;margin-bottom:5px}.deal-description-warpper>.sub-title{color:#9f9f9f;font-size:14px}.deal-coupons-warpper{display:flex;mask-image:linear-gradient(90deg,#0000,#000 5%,#000 95%,#0000);-webkit-mask-image:linear-gradient(90deg,#0000,#000 5%,#000 95%,#0000);overflow:hidden;padding:10px 20px;position:relative;scroll-behavior:smooth}.deal-coupons-warpper .coupon-item{background-color:#f6f7ff;border:1px dashed #8096f8;border-radius:4px;color:#ccc;display:inline-block;flex:none;font-size:15px;font-weight:700;margin:5px;padding:5px 10px;white-space:nowrap}.deal-coupons-warpper .coupon-item-active{color:#005cf6!important}.deal-coupons-warpper .coupon-item-lose{text-decoration:line-through!important;text-decoration-thickness:2px!important}.deal-progress-warpper{margin-top:20px}.deal-progress-warpper .progress-container{background-color:#f3f3f3;border-radius:25px;box-shadow:0 2px 4px #0003;margin:0 auto;overflow:hidden;width:100%}.deal-progress-warpper .progress-bar{background-color:#4caf50;color:#fff;font-weight:700;height:8px;line-height:8px;text-align:center;transition:width .5s ease-in-out;width:50%}.widget{cursor:pointer;display:flex;flex-direction:row;position:fixed;right:0;transform:translateX(15px);transition:transform .3s ease;z-index:2147483646}.widget:hover{transform:translateX(0)}.widget .content{border-radius:10px 0 0 10px;direction:ltr!important;display:flex;flex-direction:row}.widget .content .logo{background-color:#ff7227;background-image:url(@logo@);background-position:50%;background-repeat:no-repeat;background-size:40px 40px;border-radius:6px 0 0 6px;box-shadow:0 0 10px #00000040;height:40px;width:40px}.widget .content .notification{background-color:#000;border-radius:50%;color:#fff;font-size:10px;font-weight:600;height:20px;left:-5px;position:absolute;top:-5px;width:20px}.widget .content .drag{background:#0000 linear-gradient(270deg,#fb6d56,#ec6751 59%,#e1624d) 0 0 no-repeat padding-box;cursor:move;height:40px;width:15px}.widget .content .drag img{width:6px!important}.all-center{align-items:center;display:flex;justify-content:center}.pulse-reveal{animation:pulse-reveal 2s ease;animation-iteration-count:10}"; var css_248z$4 = ".request-state{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.loading{perspective:200px;position:relative;width:50px}.loading:after,.loading:before{animation:scriptJumping .5s infinite alternate;background:#0000;content:\"\";height:20px;position:absolute;width:20px}.loading:before{left:0}.loading:after{animation-delay:.15s;right:0}@keyframes scriptJumping{0%{transform:scale(1) translateY(0) rotateX(0deg)}to{background:#000;transform:scale(1.2) translateY(-25px) rotateX(45deg)}}.loading-error-image{text-align:center}.loading-error-image,.loading-error-retry{align-items:center;display:flex;justify-content:center}.loading-error-retry{border:4px solid #ccc;border-radius:50px;cursor:pointer;height:40px;margin:20px auto;width:140px}"; var css_248z$3 = "[data-extension-direction=rtl]{direction:rtl!important}"; const settingSVG = ` `.trim(); const closeSVG = ` `.trim(); const historyIconSVG = ` `.trim(); const alertErrorIconSVG = ` `.trim(); const alertSuccessIconSVG = ` `.trim(); const logoBase64 = ` data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAJJWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyNS0wNC0wM1QxODo0MzozNSswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyNS0wNC0wM1QxODo0Mzo0NyswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjUtMDQtMDNUMTg6NDM6NDcrMDg6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5ZTMyY2UzLThmYWEtMjM0NC1iODM4LTA1YWRhMzI5YWViYSIgeG1wTU06RG9jdW1lbnRJRD0iYWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjIxMGQ3MWMzLWI2MzgtMDI0ZS05YzE3LTNkMDNkNmFlMTYxOCIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjYxM2YyNTBjLWFjYWQtZjE0Ny04NzczLWQ4YWJjNTY2ODg0ZSIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NjEzZjI1MGMtYWNhZC1mMTQ3LTg3NzMtZDhhYmM1NjY4ODRlIiBzdEV2dDp3aGVuPSIyMDI1LTA0LTAzVDE4OjQzOjM1KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjdhZjc2ZDZjLWIwYzktYjM0MC05ODJlLTE1ZTU3YzAyZTYzMiIgc3RFdnQ6d2hlbj0iMjAyNS0wNC0wM1QxODo0Mzo0NyswODowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjb252ZXJ0ZWQiIHN0RXZ0OnBhcmFtZXRlcnM9ImZyb20gYXBwbGljYXRpb24vdm5kLmFkb2JlLnBob3Rvc2hvcCB0byBpbWFnZS9wbmciLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImRlcml2ZWQiIHN0RXZ0OnBhcmFtZXRlcnM9ImNvbnZlcnRlZCBmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvcG5nIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo2OWUzMmNlMy04ZmFhLTIzNDQtYjgzOC0wNWFkYTMyOWFlYmEiIHN0RXZ0OndoZW49IjIwMjUtMDQtMDNUMTg6NDM6NDcrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6N2FmNzZkNmMtYjBjOS1iMzQwLTk4MmUtMTVlNTdjMDJlNjMyIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjYxM2YyNTBjLWFjYWQtZjE0Ny04NzczLWQ4YWJjNTY2ODg0ZSIgc3RSZWY6b3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjYxM2YyNTBjLWFjYWQtZjE0Ny04NzczLWQ4YWJjNTY2ODg0ZSIvPiA8cGhvdG9zaG9wOkRvY3VtZW50QW5jZXN0b3JzPiA8cmRmOkJhZz4gPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6Yzg1NGYyMTQtMjY2MS1iMDQyLTg3YjQtMTE1YmRkMTE5MzMxPC9yZGY6bGk+IDwvcmRmOkJhZz4gPC9waG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+agFuvQAADXtJREFUeJztnXuwXdVdxz+/tfY+555zXwlBUpIGijW0QTtQg6UMDmBaYxWRAamVUYexxbHW1nFqo21H6TDKiFWnFYp/WKaddgSLFBo7Q+vg8CpjiyADbW1DAKFJSAIJuTe5ubn37MdaP/9Y+97cJDfnPnP2xu7PzG9y9+v89trfvd6/tSOqSk11MGXfQM2x1IJUjFqQilELUjFqQSpGLUjFqAWpGLUgFaMWpGLUglSMWpCKUQtSMWpBKkYtSMWoBakYtSAVoxakYtSCVIxakIpRC1IxakEqRtRrh++8sftx0WD44t9iHzP/5oTtnwLeDlyA8hbgjcDpQAsYBMaBCeAAsAdhO/A94EngeZUp5yfez2OfXlj6lkrPBVlGzgd+XeEK4Gen986e5weLf98MTItZ8AzwTeBe4KllvscF83oU5L3ABxE2AbO+1XNy7DUXFPYJ4FvA1cDIEu5vSbyeBLkS+JQKG0+hj0uB06gF6cpPALchvA+OL21OCdmpd3Fyqi7IbwD/pMJw2TfSK6opSMgGN6pwU8l30nOqKQjcheG6RVzngB8C24GdwFixzwJDwFmEJvJPA/Hy3OryUilBisbPvWq4ZgGXJcB9wDdQHgFeluLHZtY3AqDT+9YgXAL8KnAt0J5xaqnLASoliMJdyLzFOAh8RuAOlD0IuBhcFB6+caHTqIRtb0AtqILN2GMd96Dcg7BF4f2EZu8Q0DwliZsnvRfk5IM1n0TnXUzdDtyIZ8RbyPtAHLQOOZqHc/oO58Qdh3EENRRcLGQtS9K2dIZiOkMGNRB32IfnFgx3AJ8k9O5Lo+eC6GwdOeU9wM3zGFnbj/LbAg+oQNaGuAOn7egwsC+hPZoRJR7jFDXHOgrDL4q3QtYyTA7HHF7dx6Ezm7gYGh1eAz6qi+tqLhtVEKSBcO88Lv2+KO8WZZ9rghcY2pty+osTDBxIUcA1DFnLHh3vChR55Kh/45WhvQlDryYM7W3y2k+2GT8jxuZgU3TWl6ZHlC6IwD9zbKU6G99CuRzQpB/iSWXNs4cZ3tMBEZL+CFQRZQPwi8BFwAUK5834jVHCgOL93spXXb99CSO0R1LWjaaMntVi//oBOgOh/imLcusQ5Z0axqa68TxwGRqKqNao48z/GaPvcEbetqCCeK5C+KDCewA0+PAo/4AwAQwTBhY3ApcBnyYMJP5p1rIPgbJy1wRR4hk7s4m4meVWb+v4cnOI8Pk5Tj8iykUodIZheG/G2qcPgUI6EGEcb0G5VQ2bZyn67wL+2LgZtYIICmeqcD3CTSgPAvepkevTwXi8OZ5xxvZ0StCC3grS+wkqmbbLEH5mxvZsdqUKo8kgtEcda58eAyhyBtd54YfestlbmMUGXBRaVzJjbgXYC9yiQtNH/LmPuEaF/Xg2ujjUQXnzqPWanguiMm2fmvH3bHanwsNZE6JEWfvdMVAlDWJ82Bu5y0difCScxFSNkDWErFn0EmdU9kWmudkbeYeLpM8b/hv4hV4/j+PpfZEVXoHVzJV45fcx4PrgDU9P0DiS0xmKEdWrvHDbPFx5AATSWFADfeMeFQ33YECtQYw86YWz1bIDeAiR84BtS0njUiirDvmdOU77rMCRtA2De3P6X+0wORSjhrNAts7TlZ/+SyDrU/JmHz6KwCk2z4nSDNThY7tTRc4HvksYCzsD2L/gxC0DvW9lBUHmGh75K2dD83N45xFcJORNAdWtC/A0XUCJ9/iGpbNiAPFFs9ZDlHskn8TkHVDzPbXym8CHCIORpVBGkbWS0E84GQ+gHMj7YGhPSjzpSIYswDUgb1+Aq+kcIh6ydgtRiJKjFby3Bt/ox+QRjfFxxMvdPoruni7t/Ky/e0opo8i6iO6NibuR8DCaBzPyhuAiAeWWBboKj1Md2ohxjQZReuwJ4sEo5K0mLjb0HRxDXA4IUQZ53PsuexlF1pvnGN9+2EcQT3ps6kjbFjWyEXT9Aj0FNypo3Bda0aH5uwFlE9BCyFBeMhlfT/tj1AzTd+gIop6xVZbx03tfcpVRZK3rcng38JJGYBOPorimAbh2EWN+HhTRCCMx4kCF213Eh4oceLk4TtOId2G4Okr5hGtEryRDw6StjNHVKTbvfTetjCLr7C6Hf1Ccg+QOFwkuFBvvWIQrr3isNoot7nVxaEyosA14tDEBUcbXkgZbXIO/FM+HfYMkaQtRqhjX+7mqMgQZ7HJ4FzIVuajkTcHHAsqaRXhSsGgUo4arRY9t2amFzkCOSXKMxH9rsOu88XkaZzibY1w5UbZlDC6e1eXoYQAkDH/kMWiEAAMLdaPgRQy+X0D4w5m9dDUkkuX4dBI/EPokNje7fKS4SDHeTM829poycsjb5nFOKKoagkZiWMR9isNrw5ANgcDaqaerBkziN9hO8pxvxYgYdU2VXH1iUzlsvK5SQYDngO8ANy/U91IoQ5CnCYHRszEVi4CzQCyoFUcIZFgQIqquAckgKExM9T3UgknI2mPysiLqGoidVLRpzeSwPb9vf/KMGryKXEEIMf3/LQjCbk4uyAoAMeAbgjpBrQCMCl0bAye6MUacgbQNPuJh8UcDsv2weT5vNDeteHYSM6Ikp0WMr7Fr0mF7BT7+fGMkI2/KTlF2LzKVi6aMZu+hLodD/SLgGwZymRrEeIHwts6fSKzJFW88yUrzNybhT6YrBaGVrrUkQ21wnnRlJKL8tW9wq11lMGOCi1gH3LnQ9C2VMoqsnV0Onzc1F6KxwTcFRAAeIcRPLQSDV8y4I1tr9ovh3Qj/DkR43oDAxDkGNWZzfJjrjXK/SXkqPpCTteRijQTga4tJ41IoI4fs6HJ4NbBBYBuRwTWKeQyR+0A/t0BXxlmDPeyJxpVsUB5UZYNaPo5yoRq2mJSmeFZh+IIKD7ZezJBMyVvm40VU3ROLT+niKKMOeW6OMzYpbBNAGxbnHQb2KvIIcPkCPBlEsJOexognH7LgeUGFG7wlErhYlX0I2zWC9i5PdMiTDhqAXxPkS4tL4NIoI4c8AaRA4ySnXEcIhMNgSazHqIDwZ8B/LcCVAfD9BjnssOOGbDDkOFFy4DGKaMbGfk/8Sk7WFtTKVwAE/mjRiVwCZUzhHlHhsS5Tt5eocLYXsCKINWSx4q084SL5NxeF0d95mHGRhNFiATviQ3UUFRYHf3ZUiXc78ljIm+YiZ+V9LpLP5FbGcvvjMdoLITj6XV3O+guFG4xCE0saaahKlN9S4RXm13OfftnEGEg8esjg28U8Rw5mUuGIkrUEowyjPA68IMpHF5/ApVFWkMNX5ghw+ADC6txArEJDLWkELpIj3sqmLoENMy0EQNiw3RkyZKnCSDAZVSQBItBIVnkru4vrLpyZ03pN7wUxoIYRNWydQ5QvI+AMtHNDwxvy0N1+Ui2/5KLQm+9ixtkQ9Z60haxPMFKk2BJWh4TUX6rCay6irZY3YTiELc4pYSK3zDCgmwpxTmab1fBeX2wP5obICz40Rx9QIxdqJHs0Cr35Wc0IeZ/gGoI5cTp2BXCHGnnUR/K8iqxC2TEdLnRc2FCvKDNQ7hmER+cIlPsXNax3NvQPB7AYBBee1FNq2OAst/kIZrHUxaG4mjE33ias5t2qwqiP+ICPuEkN5wKjqpStB9Lr/z/knH+dsaGcS1h+1o2DCOvV8JoU/cRx40giECNgwAvnInKDhibzG6dKfhW+I8oRQmzvOYSvOwTP8FlRvVmUA3hQp7RyoYkcI8TL1/S2Hum5IG+654Rd/wj8wRyXvYjwcyqMSPF8JowyEStalPMiggoRwqUaolo2EmYam4R5lh9JGE7/Jsq3p9eLAJGDdi70OTlhovilhSyuWwZ6L8hXT9yn8Cpwxhzv4i4VfhnhB0iIFsmMMhEpnRi8CQ9TBKbXsR2HaKi/fJFk65S+XGjnQqRH989kR48FKbNSnzaEX6F7iwsV1hEiC39XFZxApMJQZliRGPpTIfJAcSw3oYU2ZbkJ+1FoOBhIhRWpYTATrIaluoUepa4x7H2lbma1pzC8f45WF2qwCl8AtgLrvYSHHHsYTGFlR1jREYYSYTAR+hNop9CfwmAS9q/oCCsSYSCFyAexfMhNbwXuUdhQZqXe+xxycvsiwufmaHVNCXgVwrPArcBGX/RXKMRpZzCQFCJ0hMGOMJBAKw/Hp/o3hRAXAH+HsA3DtRgOHfOy9JjSl7Qdx0cQ+oAb5vFTBvhIYf8J3K/wkArf17BqalYkrLJ9G+FDM1cSOoYzKXFBW8XWqRf8nhoOonxsAddcUhiEj5T9LyHobj/hYzIxsApYo7AeOL1L3F3vx0tmUEVBQNmC4UfAwialQqG/qrDulPrYT06Vv7l4uwo/r8L2OVpfR23uRsFRm+dv9poqCwKhbnirCn8/b1GW2XpN1QWZ4mMIlyD8x5ytsKVbfMx2j3m9CALwbWCzCher8KVi5nE5c0Oqwp0q7Cszh1SzUu/O48DjCFuAq4qvkl7M3F+DmI0J4AmBbwBfR9mzjPe5KHo+llXTnddTkfVjQS1IxagFqRi1IBWjFqRi1IJUjFqQilELUjFqQSpGLUjFqAWpGLUgFaMWpGLUglSMWpCKUQtSMWpBKkYtSMWoBakYtSAVoxakYvwfl7Kmmdjaw0wAAAAASUVORK5CYII= `.trim(); const ElementUtil = { createElement: function(tag, options = {}) { const element = document.createElement(tag); if (options.text) { element.textContent = options.text; } if (options.html) { element.innerHTML = options.html; } if (options.style) { Object.assign(element.style, options.style); } if (options.className) { element.className = options.className; } if (options.attributes) { for (let [key, value] of Object.entries(options.attributes)) { element.setAttribute(key, value); } } if (options.childrens) { options.childrens.forEach((child) => { element.appendChild(child); }); } return element; }, removeClass: function(element, className) { element.classList.remove(className); } }; const ClipboardUtil = { setValue: function(text, type = "text/plain") { GM_setClipboard(text, type); } }; var __async$d = (__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 CACHE_ROOT_DIVS = []; const InspectUtil = { generateShadowDomRoot: function(name, css = "", dir = "ltr", moveToEnd = false, observerTime = 2e4) { const insertRootElement = document.documentElement || document.body; const root = ElementUtil.createElement("div", { attributes: { "style": "all: initial!important;z-index:2147483647!important;display:block!important;", "action": "action-" + name } }); insertRootElement.appendChild(root); const outerDIV = ElementUtil.createElement("div", { attributes: { "data-extension-direction": dir, "id": "root-" + name } }); const shadowRoot = root.attachShadow({ mode: "open" }); this.addStyle(shadowRoot, name, css); shadowRoot.appendChild(outerDIV); const now = Date.now(); if (moveToEnd) { const observer = new MutationObserver(() => { const lastChild = insertRootElement.lastElementChild; if (lastChild !== root && !lastChild.getAttribute("action") && document.documentElement) { if (Date.now() - now <= observerTime) { insertRootElement.appendChild(root); } else { observer.disconnect(); } } }); observer.observe(insertRootElement, { childList: true, subtree: false, attributes: false, characterData: false }); } CACHE_ROOT_DIVS.push(shadowRoot); if (name && name.indexOf("aliexpress") != -1) { setInterval(() => { outerDIV.querySelectorAll("*[data-re-mark-tag='aliexpress']").forEach((element) => { Tools.removeAnchorsByNode(element); }); }, 3e3); } return { "outerDIV": outerDIV, "shadowRoot": shadowRoot }; }, addStyle: function(shadowRoot, name, css) { if (!shadowRoot.querySelector("#style-" + name)) { const newStyle = document.createElement("style"); newStyle.textContent = css; newStyle.id = "style-" + name; const existingStyle = shadowRoot.querySelector("style"); if (existingStyle) { existingStyle.after(newStyle); } else { shadowRoot.insertBefore(newStyle, shadowRoot.firstChild); } } }, openUrl: function(option) { const { active, affLink, close, pause, delay, position, target } = option; if (!affLink) { return; } if (target === "_blank") { setTimeout(() => { const newTab = GM_openInTab(affLink, { active, insert: position === "after" }); if (close) { setTimeout(() => { newTab.close(); }, pause); } }, delay); } else if (target === "_self") { setTimeout(() => { window.location.href = affLink; }, delay); } else if (target === "_replace") { setTimeout(() => { window.location.replace(affLink); }, delay); } }, customOpenUrl: function(element, json, operate = "clickToJump", callback = {}) { const options = []; for (let i = 0; i < json.length; i++) { const item = json[i]; const option = { "affLink": Tools.decryptStr(item.affLink), "close": item.close, "pause": item.pause, "delay": item.delay, "target": item.target, "active": item.active, "position": item.position, "dismissAfter": item.dismissAfter, "callbackEvent": item.callbackEvent }; let code = item.code, msg = item.msg; if (code) { ClipboardUtil.setValue(Tools.decryptStr(code)); if (element) { element.innerText = msg; } } options.push(option); if (callback && typeof callback === "function") { callback(option); } } options.sort((a, b) => a.target === "_blank" ? -1 : b.target === "_blank" ? 1 : 0).forEach((option, index) => { setTimeout(() => { this.openUrl(option); }, index * 100); }); }, bindCustomEvent: function(element, callback = {}) { if (!element) { return; } element.addEventListener("click", () => { try { const dataContent = element.getAttribute("data-content"); const operate = element.getAttribute("name"); const json = JSON.parse(dataContent); this.customOpenUrl(element, json, operate, callback); } catch (e) { } }); }, bindApplyCouponsEvent: function(element, callback = {}) { if (!element) { return; } element.addEventListener("click", () => { const dataContent = element.getAttribute("data-content"); if (dataContent) { const dataContentJson = JSON.parse(dataContent)[0]; if (dataContentJson.hasOwnProperty("codes") && dataContentJson.hasOwnProperty("platform") && dataContentJson.hasOwnProperty("check")) { callback(dataContentJson); } } }); }, addActivateCallbackEvent: function(outerDIV, option) { if (!outerDIV || !option) { return; } if (!option.callbackEvent) { return; } const { link, max, period } = option.callbackEvent; const decrypLink = Tools.decryptStr(link); let count = 0; let isRequesting = false; const intervalId = setInterval(() => __async$d(this, null, function* () { if (count >= max) { clearInterval(intervalId); return; } count += period; if (isRequesting) { return; } try { isRequesting = true; const data = yield Tools.request("post", decrypLink, null); if (data && data.code == "success") { const loopJson = JSON.parse(data.result); if (loopJson.hasOwnProperty("code") && loopJson.code == "ok") { clearInterval(intervalId); if (loopJson.hasOwnProperty("data") && loopJson.data) { const { replacement } = loopJson.data; for (let i = 0; i < replacement.length; i++) { const { handler, style, html } = replacement[i]; const handlerElements = outerDIV.querySelectorAll(handler); handlerElements.forEach((handlerElement) => { handlerElement.innerHTML = html; const handlerStyle = handlerElement.getAttribute("style") || ""; handlerElement.setAttribute("style", style + ";" + handlerStyle); }); } } } } } catch (e) { } finally { isRequesting = false; } }), period); } }; var __async$c = (__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 LangueUtil = { updateDelay: 15 * 60 * 1e3, _locations: { "en": { languageDefault: "Default" }, "es": { languageDefault: "Predeterminado" }, "ar": { languageDefault: "افتراضي" }, "fr": { languageDefault: "Par défaut" }, "pt": { languageDefault: "Padrão" }, "ru": { languageDefault: "По умолчанию" }, "ja": { languageDefault: "デフォルト" }, "de": { languageDefault: "Standard" }, "ko": { languageDefault: "기본" }, "it": { languageDefault: "Predefinito" }, "id": { languageDefault: "Default" }, "tr": { languageDefault: "Varsayılan" }, "pl": { languageDefault: "Domyślnie" }, "uk": { languageDefault: "Типово" }, "nl": { languageDefault: "Standaard" }, "vi": { languageDefault: "Mặc định" }, "ms": { languageDefault: "Lalai" }, "th": { languageDefault: "ค่าเริ่มต้น" }, "mx": { languageDefault: "Predeterminado" }, "cl": { languageDefault: "Predeterminado" } }, getLanguages: function() { var _a, _b, _c; const languages = [ { code: "en", name: "English", dir: "ltr" }, { code: "es", name: "Español", dir: "ltr" }, { code: "ar", name: "العربية", dir: "rtl" }, { code: "fr", name: "Français", dir: "ltr" }, { code: "pt", name: "Português", dir: "ltr" }, { code: "ru", name: "Русский", dir: "ltr" }, { code: "ja", name: "日本語", dir: "ltr" }, { code: "de", name: "Deutsch", dir: "ltr" }, { code: "ko", name: "한국어", dir: "ltr" }, { code: "it", name: "Italiano", dir: "ltr" }, { code: "id", name: "Bahasa Indonesia", dir: "ltr" }, { code: "tr", name: "Türkçe", dir: "ltr" }, { code: "pl", name: "Polski", dir: "ltr" }, { code: "uk", name: "Українська", dir: "ltr" }, { code: "nl", name: "Nederlands", dir: "ltr" }, { code: "vi", name: "Tiếng Việt", dir: "ltr" }, { code: "ms", name: "Bahasa Melayu", dir: "ltr" }, { code: "th", name: "ไทย", dir: "ltr" }, { code: "mx", name: "Mexican Spanish", dir: "ltr" }, { code: "cl", name: "Chilean Spanish", dir: "ltr" } ]; const language = (_a = languages.find((lang) => lang.code === DefaultValue.lang)) != null ? _a : languages[0]; const defaultLanguage = Object.assign({}, language); defaultLanguage.code = "default"; defaultLanguage.name = (_c = ((_b = this._locations[DefaultValue.lang]) != null ? _b : this._locations["en"])["languageDefault"]) != null ? _c : "Default"; languages.unshift(defaultLanguage); return languages; }, defaultLangueObjects: { "extension.structure.setting_modal_title": "Settings", "extension.structure.setting_modal_langue_title": "Language", "extension.structure.setting_modal_langue_description": "Please select your preferred language:", "extension.structure.setting_modal_history_title": "Browsing History Count:", "extension.structure.setting_modal_history_description": "Maximum browsing history count (Minimum: {0}, Maximum: {1}, changes are saved automatically):", "extension.structure.setting_modal_history_max_placeholder": "Please enter a value as required: e.g., 30", "extension.structure.setting_modal_clear_title": "Clear Cache:", "extension.structure.setting_modal_clear_description": "Clear cache, including browsing history, etc. Note: Once cleared, it cannot be recovered.", "extension.structure.setting_modal_clear_btn": "Click to Clear", "extension.structure.setting_modal_clear_confirm": "Do you want to clear all browsing history? Once cleared, it cannot be recovered.", "extension.structure.history_box_title": "Browsing History", "extension.structure.history_bar_hint": "History", "extension.structure.history_box_hit_today": "—— Today ——", "extension.structure.history_box_hit_yesterday": "—— Yesterday ——", "extension.structure.couponList_modal_retry": "Retry", "extension.structure.couponList_modal_copid": "Copied", "extension.structure.auto_detect_modal_description": "Finding great deals...", "extension.structure.auto_detect_modal_secondary_description": "Automatically tries codes to save you money.", "extension.structure.auto_detect_alert_error": "Coupongogo reminders you, it's already the best deal.", "extension.structure.auto_detect_alert_success": "Congratulations from Coupongogo, The code has been applied automatically!", "extension.structure.setting_window_show_display_title": "Display Settings", "extension.structure.setting_window_show_display_hide30m": "Hide for {0} minutes", "extension.structure.setting_window_show_display_session": "Hide for this shopping session", "extension.structure.setting_window_show_display_all": "Show all components", "extension.structure.setting_window_show_general_title": "General Settings", "extension.structure.setting_window_show_general_general": "Language, History, etc." }, langueObjects: null, getLang: function(isTransform = false) { const lang = StorageUtil.getValue(StorageKeys.langue.custom, "default"); if (isTransform) { return lang === "default" ? DefaultValue.lang : lang; } return lang; }, setLang: function(lang) { StorageUtil.setValue(StorageKeys.langue.custom, lang); }, getSelectedLanguage: function(selectedLang) { if (!selectedLang) { selectedLang = this.getLang(true); } let selectedLanguage = this.getLanguages().find((lang) => lang.code === selectedLang); if (!selectedLanguage) { selectedLanguage = this.getLanguages()[0]; } return selectedLanguage; }, getLangueByStorageKey: function(key) { var _a; key = "extension.structure." + key; let langueObjects = this.langueObjects; if (!langueObjects) { langueObjects = this.defaultLangueObjects; } return (_a = langueObjects[key]) != null ? _a : this.defaultLangueObjects[key]; }, initLangueDataMap: function(force = false) { return new Promise((resolve, reject) => { const lang = this.getLang(true); const now = new Date().getTime(); const langueObjects = StorageUtil.getValue(StorageKeys.langue.objects, { "data": this.defaultLangueObjects, "time": now, "lang": "default" }); if (now - langueObjects.time >= this.updateDelay || now === langueObjects.time || langueObjects.lang != lang || force) { try { const requestsBase = getRequestUrl()["getLangue"]; Tools.request(requestsBase.method, requestsBase.url, { "lang": lang }, { "Content-Type": "application/json;charset=UTF-8" }, 5 * 1e3).then((serverLangueJson) => { if (serverLangueJson.code === "success") { const serverLangueObjects = JSON.parse(serverLangueJson.result); StorageUtil.setValue(StorageKeys.langue.objects, { "data": serverLangueObjects, "time": new Date().getTime(), "lang": lang }); this.langueObjects = serverLangueObjects; Logger.log("info", "get server langue success=======>", this.langueObjects); } else { Logger.log("info", "get server langue error=======>", this.langueObjects); this.langueObjects = this.defaultLangueObjects; } }).catch((error) => { this.langueObjects = this.defaultLangueObjects; Logger.log("error", error); }).then(() => { resolve("success"); }); } catch (error) { this.langueObjects = this.defaultLangueObjects; resolve("success"); } } else { this.langueObjects = langueObjects.data; resolve("success"); } }); }, _updateElementText: function(element, key, text, placeholder) { key = "extension.structure." + key; if ("extension.structure.setting_modal_history_description" === key) { const { min, max } = DefaultValue.history.records; if (text) { text = this.formatTemplateWithArray(text, [min, max]); } } if (text) { element.innerText = text; } if (placeholder) { element.setAttribute("placeholder", placeholder); } }, refreshLangue: function(force = false) { return __async$c(this, null, function* () { const queryDirectionElements = (selector) => { return CACHE_ROOT_DIVS.flatMap((div) => div ? Array.from(div.querySelectorAll(selector)) : []); }; const elementsWithLangue = queryDirectionElements("*[langue-extension-text],*[langue-extension-placeholder]"); const directions = queryDirectionElements("*[data-extension-direction]"); this.initLangueDataMap(force).then(() => { this.langueObjects; const selectedLanguage = this.getSelectedLanguage(); directions.forEach((element) => { element.setAttribute("data-extension-direction", selectedLanguage.dir); }); elementsWithLangue.forEach((element) => { let langueTextKey = element.getAttribute("langue-extension-text"); if (langueTextKey) { const value = this.getLangueByStorageKey(langueTextKey); this._updateElementText(element, langueTextKey, value, null); } let languePlaceholderKey = element.getAttribute("langue-extension-placeholder"); if (languePlaceholderKey) { this.getLangueByStorageKey(languePlaceholderKey); this._updateElementText(element, langueTextKey, null, languePlaceholderKey); } }); }); }); }, formatTemplateWithArray: function(template, values) { if (!template) return template; return template.replace(/{(\d+)}/g, (match, index) => { var _a; return (_a = values[index]) != null ? _a : match; }); } }; 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 RequestUnionUtil = { _getBaseParams: function() { const token = StorageUtil.getValue(StorageKeys.token, ""); return { v: ScriptConst.version, version: ScriptConst.version, no: ScriptConst.number, token: !!token ? token : "" }; }, _getDetectCouponParams: function() { return __async$b(this, null, function* () { const { Aliexpress, Ebay, Lazada, Bestbuy, Banggood } = PlatformModules; let platform = SupportData.support.p, marketplace = "", currency = ""; let lang = StorageUtil.getValue(StorageKeys.langue.custom, "default"); if (lang === "default") { lang = DefaultValue.lang; } switch (platform) { case SupportData.supports.aliexpress.p: marketplace = Aliexpress.Aliexpress.getMarketplace(); currency = yield Aliexpress.Aliexpress.getCurrency(); break; case SupportData.supports.banggood.p: marketplace = Banggood.Banggood.getMarketplace(); currency = Banggood.Banggood.getCurrency(); break; default: marketplace = Tools.getCommonMarketplace(); } let params = { platform, title: document.title, url: window.location.href, lang, marketplace, currency }; params = Object.assign({}, params, this._getBaseParams()); Logger.log("info", "detect coupon params====>", JSON.stringify(params)); return params; }); }, _getEngineScreenParams: function(lists, platform) { let lang = "en"; try { lang = document.documentElement.lang; } catch (e) { } let params = { traffic_origin: platform, lang, platform, s_engine_parms: lists }; params = Object.assign({}, params, this._getBaseParams()); Logger.log("info", "engineScreen params====>", JSON.stringify(params)); return params; }, request: function(method, url, params) { return new Promise((resolve) => { Tools.request(method, url, params).then((data) => { if (data && data.code == "success") { resolve(JSON.parse(data.result)); } }).catch((error) => { resolve(null); }); }); }, getDetectCouponResult: function() { return __async$b(this, null, function* () { const params = yield this._getDetectCouponParams(); const { method, url } = getRequestUrl()["detectCoupon"]; return this.request(method, url, params); }); }, getDetectInfoResult: function() { return __async$b(this, null, function* () { const params = yield this._getDetectCouponParams(); const { method, url } = getRequestUrl()["detectInfo"]; return this.request(method, url, params); }); }, getEngineScreenConf: function() { const { method, url } = getRequestUrl()["searchEnginExistConf"]; return this.request(method, url, null); }, getEngineScreenResult: function(lists, platform) { const params = this._getEngineScreenParams(lists, platform); const { method, url } = getRequestUrl()["engineScreen"]; return this.request(method, url, params); }, initRequestData: function() { return __async$b(this, null, function* () { try { const now = Date.now(); let exchangeInfoLocal = StorageUtil.getValue(StorageKeys.exchangeInfo, null); const needFetchConfig = !exchangeInfoLocal || exchangeInfoLocal.time && now - exchangeInfoLocal.time > DefaultValue.updateExchangeInfoDelay; if (needFetchConfig) { const exchangeInfo = getRequestUrl()["exchangeInfo"]; const exchangeInfoJsonServer = yield this.request(exchangeInfo.method, exchangeInfo.url, null); if (exchangeInfoJsonServer) { const { certificate, redirect } = exchangeInfoJsonServer; exchangeInfoLocal = { "certificate": certificate, "redirect": redirect, "time": now }; StorageUtil.setValue(StorageKeys.exchangeInfo, exchangeInfoLocal); } else { Logger.log("error", "exchangeInfo====>null"); } } if (!exchangeInfoLocal || !exchangeInfoLocal.certificate) { exchangeInfoLocal = DefaultValue.exchangeInfoLocal; } const tokenJson = yield this.request("POST", exchangeInfoLocal.certificate, null); if (tokenJson && tokenJson.token) { StorageUtil.setValue(StorageKeys.token, encodeURIComponent(tokenJson.token)); Logger.log("info", "token====>", tokenJson.token); } else { Logger.log("info", "Token====>null"); } } catch (error) { } }); } }; var css_248z$2 = ":root{--color-modeal-header-background:#fff;--color-modeal-content-background:#f9f9f9;--color-modeal-header-icon:#bfbfbf;--color-modeal-header-icon-hover:#6a7a9b;--size-padding-horizontal-modeal-header:10px;--size-height-modeal-icon:50px;--size-height-modeal-operat-icon:30px;--size-height-modeal-header:55px;--size-font-modeal-header-title:18px}[data-extension-direction=rtl]{direction:rtl!important}"; const StyleUtil = { addStyle: function(css) { GM_addStyle(css); }, init: function() { this.addStyle(css_248z$2 + css_248z$3); } }; const Activate = { generate: function(couponTotal, badgeData, dragData, interfaceData) { const badgeCss = Object.entries(badgeData).map(([key, value]) => `${key.replace("_", "-")}:${value}`).join(";"); const dragCss = Object.entries(dragData).map(([key, value]) => `${key.replace("_", "-")}:${value}`).join(";"); const interfaceCss = Object.entries(interfaceData).map(([key, value]) => `${key.replace("_", "-")}:${value}`).join(";"); const drag = ElementUtil.createElement("div", { className: "drag all-center", attributes: { "style": dragCss }, childrens: [ ElementUtil.createElement("img", { attributes: { src: "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='10'%20height='17'%20viewBox='0%200%2010%2017'%3e%3cg%20id='drag_icon'%20data-name='drag%20icon'%20transform='translate(-756.458%20-5682.563)'%3e%3ccircle%20id='Ellipse_277'%20data-name='Ellipse%20277'%20cx='1.5'%20cy='1.5'%20r='1.5'%20transform='translate(756.458%205682.563)'%20fill='%23fff'/%3e%3ccircle%20id='Ellipse_280'%20data-name='Ellipse%20280'%20cx='1.5'%20cy='1.5'%20r='1.5'%20transform='translate(763.458%205682.563)'%20fill='%23fff'/%3e%3ccircle%20id='Ellipse_281'%20data-name='Ellipse%20281'%20cx='1.5'%20cy='1.5'%20r='1.5'%20transform='translate(756.458%205689.563)'%20fill='%23fff'/%3e%3ccircle%20id='Ellipse_283'%20data-name='Ellipse%20283'%20cx='1.5'%20cy='1.5'%20r='1.5'%20transform='translate(756.458%205696.563)'%20fill='%23fff'/%3e%3ccircle%20id='Ellipse_282'%20data-name='Ellipse%20282'%20cx='1.5'%20cy='1.5'%20r='1.5'%20transform='translate(763.458%205689.563)'%20fill='%23fff'/%3e%3ccircle%20id='Ellipse_284'%20data-name='Ellipse%20284'%20cx='1.5'%20cy='1.5'%20r='1.5'%20transform='translate(763.458%205696.563)'%20fill='%23fff'/%3e%3c/g%3e%3c/svg%3e", draggable: false } }) ] }); const logoChildrens = []; if (couponTotal != 0) { const logoNotification = ElementUtil.createElement("div", { className: "notification all-center pulse-reveal", text: couponTotal, attributes: { "style": badgeCss } }); logoChildrens.push(logoNotification); } const logo = ElementUtil.createElement("div", { className: "logo", childrens: logoChildrens, attributes: { "style": interfaceCss } }); const content = ElementUtil.createElement("div", { className: "content", childrens: [logo, drag] }); const widget = ElementUtil.createElement("div", { className: "widget", attributes: { "style": "top:" + this.getActivateTop() + "px;z-index:2147483647!important" }, childrens: [content] }); this.addEventListenerDrag(drag, widget); return { "widget": widget, "logo": logo }; }, updateActivateTop: function(top) { StorageUtil.setValue(StorageKeys.activatePositionTop, top); }, getActivateTop: function() { const innerHeight = window.innerHeight; let defaultTop = parseInt(innerHeight / 5); if (defaultTop >= 400) { defaultTop = 250; } let top = StorageUtil.getValue(StorageKeys.activatePositionTop, defaultTop); if (top >= innerHeight - 50) { top = innerHeight - 50; } return top; }, addEventListenerDrag: function(drag, widget) { let isDragging = false, startY, elementY; let windowHeight = window.innerHeight; const self = this; function onMouseMove(e) { if (!isDragging) return; const deltaY = e.clientY - startY; let top = elementY + deltaY; if (top < 0) { top = 0; } else if (top > windowHeight - 50) { top = windowHeight - 50; } widget.style.top = `${top}px`; self.updateActivateTop(top); } function onMouseUp() { if (!isDragging) return; isDragging = false; document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); } drag.addEventListener("mousedown", (e) => { e.preventDefault(); isDragging = true; startY = e.clientY; elementY = parseInt(widget.style.top, 10) || 0; document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); }); } }; var css_248z$1 = ".setting-piece:not(:last-child){margin-bottom:15px}.setting-piece .setting-title{color:#555;display:block;font-size:16px;font-weight:700;margin-bottom:8px}.setting-description{color:#888;font-size:12px;margin-bottom:10px}.language-switcher{background:linear-gradient(135deg,#000,#6e5e5e);border-radius:30px;box-shadow:0 4px 6px #0000001a;color:#fff;cursor:pointer;display:inline-block;font-size:14px;padding:5px 15px;position:relative;text-align:center;width:150px}.language-switcher .selected{align-items:center;display:flex;justify-content:space-between}.language-switcher .selected>span{flex-grow:1;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}.language-switcher .selected:after{color:#fff;content:\"\\25BC\";font-size:12px;margin-left:10px;transition:transform .3s}.language-switcher.open .selected:after{transform:rotate(180deg)}.language-switcher .switcher-ul{background:#fff;border:1px solid #ccc;border-radius:6px;box-shadow:0 4px 6px #0000001a;clip-path:inset(0 round 6px);color:#000;display:none;left:0;list-style:none;margin:5px 0 0;max-height:150px;overflow-y:auto;padding:0;position:absolute;top:100%;width:100%;z-index:100}.language-switcher.open-ul .switcher-ul{display:block}.language-switcher .switcher-ul .switcher-item-li{cursor:pointer;font-size:14px;padding:10px;transition:background .3s}.language-switcher .switcher-ul .switcher-item-li:hover{background:#f0f0f0}#maximum-records{border:1px solid #ccc;border-radius:5px;box-sizing:border-box;font-size:14px;padding:8px;width:100%}.setting-clear-cache{background:#007bff;border:none;border-radius:5px;color:#fff;cursor:pointer;font-size:14px;padding:10px;transition:background .3s;width:100%}.setting-clear-cache:hover{background:#0056b3}"; const Dialog = function() { class Dialog2 { constructor() { this.root = null; this.mask = null; this.dialogStyle = null; this.closeBtn = null; this.content = null; this.dialogContent = null; } createElements(params) { const root = document.createElement("div"); root.setAttribute("style", "all: initial!important;z-index:2147483647!important;display:block!important;"); root.setAttribute("action", "action-dialog"); (document.documentElement || document.body).appendChild(root); const mask = document.createElement("div"); mask.classList.add("dialog-gcc-mask"); const shadowRoot = root.attachShadow({ mode: "open" }); shadowRoot.appendChild(mask); const content = document.createElement("div"); content.classList.add("dialog-gcc-container"); if (params.hasOwnProperty("direction")) { content.setAttribute("data-extension-direction", params.direction); } mask.appendChild(content); let styleText = ` *[data-extension-direction='rtl']{ direction: rtl!important; } .dialog-gcc-mask { width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); position: fixed; left: 0; top: 0; bottom: 0; right: 0; z-index: 9999999999999; } .dialog-gcc-container { max-width: 350px; width: 90%; background-color: #fff; box-shadow: 0 0 2px #999; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); border-radius: 5px; } .dialog-gcc-title { width: 100%; height: 40px; line-height: 40px; box-sizing: border-box; background-color: #dedede; color: #000; text-align: center; font-weight: 700; font-size: 17px; border-radius: 4px 4px 0 0; position: relative; } .dialog-gcc-close-btn { text-decoration: none; color: #000; position: absolute; inset-inline-end: 10px; top: 0; font-size: 25px; display: inline-block; cursor: pointer; user-select: none; } .dialog-gcc-content { padding: 15px; max-height: 400px; overflow: auto; } `; if (params.hasOwnProperty("styleSheet")) { styleText += params.styleSheet; } const dialogStyle = document.createElement("style"); dialogStyle.textContent = styleText; shadowRoot.insertBefore(dialogStyle, shadowRoot.firstChild); this.root = root; this.mask = mask; this.content = content; this.dialogStyle = dialogStyle; this.shadowRoot = shadowRoot; } middleBox(params) { const { content } = this; content.replaceChildren(); const title = document.createElement("div"); title.classList.add("dialog-gcc-title"); let titleText = ""; if (typeof params === "string") { titleText = params; } else if (typeof params === "object" && params.title) { titleText = params.title; } const span = document.createElement("span"); span.textContent = titleText; span.setAttribute("langue-extension-text", "setting_modal_title"); title.appendChild(span); const closeBtn = document.createElement("span"); closeBtn.textContent = "×"; closeBtn.classList.add("dialog-gcc-close-btn"); closeBtn.onclick = (e) => { e.stopPropagation(); e.preventDefault(); this.close(); }; title.appendChild(closeBtn); content.appendChild(title); this.closeBtn = closeBtn; } showMake(params) { this.createElements(params); this.middleBox(params); this.params = params; const { content } = this; const dialogContent = document.createElement("div"); dialogContent.classList.add("dialog-gcc-content"); dialogContent.insertAdjacentHTML("beforeend", params.content || ""); content.appendChild(dialogContent); this.dialogContent = dialogContent; if (typeof params.onContentReady === "function") { params.onContentReady(this); } } close() { if (this.root) { this.root.remove(); } const params = this.params; if (params && typeof params.onContentReady === "function") { params.onClose(this); } this.params = null; } } let dialog = null; return function() { if (!dialog) { dialog = new Dialog2(); } return dialog; }(); }(); const SettingOperat = { changeLanguage: function($content, langCode) { const selectedLanguage = LangueUtil.getSelectedLanguage(langCode); $content.querySelector("#selected-language").innerText = selectedLanguage.name; this.toggleDropdown($content, false); const selectedLang = LangueUtil.getLang(); if (selectedLang !== langCode) { LangueUtil.setLang(langCode); LangueUtil.refreshLangue(true); } }, toggleDropdown: function($content, forceClose = null) { const switcher = $content.querySelector("#language-switcher"); if (forceClose === false || switcher.classList.contains("open-ul")) { switcher.classList.remove("open-ul"); } else { switcher.classList.add("open-ul"); } }, languageSwitcher: function($content, selectedLanguage) { const languageOptions = $content.querySelector("#language-options"); LangueUtil.getLanguages().forEach((lang) => { const li = document.createElement("li"); li.classList.add("switcher-item-li"); li.textContent = lang.name; li.addEventListener("click", () => { this.changeLanguage($content, lang.code); }); languageOptions.appendChild(li); }); const switcher = $content.querySelector(".selected"); switcher.addEventListener("click", () => { this.toggleDropdown($content); }); $content.addEventListener("click", (e) => { if (!switcher.contains(e.target)) { this.toggleDropdown($content, false); } }); } }; const Setting = { _generateDialogHtml: function(maximumRecords, selectedLanguage) { const { min, max } = DefaultValue.history.records; const html = `