Chapter Downloader

Tự động trích xuất nội dung truyện từ 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      1.3
// @description  Tự động trích xuất nội dung truyện từ truyen.tangthuvien.net
// @author       TangThuVienExtractor
// @match        https://truyen.tangthuvien.net/doc-truyen/*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Biến toàn cục để theo dõi trạng thái trích xuất tự động
    let isAutomaticExtraction = localStorage.getItem('isAutoExtractionActive') === 'true';
    
    // Biến đếm số chương đã trích xuất
    let chaptersExtracted = parseInt(localStorage.getItem('chaptersExtracted') || '0');

    // Tạo panel ở bên phải trang
    function createPanel() {
        // Tạo container chính cho panel
        const panel = document.createElement('div');
        panel.style.position = 'fixed';
        panel.style.top = '100px';
        panel.style.right = '20px';
        panel.style.width = '300px';
        panel.style.backgroundColor = '#f9f9f9';
        panel.style.border = '1px solid #ddd';
        panel.style.borderRadius = '5px';
        panel.style.padding = '10px';
        panel.style.zIndex = '9999';
        panel.style.display = 'flex';
        panel.style.flexDirection = 'column';
        panel.style.gap = '10px';
        panel.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';

        // Tạo tiêu đề panel
        const title = document.createElement('h3');
        title.textContent = 'Trích xuất nội dung truyện';
        title.style.margin = '0 0 10px 0';
        title.style.textAlign = 'center';
        title.style.borderBottom = '1px solid #ddd';
        title.style.paddingBottom = '10px';
        panel.appendChild(title);

        // Tạo textarea để hiển thị nội dung đã trích xuất
        const textarea = document.createElement('textarea');
        textarea.style.width = '100%';
        textarea.style.height = '200px';
        textarea.style.padding = '8px';
        textarea.style.borderRadius = '3px';
        textarea.style.border = '1px solid #ddd';
        textarea.style.marginBottom = '10px';
        textarea.style.resize = 'vertical';
        panel.appendChild(textarea);

        // Lấy nội dung đã lưu từ localStorage (nếu có)
        const savedContent = localStorage.getItem('tangthuvien_extracted_content');
        if (savedContent) {
            textarea.value = savedContent;
        }

        // Tạo container cho các nút
        const buttonContainer = document.createElement('div');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.flexDirection = 'column';
        buttonContainer.style.gap = '5px';
        panel.appendChild(buttonContainer);

        // Tạo nút bắt đầu trích xuất
        const startButton = document.createElement('button');
        startButton.textContent = 'Bắt đầu lấy text';
        startButton.style.padding = '8px';
        startButton.style.backgroundColor = '#4caf50';
        startButton.style.color = 'white';
        startButton.style.border = 'none';
        startButton.style.borderRadius = '3px';
        startButton.style.cursor = 'pointer';
        startButton.addEventListener('click', function() {
            if (!isAutomaticExtraction) {
                isAutomaticExtraction = true;
                localStorage.setItem('isAutoExtractionActive', 'true');
                startButton.textContent = 'Đang trích xuất...';
                startButton.style.backgroundColor = '#ff9800';
                
                // Đặt lại số chương khi bắt đầu lại quá trình
                if (!confirm("Tiếp tục đếm số chương đã trích xuất?")) {
                    chaptersExtracted = 0;
                    localStorage.setItem('chaptersExtracted', '0');
                }
                
                // Bắt đầu quá trình trích xuất tự động
                autoExtractAndNavigate();
            } else {
                isAutomaticExtraction = false;
                localStorage.setItem('isAutoExtractionActive', 'false');
                startButton.textContent = 'Bắt đầu lấy text';
                startButton.style.backgroundColor = '#4caf50';
            }
        });
        buttonContainer.appendChild(startButton);

        // Tạo nút xóa nội dung
        const clearButton = document.createElement('button');
        clearButton.textContent = 'Xóa nội dung';
        clearButton.style.padding = '8px';
        clearButton.style.backgroundColor = '#f44336';
        clearButton.style.color = 'white';
        clearButton.style.border = 'none';
        clearButton.style.borderRadius = '3px';
        clearButton.style.cursor = 'pointer';
        clearButton.addEventListener('click', function() {
            textarea.value = '';
            localStorage.removeItem('tangthuvien_extracted_content');
            
            // Hiển thị thông báo
            const notification = document.createElement('div');
            notification.textContent = 'Đã xóa nội dung';
            notification.style.position = 'fixed';
            notification.style.bottom = '20px';
            notification.style.right = '20px';
            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(clearButton);

        // Tạo nút sao chép nội dung
        const copyButton = document.createElement('button');
        copyButton.textContent = 'Sao chép nội dung';
        copyButton.style.padding = '8px';
        copyButton.style.backgroundColor = '#2196f3';
        copyButton.style.color = 'white';
        copyButton.style.border = 'none';
        copyButton.style.borderRadius = '3px';
        copyButton.style.cursor = 'pointer';
        copyButton.addEventListener('click', function() {
            textarea.select();
            document.execCommand('copy');
            
            // Hiển thị thông báo
            const notification = document.createElement('div');
            notification.textContent = 'Đã sao chép nội dung';
            notification.style.position = 'fixed';
            notification.style.bottom = '20px';
            notification.style.right = '20px';
            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 3 giây
            setTimeout(() => {
                document.body.removeChild(notification);
            }, 3000);
        });
        buttonContainer.appendChild(copyButton);

        // Thêm panel vào body
        document.body.appendChild(panel);
        
        // Trả về các phần tử để sử dụng sau này
        return {
            panel,
            textarea,
            startButton
        };
    }

    // Hàm trích xuất nội dung chương hiện tại
    function extractCurrentChapterContent() {
        const panelElements = document.querySelector('textarea');
        const startButton = document.querySelector('button');
        
        if (!panelElements || !startButton) {
            console.error('Không tìm thấy panel hoặc textarea');
            return false;
        }
        
        // Lấy tiêu đề chương
        const chapterTitle = document.querySelector('h2');
        if (!chapterTitle) {
            console.error('Không tìm thấy tiêu đề chương');
            return false;
        }
        
        // Lấy nội dung chương
        const chapterContentSelector = '.box-chap';
        const chapterContent = document.querySelector(chapterContentSelector);
        if (!chapterContent) {
            console.error('Không tìm thấy nội dung chương');
            return false;
        }
        
        // Xử lý nội dung
        let contentText = chapterContent.innerText || chapterContent.textContent;
        contentText = contentText.trim();
        
        // Thêm nội dung vào textarea
        let currentContent = panelElements.value || '';
        
        // Thêm dấu phân cách nếu đã có nội dung trước đó
        if (currentContent !== '') {
            currentContent += '\n\n------------\n\n';
        }
        
        // Thêm tiêu đề và nội dung
        currentContent += chapterTitle.innerText + '\n\n' + contentText;
        
        // Cập nhật textarea và lưu vào localStorage
        panelElements.value = currentContent;
        localStorage.setItem('tangthuvien_extracted_content', currentContent);
        
        // Tăng số chương đã trích xuất và lưu vào localStorage
        chaptersExtracted++;
        localStorage.setItem('chaptersExtracted', chaptersExtracted);
        
        // Hiển thị thông báo
        const notification = document.createElement('div');
        notification.textContent = `Đã trích xuất: ${chapterTitle.innerText} (Chương ${chaptersExtracted})`;
        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 3 giây
        setTimeout(() => {
            document.body.removeChild(notification);
        }, 3000);
        
        return true;
    }

    // Biến đếm số lần thử trích xuất
    let extractionAttempts = 0;
    
    // Hàm tự động trích xuất và chuyển trang
    function autoExtractAndNavigate() {
        if (!isAutomaticExtraction) {
            return;
        }
        
        // Đặt lại biến đếm nếu quá trình tiếp tục
        extractionAttempts = 0;
        
        // Trích xuất nội dung chương hiện tại
        const extractionSuccess = extractCurrentChapterContent();
        
        if (extractionSuccess) {
            // Tìm nút chuyển đến chương tiếp theo
            const nextButton = document.querySelector('.bot-next_chap.bot-control');
            
            // Kiểm tra xem có thông báo "Bạn đã đọc đến chương mới nhất" hay không
            const pageContent = document.body.innerText || document.body.textContent;
            if (pageContent && pageContent.includes('Bạn đã đọc đến chương mới nhất')) {
                // Kết thúc quá trình khi thấy thông báo này
                console.log("Đã phát hiện thông báo: Bạn đã đọc đến chương mới nhất");
                isAutomaticExtraction = false;
                const startButton = document.querySelector('button');
                if (startButton) {
                    startButton.textContent = 'Bắt đầu lấy text';
                    startButton.style.backgroundColor = '#4caf50';
                }
                
                // 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);
                return;
            }
            
            if (nextButton) {
                // Hiển thị thông báo
                const notification = document.createElement('div');
                notification.textContent = 'Đang chuyển đến chương tiếp theo...';
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#ff9800';
                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);
                }, 1000);
                
                // Nhấp vào nút chuyển trang
                nextButton.click();
                
                // Đợi 2 giây để trang mới tải xong, sau đó tiếp tục quá trình
                setTimeout(() => {
                    console.log("Trang mới đã được tải, tiếp tục quá trình...");
                    
                    // Đánh dấu rõ ràng rằng quá trình tự động vẫn đang diễn ra
                    window.localStorage.setItem('isAutoExtractionActive', 'true');
                    isAutomaticExtraction = true;
                    
                    // Kiểm tra xem nút có bị ẩn hay không
                    const startButton = document.querySelector('button');
                    if (startButton) {
                        startButton.textContent = 'Đang trích xuất...';
                        startButton.style.backgroundColor = '#ff9800';
                    }
                    
                    // Hiển thị thông báo đang đợi trang tải
                    const notification = document.createElement('div');
                    notification.textContent = 'Đợi trang tải xong...';
                    notification.style.position = 'fixed';
                    notification.style.bottom = '20px';
                    notification.style.right = '320px';
                    notification.style.backgroundColor = '#FFA500';
                    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 và bắt đầu trích xuất sau 3 giây (tăng thời gian cho trang tải đầy đủ)
                    setTimeout(() => {
                        try {
                            document.body.removeChild(notification);
                        } catch (error) {
                            console.log("Thông báo đã bị xóa");
                        }
                        
                        // Đảm bảo biến isAutomaticExtraction vẫn là true để tiếp tục quá trình
                        isAutomaticExtraction = true;
                        console.log("Bắt đầu trích xuất trang mới...");
                        
                        // Gọi lại hàm trích xuất để tiếp tục quá trình
                        autoExtractAndNavigate();
                    }, 3000);
                }, 3000);
            } else {
                // Nếu không tìm thấy nút chuyển trang
                isAutomaticExtraction = false;
                const startButton = document.querySelector('button');
                if (startButton) {
                    startButton.textContent = 'Bắt đầu lấy text';
                    startButton.style.backgroundColor = '#4caf50';
                }
                
                // Hiển thị thông báo
                const notification = document.createElement('div');
                notification.textContent = 'Không tìm thấy nút chuyển trang';
                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 5 giây
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 5000);
            }
        } else {
            // Nếu trích xuất thất bại
            extractionAttempts++;
            
            // Thử lại tối đa 3 lần nếu trích xuất thất bại
            if (extractionAttempts < 3) {
                console.log(`Thử trích xuất lần ${extractionAttempts}`);
                
                // Hiển thị thông báo
                const notification = document.createElement('div');
                notification.textContent = `Đang thử lại lần ${extractionAttempts}...`;
                notification.style.position = 'fixed';
                notification.style.bottom = '20px';
                notification.style.right = '320px';
                notification.style.backgroundColor = '#ff9800';
                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 và thử lại sau 2 giây
                setTimeout(() => {
                    document.body.removeChild(notification);
                    autoExtractAndNavigate();
                }, 2000);
                return;
            }
            
            // Sau 3 lần thử vẫn thất bại
            isAutomaticExtraction = false;
            const startButton = document.querySelector('button');
            if (startButton) {
                startButton.textContent = 'Bắt đầu lấy text';
                startButton.style.backgroundColor = '#4caf50';
            }
            
            // Hiển thị thông báo
            const notification = document.createElement('div');
            notification.textContent = 'Trích xuất thất bại';
            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 5 giây
            setTimeout(() => {
                document.body.removeChild(notification);
            }, 5000);
        }
    }

    // Khởi tạo panel khi trang đã tải xong
    window.addEventListener('load', function() {
        // Đợi 1 giây để đảm bảo trang đã tải hoàn toàn
        setTimeout(() => {
            createPanel();
        }, 1000);
    });
})();