TangThuVien downloader

Tải truyện từ truyen.tangthuvien.vn định dạng epub

目前為 2019-05-11 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name TangThuVien downloader
  3. // @namespace https://nntoan.com/
  4. // @description Tải truyện từ truyen.tangthuvien.vn định dạng epub
  5. // @version 1.0.1
  6. // @icon https://i.imgur.com/rt1QT6z.png
  7. // @author Toan Nguyen
  8. // @oujs:author nntoan
  9. // @license MIT; https://nntoan.mit-license.org/
  10. // @match http://truyen.tangthuvien.vn/doc-truyen/*
  11. // @match https://truyen.tangthuvien.vn/doc-truyen/*
  12. // @require https://code.jquery.com/jquery-3.3.1.min.js
  13. // @require https://unpkg.com/jepub@1.2.5/dist/jepub.min.js
  14. // @require https://unpkg.com/file-saver@2.0.1/dist/FileSaver.min.js
  15. // @noframes
  16. // @connect self
  17. // @supportURL https://github.com/nntoan/UserScripts/issues
  18. // @run-at document-idle
  19. // @grant none
  20. // ==/UserScript==
  21. (function ($, window, document) {
  22. 'use strict';
  23.  
  24. /**
  25. * Nhận cảnh báo khi có chương bị lỗi
  26. */
  27. var errorAlert = true;
  28.  
  29. /**
  30. * Những đoạn ghi chú cuối chương của converter
  31. * Chỉ cần ghi phần bắt đầu, không phân biệt hoa thường
  32. * Ngăn cách các đoạn bằng dấu |
  33. */
  34. var converter = 'ps:|hoan nghênh quảng đại bạn đọc quang lâm|Huyền ảo khoái trí ân cừu';
  35.  
  36.  
  37. converter = new RegExp('(' + converter + ')', 'i');
  38.  
  39. function cleanHtml(str) {
  40. str = str.replace(/\s*Chương\s*\d+\s?:[^<\n]/, '');
  41. str = str.replace(/[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]+/gm, ''); // eslint-disable-line
  42. str = str.replace(/\s[a-zA-Z0-9]{6,8}(="")?\s/gm, function (key, attr) {
  43. if (attr) return ' ';
  44. if (!isNaN(key)) return key;
  45. if (key.split(/[A-Z]/).length > 2) return ' ';
  46. if (key.split(/\d/).length > 1) return ' ';
  47. return key;
  48. });
  49. str = str.replace(/\([^(]+<button[^/]+<\/button>[^)]*\)\s*/gi, '');
  50. str = str.split(converter)[0];
  51. return '<div>' + str + '</div>';
  52. }
  53.  
  54. function downloadError(mess, err) {
  55. downloadStatus('error');
  56. titleError.push(chapTitle);
  57. if (errorAlert) {
  58. errorAlert = confirm('Lỗi! ' + mess + '\nBạn có muốn tiếp tục nhận cảnh báo?');
  59. }
  60.  
  61. if (err) {
  62. console.error(mess);
  63. }
  64. return '<p class="no-indent"><a href="' + referrer + chapId + '">' + mess + '</a></p>';
  65. }
  66.  
  67. function saveEbook() {
  68. if (endDownload) return;
  69. endDownload = true;
  70. $download.html('Đang nén EPUB');
  71.  
  72. if (titleError.length) {
  73. titleError = '<p class="no-indent"><strong>Các chương lỗi: </strong>' + titleError.join(', ') + '</p>';
  74. } else {
  75. titleError = '';
  76. }
  77. beginEnd = '<p class="no-indent">Nội dung từ <strong>' + begin + '</strong> đến <strong>' + end + '</strong></p>';
  78.  
  79. jepub.notes(beginEnd + titleError + '<br /><br />' + credits);
  80.  
  81. jepub.generate().then(function (epubZipContent) {
  82. document.title = '[⇓] ' + ebookTitle;
  83. $win.off('beforeunload');
  84.  
  85. $download.attr({
  86. href: window.URL.createObjectURL(epubZipContent),
  87. download: ebookFilename
  88. }).text('Hoàn thành').off('click');
  89. if (!$download.hasClass('error')) downloadStatus('success');
  90.  
  91. saveAs(epubZipContent, ebookFilename); // eslint-disable-line
  92. }).catch(function (err) {
  93. downloadStatus('error');
  94. console.error(err);
  95. });
  96. }
  97.  
  98. function getContent() {
  99. if (endDownload) {
  100. return;
  101. }
  102. chapId = chapList[count];
  103.  
  104. $.ajax({
  105. url: pathname + chapId + '/',
  106. xhrFields: {
  107. withCredentials: true
  108. }
  109. }).done(function (response) {
  110. var $data = $(response),
  111. $chapter = $data.find('.box-chap:not(.hidden)'),
  112. $notContent = $chapter.find('iframe, script, style, a, div, p:has(a[href*="truyen.tangthuvien.vn"])'),
  113. $referrer = $chapter.find('[style]').filter(function () {
  114. return (this.style.fontSize === '1px' || this.style.fontSize === '0px' || this.style.color === 'white');
  115. }),
  116. chapContent;
  117.  
  118. if (endDownload) return;
  119.  
  120. chapTitle = $data.find('h2').text().trim();
  121. if (chapTitle === '') chapTitle = 'Chương ' + chapId.match(/\d+/)[0];
  122.  
  123. if (!$chapter.length) {
  124. chapContent = downloadError('Không có nội dung');
  125. } else {
  126. if ($chapter.find('#btnChapterVip').length) {
  127. chapContent = downloadError('Chương VIP');
  128. } else if ($chapter.filter(function () {
  129. return (this.textContent.toLowerCase().indexOf('vui lòng đăng nhập để đọc chương này') !== -1);
  130. }).length) {
  131. chapContent = downloadError('Chương yêu cầu đăng nhập');
  132. } else {
  133. var $img = $chapter.find('img');
  134. if ($img.length) {
  135. $img.replaceWith(function () {
  136. return '<br /><a href="' + this.src + '">Click để xem ảnh</a><br />';
  137. });
  138. }
  139.  
  140. if ($notContent.length) $notContent.remove();
  141. if ($referrer.length) $referrer.remove();
  142.  
  143. if ($chapter.text().trim() === '') {
  144. chapContent = downloadError('Nội dung không có');
  145. } else {
  146. if (!$download.hasClass('error')) downloadStatus('warning');
  147. chapContent = cleanHtml($chapter.html());
  148. }
  149. }
  150. }
  151.  
  152. jepub.add(chapTitle, chapContent);
  153.  
  154. if (count === 0) begin = chapTitle;
  155. end = chapTitle;
  156.  
  157. $download.html('Đang tải: ' + Math.floor((count / chapListSize) * 100) + '%');
  158.  
  159. count++;
  160. document.title = '[' + count + '] ' + pageName;
  161. if (count >= chapListSize) {
  162. saveEbook();
  163. } else {
  164. getContent();
  165. }
  166. }).fail(function (err) {
  167. downloadError('Kết nối không ổn định', err);
  168. saveEbook();
  169. });
  170. }
  171.  
  172.  
  173. var pageName = document.title,
  174. $win = $(window),
  175. $download = $('<a>', {
  176. class: 'btn blue btn-download',
  177. href: '#download',
  178. text: 'Tải xuống'
  179. }),
  180. downloadStatus = function (status) {
  181. $download.removeClass('btn-primary btn-success btn-info btn-warning btn-danger blue success warning info danger error').addClass('btn-' + status).addClass(status);
  182. },
  183.  
  184. $novelId = $('#story_id_hidden'),
  185. $chapterUuid = $('.middle-box li.active'),
  186. chapList = [],
  187. chapListSize = 0,
  188. chapId = '',
  189. chapTitle = '',
  190. count = 0,
  191. begin = '',
  192. end = '',
  193. endDownload = false,
  194.  
  195. ebookTitle = '',
  196. ebookAuthor = '',
  197. ebookCover = '',
  198. ebookDesc = '',
  199. ebookType = [],
  200. beginEnd = '',
  201. titleError = [],
  202.  
  203. host = location.host,
  204. pathname = location.pathname,
  205. referrer = location.protocol + '//' + host + pathname,
  206.  
  207. ebookFilename = pathname.slice(12) + '.epub',
  208.  
  209. credits = '<p>Truyện được tải từ <a href="' + referrer + '">TangThuVien</a></p><p>Userscript được viết bởi: <a href="https://nntoan.com/">Toan Nguyen</a></p>',
  210.  
  211. jepub;
  212.  
  213.  
  214. if (!$novelId.length) return;
  215.  
  216. var $infoBlock = $('.book-detail-wrap');
  217.  
  218. ebookTitle = $infoBlock.find('h1').text().trim();
  219. ebookAuthor = $infoBlock.find('#authorId').find('p').text().trim();
  220. ebookCover = $infoBlock.find('#bookImg').find('img').attr('src');
  221. ebookDesc = $infoBlock.find('.book-intro').text().trim();
  222.  
  223. var $ebookType = $infoBlock.find('.tag-wrap a');
  224. if ($ebookType.length) {
  225. $ebookType.each(function () {
  226. ebookType.push($(this).text().trim());
  227. });
  228. }
  229.  
  230. jepub = new jEpub({ // eslint-disable-line
  231. title: ebookTitle,
  232. author: ebookAuthor,
  233. publisher: host,
  234. description: ebookDesc,
  235. tags: ebookType
  236. }).uuid(referrer);
  237.  
  238. $download.appendTo('.take-wrap');
  239. $download.one('click contextmenu', function (e) {
  240. e.preventDefault();
  241.  
  242. document.title = '[...] Vui lòng chờ trong giây lát';
  243.  
  244. $.ajax({
  245. type: 'GET',
  246. url: '/story/chapters',
  247. data: {
  248. story_id: $novelId.val()
  249. }
  250. }).done(function (response) {
  251. chapList = response.match(/(?:href=")[^")]+(?=")/g);
  252. chapList = chapList.map(function (val) {
  253. val = val.slice(6, -1);
  254. val = val.replace(referrer, '');
  255. return val.trim();
  256. });
  257.  
  258. if (e.type === 'contextmenu') {
  259. $download.off('click');
  260. var startFrom = prompt('Nhập ID chương truyện bắt đầu tải:', chapList[0]);
  261. startFrom = chapList.indexOf(startFrom);
  262. if (startFrom !== -1) chapList = chapList.slice(startFrom);
  263. } else {
  264. $download.off('contextmenu');
  265. }
  266.  
  267. chapListSize = chapList.length;
  268. if (chapListSize > 0) {
  269. $win.on('beforeunload', function () {
  270. return 'Truyện đang được tải xuống...';
  271. });
  272.  
  273. $download.one('click', function (e) {
  274. e.preventDefault();
  275. saveEbook();
  276. });
  277.  
  278. getContent();
  279. }
  280. }).fail(function (err) {
  281. $download.text('Lỗi danh mục');
  282. downloadStatus('error');
  283. console.error(err);
  284. });
  285. });
  286.  
  287. })(jQuery, window, document); // eslint-disable-line

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址