Download up to 200 chapters on truyen.tangthuvien.vn
目前為
// ==UserScript==
// @name Chapter Downloader
// @namespace http://tampermonkey.net/
// @version 2.2
// @description Download up to 200 chapters on truyen.tangthuvien.vn
// @author You
// @match https://truyen.tangthuvien.vn/doc-truyen/*
// @match https://truyen.tangthuvien.vn/doc-truyen/*/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const MAX_CHAPTERS = 200;
let downloadedCount = 0;
const panel = document.createElement('div');
panel.id = 'reader-panel';
panel.style.cssText = `
position: fixed;
top: 10%;
right: 10px;
width: 300px;
background-color: #f8f8f8;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
z-index: 9999;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
font-family: Arial, sans-serif;
`;
const textarea = document.createElement('textarea');
textarea.style.cssText = `width: 100%; height: 300px; margin-bottom: 10px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; resize: vertical;`;
const startButton = document.createElement('button');
startButton.textContent = 'Bắt đầu';
startButton.style.cssText = `width: 100%; padding: 8px; margin-bottom: 10px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;`;
const getTextButton = document.createElement('button');
getTextButton.textContent = 'Lấy Text';
getTextButton.style.cssText = `flex: 1; padding: 8px; margin-right: 5px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;`;
const nextChapterButton = document.createElement('button');
nextChapterButton.textContent = 'Chương Tiếp';
nextChapterButton.style.cssText = `flex: 1; padding: 8px; margin-left: 5px; background-color: #ff9800; color: white; border: none; border-radius: 4px; cursor: pointer;`;
const clearButton = document.createElement('button');
clearButton.textContent = 'Xoá';
clearButton.style.cssText = `flex: 1; padding: 8px; margin-right: 5px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;`;
const copyButton = document.createElement('button');
copyButton.textContent = 'Sao Chép';
copyButton.style.cssText = `flex: 1; padding: 8px; margin-left: 5px; background-color: #9c27b0; color: white; border: none; border-radius: 4px; cursor: pointer;`;
const buttonRow1 = document.createElement('div');
buttonRow1.style.cssText = `display: flex; justify-content: space-between; margin-bottom: 10px;`;
buttonRow1.appendChild(getTextButton);
buttonRow1.appendChild(nextChapterButton);
const buttonRow2 = document.createElement('div');
buttonRow2.style.cssText = `display: flex; justify-content: space-between;`;
buttonRow2.appendChild(clearButton);
buttonRow2.appendChild(copyButton);
panel.appendChild(textarea);
panel.appendChild(startButton);
panel.appendChild(buttonRow1);
panel.appendChild(buttonRow2);
document.body.appendChild(panel);
const savedContent = localStorage.getItem('chapterDownloaderContent');
if (savedContent) textarea.value = savedContent;
function saveContent() {
localStorage.setItem('chapterDownloaderContent', textarea.value);
}
textarea.addEventListener('input', saveContent);
function extractChapterContent() {
const titleElement = document.querySelector('h2');
const contentElement = document.querySelector('.box-chap');
if (titleElement && contentElement) {
const title = titleElement.innerText.trim();
const content = contentElement.innerText.trim();
textarea.value += `\n\n------------\n\n${title}\n\n${content}`;
saveContent();
return true;
}
return false;
}
function goToNextChapter() {
const next = document.querySelector('.bot-next_chap.bot-control') ||
[...document.querySelectorAll('a')].find(a => /tiếp|sau|next/i.test(a.textContent));
if (next) {
next.click();
return true;
}
return false;
}
function waitForNextChapterLoaded(oldTitle) {
return new Promise((resolve, reject) => {
const interval = setInterval(() => {
const newTitle = document.querySelector('h2')?.innerText.trim();
if (newTitle && newTitle !== oldTitle) {
clearInterval(interval);
resolve();
}
}, 500);
setTimeout(() => {
clearInterval(interval);
reject('Timeout');
}, 10000);
});
}
let isAutoDownloading = false;
async function startAutoDownloading() {
if (!isAutoDownloading) return;
const titleEl = document.querySelector('h2');
const oldTitle = titleEl?.innerText.trim();
if (downloadedCount >= MAX_CHAPTERS) {
isAutoDownloading = false;
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
return;
}
if (extractChapterContent()) {
downloadedCount++;
if (goToNextChapter()) {
try {
await waitForNextChapterLoaded(oldTitle);
setTimeout(startAutoDownloading, 1000);
} catch (err) {
isAutoDownloading = false;
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
}
} else {
isAutoDownloading = false;
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
}
}
}
startButton.addEventListener('click', () => {
isAutoDownloading = !isAutoDownloading;
startButton.textContent = isAutoDownloading ? 'Dừng' : 'Bắt đầu';
startButton.style.backgroundColor = isAutoDownloading ? '#f44336' : '#4CAF50';
if (isAutoDownloading) startAutoDownloading();
});
getTextButton.addEventListener('click', extractChapterContent);
nextChapterButton.addEventListener('click', goToNextChapter);
clearButton.addEventListener('click', () => { textarea.value = ''; saveContent(); });
copyButton.addEventListener('click', () => {
textarea.select();
document.execCommand('copy');
const notification = document.createElement('div');
notification.textContent = 'Đã sao chép!';
notification.style.cssText = `position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: #000a; color: white; padding: 10px 20px; border-radius: 4px; z-index: 10000;`;
document.body.appendChild(notification);
setTimeout(() => document.body.removeChild(notification), 2000);
});
})();