// ==UserScript== // @name RU AdList JS Fixes // @namespace ruadlist_js_fixes // @version 20170512.0 // @description try to take over the world! // @author lainverse & dimisa // @match *://*/* // @grant unsafeWindow // @grant window.close // @grant GM_getValue // @grant GM_setValue // @run-at document-start // @downloadURL none // ==/UserScript== (function() { 'use strict'; var win = (unsafeWindow || window), // http://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0, isChrome = !!window.chrome && !!window.chrome.webstore, isSafari = (Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window.safari || safari.pushNotification)), isFirefox = typeof InstallTrigger !== 'undefined', _getAttribute = Element.prototype.getAttribute, _setAttribute = Element.prototype.setAttribute, _de = document.documentElement, _appendChild = Document.prototype.appendChild.bind(_de), _removeChild = Document.prototype.removeChild.bind(_de); // NodeList iterator polyfill (mostly for Safari) // https://jakearchibald.com/2014/iterators-gonna-iterate/ if (!NodeList.prototype[Symbol.iterator]) { NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; } // Options var opts = { 'useWSIFunc': useWSI }; (function(){ function optsCall(callback) { // Register event listener var key = "optsCallEvent_" + Math.random().toString(36).substr(2), cb = callback.func.bind(callback.name); window.addEventListener(key, cb, false); // Generate and dispatch synthetic event var ev = document.createEvent("HTMLEvents"); ev.initEvent(key, true, false); window.dispatchEvent(ev); // Remove listener window.removeEventListener(key, cb, false); } function initOptsHandler() { /*jshint validthis:true */ opts[this] = GM_getValue(this, true); if(opts[this]) { opts[this+'Func'](); } } optsCall({ func: initOptsHandler, name: 'useWSI' }); // show options page function openOptions() { var ovl = document.createElement('div'), inner = document.createElement('div'); ovl.style = ( 'position: fixed;'+ 'top:0; left:0;'+ 'bottom: 0; right: 0;'+ 'background: rgba(0,0,0,0.85);'+ 'z-index: 2147483647;'+ 'padding: 5em' ); inner.style = ( 'background: whitesmoke;'+ 'font-size: 10pt;'+ 'color: black;'+ 'padding: 1em' ); inner.textContent = 'JS Fixes Options: (reload page to apply)'; inner.appendChild(document.createElement('br')); inner.appendChild(document.createElement('br')); ovl.addEventListener('click', function(e){ if (e.target === ovl) { ovl.parentNode.removeChild(ovl); e.preventDefault(); } e.stopPropagation(); }, false); // append checkbox with label function function addCheckbox(optName, optLabel) { var c = document.createElement('input'), l = document.createElement('label'); c.type = 'checkbox'; c.id = optName; optsCall({ func:function(){ c.checked = GM_getValue(this); }, name:optName }); c.addEventListener('click', function(e) { optsCall({ func:function(){ GM_setValue(this, e.target.checked); opts[this] = e.target.checked; }, name:optName }); }, true); l.textContent = optLabel; l.setAttribute('for', optName); inner.appendChild(c); inner.appendChild(l); inner.appendChild(document.createElement('br')); } // append checkboxes addCheckbox('useWSI', 'Use WebSocket filter. Disable if experience problems with WebSocket connections.'); document.body.appendChild(ovl); ovl.appendChild(inner); } // monitor keys pressed for Ctrl+Alt+Shift+J > s > f code var opPos = 0, opKey = 'Jsf', isNotKey; document.addEventListener('keydown', function(e) { isNotKey = (e.key.length > 1); if ((e.key === opKey[opPos] || isNotKey) && (!!opPos || e.altKey && e.ctrlKey)) { opPos += (isNotKey ? 0 : 1); e.stopPropagation(); e.preventDefault(); } else { opPos = 0; } if (opPos === opKey.length) { opPos = 0; openOptions(); } }, false); })(); // Special wrapper script to run scripts designed to override standard DOM functions // In Firefox appends supplied script to a page to make it run in page context and let // page content access overridden functions. In other browsers just run it as-is. function scriptLander(func, prepend) { if (!isFirefox) { func(); return; } var s = document.createElement('script'); s.textContent = '(function(){' + ( prepend && prepend.join('') || '' ) + '!' + func + '();})();'; _appendChild(s); _removeChild(s); } // Creates and return protected style (unless protection is manually disabled). // Protected style will re-add itself on removal and remaind enabled on attempt to disable it. function createStyle(rules, props, skip_protect) { var prop = '', root = _de; function _createGetterSetter(obj) { return { get: function() {return obj;}, //pretend to be empty set: function() {}, enumerable: true }; } function _protect(style) { Object.defineProperty(style, 'sheet', { value: style.sheet, enumerable: true }); for (prop of ['rules', 'cssRules']) { Object.defineProperty(style.sheet, prop, _createGetterSetter([])); } Object.defineProperty(style, 'disabled', { get: function() {return true;}, //pretend to be disabled set: function() {}, enumerable: true }); var o = new MutationObserver(function() { root.removeChild(style); }); o.observe(style, {childList: true}); } function _create() { var style = root.appendChild(document.createElement('style')), prop, rule; style.type = 'text/css'; for (prop in props) { if (style[prop] !== undefined) { style[prop] = props[prop]; } } function insertRule(rule) { try { style.sheet.insertRule(rule, 0); } catch (e) { console.error(e); } } if (typeof rules === 'string') { insertRule(rules); } else { rules.forEach(insertRule); } if (!skip_protect) { _protect(style); } return style; } var style = _create(); if (skip_protect) { return style; } var o = new MutationObserver(function(ms){ var m, node, rule; for (m of ms) { for (node of m.removedNodes) { if (node === style) { (new Promise(function(resolve){ setTimeout(function(resolve){ resolve(_create()); }, 0, resolve); })).then(function(st){ style = st; }); } } } }); o.observe(root, {childList:true}); return style; } // https://greasyfork.org/scripts/19144-websuckit/ function useWSI() { // check does browser support Proxy and WebSocket if (typeof Proxy !== 'function' || typeof WebSocket !== 'function') { return; } function getWrappedCode(removeSelf) { var text = getWrappedCode.toString()+WSI.toString(); text = ( '(function(){"use strict";'+ text.replace(/\/\/[^\r\n]*/g,'').replace(/[\s\r\n]+/g,' ')+ '(new WSI(self||window)).init();'+ '})();\n'+ (removeSelf?'var s = document.currentScript; if (s) {s.parentNode.removeChild(s);}':'') ); return text; } function WSI(win, safeWin) { safeWin = safeWin || win; var masks = [], filter; for (filter of [// blacklist '||10root25.website^', '||24video.xxx^', '||adlabs.ru^', '||adspayformymortgage.win^', '||aviabay.ru^', '||bgrndi.com^', '||brokeloy.com^', '||cnamerutor.ru^', '||docfilms.info^', '||dreadfula.ru^', '||et-code.ru^', '||film-doma.ru^', '||free-torrent.org^', '||free-torrent.pw^', '||free-torrents.org^', '||free-torrents.pw^', '||game-torrent.info^', '||gocdn.ru^', '||hdkinoshka.com^', '||hghit.com^', '||hindcine.net^', '||kiev.ua^', '||kinotochka.net^', '||kinott.com^', '||kinott.ru^', '||kuveres.com^', '||lepubs.com^', '||luxadv.com^', '||luxup.ru^', '||luxupcdna.com^', '||mail.ru^', '||marketgid.com^', '||mixadvert.com^', '||mxtads.com^', '||nickhel.com^', '||oconner.biz^', '||oconner.link^', '||pkpojhc.com^', '||psma01.com^', '||psma02.com^', '||psma03.com^', '||recreativ.ru^', '||redtram.com^', '||regpole.com^', '||rootmedia.ws^', '||ruttwind.com^', '||skidl.ru^', '||torvind.com^', '||traffic-media.co^', '||trafmag.com^', '||webadvert-gid.ru^', '||webadvertgid.ru^', '||xxuhter.ru^', '||yuiout.online^', '||zoom-film.ru^' ]) { masks.push(new RegExp( filter.replace(/([\\\/\[\].*+?(){}$])/g, '\\$1') .replace(/\^(?!$)/g,'\\.?[^\\w%._-]') .replace(/\^$/,'\\.?([^\\w%._-]|$)') .replace(/^\|\|/,'^(ws|http)s?:\\/+([^\/.]+\\.)*'), 'i')); } function isBlocked(url) { for (var mask of masks) { if (mask.test(url)) { return true; } } return false; } var realWebSocket = win.WebSocket; function wsGetter (target, name) { try { if (typeof realWebSocket.prototype[name] === 'function') { if (name === 'close' || name === 'send') { // send also closes connection target.readyState = realWebSocket.CLOSED; } return ( function fake() { console.log('[WSI] Invoked function "'+name+'"', '| Tracing', (new Error())); return; } ); } if (typeof realWebSocket.prototype[name] === 'number') { return realWebSocket[name]; } } catch(ignore) {} return target[name]; } function createWebSocketWrapper(target) { return new Proxy(realWebSocket, { construct: function (target, args) { var url = args[0]; console.log('[WSI] Opening socket on ' + url + ' \u2026'); if (isBlocked(url)) { console.log("[WSI] Blocked."); return new Proxy({ url: url, readyState: realWebSocket.OPEN }, { get: wsGetter }); } return new target(args[0], args[1]); } }); } function WorkerWrapper() { var realWorker = win.Worker; function wrappedWorker(resourceURI) { var isBlobURL = /^blob:/i, xhr = null, _callbacks = new WeakMap(), _worker = null, _terminate = false, _onerror = null, _onmessage = null, _messages = [], _events = [], /*jshint validthis:true */ _self = this; function callbackWrapper(func) { if (typeof func !== 'function') { return undefined; } return ( function callback() { func.apply(_self, arguments); } ); } _self.terminate = function(){ _terminate = true; if (_worker) { _worker.terminate(); } }; Object.defineProperty(_self, 'onmessage', { get: function() { return _onmessage; }, set: function(val) { _onmessage = val; if (_worker) { _worker.onmessage = callbackWrapper(val); } } }); Object.defineProperty(_self, 'onerror', { get: function() { return _onerror; }, set: function(val) { _onerror = val; if (_worker) { _worker.onerror = callbackWrapper(val); } } }); _self.postMessage = function(message){ if (_worker) { _worker.postMessage(message); } else { _messages.push(message); } }; _self.terminate = function() { _terminate = true; if (_worker) { _worker.terminate(); } }; _self.addEventListener = function(){ if (typeof arguments[1] !== 'function') { return; } if (!_callbacks.has(arguments[1])) { _callbacks.set(arguments[1], callbackWrapper(arguments[1])); } arguments[1] = _callbacks.get(arguments[1]); if (_worker) { _worker.addEventListener.apply(_worker, arguments); } else { _events.push(['addEventListener', arguments]); } }; _self.removeEventListener = function(){ if (typeof arguments[1] !== 'function' || !_callbacks.has(arguments[1])) { return; } arguments[1] = _callbacks.get(arguments[1]); _callbacks.delete(arguments[1]); if (_worker) { _worker.removeEventListener.apply(_worker, arguments); } else { _events.push(['removeEventListener', arguments]); } }; if (!isBlobURL.test(resourceURI)) { _worker = new realWorker(resourceURI); return; // not a blob, no need to wrap } xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; try { xhr.open('GET', resourceURI, true); } catch(ignore) { _worker = new realWorker(resourceURI); return; // failed to open connection, unable to continue wrapping procedure } (new Promise(function(resolve, reject){ if (xhr.readyState !== XMLHttpRequest.OPENED) { // connection wasn't opened, unable to continue wrapping procedure return reject(); } xhr.onload = function(){ if (this.status === 200) { var reader = new FileReader(); reader.addEventListener("loadend", function() { resolve(new realWorker(URL.createObjectURL( new Blob([getWrappedCode(false)+this.result]) ))); }); reader.readAsText(this.response); } }; xhr.send(); })).then(function(val) { _worker = val; _worker.onerror = callbackWrapper(_onerror); _worker.onmessage = callbackWrapper(_onmessage); var _e; while(_events.length) { _e = _events.shift(); _worker[_e[0]].apply(_worker, _e[1]); } while(_messages.length) { _worker.postMessage(_messages.shift()); } if (_terminate) { _worker.terminate(); } }).catch(function(){}); } win.Worker = wrappedWorker.bind(safeWin); } function CreateElementWrapper() { var realCreateElement = Document.prototype.createElement, _addEventListener = Element.prototype.addEventListener, code = encodeURIComponent(''+getWrappedCode(true)+'\n'), isDataURL = /^data:/i, isBlobURL = /^blob:/i; function frameRewrite(e) { var f = e.target, w = f.contentWindow; if (!f.src || (w && isBlobURL.test(f.src))) { w.WebSocket = createWebSocketWrapper(); } if (isDataURL.test(f.src) && f.src.indexOf(code) < 0) { f.src = f.src.replace(',',',' + code); } } var scriptMap = new WeakMap(); scriptMap.isBlocked = isBlocked; var onErrorWrapper = { set: function(val) { if (scriptMap.has(this)) { this.removeEventListener('error', scriptMap.get(this).wrp, false); scriptMap.delete(this); } if (!val || typeof val !== 'function') { return val; } scriptMap.set(this, { org: val, wrp: function() { if (scriptMap.isBlocked(this.src)) { console.log('[WSI] Blocked "onerror" callback from', this); return; } scriptMap.get(this).org.apply(this, arguments); } }); this.addEventListener('error', scriptMap.get(this).wrp, false); return val; }, get: function() { return scriptMap.has(this) ? scriptMap.get(this).org : null; }, enumerable: true }; function wrappedCreateElement(name) { /*jshint validthis:true */ var el = realCreateElement.apply(this, arguments); if (el.tagName === 'IFRAME') { _addEventListener.call(el, 'load', frameRewrite, false); } if (el.tagName === 'SCRIPT') { Object.defineProperty(el, 'onerror', onErrorWrapper); } return el; } Document.prototype.createElement = wrappedCreateElement; document.addEventListener('DOMContentLoaded', function(){ for (var ifr of document.querySelectorAll('IFRAME')) { _addEventListener.call(ifr, 'load', frameRewrite, false); } }, false); } this.init = function() { win.WebSocket = createWebSocketWrapper(); if (!(/firefox/i.test(navigator.userAgent))) { WorkerWrapper(); // skip WorkerWrapper in Firefox } if (typeof document !== 'undefined') { CreateElementWrapper(); } }; } if (isFirefox) { var script = document.createElement('script'); script.appendChild(document.createTextNode(getWrappedCode(true))); document.head.insertBefore(script, document.head.firstChild); return; //we don't want to call functions on page from here in Fx, so exit } (new WSI((unsafeWindow||self||window),(self||window))).init(); } if (!isFirefox) { // scripts for non-Firefox browsers // https://greasyfork.org/scripts/14720-it-s-not-important (function(){ var imptt = /((display|(margin|padding)(-top|-bottom)?)\s*:[^;!]*)!\s*important/ig; function unimportanter(el, si) { if (!imptt.test(si) || el.style.display === 'none') { return 0; // get out if we have nothing to do here } if (el.nodeName === 'IFRAME' && el.src && el.src.slice(0,17) === 'chrome-extension:') { return 0; // Web of Trust uses this method to add their frame } var so = si.replace(imptt, function(){return arguments[1];}), ret = 0; if (si !== so) { ret = 1; _setAttribute.call(el, 'style', so); } return ret; } function logger(c) { if (c) { console.log('Some page elements became a bit less important.'); } } function checkTarget(node, cnt) { if (!(node && node.getAttribute)) { return 0; } var si = _getAttribute.call(node, 'style'); if (si && si.indexOf('!') > -1) { cnt += unimportanter(node, si); } return cnt; } var observer = new MutationObserver(function(mutations) { setTimeout(function(ms) { var cnt = 0, m, node; for (m of ms) { cnt = checkTarget(m.target, cnt); for (node of m.addedNodes) { cnt += checkTarget(node, cnt); } } logger(cnt); }, 0, mutations); }); observer.observe(document, { childList : true, attributes : true, attributeFilter : ['style'], subtree : true }); win.addEventListener ("load", function(){ var c = 0, imp; for (imp of document.querySelectorAll('[style*="!"]')) { c+= checkTarget(imp, c); } logger(c); }, false); })(); } if (/^https?:\/\/(mail\.yandex\.|music\.yandex\.|news\.yandex\.|(www\.)?yandex\.[^\/]+\/(yand)?search[\/?])/i.test(win.location.href)) { // https://greasyfork.org/en/scripts/809-no-yandex-ads (function(){ var adWords = ['Яндекс.Директ','Реклама','Ad']; function remove(node) { node.parentNode.removeChild(node); } // Generic ads removal and fixes function removeGenericAds() { var s, i; s = document.querySelector('.serp-header'); if (s) { s.style.marginTop='0'; } for (s of document.querySelectorAll('.serp-adv__head + .serp-item, #adbanner, .serp-adv, .b-spec-adv, div[class*="serp-adv__"]:not(.serp-adv__found):not(.serp-adv__displayed)')) { remove(s); } } // Search ads function removeSearchAds() { var s, item, l; for (s of document.querySelectorAll('.t-construct-adapter__legacy')) { item = s.querySelector('.organic__subtitle'); l = window.getComputedStyle(item, ':after').content; if (item && adWords.indexOf(l.replace(/"/g,'')) > -1) { remove(s); console.log('Ads removed.'); } } } // News ads function removeNewsAds() { for (var s of document.querySelectorAll( '.page-content__left > *,'+ '.page-content__right > *:not(.page-content__col),'+ '.page-content__right > .page-content__col > *' )) { if (s.textContent.indexOf(adWords[0]) > -1 || (s.clientHeight < 15 && s.classList.contains('rubric'))) { remove(s); console.log('Ads removed.'); } } } // Music ads function removeMusicAds() { for (var s of document.querySelectorAll('.ads-block')) { remove(s); } } // Mail ads function removeMailAds() { var slice = Array.prototype.slice, nodes = slice.call(document.querySelectorAll('.ns-view-folders')), node, len, classes, cls; for (node of nodes) { if (!len || len > node.classList.length) { len = node.classList.length; } } node = nodes.pop(); while (node) { if (node.classList.length > len) { for (cls of slice.call(node.classList)) { if (cls.indexOf('-') === -1) { remove(node); break; } } } node = nodes.pop(); } } // News fixes function removePageAdsClass() { if (document.body.classList.contains("b-page_ads_yes")){ document.body.classList.remove("b-page_ads_yes"); console.log('Page ads class removed.'); } } // Function to attach an observer to monitor dynamic changes on the page function pageUpdateObserver(func, obj, params) { if (obj) { var o = new MutationObserver(func); o.observe(obj,(params || {childList:true, subtree:true})); } } // Cleaner document.addEventListener ('DOMContentLoaded', function() { removeGenericAds(); if (win.location.hostname.search(/^mail\./i) === 0) { pageUpdateObserver(function(ms, o){ var aside = document.querySelector('.mail-Layout-Aside'); if (aside) { o.disconnect(); pageUpdateObserver(removeMailAds, aside); } }, document.querySelector('BODY')); removeMailAds(); } else if (win.location.hostname.search(/^music\./i) === 0) { pageUpdateObserver(removeMusicAds, document.querySelector('.sidebar')); removeMusicAds(); } else if (win.location.hostname.search(/^news\./i) === 0) { pageUpdateObserver(removeNewsAds, document.querySelector('BODY')); pageUpdateObserver(removePageAdsClass, document.body, {attributes:true, attributesFilter:['class']}); removeNewsAds(); removePageAdsClass(); } else { pageUpdateObserver(removeSearchAds, document.querySelector('.main__content')); removeSearchAds(); } }); })(); } // Yandex Link Tracking if (/^https?:\/\/([^.]+\.)*yandex\.[^\/]+/i.test(win.location.href)) { // Partially based on https://greasyfork.org/en/scripts/22737-remove-yandex-redirect (function(){ var link; function removeTracking(scope) { for (link of scope.querySelectorAll('A')) { if (link.hasAttribute('onmousedown') && /\/jsredir/i.test(link.getAttribute('onmousedown'))) { link.removeAttribute('onmousedown'); } if (link.hasAttribute('data-vdir-href')) { link.removeAttribute('data-vdir-href'); link.removeAttribute('data-orig-href'); } link.removeAttribute('data-counter'); link.removeAttribute('data-bem'); } } removeTracking(_de); var o = new MutationObserver(function(ms) { var m, node; for (m of ms) { for (node of m.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE) { removeTracking(node); } } } }); o.observe(_de, {childList: true, subtree: true}); })(); return; //skip fixes for other sites } // https://greasyfork.org/en/scripts/21937-moonwalk-hdgo-kodik-fix v0.8 (adapted) document.addEventListener ('DOMContentLoaded', function() { var tmp; function log (e) { console.log('Moonwalk&HDGo&Kodik FIX: ' + e + ' player in ' + win.location.href); } if (win.adv_enabled !== undefined && win.condition_detected !== undefined) { // moonwalk log('Moonwalk'); if (win.adv_enabled) { win.adv_enabled = false; } win.condition_detected = false; if (win.MXoverrollCallback) { document.addEventListener('click', function catcher(e){ e.stopPropagation(); win.MXoverrollCallback.call(window); document.removeEventListener('click', catcher, true); }, true); } } else if (win.stat_url !== undefined && win.is_html5 !== undefined && win.is_wp8 !== undefined) { // hdgo log('HDGo'); document.body.onclick = null; tmp = document.querySelector('#swtf'); if (tmp) { tmp.style.display = 'none'; } if (win.banner_second !== undefined) { win.banner_second = 0; } if (win.$banner_ads !== undefined) { win.$banner_ads = false; } if (win.$new_ads !== undefined) { win.$new_ads = false; } if (win.createCookie !== undefined) { win.createCookie('popup','true','999'); } if (win.canRunAds !== undefined && win.canRunAds !== true) { win.canRunAds = true; } } else if (win.MXoverrollCallback && win.iframeSearch !== undefined) { // kodik log('Kodik'); tmp = document.querySelector('.play_button'); if (tmp) { tmp.onclick = win.MXoverrollCallback.bind(window); } win.IsAdBlock = false; } }, false); // Automated protection against specific circumvention method based on unwrapping various functions, // hiding ads in the Shadow DOM and injecting iFrames with ads. Previously this code were known as // apiBreaker since it were breaking Shadow DOM and onerror/onload API on specific domains. This // version should be safe enough to run on majority of sites without actually breaking them. scriptLander(function() { var blacklist = new WeakMap(), replacer, func; /* Wrap functions used to attach shadow root to a node */ replacer = function (func) { return function() { blacklist.set(this, true); return func.apply(this, arguments); }; }; for (func of ['createShadowRoot', 'attachShadow']) { if (func in Element.prototype) { Element.prototype[func] = replacer(Element.prototype[func]); } } /* Wrap functions used to insert/append elements to check for IFRAME objects */ replacer = function (func) { return function(el, par) { if (el.tagName === 'IFRAME' && ((typeof par === 'object' && blacklist.get(par))/* || el.style.display === 'none'*/)) { console.log('Blocked suspicious', func.name, arguments); return null; } return func.apply(this, arguments); }; }; for (func of [/*'appendChild', */'insertBefore']) { Object.defineProperty(Element.prototype, func, { value: replacer(Element.prototype[func]), enumerable: true }); } }); // === Helper functions === // function to search and remove nodes by content // selector - standard CSS selector to define set of nodes to check // words - regular expression to check content of the suspicious nodes // params - object with multiple extra parameters: // .hide - set display to none instead of removing from the page // .parent - parent node to remove if content is found in the child node // .siblings - number of simling nodes to remove (excluding text nodes) function scRemove(e) {e.parentNode.removeChild(e);} function scHide(e) { var s = _getAttribute.call(e, 'style') || '', h = ';display:none!important;'; if (s.indexOf(h) < 0) { _setAttribute.call(e, 'style', s+h); } } function scissors (selector, words, scope, params) { var remFunc = (params.hide ? scHide : scRemove), iterFunc = (params.siblings > 0 ? 'nextSibling' : 'previousSibling'), toRemove = [], siblings, node; for (node of scope.querySelectorAll(selector)) { if (params.parent) { while(node !== scope && !(node.matches(params.parent))) { node = node.parentNode; } } if (words.test(node.innerHTML) || !node.childNodes.length) { // drill up to the specified parent node if required if (node === scope) { break; } toRemove.push(node); // add multiple nodes if defined more than one sibling siblings = Math.abs(params.siblings) || 0; while (siblings) { node = node[iterFunc]; toRemove.push(node); if (node.nodeType === Node.ELEMENT_NODE) { siblings -= 1; //count only element nodes } } } } for (node of toRemove) { remFunc(node); } return toRemove.length; } // function to perform multiple checks if ads inserted with a delay // by default does 30 checks withing a 3 seconds unless nonstop mode specified // also does 1 extra check when a page completely loads // selector and words - passed dow to scissors // params - object with multiple extra parameters: // .root - selector to narrow down scope to scan; // .observe - if true then check will be performed continuously; // Other parameters passed down to scissors. function gardener(selector, words, params) { params = params || {}; var scope = document, nonstop = false; // narrow down scope to a specific element if (params.root) { scope = scope.querySelector(params.root); if (!scope) {// exit if the root element is not present on the page return 0; } } // add observe mode if required if (params.observe) { if (typeof MutationObserver === 'function') { var o = new MutationObserver(function(ms){ for (var m of ms) { if (m.addedNodes.length) { scissors(selector, words, scope, params); } } }); o.observe(scope, {childList:true, subtree: true}); } else { nonstop = true; } } // wait for a full page load to do one extra cut win.addEventListener('load',function(){ scissors(selector, words, scope, params); }); // do multiple cuts until ads removed function cut(sci, s, w, sc, p, i) { if (i > 0) { i -= 1; } if (i && !sci(s, w, sc, p)) { setTimeout(cut, 100, sci, s, w, sc, p, i); } } cut(scissors, selector, words, scope, params, (nonstop ? -1 : 30)); } // Helper function to close background tab if site opens itself in a new tab and then // loads a 3rd-party page in the background one (thus performing background redirect). function preventBackgroundRedirect() { // create "cose_me" event to call high-level window.close() var key = Math.random().toString(36).substr(2); window.addEventListener('close_me_'+key, function(e) { window.close(); }); // window.open wrapper function pbrLander() { var orgOpen = window.open.bind(window), idx = String.prototype.indexOf, event = new CustomEvent("close_me_%key%", {}); function closeWindow(){ // site went to a new tab and attempts to unload // call for high-level close through event window.dispatchEvent(event); } // window.open wrapper function open(){ console.log(arguments, window.location.host); if (arguments[0] && (idx.call(arguments[0], window.location.host) > -1 || idx.call(arguments[0], '://') === -1)) { window.addEventListener('unload', closeWindow, true); } orgOpen.apply(window, arguments); } window.open = open.bind(window); // Node.createElement wrapper to prevent click-dispatch in Google Chrome and similar browsers var realCreateElement = Document.prototype.createElement; function wrappedCreateElement(name) { /*jshint validthis:true */ var el = realCreateElement.apply(this, arguments); if (el.tagName === 'A') { el.addEventListener('click', function(e){ if (!e.target.parentNode || !e.isTrusted) { window.addEventListener('unload', closeWindow, true); } }, false); } return el; } Document.prototype.createElement = wrappedCreateElement; } // land wrapper on the page var script = document.createElement('script'); script.appendChild(document.createTextNode('('+pbrLander.toString().replace(/%key%/g,key)+')();')); document.head.insertBefore(script, document.head.firstChild); script.parentNode.removeChild(script); console.log("Background redirect prevention enabled."); } // Function to catch and block various methods to open a new window with 3rd-party content. // Some advertisement networks went way past simple window.open call to circumvent default popup protection. // This funciton blocks window.open, ability to restore original window.open from an IFRAME object, // ability to perform an untrusted (not initiated by user) click on a link, click on a link without a parent // node or simply a link with piece of javascript code in the HREF attribute. function preventPopups() { function open(){ console.log('Site attempted to open a new window', arguments); function nil(){} return { document: { write: nil, writeln: nil } }; } win.open = exportFunction(open, win); function wrapFunctions() { var realCreateElement = Document.prototype.createElement, realAppendChild = Element.prototype.appendChild; Document.prototype.createElement = function createElement(name) { /*jshint validthis:true */ var el = realCreateElement.apply(this, arguments); if (el.tagName === 'A') { el.addEventListener('click', function(e) { if (!e.target.parentNode || !e.isTrusted || (e.target.href && e.target.href.toLowerCase().indexOf('javascript') > -1)) { e.preventDefault(); console.log('Blocked suspicious click event', e, 'on', e.target); } }, false); } if (el.tagName === 'IFRAME') { el.addEventListener('load', function(){ try { this.contentWindow.open = open; } catch(ignore) {} }, false); } return el; }; Element.prototype.appendChild = function appendChild() { var child = realAppendChild.apply(this, arguments); if (child && child.nodeType === Node.ELEMENT_NODE && child.tagName === 'IFRAME') { try { child.contentWindow.open = open; } catch(ignore) {} } return child; }; } scriptLander(wrapFunctions, [open]); } // Currently unused piece of code developed to prevent site from registering serviceWorker // and uninstall any existing instances of serivceWorker in case there is one already. /* Commented out since not used function forbidServiceWorker() { if (!("serviceWorker" in navigator)) { return; } var svr = navigator.serviceWorker.ready; Object.defineProperty(navigator, 'serviceWorker', { value: { register: function(){ console.log('Registration of serviceWorker ' + arguments[0] + ' blocked.'); return new Promise(function(){}); }, ready: new Promise(function(){}), addEventListener:function(){} } }); document.addEventListener('DOMContentLoaded', function() { if (!svr) { return; } svr.then(function(sw) { console.log('Found existing serviceWorker:', sw); console.log('Attempting to unregister...'); sw.unregister().then(function() { console.log('Unregistered! :)'); }).catch(function(err) { console.log('Unregistration failed. :(', err); console.log('Try to remove it manually:'); console.log(' 1. Open: chrome://serviceworker-internals/ (Google Chrome and alike) or about:serviceworkers (Mozilla Firefox) in a new tab.'); console.log(' 2. Search there for one with "'+document.domain+'" in the name.'); console.log(' 3. Use buttons in the same block with service you found to stop it and uninstall/unregister.'); }); }).catch(function(err) { console.log("Lol, it failed on it's own. -_-", err); }); }, false); } /**/ // Currently obsolete code developed to prevent error and load calls on objects supposed to load resources // from the internet like IMG or IFRAME, but missing SRC/HREF attribute. Usually tricks like this are used // to unwrap wrapped functions to be able to load ads. /* Commented out since not used function errorAndLoadEventsFilter() { var toString = Function.prototype.toString, addEventListener = Element.prototype.addEventListener, removeEventListener = Element.prototype.removeEventListener, hasAttribute = Element.prototype.hasAttribute, evtMap = new WeakMap(); Element.prototype.addEventListener = function(evt, func, capt) { if (evt === 'error' || evt === 'load') { if (!evtMap.get(func)) { evtMap.set(func, function() { if (hasAttribute.call(this, 'src') || hasAttribute.call(this, 'href')) { func.apply(this, arguments); } else { console.log('Blocked', evt, 'handler', toString.call(func), 'on', this); } }); } } addEventListener.call(this, evt, (evtMap.get(func) || func), capt); }; Element.prototype.removeEventListener = function(evt, func, capt) { removeEventListener.call(this, evt, (evtMap.get(func) || func), capt); }; Object.defineProperty(HTMLElement.prototype, 'onload', { set: function(func) { if(evtMap.has(this)) { if (evtMap.get(this).onload) { Element.prototype.removeEventListener.call(this, 'load', evtMap.get(this).onload, false); } evtMap.get(this).onload = func; } else { evtMap.set(this, { onload: func }); } if (func) { Element.prototype.addEventListener.call(this, 'load', func, false); } return func; }, get: function() { return evtMap.has(this) ? evtMap.get(this).onload : null; } }); Object.defineProperty(HTMLElement.prototype, 'onerror', { set: function(func) { if (evtMap.has(this)) { evtMap.get(this).onerror = func; } else { evtMap.set(this, { onerror: func }); } if (func) { console.log('Blocked error handler', toString.call(func), 'on', this); } return func; }, get: function() { return evtMap.has(this) ? evtMap.get(this).onerror : null; } }); } /**/ // === Scripts for specific domains === var scripts = {}; // prevent popups and redirects block var preventPopupsNow = { 'now': preventPopups }, preventBackgroundRedirectNow = { 'now': preventBackgroundRedirect }; // Popups scripts['biqle.ru'] = preventPopupsNow; scripts['chaturbate.com'] = preventPopupsNow; scripts['dfiles.ru'] = preventPopupsNow; scripts['hentaiz.org'] = preventPopupsNow; scripts['mirrorcreator.com'] = preventPopupsNow; scripts['online-multy.ru'] = preventPopupsNow; scripts['openload.co'] = preventPopupsNow; scripts['radikal.ru'] = preventPopupsNow; scripts['seedoff.cc'] = preventPopupsNow; scripts['tapochek.net'] = preventPopupsNow; scripts['thepiratebay.org'] = preventPopupsNow; scripts['torseed.net'] = preventPopupsNow; scripts['zippyshare.com'] = preventPopupsNow; // Background redirects scripts['mediafire.com'] = preventBackgroundRedirectNow; scripts['megapeer.org'] = preventBackgroundRedirectNow; scripts['megapeer.ru'] = preventBackgroundRedirectNow; scripts['perfectgirls.net'] = preventBackgroundRedirectNow; scripts['turbobit.net'] = preventBackgroundRedirectNow; // other scripts['4pda.ru'] = { 'now': function() { // https://greasyfork.org/en/scripts/14470-4pda-unbrender var isForum = document.location.href.search('/forum/') !== -1, hStyle; function remove(n) { if (n) { n.parentNode.removeChild(n); } } function afterClean() { hStyle.disabled = true; remove(hStyle); } function beforeClean() { // attach styles before document displayed hStyle = createStyle([ 'html { overflow-y: scroll }', 'section[id] {'+( 'position: absolute;'+ 'width: 100%' )+'}', 'article + aside * { display: none !important }', '#header + div:after {'+( 'content: "";'+ 'position: fixed;'+ 'top: 0;'+ 'left: 0;'+ 'width: 100%;'+ 'height: 100%;'+ 'background-color: #E6E7E9' )+'}', // http://codepen.io/Beaugust/pen/DByiE '@keyframes spin { 100% { transform: rotate(360deg) } }', 'article + aside:after {'+( 'content: "";'+ 'position: absolute;'+ 'width: 150px;'+ 'height: 150px;'+ 'top: 150px;'+ 'left: 50%;'+ 'margin-top: -75px;'+ 'margin-left: -75px;'+ 'box-sizing: border-box;'+ 'border-radius: 100%;'+ 'border: 10px solid rgba(0, 0, 0, 0.2);'+ 'border-top-color: rgba(0, 0, 0, 0.6);'+ 'animation: spin 2s infinite linear' )+'}' ], {id:'ubrHider'}, true); // display content of a page if time to load a page is more than 2 seconds to avoid // blocking access to a page if it is loading for too long or stuck in a loading state setTimeout(2000, afterClean); } createStyle([ '#nav .use-ad { display: block !important }', 'article:not(.post) + article:not(#id), a[target="_blank"] img[height="90"] { display: none !important }' ]); if (!isForum) { beforeClean(); } // save links to non-overridden functions to use later var protectedElems; // protect/hide changed attributes in case site attempt to restore them function styleProtector(eventMode) { var oRAN = Element.prototype.removeAttributeNode, isStyleText = function(t){ return t === 'style'; }, isStyleAttr = function(a){ return a instanceof Attr && a.nodeName === 'style'; }, returnUndefined = function(){}, protectedElems = new WeakMap(); function protoOverride(element, functionName, isStyleCheck, returnIfProtected) { var oF = element.prototype[functionName], r; element.prototype[functionName] = function() { if (protectedElems.has(this) && isStyleCheck(arguments[0])) { return returnIfProtected(this, arguments); } r = oF.apply(this, arguments); return r; }; } protoOverride(Element, 'removeAttribute', isStyleText, returnUndefined); protoOverride(Element, 'hasAttribute', isStyleText, function(_this) { return protectedElems.get(_this) !== null; }); protoOverride(Element, 'setAttribute', isStyleText, function(_this, args) { protectedElems.set(_this, args[1]); }); protoOverride(Element, 'getAttribute', isStyleText, function(_this) { return protectedElems.get(_this); }); if (eventMode) { var e = document.createEvent('Event'); e.initEvent('protoOverride', false, false); window.protectedElems = protectedElems; window.dispatchEvent(e); } else { return protectedElems; } } if (isFirefox) { var s = document.createElement('script'); s.textContent = '(' + styleProtector.toString() + ')(true);'; window.addEventListener('protoOverride', function protoOverrideCallback(e){ if (win.protectedElems) { protectedElems = win.protectedElems; delete win.protectedElems; } document.removeEventListener('protoOverride', protoOverrideCallback, true); }, true); _appendChild(s); _removeChild(s); } else { protectedElems = styleProtector(false); } // clean a page window.addEventListener('DOMContentLoaded', function(){ var rem, si, itm; function width(){ return window.innerWidth||_de.clientWidth||document.body.clientWidth||0; } function height(){ return window.innerHeight||_de.clientHeight||document.body.clientHeight||0; } if (isForum) { si = document.querySelector('#logostrip'); if (si) { remove(si.parentNode.nextSibling); } } if (document.location.href.search('/forum/dl/') !== -1) { document.body.setAttribute('style', (document.body.getAttribute('style')||'')+ ';background-color:black!important'); for (itm of document.querySelectorAll('body>div')) { if (!itm.querySelector('.dw-fdwlink')) { remove(itm); } } } if (isForum) { // Do not continue if it's a forum return; } si = document.querySelector('#header'); if (si) { rem = si.previousSibling; while (rem) { si = rem.previousSibling; remove(rem); rem = si; } } for (itm of document.querySelectorAll('#nav li[class]')) { if (itm && itm.querySelector('a[href^="/tag/"]')) { remove(itm); } } var style, result; for (itm of document.querySelectorAll('DIV, A')) { if (itm.tagName ==='DIV' && itm.offsetWidth > 0.95 * width() && itm.offsetHeight > 0.85 * height()) { style = window.getComputedStyle(itm, null); result = []; if (style.backgroundImage !== 'none') { result.push('background-image:none!important'); } if (style.backgroundColor !== 'transparent' && style.backgroundColor !== 'rgba(0, 0, 0, 0)') { result.push('background-color:transparent!important'); } if (result.length) { if (itm.getAttribute('style')) { result.unshift(itm.getAttribute('style')); } (function(){ var fakeStyle = { 'backgroundImage': itm.style.backgroundImage, 'backgroundColor': itm.style.backgroundColor }; try { Object.defineProperty(itm, 'style', { value: new Proxy(itm.style, { get: function(target, prop){ if (fakeStyle.hasOwnProperty(prop)) { return fakeStyle[prop]; } else { return target[prop]; } }, set: function(target, prop, value){ if (fakeStyle.hasOwnProperty(prop)) { fakeStyle[prop] = value; } else { target[prop] = value; } return value; } }), enumerable: true }); } catch (e) { console.log('Unable to protect style property.', e); } })(); if (protectedElems) { protectedElems.set(itm, _getAttribute.call(itm, 'style')); } _setAttribute.call(itm, 'style', result.join(';')); } } if (itm.tagName ==='A' && (itm.offsetWidth > 0.95 * width() || itm.offsetHeight > 0.85 * height())) { if (protectedElems) { protectedElems.set(itm, _getAttribute.call(itm, 'style')); } _setAttribute.call(itm, 'style', 'display:none!important'); } } for (itm of document.querySelectorAll('ASIDE>DIV')) { if ( ((itm.querySelector('script, iframe, a[href*="/ad/www/"]') || itm.querySelector('img[src$=".gif"]:not([height="0"]), img[height="400"]')) && !itm.classList.contains('post') ) || !itm.childNodes.length ) { remove(itm); } } document.body.setAttribute('style', (document.body.getAttribute('style')||'')+';background-color:#E6E7E9!important'); // display content of the page afterClean(); }); } }; scripts['allmovie.pro'] = function() { // pretend to be Android to make site use different played for ads if (isSafari) { return; } Object.defineProperty(navigator, 'userAgent', { get: function(){ return 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19'; }, enumerable: true }); }; scripts['rufilmtv.org'] = scripts['allmovie.pro']; scripts['anidub-online.ru'] = function() { var script = document.createElement('script'); script.type = "text/javascript"; script.innerHTML = "function ogonekstart1() {}"; document.getElementsByTagName('head')[0].appendChild(script); var style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode('.background {background: none!important;}')); style.appendChild(document.createTextNode('.background > script + div, .background > script ~ div:not([id]):not([class]) + div[id][class] {display:none!important}')); document.head.appendChild(style); }; scripts['online.anidub.com'] = scripts['anidub-online.ru']; scripts['fs.to'] = function() { function skipClicker(i) { if (!i) { return; } var skip = document.querySelector('.b-aplayer-banners__close'); if (skip) { skip.click(); } else { setTimeout(skipClicker, 100, i-1); } } setTimeout(skipClicker, 100, 30); createStyle([ '.l-body-branding *,'+ '.b-styled__item-central,'+ '.b-styled__content-right,'+ '.b-styled__section-central,'+ 'div[id^="adsProxy-"]'+ '{display:none!important}', 'body {background-image:url(data:image/png;base64,'+ 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACX'+ 'BIWXMAAC4jAAAuIwF4pT92AAAADUlEQVR42mOQUdL5DwACMgFq'+ 'BC3ttwAAAABJRU5ErkJggg==)!important}' ]); if (/\/(view_iframe|iframeplayer)\//i.test(document.location.pathname)) { var p = document.querySelector('#player:not([preload="auto"])'), m = document.querySelector('.main'), adStepper = function(p) { if (p.currentTime < p.duration) { p.currentTime += 1; } }, adSkipper = function(f, p) { f.click(); p.waitAfterSkip = false; p.longerSkipper = false; console.log('Пропустили.'); }, cl = function(p) { var faster = document.querySelector('.b-aplayer__html5-desktop-skip'), series = document.querySelector('.b-aplayer__actions-series'); function clickSelected() { var s = document.querySelector('.b-aplayer__popup-series-episodes .selected a'); if (s) { s.click(); } } if ((!faster || faster.style.display !== 'block') && series && !p.seriesClicked) { series.click(); p.seriesClicked = true; p.longerSkipper = true; setTimeout(clickSelected, 1000); p.pause(); } function skipListener() { if (p.waitAfterSkip) { console.log('В процессе пропуска…'); return; } p.pause(); if (!p.classList.contains('m-hidden')) { p.classList.add('m-hidden'); } if (faster && p.currentTime && win.getComputedStyle(faster).display === 'block' && !faster.querySelector('.b-aplayer__html5-desktop-skip-timer')) { p.waitAfterSkip = true; setTimeout(adSkipper, (p.longerSkipper?3:1)*1000, faster, p); console.log('Доступен быстрый пропуск…'); } else { setTimeout(adStepper, 1000, p); } } p.addEventListener('timeupdate', skipListener, false); }, o = new MutationObserver(function (ms) { var m, node; for (m of ms) { for (node of m.addedNodes) { if (node.id === 'player' && node.nodeName === 'VIDEO' && _getAttribute.call(node, 'preload') !== 'auto') { cl(node); } } } }); if (p.nodeName === 'VIDEO') { cl(p); } else { o.observe(m, {childList: true}); } } }; scripts['brb.to'] = scripts['fs.to']; scripts['cxz.to'] = scripts['fs.to']; scripts['drive2.ru'] = function() { gardener('.c-block:not([data-metrika="recomm"]),.o-grid__item', />Реклама<\//i); }; scripts['fishki.net'] = function() { gardener('.drag_list > .drag_element, .list-view > .paddingtop15, .post-wrap', /543769|Новости партнеров/); }; scripts['gidonline.club'] = { 'now': function() { createStyle('.tray > div[style] {display: none!important}'); } }; scripts['gidonlinekino.com'] = scripts['gidonline.club']; scripts['hdgo.cc'] = { 'now': function(){ var o = new MutationObserver(function(ms) { var m, node; for (m of ms) { for (node of m.addedNodes) { if (node.tagName === 'SCRIPT' && _getAttribute(node, 'onerror') !== null) { node.removeAttribute('onerror'); } } } }); o.observe(document, {childList:true, subtree: true}); } }; scripts['couber.be'] = scripts['hdgo.cc']; scripts['46.30.43.38'] = scripts['hdgo.cc']; scripts['gismeteo.ru'] = { 'DOMContentLoaded': function() { gardener('div > a[target^="_"]', /Яндекс\.Директ/i, { root: 'body', observe: true, parent: 'div[class*="frame"]' }); } }; scripts['hdrezka.me'] = { 'now': function() { Object.defineProperty(win, 'fuckAdBlock', { value: { onDetected: function() { console.log('Pretending to be an ABP detector.'); } } }); Object.defineProperty(win, 'ab', { value: false, enumerable: true }); }, 'DOMContentLoaded': function() { gardener('div[id][onclick][onmouseup][onmousedown]', /onmouseout/i); } }; scripts['imageban.ru'] = { 'now': preventBackgroundRedirect, 'DOMContentLoaded': function() { win.addEventListener('unload', function() { if (!window.location.hash) { window.location.replace(window.location+'#'); } else { window.location.hash = ''; } }, true); } }; scripts['e.mail.ru'] = function() { /*gardener('#LEGO :not([data-mnemo])>.js-href[data-id]', /data:image.*>Реклама<|>Реклама<.*\/\/favicon\./i, {root:'#LEGO', observe: true, parent:'div[id][class]'});*/ }; scripts['mail.ru'] = { 'now': function() { // Trick to prevent mail.ru from removing 3rd-party styles scriptLander(function(){ Object.defineProperty(Object.prototype, 'restoreVisibility', { get: function() { return function(){}; }, set: function() {} }); }); } }; scripts['megogo.net'] = { 'now': function() { Object.defineProperty(win, "adBlock", { value : false, enumerable : true }); Object.defineProperty(win, "showAdBlockMessage", { value : function () {}, enumerable : true }); } }; scripts['naruto-base.su'] = function() { gardener('div[id^="entryID"],.block', /href="http.*?target="_blank"/i); }; scripts['overclockers.ru'] = { 'now': function() { createStyle('.fixoldhtml {display:block!important}'); if (!isChrome && !isOpera) { return; // Looks like my code works only in Chrome-like browsers } var noContentYet = true; function jWrap() { var _$ = win.$, _e = _$.extend; win.$ = function() { var _ret = _$.apply(window, arguments); if (_ret[0] === document.body) { _ret.html = function() { console.log('Anti-adblock prevented.'); }; } return _ret; }; win.$.extend = function() { return _e.apply(_$, arguments); }; win.jQuery = win.$; } (function jReady() { if (!win.$ && noContentYet) { setTimeout(jReady, 0); } else { jWrap(); } })(); document.addEventListener ('DOMContentLoaded', function(){ noContentYet = false; }, false); } }; scripts['forums.overclockers.ru'] = { 'now': function() { createStyle('.needblock {position: fixed; left: -10000px}'); Object.defineProperty(win, 'adblck', { value: 'no', enumerable: true }); } }; scripts['pb.wtf'] = function() { createStyle('.reques,#result,tbody.row1:not([id]) {display: none !important}'); // image in the slider in the header gardener('a[href$="=="]', /img/i, {root:'.release-navbar', observe:true, parent:'div'}); // ads in blocks on the page gardener('a[href^="/"]', //i, {root:'#main_content', observe:true, parent:'div[class]'}); // line above topic content gardener('.re_top1', /./, {root:'#main_content', parent:'.hidden-sm'}); }; scripts['piratbit.org'] = scripts['pb.wtf']; scripts['piratbit.ru'] = scripts['pb.wtf']; scripts['pikabu.ru'] = function() { gardener('.story', /story__sponsor|story__gag|profile\/ads"/i, {root: '.inner_wrap', observe: true}); }; scripts['rp5.ru'] = function() { createStyle('#bannerBottom {display: none!important}'); var co = document.querySelector('#content'), i, nodes; if (!co) { return; } nodes = co.parentNode.childNodes; i = nodes.length; while (i--) { if (nodes[i] !== co) { nodes[i].parentNode.removeChild(nodes[i]); } } }; scripts['rp5.by'] = scripts['rp5.ru']; scripts['rp5.ua'] = scripts['rp5.ru']; scripts['rustorka.com'] = { 'now': function() { createStyle('.header > div:not(.head-block) a, #sidebar1 img, #logo img {opacity:0!important}', { id: 'tempHidingStyles' }, true); preventPopups(); }, 'DOMContentLoaded': function() { for (var o of document.querySelectorAll('IMG, A')) { if ((o.clientWidth === 728 && o.clientHeight === 90) || (o.clientWidth === 300 && o.clientHeight === 250)) { while (o && o.tagName !== 'A') { o = o.parentNode; } if (o) { _setAttribute.call(o, 'style', 'display: none !important'); } } } var s = document.querySelector('#tempHidingStyles'); s.parentNode.removeChild(s); } }; scripts['rumedia.ws'] = scripts['rustorka.com']; scripts['sport-express.ru'] = function() { gardener('.js-relap__item',/>Реклама\s+<\//, {root:'.container', observe: true}); }; scripts['sports.ru'] = function() { gardener('.aside-news-list__item', /aside-news-list__advert/i, {root:'.columns-layout__left', observe: true}); gardener('.material-list__item', /Реклама/i, {root:'.columns-layout', observe: true}); // extra functionality: shows/hides panel at the top depending on scroll direction createStyle([ '.user-panel__fixed { transition: top 0.2s ease-in-out!important; }', '.user-panel-up { top: -40px!important }' ], {id: 'userPanelSlide'}, false); (function lookForPanel() { var panel = document.querySelector('.user-panel__fixed'); if (!panel) { setTimeout(lookForPanel, 100); } else { window.addEventListener('wheel', function(e){ if (e.deltaY > 0 && !panel.classList.contains('user-panel-up')) { panel.classList.add('user-panel-up'); } else if (e.deltaY < 0 && panel.classList.contains('user-panel-up')) { panel.classList.remove('user-panel-up'); } }, false); } })(); }; scripts['www.ukr.net'] = scripts['sinoptik.com.ru']; scripts['vk.com'] = function() { gardener('div[data-post-id]', /wall_marked_as_ads/, {root: '#page_wall_posts', observe: true}); }; scripts['yap.ru'] = function() { var words = /member1438|Administration|\/go\/?.*yplkl\.php/; gardener('form > table[id^="p_row_"]:nth-of-type(2)', words); gardener('tr > .holder.newsbottom', words, {parent:'tr', siblings:-2}); }; scripts['yaplakal.com'] = scripts['yap.ru']; scripts['rambler.ru'] = { 'now': function() { scriptLander(function() { var _createElement = Document.prototype.createElement, loadMap = new WeakMap(); Document.prototype.createElement = function createElement(name) { /*jshint validthis:true */ var el = _createElement.apply(this, arguments); if (el.tagName === 'LINK') { Object.defineProperty(el, 'onload', { get: function() { return loadMap.get(loadMap.get(this)); }, set: function(func) { var wrap = loadMap.get(this); if (wrap) { this.removeEventListener('load', wrap, false); loadMap.remove(wrap); loadMap.remove(this); } wrap = function(e) { if (e.target && e.target.sheet && e.target.sheet.cssRules && e.target.sheet.cssRules[0] && e.target.sheet.cssRules[0].cssText && /\{\s*content\s*:\s*"[^"]+"/i.test(e.target.sheet.cssRules[0].cssText)) { console.log('Blocked "onload" for', e.target.href); return false; } return func.apply(this, arguments); }; loadMap.set(this, wrap); loadMap.set(wrap, func); this.addEventListener('load', wrap, false); }, enumberable: true }); } return el; }; }); } }; scripts['reactor.cc'] = { 'now': function() { win.open = (function(){ throw new Error('Redirect prevention.'); }).bind(window); }, 'click': function(e) { var node = e.target; if (node.nodeType === Node.ELEMENT_NODE && node.style.position === 'absolute' && node.style.zIndex > 0) node.parentNode.removeChild(node); }, 'DOMContentLoaded': function() { var words = new RegExp( 'блокировщика рекламы' .split('') .map(function(e){return e+'[\u200b\u200c\u200d]*';}) .join('') .replace(' ', '\\s*') .replace(/[аоре]/g, function(e){return ['[аa]','[оo]','[рp]','[еe]']['аоре'.indexOf(e)];}), 'i'), can; function deeper(spider) { var c, l, n; if (words.test(spider.innerText)) { if (spider.nodeType === Node.TEXT_NODE) { return true; } c = spider.childNodes; l = c.length; n = 0; while(l--) { if (deeper(c[l]), can) { n++; } } if (n > 0 && n === c.length && spider.offsetHeight < 750) { can.push(spider); } return false; } return true; } function probe(){ if (words.test(document.body.innerText)) { can = []; deeper(document.body); var i = can.length, j, spider; while(i--) { spider = can[i]; if (spider.offsetHeight > 10 && spider.offsetHeight < 750) { _setAttribute.call(spider, 'style', 'background:none!important'); } } } } var o = new MutationObserver(probe); o.observe(document,{childList:true, subtree:true}); } }; scripts['joyreactor.cc'] = scripts['reactor.cc']; scripts['pornreactor.cc'] = scripts['reactor.cc']; scripts['auto.ru'] = function() { var words = /Реклама|Яндекс.Директ|yandex_ad_/; var userAdsListAds = [ '.listing-list > .listing-item', '.listing-item_type_fixed.listing-item' ]; var catalogAds = [ 'div[class*="layout_catalog-inline"]', 'div[class$="layout_horizontal"]' ]; var otherAds = [ '.advt_auto', '.sidebar-block', '.pager-listing + div[class]', '.card > div[class][style]', '.sidebar > div[class]', '.main-page__section + div[class]', '.listing > tbody']; gardener(userAdsListAds.join(','), words, {root:'.listing-wrap', observe:true}); gardener(catalogAds.join(','), words, {root:'.catalog__page,.content__wrapper', observe:true}); gardener(otherAds.join(','), words); }; scripts['rsload.net'] = { 'load': function() { var dis = document.querySelector('label[class*="cb-disable"]'); if (dis) { dis.click(); } }, 'click': function(e) { var t = e.target; if (t && t.href && (/:\/\/\d+\.\d+\.\d+\.\d+\//.test(t.href))) { t.href = t.href.replace('://','://rsload.net:rsload.net@'); } } }; var domain = document.domain, name; while (domain.indexOf('.') !== -1) { if (scripts.hasOwnProperty(domain)) { if (typeof scripts[domain] === 'function') { document.addEventListener ('DOMContentLoaded', scripts[domain], false); } for (name in scripts[domain]) { if (name !== 'now') { (name === 'load' ? window : document) .addEventListener (name, scripts[domain][name], false); } else { scripts[domain][name](); } } } domain = domain.slice(domain.indexOf('.') + 1); } })();