您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
允许您无限制地访问任何网页的函数
// ==UserScript== // @name Digitual // @name:en Digitual // @name:es Digitual // @name:fr Digitual // @name:de Digitual // @name:it Digitual // @name:pt Digitual // @name:nl Digitual // @name:ru Digitual // @name:zh-CN Digitual // @name:ja Digitual // @name:ko Digitual // @name:hi Digitual // @name:ar Digitual // @name:vi Digitual // @name:tr Digitual // @name:pl Digitual // @name:uk Digitual // @name:el Digitual // @name:sv Digitual // @name:da Digitual // @name:no Digitual // @name:fi Digitual // @name:hu Digitual // @name:cs Digitual // @name:ro Digitual // @name:th Digitual // @name:id Digitual // @name:he Digitual // @name:fa Digitual // @name:bn Digitual // @name:ta Digitual // @name:ur Digitual // @name:pa Digitual // @name:ms Digitual // @name:te Digitual // @name:ml Digitual // @name:gu Digitual // @name:kn Digitual // @name:mr Digitual // @name:or Digitual // @name:sa Digitual // @name:mk Digitual // @name:bg Digitual // @name:hr Digitual // @name:sr Digitual // @name:sk Digitual // @name:sl Digitual // @name:lt Digitual // @name:lv Digitual // @name:et Digitual // @name:ca Digitual // @name:eu Digitual // @name:gl Digitual // @namespace https://yomboxggt.neocities.org/Digitual // @version 1.5 // @description Una funcion que te permite acceder a cualquier pagina web sin ninguna renstriccion // @description:en A function that allows you to access any webpage without any restrictions // @description:es Una función que te permite acceder a cualquier página web sin ninguna restricción // @description:fr Une fonction qui vous permet d'accéder à n'importe quelle page web sans aucune restriction // @description:de Eine Funktion, die Ihnen den Zugriff auf jede Webseite ohne Einschränkungen ermöglicht // @description:it Una funzione che ti permette di accedere a qualsiasi pagina web senza alcuna restrizione // @description:pt Uma função que permite que você acesse qualquer página da web sem nenhuma restrição // @description:nl Een functie die u toelaat om toegang te krijgen tot elke website zonder beperkingen // @description:ru Функция, которая позволяет вам получить доступ к любой веб-странице без ограничений // @description:zh-CN 允许您无限制地访问任何网页的函数 // @description:ja 制限なしでどのウェブページにもアクセスできる機能 // @description:ko 제한 없이 모든 웹 페이지에 접근할 수 있는 기능 // @description:hi एक फ़ंक्शन जो आपको किसी भी वेब पेज पर बिना किसी रोक-टोक के पहुंचने देता है // @description:ar دالة تتيح لك الوصول إلى أي صفحة ويب دون أي قيود // @description:vi Một chức năng cho phép bạn truy cập bất kỳ trang web nào mà không có bất kỳ hạn chế nào // @description:tr Herhangi bir kısıtlama olmadan herhangi bir web sayfasına erişmenizi sağlayan bir fonksiyon // @description:pl Funkcja, która pozwala na dostęp do dowolnej strony internetowej bez żadnych ograniczeń // @description:uk Функція, яка дозволяє вам отримати доступ до будь-якої веб-сторінки без обмежень // @description:el Μια λειτουργία που σας επιτρέπει να προσπελάσετε οποιαδήποτε ιστοσελίδα χωρίς περιορισμούς // @description:sv En funktion som låter dig komma åt vilken hemsida som helst utan några restriktioner // @description:da En funktion, der gør det muligt at få adgang til enhver hjemmeside uden begrænsninger // @description:no En funksjon som lar deg få tilgang til hvilken som helst nettsted uten noen restriksjoner // @description:fi Toiminto, joka antaa sinulle pääsyn mihin tahansa verkkosivulle ilman rajoituksia // @description:hu Egy olyan funkció, amely lehetővé teszi bármely weblap elérését korlátozás nélkül // @description:cs Funkce, která vám umožňuje přístup k libovolné webové stránce bez jakýchkoliv omezení // @description:ro O funcție care vă permite să accesați orice pagină web fără restricții // @description:th ฟังก์ชันที่อนุญาตให้เข้าถึงเว็บเพจใดๆ ได้โดยไม่มีข้อจำกัดใดๆ // @description:id Fungsi yang memungkinkan Anda mengakses halaman web apa pun tanpa batasan // @description:he פונקציה המאפשרת לך לגשת לכל דף אינטרנט ללא כל הגבלה // @description:fa یک تابع که به شما اجازه میدهد تا به هر صفحه وب بدون هیچ قید و شرط دسترسی داشته باشید // @description:bn একটি ফাংশন যা আপনাকে কোনও ওয়েব পেজে প্রবেশ করতে দেয় কোনও বিধিনিষেধ ছাড়াই // @description:ta ஒரு செயல்பாடு அதனை உங்களுக்கு அனைத்து இணையதளங்களையும் எந்த விதமான கட்டுப்பாடுகளும் இல்லாமல் அணுக அனுமதிக்கிறது // @description:ur ایک ایسا فنکشن جو آپ کو کسی بھی ویب پیج پر کوئی تحریموں کے بغیر رسائی فراہم کرتا ہے // @description:pa ਇੱਕ ਫੰਕਸ਼ਨ ਜੋ ਤੁਹਾਡੇ ਲਈ ਕਿਸੇ ਵੀ ਵੈੱਬ ਪੇਜ ਤੱਕ ਪਹੁੰਚ ਬਿਨਾ ਕਿਸੇ ਵੀ ਪਾਬੰਦੀ ਵਾਲੇ ਦਿੱਤੀ ਹੈ // @description:ms Sebuah fungsi yang membenarkan anda mengakses laman web mana sahaja tanpa sebarang had // @description:te ఒక ఫంక్షన్ ఎటువంటి పరిమితులే లేకుండా ఏ వెబ్ పేజీకి కానీ చేరడానికి అనుమతిస్తుంది // @description:ml ഒരു ഫങ്ക്ഷൻ അതിന്റെ വഴി എല്ലാ വെബ് പേജുകളിലേക്കും പരിമിതികൾ ഒന്നുമില്ലാതെ പ്രവേശിക്കാനും അനുവദിക്കുന്നു // @description:gu એક ફંક્શન જે તમને કોઈ પણ વેબ પેજ પર જોવા માટે બંધો વગર મુજબ કરે છે // @description:kn ಒಂದು ಫಂಕ್ಷನ್ ಇದು ಯಾವುದೇ ಪರಿಸ್ಥಿತಿಗಳಿಲ್ಲದೆ ಯಾವುದೇ ವೆಬ್ ಪೇಜ್ಗೆ ಪ್ರವೇಶವನ್ನು ನೀಡುತ್ತದೆ // @description:mr एक फंक्शन जो तुम्हाला कोणत्याही वेबपेजवर प्रतीबंधांपेक्षा जाऊ देतो // @description:or ଏକ ଫଂକ୍ସନ ଯିଏ ତୁମେ କୌଣସି ଉପରି ବିନା ସମସ୍ୟା ପରିବର୍ତ୍ତନ କରିପାରିବ // @description:sa एक फ़ंक्शन जो आपको किसी भी वेब पेज तक बिना किसी प्रतिबंध के पहुंचने देता है // @description:mk Функција која ви овозможува пристап до секоја веб-страница без никакви ограничувања // @description:bg Функция, която ви позволява да достъпвате всяка уеб страница без никакви ограничения // @description:hr Funkcija koja vam omogućuje pristup bilo kojoj web stranici bez ikakvih ograničenja // @description:sr Функција која вам омогућава приступ било којој веб страници без икаквих ограничења // @description:sk Funkcia, ktorá vám umožňuje prístup k libovolnej webovej stránke bez akýchkoľvek obmedzení // @description:sl Funkcija, ki vam omogoča dostop do katere koli spletne strani brez katerih koli omejitev // @description:lt Funkcija, leidžianti prieiti prie bet kurio tinklalapio be jokios ribos // @description:lv Funkcija, kas ļauj atvērt jebkuru mājaslapu bez jebkādiem ierobežojumiem // @description:et Funktsioon, mis võimaldab ligipääsu igale veebilehele ilma piiranguteta // @description:ca Una funció que us permet accedir a qualsevol pàgina web sense cap restricció // @description:eu Funtzio bat web orri batera edozein sarbide-baldintzarik, web-orrian sarbide-baldintzarik, web-orrian sarbide-baldintzarik // @description:gl Unha función que lle permite acceder a calquera páxina web sen restricións // @author KaitoNeko // @match *://*/* // @icon https://i.ibb.co/s9z93NfZ/1744413593841.png // @license MPL-2.0 // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_openInTab // @grant GM_registerMenuCommand // @grant GM_notification // @grant GM_download // @grant GM_getTab // @grant GM_saveTab // @grant GM_getTabs // @grant GM_deleteValue // @grant GM_info // @grant unsafeWindow // @grant GM_setClipboard // @grant GM.xmlHttpRequest // @grant GM.registerMenuCommand // @grant GM.notification // @grant GM.getValue // @grant GM.setValue // @grant GM.addStyle // @grant GM.openInTab // @grant GM.deleteValue // @grant GM.info // @grant GM.setClipboard // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js // @connect * // @run-at document-start // @noframes // ==/UserScript== (function() { 'use strict'; const config = { version: "1.5", debugMode: false, bypassMethods: { paywalls: true, regionBlocks: true, adBlocks: true, cookieWalls: true, antiAdBlock: true, scrollLocks: true, inspectElement: true, rightClick: true, textSelection: true, loginWalls: true, rateLimits: true, downloadBlocks: true, clipboardBlocks: true, printBlocks: true, devToolsBlocks: true }, stealthMode: { enabled: true, level: "aggressive", hideExtensions: true, fakeUserAgent: true, fakeScreenResolution: true, fakeTimeZone: true, fakeGeolocation: true, fakeIP: true, fakeWebRTC: true, fakeFonts: true, fakeCanvas: true, fakeAudioContext: true, fakeWebGL: true }, performanceMode: { enabled: true, removeAds: true, removeTrackers: true, disableAnimations: false, blockThirdParty: true, lazyLoadImages: false, disableWebFonts: false }, uiConfig: { enabled: true, position: "bottom-right", theme: "dark", animations: true, showNotifications: true, compactMode: false }, autoBypass: true, advancedMode: false, learningMode: true, customRules: [], injectionPoints: [ 'document-start', 'document-body', 'document-end', 'document-idle' ], proxyServers: [ "https://api.allorigins.win/raw?url=", "https://api.codetabs.com/v1/proxy?quest=", "https://corsproxy.io/?", // Añade la URL directamente después del ? // "https://cors-anywhere.herokuapp.com/", // A menudo inestable o con límites // "https://proxy.cors.sh/", // Puede requerir API key para uso intensivo ], updateURL: "https://api.github.com/repos/KaitoNeko/digitual/contents/updates.json", rulesRepository: "https://api.github.com/repos/KaitoNeko/digitual-rules/contents/rules", feedbackURL: "https://api.digitual.tech/v1/feedback", analyticsURL: "https://api.digitual.tech/v1/analytics", maxRetryAttempts: 3, retryDelay: 1000, requestTimeout: 5000, cacheTTL: 3600000 }; const DEBUG_PREFIX = "%c[DIGITUAL]%c"; const DEBUG_STYLE = "color: white; background: linear-gradient(90deg, #ff5555, #ff3385); padding: 2px 5px; border-radius: 3px;"; const LOCAL_STORAGE_KEY = "digitual_ultra_settings_v7"; const SESSION_CACHE = { rules: {}, selectors: {}, sitePatterns: {}, performanceMetrics: {}, resourceUsage: {}, networkRequests: [], elementCounts: {}, memoryUsage: {}, timingMetrics: {} }; const DOM_OBSERVERS = []; const PERFORMANCE_MARKS = {}; const CRYPTO_KEYS = { primary: "4a7d1ed414474e4033ac29ccb8653d9b", secondary: "7f3b8c9a2e5d1f6c0b4e8a2d5f9c3e7", backup: "e6c5d4b3a2f1e0d9c8b7a6d5e4f3c2d1" }; const ERROR_CODES = { PAYWALL_BYPASS_FAILED: 1001, REGION_BYPASS_FAILED: 1002, ADBLOCK_DETECTED: 1003, CONFIG_LOAD_FAILED: 1004, RULE_LOAD_FAILED: 1005, NETWORK_ERROR: 1006, SECURITY_ERROR: 1007, PERFORMANCE_ISSUE: 1008, COMPATIBILITY_WARNING: 1009, UPDATE_ERROR: 1010 }; const EVENT_TYPES = { PAYWALL_DETECTED: "paywall_detected", REGION_BLOCK_DETECTED: "region_block_detected", ADBLOCK_WARNING: "adblock_warning", ELEMENT_UNLOCKED: "element_unlocked", CONTENT_ACCESSED: "content_accessed", CONFIG_CHANGED: "config_changed", RULE_APPLIED: "rule_applied", ERROR_OCCURRED: "error_occurred", PERFORMANCE_METRIC: "performance_metric", RESOURCE_USAGE: "resource_usage" }; const HTTP_HEADERS = { FAKE_HEADERS: { "X-Forwarded-For": "203.0.113.42", "X-Real-IP": "203.0.113.42", "CF-Connecting-IP": "203.0.113.42", "Client-IP": "203.0.113.42", "Via": "1.1 digitual-proxy" }, CORS_HEADERS: { "Origin": "https://digitual.tech", "Referer": "https://digitual.tech/", "Sec-Fetch-Dest": "document", "Sec-Fetch-Mode": "navigate", "Sec-Fetch-Site": "cross-site" } }; const SUPPORTED_SITES = { paywalls: [ "medium.com", "bloomberg.com", "washingtonpost.com", "nytimes.com", "ft.com", "wsj.com", "theatlantic.com", "quora.com", "forbes.com", "statista.com", "businessinsider.com", "telegraph.co.uk", "newsweek.com", "scientificamerican.com", "nationalgeographic.com", "technologyreview.com", "wired.com", "newyorker.com", "economist.com", "harvard.edu", "stanford.edu", "mit.edu", "nature.com", "sciencemag.org", "jstor.org", "springer.com", "elsevier.com", "ieee.org", "acm.org", "researchgate.net", "ssrn.com", "arxiv.org", "tandfonline.com" ], regionBlocks: [ "netflix.com", "hulu.com", "bbc.co.uk", "abc.net.au", "channel4.com", "crunchyroll.com", "disneyplus.com", "hbo.com", "peacocktv.com", "paramountplus.com", "amazon.com", "primevideo.com", "youtube.com", "twitch.tv", "dailymotion.com", "vimeo.com", "youku.com", "bilibili.com", "iq.com", "viu.com", "mytvsuper.com", "nowtv.com", "sky.com", "zattoo.com", "pluto.tv", "tubitv.com", "sling.com", "fubo.tv", "philo.com", "atttvnow.com" ], adBlocks: [ "twitch.tv", "youtube.com", "dailymotion.com", "facebook.com", "instagram.com", "twitter.com", "reddit.com", "9gag.com", "pinterest.com", "tumblr.com", "vk.com", "weibo.com", "qq.com", "baidu.com", "naver.com", "daum.net", "yahoo.com", "aol.com", "msn.com", "outlook.com", "mail.ru", "ok.ru", "live.com", "bing.com", "duckduckgo.com" ], loginWalls: [ "linkedin.com", "quora.com", "pinterest.com", "reddit.com", "medium.com", "researchgate.net", "academia.edu", "scribd.com", "slideshare.net", "issuu.com", "change.org", "patreon.com", "kickstarter.com", "indiegogo.com", "gofundme.com", "producthunt.com", "angel.co", "crunchbase.com", "glassdoor.com", "indeed.com" ] }; const RuleEngine = { rules: {}, selectors: {}, patterns: {}, customSelectors: [], dynamicRules: [], siteSpecificRules: {}, rulePriorities: {}, ruleCategories: {}, ruleDependencies: {}, ruleConditions: {}, ruleActions: {}, ruleExceptions: {}, init: function() { this.loadDefaultRules(); this.loadCustomRules(); this.loadDynamicRules(); this.compileSelectors(); this.analyzeDOM(); }, loadDefaultRules: function() { this.rules = { paywall: { selectors: [ '.paywall', '.overlay', '.modal', '.gate', '.premium', '.membership', '.subscribe', '.blocked', '.locked', '.restricted', '[class*="pay"]', '[class*="wall"]', '[class*="gate"]', '[class*="modal"]', '[class*="overlay"]' ], actions: ['remove', 'hide', 'unlock'], priority: 1, category: 'content' }, regionBlock: { selectors: [ '.geoblock', '.region-restricted', '.not-available', '.unavailable', '.location-warning', '[class*="geo"]', '[class*="region"]', '[class*="country"]' ], actions: ['bypass', 'proxy'], priority: 2, category: 'access' }, adBlock: { selectors: [ '[id*="ad"]', '[class*="ad"]', 'iframe[src*="ads"]', 'iframe[src*="doubleclick"]', 'iframe[src*="adservice"]' ], actions: ['remove', 'block'], priority: 3, category: 'performance' }, cookieWall: { selectors: [ '.cookie', '.gdpr', '.privacy', '.consent', '[class*="cookie"]', '[class*="gdpr"]', '[class*="privacy"]', '[class*="consent"]' ], actions: ['remove', 'accept-all'], priority: 2, category: 'privacy' }, scrollLock: { selectors: [ 'body[style*="overflow:hidden"]', 'html[style*="overflow:hidden"]', '[class*="scroll-lock"]', '[class*="noscroll"]' ], actions: ['unlock', 'override-style'], priority: 1, category: 'usability' } }; this.patterns = { paywall: [ /paywall/i, /premium-content/i, /subscribe-to-read/i, /member-exclusive/i ], regionBlock: [ /not-available-in-your-region/i, /geoblocked/i, /country-restricted/i, /content-unavailable/i ], adBlock: [ /advertisement/i, /adserver/i, /doubleclick/i, /googleads/i ] }; }, loadCustomRules: function() { try { const savedRules = GM_getValue('digitual_custom_rules'); if (savedRules) { const decrypted = this.decryptRules(savedRules); this.customSelectors = decrypted.selectors || []; this.siteSpecificRules = decrypted.siteRules || {}; Utils.debug.log("Reglas personalizadas cargadas:", decrypted); } } catch (e) { Utils.debug.error("Error al cargar reglas personalizadas:", e); } }, loadDynamicRules: function() { this.fetchRemoteRules() .then(rules => { this.dynamicRules = rules; Utils.debug.log("Reglas dinámicas cargadas:", rules.length); }) .catch(e => { Utils.debug.error("Error al cargar reglas dinámicas:", e); }); }, fetchRemoteRules: async function() { try { const response = await Utils.network.fetch(config.rulesRepository, { headers: { "Accept": "application/vnd.github.v3.raw", "User-Agent": "Digitual-Rules-Engine" }, timeout: config.requestTimeout }); if (response && response.status === 200) { return JSON.parse(response.responseText); } return []; } catch (e) { Utils.debug.error(`Failed to fetch remote rules: ${e.message}`, e); return []; } }, compileSelectors: function() { this.selectors = { paywall: this.rules.paywall.selectors.concat(this.customSelectors), regionBlock: this.rules.regionBlock.selectors, adBlock: this.rules.adBlock.selectors, cookieWall: this.rules.cookieWall.selectors, scrollLock: this.rules.scrollLock.selectors }; const currentHost = window.location.hostname; if (this.siteSpecificRules[currentHost]) { for (const [type, selectors] of Object.entries(this.siteSpecificRules[currentHost])) { if (this.selectors[type]) { this.selectors[type] = this.selectors[type].concat(selectors); } } } if (this.dynamicRules.length > 0) { this.dynamicRules.forEach(rule => { if (this.selectors[rule.type]) { this.selectors[rule.type].push(rule.selector); } }); } }, analyzeDOM: function() { const html = document.documentElement.outerHTML; const classes = document.documentElement.className; const ids = Array.from(document.querySelectorAll('[id]')).map(el => el.id); this.detectedTypes = []; for (const [type, patterns] of Object.entries(this.patterns)) { if (patterns.some(pattern => pattern.test(html) || pattern.test(classes) || ids.some(id => pattern.test(id)) )) { this.detectedTypes.push(type); } } Utils.debug.log("Tipos de bloqueo detectados:", this.detectedTypes); }, applyRules: function(types = null) { const rulesToApply = types || this.detectedTypes; let elementsProcessed = 0; rulesToApply.forEach(type => { if (this.selectors[type]) { this.selectors[type].forEach(selector => { try { const elements = document.querySelectorAll(selector); elements.forEach(element => { this.processElement(element, type); elementsProcessed++; }); } catch (e) { Utils.debug.error(`Error al aplicar selector ${selector}:`, e); } }); } }); Utils.debug.log(`Elementos procesados: ${elementsProcessed}`); return elementsProcessed; }, processElement: function(element, type) { switch (type) { case 'paywall': this.handlePaywall(element); break; case 'regionBlock': this.handleRegionBlock(element); break; case 'adBlock': this.handleAdBlock(element); break; case 'cookieWall': this.handleCookieWall(element); break; case 'scrollLock': this.handleScrollLock(element); break; default: this.handleGenericBlock(element); } }, handlePaywall: function(element) { if (element.parentNode) { element.parentNode.removeChild(element); Utils.debug.log(`Paywall eliminado: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'paywall', element: element.tagName, method: 'remove' }); } }, handleRegionBlock: function(element) { element.style.display = 'none'; Utils.debug.log(`Bloqueo regional oculto: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'regionBlock', element: element.tagName, method: 'hide' }); }, handleAdBlock: function(element) { if (element.tagName === 'IFRAME') { element.src = ''; } element.remove(); Utils.debug.log(`Anuncio eliminado: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'adBlock', element: element.tagName, method: 'remove' }); }, handleCookieWall: function(element) { const acceptAll = element.querySelector('[onclick*="accept"], [class*="accept"]'); if (acceptAll) { acceptAll.click(); Utils.debug.log(`Cookie wall aceptado: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'cookieWall', element: element.tagName, method: 'accept' }); } else { element.remove(); Utils.debug.log(`Cookie wall eliminado: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'cookieWall', element: element.tagName, method: 'remove' }); } }, handleScrollLock: function(element) { if (element === document.body || element === document.documentElement) { element.style.overflow = 'auto'; Utils.debug.log(`Scroll desbloqueado: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'scrollLock', element: element.tagName, method: 'style-override' }); } }, handleGenericBlock: function(element) { element.remove(); Utils.debug.log(`Elemento bloqueado eliminado: ${element.tagName}`); this.trackEvent(EVENT_TYPES.ELEMENT_UNLOCKED, { type: 'generic', element: element.tagName, method: 'remove' }); }, addCustomRule: function(site, type, selector) { if (!this.siteSpecificRules[site]) { this.siteSpecificRules[site] = {}; } if (!this.siteSpecificRules[site][type]) { this.siteSpecificRules[site][type] = []; } this.siteSpecificRules[site][type].push(selector); this.saveCustomRules(); this.compileSelectors(); }, saveCustomRules: function() { const rulesToSave = { selectors: this.customSelectors, siteRules: this.siteSpecificRules }; const encrypted = this.encryptRules(rulesToSave); GM_setValue('digitual_custom_rules', encrypted); }, encryptRules: function(rules) { try { return CryptoJS.AES.encrypt( JSON.stringify(rules), CRYPTO_KEYS.primary ).toString(); } catch (e) { Utils.debug.error("Error al encriptar reglas:", e); return JSON.stringify(rules); } }, decryptRules: function(encrypted) { try { const bytes = CryptoJS.AES.decrypt(encrypted, CRYPTO_KEYS.primary); return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); } catch (e) { Utils.debug.error("Error al desencriptar reglas:", e); try { return JSON.parse(encrypted); // Fallback si no estaba encriptado } catch (parseError) { Utils.debug.error("Error al parsear reglas (fallback):", parseError); return { selectors: [], siteRules: {} }; } } }, trackEvent: function(type, data) { SESSION_CACHE.events = SESSION_CACHE.events || []; SESSION_CACHE.events.push({ timestamp: Date.now(), type, data }); } }; const Utils = { debug: { log: function(message, data = null) { if (config.debugMode) { console.log(DEBUG_PREFIX + " " + message, DEBUG_STYLE, "", data !== null ? data : ""); PERFORMANCE_MARKS[`log_${Date.now()}`] = performance.now(); } }, warn: function(message, data = null) { if (config.debugMode) { console.warn(DEBUG_PREFIX + " " + message, DEBUG_STYLE, "", data !== null ? data : ""); } }, error: function(message, data = null) { console.error(DEBUG_PREFIX + " " + message, DEBUG_STYLE, "", data !== null ? data : ""); RuleEngine.trackEvent(EVENT_TYPES.ERROR_OCCURRED, { message, data, stack: new Error().stack }); }, table: function(data) { if (config.debugMode && console.table) { console.table(data); } }, time: function(label) { if (config.debugMode) { console.time(label); } }, timeEnd: function(label) { if (config.debugMode) { console.timeEnd(label); } }, trace: function(message) { if (config.debugMode) { console.trace(DEBUG_PREFIX + " " + message, DEBUG_STYLE); } } }, dom: { remove: function(selector) { document.querySelectorAll(selector).forEach(el => { if (el.parentNode) el.parentNode.removeChild(el); Utils.debug.log(`Elemento eliminado: ${selector}`); }); }, hide: function(selector) { document.querySelectorAll(selector).forEach(el => { el.style.display = 'none'; Utils.debug.log(`Elemento oculto: ${selector}`); }); }, show: function(selector) { document.querySelectorAll(selector).forEach(el => { el.style.display = ''; Utils.debug.log(`Elemento mostrado: ${selector}`); }); }, overrideStyles: function(selector, styles) { document.querySelectorAll(selector).forEach(el => { Object.assign(el.style, styles); Utils.debug.log(`Estilos anulados para: ${selector}`, styles); }); }, addStyles: function(css) { const style = document.createElement('style'); style.textContent = css; (document.head || document.documentElement).appendChild(style); Utils.debug.log(`Estilos añadidos: ${css.substring(0, 50)}...`); }, removeEventListeners: function(element, type) { const el = element || document; const listeners = this.getEventListeners(el); if (listeners[type]) { listeners[type].forEach(listener => { el.removeEventListener(type, listener.listener, listener.useCapture); }); Utils.debug.log(`Listeners de ${type} eliminados`); } }, getEventListeners: function(element) { const listeners = {}; const allEvents = [ 'click', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'contextmenu', 'keydown', 'keypress', 'keyup', 'blur', 'focus', 'change', 'submit', 'reset', 'select', 'scroll' ]; allEvents.forEach(type => { listeners[type] = []; const handler = element[`on${type}`]; if (typeof handler === 'function') { listeners[type].push({ listener: handler, useCapture: false }); } }); return listeners; }, disableAllEventListeners: function() { const events = [ 'scroll', 'mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'contextmenu', 'keydown', 'keypress', 'keyup', 'blur', 'focus', 'change', 'submit', 'reset', 'select', 'dragstart', 'dragend', 'dragover', 'drop' ]; events.forEach(type => { this.removeEventListeners(document, type); this.removeEventListeners(window, type); }); Utils.debug.log("Todos los event listeners deshabilitados (intentado)"); }, enableTextSelection: function() { if (!config.bypassMethods.textSelection) return; const styles = ` * { user-select: auto !important; -webkit-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; } `; this.addStyles(styles); document.onselectstart = null; document.onmousedown = null; document.onmouseup = null; Utils.debug.log("Selección de texto habilitada"); }, enableRightClick: function() { if (!config.bypassMethods.rightClick) return; document.oncontextmenu = null; const styles = ` * { pointer-events: auto !important; } `; this.addStyles(styles); const scripts = document.querySelectorAll('script'); scripts.forEach(script => { if (script.textContent.includes('contextmenu') || script.textContent.includes('oncontextmenu') || script.textContent.includes('rightclick')) { if (script.parentNode) script.parentNode.removeChild(script); } }); Utils.debug.log("Clic derecho habilitado"); }, enableInspectElement: function() { if (!config.bypassMethods.inspectElement) return; document.onkeydown = null; window.onkeydown = null; const scripts = document.querySelectorAll('script'); scripts.forEach(script => { if (script.textContent.includes('devtool') || script.textContent.includes('debugger') || script.textContent.includes('F12') || script.textContent.includes('Ctrl+Shift+I') || script.textContent.includes('contextmenu')) { if (script.parentNode) script.parentNode.removeChild(script); } }); const inlineHandlers = document.querySelectorAll('[onkeydown]'); inlineHandlers.forEach(el => { el.removeAttribute('onkeydown'); }); Utils.debug.log("Inspección de elementos habilitada"); } }, network: { fetchWithProxy: async function(url, options = {}) { const proxyUrlBase = this.getRandomProxy(); if (!proxyUrlBase) { Utils.debug.warn("No hay servidores proxy configurados o disponibles. Intentando conexión directa."); return this.fetch(url, options); } const proxyUrl = proxyUrlBase + encodeURIComponent(url); Utils.debug.log(`Intentando fetch con proxy: ${proxyUrlBase}...`); try { const response = await this.fetch(proxyUrl, options); Utils.debug.log(`Fetch con proxy exitoso para: ${url.substring(0,50)}...`); return response; } catch (e) { Utils.debug.error("Error al usar proxy, intentando directo", e); return this.fetch(url, options); } }, fetch: function(url, options = {}) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url, method: options.method || 'GET', headers: { ...this.spoofHeaders(), ...(options.headers || {}) }, timeout: options.timeout || config.requestTimeout, onload: (response) => { SESSION_CACHE.networkRequests.push({ url, status: response.status, method: options.method || 'GET' }); resolve(response); }, onerror: (error) => { SESSION_CACHE.networkRequests.push({ url, status: 'error', method: options.method || 'GET', error }); reject(error); }, ontimeout: () => { SESSION_CACHE.networkRequests.push({ url, status: 'timeout', method: options.method || 'GET' }); reject(new Error('Request timeout')); } }); }); }, getRandomProxy: function() { if (config.proxyServers && config.proxyServers.length > 0) { return config.proxyServers[Math.floor(Math.random() * config.proxyServers.length)]; } return null; }, spoofHeaders: function(customHeaders = {}) { const headers = { ...HTTP_HEADERS.FAKE_HEADERS, 'User-Agent': this.generateFakeUserAgent(), 'Accept-Language': 'en-US,en;q=0.9', 'X-Requested-With': 'XMLHttpRequest', ...customHeaders }; if (config.stealthMode.fakeIP) { headers["X-Forwarded-For"] = Utils.random.getRandomIP(); headers["X-Real-IP"] = Utils.random.getRandomIP(); } return headers; }, generateFakeUserAgent: function() { const agents = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/115.0", "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" ]; return agents[Utils.random.getRandomInt(0, agents.length - 1)]; } }, security: { encryptData: function(data, key = CRYPTO_KEYS.primary) { try { return CryptoJS.AES.encrypt(JSON.stringify(data), key).toString(); } catch (e) { Utils.debug.error("Error en encryptData:", e); return JSON.stringify(data); } }, decryptData: function(data, key = CRYPTO_KEYS.primary) { try { const bytes = CryptoJS.AES.decrypt(data, key); return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); } catch (e) { Utils.debug.error("Error en decryptData:", e); try { return JSON.parse(data); } catch (pe) { return data; } } }, protectFromDetection: function() { if (!config.stealthMode.enabled) return; try { Object.defineProperty(navigator, 'webdriver', { get: () => false }); Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] }); // Un poco más creíble Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); if (config.stealthMode.fakeScreenResolution) { Object.defineProperty(screen, 'width', { get: () => 1920, configurable: true }); Object.defineProperty(screen, 'height', { get: () => 1080, configurable: true }); Object.defineProperty(screen, 'availWidth', { get: () => 1920, configurable: true }); Object.defineProperty(screen, 'availHeight', { get: () => 1040, configurable: true }); // Considerar barra de tareas Object.defineProperty(screen, 'colorDepth', { get: () => 24, configurable: true }); Object.defineProperty(screen, 'pixelDepth', { get: () => 24, configurable: true }); } if (config.stealthMode.fakeUserAgent && navigator.userAgent) { Object.defineProperty(navigator, 'userAgent', { get: () => Utils.network.generateFakeUserAgent(), configurable: true }); } if (config.stealthMode.fakeTimeZone) { const originalDateTimeFormat = Intl.DateTimeFormat; Intl.DateTimeFormat = function(...args) { if (args.length === 0 || (args.length === 1 && args[0] === undefined)) { return new originalDateTimeFormat('en-US', { timeZone: 'America/New_York' }); } return new originalDateTimeFormat(...args); }; Intl.DateTimeFormat.prototype.resolvedOptions = function() { return { ...originalDateTimeFormat.prototype.resolvedOptions.call(this), timeZone: 'America/New_York' }; }; } if (config.stealthMode.fakeGeolocation && navigator.geolocation) { Object.defineProperty(navigator, 'geolocation', { get: function() { return { getCurrentPosition: function(success, error, options) { success({ coords: { latitude: 40.712776 + (Math.random() - 0.5) * 0.01, // NY con pequeña variación longitude: -74.005974 + (Math.random() - 0.5) * 0.01, accuracy: Utils.random.getRandomInt(5,50), altitude: null, altitudeAccuracy: null, heading: null, speed: null }, timestamp: Date.now() - Utils.random.getRandomInt(0,1000) }); }, watchPosition: function(success, error, options) { return Utils.random.getRandomInt(1,10000); }, clearWatch: function(id) {} }; }, configurable: true }); } if (typeof unsafeWindow !== 'undefined') { unsafeWindow.TamperMonkey = undefined; unsafeWindow.GM_info = undefined; unsafeWindow.GM = undefined; } else { window.TamperMonkey = undefined; window.GM_info = undefined; window.GM = undefined; } Utils.debug.log("Modo sigiloso activado"); } catch (e) { Utils.debug.error("Error al activar modo sigiloso:", e); } } }, random: { getRandomInt: function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }, getRandomString: function(length = 8) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; }, getRandomHexColor: function() { return `#${Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0')}`; }, getRandomIP: function() { return `${this.getRandomInt(1, 223)}.${this.getRandomInt(0, 255)}.${this.getRandomInt(0, 255)}.${this.getRandomInt(1, 254)}`; // Evitar IPs especiales } }, time: { sleep: function(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, waitForElement: function(selector, timeout = 5000, interval = 100) { return new Promise((resolve, reject) => { const endTime = Date.now() + timeout; const check = () => { const element = document.querySelector(selector); if (element) { resolve(element); } else if (Date.now() >= endTime) { reject(new Error(`Element ${selector} not found after ${timeout}ms`)); } else { setTimeout(check, interval); } }; check(); }); }, waitForFunction: function(fn, timeout = 5000, interval = 100) { return new Promise((resolve, reject) => { const endTime = Date.now() + timeout; const check = () => { try { const result = fn(); if (result) { resolve(result); } else if (Date.now() >= endTime) { reject(new Error(`Function did not return truthy value after ${timeout}ms`)); } else { setTimeout(check, interval); } } catch (e) { reject(e); } }; check(); }); }, formatDuration: function(ms) { if (ms < 0) ms = 0; if (ms < 1000) return `${ms}ms`; if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`; const minutes = Math.floor(ms / 60000); const seconds = Math.floor((ms % 60000) / 1000); if (ms < 3600000) return `${minutes}m ${seconds}s`; const hours = Math.floor(ms / 3600000); return `${hours}h ${minutes % 60}m`; } }, storage: { get: function(key, defaultValue = null) { try { const value = GM_getValue(key); if (value === undefined || value === null) return defaultValue; return Utils.security.decryptData(value); } catch (e) { Utils.debug.error(`Error al obtener clave ${key}:`, e); return defaultValue; } }, set: function(key, value) { try { const encrypted = Utils.security.encryptData(value); GM_setValue(key, encrypted); return true; } catch (e) { Utils.debug.error(`Error al establecer clave ${key}:`, e); return false; } }, remove: function(key) { try { GM_deleteValue(key); return true; } catch (e) { Utils.debug.error(`Error al eliminar clave ${key}:`, e); return false; } }, clear: function() { try { const keys = GM_listValues(); keys.forEach(key => GM_deleteValue(key)); Utils.debug.log("Almacenamiento limpiado."); return true; } catch (e) { Utils.debug.error("Error al limpiar almacenamiento:", e); return false; } } }, ui: { showNotification: function(message, duration = 3000, type = 'info') { if (!config.uiConfig.showNotifications) return; const notification = document.createElement('div'); notification.style.position = 'fixed'; notification.style.bottom = '70px'; notification.style.right = '20px'; notification.style.backgroundColor = type === 'error' ? '#d32f2f' : type === 'success' ? '#388e3c' : '#1976d2'; notification.style.color = 'white'; notification.style.padding = '10px 15px'; notification.style.borderRadius = '5px'; notification.style.zIndex = '2147483647'; notification.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)'; notification.style.fontFamily = 'Arial, sans-serif'; notification.style.fontSize = '14px'; notification.textContent = message; if (document.body) { document.body.appendChild(notification); } else { // Fallback si el body no está listo const tempParent = document.documentElement || document; tempParent.appendChild(notification); } gsap.from(notification, { opacity: 0, y: 20, duration: 0.3 }); setTimeout(() => { gsap.to(notification, { opacity: 0, y: -20, duration: 0.3, onComplete: () => { if (notification.parentNode) notification.parentNode.removeChild(notification); } }); }, duration); }, createToast: function(message, type = 'info', duration = 3000) { this.showNotification(message, duration, type); // Reutilizar showNotification para toasts }, createModal: function(title, content, buttons = []) { const modalOverlay = document.createElement('div'); modalOverlay.style.position = 'fixed'; modalOverlay.style.top = '0'; modalOverlay.style.left = '0'; modalOverlay.style.width = '100%'; modalOverlay.style.height = '100%'; modalOverlay.style.backgroundColor = 'rgba(0,0,0,0.7)'; modalOverlay.style.zIndex = '2147483646'; modalOverlay.style.display = 'flex'; modalOverlay.style.justifyContent = 'center'; modalOverlay.style.alignItems = 'center'; const modalContent = document.createElement('div'); modalContent.style.backgroundColor = config.uiConfig.theme === 'dark' ? '#333' : '#fff'; modalContent.style.color = config.uiConfig.theme === 'dark' ? '#eee' : '#333'; modalContent.style.padding = '25px'; modalContent.style.borderRadius = '8px'; modalContent.style.maxWidth = '90%'; modalContent.style.width = '500px'; modalContent.style.maxHeight = '80vh'; modalContent.style.overflowY = 'auto'; modalContent.style.boxShadow = '0 5px 15px rgba(0,0,0,0.3)'; modalContent.style.fontFamily = 'Arial, sans-serif'; const modalTitle = document.createElement('h2'); modalTitle.textContent = title; modalTitle.style.marginTop = '0'; modalTitle.style.color = config.uiConfig.theme === 'dark' ? '#ff7070' : '#d32f2f'; modalTitle.style.borderBottom = `1px solid ${config.uiConfig.theme === 'dark' ? '#555' : '#ddd'}`; modalTitle.style.paddingBottom = '10px'; modalTitle.style.marginBottom = '15px'; modalTitle.style.fontSize = '1.5em'; const modalBody = document.createElement('div'); if (typeof content === 'string') { modalBody.innerHTML = content; } else if (content instanceof HTMLElement) { modalBody.appendChild(content); } modalBody.style.fontSize = '1em'; modalBody.style.lineHeight = '1.6'; const modalFooter = document.createElement('div'); modalFooter.style.marginTop = '25px'; modalFooter.style.display = 'flex'; modalFooter.style.justifyContent = 'flex-end'; modalFooter.style.gap = '10px'; buttons.forEach(buttonConfig => { const btn = document.createElement('button'); btn.textContent = buttonConfig.text; btn.style.padding = '10px 20px'; btn.style.borderRadius = '5px'; btn.style.border = 'none'; btn.style.cursor = 'pointer'; btn.style.fontWeight = 'bold'; btn.style.fontSize = '0.9em'; btn.style.transition = 'background-color 0.2s, transform 0.1s'; if (buttonConfig.primary) { btn.style.backgroundColor = config.uiConfig.theme === 'dark' ? '#ff7070' : '#d32f2f'; btn.style.color = 'white'; } else { btn.style.backgroundColor = config.uiConfig.theme === 'dark' ? '#555' : '#eee'; btn.style.color = config.uiConfig.theme === 'dark' ? '#eee' : '#333'; btn.style.border = `1px solid ${config.uiConfig.theme === 'dark' ? '#666' : '#ccc'}`; } btn.onmouseover = () => btn.style.opacity = '0.8'; btn.onmouseout = () => btn.style.opacity = '1'; btn.onmousedown = () => btn.style.transform = 'scale(0.98)'; btn.onmouseup = () => btn.style.transform = 'scale(1)'; btn.addEventListener('click', () => { if (typeof buttonConfig.action === 'function') buttonConfig.action(); if (buttonConfig.closeModal !== false) { if (modalOverlay.parentNode) modalOverlay.parentNode.removeChild(modalOverlay); } }); modalFooter.appendChild(btn); }); if (buttons.length === 0) { // Add a default close button if none provided const closeBtn = document.createElement('button'); closeBtn.textContent = 'Close'; closeBtn.style.padding = '10px 20px'; closeBtn.style.borderRadius = '5px'; closeBtn.style.border = 'none'; closeBtn.style.cursor = 'pointer'; closeBtn.style.backgroundColor = config.uiConfig.theme === 'dark' ? '#555' : '#eee'; closeBtn.style.color = config.uiConfig.theme === 'dark' ? '#eee' : '#333'; closeBtn.addEventListener('click', () => { if (modalOverlay.parentNode) modalOverlay.parentNode.removeChild(modalOverlay); }); modalFooter.appendChild(closeBtn); } modalContent.appendChild(modalTitle); modalContent.appendChild(modalBody); modalContent.appendChild(modalFooter); modalOverlay.appendChild(modalContent); if (document.body) { document.body.appendChild(modalOverlay); } else { (document.documentElement || document).appendChild(modalOverlay); } gsap.from(modalOverlay, { opacity: 0, duration: 0.2 }); gsap.from(modalContent, { opacity: 0, y: -30, duration: 0.3, delay: 0.1 }); return modalOverlay; } }, performance: { startTimer: function(name) { PERFORMANCE_MARKS[name] = { start: performance.now(), end: null, duration: null }; }, endTimer: function(name) { if (PERFORMANCE_MARKS[name] && PERFORMANCE_MARKS[name].start) { PERFORMANCE_MARKS[name].end = performance.now(); PERFORMANCE_MARKS[name].duration = PERFORMANCE_MARKS[name].end - PERFORMANCE_MARKS[name].start; } else { Utils.debug.warn(`Timer "${name}" no fue iniciado o ya fue finalizado.`); } }, getMetrics: function() { return { memory: this.getMemoryUsage(), timing: this.getTimingMetrics(), resources: this.getResourceUsage() }; }, getMemoryUsage: function() { if (performance.memory) { return { jsHeapSizeLimit: performance.memory.jsHeapSizeLimit, totalJSHeapSize: performance.memory.totalJSHeapSize, usedJSHeapSize: performance.memory.usedJSHeapSize }; } return { note: "performance.memory not supported" }; }, getTimingMetrics: function() { const timing = {}; for (const [name, mark] of Object.entries(PERFORMANCE_MARKS)) { if (mark.duration !== null) { timing[name] = mark.duration; } } return timing; }, getResourceUsage: function() { const elements = { total: document.getElementsByTagName('*').length, divs: document.getElementsByTagName('div').length, scripts: document.getElementsByTagName('script').length, iframes: document.getElementsByTagName('iframe').length, images: document.getElementsByTagName('img').length }; const requests = SESSION_CACHE.networkRequests.length; return { elements, requests }; }, optimizePage: function() { if (!config.performanceMode.enabled) return; Utils.debug.log("Iniciando optimización de página..."); if (config.performanceMode.removeAds) { RuleEngine.applyRules(['adBlock']); } if (config.performanceMode.blockThirdParty) { this.blockThirdPartyRequests(); // Note: This sets up an observer, doesn't block retroactively. } if (config.performanceMode.disableAnimations) { this.disableAnimations(); } if (config.performanceMode.lazyLoadImages) { this.enableLazyLoading(); } if (config.performanceMode.disableWebFonts) { this.disableWebFonts(); } Utils.debug.log("Optimización de página completada"); }, blockThirdPartyRequests: function() { // This is complex to implement robustly in a userscript for *blocking*. // GM_xmlhttpRequest is already used, which can be controlled. // For resources loaded by the page (img, script src), it's harder. // A more realistic approach is to *monitor* and report, or try to remove elements from third parties. Utils.debug.log("Monitoreo de solicitudes de terceros activado (no bloqueo activo)."); if (typeof PerformanceObserver !== 'undefined') { const observer = new PerformanceObserver((list) => { list.getEntries().forEach(entry => { try { const url = new URL(entry.name); if (url.hostname !== window.location.hostname) { SESSION_CACHE.networkRequests.push(entry); Utils.debug.log(`Solicitud de terceros detectada (PerformanceObserver): ${entry.name}`); } } catch(e) { /* Ignore invalid URLs */ } }); }); observer.observe({ entryTypes: ["resource"] }); } }, disableAnimations: function() { const styles = ` *, *::before, *::after { transition-property: none !important; transition-duration: 0s !important; transition-delay: 0s !important; animation-name: none !important; animation-duration: 0s !important; animation-delay: 0s !important; scroll-behavior: auto !important; } `; Utils.dom.addStyles(styles); Utils.debug.log("Animaciones deshabilitadas."); }, enableLazyLoading: function() { document.querySelectorAll('img:not([loading])').forEach(img => { img.loading = 'lazy'; }); document.querySelectorAll('iframe:not([loading])').forEach(iframe => { iframe.loading = 'lazy'; }); Utils.debug.log("Lazy loading habilitado para imágenes e iframes."); }, disableWebFonts: function() { const styles = ` @font-face { font-family: 'DigitualForceDefault'; /* Nombre único para evitar conflictos */ src: local('Arial'), local('Helvetica'), local('sans-serif'); /* Fuentes comunes del sistema */ unicode-range: U+000-5FF; /* Rango amplio para cubrir la mayoría de los caracteres occidentales */ } * { font-family: 'DigitualForceDefault', sans-serif !important; } `; Utils.dom.addStyles(styles); Utils.debug.log("Fuentes web deshabilitadas (intentado)."); } }, compatibility: { checkFeatures: function() { const features = { GM_xmlhttpRequest: typeof GM_xmlhttpRequest !== 'undefined', GM_setValue: typeof GM_setValue !== 'undefined', GM_addStyle: typeof GM_addStyle !== 'undefined', gsap: typeof gsap !== 'undefined', CryptoJS: typeof CryptoJS !== 'undefined', jQuery: typeof jQuery !== 'undefined', lodash: typeof _ !== 'undefined', MutationObserver: typeof MutationObserver !== 'undefined', PerformanceObserver: typeof PerformanceObserver !== 'undefined' }; Utils.debug.log("Compatibilidad de características:", features); return features; }, addPolyfills: function() { let polyfillsAdded = false; if (!Element.prototype.remove) { Element.prototype.remove = function() { if (this.parentNode) { this.parentNode.removeChild(this); } }; polyfillsAdded = true; } if (typeof NodeList !== 'undefined' && NodeList.prototype && !NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; polyfillsAdded = true; } if (!String.prototype.includes) { String.prototype.includes = function(search, start) { 'use strict'; if (typeof start !== 'number') { start = 0; } if (start + search.length > this.length) { return false; } else { return this.indexOf(search, start) !== -1; } }; polyfillsAdded = true; } if (polyfillsAdded) { Utils.debug.log("Polyfills añadidos donde era necesario."); } } } }; const PaywallBypass = { bypassAll: async function() { if (!config.bypassMethods.paywalls) return; Utils.debug.log("Iniciando bypass de paywalls..."); Utils.performance.startTimer('paywall_bypass_all'); try { RuleEngine.applyRules(['paywall']); await this.bypassForCurrentSite(); await this.tryAlternateMethods(); this.enableBlockedFeatures(); Utils.debug.log("Bypass de paywalls completado"); Utils.ui.showNotification("Paywalls eliminados con éxito", 3000, 'success'); } catch (e) { Utils.debug.error("Error en bypass de paywalls:", e); Utils.ui.showNotification("Error al eliminar paywalls", 3000, 'error'); } finally { Utils.performance.endTimer('paywall_bypass_all'); } }, bypassForCurrentSite: async function() { const hostname = window.location.hostname; Utils.debug.log(`Intentando bypass específico para: ${hostname}`); if (hostname.includes('medium.com')) await this.bypassMedium(); else if (hostname.includes('nytimes.com')) await this.bypassNYT(); // Añadir más sitios aquí si es necesario, ej: // else if (hostname.includes('bloomberg.com')) await this.bypassBloomberg(); // else if (hostname.includes('wsj.com')) await this.bypassWSJ(); else { Utils.debug.log(`No hay bypass específico para ${hostname}. Se usarán métodos genéricos.`); } }, bypassMedium: async function() { Utils.debug.log("Ejecutando bypass específico para Medium"); Utils.dom.remove('[data-testid="paywall-background"]'); Utils.dom.remove('[data-testid="paywall-container"]'); Utils.dom.remove('.meteredContent'); Utils.dom.overrideStyles('body, html', { overflow: 'auto !important' }); window.onscroll = null; // Intentar eliminar manejadores de scroll // Podría intentar buscar el contenido en `window.__APOLLO_STATE__` o similar }, bypassNYT: async function() { Utils.debug.log("Ejecutando bypass específico para NYTimes"); Utils.dom.remove('#gateway-content'); Utils.dom.remove('.css-1bd8bfl'); // Selector común para el overlay Utils.dom.remove('[data-testid="gateway-container"]'); Utils.dom.overrideStyles('body, html', { overflow: 'auto !important' }); document.cookie = "NYT-S=0; path=/; domain=.nytimes.com; expires=Thu, 01 Jan 1970 00:00:00 GMT"; // Intenta limpiar cookies de paywall }, tryAlternateMethods: async function() { Utils.debug.log("Probando métodos alternativos de bypass..."); if (await this.tryCachedVersion()) return; // if (await this.tryAMPVersion()) return; // AMP a menudo es menos útil o no existe // if (await this.tryArchiveToday()) return; // Archive.today es lento y puede tener captchas }, tryCachedVersion: async function() { Utils.debug.log("Intentando cargar versión de caché de Google..."); try { const cachedUrl = `https://webcache.googleusercontent.com/search?q=cache:${encodeURIComponent(window.location.href)}`; const response = await Utils.network.fetchWithProxy(cachedUrl, { method: 'GET' }); if (response.status === 200 && response.responseText) { const parser = new DOMParser(); const doc = parser.parseFromString(response.responseText, 'text/html'); const mainContentSelectors = ['article', '#main', '#content', '.main-content', '.article-body', 'main']; let contentElement = null; for (const selector of mainContentSelectors) { contentElement = doc.querySelector(selector); if (contentElement) break; } if (contentElement && contentElement.innerHTML.length > 500) { // Heurística simple Utils.debug.log("Contenido encontrado en caché de Google. Reemplazando cuerpo de la página..."); document.body.innerHTML = `<h1>Contenido cargado desde Google Cache</h1>${contentElement.innerHTML}`; Utils.dom.addStyles("body { padding: 20px; font-family: sans-serif; } h1 { color: #555; border-bottom: 1px solid #ccc; padding-bottom: 10px; }"); return true; } } Utils.debug.log("No se encontró contenido útil en caché de Google."); } catch (e) { Utils.debug.error("Error al intentar cargar versión cacheada:", e); } return false; }, enableBlockedFeatures: function() { if (config.bypassMethods.textSelection) Utils.dom.enableTextSelection(); if (config.bypassMethods.rightClick) Utils.dom.enableRightClick(); if (config.bypassMethods.inspectElement) Utils.dom.enableInspectElement(); }, handleNewElements: function(nodeList) { // Para MutationObserver if (!nodeList || nodeList.length === 0) return; nodeList.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { // Re-aplicar reglas a los nuevos elementos si es necesario // Esto puede ser costoso, usar con cuidado o con selectores más específicos if (this.detectPaywallElement(node)) { Utils.debug.log("Nuevo elemento de paywall detectado y eliminado:", node); if (node.parentNode) node.parentNode.removeChild(node); } } }); }, detectPaywallElement: function(element) { // Chequea un elemento específico if (!element || typeof element.matches !== 'function') return false; const paywallSelectors = RuleEngine.selectors.paywall || []; return paywallSelectors.some(selector => { try { return element.matches(selector); } catch(e) { return false; } }); } }; const RegionBypass = { bypassAll: async function() { if (!config.bypassMethods.regionBlocks) return; Utils.debug.log("Iniciando bypass de bloqueo regional..."); RuleEngine.applyRules(['regionBlock']); // La lógica de bypass regional a menudo implica el uso de proxies para la solicitud inicial // o modificar cabeceras, lo cual Utils.network.fetchWithProxy ya intenta. // Un bypass regional más avanzado requeriría proxies específicos por región, // lo cual está fuera del alcance simple de este script. Utils.ui.showNotification("Intento de bypass regional aplicado.", 3000, 'info'); } }; const AntiAdblockBypass = { bypassAll: async function() { if (!config.bypassMethods.antiAdBlock) return; Utils.debug.log("Iniciando bypass de anti-adblock..."); // Eliminar selectores comunes de mensajes anti-adblock const antiAdblockSelectors = [ '[class*="adblock"]', '[id*="adblock"]', '[class*="blocker"]', '[id*="blocker"]', '.adblock-message', '.please-disable-adblock' ]; antiAdblockSelectors.forEach(selector => Utils.dom.remove(selector)); // Algunas páginas pueden tener scripts más sofisticados. // Esto es un intento básico. Utils.ui.showNotification("Intento de bypass anti-adblock aplicado.", 3000, 'info'); } }; const AdvancedUI = { init: function() { if (!config.uiConfig.enabled) return; Utils.debug.log("Inicializando UI avanzada..."); // Aquí se podrían registrar comandos de menú de Tampermonkey, crear un panel de control, etc. // Ejemplo: GM_registerMenuCommand("Configuración de Digitual", this.showSettingsModal); }, showSettingsModal: function() { // Implementación de un modal de configuración // Utils.ui.createModal("Configuración de Digitual", "Aquí irían las opciones...", [{text: "Guardar", action: () => {}, primary: true}]); }, cleanup: function() { // Limpiar elementos de UI si es necesario } }; const MachineLearning = { init: function() { if (!config.learningMode) return; Utils.debug.log("Módulo de aprendizaje automático (simulado) inicializado."); // En una implementación real, esto cargaría modelos, recolectaría datos anónimos (con consentimiento), etc. } }; function initialize() { Utils.debug.log(`Inicializando Digitual v${config.version}...`); Utils.performance.startTimer('full_initialization'); Utils.compatibility.checkFeatures(); Utils.compatibility.addPolyfills(); loadConfig(); // Cargar configuración guardada por el usuario Utils.security.protectFromDetection(); // Aplicar medidas de sigilo temprano RuleEngine.init(); AdvancedUI.init(); MachineLearning.init(); if (config.autoBypass) { if (config.bypassMethods.paywalls) PaywallBypass.bypassAll(); if (config.bypassMethods.regionBlocks) RegionBypass.bypassAll(); if (config.bypassMethods.antiAdBlock) AntiAdblockBypass.bypassAll(); } if (config.performanceMode.enabled) { Utils.performance.optimizePage(); } setupObservers(); Utils.debug.log("Digitual completamente inicializado."); Utils.performance.endTimer('full_initialization'); const initTime = PERFORMANCE_MARKS.full_initialization ? PERFORMANCE_MARKS.full_initialization.duration : null; if (initTime) { Utils.debug.log(`Tiempo de inicialización: ${Utils.time.formatDuration(initTime)}`); } Utils.ui.showNotification(`Digitual v${config.version} activado.`, 2000, 'success'); } function loadConfig() { const savedConfig = Utils.storage.get(LOCAL_STORAGE_KEY); if (savedConfig && typeof savedConfig === 'object') { try { // Fusionar de forma segura para no sobrescribir toda la estructura si hay nuevas claves en `config` for (const key in config) { if (savedConfig.hasOwnProperty(key) && typeof savedConfig[key] === typeof config[key]) { if (typeof config[key] === 'object' && !Array.isArray(config[key]) && config[key] !== null) { Object.assign(config[key], savedConfig[key]); } else { config[key] = savedConfig[key]; } } } Utils.debug.log("Configuración cargada desde almacenamiento:", config); } catch (e) { Utils.debug.error("Error al cargar o fusionar configuración:", e); } } else { Utils.debug.log("No se encontró configuración guardada o es inválida, usando valores por defecto."); } } function setupObservers() { if (typeof MutationObserver === "undefined") { Utils.debug.warn("MutationObserver no está disponible. Algunas funciones dinámicas pueden no funcionar."); return; } const observer = new MutationObserver(mutations => { if (PaywallBypass.handleNewElements) { // Asegurarse que la función existe PaywallBypass.handleNewElements(mutations.flatMap(m => Array.from(m.addedNodes))); } // Aquí se podrían añadir más manejadores para otros tipos de bypass si es necesario }); // Observar el body es un buen compromiso, observar documentElement puede ser demasiado. // Esperar a que el body exista. const observeBody = () => { if (document.body) { observer.observe(document.body, { childList: true, subtree: true }); DOM_OBSERVERS.push(observer); Utils.debug.log("MutationObserver iniciado en document.body."); } else { setTimeout(observeBody, 100); // Reintentar pronto } }; observeBody(); } function cleanup() { Utils.debug.log("Realizando limpieza de Digitual..."); DOM_OBSERVERS.forEach(observer => observer.disconnect()); DOM_OBSERVERS.length = 0; // Vaciar el array AdvancedUI.cleanup(); Utils.debug.log("Limpieza completada."); } // Manejo de la inicialización según el estado del documento if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { // Si 'interactive' o 'complete', es seguro inicializar. // 'document-start' es muy temprano para algunas operaciones DOM. // Esperar un poco para asegurar que el entorno esté más estable. setTimeout(initialize, 0); } window.addEventListener('beforeunload', cleanup); // 'unload' es menos fiable que 'beforeunload' para tareas de limpieza. // Exportar API para desarrollo si está en modo debug if (config.debugMode) { const digitualAPI = { config, Utils, PaywallBypass, RegionBypass, AntiAdblockBypass, RuleEngine, loadConfig, initialize, cleanup }; if (typeof unsafeWindow !== 'undefined') { unsafeWindow.__DIGITUAL_API = digitualAPI; } else { window.__DIGITUAL_API = digitualAPI; } Utils.debug.log("API de Digitual exportada a window.__DIGITUAL_API"); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址