RU AdList JS Fixes

try to take over the world!

Від 18.10.2016. Дивіться остання версія.

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

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

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

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

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

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

(У мене вже є менеджер скриптів, дайте мені встановити його!)

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

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

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

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

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

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

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

// ==UserScript==
// @name         RU AdList JS Fixes
// @namespace    ruadlist_js_fixes
// @version      20161018.0
// @description  try to take over the world!
// @author       lainverse & dimisa
// @match        *://*/*
// @grant        unsafeWindow
// @grant        window.close
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    var win = (unsafeWindow || window);

    // 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];
    }

    // 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 root = document.documentElement;

        function _protect(style) {
            Object.defineProperty(style, 'sheet', {
                value: style.sheet,
                enumerable: true
            });
            Object.defineProperty(style, 'disabled', {
                get: function() {return true;}, //pretend to be disabled
                set: function() {},
                enumerable: true
            });
        }

        function _create() {
            var style = root.appendChild(document.createElement('style')),
                prop, rule;
            style.type = 'text/css';
            for (prop in props) {
                if (style.hasOwnProperty(prop)) {
                    style[prop] = props[prop];
                }
            }
            for (rule of rules) {
                try {
                    style.sheet.insertRule(rule, 0);
                } catch (e) {
                    console.error(e);
                }
            }
            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://greatest.deepsurf.us/scripts/19144-websuckit/
    (function() {
        // 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
                '||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^',
                '||mail.ru^', '||marketgid.com^', '||mxtads.com^',
                '||oconner.biz^',
                '||pkpojhc.com^',
                '||psma01.com^', '||psma02.com^', '||psma03.com^',
                '||recreativ.ru^', '||regpole.com^', '||ruttwind.com^',
                '||skidl.ru^',
                '||torvind.com^', '||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(/^\|\|/,'^wss?:\\/+([^\/.]+\\.)*'),
                    '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,
                        _callbacks = new WeakMap(),
                        _worker = null,
                        _terminate = false,
                        _onerror = null,
                        _onmessage = null,
                        _messages = [],
                        _events = [],
                        _self = this;

                    function callbackWrapper(func) {
                        if (typeof func !== 'function') {
                            return undefined;
                        }
                        return (
                            function callback() {
                                func.apply(_self, arguments);
                            }
                        );
                    }

                    (new Promise(function(resolve, reject){
                        if (!isBlobURL.test(resourceURI)) {
                            return resolve(new realWorker(resourceURI));
                        }

                        var xhr = new XMLHttpRequest();
                        xhr.open('GET', resourceURI, true);
                        xhr.responseType = 'blob';
                        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();
                        }
                    });

                    _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]);
                        }
                    };
                }
                win.Worker = wrappedWorker.bind(safeWin);
            }

            function CreateElementWrapper() {
                var realCreateElement = document.createElement.bind(document),
                    code = encodeURIComponent('<scr'+'ipt>'+getWrappedCode(true)+'</scr'+'ipt>\n'),
                    isDataURL = /^data:/i,
                    isBlobURL = /^blob:/i;

                function frameRewrite(e) {
                    var f = e.target,
                        w = f.contentWindow;
                    if (!f.src) {
                        return; // nothing to do here if source is unknown
                    }
                    if (isDataURL.test(f.src) && f.src.indexOf(code) < 0) {
                        f.src = f.src.replace(',',',' + code);
                    }
                    if (w && isBlobURL.test(f.src)) {
                        w.WebSocket = createWebSocketWrapper();
                    }
                }

                function wrappedCreateElement(name) {
                    if (name && name.toUpperCase &&
                        name.toUpperCase() === 'IFRAME') {
                        var ifr = realCreateElement.apply(document, arguments);
                        ifr.addEventListener('load', frameRewrite, false);
                        return ifr;
                    }
                    return realCreateElement.apply(document, arguments);
                }
                document.createElement = wrappedCreateElement.bind(document);

                document.addEventListener('DOMContentLoaded', function(){
                    for (var ifr of document.querySelectorAll('IFRAME')) {
                        ifr.addEventListener('load', frameRewrite, false);
                    }
                }, false);
            }

            this.init = function() {
                win.WebSocket = createWebSocketWrapper();
                // TempFix: Skip WorkerWrapper on Twitter due to weird CPS which breaks their own Worker object (or my code instead)
                if (!/^([^.]*?\.)*?twitter.com$/.test(safeWin.location.hostname)) {
                    WorkerWrapper();
                }
                if (typeof document !== 'undefined') {
                    CreateElementWrapper();
                }
            };
        }

        if (/firefox/i.test(navigator.userAgent)) {
            var script = document.createElement('script');
            script.appendChild(document.createTextNode(getWrappedCode()));
            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 (!(/firefox/i.test(navigator.userAgent))) { // scripts for non-Firefox browsers

        // https://greatest.deepsurf.us/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;
                    el.setAttribute('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 = node.getAttribute('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?:\/\/(news\.yandex\.|(www\.)?yandex\.[^\/]+\/(yand)?search[\/?])/i.test(win.location.href)) {
        // https://greatest.deepsurf.us/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__"]')) {
                    remove(s);
                }
            }
            // Search ads
            function removeSearchAds() {
                var s, item;
                for (s of document.querySelectorAll('.serp-block, .serp-item, .search-item')) {
                    item = s.querySelector('.label, .serp-item__label, .document__provider-name');
                    if (item && adWords.indexOf(item.textContent) > -1) {
                        remove(s);
                        console.log('Ads removed.');
                    }
                }
            }
            // News ads
            function removeNewsAds() {
                var s;
                for (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) {
                        remove(s);
                        console.log('Ads removed.');
                    }
                }
            }
            // 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(/^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();
                }
            });
        })();
        return; //skip fixes for other sites
    }

    // https://greatest.deepsurf.us/en/scripts/14470-4pda-unbrender
    if (/(^|\.)4pda\.ru$/i.test(window.location.hostname)) {
        (function() {
            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 }',
                    '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();
            }

            // protect/hide changed attributes in case site attempt to restore them
            var oGA = HTMLElement.prototype.getAttribute,
                oRAN = HTMLElement.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];
                element.prototype[functionName] = function(){
                    if (protectedElems.get(this) !== undefined && isStyleCheck(arguments[0])) {
                        return returnIfProtected(protectedElems.get(this), arguments, this);
                    }
                    return oF.apply(this, arguments);
                }
            }
            protoOverride(HTMLElement, 'removeAttribute', isStyleText, returnUndefined);
            protoOverride(HTMLElement, 'removeAttributeNS', isStyleText, returnUndefined);
            protoOverride(HTMLElement, 'removeAttributeNode', isStyleAttr, function(o, args, node) {
                if (args[0] instanceof Attr && args[0].ownerElement !== node) {
                    // throw 'attribute of another element' error
                    oRAN.call(node, document.createAttribute('style'));
                }
                if (o.oldStyle === null) {
                    // throw 'not an Attr' error
                    oRAN.call(node, null);
                }
                o.oldStyle = null;
                return args[0];
            });
            protoOverride(HTMLElement, 'hasAttribute', isStyleText, function(o) {
                return o.oldStyle !== null;
            });
            protoOverride(HTMLElement, 'hasAttributeNS', isStyleText, function(o) {
                return o.oldStyle !== null;
            });
            protoOverride(HTMLElement, 'setAttribute', isStyleText, function(o, args) {
                o.oldStyle = args[1];
            });
            protoOverride(HTMLElement, 'setAttributeNS', isStyleText, returnUndefined);
            protoOverride(HTMLElement, 'setAttributeNode', isStyleAttr, returnUndefined);
            protoOverride(HTMLElement, 'getAttribute', isStyleText, function(o) {
                return o.oldStyle;
            });
            protoOverride(HTMLElement, 'getAttributeNS', isStyleText, returnUndefined);
            protoOverride(HTMLElement, 'getAttributeNode', isStyleText, function(o){
                if (o.oldStyle === null) {
                    return null;
                }
                var at = document.createAttribute('style');
                at.value = o.oldStyle;
                Object.defineProperty(at, 'ownerElement', {
                    value: this,
                    enumerable: true
                });
                return at;
            });

            // clean a page
            window.addEventListener('DOMContentLoaded', function(){
                var rem, si, itm;
                function width(){ return window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0; }
                function height(){ return window.innerHeight||document.documentElement.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, oldStyle;
                for (itm of document.querySelectorAll('DIV')) {
                    if (itm.offsetWidth > 0.95 * width() && itm.offsetHeight > 0.8 * 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 bgi = itm.style.backgroundImage,
                                    bgc = itm.style.backgroundColor;
                                Object.defineProperty(itm.style, 'backgroundImage', {
                                    get: function(){return bgi;},
                                    set: function(){}
                                });
                                Object.defineProperty(itm.style, 'backgroundColor', {
                                    get: function(){return bgc;},
                                    set: function(){}
                                });
                                Object.defineProperty(itm, 'style', {value: itm.style});
                            })();
                            oldStyle = oGA.call(itm, 'style');
                            itm.setAttribute('style', result.join(';'));
                            protectedElems.set(itm, {oldStyle: oldStyle});
                        }
                    }
                }

                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();
            });
        })();
        return;
    }

    // https://greatest.deepsurf.us/en/scripts/21937-moonwalk-hdgo-kodik-fix v0.7+ (adapted & fixed)
    document.addEventListener ('DOMContentLoaded', function() {
        var tmp, t;1
        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');
            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.banner_second !== undefined && win.$banner_ads !== undefined) { // hdgo
            log('HDGo');
            tmp = document.querySelector('#swtf');
            if (tmp) {
                tmp.style.display = 'none';
            }
            win.banner_second = 0;
            win.$banner_ads = false;
            if (win.$new_ads !== undefined) {
                win.$new_ads = false;
            }
            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);

    // 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 = e.getAttribute('style')||'',
            h = ';display:none!important;';
        if (s.indexOf(h) < 0) {
            e.setAttribute('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 (words.test(node.innerHTML) || !node.childNodes.length) {
                // drill up to the specified parent node if required
                if (params.parent) {
                    while(node !== scope && !(node.matches(params.parent))) {
                        node = node.parentNode;
                    }
                }
                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.body,
            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));
    }

    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);
            function closeWindow(){
                // site went to a new tab and attempts to unload
                // call for high-level close through event
                var event = new CustomEvent("close_me_%key%", {});
                window.dispatchEvent(event);
            }
            function open(){
                var idx = String.prototype.indexOf;
                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);
            var s = document.currentScript;
            if (s) {s.parentNode.removeChild(s);}
        }

        // 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);
        console.log("Background redirect prevention enabled.");
    }

    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);
    }

    var scripts = {};
    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' &&
                                node.getAttribute('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(.js-recommendations),.o-grid__item', />Реклама<\//i);
    };

    scripts['fishki.net'] = function() {
        gardener('.main-post', /543769|Реклама/);
    };

    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' && node.getAttribute('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['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['naruto-base.su'] = function() {
        gardener('div[id^="entryID"],.block', /href="http.*?target="_blank"/i);
    };

    scripts['forums.overclockers.ru'] = {
        'now': function() {
            createStyle(['.needblock {position: fixed; left: -10000px}']);
            Object.defineProperty(win, 'adblck', {
                value: 'no',
                enumerable: true
            });
            // Following code inspired by:
            // https://greatest.deepsurf.us/en/scripts/23922-anti-adblock-killer-for-overclockers-ru
            function antiAntiABP() {
                var o = new MutationObserver(function(ms) {
                    var triggered = false, m, node;
                    for (m of ms) {
                        for (node of m.addedNodes) {
                            if (node.nodeType === Node.ELEMENT_NODE &&
                                typeof node.onerror === 'function' &&
                                (node.tagName === 'SCRIPT' || node.tagName === 'IMG')) {
                                node.onerror = null;
                                triggered = true;
                            }
                        }
                    }
                    if (triggered) {
                        console.log('Disabled script.onerror ABP detection.');
                    }
                });
                o.observe(document, {childList: true, subtree: true});
                var s = document.currentScript;
                s.parentNode.removeChild(s);
            }
            var s = document.createElement('script');
            s.textContent = '(' + antiAntiABP.toString() + ')();';
            document.documentElement.appendChild(s);
        }
    };

    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^="/"]', /<img\s.*<br>/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() {
        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['rustorka.com'] = function() {
        var s = document.head.childNodes, node;
        if (s.length < 5) {
            for (node of s) {
                if (node.httpEquiv === 'refresh') {
                    window.close();
                }
            }
        }
        gardener('span[class],ul[class],span[id],ul[id]', /\/\d{12,}\.php/i, {root:'#sidebar1', observe:true});
        gardener('div[id][style*="!important"]', /!important/i);
    };
    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:'.aside-news-block'});
    };

    scripts['turbobit.net'] = {'now': preventBackgroundRedirect};

    scripts['yap.ru'] = function() {
        var words = /member1438|Administration/;
        gardener('form > table[id^="p_row_"]', words);
        gardener('tr > .holder.newsbottom', words, {parent:'tr', siblings:-2});
    };
    scripts['yaplakal.com'] = scripts['yap.ru'];

    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) {
                            spider.setAttribute('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['online.anidub.com'] = 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['rsload.net'] = {
        'load': function() {
            var dis = document.querySelector('.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@');
            }
        }
    };

    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);
        }
    };

    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);
    }
})();