Koharu Artist URL Collector

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

Versión del día 9/2/2025. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Koharu Artist URL Collector
// @namespace    https://koharu.to/
// @version      1.7.2.0
// @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

    // 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;
        if (continueTreatment) {
            processPage();
            goToNextPage();
        }
        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;
    }

    // Use DOMContentLoaded to ensure the DOM is fully loaded
    document.addEventListener('DOMContentLoaded', () => {
        console.log('DOM fully loaded and parsed');
        handleAutoProcessing();
    });

})();