// ==UserScript== // @name Readmoo: Blurs R-rated Covers // @name:zh-TW 讀墨電子書:模糊限制級封面 // @description Blurs the covers of R-rated books on Readmoo. // @description:zh-TW 模糊讀墨電子書限制級書本的封面。 // @icon https://wsrv.nl/?url=https://cdn.readmoo.com/images/manifest/icon_152x152.png // @author Jason Kwok // @namespace https://jasonhk.dev/ // @version 1.0.0 // @license MIT // @match https://readmoo.com/ // @match https://readmoo.com/* // @run-at document-end // @grant none // @require https://update.greasyfork.icu/scripts/483122/1304475/style-shims.js // @require https://update.greasyfork.icu/scripts/482311/1297431/queue.js // @downloadURL none // ==/UserScript== GM.addStyle(` .listItem-box.nsfw .book-cover img { filter: blur(var(--nsfw-blur-radius, 7.5px)); transition: filter var(--nsfw-transition-duration, 0.3s); } .listItem-box.nsfw:hover .book-cover img, .listItem-box.nsfw:focus-within .book-cover img { filter: blur(0px); transform: none; } `); const queue = new Queue({ autostart: true, concurrency: 10 }); queue.addEventListener("error", (event) => console.error(event.detail.error)); const products = document.querySelectorAll(".listItem-box:not(.full-list)"); for (const product of products) { const cover = product.querySelector(".book-cover img"); if ((cover?.src ?? cover?.dataset.lazyOriginal) !== "https://cdn.readmoo.com/images/r18.png") { queue.push(async () => { if (await isNsfw(product.querySelector(".product-link").href)) { product.classList.add("nsfw"); } }); } } async function isNsfw(url) { try { const response = await fetch(url, { credentials: "omit" }); if (response.status === 200) { const html = await response.text(); const parser = new DOMParser(); const page = parser.parseFromString(html, "text/html"); return (page.getElementById("18x_page") !== null); } } catch (e) { console.error(e); } return false; }