// ==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();
}
})();