- // ==UserScript==
- // @name t66y助手
- // @namespace com.t66y.jujufatu
- // @author jujufatu
- // @version 0.0.1
- // @description 优化t66y网页使用体验
- // @license CC BY-NC-ND 4.0
- // @match http*://*t66y.com/*
- // @grant GM_setClipboard
- // @grant unsafeWindow
- // @run-at document-start
- // ==/UserScript==
-
- //code start
- (function () {
- "use strict";
- // 访问页面的原始window对象
- var pageWindow = unsafeWindow;
-
- // 去除无效图床,定义需要检查的域名列表
- const BLOCK_IMG_LIST = [
- "23img.com",
- "bdimg.com",
- "sinaimg.cn",
- "ovkwiz.xyz",
- "huluxia.com",
- "imgs.moe",
- ];
- // 替换显示图片:svg:过期图床
- const BAD_IMG_SVG =
- "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMjAwcHgiIGhlaWdodD0iMjAwcHgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICAgICAgICA8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjMTBiMDE4IiAvPgogICAgICAgICAgPHRleHQgeD0iNTAlIiB5PSI3MS40IiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjZjdjNTAwIiBmb250LXNpemU9IjUyIiBmb250LWZhbWlseT0iQXJpYWwiPjx0c3BhbiB4PSI1MCUiIGR5PSIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ov4fmnJ88L3RzcGFuPjx0c3BhbiB4PSI1MCUiIGR5PSI1Ny4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7lm77luoo8L3RzcGFuPjwvdGV4dD48L3N2Zz4=";
- // dom刚加载完成,图片脚本等其他资源还在加载中
- document.addEventListener("DOMContentLoaded", function () {
- // 热门异常图床图片替换,通常是头像
- replaceImg();
- // 找到每个楼层的磁力并替换
- let floors = [...document.querySelectorAll(".tpc_content")];
- floors.forEach((floor) => {
- floor.innerHTML = createMagnetLink(floor.innerHTML);
- });
- // 初始评论,后续点击加载更多评论在loadComment中处理
- let initComments = [...document.querySelectorAll(".post_cont")];
- initComments.forEach((c) => {
- c.innerHTML = createMagnetLink(c.innerHTML);
- });
- // 处理加载评论
- if (typeof pageWindow.loadComment === "function") {
- const originalLoadComment = pageWindow.loadComment;
- pageWindow.loadComment = function () {
- var data = pageWindow["comm" + arguments[0]];
- for (var key in data) {
- //----------修改的内容--------------
- data[key].c = createMagnetLink(data[key].c);
- //----------修改的内容--------------
- }
- originalLoadComment.apply(this, arguments); // 调用原始函数
- };
- }
- });
-
- // 将传入的字符中的磁力替换为a标签地址
- function createMagnetLink(str) {
- str = decodeURIComponent(str);
- str = decodeHtmlEntities(str);
- // 正则表达式匹配哈希值、可选的dn和tr参数
- const magnetRegex =
- /(?<!<[^>]*)(?:magnet:\?xt=urn:btih:)?([a-fA-F0-9]{40})(?:&dn=([^&\s]+))?(?:&tr=([^&\s]+))?/gi;
-
- // 替换函数,用于生成a标签
- function replaceFunc(match, hash, dn, tr, offset, string) {
- const magnetPrefix = "magnet:?xt=urn:btih:";
- const decodedDn = dn
- ? `磁力链接-${decodeURIComponent(dn)}`
- : `磁力链接-${hash}`;
- const trParam = tr ? `&tr=${encodeURIComponent(tr)}` : "";
- const fullMatch = string.substring(
- offset,
- string.indexOf(" ", offset) > -1
- ? string.indexOf(" ", offset)
- : string.length
- );
-
- // 判断并添加磁力链接前缀
- let href = match.startsWith(magnetPrefix)
- ? fullMatch
- : `${magnetPrefix}${hash}${
- dn ? `&dn=${encodeURIComponent(dn)}` : ""
- }${trParam}`;
- href = href.replace(/\s+/g, "");
- return `<a href="${href}">${decodedDn}</a> | <a style="cursor: pointer;" onclick="copy('${href}')">复制</a>`;
- }
-
- // 使用正则表达式替换符合条件的部分
- return str.replace(magnetRegex, replaceFunc);
- }
- // 将失效图床的图片替换成默认头像
- function replaceImg() {
- // 初次进入页面直接遍历修改
- // 获取所有img标签
- const images = document.getElementsByTagName("img");
- // 遍历每个img标签
- for (const img of images) {
- // 如果src符合条件
- if (BLOCK_IMG_LIST.some((domain) => img.src.includes(domain))) {
- img.src = BAD_IMG_SVG;
- }
- }
- // 后续监听dom
- const isBlockedSrc = (src) =>
- BLOCK_IMG_LIST.some((blockedDomain) => src.includes(blockedDomain));
- const replaceSrc = (node) => {
- if (node.tagName === "IMG" && isBlockedSrc(node.src)) {
- node.src = BAD_IMG_SVG;
- }
- };
-
- const observer = new MutationObserver((mutations) => {
- mutations.forEach((mutation) => {
- if (mutation.type === "childList") {
- mutation.addedNodes.forEach((node) => {
- if (node.nodeType === Node.ELEMENT_NODE) {
- // 检查和替换 node 自身(如果它是 img)
- replaceSrc(node);
- // 遍历所有子节点
- node.querySelectorAll("img").forEach(replaceSrc);
- }
- });
- } else if (
- mutation.type === "attributes" &&
- mutation.attributeName === "src"
- ) {
- replaceSrc(mutation.target);
- }
- });
- });
-
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- attributes: true,
- attributeFilter: ["src"],
- });
- }
-
- // 解码html实体符号
- function decodeHtmlEntities(str) {
- return str
- .replace(/"/g, '"')
- .replace(/'/g, "'")
- .replace(/</g, "<")
- .replace(/>/g, ">")
- .replace(/ /g, " ")
- .replace(/¡/g, "¡")
- .replace(/¢/g, "¢")
- .replace(/£/g, "£")
- .replace(/¤/g, "¤")
- .replace(/¥/g, "¥")
- .replace(/¦/g, "¦")
- .replace(/§/g, "§")
- .replace(/¨/g, "¨")
- .replace(/©/g, "©")
- .replace(/ª/g, "ª")
- .replace(/«/g, "«")
- .replace(/¬/g, "¬")
- .replace(/­/g, "")
- .replace(/®/g, "®")
- .replace(/¯/g, "¯")
- .replace(/°/g, "°")
- .replace(/±/g, "±")
- .replace(/²/g, "²")
- .replace(/³/g, "³")
- .replace(/´/g, "´")
- .replace(/µ/g, "µ")
- .replace(/¶/g, "¶")
- .replace(/·/g, "·")
- .replace(/¸/g, "¸")
- .replace(/¹/g, "¹")
- .replace(/º/g, "º")
- .replace(/»/g, "»")
- .replace(/¼/g, "¼")
- .replace(/½/g, "½")
- .replace(/¾/g, "¾")
- .replace(/¿/g, "¿")
- .replace(/&/g, "&");
- // 添加更多实体替换规则
- // 注意: 如果增加新的替换规则,请确保不会互相冲突
- // 例如,& 必须最后替换,以免在替换其他实体时干扰 & 符号
- }
-
- // 复制文本到剪切板
- pageWindow.copy = function (str) {
- GM_setClipboard(str);
- Message({ msg: "复制成功", duration: 666 });
- };
-
- // Message 工具函数
- function Message({ msg, duration }) {
- // 创建消息元素
- const messageElement = document.createElement("div");
-
- // 设置消息文本
- messageElement.textContent = msg;
-
- // 设置消息样式
- messageElement.style.position = "fixed";
- messageElement.style.top = "66px";
- messageElement.style.left = "50%";
- messageElement.style.transform = "translate(-50%, -50%)";
- messageElement.style.backgroundColor = "#10b018";
- messageElement.style.color = "#f7c500";
- messageElement.style.fontSize = "3rem";
- messageElement.style.padding = "20px";
- messageElement.style.boxShadow = "0 4px 8px rgba(0,0,0,0.1)";
- messageElement.style.borderRadius = "10px";
- messageElement.style.zIndex = "1000";
- messageElement.style.transition = "opacity 0.5s, transform 0.5s";
- messageElement.style.opacity = "0";
-
- // 将消息元素添加到文档中
- document.body.appendChild(messageElement);
-
- // 动画效果:淡入
- setTimeout(() => {
- messageElement.style.opacity = "1";
- messageElement.style.transform = "translate(-50%, -50%) scale(1)";
- }, 10); // 使用setTimeout来确保元素已经插入DOM
-
- // 设置显示时长
- setTimeout(() => {
- // 动画效果:淡出
- messageElement.style.opacity = "0";
- messageElement.style.transform = "translate(-50%, -50%) scale(0.9)";
-
- // 动画完成后从文档中移除消息元素
- setTimeout(() => {
- document.body.removeChild(messageElement);
- }, 500); // 与transition的时间一致
- }, duration);
- }
- /*************************** 自定义样式 ***************************/
- // 创建并插入样式
- let style = document.createElement("style");
- document.head.appendChild(style);
- style.sheet.insertRule(
- `.bad_bg { background-image: url("${BAD_IMG_SVG}") !important; }`,
- 0
- );
- })();