// ==UserScript==
// @name Novel Unreads Highlight
// @name:ja 未読小説をハイライトする
// @namespace https://greasyfork.org/en/users/1264733
// @version 2024-05-22
// @description Add new color to novel which have more unread counts On Kakuyomu / Narou / Alphapolis's Favorite Page
// @description:ja アルファポリス・カクヨム・なろうの気に入りページで、未読数が多い小説に色分けを追加する。
// @author LE37
// @license MIT
// @include /^https:\/\/kakuyomu\.jp\/my\/antenna\/works/
// @include /^https:\/\/kakuyomu\.jp\/works\/[0-9]+\/episodes\/[0-9]+(#[^\/]+)?$/
// @include /^https:\/\/syosetu\.com\/favnovelmain\/list\//
// @include /^https:\/\/ncode\.syosetu\.com\/[A-z0-9]+\/[0-9]+\/$/
// @include /^https:\/\/www\.alphapolis\.co\.jp\/mypage\/notification\/index\/110000/
// @include /^https:\/\/www\.alphapolis\.co\.jp\/novel\/[0-9]+/[0-9]+/episode/[0-9]+$/
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(()=>{
'use strict';
// Settings
// Auto Cheering: 0 Off 1 On
const sCheer = 1;
let gMk;
switch (location.host) {
case "kakuyomu.jp":
gMk = "HUN_K";
break;
case "ncode.syosetu.com":
case "syosetu.com":
gMk = "HUN_N";
break;
case "www.alphapolis.co.jp":
gMk = "HUN_A";
break;
}
// GM Menu
GM_registerMenuCommand("Author", ADA);
GM_registerMenuCommand("Unread", SUN);
GM_registerMenuCommand("Colour", SUC);
// Read List
const URD = GM_getValue(gMk);
let tlo = URD ? URD : { FAC: "indigo", FCC: "orange", FUC: "red", FAU: 3, FAL:[] };
let tac = tlo.FAC;
let tcc = tlo.FCC;
let tuc = tlo.FUC;
let tau = tlo.FAU;
const tal = tlo.FAL;
// Save List
function USV() {
tlo = { FAC: tac, FCC: tcc, FUC: tuc, FAU: tau, FAL:tal };
GM_setValue(gMk, tlo);
}
// Set Fav Author
let sFa = false;
// Set Fav Colour
let sFc = false;
const uRi = location.href;
let fAuthor;
if ( uRi.includes("/my/") || uRi.includes("/favnovelmain/") || uRi.includes("/mypage/") ) {
FAV();
CBT();
CMU();
} else {
EPI();
}
// Episode Page
function EPI() {
let eAuthorSource, eCheerButton, eCheerButtonTag, eIsCheering;
let rMf = false;
switch (gMk) {
case "HUN_K":
eAuthorSource = document.title;
eCheerButton = "button#episodeFooter-action-cheerButton";
eCheerButtonTag = document.querySelector(eCheerButton);
eIsCheering = parseInt(eCheerButtonTag.getAttribute("data-is-cheering"));
if ( eIsCheering === 0 && tal.some(name => eAuthorSource.includes('(' + name + ') -')) ) {
rMf = true;
}
break;
case "HUN_N":
eAuthorSource = document.querySelector('div.contents1 a:nth-child(2)').textContent;
eCheerButton = "a.js-novelgood_change";
eCheerButtonTag = document.querySelector(eCheerButton);
eIsCheering = document.querySelector("div.is-empty") ? 0 : 1;
if ( eIsCheering === 0 && tal.some(name => eAuthorSource.includes(name)) ) {
rMf = true;
}
break;
case "HUN_A":
eAuthorSource = uRi;
eCheerButton = "div#contentMangaLikeBtnCircle";
eCheerButtonTag = document.querySelector(eCheerButton);
eIsCheering = parseInt(document.querySelector("div.content-manga-my-current-like-count").textContent);
if ( eIsCheering === 0 && tal.some(name => eAuthorSource.includes(name)) ) {
rMf = true;
}
break;
}
const ioc = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio <= 0) return;
ioc.disconnect();
if (rMf) {
eCheerButtonTag.style.backgroundColor = tcc;
if (sCheer === 1) {
eCheerButtonTag.click();
//console.log("===いいね===");
}
}
});
ioc.observe(eCheerButtonTag);
}
// Favorite Page
function FAV() {
let fNode, fUnreadCount;
switch (gMk) {
case "HUN_K":
fAuthor = "p.widget-antennaList-author";
fNode = "li.widget-antennaList-item";
fUnreadCount = "li.widget-antennaList-unreadEpisodeCount";
break;
case "HUN_N":
fAuthor = "div.p-up-bookmark-item__author>a";
fNode = "li.p-up-bookmark-item";
fUnreadCount = "span.p-up-bookmark-item__unread-num";
break;
case "HUN_A":
fAuthor = "h2.title>a";
fNode = "div.content-main";
fUnreadCount = "a.disp-order";
break;
}
const tNode = document.querySelectorAll(fNode);
for(let i = 0; i < tNode.length; i++) {
const fAuthorTag = tNode[i].querySelector(fAuthor);
const fAuthorName = (gMk === "HUN_A") ? fAuthorTag.href.match(/\d+$/)[0] : fAuthorTag.textContent;
fAuthorTag.style.color = CHK(fAuthorTag, fAuthorName) ? tac : "";
const tUnreadCount = tNode[i].querySelector(fUnreadCount);
const fCurrent = (gMk === "HUN_A") && tUnreadCount ? parseInt(tUnreadCount.textContent.match(/[0-9]+/)[0]) : 0;
let tUnreadNum;
if (tUnreadCount) {
tUnreadNum = (gMk === "HUN_K") ? parseInt(tUnreadCount.textContent.match(/[0-9]+/)[0])
: (gMk === "HUN_N") ? parseInt(tUnreadCount.textContent)
: parseInt(tNode[i].querySelector("a.total").textContent.match(/[0-9]+/)[0]) - fCurrent;
} else {
tUnreadNum = 0;
}
const fUnreadColor = CHK(fAuthorTag, fAuthorName) ? tac
: tUnreadCount && tUnreadNum > tau ? tuc
: "";
if (tUnreadCount) {
if (gMk === "HUN_K") {
const resume = tNode[i].querySelector("a.widget-antennaList-continueReading").href;
tUnreadCount.innerHTML = '<a href="' + resume + '" style="color:' + fUnreadColor + ';">' + tUnreadCount.textContent + '</a>';
} else if (gMk === "HUN_N") {
tNode[i].querySelector("span.p-up-bookmark-item__unread").style.color = fUnreadColor;
} else {
tNode[i].querySelector(fUnreadCount).style.color = fUnreadColor;
}
} else {
if (gMk === "HUN_A") {
tNode[i].querySelector(fAuthor).style.color = tuc;
}
}
}
}
// Check Author Name
function CHK(elem, s) {
const result = tal.some((v) => s === v);
if (sFa) {
elem.style.border = result ? "thin solid fuchsia" : "thin solid dodgerblue";
} else {
elem.style.border = "none";
}
return result;
}
// Add Fav Author
function ADA() {
if (!sFa) {
sFa = true;
document.addEventListener("click", AAH, true);
} else {
sFa = false;
document.removeEventListener("click", AAH, true);
USV();
}
document.getElementById("cFbtn").textContent = sFa ? "💖" : "💟";
FAV();
}
// Add Author Handler
function AAH(e) {
e.preventDefault();
if (e.target.closest(fAuthor)) {
if (gMk === "HUN_A") {
UTL(e, e.target.href.match(/\d+$/)[0]);
} else {
UTL(e, e.target.textContent);
}
FAV();
}
return false;
}
// Update Temp List
function UTL(e, s) {
const i = tal.findIndex((v) => v === s);
if (i !== -1) {
tal.splice(i,1);
} else {
tal.push(s);
}
//console.log(tal);
return tal;
}
// Set Unread Number
function SUN() {
const t = parseInt(prompt("Enter unread counts", tau), 10);
if (t >= 0) {
tau = t;
} else {
// Popup may unable to interactive in violentmonkey for fennec,
// Update from a version without key "FAU" may unable to reset,
// Force use default value when enter a invalid number incase.
tau = 3;
alert("Invalid number, default[3] will be used.");
}
USV();
FAV();
}
// Set Unread Colour
function SUC() {
if (!sFc) {
sFc = true;
document.addEventListener("click", CSH, true);
} else {
sFc = false;
document.removeEventListener("click", CSH, true);
USV();
}
document.getElementById("cMenu").style.display = sFc ? "" : "none";
}
let tCate;
// Colour Select Handler
function CSH(e) {
e.preventDefault();
if (e.target.classList.contains("customCates")) {
e.target.textContent = "▣" + e.target.textContent.slice(1);
const cca = document.getElementsByClassName("customCates");
for(let i = 0; i < cca.length; i++) {
cca[i].textContent = cca[i] === e.target ? "◉" + cca[i].textContent.slice(1) : "○" + cca[i].textContent.slice(1);
}
tCate = e.target.textContent.slice(1, 2);
let tctc;
switch (tCate) {
case "0":
tctc = tac;
break;
case "1":
tctc = tcc;
break;
case "2":
tctc = tuc;
break;
}
const ccb = document.getElementsByClassName("customColour");
for(let j = 0; j < ccb.length; j++) {
ccb[j].textContent = ccb[j].style.color === tctc ? "▣" + "ColourTest" : "▢" + "ColourTest";
}
} else if (e.target.classList.contains("customColour")) {
const cca = document.getElementsByClassName("customCates");
for(let i = 0; i < cca.length; i++) {
if (cca[i].textContent.slice(1, 2) === tCate) cca[i].style.color = e.target.style.color;
}
switch (tCate) {
case "0":
tac = e.target.style.color;
break;
case "1":
tcc = e.target.style.color;
break;
case "2":
tuc = e.target.style.color;
break;
}
const ccb = document.getElementsByClassName("customColour");
for(let j = 0; j < ccb.length; j++) {
ccb[j].textContent = ccb[j] === e.target ? "▣" + "ColourTest" : "▢" + "ColourTest";
}
FAV();
}
return false;
}
// Create Float Button
function CBT() {
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%; cursor:pointer; border: none; padding: unset;";
cButton.type = "button";
cButton.addEventListener("click", (e) => {
ADA();
});
}
// Create Colour List
function CMU() {
const cMenu = document.body.appendChild(document.createElement("div"));
cMenu.id = 'cMenu';
const cCates = [ 'AuthorColour', 'ButtonColour', 'UnreadColour' ];
cCates.forEach((item, index) => {
let tctc;
switch (index) {
case 0:
tctc = tac;
break;
case 1:
tctc = tcc;
break;
case 2:
tctc = tuc;
break;
}
const cMc = cMenu.appendChild(document.createElement("p"));
cMc.classList.add("customCates");
cMc.style = 'position: fixed; bottom: ' + (4+index)*5 + '%; right: 15%; z-index: 9999; color: ' + tctc + '; background-color: #393939; padding: 1em;';
cMc.type = "button";
cMc.textContent = "○" + index + ". " + item;
});
const colors = ['deepskyblue', 'blue', 'lime', 'green', 'fuchsia', 'indigo', 'orange', 'red'];
colors.forEach((item, index) => {
const cMb = cMenu.appendChild(document.createElement("p"));
cMb.classList.add("customColour");
cMb.style = 'position: fixed; bottom: ' + (4+index)*5 + '%; right: 30%; z-index: 9999; color: ' + item + '; background-color: #F3F3F3; padding: 1em;';
cMb.type = "button";
cMb.textContent = "▢" + "ColourTest";
});
cMenu.style.display = "none";
}
})();