Greasy Fork

Greasy Fork is available in English.

Novel Ranking/Comments Filter

Hide not interested content on ranking/comments page

当前为 2024-05-11 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           Novel Ranking/Comments Filter
// @name:ja        小説ランキング/コメント・フィルター
// @namespace      http://greasyfork.icu/en/users/1264733
// @version        2024-05-11
// @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("span");
			bTn.classList = "bbtn";
			bTn.type = "button";
			bTn.setAttribute("data-l", n);
			bTn.setAttribute("data-k", s);
			ele.after(bTn);
		}
		// Button Style
		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();
		}
	}
	function SVM() {
		cSv = !cSv;
		FMT();
	}
})();