Koharu Artist URL Collector

Collect URLs from koharu.to artist pages and store them in GM_storage

2024-08-20 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

  1. // ==UserScript==
  2. // @name Koharu Artist URL Collector
  3. // @namespace https://koharu.to/
  4. // @version 1.7.1.3
  5. // @description Collect URLs from koharu.to artist pages and store them in GM_storage
  6. // @license MIT
  7. // @author viatana35
  8. // @match https://koharu.to/?s=artist*
  9. // @match https://koharu.to/?s=circle*
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_deleteValue
  13. // @grant GM_download
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. 'use strict';
  18.  
  19. const urlKey = 'koharuUrls';
  20. const continueKey = 'continue_treatment';
  21. const artistsLibKey = 'artists_lib';
  22. let urlList = GM_getValue(urlKey, []);
  23. let continueTreatment = GM_getValue(continueKey, false);
  24. let artistsLib = GM_getValue(artistsLibKey, []);
  25.  
  26. // Function to process the current page and store English articles
  27. function processPage() {
  28. const articles = document.querySelectorAll('article');
  29. articles.forEach(article => {
  30. const isEnglish = article.querySelector('a > header > h3 > span > svg[id="flag-icons-gb"]');
  31. if (isEnglish) {
  32. const articleUrl = article.querySelector('a').href;
  33. if (!urlList.includes(articleUrl)) {
  34. urlList.push(articleUrl);
  35. }
  36. }
  37. });
  38.  
  39. // Save the updated URL list
  40. GM_setValue(urlKey, urlList);
  41. }
  42.  
  43. // Function to navigate to the next page
  44. function goToNextPage() {
  45. const paginationList = document.querySelector('footer nav.pagination ul');
  46. if (paginationList) {
  47. const paginationItems = paginationList.children;
  48. const lastItem = paginationItems[paginationItems.length - 1]; // On prend le dernier élément de la liste
  49.  
  50. const nextPageLink = lastItem.querySelector('a');
  51. if (nextPageLink) {
  52. const currentPageNumber = parseInt(new URL(window.location.href).searchParams.get('page') || '1', 10);
  53. const nextPageNumber = parseInt(new URL(nextPageLink.href).searchParams.get('page'), 10);
  54.  
  55. if (nextPageNumber === currentPageNumber + 1) {
  56. console.log(currentPageNumber, "->", nextPageNumber);
  57. GM_setValue(continueKey, true);
  58. window.location.href = nextPageLink.href;
  59. } else {
  60. console.log("end of treatment 1");
  61. saveArtistData();
  62. GM_setValue(continueKey, false); // Pas de page suivante
  63. }
  64. } else {
  65. saveArtistData();
  66. GM_setValue(continueKey, false); // Pas de lien pour la page suivante
  67. }
  68. }
  69. else
  70. {
  71. console.log("end of treatment 2");
  72. saveArtistData();
  73. GM_setValue(continueKey, false); // Pas de page suivante
  74. }
  75. }
  76.  
  77. function treatArtist() {
  78. // If there is no pagination list, check if the URL contains "&page"
  79. const urlParams = new URLSearchParams(window.location.search);
  80. if (urlParams.has('page')) {
  81. showPopup("please go to page one to treat artist");
  82. } else {
  83. console.log("beginning of the treatment");
  84. processPage();
  85. goToNextPage();
  86. }
  87. }
  88.  
  89.  
  90. function getArtistName() {
  91. const urlParams = new URLSearchParams(window.location.search);
  92. let artistName = null;
  93.  
  94. // Check for 's' parameter
  95. if (urlParams.has('s')) {
  96. const searchQuery = decodeURIComponent(urlParams.get('s'));
  97. console.log(searchQuery);
  98. // Extract the artist or circle name from the search query
  99. const match = searchQuery.match(/(artist|circle):(?:"(.+)"|\^(.+)\$)/);
  100. console.log(match);
  101. if (match && (match[2] || match[3])) {
  102. artistName = match[2] || match[3];
  103. // Remove caret and dollar sign characters from the artist name
  104. artistName = artistName.replace(/[\^$]/g, '');
  105. }
  106. }
  107.  
  108. return artistName;
  109. }
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117. function showPopup(message) {
  118. const popup = document.createElement('div');
  119. popup.id = 'popup';
  120. popup.style.position = 'fixed';
  121. popup.style.top = '50%';
  122. popup.style.left = '50%';
  123. popup.style.transform = 'translate(-50%, -50%)';
  124. popup.style.backgroundColor = '#f1f1f1';
  125. popup.style.padding = '20px';
  126. popup.style.border = '1px solid #ccc';
  127. popup.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)';
  128. popup.style.zIndex = '1001';
  129. popup.style.textAlign = 'center';
  130. popup.style.opacity = '0';
  131. popup.style.transition = 'opacity 0.3s ease-in-out';
  132. popup.textContent = message;
  133.  
  134. document.body.appendChild(popup);
  135.  
  136. // Fade in the popup
  137. setTimeout(() => {
  138. popup.style.opacity = '1';
  139. }, 10);
  140.  
  141. // Fade out and remove the popup after 5 seconds
  142. setTimeout(() => {
  143. popup.style.opacity = '0';
  144. setTimeout(() => {
  145. document.body.removeChild(popup);
  146. }, 300);
  147. }, 5000);
  148. }
  149.  
  150.  
  151.  
  152. // Function to save the current artist's data
  153. function saveArtistData() {
  154. const artistName = getArtistName();
  155. console.log(artistName);
  156. if (artistName && urlList.length > 0) {
  157. const artistData = {
  158. artist: artistName,
  159. lst_dl: urlList
  160. };
  161.  
  162. artistsLib = GM_getValue(artistsLibKey, []);
  163. // Add the artist data to the artistsLib
  164. artistsLib.push(artistData);
  165.  
  166. // Save the updated artistsLib
  167. GM_setValue(artistsLibKey, artistsLib);
  168.  
  169. // Clear the URL list for the next artist
  170. GM_setValue(urlKey, []);
  171. urlList = [];
  172.  
  173. showPopup(`Artist ${artistName} has been processed.`);
  174.  
  175. clearButton.disabled = false;
  176.  
  177. }
  178. }
  179.  
  180. // Function to handle automatic processing if continue_treatment is true
  181. function handleAutoProcessing() {
  182. console.log(continueTreatment);
  183. if (continueTreatment) {
  184. processPage();
  185. goToNextPage();
  186. }
  187. }
  188.  
  189. // Function to download the artists_lib as a JSON file
  190. function downloadArtistsLib() {
  191. const artistsLibData = GM_getValue(artistsLibKey, []);
  192. const jsonContent = JSON.stringify(artistsLibData, null, 2); // Pretty print JSON with indentation
  193. const blob = new Blob([jsonContent], { type: 'application/json' });
  194. const url = URL.createObjectURL(blob);
  195.  
  196. const a = document.createElement('a');
  197. a.href = url;
  198. a.download = 'artists_lib.json';
  199. a.click();
  200.  
  201. URL.revokeObjectURL(url); // Clean up the URL object
  202. }
  203.  
  204. // Create a container for the buttons
  205. const buttonContainer = document.createElement('div');
  206. buttonContainer.style.position = 'sticky';
  207. buttonContainer.style.top = '0';
  208. buttonContainer.style.backgroundColor = '#f1f1f1';
  209. buttonContainer.style.padding = '10px';
  210. buttonContainer.style.zIndex = 1000;
  211. buttonContainer.style.display = 'flex';
  212. buttonContainer.style.justifyContent = 'center';
  213. buttonContainer.style.alignItems = 'center';
  214. document.body.prepend(buttonContainer);
  215.  
  216. // Create a button to process the artist's pages
  217. const processButton = document.createElement('button');
  218. processButton.textContent = 'Traiter l\'artiste';
  219. processButton.style.margin = '0 10px';
  220. processButton.style.padding = '10px';
  221. processButton.style.backgroundColor = '#4CAF50';
  222. processButton.style.color = 'white';
  223. processButton.style.border = 'none';
  224. processButton.style.cursor = 'pointer';
  225. processButton.onclick = () => {
  226. GM_setValue(continueKey, true);
  227. treatArtist();
  228. };
  229. buttonContainer.appendChild(processButton);
  230.  
  231. // Create a button to clear the list and artists_lib
  232. const clearButton = document.createElement('button');
  233. clearButton.textContent = 'Clear list';
  234. clearButton.style.margin = '0 10px';
  235. clearButton.style.padding = '10px';
  236. clearButton.style.backgroundColor = '#f44336';
  237. clearButton.style.color = 'white';
  238. clearButton.style.border = 'none';
  239. clearButton.style.cursor = 'pointer';
  240. clearButton.disabled = artistsLib.length === 0;
  241. clearButton.onclick = () => {
  242. if (confirm('Do you really want to clear the list ?')) {
  243. GM_deleteValue(urlKey);
  244. GM_deleteValue(artistsLibKey);
  245. urlList = [];
  246. artistsLib = [];
  247. clearButton.disabled = true;
  248. showPopup("list cleared");
  249. }
  250. };
  251. buttonContainer.appendChild(clearButton);
  252.  
  253. // Create a button to download the artists_lib JSON
  254. const downloadButton = document.createElement('button');
  255. downloadButton.textContent = 'Download the list';
  256. downloadButton.style.margin = '0 10px';
  257. downloadButton.style.padding = '10px';
  258. downloadButton.style.backgroundColor = '#2196F3';
  259. downloadButton.style.color = 'white';
  260. downloadButton.style.border = 'none';
  261. downloadButton.style.cursor = 'pointer';
  262. downloadButton.onclick = downloadArtistsLib;
  263. buttonContainer.appendChild(downloadButton);
  264.  
  265. // Enable the clear button if the list contains elements
  266. if (artistsLib.length > 0) {
  267. clearButton.disabled = false;
  268. }
  269.  
  270. // Wait for DOM to fully load before executing handleAutoProcessing
  271. window.onload = () => {
  272. handleAutoProcessing();
  273. };
  274.  
  275. })();