shadofx / KissManga Adblock

// ==UserScript==
// @name         KissManga Adblock
// @namespace    https://openuserjs.org/scripts/shadofx
// @description  Sometimes KissManga goes out of its way to screw with ad block. Install this and disable your normal adblock to avoid ads
// @copyright    2018, shadofx (https://openuserjs.org/users/shadofx)
// @license      MIT
// @match        http://kissmanga.com/*
// @match        https://kissmanga.com/*
// @match        https://kisscartoon.ac/*
// @match        https://kissanime.ac/*
// @match        http://kissanime.ru/*
// @match        https://kissanime.ru/*
// @match        https://kimcartoon.ac/*
// @match        https://readcomiconline.to/*
// @match        http://kimcartoon.me/*
// @match        https://kimcartoon.me/*
// @updateURL    https://openuserjs.org/meta/shadofx/KissManga_Adblock.meta.js
// @grant        GM_xmlhttpRequest
// @version      5.17
// @run-at       document-start
// @require      http://code.jquery.com/jquery-1.7.2.min.js
// @require      https://unpkg.com/tesseract.js@2.0.0/dist/tesseract.min.js
// ==/UserScript==
// ==OpenUserJS==
// @author       shadofx
// ==/OpenUserJS==
var $ = jQuery;
let oldDocEvLi = EventTarget.prototype.addEventListener;
let oldWOpen = window.open;
let oldWAlert = window.alert;
function addEventListener(type,lis){
    try{
        if(type=='mousedown'||type=='mousemove'){return;}
        if(type=='click'&&lis.name=='m0'){return;}
        oldDocEvLi.call(this,type,lis)//prevent javascript popups (mostly for Edge)
    }catch(e){console.log(e)}
}
function SwapAEL(){//sabotage addEventListener and window.open and window.alert
    EventTarget.prototype.addEventListener = addEventListener
    window.open = wopen
    window.alert = walert
    let k = document.title;
    Object.defineProperty(document,'title',{
        set:function(x){console.log(x)},
        get:function(){return k}
    });//also prevent page title changes
}
function wopen(URL, name, specs, replace){
    if(URL.includes(window.location.origin)){
        oldWOpen(URL,name,specs,replace)//only open javascript navs to same origin
    }
}
function walert(text){
    console.log(text)
}
// If it's the challenge page then wait for it to finish beofore sabotage (sometimes challenge page gets stuck)
if($('head title').text()=="Please wait 5 seconds..."){setInterval(SwapAEL,5000)}else{SwapAEL()}
//RemoveAds removes the offending nodes
function RemoveAds(){
    if($('iframe[src*=captcha]').length==0)//don't block when there's google recaptcha
    {
        $("a:contains('Hide')").click();//click on hide button
        $(".divCloseBut").remove();
        $(".glx-ctrls-button").parent().parent().parent().remove()
        $('.divCloseBut').remove();
        $('[src*="propellerads"]').remove();
        $('[id^="p_"]').remove();
        $('[src*="mgid.com"]').remove();
        $('div[id^="MarketGidComposite"]').remove();
        $('a[target^="_blank"]>img').remove();//remove any image inside a link which opens in a new tab
        $('div[style*="width: 2048px"][style*="z-index: 2147483647"]').remove();//remove the massive click-interceptor that spans the entire page
        $('div[style*="z-index: 2000"]').remove();//remove the click-interceptor that blocks disqus
        $('iframe').not('#disqus_thread>iframe[src*="comments"]').not('[id^="dsq-app"]:not([src*="disqusads.com"])').not('#ifrmVast').remove();//remove iframes except for the disqus/video ones
        $('iframe[src*="ads-iframe"]').remove();//disqus ads
        $('#divImage,#btnShowComments').show();//from https://greasyfork.org/en/scripts/372860-fu-kissmanga
        $('div.bebi-icon-hover').remove();
        $('body>div[style*="absolute"]:not(.tooltip)').remove()//remove click-interceptor that blocks disqus (added 3/29/2019),with exception for tooltips, thanks FooBar@openuserjs.org
        $('#footer').remove()//footer gets in the way for some reason
        $('#__vliadb83-bg').remove()
        $('#__vliadb83').remove()
    }
    $('a[href*="bebi.com"]').remove();
    $("b:contains('[Hide]')").parent().click();//click on hide button
}
//repeatedly run RemoveAds while DOM loads
var loadproc = setInterval(RemoveAds, 50);
//When DOM is loaded...
window.addEventListener("DOMContentLoaded", () => {
    //..stop spamming RemoveAds...
    clearInterval(loadproc);
    //..because we can add more targeted handlers to spam RemoveAds more efficiently:
    document.addEventListener("readystatechange", RemoveAds);//Run when page is entirely loaded
    new MutationObserver(RemoveAds).observe($('body')[0],{childList: true}); //Run whenever body is changed
    document.addEventListener("visibilitychange", RemoveAds);//Run when you switch tabs
    loadproc = setInterval(RemoveAds, 1000);//Run every second just in case
});
var covering,tries;
window.addEventListener("load",()=>{
setTimeout(()=>{
    if($('#challenge-form').length != 0)
    {//hcaptcha exists
        covering = $('<div />').appendTo('body').css('position','absolute').css('top','0').css('bottom','0').css('width','100%').css('height','100%').css('background','#333').css('z-index','999999999')
        covering.click(()=>{covering.hide()})
        tries = 9;//9 tries should be enough, doing it too much gets your ip temporarily blocked
        BypassHCaptcha();
    }
},500)});
function BypassHCaptcha(){
    if(tries<0){covering.remove();return;}tries--;
    covering.text("Attempting to autosolve Hcaptcha.Click to Remove.Remaining attempts: "+tries);
    let sk = $('iframe[src*=sitekey]').first().attr('src').split('&').filter(c=>c.startsWith('sitekey'))[0].substring(8)
    GM_xmlhttpRequest({
        method:'POST',headers:{'Content-type':'application/x-www-form-urlencoded'},
        url:'https://hcaptcha.com/getcaptcha',
        data:'sitekey='+sk+'&host=kissmanga.com&hl=en-US',
        onabort:BypassHCaptcha,onerror:BypassHCaptcha,ontimeout:BypassHCaptcha,
        onload :(x)=>{
            let r1 =JSON.parse(x.responseText);
            let ans = {
                answers:r1.tasklist.reduce((m,o)=>{m[o.task_key]='true';return m;},{}),//select all images.
                c:'null',n:null,job_mode:r1.request_type,serverdomain:'kissmanga.com',sitekey:sk
            }
            GM_xmlhttpRequest({
                method:'POST',headers:{'Content-type':'application/json'},
                url:'https://hcaptcha.com/checkcaptcha/'+r1.key,
                data:JSON.stringify(ans),
                onabort:BypassHCaptcha,onerror:BypassHCaptcha,ontimeout:BypassHCaptcha,
                onload :(x)=>{
                    let r2 = JSON.parse(x.responseText);
                    if(r2.pass==true&&r2.error!='invalid'&&r2.generated_pass_UUID)
                    {
                        $('textarea[name="h-captcha-response"]').val(r2.generated_pass_UUID)
                        $('textarea[name="g-captcha-response"]').val(r2.generated_pass_UUID)
                        $('#challenge-form').submit()
                    }
                    else{setTimeout(BypassHCaptcha,10)}
                }
            })
        }
    })
}
//Custom Captcha Assist using canvas based image diffing and Tesseract OCR
if(window.location.pathname == "/Special/AreYouHuman2"){
    const whitelistedColors = [
        '234,1,0,255',//red
        '255,139,0,255',//orange
        '0,117,1,255',//green
        '0,1,254,255',//blue
        '114,0,118,255'//purple
    ]
    let worker = new Tesseract.createWorker({});
    function ImageIsLoaded(img){
        if(!img.complete){return false}
        if(img.naturalWidth === 0){return false}
        return true
    }
    async function GetAccessor(img){
        if(!ImageIsLoaded(img)){await new Promise(resolve => img.addEventListener('load', resolve));}
        let canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
        let context = canvas.getContext('2d')
        return {
            context: context,
            getPixel:(x,y)=>context.getImageData(x, y, 1, 1).data,
            width: img.width,
            height:img.height,
            data:()=>context.getImageData(0,0,img.width,img.height)
        }
    }
    function GetDraw(width,height){
        let canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        let context = canvas.getContext('2d')
        let idat = context.createImageData(1,1)
        let imgdat = idat.data
        return {
            canvas: canvas,
            drawPixel:(x,y,r,g,b,a)=>
            {
                imgdat[0]= r;
                imgdat[1]= g;
                imgdat[2]= b;
                imgdat[3]= a;
                context.putImageData( idat, x, y );
            },
            getPixel:(x,y)=>context.getImageData(x, y, 1, 1).data,
            width: width,
            height:height,
            data:()=>context.getImageData(0,0,width,height),
            setData:(data)=>context.putImageData(data,0,0)
        }
    }
    function AddColor(colgroup,color){
        let item = color.join(',')
        Increment(colgroup,item)
    }
    function Increment(group,item){
        if(group[item])
        {group[item] = group[item] +1}
        else
        {group[item] = 1}
    }
    function AddColorFromData(colgroup,data,offset){
        Increment(colgroup,data[offset]+','+data[offset+1]+','+data[offset+2]+','+data[offset+3])
    }
    function Diff(first,firstIndex,second,secondIndex){
        return Math.abs(first[firstIndex]-second[secondIndex])+Math.abs(first[firstIndex+1]-second[secondIndex+1])+Math.abs(first[firstIndex+2]-second[secondIndex+2])
    }
    function DiffStrCol(first,second){
        let firstSplit = first.split(',').map(c=>parseInt(c))
        let secondSplit = second.split(',').map(c=>parseInt(c))
        return Diff(firstSplit,0,secondSplit,0)
    }
    function SetRef(dest,destIndex,src,srcIndex){
        dest[destIndex] = src[srcIndex]
        dest[destIndex+1] = src[srcIndex+1]
        dest[destIndex+2] = src[srcIndex+2]
        dest[destIndex+3] = src[srcIndex+3]
    }
    function SetColor(dest,destIndex,r,g,b,a){
        dest[destIndex] = r
        dest[destIndex+1] = g
        dest[destIndex+2] = b
        dest[destIndex+3] = a
    }
    function GenDiffMap(differenceColors,maindata,otherdata,width,height){
        let sortedDifferenceColors = Object.keys(differenceColors).sort((a,b)=> differenceColors[b]-differenceColors[a]).filter(color=>{
            for(let item in whitelistedColors)
            {
                if(DiffStrCol(whitelistedColors[item],color)<10)
                {return true;}
            }
            return false;
        })
        let colmax = sortedDifferenceColors[0].split(',')
        console.log(colmax)
        let difference = GetDraw(width,height)
        let differenceinfo = difference.data()
        let differencedata = differenceinfo.data
        for (let i = 0; i < maindata.length; i += 4) {
            if(Diff(maindata,i,colmax,0)>50)
            {SetColor(differencedata,i,0,0,0,0)}
            else
            {
                if(Diff(maindata,i,otherdata,i)>100)
                {SetRef(differencedata,i,maindata,i)}
                else
                {SetColor(differencedata,i,255,0,255,255)}
            }
        }
        difference.setData(differenceinfo)
        return difference.canvas
    }
    async function GenDiffMapPair(firstimg,secondimg){
        let first = await GetAccessor(firstimg)
        let second = await GetAccessor(secondimg)
        let firstDifferenceColors = {}
        let secondDifferenceColors = {}
        let firstdata = first.data().data
        let seconddata = second.data().data
        for (let i = 0; i < firstdata.length; i += 4) {
            if(Diff(firstdata,i,seconddata,i)>100)
            {
                AddColorFromData(firstDifferenceColors,firstdata,i)
                AddColorFromData(secondDifferenceColors,seconddata,i)
            }
        }
        let firstdiffmap = GenDiffMap(firstDifferenceColors,firstdata,seconddata,first.width,first.height);
        let seconddiffmap = GenDiffMap(secondDifferenceColors,seconddata,firstdata,second.width,second.height);
        return [{img: firstimg, diffmap:firstdiffmap},{img: secondimg, diffmap:seconddiffmap}]
    }
    window.addEventListener("load",()=>{//auto returns from error page
        let dest = document.evaluate('//a[text()="HERE"]').iterateNext().href
        if(dest){window.location = dest}
    })
    window.addEventListener("DOMContentLoaded", async () => {
        await worker.load();
        await worker.loadLanguage('eng');
        await worker.initialize('eng');
        let spans = $('span[style="font-weight: bold; color: #d5f406"]');
        let terms = spans.toArray().map(d=>'cap-'+d.innerText.split(', ').slice(0,2).sort().join('_'));
        let numbers = spans.toArray().map(d=>d.innerText.split(', ')[2]);
        console.log(numbers)
        let images = $('img[indexvalue]');
        let promises = new Array();
        for(let i = 0;i<images.length;i+=2){promises.push(GenDiffMapPair(images[i],images[i+1]))}
        let numProcessedImages = 0;
        let numUsage = {}
        for(let i in promises)
        {
            let result = await promises[i]
            for(let item in result)
            {
                let data = await (worker.recognize(result[item].diffmap));
                numbers.forEach(n=>{
                    if(data.data.text.includes(n)){
                        Increment(numUsage,n)
                        result[item].img.setAttribute('result',n)
                        return;
                    }
                });
                if(!result[item].img.getAttribute('result')) {result[item].img.style.cssText = "opacity:0.3"}
                numProcessedImages++;
                if(numProcessedImages == images.length)//done with all image recog
                {
                    let remainder = new Array()
                    for(let item in numUsage)
                    {
                        let matching = $('img[indexvalue][result="'+item+'"]')
                        if(numUsage[item]===1)
                        {
                            matching.click()
                            spans.filter((_,d)=>d.innerText.includes(item)).css('color','#aaaaaa')
                            await new Promise(resolve => setTimeout(resolve, 500));
                        }
                        else
                        {
                            matching.each((_,d)=>{
                                if(d.style.cssText != "opacity:0.3")
                                {remainder.push(d)}
                            })
                        }
                    }
                }
            }
        }
    })
}