Greasy Fork

Greasy Fork is available in English.

Novel Ranking Filter

Alphapolis Hameln Kakuyomu Narou Ranking Page Filtering by AuthorID and Tag

目前为 2024-03-11 提交的版本,查看 最新版本

// ==UserScript==
// @name           Novel Ranking Filter
// @name:ja        小説ランキングフィルター
// @namespace      http://greasyfork.icu/en/users/1264733
// @version        2024-03-10
// @description    Alphapolis Hameln Kakuyomu Narou Ranking Page Filtering by AuthorID and Tag
// @description:ja アルファポリス・ハーメルン・カクヨム・なろう 作者IDとタグによるランキングページの小説フィルタリング
// @author         LE37
// @license        MIT
// @include        https://www.alphapolis.co.jp/novel/index*
// @include        https://www.alphapolis.co.jp/novel/ranking/*
// @include        https://kakuyomu.jp/rankings/*
// @include        https://kakuyomu.jp/*recent_works
// @include        https://syosetu.org/?mode=rank*
// @include        https://yomou.syosetu.com/rank/*
// @exclude        https://www.alphapolis.co.jp/novel/ranking/annual
// @exclude        https://yomou.syosetu.com/rank/top/
// @grant          GM_setValue
// @grant          GM_getValue
// ==/UserScript==

(function() {
	'use strict';
	// a_key: AuthorListKey, a_lk: AuthorLink, a_re: RegForAuthorID, n_nc: NovelNode, t_nc: Tag, s_type: ShowType, a_lst: DislikedAuthorList, t_lst: DislikedTagList;
	let a_key, a_lk, a_re, n_nc, t_nc, s_type, a_lst, t_lst;
	switch (location.host) {
		case "www.alphapolis.co.jp":
			a_key = "Alphapolis";
			a_lk = "div.author>a:nth-child(1)";
			a_re = /detail\/(\d+)$/;
			n_nc = "div.section";
			t_nc = "li.tag a";
			/*AlphapolisBegin*/
			s_type = 0;
			a_lst = [];
			t_lst = [];
			/*AlphapolisEnd*/
			break;
		case "syosetu.org":
			a_key = "Hameln";
			a_lk = "div.blo_title_sak a";
			a_re = /user\/(\d+)/;
			n_nc = "div.section3";
			t_nc = "div.all_keyword:nth-child(9) a";
			/*HamelnBegin*/
			s_type = 0;
			a_lst = [];
			t_lst = [];
			/*HamelnEnd*/
			break;
		case "kakuyomu.jp":
			a_key = "Kakuyomu";
			a_lk = "a.widget-workCard-authorLabel";
			a_re = /users\/(.*)$/;
			n_nc = "div.widget-work";
			t_nc = "a[itemprop='keywords']";
			/*KakuyomuBegin*/
			s_type = 0;
			a_lst = [];
			t_lst = [];
			/*KakuyomuEnd*/
			break;
		case "yomou.syosetu.com":
			a_key = "Narou";
			a_lk = "div.p-ranklist-item__author a";
			a_re = /\/(\d+)/;
			n_nc = "div.p-ranklist-item";
			t_nc = "div.p-ranklist-item__keyword a";
			/*NarouBegin*/
			s_type = 0;
			a_lst = [];
			t_lst = [];
			/*NarouEnd*/
			break;
		default:
			//console.log("Unknown Host");
	}
	// CustomCss Default
	let c_css = (`/*CssBegin: Default Css, U can Edit them here if u know how to do. Click 📝 again will Apply&Save new style. If menu stop showing up after edit then goto ScriptsManager's settings page to delete incorrect "c_css" value. Do not delete this line.*/
		/* NormalMode */
		.nm_bgc { background-color: #C0C0C0; }
		.nm_blr { opacity: 36%; }
		.nm_hid { display: none; }
		/* SelectMode */
		.sm_bgc { background-color: #0099FF; }
		/* NavBar */
		.bd_nav { position: fixed; top: 16%; left: 19%; width: 62%; height: 44px; z-index: 9999; }
		/* All Buttons */
		.bd_ico { width: 44px; height: 44px; font-size: 200%; }
		/* 📘 Button */
		#bd_mi  { opacity: 50%; }
		/* Text Area */
		#bd_ta  { background-color: #55ACEE; max-height: 280px; overflow: hidden; padding: 2%; }
		#bd_ta:focus { color: lawngreen; background-color: #222; overflow: scroll; }
	/*Do not delete this line. CssEnd*/`);
	// AutoSave: false Off true On
	let a_sav = true;
	// Load stored values
	if (GM_getValue("ShowType") !== undefined) {
		s_type = GM_getValue("ShowType");
		//console.log("ShowType: " + s_type);
	}
	if (GM_getValue(a_key) !== undefined) {
		a_lst = GM_getValue(a_key);
		//console.log(a_key + " AuthorID List loaded: " + a_lst);
	}
	if (GM_getValue("Tags") !== undefined) {
		t_lst = GM_getValue("Tags");
		//console.log("Tag List loaded: " + t_lst);
	}
	if (GM_getValue("StyleSheet") !== undefined) {
		c_css = GM_getValue("StyleSheet");
		//console.log("StyleSheet loaded: " + c_css);
	}
	const addCSS = (() => {
		const css = document.createElement('style');
		document.head.appendChild(css);
		return (styleString) => css.textContent = styleString;
	})();
	addCSS(c_css);
	// NormalMode
	const no = document.querySelectorAll(n_nc);
	nmode();
	function nmode() {
		let i = no.length;
		while (i--) {
			let dislike = false;
			const al = no[i].querySelector(a_lk);
			// Hameln: No AuthorLink
			if (al !== null) {
				const aid = al.href.match(a_re)[1];
				//console.log(aid);
				if (a_lst.some(v => aid.includes(v))) {
					dislike = true;
					al.classList.add("nm_bgc");
				} else {
					al.classList.remove("nm_bgc");
				}
			}
			if (dislike === false) {
				const kl = no[i].querySelectorAll(t_nc);
				// All: No Tag
				if (kl !== null) {
					let k = kl.length;
					while (k--) {
						const kwd = kl[k];
						//console.log(kwd);
						if (t_lst.some(v => kwd.text.includes(v))) {
							dislike = true;
							kwd.classList.add("nm_bgc");
							break;
						} else {
							kwd.classList.remove("nm_bgc");
						}
					}
				}
			}
			if (dislike === true) {
				switch (s_type) {
					case 0:
						no[i].classList.remove("nm_hid");
						no[i].classList.add("nm_blr");
						break;
					case 1:
						no[i].classList.add("nm_hid");
						break;
					default:
						console("Unknown ShowType");
				}
			} else {
				// Novel isn't on any list
				//no[i].style.backgroundColor = "#00FFFF";
				no[i].classList.remove("nm_blr");
				no[i].classList.remove("nm_hid");
			}
		}
	}
	// CustomMenu
	const bd_bar = document.createElement("div");
	bd_bar.innerHTML =  '<nav class="bd_nav">' +
							'<button id="bd_mi" class="bd_ico" type="button">📘</button>' + 
							'<button id="bd_st" class="bd_cmd bd_ico" type="button">👀</button>' + 
							'<button id="bd_sm" class="bd_cmd bd_ico" type="button">💮</button>' + 
							'<button id="bd_ce" class="bd_cmd bd_ico" type="button">📝</button>' + 
							'<button id="bd_cp" class="bd_cmd bd_ico" type="button">💾</button>' + 
							'<p id="bd_ta" contenteditable>' + 
							a_key + ':<br />👀 View 💮 Select 📝Style 💾 Option' + 
							'</p>' + 
						'</nav>';
	document.body.appendChild(bd_bar);
	const bd_st = document.getElementById("bd_st");
	bd_st.style.visibility = "hidden";
	const bd_sm = document.getElementById("bd_sm");
	bd_sm.style.visibility = "hidden";
	const bd_ce = document.getElementById("bd_ce");
	bd_ce.style.visibility = "hidden";
	const bd_cp = document.getElementById("bd_cp");
	bd_cp.style.visibility = "hidden";
	const bd_ta = document.getElementById("bd_ta");
	bd_ta.style.visibility = "hidden";
	const bd_mi = document.getElementById("bd_mi");
	bd_mi.addEventListener("click", cMenu, true);
	function cMenu() {
		const bd = document.getElementsByClassName("bd_cmd");
		let bd_func;
		for (let j=0;j<bd.length;j++) {
			switch (bd[j].id) {
				case "bd_st":
					bd_func = stype;
					break;
				case "bd_sm":
					bd_func = smode;
					break;
				case "bd_ce":
					bd_func = cedit;
					break;
				case "bd_cp":
					bd_func = scopy;
					break;
				default:
					//console.log("Unknown Funciton");
			}
			if (bd[j].style.visibility === "hidden") {
				bd[j].style.visibility = "visible";
				bd[j].addEventListener("click", bd_func, true);
			} else {
				bd[j].style.visibility = "hidden";
				bd[j].removeEventListener("click", bd_func, true);
			}
		}
		if (bd_ta.style.visibility === "hidden") {
			bd_ta.style.visibility = "visible";
		} else {
			bd_ta.style.visibility = "hidden";
		}
	}
	// SelectMode: 0 Off 1 On
	let s_mode = 0;
	const addECSS = (() => {
		const ecss = document.createElement('style');
		document.head.appendChild(ecss);
		return (styleString) => ecss.textContent = styleString;
	})();
	function smode() {
		//console.log(a_key + ": " + a_lst);
		//console.log("Tags: " + t_lst);
		let sCss;
		if (s_mode === 0) {
			s_mode = 1;
			// Disable default click
			document.addEventListener("click", DChandler, true);
			sCss = a_lk + ", " + t_nc + "{ border: thin solid #0000FF; }";
			bd_ta.innerText = 'SelectMode: On.\r\nClick Author/Tag(blue box) to Add/Remove.\r\nClick 💮 again to return to NormalMode.';
		} else {
			s_mode = 0;
			// Restore default click
			document.removeEventListener("click", DChandler, true);
			// Clear remain selected elements's background color
			const et_no = document.getElementsByClassName("sm_bgc");
			let i = et_no.length;
			while (i--) {
				et_no[i].classList.remove("sm_bgc");
			}
			sCss = a_lk + ", " + t_nc + " { border: none; }";
			nmode();
			bd_ta.innerText = 'SelectMode: Off.';
		}
		addECSS(sCss);
	}
	function DChandler(e) {
		if (e.target.matches(a_lk)) {
			e.preventDefault();
			e.target.classList.add("sm_bgc");
			const aid = e.target.href.match(a_re)[1];
			//console.log(aid);
			if (a_lst.some(v => aid.includes(v))) {
				const a_i = a_lst.findIndex(x => x === aid);
				a_lst.splice(a_i,1);
				//console.log(a_i, a_lst);
				if (a_sav === true) {
					GM_setValue(a_key, a_lst);
				}
				e.target.classList.remove("sm_bgc");
				nmode();
			} else {
				a_lst.push(aid);
				//console.log(a_key + ": " + a_lst);
				if (a_sav === true) {
					GM_setValue(a_key, a_lst);
				}
				nmode();
			}
			bd_ta.innerText = 'a_lst = [' + a_lst + '];';
		} else if (e.target.closest(t_nc)) {
			e.preventDefault();
			e.target.classList.add("sm_bgc");
			const kwd = e.target.textContent;
			//console.log(kwd);
			if (t_lst.some(v => kwd.includes(v))) {
				const k_i = t_lst.findIndex(x => x === kwd);
				t_lst.splice(k_i,1);
				//console.log(k_i, t_lst);
				if (a_sav === true) {
					GM_setValue("Tags", t_lst);
				}
				e.target.classList.remove("sm_bgc");
				nmode();
			} else {
				t_lst.push(kwd);
				//console.log("Tags: " + t_lst);
				if (a_sav === true) {
					GM_setValue("Tags", t_lst);
				}
				nmode();
			}
			bd_ta.innerText = 't_lst = [' + t_lst + '];';
		}
		return false;
	}
	function cedit() {
		if (bd_ta.innerText.startsWith("/*Css") === false) {
			bd_ta.innerText = c_css;
		} else {
			addCSS(bd_ta.innerText);
			c_css = bd_ta.innerText;
			if (a_sav === true) {
				GM_setValue("StyleSheet", c_css);
			}
		}
	}
	function scopy() {
		const copt = "/*" + a_key;
		if (bd_ta.innerText.startsWith(copt) === false) {
			//console.log("Current Settings");
			bd_ta.innerText = '/*' + a_key + 'Begin: Current Settings/Values, U can Edit them here if u know how to do. Click 💾 again to Apply&Save new settings. Delete a list u just need replace that line with a empty line, So delete both author list and tag list u will need 2 empty line. If script stop running after edit then goto ScriptsManager settings page to delete incorrect values. Do not delete this line.*/\r\nShowType=' + s_type + ';\r\nAuthorList=' + a_lst + ';\r\nTagList=' + t_lst + ';\r\n/*Do not delete this line. ' + a_key + 'End*/';
		} else {
			try {
				let tc = bd_ta.innerText.split('\n');
				let t_st = tc[1].slice(9, -1);
				let t_ak = tc[2].slice(11, -1);
				let t_tg = tc[3].slice(8, -1);
				// Save temp values to storge
				if (t_st !== null && t_st !== "") {
					GM_setValue("ShowType", parseInt(t_st));
				} else {
					GM_setValue("ShowType", 0);
				}
				if (t_ak !== null && t_ak !== "") {
					GM_setValue(a_key, t_ak.split(','));
				} else {
					t_ak = [];
					GM_setValue(a_key, t_ak);
				}
				if (t_tg !== null && t_tg !== "") {
					GM_setValue("Tags", t_tg.split(','));
				} else {
					t_tg = [];
					GM_setValue("Tags", t_tg);
				}
				// Reload temp values from storge
				s_type = GM_getValue("ShowType");
				a_lst = GM_getValue(a_key);
				t_lst = GM_getValue("Tags");
				bd_ta.innerText = '=== Settings Save Complete ===';
				nmode();
			} catch (error) {
				console.error(error.message);
				bd_ta.innerText = "=== Settings Save Failed ===";
			}
		}
	}
	function stype() {
		if (s_type === 0) {
			s_type = 1;
		} else {
			s_type = 0;
		}
		if (a_sav === true) {
			GM_setValue("ShowType", s_type);
		}
		bd_ta.innerText = 's_type = ' + s_type + ';\r\nShowType for disliked novels, Click 👀 to switch between Blur / Hide';
		nmode();
	}
})();