Chapter Downloader

Extract content from truyen.tangthuvien.net

目前為 2025-03-09 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Chapter Downloader
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  Extract content from truyen.tangthuvien.net
// @author       You
// @match        https://truyen.tangthuvien.net/doc-truyen/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Create container for extracted content
    function createContainer() {
        // Check if container already exists
        if (document.getElementById('content-extractor')) {
            return;
        }

        const container = document.createElement('div');
        container.id = 'content-extractor';
        container.style.position = 'fixed';
        container.style.top = '0';
        container.style.right = '0';
        container.style.bottom = '0';
        container.style.width = '300px';
        container.style.backgroundColor = '#f5f5f5';
        container.style.padding = '15px';
        container.style.zIndex = '9999';
        container.style.boxShadow = '-2px 0 10px rgba(0,0,0,0.1)';
        container.style.overflow = 'auto';

        const title = document.createElement('h3');
        title.textContent = 'Nội dung truyện đã trích xuất';
        title.style.marginTop = '0';
        container.appendChild(title);

        const textarea = document.createElement('textarea');
        textarea.id = 'extracted-content';
        textarea.style.width = '100%';
        textarea.style.height = '150px';
        textarea.style.marginBottom = '10px';
        textarea.style.padding = '10px';
        textarea.style.boxSizing = 'border-box';
        
        // Load saved content if available
        const savedContent = localStorage.getItem('extractedNovelContent');
        if (savedContent) {
            textarea.value = savedContent;
        }
        
        // Auto-save content when it changes
        textarea.addEventListener('input', () => {
            localStorage.setItem('extractedNovelContent', textarea.value);
        });
        
        container.appendChild(textarea);

        const buttonContainer = document.createElement('div');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.flexDirection = 'column';
        buttonContainer.style.gap = '10px';

        // Tạo nút "Bắt đầu lấy text"
        const startButton = document.createElement('button');
        startButton.textContent = 'Bắt đầu lấy text';
        startButton.style.padding = '10px 15px';
        startButton.style.backgroundColor = '#9c27b0';
        startButton.style.color = 'white';
        startButton.style.border = 'none';
        startButton.style.borderRadius = '4px';
        startButton.style.cursor = 'pointer';
        startButton.style.fontWeight = 'bold';
        
        // Thêm biến để kiểm soát quá trình tự động
        let isAutomaticExtraction = false;
        
        // Hàm đệ quy để tự động trích xuất và chuyển chương
        function autoExtractAndNavigate() {
            if (!isAutomaticExtraction) return;
            
            // Trích xuất nội dung chương hiện tại
            extractContent();
            
            // Tìm nút chuyển đến chương tiếp theo
            const nextButton = document.querySelector('.bot-next_chap.bot-control');
            
            if (nextButton) {
                // Hiển thị thông báo
                const notification = document.createElement('div');
                notification.textContent = 'Đã lấy xong chương hiện tại, đang chuyển đến chương kế tiếp...';
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#2196f3';
                notification.style.color = 'white';
                notification.style.padding = '10px';
                notification.style.borderRadius = '5px';
                notification.style.zIndex = '10000';
                document.body.appendChild(notification);
                
                // Xóa thông báo sau 2 giây
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 2000);
                
                // Lấy liên kết của chương tiếp theo
                const nextChapterUrl = nextButton.href;
                
                // Chuyển đến chương tiếp theo
                window.location.href = nextChapterUrl;
                
                // Khi trang mới tải xong, khởi động lại quá trình
                // Sử dụng localStorage để truyền trạng thái giữa các trang
                localStorage.setItem('continueAutoExtract', 'true');
            } else {
                // Kết thúc quá trình khi không còn chương tiếp theo
                isAutomaticExtraction = false;
                startButton.textContent = 'Bắt đầu lấy text';
                startButton.style.display = 'block';
                
                // Hiển thị thông báo hoàn thành
                const notification = document.createElement('div');
                notification.textContent = 'Đã hoàn thành trích xuất toàn bộ truyện!';
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#4caf50';
                notification.style.color = 'white';
                notification.style.padding = '10px';
                notification.style.borderRadius = '5px';
                notification.style.zIndex = '10000';
                document.body.appendChild(notification);
                
                // Xóa thông báo sau 5 giây
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 5000);
            }
        }
        
        // Thêm sự kiện khi click vào nút bắt đầu
        startButton.addEventListener('click', function() {
            if (!isAutomaticExtraction) {
                // Bắt đầu quá trình tự động
                isAutomaticExtraction = true;
                startButton.textContent = 'Dừng trích xuất';
                
                // Hiển thị thông báo đã bắt đầu
                const notification = document.createElement('div');
                notification.textContent = 'Đã bắt đầu tự động trích xuất nội dung';
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#9c27b0';
                notification.style.color = 'white';
                notification.style.padding = '10px';
                notification.style.borderRadius = '5px';
                notification.style.zIndex = '10000';
                document.body.appendChild(notification);
                
                // Xóa thông báo sau 3 giây
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 3000);
                
                // Bắt đầu quá trình tự động
                autoExtractAndNavigate();
            } else {
                // Dừng quá trình tự động
                isAutomaticExtraction = false;
                startButton.textContent = 'Bắt đầu lấy text';
                
                // Hiển thị thông báo đã dừng
                const notification = document.createElement('div');
                notification.textContent = 'Đã dừng quá trình tự động trích xuất';
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#f44336';
                notification.style.color = 'white';
                notification.style.padding = '10px';
                notification.style.borderRadius = '5px';
                notification.style.zIndex = '10000';
                document.body.appendChild(notification);
                
                // Xóa thông báo sau 3 giây
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 3000);
            }
        });
        buttonContainer.appendChild(startButton);

        // Tạo các nút nhưng ẩn đi
        const extractButton = document.createElement('button');
        extractButton.textContent = 'Trích xuất nội dung trang hiện tại';
        extractButton.style.padding = '8px 15px';
        extractButton.style.backgroundColor = '#4caf50';
        extractButton.style.color = 'white';
        extractButton.style.border = 'none';
        extractButton.style.borderRadius = '4px';
        extractButton.style.cursor = 'pointer';
        extractButton.style.display = 'none'; // Ẩn nút
        extractButton.addEventListener('click', extractContent);
        buttonContainer.appendChild(extractButton);

        const nextChapterButton = document.createElement('button');
        nextChapterButton.textContent = 'Chuyển đến chương tiếp theo';
        nextChapterButton.style.padding = '8px 15px';
        nextChapterButton.style.backgroundColor = '#2196f3';
        nextChapterButton.style.color = 'white';
        nextChapterButton.style.border = 'none';
        nextChapterButton.style.borderRadius = '4px';
        nextChapterButton.style.cursor = 'pointer';
        nextChapterButton.style.display = 'none'; // Ẩn nút
        nextChapterButton.addEventListener('click', goToNextChapter);
        buttonContainer.appendChild(nextChapterButton);

        const clearButton = document.createElement('button');
        clearButton.textContent = 'Xóa nội dung';
        clearButton.style.padding = '8px 15px';
        clearButton.style.backgroundColor = '#f44336';
        clearButton.style.color = 'white';
        clearButton.style.border = 'none';
        clearButton.style.borderRadius = '4px';
        clearButton.style.cursor = 'pointer';
        clearButton.addEventListener('click', clearContent);
        buttonContainer.appendChild(clearButton);

        const copyButton = document.createElement('button');
        copyButton.textContent = 'Sao chép nội dung';
        copyButton.style.padding = '8px 15px';
        copyButton.style.backgroundColor = '#ff9800';
        copyButton.style.color = 'white';
        copyButton.style.border = 'none';
        copyButton.style.borderRadius = '4px';
        copyButton.style.cursor = 'pointer';
        copyButton.addEventListener('click', copyContent);
        buttonContainer.appendChild(copyButton);

        container.appendChild(buttonContainer);
        document.body.appendChild(container);
    }

    // Extract content from current page
    function extractContent() {
        const textarea = document.getElementById('extracted-content');
        
        // Get chapter title
        const chapterTitle = document.querySelector('h2');
        let titleText = chapterTitle ? chapterTitle.textContent.trim() : 'Không tìm thấy tiêu đề';
        
        // Get chapter content
        const chapterContentBox = document.querySelector('.box-chap');
        let contentText = '';
        
        if (chapterContentBox) {
            // Remove unwanted elements like scripts, styles, ads
            const contentClone = chapterContentBox.cloneNode(true);
            const scripts = contentClone.querySelectorAll('script, style, .ads, .banner, .comment');
            scripts.forEach(script => script.remove());
            
            // Get the clean text
            contentText = contentClone.innerText.trim();
        } else {
            contentText = 'Không tìm thấy nội dung chương';
        }
        
        // Append to existing content
        textarea.value += `\n\n${titleText}\n\n${contentText}`;
        
        // Save content to localStorage
        localStorage.setItem('extractedNovelContent', textarea.value);
        
        // Scroll to bottom of textarea
        textarea.scrollTop = textarea.scrollHeight;
    }

    // Go to next chapter
    function goToNextChapter() {
        const nextButton = document.querySelector('.bot-next_chap.bot-control');
        if (nextButton) {
            // Extract current content before moving to next chapter
            extractContent();
            
            // Navigate to next chapter
            nextButton.click();
            
            // Add a delay to let the next page load before extracting content
            setTimeout(() => {
                // Don't clear the textarea, just append the new content
                extractContent();
                
                // Show notification
                const notification = document.createElement('div');
                notification.textContent = 'Đã thêm nội dung chương mới';
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#4caf50';
                notification.style.color = 'white';
                notification.style.padding = '10px';
                notification.style.borderRadius = '5px';
                notification.style.zIndex = '10000';
                document.body.appendChild(notification);
                
                // Remove notification after 3 seconds
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 3000);
            }, 2000);
        } else {
            alert('Không tìm thấy nút chuyển đến chương tiếp theo');
        }
    }

    // Clear content in textarea
    function clearContent() {
        const textarea = document.getElementById('extracted-content');
        textarea.value = '';
        // Also clear the saved content
        localStorage.removeItem('extractedNovelContent');
    }

    // Copy content to clipboard
    function copyContent() {
        const textarea = document.getElementById('extracted-content');
        textarea.select();
        document.execCommand('copy');
        
        // Visual feedback
        const originalColor = textarea.style.backgroundColor;
        textarea.style.backgroundColor = '#e6ffe6';
        setTimeout(() => {
            textarea.style.backgroundColor = originalColor;
        }, 500);
    }

    // Initialize when page is loaded
    function init() {
        createContainer();
        
        // Kiểm tra xem có đang trong quá trình tự động trích xuất hay không
        const continueAutoExtract = localStorage.getItem('continueAutoExtract');
        if (continueAutoExtract === 'true') {
            // Xóa trạng thái để tránh lặp vô hạn nếu người dùng refresh trang
            localStorage.removeItem('continueAutoExtract');
            
            // Đợi một chút để trang tải hoàn toàn
            setTimeout(() => {
                // Kích hoạt quá trình tự động
                const startButton = document.querySelector('#content-extractor button');
                if (startButton && startButton.textContent === 'Bắt đầu lấy text') {
                    startButton.click();
                } else {
                    // Nếu không tìm thấy nút hoặc nút không đúng trạng thái,
                    // bắt đầu trực tiếp quá trình trích xuất
                    let isAutomaticExtraction = true;
                    autoExtractAndNavigate();
                }
            }, 2000);
        }
    }

    // Run when page is fully loaded
    window.addEventListener('load', init);
})();