// ==UserScript==
// @name Content Filter
// @name:ja コンテンツフィルター
// @namespace https://greasyfork.org/en/users/1264733
// @version 2024-05-05
// @description Hide not interested content
// @description:ja 興味のない内容を隠す
// @author LE37
// @license MIT
// @include https://*
// @exclude https://kakuyomu.jp/my/*
// @enclude https://syosetu.com/favnovelmain/*
// @enclude https://www.alphapolis.co.jp/mypage/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(()=>{
'use strict';
// GM Key
let gMk;
switch (location.host) {
case "www.alphapolis.co.jp":
gMk = "APS";
break;
case "greasyfork.org":
//case "":
gMk = "GFK";
break;
case "syosetu.org":
gMk = "HML";
break;
/*case "":
gMk = "HTM";
break;*/
case "www.ign.com":
gMk = "IGN";
break;
case "kakuyomu.jp":
gMk = "KYU";
break;
/*case "":
gMk = "NNN";
break;*/
case "novelcom.syosetu.com":
gMk = "NUC";
break;
case "mypage.syosetu.com":
case "ncode.syosetu.com":
case "yomou.syosetu.com":
gMk = "NRK";
break;
/*case "":
case "":
gMk = "PHB";
break;*/
case "forum.palemoon.org":
gMk = "PMF";
break;
/*case "":
gMk = "SRB";
break;*/
case "forum.vivaldi.net":
gMk = "VVF";
break;
case "social.vivaldi.net":
gMk = "VVS";
break;
case "yandex.com":
case "www.yandex.com":
gMk = "YDX";
break;
default:
//console.log("DoNothing");
}
if (gMk) {
RUN();
}
function RUN() {
// cSr: Filting shadowroot content, only used when target within shadowroot
// 0:off[default] 1:on
let cSr = 0;
// Shadowhost, Shadowroot, used when cSr = 1
let eSh , eSr;
// cAp: Filtering author/novel page
// 0:off[default] 1:on
let cAp = 0;
// Select mode, 0:off[default] 1:on
let cSv = 0;
// cFt: Script firetime, prevent script fires too early
// 0:Normal[default] 1:ReadyState Complete 2:MutationObserver 3:IntersectionObserver
let cFt = 0;
// eOn: MutationObserver targetNode, used when cFt = 2
let eOn;
// eIo: IntersectionObserver target, used when cFt = 3
let eIo;
// eNo: target nodelist, eUl: userLink, sId: userID, sTg: tag
let eNo, eUl, sId, sTg;
// eAt: Alternate text(target's textContent), used when predefine eUl(userlink) doen't contain valid href
let eAt;
// rMb: Client type
// true:Mobile false:Desktop
const rMb = navigator.userAgent.includes("Mobile");
// cAd: Additional Delay
// 0:off[default] 1:on
let cAd = 0;
const uRi = location.href;
switch (gMk) {
case "APS":
// Alphapolis
if (uRi.includes("comment")) {
// Comments
eNo = "div.comment";
eUl = "span.name>a";
} else if (uRi.includes("index") || uRi.includes("ranking")) {
// Ranking
eNo = "div.section";
eUl = "div.author>a";
sTg = "li.tag a";
} else if (uRi.includes("author") || (/novel[0-9\/]+$/).test(uRi)) {
// Author Page
cAp = 1;
eUl = uRi.includes("author") ? "div.name>h1" : "div.author a";
}
sId = /detail\/(\d+)$/;
break;
case "GFK":
// Greasyfork
if (uRi.includes("/scripts")) {
// Scripts
eNo = "li[data-script-id]";
// Script link
eUl = "a.script-link";
// Script authors
sTg = "dd.script-list-author a";
} else if (uRi.includes("/discussions")) {
// Discussions
eNo = "div.discussion-list-container";
// Discussion link
eUl = "a.script-link";
// Discussion author
sTg = "a.user-link";
}
sId = /s\/(\d+)/;
break;
case "HML":
// Hameln
eNo = rMb ? "div.search_box" : "div.section3";
if (uRi.includes("rank")) {
// Ranking
eUl = null;
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("review")) {
// Comments
eUl = null;
eAt = rMb ? "h4" : "h3";
sId = /([^\s]+)/;
} else if ((/novel|user\/\d+\/$/).test(uRi)) {
// Author Page
cAp = 1;
eUl = null;
if (/novel\/\d+\/$/.test(uRi)) {
eAt = 'span[itemprop="author"]'
} else {
eAt = rMb ? 'h3>a' : 'h3';
}
sId = /([^/]+)/;
}
break;
/*case "HTM":
//
cFt = 2;
eOn = "div.gallery-content";
eNo = "div.gallery-content>div";
eUl = "table.dj-desc tr:nth-child(3) td:nth-child(2) a";
sId = /index-(\w+)\.html/;
sTg = "td.relatedtags>ul>li";
break;*/
case "IGN":
// IGN
cSr = 1;
cFt = 2;
eOn = 'body';
eNo = "li";
eUl = null;
eAt = 'span[data-spot-im-class="message-username"]';
sId = /(.*)/;
break;
case "KYU":
// Kakuyomu
if (uRi.includes("/pickup") || uRi.includes("/rank") || uRi.includes("/recent")) {
// Ranking
eNo = "div.widget-work";
eUl = "a.widget-workCard-authorLabel";
sId = /users\/(.*)$/;
sTg = "a[itemprop='keywords']";
} else if (uRi.includes("comments")) {
// Comments
cAd = 1;
eNo = rMb ? 'div[class^="NewBox_box__"]>ul>li' : 'ul:nth-child(1) li';
eUl = 'div.partialGiftWidgetActivityName>a';
} else if (uRi.includes("episodes")) {
// Comments in 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 Page
cAd = 1;
cAp = 1;
eUl = uRi.includes("users") ? 'div[class^="HeaderText"]>a' : 'div.partialGiftWidgetActivityName>a';
}
sId = /users\/(.*)$/;
break;
/*case "NNN":
//
eNo = rMb ? "ul.ranking" : "div.rank_h";
eUl = null;
eAt = rMb ? "li:nth-child(2)" : "span.name";
sId = /.{3}(.*)/;
sTg = rMb ? "li.keyword a" : "td.s a";
break;*/
case "NUC":
// Narou Comments
eNo = rMb ? "div.impression" : "div.waku";
eUl = "div.comment_authorbox>div>a";
eAt = "div.comment_authorbox>div";
sId = /\/(\d+)/;
break;
case "NRK":
// Narou Ranking
if (uRi.includes("mypage") || uRi.includes("ncode")) {
// Author Page
cAp = 1;
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;
/*case "PHB":
//
eNo = rMb ? "div.videoWrapper" : "div.wrap";
eUl = rMb ? "a.uploaderLink" : "div.usernameWrap a";
sId = /([^\/]+)$/;
break;*/
case "PMF":
// Palemoon Forum
if (uRi.includes("viewtopic")) {
// Topic
eNo = "#page-body div.post";
eUl = 'a[class^="username"]';
sId = /u=(\d+)/;
} else {
// Index
eNo = "ul.topiclist>li";
eUl = "div.topic-poster>a";
sId = /u=(\d+)/;
}
break;
/*case "SRB":
//
if (uRi.includes("thread")) {
// Thread
eNo = rMb ? 'div[id^="pid"]' : 'div[id^="post_"]:not([id^="post_rate"]):not([id^="post_new"])';
eUl = null;
eAt = rMb ? "ul.authi a" : "a.xw1";
sId = /(.*)/;
} else {
// Index
eOn = "#threadlisttableid";
eNo = rMb ? "div.threadlist>ul>li" : "table#threadlisttableid tbody";
eUl = null;
eAt = rMb ? "span.by" : "td:nth-child(3)>cite>a";
sId = /(.*)/;
}
break;*/
case "VVF":
// Vivaldi Forum
if (uRi.includes("topic")) {
// Topic
eNo = "ul.posts>li";
eUl = "small.d-flex a";
sId = /user\/(.*)/;
} else {
// Index
eNo = "ul.topic-list li";
eUl = "small.hidden-xs>a";
sId = /user\/(.*)/;
}
break;
case "VVS":
// Vivaldi Social
cFt = 2;
eOn = "body";
eIo = ".load-more";
eNo = "div.item-list>article";
eUl = null;
eAt = "strong.display-name__html";
sId = /(.*)/;
break;
case "YDX":
// Yandex Search
eNo = rMb ? "div.serp-item" : "#search-result>li";
eUl = rMb ? null : "div.Path>a.Link";
eAt = "span.Path-Item>b";
sId = rMb ? /(.*)/ : /\/([^\/]+)/;
break;
}
// 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
// mapsort???
function UST() {
tal.sort();
ttl.sort();
USV();
}
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Script Fire Time
switch (cFt) {
case 1:
// ReadyState complete
RSC();
break;
case 2:
// MutationObserver
MOC();
break;
case 3:
// IntersectionObserver
IOC();
break;
case 0:
default:
if (cAd) {
// Delay
wait(1500).then(() => FMD());
} else {
// Normal
FMD();
}
/*
if (gMk === "SRB" && !rMb && !uRi.includes("thread")) {
MOC();
}*/
}
// ReadyState complete
function RSC() {
document.addEventListener("readystatechange", (e) => {
if (e.target.readyState === "complete") {
//console.log('RSC: Complete');
}
});
}
// MutationObserver
function MOC() {
if (gMk === "KYU") {
// Comments in Episode
// Button load comments
const bLc = document.querySelector('#episodeFooter-action-cheerCommentsButton');
bLc.addEventListener("click", (e) => {
waitForElement(eNo, 2000).then(() => {
//console.log('MOC: Ready');
FTR();
}).catch(() => {
//console.log('MOC: Timeout');
});
});
} else {
waitForElement(eNo, 30000).then(() => {
//console.log('MOC: Ready');
FMD();
// IGN news
if (gMk === "IGN") {
// Button load more messages
const bLm = eSr.querySelector('.spcv_load-more-messages');
bLm.addEventListener("click", (e) => {
wait(2000).then(() => FTR());
});
}
// Vivaldi Social
if (gMk === "VVS") {
wait(1500).then(() => IOC());
}
}).catch(() => {
//console.log('MOC: Timeout');
});
}
}
// Wait for an element to be loaded
function waitForElement(selector, timeout) {
return new Promise((resolve, reject) => {
var timer = false;
// Spot im shadownode
if (cSr) {
if (eSr) {
if (eSr.querySelectorAll(selector).length) {
return resolve();
}
}
} else {
if (document.querySelectorAll(selector).length) return resolve();
}
const obs = new MutationObserver(mutations => {
// Spot im shadownode
if (cSr) {
eSh = document.querySelector('div[data-spotim-module]').firstElementChild;
if (eSh) {
eSr = eSh.shadowRoot;
if (eSr) {
if (eSr.querySelectorAll(selector).length) {
obs.disconnect();
if (timer !== false) clearTimeout(timer);
return resolve();
}
}
}
} else {
if (document.querySelectorAll(selector).length) {
obs.disconnect();
if (timer !== false) clearTimeout(timer);
return resolve();
}
}
});
// Spot im shadownode
const obn = eSr ? eSr.querySelectorAll('.spcv_conversation')[0] : document.querySelector(eOn);
obs.observe(obn, {
childList: true,
subtree: true
});
if (timeout) {
timer = setTimeout(() => {
obs.disconnect();
reject();
}, timeout);
}
});
}
// IntersectionObserver
function IOC() {
const ioc = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio <= 0) return;
ioc.disconnect();
// Vivaldi Social
if (gMk === "VVS") {
wait(1500).then(() => MOC());
}
});
ioc.observe(document.querySelector(eIo));
}
// Filtering mode
function FMD() {
if (cAp) {
// Filtering single target
FAP();
} else {
// Filtering multiple targets
FTR();
}
}
// Filtering single target
function FAP() {
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, tal, uId);
eLk.style.opacity = rBk ? "0.5" : "1";
eLk.style.color = rBk ? "red" : "lime";
}
// Filtering multiple targets
function FTR() {
const no = cSr ? eSr.querySelectorAll(eNo) : 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" || gMk === "VVS") {
// Narou nologin user fix
// Vivaldi Social element out of view fix
if (!eLk) {
eLk = gMk === "VVS" ? no[i].querySelector("span") : no[i].querySelector(eAt);
uId = gMk === "VVS" ? eLk.textContent.match(sId)[1].replace(/\s/g,'') : eLk.textContent.split("\n")[2];
} else {
uId = eUl ? eLk.href.match(sId)[1] : eLk.textContent.match(sId)[1];
// Vivaldi Social id fix for foreground & background
if (gMk ==="VVS") {
let emoji = "";
const ino = no[i].querySelectorAll(eAt + " img");
if (ino) {
for (let k = 0; k < ino.length; k++) {
emoji += ino[k].alt;
}
}
uId = eLk.textContent.match(sId)[1] + emoji;
uId = uId.replace(/\s/g,'');
}
}
//console.log(uId);
// Vivaldi Social use static no[i] instead of dynamic eLk
rBk = gMk === "VVS" ? CHK(no[i], tal, uId) : CHK(eLk, tal, uId);
}
//const eNes = no[i].nextElementSibling;
if (sTg && !rBk) {
// Filtering content contain multiple tags(text)
// Tag node
let tno;
// Hameln mobile origin tag, custom tag
let tot, tct;
if (gMk === "HML" && rMb) {
tot = no[i].querySelector(".trigger p:nth-child(4)");
tct = no[i].querySelector(sTg);
if (!tct) {
tno = tot.textContent.slice(3).match(/[^\s]+/g);
tot.innerHTML = "";
} else {
tno = no[i].querySelectorAll(sTg);
}
} else {
// NNN desktop fix
tno = no[i].querySelectorAll(sTg);//gMk === "NNN" && !rMb ? eNes.querySelectorAll(sTg) : no[i].querySelectorAll(sTg);
}
for (let j = 0; j < tno.length; j++) {
let tag;
if (tot && !tct) {
tag = tno[j];
tot.innerHTML += '<span id="tag_' + j + '">' + tag + '</span>';
} else {
// Greasyfork fix
tag = gMk === "GFK" ? tno[j].href.match(sId)[1] : tno[j].textContent;
}
//console.log(tag);
/* HTM hidden tag fix
if (gMk === "HTM" && tno[j].classList.length !== 0 || tag === "...") {
break;
}*/
rBk = tot && !tct ? CHK(no[i].querySelector("span#tag_"+j), ttl, tag) : CHK(tno[j], ttl, tag);
if (rBk) {
break;
}
}
}
// Blocked Show Type
if (cSv === 0) {
no[i].style.display = rBk ? "none" : "";
no[i].style.opacity = "1";
/* NNN desktop fix
if (gMk === "NNN" && !rMb) {
eNes.style.display = rBk ? "none" : "";
eNes.style.opacity = "1";
}*/
} else {
no[i].style.display = "";
no[i].style.opacity = rBk ? "0.5" : "1";
/* NNN desktop fix
if (gMk === "NNN" && !rMb) {
eNes.style.display = "";
eNes.style.opacity = rBk ? "0.5" : "1";
}*/
}
}
}
// CheckKeyword
function CHK(ele, l, s) {
const result = l.some((v) => s === v);
if (cSv === 1) {
ele.style.border = result ? "thin solid fuchsia" : "thin solid dodgerblue";
} else {
ele.style.border = "none";
}
return result;
}
// Select mode
function SVM() {
if (cSv === 0) {
cSv = 1;
// Disable default click
document.addEventListener("click", PAC, true);
} else {
cSv = 0;
// Enable default click
document.removeEventListener("click", PAC, true);
// Auto save list
USV();
}
FMD();
}
// PreventAnchorChange
function PAC(e) {
e.preventDefault();
// Vivaldi Forum & Social fix
if (gMk === "VVF" || gMk === "VVS") {
e.stopPropagation();
}
const targetElement = cSr ? e.composedPath()[0] : e.target;
//console.log(targetElement);
let eLk;
// Narou nologin user fix
if (gMk === "NUC") {
eLk = targetElement.href ? eUl : eAt;
} else {
eLk = eUl ? eUl : eAt;
}
// StopPropagation fix
if (targetElement.closest("#cFbtn")) {
SVM;
} else if (targetElement.closest(eLk)) {
let ai;
switch (gMk) {
// Narou author page fix
case "NRK":
if (uRi.includes("mypage")) {
// Author Page
ai = uRi.match(sId)[1];
} else {
ai = eUl ? targetElement.href.match(sId)[1] : targetElement.textContent.match(sId)[1];
}
break;
// Narou nologin user fix
case "NUC":
ai = targetElement.href ? targetElement.href.match(sId)[1] : targetElement.textContent.split("\n")[2];
break;
// Vivaldi Social different id fix
case "VVS":
let emoji = "";
const ino = targetElement.parentElement.querySelectorAll(eAt + " img");
if (ino) {
for (let k = 0; k < ino.length; k++) {
emoji += ino[k].alt;
}
}
ai = targetElement.textContent.match(sId)[1] + emoji;
ai = ai.replace(/\s/g,'');
break;
// Yandex fix
case "YDX":
ai = targetElement.href ? targetElement.href.match(sId)[1] : targetElement.parentElement.href.match(sId)[1];
break;
default:
ai = eUl ? targetElement.href.match(sId)[1] : targetElement.textContent.match(sId)[1];
}
//console.log(ai);
UTL(e, ai, tal);
FMD();
} else if (targetElement.closest(sTg)) {
// Greasyfork fix
const kd = gMk === "GFK" ? targetElement.href.match(sId)[1] : targetElement.textContent;
//console.log(kd);
UTL(e, kd, ttl);
FMD();
}
// IGN Popup temp fix
if (gMk === "IGN") {
wait(500).then(() => {
const bsh = document.body.lastChild.shadowRoot;
if (bsh) {
const bsr = bsh.querySelector('button[title="Close the modal"]');
if (bsr) {
bsr.click();
}
}
});
}
return false;
}
// UpdateTempList
function UTL(e, s, l) {
const li = l.findIndex((v) => v === s);
if (li !== -1) {
l.splice(li,1);
} else {
l.push(s);
}
//console.log(l);
return l;
}
// Create Float Button
const cButton = document.body.appendChild(document.createElement("button"));
// Button Style
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%;";
cButton.type = "button";
cButton.addEventListener("click", (e) => {
SVM();
});
// Vivaldi Social CSP temp fix
if (gMk === "VVF" || gMk === "VVS") {
cButton.addEventListener("dblclick", (e) => {
cSv = 1;
SVM();
});
}
}
})();