Pixiv Ajax Bookmark Mod

Automatically adds artwork tags when you bookmark. ブックマークのタグを自動的につける。

Verzia zo dňa 30.01.2022. Pozri najnovšiu verziu.

// ==UserScript==
// @name             Pixiv Ajax Bookmark Mod
// @namespace        com.SaddestPanda.net.moe
// @version          2.7.2
// @description      Automatically adds artwork tags when you bookmark. ブックマークのタグを自動的につける。 
// @include          /^https?:\/\/www.pixiv.net\/.*/
// @homepage         https://greasyfork.dpdns.org/en/scripts/22767-pixiv-ajax-bookmark-mod
// @supportURL       https://greasyfork.dpdns.org/en/scripts/22767-pixiv-ajax-bookmark-mod/feedback
// @author           qa2 & SaddestPanda
// @require          https://cdn.jsdelivr.net/npm/[email protected]/dist/GM_webextPref.user.js
// @require          https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @grant            GM.getValue
// @grant            GM.setValue
// @grant            GM.deleteValue
// @grant            GM_addValueChangeListener
// @grant            GM.registerMenuCommand
// @run-at           document-idle
// @noframes
// ==/UserScript==

var tags = "",
    currLocation = "",
    theToken = "",
    restartCheckerInterval = null,
    startingSoonInterval = null;

/* 
    ❗ You don't have to touch these settings anymore. Use the new settings ui. 
    ❗ もうここの設定を手動で変更する必要はあるません。ページ内の新しい設定UIを使用してください。
*/
const pref = GM_webextPref({
    default: {
        givelike: true,
        r18private: true,
        bkm_restrict: false,
        add_all_tags: true
    },
    body: [{
            key: "givelike",
            type: "checkbox",
            label: "Automatically give your bookmarks a like.(ブックマークした作品に自動的に「いいね!」をくれます。)"
        },
        {
            key: "add_all_tags",
            type: "checkbox",
            label: "Automatically add the work's tags as bookmark tags.(作品に登録されているすべてのタグをブックマークタグとして追加します。)"
        },
        {
            key: "r18private",
            type: "checkbox",
            label: "R-18 works are automatically added as private bookmarks.(作品はR-18であった場合、自動的に非公開としてブックマークします。)"
        },
        {
            key: "bkm_restrict",
            type: "checkbox",
            label: "❗ Always add to private bookmarks list.(常に非公開としてブックマークします。)"
        },
    ]
});

//Start running startingSoon if the page is different
function restartChecker() {
    //check for url changes
    if (document.location != currLocation) {
        //Remove the spinner if it still exists
        let spinner = document.querySelector(".pabm_spinner");
        if (spinner) {
            spinner.remove();
        }
        //Stop restart checker and go for startingSoon instead
        clearInterval(restartCheckerInterval);
        clearInterval(startingSoonInterval);
        startingSoonInterval = setInterval(startingSoon, 150);
    }
}

function startingSoon() {
    try {
        //Check if the main bookmark button exists
        if ((document.querySelectorAll(".gtm-main-bookmark").length == 1) &&
            //Also check if the current url matches /artworks/
            (document.location.toString().match(/^https?:\/\/www.pixiv.net\/.*?artworks\/.*/) != null) &&
            //Also check if we DO NOT have the hover buttons added into the page yet
            (document.querySelector("#pabmButtonsContainer") == null) &&
            //Also check if the bookmark button is enabled
            (document.querySelector(".gtm-main-bookmark").disabled == false)) {

            //Continue if everything above succeeds
            clearInterval(startingSoonInterval);
            try {
                //get the necessary token
                getthetoken();
                setTimeout(startingUp, 150);
            } catch (e) {
                console.log("Pixiv ajax bookmark mod token error: ", e);
            }

        }
    } catch (e) {
        // console.log("PABM startingSoon error: ", e);
    }
}

//Get tags, add hover buttons
function startingUp() {
    //Start restart checker
    currLocation = document.location.href;
    restartCheckerInterval = setInterval(restartChecker, 150);
    //clear tags
    tags = "";
    //get all tags
    $("footer >").children().each(function() {
        try {
            tags += decodeURIComponent($(this).find("a")[0].href).split("tags/")[1].split("/artworks")[0] + " ";
        } catch (e) {}
    });

    //cancel if tags were not found or are empty
    if (tags != "") {
        //add css
        AddMyStyle("pabmButtonsStyle", `
        #pabmButtonsContainer {
            position: absolute;
            width: 64px;
            display: flex;
            flex-direction: row;
            justify-content: space-around;
            background-color: rgba(0, 0, 0, .2);
            padding: 3px 8px 2px 8px;
            height: 25px;
            /*! border: 2px black solid; */
            border-radius: 15px;
            margin-left: -26px !important;
            margin-top: -29px;
            z-index: 555;
            filter: opacity(100%);
            /*! left: -55px; */
            display: none
        }
        
        #pabmButtonsContainer:hover,
        .gtm-main-bookmark:hover ~ #pabmButtonsContainer {
            display: flex !important
        }
        
        .pabmButtons:first-of-type {
            margin-left: 4px;
        }
        
        .pabmButtons > svg:hover {
            filter: contrast(180%);
            stroke: #fff;
            stroke-width: .15em;
            stroke-opacity: 35%
        }
        
        .pabmButtonSettings {
            margin: 3px 4px 4px 4px;
        }

        /* START spinner stuff */
        .pabm_spinner {
            -webkit-animation: spinner_rotate 2s linear infinite;
            animation: spinner_rotate 2s linear infinite;
            z-index: 2;
            position: absolute;
            margin: 8px 0 0 -46px;
            width: 22px;
            height: 22px;
          }
        
        .pabm_spinner .path {
            stroke: #42a7ce;
            stroke-linecap: round;
            -webkit-animation: spinner_dash 1.5s ease-in-out infinite;
            animation: spinner_dash 1.5s ease-in-out infinite;
        }
        
        @keyframes spinner_rotate {
            100% {
                transform: rotate(360deg);
            }
        }
        
        @keyframes spinner_dash {
            0% {
                stroke-dasharray: 1, 150;
                stroke-dashoffset: 0;
            }
        
            50% {
                stroke-dasharray: 90, 150;
                stroke-dashoffset: -35;
            }
        
            100% {
                stroke-dasharray: 90, 150;
                stroke-dashoffset: -124;
            }
        }
        /* END spinner stuff */
        
        `);

        //Set the button action
        $(".gtm-main-bookmark")[0].href = "javascript:void(0)";
        $(".gtm-main-bookmark").on("click", function() {
            bkm(-1);
            return false;
        });
        //Set the hover buttons
        var hoverButtons = document.createElement("div");
        $(".gtm-main-bookmark").after(hoverButtons);
        $(".gtm-main-bookmark")[0].nextSibling.outerHTML = `
        <div id="pabmButtonsContainer">
            <div class="pabmButtons pabmButtonPublic">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 32 32">
                    <path fill-rule="evenodd" clip-rule="evenodd" d="M21 5.5a7 7 0 017 7c0 5.77-3.703 10.652-10.78 14.61a2.5 2.5 0 01-2.44 0C7.703 23.152 4 18.27 4 12.5a7 7 0 017-7c1.83 0 3.621.914 5 2.328C17.379 6.414 19.17 5.5 21 5.5z" fill="#FF4060"></path>
                </svg>
            </div>
            <div class="pabmButtons pabmButtonPrivate">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 32 32">
                    <path fill-rule="evenodd" clip-rule="evenodd" d="M21 5.5a7 7 0 017 7c0 5.77-3.703 10.652-10.78 14.61a2.5 2.5 0 01-2.44 0C7.703 23.152 4 18.27 4 12.5a7 7 0 017-7c1.83 0 3.621.914 5 2.328C17.379 6.414 19.17 5.5 21 5.5z" fill="#FF4060"></path>
                    <path fill-rule="evenodd" clip-rule="evenodd" d="M29.98 20.523A3.998 3.998 0 0132 24v4a4 4 0 01-4 4h-7a4 4 0 01-4-4v-4c0-1.489.814-2.788 2.02-3.477a5.5 5.5 0 0110.96 0z" fill="#fff"></path>
                    <path fill-rule="evenodd" clip-rule="evenodd" d="M28 22a2 2 0 012 2v4a2 2 0 01-2 2h-7a2 2 0 01-2-2v-4a2 2 0 012-2v-1a3.5 3.5 0 117 0v1zm-5-1a1.5 1.5 0 013 0v1h-3v-1z" fill="#1F1F1F"></path>
                </svg>
            </div>
            <div class="pabmButtons pabmButtonSettings">
                <svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
                    <path fill="#444" d="M16 9v-2l-1.7-0.6c-0.2-0.6-0.4-1.2-0.7-1.8l0.8-1.6-1.4-1.4-1.6 0.8c-0.5-0.3-1.1-0.6-1.8-0.7l-0.6-1.7h-2l-0.6 1.7c-0.6 0.2-1.2 0.4-1.7 0.7l-1.6-0.8-1.5 1.5 0.8 1.6c-0.3 0.5-0.5 1.1-0.7 1.7l-1.7 0.6v2l1.7 0.6c0.2 0.6 0.4 1.2 0.7 1.8l-0.8 1.6 1.4 1.4 1.6-0.8c0.5 0.3 1.1 0.6 1.8 0.7l0.6 1.7h2l0.6-1.7c0.6-0.2 1.2-0.4 1.8-0.7l1.6 0.8 1.4-1.4-0.8-1.6c0.3-0.5 0.6-1.1 0.7-1.8l1.7-0.6zM8 12c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z" />
                    <path fill="#444" d="M10.6 7.9c0 1.381-1.119 2.5-2.5 2.5s-2.5-1.119-2.5-2.5c0-1.381 1.119-2.5 2.5-2.5s2.5 1.119 2.5 2.5z" />
                </svg>
            </div>
        </div>
        `;
        $(".pabmButtonPublic").on("click", function() {
            bkm(0);
            return false;
        });
        $(".pabmButtonPrivate").on("click", function() {
            bkm(1);
            return false;
        });
        $(".pabmButtonSettings").on("click", function() {
            pref.openDialog();
            return false;
        });
    } else {
        return;
    }
}

function getthetoken() {
    var userid_first = null;
    //find user id
    if (dataLayer.length > 0) {
        userid_first = dataLayer[0].user_id.toString();
    } else if (_gaq.length > 0) {
        _gaq.forEach((item) => {
            if (item[2] == "user_id") {
                userid_first = item[3].toString();
            }
        });
    } else {
        document.querySelectorAll("script").forEach((node) => {
            if (node.innerHTML.indexOf("dataLayer = ") != -1) {
                //could also use eval() as well
                userid_first = node.innerHTML.match(/user_id:.*?"(\w*?)\"/)[1].toString();
            }
        });
    }
    var gettingCookie = getCookie(userid_first + "pixivajaxbm");
    if (gettingCookie != "") {
        theToken = gettingCookie;
    }
    if (theToken == "") {
        var illustid = $("link[rel=canonical]")[0].href.split("artworks/")[1];
        $.ajax({
            url: "https://www.pixiv.net/bookmark_add.php?type=illust&illust_id=" + illustid,
            type: 'GET',
            tryCount: 0,
            retryLimit: 2,
            success: function(sss) {
                //do something
                theToken = $(sss).find("form")[1].children[1].value;

                //add it to cookies (15 mins and userid)
                var expires = (new Date(Date.now() + 900 * 1000)).toUTCString();
                document.cookie = userid_first + "pixivajaxbm=" + theToken + "; expires=" + expires + ";path=/;";
            },
            error: function(xhr, textStatus, errorThrown) {
                this.tryCount++;
                if (this.tryCount <= this.retryLimit) {
                    //try again
                    $.ajax(this);
                    return;
                }
                return;
                /*
                if (textStatus == 'timeout') {

                }
                if (xhr.status == 500) {
                    //handle error
                } else {
                    //handle error
                }
                */
            }
        });
    }
}

// ajaxでブックマークする関数
/**
 * asPrivate values: value < 0 means auto detect
 *                   value == 1 means always private 
 *                   value == 0 means always public
 * 
 */
function bkm(asPrivate) {
    //var illustid = $("input[name=illust_id").val();
    //var tt = $("input[name=tt]").val();
    //var type = $("input[name=type]:eq(1)").val();
    //var illustid = pixiv.context.queries.id;
    //var illustid = document.location.href.split("illust_id=")[1];
    //var illustid = Object.keys(globalInitData.preload.illust)[0];

    var illustid = $("link[rel=canonical]")[0].href.split("artworks/")[1];
    var url = "https://www.pixiv.net/bookmark_add.php?id=" + illustid; //https://www.pixiv.net/bookmark_add.php?rest=show&type=illust&p=1&illust_id=70318176
    var tt = theToken;

    if (!pref.get("add_all_tags")) {
        //don't add the tags
        tags = "";
    }
    //var illusttype = "illust";

    //Get bkm_restrict as number (As we use it in the post request)
    let restrict_value = Number(pref.get("bkm_restrict"));
    if (asPrivate >= 0) {
        restrict_value = asPrivate;
    } else {
        //Auto-detect privacy
        try {
            if ($("footer >")[0].firstChild.innerText == "R-18" && pref.get("r18private")) {
                restrict_value = 1;
            }
        } catch (e) {}
    }

    let like = pref.get("givelike");
    if (like) {
        let likeButton = $(".gtm-main-bookmark").parent()[0].nextSibling.children[0];
        //basic spinner from https://codepen.io/supah/pen/BjYLdW
        if (likeButton && likeButton.disabled == false) {
            $(likeButton).after(`<svg class="pabm_spinner" viewBox="0 0 50 50">
                <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="10"></circle>
            </svg>`);
            //^^insertadjacenthtml doesnt work
            likeButton.click();
            //wait for the like button to be disabled and
            let spinnerInterval = setInterval(() => {
                if (likeButton.disabled) {
                    clearInterval(spinnerInterval);
                    //Remove spinner
                    let spinner = $(".pabm_spinner");
                    if (spinner) {
                        spinner.remove();
                    }
                }
            }, 100);
        }
    }

    $.ajax({
        url: url,
        type: 'POST',
        dataType: 'json',
        data: {
            mode: "add",
            tt: tt,
            id: illustid,
            from_sid: "",
            type: "illust",
            comment: "",
            tag: tags,
            restrict: restrict_value,
            success: function() {
                if (restrict_value) {
                    //INSERT THE LOCKED HEART (PRIVATE BOOKMARK) SVG        https://yoksel.github.io/url-encoder/
                    $(".gtm-main-bookmark svg")[0].outerHTML = decodeURIComponent("%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='32' height='32' class='j89e3c-1 kcOjCr' style='color: rgb(255, 64, 96);'%3E%3Cdefs%3E%3Cmask id='uid-mask-2'%3E%3Crect x='0' y='0' width='32' height='32' fill='white'%3E%3C/rect%3E%3Cpath d='M16,11.3317089 C15.0857201,9.28334665 13.0491506,7.5 11,7.5%0AC8.23857625,7.5 6,9.73857647 6,12.5 C6,17.4386065 9.2519779,21.7268174 15.7559337,25.3646328%0AC15.9076021,25.4494645 16.092439,25.4494644 16.2441073,25.3646326 C22.7480325,21.7268037 26,17.4385986 26,12.5%0AC26,9.73857625 23.7614237,7.5 21,7.5 C18.9508494,7.5 16.9142799,9.28334665 16,11.3317089 Z' class='j89e3c-0 kBfARi'%3E%3C/path%3E%3C/mask%3E%3C/defs%3E%3Cg mask='url(%23uid-mask-2)'%3E%3Cpath d='%0AM21,5.5 C24.8659932,5.5 28,8.63400675 28,12.5 C28,18.2694439 24.2975093,23.1517313 17.2206059,27.1100183%0AC16.4622493,27.5342993 15.5379984,27.5343235 14.779626,27.110148 C7.70250208,23.1517462 4,18.2694529 4,12.5%0AC4,8.63400691 7.13400681,5.5 11,5.5 C12.829814,5.5 14.6210123,6.4144028 16,7.8282366%0AC17.3789877,6.4144028 19.170186,5.5 21,5.5 Z'%3E%3C/path%3E%3Cpath d='M16,11.3317089 C15.0857201,9.28334665 13.0491506,7.5 11,7.5%0AC8.23857625,7.5 6,9.73857647 6,12.5 C6,17.4386065 9.2519779,21.7268174 15.7559337,25.3646328%0AC15.9076021,25.4494645 16.092439,25.4494644 16.2441073,25.3646326 C22.7480325,21.7268037 26,17.4385986 26,12.5%0AC26,9.73857625 23.7614237,7.5 21,7.5 C18.9508494,7.5 16.9142799,9.28334665 16,11.3317089 Z' class='j89e3c-0 kBfARi'%3E%3C/path%3E%3C/g%3E%3Cpath d='M29.9796 20.5234C31.1865 21.2121 32 22.511 32 24V28%0AC32 30.2091 30.2091 32 28 32H21C18.7909 32 17 30.2091 17 28V24C17 22.511 17.8135 21.2121 19.0204 20.5234%0AC19.2619 17.709 21.623 15.5 24.5 15.5C27.377 15.5 29.7381 17.709 29.9796 20.5234Z' class='j89e3c-2 jTfVcI' style='fill: rgb(255, 255, 255); fill-rule: evenodd; clip-rule: evenodd;'%3E%3C/path%3E%3Cpath d='M28 22C29.1046 22 30 22.8954 30 24V28C30 29.1046 29.1046 30 28 30H21%0AC19.8954 30 19 29.1046 19 28V24C19 22.8954 19.8954 22 21 22V21C21 19.067 22.567 17.5 24.5 17.5%0AC26.433 17.5 28 19.067 28 21V22ZM23 21C23 20.1716 23.6716 19.5 24.5 19.5C25.3284 19.5 26 20.1716 26 21V22H23%0AV21Z' class='j89e3c-3 fZVtyd' style='fill: rgb(31, 31, 31); fill-rule: evenodd; clip-rule: evenodd;'%3E%3C/path%3E%3C/svg%3E");
                } else {}
                $(".gtm-main-bookmark svg")[0].style.fill = "#ff4060";
                $(".gtm-main-bookmark svg path")[0].style.fill = "white";
                $(".gtm-main-bookmark")[0].href = "https://www.pixiv.net/bookmark_add.php?type=illust&illust_id=" + illustid;
                $(".gtm-main-bookmark").unbind("click");
                $(".gtm-main-bookmark").on("click", function(e) {
                    e.preventDefault();
                    window.location = "https://www.pixiv.net/bookmark_add.php?type=illust&illust_id=" + illustid;
                    return false;
                });
                $("#pabmButtonsContainer")[0].style.visibility = "hidden";

            }
        },
    });
}

function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

function AddMyStyle(styleID, styleCSS) {
    var myStyle = document.createElement('style');
    //myStyle.type = 'text/css';
    myStyle.id = styleID;
    myStyle.textContent = styleCSS;
    document.querySelector("head").appendChild(myStyle);
}

startingSoonInterval = setInterval(startingSoon, 150);
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元