Add a control panel for novel reading on truyen.tangthuvien.net, auto download max 200 chapters
当前为
// ==UserScript==
// @name Chapter Downloader
// @namespace http://tampermonkey.net/
// @version 2.2
// @description Add a control panel for novel reading on truyen.tangthuvien.net, auto download max 200 chapters
// @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 isAutoDownloading = false;
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.id = 'content-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 buttonRow1 = document.createElement('div');
buttonRow1.style.cssText = `
display: flex;
justify-content: space-between;
margin-bottom: 10px;
`;
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 buttonRow2 = document.createElement('div');
buttonRow2.style.cssText = `
display: flex;
justify-content: space-between;
`;
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;
`;
buttonRow1.appendChild(getTextButton);
buttonRow1.appendChild(nextChapterButton);
buttonRow2.appendChild(clearButton);
buttonRow2.appendChild(copyButton);
panel.appendChild(textarea);
panel.appendChild(startButton);
panel.appendChild(buttonRow1);
panel.appendChild(buttonRow2);
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();
if (textarea.value) {
textarea.value += '\n\n------------\n\n' + title + '\n\n' + content;
} else {
textarea.value = title + '\n\n' + content;
}
saveContent();
return true;
}
return false;
}
function goToNextChapter() {
const nextChapterLink = document.querySelector('.bot-next_chap.bot-control');
if (nextChapterLink) {
nextChapterLink.click();
return true;
} else {
const alternativeNextLinks = document.querySelectorAll('a[href*="chuong"]');
for (const link of alternativeNextLinks) {
if (link.textContent.includes('tiếp') || link.textContent.includes('sau') || link.textContent.toLowerCase().includes('next')) {
link.click();
return true;
}
}
return false;
}
}
function startAutoDownloading() {
if (!isAutoDownloading) return;
console.log(`Auto-downloading: Extracting chapter ${downloadedCount + 1}`);
if (downloadedCount >= MAX_CHAPTERS) {
console.log(`Auto-downloading: Đã tải ${MAX_CHAPTERS} chương, dừng.`);
isAutoDownloading = false;
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
return;
}
if (extractChapterContent()) {
downloadedCount++;
setTimeout(() => {
if (!isAutoDownloading) return;
if (goToNextChapter()) {
setTimeout(() => {
if (isAutoDownloading) {
startAutoDownloading();
}
}, 2000);
} else {
isAutoDownloading = false;
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
}
}, 1000);
} else {
isAutoDownloading = false;
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
}
}
startButton.addEventListener('click', () => {
isAutoDownloading = !isAutoDownloading;
if (isAutoDownloading) {
downloadedCount = 0;
startButton.textContent = 'Dừng';
startButton.style.backgroundColor = '#f44336';
startAutoDownloading();
} else {
startButton.textContent = 'Bắt đầu';
startButton.style.backgroundColor = '#4CAF50';
}
});
getTextButton.addEventListener('click', () => {
if (!isAutoDownloading) {
downloadedCount = 0;
isAutoDownloading = true;
startButton.textContent = 'Dừng';
startButton.style.backgroundColor = '#f44336';
startAutoDownloading();
}
});
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-color: rgba(0,0,0,0.8);
color: white;
padding: 10px 20px;
border-radius: 4px;
z-index: 10000;
`;
document.body.appendChild(notification);
setTimeout(() => {
document.body.removeChild(notification);
}, 2000);
});
let isDragging = false;
let offsetX, offsetY;
panel.addEventListener('mousedown', (e) => {
if (e.target === panel) {
isDragging = true;
offsetX = e.clientX - panel.getBoundingClientRect().left;
offsetY = e.clientY - panel.getBoundingClientRect().top;
}
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
panel.style.left = (e.clientX - offsetX) + 'px';
panel.style.top = (e.clientY - offsetY) + 'px';
panel.style.right = 'auto';
}
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
const shortcutsInfo = document.createElement('div');
shortcutsInfo.style.cssText = `
font-size: 11px;
color: #666;
margin-top: 10px;
padding-top: 5px;
border-top: 1px solid #ddd;
`;
shortcutsInfo.innerHTML = `
<b>Phím tắt:</b> Alt+G (Lấy text), Alt+N (Chương tiếp), Alt+S (Tự động), Alt+C (Sao chép)
`;
panel.appendChild(shortcutsInfo);
document.body.appendChild(panel);
})();