您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Filters messages by blacklisted users in groups. [!] script relies on usernames (which can be changed). All images sent by the blacklisted are blank
// ==UserScript== // @name Telegram Message Hide (fixed) // @version 0.5.1 // @description Filters messages by blacklisted users in groups. [!] script relies on usernames (which can be changed). All images sent by the blacklisted are blank // @license MIT // @namespace Telegram-Message-Hide // @include https://web.telegram.org/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // ==/UserScript== (function main() { 'use strict'; const defaultList = ["user1293847293847129083471029384", "user02938421057293084572930584"]; let userNames = GM_getValue("user-names", defaultList); if (typeof userNames === 'string') { try { userNames = JSON.parse(userNames); } catch { userNames = userNames.split(',').map(s => s.trim()).filter(Boolean); } } if (!Array.isArray(userNames)) userNames = [String(userNames).trim()]; let delay = parseInt(GM_getValue("update-interval", 3000), 10) || 3000; let eventTimeout = null; console.log("[TMH] Initialized with filters:", userNames, "interval:", delay); GM_addStyle(` .tmh-placeholder { padding: 6px 12px; margin: 2px 0; border-radius: 8px; background: #eee; color: #555; font-style: italic; cursor: pointer; opacity: 0.8; } .tmh-placeholder:hover { opacity: 1; background: #ddd; } `); function shouldHide(wrapper) { if (!wrapper) return false; const group = wrapper.closest('.sender-group-container'); // Sender candidates const senderEl = wrapper.querySelector('.sender-title, .message-title-name') || group?.querySelector('.sender-title, .message-title-name') || group?.querySelector('.Avatar'); const sender = senderEl ? (senderEl.getAttribute('aria-label') || senderEl.textContent || '').trim() : ''; // Message text const bodyEl = wrapper.querySelector('.text-content, .message-text'); let body = bodyEl ? (bodyEl.textContent || '').trim() : ''; if (!body) { const img = wrapper.querySelector('img[alt]'); if (img) body = img.alt; } const hay = (sender + ' ' + body).toLowerCase(); const match = userNames.find(entry => { const s = entry.toLowerCase().trim(); const sNoAt = s.replace(/^@/, ''); return (s && hay.includes(s)) || (sNoAt && hay.includes(sNoAt)); }); if (match) { console.log(`[TMH] Filter match "${match}" in sender="${sender}" body="${body}"`); return { match, sender }; } return null; } function replaceWithPlaceholder(target, sender) { if (!target || (target.dataset.tmhHidden && target.querySelectorAll("img").length === target.dataset.imgCount)) return; target.dataset.tmhHidden = '1'; target.dataset.imgCount = target.querySelectorAll("img").length; for (const msg of target.querySelectorAll('.text-content, .message-text')){ msg.textContent = `Removed message from ${sender || "unknown"}`; } target.style.opacity = '0.3'; target.style.fontStyle = 'italic'; for (const img of target.querySelectorAll("img")){ console.log(img); img.style.visibility = "hidden"; } } function applyStyles(wrappers) { Array.from(wrappers).forEach(wrapper => { const result = shouldHide(wrapper); if (result) { const group = wrapper.closest('.sender-group-container'); if (group) { console.log(`[TMH] Replacing group for "${result.sender}" with placeholder`); replaceWithPlaceholder(group, result.sender); } else { console.log(`[TMH] Replacing single message with placeholder`); replaceWithPlaceholder(wrapper, result.sender); } } }); } function scanMessages() { console.log("[TMH] Scanning for messages..."); const nodes = document.querySelectorAll( '.Message.message-list-item, .message-list-item, [data-message-id], .sender-group-container' ); console.log("[TMH] Found", nodes.length, "nodes"); if (!nodes || nodes.length === 0) return; applyStyles(nodes); } function eventThrottler(timeout) { if (eventTimeout) return; eventTimeout = setTimeout(() => { eventTimeout = null; console.log("[TMH] Throttled scan triggered"); scanMessages(); }, timeout); } GM_registerMenuCommand("Filter list", () => { let current = GM_getValue("user-names", userNames); if (Array.isArray(current)) current = current.join(', '); let val = prompt("Enter usernames to filter, separated by comma:", current); if (val !== null && typeof val === "string") { const arr = val.split(",").map(v => v.trim()).filter(Boolean); userNames = arr; GM_setValue("user-names", arr); console.log("[TMH] Updated filter list:", userNames); scanMessages(); } }); GM_registerMenuCommand("Update interval", () => { const updateInterval = GM_getValue("update-interval", delay); const val = prompt("Enter message scanning frequency (in ms):", String(updateInterval)); if (val !== null && typeof val === "string") { const n = parseInt(val, 10); if (!Number.isNaN(n) && n > 0) { delay = n; GM_setValue("update-interval", n); console.log("[TMH] Updated interval:", delay); } } }); function init() { console.log("[TMH] Starting script..."); scanMessages(); const observer = new MutationObserver(() => { console.log("[TMH] DOM mutation detected"); eventThrottler(delay); }); observer.observe(document.body, { childList: true, subtree: true }); window.addEventListener("message", () => { console.log("[TMH] Window message event fired"); eventThrottler(delay); }, false); window.TMH = { scan: scanMessages, list: () => Array.from(userNames), setList: (arr) => { userNames = Array.isArray(arr) ? arr : String(arr).split(',').map(s => s.trim()).filter(Boolean); GM_setValue('user-names', userNames); console.log("[TMH] List updated via debug API:", userNames); scanMessages(); } }; } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } }());