t66y助手

优化t66y网页使用体验

As of 26.11.2023. See ბოლო ვერსია.

  1. // ==UserScript==
  2. // @name t66y助手
  3. // @namespace com.t66y.jujufatu
  4. // @author jujufatu
  5. // @version 0.0.1
  6. // @description 优化t66y网页使用体验
  7. // @license CC BY-NC-ND 4.0
  8. // @match http*://*t66y.com/*
  9. // @grant GM_setClipboard
  10. // @grant unsafeWindow
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. //code start
  15. (function () {
  16. "use strict";
  17. // 访问页面的原始window对象
  18. var pageWindow = unsafeWindow;
  19.  
  20. // 去除无效图床,定义需要检查的域名列表
  21. const BLOCK_IMG_LIST = [
  22. "23img.com",
  23. "bdimg.com",
  24. "sinaimg.cn",
  25. "ovkwiz.xyz",
  26. "huluxia.com",
  27. "imgs.moe",
  28. ];
  29. // 替换显示图片:svg:过期图床
  30. const BAD_IMG_SVG =
  31. "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMjAwcHgiIGhlaWdodD0iMjAwcHgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICAgICAgICA8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjMTBiMDE4IiAvPgogICAgICAgICAgPHRleHQgeD0iNTAlIiB5PSI3MS40IiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjZjdjNTAwIiBmb250LXNpemU9IjUyIiBmb250LWZhbWlseT0iQXJpYWwiPjx0c3BhbiB4PSI1MCUiIGR5PSIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ov4fmnJ88L3RzcGFuPjx0c3BhbiB4PSI1MCUiIGR5PSI1Ny4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7lm77luoo8L3RzcGFuPjwvdGV4dD48L3N2Zz4=";
  32. // dom刚加载完成,图片脚本等其他资源还在加载中
  33. document.addEventListener("DOMContentLoaded", function () {
  34. // 热门异常图床图片替换,通常是头像
  35. replaceImg();
  36. // 找到每个楼层的磁力并替换
  37. let floors = [...document.querySelectorAll(".tpc_content")];
  38. floors.forEach((floor) => {
  39. floor.innerHTML = createMagnetLink(floor.innerHTML);
  40. });
  41. // 初始评论,后续点击加载更多评论在loadComment中处理
  42. let initComments = [...document.querySelectorAll(".post_cont")];
  43. initComments.forEach((c) => {
  44. c.innerHTML = createMagnetLink(c.innerHTML);
  45. });
  46. // 处理加载评论
  47. if (typeof pageWindow.loadComment === "function") {
  48. const originalLoadComment = pageWindow.loadComment;
  49. pageWindow.loadComment = function () {
  50. var data = pageWindow["comm" + arguments[0]];
  51. for (var key in data) {
  52. //----------修改的内容--------------
  53. data[key].c = createMagnetLink(data[key].c);
  54. //----------修改的内容--------------
  55. }
  56. originalLoadComment.apply(this, arguments); // 调用原始函数
  57. };
  58. }
  59. });
  60.  
  61. // 将传入的字符中的磁力替换为a标签地址
  62. function createMagnetLink(str) {
  63. str = decodeURIComponent(str);
  64. str = decodeHtmlEntities(str);
  65. // 正则表达式匹配哈希值、可选的dn和tr参数
  66. const magnetRegex =
  67. /(?<!<[^>]*)(?:magnet:\?xt=urn:btih:)?([a-fA-F0-9]{40})(?:&dn=([^&\s]+))?(?:&tr=([^&\s]+))?/gi;
  68.  
  69. // 替换函数,用于生成a标签
  70. function replaceFunc(match, hash, dn, tr, offset, string) {
  71. const magnetPrefix = "magnet:?xt=urn:btih:";
  72. const decodedDn = dn
  73. ? `磁力链接-${decodeURIComponent(dn)}`
  74. : `磁力链接-${hash}`;
  75. const trParam = tr ? `&tr=${encodeURIComponent(tr)}` : "";
  76. const fullMatch = string.substring(
  77. offset,
  78. string.indexOf(" ", offset) > -1
  79. ? string.indexOf(" ", offset)
  80. : string.length
  81. );
  82.  
  83. // 判断并添加磁力链接前缀
  84. let href = match.startsWith(magnetPrefix)
  85. ? fullMatch
  86. : `${magnetPrefix}${hash}${
  87. dn ? `&dn=${encodeURIComponent(dn)}` : ""
  88. }${trParam}`;
  89. href = href.replace(/\s+/g, "");
  90. return `<a href="${href}">${decodedDn}</a>&nbsp;|&nbsp;<a style="cursor: pointer;" onclick="copy('${href}')">复制</a>`;
  91. }
  92.  
  93. // 使用正则表达式替换符合条件的部分
  94. return str.replace(magnetRegex, replaceFunc);
  95. }
  96. // 将失效图床的图片替换成默认头像
  97. function replaceImg() {
  98. // 初次进入页面直接遍历修改
  99. // 获取所有img标签
  100. const images = document.getElementsByTagName("img");
  101. // 遍历每个img标签
  102. for (const img of images) {
  103. // 如果src符合条件
  104. if (BLOCK_IMG_LIST.some((domain) => img.src.includes(domain))) {
  105. img.src = BAD_IMG_SVG;
  106. }
  107. }
  108. // 后续监听dom
  109. const isBlockedSrc = (src) =>
  110. BLOCK_IMG_LIST.some((blockedDomain) => src.includes(blockedDomain));
  111. const replaceSrc = (node) => {
  112. if (node.tagName === "IMG" && isBlockedSrc(node.src)) {
  113. node.src = BAD_IMG_SVG;
  114. }
  115. };
  116.  
  117. const observer = new MutationObserver((mutations) => {
  118. mutations.forEach((mutation) => {
  119. if (mutation.type === "childList") {
  120. mutation.addedNodes.forEach((node) => {
  121. if (node.nodeType === Node.ELEMENT_NODE) {
  122. // 检查和替换 node 自身(如果它是 img)
  123. replaceSrc(node);
  124. // 遍历所有子节点
  125. node.querySelectorAll("img").forEach(replaceSrc);
  126. }
  127. });
  128. } else if (
  129. mutation.type === "attributes" &&
  130. mutation.attributeName === "src"
  131. ) {
  132. replaceSrc(mutation.target);
  133. }
  134. });
  135. });
  136.  
  137. observer.observe(document.body, {
  138. childList: true,
  139. subtree: true,
  140. attributes: true,
  141. attributeFilter: ["src"],
  142. });
  143. }
  144.  
  145. // 解码html实体符号
  146. function decodeHtmlEntities(str) {
  147. return str
  148. .replace(/&quot;/g, '"')
  149. .replace(/&apos;/g, "'")
  150. .replace(/&lt;/g, "<")
  151. .replace(/&gt;/g, ">")
  152. .replace(/&nbsp;/g, " ")
  153. .replace(/&iexcl;/g, "¡")
  154. .replace(/&cent;/g, "¢")
  155. .replace(/&pound;/g, "£")
  156. .replace(/&curren;/g, "¤")
  157. .replace(/&yen;/g, "¥")
  158. .replace(/&brvbar;/g, "¦")
  159. .replace(/&sect;/g, "§")
  160. .replace(/&uml;/g, "¨")
  161. .replace(/&copy;/g, "©")
  162. .replace(/&ordf;/g, "ª")
  163. .replace(/&laquo;/g, "«")
  164. .replace(/&not;/g, "¬")
  165. .replace(/&shy;/g, "­")
  166. .replace(/&reg;/g, "®")
  167. .replace(/&macr;/g, "¯")
  168. .replace(/&deg;/g, "°")
  169. .replace(/&plusmn;/g, "±")
  170. .replace(/&sup2;/g, "²")
  171. .replace(/&sup3;/g, "³")
  172. .replace(/&acute;/g, "´")
  173. .replace(/&micro;/g, "µ")
  174. .replace(/&para;/g, "¶")
  175. .replace(/&middot;/g, "·")
  176. .replace(/&cedil;/g, "¸")
  177. .replace(/&sup1;/g, "¹")
  178. .replace(/&ordm;/g, "º")
  179. .replace(/&raquo;/g, "»")
  180. .replace(/&frac14;/g, "¼")
  181. .replace(/&frac12;/g, "½")
  182. .replace(/&frac34;/g, "¾")
  183. .replace(/&iquest;/g, "¿")
  184. .replace(/&amp;/g, "&");
  185. // 添加更多实体替换规则
  186. // 注意: 如果增加新的替换规则,请确保不会互相冲突
  187. // 例如,&amp; 必须最后替换,以免在替换其他实体时干扰 & 符号
  188. }
  189.  
  190. // 复制文本到剪切板
  191. pageWindow.copy = function (str) {
  192. GM_setClipboard(str);
  193. Message({ msg: "复制成功", duration: 666 });
  194. };
  195.  
  196. // Message 工具函数
  197. function Message({ msg, duration }) {
  198. // 创建消息元素
  199. const messageElement = document.createElement("div");
  200.  
  201. // 设置消息文本
  202. messageElement.textContent = msg;
  203.  
  204. // 设置消息样式
  205. messageElement.style.position = "fixed";
  206. messageElement.style.top = "66px";
  207. messageElement.style.left = "50%";
  208. messageElement.style.transform = "translate(-50%, -50%)";
  209. messageElement.style.backgroundColor = "#10b018";
  210. messageElement.style.color = "#f7c500";
  211. messageElement.style.fontSize = "3rem";
  212. messageElement.style.padding = "20px";
  213. messageElement.style.boxShadow = "0 4px 8px rgba(0,0,0,0.1)";
  214. messageElement.style.borderRadius = "10px";
  215. messageElement.style.zIndex = "1000";
  216. messageElement.style.transition = "opacity 0.5s, transform 0.5s";
  217. messageElement.style.opacity = "0";
  218.  
  219. // 将消息元素添加到文档中
  220. document.body.appendChild(messageElement);
  221.  
  222. // 动画效果:淡入
  223. setTimeout(() => {
  224. messageElement.style.opacity = "1";
  225. messageElement.style.transform = "translate(-50%, -50%) scale(1)";
  226. }, 10); // 使用setTimeout来确保元素已经插入DOM
  227.  
  228. // 设置显示时长
  229. setTimeout(() => {
  230. // 动画效果:淡出
  231. messageElement.style.opacity = "0";
  232. messageElement.style.transform = "translate(-50%, -50%) scale(0.9)";
  233.  
  234. // 动画完成后从文档中移除消息元素
  235. setTimeout(() => {
  236. document.body.removeChild(messageElement);
  237. }, 500); // 与transition的时间一致
  238. }, duration);
  239. }
  240. /*************************** 自定义样式 ***************************/
  241. // 创建并插入样式
  242. let style = document.createElement("style");
  243. document.head.appendChild(style);
  244. style.sheet.insertRule(
  245. `.bad_bg { background-image: url("${BAD_IMG_SVG}") !important; }`,
  246. 0
  247. );
  248. })();