您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Blink/show a frame when having unread PM, unread Chats (main chat) or when user enter or leaves a streamers room. With setting window that can toggle them on or off
// ==UserScript== // @name Chaturbate Chat, PM and User enter/leave Notifier for streamers // @namespace http://tampermonkey.net/ // @version 1.0 // @description Blink/show a frame when having unread PM, unread Chats (main chat) or when user enter or leaves a streamers room. With setting window that can toggle them on or off // @author Brsrk // @license MIT // @icon https://www.google.com/s2/favicons?sz=32&domain=chaturbate.com // @icon64 https://www.google.com/s2/favicons?sz=64&domain=chaturbate.com // @match https://chaturbate.com/b/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; // Define the specific text to monitor const monitorText = { before1: 'CHAT', // text to look for after1: 'CHAT \\(\\d+\\)', // regex pattern to match "CHAT (any number)" before2: 'PM', // text to look for after2: 'PM \\(\\d+\\)', // regex pattern to match "PM (any number)" before3: 'USERS', // text to look for after3: 'USERS \\(\\d+\\)', // regex pattern to match "USERS (any number)" }; let previousTextContent = ''; let previousUserCount = ''; let blinkingBox = null; let blinkingFrame = null; let userBlinkingFrame = null; let titleBlinkInterval = null; let originalTitle = document.title; // Load settings from local storage let settings = { pmNotifications: GM_getValue('pmNotifications', true), userNotifications: GM_getValue('userNotifications', true), chatNotifications: GM_getValue('chatNotifications', true), }; // Add CSS for blinking effect and settings menu const style = document.createElement('style'); style.textContent = ` #blinking-frame { position: fixed; top: 0; left: 0; width: 100%; height: 100%; border: 10px solid red; animation: blink 1s infinite; z-index: 9999; pointer-events: none; box-sizing: border-box; } #user-blinking-frame-green { position: fixed; top: 0; left: 0; width: 100%; height: 100%; border: 5px solid green; animation: blink-green 5s; z-index: 9997; pointer-events: none; box-sizing: border-box; } #user-blinking-frame-orange { position: fixed; top: 0; left: 0; width: 100%; height: 100%; border: 2px solid orange; animation: blink-orange 5s; z-index: 9998; pointer-events: none; box-sizing: border-box; } @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } } @keyframes blink-green { 0% { opacity: 1; } 20% { opacity: 0; } 40% { opacity: 1; } 60% { opacity: 0; } 80% { opacity: 1; } 100% { opacity: 0; } } @keyframes blink-orange { 0% { opacity: 1; } 20% { opacity: 0; } 40% { opacity: 1; } 60% { opacity: 0; } 80% { opacity: 1; } 100% { opacity: 0; } } #settings-menu { position: fixed; top: 20px; right: 10px; background-color: #fff; padding: 10px; border: 1px solid #ddd; z-index: 10000; display: none; } #settings-menu-close { position: absolute; top: 0; right: 0; padding: 5px; cursor: pointer; } `; document.head.appendChild(style); // Create settings menu const settingsMenu = document.createElement('div'); settingsMenu.id = 'settings-menu'; settingsMenu.innerHTML = ` <div id="settings-menu-close">X</div> <label><input type="checkbox" id="chat-notifications" ${settings.chatNotifications ? 'checked' : ''}> Main Chat Notifications</label><br> <label><input type="checkbox" id="pm-notifications" ${settings.pmNotifications ? 'checked' : ''}> PM Notifications</label><br> <label><input type="checkbox" id="user-notifications" ${settings.userNotifications ? 'checked' : ''}> User enter/leave Notification Frame</label> `; document.body.appendChild(settingsMenu); // Add event listeners to settings menu document.getElementById('pm-notifications').addEventListener('change', (e) => { settings.pmNotifications = e.target.checked; GM_setValue('pmNotifications', settings.pmNotifications); }); document.getElementById('user-notifications').addEventListener('change', (e) => { settings.userNotifications = e.target.checked; GM_setValue('userNotifications', settings.userNotifications); }); document.getElementById('chat-notifications').addEventListener('change', (e) => { settings.chatNotifications = e.target.checked; GM_setValue('chatNotifications', settings.chatNotifications); }); document.getElementById('settings-menu-close').addEventListener('click', () => { settingsMenu.style.display = 'none'; }); // Register menu command GM_registerMenuCommand('Settings', () => { settingsMenu.style.display = 'block'; }); // Function to check for text changes function checkForChanges() { const textContent = document.body.textContent; if (textContent !== previousTextContent) { previousTextContent = textContent; // Check if the text content matches any of the after regex patterns const match1 = new RegExp(monitorText.after1).test(textContent); const match2 = new RegExp(monitorText.after2).test(textContent); const match3 = new RegExp(monitorText.after3).test(textContent); if ((match1 && settings.chatNotifications) || (match2 && settings.pmNotifications)) { // Show the blinking box and frame showBlinkingFrame(); } else { // Hide the blinking box and frame hideBlinkingFrame(); } // Blink page title (?) if (match2 && settings.pmNotifications) { blinkTitle('- '); } else { stopBlinkingTitle(); document.title = originalTitle; } if (match3 && settings.userNotifications) { const userCountMatch = textContent.match(/USERS \((\d+)\)/); if (userCountMatch && userCountMatch[1] !== previousUserCount) { const currentUserCount = parseInt(userCountMatch[1]); if (previousUserCount !== '') { showUserBlinkingFrame(currentUserCount > parseInt(previousUserCount)); } previousUserCount = userCountMatch[1]; } } } } // Function to show the blinking frame function showBlinkingFrame() { if (!blinkingFrame) { blinkingFrame = document.createElement('div'); blinkingFrame.id = 'blinking-frame'; document.body.appendChild(blinkingFrame); } } // Function to hide the blinking frame function hideBlinkingFrame() { if (blinkingFrame) { blinkingFrame.remove(); blinkingFrame = null; } } // Function to show the user blinking frame function showUserBlinkingFrame(increased) { if (userBlinkingFrame) { userBlinkingFrame.remove(); } userBlinkingFrame = document.createElement('div'); userBlinkingFrame.id = increased ? 'user-blinking-frame-green' : 'user-blinking-frame-orange'; document.body.appendChild(userBlinkingFrame); setTimeout(() => { userBlinkingFrame.remove(); }, 5000); } function blinkTitle(prefix) { stopBlinkingTitle(); let visible = true; titleBlinkInterval = setInterval(() => { if (visible) { document.title = originalTitle; visible = false; } else { document.title = prefix + originalTitle; visible = true; } }, 1000); } function stopBlinkingTitle() { if (titleBlinkInterval) { clearInterval(titleBlinkInterval); titleBlinkInterval = null; } } // Continuously check for changes setInterval(checkForChanges, 1000); // Check every 1 second })();