Scribd Book Downloader

Scribd Book and Document Downloader

  1. // ==UserScript==
  2. // @name Scribd Book Downloader
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.1
  5. // @description Scribd Book and Document Downloader
  6. // @author https://github.com/jtrancozo/scribd-downloader
  7. // @match https://*.scribd.com/*
  8. // @icon https://www.google.com/s2/favicons?domain=scribd.com
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. let bookName = document.title;
  15.  
  16. let url = document.location.href;
  17.  
  18. const styles = "#app-wrapper { position: fixed; bottom: 10px; left: 10px; z-index: 9999; }"+
  19. "#app-wrapper .btn-app {display: inline-block; padding: 10px 20px; margin-right: 15px; background: #fd4343; color: #fff; font-size: 14px; font-weight: bold; border-radius: 5px; display:none; }";
  20.  
  21. const styleSheet = document.createElement("style");
  22. styleSheet.type = "text/css";
  23. styleSheet.innerText = styles;
  24. document.head.appendChild(styleSheet);
  25.  
  26. // btn wrapper
  27. const wrapper = document.createElement('DIV');
  28. wrapper.id = 'app-wrapper';
  29. document.body.appendChild(wrapper);
  30.  
  31. // Btn Download
  32. const btn = document.createElement('A');
  33. btn.innerText = 'Download Content';
  34. btn.id = 'btn-download';
  35. btn.className = 'btn btn-app';
  36. btn.href = "javascript:;"
  37. wrapper.appendChild(btn);
  38.  
  39. const btn_print = document.createElement('SPAN');
  40. btn_print.innerText = 'Print';
  41. btn_print.id = 'btn-print';
  42. btn_print.className = 'btn-app';
  43. wrapper.appendChild(btn_print);
  44.  
  45. // Book
  46. const book = document.createElement('DIV');
  47. book.id = 'book';
  48. document.body.appendChild(book);
  49.  
  50.  
  51. // Next Page Arrow
  52. const next = document.querySelector('.page_right.next_btn');
  53.  
  54. function createBook () {
  55. const book_w = document.querySelector('#column_container .reader_column.left_column > div').style.width;
  56. const book_h = document.querySelector('#column_container .reader_column.left_column > div').style.height;
  57.  
  58. // const book_w = 585;
  59. // const book_h = 765;
  60.  
  61. let css = "<head><style>"+
  62. `#book .reader_column.left_column, #book .reader_column.right_column {position: relative; width: ${book_w}; height: auto; overflow: hidden } `+
  63. "#book * {position: static !important; display: inline-block !important; transform: none !important; padding-left: 0 !important; padding-right: 0 !important } "+
  64. "#book .reader_column > div {height: auto !important} " +
  65. "#book .text_line > span { margin-right: 4px; }"+
  66. "style {color: #fff; display: none; opacity: 0;}"+
  67. "@media print { style {color: #fff; display: none; opacity: 0;} #book .text_line > span { margin-right: 4px; } }" +
  68. "</style></head>";
  69.  
  70. book.style.cssText = `width: ${book_w}px; height: auto;`;
  71. book.innerHTML = css;
  72. }
  73.  
  74.  
  75. const initBookScrapper = function () {
  76. createBook();
  77.  
  78. let pages = getPageCounter();
  79. // let pageBefore = 1;
  80.  
  81. function loop () {
  82. // pageBefore = pages.atual;
  83.  
  84. setTimeout(() => {
  85. clonePageContent();
  86. next.click();
  87.  
  88. pages = getPageCounter();
  89.  
  90. if (pages.atual < pages.total) {
  91. // if (pages.atual < 20) {
  92. loop();
  93. } else {
  94. // fixColumnsHeight();
  95. }
  96.  
  97. // console.log(pages.atual);
  98.  
  99. }, 2000);
  100. }
  101.  
  102. loop();
  103.  
  104.  
  105. }
  106.  
  107. const clonePageContent = function () {
  108. convertImages();
  109.  
  110. let pageLeft = document.querySelector('#column_container .reader_column.left_column');
  111. let pageRight = document.querySelector('#column_container .reader_column.right_column');
  112.  
  113. book.append(pageLeft.cloneNode(true));
  114. book.append(pageRight.cloneNode(true));
  115. }
  116.  
  117. const convertImages = function () {
  118. let imgs = document.querySelectorAll('#column_container img');
  119.  
  120. for (let img of imgs) {
  121. if (img.naturalWidth == 1 && img.naturalHeight == 1) {
  122. img.style.display = 'none !important';
  123. img.remove();
  124. }
  125.  
  126. const newImg = getBase64Image(img);
  127.  
  128. img.src = newImg;
  129. }
  130. }
  131.  
  132. const nextPage = function () {
  133.  
  134. }
  135.  
  136. const getPageCounter = () => {
  137. let text = document.querySelector('.page_counter').innerText;
  138.  
  139. text = text.split(' ');
  140.  
  141. return {
  142. atual: parseInt(text[1]),
  143. total: parseInt(text[3])
  144. }
  145. }
  146.  
  147. const getBase64Image = function (img) {
  148. var canvas = document.createElement("canvas");
  149. canvas.width = img.naturalWidth;
  150. canvas.height = img.naturalHeight;
  151. var ctx = canvas.getContext("2d");
  152. ctx.drawImage(img, 0, 0);
  153. var dataURL = canvas.toDataURL("image/jpeg", 1);
  154. // return '<img src="'+dataURL+'">';
  155. return dataURL;
  156. }
  157.  
  158. const fixColumnsHeight = function () {
  159. let columns = document.querySelectorAll('#book .reader_column');
  160.  
  161. for (let column of columns) {
  162. let contents = column.querySelector('div').querySelectorAll('div > *');
  163. let height = 0;
  164.  
  165. for (let content of contents) {
  166. height+= content.clientHeight;
  167. }
  168.  
  169. column.style.height = height+'px';
  170. }
  171. }
  172.  
  173. const getPDFUrl = function (mobile) {
  174. // return location.href.replace(/^.*?(\d+).*$/, "https://www.scribd.com/document_downloads/$1?extension=pdf&source=mobile_download");
  175. let mobileTag = mobile ? "&source=mobile_download" : "/";
  176. return location.href.replace(/^.*?(\d+).*$/, "https://www.scribd.com/document_downloads/$1?extension=pdf" + mobileTag);
  177. }
  178.  
  179. const print = () => {
  180. var divContents = document.querySelector('#book').outerHTML;
  181. let fonts = document.querySelector('#fontfaces').outerHTML;
  182.  
  183. var printWindow = window.open('/', 'Livro', 'height=585,width=1015');
  184. printWindow.document.write('<html><head><title>'+ bookName +'</title>');
  185. printWindow.document.write(fonts);
  186.  
  187. printWindow.document.write('<link href="https://s-f.scribdassets.com/webpack/monolith/books.53ebd7db38ffe4c98aa2.css"/>');
  188.  
  189. printWindow.document.write('</head><body><div class="auto__books_epub_book_view">');
  190. printWindow.document.write(divContents);
  191. printWindow.document.write('</div></body></html>');
  192. // printWindow.document.close();
  193. // printWindow.print();
  194. }
  195.  
  196.  
  197. const downloadDocument = function () {
  198. if (/document/.test(url)) {
  199. let link = getPDFUrl();
  200. btn.innerText = "Download as PDF";
  201. btn.style.display = "inline-block";
  202. btn.href = link;
  203. btn.download = "Book.pdf";
  204. // btn.target = "_blank";
  205.  
  206. // Btn Download
  207. const btnMobile = document.createElement('A');
  208. btnMobile.innerText = 'Download as PDF Mobile';
  209. btnMobile.id = 'btn-download-mobile';
  210. btnMobile.className = 'btn btn-app';
  211. btnMobile.style.display = "inline-block";
  212. btnMobile.href = getPDFUrl('mobile');
  213. wrapper.appendChild(btnMobile);
  214.  
  215. console.log(btnMobile);
  216. }
  217. }
  218.  
  219. const downloadEbook = function () {
  220. if (/read/.test(url)) {
  221. btn.innerText = "Get Content";
  222. btn.style.display = "inline-block";
  223. btn.addEventListener('click', () => initBookScrapper());
  224.  
  225. btn_print.style.display = "inline-block";
  226. btn_print.addEventListener('click', () => print());
  227. }
  228. }
  229.  
  230.  
  231. switch (true) {
  232. case /document/.test(url):
  233. downloadDocument();
  234. break;
  235. case /read/.test(url):
  236. downloadEbook();
  237. break;
  238. case /listen/.test(url):
  239. downloadAudio();
  240. break;
  241. default:
  242. console.log();
  243. }
  244.  
  245. })();