您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Highlights the keyword and alerts with sound and notification.
// ==UserScript== // @name Torn - Pickpocketing - Cyclist Monitor // @namespace http://tampermonkey.net/ // @version 1.2 // @description Highlights the keyword and alerts with sound and notification. // @author zstorm [2268511] // @match https://www.torn.com/page.php?sid=crimes* // @grant GM_notification // @grant window.focus // @license MIT // ==/UserScript== (function () { 'use strict'; const keyword = "Cyclist"; const notificationTitle = `Found a ${keyword}`; const notificationMessage = `"${keyword}" has been detected!`; const notificationTimeout = 2000; let keywordFound = false; let observerPaused = false; console.log(`Monitoring keyword: "${keyword}"`); // Beep sound function playBeep() { const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const oscillator = audioContext.createOscillator(); oscillator.type = "sine"; oscillator.frequency.setValueAtTime(440, audioContext.currentTime); oscillator.connect(audioContext.destination); oscillator.start(); oscillator.stop(audioContext.currentTime + 0.2); } // Show notification function sendChromeNotification() { GM_notification({ title: notificationTitle, text: notificationMessage, timeout: notificationTimeout, onclick: () => window.focus() }); } // Highlight keyword without triggering infinite loops function highlightKeyword() { const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false); let found = false; while (walker.nextNode()) { const node = walker.currentNode; if (!node.nodeValue.includes(keyword)) continue; if (node.parentNode.tagName === 'MARK') continue; const span = document.createElement('mark'); span.style.backgroundColor = 'red'; span.style.color = 'black'; const parts = node.nodeValue.split(new RegExp(`(${keyword})`, 'gi')); parts.forEach(part => { if (part.toLowerCase() === keyword.toLowerCase()) { const mark = span.cloneNode(); mark.textContent = part; node.parentNode.insertBefore(mark, node); } else { node.parentNode.insertBefore(document.createTextNode(part), node); } }); node.parentNode.removeChild(node); found = true; } return found; } // Debounced observer logic let observerTimeout; const observer = new MutationObserver(() => { if (observerPaused) return; clearTimeout(observerTimeout); observerTimeout = setTimeout(() => { observerPaused = true; // prevent loop const found = highlightKeyword(); if (found && !keywordFound) { playBeep(); sendChromeNotification(); console.log(`"1 ${keyword}" found.`); keywordFound = true; } // Re-enable observer after short delay setTimeout(() => { observerPaused = false; }, 500); // adjust if needed }, 300); // debounce time }); observer.observe(document.body, { childList: true, subtree: true }); window.addEventListener('load', () => { setTimeout(() => { highlightKeyword(); }, 500); }); })();