// ==UserScript==
// @name 轻小说文库+
// @namespace Wenku8+
// @version 0.5.1
// @description 章节批量下载,版权限制小说TXT简繁全本下载,书名/作者名双击复制
// @author PY-DNG
// @match http*://www.wenku8.net/*
// @grant GM_download
// @grant GM_xmlhttpRequest
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
// CONSTS
const HTML_DOWNLOAD_CONTENER = '
\n
\n';
const HTML_DOWNLOAD_LINKS = '';
const HTML_DOWNLOAD_BOARD = '[轻小说文库+] 为您提供《{BOOKNAME}》的TXT简繁全本下载!由此产生的一切法律及其他问题均由脚本用户承担—— PY-DNG';
const CSS_DOWNLOAD = '.even {display: grid; grid-template-columns: repeat(3, 1fr); text-align: center;} .dlink {text-align: center;}';
const TEXT_TIP_COPY = '双击复制';
// Get tab url api part
const API = window.location.href.replace(/https?:\/\/www\.wenku8\.net\//, '').replace(/\?.*/, '').replace(/^book\/\d+\.html?/, 'book');
switch (API) {
// Dwonload page
case 'modules/article/packshow.php':
pageDownload();
break;
// Index page
case 'index.php':
pageIndex();
break;
// Book page
case 'book':
pageBook();
break;
// Other pages
default:
console.log(API);
}
// Book page add-on
function pageBook() {
const bookIdText = location.href.match(/\/(\d+)\.htm/)[1];
const bookNameElement = document.querySelector('#content > div:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > span:nth-child(1) > b:nth-child(1)');
const bookName = bookNameElement.innerText;
const authorNameElement = document.querySelector('#content > div:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2)');
const authorName = authorNameElement.innerText.substr(authorNameElement.innerText.indexOf(':') + 1);
const downloadEnabled = document.querySelector('#content > div:nth-child(1) > div > fieldset:nth-child(1) > legend:nth-child(1) > b:nth-child(1)') !== null;
// Provide book & author name doubleclick copy
bookNameElement.title = TEXT_TIP_COPY;
authorNameElement.title = TEXT_TIP_COPY;
bookNameElement.addEventListener('dblclick', function() {copyText(bookName);});
authorNameElement.addEventListener('dblclick', function() {copyText(authorName);});
// Provide txtfull download for book which download is disabled
if (!downloadEnabled) {
// Append download html model
document.querySelector('#content div').innerHTML += HTML_DOWNLOAD_CONTENER.replaceAll('{BOOKNAME}', bookName);
document.querySelector('#content div').lastChild.querySelector('fieldset').innerHTML += HTML_DOWNLOAD_LINKS.replaceAll('{BOOKID}', bookIdText);
// Append CSS
addStyle(CSS_DOWNLOAD);
// Write textboard
let textBoard = document.querySelector('#content > div:nth-child(1) > table:nth-child(4) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2) > span:nth-child(1) > b:nth-child(2)');
textBoard.innerHTML = HTML_DOWNLOAD_BOARD.replaceAll('{BOOKNAME}', bookName);
textBoard.style.color = 'green';
}
}
// Index page add-on
function pageIndex() {
}
// Download page add-on
function pageDownload() {
let i;
/* ******************* GUI ******************* */
// Create left operation GUI
let downloadGUI = document.querySelectorAll('#left div.block')[1].cloneNode(true);
// Rename title
downloadGUI.querySelector('.blocktitle .txt').innerHTML = '下载全部章节';
// Remove content
downloadGUI.removeChild(downloadGUI.querySelector('.blockcontent'));
// Create operation ul list
let optionButtonsForm = document.querySelector('#left div.block div.blockcontent div ul[style]').cloneNode(true);
// Reset lis
const NAMES = ['本地简体(G)', '本地简体(U)', '本地繁体(U)', '地址二简体(G)', '地址二简体(U)', '地址二繁体(U)'];
let lis = optionButtonsForm.querySelectorAll('li');
let li = lis[0].cloneNode(true);
let newli;
li.querySelector('a').href = 'javascript:void(0);';
li.querySelector('a').className = '';
li.querySelector('a').innerHTML = '默认按钮文本';
for (i = 0; i < 6; i++) {
// If li exist, remove it
if (lis[i]) {
optionButtonsForm.removeChild(lis[i]);
};
// Create a new one
newli = li.cloneNode(true);
// Modify name
newli.querySelector('a').innerHTML = NAMES[i];
// Mark i
newli.i = i;
// Append it
optionButtonsForm.appendChild(newli);
// Add event listener
newli.addEventListener('click',
function() { // i refers to its current value in loop by marking on the li element
downloadAll(this.i);
})
}
// Create a container
let blockcontent = document.createElement('div');
blockcontent.classList.add('blockcontent');
blockcontent.style.paddingLeft = '10px';
// Append ul
blockcontent.appendChild(optionButtonsForm);
// Append container
downloadGUI.appendChild(blockcontent);
// Append GUI
document.querySelector('#left').appendChild(downloadGUI);
/* ******************* Code ******************* */
// Get novel name
const novelName = document.querySelector('html body div.main div#centerm div#content table.grid caption a').innerText;
let downloadAll = function(type) {
// GUI display
downloadGUI.querySelector('.blocktitle .txt').innerHTML = '下载中...';
// Name customize
let NAME = novelName + ' {j}.';
let allNames = getAllNames();
if (window.location.href.indexOf('txt') != -1) {
NAME += 'txt';
} else {
NAME += document.querySelector('html body div.main div#centerm div#content table.grid tbody tr td.even a').innerText.replace(/[^\w]+/, '').toLowerCase();
}
let i,j = 0;
const allA = document.querySelectorAll('.even a');
for (i = type; i < allA.length; i = i + 6) {
GM_download({
url: allA[i].href,
name: NAME.replace('{j}', (window.location.href.indexOf('txtfull') === -1 ? allNames[j] : ''))
});
j += 1;
}
downloadGUI.querySelector('.blocktitle .txt').innerHTML = '下载全部章节';
}
function getAllNames() {
let all = document.querySelectorAll('.grid tbody tr .odd');
let names = [];
for (let i = 0; i < all.length; i++) {
names[i] = all[i].innerText;
}
return names;
}
// File download function
function download(details) {
// Check
if (!details.url || !details.name) {
return false;
}
// xmlHTTPRequest
GM_xmlhttpRequest({
method: 'GET',
url: details.url,
responseType: 'blob',
onload: function(request) {}
})
// Create
const a = document.createElement('a');
//a.style.display = 'none';
a.href = details.url;
a.download = details.name;
document.body.appendChild(a);
a.click();
console.log(a);
//document.body.removeChild(a);
}
}
function addStyle(css) {
document.head.appendChild(document.createElement("style")).textContent = css;
}
function copyText(text) {
// Create a new textarea for copying
const newInput = document.createElement('input');
document.body.appendChild(newInput);
newInput.value = text;
newInput.select();
document.execCommand('copy');
document.body.removeChild(newInput);
}
})();