// ==UserScript== // @name Pixiv animated image downloader (and gif converter) English version // @namespace https://greasyfork.org/scripts/367780 // @include http://www.pixiv.net/member_illust.php?mode=medium&illust_id=* // @include https://www.pixiv.net/member_illust.php?mode=medium&illust_id=* // @require https://cdn.staticfile.org/jquery/1.11.1/jquery.min.js // @require https://greasyfork.org/scripts/2350-filesaver-js/code/filesaverjs.js?version=6255 // @require https://cdn.staticfile.org/jszip/2.3.0/jszip.min.js // @require https://greasyfork.org/scripts/2963-gif-js/code/gifjs.js?version=8462 // @version 1.0.3e // @grant GM_registerMenuCommand // @grant GM_openInTab // @description A small script to download the new png animated image in pixiv. This modification has an english interface instead of the original chinese. // @downloadURL https://update.greasyfork.icu/scripts/367780/Pixiv%20animated%20image%20downloader%20%28and%20gif%20converter%29%20English%20version.user.js // @updateURL https://update.greasyfork.icu/scripts/367780/Pixiv%20animated%20image%20downloader%20%28and%20gif%20converter%29%20English%20version.meta.js // ==/UserScript== // Generated by CommonJS Everywhere 0.9.7 (function (global) { function require(file, parentModule) { if ({}.hasOwnProperty.call(require.cache, file)) return require.cache[file]; var resolved = require.resolve(file); if (!resolved) throw new Error('Failed to resolve module ' + file); var module$ = { id: file, require: require, filename: file, exports: {}, loaded: false, parent: parentModule, children: [] }; if (parentModule) parentModule.children.push(module$); var dirname = file.slice(0, file.lastIndexOf('/') + 1); require.cache[file] = module$.exports; resolved.call(module$.exports, module$, module$.exports, dirname, file); module$.loaded = true; return require.cache[file] = module$.exports; } require.modules = {}; require.cache = {}; require.resolve = function (file) { return {}.hasOwnProperty.call(require.modules, file) ? require.modules[file] : void 0; }; require.define = function (file, fn) { require.modules[file] = fn; }; var process = function () { var cwd = '/'; return { title: 'browser', version: 'v0.10.26', browser: true, env: {}, argv: [], nextTick: global.setImmediate || function (fn) { setTimeout(fn, 0); }, cwd: function () { return cwd; }, chdir: function (dir) { cwd = dir; } }; }(); require.define('/pixiv_helper.coffee', function (module, exports, __dirname, __filename) { var Button, Deferer, Downloader, EventEmitter, Extracter, Gifcreater, GifFrames, ImageCreater, lib, main, Menu, Modal, Util; EventEmitter = require('events', module).EventEmitter; Modal = require('/view/modal.js', module); Menu = require('/view/menu.coffee', module); Button = require('/view/downloadButton.coffee', module); Util = require('/util.js', module); lib = { $: jQuery, JSZip: JSZip, GIF: GIF, GIF_worker_URL: GIF_worker_URL, saveAs: saveAs }; Deferer = function (super$) { extends$(Deferer, super$); function Deferer() { this.all = 0; this.counted = 0; } Deferer.prototype.add = function () { return this.all++; }; Deferer.prototype.count = function () { this.counted++; this.emit('progress', { all: this.all, fired: this.counted }); if (this.counted === this.all) return this.emit('done'); }; return Deferer; }(EventEmitter); ImageCreater = function (super$1) { extends$(ImageCreater, super$1); function ImageCreater(param$, param$1) { if (null == param$) param$ = Deferer; this.Deferer = param$; if (null == param$1) param$1 = lib.$; this.$ = param$1; this.locked = false; } ImageCreater.prototype.create = function (blobs) { var file, imgElement, imgURL; if (this.locked === true) { console.log('incorrect invoke'); return false; } this.locked = true; console.log('image create start'); this.deferer = new this.Deferer; for (var i$ = 0, length$ = blobs.length; i$ < length$; ++i$) { file = blobs[i$]; imgURL = Util.getUrl(file.blob); imgElement = document.createElement('img'); imgElement.src = imgURL; file.image = imgElement; this.deferer.add(); this.$(imgElement).on('load', function (this$) { return function () { this$.deferer.count(); return true; }; }(this)); } this.deferer.on('done', function (this$) { return function () { this$.emit('done', blobs); this$.deferer.removeAllListeners('done'); this$.deferer = null; this$.removeAllListeners('done'); this$.locked = false; return true; }; }(this)); return true; }; return ImageCreater; }(EventEmitter); GifFrames = function () { function GifFrames(param$) { if (null == param$) param$ = []; this.frames = param$; } GifFrames.prototype.add = function (imgElement, delay) { this.frames.push({ image: imgElement, delay: delay }); return true; }; return GifFrames; }(); Gifcreater = function (super$2) { extends$(Gifcreater, super$2); function Gifcreater(param$, param$1) { if (null == param$) param$ = lib.GIF; this.Gif = param$; if (null == param$1) param$1 = lib.GIF_worker_URL; this.Gif_worker_path = param$1; this.locked = false; this.cachedFrames = []; this.cachedGif = []; } Gifcreater.prototype.render = function (gifFrames, size) { var frame, index; if (this.locked === true) { console.log('incorrect invoke'); return false; } index = this.cachedFrames.indexOf(gifFrames); if (index >= 0) { this.emit('finished', this.cachedGif[index]); this.removeAllListeners('finished'); return true; } this.locked = true; console.log('Gif create start'); this.gif = new this.Gif({ workers: 2, quality: 10, workerScript: this.Gif_worker_path, width: size[0], height: size[1] }); for (var i$ = 0, length$ = gifFrames.length; i$ < length$; ++i$) { frame = gifFrames[i$]; this.gif.addFrame(frame.image, { delay: frame.delay }); } this.gif.on('progress', function (this$) { return function (p) { return this$.emit('progress', p); }; }(this)); this.gif.on('finished', function (this$) { return function (blob) { this$.emit('finished', blob); try { this$.gif.removeAllListeners('finished'); } catch (e$) { } try { this$.gif.removeAllListeners('progress'); } catch (e$1) { } try { this$.removeAllListeners('finished'); } catch (e$2) { } try { this$.gremoveAllListeners('progress'); } catch (e$3) { } this$.cachedFrames.push(gifFrames); this$.cachedGif.push(blob); this$.gif = null; return this$.locked = false; }; }(this)); this.gif.render(); return true; }; return Gifcreater; }(EventEmitter); Extracter = function (super$3) { extends$(Extracter, super$3); function Extracter(param$) { if (null == param$) param$ = lib.JSZip; this.JSZip = param$; this.locked = false; this.zippedFiles = []; this.unzippedFiles = []; } Extracter.prototype.extract = function (param$) { var index; this.blob = param$; if (this.locked === true) { console.log('incorrect invoke'); return false; } console.log('extract start'); index = this.zippedFiles.indexOf(this.blob); if (index >= 0) { console.log('emit ' + this.emit('done', this.unzippedFiles[index])); this.removeAllListeners('done'); return true; } this.locked = true; this.fileReader = new FileReader; this.fileReader.onload = function (this$) { return function () { var result = this$.fileReader.result, rv; try { rv = new Uint8Array(result); result = rv instanceof Uint8Array ? rv : new unsafeWindow.Uint8Array(result); if (!(result instanceof Uint8Array)) { var global = (new Function('return this;'))(); global.Uint8Array = unsafeWindow.Uint8Array; if (global.console) { (console.warn || console.error || console.log || function () {}).bind(console) ( 'A terrible workaround is used to bypass the firefox sandbox issue!', 'Please view https://github.com/greasemonkey/greasemonkey/issues/2034 for information' ); } } } catch (e) { console.log(e); } return this$._onArrayBufferLoaded(result); }; }(this); return this.fileReader.readAsArrayBuffer(this.blob); }; Extracter.prototype._onArrayBufferLoaded = function (arrBuffer) { var arrayBuffer_file, blob, file, fileName, files, MIME, temp; this.zip = new this.JSZip(arrBuffer); files = this.zip.file(/\d+.(?:jpg|png|gif)/i); temp = []; for (var i$ = 0, length$ = files.length; i$ < length$; ++i$) { file = files[i$]; if (file.dir) break; fileName = file.name; MIME = Util.getMIME(fileName); arrayBuffer_file = file.asArrayBuffer(); blob = new Blob([arrayBuffer_file], { type: MIME }); temp.push({ blob: blob, fileName: fileName, mime: MIME }); } this.zippedFiles.push(this.blob); this.unzippedFiles.push(temp); console.log('emit ' + this.emit('done', temp)); this.blob = null; this.removeAllListeners('done'); this.zip = null; this.fileReader = null; this.locked = false; return true; }; return Extracter; }(EventEmitter); Downloader = function (super$4) { extends$(Downloader, super$4); function Downloader() { this._cachedURL = []; this._cache = {}; this.locked = false; } Downloader.prototype.download = function (url) { if (this.locked) { console.log('incorrect invoke'); return false; } if (in$(url, this._cachedURL)) { this.emit('success', this._cache[url]); this.removeAllListeners('success'); return true; } this.locked = true; console.log('download start'); this.req = new XMLHttpRequest; this.req.open('GET', url, true); this.req.responseType = 'blob'; this.req.onload = function (this$) { return function (e) { var blob; blob = this$.req.response; if (null != blob) { this$._cachedURL.push(url); this$._cache[url] = blob; this$.emit('success', blob); this$.removeAllListeners('success'); } else { this$.emit('fail', url); } this$.locked = false; return true; }; }(this); this.req.send(null); return true; }; return Downloader; }(EventEmitter); main = function (global, $, util, saveAs) { var downloader, downloadPicture, extracter, getTitle, gifCreater, imageCreater, showGif, showPic; Modal.hook($); Menu.hook($); downloader = new Downloader; extracter = new Extracter; imageCreater = new ImageCreater; gifCreater = new Gifcreater; getTitle = function () { return global.pixiv.context.illustTitle; }; downloadPicture = function (size) { var title, url; title = getTitle(); switch (size) { case 'small': url = global.pixiv.context.ugokuIllustData.src; break; case 'full': url = global.pixiv.context.ugokuIllustFullscreenData.src; break; default: throw new Error('unknown size'); } downloader.on('success', function (blob) { console.log(blob); return saveAs(blob, '' + title + '.zip'); }); return console.log(downloader.download(url)); }; showPic = function (size) { var title, url; title = getTitle(); switch (size) { case 'small': url = global.pixiv.context.ugokuIllustData.src; break; case 'full': url = global.pixiv.context.ugokuIllustFullscreenData.src; break; default: throw new Error('unknown size'); } downloader.on('success', function (blob) { Modal.clear(); Modal.show(); extracter.on('done', function (files) { imageCreater.on('done', function (files) { var file; Modal.clear(); for (var i$ = 0, length$ = files.length; i$ < length$; ++i$) { file = files[i$]; Modal.modalContent.append($('

').text(file.fileName)); Modal.modalContent.append(file.image); } return true; }); imageCreater.create(files); return true; }); extracter.extract(blob); return true; }); console.log(downloader.download(url)); return true; }; showGif = function (size, useDownload) { var delays, imageSize, title, url; title = getTitle(); delays = global.pixiv.context.ugokuIllustData.frames.slice(0); switch (size) { case 'small': url = global.pixiv.context.ugokuIllustData.src; imageSize = global.pixiv.context.ugokuIllustData.size.slice(0); break; case 'full': url = global.pixiv.context.ugokuIllustFullscreenData.src; imageSize = global.pixiv.context.illustSize.slice(0); break; default: throw new Error('unknown size'); } downloader.on('success', function (blob) { if (!useDownload) { Modal.clear(); Modal.show(); } extracter.on('done', function (files) { console.log('extract done'); imageCreater.on('done', function (files) { var delay, file; imageSize = [ files[0].image.clientWidth || files[0].image.width, files[0].image.clientHeight || files[0].image.height ]; Modal.clear(); for (var i$ = 0, length$ = files.length; i$ < length$; ++i$) { file = files[i$]; for (var i$1 = 0, length$1 = delays.length; i$1 < length$1; ++i$1) { delay = delays[i$1]; if (file.fileName === delay.file) { file.delay = delay.delay; break; } } } console.log(files); console.log(delays); if (!useDownload) { gifCreater.on('finished', function (blob) { var img; Modal.clear(); url = Util.getUrl(blob); img = document.createElement('img'); img.src = url; Modal.modalContent.append(img); return true; }); gifCreater.on('progress', function (p) { Modal.modalContent.html('progressing
' + Math.floor(p * 100) + '%'); return true; }); } else { gifCreater.on('finished', function (blob) { saveAs(blob, '' + title + '.gif'); return true; }); } gifCreater.render(files, imageSize); return true; }); imageCreater.create(files); return true; }); console.log(extracter); extracter.extract(blob); return true; }); console.log(downloader.download(url)); return true; }; if (global.pixiv.context.ugokuIllustData) { GM_registerMenuCommand('\u4E0B\u8F09\u52D5\u5716', function () { return Menu.show(); }); Button.hook($); Button.on('click', function () { return Menu.show(); }); } return Menu.on('run', function (data) { switch (data.size) { case 'mini': switch (data.type) { case 'gif': switch (data.action) { case 'download': return showGif('small', true); case 'view': return showGif('small'); } case 'frame': switch (data.action) { case 'download': return downloadPicture('small'); case 'view': return showPic('small'); } } case 'full': if (!global.pixiv.context.ugokuIllustFullscreenData) { alert('\u672A\u767B\u5165\u662F\u7121\u6CD5\u4E0B\u8F09\u5168\u5716\u7684\u6B50'); return true; } switch (data.type) { case 'gif': switch (data.action) { case 'download': return showGif('full', true); case 'view': return showGif('full'); } case 'frame': switch (data.action) { case 'download': return downloadPicture('full'); case 'view': return showPic('full'); } } } }); }; console.log(lib); main(unsafeWindow, lib.$, Util, lib.saveAs); function isOwn$(o, p) { return {}.hasOwnProperty.call(o, p); } function extends$(child, parent) { for (var key in parent) if (isOwn$(parent, key)) child[key] = parent[key]; function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; } function in$(member, list) { for (var i = 0, length = list.length; i < length; ++i) if (i in list && list[i] === member) return true; return false; } }); require.define('/util.js', function (module, exports, __dirname, __filename) { 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 getUrl(blob, name) { return URL.createObjectURL(blob); } module.exports = { getMIME: getMIME, getFileExtension: getFileExtension, getUrl: getUrl }; }); require.define('/view/downloadButton.coffee', function (module, exports, __dirname, __filename) { var botton, buttonCss, buttonHTML, EventEmitter; EventEmitter = require('events', module).EventEmitter; buttonHTML = '\r\n'; buttonCss = '\r\n.wrapper .mmis-botton {\r\n position: absolute;\r\n right: 42px;\r\n top: 5px;\r\n background: rgba(153, 153, 153, 0.5);\r\n color: #f9f9f9;\r\n box-sizing: content-box;\r\n border: 0px;\r\n padding: 6px 6px 6px 6px;\r\n margin: 0px;\r\n width: 20px;\r\n height: 20px;\r\n border-radius: 5px;\r\n line-height: 20px;\r\n font-size: 20px;\r\n font-weight: bold;\r\n text-align: center;\r\n -webkit-transition: background-color, opacity 0.2s;\r\n -moz-transition: background-color, opacity 0.2s;\r\n -o-transition: background-color, opacity 0.2s;\r\n -ms-transition: background-color, opacity 0.2s;\r\n transition: background-color, opacity 0.2s;\r\n opacity: 0;\r\n display: block;\r\n}\r\n.wrapper .mmis-botton:hover {\r\n background-color: rgba(153,153,153,0.75);\r\n}\r\n\r\n.wrapper .mmis-botton::after {\r\n content: "\u2193";\r\n display: inline;\r\n}\r\n._ugoku-illust-player-container:hover .mmis-botton {\r\n opacity: 1;\r\n}'; botton = function (super$) { extends$(botton, super$); function botton() { this.$ = null; this.inited = false; } botton.prototype.hook = function (jQuery) { if (this.inited) return false; this.$ = jQuery; this.inited = true; this.$('head').append(this.$('').html(modal_css)); this.modal = $(modalContent); this.modalContent = this.modal.find('.content'); $('body').append(this.modal); }, show: function () { this.$(this.modal).modal(); }, hide: function () { this.$(this.modal).modal({ stat: off }); }, clear: function () { this.modalContent.find('*').remove(); this.modalContent.text(''); } }; module.exports = modal; }); global.pixiv_helper = require('/pixiv_helper.coffee'); }.call(this, this)); //# sourceMappingURL=pixiv_helper.js.map // pixiv_helper.js https://github.com/mmis1000/Pixiv_Helper