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