Novel Ranking/Comments Filter

Hide not interested content on ranking/comments page

Version vom 02.06.2024. Aktuellste Version

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name           Novel Ranking/Comments Filter
// @name:ja        小説ランキング/コメント・フィルター
// @namespace      https://greasyfork.org/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();
		}
	}
})();