Greasy Fork

Greasy Fork is available in English.

Novel Ranking/Comments Filter

Hide not interested content on ranking/comments page

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

// ==UserScript==
// @name           Novel Ranking/Comments Filter
// @name:ja        小説ランキング/コメント・フィルター
// @namespace      http://greasyfork.icu/en/users/1264733
// @version        2024-05-12
// @description    Hide not interested content on ranking/comments page
// @description:ja ランキング/コメントページで興味のないコンテンツを隠す
// @author         LE37
// @license        MIT
// @include        /https:\/\/www\.alphapolis\.co\.jp\/(author|novel)\//
// @include        /https:\/\/kakuyomu\.jp\/(pick|rank|rece|user|works\/)/
// @include        /https:\/\/(mypage|ncode)\.syosetu\.com\/[a-z0-9]+\//
// @include        https://yomou.syosetu.com/rank/*
// @include        https://novelcom.syosetu.com/impression/*
// @include        /https:\/\/syosetu\.org\/\?mode=r(ank|evi)/
// @include        /https:\/\/syosetu\.org\/(novel|user)\/[0-9]+\//
// @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
// ==/UserScript==

(()=>{
	'use strict';
	// GM Key
	let gMk;
	// Author page
	let cAp = false;
	// View Mode
	let cSv = false;
	// Fire time, Observe node
	let cFt, eOn;
	// Nodelist, userLink, userid, tag, alt
	let eNo, eUl, sId, sTg, eAt;
	// Client type
	const rMb = navigator.userAgent.includes("Mobile");
	// Url
	const uRi = location.href;
	switch (location.host) {
		case "www.alphapolis.co.jp":
			gMk = "APS";
			if (uRi.includes("comme")) {
				// Comments
				eNo = "div.comment";
				eUl = "span.name>a";
			} else if (uRi.includes("index") || uRi.includes("ranki")) {
				// Ranking
				eNo = "div.section";
				eUl = "div.author>a";
				sTg = "li.tag a";
			} else if (uRi.includes("autho") || (/novel[0-9\/]+$/).test(uRi)) {
				// Author
				cAp = true;
				eUl = uRi.includes("author") ? "div.name>h1" : "div.author a";
			}
			sId = /detail\/(\d+)$/;
			break;
		case "syosetu.org":
			gMk = "HML";
			eNo = rMb ? "div.search_box" : "div.section3";
			eUl = null;
			if (uRi.includes("rank")) {
				// Ranking
				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("revi")) {
				// Comments
				eAt = rMb ? "h4" : "h3";
				sId = /([^\s]+)/;
			} else if ((/novel|user\/\d+\/$/).test(uRi)) {
				// Author
				cAp = 1;
				if (/novel\/\d+\/$/.test(uRi)) {
					eAt = 'span[itemprop="author"]'
				} else {
					eAt = rMb ? 'h3>a' : 'h3';
				}
				sId = /([^/]+)/;
			}
			break;
		case "kakuyomu.jp":
			gMk = "KYU";
			if (uRi.includes("/pick") || uRi.includes("/rank") || uRi.includes("/rece")) {
				// Ranking
				eNo = "div.widget-work";
				eUl = "a.widget-workCard-authorLabel";
				sId = /users\/(.*)$/;
				sTg = "a[itemprop='keywords']";
			} else if (uRi.includes("comme")) {
				// Comments
				cFt = 1;
				eNo = rMb ? 'div[class^="NewBox_box__"]>ul>li' : 'ul:nth-child(1) li';
				eUl = 'div.partialGiftWidgetActivityName>a';
			} else if (uRi.includes("episo")) {
				// 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
				cFt = 1;
				cAp = true;
				eUl = uRi.includes("users") ? 'div[class^="HeaderText"]>a' : 'div.partialGiftWidgetActivityName>a';
			}
			sId = /users\/(.*)$/;
			break;
		case "novelcom.syosetu.com":
			gMk = "NUC";
			eNo = rMb ? "div.impression" : "div.waku";
			eUl = "div.comment_authorbox>div>a";
			eAt = "div.comment_authorbox>div";
			sId = /\/(\d+)/;
			break;
		case "mypage.syosetu.com":
		case "ncode.syosetu.com":
		case "yomou.syosetu.com":
			gMk = "NRK";
			if (uRi.includes("mypag") || uRi.includes("ncode")) {
				// Author
				cAp = true;
				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;
		default:
			//console.log("DoNothing");
	}

	// 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
	function UST() {
		tal.sort();
		ttl.sort();
		USV();
	}

	const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
	// Script Fire Time
	switch (cFt) {
		case 1:
			// Delay
			wait(1500).then(() => FMD());
			break;
		case 2:
			// MutationObserver
			MOC();
			break;
		default:
			// Normal
			FMD();
	}
	function MOC() {
		const obs = new MutationObserver(() => {
			obs.disconnect();
			FMT();
		});
		obs.observe(document.querySelector(eOn), {
			childList: true,
			subtree: true
		});
	}

	// Filtering mode
	function FMD() {
		if (cAp) {
			// Filtering single target
			FST();
		} else {
			// Filtering multiple targets
			FMT();
		}
	}
	// Filtering single target
	function FST() {
		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 = CBN(eLk, "a", tal, uId);
		eLk.style.opacity = rBk ? "0.5" : "1";
	}
	// Filtering multiple targets
	function FMT() {
		const no = 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") {
				// Narou nologin user fix
				if (!eLk) {
					eLk = no[i].querySelector(eAt);
					uId = eLk.textContent.split("\n")[2];
				} else {
					uId = eUl ? eLk.href.match(sId)[1] : eLk.textContent.match(sId)[1];
				}
				//console.log(uId);
				rBk = CBN(eLk, "a", tal, uId);
			}
			if (sTg && !rBk) {
				// Filtering content contain multiple tags(text)
				// Tag node
				let tno = no[i].querySelectorAll(sTg);
				for (let j = 0; j < tno.length; j++) {
					//console.log(tno[j].textContent);
					rBk = CBN(tno[j], "t", ttl, tno[j].textContent);
					if (rBk) break;
				}
			}
			// Blocked Show Type
			no[i].style.display = !cSv && rBk ? "none" : "";
			no[i].style.opacity = cSv && rBk ? "0.5" : "1";
		}
	}

	// Create Buttons
	function CBN(ele, n, l, s) {
		const result = l.some((v) => s === v);
		const eNes = ele.nextElementSibling;
		let bTn;
		if (eNes && (eNes.className === "bbtn")) {
			bTn = eNes;
		} else {
			bTn = document.createElement("button");
			bTn.classList = "bbtn";
			bTn.style = "border: none; padding: unset;";
			bTn.type = "button";
			bTn.setAttribute("data-l", n);
			bTn.setAttribute("data-k", s);
			ele.after(bTn);
		}
		bTn.textContent = result ? "⛔" : "✅";
		return result;
	}
	document.addEventListener("click", ECH);
	function ECH(e) {
		//console.log(e.target);
		if(e.target.className === "bbtn") {
			const tlst = e.target.getAttribute("data-l") === "a" ? tal : ttl;
			const tid = e.target.getAttribute("data-k");
			const li = tlst.findIndex((v) => v === tid);
			if (li !== -1) {
				tlst.splice(li,1);
			} else {
				tlst.push(tid);
			}
			FMD();
			USV();
		}
	}

	// Float Button
	const cButton = document.body.appendChild(document.createElement("button"));
	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%; border: none; padding: unset;";
	cButton.type = "button";
	cButton.addEventListener("click", (e) => { SVM(); });
	function SVM() {
		cSv = !cSv;
		cButton.textContent = cSv ? "📙" : "📘";
		FMT();
	}
})();