Intercept WebSocket messages on StumbleChat and display them with tabs
当前为
// ==UserScript==
// @name Stumblechat Stalker
// @namespace http://tampermonkey.net/
// @version 1.03
// @description Intercept WebSocket messages on StumbleChat and display them with tabs
// @author MeKLiN
// @match https://stumblechat.com/room/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=stumblechat.com
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Create a function to display WebSocket messages under the appropriate tab
function displayWebSocketMessage(message, tab) {
const tabDiv = document.getElementById(tab);
if (tabDiv) {
const messageDiv = document.createElement("div");
messageDiv.innerHTML = message;
tabDiv.appendChild(messageDiv);
tabDiv.scrollTop = tabDiv.scrollHeight; // Auto-scroll
}
}
// Override WebSocket constructor to intercept WebSocket creation
const originalWebSocket = window.WebSocket;
window.WebSocket = function(url, protocols) {
console.log('WebSocket URL:', url);
// Call original WebSocket constructor
const ws = new originalWebSocket(url, protocols);
// Event listener for receiving messages
ws.addEventListener('message', event => {
try {
const message = JSON.parse(event.data);
// Filter messages by the "stumble" type (join, joined, msg, subscribe, publish)
switch (message.stumble) {
case "join":
displayWebSocketMessage(JSON.stringify(message), "joinTab");
break;
case "joined":
displayWebSocketMessage(JSON.stringify(message), "joinedTab");
break;
case "msg":
displayWebSocketMessage(JSON.stringify(message), "msgTab");
break;
case "subscribe":
displayWebSocketMessage(JSON.stringify(message), "subscribeTab");
break;
case "publish":
displayWebSocketMessage(JSON.stringify(message), "publishTab");
break;
default:
console.log("Unhandled message type:", message.stumble);
break;
}
} catch (error) {
console.error("Error processing WebSocket message:", error);
}
});
return ws;
};
// Method to create the overlay container with tabs
function createWebSocketTabs() {
const overlayDiv = document.createElement("div");
overlayDiv.style.position = "fixed";
overlayDiv.style.top = "0";
overlayDiv.style.left = "0";
overlayDiv.style.zIndex = "9999";
overlayDiv.style.backgroundColor = "#222";
overlayDiv.style.color = "#fff";
overlayDiv.style.padding = "10px";
overlayDiv.style.borderRadius = "8px";
overlayDiv.style.maxWidth = "400px";
overlayDiv.style.maxHeight = "80vh";
overlayDiv.style.overflowY = "auto";
overlayDiv.style.display = "flex";
overlayDiv.style.flexDirection = "column";
overlayDiv.style.justifyContent = "flex-start";
// Create Tabs
const tabNames = ["join", "joined", "msg", "subscribe", "publish"];
tabNames.forEach(tab => {
const tabButton = document.createElement("button");
tabButton.innerHTML = tab.charAt(0).toUpperCase() + tab.slice(1);
tabButton.style.backgroundColor = "#444";
tabButton.style.border = "none";
tabButton.style.padding = "10px";
tabButton.style.margin = "2px";
tabButton.style.cursor = "pointer";
tabButton.onclick = () => {
showTab(tab); // Show the clicked tab
};
overlayDiv.appendChild(tabButton);
});
// Create divs for each tab
const tabContentDivs = ["join", "joined", "msg", "subscribe", "publish"];
tabContentDivs.forEach(tab => {
const tabDiv = document.createElement("div");
tabDiv.id = tab + "Tab";
tabDiv.style.display = "none";
tabDiv.style.padding = "10px";
tabDiv.style.border = "1px solid #555";
tabDiv.style.borderRadius = "5px";
tabDiv.style.marginTop = "5px";
tabDiv.style.maxHeight = "60vh";
tabDiv.style.overflowY = "auto";
overlayDiv.appendChild(tabDiv);
});
// Append the overlay to the body
document.body.appendChild(overlayDiv);
// Function to show the selected tab
function showTab(tab) {
tabContentDivs.forEach(tabName => {
const tabDiv = document.getElementById(tabName + "Tab");
tabDiv.style.display = tabName === tab ? "block" : "none";
});
}
// Default to showing the "join" tab
showTab("join");
}
// Call the function to create the WebSocket tabs
createWebSocketTabs();
})();