Chapter Downloader

Add a control panel for novel reading

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

  1. // ==UserScript==
  2. // @name Chapter Downloader
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.7
  5. // @description Add a control panel for novel reading
  6. // @author You
  7. // @match https://truyen.tangthuvien.net/doc-truyen/*
  8. // @match https://truyen.tangthuvien.net/doc-truyen/*/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Create panel container
  16. const panel = document.createElement('div');
  17. panel.id = 'reader-panel';
  18. panel.style.cssText = `
  19. position: fixed;
  20. top: 10%;
  21. right: 10px;
  22. width: 300px;
  23. background-color: #f8f8f8;
  24. border: 1px solid #ccc;
  25. border-radius: 5px;
  26. padding: 10px;
  27. z-index: 9999;
  28. box-shadow: 0 0 10px rgba(0,0,0,0.2);
  29. font-family: Arial, sans-serif;
  30. `;
  31.  
  32. // Create textarea
  33. const textarea = document.createElement('textarea');
  34. textarea.id = 'content-textarea';
  35. textarea.style.cssText = `
  36. width: 100%;
  37. height: 300px;
  38. margin-bottom: 10px;
  39. padding: 8px;
  40. border: 1px solid #ddd;
  41. border-radius: 4px;
  42. resize: vertical;
  43. `;
  44.  
  45. // Create start button
  46. const startButton = document.createElement('button');
  47. startButton.textContent = 'Bắt đầu';
  48. startButton.style.cssText = `
  49. width: 100%;
  50. padding: 8px;
  51. margin-bottom: 10px;
  52. background-color: #4CAF50;
  53. color: white;
  54. border: none;
  55. border-radius: 4px;
  56. cursor: pointer;
  57. `;
  58.  
  59. // Create container for getTextButton and nextChapterButton (same row)
  60. const buttonRow1 = document.createElement('div');
  61. buttonRow1.style.cssText = `
  62. display: flex;
  63. justify-content: space-between;
  64. margin-bottom: 10px;
  65. `;
  66.  
  67. // Create get text button
  68. const getTextButton = document.createElement('button');
  69. getTextButton.textContent = 'Lấy Text';
  70. getTextButton.style.cssText = `
  71. flex: 1;
  72. padding: 8px;
  73. margin-right: 5px;
  74. background-color: #2196F3;
  75. color: white;
  76. border: none;
  77. border-radius: 4px;
  78. cursor: pointer;
  79. `;
  80.  
  81. // Create next chapter button
  82. const nextChapterButton = document.createElement('button');
  83. nextChapterButton.textContent = 'Chương Tiếp';
  84. nextChapterButton.style.cssText = `
  85. flex: 1;
  86. padding: 8px;
  87. margin-left: 5px;
  88. background-color: #ff9800;
  89. color: white;
  90. border: none;
  91. border-radius: 4px;
  92. cursor: pointer;
  93. `;
  94.  
  95. // Create container for clearButton and copyButton (same row)
  96. const buttonRow2 = document.createElement('div');
  97. buttonRow2.style.cssText = `
  98. display: flex;
  99. justify-content: space-between;
  100. `;
  101.  
  102. // Create clear button
  103. const clearButton = document.createElement('button');
  104. clearButton.textContent = 'Xoá';
  105. clearButton.style.cssText = `
  106. flex: 1;
  107. padding: 8px;
  108. margin-right: 5px;
  109. background-color: #f44336;
  110. color: white;
  111. border: none;
  112. border-radius: 4px;
  113. cursor: pointer;
  114. `;
  115.  
  116. // Create copy button
  117. const copyButton = document.createElement('button');
  118. copyButton.textContent = 'Sao Chép';
  119. copyButton.style.cssText = `
  120. flex: 1;
  121. padding: 8px;
  122. margin-left: 5px;
  123. background-color: #9c27b0;
  124. color: white;
  125. border: none;
  126. border-radius: 4px;
  127. cursor: pointer;
  128. `;
  129.  
  130. // Add buttons to their respective row containers
  131. buttonRow1.appendChild(getTextButton);
  132. buttonRow1.appendChild(nextChapterButton);
  133. buttonRow2.appendChild(clearButton);
  134. buttonRow2.appendChild(copyButton);
  135.  
  136. // Add all elements to panel
  137. panel.appendChild(textarea);
  138. panel.appendChild(startButton);
  139. panel.appendChild(buttonRow1);
  140. panel.appendChild(buttonRow2);
  141.  
  142. // Add panel to body
  143. document.body.appendChild(panel);
  144.  
  145. // Load saved content from localStorage if exists
  146. const savedContent = localStorage.getItem('chapterDownloaderContent');
  147. if (savedContent) {
  148. textarea.value = savedContent;
  149. }
  150.  
  151. // Function to save content to localStorage
  152. function saveContent() {
  153. localStorage.setItem('chapterDownloaderContent', textarea.value);
  154. console.log('Content saved to localStorage');
  155. }
  156.  
  157. // Auto save when textarea value changes
  158. textarea.addEventListener('input', saveContent);
  159.  
  160. // Add event listeners
  161. startButton.addEventListener('click', () => {
  162. console.log('Start button clicked');
  163. // Add your start functionality here
  164. });
  165.  
  166. getTextButton.addEventListener('click', () => {
  167. console.log('Get text button clicked');
  168. // Get chapter title
  169. const titleElement = document.querySelector('h2');
  170. // Get chapter content
  171. const contentElement = document.querySelector('.box-chap');
  172. if (titleElement && contentElement) {
  173. // Append to existing content rather than replacing
  174. const title = titleElement.innerText.trim();
  175. const content = contentElement.innerText.trim();
  176. // Append with proper formatting
  177. if (textarea.value) {
  178. textarea.value += '\n\n------------\n\n' + title + '\n\n' + content;
  179. } else {
  180. textarea.value = title + '\n\n' + content;
  181. }
  182. // Save content after adding new chapter
  183. saveContent();
  184. } else {
  185. console.log('Could not find title or content elements');
  186. }
  187. });
  188.  
  189. nextChapterButton.addEventListener('click', () => {
  190. console.log('Next chapter button clicked');
  191. // Add your next chapter functionality here
  192. // For example, find and click the next chapter link
  193. const nextChapterLink = document.querySelector('.next-chapter'); // Replace with actual next chapter selector
  194. if (nextChapterLink) {
  195. nextChapterLink.click();
  196. }
  197. });
  198.  
  199. clearButton.addEventListener('click', () => {
  200. console.log('Clear button clicked');
  201. textarea.value = '';
  202. saveContent(); // Save empty content to localStorage
  203. });
  204.  
  205. copyButton.addEventListener('click', () => {
  206. console.log('Copy button clicked');
  207. textarea.select();
  208. document.execCommand('copy');
  209. });
  210.  
  211. // Make panel draggable
  212. let isDragging = false;
  213. let offsetX, offsetY;
  214.  
  215. panel.addEventListener('mousedown', (e) => {
  216. if (e.target === panel) {
  217. isDragging = true;
  218. offsetX = e.clientX - panel.getBoundingClientRect().left;
  219. offsetY = e.clientY - panel.getBoundingClientRect().top;
  220. }
  221. });
  222.  
  223. document.addEventListener('mousemove', (e) => {
  224. if (isDragging) {
  225. panel.style.left = (e.clientX - offsetX) + 'px';
  226. panel.style.top = (e.clientY - offsetY) + 'px';
  227. panel.style.right = 'auto';
  228. }
  229. });
  230.  
  231. document.addEventListener('mouseup', () => {
  232. isDragging = false;
  233. });
  234. })();