TTV Auto Upload

Tự động điền form đăng chương trên tangthuvien.net với tính năng nâng cao

当前为 2025-03-08 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         TTV Auto Upload
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  Tự động điền form đăng chương trên tangthuvien.net với tính năng nâng cao
// @author       HA
// @match        https://tangthuvien.net/dang-chuong/story/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Thêm CSS cho thông báo và nút
    const style = document.createElement('style');
    style.textContent = `
        .ttv-notification {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 10px 20px;
            background: #4CAF50;
            color: white;
            border-radius: 4px;
            z-index: 9999;
            display: none;
        }
        .ttv-error {
            background: #f44336;
        }
        .ttv-control-panel {
            position: fixed;
            top: 70px;
            right: 20px;
            background: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            z-index: 9998;
            width: 250px;
        }
        .ttv-button-group {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .ttv-button-group button,
        .ttv-file-label {
            width: 100%;
            padding: 8px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            text-align: center;
        }
        .ttv-file-input {
            display: none;
        }
        .ttv-file-label {
            background: #5bc0de;
            color: white;
            margin: 0;
        }
        .ttv-file-label:hover {
            background: #46b8da;
        }
        .ttv-header {
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid #eee;
            font-weight: bold;
            text-align: center;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        button.ttv-minimize {
            position: absolute;
            top: 10px;
            right: 10px;
            background: none;
            border: none;
            cursor: pointer;
            padding: 0;
            font-size: 18px;
            color: #666;
        }
        .ttv-control-panel.minimized {
            width: auto;
            height: auto;
            padding: 10px;
        }
        .ttv-control-panel.minimized .ttv-button-group,
        .ttv-control-panel.minimized .ttv-header {
            display: none;
        }
        .ttv-content-editor {
            width: 100%;
            height: 300px;
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
            line-height: 1.5;
            resize: vertical;
        }
        .ttv-heading {
            font-size: 12px;
            color: #666;
            margin: 5px 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .ttv-word-count {
            font-size: 11px;
            color: #999;
        }
        .ttv-preview {
            display: none;
            width: 100%;
            height: 300px;
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
            line-height: 1.5;
            overflow-y: auto;
            background: #f9f9f9;
        }
        .ttv-control-panel.fullscreen {
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 0;
            z-index: 9999;
        }
        .ttv-control-panel.fullscreen .ttv-content-editor,
        .ttv-control-panel.fullscreen .ttv-preview {
            height: calc(100vh - 250px);
        }
        .ttv-toolbar {
            display: flex;
            gap: 5px;
        }
        .ttv-toolbar button {
            padding: 2px 8px;
            font-size: 12px;
            color: #666;
            background: none;
            border: 1px solid #ddd;
            border-radius: 3px;
            cursor: pointer;
        }
        .ttv-toolbar button:hover {
            background: #f0f0f0;
        }
    `;
    document.head.appendChild(style);

    // Tạo div thông báo
    const notification = document.createElement('div');
    notification.className = 'ttv-notification';
    document.body.appendChild(notification);

    // Hiển thị thông báo
    function showNotification(message, isError = false) {
        notification.textContent = message;
        notification.className = 'ttv-notification' + (isError ? ' ttv-error' : '');
        notification.style.display = 'block';
        setTimeout(() => {
            notification.style.display = 'none';
        }, 3000);
    }

    // Đọc nội dung file
    function readFileContent(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => resolve(e.target.result);
            reader.onerror = (e) => reject(new Error('Lỗi đọc file: ' + e.target.error));
            reader.readAsText(file, 'UTF-8');
        });
    }

    // Đếm số từ và ký tự
    function updateWordCount(content) {
        const wordCount = content.trim().split(/\s+/).length;
        const charCount = content.length;
        return `${wordCount} từ | ${charCount} ký tự`;
    }

    // Tự động lưu nội dung
    let autoSaveTimeout;
    function autoSaveContent(content) {
        clearTimeout(autoSaveTimeout);
        autoSaveTimeout = setTimeout(() => {
            localStorage.setItem('ttv_autosave_content', content);
            showNotification('Đã tự động lưu nội dung');
        }, 2000);
    }

    // Chuyển đổi giữa chế độ soạn thảo và xem trước
    function togglePreview() {
        const contentEditor = document.querySelector('.ttv-content-editor');
        const preview = document.querySelector('.ttv-preview');
        const previewBtn = document.querySelector('.ttv-preview-btn');

        if (contentEditor.style.display !== 'none') {
            contentEditor.style.display = 'none';
            preview.style.display = 'block';
            preview.innerHTML = contentEditor.value.replace(/\n/g, '<br>');
            previewBtn.textContent = 'Soạn thảo';
        } else {
            contentEditor.style.display = 'block';
            preview.style.display = 'none';
            previewBtn.textContent = 'Xem trước';
        }
    }

    // Chuyển đổi chế độ toàn màn hình
    function toggleFullscreen() {
        const panel = document.querySelector('.ttv-control-panel');
        const fullscreenBtn = document.querySelector('.ttv-fullscreen-btn');

        panel.classList.toggle('fullscreen');
        fullscreenBtn.textContent = panel.classList.contains('fullscreen') ? 'Thu nhỏ' : 'Toàn màn hình';
    }

    // Xử lý khi chọn file
    async function handleFileSelect(event) {
        try {
            const file = event.target.files[0];
            if (!file) return;

            // Đọc nội dung file
            const content = await readFileContent(file);

            // Điền vào khung soạn thảo nội dung
            const contentEditor = document.querySelector('.ttv-content-editor');
            if (contentEditor) {
                contentEditor.value = content;

                // Cập nhật số từ
                const wordCountSpan = document.querySelector('.ttv-word-count');
                if (wordCountSpan) {
                    wordCountSpan.textContent = updateWordCount(content);
                }

                // Tự động lưu nội dung
                autoSaveContent(content);

                showNotification('Đã tải nội dung từ file thành công!');
            } else {
                showNotification('Không tìm thấy khung soạn thảo!', true);
            }
        } catch (error) {
            console.error('Lỗi xử lý file:', error);
            showNotification('Có lỗi xảy ra khi đọc file!', true);
        }
    }

    // Chuyển nội dung từ khung soạn thảo sang form
    function transferContent() {
        const contentEditor = document.querySelector('.ttv-content-editor');
        const contentInput = document.querySelector('textarea[name="introduce[1]"]');

        if (contentEditor && contentInput) {
            contentInput.value = contentEditor.value;
            showNotification('Đã chuyển nội dung sang form đăng chương!');
        } else {
            showNotification('Không tìm thấy form đăng chương!', true);
        }
    }

    // Thêm panel điều khiển
    function addControlPanel() {
        // Tạo panel
        const panel = document.createElement('div');
        panel.className = 'ttv-control-panel';

        // Thêm header
        const header = document.createElement('div');
        header.className = 'ttv-header';
        header.innerHTML = `
            <div>Soạn Thảo Nội Dung</div>
            <div class="ttv-toolbar">
                <button class="ttv-preview-btn" onclick="togglePreview()">Xem trước</button>
                <button class="ttv-fullscreen-btn" onclick="toggleFullscreen()">Toàn màn hình</button>
                <button class="ttv-minimize">−</button>
            </div>
        `;

        // Container cho các nút
        const buttonGroup = document.createElement('div');
        buttonGroup.className = 'ttv-button-group';


        // Input chọn file
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = '.txt';
        fileInput.className = 'ttv-file-input';
        fileInput.id = 'ttv-file-input';
        fileInput.onchange = handleFileSelect;

        // Label cho input file
        const fileLabel = document.createElement('label');
        fileLabel.htmlFor = 'ttv-file-input';
        fileLabel.className = 'ttv-file-label';
        fileLabel.innerHTML = '<span>Chọn file txt chứa nội dung</span>';

        // Khung soạn thảo nội dung
        const contentEditorLabel = document.createElement('div');
        contentEditorLabel.className = 'ttv-heading';
        contentEditorLabel.innerHTML = `
            Nội dung chương:
            <span class="ttv-word-count">0 từ | 0 ký tự</span>
        `;

        const contentEditor = document.createElement('textarea');
        contentEditor.className = 'ttv-content-editor';
        contentEditor.placeholder = 'Nhập hoặc dán nội dung chương vào đây...';

        // Khung xem trước
        const preview = document.createElement('div');
        preview.className = 'ttv-preview';

        // Cập nhật số từ và tự động lưu khi nhập nội dung
        contentEditor.oninput = () => {
            const wordCountSpan = document.querySelector('.ttv-word-count');
            if (wordCountSpan) {
                wordCountSpan.textContent = updateWordCount(contentEditor.value);
            }
            autoSaveContent(contentEditor.value);
        };

        // Nút chuyển nội dung
        const transferBtn = document.createElement('button');
        transferBtn.type = 'button';
        transferBtn.className = 'btn btn-warning';
        transferBtn.innerHTML = '<span>Chuyển nội dung sang form</span>';
        transferBtn.onclick = transferContent;


        // Thêm các phần tử vào panel
        panel.appendChild(header);
        buttonGroup.appendChild(fileInput);
        buttonGroup.appendChild(fileLabel);
        buttonGroup.appendChild(contentEditorLabel);
        buttonGroup.appendChild(contentEditor);
        buttonGroup.appendChild(preview);
        buttonGroup.appendChild(transferBtn);
        panel.appendChild(buttonGroup);

        // Khôi phục nội dung đã lưu tự động
        const savedContent = localStorage.getItem('ttv_autosave_content');
        if (savedContent) {
            contentEditor.value = savedContent;
            const wordCountSpan = document.querySelector('.ttv-word-count');
            if (wordCountSpan) {
                wordCountSpan.textContent = updateWordCount(savedContent);
            }
        }

        document.body.appendChild(panel);

        // Thêm xử lý sự kiện cho các nút trong toolbar
        const minimizeBtn = panel.querySelector('.ttv-minimize');
        minimizeBtn.onclick = () => {
            if (panel.classList.contains('minimized')) {
                panel.classList.remove('minimized');
                minimizeBtn.innerHTML = '−';
            } else {
                panel.classList.add('minimized');
                minimizeBtn.innerHTML = '+';
            }
        };

        window.togglePreview = togglePreview;
        window.toggleFullscreen = toggleFullscreen;
    }

    // Thêm control panel khi trang đã load
    window.addEventListener('load', function() {
        addControlPanel();
    });
})();