e621 Page Result Grabber

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

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==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;
        }
    `);
})();