Content Filter

Hide not interested content

目前为 2024-04-17 提交的版本。查看 最新版本

// ==UserScript==
// @name           Content Filter
// @name:ja        コンテンツフィルター
// @namespace      https://gf.qytechs.cn/en/users/1264733
// @version        2024-04-17
// @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://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_registerMenuCommand
// @grant          GM_setValue
// @grant          GM_getValue
// ==/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 "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
					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 "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;
		}

		// 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
				if (cAp) {
					// Filtering author/novel page
					FAP();
				} else {
					// Filtering ranking/comments
					FTR();
				}
		}

		// ReadyState complete
		function RSC() {
			document.addEventListener("readystatechange", (e) => {
				if (e.target.readyState === "complete") {
					FTR();
				}
			});
		}

		// MutationObserver
		function MOC() {
			const obs = new MutationObserver(() => {
				FTR();
				//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 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();
			//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;
			}
			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 Buttons
		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 ? '<button style="color:lime;background-color:black;" type="button">✔Unblock</button>' : '<button style="color:red;background-color:white;" type="button">❌Block</button>';
			return result;
		}

		// CustomMenu
		if (!cAp) {
			const cMenu = document.createElement("div");
			cMenu.innerHTML = '<nav class="cNav" style="position: fixed; top: 16%; left: 19%; width: 62%; height: 44px; z-index: 9999;">' +
									'<button id="cBtn" style="width: 44px; height: 44px; font-size: 200%; opacity: 50%;" type="button">📘</button>' + 
								'</nav>';
			document.body.appendChild(cMenu);
			document.getElementById("cBtn").addEventListener("click", SVM, true);
		}
	}
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址