E-Hentai Automated Downloads

Automates downloads through the Doggie Bag Archiver

Versión del día 7/9/2016. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name           E-Hentai Automated Downloads
// @description    Automates downloads through the Doggie Bag Archiver
// @include        http://g.e-hentai.org/*
// @include        https://exhentai.org/*
// @include        http://*/*automatedEHDL=*
// @run-at         document-start
// @author         etc
// @version        1.2.2
// @namespace https://greasyfork.org/users/2168
// ==/UserScript==

var automating = (window.location.href.indexOf('automatedEHDL') != -1);

var addMetadata = function(url,metadata) {
    return url +
        (url.indexOf('?') != -1 ? '&' : '?') + 'automatedEHDL=' + metadata.nonce +
        '&automatedTorrent=' + (metadata.isTorrent ? 1 : 0);
};
       
var getMetadata = function(url) {
    var metadata = url.match(/automatedEHDL=(\d+).*automatedTorrent=(\d)/);
    return { nonce: metadata[1], isTorrent: metadata[2] == '1' };
};

if (automating) {

    var clear     = function() { for (var i=0;i<10;++i) clearTimeout(i); };
    var abort     = function(reason) { parent.postMessage({ type: 'failure', nonce: metadata.nonce, reason: reason },'*'); };
    var heartbeat = function() { parent.postMessage({ type: 'heartbeat', nonce: metadata.nonce },'*'); };

    var metadata = getMetadata(window.location.href), target;

    if (window.location.href.indexOf('archive') != -1)
        document.addEventListener('DOMSubtreeModified',clear,false);

    var onLoad = function() {

        for (var i=0;i<100;++i) clearTimeout(i);

        target = document.evaluate('.//a[starts-with(text(),"' + (metadata.isTorrent ? 'Torrent' : 'Archive') + ' Download")]',document,null,9,null).singleNodeValue;
        if (target !== null) {
            if (metadata.isTorrent && /\( 0 \)/.test(target.innerHTML)) abort('could not find any torrent');
            else {
                heartbeat();
                var url = target.getAttribute('onclick').match(/'(.+?)'/)[1];
                window.location.replace(addMetadata(url,metadata));
            }
            return;
        }

        // download confirmation popup
        target = document.evaluate('.//input[@value="Download Original Archive"]',document,null,9,null).singleNodeValue;
        if (target !== null) {
            heartbeat();
            target.parentNode.parentNode.action = addMetadata(target.parentNode.parentNode.action,metadata);
            target.click();
            return;
        }

        // server location popup
        target = document.evaluate('.//script[contains(text(),"gotonext")]',document,null,9,null).singleNodeValue;
        if (target !== null) {
            heartbeat();
            var url   = target.innerHTML.match(/document.location = "(.+?)"/)[1];
            var delay = target.innerHTML.match(/(\d+)\)/)[1];
            document.removeEventListener('DOMSubtreeModified',clear,false);
            setTimeout(function() { window.location.replace(addMetadata(url,metadata)); },parseInt(delay,10));
            return;
        }
        
        // download ready popup
        target = document.evaluate('.//a[text()="Click Here To Start Downloading"]',document,null,9,null).singleNodeValue;
        if (target !== null) {
            parent.postMessage({ type: 'success', nonce: metadata.nonce, url: target.href },'*');
            return;
        }

        // torrent page
        target = document.evaluate('.//input[@name="torrent_info"]',document,null,9,null).singleNodeValue;
        if (target != null) {
            var targets = Array.prototype.slice.call(document.querySelectorAll('[name="gtid"] + table'),0);
            targets = targets.map(function(x) {
                var link = x.querySelector('a').href;
                var data = x.textContent.match(/Seeds:\s*(\d+)(?:.|\n)*Peers:\s*(\d+)/);
                return { link: link, seeds: parseInt(data[1],10), peers: parseInt(data[2],10) };
            });
            targets = targets.sort(function(a,b) { return b.seeds - a.seeds; });
            if (targets.length === 0) abort('could not find any torrent');
            else if (targets[0].seeds === 0) abort('could not find any seeded torrent');
            else parent.postMessage({ type: 'success', nonce: metadata.nonce, url: targets[0].link },'*');
            return;
        }

        // we really shouldn't be here
        abort('No viable option found. Perhaps you\'re not logged in?\nCurrent URL: ' + window.location.href);

    };

    if (document.readyState == 'complete') onLoad();
    else window.addEventListener('load',onLoad,false);

} else {

    var downloadData = { }, downloadQueue = [ ];

    var loadingGIF =
        'R0lGODlhEgASAMQaAHl5d66urMXFw3l5dpSUk5WVlKOjoq+vrsbGw6Sko7u7uaWlpbm5t3h4doiIhtLSz4aGhJaWlsbGxNHRzrC' +
        'wr5SUkqKiobq6uNHRz4eHhf///wAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAaACwAAAAAEgASAAAFaq' +
        'AmjmRplstyrkmbrCNFaUZtaFF0HvyhWRZNYVgwBY4BEmFJOB1NlYpJoYBpHI7RZXtZZb4ZEbd7AodFDIYVAjFJJCYA4ISoI0hyu' +
        'UnAF2geDxoDgwMnfBoYiRgaDQ1WiIqPJBMTkpYaIQAAIfkEBQoAGgAsAQABABAAEAAABWSgJo4aRZEoeaxHOiqKFsyBtizopV9y' +
        'nfwJ0o43MhgNKAYjZbGQJBLXKBLRIK4IaWFbEHgFUoKYoPFKRZUK6fFIORwojBxDytgzpDkdANDc8SQTExp8fBoQEGcDiwNnJA0' +
        'NLiEAACH5BAUKABoALAEAAQAQABAAAAVloCaOmqKQKHmtVzpKksa2FIUiOKIxjHb8B5JgKCAFjgHUMHUkPR6u0WKhwVgx0YQ2cc' +
        'W6DGCDZjKJiiwWEgCQikRQ6zWpQC+QBviBxuHQEP4EKA0NGhmGGRoVFWaHiGYjEBAuIQAAIfkEBQoAGgAsAQABABAAEAAABWSgJ' +
        'o6aJJEoiaxIOj6PJsyCpigopmNyff0X0o43AgZJk0mKwSABAK4RhaJ5PqOH7GHAHUQD4ICm0YiKwCSHI7VYoDLwDClBT5Di8khE' +
        'Y+gbUBAQGgWEBRoWFmYEiwRmJBUVLiEAACH5BAUKABoALAEAAQAQABAAAAVloCaO2vOQKImtWDoCgMa2koTCsDZNGuIjpIFwQBI' +
        'YBahGI2UkORyukUKhyVgz0Yv2csW6thcNBBIVMRikSCRFoaAK8ALpQD+QCHiCZrHQBP4BKBUVGgmGCX6BUQaMBmUkFhYuIQAAIf' +
        'kEBQoAGgAsAQABABAAEAAABWagJo4aAJAoaZrp6DjaIA/a86BZnmlNo2FADEm3GwWFJAgkNZmQIpHWSCLRFK4FKWKLIHgJUoFYo' +
        'KlUpCIxabFIKRSohDxButgvJIPeoKFQNHd4JBYWGgeHBxoMDGgBjgFoJI4tIQAAIfkEBQoAGgAsAQABABAAEAAABWSgJo6a45Ao' +
        'ma1ZOkaRxrYAgBZ4oUGQVtckgpBAGhgHqEol1WiQFgvX6PHQJK4JKWaLMXgNWq7GYpGKJhMShZKSSFCH+IGEqCNIgXxAo1BoBIA' +
        'CKHkaF4YXf4JSh4hmIwwMLiEAACH5BAUKABoALAEAAQAQABAAAAVloCaOWhSRKFmsRToui0bMhOY4aKInWlVpmWCGZCgaSMIhyW' +
        'JJQSAkCsU1AgA0h+yBarUGvgHqYDzQfKmiRoOkUKQeD9RlfiFh7hgSvS6RaPB5JAwMGgiGCBoTE2gCjQJoJI0uIQAAOw==';

    var icons = {
        download : 'M8.037,11.166L14.5,22.359c0.825,1.43,2.175,1.43,3,0l6.463-11.194c0.826-1.429,0.15-2.598-' +
            '1.5-2.598H9.537C7.886,8.568,7.211,9.737,8.037,11.166z',
        torrent  : 'M22.404,13.585c0-5.319-4.313-9.631-9.632-9.631c-5.32,0-9.632,4.313-9.632,9.631c0,4.1,2.5' +
            '67,7.593,6.177,8.982l-1.818-8.45l-0.514-2.388L6.075,7.505L9.6,6.746l1.303,6.059c0.352,1.636,1.0' +
            '94,2.514,2.316,2.25c0.967-0.208,1.377-0.995,1.487-1.597c0.049-0.228,0.013-0.51-0.047-0.786l-1.4' +
            '43-6.705L16.74,5.21l1.646,7.651c0.662,3.077,2.454,3.548,2.454,3.548s-2.419,0.521-3.433,0.738c-1' +
            '.012,0.219-1.694-1.591-1.694-1.591l-0.07,0.015c-0.288,0.785-0.613,2.06-3.127,2.602c-0.184,0.039' +
            '-0.364,0.064-0.542,0.083l1.064,4.948C18.232,23.063,22.404,18.814,22.404,13.585z',
        picker   : 'M22.727,18.242L4.792,27.208l8.966-8.966l-4.483-4.484l17.933-8.966l-8.966,8.966L22.727,18.242z',
        done     : 'M2.379,14.729 5.208,11.899 12.958,19.648 25.877,6.733 28.707,9.561 12.958,25.308z'
    };

    var getIcon = function(name,color) {
        return 'url("data:image/svg+xml,<svg viewBox=\'0 0 30 30\' preserveAspectRatio=\'true\' xmlns=\'http' +
            '://www.w3.org/2000/svg\'><path fill=\'' + color + '\' d=\'' + icons[name] + '\'/></svg>")';
    };

    var createButton = function(data) {
        var result = document.createElement(data.hasOwnProperty('type') ? data.type : 'a');
        if (data.hasOwnProperty('class')) result.className = data.class;
        if (data.hasOwnProperty('title')) result.title = data.title;
        if (data.hasOwnProperty('onClick')) result.addEventListener('click',data.onClick,false);
        if (data.hasOwnProperty('parent')) data.parent.appendChild(result);
        if (data.hasOwnProperty('target')) result.setAttribute('target',data.target);
        if (data.hasOwnProperty('style'))
            result.style.cssText = Object.keys(data.style).map(function(x) { return x + ': ' + data.style[x] + 'px'; }).join('; ');
        return result;
    };

    var start = function() {

        // button generation (thumbnail list)
        var thumbnails = document.querySelectorAll('.id3 > a'), n = thumbnails.length;
        while (n --> 0) {
            var bottom = Math.max(0,parseInt(thumbnails[n].parentNode.style.height,10) - thumbnails[n].firstChild.height);
            var right  = Math.max(0,0.5 * (200 - thumbnails[n].firstChild.width));
            createButton({ class: 'automatedButton downloadLink', title: 'Automated download', target: thumbnails[n].href,
                style: { bottom: bottom, right: right }, onClick: requestDownload, parent: thumbnails[n] });
            createButton({ class: 'automatedButton torrentLink', title: 'Torrent download', target: thumbnails[n].href,
                style: { bottom: bottom, left: 1 }, onClick: requestDownload, parent: thumbnails[n] });
        }

        // button generation (gallery)
        var bigThumbnail = document.querySelector('#gd1 > img');
        if (bigThumbnail !== null) {
            var bottom = bigThumbnail.parentNode.parentNode.clientHeight - bigThumbnail.offsetTop - bigThumbnail.height - 1;
            var right  = bigThumbnail.parentNode.parentNode.clientWidth - bigThumbnail.offsetLeft - bigThumbnail.width - 2;
            var left   = bigThumbnail.offsetLeft + 1;
            createButton({ class: 'automatedButton downloadLink', title: 'Automated download', target: window.location.href,
                style: { bottom: bottom, right: right }, onClick: requestDownload, parent: bigThumbnail.parentNode });
            createButton({ class: 'automatedButton torrentLink', title: 'Torrent download', target: window.location.href,
                style: { bottom: bottom, left: left }, onClick: requestDownload, parent: bigThumbnail.parentNode });
        }

        // button generation (row list)
        var rows = document.querySelectorAll('.it5 > a'), n = rows.length;
        while (n --> 0) {
            var div = createButton({ type: 'div', class: 'automatedPicker', onClick: requestDownload, parent: rows[n].parentNode });
            var picker = createButton({ type: 'div', parent: div });
            createButton({ type: 'div', class: 'automatedInline torrentLink', title: 'Torrent download', 
                target: rows[n].href, parent: picker });
            createButton({ type: 'div', class: 'automatedInline downloadLink', title: 'Automated download',
                target: rows[n].href, parent: picker });
        }

        // message listener
        window.addEventListener('message',function(message) {
            var data = message.data;
            if (!downloadData.hasOwnProperty(data.nonce)) return;
            if (data.type == 'heartbeat') onHeartbeat(data);
            else if (data.type == 'success') onSuccess(data);
            else onFailure(data);
        },false);

        // document style
        var style = document.createElement('style');
        style.innerHTML =
            '.automatedButton { display: none; position: absolute; text-align: left; cursor: pointer; padding: 8px;' +
                'color: white; margin-right: 1px; font-size: 20px; line-height: 11px; }' +
            '.downloadLink  { background-image: ' + getIcon('download','rgb(0,0,0)') + '; background-color: rgba(98,220,151,1); }' +
            '.torrentLink  { background-image: ' + getIcon('torrent','rgb(0,0,0)') + '; background-color: rgba(98,182,210,1); }' +
            '.torrentLink:not(.requested) { background-position: 2px 2px; }' +
            '.requested  { background-image: ' + getIcon('done','rgb(0,0,0)') + '; }' +
            '.requested, .working { background-color: rgba(255,143,113,1); }' +
            '.automatedButton.downloadLink  { border-radius: 0 0 5px 0 !important; width: 12px; height: 12px; }' +
            '.automatedButton.torrentLink  { border-radius: 0 0 0 5px !important; width: 12px; height: 12px; }' +
            '#gd1 > .automatedButton { border-radius: 0 0 0 0 !important; }' +
            '.working { background-image: url(data:image/gif;base64,' + loadingGIF + ') !important; background-repeat: no-repeat; }' +
            '.automatedInline.working { background-position: 3px 3px; }' +
            '.automatedButton.working { width: 18px; height: 18px; font-size: 0px; background-position: 5px 5px; padding: 5px !important; }' +
            '.automatedPicker { background-image: ' + getIcon('picker','rgb(252,0,97)') + '; width: 16px;' + 
                'height: 16px; float: left; cursor: pointer; }' +
            '.automatedButton:hover, .automatedInline:hover { background-color: rgba(255,199,139,1) !important; color: black !important; }' +
            '*:hover > .automatedButton, .automatedButton.working, .automatedButton.requested { display: block !important; }' +
            '.EHADiframe { width: 0px !important; height: 0px !important; opacity: 0 !important; }' +
            '.automatedPicker > div { display: none; z-index: 2; position: absolute; top: -4px; text-align: center; }' +
            '.automatedPicker:hover > div, .automatedPicker > div:hover { display: block; }' +
            '.automatedInline { padding: 3px; border: 1px solid black; width: 17px; height: 17px; display: inline-block; }' +
            '.automatedInline:first-child { border-right: none !important; }';
        document.head.appendChild(style);

    };

    var startDownload = function(url) {
        downloadQueue.push(url);
        doDownload(false);
    };

    var doDownload = function(force) {
        if (doDownload.inhibit && !force) return;
        if (downloadQueue.length === 0) {
            doDownload.inhibit = false;
            return;
        }
        doDownload.inhibit = true;
        var a = document.createElement('a');
        // don't use display: none as some versions of firefox don't like it
        a.style.cssText = 'width: 0px; height: 0px; overflow: hidden; white-space: nowrap; visibility: hidden;';
        a.href = downloadQueue.splice(0,1)[0];
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        setTimeout(function() { doDownload(true); },1000);
    };

    var onHeartbeat = function(message) {
        generateTimeout(message.nonce);
    };

    var onSuccess = function(message) {
        var data = downloadData[message.nonce];
        document.body.removeChild(data.iframe);
        data.button.className = data.button.className.replace(/working/,'requested');
        clearTimeout(data.timeout);
        delete downloadData[message.nonce];
        startDownload(message.url);
    };

    var onFailure = function(message) {
        var data = downloadData[message.nonce];
        document.body.removeChild(data.iframe);
        data.button.className = data.button.className.replace(/\s?working/,'');
        clearTimeout(data.timeout);
        delete downloadData[data.nonce];
        alert('Something went wrong. Reason: ' + message.reason);
    };
    
    var generateTimeout = function(nonce) {
        if (!downloadData.hasOwnProperty(nonce)) return;
        clearTimeout(downloadData[nonce].timeout);
        downloadData[nonce].timeout = setTimeout(function() {
            onFailure({ nonce: nonce, reason: 'Operation timed out. Try again or download manually.' });
        },10000);
    };

    var requestDownload = function(e) {
        if (/working|requested/.test(e.target.className)) return; 
        e.preventDefault();
        e.target.className += ' working';
        var isTorrent = /torrentLink/.test(e.target.className);
        var gallery   = e.target.getAttribute('target');
        var nonce     = Math.floor(Math.random() * (1<<30));
        var iframe    = document.createElement('iframe');
        downloadData[nonce] = { button: e.target, iframe: iframe, timeout: null };
        generateTimeout(nonce);
        document.body.appendChild(iframe);
        iframe.className = 'EHADiframe';
        iframe.src = addMetadata(gallery,{ nonce: nonce, isTorrent: isTorrent });
    };

    window.addEventListener('load',start,false);

}