Chapter Downloader

Tải nội dung chương truyện từ TangThuVien

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

// ==UserScript==
// @name         Chapter Downloader 
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Tải nội dung chương truyện từ TangThuVien
// @author       Your name
// @match        https://truyen.tangthuvien.net/doc-truyen/*/*
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // Thêm CSS cho khung soạn thảo
    GM_addStyle(`
        .story-editor-container {
            position: fixed;
            top: 20px;
            right: 20px;
            width: 400px;
            height: 80vh;
            background: white;
            border: 1px solid #ccc;
            padding: 10px;
            z-index: 9999;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .story-editor {
            flex: 1;
            width: 100%;
            resize: none;
            font-family: Arial, sans-serif;
            font-size: 14px;
            line-height: 1.6;
            padding: 10px;
        }
        .button-container {
            display: flex;
            gap: 10px;
        }
        button {
            padding: 8px 16px;
            cursor: pointer;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
        }
        button:hover {
            background: #45a049;
        }
        .status-text {
            font-size: 12px;
            color: #666;
        }
    `);

    // Log tất cả các elements có thể chứa nội dung
    function logPossibleElements() {
        const elements = document.querySelectorAll('*');
        const contentElements = Array.from(elements).filter(el => {
            const text = el.textContent?.trim();
            return text && text.length > 100;
        });

        console.log('Các elements có thể chứa nội dung:', 
            contentElements.map(el => ({
                tagName: el.tagName,
                className: el.className,
                id: el.id,
                textLength: el.textContent?.trim().length,
                firstChars: el.textContent?.trim().substring(0, 50)
            }))
        );
    }

    // Lấy nội dung chương hiện tại
    async function getCurrentChapter() {
        try {
            console.log('Bắt đầu lấy nội dung chương...');
            logPossibleElements();

            // Đợi nội dung tải xong
            await new Promise(resolve => setTimeout(resolve, 3000));

            // Tìm container chính
            const mainContainer = document.querySelector('#article') || 
                                document.querySelector('.content-chapter') ||
                                document.querySelector('.chapter-content');

            console.log('Container chính:', {
                found: !!mainContainer,
                id: mainContainer?.id,
                className: mainContainer?.className
            });

            if (!mainContainer) {
                throw new Error('Không tìm thấy container chính');
            }

            // Tìm tiêu đề
            const titleSelectors = [
                'h2.chapter-title',
                '.chapter-title',
                '.truyen-title',
                'h2.title',
                '.content-chapter h2'
            ];

            let titleElement;
            for (const selector of titleSelectors) {
                titleElement = mainContainer.querySelector(selector);
                if (titleElement?.textContent?.trim()) {
                    console.log('Tìm thấy tiêu đề với selector:', selector);
                    break;
                }
            }

            // Tìm nội dung
            const contentSelectors = [
                '.chapter-c',
                '.chapter-content',
                '.content-chapter',
                '.box-chap'
            ];

            let contentElement;
            for (const selector of contentSelectors) {
                contentElement = mainContainer.querySelector(selector);
                if (contentElement?.textContent?.trim()) {
                    console.log('Tìm thấy nội dung với selector:', selector);
                    break;
                }
            }

            if (!titleElement || !contentElement) {
                console.error('Không tìm thấy nội dung:', {
                    hasTitle: !!titleElement,
                    hasContent: !!contentElement,
                    titleHTML: titleElement?.outerHTML,
                    contentPreview: contentElement?.textContent?.trim().substring(0, 100)
                });
                throw new Error('Không tìm thấy nội dung hoặc tiêu đề');
            }

            // Xử lý nội dung
            let title = titleElement.textContent.trim();
            let content = contentElement.textContent.trim();

            // Làm sạch nội dung
            content = content.replace(title, ''); // Xóa tiêu đề khỏi nội dung
            content = content.replace(/\[\s*\w+\s*\]/g, ''); // Xóa [xxx]
            content = content.replace(/[""]/g, '"'); // Chuẩn hóa dấu ngoặc kép
            content = content.replace(/\s+/g, ' ').trim(); // Chuẩn hóa khoảng trắng

            console.log('Đã lấy nội dung:', {
                title,
                contentLength: content.length,
                contentPreview: content.substring(0, 100) + '...'
            });

            return { title, content };
        } catch (error) {
            console.error('Lỗi khi lấy nội dung:', error);
            return null;
        }
    }

    // Thêm nội dung chương mới vào editor
    function appendChapterContent(editor, title, content) {
        try {
            if (!editor || !title || !content) {
                console.error('Input không hợp lệ:', {
                    hasEditor: !!editor,
                    hasTitle: !!title,
                    hasContent: !!content
                });
                return false;
            }

            // Thêm dấu phân cách nếu đã có nội dung
            const separator = editor.value ? '\n\n' + '-'.repeat(50) + '\n\n' : '';
            const newContent = title + '\n\n' + content;

            // Nối tiếp nội dung vào cuối
            editor.value += separator + newContent;
            editor.scrollTop = editor.scrollHeight;

            console.log('Đã thêm nội dung:', {
                previousLength: editor.value.length - (separator + newContent).length,
                addedLength: newContent.length,
                newTotalLength: editor.value.length
            });

            return true;
        } catch (error) {
            console.error('Lỗi khi thêm nội dung:', error);
            return false;
        }
    }

    // Chuyển đến chương tiếp theo
    function goToNextChapter() {
        const nextButton = document.querySelector('a.next-chap');
        if (nextButton && !nextButton.classList.contains('disabled') && nextButton.style.display !== 'none') {
            console.log('Chuyển đến chương tiếp theo');
            nextButton.click();
            return true;
        }
        console.log('Không tìm thấy nút next hợp lệ');
        return false;
    }

    // Tải chương tiếp theo
    async function loadNextChapter() {
        try {
            console.log('Bắt đầu tải chương tiếp...');

            const editor = document.querySelector('.story-editor');
            if (!editor) {
                throw new Error('Không tìm thấy editor');
            }

            // Đợi nội dung tải
            const chapterData = await getCurrentChapter();
            if (!chapterData) {
                throw new Error('Không lấy được nội dung chương');
            }

            // Thêm nội dung vào editor
            if (!appendChapterContent(editor, chapterData.title, chapterData.content)) {
                throw new Error('Không thêm được nội dung vào editor');
            }

            // Tự động tải chương tiếp
            setTimeout(() => {
                if (goToNextChapter()) {
                    setTimeout(loadNextChapter, 3000);
                }
            }, 1000);

        } catch (error) {
            console.error('Lỗi khi tải chương:', error);
        }
    }

    // Xuất nội dung ra file txt
    function exportToTxt() {
        try {
            const editor = document.querySelector('.story-editor');
            if (!editor?.value) {
                throw new Error('Không có nội dung để xuất');
            }

            const blob = new Blob([editor.value], { type: 'text/plain;charset=utf-8' });
            const url = window.URL.createObjectURL(blob);
            const link = document.createElement('a');

            const storyName = window.location.pathname.split('/')[2] || 'truyen';
            link.href = url;
            link.download = `${storyName}.txt`;

            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            window.URL.revokeObjectURL(url);

            console.log('Đã xuất file thành công');
        } catch (error) {
            console.error('Lỗi khi xuất file:', error);
        }
    }

    // Tạo giao diện
    function createUI() {
        console.log('Tạo giao diện...');

        const container = document.createElement('div');
        container.className = 'story-editor-container';

        const editor = document.createElement('textarea');
        editor.className = 'story-editor';
        editor.placeholder = 'Nội dung truyện sẽ hiển thị ở đây...';
        editor.readOnly = true;

        const buttonContainer = document.createElement('div');
        buttonContainer.className = 'button-container';

        const downloadBtn = document.createElement('button');
        downloadBtn.textContent = 'Tải chương tiếp';
        downloadBtn.onclick = loadNextChapter;

        const exportBtn = document.createElement('button');
        exportBtn.textContent = 'Xuất file TXT';
        exportBtn.onclick = exportToTxt;

        buttonContainer.appendChild(downloadBtn);
        buttonContainer.appendChild(exportBtn);

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

        console.log('Đã tạo giao diện thành công');
    }

    // Khởi tạo script
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', createUI);
    } else {
        createUI();
    }

    console.log('TangThuVien Chapter Downloader đã khởi chạy');
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址