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
})();