您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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);
- });
- })();