สคริปต์นี้ช่วยปรับปรุง Twitter (X) และ TikTok โดยการปรับปรุงฟีเจอร์ต่าง ๆ เช่น รูปแบบวันที่ การดาวน์โหลดภาพและวิดีโอ และอื่น ๆ สำหรับ Twitter (X) และการดาวน์โหลดวิดีโอสำหรับ TikTok จะได้รับการบำรุงรักษาและอัปเดตอย่างต่อเนื่อง ดังนั้นคุณสามารถใช้งานได้อย่างมั่นใจ
// ==UserScript== // @name Twitter(X), Tiktok feature improvements // @name:ar تحسينات ميزات تويتر (إكس)، تيك توك // @name:bg Подобрения на функциите на Twitter (X), Tiktok // @name:ckb پیشەسازی تایبەتمەندیەکانەوەی تویتەر (X)، تیكتۆك // @name:cs Vylepšení funkcí Twitter (X), Tiktok // @name:da Forbedringer af funktioner på Twitter (X), Tiktok // @name:de Verbesserungen der Funktionen von Twitter (X), Tiktok // @name:el Βελτιώσεις λειτουργιών του Twitter (X), Tiktok // @name:en Twitter(X), Tiktok feature improvements // @name:eo Plibonigoj de funkcioj de Twitter (X), Tiktok // @name:es Mejoras en las funciones de Twitter (X), Tiktok // @name:es-419 Mejoras en las funciones de Twitter (X), Tiktok // @name:fi Twitterin (X) ja TikTokin ominaisuuspäivitykset // @name:fr Améliorations des fonctionnalités de Twitter (X), Tiktok // @name:fr-CA Améliorations des fonctionnalités de Twitter (X), Tiktok // @name:he שיפורים בתכונות של טוויטר (X), טיק טוק // @name:hr Poboljšanja značajki Twittera (X), Tiktok // @name:hu A Twitter (X), Tiktok funkcióinak fejlesztései // @name:id Peningkatan fitur Twitter (X), Tiktok // @name:it Miglioramenti delle funzionalità di Twitter (X), Tiktok // @name:ja Twitter(X)、Tiktokの機能改善 // @name:ka Twitter(X), Tiktok ფუნქციის გაუმჯობესებები // @name:ko Twitter(X), Tiktok 기능 개선 // @name:nb Forbedringer av funksjoner på Twitter (X), Tiktok // @name:nl Verbeteringen van de functies van Twitter (X), Tiktok // @name:pl Ulepszenia funkcji Twittera (X), Tiktok // @name:pt-BR Melhorias nas funcionalidades do Twitter (X), Tiktok // @name:ro Îmbunătățiri ale funcțiilor Twitter (X), Tiktok // @name:ru Улучшения функций Twitter (X), Tiktok // @name:sk Vylepšenia funkcií Twitter (X), Tiktok // @name:sr Poboljšanja funkcija Twitter (X), Tiktok // @name:sv Förbättringar av funktioner på Twitter (X), Tiktok // @name:th การปรับปรุงฟีเจอร์ Twitter (X), Tiktok // @name:tr Twitter (X), Tiktok özellik iyileştirmeleri // @name:uk Поліпшення функцій Twitter (X), Tiktok // @name:ug Twitter (X), Tiktok ئورۇنلارنىڭ يۇقىرى سۈپەت ئۆزگىرىشى // @name:vi Cải tiến tính năng Twitter (X), Tiktok // @description The script enhances Twitter (X) and TikTok by improving features such as date format, image and video downloads, and more for Twitter (X), and video downloads for TikTok. It will be continuously maintained and updated, so you can use it with confidence. // @description:ar يعمل السكربت على تحسين تويتر (X) وتيك توك عن طريق تحسين ميزات مثل تنسيق التاريخ، تحميل الصور والفيديوهات، والمزيد لتويتر (X)، وتحميل الفيديوهات لتيك توك. سيتم صيانته وتحديثه باستمرار، حتى تتمكن من استخدامه بثقة. // @description:bg Скриптът подобрява Twitter (X) и TikTok чрез подобряване на функции като формат на дата, изтегляне на изображения и видеоклипове и други за Twitter (X) и изтегляне на видеоклипове за TikTok. Той ще се поддържа и обновява непрекъснато, така че можете да го използвате с увереност. // @description:ckb اسکریپتەکە تەنها تایبەتمەندیەکانەی تیوتر (X) و تیکتۆکەکان پەسەند دەکات وەکوو فۆرماتی ڕووداو، داگرتنی وێنە و ڤیدیۆ و زۆرتر بۆ تیوتر (X) و داگرتنی ڤیدیۆ بۆ تیکتۆک. ئەم پڕۆگرامە بە شێوەیەکی پەیوەندیدار و نوێ دەبێت، بۆیە دەتوانیت بە بەرەوپێش کارەکە بە بەرەوپێش بەکاربەریت. // @description:cs Skript zlepšuje Twitter (X) a TikTok vylepšením funkcí jako je formát data, stahování obrázků a videí a další pro Twitter (X), a stahování videí pro TikTok. Bude neustále udržováno a aktualizováno, takže ho můžete používat s důvěrou. // @description:da Scriptet forbedrer Twitter (X) og TikTok ved at forbedre funktioner som datoformat, billede- og video-downloads og mere for Twitter (X), samt video-downloads for TikTok. Det vil løbende blive vedligeholdt og opdateret, så du kan bruge det med tillid. // @description:de Das Skript verbessert Twitter (X) und TikTok, indem es Funktionen wie das Datumsformat, das Herunterladen von Bildern und Videos und mehr für Twitter (X) sowie das Herunterladen von Videos für TikTok verbessert. Es wird kontinuierlich gewartet und aktualisiert, damit Sie es mit Vertrauen verwenden können. // @description:el Το σενάριο βελτιώνει το Twitter (X) και το TikTok, βελτιώνοντας δυνατότητες όπως η μορφή ημερομηνίας, η λήψη εικόνας και βίντεο και άλλα για το Twitter (X) και η λήψη βίντεο για το TikTok. Θα συντηρείται και θα ενημερώνεται συνεχώς, ώστε να το χρησιμοποιείτε με εμπιστοσύνη. // @description:en The script enhances Twitter (X) and TikTok by improving features such as date format, image and video downloads, and more for Twitter (X), and video downloads for TikTok. It will be continuously maintained and updated, so you can use it with confidence. // @description:eo La skripto plibonigas Twitter (X) kaj TikTok per plibonigo de funkcioj kiel dato-formato, bildaj kaj videodownloads, kaj pli por Twitter (X), kaj videodownloads por TikTok. Ĝi estos konstante subtenata kaj ĝisdatigita, tiel ke vi povas uzi ĝin kun konfido. // @description:es El script mejora Twitter (X) y TikTok al mejorar características como el formato de fecha, descargas de imágenes y videos, y más para Twitter (X), y descargas de videos para TikTok. Será mantenido y actualizado de manera continua, por lo que puedes usarlo con confianza. // @description:es-419 El script mejora Twitter (X) y TikTok mejorando características como el formato de fecha, descargas de imágenes y videos, y más para Twitter (X), y descargas de videos para TikTok. Se mantendrá y actualizará continuamente, por lo que puedes usarlo con confianza. // @description:fi Skripti parantaa Twitter (X):ää ja TikTokia parantamalla ominaisuuksia, kuten päivämäärämuotoa, kuvien ja videoiden latauksia ja enemmän Twitter (X):lle sekä videoiden latausta TikTokille. Sitä ylläpidetään ja päivitetään jatkuvasti, joten voit käyttää sitä luottavaisin mielin. // @description:fr Le script améliore Twitter (X) et TikTok en améliorant des fonctionnalités telles que le format de la date, le téléchargement d'images et de vidéos, et plus encore pour Twitter (X), et le téléchargement de vidéos pour TikTok. Il sera continuellement maintenu et mis à jour, vous pouvez donc l'utiliser en toute confiance. // @description:fr-CA Le script améliore Twitter (X) et TikTok en améliorant des fonctionnalités telles que le format de la date, les téléchargements d'images et de vidéos, et plus encore pour Twitter (X), ainsi que les téléchargements de vidéos pour TikTok. Il sera maintenu et mis à jour en continu, afin que vous puissiez l'utiliser en toute confiance. // @description:he הסקריפט משדרג את טוויטר (X) ואת טיקטוק על ידי שיפור תכונות כמו פורמט תאריך, הורדת תמונות ווידאו, ועוד עבור טוויטר (X), והורדות וידאו עבור טיקטוק. הוא יתוחזק ויתעדכן באופן רציף, כך שתוכל להשתמש בו בביטחון. // @description:hr Skript poboljšava Twitter (X) i TikTok poboljšanjem funkcija kao što su format datuma, preuzimanje slika i videa i drugo za Twitter (X) te preuzimanje videa za TikTok. Bit će kontinuirano održavan i ažuriran, tako da ga možete koristiti s povjerenjem. // @description:hu A script javítja a Twitter (X) és TikTok szolgáltatásokat olyan funkciók javításával, mint a dátumformátum, képek és videók letöltése, és még sok más a Twitter (X) számára, valamint videók letöltése a TikTok számára. Folyamatosan karbantartva és frissítve lesz, így bizalommal használhatod. // @description:id Skrip ini meningkatkan Twitter (X) dan TikTok dengan memperbaiki fitur seperti format tanggal, unduhan gambar dan video, dan lebih banyak lagi untuk Twitter (X), serta unduhan video untuk TikTok. Skrip ini akan terus dipelihara dan diperbarui, sehingga Anda dapat menggunakannya dengan percaya diri. // @description:it Lo script migliora Twitter (X) e TikTok migliorando funzionalità come il formato della data, il download di immagini e video e altro per Twitter (X), e il download di video per TikTok. Sarà continuamente mantenuto e aggiornato, quindi puoi usarlo con fiducia. // @description:ja このスクリプトは、Twitter (X) と TikTok の機能を改善し、Twitter (X) では日付形式、画像や動画のダウンロード、その他の機能を改善し、TikTok では動画のダウンロード機能を向上させます。継続的にメンテナンスされ、更新されるため、安心して使用できます。 // @description:ka სკრიპტი აუმჯობესებს Twitter (X) და TikTok-ს, აძლიერებს ისეთ მახასიათებლებს, როგორიცაა თარიღის ფორმატი, სურათების და ვიდეოების ჩამოტვირთვა და სხვა Twitter (X)-სთვის, ხოლო TikTok-სთვის ვიდეოების ჩამოტვირთვა. ის მუდმივად განახლდება და განახლდება, ასე რომ შეგიძლიათ გამოიყენოთ იგი ნდობით. // @description:ko 이 스크립트는 Twitter (X)와 TikTok을 향상시켜 날짜 형식, 이미지 및 비디오 다운로드 기능 등을 개선하고, TikTok에 대한 비디오 다운로드도 지원합니다. 지속적으로 유지 관리되고 업데이트되므로 안심하고 사용할 수 있습니다. // @description:nb Skriptet forbedrer Twitter (X) og TikTok ved å forbedre funksjoner som datoformat, nedlasting av bilder og videoer og mer for Twitter (X), samt videonedlastinger for TikTok. Det vil kontinuerlig vedlikeholdes og oppdateres, slik at du kan bruke det med tillit. // @description:nl Het script verbetert Twitter (X) en TikTok door functies zoals datumformaat, beeld- en video-downloads en meer voor Twitter (X) te verbeteren, en videodownloads voor TikTok. Het zal continu worden onderhouden en bijgewerkt, zodat je het met vertrouwen kunt gebruiken. // @description:pl Skrypt ulepsza Twitter (X) i TikTok, poprawiając funkcje takie jak format daty, pobieranie obrazów i wideo i inne dla Twitter (X) oraz pobieranie wideo dla TikTok. Będzie ciągle utrzymywany i aktualizowany, dzięki czemu możesz go używać z pewnością. // @description:pt-BR O script aprimora o Twitter (X) e o TikTok melhorando recursos como o formato de data, downloads de imagens e vídeos e mais para o Twitter (X), e downloads de vídeos para o TikTok. Ele será mantido e atualizado continuamente, para que você possa usá-lo com confiança. // @description:ro Scriptul îmbunătățește Twitter (X) și TikTok prin îmbunătățirea funcțiilor precum formatul datei, descărcarea imaginilor și videoclipurilor și altele pentru Twitter (X) și descărcarea videoclipurilor pentru TikTok. Va fi menținut și actualizat continuu, astfel încât să-l puteți utiliza cu încredere. // @description:ru Скрипт улучшает Twitter (X) и TikTok, улучшая такие функции, как формат даты, загрузка изображений и видео и многое другое для Twitter (X), а также загрузку видео для TikTok. Он будет постоянно поддерживаться и обновляться, чтобы вы могли использовать его с уверенностью. // @description:sk Skript vylepšuje Twitter (X) a TikTok zlepšením funkcií, ako je formát dátumu, sťahovanie obrázkov a videí a ďalšie pre Twitter (X) a sťahovanie videí pre TikTok. Bude neustále udržiavaný a aktualizovaný, takže ho môžete používať s dôverou. // @description:sr Skript unapređuje Twitter (X) i TikTok poboljšanjem funkcija kao što su format datuma, preuzimanje slika i video klipova i drugih za Twitter (X) i preuzimanje video klipova za TikTok. Biće stalno održavan i ažuriran, tako da ga možete koristiti sa poverenjem. // @description:sv Skriptet förbättrar Twitter (X) och TikTok genom att förbättra funktioner som datumformat, bild- och videonedladdningar och mer för Twitter (X), samt videonedladdningar för TikTok. Det kommer kontinuerligt att underhållas och uppdateras, så att du kan använda det med förtroende. // @description:th สคริปต์นี้ช่วยปรับปรุง Twitter (X) และ TikTok โดยการปรับปรุงฟีเจอร์ต่าง ๆ เช่น รูปแบบวันที่ การดาวน์โหลดภาพและวิดีโอ และอื่น ๆ สำหรับ Twitter (X) และการดาวน์โหลดวิดีโอสำหรับ TikTok จะได้รับการบำรุงรักษาและอัปเดตอย่างต่อเนื่อง ดังนั้นคุณสามารถใช้งานได้อย่างมั่นใจ // @description:tr Bu script, Twitter (X) ve TikTok'u tarih formatı, resim ve video indirmeleri gibi özellikleri geliştirerek ve TikTok için video indirmelerini iyileştirerek geliştirir. Sürekli olarak bakım yapılacak ve güncellenmiş olacak, böylece güvenle kullanabilirsiniz. // @description:uk Скрипт покращує Twitter (X) та TikTok, вдосконалюючи функції, такі як формат дати, завантаження зображень та відео, а також інші для Twitter (X) та завантаження відео для TikTok. Він буде постійно підтримуватись і оновлюватись, тому ви можете використовувати його з упевненістю. // @description:ug بۇ سكىرپت تويتر (X) ۋە TikTokنىڭ مۇنەۋۋەرلىكتىكى خۇسۇسىيەتلەرنى يۇقىرى سەۋىيەگە كۆتۈرۈپ، تويتر (X) ئۈچۈن ۋاقىت تەرتىپى، رەسىم ۋە ۋىدېئو چۈشۈرۈش قاتارلىق خۇسۇسىيەتلەرنى ۋە TikTok ئۈچۈن ۋىدېئو چۈشۈرۈشنى يېڭىلايدۇ. بۇنىڭغا داۋاملىق تەسىر قىلىپ يېڭىلاندۇرۇلۇپ تۇرىدىغان بولىدۇ، شۇڭا ئۇنى ئىشلىتىشكە ئىشەنچىلىك بەلگىلىسىڭىز بولىدۇ. // @description:vi Script này cải thiện Twitter (X) và TikTok bằng cách cải thiện các tính năng như định dạng ngày, tải xuống hình ảnh và video, và nhiều hơn nữa cho Twitter (X), và tải xuống video cho TikTok. Nó sẽ được duy trì và cập nhật liên tục, vì vậy bạn có thể sử dụng nó với sự tự tin. // @namespace enochLiu_self_script // @version 1.0.1 // @author EnochLiu, PeterParker // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAl5JREFUaEPtWVtuAzEIdO7jO7Q5WZOTNYfwfVpZ8kZ+AAOGVRQpkfq1Xe8MzAC2L+nNf5c3x58+BF6dwWcGcs7fKaX6Z/09SikP60vc/+ecb9yzUsrybJBQe/nHCqaUEiJF8P0rFajlwznnPyuBlNKdio5lnaaAX+Yddn2KQJURt5CEaZvELvgKhkw9k8qq83vHoBKd5UamGWVCyDoMCqtdhsQAMOdcMzUY3+oHao1GuBaHKyIvmg8BZFIPo3aA8oJnJdR9gPLDAJDJFCQhVBxV5A+MsPxpAGrk1kthp1xyUoIE6otKEio/RIKHEpqiJgLU+MFTLl0Z6DwxNzm1H84Ab8qAQUp1Xpn7Q+0f3I###S+VUpUHFAacM7HIjQFhqjjUGmYCLRPQsIqZyg3eLKEpE7MfBkCg2oSA9xIgtd5PpQKJrZkpTEJdVdKQgHJD806oiefFNF2Y8IOr8vQYtkxMkNjxQwiJKAKnDX1IXiEEDE0u3A+RBLjmNW+CRLmhiM/PQwig04x+l6aZbC0k3AQQ+AZGPfRZwLsamaB7DgMkYd1Puwig8bixWKbSqVO7/bAlIQT+AKk4FICdHElqlwB3erc0J9SFvaY2E7AehWgAasaRqC0lV+vF8VhJYssP6gx4z3HO8oOKQNRRCOEHzSZIHPoggSjwhnmJqkzsBgidjUpH7VvjcLQfpNPpcPBoJ9dVmi/iuosMmERAXetRs6GeK04tqNcWEtwFx1a5tBAB3VxaavADdcV0OnggJRSHoXJRBMhrTu8lHodq83r3ebULyygKx6uffwh8MuCMwD9nR9JAVVitigAAAABJRU5ErkJggg== // @include https://x.com/* // @include https://twitter.com/* // @include https://mobile.x.com/* // @include https://www.tiktok.com/** // @exclude *://x.com/i/flow/* // @connect tikdownloader.io // @license MIT // @run-at document-idle // @antifeature referral-link // @noframes // @grant GM_registerMenuCommand // @grant GM_openInTab // @grant GM.openInTab // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_setClipboard // ==/UserScript== (function () { 'use strict'; /*! * Copyright (c) 2024 - 2025, EnochLiu, PeterParker. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ const ScriptConst = { "lang": (navigator.language || navigator.userLanguage).slice(0, 2).toLowerCase(), "isDev": false, "isDebug": true, "currentHost": window.location.host, "currentUrl": window.location.href }; const PlatformConst = { "aliexpress": "aliexpress", "amazon": "amazon", "shopee": "shopee", "lazada": "lazada", "ebay": "ebay", "bestbuy": "bestbuy", "banggood": "banggood", "wish": "wish", "airbaltic": "airbaltic", "edureka": "edureka", "ranavat": "ranavat", "alibaba": "alibaba", "ticketmaster": "ticketmaster", "wilson": "wilson", "wilsonsleather": "wilsonsleather", "pictarine": "pictarine", "suiteness": "suiteness", "trip": "trip", "treatwell": "treatwell", "samsung": "samsung", "x": "x", "youtube": "youtube", "tiktok": "tiktok", "cobalt": "cobalt", "temu": "temu", "walmart": "walmart", "wildberries": "wildberries", "zalando": "zalando", "noon": "noon", "daraz": "daraz", "ozon": "ozon", "allegro": "allegro", "rakuten": "rakuten", "shein": "shein" }; var __async$2 = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; const Logger = { log: function(level = "info", ...messages) { { if (level.toLowerCase() === "info") { console.info(...messages); } else if (level.toLowerCase() === "error") { console.error(...messages); } else { console.log(...messages); } } } }; const Tools = { decryptStr: function(str) { if (!str) return str; let r###lt = atob(str); return r###lt.split("").reverse().join(""); }, encryptStr: function(str) { if (!str) return str; let r###lt = str.split("").reverse().join(""); return btoa(r###lt); }, getEcommercePlatform: function() { let platform = null; const currentHost = window.location.host; if (/amazon\./.test(currentHost)) { platform = PlatformConst.amazon; } else if (/ebay\./.test(currentHost)) { platform = PlatformConst.ebay; } else if (/lazada\./.test(currentHost)) { platform = PlatformConst.lazada; } else if (/aliexpress./.test(currentHost)) { platform = PlatformConst.aliexpress; } else if (/bestbuy\./.test(currentHost)) { platform = PlatformConst.bestbuy; } else if (/banggood\./.test(currentHost)) { platform = PlatformConst.banggood; } else if (/wish\./.test(currentHost)) { platform = PlatformConst.wish; } else if (/airbaltic\./.test(currentHost)) { platform = PlatformConst.airbaltic; } else if (/edureka\./.test(currentHost)) { platform = PlatformConst.edureka; } else if (/ranavat\./.test(currentHost)) { platform = PlatformConst.ranavat; } else if (/alibaba\./.test(currentHost)) { platform = PlatformConst.alibaba; } else if (/ticketmaster\./.test(currentHost)) { platform = PlatformConst.ticketmaster; } else if (/wilson\./.test(currentHost)) { platform = PlatformConst.wilson; } else if (/wilsonsleather\./.test(currentHost)) { platform = PlatformConst.wilsonsleather; } else if (/pictarine\./.test(currentHost)) { platform = PlatformConst.pictarine; } else if (/suiteness\./.test(currentHost)) { platform = PlatformConst.suiteness; } else if (/trip\./.test(currentHost)) { platform = PlatformConst.trip; } else if (/treatwell\./.test(currentHost)) { platform = PlatformConst.treatwell; } else if (/samsung\./.test(currentHost)) { platform = PlatformConst.samsung; } else if (/temu\./.test(currentHost)) { platform = PlatformConst.temu; } else if (/walmart\./.test(currentHost)) { platform = PlatformConst.walmart; } else if (/shopee\./.test(currentHost)) { platform = PlatformConst.shopee; } else if (/wildberries\./.test(currentHost)) { platform = PlatformConst.wildberries; } else if (/zalando\./.test(currentHost)) { platform = PlatformConst.zalando; } else if (/noon\./.test(currentHost)) { platform = PlatformConst.noon; } else if (/daraz\./.test(currentHost)) { platform = PlatformConst.daraz; } else if (/ozon\./.test(currentHost)) { platform = PlatformConst.ozon; } else if (/allegro\./.test(currentHost)) { platform = PlatformConst.allegro; } else if (/rakuten\./.test(currentHost)) { platform = PlatformConst.rakuten; } else if (/shein\./.test(currentHost)) { platform = PlatformConst.shein; } return platform; }, getOtherPlatform: function() { let platform = null; const currentHost = window.location.host; if (/twitter|x\.com$/.test(currentHost)) { platform = PlatformConst.x; } else if (/youtube\.com$/.test(currentHost)) { platform = PlatformConst.youtube; } else if (/www\.tiktok\.com/.test(currentHost)) { platform = PlatformConst.tiktok; } else if (/cobalt\.tools/.test(currentHost)) { platform = PlatformConst.cobalt; } return platform; }, getAllMatchPlatform: function() { var _a; return (_a = this.getEcommercePlatform()) != null ? _a : this.getOtherPlatform(); }, removeAnchorsByNode: function(node) { const tagName = node.tagName; if (!tagName) return; const exist = ["A", "IMG", "DIV", "SPAN", "LABEL", "TABLE", "TR", "TD", "CANVAS"].some((name) => name === tagName); if (exist) { node.removeAttribute("data-spm-anchor-id"); for (let i = 0; i < node.childNodes.length; i++) { this.removeAnchorsByNode(node.childNodes[i]); } } }, removeAnchorsBySeletor: function() { document.querySelectorAll("*[data-re-mark-tag='aliexpress']").forEach((element) => { this.removeAnchorsByNode(element); }); }, openInTab: function(url, options = { "active": true, "insert": true, "setParent": true }) { if (typeof GM_openInTab === "function") { GM_openInTab(url, options); } else { GM.openInTab(url, options); } }, request: function(method, url, param, headers = { "Content-Type": "application/json;charset=UTF-8" }, timeout = 20 * 1e3) { if (!url) { return Promise.reject({ "code": "exception", "r###lt": 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", "r###lt": response.responseText }); } else { reject({ "code": "error", "r###lt": response.statusText }); } }, ontimeout: function(error) { reject({ "code": "error", "r###lt": error }); }, onerror: function(error) { reject({ "code": "error", "r###lt": error }); } }; if (config.method === "POST") { config.headers = headers != null ? headers : { "Content-Type": "application/json" }; if (JSON.stringify(config.headers).indexOf("application/json") != -1) { config.data = JSON.stringify(param); } else { config.data = param; } } else if (config.method === "GET") { config.headers = headers != null ? headers : { "Content-Type": "application/json" }; config.data = param; } GM_xmlhttpRequest(config); }); }, crossRequest: function(method = "GET", url, param = {}, headers = { "Content-Type": "application/json;charset=UTF-8" }, timeout = 20 * 1e3) { if (!url) { return Promise.reject({ "code": "exception", "r###lt": null }); } const config = { method: method.toUpperCase(), headers }; const controller = new AbortController(); const signal = controller.signal; config.signal = signal; if (config.method === "POST") { config.headers = headers != null ? headers : { "Content-Type": "application/json" }; config.body = JSON.stringify(param); } const timeoutId = setTimeout(() => controller.abort(), timeout); return fetch(url, config).then((response) => response.ok ? response.text() : Promise.reject(response.statusText)).then((r###lt) => { clearTimeout(timeoutId); return { "code": "success", "r###lt": r###lt }; }).catch((error) => { clearTimeout(timeoutId); if (error.name === "AbortError") { return { "code": "error", "r###lt": "Request timeout" }; } return { "code": "error", "r###lt": error }; }); }, getParamterBySuffix: function(url = window.location.href, suffix = "html") { if (url.indexOf("?") != -1) { url = url.split("?")[0]; } if (url.indexOf("#") != -1) { url = url.split("#")[0]; } let regex = new RegExp("\\/([^\\/]*?)\\." + suffix); if (/lazada/.test(url)) { regex = new RegExp("-i(\\d+)(?:-s(\\d+))?\\.html"); } else if (/www\.ebay/.test(url)) { regex = new RegExp("\\/itm\\/(\\d+)"); } const match = url.match(regex); return match ? match[1] : null; }, getParamterBySearch: function(paramsString = window.location.href, tag) { if (paramsString.indexOf("?") != -1) { paramsString = paramsString.split("?")[1]; } const params = new URLSearchParams(paramsString); return params.get(tag); }, waitForElementByInterval: function(selector, target = document.body, allowEmpty = true, delay = 10, maxDelay = 10 * 1e3) { return new Promise((resolve, reject) => { let totalDelay = 0; let element = target.querySelector(selector); let r###lt = allowEmpty ? !!element : !!element && !!element.innerHTML; if (r###lt) { resolve(element); } const elementInterval = setInterval(() => { if (totalDelay >= maxDelay) { clearInterval(elementInterval); resolve(null); } element = target.querySelector(selector); r###lt = allowEmpty ? !!element : !!element && !!element.innerHTML; if (r###lt) { clearInterval(elementInterval); resolve(element); } else { totalDelay += delay; } }, delay); }); }, randomNumber: function() { return Math.ceil(Math.random() * 1e8); }, elementInContainer: function(container, element) { return container.contains(element); }, mustGetElement: function(handler) { return __async$2(this, null, function* () { const getElements = (handler2) => __async$2(this, null, function* () { const promiseArray = []; const handlers = handler2.split("@"); for (let i = 0; i < handlers.length; i++) { const eleName = handlers[i]; if (!eleName) { continue; } if (eleName == "body") { promiseArray.push( new Promise((resolve, reject) => { resolve(document.body); }) ); } else if (eleName == "html") { promiseArray.push( new Promise((resolve, reject) => { resolve(document.html); }) ); } else { promiseArray.push(this.waitForElementByInterval(eleName, document.body, true, 10, 1500)); } } let element2 = yield Promise.race(promiseArray); return element2; }); let element = yield getElements(handler); return new Promise((resolve, reject) => { if (element) { resolve(element); return; } const waitInterval = setInterval(() => { element = getElements(handler); if (element) { clearInterval(waitInterval); resolve(element); return; } }, 2e3); }); }); }, loopTask: function(callback, delay = 1500) { callback(); setInterval(() => { callback(); }, delay); }, distinguishRemoveAndTry: function(distinguish, callback) { const distinguishElements = distinguish.map((name) => document.querySelector("*[name='" + name + "']")); const validateRs = distinguishElements.some((ele) => ele === null || ele === void 0); if (validateRs) { distinguishElements.reverse().forEach((element) => { if (element) { element.remove(); } }); callback(); } }, getDomain: function(url) { try { const hostname = new URL(url).hostname; const parts = hostname.split("."); if (parts.length > 2) { return `${parts[parts.length - 2]}.${parts[parts.length - 1]}`; } return hostname; } catch (error) { console.error("Invalid URL:", error); return null; } }, getCommonMarketplace: function(url = window.location.href) { try { const domainParts = new URL(url).hostname.split("."); const countryCode = domainParts[domainParts.length - 1]; return countryCode; } catch (error) { console.log(error); } return null; } }; const Toast = { show: function(params) { let time = params.time; let background = params.background; let color = params.color; let position = params.position; let defaultMarginValue = 50; if (time == void 0 || time == "") { time = 1500; } if (position == void 0 || position == "") { position = "center-bottom"; } const style = document.createElement("style"); style.textContent = `@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-o-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-ms-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-o-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@-ms-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.toast-style-kk998y{position:fixed;background:rgba(0,0,0,0.7);color:#fff;font-size:14px;line-height:1;padding:10px;border-radius:3px;left:50%;transform:translateX(-50%);-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-o-transform:translateX(-50%);-ms-transform:translateX(-50%);z-index:999999999999999999999999999;white-space:nowrap}.fadeOut{animation:fadeOut .5s}.fadeIn{animation:fadeIn .5s}`; const el = document.createElement("div"); if (background != void 0 && background != "") { el.style.backgroundColor = background; } if (color != void 0 && color != "") { el.style.color = color; } el.setAttribute("class", "toast-style-kk998y"); el.innerText = params.message; el.style.zIndex = 999999999; if (position === "center-bottom") { el.style.bottom = defaultMarginValue + "px"; } else { el.style.top = defaultMarginValue + "px"; } document.body.appendChild(el); document.head.appendChild(style); el.classList.add("fadeIn"); setTimeout(function() { el.classList.remove("fadeIn"); el.classList.add("fadeOut"); el.addEventListener("animationend", function() { document.body.removeChild(el); document.head.removeChild(style); }); el.addEventListener("webkitAnimationEnd", function() { document.body.removeChild(el); document.head.removeChild(style); }); }, time); } }; var _a; const language = { "zh": { "dateFormat": { "week": ["日", "一", "二", "三", "四", "五", "六"] }, "download": { "download": "下载", "completed": "下载完成", "tip": "点击下载视频", "preparing": "正在准备下载(如果失败,请手动操作)" }, "menuCommand": { "settings": "设置", "titleDateFormat": "时间格式设置:", "buttonClose": "关闭" } }, "en": { "dateFormat": { "week": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] }, "download": { "download": "Download", "completed": "Download Completed", "tip": "Click to download video", "preparing": "Preparing to download (if failed, please do it manually)" }, "menuCommand": { "settings": "Settings", "titleDateFormat": "Time format settings:", "buttonClose": "Close" } }, "ja": { "dateFormat": { "week": ["日", "月", "火", "水", "木", "金", "土"] }, "download": { "download": "ダウンロード", "completed": "ダウンロード完了", "tip": "クリックしてビデオをダウンロード", "preparing": "ダウンロードの準備中(失敗する場合は手動で行ってください)" }, "menuCommand": { "settings": "設定", "titleDateFormat": "時刻形式の設定:", "buttonClose": "閉鎖" } }, "fr": { "dateFormat": { "week": ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"] }, "download": { "download": "télécharger", "completed": "éléchargement terminé", "tip": "Cliquez pour télécharger la vidéo", "preparing": "Préparation du téléchargement (en cas d'échec, veuillez le faire manuellement)" }, "menuCommand": { "settings": "installation", "titleDateFormat": "Paramètres du format de l'heure :", "buttonClose": "fermeture" } }, "de": { "dateFormat": { "week": ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam"] }, "download": { "download": "herunterladen", "completed": "Download abgeschlossen", "tip": "Klicken Sie hier, um das Video herunterzuladen", "preparing": "Vorbereitung für den Download (falls der Download fehlschlägt, führen Sie ihn bitte manuell durch)" }, "menuCommand": { "settings": "aufstellen", "titleDateFormat": "Einstellungen für das Zeitformat:", "buttonClose": "Schließung" } }, "it": { "dateFormat": { "week": ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"] }, "download": { "download": "scaricamento", "completed": "Download completato", "tip": "Fare clic per scaricare il video", "preparing": "Preparazione per il download (se fallisce, eseguilo manualmente)" }, "menuCommand": { "settings": "impostare", "titleDateFormat": "Impostazioni del formato dell'ora:", "buttonClose": "chiusura" } }, "ko": { "dateFormat": { "week": ["일", "월", "화", "수", "목", "금", "토"] }, "download": { "download": "다운로드", "completed": "다운로드 완료", "tip": "비디오를 다운로드하려면 클릭하세요", "preparing": "다운로드 준비 중 (실패할 경우 수동으로 진행해주세요)" }, "menuCommand": { "settings": "설정", "titleDateFormat": "시간 형식 설정:", "buttonClose": "폐쇄" } }, "ru": { "dateFormat": { "week": ["ВС", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"] }, "download": { "download": "скачать", "completed": "Загрузка завершена", "tip": "Нажмите, чтобы скачать видео", "preparing": "Подготовка к загрузке (если не получается, сделайте это вручную)" }, "menuCommand": { "settings": "настраивать", "titleDateFormat": "Настройки формата времени:", "buttonClose": "закрытие" } }, "pt": { "dateFormat": { "week": ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"] }, "download": { "download": "descargar", "completed": "Descarga completa", "tip": "Clique para baixar o vídeo", "preparing": "Preparação para download (se falhar, faça-o manualmente)" }, "menuCommand": { "settings": "configuración", "titleDateFormat": "Configuración de formato de hora:", "buttonClose": "cierre" } }, "es": { "dateFormat": { "week": ["DOM", "LUN", "MAR", "MIER", "JUE", "VIE", "SÁB"] }, "download": { "download": "descargar", "completed": "Descarga completa", "tip": "Haga clic para descargar el vídeo", "preparing": "Preparándose para la descarga (si falla, hágalo manualmente)" }, "menuCommand": { "settings": "configuración", "titleDateFormat": "Configuración de formato de hora:", "buttonClose": "cierre" } }, "th": { "dateFormat": { "week": ["วันอาทิตย์", "วันจันทร์", "วันอังคาร", "วันพุธ", " วันพฤหัสบดี", "วันศุกร์ ", "วันเสาร์ "] }, "download": { "download": "ดาวน์โหลด", "completed": "ดาวน์โหลดเสร็จสมบูรณ์", "tip": "คลิกเพื่อดาวน์โหลดวิดีโอ", "preparing": "กำลังเตรียมการดาวน์โหลด (หากล้มเหลว กรุณาดำเนินการด้วยตนเอง)" }, "menuCommand": { "settings": "ตั้งค่า", "titleDateFormat": "การตั้งค่ารูปแบบเวลา:", "buttonClose": "ปิด" } }, "tr": { "dateFormat": { "week": ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"] }, "download": { "download": "indirmek", "completed": "İndirme tamamlandı", "tip": "Videoyu indirmek için tıklayın", "preparing": "İndirmeye hazırlanıyor (başarısız olursa lütfen manuel olarak yapın)" }, "menuCommand": { "settings": "kurmak", "titleDateFormat": "Saat formatı ayarları:", "buttonClose": "kapatma" } }, "nl": { "dateFormat": { "week": ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"] }, "download": { "download": "downloaden", "completed": "Downloaden voltooid", "tip": "Klik om video te downloaden", "preparing": "Voorbereiden voor downloaden (als dit mislukt, doe dit dan handmatig)" }, "menuCommand": { "settings": "opgezet", "titleDateFormat": "Instellingen tijdformaat:", "buttonClose": "sluiting" } } }; const Commonlanguage = (_a = language[ScriptConst["lang"]]) != null ? _a : language["en"]; var __async$1 = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; const FMT = 7; let fmt = GM_getValue("fmt", FMT); const XSettingsDialog = { number: Math.ceil(Math.random() * 1e8), formats: [ { "format": "Do nothing", "example": "N/A" }, { "format": "dd.MM.yy HH:mm", "example": "22.10.24 03:12" }, { "format": "dd.MM.yy HH:mm:ss", "example": "22.10.24 03:12:56" }, { "format": "dd.MM.yy(W) HH:mm", "example": "22.10.24(Mon) 03:12" }, { "format": "dd.MM.yy(W) HH:mm:ss", "example": "22.10.24(Mon) 03:12:56" }, { "format": "yy/MM/dd HH:mm", "example": "24/10/22 03:12" }, { "format": "yy/MM/dd HH:mm:ss", "example": "24/10/22 03:12:56" }, { "format": "yy/MM/dd(W) HH:mm", "example": "24/10/22(Mon) 03:12" }, { "format": "yy/MM/dd(W) HH:mm:ss [ye/mo/da(we) ho:mi:se]", "example": "24/10/22(Mon) 03:12:56 [ye/mo/da(we) ho:mi:se]" }, { "format": "yy-MM/dd HH:mm", "example": "24-10/22 03:12" }, { "format": "yy-MM/dd HH:mm'ss", "example": "24-10/22 03:12'56" }, { "format": "yy-MM/dd(W) HH:mm", "example": "24-10/22(Mon) 03:12" }, { "format": "yy-MM/dd(W) HH:mm'ss", "example": "24-10/22(Mon) 03:12'56" }, { "format": "MM/dd/yy HH:mm", "example": "10/22/24 03:12" }, { "format": "MM/dd/yy HH:mm:ss", "example": "10/22/24 03:12:56" }, { "format": "W, MM/dd/yy HH:mm", "example": "Mon, 10/22/24 03:12" }, { "format": "W, MM/dd/yy HH:mm:ss", "example": "Mon, 10/22/24 03:12:56" }, { "format": "M59-MM-dd HH:mm", "example": "M59-10-22 03:12" }, { "format": "M59-MM-dd HH:mm:ss", "example": "M59-10-22 03:12:56" }, { "format": "M59-MM-dd(W) HH:mm", "example": "M59-10-22(Mon) 03:12" }, { "format": "M59-MM-dd(W) HH:mm:ss", "example": "M59-10-22(Mon) 03:12:56" } ], make: function() { let dialog = document.createElement("div"); dialog.className = "dialog_u_" + this.number; dialog.style.all = "initial"; dialog.style.backgroundColor = "rgb(255, 255, 255)"; dialog.style.border = "1px solid #ccc"; dialog.style.borderRadius = "2px"; dialog.style.display = "none"; dialog.style.fontFamily = "monospace"; dialog.style.fontSize = "12px"; dialog.style.width = "480px"; dialog.style.paddingLeft = "5px"; dialog.style.paddingRight = "5px"; dialog.style.paddingTop = "5px"; dialog.style.paddingBottom = "5px"; dialog.style.position = "fixed"; dialog.style.right = "8px"; dialog.style.top = "8px"; dialog.style.zIndex = "2147483647"; dialog.style.overflow = "auto"; let formatsHtml = `<table style="width:100%;border: 1px solid #c0bfbf;border-collapse: collapse;">`; for (var i = 1; i <= this.formats.length; i++) { if (i % 2 != 0) { formatsHtml += `<tr style="width:100%;border: 1px solid #c0bfbf;">`; } formatsHtml += `<td width="50" style="border: 1px solid #c0bfbf;padding: 5px 0px;" title="` + this.formats[i - 1].example + `"><input type="radio" name="fmt" value="` + (i - 1) + `" class="top_r" />` + ("【" + i + "】" + this.formats[i - 1].format) + `</td>`; if (i % 2 == 0) { formatsHtml += `</tr>`; } } formatsHtml += `</table>`; let html = ` <div style="font-size:15px;font-weight:bold;margin-bottom:5px;">` + Commonlanguage.menuCommand.titleDateFormat + `</div> <div>` + formatsHtml + `</div> <div style="margin-top:15px;text-align:center;"> <button name="closex">` + Commonlanguage.menuCommand.buttonClose + `</button> </div> `; dialog.innerHTML = html; return dialog; }, addEvent: function(dialog) { dialog.querySelector("button[name='closex']").addEventListener("click", function(event) { for (let e of dialog.querySelectorAll('input[name="fmt"]')) { if (e.checked) { fmt = e.value; break; } } GM_setValue("fmt", fmt); dialog.style.display = "none"; }, false); }, init: function() { let dialog = this.make(); this.addEvent(dialog); document.body.appendChild(dialog); GM_registerMenuCommand(Commonlanguage.menuCommand.settings, function() { if (dialog.style.display == "none") { dialog.querySelector('input[name="fmt"][value="' + fmt + '"]').checked = true; dialog.style.display = "block"; } }); } }; const XDateFormat = { df: function(date, f) { var _a; const WEEK = Commonlanguage.dateFormat.week; const YE = date.getFullYear().toString().slice(-2); const YM = date.getFullYear() - 1911; const MO = ("0" + (date.getMonth() + 1)).slice(-2); const DA = ("0" + date.getDate()).slice(-2); const WE = WEEK[date.getDay()]; const HO = ("0" + date.getHours()).slice(-2); const MI = ("0" + date.getMinutes()).slice(-2); const SE = ("0" + date.getSeconds()).slice(-2); const F = [ DA + "." + MO + "." + YE + " " + HO + ":" + MI, DA + "." + MO + "." + YE + " " + HO + ":" + MI + ":" + SE, DA + "." + MO + "." + YE + "(" + WE + ") " + HO + ":" + MI, DA + "." + MO + "." + YE + "(" + WE + ") " + HO + ":" + MI + ":" + SE, YE + "/" + MO + "/" + DA + " " + HO + ":" + MI, YE + "/" + MO + "/" + DA + " " + HO + ":" + MI + ":" + SE, YE + "/" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI, YE + "/" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI + ":" + SE, YE + "-" + MO + "/" + DA + " " + HO + ":" + MI, YE + "-" + MO + "/" + DA + " " + HO + ":" + MI + "'" + SE, YE + "-" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI, YE + "-" + MO + "/" + DA + "(" + WE + ") " + HO + ":" + MI + "'" + SE, MO + "/" + DA + "/" + YE + " " + HO + ":" + MI, MO + "/" + DA + "/" + YE + " " + HO + ":" + MI + ":" + SE, WE + ", " + MO + "/" + DA + "/" + YE + " " + HO + ":" + MI, WE + ", " + MO + "/" + DA + "/" + YE + " " + HO + ":" + MI + ":" + SE, "M" + YM + "-" + MO + "-" + DA + " " + HO + ":" + MI, "M" + YM + "-" + MO + "-" + DA + " " + HO + ":" + MI + ":" + SE, "M" + YM + "-" + MO + "-" + DA + "(" + WE + ") " + HO + ":" + MI, "M" + YM + "-" + MO + "-" + DA + "(" + WE + ") " + HO + ":" + MI + ":" + SE ]; return (_a = F[f]) != null ? _a : F[0]; }, repldatetime: function() { const MYNAME = "peter_parker_x1190"; const SEL = 'main div[data-testid="primaryColumn"] section article time[datetime*=":"]'; const SEL_2 = 'div[aria-labelledby="modal-header"] div[data-testid^="User-Name"] time[datetime]'; const SEL_3 = 'div[aria-labelledby="modal-header"] div[aria-label] time[datetime]'; const SEL_4 = 'main section[aria-labelledby="detail-header"] article div[data-testid^="User-Name"] time[datetime]'; const SEL_5 = 'main section div[data-testid="conversation"] div[aria-label] time[datetime]'; document.querySelectorAll(SEL + ", " + SEL_2 + ", " + SEL_3 + ", " + SEL_4 + ", " + SEL_5).forEach((e) => { if (fmt != 0) { const SEL_ADD = "span.us-" + MYNAME; let d = e.getAttribute("datetime"); let df = this.df(new Date(d), fmt - 1); let pe = e.parentNode; let old = pe.querySelectorAll(SEL_ADD); if (!old.length) { let span = document.createElement("span"); span.className = "us-" + MYNAME; span.setAttribute("datetime", d); span.setAttribute("local-datetime", df); span.textContent = df; span.style = e.style; e.style.setProperty("display", "none"); pe.appendChild(span); } else if (old[0].getAttribute("local-datetime") != df) { old[0].setAttribute("local-datetime", df); old[0].textContent = df; old[0].style = e.style; } } }); } }; const XOrigimg = () => { const SEL_D = 'div[style*="background-image:"]'; const SEL_I = "img"; let elms = document.querySelectorAll(SEL_D + ", " + SEL_I); for (let e of elms) { let regex = /^(.+pbs\.twimg\.com\/[^?]+\?format=\w+)(&|&)(name=)(\w+)([")]*)$/; if (/div/i.test(e.tagName)) { let r2 = regex.exec(e.style.backgroundImage); if (r2 && r2[4] != "orig") { e.style.backgroundImage = r2[1] + r2[2] + r2[3] + "orig" + r2[5]; continue; } continue; } let r = regex.exec(e.getAttribute("src")); if (r && r[4] != "orig") { e.setAttribute("src", r[1] + r[2] + r[3] + "orig" + r[5]); continue; } } }; const XHidepromo = () => { var _a, _b; const SEL = 'path[d^="M19.498 3h-15c-1.381 0-2.5 1.12-2.5 2.5v13c0 1.38 1.119 2.5"]'; const SEL_2 = 'main div[data-testid="sidebarColumn"] section div[data-testid="trend"] div.r-14gqq1x span.css-1qaijid.r-bcqeeo.r-qvutc0'; const SEL_3 = 'main div[data-testid="primaryColumn"] section article span.css-1jxf684.r-bcqeeo.r-qvutc0.r-poiln3'; const SEL_4 = 'main div[data-testid="primaryColumn"] section span.css-901oao.css-16my406.r-bcqeeo.r-qvutc0'; let elms = document.querySelectorAll(SEL); let elms_2 = document.querySelectorAll(SEL_2); let elms_3 = document.querySelectorAll(SEL_3); let elms_4 = document.querySelectorAll(SEL_4); const PROMO = { "ja": "によるプロモーション$", "ko": " 님이 프로모션함$", "zh": "^由 .+ 推广$", "ru": "^Реклама от ", "de": "^Gesponsert von ", "it": "^Sponsorizzato da ", "fr": "^Sponsorisé par ", "pt": "^Promovido por ", "en": "^Promoted by " }; const PROMO_L = (_a = PROMO[ScriptConst.lang]) != null ? _a : PROMO["en"]; const PROMO_2 = { "ja": "プロモポスト", "ko": "Promoted Post", "zh": "推广帖", "ru": "Promoted Post", "de": "Gesponserter Post", "it": "Promoted Post", "fr": "Promoted Post", "pt": "Post promovido", "en": "Promoted Post" }; const PROMO_L_2 = (_b = PROMO_2[ScriptConst.lang]) != null ? _b : PROMO_2["en"]; for (let e of elms) { let xpe = e.closest('div[data-testid="cellInnerDiv"]'); if (!xpe) xpe = e.closest("div.css-175oi2r.r-1adg3ll.r-1ny4l3l"); if (!xpe) xpe = e.closest('div.css-175oi2r.r-1ny4l3l[data-testid="UserCell"]'); if (xpe) xpe.style.setProperty("display", "none"); } for (let e of elms_2) { const REGEX = new RegExp(PROMO_L, "i"); if (!REGEX.test(e.textContent)) continue; let xpe = e.closest("div.css-175oi2r.r-1adg3ll.r-1ny4l3l"); xpe.style.setProperty("display", "none"); } for (let e of elms_3) { if (e.textContent != "Ad") continue; let xpe = e.closest('div[data-testid="cellInnerDiv"]'); xpe.style.setProperty("display", "none"); } for (let e of elms_4) { if (e.textContent != PROMO_2["en"] && e.textContent != PROMO_L_2) continue; let xpe = e.closest('div[data-testid="cellInnerDiv"]'); xpe.style.setProperty("display", "none"); } }; const XDownload = { history: [], show_sensitive: true, filename: "twitter_{user-name}(@{user-id})_{date-time}_{status-id}_{file-type}", css: ` .tmd-down {margin-left: 12px; order: 99;} .tmd-down:hover > div > div > div > div {color: rgba(29, 161, 242, 1.0);} .tmd-down:hover > div > div > div > div > div {background-color: rgba(29, 161, 242, 0.1);} .tmd-down:active > div > div > div > div > div {background-color: rgba(29, 161, 242, 0.2);} .tmd-down:hover svg {color: rgba(29, 161, 242, 1.0);} .tmd-down:hover div:first-child:not(:last-child) {background-color: rgba(29, 161, 242, 0.1);} .tmd-down:active div:first-child:not(:last-child) {background-color: rgba(29, 161, 242, 0.2);} .tmd-down.tmd-media {position: absolute; right: 0;} .tmd-down.tmd-media > div {display: flex; border-radius: 99px; margin: 2px;} .tmd-down.tmd-media > div > div {display: flex; margin: 6px; color: #fff;} .tmd-down.tmd-media:hover > div {background-color: rgba(255,255,255, 0.6);} .tmd-down.tmd-media:hover > div > div {color: rgba(29, 161, 242, 1.0);} .tmd-down.tmd-media:not(:hover) > div > div {filter: drop-shadow(0 0 1px #000);} .tmd-down g {display: none;} .tmd-down.download g.download, .tmd-down.completed g.completed, .tmd-down.loading g.loading,.tmd-down.failed g.failed {display: unset;} .tmd-down.loading svg {animation: spin 1s linear infinite;} @keyframes spin {0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}} .tmd-btn {display: inline-block; background-color: #1DA1F2; color: #FFFFFF; padding: 0 20px; border-radius: 99px;} .tmd-tag {display: inline-block; background-color: #FFFFFF; color: #1DA1F2; padding: 0 10px; border-radius: 10px; border: 1px solid #1DA1F2; font-weight: bold; margin: 5px;} .tmd-btn:hover {background-color: rgba(29, 161, 242, 0.9);} .tmd-tag:hover {background-color: rgba(29, 161, 242, 0.1);} .tmd-notifier {display: none; position: fixed; left: 16px; bottom: 16px; color: #000; background: #fff; border: 1px solid #ccc; border-radius: 8px; padding: 4px;} .tmd-notifier.running {display: flex; align-items: center;} .tmd-notifier label {display: inline-flex; align-items: center; margin: 0 8px;} .tmd-notifier label:before {content: " "; width: 32px; height: 16px; background-position: center; background-repeat: no-repeat;} .tmd-notifier label:nth-child(1):before {background-image:url("data:image/svg+xml;charset=utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2216%22 height=%2216%22 viewBox=%220 0 24 24%22><path d=%22M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l4,4 q1,1 2,0 l4,-4 M12,3 v11%22 fill=%22none%22 stroke=%22%23666%22 stroke-width=%222%22 stroke-linecap=%22round%22 /></svg>");} .tmd-notifier label:nth-child(2):before {background-image:url("data:image/svg+xml;charset=utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2216%22 height=%2216%22 viewBox=%220 0 24 24%22><path d=%22M12,2 a1,1 0 0 1 0,20 a1,1 0 0 1 0,-20 M12,5 v7 h6%22 fill=%22none%22 stroke=%22%23999%22 stroke-width=%222%22 stroke-linejoin=%22round%22 stroke-linecap=%22round%22 /></svg>");} .tmd-notifier label:nth-child(3):before {background-image:url("data:image/svg+xml;charset=utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2216%22 height=%2216%22 viewBox=%220 0 24 24%22><path d=%22M12,0 a2,2 0 0 0 0,24 a2,2 0 0 0 0,-24%22 fill=%22%23f66%22 stroke=%22none%22 /><path d=%22M14.5,5 a1,1 0 0 0 -5,0 l0.5,9 a1,1 0 0 0 4,0 z M12,17 a2,2 0 0 0 0,5 a2,2 0 0 0 0,-5%22 fill=%22%23fff%22 stroke=%22none%22 /></svg>");} .tmd-down.tmd-img {position: absolute; right: 0; bottom: 0; display: none !important;} .tmd-down.tmd-img > div {display: flex; border-radius: 99px; margin: 2px; background-color: rgba(255,255,255, 0.6);} .tmd-down.tmd-img > div > div {display: flex; margin: 6px; color: #fff !important;} .tmd-down.tmd-img:not(:hover) > div > div {filter: drop-shadow(0 0 1px #000);} .tmd-down.tmd-img:hover > div > div {color: rgba(29, 161, 242, 1.0);} :hover > .tmd-down.tmd-img, .tmd-img.loading, .tmd-img.completed, .tmd-img.failed {display: block !important;} .tweet-detail-action-item {width: 20% !important;} `, css_ss: ` /* show sensitive in media tab */ li[role="listitem"]>div>div>div>div:not(:last-child) {filter: none;} li[role="listitem"]>div>div>div>div+div:last-child {display: none;} `, svg: ` <g class="download"><path d="M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l4,4 q1,1 2,0 l4,-4 M12,3 v11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></g> <g class="completed"><path d="M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l3,4 q1,1 2,0 l8,-11" fill="none" stroke="#1DA1F2" stroke-width="2" stroke-linecap="round" /></g> <g class="loading"><circle cx="12" cy="12" r="10" fill="none" stroke="#1DA1F2" stroke-width="4" opacity="0.4" /><path d="M12,2 a10,10 0 0 1 10,10" fill="none" stroke="#1DA1F2" stroke-width="4" stroke-linecap="round" /></g> <g class="failed"><circle cx="12" cy="12" r="11" fill="#f33" stroke="currentColor" stroke-width="2" opacity="0.8" /><path d="M14,5 a1,1 0 0 0 -4,0 l0.5,9.5 a1.5,1.5 0 0 0 3,0 z M12,17 a2,2 0 0 0 0,4 a2,2 0 0 0 0,-4" fill="#fff" stroke="none" /></g> `, isTweetdeck: function() { return ScriptConst.currentHost.indexOf("tweetdeck") >= 0; }, getCookie: function() { const cookieString = document.cookie; const cookiePairs = cookieString.split(";"); const cookiesObject = {}; for (const pair of cookiePairs) { const [key, value] = pair.split("="); cookiesObject[key.trim()] = value.trim(); } return cookiesObject; }, formatDate: function(i, o, tz) { let d = new Date(i); if (tz) { d.setMinutes(d.getMinutes() - d.getTimezoneOffset()); } let m = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]; let v = { YYYY: d.getUTCFullYear().toString(), YY: d.getUTCFullYear().toString(), MM: d.getUTCMonth() + 1, MMM: m[d.getUTCMonth()], DD: d.getUTCDate(), hh: d.getUTCHours(), mm: d.getUTCMinutes(), ss: d.getUTCSeconds(), h2: d.getUTCHours() % 12, ap: d.getUTCHours() < 12 ? "AM" : "PM" }; return o.replace(/(YY(YY)?|MMM?|DD|hh|mm|ss|h2|ap)/g, (n) => ("0" + v[n]).substr(-n.length)); }, detect: function(node) { let article = node.tagName == "ARTICLE" && node || node.tagName == "DIV" && (node.querySelector("article") || node.closest("article")); if (article) { this.addButtonTo(article); } let listitems = node.tagName == "LI" && node.getAttribute("role") == "listitem" && [node] || node.tagName == "DIV" && node.querySelectorAll('li[role="listitem"]'); if (listitems) { this.addButtonToMedia(listitems); } }, addButtonTo: function(article) { if (article.dataset.detected) { return; } article.dataset.detected = "true"; const media_selector = [ 'a[href*="/photo/1"]', 'div[role="progressbar"]', 'button[data-testid="playButton"]', 'a[href="/settings/content_you_see"]', "div.media-image-container", "div.media-preview-container", 'div[aria-labelledby]>div:first-child>div[role="button"][tabindex="0"]' ]; const media = article.querySelector(media_selector.join(",")); if (media) { let status_id2 = article.querySelector('a[href*="/status/"]').href.split("/status/").pop().split("/").shift(); let btn_group = article.querySelector('div[role="group"]:last-of-type, ul.tweet-actions, ul.tweet-detail-actions'); let btn_share = Array.from(btn_group.querySelectorAll(":scope>div>div, li.tweet-action-item>a, li.tweet-detail-action-item>a")).pop().parentNode; let btn_down = btn_share.cloneNode(true); btn_down.querySelector("button").removeAttribute("disabled"); if (this.isTweetdeck()) { btn_down.firstElementChild.innerHTML = '<svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">' + this.svg + "</svg>"; btn_down.firstElementChild.removeAttribute("rel"); btn_down.classList.replace("pull-left", "pull-right"); } else { btn_down.querySelector("svg").innerHTML = this.svg; } let is_exist = this.history.indexOf(status_id2) >= 0; this.status(btn_down, "tmd-down"); this.status(btn_down, is_exist ? "completed" : "download", is_exist ? Commonlanguage.download.completed : Commonlanguage.download.download); btn_group.insertBefore(btn_down, btn_share.nextSibling); btn_down.onclick = () => { this.click(btn_down, status_id2, is_exist); }; if (this.show_sensitive) { let btn_show = article.querySelector('div[aria-labelledby] div[role="button"][tabindex="0"]:not([data-testid]) > div[dir] > span > span'); if (btn_show) { btn_show.click(); } } } const imgs = article.querySelectorAll('a[href*="/photo/"]'); if (imgs.length > 1) { let status_id2 = article.querySelector('a[href*="/status/"]').href.split("/status/").pop().split("/").shift(); let btn_group = article.querySelector('div[role="group"]:last-of-type'); Array.from(btn_group.querySelectorAll(":scope>div>div")).pop().parentNode; imgs.forEach((img) => { let index = img.href.split("/status/").pop().split("/").pop(); let is_exist = this.history.indexOf(status_id2) >= 0; let btn_down = document.createElement("div"); btn_down.innerHTML = '<div><div><svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">' + this.svg + "</svg></div></div>"; btn_down.classList.add("tmd-down", "tmd-img"); this.status(btn_down, "download"); img.parentNode.appendChild(btn_down); btn_down.onclick = (e) => { e.preventDefault(); this.click(btn_down, status_id2, is_exist, index); }; }); } }, addButtonToMedia: function(listitems) { listitems.forEach((li) => { if (li.dataset.detected) return; li.dataset.detected = "true"; let is_exist = false; try { let status_id2 = li.querySelector('a[href*="/status/"]').href.split("/status/").pop().split("/").shift(); is_exist = this.history.indexOf(status_id2) >= 0; } catch (e) { Logger.log("error", "get status_id error:", e); } let btn_down = document.createElement("div"); btn_down.innerHTML = '<div><div><svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">' + this.svg + "</svg></div></div>"; btn_down.classList.add("tmd-down", "tmd-media"); this.status(btn_down, is_exist ? "completed" : "download", is_exist ? Commonlanguage.download.completed : Commonlanguage.download.download); li.appendChild(btn_down); btn_down.onclick = () => { this.click(btn_down, status_id, is_exist); }; }); }, status: function(btn, css, title, style) { if (css) { btn.classList.remove("download", "completed", "loading", "failed"); btn.classList.add(css); } if (title) btn.title = title; if (style) btn.style.cssText = style; }, fetchJson: function(status_id2) { return __async$1(this, null, function* () { const base_url = `https://${ScriptConst.currentHost}/i/api/graphql/NmCeCgkVlsRGS1cAwqtgmw/TweetDetail`; const variables = { "focalTweetId": status_id2, "with_rux_injections": false, "includePromotedContent": true, "withCommunity": true, "withQuickPromoteEligibilityTweetFields": true, "withBirdwatchNotes": true, "withVoice": true, "withV2Timeline": true }; const features = { "rweb_lists_timeline_redesign_enabled": true, "responsive_web_graphql_exclude_directive_enabled": true, "verified_phone_label_enabled": false, "creator_subscriptions_tweet_preview_api_enabled": true, "responsive_web_graphql_timeline_navigation_enabled": true, "responsive_web_graphql_skip_user_profile_image_extensions_enabled": false, "tweetypie_unmention_optimization_enabled": true, "responsive_web_edit_tweet_api_enabled": true, "graphql_is_translatable_rweb_tweet_is_translatable_enabled": true, "view_counts_everywhere_api_enabled": true, "longform_notetweets_consumption_enabled": true, "responsive_web_twitter_article_tweet_consumption_enabled": false, "tweet_awards_web_tipping_enabled": false, "freedom_of_speech_not_reach_fetch_enabled": true, "standardized_nudges_misinfo": true, "tweet_with_visibility_r###lts_prefer_gql_limited_actions_policy_enabled": true, "longform_notetweets_rich_text_read_enabled": true, "longform_notetweets_inline_media_enabled": true, "responsive_web_media_download_video_enabled": false, "responsive_web_enhance_cards_enabled": false }; const url = encodeURI(`${base_url}?variables=${JSON.stringify(variables)}&features=${JSON.stringify(features)}`); const cookies = this.getCookie(); const headers = { "authorization": "Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", "x-twitter-active-user": "yes", "x-twitter-client-language": cookies.lang, "x-csrf-token": cookies.ct0 }; if (cookies.ct0.length == 32) headers["x-guest-token"] = cookies.gt; let tweet_detail = yield fetch(url, { headers }).then((r###lt) => r###lt.json()); let tweet_entrie = tweet_detail.data.threaded_conversation_with_injections_v2.instructions[0].entries.find((n) => n.entryId == `tweet-${status_id2}`); let tweet_r###lt = tweet_entrie.content.itemContent.tweet_r###lts.r###lt; return tweet_r###lt.tweet || tweet_r###lt; }); }, click: function(btn, status_id2, is_exist, index) { return __async$1(this, null, function* () { if (btn.classList.contains("loading")) return; this.status(btn, "loading"); let save_history = yield GM_getValue("save_history", true); let json = yield this.fetchJson(status_id2); let tweet = json.legacy; let user = json.core.user_r###lts.r###lt.legacy; let invalid_chars = { "\\": "\", "/": "/", "|": "|", "<": "<", ">": ">", ":": ":", "*": "*", "?": "?", '"': """, "": "", "": "", "": "", "": "", "\uFEFF": "", "🔞": "" }; let datetime = this.filename.match(/{date-time(-local)?:[^{}]+}/) ? this.filename.match(/{date-time(?:-local)?:([^{}]+)}/)[1].replace(/[\\/ | <>*?:"]/g, (v) => invalid_chars[v]) : "YYYYMMDD-hhmmss"; let info = {}; info["status-id"] = status_id2; info["user-name"] = user.name.replace(/([\\/|*?:"] | [\u200b - \u200d\u2060\ufeff] | 🔞) /g, (v) => invalid_chars[v]); info["user-id"] = user.screen_name; info["date-time"] = this.formatDate(tweet.created_at, datetime); info["date-time-local"] = this.formatDate(tweet.created_at, datetime, true); info["full-text"] = tweet.full_text.split("\n").join(" ").replace(/\s*https:\/\/t\.co\/\w+/g, "").replace(/[\\/ | <>*?:"]|[\u200b-\u200d\u2060\ufeff]/g, (v) => invalid_chars[v]); let medias = tweet.extended_entities && tweet.extended_entities.media; if (!medias || medias.length == 0) { try { medias = JSON.parse(json.card.legacy.binding_values[0].value.string_value).media_entities; medias = Object.values(medias); } catch (e) { } } if (!medias || medias.length == 0) { this.status(btn, "failed", "MEDIA_NOT_FOUND"); return; } if (index) { medias = [medias[index - 1]]; } if (medias.length > 0) { let tasks = medias.length; let tasks_r###lt = []; medias.forEach((media, i) => { info.url = media.type == "photo" ? media.media_url_https + ":orig" : media.video_info.variants.filter((n) => n.content_type == "video/mp4").sort((a, b) => b.bitrate - a.bitrate)[0].url; info.file = info.url.split("/").pop().split(/[:?]/).shift(); info["file-name"] = info.file.split(".").shift(); info["file-ext"] = info.file.split(".").pop(); info["file-type"] = media.type.replace("animated_", ""); info.out = (this.filename.replace(/\.?{file-ext}/, "") + ((medias.length > 1 || index) && !this.filename.match("{file-name}") ? "-" + (index ? index - 1 : i) : "") + ".{file-ext}").replace(/{([^{}:]+)(:[^{}]+)?}/g, (match, name) => info[name]); this.downloader.add({ url: info.url, name: info.out, onload: () => { tasks -= 1; tasks_r###lt.push((medias.length > 1 || index ? (index ? index : i + 1) + ": " : "") + Commonlanguage.download.completed); this.status(btn, null, tasks_r###lt.sort().join("\n")); if (tasks === 0) { this.status(btn, "completed", Commonlanguage.download.completed); if (save_history && !is_exist) { this.history.push(status_id2); } } }, onerror: (r###lt) => { tasks = -1; tasks_r###lt.push((medias.length > 1 ? i + 1 + ": " : "") + r###lt.details.current); this.status(btn, "failed", tasks_r###lt.sort().join("\n")); } }); }); } else { this.status(btn, "failed", "MEDIA_NOT_FOUND"); } }); }, downloader: function() { let tasks = [], thread = 0, max_thread = 2, retry = 0, max_retry = 2, failed = 0, notifier, has_failed = false; return { add: function(task) { tasks.push(task); if (thread < max_thread) { thread += 1; this.next(); } else { this.update(); } }, next: function() { return __async$1(this, null, function* () { let task = tasks.shift(); yield this.start(task); if (tasks.length > 0 && thread <= max_thread) { this.next(); } else { thread -= 1; } this.update(); }); }, start: function(task) { this.update(); return new Promise((resolve) => { GM_download({ url: task.url, name: task.name, onload: (r###lt) => { task.onload(); resolve(); }, onerror: (r###lt) => { this.retry(task, r###lt); resolve(); }, ontimeout: (r###lt) => { this.retry(task, r###lt); resolve(); } }); }); }, retry: function(task, r###lt) { retry += 1; if (retry == 3) max_thread = 1; if (task.retry && task.retry >= max_retry || r###lt.details && r###lt.details.current == "USER_CANCELED") { task.onerror(r###lt); failed += 1; } else { if (max_thread == 1) task.retry = (task.retry || 0) + 1; this.add(task); } }, update: function() { if (!notifier) { notifier = document.createElement("div"); notifier.title = "Twitter Media Downloader"; notifier.classList.add("tmd-notifier"); notifier.innerHTML = "<label>0</label>|<label>0</label>"; document.body.appendChild(notifier); } if (failed > 0 && !has_failed) { has_failed = true; notifier.innerHTML += "|"; let clear = document.createElement("label"); notifier.appendChild(clear); clear.onclick = () => { notifier.innerHTML = "<label>0</label>|<label>0</label>"; failed = 0; has_failed = false; this.update(); }; } notifier.firstChild.innerText = thread; notifier.firstChild.nextElementSibling.innerText = tasks.length; if (failed > 0) { notifier.lastChild.innerText = failed; } if (thread > 0 || tasks.length > 0 || failed > 0) { notifier.classList.add("running"); } else { notifier.classList.remove("running"); } } }; }(), init: function() { document.head.insertAdjacentHTML("beforeend", "<style>" + this.css + (this.show_sensitive ? this.css_ss : "") + "</style>"); } }; const X = { XSettingsDialog, XDateFormat, XOrigimg, XHidepromo, XDownload }; var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; const Tiktok = { extractHref: function(html) { const regex = /<a\s+(?:[^>]*?\s+)?href=(['"])(.*?)\1/gi; const hrefs = []; let match; while ((match = regex.exec(html)) !== null) { hrefs.push(match[2]); } return hrefs.filter((href) => href.indexOf("snapcdn.app") != -1); }, download: function(url, element) { return __async(this, null, function* () { Toast.show({ "message": Commonlanguage.download.preparing, "background": "#000" }); element.classList.add("download-loadding"); const param = new URLSearchParams({ lang: "en", q: url }).toString(); const data = yield Tools.request("POST", "https://tikdownloader.io/api/ajaxSearch", param, { "Content-Type": "application/x-www-form-urlencoded" }); if (data.code === "success") { const r###lt = JSON.parse(data.r###lt); if (r###lt.status == "ok" && r###lt.hasOwnProperty("data")) { const data2 = r###lt.data; const downloadUrls = this.extractHref(data2); if (downloadUrls.length >= 2) { Tools.openInTab(downloadUrls.at(-2)); } } } element.classList.remove("download-loadding"); }); }, appendHtml: function() { if (!document.querySelector("#tiktok-download-990i")) { const container = document.querySelector("#main-content-video_detail") || document.body; if (!container) { return; } const matchedDiv = document.querySelector("*[class*='-DivRightControlsWrapper'], *[class*='-DivMiniPlayerContainer']"); if (matchedDiv) { let cloneNode = null; let isDetail = matchedDiv.children.length != 1; if (isDetail) { cloneNode = matchedDiv.children[0].cloneNode(true); } else { cloneNode = matchedDiv.cloneNode(true); } cloneNode.id = "tiktok-download-990i"; cloneNode.querySelector("div").innerHTML = `<svg t="1724300009050" class="icon" viewBox="0 0 #### ####" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5307" width="35" height="35"><path d="M298.666667 554.666667v85.333333H256v128h512v-128h-42.666667v-85.333333h128v213.333333a85.333333 85.333333 0 0 1-78.933333 85.077333L768 853.333333H256a85.333333 85.333333 0 0 1-85.12-78.933333L170.666667 768v-213.333333h128z" fill="#ffffff" p-id="5308"></path><path d="M512 627.498667l219.477333-219.477334h-120.704L512 506.88 413.141333 408.021333H292.522667L512 627.498667z" fill="#ffffff" p-id="5309"></path><path d="M554.666667 528V167.978667h-85.333334v360.021333h85.333334z" fill="#ffffff" p-id="5310"></path></svg>`; if (isDetail) { matchedDiv.insertBefore(cloneNode, matchedDiv.children[0]); } else { cloneNode.style.right = 166 + "px"; matchedDiv.parentNode.insertBefore(cloneNode, matchedDiv); } cloneNode.title = Commonlanguage.download.tip; cloneNode.addEventListener("click", () => { Tiktok.download(window.location.href, cloneNode); }); } } }, start: function() { return __async(this, null, function* () { if (!/www\.tiktok\.com/.test(window.location.host)) { return; } GM_addStyle(` @keyframes scriptspin {0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}} .download-loadding{ animation: scriptspin 1s linear infinite; } `); setInterval(() => { this.appendHtml(); }, 1e3); }); } }; const AllModules = { X, Tiktok }; const Init = { x: function() { AllModules.X.XDownload.init(); AllModules.X.XSettingsDialog.init(); const observer = new MutationObserver((ms) => ms.forEach((m) => { m.addedNodes.forEach((node) => { AllModules.X.XDownload.detect(node); AllModules.X.XDateFormat.repldatetime(); AllModules.X.XOrigimg(); AllModules.X.XHidepromo(); }); })); observer.observe(document.body, { childList: true, subtree: true }); }, tiktok: function() { AllModules.Tiktok.start(); }, unknown: function() { Logger.log("error", "Hoooo,This method was not found"); }, start: function() { const otherPlatform = Tools.getOtherPlatform(); if (otherPlatform) { try { this[otherPlatform](); } catch (e) { console.log("error", "Hoooo,catch", e); } } } }; Init.start(); }());