Chapter Downloader

Tự động lấy nội dung từ chương hiện tại đến hết trên truyen.tangthuvien.vn

当前为 2025-04-22 提交的版本,查看 最新版本

// ==UserScript==
// @name         Chapter Downloader
// @namespace    http://tampermonkey.net/
// @version      2.3
// @description  Tự động lấy nội dung từ chương hiện tại đến hết trên truyen.tangthuvien.vn
// @author       Bạn
// @match        https://truyen.tangthuvien.vn/doc-truyen/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    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);
    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();

            if (textarea.value) {
                textarea.value += '\n\n' + title + '\n\n' + content;
            } else {
                textarea.value = title + '\n\n' + content;
            }

            saveContent();
            return true;
        } else {
            return false;
        }
    }

    function goToNextChapter() {
        const nextChapterLink = document.querySelector('.bot-next_chap.bot-control');
        if (nextChapterLink) {
            nextChapterLink.click();
            return true;
        } else {
            const alternatives = document.querySelectorAll('a[href*="chuong"]');
            for (const link of alternatives) {
                if (link.textContent.toLowerCase().includes('tiếp') || link.textContent.toLowerCase().includes('sau') || link.textContent.toLowerCase().includes('next')) {
                    link.click();
                    return true;
                }
            }
        }
        return false;
    }

    let isAutoDownloading = false;

    function startAutoDownloading() {
        if (!isAutoDownloading) return;

        if (extractChapterContent()) {
            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) {
            startButton.textContent = 'Dừng';
            startButton.style.backgroundColor = '#f44336';
            startAutoDownloading();
        } else {
            startButton.textContent = 'Bắt đầu';
            startButton.style.backgroundColor = '#4CAF50';
        }
    });

    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-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 (Bắt đầu/Dừng), Alt+C (Sao chép)
    `;
    panel.appendChild(shortcutsInfo);

    document.addEventListener('keydown', (e) => {
        if (e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'INPUT') {
            if (e.altKey && e.key === 'g') { extractChapterContent(); e.preventDefault(); }
            else if (e.altKey && e.key === 'n') { goToNextChapter(); e.preventDefault(); }
            else if (e.altKey && e.key === 's') { startButton.click(); e.preventDefault(); }
            else if (e.altKey && e.key === 'c') { textarea.select(); document.execCommand('copy'); e.preventDefault(); }
        }
    });

    console.log('Chapter Downloader script loaded (no separator mode)');
})();