· 6 years ago · Nov 16, 2019, 06:32 AM
1// ==UserScript==
2// @name ebjhooker
3// @namespace ebjhooker
4// @version 1.3
5// @icon https://ebookjapan.yahoo.co.jp/favicon.ico
6// @description Grabs image data from the browser viewer to save locally. Still a bit buggy. Currently works when you click off one of the pages. Source has further comments. Last updated by m3ch_mania (07/01/2018)
7// @author m3ch_mania, Cure, eligrey, anonymous, kabuto93
8// @updateURL https://gitlab.com/m3ch_mania/ebjhooker/raw/master/ebjhooker.user.js
9// @downloadURL https://gitlab.com/m3ch_mania/ebjhooker/raw/master/ebjhooker.user.js
10// @run-at document-start
11// @include https://ebookjapan.yahoo.co.jp/viewer?*
12// @grant GM_xmlhttpRequest
13// ==/UserScript==
14
15// Borrows code from eligrey (https://github.com/eligrey/) that's been embedded and changed due to updates to the EMCAscript standards
16
17// Here's some usage tips
18// 1. Get the reader to go in single page mode, it'll make your crop job easier later.
19// 1.1. Create a transparency mask in PS, set its treshold to 255, trim transparent pixels, easy cropping done in 5 seconds or less.
20// 2. If you pressed cancel at the prompt or if it didn't show at all, press the 'up' key on your keyboard to turn on autoripping
21// 3. Autoripping won't stop until it gets to the end or if you make it save the same page twice.
22// 4. You can just manually rip using the left arrow key to scroll
23// 5. If you want to start ripping at a certain spot, just use any method to get through the book that isn't the left arrow key and it won't rip anything.
24(function() {
25
26 let f = HTMLCanvasElement.prototype.toBlob;
27 let globPress;
28 let pad;
29
30 pad = function (n, width, z) {
31 z = z || '0';
32 n = n + '';
33 return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
34 }
35
36
37 function triggerKey(){
38 try{
39 var eventObj = document.createEvent("Events");
40 eventObj.initEvent("keydown", true, true);
41 eventObj.which = 37;
42 eventObj.keyCode = 37;
43 eventObj.key = "ArrowLeft";
44 document.dispatchEvent(eventObj);
45 }
46 catch(e){
47 console.log(e);
48 }
49 }
50
51 // wait for page to load
52 function domReady(){
53 let pages = [];
54 let pagenumber = 0; //cover has page number 0
55 let pagedata = "";
56 let interval;
57 let pagecanvas;
58 if(confirm("Dump automatically? (Press the up arrow key to turn it on later, or use the left arrow key to rip manually)")){
59 interval = setInterval(triggerKey,4000);
60 }
61 document.addEventListener('keydown', function(e) {
62 if(e.keyCode == 37){
63 pagecanvas = document.querySelectorAll(".viewer > canvas:nth-of-type(1)");
64 pagenumber = document.querySelector("#__layout > div > div.main > footer > div.footer__page-slider.normal-color > div.footer__page-output > output").innerText
65 if(pages.includes(pagenumber)){
66 console.log("Saving done");
67 clearInterval(interval);
68 }
69 else{
70 var tempCanvas = pagecanvas[0];
71 tempCanvas.toBlob = f;
72 tempCanvas.toBlob(function(blob) {
73 let bookName = document.querySelector("#__layout > div > div.main > header > div.heading > div.header__title").innerText
74 // var bookName = $('.header__title > h2').text().replace(' ????�???�_', ' ')
75 let filename = bookName + pad(parseInt(pagenumber) - 1,4)+'.png';
76 saveAs(blob, filename);
77 //console.log("saved as "+filename);
78 });
79 pages.push(pagenumber);
80 }
81 //super();
82 }else if(e.keyCode == 38){
83 console.log("Manually turning on timer");
84 interval = setInterval(triggerKey,2200);
85 }
86 });
87 }
88
89 // Mozilla, Opera, Webkit
90 if ( document.addEventListener ) {
91 document.addEventListener( "DOMContentLoaded", function(){
92 document.removeEventListener( "DOMContentLoaded", arguments.callee, false);
93 domReady();
94 }, false );
95 }
96
97 var saveAs = saveAs || (function(view) {
98 "use strict";
99 // IE <10 is explicitly unsupported
100 if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
101 return;
102 }
103 var
104 doc = view.document
105 // only get URL when necessary in case Blob.js hasn't overridden it yet
106 , get_URL = function() {
107 return view.URL || view.webkitURL || view;
108 }
109 , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
110 , can_use_save_link = "download" in save_link
111 , click = function(node) {
112 var event = new MouseEvent("click");
113 node.dispatchEvent(event);
114 }
115 , is_safari = /constructor/i.test(view.HTMLElement) || view.safari
116 , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
117 , setImmediate = view.setImmediate || view.setTimeout
118 , throw_outside = function(ex) {
119 setImmediate(function() {
120 throw ex;
121 }, 0);
122 }
123 , force_saveable_type = "application/octet-stream"
124 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
125 , arbitrary_revoke_timeout = 1000 * 40 // in ms
126 , revoke = function(file) {
127 var revoker = function() {
128 if (typeof file === "string") { // file is an object URL
129 get_URL().revokeObjectURL(file);
130 } else { // file is a File
131 file.remove();
132 }
133 };
134 setTimeout(revoker, arbitrary_revoke_timeout);
135 }
136 , dispatch = function(filesaver, event_types, event) {
137 event_types = [].concat(event_types);
138 var i = event_types.length;
139 while (i--) {
140 var listener = filesaver["on" + event_types[i]];
141 if (typeof listener === "function") {
142 try {
143 listener.call(filesaver, event || filesaver);
144 } catch (ex) {
145 throw_outside(ex);
146 }
147 }
148 }
149 }
150 , auto_bom = function(blob) {
151 // prepend BOM for UTF-8 XML and text/* types (including HTML)
152 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
153 if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
154 return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
155 }
156 return blob;
157 }
158 , FileSaver = function(blob, name, no_auto_bom) {
159 if (!no_auto_bom) {
160 blob = auto_bom(blob);
161 }
162 // First try a.download, then web filesystem, then object URLs
163 var
164 filesaver = this
165 , type = blob.type
166 , force = type === force_saveable_type
167 , object_url
168 , dispatch_all = function() {
169 dispatch(filesaver, "writestart progress write writeend".split(" "));
170 }
171 // on any filesys errors revert to saving with object URLs
172 , fs_error = function() {
173 if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
174 // Safari doesn't allow downloading of blob urls
175 var reader = new FileReader();
176 reader.onloadend = function() {
177 var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
178 var popup = view.open(url, '_blank');
179 if(!popup) view.location.href = url;
180 url=undefined; // release reference before dispatching
181 filesaver.readyState = filesaver.DONE;
182 dispatch_all();
183 };
184 reader.readAsDataURL(blob);
185 filesaver.readyState = filesaver.INIT;
186 return;
187 }
188 // don't create more object URLs than needed
189 if (!object_url) {
190 object_url = get_URL().createObjectURL(blob);
191 }
192 if (force) {
193 view.location.href = object_url;
194 } else {
195 var opened = view.open(object_url, "_blank");
196 if (!opened) {
197 // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
198 view.location.href = object_url;
199 }
200 }
201 filesaver.readyState = filesaver.DONE;
202 dispatch_all();
203 revoke(object_url);
204 }
205 ;
206 filesaver.readyState = filesaver.INIT;
207
208 if (can_use_save_link) {
209 object_url = get_URL().createObjectURL(blob);
210 setImmediate(function() {
211 save_link.href = object_url;
212 save_link.download = name;
213 click(save_link);
214 dispatch_all();
215 revoke(object_url);
216 filesaver.readyState = filesaver.DONE;
217 }, 0);
218 return;
219 }
220
221 fs_error();
222 }
223 , FS_proto = FileSaver.prototype
224 , saveAs = function(blob, name, no_auto_bom) {
225 return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
226 }
227 ;
228
229 // IE 10+ (native saveAs)
230 if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
231 return function(blob, name, no_auto_bom) {
232 name = name || blob.name || "download";
233
234 if (!no_auto_bom) {
235 blob = auto_bom(blob);
236 }
237 return navigator.msSaveOrOpenBlob(blob, name);
238 };
239 }
240
241 // todo: detect chrome extensions & packaged apps
242 //save_link.target = "_blank";
243
244 FS_proto.abort = function(){};
245 FS_proto.readyState = FS_proto.INIT = 0;
246 FS_proto.WRITING = 1;
247 FS_proto.DONE = 2;
248
249 FS_proto.error =
250 FS_proto.onwritestart =
251 FS_proto.onprogress =
252 FS_proto.onwrite =
253 FS_proto.onabort =
254 FS_proto.onerror =
255 FS_proto.onwriteend =
256 null;
257
258 return saveAs;
259}(
260 typeof self !== "undefined" && self
261 || typeof window !== "undefined" && window
262 || this
263));
264})();