您需要先安装一个扩展,例如 篡改猴、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或关注我们的公众号极客氢云获取最新地址