Greasy Fork

来自缓存

Content Filter

Hide not interested content

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

// ==UserScript==
// @name           Content Filter
// @name:ja        コンテンツフィルター
// @namespace      https://greasyfork.org/en/users/1264733
// @version        2024-05-05
// @description    Hide not interested content
// @description:ja 興味のない内容を隠す
// @author         LE37
// @license        MIT
// @include        https://*
// @exclude        https://kakuyomu.jp/my/*
// @enclude        https://syosetu.com/favnovelmain/*
// @enclude        https://www.alphapolis.co.jp/mypage/*
// @grant          GM_getValue
// @grant          GM_setValue
// @grant          GM_registerMenuCommand
// ==/UserScript==

(()=>{
	'use strict';
	// GM Key
	let gMk;
	switch (location.host) {
		case "www.alphapolis.co.jp":
			gMk = "APS";
			break;
		case "greasyfork.org":
		//case "":
			gMk = "GFK";
			break;
		case "syosetu.org":
			gMk = "HML";
			break;
		/*case "":
			gMk = "HTM";
			break;*/
		case "www.ign.com":
			gMk = "IGN";
			break;
		case "kakuyomu.jp":
			gMk = "KYU";
			break;
		/*case "":
			gMk = "NNN";
			break;*/
		case "novelcom.syosetu.com":
			gMk = "NUC";
			break;
		case "mypage.syosetu.com":
		case "ncode.syosetu.com":
		case "yomou.syosetu.com":
			gMk = "NRK";
			break;
		/*case "":
		case "":
			gMk = "PHB";
			break;*/
		case "forum.palemoon.org":
			gMk = "PMF";
			break;
		/*case "":
			gMk = "SRB";
			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");

		// cAd: Additional Delay
		// 0:off[default] 1:on
		let cAd = 0;

		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 "GFK":
				// Greasyfork
				if (uRi.includes("/scripts")) {
					// Scripts
					eNo = "li[data-script-id]";
					// Script link
					eUl = "a.script-link";
					// Script authors
					sTg = "dd.script-list-author a";
				} else if (uRi.includes("/discussions")) {
					// Discussions
					eNo = "div.discussion-list-container";
					// Discussion link
					eUl = "a.script-link";
					// Discussion author
					sTg = "a.user-link";
				}
				sId = /s\/(\d+)/;
				break;
			case "HML":
				// Hameln
				eNo = rMb ? "div.search_box" : "div.section3";
				if (uRi.includes("rank")) {
					// Ranking
					eUl = null;
					eAt = rMb ? "p:nth-child(2)" : "div.blo_title_sak";
					sId = /:(.*)/;
					sTg = rMb ? 'span[id^="tag_"]' : 'div.all_keyword:nth-child(9) a';
				} else if (uRi.includes("review")) {
					// Comments
					eUl = null;
					eAt = rMb ? "h4" : "h3";
					sId = /([^\s]+)/;
				} else if ((/novel|user\/\d+\/$/).test(uRi)) {
					// Author Page
					cAp = 1;
					eUl = null;
					if (/novel\/\d+\/$/.test(uRi)) {
						eAt = 'span[itemprop="author"]'
					} else {
						eAt = rMb ? 'h3>a' : 'h3';
					}
					sId = /([^/]+)/;
				}
				break;
			/*case "HTM":
				//
				cFt = 2;
				eOn = "div.gallery-content";
				eNo = "div.gallery-content>div";
				eUl = "table.dj-desc tr:nth-child(3) td:nth-child(2) a";
				sId = /index-(\w+)\.html/;
				sTg = "td.relatedtags>ul>li";
				break;*/
			case "IGN":
				// IGN
				cSr = 1;
				cFt = 2;
				eOn = 'body';
				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
					cAd = 1;
					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
					cAd = 1;
					cAp = 1;
					eUl = uRi.includes("users") ? 'div[class^="HeaderText"]>a' : 'div.partialGiftWidgetActivityName>a';
				}
				sId = /users\/(.*)$/;
				break;
			/*case "NNN":
				//
				eNo = rMb ? "ul.ranking" : "div.rank_h";
				eUl = null;
				eAt = rMb ? "li:nth-child(2)" : "span.name";
				sId = /.{3}(.*)/;
				sTg = rMb ? "li.keyword a" : "td.s a";
				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 "PHB":
				//
				eNo = rMb ? "div.videoWrapper" : "div.wrap";
				eUl = rMb ? "a.uploaderLink" : "div.usernameWrap a";
				sId = /([^\/]+)$/;
				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 "SRB":
				//
				if (uRi.includes("thread")) {
					// Thread
					eNo = rMb ? 'div[id^="pid"]' : 'div[id^="post_"]:not([id^="post_rate"]):not([id^="post_new"])';
					eUl = null;
					eAt = rMb ? "ul.authi a" : "a.xw1";
					sId = /(.*)/;
				} else {
					// Index
					eOn = "#threadlisttableid";
					eNo = rMb ? "div.threadlist>ul>li" : "table#threadlisttableid tbody";
					eUl = null;
					eAt = rMb ? "span.by" : "td:nth-child(3)>cite>a";
					sId = /(.*)/;
				}
				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 = "body";
				eIo = ".load-more";
				eNo = "div.item-list>article";
				eUl = null;
				eAt = "strong.display-name__html";
				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("Sort", UST);

		// 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);
		}

		// Sort List
		// mapsort???
		function UST() {
			tal.sort();
			ttl.sort();
			USV();
		}

		const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

		// Script Fire Time
		switch (cFt) {
			case 1:
				// ReadyState complete
				RSC();
				break;
			case 2:
				// MutationObserver
				MOC();
				break;
			case 3:
				// IntersectionObserver
				IOC();
				break;
			case 0:
			default:
				if (cAd) {
					// Delay
					wait(1500).then(() => FMD());
				} else {
					// Normal
					FMD();
				}
				/*
				if (gMk === "SRB" && !rMb && !uRi.includes("thread")) {
					MOC();
				}*/
		}

		// ReadyState complete
		function RSC() {
			document.addEventListener("readystatechange", (e) => {
				if (e.target.readyState === "complete") {
					//console.log('RSC: Complete');
				}
			});
		}

		// MutationObserver
		function MOC() {
			if (gMk === "KYU") {
				// Comments in Episode
				// Button load comments
				const bLc = document.querySelector('#episodeFooter-action-cheerCommentsButton');
				bLc.addEventListener("click", (e) => {
					waitForElement(eNo, 2000).then(() => {
						//console.log('MOC: Ready');
						FTR();
					}).catch(() => {
						//console.log('MOC: Timeout');
					});
				});
			} else {
				waitForElement(eNo, 30000).then(() => {
					//console.log('MOC: Ready');
					FMD();
					// IGN news
					if (gMk === "IGN") {
						// Button load more messages
						const bLm = eSr.querySelector('.spcv_load-more-messages');
						bLm.addEventListener("click", (e) => {
							wait(2000).then(() => FTR());
						});
					}
					// Vivaldi Social
					if (gMk === "VVS") {
						wait(1500).then(() => IOC());
					}
				}).catch(() => {
					//console.log('MOC: Timeout');
				});
			}
		}

		// Wait for an element to be loaded
		function waitForElement(selector, timeout) {
			return new Promise((resolve, reject) => {
				var timer = false;
				// Spot im shadownode
				if (cSr) {
					if (eSr) {
						if (eSr.querySelectorAll(selector).length) {
							return resolve();
						}
					}
				} else {
					if (document.querySelectorAll(selector).length) return resolve();
				}

				const obs = new MutationObserver(mutations => {
					// Spot im shadownode
					if (cSr) {
						eSh = document.querySelector('div[data-spotim-module]').firstElementChild;
						if (eSh) {
							eSr = eSh.shadowRoot;
							if (eSr) {
								if (eSr.querySelectorAll(selector).length) {
									obs.disconnect();
									if (timer !== false) clearTimeout(timer);
									return resolve();
								}
							}
						}
					} else {
						if (document.querySelectorAll(selector).length) {
							obs.disconnect();
							if (timer !== false) clearTimeout(timer);
							return resolve();
						}
					}
				});
				// Spot im shadownode
				const obn = eSr ? eSr.querySelectorAll('.spcv_conversation')[0] : document.querySelector(eOn);
				obs.observe(obn, {
					childList: true,
					subtree: true
				});

				if (timeout) {
					timer = setTimeout(() => {
						obs.disconnect();
						reject();
					}, timeout);
				}
			});
		}

		// IntersectionObserver
		function IOC() {
			const ioc = new IntersectionObserver((entries) => {
				if (entries[0].intersectionRatio <= 0) return;
				ioc.disconnect();
				// Vivaldi Social
				if (gMk === "VVS") {
					wait(1500).then(() => MOC());
				}
			});
			ioc.observe(document.querySelector(eIo));
		}

		// Filtering mode
		function FMD() {
			if (cAp) {
				// Filtering single target
				FAP();
			} else {
				// Filtering multiple targets
				FTR();
			}
		}

		// Filtering single target
		function FAP() {
				let rBk = false;
				const eLk = eUl ? document.querySelector(eUl) : document.querySelector(eAt);
				let uId;
				// Narou author page fix
				if (gMk === "NRK") {
					uId = eLk.href ? eLk.href.match(sId)[1] : uRi.match(sId)[1];
				} else {
					uId = eUl ? eLk.href.match(sId)[1] : eLk.textContent.match(sId)[1];
				}
				rBk = CHK(eLk, tal, uId);
				eLk.style.opacity = rBk ? "0.5" : "1";
				eLk.style.color = rBk ? "red" : "lime";
		}

		// Filtering multiple targets
		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 === "NUC" || gMk === "VVS") {
					// Narou nologin user fix
					// Vivaldi Social element out of view fix
					if (!eLk) {
						eLk = gMk === "VVS" ? no[i].querySelector("span") : no[i].querySelector(eAt);
						uId = gMk === "VVS" ? eLk.textContent.match(sId)[1].replace(/\s/g,'') : eLk.textContent.split("\n")[2];
					} else {
						uId = eUl ? eLk.href.match(sId)[1] : eLk.textContent.match(sId)[1];
						// Vivaldi Social id fix for foreground & background
						if (gMk ==="VVS") {
							let emoji = "";
							const ino = no[i].querySelectorAll(eAt + " img");
							if (ino) {
								for (let k = 0; k < ino.length; k++) {
									emoji += ino[k].alt;
								}
							}
							uId = eLk.textContent.match(sId)[1] + emoji;
							uId = uId.replace(/\s/g,'');
						}
					}
					//console.log(uId);
					// Vivaldi Social use static no[i] instead of dynamic eLk
					rBk = gMk === "VVS" ? CHK(no[i], tal, uId) : CHK(eLk, tal, uId);
				}

				//const eNes = no[i].nextElementSibling;
				if (sTg && !rBk) {
					// Filtering content contain multiple tags(text)
					// Tag node
					let tno;
					// Hameln mobile origin tag, custom tag
					let tot, tct;
					if (gMk === "HML" && rMb) {
						tot = no[i].querySelector(".trigger p:nth-child(4)");
						tct = no[i].querySelector(sTg);
						if (!tct) {
							tno = tot.textContent.slice(3).match(/[^\s]+/g);
							tot.innerHTML = "";
						} else {
							tno = no[i].querySelectorAll(sTg);
						}
					} else {
						// NNN desktop fix
						tno = no[i].querySelectorAll(sTg);//gMk === "NNN" && !rMb ? eNes.querySelectorAll(sTg) : no[i].querySelectorAll(sTg);
					}
					for (let j = 0; j < tno.length; j++) {
						let tag;
						if (tot && !tct) {
							tag = tno[j];
							tot.innerHTML += '<span id="tag_' + j + '">' + tag + '</span>';
						} else {
							// Greasyfork fix
							tag = gMk === "GFK" ? tno[j].href.match(sId)[1] : tno[j].textContent;
						}
						//console.log(tag);
						/* HTM hidden tag fix
						if (gMk === "HTM" && tno[j].classList.length !== 0 || tag === "...") {
							break;
						}*/
						rBk = tot && !tct ? CHK(no[i].querySelector("span#tag_"+j), ttl, tag) : CHK(tno[j], ttl, tag);
						if (rBk) {
							break;
						}
					}
				}

				// Blocked Show Type
				if (cSv === 0) {
					no[i].style.display = rBk ? "none" : "";
					no[i].style.opacity = "1";
					/* NNN desktop fix
					if (gMk === "NNN" && !rMb) {
						eNes.style.display = rBk ? "none" : "";
						eNes.style.opacity = "1";
					}*/
				} else {
					no[i].style.display = "";
					no[i].style.opacity = rBk ? "0.5" : "1";
					/* NNN desktop fix
					if (gMk === "NNN" && !rMb) {
						eNes.style.display = "";
						eNes.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 fuchsia" : "thin solid dodgerblue";
			} 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;
				// Enable default click
				document.removeEventListener("click", PAC, true);
				// Auto save list
				USV();
			}
			FMD();
		}

		// PreventAnchorChange
		function PAC(e) {
			e.preventDefault();
			// Vivaldi Forum & Social fix
			if (gMk === "VVF" || gMk === "VVS") {
				e.stopPropagation();
			}
			const targetElement = cSr ? e.composedPath()[0] : e.target;
			//console.log(targetElement);
			let eLk;
			// Narou nologin user fix
			if (gMk === "NUC") {
				eLk = targetElement.href ? eUl : eAt;
			} else {
				eLk = eUl ? eUl : eAt;
			}
			// StopPropagation fix
			if (targetElement.closest("#cFbtn")) {
				SVM;
			} else if (targetElement.closest(eLk)) {
				let ai;
				switch (gMk) {
					// Narou author page fix
					case "NRK":
						if (uRi.includes("mypage")) {
							// Author Page
							ai = uRi.match(sId)[1];
						} else {
							ai = eUl ? targetElement.href.match(sId)[1] : targetElement.textContent.match(sId)[1];
						}
						break;
					// Narou nologin user fix
					case "NUC":
						ai = targetElement.href ? targetElement.href.match(sId)[1] : targetElement.textContent.split("\n")[2];
						break;
					// Vivaldi Social different id fix
					case "VVS":
							let emoji = "";
							const ino = targetElement.parentElement.querySelectorAll(eAt + " img");
							if (ino) {
								for (let k = 0; k < ino.length; k++) {
									emoji += ino[k].alt;
								}
							}
							ai = targetElement.textContent.match(sId)[1] + emoji;
							ai = ai.replace(/\s/g,'');
						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);
				FMD();
			} else if (targetElement.closest(sTg)) {
				// Greasyfork fix
				const kd = gMk === "GFK" ? targetElement.href.match(sId)[1] : targetElement.textContent;
				//console.log(kd);
				UTL(e, kd, ttl);
				FMD();
			}
			// IGN Popup temp fix
			if (gMk === "IGN") {
				wait(500).then(() => {
					const bsh = document.body.lastChild.shadowRoot;
					if (bsh) {
						const bsr = bsh.querySelector('button[title="Close the modal"]');
						if (bsr) {
							bsr.click();
						}
					}
				});
			}
			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 Float Button
		const cButton = document.body.appendChild(document.createElement("button"));
		// Button Style
		cButton.id = "cFbtn";
		cButton.textContent = "📘";
		cButton.style = "position: fixed; bottom: 20%; right: 10%; width: 44px; height: 44px; z-index: 9999; font-size: 200%; opacity: 50%;";
		cButton.type = "button";
		cButton.addEventListener("click", (e) => {
			SVM();
		});
		// Vivaldi Social CSP temp fix
		if (gMk === "VVF" || gMk === "VVS") {
			cButton.addEventListener("dblclick", (e) => {
				cSv = 1;
				SVM();
			});
		}
	}
})();