e621 Page Result Grabber

Adds buttons below the tag searchbar to copy queries for the page result post ID's to the clipboard.

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name         e621 Page Result Grabber
// @namespace    https://greasyfork.org/users/1582013
// @version      1.03
// @description  Adds buttons below the tag searchbar to copy queries for the page result post ID's to the clipboard.
// @author       FreekyCreep
// @license      GNU GPLv3
// @match        https://e621.net/posts?*
// @match        https://e926.net/posts?*
// @grant        GM_addStyle
// ==/UserScript==
(function () {
    "use strict";
    //site elements
    const TAGS = document.getElementById("tags");
    const SEARCH_CONTROLS = document.querySelector(".search-controls");
    const THUMBNAILS = document.querySelectorAll(".posts-container > .thumbnail");

    //queries
    const tagLimit = 40;
    const queryCount = Math.ceil(THUMBNAILS.length / tagLimit);
    const queries = new Array(queryCount).fill("");

    //functions
    function buttonClickHandler(e) {
        let button = e.target;
        let queryIndex = Number(button.dataset.index);
        button.disabled = true;
        if (!queries[queryIndex]) {
            const start = queryIndex * tagLimit;
            const end = (queryIndex + 1 === queryCount) ? THUMBNAILS.length : start + tagLimit;
            for (let i = start; i < end; i++) queries[queryIndex] += "~id:" + THUMBNAILS[i].dataset.id + " ";
        }
        navigator.clipboard.writeText(queries[queryIndex])
            .then(() => {
                button.classList.add("active");
                button.textContent = getRandomRjSmiley();
            }).catch(err =>
                console.error("Failed to copy query:", err)
            );
        setTimeout(() => {
            button.disabled = false;
            button.classList.remove("active");
            button.textContent = buttonText + (queryIndex + 1);
        }, 1500);
    }
    function thumbnailClickHandler(e) {
        if (!e.ctrlKey || !e.shiftKey || e.button || e.target === e.currentTarget || e.target.tagName === "HR") return;
        e.preventDefault();
        let target = e.target;
        while (target.parentNode !== e.currentTarget) target = target.parentNode;
        TAGS.value += " -id:" + target.dataset.id;
        const scrollY = window.scrollY;
        TAGS.style.height = 0;
        TAGS.style.height = TAGS.scrollHeight + "px";
        window.scrollBy(0, scrollY - window.scrollY);
    }
    function getRandomRjSmiley() {
        if (Math.random() < 0.000001) return "(':}',"; //signal for help (1/1,000,000, 0.0001%)
        let smiley = "";
        smiley += (Math.random() < 0.01) ? "'," : ",'"; //ears (1% chance to be reversed)
        smiley += (Math.random() < 0.05) ? "}" : "{"; //face pattern (5% chance to be devil horns)
        smiley += (Math.random() < 0.05) ? ">" : ""; //eyebrows (5% chance to add anger brows)
        switch (Math.random() * 10 | 0) { //eyes
            default: //0,1,2
                smiley += ":"; //30%
                break;
            case 3:
            case 4:
                smiley += ";"; //20%
                break;
            case 5:
            case 6:
                smiley += "B"; //20%
                break;
            case 7:
            case 8:
                smiley += "x"; //20%
                break;
            case 9:
                smiley += "="; //10%
                break;
        }
        smiley += (Math.random() < 0.001) ? "*" : "'"; //nose (0.1% chance to be star)
        switch (Math.random() * 10 | 0) { //mouth
            default: //0,1
                smiley += "D"; //20%
                break;
            case 2:
            case 3:
                smiley += "3"; //20%
                break;
            case 4:
                smiley += "))"; //10%
                break;
            case 5:
                smiley += "]"; //10%
                break;
            case 6:
                smiley += "P"; //10%
                break;
            case 7:
                smiley += "o"; //10%
                break;
            case 8:
                smiley += "v"; //10%
                break;
            case 9:
                smiley += "|"; //10%
                break;
        }
        smiley += (Math.random() < 0.05) ? "c" : ""; //chin paw (5% chance)
        return smiley;
    }

    //DOM+events
    const buttonText = (queryCount < 4) ? ",'{:') " : "";
    for (let i = 0; i < queryCount; i++) {
        let button = document.createElement("button");
        button.className = "st-button freeky-button";
        button.textContent = buttonText + (i + 1);
        button.title = "Copy query " + (i + 1);
        button.dataset.index = i;
        button.addEventListener("click", buttonClickHandler);
        SEARCH_CONTROLS.append(button);
    }
    for (let i = tagLimit; i < THUMBNAILS.length; i += tagLimit) THUMBNAILS[i].before(document.createElement("hr"));
    document.querySelector(".posts-container").addEventListener("click", thumbnailClickHandler);

    //styles
    GM_addStyle(`
        .freeky-button {
            height: auto;
            width: auto;
            padding: 0 0 2px 0 !important;
            display: flex;
            justify-content: center;
            align-items: center;
            min-width: 34px;
            font-size: 13.6px;
            letter-spacing: -1px;
            line-height: 0;
        }
        .posts-container > hr {
            grid-column: 1 / -1;
            margin: 12px;
            border-style: dashed;
        }
        body[data-st-fullscreen='true'] .posts-index-stats {
            margin-right: ${43 * queryCount + 120}px !important;
        }
    `);
    if (queryCount < 4) return;
    GM_addStyle(`
        body[data-st-fullscreen='false'] .search-controls {
            gap: ${8 - queryCount}px !important;
        }
        body[data-st-fullscreen='false'] .freeky-button {
            min-width: ${48 - 4 * queryCount}px !important;
        }
    `);
})();