// ==UserScript== // @name ESJ Zone: Repair Non-clickable Chapters // @name:zh-TW ESJ Zone:修復無法點擊的章節 // @description Repair chapter links that were not-clickable due to for example, author misconfigured or by-designed. // @description:zh-TW 修復因作者設定錯誤或網頁設計問題等原因而無法點擊的章節連結。 // @icon https://icons.duckduckgo.com/ip3/www.esjzone.cc.ico // @author Jason Kwok // @namespace https://jasonhk.dev/ // @version 1.0.0 // @license MIT // @match https://www.esjzone.cc/ // @match https://www.esjzone.cc/update // @match https://www.esjzone.cc/update/ // @match https://www.esjzone.cc/list // @match https://www.esjzone.cc/list/ // @match https://www.esjzone.cc/list-* // @match https://www.esjzone.cc/tags/* // @match https://www.esjzone.cc/tags-* // @match https://www.esjzone.cc/my/favorite // @match https://www.esjzone.cc/my/favorite/* // @match https://www.esjzone.me/ // @match https://www.esjzone.me/update // @match https://www.esjzone.me/update/ // @match https://www.esjzone.me/list // @match https://www.esjzone.me/list/ // @match https://www.esjzone.me/list-* // @match https://www.esjzone.me/tags/* // @match https://www.esjzone.me/tags-* // @match https://www.esjzone.me/my/favorite // @match https://www.esjzone.me/my/favorite/* // @run-at document-end // @grant none // @require https://update.greasyfork.org/scripts/482311/1296481/queue.js // @supportURL https://greasyfork.org/scripts/487645/feedback // @downloadURL none // ==/UserScript== async function findChapterUrl(novelUrl, chapterName) { const response = await fetch(novelUrl); if (response.status === 200) { const html = await response.text(); const parser = new DOMParser(); const page = parser.parseFromString(html, "text/html"); return Array.from(page.querySelectorAll("#chapterList a")) .find((chapter) => (chapter.innerText.trim() === chapterName))?.href ?? null; } } let repaired = 0; const queue = new Queue({ autostart: true, concurrency: 4 }); queue.addEventListener("error", (event) => console.error(event.detail.error)); queue.addEventListener("end", () => console.debug(`Repaired ${repaired} URL(s).`)); const pathname = location.pathname; if (pathname === "/my/favorite" || pathname.startsWith("/my/favorite/")) { const novels = document.querySelectorAll(".product-item"); for (const novel of novels) { const chapterWrapper = novel.querySelector(".book-ep div:nth-child(2)"); const chapter = chapterWrapper.childNodes[0]?.splitText(5); if (chapter instanceof Text) { queue.push(async () => { const url = await findChapterUrl(novel.querySelector(".product-title a").href, chapter.data); if (url) { const link = document.createElement("a"); link.href = url; link.append(chapter); chapterWrapper.append(link); repaired++; } }); } } } else { const novels = document.querySelectorAll(".card"); for (const novel of novels) { const chapterWrapper = novel.querySelector(".card-ep"); const chapter = chapterWrapper.childNodes[0]; if (chapter instanceof Text) { queue.push(async () => { const url = await findChapterUrl(novel.querySelector(".card-title a").href, chapter.wholeText); if (url) { const link = document.createElement("a"); link.href = url; link.append(chapter); chapterWrapper.append(link); repaired++; } }); } } }