Greasy Fork

Greasy Fork is available in English.

Novel Ranking/Comments Filter

Hide not interested content on ranking/comments page

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

// ==UserScript==
// @name           Novel Ranking/Comments Filter
// @name:ja        小説ランキング/コメント・フィルター
// @namespace      http://greasyfork.icu/en/users/1264733
// @version        2024-05-17
// @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;
	// View mode
	let cSv = false;
	// Fire time, Observe node
	let cFt, eOn;
	// Author page
	let cAp = false;
	// Nodelist, userLink, userid, tag, alt
	let eNo, eUl, sId, sTg, eAt;
	// Client type
	const rMb = navigator.userAgent.includes("Mobile");
	// Url
	const uRi = location.href;
	// Site info
	const SITE_INFO = [
		// Alphapolis
		[/^https:\/\/www\.alphapolis\.co\.jp\/.*\/comment/, 'gMk = "APS"; eNo = "div.comment"; eUl = "span.name>a"; sId = /detail\\/(\\d+)$/;'],
		[/^https:\/\/www\.alphapolis\.co\.jp\/novel\/(index|ranki)/, 'gMk = "APS"; eNo = "div.section"; eUl = "div.author>a"; sId = /detail\\/(\\d+)$/; sTg = "li.tag a";'],
		[/^https:\/\/www\.alphapolis\.co\.jp\/(author|novel\/[0-9]+\/[0-9]+$)/, 'gMk = "APS"; cAp = true; eUl = uRi.includes("author") ? "div.name>h1" : "div.author a"; sId = /detail\\/(\\d+)$/;'],
		// Hameln
		[/^https:\/\/syosetu\.org\/\?mode=rank/, 'gMk = "HML"; eNo = rMb ? "div.search_box" : "div.section3"; eUl = null; sId = /:(.*)/; sTg = rMb ? \'span[id^="tag_"]\' : \'div.all_keyword:nth-child(9) a\'; eAt = rMb ? "p:nth-child(2)" : "div.blo_title_sak";'],
		[/^https:\/\/syosetu\.org\/\?mode=revi/, 'gMk = "HML"; eNo = rMb ? "div.search_box" : "div.section3"; eUl = null; sId = /([^\\s]+)/; eAt = rMb ? "h4" : "h3";'],
		[/^https:\/\/syosetu\.org\/novel\/[0-9]+\/$/, 'gMk = "HML"; cAp = 1; eNo = rMb ? "div.search_box" : "div.section3"; eUl = null; sId = /([^/]+)/; eAt = \'span[itemprop="author"]\';'],
		[/^https:\/\/syosetu\.org\/user\/[0-9]+\/$/, 'gMk = "HML"; cAp = 1; eNo = rMb ? "div.search_box" : "div.section3"; eUl = null; sId = /([^/]+)/; eAt = rMb ? \'h3>a\' : \'h3\';'],
		// kakuyomu
		[/^https:\/\/kakuyomu\.jp\/(picku|ranki|recen)/, 'gMk = "KYU"; eNo = "div.widget-work"; eUl = "a.widget-workCard-authorLabel"; sId = /users\\/(.*)$/; sTg = "a[itemprop=\'keywords\']";'],
		[/^https:\/\/kakuyomu\.jp\/.*\/comme/, 'gMk = "KYU"; cFt = 1; eNo = rMb ? \'div[class^="NewBox_box__"]>ul>li\' : \'ul:nth-child(1) li\'; eUl = \'div.partialGiftWidgetActivityName>a\'; sId = /users\\/(.*)$/;'],
		[/^https:\/\/kakuyomu\.jp\/.*\/episo/, 'gMk = "KYU"; cFt = 2; eOn = "#episodeFooter-cheerComments-panel-mainContents"; eNo = "ul.widget-cheerCommentList li"; eUl = "h5.widget-cheerComment-author a"; sId = /users\\/(.*)$/;'],
		[/^https:\/\/kakuyomu\.jp\/(users\/|works\/[0-9]+$)/, 'gMk = "KYU"; cFt = 1; cAp = true; eUl = uRi.includes("users") ? \'div[class^="HeaderText"]>a\' : \'div.partialGiftWidgetActivityName>a\'; sId = /users\\/(.*)$/;'],
		// Narou
		[/^https:\/\/novelcom\.syosetu\.com\/impre/, 'gMk = "NUC"; eNo = rMb ? "div.impression" : "div.waku"; eUl = "div.comment_authorbox>div>a"; sId = /\\/(\\d+)/; eAt = "div.comment_authorbox>div";'],
		[/^https:\/\/(mypage|ncode)\.syosetu\.com\/[A-z0-9]+\/$/, 'gMk = "NRK"; cAp = true; eUl = uRi.includes("ncode") ? \'div.novel_writername>a\' : \'div.p-userheader__username\'; sId = /\\/(\\d+)/;'],
		[/^https:\/\/yomou\.syosetu\.com\/rank\//, 'gMk = "NRK"; eNo = "div.p-ranklist-item"; eUl = "div.p-ranklist-item__author a"; sId = /\\/(\\d+)/; sTg = "div.p-ranklist-item__keyword a";'],
	];
	// Load site info
	function LSI() {
		for(let i = 0; i < SITE_INFO.length; i++){
			if(SITE_INFO[i][0].test(uRi)){
				eval(SITE_INFO[i][1]);
			}
		}
	}
	LSI();
	//console.log('gMk: ' + gMk + '; cFt: ' + cFt + '; cAp: ' + cAp + '; eOn: ' + eOn + '; eNo: ' + eNo + '; eUl: ' + eUl + '; sId: ' + sId + '; sTg: ' + sTg + '; eAt: ' + eAt);
	// GM menu
	GM_registerMenuCommand("View", SVM);
	GM_registerMenuCommand("Sort", UST);
	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);
	}
	// 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:
			// Mutation observer
			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 = CHK(eLk, "a", tal, uId);
		eLk.style.color = rBk ? "fuchsia" : "dodgerblue";
	}
	// 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 = CHK(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 = CHK(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";
		}
	}
	// Check keyword
	function CHK(ele, n, l, s) {
		const result = l.some((v) => s === v);
		if (!ele.classList.contains("c_h_k")) {
			ele.classList.add("c_h_k");
			ele.setAttribute("data-lkw", n + s);
		}
		if (cSv) {
			ele.style.border = result ? "thin solid fuchsia" : "thin solid dodgerblue";
		} else {
			ele.style.border = "none";
		}
		return result;
	}

	// 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%; cursor:pointer; border: none; padding: unset;";
	cButton.type = "button";
	cButton.addEventListener("click", (e) => { SVM(); });

	// Select mode
	function SVM() {
		if (!cSv) {
			cSv = true;
			cButton.textContent = "📙";
			document.addEventListener("click", ECH, true);
		} else {
			cSv = false;
			cButton.textContent = "📘";
			document.removeEventListener("click", ECH, true);
			// Auto save list
			USV();
		}
		FMD();
	}
	// Handler
	function ECH(e) {
		e.preventDefault();
		const tEle = e.target.classList.contains("c_h_k") ? e.target
					: e.target.parentElement.classList.contains("c_h_k") ? e.target.parentElement
					: null;
		//console.log(tEle);
		if (tEle) {
			const tda = tEle.getAttribute("data-lkw");
			const tlst = tda.slice(0, 1) === "a" ? tal : ttl;
			const tid = tda.slice(1);
			const li = tlst.findIndex((v) => v === tid);
			if (li !== -1) {
				tlst.splice(li,1);
			} else {
				tlst.push(tid);
			}
			FMD();
		}
	}
})();