Pixiv Auto Expand Multiple Images

Auto Expand Pixiv multiple images without clicking. Works for both illustrations and manga.

// ==UserScript==
// @name         Pixiv Auto Expand Multiple Images
// @namespace    http://tampermonkey.net/
// @version      1.6
// @description  Auto Expand Pixiv multiple images without clicking. Works for both illustrations and manga.
// @author       CHATGPT + GEMINI - jarsang010
// @license      None
// @match        https://www.pixiv.net/en/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function () {
    'use strict';

    let hasClickedExpandButtonThisPage = false; // Tracks if we've clicked the expand button for the current artwork
    let isMangaViewerCurrentlyActive = false; // Tracks if the manga viewer modal is open
    let currentArtworkId = null;

    // Function to click the "Show all" or "Start reading" button
    function tryClickExpandButton() {
        // Only proceed if the current URL is an artwork page
        if (!window.location.pathname.startsWith('/en/artworks/')) {
            console.log("[PixivScript] Not on an artwork page. Skipping click attempts.");
            return false;
        }

        if (hasClickedExpandButtonThisPage || isMangaViewerCurrentlyActive) {
            console.log("[PixivScript] Already clicked expand button for this page or manga viewer active - skipping click attempt.");
            return false;
        }

        console.log("[PixivScript] Checking for expand buttons...");
        const buttons = Array.from(document.querySelectorAll("button, a"));

        for (const btn of buttons) {
            const text = btn.textContent.trim();
            if (text === "Show all" || text === "Reading works" || text === "Start reading") {
                console.log(`[PixivScript] Clicking "${text}"`);
                btn.click();
                hasClickedExpandButtonThisPage = true; // Mark that we've clicked it for this page
                return true;
            }
        }
        return false;
    }

    // Observer to detect when the manga viewer is opened or closed
    const viewerObserver = new MutationObserver(function (mutations) {
        const viewerModal = document.querySelector(".sc-fgvYmX.hCqDkB, ._viewer, ._modal.ui-modal");

        if (viewerModal && !isMangaViewerCurrentlyActive) {
            console.log("[PixivScript] Manga viewer modal detected as opened.");
            isMangaViewerCurrentlyActive = true;
            hasClickedExpandButtonThisPage = true;
        } else if (!viewerModal && isMangaViewerCurrentlyActive) {
            console.log("[PixivScript] Manga viewer modal detected as closed.");
            isMangaViewerCurrentlyActive = false;
        }
    });

    // Start observing the body for changes that indicate viewer state
    setTimeout(() => {
        viewerObserver.observe(document.body, { childList: true, subtree: true });
        console.log("[PixivScript] Viewer observer started.");
    }, 500);

    // Function to handle initial clicks and clicks on URL change
    function activateAutoClick() {
        let attempts = 0;
        const maxAttempts = 20; // Try for up to 10 seconds (20 * 500ms)
        const clickInterval = setInterval(() => {
            if (hasClickedExpandButtonThisPage || isMangaViewerCurrentlyActive || attempts >= maxAttempts) {
                clearInterval(clickInterval);
                if (attempts >= maxAttempts && !hasClickedExpandButtonThisPage && !isMangaViewerCurrentlyActive) {
                    console.log("[PixivScript] Max click attempts reached, no expand button found or viewer active.");
                }
                return;
            }
            attempts++;
            console.log(`[PixivScript] Click attempt ${attempts}...`);
            tryClickExpandButton();
        }, 500);
    }

    // Reset state and activate auto-click when URL changes (user navigates to a new artwork)
    function handleUrlChange() {
        const newArtworkIdMatch = window.location.pathname.match(/\/artworks\/(\d+)/);
        const newArtworkId = newArtworkIdMatch ? newArtworkIdMatch[1] : null;

        if (newArtworkId && newArtworkId !== currentArtworkId) {
            console.log(`[PixivScript] Navigated to new artwork (ID: ${newArtworkId}). Resetting state.`);
            currentArtworkId = newArtworkId;
            hasClickedExpandButtonThisPage = false;
            isMangaViewerCurrentlyActive = false;
            setTimeout(activateAutoClick, 800);
        } else if (!newArtworkId) {
            currentArtworkId = null;
            hasClickedExpandButtonThisPage = false;
            isMangaViewerCurrentlyActive = false;
            console.log("[PixivScript] Navigated away from artwork page. State reset.");
        } else {
            console.log("[PixivScript] URL change detected, but it's the same artwork ID. No full reset.");
        }
    }

    // Hook browser history API to detect URL changes within Pixiv's SPA
    function hookHistory(fn) {
        return function () {
            const ret = fn.apply(this, arguments);
            window.dispatchEvent(new Event("customurlchange"));
            return ret;
        };
    }
    history.pushState = hookHistory(history.pushState);
    history.replaceState = hookHistory(history.replaceState);
    window.addEventListener("popstate", () => window.dispatchEvent(new Event("customurlchange")));
    window.addEventListener("customurlchange", handleUrlChange);

    // Initial run when the script loads
    console.log("[PixivScript] Initializing...");
    handleUrlChange();
    activateAutoClick();

})();