pixiv helper

A small script to download the new png animated image in pixiv

As of 2014-06-30. See the latest version.

// ==UserScript==
// @name        pixiv helper
// @namespace   http://mfish.twbbs.org/
// @include     http://www.pixiv.net/member_illust.php?mode=medium&illust_id=*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
// @require     https://greasyfork.dpdns.org/scripts/2350-filesaver-js/code/filesaverjs.js?version=6255
// @require     http://cdnjs.cloudflare.com/ajax/libs/jszip/2.3.0/jszip.min.js
// @version     0.2
// @grant       GM_registerMenuCommand
// @grant       GM_openInTab
// @description A small script to download the new png animated image in pixiv
// ==/UserScript==

var global = unsafeWindow;
this.$ = this.jQuery = $.noConflict();

//https://gist.github.com/lsauer/5196979
//lsauer.com , lo sauer 2013
//JavaScript List of selected MIME types
//A comprehensive MIME List is available here: https://gist.github.com/lsauer/2838503

var mimeTypes =
{
'a' : 'application/octet-stream',
'ai' : 'application/postscript',
'aif' : 'audio/x-aiff',
'aifc' : 'audio/x-aiff',
'aiff' : 'audio/x-aiff',
'au' : 'audio/basic',
'avi' : 'video/x-msvideo',
'bat' : 'text/plain',
'bin' : 'application/octet-stream',
'bmp' : 'image/x-ms-bmp',
'c' : 'text/plain',
'cdf' : 'application/x-cdf',
'csh' : 'application/x-csh',
'css' : 'text/css',
'dll' : 'application/octet-stream',
'doc' : 'application/msword',
'dot' : 'application/msword',
'dvi' : 'application/x-dvi',
'eml' : 'message/rfc822',
'eps' : 'application/postscript',
'etx' : 'text/x-setext',
'exe' : 'application/octet-stream',
'gif' : 'image/gif',
'gtar' : 'application/x-gtar',
'h' : 'text/plain',
'hdf' : 'application/x-hdf',
'htm' : 'text/html',
'html' : 'text/html',
'jpe' : 'image/jpeg',
'jpeg' : 'image/jpeg',
'jpg' : 'image/jpeg',
'js' : 'application/x-javascript',
'ksh' : 'text/plain',
'latex' : 'application/x-latex',
'm1v' : 'video/mpeg',
'man' : 'application/x-troff-man',
'me' : 'application/x-troff-me',
'mht' : 'message/rfc822',
'mhtml' : 'message/rfc822',
'mif' : 'application/x-mif',
'mov' : 'video/quicktime',
'movie' : 'video/x-sgi-movie',
'mp2' : 'audio/mpeg',
'mp3' : 'audio/mpeg',
'mp4' : 'video/mp4',
'mpa' : 'video/mpeg',
'mpe' : 'video/mpeg',
'mpeg' : 'video/mpeg',
'mpg' : 'video/mpeg',
'ms' : 'application/x-troff-ms',
'nc' : 'application/x-netcdf',
'nws' : 'message/rfc822',
'o' : 'application/octet-stream',
'obj' : 'application/octet-stream',
'oda' : 'application/oda',
'pbm' : 'image/x-portable-bitmap',
'pdf' : 'application/pdf',
'pfx' : 'application/x-pkcs12',
'pgm' : 'image/x-portable-graymap',
'png' : 'image/png',
'pnm' : 'image/x-portable-anymap',
'pot' : 'application/vnd.ms-powerpoint',
'ppa' : 'application/vnd.ms-powerpoint',
'ppm' : 'image/x-portable-pixmap',
'pps' : 'application/vnd.ms-powerpoint',
'ppt' : 'application/vnd.ms-powerpoint',
'pptx' : 'application/vnd.ms-powerpoint',
'ps' : 'application/postscript',
'pwz' : 'application/vnd.ms-powerpoint',
'py' : 'text/x-python',
'pyc' : 'application/x-python-code',
'pyo' : 'application/x-python-code',
'qt' : 'video/quicktime',
'ra' : 'audio/x-pn-realaudio',
'ram' : 'application/x-pn-realaudio',
'ras' : 'image/x-cmu-raster',
'rdf' : 'application/xml',
'rgb' : 'image/x-rgb',
'roff' : 'application/x-troff',
'rtx' : 'text/richtext',
'sgm' : 'text/x-sgml',
'sgml' : 'text/x-sgml',
'sh' : 'application/x-sh',
'shar' : 'application/x-shar',
'snd' : 'audio/basic',
'so' : 'application/octet-stream',
'src' : 'application/x-wais-source',
'swf' : 'application/x-shockwave-flash',
't' : 'application/x-troff',
'tar' : 'application/x-tar',
'tcl' : 'application/x-tcl',
'tex' : 'application/x-tex',
'texi' : 'application/x-texinfo',
'texinfo': 'application/x-texinfo',
'tif' : 'image/tiff',
'tiff' : 'image/tiff',
'tr' : 'application/x-troff',
'tsv' : 'text/tab-separated-values',
'txt' : 'text/plain',
'ustar' : 'application/x-ustar',
'vcf' : 'text/x-vcard',
'wav' : 'audio/x-wav',
'wiz' : 'application/msword',
'wsdl' : 'application/xml',
'xbm' : 'image/x-xbitmap',
'xlb' : 'application/vnd.ms-excel',
'xls' : 'application/vnd.ms-excel',
'xlsx' : 'application/vnd.ms-excel',
'xml' : 'text/xml',
'xpdl' : 'application/xml',
'xpm' : 'image/x-xpixmap',
'xsl' : 'application/xml',
'xwd' : 'image/x-xwindowdump',
'zip' : 'application/zip'
}

function last(arr) {
    var l = arr.length;
    return arr[l - 1];
}

function getMIME(name) {
    return mimeTypes[getFileExtension(name)] || '';
}
function getFileExtension(name) {
    return last(name.split('.'));
}
function extractFiles(blob, callback) {
    var fileReader = new FileReader();
    fileReader.onload = function() {
        var arrayBuffer = this.result;

        var zip = new JSZip();
        zip.load(arrayBuffer);
        var file = zip.file(/(jpg|png|gif|bmp)/ig);
        console.log(file);
        file.forEach(function(file){
            var fileName, arrayBuffer, mime, blob;
            if(file.dir) {return;}
            fileName = file.name;
            arrayBuffer = file.asArrayBuffer();
            mime = getMIME(fileName);
            //console.log(arrayBuffer);
            //console.log(mime);
            blob = new Blob([arrayBuffer], {type : mime});
            callback(blob, fileName, mime)
        })
        
    };
    fileReader.readAsArrayBuffer(blob);
}

var download = function(){
    var cachedFile = {};
    function download(src, callback) {
        if (cachedFile[src]) {
            setTimeout(function(){
                callback(cachedFile[src]);
            }, 0)
            return;
        }

        //console.log(src);
        var oReq = new XMLHttpRequest();
        oReq.open("GET", src, true);
        oReq.responseType = "blob";

        oReq.onload = function (oEvent) {
            var blob, objectURL;
            blob = oReq.response; // Note: not oReq.responseText
            if (blob) {
                cachedFile[src] = blob;
                callback(blob);
                //objectURL = URL.createObjectURL(blob);
                //GM_openInTab(objectURL);
            } else {
                console.log('fail to download', src);
            }
        };
        oReq.send(null);
    }
    return download;
}();

function getUrl (blob, name) {
    return URL.createObjectURL(blob);
}


$('body').append(modal);
(function($){
    var defaultOption = {
        stat : 'on'
    };
    function off(el) {
        el = $(el);
        el.find('.modal').slideUp(500,function(){
            el.fadeOut(200);
        });
    }
    function on(el) {
        el = $(el);
        el.find('.modal').hide();
        el.fadeIn(200,function(){
            el.find('.modal').slideDown(500);
        });
    }
    $.fn.modal = function modal(option) {
        option = option || {};
        $.extend(option, defaultOption);
        var _modal = $(this);
        if (!_modal.is('.inited')) {
            _modal.on('click', function(e){
                if ($(e.target).is('.mmis1000-modal .exit')) {
                    off(_modal);
                }
                if ($(e.target).is('.mmis1000-modal')) {
                    off(_modal);
                }
            });
            _modal.addClass('inited');
        }
        switch (option.stat) {
            case "on":
                on(_modal);
                break;
            case "off":
                off(_modal);
                break;
            default:
                on(_modal);
        }
    };
}(jQuery));

var modal_css = ".mmis1000-modal{background:rgba(128,128,128,0.5);bottom:0;display:none;left:0;overflow:hidden;position:fixed;right:0;top:0;z-index:99999}"+
    ".mmis1000-modal .modal{background:#fff;border-radius:10px;bottom:25px;left:25px;position:absolute;right:25px;top:25px}"+
    ".mmis1000-modal .modal .head{border-bottom-color:#ddd;border-bottom-style:solid;border-bottom-width:2px;height:30px;left:0;padding-left:5px;position:absolute;right:0;top:0}"+
    ".mmis1000-modal .modal .head .text{color:#666;font-size:20px;line-height:30px}"+
    ".mmis1000-modal .modal .head .exit{background:red;border-radius:4px;color:#fff;cursor:pointer;font-size:20px;height:20px;line-height:20px;position:absolute;right:5px;text-align:center;top:5px;width:20px}"+
    ".mmis1000-modal .modal .content-wrapper{bottom:10px;left:0;overflow:auto;position:absolute;right:0;top:32px}"+
    ".mmis1000-modal .modal .content-wrapper .content{font-size:18px;left:10px;position:absolute;right:10px;text-align:center;top:10px}"+
    ".mmis1000-modal .modal .content-wrapper .content img{max-width:100%}";
$('head').append($('<style></style>').html(modal_css));
var modal = $([
    "<div id='test' class='mmis1000-modal'>",
        "<div class='modal'>",
            "<div class='head'>",
                "<span class='text'>大圖檢視</span>",
                "<div class='exit'>",
                    "X",
                "</div>",
            "</div>",
            "<div class='content-wrapper'>",
                "<div class='content'>",
                "</div>",
            "</div>",
        "</div>",
    "</div>"
].join(''));
$('body').append(modal);
var modalContent = modal.find('.content');
//$(modal).modal();//debug
/*=== main program starts from here ===*/

GM_registerMenuCommand( '下載檔案!', downloadSmall);
GM_registerMenuCommand( '下載檔案!(大圖)', downloadFullScreen);
GM_registerMenuCommand( '檢視個別檔案!(大圖)', showPictures);

function checkUp() {
    if (!global.pixiv.context.ugokuIllustData) {
        alert('這看起來只是一般的gif或靜圖歐,請直接右鍵下載!');
        throw new Error('can not found zipped image source');
    }
}

function downloadSmall() {
    checkUp()
    var context = global.pixiv.context;
    var illustrate = context.ugokuIllustData;
    var src = illustrate.src;
    download(src, function(blob) {
        objectURL = getUrl(blob);
        GM_openInTab(objectURL);
    });
}

function downloadFullScreen() {
    checkUp()
    var context = global.pixiv.context;
    var illustrate = context.ugokuIllustFullscreenData;
    var src = illustrate.src;
    download(src, function(blob) {
        objectURL = getUrl(blob);
        GM_openInTab(objectURL);
    });
}

function showPictures() {
    checkUp()
    var context = global.pixiv.context;
    var illustrate = context.ugokuIllustFullscreenData;
    var src = illustrate.src;
    download(src, function(blob) {
        modal.modal();
        modalContent.html('');
        extractFiles(blob, function(blob, fileName){
            var url = getUrl(blob);
            modalContent.append($('<p></p>').text(fileName));
            modalContent.append($('<img/>').attr('src', url));
        });
    });
}
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元