JustMoeComments

萌娘百科看Lih的镜像站的评论,同时集成了作品讨论的评论

目前为 2023-10-16 提交的版本。查看 最新版本

// ==UserScript==
// @name         JustMoeComments
// @namespace    https://github.com/gui-ying233/JustMoeComments
// @version      2.10.3
// @description  萌娘百科看Lih的镜像站的评论,同时集成了作品讨论的评论
// @author       鬼影233
// @license      MIT
// @match        zh.moegirl.org.cn/*
// @match        mzh.moegirl.org.cn/*
// @match        mobile.moegirl.org.cn/*
// @icon         https://moegirl.uk/images/a/a2/%E7%B2%89%E8%89%B2%E5%A4%A7%E7%8C%9B%E5%AD%97.png
// @supportURL   https://github.com/gui-ying233/JustMoeComments/issues
// ==/UserScript==

(async function () {
	"use strict";
	await new Promise(resolve => {
		const intervId = setInterval(() => {
			if (typeof mw !== "undefined" && typeof wgULS !== "undefined") {
				clearInterval(intervId);
				resolve();
			}
		}, 50);
	});
	if (
		mw.config.get("wgAction") === "view" &&
		[0, 2, 4, 12, 274].includes(mw.config.get("wgNamespaceNumber"))
	) {
		const api = new mw.Api();
		const generatePost = post => {
			let timestamp;
			if (typeof post.timestamp === "number") {
				const diff = Date.now() - post.timestamp * 1000;
				if (diff > 0 && diff < 86400000) {
					timestamp = moment(post.timestamp * 1000)
						.locale(mw.config.get("wgUserLanguage"))
						.fromNow();
				} else {
					timestamp = moment(post.timestamp * 1000)
						.locale(mw.config.get("wgUserLanguage"))
						.format("LL, HH:mm:ss");
				}
			} else {
				timestamp = post.timestamp;
			}
			const postDiv = document.createElement("div");
			postDiv.className = "comment-thread";
			postDiv.innerHTML = `<div class="comment-post"><div class="comment-avatar"><a href="//moegirl.uk/U:${
				post.username
			}"><img src="//moegirl.uk/extensions/Avatar/avatar.php?user=${
				post.username
			}" decofing="async" loading="lazy" fetchpriority="low"></a></div><div class="comment-body"><div class="comment-user"><a href="//moegirl.uk/U:${
				post.username
			}">${post.username}</a></div><div class="comment-text">${
				post.text
			}</div><div class="comment-footer"><span class="comment-time">${timestamp}</span>${
				post.like
					? `<span class="comment-like">赞 ${post.like}</span>`
					: ""
			}</div></div></div>`;
			[...postDiv.querySelectorAll("img[src^='/images/']")].forEach(i => {
				i.src = `//img.moegirl.org.cn/common/${new URL(
					i.src
				).pathname.slice(8)}`;
				i.srcset = i.srcset.replaceAll(
					"/images/",
					"//img.moegirl.org.cn/common/"
				);
			});
			[
				...postDiv.querySelectorAll(
					'img[src*="thumb"][src$=".svg.png"], img[src*="thumb"][data-lazy-src$=".svg.png"], img[src*="thumb"][src$=".gif"], img[data-lazy-src*="thumb"][data-lazy-src$=".gif"]'
				),
			].forEach(i => {
				try {
					const _i = i.cloneNode();
					if (
						new mw.Uri(_i.src || _i.dataset.lazySrc).host ===
						"img.moegirl.org.cn"
					) {
						_i.src = _i.src
							.replace("/thumb/", "/")
							.replace(/\.svg\/[^/]+\.svg\.png$/, ".svg")
							.replace(/\.gif\/[^/]+\.gif$/, ".gif");
						_i.removeAttribute("srcset");
						_i.removeAttribute("data-lazy-src");
						_i.removeAttribute("data-lazy-srcset");
						_i.removeAttribute("data-lazy-state");
						_i.classList.remove("lazyload");
						_i.onload = function () {
							i.replaceWith(_i);
						};
					}
				} catch {}
			});
			[
				...postDiv.querySelectorAll(
					"a.extiw[title^='moe:'], a.extiw[title^='zhmoe:']"
				),
			].forEach(a => {
				a.classList.remove("extiw");
				api.get({
					action: "query",
					format: "json",
					titles: decodeURI(a.pathname.slice(1)),
					utf8: 1,
					formatversion: 2,
				}).done(b => {
					if (b.query.pages[0].missing) {
						a.href = `/index.php?title=${a.pathname.slice(
							1
						)}&action=edit&redlink=1`;
						a.title += wgULS(" (页面不存在)", "(頁面不存在)");
						a.classList += "new";
					} else if (
						b.query.pages[0].pageid === mw.config.get("wgArticleId")
					) {
						a.href = "";
						a.title = "";
						a.classList += "mw-selflink selflink";
					} else {
						a.href = a.pathname;
						a.title = a.title.replace(/moe:|zhmoe:/, "");
					}
				});
			});
			[...postDiv.getElementsByTagName("script")].forEach(s => {
				const _s = document.createElement("script");
				_s.innerHTML = s.innerHTML;
				[...s.attributes].forEach(a => {
					_s.setAttribute(a.name, a.value);
				});
				s.parentNode.replaceChild(_s, s);
			});
			return postDiv;
		};
		mw.loader.using(["moment"]).done(() => {
			const commentCSS = document.createElement("style");
			commentCSS.innerHTML =
				"#flowthread{clear:both;padding:1.5em}body.skin-moeskin #flowthread{background-color:var(--theme-background-color)}.comment-container-top:not(:empty){border:1px #ccc solid;border-radius:5px}body.skin-vector .comment-container-top{background-color:rgb(191 234 181 / 20%)}body.skin-moeskin .comment-container-top{background-color:var(--theme-card-background-color)}.comment-container-top>div:first-child{height:24px;line-height:24px;text-indent:1em;font-size:small;border-radius:5px 5px 0 0;font-weight:bold}body.skin-vector .comment-container-top>div:first-child{background-color:rgb(18 152 34 / 47%);color:#fff}body.skin-moeskin .comment-container-top>div:first-child{background-color:var(--theme-accent-color);color:var(--theme-accent-link-color)}.comment-thread{border-top:1px solid rgba(0,0,0,0.13)}.comment-thread .comment-thread{margin-left:40px}.comment-post{padding:10px}.comment-avatar{float:left}.comment-avatar img{width:50px;height:50px}.comment-body{padding-left:60px}.comment-thread>div:not(:first-of-type) .comment-avatar img{width:30px;height:30px}.comment-thread>div:not(:first-of-type) .comment-body{padding-left:40px}.comment-user,.comment-user a{color:#777;font-size:13px;margin-right:8px}.post-content .comment-text{position:static}.comment-text{font-size:13px;line-height:1.5em;margin:.5em 0;word-wrap:break-word;position:relative;overflow:hidden;min-height:1em}.comment-footer{font-size:12px;margin-right:8px;color:#999}.comment-like{margin-left:5px}";
			document.head.appendChild(commentCSS);
			const containerTop = document.createElement("div");
			containerTop.className = "comment-container-top";
			const container = document.createElement("div");
			container.className = "comment-container";
			const postContent = document.createElement("div");
			postContent.id = "flowthread";
			postContent.className = "post-content";
			postContent.appendChild(containerTop);
			postContent.appendChild(container);
			switch (mw.config.get("skin")) {
				case "vector":
					document.getElementById("footer").appendChild(postContent);
					break;
				case "moeskin":
				default:
					document
						.getElementById("moe-global-footer")
						.appendChild(postContent);
					break;
			}
			fetch(
				`https://moegirl.uk/api.php?${new URLSearchParams({
					action: "query",
					format: "json",
					prop: "pageprops",
					titles: mw.config.get("wgPageName"),
					utf8: 1,
					formatversion: 2,
					origin: "*",
				})}`
			)
				.then(a => a.json())
				.then(a =>
					(function getComment(offset) {
						fetch(
							`https://moegirl.uk/api.php?${new URLSearchParams({
								action: "flowthread",
								format: "json",
								type: "list",
								pageid: a.query.pages[0].pageid,
								limit: 15,
								offset,
								utf8: 1,
								formatversion: 2,
								origin: "*",
							})}`
						)
							.then(b => b.json())
							.then(b => {
								if (b.flowthread.popular.length) {
									document.body.getElementsByClassName(
										"comment-container-top"
									)[0].innerHTML = "<div>热门评论</div>";
									for (const post of b.flowthread.popular) {
										const _post = generatePost(post);
										_post.classList.add("comment-popular");
										document.body
											.getElementsByClassName(
												"comment-container-top"
											)[0]
											.appendChild(_post);
									}
								}
								for (const post of b.flowthread.posts) {
									const _post = generatePost(post);
									_post.id = `comment-${post.id}`;
									if (post.parentid) {
										document
											.getElementById(
												`comment-${post.parentid}`
											)
											.appendChild(_post);
									} else {
										document
											.getElementsByClassName(
												"comment-container"
											)[0]
											.appendChild(_post);
									}
								}
								if (b.flowthread.count > offset + 15) {
									new IntersectionObserver(
										(entries, observer) => {
											entries.forEach(entry => {
												if (entry.isIntersecting) {
													getComment(offset + 15);
													observer.unobserve(
														entry.target
													);
												}
											});
										}
									).observe(
										document.querySelector(
											".comment-container > div.comment-thread:last-of-type"
										)
									);
								}
							});
					})(0)
				)
				.catch(() => {
					fetch(
						"https://raw.githubusercontent.com/gui-ying233/JustMoeComments/main/flowthread.json"
					)
						.then(a => a.json())
						.then(a => {
							let f = 0;
							for (const t of a) {
								if (
									t.title ===
									mw.config
										.get("wgPageName")
										.replace("_", " ")
								) {
									a = t.posts;
									f = 1;
									break;
								}
							}
							if (!f) return;
							for (const b of a) {
								if (+b.status) continue;
								const _post = generatePost({
									username: b.username,
									text: b.text,
									timestamp: "",
								});
								_post.id = `comment-${b.id}`;
								if (b.parentid) {
									document
										.getElementById(`comment-${b.parentid}`)
										.appendChild(_post);
								} else {
									document
										.getElementsByClassName(
											"comment-container"
										)[0]
										.appendChild(_post);
								}
							}
						});
				});
			if (mw.config.get("skin") === "moeskin") {
				setTimeout(() => {
					if (
						[
							(mw.config.get("wgPageName"),
							mw.config
								.get("wgPageName")
								.replace(/^(.+)\(.+?\)$/, "$1"),
							document.getElementById("firstHeading").innerText),
						].includes(
							document.body.getElementsByClassName(
								"artwork-title"
							)[0]?.innerText
						)
					) {
						document.body
							.getElementsByClassName("comment-item")
							.forEach(c => {
								if (
									c.getElementsByClassName("comment-title")[0]
										.innerText ||
									c.getElementsByClassName(
										"comment-content"
									)[0].innerText
								) {
									const post = {
										like: +c
											.getElementsByClassName(
												"n-button-group"
											)[0]
											.innerText.split("\n")[0],
										username:
											c.getElementsByClassName(
												"comment-author"
											)[0].innerText,
										text:
											c.getElementsByClassName(
												"comment-title"
											)[0].innerText +
											(c.getElementsByClassName(
												"comment-title"
											)[0].innerText &&
											c.getElementsByClassName(
												"comment-content"
											)[0].innerText
												? document.createElement("br")
														.outerHTML
												: "") +
											c.getElementsByClassName(
												"comment-content"
											)[0].innerText,
										timestamp:
											c.getElementsByClassName(
												"comment-time"
											)[0].innerText,
									};
									document
										.getElementsByClassName(
											"comment-container"
										)[0]
										.appendChild(generatePost(post));
								}
							});
					}
				}, 5000);
			}
		});
	}
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址