JTMate - نەق پۇل قايتۇرۇش ۋە كۇپونلار

چىكىتلاشتا ئەڭ ياخشى كۇپون كودى ۋە ئەڭ ياخشى نەق پۇل قايتۇرۇشنى ئاپتوماتىك تېپىپ قوللىنىدۇ. (مەخپىيەتلىك سىياسىتى: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)

Before you install, Greasy Fork would like you to know that this script contains antifeatures, which are things there for the script author's benefit, rather than yours.

This script earns commission for the author, for example by rewriting links or providing coupon codes to include a referral or affiliate code.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        JTMate - Cash Back And Coupons
// @name:ar     JTMate - استرداد نقدي وكوبونات
// @name:bg     JTMate - Кешбек и купони
// @name:ckb    JTMate - گەڕاندنەوەی پارە و کوپۆن
// @name:cs     JTMate - Cashback a kupóny
// @name:da     JTMate - Cashback og kuponer
// @name:de     JTMate - Cashback und Gutscheine
// @name:el     JTMate - Επιστροφή χρημάτων και κουπόνια
// @name:en     JTMate - Cash Back And Coupons
// @name:eo     JTMate - Repagoj kaj kuponoj
// @name:es     JTMate - Reembolso y cupones
// @name:es-419 JTMate - Cashback y cupones
// @name:fi     JTMate - Cashback ja kupongit
// @name:fr     JTMate - Cashback et coupons
// @name:fr-CA  JTMate - Remises en argent et coupons
// @name:he     JTMate - קאשבק וקופונים
// @name:hr     JTMate - Povrat novca i kuponi
// @name:hu     JTMate - Pénzvisszatérítés és kuponok
// @name:id     JTMate - Cashback dan kupon
// @name:it     JTMate - Cashback e coupon
// @name:ja     JTMate - キャッシュバックとクーポン
// @name:ka     JTMate - ქეშბექი და კუპონები
// @name:ko     JTMate - 캐시백 및 쿠폰
// @name:nb     JTMate - Cashback og kuponger
// @name:nl     JTMate - Cashback en kortingsbonnen
// @name:pl     JTMate - Cashback i kupony
// @name:pt-BR  JTMate - Cashback e cupons
// @name:ro     JTMate - Cashback și cupoane
// @name:ru     JTMate - Кэшбэк и купоны
// @name:sk     JTMate - Cashback a kupóny
// @name:sr     JTMate - Повраћај новца и купони
// @name:sv     JTMate - Cashback och kuponger
// @name:th     JTMate - เงินคืนและคูปอง
// @name:tr     JTMate - Nakit iadesi ve kuponlar
// @name:uk     JTMate - Кешбек і купони
// @name:ug     JTMate - نەق پۇل قايتۇرۇش ۋە كۇپونلار
// @name:vi     JTMate - Hoàn tiền và mã giảm giá
// @name:zh-CN  JTMate - 购物助手
// @name:zh-TW  JTMate - 購物助手
// @description        Automatically finds and applies the best coupon code and cashback. (Privacy Policy: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ar     يبحث تلقائيًا عن أفضل رمز قسيمة ويطبق أفضل استرداد نقدي عند إتمام الشراء. (سياسة الخصوصية: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:bg     Автоматично намира и прилага най-добрия код за купон и най-добрия кешбек при плащане. (Политика за поверителност: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ckb    بە شێوەی خۆکار باشترین کۆدی کوپۆن و باشترین گەڕاندنەوەی پارە دەدۆزێتەوە و لە کاتی پارەداندا بەکاری دەهێنێت. (سیاسەتی نهێنی: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:cs     Při placení automaticky najde a použije nejlepší kód kupónu i cashback. (Zásady ochrany osobních údajů: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:da     Finder automatisk og anvender den bedste kuponkode og cashback ved checkout. (Privatlivspolitik: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:de     Findet automatisch den besten Gutscheincode und das beste Cashback und wendet beides beim Checkout an. (Datenschutzrichtlinie: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:el     Βρίσκει αυτόματα και εφαρμόζει τον καλύτερο κωδικό κουπονιού και το καλύτερο cashback στο checkout. (Πολιτική Απορρήτου: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:en     Automatically finds and applies the best coupon code and cashback. (Privacy Policy: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:eo     Aŭtomate trovas kaj aplikas la plej bonan kuponkodon kaj cashback ĉe pagado. (Privateca Politiko: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:es     Encuentra y aplica automáticamente el mejor código de cupón y el mejor cashback al finalizar la compra. (Política de privacidad: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:es-419 Encuentra y aplica automáticamente el mejor código de cupón y el mejor cashback al finalizar la compra. (Política de privacidad: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:fi     Löytää ja käyttää automaattisesti parhaan kuponkoodin ja cashbackin kassalla. (Tietosuojakäytäntö: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:fr     Trouve et applique automatiquement le meilleur code promo et le meilleur cashback au moment du paiement. (Politique de confidentialité: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:fr-CA  Trouve et applique automatiquement le meilleur code promo et le meilleur cashback au passage à la caisse. (Politique de confidentialité: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:he     מאתר ומחיל אוטומטית את קוד הקופון הטוב ביותר ואת הקאשבק הטוב ביותר בשלב התשלום. (מדיניות פרטיות: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:hr     Automatski pronalazi i primjenjuje najbolji kod kupona i najbolji cashback pri naplati. (Pravila privatnosti: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:hu     Automatikusan megkeresi és alkalmazza a legjobb kuponkódot és cashbacket fizetéskor. (Adatvédelmi irányelv: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:id     Secara otomatis menemukan dan menerapkan kode kupon terbaik dan cashback terbaik saat checkout. (Kebijakan Privasi: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:it     Trova e applica automaticamente il miglior codice coupon e il miglior cashback al checkout. (Informativa sulla privacy: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ja     チェックアウト時に最適なクーポンコードとキャッシュバックを自動で見つけて適用します。 (プライバシーポリシー: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ka     გადახდისას ავტომატურად პოულობს და იყენებს საუკეთესო კუპონის კოდსა და საუკეთესო ქეშბექს. (კონფიდენციალურობის პოლიტიკა: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ko     결제 시 최적의 쿠폰 코드와 캐시백을 자동으로 찾아 적용합니다. (개인정보 처리방침: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:nb     Finner og bruker automatisk den beste kupongkoden og cashback i kassen. (Personvernerklæring: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:nl     Vindt en past automatisch de beste couponcode en cashback toe bij het afrekenen. (Privacybeleid: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:pl     Automatycznie znajduje i stosuje najlepszy kod kuponu oraz najlepszy cashback przy finalizacji zakupu. (Polityka prywatności: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:pt-BR  Encontra e aplica automaticamente o melhor código de cupom e o melhor cashback no checkout. (Política de Privacidade: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ro     Găsește și aplică automat cel mai bun cod de cupon și cel mai bun cashback la checkout. (Politica de confidențialitate: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ru     Автоматически находит и применяет лучший промокод и лучший кэшбэк при оформлении заказа. (Политика конфиденциальности: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:sk     Pri platbe automaticky nájde a použije najlepší kód kupónu aj cashback. (Zásady ochrany osobných údajov: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:sr     Аутоматски проналази и примењује најбољи код купона и најбољи cashback при наплати. (Политика приватности: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:sv     Hittar och tillämpar automatiskt den bästa kupongkoden och cashback i kassan. (Integritetspolicy: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:th     ค้นหาและใช้รหัสคูปองและแคชแบ็กที่ดีที่สุดโดยอัตโนมัติในขั้นตอนชำระเงิน (นโยบายความเป็นส่วนตัว: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:tr     Ödeme sırasında en iyi kupon kodunu ve en iyi cashback'i otomatik olarak bulur ve uygular. (Gizlilik Politikası: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:uk     Автоматично знаходить і застосовує найкращий код купона та найкращий кешбек під час оформлення замовлення. (Політика конфіденційності: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:ug     چىكىتلاشتا ئەڭ ياخشى كۇپون كودى ۋە ئەڭ ياخشى نەق پۇل قايتۇرۇشنى ئاپتوماتىك تېپىپ قوللىنىدۇ. (مەخپىيەتلىك سىياسىتى: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:vi     Tự động tìm và áp dụng mã giảm giá tốt nhất và hoàn tiền tốt nhất khi thanh toán. (Chính sách quyền riêng tư: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:zh-CN  自动查找并应用最佳优惠券代码和返现 (隐私政策: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @description:zh-TW  自動搜尋並套用最佳優惠券代碼及現金回饋 (隱私政策: https://github.com/jtmate/JTMate-Shopping-Assistant-Userscript/blob/main/SCRIPT_POLICY.md)
// @namespace   jtmate_shopping_assistant
// @version     1.1.4
// @author      Jtmate
// @icon        data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGYktHRAD/AP8A/6C9p5MAAAABb3JOVAHPoneaAAAogklEQVR42u2deZRfVZXvP/vc31RjqipVmSoJCSEJCVOgwyAIiDiiIAoqiqt9jq2r1W6f3a1tP7vV10uWttKi0nY/7FZaBWlQUAREwSCThikJgyRAAkllqgw1D7/h3rPfH+ec+6uQAAmQ+hWm9lqVVP3u8Lv3nH328N3DEV4EzfiLb+uLuW6SDi713XrF24vPPHzDgVwj+3ti4Yjl78nPPeotdQuXX1zrF52k56Z4uG9zacPq6wbv/emn9+f86IVOMPm6lsyUaYva3vqJ27JTZx1b6xecpOcnkys056bPOyVqnXV0vHPj/Voe7Xu+819QAkx99/95PNsy/chav9gkvTjqu/0H7yk+9eBPnuv4czKAqW+e0XHRF56UbKGx1i8xSS+Nen7+zdPL29ffva9j+2SAltd94CeZ6fNflWlsnVvrh5+kl4E0SSo92x7Zfd1Xj3/2IbPXB/XNM7KTk/+nRRJF2amzlxXmHXPeXoee/cH0D/zLoOQmxf6fJGmS9Pzi268Zqw5SL8Dk61qmXvi5VVFDy6xaP+ckHSQSY+qOPOWDSf+OdXHPtkdhjAowja1zM5PWfk1JOABg5iVQYeGJ70PEgJcAdUcsf0/bWz9xW60HYJLGhzJTpi2KWmYeVdqw6loDkJt71Ftq/VAHk8ZjVb3SqG7BsgujhpbOCKD1DR/+aa0faJJqQGKMTAZ2XjkkwMs9Weal32KSxosOxkqdZIAJROPlBYylSQaYQKQ8/yo/GMwxyQATiF5IAhwMFZCp9UtPUpVqYY1PSoBDnCYZ4BCnSQY4xGmSAQ5xmmSACUS1wAEmvYAJRLXwAiYZAMhIgiGmjiL1UUxOSyQmoqJ5epJGYo3QP9GY4iHNANOjXk5qe4K3L3iE1kwPDYUidSamsVCmFGcYGcmwdnAaKzYv5a5dx7A9mQocnKBMuC8H6d7P+Z2HYjSw2Yzw2tY1vH/x7zjl8C3YYYOKIgkogsSKEcWKIPWAwBPdbfznIydwc88Z7LYttX6Fl40OOQZYmOvi88fewBnzN1BILFoCjIAqxiiageFSFrVCQyEmIsFWBBGhVCfct2Uun733nTyjc2r9Ki8LHTIMYLAcP+VpLll+NUdP7YaikGDAKmIgyQubBtu49emj+d22xQAsbd3FSe1rOW3mepqkiMYRUpewcvdsPnXv+9lcmf6yPuOkCjhYL4lyRsMDXPqmnzK9MgIGDIqNI6xC0mj43gOn8P1Nr6M7biHRqnecNxX+rOlpvnbSNSxo3AEVIcnCnV0dfOz+v2JAmmv9ei+Josbl53yx1g9xsOmIzCa+8ZqrmJcdQhAMiqqBPOygkX+4+wK+1/V6Bmz9XtZ+ohFdpams3HkEJ3Y8SXthBIlhXucw3T1ZVg0uqvXrvST6kweCDsvu5N9P/y+ObBlAY4NawDPB08NTedfNn+L67pNRPxTP5ew9NtjJx//wYXbH9aiBZNBw8dL7aYqKtX7Fl0R/0gywoLCDb5z03yyd1ksyKiAWgCSBPsnxlYfezvrK9D0m/fn04TPD7fzmmcVIXjFWmd/Sy0mFNbV+zZdEr3gGEHSPH4OSlZhjG5/hqjO+w6kzNmJHDGIUEUEMDJs6PnLXR/lV99HpffbHECpphpu3/Rn9xRwSKXngXYfdRb28cqXAKxYIqpciR9ZtZnZ+J6ihYjM05SvUyxDLZmzkNfPXMy0axCYGMXbMBCuDIwVOb1vH4fXb2TLUxuZSB1tKUxhO8i+I+K3sW8jO4ak0t2xHEjjr2C4Wb+pi1dDCWg/Ji6JXHANksBzZ0MX/XvJLls/aQEeuzO4kCxgKJqEgMVEG599jnG+PgChYBYTOpl4+tezXqJ/rrYMNbOyfybrd0+gut7JxdCobRmYwnNQxnOQYiXOUbJZEhaGkwLrBmSycug1bERoiOKdzNavWHRwGONiu4SuKAfIm5s9nreCjJ65glgxBApoIrTZ2yJ0VEMGWAXGArQGH8imoGEQUVFEFtQYszGgYZUbTBk6eux5VIRFDsZJltJSlRJ7ugRa6htrYOdrCiGZY1rYZTQwCJP2G8xeu4v6th7G2tIDt5SbK5F7yuzZmyrRlR9k22kDlIE7TKwYHqJMSHzvsN3zyxN9SKFdQK5ABUXVIngULSOTDqqJYFRAQBKsKGEQsgoLxDICi6hjHqLp7qGIyikUQPzpqQTKCWg22JGKVxBrIKMVixI5KM88MNHPLtuX8YdeRdI22UbLZ/Vq9kVimZQdY0tTFSc3reO2cLqY29vKH7pl8/dF38nSp/aCM6ytCAgjKhdPv5tOn/JrMMKiAidTp90Zl07YpTKkfpSlXdhPuZ028FFBRUDBi3XELqpIyiRoQLOr4wSPD4oI+6sWwUTTxv4vHESIc46DU1SXMK/Qxr7mXM+dtZKBU4N4Ni7hp+8k80D+HHZUGykkGuw8bY2auj7d2rOHDx69gZnMfmVICsTvvDQsGWLHhqUObARbnt/CJ41YQjYgT54gT1RnhticX8vU/ns9x7dv5yglXkQnrzaG81QYInjGsNU47hM8sXiIIouqOibMVAMR/nhoMAqLiDEt1XgUECSQYFbQIzZkSb178MK9f9BgD5UbWD0xj21ATGwfbGYqzZCUhFymLmrezpKOLOQ29SGKQIUXxqiorrN06nRWDB68524RngIaoyFeO/RGzGweQSnV12wjW7JrJRx/8OCWbZWOpg/fMn8YJs7ZBGdQKkVishOCtkIggRj2LqF/dgg1LPZB6plCwKniJ71hCvUGp4o5bxWAJXKWCkyiJUxGRVZplmOVtT0G7i0mQwXGmBSpQKUdQFBTr+Cx8Z4PyH4++ht1x/UEb3wmLA4RFeuHMuzlx8VaIASOocSLbGOWmp5dRslkAyjbD+r5myJGudsVNkqpPtkrE39c5e8b4+fQ/IScrsIwVA+JUggHEVBlQAUQxBiRyJ4gLKmIExDjdYSIlE8XueRKntrRo0BGBESBx5xB5aePkG6O5iM9cfzq39//ZQR3nCcsACtSbEufOW0M0PEYqOwuPYmJ4fHDeni8jjhkSlarrh3iHQJHIXR8Yw6pf/e5iPxruS9y/6idcHENocMckGAME+WA02B1Vu0Ex7hrjGVHcs6hRb7w65lQr3pxwYJZtgGtXL+H6gfMp6kv3KJ6PJiwDALxqylqOmrIVLYtXwW6AENg6OpM/js5Oz3UWu0Dsp9AzTBhUBdS6/43xK04gwoFERoN174xGFXFaoQofEIVJF+9yWPyMV5kqkPp/BHX2gQpo9Z6aMpu71ipYK5QLwg2PHM0317+TCvvnQbwUmrAMkDMx5866j5ZcjERe7PpBJAPbeyJKcdWEyUlCe2HEW/FuEpPYGXDWy3jxLqGqeLXgsAGlqudT0qpaCPaAos5V9O4l3mtA1HkG7iHxZqpjPlFM1URwzOS+GKy73AR7ox5+uW4JX1p7ETvHKetowjLAzGw/Z81dj429n+4HWhEkUZbN6eK1LY+k5y+u38Jx0zajJZO6WiYCNQZjxa9zQdUBQW6inKFmRBG/Oo1q6vsL6vx/P6FqTVX6g5tA6xkqcXJGMc6ltOIljjiPTt35brLFcUIAKC1oi+X6Px7JFx55H7vipnEb5wnLALMLu2jJF92Ei8vacVLTDW6hAO9eeh+tmRHOaFvLJcf9kKZ82Yv8YLG7f2xAAr1ydpLcSQcVvxI9Q1gVUq2v7rxEnd+v6hiCBOenCwyTZ/dQA2oNJlUZPrSsAlacAaneMA33D7aChaKJ+PbdZ/BPj1xMb9IwruM8Yd3AxY1bMMa6QfSWvBgLHsBJhiNOn7mOW8/8Bm0Ng9QXStiKgSipGnoGsN56V/XAUJhXTdWA5wFnA6RGolu9xlq3plUdpqDuOslbfrf5WO54ai4fXXYHRqxf1BrwIfD2R7AVVAWjTuoQ+S9tV77z69P59ubzJ+sCxtKC5h1EOH0bDL8wYQDGWDQxzG7biSagcdD9pIYZ1uM3PtvXXa8YI2ji4wHGo4TqRLhX507yKM5+8CLbGrCRYV3/TL6z8g0kScQXT/o5M3LDaMW5cZqu9PRJncGXqJcE3kPB0p/LculNZ3PVzteSEcuswgAbR1vGdZwnpAoQYH7jNrQiLlXbCol1eHxgBBFF1IIVggHuIF0fH1Cf4+MNLfz1Ai4RNPyeAF5fWxuscVIGSuIIGwtx3rAjbuS7q87m4js+zrRcD/926pVMZxdUnItnEyfWbeIYxkkSi3ovwNqqrdBfyPH3v3oTV3SfQ9Hm+MCsO7jsuO8TyfjKgQkpAep1iPb8IGKr+jJSB66IdatSEqn6e9YhfIRjweK2Ui3iEM8Q3qVLMfkxVR6RlyCp2FYhyll6K3muX72cq7ecTls0yA9O+3eObtuKKblVb8UlolgDYj22IIL46CQJREadbZCx7CzX8dVfn8MvB18FAud1rOTzp9/IDQ8dU/USxokmJANMy/XRURjxPXMc2CImgDvVaJ8iTp8Gve0nQr3aCD139kz5Em+QOckCVRQ4fI519sNwlOXWdUu5Yv0bWT/azps6VvNPy26grTACJarSSD1DeYY0XtWkgSQxTk1llK7RVi75wzncNLCcRAxL88/w6aNvIVdKWDs4a9xL0CYkA3TUl2itK6Oxi+Wrg8xSy94CkfGL3/iBT9wKhDFRPlxEUMNFBA/BW/9qEXVVQeBEt0SQZJWHumbxtXXns2ZgPkYt/7joJ1ywdA11ceJduMA8qWPv/w6/uyihVSGJlWy9sqq7g3+4/2L+WJ5HosK8/A6+8+rvM7+hn7JGdI12jPtYT0gGmGZ6yGYSh/8LTtcrSAZvSVct+LHAjFHnZ6t38TCCwZKoVF3DsPIVH/cl9RSSAjyzu43//uMJ3LjrdLorLZwy5Sn+dtGNnDjzGaLYQ7iQWvzBn3MAU9AogtFq6DlTUFZu6+TTv38fG3UWCDQyxCcXXcuRLb0kQ0KxYOiuTBn3sZ5wDCDA9Fw35diSVQ/vBvHqQ7fBTQNxhqF395yZ7UEWFUi8K4czAFU8g/jTNHaGm6mDcj7PdSuX8u1N57G53IZFeFvLA1zy6v+hSUoQi/MYwlc7w8Jb9VU1k6ZwiUAFpBke6ergk/d9gM06DYC8xPzzkut455In0D5BI8PASI6dpfHfpmFCMYAAGYlZ3NpLlmoUL6y6YKxVtaSmOr3KFB7uBUKGhw2QrXfBJKQPGYEc3L1xAf9v3ZncM7iUouaoj8q8d8ZdfO6Em6mXCrYizu0MeMSYRD3F1xRaVz+YQsqxIHXK7U8dzufWvIfNybTU3nzztDWcv/hhTJ/1QaiEOM4ySmHcx3xCMYACBSlzRPMWDEEDKNY6WBfrdXcIyauL0NhEUy8ACfqdsNYhcceM+BVs3ZvvjnN86/Yz+Z/hsxlI6gBojkb41Izr+MAJD5Ivg2ZwIE4wz1T3MtTUeyshLUBjoEG5Z207/7ThvWxOpqXvt6x+I5ccfS254di/i7NZNg+2Uj7Ikb990YRiAID27AAzGwahIkQomgjGi38NSy9E1ERd9M+DPQAaud9FxmD6XitYFUzG0pfk+dX6xfy460xWDR+B9XDI1OwQn5t/HRcsXE0+Dgrdr1tb9SjEexppopA/J6CJ0qj8esN8/umpi9lUmZa+2+zsLr50zDU0Z0fRwJBWsUZ4clc7w8kkAzAv182MuhGoOKtOXKzWr0L85LpzxQ9+QPCsgCTiM3997p+3D9QKUlCeHm7m8gdfw3W9Z1HW6ut3ZAf46uKreNP8x5AKaQzC2rR6PDX6NASJUgzB9xNIDNQp92yYyRcffjeb7LTUZW00Rf523rWc2N6FlgwSVYEpmwir+zsPavbvc9GEY4AZdls68K6M1zVuIGTthCxepBpb9QihUcc0wb9PABN7RmoWfv3oPC5Zdz5P28OIx1QAL8lv5ktHXcWpM7dgRyNMlDhVYiVlMtFg8Y8J7Hi8QBUSK0R5y4Pd0/mbxz7IJutKx0OuwWfm/Zy3HbUOHTJVz8NLtpKJeGzXtP3Yx/XlpwnHADPbSkg8ZvCTMcEan4sXpK5ocLoc6meME6lqffp3LGgeum0dl958Kj/tO5tipmpp5yTmtKZ1fH7hzzhq5g5s0YCxVV2OT+RgLMDkyPqsIZt4YMkoD+9u57P3XZROPkCdKfHx9ht538KVmH6PNHqj1IW2oTvOsTs3O1Vj40kTjgFia9CoiueLT9hI3SwftjV4IzC49Fg0Cf6+T9NqVH739Gy++Pi7eKo8hyQT7dHf530dd/L3R91EfS4mKRoiMwa9g2pyiVa/O8SGxjKEiDJo8vzdA+/mcbtgj+84p/0BPrX8TnIV0EgQtY5BU6MVdvVPYVjrajLeE44BNvU3O5/dZWX6HDp3TGzV/98DavVQrAkhXgOjEnH1qmX855Y38kw8Y4/vyFHhgpa7+KvFv6IhU8FWDCbSarBpjAQI6eCaMlqaT5Ku/L44z/9d/XYeLS9MJ16AeZntfHTOCnKx8wyCkxo8BpdnpmwYnM6wzdekQ8iEY4CHikeyc7iBzsxQmjxhrHi4VkLwzyGCuOodUuzdJWAMF4TL7jmV7/ZckFr44VwF3ttxJ19ediORtdjYBXOiWEl8kUcQK+LTvDQZmznsgko2ZJO2KF+5/bX8pO/U9B0El9D65dk/5Ji2HdiSZ1Avm8J9UUXy8ORw514xi/GiCRUOFmBb3M53Hz2ZOGcw6oI9atXpR7VuJSWSZuxISM70SODWpI5P3HYhV+x+Wzr54CYgKwkf6riFzx/7SzKVkKypPhcAIp8YatTnAFrHXBJ5UW81Tf8SC5Us/Os9p/HT3rP2eA8FFtVt5cQ5rkbBhAIV9elnFueyKJCDR/rHPwYQaEIxgAIxEdf0vYlbn5yHZvyA2+oJkU+21BBft6QI3WBi+Naas7ht9FTKUvWpBcgQ847W+/jcktto1MRFe9X4fD8w3tKUECoOWIM6CYAqahz0K1bRPPx8wxK+vv0iSrI3gnds/SaaMnGaY4BPJ5NQiOBehqFe6I5n1mzMJxQDgBv3Uc3zL13v5PdbOiDjs2oTIBEX5UtAYrf6jc/2KWYjvrP6NVzbf1a68tOUfxI+1voL/nHJz2igArESWYtYi1jFJmBj9+U2AYmdN2GsunCzepevooi12AjuWD+bS555V/rMz6bFhQ2uYYXa1GAV49xbDXaMCN2DEaNxlN5nvNPCJhwDhIF4stLJZ594Pzd3zcfm/YeqPms3LE0go+xK8lyy8iy+1/PmvQopClLmr6f/gk8dcyetmdIeg5zmFASImDEVQv5EweNQ3t1UhCcGpvLlrovZFk/d5/M3yQiLGrb64JVgbTUHUbBenTmv4undzYzY8Y8BBJpwRmAgAdbbOfzD+vfzx5038aGlD9HeUHHQbwxkoRgJD2xo5Ttb38E9o0eTPAtJUeADrbfziSN/R8ZC4vEBk0K3XlKI7mHhE/L+fQp3sBOsCkPAlx87jyfKz73HdoPtZ0lbT1rhi+LK0lSxYlzaVwU0I2zY3VEzFxBqxABp2ZWfBN3H8fDZTtvKt/ou5verTuCs5tUc3tTL1FyJPs1y565F3NJzEjuS1r2uz1HhgsIK/nLhb8iquoBQQAuxLtnUuHoA6yN8lir0rN73VBuQR0sxirjk0TdyR/H4583cmSXdZLOxm2R8lZIvBQs9CADKBtbGCyjVAgL0VBMGUKAhU+aTbdfx/Z3nsF1b9zq+59/CytGl3D96JNGOUOolxGr2mojAPG9r/gNfOO4WpkiS+uCRVedGVvM4sIRcwVD8EfxMn4LuJ00K8NuN87mu98znnXwB5jUOkSTi7AVxhqoxPh7hgxYGZaSY4YHyUeEJakI1++bhOEc+X+Hqky7jzOwDe8iBZw9vOGIxVDSirBkqz9PC/fT8w3z2iFto1sSla1vntqX5gOqzeBIwic/UtdUYAt7NE1VIHLC0avs0vvjUuxim7jmn39kLFRbq47REroDF2Q+SZiFpUAUZoXuwmW16cBo/7C/VjAEU4cebTmHxtN189ZhreFPmbvJUXvJ9D89u46sLr2FmfhBTxqV2e+s+ib1LqW4Vqqr/cWlmWO/yWU0jiDaGYTF8ZcNb2Coz9lBPe78TZMVyzIx+KGvqRprEOizDalpdJKJsGa5nVPO1mgKghgwgwMbKTB56eApzCiUuOfYX/J/Wq2hPdr5oV6hNBvjczKuY2zSIVkyq08Vavzp9EWaAlH1MX9Smvr+rG/DRp1iJI7h89cncV3Q9BV/o2eoYYXrz8Fix5VLVNeQzehVklS3DU0mktnZ4DSUAlHNT+OoTZzNSMbRXSnxo0UNcOvN7vLP+Lppk+IDuV5AKH2u9mdd1bkLKPnCTuIk0CT7PHyfek4ArjDkW++CS9/uxLnhzz865fHfwgv3u/NUUVYjKsXP5fCaS+B9jvZHpXY5dpdq5f4FqjgOszJ3GA90dGKPIkOV1ndv42uLr+MHh/8bbs7fRLn0veI9IlA823swH5q0kP6opkKMxbmKRFDJOgZ1QvZOYql+eWKfzE+en9I5m+Prm8w+o7VuH7GJW3tUNaICoE/8VCjZxzaaIoH+cC0H3RTVngLLk+M32xdg8rk17WclX4OSGzVy65JdcMetyTmA10fMEy8/N38Un5qygUA792yRNAFUkxd1T1z5k9wAh18v4SiD8OYNJxOcfP4/VpQXulvupmNqjXjImcWhlgJOByDro2eUACsUibCx17nFtmro+jlRzBgBYMXoCW/qzGLS6UiuWbKyc1LaD7x/zY07NPrbXdYKyWDfwhcNvZkpkXe5g4iSAJIqxllDsp4kzBNWSqgaJA6zsjD0bi5MakfK7HQv4VXxaOu37U7EjwLxsD/nEVsvLPIxtrWBi6zJdrfMLN/Vn97j+kIWCu8xcbtm62A2Axad6GeeGxUo7Jb4w+wYWZLbtcd2R0Ub+fd4VzMyMVGWsN7Y0uFy2uhLFRw8lnIeDedPBsIoR2NDXwKXd51Imu9/vABCRcJh0YypaTSAIEsdq+n5qhdJgll0y9YDufzBoQjBALBl+NvJa+m0m1ZtpMwYEGwtHNezi32b9Fy3GGYftZoB/nPojFjcMY0MPIa/LQ9FGmAPr27qGJJLgCWjiq4ETL3kUigrf3PIG1iaH7bfYrw6mpbMw4OyKkNSiYxJLrKSG4CNdBaL8njbAIasCAJ6KO7lvRztS8MPurXJNILIWynBUQzffa7+cc/U2rpxxGae1uy1cHGCDN+Rwjn+sqbVvvNGnFeMAIf+5WA8GqasSUoFrNi7lpqJL7jjQQs1G288RDd3uSuuwBvcMmuILNnE17M+UmumL94wB1EIFTJhg0KjUce2uZbxuzi2+YNOJZLeSHfwSWTittYvlLZvJigvbBljYWFcoqqF8LNRvhrRtSMvL0sZPVPMKrVXW9jfz3b5zGTUvzj1ryxQRKq4TiY/2Oar2ITbiahW32ulUokk3MCWLsDI5nsd35FxM3htsaR1eSACJIedj9mmRZyja0DGTiqsMUv+3VaooYOJq9jVcm0Alb7is+81sMlXL/EBVQLvppyUDmmhajTQ2aSWgi4nC5qHGcS8F3xdNGAYA6M10cPO2o7F5L0JF/OrW1Igba1yl5WGBSYLfHQzAsTaBt8R9X1jf7Mldm+ThiicXcnvp+Bf97AIclmygJUQBQzFK+O5YsLHxzyhsKdUeA4AJxgCJZLjTnsDOgciJ88QxgvWNICTF0z0zJB7UcblkadfNtBWMelfPJ5BGwSCLSXsBicB926fwXyMXUjR79uQ9kBWaIeaYQjfEHs+wY2wTX10kvi/JQDHDcONhe93jkDQCWxlilulJ/35K5vPQ7mlEJnR48oadVwHgXDnrEzbVOv0fbAbXN4i0O6eKE8cuichvD+uvI1GKkeHyLWeyI3ppm0DmiFlSvwONXXIp4qRQ1RUMiabQX4wY0r17AR6SOMDbcg/x4cyNgNO5A9LMTQNLGVGPAwS97X1pF8XzEsADRy7i5vCV0P5dLUQeChYLSWJIEvEtXdx9KyJ8b9UcVuZOO2B9/2xqk346C/1OEqVZzD4G4L0M8TZLb6mendpS66EHJgADaHmUV09dT0vSk4rcO5LlPNnb4CJ41sXz1fv2KaAzpoe/hJarKWznMn19SaGDelGigMr4jR/WDTfx/exFFKWOlyp8jyuvoZ1yNYdQx6QWhg6hvsRsd7GO8j4csENOBWSJmZs8zeJCH68r/9aVdwH9dZ3cPbjE9wZQv7I1teKDgRVQw2Bhk/h9g5IQ9GHPKGDqCUBSUL635QS2ZzpT0ftipUCBMm/Or6LOJA7E9C3pNFZfS1CNCFqBDZUO4n2EgQ85FZDTErMLPeQS5c+nP0y79qXHbo5PYiTJ+PIw9QEbXzQaOoGE8irrwJZQsBnCuZJodUTVYmOvKiLh2g1zuSXzRncfqnjCi6ETzDpeP3WbS1YNpkvwUnw2kg0IZyI8NdqKrWEe4FiqKQNEmtAoJbQsHNcwwPG5rvTY2mQOK3dNdZ3CraRdOCTt/0O1b6+SVtqG/kChpZwm7sfY0EAK1o/W883SuxkUVymcRg1f1ABazo1W0mQSH2gKLmC17zC22o6+VIG1cec+9w465FTAFIbpzA2jCtnYclHmdxR8WljR1HHl4GmMlkxqTI1d8WnJbkje8Ll3Qc1jg8XvJEeiBmsNwyJctulVbI5mv8in3pNOL97LOU2Pu93DgrRJgtvqUtjVxx4SK2wdzjFs9t0N/JBTAU2MMCVbdha9hTMa1/MWvdPtqwPcmz2ZR0ebg8mPhlYx3n8PhmDA9K1fZWI1BYlcFxbxGT7w0y3zuSX3OpIDfPVn2wdZrfBG7ufy9mvpyFR8u5dqEoj1qkqsRwU9GtlVzFOKDt4eQAdKNWWAxHrQxLt5eYWPTLmbVgZRhGGp54a+pZDxqVqJz+b1ujUwg/oefQF0QTxsHFxH36r1qVIdXx95B6NRwwEbfGETiAZKLNMn+Jv4h1xS/z+01rnSMo2DtHHfGaHYJLisgvFqaPtIM9vNvmsBa6ECahoMEoG8+IYJWLQCi3O9nGDX8htzMgrcJafydN9q5uVHfDv3UMPl7HZJu3ZJKjkkrsYE1Cdk9pQNl24+nd66Z2fhVI2/LBXaGKKeClN0kFYZojVT4XCzhVYGmaoDdOb6mGd205Yruz0E4rHtK6oVa5o2lZJQ1UYlA6viBZSj7D6zi8db/EONGWAwyVBwxf4OMAHyNuFzuRu4t3w0w6aB9dFcvjF4Dv+avw5jXecwCX2AxG0HE2r31PcIwlZXk1jQHFzZdTg31r9lzGALeSp0spvTkgc5qqGXpriX4/JbmW5KZLMJUWRdk+owWyGamHYet25vITvmmCrqNhN0uAO+sQVKCcP6zOETIggUqLYMEE1h9Y46TusYJfE60sTC4sYh3tx3Pz/FVeH8muU8OHI3p9Rtd7F8n9WT7sKl1XK+NEKItxVy8Ojuen6s57kX1oSl9kneW7ibU/JddEQjNJmy3xbOx/B9FodWxG8e5Rs6+CohFXHGnVT5wiPOCGGHEF/a7m3WKA8rtrTxeHR4LYd8L6qpDTBsmvhDZYlv70a65Yqxwscb7qBVB9151HHtwHFUwsT6SbZjAB4JQRev89Ufe2KgwF+NfJCt+XlkiPmLyvVcNfU/eH/rGo7I9tIs5bTxg8sZ1NR1DDCzTYNP1e9QSKOUAYwyXh2FzShCelpSFraOCD8ZOpGBqLmWQ74X1dYIlIhrzFlsK2XTnbOC9b4w6uUz8Q/JEQNwozmTa3oWoRnxVraphnM9RuB0r6QwbCkDn+k+l7W5RQC83t7PX07/PW3E2JI7L/LdJ4y1LojjRyW0m5e0cs/vVZB2CPHtaUIicgj/WptOvKhjJtMA12ydz/0tZx6w93GwqeZPszl/GHcPHoYaSWsyxJduXdT2BK/WNSjCkGnkX5N3sWLnVKzfdjWFWUPQKAmqATZXCnx8yzt4aMqrEZTTKqv4WuO1NMVJCtVpmrAhaZcRly1cNQwDdBzEuQQ9n+IRvoTM/25DCrpHLStZ4c4d7fyo7kJGzcRx/wLVnAEArrZnMpiI69GD3/TZWgoCH4l+S1ZjBGV71MHfVT7M9b1HuKiBzxp2SZiCMTBYjPjJrsP5cP8H+U39GSjCWaWVXNZyFW2ZmMgXC4aMYbVuNxLnOo5J5NRq7qBacVG+uNpUYo9OYWngJ5SAuWHdXM7wz9uX83H9FNtynS9hhA4eRY3Lz/lirR9ip5lKR3kbxxV2pCIVXP7+jOwAdaXdPCSLKUuWoaiJe1hK10iGnLEMW9idFNhUqeeO4Xl8t3I2V2beQlc0ExBOKD/KpU1XMztXdFh92L2LMd6k+zjd08/FE8LOIt6SD1uR+qwk43cqCa5ocE9HrOGJeAo/Hj6Ofym/ldvzZ1CM6qlND7AXJpnxF9+uhfu5F81NtvKTum9ymCm69qtpzz4DdZZv7zqFy6J3UvL7AwtKhoSIBIMSq3F/iQuyGJRTksf4PFezrHEIFdfWPZSGp51mx+xE5sx3IHbbyzrvwpeV4SWTP0dCepFATylDd7mR20fncpc5hoeyxzBi6vboUjZRacJkBW+JZvDdoVP55/bfIqOCRG6yRMAU4ZMtKzl2ZCeXJ29kjcxnhDwVMtUGy34es8QcXnmGi7iL9zStoSlrfRKJpJtIhc2jgqGXOvrBq0B952nXIAKjlFQoJ0JPOctOmngynsom2nlgaCY7C7PZGU1loK55n0GeiUwTRgIA1GmJLw59iws6t5AtQeSXXsBhTATDZeH+Uif32kX8kU6siRisZMmJZYF2cVpmPcdnNjG3vpLmDUTGkviGcBZ1wJFREiTtORhUgOZdAmdsDQPWsH60wJZSGw8lc3kwmc3Owhx6Mu2Uope/r08tOoVOKAYAmB7v5C32Tj6S/wNzCkWwZgxu77F1oyRWGPFuoEYuEtdgEkxUrfJR49OxQst4U92omSyUS0JPxVDULBuZQo82sVGnsb7UypNRJzuljVLUyIgUKEvuFbe694cmHAMEOjp+krcnKzi90EVnbpgm4lR8p8hsNKZuILwQbosYRbAijFhDApTjDLuSHAOVOtZVWllfqmO7mc3mzHQ2aRvFug5iMvvM1PlTpgnLAIILubZqP0fEXSxNnmJOpofpDDJVh8gYi6p1e/oaB74M2Dw90kS/1LOrkme7drAzO41dSY6RTAv9ppGS5ogzdZQ0AonGVdzuzzvD+KqACc3uZcnSLe1059q5B1e0EWlCQzxIokqcWPLGUipbh8NnC9hso/MEXqiwV8b++uLTwV5OOuSigc9HzzUYiUQMZFvcH1m3gecBNPB4ju+q/eTXiia+o3oI0SGXEDJJe1ItVMCkBDjEaZIBJhDVJC2879Yr3l7rF58kR+OdFl7a+OiNpvjMwzckw32ba/3ykzT+VN78+K0GoLhh9XW1fphJGn8afvTOyyOActfjt0ats47Ots1YWuuHmqSDT/FQ76ZdV3/pCI0rI6kROLTy+r+t9YNN0vhQvKvrIVsc3gVjdqvV8mhf0r9jXeHwZRfW+gEn6eDRyBMrr+y/7QfvCX/v5XXkZix4ddt5n7wDiSZG/fIkvWxU3rb+rp5ffPOMsZ/thQOUt6+/u9Kz7ZFaP+wkvfz07MmH58Ed8vOOOa/1DR/62aQkeOXTvlZ+oOcFnnIzFry67W1/fVetX2CSXjyNPLHyyoEVP/pfz3X8eVd3MtS7Ke7fsU4y2brMlGmLav0yk7T/FA/1bipvfXLFWINvX7R/0LOImXL2B6+pWzDpIbxSaMeVf99hi0O7Xui8A4o9RA0tnfXHnf03Dce85q9r/YKTtDeVNj56Y6nr8VtHHrvz8v295v8DBDsyCiLWPQsAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDQtMDFUMDg6MjM6MzIrMDA6MDDJJWdkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTA0LTAxVDA4OjIzOjMyKzAwOjAwuHjf2AAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wNC0wMVQwODoyMzozMiswMDowMO9t/gcAAAAASUVORK5CYII=
// @match       *://*/*
// @exclude     *://www.lazada.com/*
// @exclude     *://shopee.com/*
// @connect     jtm.pub
// @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
// ==/UserScript==
(function () {
  'use strict';

  
  /*!
   * Before using this script, please make sure to read the information provided
   * in the @description section, which includes an overview of the script’s
   * features and the privacy notice. By continuing to use this script, you
   * acknowledge that you have read and understood the relevant content.
   * If you do not agree, please stop using the script immediately.
   *
   *
   * Copyright (c) 2024 - 2026, Jtmate.
   * 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": (() => {
      const navLang = navigator.language || navigator.userLanguage || "en";
      if (navLang.startsWith("zh")) {
        return navLang === "zh-CN" || navLang === "zh-TW" ? navLang : "zh-CN";
      }
      return navLang.slice(0, 2).toLowerCase() || "en";
    })(),
    "isDev": false,
    "isDebug": false,
    "version": "1.0.1",
    "number": "13",
    "currentHost": window.location.host,
    "currentUrl": window.location.href
  };
  const PlatformConst = {
    "x": { "p": "x", "match": /twitter|x\.com$/ },
    "youtube": { "p": "youtube", "match": /youtube\.com$/ },
    "google": { "p": "google", "match": /google\.com$/ },
    "tiktok": { "p": "tiktok", "match": /www\.tiktok\.com/ },
    "cobalt": { "p": "cobalt", "match": /cobalt\.tools/ }
  };

  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 ?? { "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 ?? { "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 ?? { "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");
      } else if (/amazon\./.test(url)) {
        regex = new RegExp("\\/(?:dp|gp\\/product|gp\\/aw\\/d|gp\\/offer-listing)\\/([A-Za-z0-9]{8,15})");
      }
      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);
    },
    getElementByHandler: function(handler) {
      if (!handler)
        return null;
      const names = String(handler).split("@").filter((s) => s.length);
      for (let i = 0; i < names.length; i++) {
        const eleName = names[i];
        if (eleName === "body")
          return document.body;
        if (eleName === "html")
          return document.documentElement;
        const el = document.body ? document.body.querySelector(eleName) : document.querySelector(eleName);
        if (el)
          return el;
      }
      return null;
    },
    getLiveElement: function(element, handler) {
      if (element && this.elementInContainer(document, element))
        return element;
      return this.getElementByHandler(handler);
    },
    mustGetElement: async function(handler) {
      const getElements = async (h) => {
        const names = h.split("@").filter((s) => s.length);
        const promises = names.map((eleName) => {
          if (eleName === "body")
            return Promise.resolve(document.body);
          if (eleName === "html")
            return Promise.resolve(document.documentElement);
          return this.waitForElementByInterval(eleName, document.body, true, 10, 1500);
        });
        return promises.length ? Promise.race(promises) : null;
      };
      let element = await getElements(handler);
      if (element)
        return element;
      return new Promise((resolve) => {
        const waitInterval = setInterval(async () => {
          const el = await getElements(handler);
          if (el) {
            clearInterval(waitInterval);
            resolve(el);
          }
        }, 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;
    },
    getDocumentBody: function() {
      return new Promise((resolve, reject) => {
        if (document.body) {
          resolve(document.body);
          return;
        }
        const checkBody = setInterval(function() {
          if (document.body) {
            clearInterval(checkBody);
            resolve(document.body);
          }
        }, 50);
      });
    }
  };

  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"
    },
    api: {
      loadConfSupportCache: { "key": "conf_cache_support", "time": 30 * 60 * 1e3 },
      loadConfExistCache: { "key": "conf_cache_exist", "time": 30 * 60 * 1e3 },
      loadConfSECache: { "key": "conf_cache_se", "time": 30 * 60 * 1e3 }
    }
  };
  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="
    },
    updateExchangeInfoDelay: 1e3 * 60 * 10
  };
  const getRequestUrl = () => {
    const baseUrl = "https://o.jtm.pub";
    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);
    },
    requestConfCached: function(method, url, storageKey, ttlMs, needStuffingRetry = true) {
      const cached = StorageUtil.getValue(storageKey, null);
      const now = Date.now();
      if (cached && cached.content && now - cached.time < ttlMs) {
        return Promise.resolve(cached.content);
      }
      let hashValue = !needStuffingRetry ? "init" : cached && cached.hash ? cached.hash : "init";
      const urlObj = new URL(url);
      urlObj.searchParams.set("hash", hashValue);
      const finalUrl = urlObj.toString();
      const stuffingParams = { url, method, storageKey, ttlMs };
      return Tools.request(method, finalUrl, null).then((data) => {
        const fallback = { content: cached ? cached.content : null, stuffing: stuffingParams };
        if (data.code === "success" && data.result) {
          const json = JSON.parse(data.result);
          if (json.changed === false && cached) {
            StorageUtil.setValue(storageKey, Object.assign({}, cached, { time: now }));
            hashValue = cached.hash;
          } else if (json.changed === true) {
            hashValue = json.hash;
            if (hashValue !== "unsupported" && !!json.content) {
              const contentStr = JSON.stringify(json.content);
              StorageUtil.setValue(storageKey, { content: contentStr, hash: hashValue, time: now });
              fallback.content = contentStr;
            }
          }
        }
        try {
          this._retryConfCachedIfUnsupported(fallback, hashValue, needStuffingRetry);
        } catch (e) {
        }
        return fallback ? fallback.content : null;
      }).catch(() => {
        return cached ? cached.content : null;
      });
    },
    _retryConfCachedIfUnsupported: function(filterData, hashValue, needStuffingRetry) {
      if (!needStuffingRetry || !filterData || hashValue !== "unsupported") {
        return;
      }
      try {
        const stuffingUrl = new URL(filterData.stuffing.url);
        stuffingUrl.searchParams.set("url", "https://www.aliexpress.com");
        const retryPromise = this.requestConfCached(
          filterData.stuffing.method,
          stuffingUrl.toString(),
          filterData.stuffing.storageKey,
          filterData.stuffing.ttlMs,
          false
        );
        if (retryPromise && typeof retryPromise.catch === "function") {
          retryPromise.catch(() => {
          });
        }
      } catch (e) {
      }
    },
    _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://o.jtm.pub",
    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() {
      const loadConfExistCache = StorageKeys.api.loadConfExistCache;
      return RequestUtil.requestConfCached("GET", this.baseUrl + "/api/load/conf", loadConfExistCache.key, loadConfExistCache.time);
    },
    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"],
              "price": elements[j]["price"]
            });
          }
        }
      }
      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) {
      if (!element || !tag) {
        return "";
      }
      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, itemsPerGroup = 10) {
      const groups = [];
      for (let i = 0; i < array.length; i += itemsPerGroup) {
        groups.push(array.slice(i, i + itemsPerGroup));
      }
      return groups;
    }
  };

  const Aliexpress = {
    languageStorageKey: "aliexpress-language-key",
    currencyStorageKey: "aliexpress-currency-key",
    marketplaceStorageKey: "aliexpress-marketplace-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.languageStorageKey, lang);
      return lang;
    },
    getMarketplace: async function(marketplaceHandler) {
      let countryCode = "";
      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)) {
        countryCode = host.split(".")[0];
      } else {
        countryCode = host.split(".").slice(-1)[0];
      }
      let marketplace = GM_getValue(this.marketplaceStorageKey, null);
      const defaultMarketplace = { countryCode, className: "", html: "" };
      if (marketplaceHandler && !/\.ru/.test(host)) {
        const handlerElement = await Tools.waitForElementByInterval(marketplaceHandler, document.body, true, 50, 2 * 1e3);
        if (handlerElement) {
          marketplace = {
            countryCode,
            className: handlerElement.className ?? "",
            html: handlerElement.outerHTML ?? ""
          };
          GM_setValue(this.marketplaceStorageKey, marketplace);
        }
      }
      if (!marketplace) {
        marketplace = defaultMarketplace;
      }
      return encodeURIComponent(JSON.stringify(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.currencyStorageKey, currency);
              resolve(currency);
            } else {
              resolve("unknown");
            }
          } else {
            resolve("unknown");
          }
        }
      });
    },
    detail: async function(marketplaceHandler) {
      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 = await this.getCurrency();
      const marketplace = await this.getMarketplace(marketplaceHandler);
      const id = Tools.getGoodsIdByLink(visitUrl);
      try {
        const params = {
          "ids": id,
          "qu": "",
          "p": SupportData.support.p,
          "lang": language,
          "mul": false,
          "currency": currency,
          "marketplace": marketplace
        };
        const data = await RequestUtil.getCouponQuery(params);
        if (data.code == "success" && !!data.result) {
          const json = JSON.parse(data.result);
          Logger.log("info", "detail request json=", json);
          await this.detailAnalyze(json, language, currency, marketplace);
        }
      } catch (e) {
      }
    },
    detailAnalyze: async function(json, language, currency, marketplace) {
      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 = await 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, "handler": handler };
          }
        }
        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,
            "marketplace": marketplace
          };
          const reqPromise = RequestUtil.getCouponChange(params);
          promiseResultArray.push(elementPromise, reqPromise);
          const allResult = await 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, "handler": mount };
          }
        }
        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 { html, templateId, hint, mid, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element) {
        return;
      }
      result.element = element;
      element.insertAdjacentHTML("afterend", html);
      const templateIdEle = document.querySelector("div[id='" + templateId + "']");
      if (templateIdEle) {
        const couponCodeElement = templateIdEle.querySelector(".coupon-code");
        if (couponCodeElement) {
          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 { html, qrcodeData, iden, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element) {
        return;
      }
      result.element = element;
      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: async 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 = await GM_getValue(this.languageStorageKey, navigator.language);
      const currency = await GM_getValue(this.currencyStorageKey, "USD");
      const marketplace = await this.getMarketplace();
      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,
        "marketplace": marketplace
      };
      const res = await RequestUtil.getCouponQuery(params);
      if (res.code == "success" && !!res.result) {
        const json = JSON.parse(res.result);
        await this.tradeAnalyze(json, language);
      }
    },
    tradeAnalyze: async function(json, language) {
      if (!json || !json.handler || !json.css || !json.templateId) {
        return;
      }
      const { handler, css, html, templateId, distinguish } = json;
      GM_addStyle(css);
      let element = await Tools.mustGetElement(handler);
      Tools.loopTask(() => {
        Tools.distinguishRemoveAndTry(distinguish, () => {
          const liveElement = Tools.getLiveElement(element, handler);
          if (!liveElement) {
            return;
          }
          element = liveElement;
          liveElement.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: async function() {
      const { support } = SupportData;
      const visitUrl = window.location.href;
      if (support.detail.test(visitUrl)) {
        this.detail(support.marketplace);
      }
      this.trade();
      this.removeAnchor();
    }
  };

  const AliexpressSearch = {
    loopIsComplete: true,
    cacheLinkDoms: {},
    isInbusinessPage: function() {
      return /inbusiness\.aliexpress\.com\/web\/search-products/.test(ItemSearchBaseObj.visitUrl);
    },
    isItemLink: function(url) {
      return SupportData.support.detail.test(url);
    },
    pickUpWholesale: async function(selectors, language, currency, marketplace, couponExistPer) {
      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 goodsLink2 = ItemSearchBaseObj.getGoodsLinkByElement(element, findA);
                let id = null;
                if (this.isItemLink(goodsLink2)) {
                  id = Tools.getGoodsIdByLink(goodsLink2.getAttribute("href"));
                  this.cacheLinkDoms[id] = goodsLink2;
                }
                if (id) {
                  items.push({
                    "id": id,
                    "platform": SupportData.support.p,
                    "handler": element,
                    "findA": findA,
                    "from": "wholesale"
                  });
                }
              }
            });
          }
        });
        if (items.length > 0) {
          await this.search(items, language, currency, marketplace, couponExistPer);
        }
      } catch (e) {
      }
    },
    pickUpInbusiness: async function(language, currency, marketplace, couponExistPer) {
      const validate = this.isInbusinessPage();
      if (!validate)
        return;
      try {
        const iceContainerElement = document.querySelector("#ice-container");
        const loadMoreElement = await 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"
                  });
                  this.cacheLinkDoms[id] = goodsLink;
                }
              }
            });
          }
          await this.search(array, language, currency, marketplace, couponExistPer);
        }
      } catch (e) {
      }
    },
    search: function(array, language, currency, marketplace, couponExistPer) {
      const groups = ItemSearchBaseObj.calcRequestGroup(array, couponExistPer);
      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, marketplace));
        }
        Promise.all(promises).then((data) => {
          resolve("complete");
        });
      });
    },
    createItemHtml: function(group, language, currency, 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].handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true");
          }
          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=13&v=1.0.1&currency=" + currency + "&marketplace=" + marketplace;
          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 (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;
    },
    changePageEvent: function() {
      let hookDivTimer = null, removeTagIsComplete = true;
      const onInitDom = () => {
        if (!removeTagIsComplete)
          return;
        removeTagIsComplete = false;
        const attr = ItemSearchBaseObj.searchAttribute;
        document.querySelectorAll(`*[${attr}='true']`).forEach((el) => {
          el.removeAttribute(attr);
          const tip = el.querySelector("*[name^='ali-gogo-coupon-']");
          if (tip) {
            tip.remove();
          }
        });
        removeTagIsComplete = true;
        this.cacheLinkDoms = {};
      };
      const checkObjectValues = () => {
        const obj = this.cacheLinkDoms;
        const keys = Object.keys(obj);
        let notContain = 0;
        for (let i = 0; i < keys.length; i++) {
          const key = keys[i];
          const el = obj[key];
          try {
            const href = el.getAttribute("href");
            if (!href.includes(key)) {
              if (++notContain > 2)
                return true;
            }
          } catch (e) {
          }
        }
        return false;
      };
      const observer = new MutationObserver((mutations) => {
        const hasDelete = mutations.some(
          (m) => m.target === document.body && m.removedNodes.length > 0
        );
        if (!hasDelete)
          return;
        if (hookDivTimer)
          clearTimeout(hookDivTimer);
        hookDivTimer = setTimeout(() => {
          hookDivTimer = null;
          if (checkObjectValues())
            onInitDom();
        }, 500);
      });
      observer.observe(document.body, { childList: true, subtree: false });
    },
    start: async function() {
      const { support } = SupportData;
      if (!this.isRun()) {
        return;
      }
      const language = Aliexpress.getLang();
      const currency = await Aliexpress.getCurrency();
      const marketplace = await Aliexpress.getMarketplace(support.marketplace);
      const confString = await ItemSearchBaseObj.requestConf();
      if (!confString) {
        return;
      }
      const couponExistPer = support.couponExistPer || 10;
      const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString);
      setInterval(async () => {
        if (this.loopIsComplete) {
          this.loopIsComplete = false;
          await this.pickUpInbusiness(language, currency, marketplace, couponExistPer);
          await this.pickUpWholesale(selectors, language, currency, marketplace, couponExistPer);
          this.loopIsComplete = true;
        }
      }, 1700);
      if (selectors.length != 0 && window.location.pathname != "/") {
        this.changePageEvent();
      }
    }
  };

  const Ebay = {
    detail: async 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 = await RequestUtil.getCouponQuery(params);
        if (data.code == "success" && !!data.result) {
          const json = JSON.parse(data.result);
          Logger.log("info", "detail request json=", json);
          await this.detailAnalyze(json, marketplace);
        }
      } catch (e) {
      }
    },
    detailAnalyze: async function(json, marketplace) {
      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 = await Tools.mustGetElement(handler);
        if (element) {
          couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "hint": hint, "mid": mid, "handler": handler };
        }
      }
      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 = await 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, "handler": mount };
        }
      }
      Tools.loopTask(() => {
        if (couponResult) {
          Tools.distinguishRemoveAndTry(couponResult.distinguish, () => {
            this.detailCouponAnalyze(couponResult);
          });
        }
        if (qrcodeResult) {
          Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => {
            this.detailMscanAnalyze(qrcodeResult);
          });
        }
      });
    },
    detailCouponAnalyze: function(result) {
      const { html, templateId, hint, mid, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      element.insertAdjacentHTML("afterend", html);
      const templateIdEle = document.querySelector("div[id='" + templateId + "']");
      if (templateIdEle) {
        const couponCodeElement = templateIdEle.querySelector(".coupon-code");
        if (couponCodeElement) {
          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 { html, qrcodeData, iden, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      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: async function() {
      const { support } = SupportData;
      const visitUrl = window.location.href;
      if (support.detail.test(visitUrl)) {
        this.detail();
      }
    }
  };

  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: async function(selectors, marketplace, couponExistPer) {
      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 = elementObj.price;
                Logger.log("info", "search price elements======>", element, priceQuery);
                const price = ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery);
                Logger.log("info", "search price======>", price);
                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) {
          await this.search(items, marketplace, couponExistPer);
        }
      } catch (e) {
      }
    },
    search: async function(array, marketplace, couponExistPer) {
      const groups = ItemSearchBaseObj.calcRequestGroup(array, couponExistPer);
      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 + ",";
            group[i].handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true");
          }
          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=13&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 (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: async function() {
      const { support } = SupportData;
      if (!this.isRun()) {
        return;
      }
      const marketplace = Tools.getCommonMarketplace(window.location.href);
      const confString = await ItemSearchBaseObj.requestConf();
      if (!confString) {
        return;
      }
      const couponExistPer = support.couponExistPer || 10;
      const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString);
      setInterval(async () => {
        if (this.loopIsComplete) {
          this.loopIsComplete = false;
          await this.pickUpItems(selectors, marketplace, couponExistPer);
          this.loopIsComplete = true;
        }
      }, 1700);
    }
  };

  const Lazada = {
    detailMyMscanAnalyze: async function(result) {
      const { id, iden, marketplace, platform, mount, html, cmd } = result;
      if (!mount || !html) {
        return;
      }
      if (cmd && cmd.do && cmd.ele) {
        const cmdElement = await Tools.waitForElementByInterval(cmd.ele);
        if (cmdElement) {
          if (cmd.do == "empty") {
            cmdElement.innerHTML = "";
          }
        }
      }
      const element = await Tools.mustGetElement(mount);
      if (!element) {
        return;
      }
      element.insertAdjacentHTML("beforeend", html);
      const params = {
        "id": id,
        "marketplace": marketplace,
        "platform": platform
      };
      const qrcodeData = await 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: async 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 = await 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: async function() {
      const { support } = SupportData;
      const visitUrl = window.location.href;
      if (support.detail.test(visitUrl)) {
        this.detail();
      }
    }
  };

  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: async function(selectors, marketplace, couponExistPer) {
      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) {
          await this.search(items, marketplace, couponExistPer);
        }
      } catch (e) {
      }
    },
    search: async function(array, marketplace, couponExistPer) {
      const groups = ItemSearchBaseObj.calcRequestGroup(array, couponExistPer);
      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 + ",";
            group[i].handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true");
          }
          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=13&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 (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: async function() {
      const { support } = SupportData;
      if (!this.isRun()) {
        return;
      }
      const marketplace = Tools.getCommonMarketplace(window.location.href);
      const confString = await ItemSearchBaseObj.requestConf();
      if (!confString) {
        return;
      }
      const couponExistPer = support.couponExistPer || 10;
      const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString);
      setInterval(async () => {
        if (this.loopIsComplete) {
          this.loopIsComplete = false;
          await this.pickUpItems(selectors, marketplace, couponExistPer);
          this.loopIsComplete = true;
        }
      }, 1700);
    }
  };

  const Bestbuy = {
    detail: async 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 = await RequestUtil.getCouponQuery(params);
        if (data.code == "success" && !!data.result) {
          const json = JSON.parse(data.result);
          Logger.log("info", "detail request json=", json);
          await this.detailAnalyze(json, marketplace);
        }
      } catch (e) {
      }
    },
    detailAnalyze: async function(json, marketplace) {
      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 = await Tools.mustGetElement(handler);
        if (element) {
          couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "handler": handler };
        }
      }
      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 = await 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, "handler": mount };
        }
      }
      Tools.loopTask(() => {
        if (couponResult) {
          Tools.distinguishRemoveAndTry(couponResult.distinguish, () => {
            this.detailCouponAnalyze(couponResult);
          });
        }
        if (qrcodeResult) {
          Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => {
            this.detailMscanAnalyze(qrcodeResult);
          });
        }
      });
    },
    detailCouponAnalyze: function(result) {
      const { html, templateId, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      element.insertAdjacentHTML("afterend", html);
      const templateIdEle = document.querySelector("div[id='" + templateId + "']");
      if (templateIdEle) {
        const couponCodeElement = templateIdEle.querySelector(".coupon-code");
        if (couponCodeElement) {
          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 { html, qrcodeData, iden, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      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: async function() {
      const { support } = SupportData;
      const visitUrl = window.location.href;
      if (support.detail.test(visitUrl)) {
        this.detail();
      }
    }
  };

  const BestbuySearch = {
    loopIsComplete: true,
    pickUpItems: async function(selectors, marketplace, couponExistPer) {
      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 = elementObj.price;
                Logger.log("info", "search price elements======>", element, priceQuery);
                const price = ItemSearchBaseObj.getGoodsPrice(
                  ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery)
                );
                Logger.log("info", "search price======>", price);
                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) {
          await this.search(items, marketplace, couponExistPer);
        }
      } catch (e) {
      }
    },
    search: async function(array, marketplace, couponExistPer) {
      const groups = ItemSearchBaseObj.calcRequestGroup(array, couponExistPer);
      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 + ",";
            group[i].handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true");
          }
          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=13&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 (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: async function() {
      const { support } = SupportData;
      if (!this.isRun()) {
        return;
      }
      const marketplace = Tools.getCommonMarketplace(window.location.href);
      const confString = await ItemSearchBaseObj.requestConf();
      if (!confString) {
        return;
      }
      const couponExistPer = support.couponExistPer || 10;
      const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString);
      setInterval(async () => {
        if (this.loopIsComplete) {
          this.loopIsComplete = false;
          await this.pickUpItems(selectors, marketplace, couponExistPer);
          this.loopIsComplete = true;
        }
      }, 1700);
    }
  };

  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: async 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 = await RequestUtil.getCouponQuery(params);
        if (data.code == "success" && !!data.result) {
          const json = JSON.parse(data.result);
          Logger.log("info", "detail request json=", json);
          await this.detailAnalyze(json, marketplace);
        }
      } catch (e) {
      }
    },
    detailAnalyze: async function(json, marketplace) {
      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 = await Tools.mustGetElement(handler);
        if (element) {
          couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "hint": hint, "mid": mid, "handler": handler };
        }
      }
      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 = await 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, "handler": mount };
        }
      }
      Tools.loopTask(() => {
        if (couponResult) {
          Tools.distinguishRemoveAndTry(couponResult.distinguish, () => {
            this.detailCouponAnalyze(couponResult);
          });
        }
        if (qrcodeResult) {
          Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => {
            this.detailMscanAnalyze(qrcodeResult);
          });
        }
      });
    },
    detailCouponAnalyze: function(result) {
      const { html, templateId, hint, mid, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      element.insertAdjacentHTML("afterend", html);
      const templateIdEle = document.querySelector("div[id='" + templateId + "']");
      if (templateIdEle) {
        const couponCodeElement = templateIdEle.querySelector(".coupon-code");
        if (couponCodeElement) {
          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 { html, qrcodeData, iden, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      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: async function() {
      const { support } = SupportData;
      const visitUrl = window.location.href;
      if (support.detail.test(visitUrl)) {
        this.detail();
      }
    }
  };

  const BanggoodSearch = {
    loopIsComplete: true,
    pickUpItems: async function(selectors, marketplace, lang, currency, couponExistPer) {
      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 = elementObj.price;
                Logger.log("info", "search price elements======>", element, priceQuery);
                const price = ItemSearchBaseObj.getGoodsPriceByElement(element, priceQuery);
                Logger.log("info", "search price======>", price);
                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) {
          await this.search(items, marketplace, lang, currency, couponExistPer);
        }
      } catch (e) {
      }
    },
    search: async function(array, marketplace, lang, currency, couponExistPer) {
      const groups = ItemSearchBaseObj.calcRequestGroup(array, couponExistPer);
      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 + ",";
            group[i].handler.setAttribute(ItemSearchBaseObj.searchAttribute, "true");
          }
          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=13&v=1.0.1&currency=" + 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 (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: async function() {
      const { support } = SupportData;
      if (!this.isRun(support)) {
        return;
      }
      const marketplace = Banggood.getMarketplace(window.location.href);
      const lang = Banggood.getLang();
      const confString = await ItemSearchBaseObj.requestConf();
      if (!confString) {
        return;
      }
      const couponExistPer = support.couponExistPer || 10;
      const selectors = ItemSearchBaseObj.pickupGoodsItem(SupportData.support.p, confString);
      setInterval(async () => {
        if (this.loopIsComplete) {
          this.loopIsComplete = false;
          const currency = Banggood.getCurrency();
          await this.pickUpItems(selectors, marketplace, lang, currency, couponExistPer);
          this.loopIsComplete = true;
        }
      }, 1700);
    }
  };

  const Amazon = {
    detail: async 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 = await RequestUtil.getCouponQuery(params);
        if (data.code == "success" && !!data.result) {
          const json = JSON.parse(data.result);
          Logger.log("info", "detail request json=", json);
          await this.detailAnalyze(json, marketplace);
        }
      } catch (e) {
      }
    },
    detailAnalyze: async function(json, marketplace) {
      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 = await Tools.mustGetElement(handler);
        if (element) {
          couponResult = { "element": element, "html": html, "templateId": templateId, "distinguish": distinguish, "hint": hint, "mid": mid, "handler": handler };
        }
      }
      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 = await 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, "handler": mount };
        }
      }
      Tools.loopTask(() => {
        if (couponResult) {
          Tools.distinguishRemoveAndTry(couponResult.distinguish, () => {
            this.detailCouponAnalyze(couponResult);
          });
        }
        if (qrcodeResult) {
          Tools.distinguishRemoveAndTry(qrcodeResult.distinguish, () => {
            this.detailMscanAnalyze(qrcodeResult);
          });
        }
      });
    },
    detailCouponAnalyze: function(result) {
      const { html, templateId, hint, mid, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      element.insertAdjacentHTML("afterend", html);
      const templateIdEle = document.querySelector("div[id='" + templateId + "']");
      if (templateIdEle) {
        const couponCodeElement = templateIdEle.querySelector(".coupon-code");
        if (couponCodeElement) {
          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 { html, qrcodeData, iden, handler } = result;
      const element = Tools.getLiveElement(result.element, handler);
      if (!element)
        return;
      result.element = element;
      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: async function() {
      const { support } = SupportData;
      const visitUrl = window.location.href;
      if (support.detail.test(visitUrl)) {
        this.detail();
      }
    }
  };

  const PlatformModules = {
    Aliexpress: {
      Aliexpress,
      AliexpressSearch
    },
    Ebay: {
      Ebay,
      EbaySearch
    },
    Lazada: {
      Lazada,
      LazadaSearch
    },
    Bestbuy: {
      Bestbuy,
      BestbuySearch
    },
    Banggood: {
      Banggood,
      BanggoodSearch
    },
    Amazon: {
      Amazon
    }
  };

  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 = `
  <svg style="height:30px;width:30px;" class="icon-i87i-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1770" width="30" height="30"><path d="M811.04 468.728a39.72 39.72 0 0 0-27.672-30.36l-10.2-2.28a100.872 100.872 0 0 1-68.856-120.24l3.12-9.552a41.592 41.592 0 0 0-11.424-40.368 281.64 281.64 0 0 0-36.816-24.336c-12.36-7.2-25.224-13.536-38.496-18.912a41.592 41.592 0 0 0-41.592 9.984l-7.08 7.488a100.248 100.248 0 0 1-69.264 27.456 100.464 100.464 0 0 1-68.64-27.672l-6.864-7.272a41.592 41.592 0 0 0-41.592-9.984 294.96 294.96 0 0 0-37.848 18.912c-12.696 7.152-24.792 15.288-36.192 24.336a41.592 41.592 0 0 0-10.824 40.368l2.904 9.552a101.088 101.088 0 0 1-10.8 74.064 96.72 96.72 0 0 1-57.408 45.552l-9.792 2.28a35.352 35.352 0 0 0-26.616 28.488c-1.872 14.352-2.64 28.8-2.28 43.272-0.408 14.736 0.36 29.472 2.28 44.088a39.936 39.936 0 0 0 25.8 31.2l9.552 2.304a99 99 0 0 1 57.624 46.992c12.984 22.392 16.848 48.912 10.8 74.064l-2.064 9.36a41.592 41.592 0 0 0 11.856 40.344c11.136 9.072 22.968 17.28 35.352 24.552 12.312 7.488 25.176 14.016 38.496 19.536 14.64 4.608 30.624 0.768 41.592-9.984l6.648-7.272a101.088 101.088 0 0 1 139.152 0l6.672 7.272a41.592 41.592 0 0 0 41.592 9.984 295.152 295.152 0 0 0 37.224-19.536 271.848 271.848 0 0 0 36.624-24.336c10.944-10.32 15.48-25.752 11.856-40.368l-2.928-9.768a100.872 100.872 0 0 1 69.48-120l9.576-2.304a39.72 39.72 0 0 0 27.648-30.36c1.68-14.376 2.232-28.824 1.68-43.272a291.192 291.192 0 0 0-2.304-43.272z m-307.44 190.944a147.672 147.672 0 1 1 0-295.344 147.672 147.672 0 0 1 0 295.344z" fill="#8a8a8a" p-id="1771"></path></svg>
`.trim();
  const closeSVG = `
  <svg style="height:30px;width:30px;" class="icon-i87i-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1609" width="30" height="30"><path d="M673.5644448 281.66826667L512 447.82933333 351.16373333 281.71377813a44.6464 44.6464 0 0 0-63.6700448-0.50062293 46.1027552 46.1027552 0 0 0-0.50062186 64.6712896L447.82933333 512l-160.83626666 165.84248853c-17.52177813 18.06791147-17.29422187 46.8764448 0.50062186 64.6712896a44.69191147 44.69191147 0 0 0 63.71555627-0.45511146L512 576.17066667l161.5644448 165.93351146a44.78293333 44.78293333 0 0 0 63.7155552 0.4096 45.96622187 45.96622187 0 0 0 0.45511147-64.62577813L576.17066667 512l161.5644448-166.16106667a46.01173333 46.01173333 0 0 0-0.45511147-64.62577813 44.73742187 44.73742187 0 0 0-63.7155552 0.45511147z" fill="#5D6E7F" p-id="1610"></path></svg>
`.trim();
  const historyIconSVG = `
  <svg t="1736495784741" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2656" width="48" height="48"><path d="M539.7171875 536.1734375m-280.63125 0a280.63125 280.63125 0 1 0 561.2625 0 280.63125 280.63125 0 1 0-561.2625 0Z" fill="#56E5BE" p-id="2657"></path><path d="M567.940625 564.3546875m-252.45 0a252.45 252.45 0 1 0 504.9 0 252.45 252.45 0 1 0-504.9 0Z" fill="#50DDB8" p-id="2658"></path><path d="M596.7546875 584.9421875m-219.5015625 0a219.5015625 219.5015625 0 1 0 439.003125 0 219.5015625 219.5015625 0 1 0-439.003125 0Z" fill="#42D3AD" p-id="2659"></path><path d="M512.590625 165.1765625c-13.9640625 0-25.3125 11.3484375-25.3125 25.3125s11.3484375 25.3125 25.3125 25.3125c162.253125 0 294.2578125 132.0046875 294.2578125 294.2578125s-132.0046875 294.2578125-294.2578125 294.2578125S218.3328125 672.3125 218.3328125 510.059375c0-88.171875 38.6015625-169.7625 104.9203125-225.28125v55.6453125c0 13.9640625 11.3484375 25.3125 25.3125 25.3125s25.3125-11.3484375 25.3125-25.3125V219.640625c0-13.9640625-11.3484375-25.3125-25.3125-25.3125h-115.59375c-13.9640625 0-25.3125 11.3484375-25.3125 25.3125s11.3484375 25.3125 25.3125 25.3125h58.978125C213.4390625 310.0484375 167.7078125 406.1515625 167.7078125 510.059375c0 190.18125 154.7015625 344.8828125 344.8828125 344.8828125s344.8828125-154.7015625 344.8828125-344.8828125-154.74375-344.8828125-344.8828125-344.8828125z" fill="#515151" p-id="2660"></path><path d="M617.6796875 579.7109375H474.36875c-13.9640625 0-25.3125-11.3484375-25.3125-25.3125V423.9546875c0-13.9640625 11.3484375-25.3125 25.3125-25.3125s25.3125 11.3484375 25.3125 25.3125v105.13125h117.9984375c13.9640625 0 25.3125 11.3484375 25.3125 25.3125s-11.3484375 25.3125-25.3125 25.3125z" fill="#515151" p-id="2661"></path></svg>
`.trim();
  const alertErrorIconSVG = `
  <svg t="1750318981890" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7681" width="45" height="45"><path d="M736 336zM336 736h-0.01 0.02-0.01zM688 736h0.01-0.01zM736 688z" fill="#666666" p-id="7682"></path><path d="M512 64C264.58 64 64 264.58 64 512s200.58 448 448 448 448-200.57 448-448S759.42 64 512 64z m220.62 346.18L472.4 670.39a40 40 0 0 1-56.57 0L291.38 545.94a40 40 0 0 1 0-56.57 40 40 0 0 1 56.57 0l96.17 96.17 231.93-231.93a40 40 0 0 1 56.57 0 40 40 0 0 1 0 56.57z" fill="#999999" p-id="7683"></path><path d="M732.62 353.61a40 40 0 0 0-56.57 0L444.12 585.54 348 489.37a40 40 0 0 0-56.57 0 40 40 0 0 0 0 56.57l124.4 124.45a40 40 0 0 0 56.57 0l260.22-260.21a40 40 0 0 0 0-56.57z" fill="#FFFFFF" p-id="7684"></path></svg>
`.trim();
  const alertSuccessIconSVG = `
  <svg t="1750318938251" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7517" width="45" height="45"><path d="M511.950005 512.049995m-447.956254 0a447.956254 447.956254 0 1 0 895.912508 0 447.956254 447.956254 0 1 0-895.912508 0Z" fill="#20B759" p-id="7518"></path><path d="M458.95518 649.636559L289.271751 479.95313c-11.698858-11.698858-30.697002-11.698858-42.39586 0s-11.698858 30.697002 0 42.395859l169.683429 169.68343c11.698858 11.698858 30.697002 11.698858 42.39586 0 11.798848-11.598867 11.798848-30.597012 0-42.39586z" fill="#FFFFFF" p-id="7519"></path><path d="M777.62406 332.267552c-11.698858-11.698858-30.697002-11.698858-42.39586 0L424.158578 643.437164c-11.698858 11.698858-11.698858 30.697002 0 42.39586s30.697002 11.698858 42.39586 0l311.069622-311.069622c11.798848-11.798848 11.798848-30.796992 0-42.49585z" fill="#FFFFFF" p-id="7520"></path></svg>
`.trim();
  const logoBase64 = `
  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAJJWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyNS0wNC0wM1QxODo0MzozNSswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyNS0wNC0wM1QxODo0Mzo0NyswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjUtMDQtMDNUMTg6NDM6NDcrMDg6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5ZTMyY2UzLThmYWEtMjM0NC1iODM4LTA1YWRhMzI5YWViYSIgeG1wTU06RG9jdW1lbnRJRD0iYWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjIxMGQ3MWMzLWI2MzgtMDI0ZS05YzE3LTNkMDNkNmFlMTYxOCIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjYxM2YyNTBjLWFjYWQtZjE0Ny04NzczLWQ4YWJjNTY2ODg0ZSIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NjEzZjI1MGMtYWNhZC1mMTQ3LTg3NzMtZDhhYmM1NjY4ODRlIiBzdEV2dDp3aGVuPSIyMDI1LTA0LTAzVDE4OjQzOjM1KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjdhZjc2ZDZjLWIwYzktYjM0MC05ODJlLTE1ZTU3YzAyZTYzMiIgc3RFdnQ6d2hlbj0iMjAyNS0wNC0wM1QxODo0Mzo0NyswODowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjb252ZXJ0ZWQiIHN0RXZ0OnBhcmFtZXRlcnM9ImZyb20gYXBwbGljYXRpb24vdm5kLmFkb2JlLnBob3Rvc2hvcCB0byBpbWFnZS9wbmciLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImRlcml2ZWQiIHN0RXZ0OnBhcmFtZXRlcnM9ImNvbnZlcnRlZCBmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvcG5nIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo2OWUzMmNlMy04ZmFhLTIz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
`.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);
    },
    toStyleObject: function(obj) {
      const result = {};
      for (const [key, value] of Object.entries(obj)) {
        const camelKey = key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
        result[camelKey] = value;
      }
      return result;
    }
  };

  const ClipboardUtil = {
    setValue: function(text, type = "text/plain") {
      GM_setClipboard(text, type);
    }
  };

  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
        }
      });
      root.addEventListener("wheel", (e) => {
        e.stopImmediatePropagation();
      }, { passive: false, capture: true });
      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;
      let realAffLink = affLink;
      if (!realAffLink) {
        return;
      }
      if (realAffLink.indexOf("http") == -1) {
        realAffLink = Tools.decryptStr(affLink);
      }
      if (target === "_blank") {
        setTimeout(() => {
          const newTab = GM_openInTab(realAffLink, {
            active,
            insert: position === "after"
          });
          if (close) {
            setTimeout(() => {
              newTab.close();
            }, pause);
          }
        }, delay);
      } else if (target === "_self") {
        setTimeout(() => {
          window.location.href = realAffLink;
        }, delay);
      } else if (target === "_replace") {
        setTimeout(() => {
          window.location.replace(realAffLink);
        }, 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 () => {
        if (count >= max) {
          clearInterval(intervalId);
          return;
        }
        count += period;
        if (isRequesting) {
          return;
        }
        try {
          isRequesting = true;
          const data = await 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);
    }
  };

  const LangueUtil = {
    updateDelay: 15 * 60 * 1e3,
    _locations: {
      "en": { "languageDefault": "Follow Browser" },
      "es": { "languageDefault": "Seguir el navegador" },
      "ar": { "languageDefault": "اتباع المتصفح" },
      "fr": { "languageDefault": "Suivre le navigateur" },
      "pt": { "languageDefault": "Seguir o navegador" },
      "ru": { "languageDefault": "Следовать браузеру" },
      "ja": { "languageDefault": "ブラウザに従う" },
      "de": { "languageDefault": "Dem Browser folgen" },
      "ko": { "languageDefault": "브라우저 따르기" },
      "it": { "languageDefault": "Segui il browser" },
      "id": { "languageDefault": "Ikuti browser" },
      "tr": { "languageDefault": "Tarayıcıyı takip et" },
      "pl": { "languageDefault": "Podążaj za przeglądarką" },
      "uk": { "languageDefault": "Слідувати браузеру" },
      "nl": { "languageDefault": "Volg browser" },
      "vi": { "languageDefault": "Theo trình duyệt" },
      "ms": { "languageDefault": "Ikut pelayar" },
      "th": { "languageDefault": "ตามเบราว์เซอร์" },
      "mx": { "languageDefault": "Seguir el navegador" },
      "zh-CN": { "languageDefault": "跟随浏览器" },
      "zh-TW": { "languageDefault": "跟隨瀏覽器" }
    },
    getLanguages: function() {
      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" },
        { code: "zh-CN", name: "中文(简体)", dir: "ltr" },
        { code: "zh-TW", name: "中文(繁體)", dir: "ltr" }
      ];
      const language = languages.find((lang) => lang.code === DefaultValue.lang) ?? languages[0];
      const defaultLanguage = Object.assign({}, language);
      defaultLanguage.code = "default";
      defaultLanguage.name = (this._locations[DefaultValue.lang] ?? this._locations["en"])["languageDefault"] ?? "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) {
      key = "extension.structure." + key;
      let langueObjects = this.langueObjects;
      if (!langueObjects) {
        langueObjects = this.defaultLangueObjects;
      }
      return langueObjects[key] ?? 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"];
            Logger.log("info", "lang=======>", requestsBase.method, requestsBase.url, { "lang": lang });
            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: async function(force = false) {
      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) => values[index] ?? match);
    }
  };

  const RequestUnionUtil = {
    _getBaseParams: function() {
      const token = StorageUtil.getValue(StorageKeys.token, "");
      return {
        v: ScriptConst.version,
        version: ScriptConst.version,
        no: ScriptConst.number,
        token: !!token ? token : ""
      };
    },
    _getDetectCouponParams: async function() {
      const { Aliexpress, Ebay, Lazada, Bestbuy, Banggood } = PlatformModules;
      let platform = SupportData.support.p, marketplace = "", currency = "", countryCode = "";
      let lang = StorageUtil.getValue(StorageKeys.langue.custom, "default");
      if (lang === "default") {
        lang = DefaultValue.lang;
      }
      switch (platform) {
        case SupportData.supports.aliexpress.p:
          marketplace = await Aliexpress.Aliexpress.getMarketplace();
          currency = await Aliexpress.Aliexpress.getCurrency();
          break;
        case SupportData.supports.banggood.p:
          countryCode = Banggood.Banggood.getMarketplace();
          currency = Banggood.Banggood.getCurrency();
          marketplace = encodeURIComponent(JSON.stringify({ "countryCode": countryCode, "className": "", "html": "" }));
          break;
        default:
          countryCode = Tools.getCommonMarketplace();
          marketplace = encodeURIComponent(JSON.stringify({ "countryCode": countryCode, "className": "", "html": "" }));
      }
      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);
        });
      });
    },
    requestConfCached: function(method, url, storageKey, ttlMs) {
      return RequestUtil.requestConfCached(method, url, storageKey, ttlMs);
    },
    getDetectCouponResult: async function() {
      const params = await this._getDetectCouponParams();
      const { method, url } = getRequestUrl()["detectCoupon"];
      return this.request(method, url, params);
    },
    getDetectInfoResult: async function() {
      const params = await this._getDetectCouponParams();
      const { method, url } = getRequestUrl()["detectInfo"];
      return this.request(method, url, params);
    },
    getEngineScreenConf: function() {
      const loadConfSECache = StorageKeys.api.loadConfSECache;
      const { method, url } = getRequestUrl()["searchEnginExistConf"];
      return this.requestConfCached(method, url, loadConfSECache.key, loadConfSECache.time).then((text) => text ? JSON.parse(text) : null);
    },
    getEngineScreenResult: function(lists, platform) {
      const params = this._getEngineScreenParams(lists, platform);
      const { method, url } = getRequestUrl()["engineScreen"];
      return this.request(method, url, params);
    },
    initRequestData: async 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 = await 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 = await 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 = ElementUtil.toStyleObject(badgeData);
      const dragCss = ElementUtil.toStyleObject(dragData);
      const interfaceCss = ElementUtil.toStyleObject(interfaceData);
      const drag = ElementUtil.createElement("div", {
        className: "drag all-center",
        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,
          style: badgeCss
        });
        logoChildrens.push(logoNotification);
      }
      const logo = ElementUtil.createElement("div", {
        className: "logo",
        childrens: logoChildrens,
        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 = `
      <div class="setting-piece">
          <div class="setting-title" langue-extension-text="setting_modal_langue_title">` + LangueUtil.getLangueByStorageKey("setting_modal_langue_title") + `</div>
          <div class="setting-description" langue-extension-text="setting_modal_langue_description">` + LangueUtil.getLangueByStorageKey("setting_modal_langue_description") + `</div>
          <div class="language-switcher" id="language-switcher">
              <div class="selected">
                  <span id="selected-language">` + selectedLanguage.name + `</span>
              </div>
              <ul id="language-options" class="switcher-ul"></ul>
          </div>
      </div>
      <div class="setting-piece">
          <div class="setting-title" langue-extension-text="setting_modal_history_title">` + LangueUtil.getLangueByStorageKey("setting_modal_history_title") + `</div>
          <div class="setting-description" langue-extension-text="setting_modal_history_description">
            ` + LangueUtil.formatTemplateWithArray(
        LangueUtil.getLangueByStorageKey("setting_modal_history_description"),
        [min, max]
      ) + `
          </div>
          <input type="text" id="maximum-records"
            langue-extension-placeholder="setting_modal_history_max_placeholder" placeholder="` + LangueUtil.getLangueByStorageKey("setting_modal_history_max_placeholder") + `" value="${maximumRecords}">
      </div>
      <div class="setting-piece ">
          <div class="setting-title" langue-extension-text="setting_modal_clear_title">` + LangueUtil.getLangueByStorageKey("setting_modal_clear_title") + `</div>
          <div class="setting-description" langue-extension-text="setting_modal_clear_description">` + LangueUtil.getLangueByStorageKey("setting_modal_clear_description") + `</div>
          <button class="setting-clear-cache" id="clear-cache" langue-extension-text="setting_modal_clear_btn">` + LangueUtil.getLangueByStorageKey("setting_modal_clear_btn") + `</button>
      </div>
    `;
      return { "styleSheet": css_248z$1, "content": html };
    },
    showDialog: function(callback) {
      const { min, max } = DefaultValue.history.records;
      const maximumRecords = StorageUtil.getValue(StorageKeys.history.maximumRecordsKey, DefaultValue.history.records.default);
      const selectedLang = LangueUtil.getLang();
      const selectedLanguage = LangueUtil.getSelectedLanguage(selectedLang);
      const { styleSheet, content } = this._generateDialogHtml(maximumRecords, selectedLanguage);
      Dialog.showMake({
        title: LangueUtil.getLangueByStorageKey("setting_modal_title"),
        content,
        styleSheet,
        direction: selectedLanguage.dir,
        onContentReady: function($that) {
          CACHE_ROOT_DIVS.push($that.shadowRoot);
          SettingOperat.languageSwitcher($that.dialogContent, selectedLanguage);
          const $input = $that.dialogContent.querySelector("#maximum-records");
          const $clearCache = $that.dialogContent.querySelector("#clear-cache");
          $input.value = maximumRecords;
          $input.onchange = function(e) {
            const value = this.value;
            if (value >= min && value <= max) {
              StorageUtil.setValue(StorageKeys.history.maximumRecordsKey, value);
            }
          };
          $clearCache.addEventListener("click", function() {
            if (confirm(LangueUtil.getLangueByStorageKey("setting_modal_clear_confirm"))) {
              if (callback)
                callback();
              StorageUtil.setValue(StorageKeys.history.goodsHistory, DefaultValue.history.historyStorage);
            }
          });
        },
        onClose: function($that) {
          const index = CACHE_ROOT_DIVS.indexOf($that.mask);
          if (index !== -1) {
            CACHE_ROOT_DIVS.splice(index, 1);
          }
        }
      });
    }
  };

  const Mask = {
    generate: function() {
      const mask = ElementUtil.createElement("div", {
        className: "mask-container"
      });
      return mask;
    }
  };

  class AutoDetectBase {
    constructor() {
      this.BUTTON_CLICK_PASUE_MS = 700;
      this.VALIDATE_DELAY_MAX_MS = 10 * 1e3;
      this.VALIDATE_LOOP_DELAY_MS = 1500;
      this.VALIDATE_END_PASUE_MS = 500;
      this.HookType = {
        "react": "react",
        "default": "default"
      };
    }
    reactHook(element, value, useSetter = true) {
      const inputEvent = new InputEvent("input", {
        view: unsafeWindow,
        bubbles: true,
        cancelable: true
      });
      const changeEvent = new InputEvent("change", {
        view: unsafeWindow,
        bubbles: true,
        cancelable: true
      });
      const keyupEvent = new InputEvent("keyup", {
        view: unsafeWindow,
        bubbles: true,
        cancelable: true
      });
      element.setAttribute("readonly", "readonly");
      setTimeout(() => {
        element.removeAttribute("readonly");
      }, 200);
      const valueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
      if (valueSetter && useSetter) {
        valueSetter.call(element, value);
      } else {
        element.value = value;
      }
      element.dispatchEvent(inputEvent);
      element.dispatchEvent(changeEvent);
      element.dispatchEvent(keyupEvent);
    }
    unusedHook(element, value) {
      element.value = value;
    }
    validate(supportData) {
      const submitButton = document.querySelector(supportData.submitButtonSelector);
      const couponInput = document.querySelector(supportData.couponInputSelector);
      const validateData = { "couponInput": null, "submitButton": null };
      if (couponInput) {
        validateData.couponInput = couponInput;
        validateData.submitButton = submitButton;
      }
      return validateData;
    }
    clickValidateButton(supportData, couponInput, submitButton, code, hookType) {
      if (!couponInput) {
        return new Promise((resolve) => {
          resolve(false);
        });
      }
      if (hookType === this.HookType.react) {
        this.reactHook(couponInput, code);
      } else if (hookType === this.HookType.default) {
        this.unusedHook(couponInput, code);
      }
      if (!submitButton) {
        submitButton = document.querySelector(supportData.submitButtonSelector);
        if (!submitButton) {
          return new Promise((resolve) => {
            resolve(false);
          });
        }
      }
      return new Promise((resolve) => {
        const clickPromise = new Promise((resolveCheck) => {
          setTimeout(() => {
            submitButton.click();
            resolveCheck(true);
          }, this.BUTTON_CLICK_PASUE_MS);
        });
        clickPromise.then((result) => {
          resolve(result);
        });
      });
    }
  }

  class AliexpressAutoDetect extends AutoDetectBase {
    start(supportData, code) {
      const { couponInput, submitButton } = this.validate(supportData);
      return new Promise(async (resolve) => {
        const clickResult = await this.clickValidateButton(supportData, couponInput, submitButton, code, this.HookType.react);
        if (!clickResult) {
          resolve(clickResult);
          return;
        }
        let errors = null, existingCode = null, inputCode = null;
        let checkResult = false, current = 0;
        const checkInterval = setInterval(() => {
          errors = document.querySelector(supportData.applyErrorSelector);
          if (supportData.existingCodeSelector) {
            existingCode = document.querySelector(supportData.existingCodeSelector);
          }
          inputCode = document.querySelector(supportData.couponInputSelector);
          if (errors || existingCode || !inputCode || current >= this.VALIDATE_DELAY_MAX_MS) {
            clearInterval(checkInterval);
            checkResult = !!existingCode || !inputCode;
            setTimeout(() => {
              resolve(checkResult);
            }, this.VALIDATE_END_PASUE_MS);
          }
          current += this.VALIDATE_LOOP_DELAY_MS;
        }, this.VALIDATE_LOOP_DELAY_MS);
      });
    }
  }

  class WishAutoDetect extends AutoDetectBase {
    start(supportData, code) {
      const { couponInput, submitButton } = this.validate(supportData);
      return new Promise(async (resolve) => {
        const clickResult = await this.clickValidateButton(supportData, couponInput, submitButton, code, this.HookType.react);
        if (!clickResult) {
          resolve(clickResult);
          return;
        }
        let errors = null, existingCode = null;
        let checkResult = false, current = 0;
        const checkInterval = setInterval(() => {
          errors = document.querySelector(supportData.applyErrorSelector);
          if (supportData.existingCodeSelector) {
            existingCode = document.querySelector(supportData.existingCodeSelector);
          }
          if (errors || existingCode || current >= this.VALIDATE_DELAY_MAX_MS) {
            clearInterval(checkInterval);
            checkResult = !!existingCode;
            setTimeout(() => {
              resolve(checkResult);
            }, this.VALIDATE_END_PASUE_MS);
          }
          current += this.VALIDATE_LOOP_DELAY_MS;
        }, this.VALIDATE_LOOP_DELAY_MS);
      });
    }
  }

  class EbayAutoDetect extends AutoDetectBase {
    start(supportData, code) {
      const { couponInput, submitButton } = this.validate(supportData);
      return new Promise(async (resolve) => {
        const clickResult = await this.clickValidateButton(supportData, couponInput, submitButton, code, this.HookType.react);
        if (!clickResult) {
          resolve(clickResult);
          return;
        }
        let errors = null, existingCode = null;
        let checkResult = false, current = 0;
        errors = document.querySelector(supportData.applyErrorSelector);
        if (errors) {
          errors.remove();
        }
        const checkInterval = setInterval(() => {
          errors = document.querySelector(supportData.applyErrorSelector);
          if (supportData.existingCodeSelector) {
            existingCode = document.querySelector(supportData.existingCodeSelector);
          }
          if (errors || existingCode || current >= this.VALIDATE_DELAY_MAX_MS) {
            clearInterval(checkInterval);
            checkResult = !!existingCode;
            setTimeout(() => {
              resolve(checkResult);
            }, this.VALIDATE_END_PASUE_MS);
          }
          current += this.VALIDATE_LOOP_DELAY_MS;
        }, this.VALIDATE_LOOP_DELAY_MS);
      });
    }
  }

  class AmazonAutoDetect extends AutoDetectBase {
    start(supportData, code) {
      const { couponInput, submitButton } = this.validate(supportData);
      return new Promise(async (resolve) => {
        const clickResult = await this.clickValidateButton(supportData, couponInput, submitButton, code, this.HookType.react);
        if (!clickResult) {
          resolve(clickResult);
          return;
        }
        let errors = null, existingCode = null, loading = null;
        let checkResult = false, current = 0;
        const checkInterval = setInterval(() => {
          loading = document.querySelector(supportData.loadingSelector);
          if (!loading) {
            errors = document.querySelector(supportData.applyErrorSelector);
            if (supportData.existingCodeSelector) {
              existingCode = document.querySelector(supportData.existingCodeSelector);
            }
            if (errors || existingCode || current >= this.VALIDATE_DELAY_MAX_MS) {
              clearInterval(checkInterval);
              checkResult = !!existingCode;
              setTimeout(() => {
                resolve(checkResult);
              }, this.VALIDATE_END_PASUE_MS);
            }
          }
          current += this.VALIDATE_LOOP_DELAY_MS;
        }, this.VALIDATE_LOOP_DELAY_MS);
      });
    }
  }

  const DetectHelper = {
    _tryClickExpand: function(supportData) {
      const { couponInputSelector, expandCodeBoxSelectors } = supportData;
      const couponInput = document.querySelector(couponInputSelector);
      if (couponInput) {
        return new Promise((resolve) => {
          resolve(true);
        });
      }
      if (!expandCodeBoxSelectors || expandCodeBoxSelectors.length == 0) {
        return new Promise((resolve) => {
          resolve(false);
        });
      }
      return new Promise(async (resolve) => {
        let result = false;
        for (let i = 0; i < expandCodeBoxSelectors.length; i++) {
          const elements = document.querySelectorAll(expandCodeBoxSelectors[i]);
          for (let j = 0; j < elements.length; j++) {
            let element = elements[j];
            element.click();
            result = await new Promise((resolveInner) => {
              let elapsed = 0;
              const interval = 200, maxTime = 6e3;
              const timer = setInterval(() => {
                let hasCouponInput = document.querySelector(couponInputSelector);
                if (hasCouponInput) {
                  clearInterval(timer);
                  resolveInner(true);
                } else if (elapsed >= maxTime) {
                  clearInterval(timer);
                  resolveInner(false);
                }
                elapsed += interval;
              }, interval);
            });
            if (result) {
              break;
            }
          }
          if (result) {
            break;
          }
        }
        resolve(result);
      });
    },
    isPrepared: function(supportData) {
      return new Promise((resolve) => {
        Tools.waitForElementByInterval(supportData.promoContainerSelector, document.body, true, 50, 5 * 1e3).then((promoContainerElement) => {
          if (promoContainerElement) {
            this._tryClickExpand(supportData).then((result) => {
              resolve(result);
            });
          } else {
            resolve(false);
          }
        }).catch(() => {
          resolve(false);
        });
      });
    }
  };
  const AutoDetectUtil = {
    validate: async function(platform, supportData) {
      const preparedData = {
        "result": false
      };
      if (!!platform && !!supportData) {
        const isPrepared = await DetectHelper.isPrepared(supportData);
        preparedData.result = isPrepared;
      }
      return preparedData;
    },
    tryCode: function(platform, _supportData, code) {
      let promise = null;
      const supports = SupportData.supports;
      try {
        if (platform === supports.aliexpress.p) {
          promise = new AliexpressAutoDetect().start(_supportData, code);
        } else if (platform === supports.wish.p) {
          promise = new WishAutoDetect().start(_supportData, code);
        } else if (platform === supports.ebay.p) {
          promise = new EbayAutoDetect().start(_supportData, code);
        } else if (platform === supports.amazon.p) {
          promise = new AmazonAutoDetect().start(_supportData, code);
        }
      } catch (e) {
      }
      return promise;
    }
  };

  const CustomAlert = {
    show: function(params) {
      const style = document.createElement("style");
      const random = "_" + Math.ceil(Math.random() * 1e8);
      style.textContent = `
      .custom-alert-container` + random + ` {
        position: fixed;
        bottom: 30px;
        left: 50%;
        transform: translateX(-50%);
        z-index: 2147483647;
        width: 250px;
      }
      .custom-alert-content` + random + ` {
        display: flex;
        flex-direction: column;
        align-items: center;
        background-color: #FFF;
        border: 1px solid #ecebeb;
        border-radius: 5px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        padding: 10px;
        opacity: 1;
        animation: fadein 0.5s;
      }
      .custom-alert-icon` + random + ` {
        margin-bottom: 10px;
      }
      .custom-alert-message` + random + ` {
        font-size: 15px;
        color: #333;
        text-align: center;
      }
      @keyframes customFadein` + random + ` {
        from { opacity: 0; transform: translateY(-10px); }
        to { opacity: 1; transform: translateY(0); }
      }

      @keyframes customFadeout` + random + ` {
        from { opacity: 1; }
        to { opacity: 0; }
      }
    `;
      const container = document.createElement("div");
      container.className = "custom-alert-container" + random;
      const alertContent = document.createElement("div");
      alertContent.className = `custom-alert-content` + random;
      container.appendChild(alertContent);
      if (params.icon) {
        const icon = document.createElement("div");
        icon.className = "custom-alert-icon" + random;
        icon.innerHTML = params.icon;
        alertContent.appendChild(icon);
      }
      const text = document.createElement("div");
      text.className = "custom-alert-message" + random;
      text.textContent = params.message;
      alertContent.appendChild(text);
      document.body.appendChild(container);
      document.head.appendChild(style);
      setTimeout(() => {
        alertContent.style.animation = "customFadeout" + random + " 0.5s";
        alertContent.addEventListener("animationend", () => {
          container.remove();
          style.remove();
        });
      }, params.delay);
    }
  };

  const ProgressModal = {
    checkIsStop: false,
    _start: function() {
      this.checkIsStop = false;
      document.body.style.overflow = "hidden";
    },
    _end: function() {
      document.body.style.overflow = "auto";
      this.checkIsStop = true;
    },
    initProgress: function(progressBar) {
      progressBar.style.width = "0%";
    },
    updateProgressValue: function(progressBar, value) {
      progressBar.style.width = value * 100 + "%";
    },
    activeCouponItem: function(couponItem) {
      couponItem.classList.add("coupon-item-active");
    },
    inactiveCouponItem: function(couponItem) {
      ElementUtil.removeClass(couponItem, "coupon-item-active");
      couponItem.classList.add("coupon-item-lose");
    },
    closeModal: function(mask) {
      mask.remove();
      this._end();
    },
    addCloseEventListener: function(mask, modal) {
      modal.querySelector("div[class^='close']").addEventListener("click", (e) => {
        this.closeModal(mask);
      });
    },
    showCouponItems: async function(mask, modal, platform, coupons, supportData) {
      const couponsWarpper = modal.querySelector("div[class^='deal-coupons-warpper']");
      const progressBar = modal.querySelector("div[class^='progress-bar']");
      const couponElements = coupons.map((coupon) => {
        return {
          "element": ElementUtil.createElement("div", {
            className: "coupon-item",
            text: coupon
          }),
          "code": coupon
        };
      });
      couponElements.forEach((item, index2) => {
        couponsWarpper.append(item.element);
      });
      let total = coupons.length;
      const alertHiddenDelay = 4e3;
      this.initProgress(progressBar);
      const validateData = await AutoDetectUtil.validate(platform, supportData);
      if (!validateData || !validateData.result) {
        this.closeModal(mask);
        CustomAlert.show({
          "icon": alertErrorIconSVG,
          "message": LangueUtil.getLangueByStorageKey("auto_detect_alert_error"),
          "delay": alertHiddenDelay
        });
        return;
      }
      const results = [];
      for (let index2 = 0; index2 < total; index2++) {
        if (this.checkIsStop) {
          break;
        }
        const { element, code } = couponElements[index2];
        if (index2 != 0) {
          this.inactiveCouponItem(couponElements[index2 - 1].element);
        }
        this.activeCouponItem(element);
        this.couponScrollToCenter(couponsWarpper, element);
        this.updateProgressValue(progressBar, (index2 + 1) / total);
        let result = await AutoDetectUtil.tryCode(platform, supportData, code);
        results.push({ "code": code, "result": result });
        if (result) {
          break;
        }
      }
      this.closeModal(mask);
      const successCodeObj = results.find((item) => item.result === true);
      if (successCodeObj) {
        CustomAlert.show({
          "icon": alertSuccessIconSVG,
          "message": LangueUtil.getLangueByStorageKey("auto_detect_alert_success"),
          "delay": alertHiddenDelay
        });
      } else {
        CustomAlert.show({
          "icon": alertErrorIconSVG,
          "message": LangueUtil.getLangueByStorageKey("auto_detect_alert_error"),
          "delay": alertHiddenDelay
        });
      }
    },
    couponScrollToCenter: function(couponsWarpper, element) {
      const couponsWarpperRect = couponsWarpper.getBoundingClientRect();
      const elementRect = element.getBoundingClientRect();
      const scrollLeft = couponsWarpper.scrollLeft + (elementRect.left + elementRect.width / 2) - (couponsWarpperRect.left + couponsWarpperRect.width / 2);
      couponsWarpper.scrollTo({
        left: scrollLeft,
        behavior: "smooth"
      });
    },
    generate: function(logoBase64, root, platform, coupons, supportData) {
      const { outerDIV } = root;
      this._start();
      const modalHtml = `
      <div class="modal-header">
        <div class="logo">
          <img src="` + logoBase64 + `" />
        </div>
        <div class="title"></div>
        <div class="btns">
          <div class="close">` + closeSVG + `</div>
        </div>
      </div>
      <div class="modal-body">
        <div class="deal-pic-warpper"></div>
        <div class="deal-description-warpper">
          <div class="title" langue-extension-text="auto_detect_modal_description">` + LangueUtil.getLangueByStorageKey("auto_detect_modal_description") + `</div>
          <div class="sub-title" langue-extension-text="auto_detect_modal_secondary_description">` + LangueUtil.getLangueByStorageKey("auto_detect_modal_secondary_description") + `</div>
        </div>
        <div class="deal-coupons-warpper"></div>
        <div class="deal-progress-warpper">
          <div class="progress-container">
            <div class="progress-bar" style="width:0px;"></div>
          </div>
        </div>
      </div>
    `;
      const mask = Mask.generate();
      const modal = ElementUtil.createElement("div", {
        className: "modal-content",
        html: modalHtml
      });
      mask.append(modal);
      outerDIV.append(mask);
      this.showCouponItems(mask, modal, platform, coupons, supportData);
      this.addCloseEventListener(mask, modal);
    }
  };

  const FeatureControl = {
    createFeatureKey: function(key) {
      return {
        until: `${key}_disabledUntil`
      };
    },
    disableTemporarily: async function(key, durationMs) {
      const until = Date.now() + durationMs;
      StorageUtil.setValue(this.createFeatureKey(key).until, until);
    },
    isEnabled: async function(key) {
      const { until } = this.createFeatureKey(key);
      const disabledUntil = StorageUtil.getValue(until, null);
      if (disabledUntil && Date.now() < disabledUntil) {
        return false;
      }
      return true;
    },
    runIfEnabled: async function(key, callback) {
      const enabled = await this.isEnabled(key);
      if (enabled) {
        callback();
      }
    }
  };

  var css_248z = ".history-panel-wrapper{box-sizing:border-box;position:fixed;z-index:2147483646}.history-panel-wrapper svg.icon-i87i-svg path{fill:var(--color-modeal-header-icon)!important}.history-panel-wrapper svg.icon-i87i-svg:hover path{fill:var(--color-modeal-header-icon-hover)!important}.history-panel-wrapper>.history-panel-aside-main{background-color:#fff;border:1px solid #ebebeb;border-radius:5px;bottom:70px;box-shadow:2px 2px 5px #b6bdc5;height:400px;overflow-x:hidden;overflow-y:auto;position:absolute;right:0;width:400px}.history-panel-wrapper>.history-panel-aside-main>.panel-aside-main-inner{display:flex;flex-direction:column;height:100%;width:100%}.history-panel-aside-main .panel-aside-main-header{align-items:center;background-color: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)}.history-panel-aside-main .panel-aside-main-header>.logo-header{align-items:center;display:flex;justify-content:center}.history-panel-aside-main .panel-aside-main-header>.logo-header>svg{height:var(--size-height-modeal-icon)!important;width:var(--size-height-modeal-icon)!important}.history-panel-aside-main .panel-aside-main-header>.title-header{flex:1;font-size:var(--size-font-modeal-header-title);font-weight:700;padding-left:10px}.history-panel-aside-main .panel-aside-main-header .btns-header{display:flex;flex-direction:row}.history-panel-aside-main .panel-aside-main-header .btns-header .close,.history-panel-aside-main .panel-aside-main-header .btns-header .setting{align-items:center;cursor:pointer;display:flex;justify-content:center;width:var(--size-height-modeal-operat-icon)}.history-panel-aside-main .panel-aside-main-content{background-color:var(--color-modeal-content-background);flex:1;overflow-x:hidden;overflow-y:auto}.history-panel-aside-main .panel-aside-main-content::-webkit-scrollbar{width:2px}.history-panel-aside-main .panel-aside-main-content::-webkit-scrollbar-track{background:#0000}.history-panel-aside-main .panel-aside-main-content::-webkit-scrollbar-thumb{background-color:#969696;border-radius:2px}.history-panel-aside-main .panel-aside-main-item{margin:5px 0;padding:5px}.history-panel-aside-main .panel-aside-main-item .item-title{color:#b6b6b6;font-size:13px;font-weight:500;padding:5px 0;text-align:center}.history-panel-aside-main .panel-aside-main-item .item-container{display:flex;flex-flow:wrap;flex-direction:row;justify-content:flex-start}.history-panel-aside-main .histories-box-review_item{margin:5px 0;overflow:hidden;width:33.3333%}.history-panel-aside-main .histories-box-review_item>a{background-color:#fff!important;border:1px solid #ccc!important;border-radius:5px!important;box-sizing:initial!important;display:block!important;margin:0 auto!important;position:relative!important;width:110px!important}.history-panel-aside-main .histories-box-review_item>a>.review-shadow{border:2px solid red;border-radius:5px;bottom:0;display:none;left:0;position:absolute;right:0;text-align:center;top:0;z-index:99}.history-panel-aside-main .histories-box-review_item>a>.review-shadow .delete-btn{background-color:red;border-radius:3px;color:#fff;font-size:13px;height:15px;line-height:10px;position:absolute;right:0;text-align:center;top:0;width:15px}.history-panel-aside-main .histories-box-review_item>a>.review-img{border-radius:5px 5px 0 0;height:110px;overflow:hidden;width:110px}.history-panel-aside-main .histories-box-review_item>a>.review-img>img{width:100%!important}.history-panel-aside-main .histories-box-review_item>a>.review-text{color:#000!important;font-size:13px!important;overflow:hidden!important;padding:5px!important;text-align:center!important;text-decoration:underline!important;text-overflow:ellipsis!important;white-space:nowrap!important}.history-panel-wrapper>.history-panel-aside-body{background-color:#fafafa;border-radius:5px;box-shadow:1px 1px 2px #b6bdc5;direction:ltr!important;display:flex;height:60px;overflow:hidden}.history-panel-wrapper>.history-panel-aside-body>div{align-items:center!important;display:flex!important;justify-content:center!important}.history-panel-aside-body .goods-expand{cursor:pointer;width:20px!important}.history-panel-aside-body .goods-expand svg{transition:transform .3s!important}.history-panel-aside-body .goods-review{flex-direction:row;transition:all .5s ease-in-out;width:auto}.history-panel-aside-body .goods-review-item{border-radius:4px;cursor:pointer;height:45px;line-height:45px;margin:0 5px;overflow:hidden;position:relative;width:45px}.history-panel-aside-body .goods-review-item>a{display:block!important;height:100%!important;width:100%!important}.history-panel-aside-body .goods-review-item>a>.review-shadow{background-color:#3d9ba433;bottom:0;display:none;left:0;position:absolute;right:0;text-align:center;top:0;z-index:99}.history-panel-aside-body .goods-review-item>a>.review-shadow img{width:15px!important}.history-panel-aside-body .goods-review-item img{width:100%!important}.history-panel-aside-body .history-box-expand{cursor:pointer;flex-direction:column;margin:0 10px;text-align:center}.history-panel-aside-body .history-box-expand svg{height:33px!important;width:33px!important}.history-panel-aside-body .history-box-expand label{font-size:12px!important;font-weight:700!important}.history-panel-aside-body .wrapper-drag-handle{box-shadow:0 3px 3px -2px #0003,0 3px 4px 0 #00000024,0 1px 8px 0 #0000001f;cursor:move;width:20px!important}";

  const GoodsHistory = {
    root: null,
    models: {
      history: "history-model"
    },
    push: function(platform, obj) {
      try {
        const storageObj = StorageUtil.getValue(StorageKeys.history.goodsHistory, DefaultValue.history.historyStorage);
        const maximumRecords = StorageUtil.getValue(StorageKeys.history.maximumRecordsKey, DefaultValue.history.records.default);
        const histories = storageObj[platform] ?? [];
        if (histories.length >= maximumRecords) {
          histories.splice(0, parseInt(maximumRecords / 5));
        }
        const newArr = histories.filter((item, index) => item.id != obj.id);
        newArr.push(obj);
        storageObj[platform] = newArr;
        StorageUtil.setValue(StorageKeys.history.goodsHistory, storageObj);
      } catch (e) {
      }
    },
    get: function(platform, num = -1) {
      const storageObj = StorageUtil.getValue(StorageKeys.history.goodsHistory, DefaultValue.history.historyStorage);
      const histories = storageObj[platform] ?? [];
      if (num > 0) {
        const showHistories = [];
        for (let i = histories.length - 1; i >= 0; i--) {
          if (showHistories.length >= num)
            break;
          showHistories.push(histories[i]);
        }
        return showHistories;
      }
      return histories;
    },
    remove: function(platform, id) {
      const storageObj = StorageUtil.getValue(StorageKeys.history.goodsHistory, DefaultValue.history.historyStorage);
      const histories = storageObj[platform];
      let newArr = histories.filter((item, index) => item.id != id);
      storageObj[platform] = newArr;
      StorageUtil.setValue(StorageKeys.history.goodsHistory, storageObj);
    },
    getGoodsByDateGroup: function(platform) {
      const histories = this.get(platform).reverse();
      const group = [];
      const today = new Date();
      const yesterday = new Date(today);
      const format = "dd/MM";
      yesterday.setDate(today.getDate() - 1);
      const todayStr = this.dateFormat(today, format);
      const yesterdayStr = this.dateFormat(yesterday, format);
      const showDateFormat = (todayStr2, yesterdayStr2, current) => {
        const langueFormat2 = {};
        if (current === todayStr2) {
          langueFormat2.str = LangueUtil.getLangueByStorageKey("history_box_hit_today");
          langueFormat2.langueKey = "history_box_hit_today";
        } else if (current === yesterdayStr2) {
          langueFormat2.str = LangueUtil.getLangueByStorageKey("history_box_hit_yesterday");
          langueFormat2.langueKey = "history_box_hit_yesterday";
        } else {
          langueFormat2.str = " —— " + current + " —— ";
          langueFormat2.langueKey = "";
        }
        return langueFormat2;
      };
      let items = [], cacheDateStr = null, currentDateStr = null, langueFormat = null;
      for (let i = 0; i < histories.length; i++) {
        today.setTime(histories[i].date);
        currentDateStr = this.dateFormat(today, format);
        if (!!cacheDateStr) {
          if (cacheDateStr != currentDateStr) {
            langueFormat = showDateFormat(todayStr, yesterdayStr, cacheDateStr);
            group.push({
              "str": langueFormat.str,
              "langueKey": langueFormat.langueKey,
              "items": items
            });
            items = [];
            cacheDateStr = currentDateStr;
          }
        } else {
          cacheDateStr = currentDateStr;
        }
        items.push(histories[i]);
      }
      if (items.length != 0) {
        langueFormat = showDateFormat(todayStr, yesterdayStr, cacheDateStr);
        group.push({
          "str": langueFormat.str,
          "langueKey": langueFormat.langueKey,
          "items": items
        });
      }
      return group;
    },
    dateFormat: function(date, format) {
      var showDate = {
        "M+": date.getMonth() + 1,
        "d+": date.getDate(),
        "h+": date.getHours(),
        "m+": date.getMinutes(),
        "s+": date.getSeconds(),
        "q+": Math.floor((date.getMonth() + 3) / 3),
        "S+": date.getMilliseconds()
      };
      if (/(y+)/i.test(format)) {
        format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
      }
      for (var k in showDate) {
        if (new RegExp("(" + k + ")").test(format)) {
          format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? showDate[k] : ("00" + showDate[k]).substr(("" + showDate[k]).length));
        }
      }
      return format;
    },
    showOrHideHistoryBox: function(platform) {
      const { outerDIV, shadowRoot } = this.root;
      const self = this;
      const group = this.getGoodsByDateGroup(platform);
      const contentElement = outerDIV.querySelector(".history-panel-aside-main .panel-aside-main-content");
      contentElement.innerHTML = "";
      let historiesBoxHtml = "", jumpUrl = "", imgUrl = "";
      for (let i = 0; i < group.length; i++) {
        historiesBoxHtml += `<div class="panel-aside-main-item">`;
        historiesBoxHtml += `<div class="item-title" langue-extension-text="` + group[i].langueKey + `">` + group[i].str + `</div>`;
        historiesBoxHtml += `<div class="item-container">`;
        for (let j = 0; j < group[i].items.length; j++) {
          jumpUrl = this.pretreatmentJumpUrl(group[i].items[j].url, platform);
          imgUrl = this.pretreatmentImageUrl(group[i].items[j].pic, platform);
          historiesBoxHtml += `
          <div class="histories-box-review_item">
            <a title="` + group[i].items[j].title + `" jump-tag="true" href="javascript:void(0);" jump-url="` + jumpUrl + `" target="_blank">
              <div class="review-shadow">
                <div class="delete-btn" data-id="` + group[i].items[j].id + `">×</div>
              </div>
              <div class="review-img"><img src="` + imgUrl + `" /></div>
              <div class="review-text">` + group[i].items[j].price + `</div>
            </a>
          </div>
        `;
        }
        historiesBoxHtml += `</div>`;
        historiesBoxHtml += `</div>`;
      }
      contentElement.innerHTML = historiesBoxHtml;
      outerDIV.querySelectorAll(".history-panel-aside-main .delete-btn").forEach((ele) => {
        ele.addEventListener("click", function(e) {
          e.stopPropagation();
          e.preventDefault();
          const id = this.getAttribute("data-id");
          this.parentNode.parentNode.parentNode.remove();
          self.remove(platform, id);
        });
      });
      const items = outerDIV.querySelectorAll(".history-panel-aside-main .histories-box-review_item > a");
      items.forEach((ele) => {
        ele.addEventListener("mouseover", function() {
          this.querySelector(".review-shadow").style.display = "block";
        });
        ele.addEventListener("mouseout", function() {
          this.querySelector(".review-shadow").style.display = "none";
        });
      });
      outerDIV.querySelectorAll(".history-panel-aside-main a[jump-tag='true']").forEach((ele) => {
        ele.addEventListener("click", function(e) {
          e.stopPropagation();
          e.preventDefault();
          const href = this.getAttribute("jump-url");
          Tools.openInTab(Tools.decryptStr(href));
        });
      });
    },
    pretreatmentJumpUrl: function(url, platform) {
      const exchangeInfoLocal = StorageUtil.getValue(StorageKeys.exchangeInfo, DefaultValue.exchangeInfoLocal);
      const redirect = exchangeInfoLocal.redirect;
      const jumpUrl = redirect + encodeURIComponent(url);
      return Tools.encryptStr(jumpUrl);
    },
    pretreatmentImageUrl: function(imgUrl, platform) {
      let dealImgUrl = "";
      if (platform == "aliexpress") {
        dealImgUrl = imgUrl.replace(/_\d+x\d+\./, "_150x150.");
      } else {
        dealImgUrl = imgUrl;
      }
      return dealImgUrl;
    },
    createHistoryBox: function(platform) {
      const { outerDIV, shadowRoot } = this.root;
      const wrapperOffset = StorageUtil.getValue(StorageKeys.history.offset, DefaultValue.history.offsetWrapper);
      const histories = this.get(platform, DefaultValue.history.toolbarGoodsNum);
      const selectedLanguage = LangueUtil.getSelectedLanguage();
      let goodsHtml = ``, jumpUrl = "";
      histories.forEach((h) => {
        jumpUrl = this.pretreatmentJumpUrl(h.url, platform);
        goodsHtml += `
        <div class="goods-review-item">
          <a title="` + h.title + `" jump-tag="true" jump-url="` + jumpUrl + `" target="_blank">
            <div class="review-shadow">
              <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAVlJREFUWEftlsGRgzAMRS26wBQTUtluKltSDKYLlJUHMY6xZMGFi7lkCObr6cuWAHfzBTfHdw2gOdAcOOXAPM+/fGwB4OGcG7f7iX4R8d113dT3fby3XCYACgwAPxZBBiKYYRh2YOldFUAKjIivNNNlWUZEJEB2ZI9HazUQEUALLgluIH95thpEESCEQCKHbADgyfXNACcAeNEzpVyT9/6Zwx0ApOD/QFFAypKEvfdR74x7XwCaOGevANIpiPXWNm1eji8ATZyzCyGgdhos63gN6eQAorhFmMugOcml3PtJmo3FukpPqO6TdCMfHLBuIKkMiUvFU5RnXwSgP6W9kG6gbQ0tpya0NxvFftsx5JJIVucWWkp4uhHVIMhKajy0jptPtLMwLy634kJm6fSrzqVa4OIpqKlSfdd1HbdRHOufTj9+3zIFLwHUAK88N30PXBG2vtMAmgPNgQ/i7v8h6Um2jAAAAABJRU5ErkJggg==" />
            </div>
            <img src="` + h.pic + `" />
          </a>
        </div>
      `;
      });
      let html = `
      <div class="history-panel-wrapper" data-re-mark-tag="` + platform + `" style="bottom:` + wrapperOffset.bottom + `px; right:` + wrapperOffset.right + `px;">
        <div class="history-panel-aside-main" data-extension-direction="` + selectedLanguage.dir + `" style="display:none;">
          <div class="panel-aside-main-inner">
            <div class="panel-aside-main-header">
              <div class="logo-header">` + historyIconSVG + `</div>
              <div class="title-header" langue-extension-text="history_box_title">` + LangueUtil.getLangueByStorageKey("history_box_title") + `</div>
              <div class="btns-header">
                <div class="setting">` + settingSVG + `</div>
                <div class="close">` + closeSVG + `</div>
              </div>
            </div>
            <div class="panel-aside-main-content"></div>
          </div>
        </div>
        <div class="history-panel-aside-body">
          <div class="goods-expand">
            <svg focusable="false" class="icon-i87i-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1365" width="20" height="20"><path d="M317.84959998 926.1056a46.08 46.08 0 0 1 10.8544-29.9008L643.68639998 521.216a13.312 13.312 0 0 0 0-18.432l-3.6864-3.072L328.70399998 127.7952a46.4896 46.4896 0 0 1 71.0656-59.8016l311.0912 370.68799999a105.8816 105.8816 0 0 1 0 146.63680002l-311.0912 370.68799999a46.2848 46.2848 0 0 1-81.92-29.9008z" fill="#bfbfbf" p-id="1366"></path></svg>
          </div>
          <div class="goods-review">
            ` + goodsHtml + `
          </div>
          <div class="history-box-expand">
            ` + historyIconSVG + `
            <label langue-extension-text="history_bar_hint">` + LangueUtil.getLangueByStorageKey("history_bar_hint") + `</label>
          </div>
          <div class="wrapper-drag-handle">
            <svg focusable="false" class="icon-i87i-svg" viewBox="0 0 24 24" data-testid="DragIndicatorIcon"><path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2m-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2m0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2" fill="#bfbfbf"></path></svg>
          </div>
        </div>
      </div>
    `;
      outerDIV.insertAdjacentHTML("beforeend", html);
      this.addEventListener(platform);
    },
    addDragEventListener: function() {
      const { outerDIV, shadowRoot } = this.root;
      const draggable = outerDIV.querySelector(".history-panel-wrapper .wrapper-drag-handle");
      const wrapper = outerDIV.querySelector(".history-panel-wrapper");
      const offsetWrapper = Object.assign({}, DefaultValue.history.offsetWrapper);
      let isDragging = false, startY, elementBottom;
      let windowHeight = window.innerHeight;
      let bottomMax = parseInt(windowHeight / 3) * 2, bottomMin = DefaultValue.history.offsetWrapper.bottom;
      window.addEventListener("resize", () => {
        windowHeight = window.innerHeight;
        bottomMax = parseInt(windowHeight / 3) * 2;
      });
      function onMouseUp() {
        if (!isDragging)
          return;
        isDragging = false;
        document.removeEventListener("mousemove", onMouseMove);
        document.removeEventListener("mouseup", onMouseUp);
        StorageUtil.setValue(StorageKeys.history.offset, offsetWrapper);
      }
      function onMouseMove(e) {
        if (!isDragging)
          return;
        const deltaY = e.clientY - startY;
        let newBottom = elementBottom - deltaY;
        if (newBottom <= bottomMin) {
          newBottom = bottomMin;
        } else if (newBottom > bottomMax) {
          newBottom = bottomMax;
        }
        wrapper.style.bottom = `${newBottom}px`;
        offsetWrapper.bottom = newBottom;
      }
      draggable.addEventListener("mousedown", (e) => {
        e.preventDefault();
        if (window.getComputedStyle(wrapper).position !== "absolute" && window.getComputedStyle(wrapper).position !== "fixed") {
          return;
        }
        isDragging = true;
        startY = e.clientY;
        elementBottom = parseInt(window.getComputedStyle(wrapper).bottom, DefaultValue.history.offsetWrapper.bottom) || DefaultValue.history.offsetWrapper.bottom;
        document.addEventListener("mousemove", onMouseMove);
        document.addEventListener("mouseup", onMouseUp);
      });
    },
    addEventListener: function(platform) {
      const { outerDIV, shadowRoot } = this.root;
      const self = this;
      const items = outerDIV.querySelectorAll(".goods-review >.goods-review-item >a");
      items.forEach((ele) => {
        ele.addEventListener("mouseover", function() {
          this.querySelector(".review-shadow").style.display = "block";
        });
        ele.addEventListener("mouseout", function() {
          this.querySelector(".review-shadow").style.display = "none";
        });
      });
      const goodsExpandEle = outerDIV.querySelector(".history-panel-wrapper .goods-expand");
      if (goodsExpandEle) {
        goodsExpandEle.addEventListener("click", function() {
          const goodsReviewEle = this.nextElementSibling;
          const svgEle = this.querySelector("svg");
          svgEle.style.transition = "transform 0.3s";
          if (goodsReviewEle.style.width == "0px") {
            goodsReviewEle.style.width = "auto";
            svgEle.style.transform = "rotate(0deg)";
          } else {
            goodsReviewEle.style.width = "0px";
            svgEle.style.transform = "rotate(180deg)";
          }
        });
      }
      const historyBoxExpandEles = [
        outerDIV.querySelector(".history-panel-wrapper .history-box-expand"),
        outerDIV.querySelector(".history-panel-wrapper .close")
      ];
      const asideMainEle = outerDIV.querySelector(".history-panel-wrapper >.history-panel-aside-main");
      if (asideMainEle) {
        historyBoxExpandEles.forEach((ele) => {
          if (ele) {
            ele.addEventListener("click", function() {
              const computedDisplay = window.getComputedStyle(asideMainEle).display;
              if (computedDisplay === "none") {
                self.showOrHideHistoryBox(platform);
                asideMainEle.style.display = "block";
              } else {
                asideMainEle.style.display = "none";
              }
            });
          }
        });
      }
      document.addEventListener("click", function(event) {
        const path = event.composedPath();
        const clickedInsideShadow = path.some((el) => el === outerDIV || el === shadowRoot);
        if (!clickedInsideShadow) {
          asideMainEle.style.display = "none";
        }
      });
      const headerSettingElement = outerDIV.querySelector(".history-panel-wrapper .setting");
      if (headerSettingElement) {
        headerSettingElement.addEventListener("click", () => {
          Setting.showDialog(() => {
            outerDIV.querySelector(".history-panel-aside-body .goods-review").innerHTML = "";
            outerDIV.querySelector(".history-panel-aside-main .panel-aside-main-content").innerHTML = "";
          });
        });
      }
      outerDIV.querySelectorAll(".history-panel-aside-body a[jump-tag='true']").forEach((ele) => {
        ele.addEventListener("click", function(e) {
          e.stopPropagation();
          e.preventDefault();
          const href = this.getAttribute("jump-url");
          Tools.openInTab(Tools.decryptStr(href));
        });
      });
      self.addDragEventListener();
    },
    show: function() {
      const outerDIV = this.root?.outerDIV;
      if (outerDIV) {
        outerDIV.style.display = "block";
      }
    },
    hide: function() {
      const outerDIV = this.root?.outerDIV;
      if (outerDIV) {
        outerDIV.style.display = "none";
      }
    },
    start: function(support) {
      try {
        if (support.record.disabled) {
          return;
        }
        const platform = support.p;
        const styles = css_248z$3 + css_248z;
        const root = InspectUtil.generateShadowDomRoot(platform + "-" + this.models.history, styles);
        this.root = root;
        this.createHistoryBox(platform);
      } catch (e) {
      }
    }
  };

  const CouponListModal = {
    _root: null,
    _logoBase64: null,
    _hasModal: false,
    removeModel: function(modal) {
      modal.remove();
      this._hasModal = false;
    },
    addCloseEventListener: function(button, modal) {
      button.addEventListener("click", (e) => {
        this.removeModel(modal);
      });
    },
    addShowSettingEventListener: async function(platform, modal) {
      const setting = modal.querySelector(".modal-header .btns> .setting");
      const dropdown = modal.querySelector(".modal-header #settingsDropdown");
      const hide30m = 15;
      const settingsData = [
        {
          category: LangueUtil.getLangueByStorageKey("setting_window_show_display_title"),
          items: [
            { id: "hide30m", label: LangueUtil.formatTemplateWithArray(
              LangueUtil.getLangueByStorageKey("setting_window_show_display_hide30m"),
              [hide30m]
            ) },
            { id: "showAll", label: LangueUtil.getLangueByStorageKey("setting_window_show_display_all") }
          ]
        },
        {
          category: LangueUtil.getLangueByStorageKey("setting_window_show_general_title"),
          items: [
            { id: "general", label: LangueUtil.getLangueByStorageKey("setting_window_show_general_general") }
          ]
        }
      ];
      const windowShow = await FeatureControl.isEnabled(StorageKeys.featureControl.windowShow + "_" + platform);
      if (windowShow) {
        settingsData.forEach((group) => {
          group.items = group.items.filter((item) => item.id !== "showAll");
        });
      } else {
        settingsData.forEach((group) => {
          group.items = group.items.filter((item) => item.id === "showAll");
        });
      }
      const renderSettings = () => {
        dropdown.innerHTML = "";
        settingsData.forEach((group) => {
          const categoryDiv = document.createElement("div");
          categoryDiv.className = "setting-category";
          const title = document.createElement("div");
          title.className = "setting-category-title";
          title.textContent = group.category;
          categoryDiv.appendChild(title);
          group.items.forEach((item) => {
            const opt = document.createElement("div");
            opt.className = "setting-option";
            opt.textContent = item.label;
            opt.dataset.id = item.id;
            opt.addEventListener("click", () => {
              if (item.id === "hide30m") {
                FeatureControl.disableTemporarily(StorageKeys.featureControl.windowShow + "_" + platform, hide30m * 60 * 1e3);
                this.hideAllComponents();
                this.removeModel(modal);
              } else if (item.id === "showAll") {
                FeatureControl.enable(StorageKeys.featureControl.windowShow + "_" + platform);
                this.showAllComponents();
              } else if (item.id === "general") {
                this.removeModel(modal);
                Setting.showDialog();
              }
              dropdown.classList.remove("active");
            });
            categoryDiv.appendChild(opt);
          });
          dropdown.appendChild(categoryDiv);
        });
      };
      setting.addEventListener("click", () => {
        dropdown.classList.toggle("active");
        if (dropdown.classList.contains("active")) {
          renderSettings();
        }
      });
      modal.addEventListener("click", (e) => {
        if (!modal.querySelector(".modal-header .btns").contains(e.target)) {
          dropdown.classList.remove("active");
        }
      });
    },
    addApplyCouponsEventListener: function(button, modal) {
      InspectUtil.bindApplyCouponsEvent(button, (dataJson) => {
        this.removeModel(modal);
        const { platform, codes, check, open } = dataJson;
        Promise.resolve().then(() => {
          ProgressModal.generate(
            this._logoBase64,
            this._root,
            platform,
            codes,
            check
          );
        });
        Promise.resolve().then(() => {
          if (!!open) {
            try {
              InspectUtil.openUrl(open);
            } catch (e) {
            }
          }
        });
      });
    },
    generateRequest: function(modalBody) {
      const requestState = ElementUtil.createElement("div", {
        className: "request-state"
      });
      modalBody.append(requestState);
      return requestState;
    },
    generateRequestLoadding: function() {
      return ElementUtil.createElement("div", {
        className: "loading"
      });
    },
    generateRequestLoaddingError: function(callback) {
      const retry = ElementUtil.createElement("div", {
        className: "loading-error-retry",
        text: LangueUtil.getLangueByStorageKey("couponList_modal_retry"),
        attributes: {
          "langue-extension-text": "couponList_modal_retry"
        }
      });
      retry.addEventListener("click", () => {
        callback();
      });
      const error = ElementUtil.createElement("div", {
        className: "loading-error",
        childrens: [
          ElementUtil.createElement("div", {
            className: "loading-error-image",
            html: `
            <svg t="1735570722474" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7538" width="64" height="64"><path d="M143.1552 722.0224s-2.56-1.536-7.7824-4.096l4.096-7.2704c4.608 2.56 7.2704 4.096 7.2704 4.096l-3.584 7.2704z m-22.7328-12.9024c-4.608-2.56-9.3184-6.2464-14.4384-9.3184l4.608-7.2704c5.12 3.584 9.8304 6.7584 13.9264 9.3184l-4.096 7.2704z m-28.3648-19.6608c-4.608-3.072-8.8064-6.7584-13.4144-10.8544l5.632-6.7584c4.608 3.584 8.8064 7.2704 13.4144 10.3424l-5.632 7.2704z m-26.8288-22.2208c-4.096-4.096-8.2944-7.7824-12.3904-12.3904l6.2464-5.632c4.096 4.096 7.7824 8.2944 11.8784 11.8784l-5.7344 6.144z m-23.7568-25.2928c-3.584-4.608-7.2704-9.3184-10.3424-13.9264l7.2704-4.608c3.072 4.608 6.2464 8.8064 9.8304 13.4144l-6.7584 5.12z m-19.6608-29.3888c-2.56-5.7344-5.12-10.8544-6.7584-16.4864l8.2944-2.56c1.536 5.12 3.584 10.3424 6.2464 14.9504l-7.7824 4.096z m-10.8544-33.5872c-0.512-4.096-1.024-8.2944-1.024-12.3904v-5.632l8.2944 0.512v5.12c0 3.584 0.512 7.2704 1.024 10.8544l-8.2944 1.536z m10.8544-33.0752l-8.2944-2.56c1.536-5.7344 3.584-11.3664 6.7584-16.4864l7.7824 3.584c-3.1744 5.12-5.2224 10.24-6.2464 15.4624z m815.616-19.6608h-16.9984v-8.2944h16.4864l0.512 8.2944z m17.1008-0.512v-8.2944c5.7344 0 11.3664 0 16.9984-0.512l0.512 8.2944c-5.632 0.512-11.3664 0.512-17.5104 0.512z m-51.2 0c-5.632 0-11.3664-0.512-16.9984-0.512l0.512-8.2944c5.632 0 11.3664 0.512 16.9984 0.512l-0.512 8.2944z m85.8112-1.024l-0.512-8.2944c5.632-0.512 11.3664-0.512 16.9984-1.024l0.512 8.2944c-5.12 0.512-11.3664 0.512-16.9984 1.024z m-120.32-0.512c-5.7344-0.512-11.3664-0.512-16.9984-1.024l0.512-8.2944c5.7344 0.512 11.3664 0.512 17.1008 1.024l-0.6144 8.2944z m-34.0992-2.048c-5.632-0.512-11.3664-1.024-16.9984-1.024l0.512-8.2944c5.632 0.512 11.3664 1.024 16.9984 1.024l-0.512 8.2944z m189.0304-0.512l-1.024-8.2944c5.7344-0.512 11.3664-1.536 16.4864-2.56l1.536 8.2944c-5.632 1.024-11.3664 2.048-16.9984 2.56z m-223.1296-2.048l-17.1008-1.536 1.024-8.2944 16.9984 1.536-0.9216 8.2944z m-663.8592-1.024l-5.7344-6.2464c3.584-3.584 8.8064-7.2704 14.4384-10.3424l4.608 7.2704c-5.5296 3.072-9.6256 6.144-13.312 9.3184z m629.248-2.1504l-16.9984-1.536 1.024-8.2944 16.9984 1.536-1.024 8.2944z m291.84-0.512l-2.048-8.2944c5.7344-1.536 11.3664-2.56 15.9744-4.096l2.56 8.2944c-4.608 1.536-10.3424 3.072-16.4864 4.096z m-325.9392-3.072c-5.7344-0.512-11.3664-1.536-17.1008-2.048l1.024-8.2944c5.632 0.512 11.3664 1.536 16.9984 2.048l-0.9216 8.2944z m-34.0992-4.096c-5.632-0.512-11.3664-1.536-16.9984-2.048l1.024-8.2944c5.7344 0.512 11.3664 1.536 17.1008 2.048l-1.1264 8.2944z m393.1136-4.1984l-4.096-7.7824c5.12-2.56 9.3184-5.7344 12.3904-9.3184l6.2464 5.7344c-3.1744 4.7104-7.8848 8.2944-14.5408 11.3664z m-426.7008-0.512c-5.632-1.024-11.3664-1.536-16.9984-2.56l1.024-8.2944c5.632 1.024 11.3664 1.536 16.9984 2.56l-1.024 8.2944z m-499.5072-3.072l-3.584-7.7824c5.12-2.56 10.3424-4.608 15.9744-6.7584l3.072 7.7824c-5.7344 2.6624-10.8544 4.7104-15.4624 6.7584z m465.408-2.048c-5.7344-1.024-11.3664-1.536-17.1008-2.56l1.536-8.2944c5.632 1.024 11.3664 2.048 16.9984 2.56l-1.4336 8.2944z m-34.0992-5.7344l-16.9984-3.072 1.536-8.2944 17.1008 3.072-1.6384 8.2944z m-399.872-4.608l-3.072-8.2944c5.12-2.048 10.8544-3.584 16.4864-5.12l2.56 8.2944c-5.632 1.536-10.752 3.072-15.9744 5.12z m366.2848-1.024l-16.9984-3.072 1.536-8.2944 16.9984 3.072-1.536 8.2944z m-33.5872-6.7584c-5.7344-1.024-11.3664-2.048-17.1008-3.584l1.536-8.2944c5.632 1.024 11.3664 2.048 16.4864 3.584l-0.9216 8.2944zM128.7168 478.208l-2.048-8.2944c5.12-1.536 10.8544-3.072 16.4864-4.608l2.048 8.2944c-5.632 1.536-11.264 3.072-16.4864 4.608z m875.6224-2.56v-1.024c-0.512-4.096-2.048-8.2944-5.12-12.3904l6.7584-5.12c3.584 5.12 6.2464 10.8544 6.7584 16.4864v1.536l-8.3968 0.512zM395.264 474.112c-5.7344-1.024-11.3664-2.56-16.4864-3.584l2.048-8.2944c5.632 1.024 10.8544 2.56 16.4864 3.584l-2.048 8.2944z m-233.984-4.1984l-1.536-8.2944c5.632-1.536 10.8544-2.56 16.4864-4.096l2.048 8.2944c-5.632 1.536-11.264 2.56-16.9984 4.096z m200.3968-3.584c-5.632-1.536-11.3664-2.56-16.4864-4.096l2.048-8.2944c5.632 1.536 10.8544 2.56 16.4864 4.096l-2.048 8.2944z m-166.8096-4.096l-1.536-8.2944c5.7344-1.024 11.3664-2.048 17.1008-3.584l1.536 8.2944c-6.2464 1.4336-11.4688 2.56-17.1008 3.584z m133.2224-4.1984c-5.632-1.536-11.3664-3.072-16.4864-4.096l2.048-8.2944c5.7344 1.536 10.8544 3.072 16.4864 4.096l-2.048 8.2944z m-99.6352-2.56l-1.536-8.2944 16.9984-3.072 1.536 8.2944c-6.144 1.024-11.8784 2.048-16.9984 3.072z m759.296-3.584c-4.096-2.56-8.8064-5.12-14.4384-7.7824l3.584-7.7824c5.7344 2.56 11.3664 5.7344 15.4624 8.2944l-4.608 7.2704z m-725.7088-2.56l-1.536-8.2944c5.632-1.024 11.3664-2.048 16.9984-2.56l1.024 6.2464 2.56-8.2944c4.608 1.536 9.3184 2.56 14.4384 4.096l-1.024-4.608c5.632-1.024 11.3664-1.536 16.9984-2.56l1.024 8.2944c-5.7344 1.024-10.8544 1.536-15.9744 2.56l-1.536 5.12c-5.632-1.536-10.8544-3.072-16.4864-4.608l0.512 2.048c-5.632 0.9216-11.3664 1.9456-16.9984 2.56z m0-9.8304c-5.7344-1.536-10.8544-3.584-16.4864-5.12l2.56-8.2944c5.12 1.536 10.8544 3.584 15.9744 5.12l-2.048 8.2944z m67.6864-0.512l-1.024-8.2944c5.7344-1.024 11.3664-1.536 16.9984-2.048l1.024 8.2944c-5.632 0.4096-11.3664 1.536-16.9984 2.048z m628.1216-1.024c-5.12-1.536-10.3424-3.072-15.9744-4.608l2.048-8.2944c5.632 1.536 11.3664 3.072 16.4864 5.12l-2.56 7.7824z m-594.6368-3.1744l-1.024-8.2944c5.632-0.512 11.3664-1.536 16.9984-2.048l1.024 8.2944c-5.632 0.512-11.264 1.024-16.9984 2.048z m34.0992-4.096l-1.024-8.2944c5.7344-0.512 11.3664-1.024 17.1008-2.048l1.024 8.2944c-5.7344 1.024-11.3664 1.536-17.1008 2.048z m527.9744-1.536c-5.12-1.024-10.8544-2.048-16.4864-3.072l1.536-8.2944 16.9984 3.072-2.048 8.2944z m-695.808 0c-5.632-2.048-10.8544-3.584-15.9744-5.632l3.072-7.7824c5.12 2.048 10.3424 3.584 15.9744 5.632l-3.072 7.7824z m201.9328-2.048l-1.024-8.2944 16.9984-1.536 1.024 8.2944-16.9984 1.536z m34.0992-3.1744l-1.024-8.8064 16.9984-1.536 0.512 8.2944c-5.12 1.024-10.752 1.536-16.4864 2.048z m426.1888-0.512c-5.7344-1.024-10.8544-1.536-16.9984-2.048l1.024-8.2944c5.7344 0.512 11.3664 1.536 17.1008 2.048l-1.1264 8.2944zM499.6096 420.864l-0.512-8.2944c5.7344-0.512 11.3664-1.024 16.9984-1.024l0.512 8.2944c-5.632 0.512-11.264 1.024-16.9984 1.024z m358.5024-1.536l-16.9984-1.536 0.512-8.2944 16.9984 1.536-0.512 8.2944z m-324.4032-0.512l-0.512-8.2944c5.632-0.512 11.3664-0.512 16.9984-1.024l0.512 8.2944c-5.632 0-11.264 0.512-16.9984 1.024z m-336.7936-1.536c-5.632-2.56-10.8544-4.608-15.9744-6.7584l3.072-7.7824c5.12 2.048 10.3424 4.096 15.4624 6.7584l-2.56 7.7824z m370.8928-0.512l-0.512-8.2944c5.7344-0.512 11.3664-0.512 17.1008-1.024l0.512 8.2944c-5.7344 0.512-11.3664 0.512-17.1008 1.024z m256.2048-0.512c-5.7344-0.512-11.3664-0.512-17.1008-1.024l0.512-8.2944c5.7344 0.512 11.3664 0.512 16.9984 1.024l-0.4096 8.2944zM601.9072 414.72l-0.512-8.2944c5.632 0 11.3664-0.512 16.9984-0.512l0.512 8.2944c-5.632 0.512-11.264 0.512-16.9984 0.512z m188.0064-0.6144c-5.632 0-11.3664-0.512-16.9984-0.512l0.512-8.2944c5.632 0 11.3664 0.512 16.9984 0.512l-0.512 8.2944z m-153.9072-0.512v-8.2944c5.7344 0 11.3664-0.512 17.1008-0.512v8.2944c-5.7344 0-11.3664 0.512-17.1008 0.512z m119.808-0.512c-5.632 0-11.3664 0-16.9984-0.512v-8.2944c5.7344 0 11.3664 0 16.9984 0.512v8.2944z m-85.1968-0.512v-8.2944h16.9984v8.2944h-16.9984z m51.0976 0h-17.1008v-8.2944h17.1008v8.2944z m-556.3392-9.216c-5.12-2.56-10.8544-5.12-15.4624-7.7824l4.096-7.7824c4.608 2.56 9.8304 5.12 14.9504 7.7824l-3.584 7.7824z m-30.9248-16.0768c-5.12-3.072-10.3424-6.2464-14.4384-9.3184l5.12-6.7584c4.096 3.072 8.8064 6.2464 13.9264 9.3184l-4.608 6.7584zM105.984 366.592c-4.608-4.096-8.8064-8.8064-11.8784-12.9024l6.7584-5.12c3.072 4.096 6.7584 7.7824 10.8544 11.8784l-5.7344 6.144z m-20.1728-28.8768c-1.024-3.584-1.536-6.7584-1.536-10.3424 0-3.072 0.512-5.632 1.024-8.8064l8.2944 2.048c-0.512 2.048-0.512 4.096-0.512 6.7584 0 2.56 0.512 5.12 1.024 7.7824l-8.2944 2.56zM100.864 306.176l-7.2704-4.608c3.072-5.12 6.7584-9.8304 10.3424-14.4384l6.7584 5.12c-3.6864 5.12-7.2704 9.3184-9.8304 13.9264z m768.1024-16.4864c-5.632-0.512-11.3664-0.512-16.9984-1.024l0.512-8.2944c5.632 0.512 11.3664 1.024 16.9984 1.024l-0.512 8.2944z m-34.6112-2.6624l-17.1008-1.536 1.024-8.2944 16.9984 1.536-0.9216 8.2944z m-34.0992-4.096c-5.632-0.512-11.3664-1.536-16.9984-2.048l1.024-8.2944c5.632 0.512 11.3664 1.536 16.9984 2.048l-1.024 8.2944z m-678.7072-2.56l-6.2464-6.2464c4.096-4.096 8.2944-8.2944 12.9024-11.8784l5.12 6.7584c-4.096 4.096-8.192 7.7824-11.776 11.3664z m645.12-2.048c-5.632-1.024-11.3664-1.536-16.9984-2.56l1.024-8.2944c5.632 1.024 11.3664 1.536 16.9984 2.56l-1.024 8.2944z m-34.0992-4.7104l-17.1008-2.56 1.536-8.2944 16.9984 2.56-1.4336 8.2944z m-34.0992-5.632l-16.9984-2.56 1.536-8.2944 17.1008 2.56-1.6384 8.2944z m-33.4848-5.7344l-16.9984-3.072 1.536-8.2944 16.9984 3.072-1.536 8.2944z m-517.632-2.56l-4.608-7.2704c4.608-3.072 9.8304-6.2464 14.9504-8.8064l4.096 7.7824c-5.12 2.6624-9.8304 5.2224-14.4384 8.2944z m484.0448-3.072l-17.1008-3.072 1.536-8.2944 16.9984 3.072-1.4336 8.2944z m-34.0992-6.2464l-16.9984-3.072 1.536-8.2944 17.1008 3.072-1.6384 8.2944z m-33.5872-5.632l-16.9984-2.56 1.536-8.2944 16.9984 2.56-1.536 8.2944z m-386.9696-0.512l-3.072-7.7824c5.12-2.048 10.8544-4.096 15.9744-6.2464l2.56 8.2944c-5.12 1.536-10.24 3.6864-15.4624 5.7344z m352.8704-4.7104c-5.7344-1.024-11.3664-1.536-17.1008-2.56l1.024-8.2944c5.7344 1.024 11.3664 1.536 16.9984 2.56l-0.9216 8.2944z m-33.5872-5.12c-5.632-1.024-11.3664-1.536-16.9984-2.56l1.024-8.2944c5.7344 0.512 11.3664 1.536 17.1008 2.56l-1.1264 8.2944z m-287.232-1.024l-2.048-8.2944c5.632-1.536 11.3664-3.072 16.9984-4.096l1.536 8.2944c-5.632 1.024-11.264 2.56-16.4864 4.096z m253.6448-3.584c-5.632-0.512-11.3664-1.536-16.9984-2.048l1.024-8.2944c5.632 0.512 11.3664 1.536 16.9984 2.048l-1.024 8.2944z m-220.5696-3.6864l-1.536-8.2944c5.7344-1.024 11.3664-1.536 17.1008-2.56l1.024 8.2944c-5.7344 0.512-11.4688 1.536-16.5888 2.56z m186.4704 0l-17.1008-1.536 1.024-8.2944 16.9984 1.536-0.9216 8.2944z m-34.0992-3.072c-5.632-0.512-11.3664-1.024-16.9984-1.024l0.512-8.2944c5.632 0.512 11.3664 0.512 16.9984 1.024l-0.512 8.2944z m-118.784-1.024l-0.512-8.2944c5.632-0.512 11.3664-1.024 16.9984-1.024l0.512 8.2944c-6.144 0-11.8784 0.512-16.9984 1.024z m84.6848-1.024c-5.632 0-11.3664-0.512-16.9984-0.512v-8.2944c5.7344 0 11.3664 0.512 16.9984 0.512v8.2944z m-51.0976-1.024v-8.2944h16.9984v8.2944h-16.9984z m585.728 70.7584h-8.8064l0.512-8.2944h8.2944v8.2944z m0 0" fill="#CCE1FF" p-id="7539"></path><path d="M677.376 592.384l-324.4032 1.024c-3.072 0-6.2464-2.56-6.2464-6.2464v-7.7824c0-3.072 2.56-6.2464 6.2464-6.2464l324.4032-1.024c3.072 0 6.2464 2.56 6.2464 6.2464v7.7824c-0.6144 3.6864-3.1744 6.2464-6.2464 6.2464z m0 0" fill="#E6EFFF" p-id="7540"></path><path d="M863.8464 323.2768c-38.1952-42.9056-92.4672-99.7376-144.0768-160.6656l-287.232 1.024-2.048 39.7312 36.1472 25.2928-34.0992 8.2944 34.0992 30.0032-27.3408 4.608-21.1968 53.248-19.1488-25.2928-36.1472-19.1488 23.2448-27.8528-47.104-21.1968 30.0032-21.1968-25.2928-45.9776-124.5184 0.512c-23.2448 0-41.8816 19.1488-41.8816 42.3936l1.536 389.5296c0 23.2448 19.1488 41.8816 42.3936 41.8816l602.3168-1.536c23.2448 0 41.8816-19.1488 41.8816-42.3936l-1.536-271.2576z m0 0" fill="#FFFFFF" p-id="7541"></path><path d="M220.16 640.9216c-11.8784 0-23.2448-4.608-32.0512-13.4144-8.8064-8.8064-13.4144-20.1728-13.4144-32.0512l-1.536-389.5296c0-11.8784 4.608-23.2448 12.9024-32.0512 8.8064-8.8064 20.1728-13.4144 32.0512-13.4144l126.5664-0.512 27.8528 50.0736-27.8528 19.6608 45.4656 20.6848-23.7568 27.8528 33.5872 18.1248 15.9744 21.1968 19.6608-49.5616 22.7328-3.584-33.5872-29.4912 33.0752-8.2944-32.0512-22.7328 2.048-44.9536 291.84-1.024 1.024 1.024c34.0992 40.2432 69.2224 78.5408 100.2496 112.64 15.9744 16.9984 30.5152 33.0752 43.4176 47.5136l1.024 1.024v1.024l1.024 270.6432c0 24.7808-20.1728 45.4656-44.9536 45.4656L220.16 640.9216z m121.4464-474.2144l-122.9824 0.512c-10.3424 0-20.1728 4.096-27.3408 11.3664-7.2704 7.2704-11.3664 17.1008-11.3664 27.3408l1.536 389.5296c0 10.3424 4.096 20.1728 11.3664 27.3408 7.2704 7.2704 16.9984 11.3664 27.3408 11.3664l602.3168-1.536c21.7088 0 38.7072-17.6128 38.7072-39.2192l-1.024-269.1072c-12.9024-14.4384-27.3408-30.0032-42.3936-47.0016-31.0272-33.5872-65.6384-71.7824-99.7376-111.616l-282.5216 0.512-1.536 35.1232 40.2432 28.3648-35.1232 9.3184 34.6112 30.5152-32.5632 5.12-22.7328 56.832-22.1184-29.9008-39.2192-20.6848 23.2448-27.3408-48.0256-21.7088 32.0512-22.7328-22.7328-42.3936z m0 0" fill="#A2ADC2" p-id="7542"></path><path d="M860.672 318.0544c-1.024 7.7824-7.7824 12.9024-14.9504 12.3904l-137.9328-14.4384c-7.7824-1.024-12.9024-7.7824-12.3904-14.9504l11.3664-125.0304c1.024-7.7824 7.7824-12.9024 14.9504-12.3904l138.9568 154.4192z m0 0" fill="#FFEED4" p-id="7543"></path><path d="M847.2576 333.6192h-1.536l-137.9328-13.9264c-4.608-0.512-8.2944-2.56-11.3664-6.2464-2.56-3.584-4.096-7.7824-3.584-12.3904l11.3664-125.0304c1.024-9.3184 9.3184-15.9744 18.6368-14.9504h1.024l1.024 1.024 139.4688 154.9312v1.536c-1.024 8.8064-8.8064 15.0528-17.1008 15.0528zM720.6912 167.2192c-5.12 0-9.8304 4.096-10.3424 9.3184l-11.3664 125.0304c-0.512 2.56 0.512 5.7344 2.048 7.7824s4.096 3.584 7.2704 3.584l137.9328 14.4384c2.56 0.512 5.7344-0.512 7.7824-2.048s3.072-3.584 3.584-5.7344L720.6912 167.2192z m0 0" fill="#A2ADC2" p-id="7544"></path><path d="M828.7232 864.0512h-629.76c-15.4624 0-28.3648-12.9024-28.3648-28.3648l-42.3936-271.6672c0-15.4624 12.9024-28.3648 28.3648-28.3648h720.0768c15.4624 0 28.3648 12.9024 28.3648 28.3648L857.088 835.6864c-0.512 15.4624-12.9024 28.3648-28.3648 28.3648z m0 0" fill="#FFEED4" p-id="7545"></path><path d="M828.7232 867.2256h-629.76c-17.6128 0-31.5392-13.9264-31.5392-31.5392l-42.3936-271.1552c0-18.1248 13.9264-32.0512 31.5392-32.0512h720.0768c17.5104 0 31.5392 13.9264 31.5392 31.5392L860.16 836.1984c0 16.9984-14.4384 31.0272-31.4368 31.0272zM156.672 538.624c-13.9264 0-25.2928 11.3664-25.2928 25.2928l42.3936 271.1552c0 14.4384 11.3664 25.8048 25.2928 25.8048h629.1456c13.9264 0 25.2928-11.3664 25.2928-25.2928l48.0256-272.2816c0-13.4144-11.3664-24.7808-25.2928-24.7808H156.672z m0 0" fill="#A2ADC2" p-id="7546"></path><path d="M411.3408 671.9488c0 3.584 1.536 7.7824 4.096 10.3424s6.7584 4.096 10.3424 4.096 7.7824-1.536 10.3424-4.096 4.096-6.7584 4.096-10.3424-1.536-7.7824-4.096-10.3424-6.7584-4.096-10.3424-4.096-7.7824 1.536-10.3424 4.096c-2.56 3.072-4.096 6.656-4.096 10.3424z m170.9056 0c0 3.584 1.536 7.7824 4.096 10.3424s6.7584 4.096 10.3424 4.096 7.7824-1.536 10.3424-4.096 4.096-6.7584 4.096-10.3424-1.536-7.7824-4.096-10.3424-6.7584-4.096-10.3424-4.096-7.7824 1.536-10.3424 4.096c-2.4576 3.072-4.096 6.656-4.096 10.3424z m0 0M561.152 757.6576c5.12 0 9.3184-3.072 8.2944-6.7584-4.608-18.1248-27.8528-32.0512-55.808-32.0512-27.8528 0-51.0976 13.9264-55.808 32.0512-1.024 3.584 3.072 6.7584 8.2944 6.7584 4.096 0 7.7824-2.048 8.2944-4.608 3.072-12.9024 19.6608-22.2208 39.2192-22.2208 19.6608 0 35.6352 9.8304 39.2192 22.2208 0.512 2.56 4.096 4.608 8.2944 4.608z m0 0" fill="#A2ADC2" p-id="7547"></path><path d="M33.1776 498.8928c0 71.8848 58.2656 130.1504 130.1504 130.1504 71.8848 0 130.1504-58.2656 130.1504-130.1504s-58.2656-130.1504-130.1504-130.1504c-71.8848 0-130.1504 58.2656-130.1504 130.1504z m0 0" fill="#FFFFFF" p-id="7548"></path><path d="M163.328 632.1152c-73.3184 0-133.3248-59.904-133.3248-133.3248S90.0096 365.568 163.328 365.568s133.3248 59.904 133.3248 133.3248-60.0064 133.2224-133.3248 133.2224z m0-260.3008c-69.7344 0-127.0784 56.832-127.0784 127.0784 0 69.7344 56.832 127.0784 127.0784 127.0784s127.0784-56.832 127.0784-127.0784c0-69.7344-56.832-127.0784-127.0784-127.0784z m0 0" fill="#A2ADC2" p-id="7549"></path><path d="M173.6704 572.2112c-2.56 2.56-6.2464 4.608-9.8304 4.608s-7.2704-1.536-9.8304-4.096-4.096-6.7584-4.096-10.3424 1.536-7.7824 4.096-10.3424 6.2464-4.608 9.8304-4.608 7.2704 1.536 9.8304 4.096 4.096 6.7584 4.096 10.3424-1.536 7.7824-4.096 10.3424z m5.2224-116.736l-6.2464 71.7824c0 5.7344-4.608 9.8304-9.8304 9.8304-5.12 0-9.8304-4.096-10.3424-9.8304l-9.3184-71.7824c-0.512-1.536-0.512-2.56-0.512-4.096 0-10.3424 7.7824-19.1488 18.1248-19.1488s18.6368 8.2944 18.6368 18.6368c0 2.048-0.512 3.584-0.512 4.608z m0 0M643.7888 601.1904c-2.56 0-4.608 2.048-4.608 4.096v32.5632c0 2.56 2.048 4.096 4.608 4.096s4.608-2.048 4.608-4.096v-32.5632c0-2.048-2.048-4.096-4.608-4.096z m19.0464 0c-2.56 0-4.608 2.048-4.608 4.096v32.5632c0 2.56 2.048 4.096 4.608 4.096s4.608-2.048 4.608-4.096v-32.5632c0.1024-2.048-1.9456-4.096-4.608-4.096z m21.1968 0c-2.56 0-4.608 2.048-4.608 4.096v32.5632c0 2.56 2.048 4.096 4.608 4.096s4.608-2.048 4.608-4.096v-32.5632c0.1024-2.048-2.048-4.096-4.608-4.096z m0 0" fill="#A2ADC2" p-id="7550"></path></svg>
          `
          }),
          retry
        ]
      });
      return error;
    },
    setCouponsHtml: function(root, modal) {
      const { outerDIV, shadowRoot } = root;
      const modalBody = modal.querySelector("div[name='modalBody']");
      const self = this;
      const generateRequest = this.generateRequest(modalBody);
      const generateRequestLoadding = this.generateRequestLoadding();
      const generateRequestLoaddingError = this.generateRequestLoaddingError(() => {
        generateRequest.remove();
        this.setCouponsHtml(root, modal);
      });
      generateRequest.append(generateRequestLoadding);
      RequestUnionUtil.getDetectCouponResult().then((dataJson) => {
        if (!dataJson) {
          generateRequestLoadding.remove();
          generateRequest.append(generateRequestLoaddingError);
          return;
        }
        generateRequest.remove();
        const { data, structure } = dataJson;
        if (structure.hasOwnProperty("css") && structure.hasOwnProperty("html")) {
          const { css, html } = structure;
          InspectUtil.addStyle(this._root.shadowRoot, "coupon-list", css);
          modalBody.innerHTML = html;
          [".discount-base", ".cgg-store-item", ".showmore-btn", "*[name='cgg02xClickToActivate']"].flatMap((selector) => Array.from(modalBody.querySelectorAll(selector))).forEach((button) => {
            const isActivateButton = button.matches("*[name='cgg02xClickToActivate']");
            InspectUtil.bindCustomEvent(button, (option) => {
              if (isActivateButton) {
                InspectUtil.addActivateCallbackEvent(outerDIV, option);
              }
            });
          });
          const tabs = modalBody.querySelectorAll("a[data-toggle='tab']");
          const tabPanes = modalBody.querySelectorAll(".tab-pane");
          tabs.forEach((element) => {
            element.addEventListener("click", function(e) {
              e.preventDefault();
              e.stopPropagation();
              tabs.forEach((tab) => tab.classList.remove("active"));
              e.target.classList.add("active");
              tabPanes.forEach((tab) => tab.classList.remove("fade-in", "active"));
              const toggle = modalBody.querySelector(e.target.getAttribute("data-href") || e.target.getAttribute("href"));
              toggle.classList.add("fade-in", "active");
            });
          });
          const items = modalBody.querySelectorAll(".cgg-store-item");
          items.forEach((item) => {
            item.addEventListener("mouseenter", (e) => {
              e.target.querySelector("span").classList.add("underline-show");
            });
            item.addEventListener("mouseleave", (e) => {
              e.target.querySelector("span").classList.remove("underline-show");
            });
          });
          const activateButton = modalBody.querySelector("*[name='activateButton']");
          self.addApplyCouponsEventListener(activateButton, modal);
        }
      }).catch((error) => {
        generateRequestLoadding.remove();
        generateRequest.append(generateRequestLoaddingError);
      });
    },
    showAllComponents: function() {
      const outerDIV = this._root?.outerDIV;
      if (outerDIV) {
        outerDIV.querySelector(".widget").style.display = "block";
      }
      GoodsHistory.show();
    },
    hideAllComponents: function() {
      const outerDIV = this._root?.outerDIV;
      if (outerDIV) {
        outerDIV.querySelector(".widget").style.display = "none";
      }
      GoodsHistory.hide();
    },
    generate: function(logoBase64, root, title, modalPosition, platform) {
      if (this._hasModal) {
        return;
      }
      const { outerDIV, shadowRoot } = root;
      this._root = root;
      this._logoBase64 = logoBase64;
      const contentHtml = `
      <div class="modal-header">
        <div class="logo">
          <img src="` + logoBase64 + `" />
        </div>
        <div class="title">` + title + `</div>
        <div class="btns">
          <div class="setting">` + settingSVG + `</div>
          <div class="setting-dropdown" id="settingsDropdown"></div>
          <div class="close">` + closeSVG + `</div>
        </div>
      </div>
      <div class="modal-body" name="modalBody">

      </div>
    `;
      let modelCss = Object.entries(modalPosition).map(([key, value]) => `${key.replace("_", "-")}:${value}`).join(";");
      const modal = ElementUtil.createElement("div", {
        className: "coupon-list-widget-conent",
        html: contentHtml,
        attributes: {
          "style": modelCss
        }
      });
      outerDIV.append(modal);
      this._hasModal = true;
      const close = modal.querySelector(".modal-header .btns> .close");
      this.addCloseEventListener(close, modal);
      this.addShowSettingEventListener(platform, modal);
      this.setCouponsHtml(root, modal);
      return modal;
    }
  };

  const InspectCouponsHTML = {
    root: null,
    models: {
      flyout: "flyout-model",
      detect: "detect-model"
    },
    getStyle: function() {
      const css = css_248z$3 + css_248z$5 + css_248z$4;
      return css.replace(/@logo@/g, logoBase64);
    },
    showFlyOut: function(root, flyout, platform, logoBase64) {
      const { outerDIV, shadowRoot } = root;
      if (!!flyout && !!flyout.html && !!flyout.css && !!flyout.conf) {
        const { html, css, conf } = flyout;
        InspectUtil.addStyle(shadowRoot, this.models.flyout, css);
        outerDIV.insertAdjacentHTML("beforeend", html);
        const cggfCloseFlyout = () => {
          const flyoutEl = outerDIV.querySelector("[name='" + flyout.conf.name + "']");
          if (flyoutEl) {
            flyoutEl.classList.add(flyout.conf.close_animation);
            flyoutEl.addEventListener("animationend", () => flyoutEl.remove(), { once: true });
          }
        };
        if (flyout.conf.delay > 0) {
          setTimeout(cggfCloseFlyout, flyout.conf.delay);
        }
        const closeButton = outerDIV.querySelector(flyout.conf.close_button);
        if (closeButton) {
          closeButton.addEventListener("click", cggfCloseFlyout);
        }
        InspectUtil.bindCustomEvent(outerDIV.querySelector("*[name='cgg02xClickToActivate']"), (option) => {
          if (!option) {
            return;
          }
          if (option.hasOwnProperty("dismissAfter") && option.dismissAfter) {
            cggfCloseFlyout();
          }
          if (option.hasOwnProperty("callbackEvent")) {
            InspectUtil.addActivateCallbackEvent(outerDIV, option);
          }
        });
        InspectUtil.bindApplyCouponsEvent(outerDIV.querySelector("*[name='applyCouponButton']"), (dataJson) => {
          const { codes, check, open } = dataJson;
          Promise.resolve().then(() => {
            ProgressModal.generate(
              logoBase64,
              root,
              platform,
              codes,
              check
            );
          });
          Promise.resolve().then(() => {
            if (!!open) {
              try {
                InspectUtil.openUrl(open);
              } catch (e) {
              }
            }
          });
        });
      }
    },
    start: async function() {
      const support = SupportData.support;
      const platform = support.p;
      const windowShow = await FeatureControl.isEnabled(StorageKeys.featureControl.windowShow + "_" + platform);
      let infoJson = null;
      try {
        infoJson = await RequestUnionUtil.getDetectInfoResult();
      } catch (e) {
      }
      if (!infoJson)
        return;
      const couponTotal = infoJson["coupon_total"];
      const modalPosition = infoJson["modal"];
      const historyShow = infoJson["history_show"];
      const iconJson = infoJson["icon"];
      const badgeData = iconJson["badge"];
      const dragData = iconJson["drag"];
      const interfaceData = iconJson["interface"];
      const cggJson = infoJson["cgg"];
      const autoOpen = cggJson["auto_open"];
      const modalTitle = cggJson["current_platform"];
      const logoBase64$1 = !!cggJson["logo"] ? cggJson["logo"] : logoBase64;
      const moveToEnd = cggJson["move_to_end"];
      const observerTime = cggJson["observer_time"] ?? 20 * 1e3;
      const flyout = infoJson["flyout"];
      if (historyShow) {
        GoodsHistory.start(support);
        if (!windowShow) {
          GoodsHistory.hide();
        }
      }
      if (!infoJson["show"]) {
        return;
      }
      const selectedLanguage = LangueUtil.getSelectedLanguage();
      const style = this.getStyle();
      const root = InspectUtil.generateShadowDomRoot(
        platform + "-" + this.models.detect,
        style,
        selectedLanguage.dir,
        moveToEnd,
        observerTime
      );
      const { outerDIV } = root;
      this.root = root;
      outerDIV.setAttribute("data-re-mark-tag", platform);
      const { widget, logo } = Activate.generate(couponTotal, badgeData, dragData, interfaceData, platform);
      outerDIV.append(widget);
      if (windowShow) {
        if (autoOpen) {
          CouponListModal.generate(logoBase64$1, root, modalTitle, modalPosition, platform);
        }
      } else {
        widget.style.display = "none";
      }
      logo.addEventListener("click", (e) => {
        CouponListModal.generate(logoBase64$1, root, modalTitle, modalPosition, platform);
      });
      setTimeout(() => {
        this.showFlyOut(root, flyout, platform, logoBase64$1);
        outerDIV.setAttribute("status", "complete");
      }, 100);
    }
  };

  const SearchEnginScreen = {
    blockAttributeKey: "jscan-slo-u8",
    uniqueMarkAttributeKey: "jvtxi-uid-t8",
    loopIsComplete: true,
    UUIDGenerator: function() {
      let counter = 0;
      const seed = Math.floor(Math.random() * 1e6).toString(36);
      return function getUUID() {
        const prefix = Date.now().toString(36);
        return `${seed}${prefix}${(counter++).toString(36)}`;
      };
    }(),
    getLinkByElement: function(element, findTag) {
      let searchElement = null;
      if (findTag == "this") {
        searchElement = element;
      } else if (/^child@/.test(findTag)) {
        searchElement = element.querySelector(findTag.replace(/^child@/, ""));
      }
      return searchElement;
    },
    pickupSelectors: function(confJson, platform) {
      const list = new Array();
      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.replace(/\\\\/g, "\\"), "i").test(window.location.href)).some((res) => res);
        if (isMatch) {
          for (let j = 0; j < elements.length; j++) {
            list.push({
              "selector": elements[j]["element"],
              "findA": elements[j]["findA"]
            });
          }
        }
      }
      return list;
    },
    queryElements: async function(selectors, platform) {
      const items = [];
      try {
        selectors.forEach((selectorObj) => {
          if (selectorObj.selector) {
            const elements = document.querySelectorAll(selectorObj.selector + ":not([" + this.blockAttributeKey + "='true'])");
            Logger.log("info", "search items======>", elements);
            const findA = selectorObj.findA;
            elements.forEach((element) => {
              if (element && !element.getAttribute(this.blockAttributeKey) && !element.querySelector("[" + this.blockAttributeKey + "]")) {
                const linkElement = this.getLinkByElement(element, findA);
                const handler = this.UUIDGenerator();
                element.setAttribute(this.uniqueMarkAttributeKey, handler);
                element.setAttribute(this.blockAttributeKey, "true");
                if (linkElement) {
                  let link = linkElement.getAttribute("href") || linkElement.textContent;
                  if (link) {
                    link = link.replace(/\s+/g, "");
                  }
                  if (link && link.indexOf("http") != -1) {
                    items.push({
                      "handler": handler,
                      "link": link,
                      "platform": platform,
                      "element": element
                    });
                  }
                }
              }
            });
          }
        });
        if (items.length > 0) {
          await this.search(items, platform);
        }
      } catch (e) {
      }
    },
    search: async function(items, platform) {
      const lists = [];
      items.forEach((item) => {
        lists.push({ "handler": item.handler, "url": item.link });
      });
      const dataJson = await RequestUnionUtil.getEngineScreenResult(lists, platform);
      if (dataJson && dataJson.list) {
        const { list } = dataJson;
        this.createHtml(items, list, platform);
      }
    },
    createHtml: function(items, list, platform) {
      for (let i = 0; i < list.length; i++) {
        const { handler, content } = list[i];
        const item = items.find((obj) => obj.handler === handler);
        if (!item) {
          continue;
        }
        if (item.hasOwnProperty("handler") && item.hasOwnProperty("element")) {
          item.handler;
          let element = item.element;
          if (content) {
            element.insertAdjacentHTML("afterbegin", content);
          }
        }
      }
      document.querySelectorAll("*[name='se-rebate-343234xy-funx']").forEach((element) => {
        InspectUtil.bindCustomEvent(element);
      });
    },
    start: async function(platform) {
      const confDataJson = await RequestUnionUtil.getEngineScreenConf();
      if (!confDataJson) {
        return;
      }
      const confJson = confDataJson[platform];
      const runSearch = () => {
        if (this.loopIsComplete) {
          this.loopIsComplete = false;
          const selectors = this.pickupSelectors(confJson, platform);
          this.queryElements(selectors, platform).then(() => {
            this.loopIsComplete = true;
          });
        }
      };
      runSearch();
      setInterval(() => {
        runSearch();
      }, 1500);
    }
  };

  const MidListener = {
    start: function() {
      if ((window.location.host !== "www.jtmate.com" || window.location.href.indexOf("www.jtmate.com/mid/merge") == -1) && !ScriptConst.isDev) {
        return;
      }
      const autoRedirect = document.querySelector(".auto-redirect");
      if (autoRedirect) {
        const dataContent = autoRedirect.getAttribute("data-content");
        if (dataContent) {
          const json = JSON.parse(dataContent);
          InspectUtil.customOpenUrl(null, json);
        }
      }
    }
  };

  const GoodsRecord = {
    start: function() {
      const href = window.location.href;
      const support = SupportData.support;
      if (support.record.disabled) {
        return;
      }
      const { title, price, cover } = support.record.elements;
      if (!support.detail.test(href)) {
        return;
      }
      const id = Tools.getGoodsIdByLink(href);
      if (title && price && cover) {
        Promise.all([
          Tools.waitForElementByInterval(cover, document.body, true),
          Tools.waitForElementByInterval(price, document.body, false, 10, 5e3)
        ]).then((elements) => {
          const coverElement = elements[0];
          const priceElement = elements[1];
          const titleElement = document.querySelector(title);
          if (coverElement) {
            var imgSrc = "";
            if (coverElement.tagName == "IMG") {
              imgSrc = coverElement.getAttribute("data-src") || coverElement.getAttribute("data-url") || coverElement.getAttribute("src");
            } else if (coverElement.tagName == "SOURCE") {
              imgSrc = coverElement.getAttribute("srcSet") || coverElement.getAttribute("src");
            }
            const price2 = priceElement ? priceElement.innerText : "Unknown";
            const title2 = titleElement ? titleElement.innerText : "--";
            const goods = { "id": id, "url": href, "pic": imgSrc, "date": new Date().getTime(), "price": price2, "title": title2 };
            GoodsHistory.push(support.p, goods);
          }
        }).catch(() => {
        });
      }
    }
  };

  const supportModules = {
    InspectCouponsHTML,
    SearchEnginScreen,
    MidListener,
    GoodsRecord
  };
  const AllModules = {
    ...PlatformModules,
    ...supportModules
  };

  const SupportsHelper = {
    defaultSupportsString: `
    {
      "jtmMid":{
          "p":"jtmMid",
          "match": "www\\\\.jtmate\\\\.com\\\\/mid",
          "record":{
              "disabled":true
          },
          "disabled":false
      },
      "aliexpress": {
          "p": "aliexpress",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?aliexpress\\\\.[a-z]{2,}(\\\\.[a-z]{2,})*(\\\\/.*)?",
          "detail": "\\\\/item\\\\/[^.\\\\/]+\\\\.html",
          "trade": ["\\\\/trade\\\\/confirm\\\\.html", "\\\\/checkout\\\\?"],
          "record":{
              "elements":{
                  "title":"h1[data-pl='product-title'], h1[class*='HazeProductDescription_HazeProductDescription__smallText_']",
                  "price":"span.product-price-value, div[class*='currentPriceText'], div[class*='HazeProductPrice_SnowPrice__container']>div",
                  "cover":"div[class*='slider--img'] >img, div[class*='__previewItem__'] picture[class*='Picture__container']>source"
              },
              "disabled":false
          },
          "disabled":false
      },
      "lazada":{
          "p": "lazada",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?lazada\\\\.[\\\\w.-]+([/?#].*)?$",
          "detail": "\\\\/products\\\\/.*-i\\\\d+.*\\\\.html",
          "trade":[],
          "record":{
              "elements":{
          "title":"h1[class*='pdp-mod-product-badge-title']",
                  "price":"div[class*='product-current-price-container'],div[class*='product-price-content-salePrice'],.pdp-product-price",
                  "cover":"div[class*='gallery-preview-panel'] >img:last-child, .gallery-preview-panel__content >img:last-child"
              },
              "disabled":false
          },
          "disabled":false
      },
      "banggood":{
          "p": "banggood",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?banggood\\\\.[\\\\w.-]+([/?#].*)?$",
          "detail":"\\\\/.*-p-\\\\d+\\\\.html",
          "trade":[],
          "record":{
              "elements":{
                  "title":".product-title-text",
                  "price":".newbie-price",
                  "cover":"a.p-img >img"
              },
              "disabled":false
          },
          "disabled":false
      },
      "ebay": {
          "p": "ebay",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?ebay\\\\.[\\\\w.-]+([/?#].*)?$",
          "detail":"\\\\/itm\\\\/\\\\d+",
          "trade":[],
          "record":{
              "elements":{
                  "title":".x-item-title__mainTitle",
                  "price":".x-price-primary >span",
                  "cover":".ux-image-grid-item >img, .ux-image-carousel-item >img"
              },
              "disabled":false
          },
          "disabled":false
      },
      "bestbuy": {
          "p": "bestbuy",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?bestbuy\\\\.[\\\\w.-]+([/?#].*)?$",
          "detail":"\\\\/site\\\\/.*\\\\/\\\\d+\\\\.p",
          "trade":[],
          "record":{
              "elements":{
                  "title":".sm:text-title-sm",
                  "price":"*[class*='_price_']",
                  "cover":"*[class*='displayingImage'] img"
              },
              "disabled":true
          },
          "disabled":false
      },
      "shopee": {
          "p": "shopee",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?shopee\\\\.[\\\\w.-]+([/?#].*)?$",
          "record":{
              "disabled":true
          },
          "disabled":false
      },
      "wish": {
          "p": "wish",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?wish\\\\.[\\\\w.-]+([/?#].*)?$",
          "record":{
              "disabled":true
          },
          "disabled":false
      },
      "amazon": {
          "p": "amazon",
          "match": "^https:\\\\/\\\\/([\\\\w-]+\\\\.)?amazon\\\\.[\\\\w.-]+([/?#].*)?$",
          "record":{
              "disabled":true
          },
          "disabled":false
      }
    }
  `,
    getSupportsByServer: async function() {
      const { method, url } = getRequestUrl()["supports"];
      const finalUrl = url + "&v=" + ScriptConst.version + "&no=" + ScriptConst.number + "&url=" + encodeURIComponent(window.location.href);
      const loadConfSupportCache = StorageKeys.api.loadConfSupportCache;
      let supportsString = await RequestUnionUtil.requestConfCached(method, finalUrl, loadConfSupportCache.key, loadConfSupportCache.time);
      if (supportsString) {
        supportsString = supportsString.replace(/\\\\/g, "\\");
      }
      return supportsString;
    },
    analysisSupports: async function() {
      let supportsString = await this.getSupportsByServer();
      if (!supportsString) {
        supportsString = this.defaultSupportsString;
      }
      let supportsJson = null;
      try {
        supportsJson = JSON.parse(supportsString);
      } catch (e) {
        supportsJson = JSON.parse(this.defaultSupportsString);
      }
      return supportsJson;
    },
    getSupport: async function() {
      const currentUrl = window.location.href;
      const supports = await this.analysisSupports();
      let support = null;
      for (let key in supports) {
        const { match, disabled } = supports[key];
        const matchReg = new RegExp(match);
        if (matchReg.test(currentUrl) && !disabled) {
          support = supports[key];
          support.match = matchReg;
          if (support.detail) {
            support.detail = new RegExp(support.detail);
          }
          if (support.trade) {
            support.trade = support.trade.map((pattern) => new RegExp(pattern));
          }
          break;
        }
      }
      return { support, supports };
    }
  };

  const Init = {
    aliexpress: function() {
      AllModules.Aliexpress.Aliexpress.start();
      AllModules.Aliexpress.AliexpressSearch.start();
    },
    ebay: function(support) {
      AllModules.Ebay.Ebay.start();
      AllModules.Ebay.EbaySearch.start();
    },
    lazada: function() {
      AllModules.Lazada.Lazada.start();
      AllModules.Lazada.LazadaSearch.start();
    },
    bestbuy: function() {
      AllModules.Bestbuy.Bestbuy.start();
      AllModules.Bestbuy.BestbuySearch.start();
    },
    banggood: function() {
      AllModules.Banggood.Banggood.start();
      AllModules.Banggood.BanggoodSearch.start();
    },
    amazon: function() {
      AllModules.Amazon.Amazon.start();
    },
    unknown: function() {
    },
    start: async function() {
      const { support, supports } = await SupportsHelper.getSupport();
      SupportData.supports = supports;
      SupportData.support = support;
      if (!support) {
        return;
      }
      const disabled = support.disabled, platform = support.p;
      if (disabled) {
        return;
      }
      await RequestUnionUtil.initRequestData();
      await LangueUtil.initLangueDataMap();
      await Tools.getDocumentBody();
      if (platform === "bing" || platform === "google") {
        AllModules.SearchEnginScreen.start(platform);
      } else {
        StyleUtil.init();
        try {
          if (typeof this[platform] === "function") {
            this[platform]();
          } else {
          }
        } catch (e) {
        }
        AllModules.InspectCouponsHTML.start();
        AllModules.MidListener.start();
        AllModules.GoodsRecord.start();
      }
    }
  };
  Init.start();

}());