JustMoeComments

萌百看Lih的镜像站的评论

当前为 2023-04-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name JustMoeComments
  3. // @namespace https://github.com/gui-ying233/JustMoeComments
  4. // @version 2.5.0
  5. // @description 萌百看Lih的镜像站的评论
  6. // @author 鬼影233
  7. // @license MIT
  8. // @match *.moegirl.org.cn/*
  9. // @icon https://moegirl.uk/images/a/a2/%E7%B2%89%E8%89%B2%E5%A4%A7%E7%8C%9B%E5%AD%97.png
  10. // @supportURL https://github.com/gui-ying233/JustMoeComments/issues
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. "use strict";
  15. (function wait() {
  16. if (typeof mw !== "undefined") {
  17. if (
  18. mw.config.get("wgAction") === "view" &&
  19. [0, 2, 12, 274].indexOf(mw.config.get("wgNamespaceNumber")) + 1
  20. ) {
  21. function generatePost(post) {
  22. const diff = Date.now() - post.timestamp * 1000;
  23. if (diff > 0 && diff < 86400000) {
  24. var timestamp = moment(post.timestamp * 1000)
  25. .locale(mw.config.get("wgUserLanguage"))
  26. .fromNow();
  27. } else {
  28. var timestamp = moment(post.timestamp * 1000)
  29. .locale(mw.config.get("wgUserLanguage"))
  30. .format("LL, HH:mm:ss");
  31. }
  32. const postDiv = document.createElement("div");
  33. postDiv.className = "comment-thread";
  34. postDiv.innerHTML = `<div class="comment-post"><div class="comment-avatar"><a href="//moegirl.uk/U:${
  35. post.username
  36. }"><img src="//moegirl.uk/extensions/Avatar/avatar.php?user=${
  37. post.username
  38. }" decofing="async" loading="lazy" fetchpriority="low"></a></div><div class="comment-body"><div class="comment-user"><a href="//moegirl.uk/U:${
  39. post.username
  40. }">${post.username}</a></div><div class="comment-text">${
  41. post.text
  42. }</div><div class="comment-footer"><span class="comment-time">${timestamp}</span>${
  43. post.like
  44. ? `<span class="comment-like">赞 ${post.like}</span>`
  45. : ""
  46. }</div></div></div>`;
  47. [
  48. ...document.body.querySelectorAll(
  49. "#flowthread img[src^='/images/']"
  50. ),
  51. ].forEach((i) => {
  52. i.src = `//img.moegirl.org.cn/common/${new URL(
  53. i.src
  54. ).pathname.slice(8)}`;
  55. i.srcset = i.srcset.replaceAll(
  56. "/images/",
  57. "//img.moegirl.org.cn/common/"
  58. );
  59. });
  60. [
  61. ...document.body.querySelectorAll(
  62. "#flowthread a.extiw[title^='moe:'], #flowthread a.extiw[title^='zhmoe:']"
  63. ),
  64. ].forEach((a) => {
  65. a.classList.remove("extiw");
  66. new mw.Api()
  67. .get({
  68. action: "query",
  69. format: "json",
  70. titles: decodeURI(a.pathname.slice(1)),
  71. utf8: 1,
  72. formatversion: 2,
  73. })
  74. .done((b) => {
  75. if (b.query.pages[0].missing) {
  76. a.href = `/index.php?title=${a.pathname.slice(
  77. 1
  78. )}&action=edit&redlink=1`;
  79. a.title += " (页面不存在)";
  80. a.classList += "new";
  81. } else if (
  82. b.query.pages[0].pageid ===
  83. mw.config.get("wgArticleId")
  84. ) {
  85. a.href = "";
  86. a.title = "";
  87. a.classList += "mw-selflink selflink";
  88. } else {
  89. a.href = a.pathname;
  90. a.title = a.title.replace(
  91. /moe:|zhmoe:/,
  92. ""
  93. );
  94. }
  95. });
  96. });
  97. [
  98. ...document.body.querySelectorAll("#flowthread script"),
  99. ].forEach((s) => {
  100. const _s = document.createElement("script");
  101. _s.innerHTML = s.innerHTML;
  102. [...s.attributes].forEach((a) => {
  103. _s.setAttribute(a.name, a.value);
  104. });
  105. s.parentNode.replaceChild(_s, s);
  106. });
  107. return postDiv;
  108. }
  109. mw.loader.using(["moment"]).done(() => {
  110. fetch(
  111. `https://moegirl.uk/api.php?${new URLSearchParams({
  112. action: "query",
  113. format: "json",
  114. prop: "pageprops",
  115. titles: mw.config.get("wgPageName"),
  116. utf8: 1,
  117. formatversion: 2,
  118. origin: "*",
  119. })}`
  120. )
  121. .then((a) => a.json())
  122. .then((a) => {
  123. const commentCSS = document.createElement("style");
  124. commentCSS.innerHTML =
  125. "#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-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}";
  126. document.head.appendChild(commentCSS);
  127. const containerTop = document.createElement("div");
  128. containerTop.className = "comment-container-top";
  129. const container = document.createElement("div");
  130. container.className = "comment-container";
  131. const postContent = document.createElement("div");
  132. postContent.id = "flowthread";
  133. postContent.className = "post-content";
  134. postContent.appendChild(containerTop);
  135. postContent.appendChild(container);
  136. switch (mw.config.get("skin")) {
  137. case "vector":
  138. document
  139. .getElementById("footer")
  140. .appendChild(postContent);
  141. break;
  142. case "moeskin":
  143. default:
  144. document
  145. .getElementById("moe-global-footer")
  146. .appendChild(postContent);
  147. break;
  148. }
  149. (function getComment(offset) {
  150. fetch(
  151. `https://moegirl.uk/api.php?${new URLSearchParams(
  152. {
  153. action: "flowthread",
  154. format: "json",
  155. type: "list",
  156. pageid: a.query.pages[0].pageid,
  157. limit: 15,
  158. offset,
  159. utf8: 1,
  160. formatversion: 2,
  161. origin: "*",
  162. }
  163. )}`
  164. )
  165. .then((b) => b.json())
  166. .then((b) => {
  167. if (b.flowthread.popular.length) {
  168. document.body.getElementsByClassName(
  169. "comment-container-top"
  170. )[0].innerHTML =
  171. "<div>热门评论</div>";
  172. for (const post of b.flowthread
  173. .popular) {
  174. const _post =
  175. generatePost(post);
  176. _post.classList.add(
  177. "comment-popular"
  178. );
  179. document.body
  180. .getElementsByClassName(
  181. "comment-container-top"
  182. )[0]
  183. .appendChild(_post);
  184. }
  185. }
  186. for (const post of b.flowthread.posts) {
  187. const _post = generatePost(post);
  188. _post.id = `comment-${post.id}`;
  189. if (post.parentid) {
  190. document
  191. .getElementById(
  192. `comment-${post.parentid}`
  193. )
  194. .appendChild(_post);
  195. } else {
  196. document
  197. .getElementsByClassName(
  198. "comment-container"
  199. )[0]
  200. .appendChild(_post);
  201. }
  202. }
  203. if (b.flowthread.count > offset + 15) {
  204. new IntersectionObserver(
  205. (entries, observer) => {
  206. entries.forEach((entry) => {
  207. if (
  208. entry.isIntersecting
  209. ) {
  210. getComment(
  211. offset + 15
  212. );
  213. observer.unobserve(
  214. entry.target
  215. );
  216. }
  217. });
  218. }
  219. ).observe(
  220. document.querySelector(
  221. ".comment-container > div.comment-thread:last-of-type"
  222. )
  223. );
  224. }
  225. });
  226. })(0);
  227. });
  228. });
  229. }
  230. } else {
  231. setTimeout(wait, 50);
  232. }
  233. })();
  234. })();