HentaiLx Downloader

Download manga on hentaiLx.com

  1. // ==UserScript==
  2. // @name HentaiLx Downloader
  3. // @namespace https://holy-donkey.github.io/
  4. // @description Download manga on hentaiLx.com
  5. // @version 1.1.1
  6. // @icon http://i.imgur.com/ICearPQ.png
  7. // @author The Holy Donkey
  8. // @license MIT
  9. // @include http://hentailx.com/*
  10. // @include http://hentailx.com/doc-truyen/*
  11. // @exclude http://hentailx.com/
  12. // @exclude http://hentailx.com/index.aspx
  13. // @exclude http://hentailx.com/danhsach/*
  14. // @exclude http://hentailx.com/Theloai/*
  15. // @exclude http://hentailx.com/trangthai/*
  16. // @exclude http://hentailx.com/Users/*
  17. // @exclude http://hentailx.com/dang-ky-thanh-vien.html
  18. // @exclude http://hentailx.com/nhom-dich/*
  19. // @exclude http://hentailx.com/Tacgia/*
  20. // @require https://cdn.jsdelivr.net/jquery/2.2.4/jquery.min.js
  21. // @require https://cdn.jsdelivr.net/jszip/3.1.3/jszip.min.js
  22. // @require https://cdn.jsdelivr.net/filesaver.js/1.3.3/FileSaver.min.js
  23. // @noframes
  24. // @connect self
  25. // @connect blogspot.com
  26. // @supportURL https://github.com/holy-donkey/UserScripts/issues
  27. // @run-at document-idle
  28. // @grant GM_xmlhttpRequest
  29. // ==/UserScript==
  30.  
  31. jQuery(function ($) {
  32. 'use strict';
  33.  
  34. function deferredAddZip(url, filename, current, total, zip, $download) {
  35. var deferred = $.Deferred();
  36.  
  37. GM_xmlhttpRequest({
  38. method: 'GET',
  39. url: url,
  40. responseType: 'arraybuffer',
  41. onload: function (response) {
  42. zip.file(filename, response.response);
  43. $download.text(counter[current] + '/' + total);
  44. ++counter[current];
  45. deferred.resolve(response);
  46. },
  47. onerror: function (err) {
  48. console.error(err);
  49. deferred.reject(err);
  50. }
  51. });
  52.  
  53. return deferred;
  54. }
  55.  
  56. function getChaper(obj) {
  57. var $this = $(obj.download),
  58. zip = new JSZip(),
  59. deferreds = [],
  60. images = [];
  61.  
  62. $this.text('Waiting...');
  63.  
  64. obj.contentChap.children('img').each(function (i, v) {
  65. images[i] = v.src;
  66. });
  67.  
  68. $.each(images, function (i, v) {
  69. var filename = v.replace(/.*\//g, '');
  70.  
  71. deferreds.push(deferredAddZip(images[i], filename, obj.current, images.length, zip, $this));
  72. });
  73.  
  74. $.when.apply($, deferreds).done(function () {
  75. zip.generateAsync({
  76. type: 'blob'
  77. }).then(function (blob) {
  78. var zipName = obj.nameChap.replace(/\s/g, '_') + '.zip';
  79.  
  80. $this.text('Complete').css('color', 'green').attr({
  81. href: window.URL.createObjectURL(blob),
  82. download: zipName
  83. }).off('click');
  84.  
  85. saveAs(blob, zipName);
  86.  
  87. doc.title = '[⇓ ' + (++complete) + '/' + progress + '] ' + tit;
  88. }, function (reason) {
  89. console.error(reason);
  90. });
  91. }).fail(function (err) {
  92. $this.text('Fail').css('color', 'red');
  93. console.error(err);
  94. }).always(function () {
  95. if (--alertUnload <= 0) {
  96. $(window).off('beforeunload');
  97. }
  98. });
  99. }
  100.  
  101. var $download = $('<a>', {
  102. 'class': 'chapter-download',
  103. href: '#download',
  104. text: 'Download'
  105. }),
  106. counter = [],
  107. current = 0,
  108. alertUnload = 0,
  109. complete = 0,
  110. progress = 0,
  111. doc = document,
  112. tit = doc.title;
  113.  
  114. window.URL = window.URL || window.webkitURL;
  115.  
  116. if (!location.pathname.indexOf('/doc-truyen/')) {
  117.  
  118. $('.chapter-info').find('ul').append('<span class="glyphicon glyphicon-save"></span> ').append($download);
  119.  
  120. $download.one('click', function (e) {
  121. e.preventDefault();
  122.  
  123. ++progress;
  124.  
  125. $download.attr('href', '#download');
  126.  
  127. $(window).on('beforeunload', function () {
  128. return 'Progress is running...';
  129. });
  130. ++alertUnload;
  131.  
  132. counter[current] = 1;
  133. getChaper({
  134. download: this,
  135. contentChap: $('#content_chap'),
  136. nameChap: $('.link_truyen').eq(0).text() + ' ' + $('.link_truyen').eq(1).text(),
  137. current: current
  138. });
  139. });
  140.  
  141. } else {
  142.  
  143. $('.chapter-name-label').attr('class', 'chapter-name-label col-xs-6 col-sm-6 col-md-6');
  144. $('.chap-link').attr('class', 'chap-link col-xs-6 col-sm-6 col-md-6');
  145. $('.list-group-item').eq(2).append('<div class="col-xs-3 col-sm-3 col-md-3 text-right chapter-view-download">Download</div>');
  146. $('.item_chap:not(:last)').append($('<span>', {
  147. 'class': 'col-xs-3 col-sm-3 col-md-3 text-right chapter-view-download'
  148. }).append($download));
  149.  
  150. $('.chapter-download').each(function () {
  151.  
  152. $(this).one('click', function (e) {
  153. e.preventDefault();
  154.  
  155. ++progress;
  156.  
  157. var _this = this,
  158. $chapLink = $(_this).closest('.item_chap').find('.chap-link');
  159.  
  160. $(_this).attr('href', '#download');
  161.  
  162. if (alertUnload <= 0) {
  163. $(window).on('beforeunload', function () {
  164. return 'Progress is running...';
  165. });
  166. }
  167. ++alertUnload;
  168.  
  169. GM_xmlhttpRequest({
  170. method: 'GET',
  171. url: $chapLink.attr('href'),
  172. responseType: 'text',
  173. onload: function (response) {
  174. var $data = $(response.responseText);
  175.  
  176. counter[current] = 1;
  177. getChaper({
  178. download: _this,
  179. contentChap: $data.filter('#content_chap'),
  180. nameChap: $('.breadcrumb').find('.active').text() + ' ' + $chapLink.text(),
  181. current: current
  182. });
  183. ++current;
  184. },
  185. onerror: function (err) {
  186. console.error(err);
  187. }
  188. });
  189. });
  190. });
  191. }
  192. });