// ==UserScript== // @name Content Filter // @name:ja コンテンツフィルター // @namespace https://greasyfork.org/en/users/1264733 // @version 2024-04-18 // @description Hide not interested content // @description:ja 興味のない内容を隠す // @author LE37 // @license MIT // @include https://forum.palemoon.org/viewforum* // @include https://forum.palemoon.org/viewtopic* // @include https://forum.vivaldi.net/category/* // @include https://forum.vivaldi.net/topic/* // @include https://kakuyomu.jp/pickup_works* // @include https://kakuyomu.jp/rankings/* // @include https://kakuyomu.jp/recent_works* // @include https://kakuyomu.jp/users/* // @include https://kakuyomu.jp/works/* // @include https://mypage.syosetu.com/*/ // @include https://ncode.syosetu.com/*/ // @include https://novelcom.syosetu.com/impression/* // @include https://yomou.syosetu.com/rank/* // @include https://social.vivaldi.net/ // @include https://social.vivaldi.net/explore* // @include https://social.vivaldi.net/public* // @include https://syosetu.org/novel/*/ // @include https://syosetu.org/user/*/ // @include https://syosetu.org/?mode=rank* // @include https://syosetu.org/?mode=review* // @include https://www.alphapolis.co.jp/author/* // @include https://www.alphapolis.co.jp/novel/* // @include https://www.ign.com/articles/* // @include https://www.yandex.com/search/* // @include https://yandex.com/search/* // @exclude https://www.alphapolis.co.jp/novel/ranking/annual // @exclude https://yomou.syosetu.com/rank/top/ // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @downloadURL none // ==/UserScript== (()=>{ 'use strict'; // GM Key let gMk; // Needed if remove include and exclude in future switch (location.host) { case "www.alphapolis.co.jp": gMk = "APS"; break; case "syosetu.org": gMk = "HML"; break; case "www.ign.com": gMk = "IGN"; break; case "kakuyomu.jp": gMk = "KYU"; break; case "novelcom.syosetu.com": gMk = "NUC"; break; case "mypage.syosetu.com": case "ncode.syosetu.com": case "yomou.syosetu.com": gMk = "NRK"; break; case "forum.palemoon.org": gMk = "PMF"; break; case "forum.vivaldi.net": gMk = "VVF"; break; case "social.vivaldi.net": gMk = "VVS"; break; case "yandex.com": case "www.yandex.com": gMk = "YDX"; break; default: //console.log("DoNothing"); } if (gMk) { RUN(); } function RUN() { // cSr: Filting shadowroot content, only used when target within shadowroot // 0:off[default] 1:on let cSr = 0; // Shadowhost, Shadowroot, used when cSr = 1 let eSh , eSr; // cAp: Filtering author/novel page // 0:off[default] 1:on let cAp = 0; // Select mode, 0:off[default] 1:on let cSv = 0; // cFt: Script firetime, prevent script fires too early // 0:Normal[default] 1:ReadyState Complete 2:MutationObserver 3:IntersectionObserver let cFt = 0; // eOn: MutationObserver targetNode, used when cFt = 2 let eOn; // eIo: IntersectionObserver target, used when cFt = 3 let eIo; // eNo: target nodelist, eUl: userLink, sId: userID, sTg: tag let eNo, eUl, sId, sTg; // eAt: Alternate text(target's textContent), used when predefine eUl(userlink) doen't contain valid href let eAt; // rMb: Client type // true:Mobile false:Desktop const rMb = navigator.userAgent.includes("Mobile"); const uRi = location.href; switch (gMk) { case "APS": // Alphapolis if (uRi.includes("comment")) { // Comments eNo = "div.comment"; eUl = "span.name>a"; } else if (uRi.includes("index") || uRi.includes("ranking")) { // Ranking eNo = "div.section"; eUl = "div.author>a"; sTg = "li.tag a"; } else if (uRi.includes("author") || (/novel[0-9\/]+$/).test(uRi)) { // Author Page cAp = 1; eUl = uRi.includes("author") ? "div.name>h1" : "div.author a"; } sId = /detail\/(\d+)$/; break; case "HML": // Hameln eNo = rMb ? "div.search_box" : "div.section3"; if (uRi.includes("rank")) { // Ranking eUl = "div.blo_title_sak a"; eAt = "div.blo_title_sak"; sTg = "div.all_keyword:nth-child(9) a"; } else if (uRi.includes("review")) { // Comments eUl = "h3>a:nth-child(1)"; } else if ((/novel|user\/\d+\/$/).test(uRi)) { // Author Page cAp = 1; eUl = /novel\/\d+\/$/.test(uRi) ? 'span[itemprop="author"]>a' : 'div.section3>h3'; eAt = 'span[itemprop="author"]'; } sId = /((?<=uid=).*|(\d+)(?=\/))/; break; case "IGN": // IGN cSr = 1; cFt = 3; eIo = '#comments-section'; eOn = '.spcv_conversation'; eNo = "li"; eUl = null; eAt = 'span[data-spot-im-class="message-username"]'; sId = /(.*)/; break; case "KYU": // Kakuyomu if (uRi.includes("/pickup") || uRi.includes("/rank") || uRi.includes("/recent")) { // Ranking eNo = "div.widget-work"; eUl = "a.widget-workCard-authorLabel"; sId = /users\/(.*)$/; sTg = "a[itemprop='keywords']"; } else if (uRi.includes("comments")) { // Comments cFt = 2; eOn = '#__next'; eNo = rMb ? 'div[class^="NewBox_box__"]>ul>li' : 'ul:nth-child(1) li'; eUl = 'div.partialGiftWidgetActivityName>a'; } else if (uRi.includes("episodes")) { // Comments in Episode cFt = 2; eOn = "#episodeFooter-cheerComments-panel-mainContents"; eNo = "ul.widget-cheerCommentList li"; eUl = "h5.widget-cheerComment-author a"; } else if (uRi.includes("users") || (/works\/\d+$/).test(uRi)) { // Author Page cFt = 2; eOn = '#__next'; cAp = 1; eUl = uRi.includes("users") ? 'div[class^="HeaderText"]>a' : 'div.partialGiftWidgetActivityName>a'; } sId = /users\/(.*)$/; break; case "NUC": // Narou Comments eNo = rMb ? "div.impression" : "div.waku"; eUl = "div.comment_authorbox>div>a"; eAt = "div.comment_authorbox>div"; sId = /\/(\d+)/; break; case "NRK": // Narou Ranking if (uRi.includes("mypage") || uRi.includes("ncode")) { // Author Page cAp = 1; eUl = uRi.includes("ncode") ? 'div.novel_writername>a' : 'div.p-userheader__username'; } else { // Ranking eNo = "div.p-ranklist-item"; eUl = "div.p-ranklist-item__author a"; sTg = "div.p-ranklist-item__keyword a"; } sId = /\/(\d+)/; break; case "PMF": // Palemoon Forum if (uRi.includes("viewtopic")) { // Topic eNo = "#page-body div.post"; eUl = 'a[class^="username"]'; sId = /u=(\d+)/; } else { // Index eNo = "ul.topiclist>li"; eUl = "div.topic-poster>a"; sId = /u=(\d+)/; } break; case "VVF": // Vivaldi Forum if (uRi.includes("topic")) { // Topic eNo = "ul.posts>li"; eUl = "small.d-flex a"; sId = /user\/(.*)/; } else { // Index eNo = "ul.topic-list li"; eUl = "small.hidden-xs>a"; sId = /user\/(.*)/; } break; case "VVS": // Vivaldi Social cFt = 2; eOn = "div.app-holder"; eNo = "div.item-list>article"; eUl = null; eAt = "span.display-name__account"; sId = /@(.*)$/; break; case "YDX": // Yandex Search eNo = rMb ? "div.serp-item" : "#search-result>li"; eUl = rMb ? null : "div.Path>a.Link"; eAt = "span.Path-Item>b"; sId = rMb ? /(.*)/ : /\/([^\/]+)/; break; } // GM Menu GM_registerMenuCommand("View", SVM); GM_registerMenuCommand("Save", USV); // Read List const URD = GM_getValue(gMk); let tlo = URD ? URD : { BAL:[], BTL:[] }; const tal = tlo.BAL; const ttl = tlo.BTL; // Save List function USV() { tlo = { BAL:tal, BTL:ttl }; GM_setValue(gMk, tlo); } // Script Fire Time switch (cFt) { case 1: // ReadyState complete RSC(); break; case 2: // MutationObserver MOC(); break; case 3: // IntersectionObserver IOC(); break; case 0: default: // Normal FMD(); } // ReadyState complete function RSC() { document.addEventListener("readystatechange", (e) => { if (e.target.readyState === "complete") { FMD(); } }); } // MutationObserver function MOC() { const obs = new MutationObserver(() => { FMD(); // Kakuyomu author/novel page fix // Prevent infinite loop if (gMk === "KYU" && cAp && document.getElementsByClassName("bbtn")) { obs.disconnect(); } }); // Shadowroot fix const obn = cSr ? eSr.querySelectorAll(eOn)[0] : document.querySelector(eOn); obs.observe(obn, { childList: true, subtree: true }); } // IntersectionObserver function IOC() { // Shadowroot fix if (cSr) { eSh = document.querySelector('div[data-spotim-module]').firstElementChild; if (eSh) { eSr = eSh.shadowRoot; } //console.log(eSr); } const ioc = new IntersectionObserver((entries) => { if (entries[0].intersectionRatio <= 0) return; FTR(); // IGN fix if (gMk === "IGN") { MOC(); } ioc.disconnect(); }); ioc.observe(document.querySelector(eIo)); } // Filtering mode function FMD() { if (cAp) { // Filtering author/novel page FAP(); } else { // Filtering ranking/comments FTR(); } } // Filtering author/novel page function FAP() { let rBk = false; let eLk = document.querySelector(eUl); let uId; // Hameln nologin author fix if (!eLk && gMk === "HML") { eLk = document.querySelector(eAt); uId = eLk.textContent; } else { // Hameln Narou author page fix uId = eLk.href ? eLk.href.match(sId)[1] : uRi.match(sId)[1]; } rBk = CBN(eLk, tal, uId); eLk.style.opacity = rBk ? "0.5" : "1"; } // Filtering ranking/comments function FTR() { const no = cSr ? eSr.querySelectorAll(eNo) : document.querySelectorAll(eNo); for (let i = 0; i < no.length; i++) { let rBk = false; let uId; // Filtering content contain single id(link) or text let eLk = eUl ? no[i].querySelector(eUl) : no[i].querySelector(eAt); if (eLk !== null || gMk === "HML" || gMk === "NUC") { // Hameln Narou nologin user fix if (!eLk) { eLk = no[i].querySelector(eAt); uId = gMk === "HML" ? no[i].querySelector(eAt).textContent.slice(3, -1) : no[i].querySelector(eAt).textContent.split("\n")[2]; } else { uId = eUl ? eLk.href.match(sId)[1] : eLk.textContent.match(sId)[1]; } //console.log(uId); rBk = CHK(eLk, tal, uId); } if (!rBk) { // Filtering content contain multiple tags(text) const tno = no[i].querySelectorAll(sTg); if (tno !== null) { for (let j = 0; j < tno.length; j++) { const tag = tno[j].textContent; //console.log(tag); rBk = CHK(tno[j], ttl, tag); if (rBk) { break; } } } } // Blocked Show Type if (cSv === 0) { //no[i].style.visibility = rBk ? "hidden" : "visible"; no[i].style.display = rBk ? "none" : ""; no[i].style.opacity = "1"; } else { //no[i].style.visibility = "visible"; no[i].style.display = ""; no[i].style.opacity = rBk ? "0.5" : "1"; } } } // CheckKeyword function CHK(ele, l, s) { const result = l.some((v) => s === v); if (cSv === 1) { ele.style.border = result ? "thin solid lime" : "thin solid red"; } else { ele.style.border = "none"; } return result; } // Select mode function SVM() { if (cSv === 0) { cSv = 1; // Disable default click document.addEventListener("click", PAC, true); } else { cSv = 0; // Disable default click document.removeEventListener("click", PAC, true); // Autosave list when turn off select mode USV(); } FTR(); } // PreventAnchorChange function PAC(e) { e.preventDefault(); // Vivaldi Social fix if (gMk === "VVS") { e.stopPropagation(); } const targetElement = cSr ? e.composedPath()[0] : e.target; //console.log(targetElement); let eLk; // Hameln Narou nologin user fix if (gMk === "HML" || gMk === "NUC") { eLk = targetElement.href ? eUl : eAt; } else { eLk = eUl ? eUl : eAt; } // StopPropagation fix // StopPropagation will stop float button working, // So need binding #cFbtn to SVM temporary. if (targetElement.closest("#cFbtn")) { SVM; } else if (targetElement.closest(eLk)) { let ai; switch (gMk) { // Hameln nologin author fix case "HML": ai = targetElement.href ? targetElement.href.match(sId)[1] : targetElement.textContent.slice(3, -1); break; // Narou nologin user fix case "NUC": ai = targetElement.href ? targetElement.href.match(sId)[1] : targetElement.textContent.split("\n")[2]; break; // Yandex fix case "YDX": ai = targetElement.href ? targetElement.href.match(sId)[1] : targetElement.parentElement.href.match(sId)[1]; break; default: ai = eUl ? targetElement.href.match(sId)[1] : targetElement.textContent.match(sId)[1]; } //console.log(ai); UTL(e, ai, tal); FTR(); } else if (targetElement.closest(sTg)) { const kd = targetElement.textContent; UTL(e, kd, ttl); FTR(); } return false; } // UpdateTempList function UTL(e, s, l) { const li = l.findIndex((v) => v === s); if (li !== -1) { l.splice(li,1); } else { l.push(s); } //console.log(l); return l; } // Create Normal Buttons(author/novel page) function CBN(ele, l, s) { const result = l.some((v) => s === v); const eNes = ele.nextElementSibling; let bBtn; if (eNes && eNes.classList.contains("bbtn")) { bBtn = eNes; } else { bBtn = document.createElement("span"); bBtn.classList.add("bbtn"); ele.after(bBtn); bBtn.addEventListener("click", ()=>{ const li = l.findIndex((v) => v === s); if (li !== -1) { l.splice(li,1); } else { l.push(s); } //console.log(l); USV(); FAP(); }, true); } // Button Style bBtn.innerHTML = result ? '' : ''; return result; } // Create Float Button(ranking/comments page) // Vivaldi Social CSP:refuse inline style if (!cAp && gMk !== "VVS") { const cMenu = document.createElement("div"); // Button Style cMenu.innerHTML = ''; document.body.appendChild(cMenu); document.getElementById("cFbtn").addEventListener("click", SVM, true); } } })();