// ==UserScript== // @name 52 Enhance // @namespace http://tampermonkey.net/ // @version 0.4.1 // @description 52 破解论坛增强脚本 // @author PRO // @match https://www.52pojie.cn/* // @icon http://52pojie.cn/favicon.ico // @license gpl-3.0 // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @require https://greasyfork.org/scripts/470224-tampermonkey-config/code/Tampermonkey%20Config.js?version=1229665 // @downloadURL none // ==/UserScript== (function() { 'use strict'; let idPrefix = "52-enhance-"; let config_desc = {}; function addDesc(id, name, default_value=true) { config_desc[id] = { name: name, value: default_value, input: "current", processor: "not", formatter: "boolean", }; } addDesc("css-fix", "CSS 修复"); // 动态透明度;图标上光标不显示为 pointer addDesc("hide", "* 一键隐藏"); // 为旧版代码块添加“隐藏代码”的按钮;一键隐藏所有置顶帖;添加隐藏回复的按钮 addDesc("get-to-top", "* 回到顶部"); // 双击导航栏回到顶部;修改回到顶部按钮行为为原生 addDesc("emoji-fix", "* 修复 Emoji"); // 修复 Emoji 显示 addDesc("hide-signature", "隐藏签名档", false); // 隐藏所有签名档 addDesc("allow-tiny-signature", "允许小签名", true); // 允许小型签名档 (clientHeight <= 41) addDesc("hide-warning", "隐藏提醒", false); // 隐藏所有提醒 addDesc("hide-avatar-detail", "隐藏头像详情", false); // 隐藏头像下的详情 (注册时间等、收听按钮) addDesc("hide-rating", "隐藏评分", false); // 隐藏所有评分 addDesc("hide-comment", "隐藏点评", false); // 隐藏所有点评 addDesc("auto-sign", "自动签到"); // 自动签到 let config = GM_config(config_desc, false); // Styles const dynamicStyle = { "css-fix": `#jz52top { opacity: 0.2; transition: opacity 0.2s ease-in-out; } #jz52top:hover { opacity: 0.8; } .authicn { cursor: initial; } @media (any-hover: none) { #jz52top { opacity: 0.8; } #jz52top:hover { opacity: 0.8; } }`, "hide-signature": "div.sign { display: none; }", "allow-tiny-signature": "div.sign.tiny-sign { display: block; }", "hide-warning": "div[class^=vw50_kfc_p] { display: none; }", "hide-avatar-detail": "dl.credit-list, ul.xl.xl2.o.cl { display: none; }", "hide-rating": "div.pcb > h3.psth.xs1, dl.rate { display: none; }", "hide-comment": "div.pcb > div.cm { display: none; }", }; // Helper function for css function injectCSS(id, css) { let style = document.createElement("style"); style.id = idPrefix + id; style.textContent = css; document.head.appendChild(style); } function cssHelper(id, enable) { let current = document.getElementById(idPrefix + id); if (current) { current.disabled = !enable; } else if (enable) { injectCSS(id, dynamicStyle[id]); } } // Hide if (config["hide"]) { // Hide code function toggleCode() { let code = this.parentNode.parentNode.lastChild; if (code.classList.toggle("hidden")) { this.textContent = " 显示代码"; } else { this.textContent = " 隐藏代码"; } } document.querySelectorAll("em.viewsource").forEach(ele => { let hide_code = document.createElement("em"); hide_code.setAttribute("style", ele.getAttribute("style")); hide_code.setAttribute("num", ele.getAttribute("num")); hide_code.textContent = " 隐藏代码"; hide_code.addEventListener("click", toggleCode); ele.parentNode.appendChild(hide_code); }); // Hide all top threads let display = Boolean(document.querySelectorAll("tbody[id^='stickthread_']").length); let table = document.getElementById("threadlisttableid"); if (display && table) { function hideAll() { document.querySelectorAll("tbody[id^='stickthread_']").forEach(ele => { let close = ele.querySelector("a.closeprev"); if (close) close.click(); }); } let tooltip = document.querySelector("div#threadlist > div.th > table > tbody > tr > th > div.tf"); let show_top = tooltip.querySelector("span#clearstickthread"); show_top.removeAttribute("style"); show_top.insertAdjacentHTML("beforeend", "  "); let hide_all = document.createElement("a"); hide_all.href = "javascript:;"; hide_all.className = "xi2"; hide_all.textContent = "隐藏置顶"; hide_all.title = "隐藏置顶"; hide_all.addEventListener("click", hideAll); show_top.insertAdjacentElement("beforeend", hide_all); } // Hide reply let css = `tr.hidden { display: none; } td.hidden { cursor: help; background: repeating-linear-gradient(135deg, transparent 0, transparent 6px, #e7e7e7 6px, #e7e7e7 12px, transparent 12px) no-repeat 0 0, #eee; } td.hidden > div { pointer-events: none; } td.hidden > div > div > em::after { content: "此回复已被隐藏,点击以重新显示"; } .plhin:hover td.hidden .hin { opacity: 0.2; } .toggle-reply { display: block; text-align: center; position: relative; top: 0.8em; }`; injectCSS("hide", css); function toggleReply() { let keep = this.parentElement.parentElement; for (let ele of keep.parentElement.children) { if (ele != keep) { ele.classList.toggle("hidden"); } } let ele = keep.lastElementChild; if (ele.classList.toggle("hidden")) { ele.addEventListener("click", e => { toggleReply.apply(this); ele.removeAttribute("title"); }, { once: true }); ele.title = "点击显示被隐藏的回复"; } } document.querySelectorAll("table.plhin tr:nth-child(4) > td.pls").forEach(ele => { let toggle_reply = document.createElement("a"); toggle_reply.href = "javascript:void(0);"; toggle_reply.className = "toggle-reply"; toggle_reply.textContent = "隐藏/显示回复"; toggle_reply.addEventListener("click", toggleReply); ele.appendChild(toggle_reply); }); } // Get to top if (config["get-to-top"]) { // Double click navbar to get to top let nv = document.getElementById("nv"); if (nv) nv.addEventListener("dblclick", e => { window.scrollTo({ top: 0, behavior: "smooth" }); }); // Change get to top button behavior (use vanilla solution) let btn = document.getElementById("goTopBtn"); if (btn) btn.onclick = e => { window.scrollTo({ top: 0, behavior: "smooth" }); }; } // Emoji fix if (config["emoji-fix"]) { let temp = document.createElement("span"); function fixEmoji(html) { // Replace patterns like `&#128077;` with represented emoji return html.replace(/&(amp;)*#(\d+);/g, (match, p1, p2) => { temp.innerHTML = `&#${p2};`; // console.log(`${match} -> ${temp.textContent}`); // DEBUG return temp.textContent; }); } function fix(node) { // Select text nodes let walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT, null, false); let textNode; while (textNode = walker.nextNode()) { textNode.nodeValue = fixEmoji(textNode.nodeValue); } } let replies = document.querySelectorAll("table.plhin td.plc div.pct > div.pcb > div.t_fsz"); replies.forEach(fix); let ratings = document.querySelectorAll("tbody.ratl_l > tr"); ratings.forEach(rating => fix(rating.lastElementChild)); let signatures = document.querySelectorAll("div.sign"); signatures.forEach(fix); } // Auto sign function autoSign(enable) { if (enable) { let signEventName = "52-enhance-sign"; let sign = document.querySelector("#um > p:nth-child(3) > a:nth-child(1) > img"); let url = "https://www.52pojie.cn/home.php?mod=task&do=apply&id=2&referer=%2F"; if (window.location.href.startsWith("https://www.52pojie.cn/home.php?mod=task")) { // We are on the task page (presumably iframe) let msg = document.querySelector("div#messagetext > p:nth-child(1)"); if (!msg) return; window.dispatchEvent(new CustomEvent(signEventName, { detail: { msg: msg.textContent, } })); } else if (sign) { // Create an iframe to sign in let iframe = document.createElement("iframe"); iframe.src = url; iframe.style.display = "none"; document.body.appendChild(iframe); iframe.contentWindow.addEventListener(signEventName, e => { console.debug(e.detail.msg); if (e.detail.msg.startsWith("抱歉,本期您已申请过此任务,请下期再来") || e.detail.msg.startsWith("恭喜")) { // TODO: msg text? console.log("Already signed in."); sign.title = "已签到"; sign.src = "https://static.52pojie.cn/static/image/common/wbs.png"; sign.style.opacity = 1; sign.style.cursor = "default"; } }); sign.title = "签到中..."; sign.style.opacity = 0.5; sign.style.cursor = "progress"; sign.parentElement.removeAttribute("href"); } } } autoSign(config["auto-sign"]); // CSS injection let delayedCSS = ["hide-signature", "allow-tiny-signature"]; for (let prop in dynamicStyle) { if (delayedCSS.includes(prop)) continue; cssHelper(prop, config[prop]); } // Tag tiny signatures as `tiny-sign`; Delayed CSS injection document.addEventListener("readystatechange", e => { if (document.readyState == "complete") { document.querySelectorAll("div.sign").forEach(ele => { if (ele.clientHeight <= 41) { ele.classList.add("tiny-sign"); } }); for (let prop of delayedCSS) { cssHelper(prop, config[prop]); } } }); // Listen to config changes let callbacks = { "auto-sign": autoSign }; window.addEventListener(GM_config_event, e => { if (e.detail.type == "set") { let callback = callbacks[e.detail.prop]; if (callback && (e.detail.before !== e.detail.after)) { callback(e.detail.after); } else if (e.detail.prop in dynamicStyle) { cssHelper(e.detail.prop, e.detail.after); } else { console.error(`Unexpected config change: ${e.detail}`); } } }); })();