您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a control panel for novel reading on truyen.tangthuvien.net
当前为
// ==UserScript== // @name Chapter Downloader // @namespace http://tampermonkey.net/ // @version 1.9 // @description Add a control panel for novel reading on truyen.tangthuvien.net // @author You // @match https://truyen.tangthuvien.net/doc-truyen/* // @match https://truyen.tangthuvien.net/doc-truyen/*/* // @grant none // ==/UserScript== (function() { 'use strict'; // Create panel container 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; `; // Create textarea 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; `; // Create start button 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; `; // Create container for getTextButton and nextChapterButton (same row) const buttonRow1 = document.createElement('div'); buttonRow1.style.cssText = ` display: flex; justify-content: space-between; margin-bottom: 10px; `; // Create get text button 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; `; // Create next chapter button 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; `; // Create container for clearButton and copyButton (same row) const buttonRow2 = document.createElement('div'); buttonRow2.style.cssText = ` display: flex; justify-content: space-between; `; // Create clear button 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; `; // Create copy button 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; `; // Add buttons to their respective row containers buttonRow1.appendChild(getTextButton); buttonRow1.appendChild(nextChapterButton); buttonRow2.appendChild(clearButton); buttonRow2.appendChild(copyButton); // Add all elements to panel panel.appendChild(textarea); panel.appendChild(startButton); panel.appendChild(buttonRow1); panel.appendChild(buttonRow2); // Add panel to body document.body.appendChild(panel); // Load saved content from localStorage if exists const savedContent = localStorage.getItem('chapterDownloaderContent'); if (savedContent) { textarea.value = savedContent; } // Function to save content to localStorage function saveContent() { localStorage.setItem('chapterDownloaderContent', textarea.value); console.log('Content saved to localStorage'); } // Auto save when textarea value changes textarea.addEventListener('input', saveContent); // Function to extract and add chapter content function extractChapterContent() { // Get chapter title const titleElement = document.querySelector('h2'); // Get chapter content const contentElement = document.querySelector('.box-chap'); if (titleElement && contentElement) { // Append to existing content rather than replacing const title = titleElement.innerText.trim(); const content = contentElement.innerText.trim(); // Append with proper formatting if (textarea.value) { textarea.value += '\n\n------------\n\n' + title + '\n\n' + content; } else { textarea.value = title + '\n\n' + content; } // Save content after adding new chapter saveContent(); return true; } else { console.log('Could not find title or content elements'); return false; } } // Function to navigate to next chapter function goToNextChapter() { // Find the next chapter button with the correct selector const nextChapterLink = document.querySelector('.bot-next_chap.bot-control'); if (nextChapterLink) { console.log('Found next chapter link, navigating...'); nextChapterLink.click(); return true; } else { console.log('Could not find next chapter link with class ".bot-next_chap.bot-control"'); // Try alternative selectors if the main one doesn't work const alternativeNextLinks = document.querySelectorAll('a[href*="chuong"]'); for (const link of alternativeNextLinks) { if (link.textContent.includes('tiếp') || link.textContent.includes('sau') || link.textContent.includes('next')) { console.log('Found alternative next chapter link, navigating...'); link.click(); return true; } } return false; } } // Variable to track auto-downloading state let isAutoDownloading = false; // Function to handle automatic downloading function startAutoDownloading() { if (!isAutoDownloading) return; console.log('Auto-downloading: Extracting chapter content...'); if (extractChapterContent()) { // After extracting, wait 1 second then navigate to next chapter setTimeout(() => { if (!isAutoDownloading) return; console.log('Auto-downloading: Navigating to next chapter...'); if (goToNextChapter()) { // After navigation, wait 2 seconds for page to load then extract again setTimeout(() => { if (isAutoDownloading) { startAutoDownloading(); } }, 2000); // Wait 2 seconds for page to load before extracting next chapter } else { console.log('Auto-downloading: Could not find next chapter, stopping.'); isAutoDownloading = false; startButton.textContent = 'Bắt đầu'; startButton.style.backgroundColor = '#4CAF50'; } }, 1000); // Wait 1 second before navigating } else { console.log('Auto-downloading: Could not extract chapter content, stopping.'); isAutoDownloading = false; startButton.textContent = 'Bắt đầu'; startButton.style.backgroundColor = '#4CAF50'; } } // Add event listeners startButton.addEventListener('click', () => { // Toggle auto-downloading state isAutoDownloading = !isAutoDownloading; if (isAutoDownloading) { console.log('Start button clicked: Beginning auto-download sequence'); startButton.textContent = 'Dừng'; startButton.style.backgroundColor = '#f44336'; // Red color to indicate active startAutoDownloading(); // Start the sequence } else { console.log('Start button clicked: Stopping auto-download sequence'); startButton.textContent = 'Bắt đầu'; startButton.style.backgroundColor = '#4CAF50'; // Green color when inactive } }); getTextButton.addEventListener('click', () => { console.log('Get text button clicked'); extractChapterContent(); }); nextChapterButton.addEventListener('click', () => { console.log('Next chapter button clicked'); goToNextChapter(); }); clearButton.addEventListener('click', () => { console.log('Clear button clicked'); textarea.value = ''; saveContent(); // Save empty content to localStorage }); copyButton.addEventListener('click', () => { console.log('Copy button clicked'); textarea.select(); document.execCommand('copy'); // Show a temporary copy notification 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); // Remove notification after 2 seconds setTimeout(() => { document.body.removeChild(notification); }, 2000); }); // Make panel draggable 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; }); // Add keyboard shortcuts document.addEventListener('keydown', (e) => { // Only handle if not typing in a text field if (e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'INPUT') { // Alt+G: Get text if (e.altKey && e.key === 'g') { extractChapterContent(); e.preventDefault(); } // Alt+N: Next chapter else if (e.altKey && e.key === 'n') { goToNextChapter(); e.preventDefault(); } // Alt+S: Toggle auto-downloading (same as clicking Start/Stop button) else if (e.altKey && e.key === 's') { // Simulate clicking the start button startButton.click(); e.preventDefault(); } // Alt+C: Copy text else if (e.altKey && e.key === 'c') { textarea.select(); document.execCommand('copy'); e.preventDefault(); } } }); // Add information about keyboard shortcuts 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 tự động), Alt+C (Sao chép) `; panel.appendChild(shortcutsInfo); console.log('Chapter Downloader script initialized successfully'); })();