您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sleazy Fork is available in English.
Collect URLs from koharu.to artist pages and store them in GM_storage
// ==UserScript== // @name Koharu Artist URL Collector // @namespace https://koharu.to/ // @version 1.7.2.1 // @description Collect URLs from koharu.to artist pages and store them in GM_storage // @license MIT // @author viatana35 // @match https://hoshino.one/tag/artist:* // @match https://hoshino.one/tag/circle:* // @match https://shupogaki.moe/tag/artist:* // @match https://shupogaki.moe/tag/circle:* // @match https://niyaniya.moe/tag/artist:* // @match https://niyaniya.moe/tag/circle:* // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_download // ==/UserScript== (function () { 'use strict'; const urlKey = 'koharuUrls'; const continueKey = 'continue_treatment'; const artistsLibKey = 'artists_lib'; let urlList = GM_getValue(urlKey, []); let continueTreatment = GM_getValue(continueKey, false); let artistsLib = GM_getValue(artistsLibKey, []); let isProcessing = false; // Flag to prevent infinite loop let lastProcessedUrl = ''; // Function to process the current page and store English articles function processPage() { const articles = document.querySelectorAll('article'); articles.forEach(article => { //const isEnglish = article.querySelector('a > header > h3 > span > svg[id="flag-icons-gb"]'); const isEnglish = article.querySelector('a > div > main > div > div > svg[id="flag-icons-gb"]'); if (isEnglish) { const articleUrl = article.querySelector('a').href; if (!urlList.includes(articleUrl)) { urlList.push(articleUrl); } } }); GM_setValue(urlKey, urlList); } // Function to navigate to the next page function goToNextPage() { const paginationList = document.querySelector('footer > nav > ul'); if (paginationList) { const paginationItems = paginationList.children; const lastItem = paginationItems[paginationItems.length - 1]; // On prend le dernier élément de la liste const nextPageLink = lastItem.querySelector('a'); if (nextPageLink) { const currentPageNumber = parseInt(new URL(window.location.href).searchParams.get('page') || '1', 10); const nextPageNumber = parseInt(new URL(nextPageLink.href).searchParams.get('page'), 10); if (nextPageNumber === currentPageNumber + 1) { console.log(currentPageNumber, "->", nextPageNumber); GM_setValue(continueKey, true); window.location.href = nextPageLink.href; } else { console.log("end of treatment 1"); saveArtistData(); GM_setValue(continueKey, false); // Pas de page suivante } } else { saveArtistData(); GM_setValue(continueKey, false); // Pas de lien pour la page suivante } } else { console.log("end of treatment 2"); saveArtistData(); GM_setValue(continueKey, false); // Pas de page suivante } } function treatArtist() { // If there is no pagination list, check if the URL contains "&page" const urlParams = new URLSearchParams(window.location.search); if (urlParams.has('page')) { showPopup("please go to page one to treat artist"); } else { console.log("beginning of the treatment"); processPage(); goToNextPage(); } } function getArtistName() { let artistName = null; // Get the pathname from the window location const pathname = window.location.pathname; // Check if the pathname starts with '/tag/' if (pathname.startsWith('/tag/')) { // Extract the part after '/tag/' const tagPart = pathname.substring('/tag/'.length); // Check if the tag part starts with 'artist:' or 'circle:' if (tagPart.startsWith('artist:') || tagPart.startsWith('circle:')) { // Extract the artist or circle name artistName = tagPart.split(':')[1]; // Remove caret and dollar sign characters from the artist name artistName = artistName.replace(/[\^$]/g, ''); } } return artistName; } function showPopup(message) { const popup = document.createElement('div'); popup.id = 'popup'; popup.style.position = 'fixed'; popup.style.top = '50%'; popup.style.left = '50%'; popup.style.transform = 'translate(-50%, -50%)'; popup.style.backgroundColor = '#f1f1f1'; popup.style.padding = '20px'; popup.style.border = '1px solid #ccc'; popup.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)'; popup.style.zIndex = '1001'; popup.style.textAlign = 'center'; popup.style.color = 'black'; // Set text color to black popup.style.opacity = '0'; popup.style.transition = 'opacity 0.3s ease-in-out'; popup.textContent = message; document.body.appendChild(popup); // Fade in the popup setTimeout(() => { popup.style.opacity = '1'; }, 10); // Fade out and remove the popup after 5 seconds setTimeout(() => { popup.style.opacity = '0'; setTimeout(() => { document.body.removeChild(popup); }, 300); }, 5000); } // Function to save the current artist's data function saveArtistData() { const artistName = getArtistName(); if (artistName && urlList.length > 0) { const artistData = { artist: artistName, lst_dl: urlList }; artistsLib = GM_getValue(artistsLibKey, []); // Add the artist data to the artistsLib artistsLib.push(artistData); // Save the updated artistsLib GM_setValue(artistsLibKey, artistsLib); // Clear the URL list for the next artist GM_setValue(urlKey, []); urlList = []; showPopup(`Artist ${artistName} has been processed.`); clearButton.disabled = false; } } // Function to handle automatic processing if continue_treatment is true function handleAutoProcessing() { if (isProcessing) return; // Prevent multiple processing isProcessing = true; const currentUrl = window.location.href; if (currentUrl !== lastProcessedUrl && continueTreatment) { lastProcessedUrl = currentUrl; processPage(); goToNextPage(); } else { isProcessing = false; return; } isProcessing = false; } // Function to download the artists_lib as a JSON file function downloadArtistsLib() { const artistsLibData = GM_getValue(artistsLibKey, []); const jsonContent = JSON.stringify(artistsLibData, null, 2); // Pretty print JSON with indentation const blob = new Blob([jsonContent], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'artists_lib.json'; a.click(); URL.revokeObjectURL(url); // Clean up the URL object } function clearList() { if (confirm('Do you really want to clear the list ?')) { GM_deleteValue(urlKey); GM_deleteValue(artistsLibKey); urlList = []; artistsLib = []; clearButton.disabled = true; showPopup("list cleared"); } } // Create a container for the buttons const buttonContainer = document.createElement('div'); buttonContainer.style.position = 'sticky'; buttonContainer.style.top = '0'; buttonContainer.style.backgroundColor = '#f1f1f1'; buttonContainer.style.padding = '10px'; buttonContainer.style.zIndex = 1000; buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'center'; buttonContainer.style.alignItems = 'center'; document.body.prepend(buttonContainer); // Create a button to process the artist's pages const processButton = document.createElement('button'); processButton.textContent = 'Treat artist'; processButton.style.margin = '0 10px'; processButton.style.padding = '10px'; processButton.style.backgroundColor = '#4CAF50'; processButton.style.color = 'white'; processButton.style.border = 'none'; processButton.style.cursor = 'pointer'; processButton.onclick = () => { GM_setValue(continueKey, true); treatArtist(); }; buttonContainer.appendChild(processButton); // Create a button to clear the list and artists_lib const clearButton = document.createElement('button'); clearButton.textContent = 'Clear list'; clearButton.style.margin = '0 10px'; clearButton.style.padding = '10px'; clearButton.style.backgroundColor = '#f44336'; clearButton.style.color = 'white'; clearButton.style.border = 'none'; clearButton.style.cursor = 'pointer'; clearButton.disabled = artistsLib.length === 0; clearButton.onclick = clearList; buttonContainer.appendChild(clearButton); // Create a button to download the artists_lib JSON const downloadButton = document.createElement('button'); downloadButton.textContent = 'Download the list'; downloadButton.style.margin = '0 10px'; downloadButton.style.padding = '10px'; downloadButton.style.backgroundColor = '#2196F3'; downloadButton.style.color = 'white'; downloadButton.style.border = 'none'; downloadButton.style.cursor = 'pointer'; downloadButton.onclick = downloadArtistsLib; buttonContainer.appendChild(downloadButton); // Enable the clear button if the list contains elements if (artistsLib.length > 0) { clearButton.disabled = false; } // Observe the second div inside the body, which contains the section that gets replaced const targetDiv = document.querySelector('body > div:nth-of-type(2)'); if (targetDiv) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { console.log('DOM changed'); handleAutoProcessing(); } }); }); observer.observe(targetDiv, { childList: true, subtree: true }); } // Initial processing document.addEventListener('DOMContentLoaded', () => { console.log('DOM fully loaded and parsed'); handleAutoProcessing(); }); })();