您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
7/2/2024, 8:37:14 PM
当前为
// ==UserScript== // @name Bobby's Pixiv Utils // @namespace https://github.com/BobbyWibowo // @match *://www.pixiv.net/* // @match *://pixiv.net/* // @icon https://www.google.com/s2/favicons?sz=64&domain=pixiv.net // @grant GM_addStyle // @run-at document-end // @version 1.0.10 // @author Bobby Wibowo // @license MIT // @description 7/2/2024, 8:37:14 PM // @noframes // ==/UserScript== (function () { 'use strict' /** CONFIG **/ const SELECTORS_IMAGE = '.jtUPOE > li, .gmoaNn > li, .hjtPnz > li, .boBnlf > div, .hkzusx > div, .ranking-item'; const SELECTORS_ILLUST_CONTROLS = '.gMEAWM'; const SELECTORS_BOTTOM_RIGHT_CONTROLS = '.iHfghO, .cGfNRT, ._layout-thumbnail'; const DATE_CONVERSION = true; const SELECTORS_DATE = '.dqHJfP'; /** STYLES **/ const mainStyle = ` .pu_edit_bookmark { color: rgb(245, 245, 245); background: rgba(0, 0, 0, 0.32); display: block; box-sizing: border-box; padding: 0px 6px; margin-top: 7px; margin-right: 2px; border-radius: 10px; font-weight: bold; font-size: 10px; line-height: 20px; height: 20px; } .gMEAWM .pu_edit_bookmark { font-size: 12px; height: 24px; line-height: 24px; margin-top: 5px; margin-right: 7px; } ._layout-thumbnail .pu_edit_bookmark { position: absolute; right: calc(50% - 71px); bottom: 4px; z-index: 2; } .iHfghO, .cGfNRT { display: flex; justify-content: flex-end; }`; const addPageStyle = ` .bookmark-detail-unit .meta { display: block; font-size: 16px; font-weight: bold; color: inherit; margin-left: 0; margin-top: 10px; }`; /** UTILS **/ const log = (message, ...args) => { console.log(`[Bobby's Pixiv Utils]: ${message}`, ...args) } const logError = (message, ...args) => { console.error(`[Bobby's Pixiv Utils]: ${message}`, ...args) } const convertDate = elem => { const date = new Date(elem.getAttribute('datetime') || elem.innerText); if (date) { const timestamp = String(date.getTime()); if (elem.dataset.oldTimestamp && elem.dataset.oldTimestamp === timestamp) { return } elem.dataset.oldTimestamp = timestamp; elem.innerText = date.toLocaleString("en-GB", { hour12: true, year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } } /** INTERCEPT SOME PAGES **/ const path = location.pathname; if (path.startsWith('/bookmark_add.php')) { GM_addStyle(addPageStyle); const date = document.querySelector('.bookmark-detail-unit .meta'); convertDate(date); log(`${path}: Applied customization, and disabled mutation observer.`) return; } /** MAIN **/ GM_addStyle(mainStyle); class FunctionQueue { constructor() { this.queue = []; this.running = false; } go() { if (this.queue.length) { this.running = true; this.queue.shift()(); this.go(); } else { this.running = false; } } add(func) { this.queue.push(func); if(!this.running) { this.go(); } } } const observerFactory = function (option) { let options; if (typeof option === 'function') { options = { callback: option, node: document.getElementsByTagName('body')[0], option: { childList: true, subtree: true } }; } else { options = $.extend({ callback: () => {}, node: document.getElementsByTagName('body')[0], option: { childList: true, subtree: true } }, option); } const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; const observer = new MutationObserver((mutations, observer) => { options.callback.call(this, mutations, observer); }); observer.observe(options.node, options.option); return observer; }; const editBookmarkButton = id => { const buttonContainer = document.createElement('div'); const button = document.createElement('a'); button.className = 'pu_edit_bookmark'; button.href = `https://www.pixiv.net/bookmark_add.php?type=illust&illust_id=${id}`; button.innerText = 'Edit bookmark'; buttonContainer.appendChild(button); return buttonContainer; } const doImage = element => { // Skip if already modified if (element.getElementsByClassName('pu_edit_bookmark').length) { return; } const link = element.querySelector('a[href*="artworks/"]'); const bottomRightControls = element.querySelector(SELECTORS_BOTTOM_RIGHT_CONTROLS); if (!link || !bottomRightControls) { return; } const match = link.href.match(/artworks\/(\d+)/); if (!match || !match[1]) { return; } bottomRightControls.insertBefore(editBookmarkButton(match[1]), bottomRightControls.firstChild); } const doIllustControls = element => { // Skip if already modified if (element.getElementsByClassName('pu_edit_bookmark').length) { return; } const match = window.location.href.match(/artworks\/(\d+)/); if (!match || !match[1]) { return; } element.appendChild(editBookmarkButton(match[1])); } const queue = new FunctionQueue(); observerFactory((mutations, observer) => { for (let i = 0, len = mutations.length; i < len; i++) { const mutation = mutations[i]; // Whether to change nodes if (mutation.type !== 'childList') { continue; } // Images const images = mutation.target.querySelectorAll(SELECTORS_IMAGE); for (const image of images) { queue.add(() => { doImage(image); }); } // Illust controls const illustControls = mutation.target.querySelector(SELECTORS_ILLUST_CONTROLS); if (illustControls) { queue.add(() => { doIllustControls(illustControls); }); } // Dates const dates = mutation.target.querySelectorAll(SELECTORS_DATE); for (const date of dates) { queue.add(() => { convertDate(date); }); } } }); })()