Highlight Unread Novel

Add new color to novel which have more unread counts On Kakuyomu / Narou / Alphapolis's Favorite Page

目前为 2024-05-14 提交的版本。查看 最新版本

// ==UserScript==
// @name           Highlight Unread Novel
// @name:ja        未読小説をハイライトする
// @namespace      https://greasyfork.org/en/users/1264733
// @version        2024-05-14
// @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
	// Unread count
	const sCount = 3;
	// 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("AddFavAuthor", SVM);
	
	// Read List
	const URD = GM_getValue(gMk);
	let tlo = URD ? URD : { FAC: "red",FAL:[] };
	let tac = tlo.FAC;
	const tal = tlo.FAL;

	// Save List
	function USV() {
		tlo = { FAC: tac, FAL:tal };
		GM_setValue(gMk, tlo);
	}

	let cSv = false;
	const uRi = location.href;
	let fAuthor;
	if ( uRi.includes("/my/") || uRi.includes("/favnovelmain/") || uRi.includes("/mypage/") ) {
		FAV();
		CBT();
	} 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 = tac;
				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 = tUnreadCount && tUnreadNum > sCount ? tac : "";
			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 = tac;
				}
			}
		}
	}

	// Check Keyword
	function CHK(elem, s) {
		const result = tal.some((v) => s === v);
		if (cSv) {
			elem.style.border = result ? "thin solid fuchsia" : "thin solid dodgerblue";
		} else {
			elem.style.border = "none";
		}
		return result;
	}

	// Select mode
	function SVM() {
		if (!cSv) {
			cSv = true;
			// Disable default click
			document.addEventListener("click", PAC, true);
		} else {
			cSv = false;
			// Enable default click
			document.removeEventListener("click", PAC, true);
			// Auto save list
			USV();
		}
		document.getElementById("cFbtn").textContent = cSv ? "💖" : "💟";
		document.getElementById("cMenu").style.display = cSv ? "" : "none";
		FAV();
	}

	// Prevent Anchor Change
	function PAC(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();
		} else if (e.target.classlist === "customColour") {
			tac = e.target.style.color;
			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;
	}

	// 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%;";
		cButton.type = "button";
		cButton.addEventListener("click", (e) => {
			SVM();
		});
		const cMenu = document.body.appendChild(document.createElement("div"));
		cMenu.id = 'cMenu';
		const colors = ['deepskyblue', 'blue', 'lime', 'green', 'fuchsia', 'indigo', 'orange', 'red'];
		for(let i = 0; i < colors.length; i++) {
			const cMb = cMenu.appendChild(document.createElement("p"));
			cMb.classlist = "customColour";
			cMb.style = 'position: fixed; bottom: ' + (6+i) * 5 + '%; right: 10%; z-index: 9999; color: ' + colors[i] + ';';
			cMb.type = "button";
			cMb.textContent = "Example";
		}
		cMenu.style.display = "none";
	}
})();