Blacklist
// ==UserScript== // @name Hunter // @namespace http://tampermonkey.net/ // @version 0.94 // @description Blacklist // @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'; const handleUserMap = {}; // Initialize handleUserMap as an empty object // Define yourHandle variable const yourHandle = "myHandle"; // Replace "myHandle" with the actual handle function parseWebSocketMessage(message) { const parsedMessage = JSON.parse(message); if (parsedMessage.stumble === "joined") { const userList = parsedMessage.userlist; if (userList && userList.length > 0) { userList.forEach(user => { const username = user.username || user.nick; handleUserMap[user.handle] = username; addUserToUserList({ handle: user.handle, username }); }); } const joinMessage = "A user or users joined the chat."; // Example join message displayWebSocketMessage(joinMessage); } else if (parsedMessage.stumble === "join") { const { handle, username } = parsedMessage; handleUserMap[handle] = username; addUserToUserList({ handle, username }); const joinMessage = `${username} joined the chat.`; displayWebSocketMessage(joinMessage); } else if (parsedMessage.stumble === "quit") { const handle = parsedMessage.handle; const username = handleUserMap[handle]; if (username) { delete handleUserMap[handle]; removeUserFromUserList(handle); const quitMessage = `${username} left the chat.`; displayWebSocketMessage(quitMessage); } } else if (parsedMessage.stumble === "msg") { // Handle additional changes to the user list for specific "msg" messages } } // WebSocket Listener: 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 => { const parsedMessage = JSON.parse(event.data); // Check if the message is a "joined" message if (parsedMessage.stumble === "joined") { // Extracting our own handle from the "self" object in the message const selfHandle = parsedMessage.self.handle; // Update handleUserMap and custom user list when a user joins const userList = parsedMessage.userlist; if (userList && userList.length > 0) { userList.forEach(user => { // Check if the user being added is ourselves const isSelf = user.handle === selfHandle; // If it's our own user, update handleUserMap and display our own handle in the user list if (isSelf) { // Update handleUserMap with our own handle and username handleUserMap[user.handle] = user.username || user.nick; // Add our own handle to the custom user list with purple icon addUserToUserList({ username: user.username, handle: user.handle, active: true, // We just joined, so we're considered active icon: "🟣" // Purple icon for our own user entry }, "self"); } else { // If it's not our own user, proceed as usual and add them to the user list updateUserListAndMapOnJoin(user); } }); } } else if (parsedMessage.stumble === "join") { // Handle join messages const { handle, username } = parsedMessage; // Check if the user being added is not ourselves if (handle !== yourHandle) { handleUserMap[handle] = username; addUserToUserList({ handle, username }, "join"); } } else if (parsedMessage.stumble === "quit") { // Handle quit messages const handle = parsedMessage.handle; const username = handleUserMap[handle]; if (username) { delete handleUserMap[handle]; removeUserFromUserList(handle); setTimeout(() => { removeUserFromUserList(handle); }, 30000); // 30 seconds delay addUserToUserList({ handle, username }, "quit"); } } else if (parsedMessage.stumble === "msg") { // Handle message messages const { handle, text } = parsedMessage; const username = handleUserMap[handle] || handle; displayWebSocketMessage(event.data); } // Check if the message is a system message if (parsedMessage.stumble === "system") { const systemMessage = parsedMessage.message; // Check if the system message contains the client version if (systemMessage.startsWith('"Client Version:')) { // Save the user list to a file console.log("sysmsgdetected"); } } }); return ws; }; // Function to create user list div function createUserListDiv() { const userListDiv = document.createElement("div"); userListDiv.id = "userList"; userListDiv.style.position = "absolute"; // Change to absolute positioning userListDiv.style.top = "100px"; // Adjust top position as needed userListDiv.style.left = "10px"; // Adjust left position as needed userListDiv.style.height = "calc(100% - 100px)"; // Adjust height to fill remaining space userListDiv.style.overflowY = "auto"; userListDiv.style.color = "#ffffff"; userListDiv.style.padding = "10px"; userListDiv.style.zIndex = "2"; // Set a higher z-index value userListDiv.style.display = "none"; // Hide the custom user list by default return userListDiv; } // Function to append new content to users.txt file function appendToUserListFile(newContent) { // Create a Blob object containing the new content const blob = new Blob([newContent], { type: "text/plain" }); // Create a temporary anchor element to trigger the download const a = document.createElement("a"); const url = URL.createObjectURL(blob); a.href = url; a.download = "users.txt"; // Simulate a click on the anchor element to start the download document.body.appendChild(a); a.click(); // Remove the temporary anchor element document.body.removeChild(a); // Release the Object URL URL.revokeObjectURL(url); } // Function to save user list to users.txt file function saveUserListToFile() { // Extracting user information from handleUserMap const users = []; for (const handle in handleUserMap) { const username = handleUserMap[handle]; users.push(`${username} (${handle}) B`); // Append 'B' to the handle } // Convert the user list to a string const userListString = users.join("\n"); // Append the new content to the existing users.txt file appendToUserListFile(userListString); } // Function to display the user list (handle map) function displayUserList() { const userList = document.getElementById("userListDisplay"); if (userList) { // Clear the user list before updating userList.innerHTML = ""; // Iterate over the handleUserMap and display each handle and username for (const handle in handleUserMap) { const username = handleUserMap[handle]; const listItem = document.createElement("li"); listItem.textContent = `${username} (${handle})`; userList.appendChild(listItem); } } } // Function to create and append the pop-up window overlay with input menu and close button function createUserOverlay() { const overlay = document.createElement("div"); overlay.id = "overlay"; overlay.style.position = "fixed"; overlay.style.top = "50%"; overlay.style.width = "80%"; // container width overlay.style.left = "50%"; overlay.style.transform = "translate(-50%, -50%)"; overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; overlay.style.zIndex = "9999"; overlay.style.padding = "20px"; overlay.style.textAlign = "center"; const closeButton = document.createElement("button"); closeButton.textContent = "Close"; closeButton.style.position = "absolute"; closeButton.style.top = "10px"; closeButton.style.right = "10px"; closeButton.addEventListener("click", () => { overlay.remove(); // Remove the overlay when the close button is clicked }); overlay.appendChild(closeButton); const userListContainer = document.createElement("div"); userListContainer.style.display = "flex"; userListContainer.style.justifyContent = "space-between"; // Align columns to left and right edges overlay.appendChild(userListContainer); const userListHandleMap = document.createElement("ul"); userListHandleMap.id = "userListHandleMap"; userListHandleMap.style.listStyleType = "none"; userListHandleMap.style.padding = "0"; userListHandleMap.style.width = "50%"; // Adjust the percentage based on your layout needs userListHandleMap.style.color = "lime"; userListHandleMap.style.backgroundColor = "black"; userListContainer.appendChild(userListHandleMap); // Second column for data from loadUsersFromFile() function const userListLoadedFromFile = document.createElement("ul"); userListLoadedFromFile.id = "userListLoadedFromFile"; // Add an id to reference the user list later userListLoadedFromFile.style.listStyleType = "none"; userListLoadedFromFile.style.padding = "0"; userListLoadedFromFile.style.color = "cyan"; // Set font color to cyan userListLoadedFromFile.style.backgroundColor = "black"; // Set background color to black userListLoadedFromFile.style.flex = "1"; // Use flex to make the column expand to fill available space userListLoadedFromFile.style.marginLeft = "10px"; // Add margin to separate from the first column userListContainer.appendChild(userListLoadedFromFile); function populateUserListHandleMap() { userListHandleMap.innerHTML = ""; for (const handle in handleUserMap) { if (handleUserMap.hasOwnProperty(handle)) { const listItem = document.createElement("li"); listItem.textContent = `${handleUserMap[handle]} (${handle})`; listItem.style.marginBottom = "5px"; userListHandleMap.appendChild(listItem); } } } function populateUserListLoadedFromFile(loadedUsers) { userListLoadedFromFile.innerHTML = ""; loadedUsers.forEach(user => { const listItem = document.createElement("li"); listItem.textContent = `${user.username} (${user.handle})`; listItem.style.marginBottom = "5px"; userListLoadedFromFile.appendChild(listItem); }); } populateUserListHandleMap(); const inputLabel = document.createElement("label"); inputLabel.textContent = "Add 'B' to user handles:"; inputLabel.style.color = "#ffffff"; inputLabel.style.marginTop = "20px"; overlay.appendChild(inputLabel); const inputField = document.createElement("input"); inputField.id = "handleInput"; inputField.type = "text"; inputField.style.margin = "10px auto"; inputField.style.display = "block"; overlay.appendChild(inputField); const applyButton = document.createElement("button"); applyButton.textContent = "Apply"; applyButton.style.margin = "10px auto"; applyButton.style.display = "block"; overlay.appendChild(applyButton); document.body.appendChild(overlay); } // Function to create and append the input box overlay with user list display function createTartOverlay() { const overlay = document.createElement("div"); overlay.id = "overlay"; overlay.style.position = "fixed"; overlay.style.bottom = "50px"; overlay.style.left = "0px"; overlay.style.zIndex = "9999"; overlay.style.display = "flex"; overlay.style.flexDirection = "column"; overlay.style.alignItems = "flex-start"; const userList = document.createElement("ul"); userList.id = "userList"; userList.style.listStyleType = "none"; overlay.appendChild(userList); const inputField = document.createElement("input"); inputField.id = "commandInput"; inputField.type = "text"; inputField.placeholder = "Type command here..."; inputField.style.margin = "10px"; inputField.style.width = "200px"; // Adjust width as needed overlay.appendChild(inputField); // Listen for input changes inputField.addEventListener("input", () => { const command = inputField.value.trim(); if (command.startsWith("#ban")) { const handle = command.replace("#ban", "").trim(); if (handle !== "") { addBToHandleOrUsername(handle); inputField.value = ""; // Clear input field after processing command } } // Add more command listeners here as needed }); document.body.appendChild(overlay); } // Function to create buttons for other overlays function createButtonsForOverlays() { // Create button for Tart overlay const tartButton = document.createElement("button"); tartButton.textContent = "Open Tart Overlay"; tartButton.style.position = "fixed"; tartButton.style.bottom = "50px"; tartButton.style.left = "210px"; // Adjust position as needed tartButton.style.zIndex = "9999"; tartButton.addEventListener("click", createTartOverlay); document.body.appendChild(tartButton); // Create button for User overlay const userButton = document.createElement("button"); userButton.textContent = "Open User Overlay"; userButton.style.position = "fixed"; userButton.style.bottom = "50px"; userButton.style.left = "420px"; // Adjust position as needed userButton.style.zIndex = "9999"; userButton.addEventListener("click", createUserOverlay); document.body.appendChild(userButton); } // Call the function to create buttons for other overlays createButtonsForOverlays(); // Function to create and append the input box overlay function createBox() { const overlay = document.createElement("div"); overlay.id = "overlay"; overlay.style.position = "fixed"; overlay.style.bottom = "50px"; overlay.style.left = "0px"; overlay.style.zIndex = "9999"; const inputField = document.createElement("input"); inputField.id = "commandInput"; inputField.type = "text"; inputField.placeholder = "Type command here..."; inputField.style.margin = "10px"; inputField.style.width = "200px"; // Adjust width as needed overlay.appendChild(inputField); let commandBuffer = ""; // Buffer to store the command until Enter is pressed // Listen for input changes inputField.addEventListener("input", () => { commandBuffer = inputField.value.trim(); // Update command buffer with current input }); // Listen for keydown event inputField.addEventListener("keydown", (event) => { if (event.key === "Enter") { // Process the command when Enter key is pressed if (commandBuffer.startsWith("#ban ")) { const usernameOrHandle = commandBuffer.replace("#ban ", "").trim(); if (usernameOrHandle !== "") { addBToHandleOrUsername(usernameOrHandle); inputField.value = ""; // Clear input field after processing command } else { alert("Username or handle not provided!"); } } else { alert("Invalid command! Please use '#ban usernameOrHandle'"); } commandBuffer = ""; // Clear the command buffer after processing } }); document.body.appendChild(overlay); } // Call the function to create the input box overlay createBox(); function addBToHandleOrUsername(handleOrUsername) { let handle = handleOrUsername; let found = false; // Check if the handle exists in the handleUserMap if (handleUserMap.hasOwnProperty(handleOrUsername)) { handle = handleOrUsername; found = true; } if (found) { // Add 'B' next to the handle number handleUserMap[handle] += " B"; // Update the user list display displayUserList(); // Save the updated user list to the file saveUserListToFile(); } else { alert("User not found!"); } } // Function to load users from the users.txt file function loadUsersFromFile() { const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = '.txt'; fileInput.addEventListener('change', function() { const file = fileInput.files[0]; const reader = new FileReader(); reader.onload = function(event) { const fileContent = event.target.r###lt; // Update handleUserMap with user data from the loaded file updateHandleUserMap(fileContent); // Display loaded users console.log("Loaded Users:"); for (const handle in handleUserMap) { if (handleUserMap.hasOwnProperty(handle)) { console.log(`${handleUserMap[handle]} (${handle})`); } } // Define and populate loadedUsers based on handleUserMap const loadedUsers = Object.keys(handleUserMap).map(handle => ({ handle: handle, username: handleUserMap[handle] })); // Example usage of addBToHandleOrUsername with loadedUsers addBToHandleOrUsername("handleOrUsername", loadedUsers); }; reader.readAsText(file); }); fileInput.click(); } // Function to update handleUserMap with user data from the loaded file function updateHandleUserMap(fileContent) { // Split the file content into lines const lines = fileContent.split('\n'); // Iterate over each line to parse user data lines.forEach(line => { const userData = line.trim().split(' '); // Splitting by space to separate username and handle if (userData.length === 2) { const username = userData[0].trim(); const handle = userData[1].trim(); // Check if the handle already exists in the handleUserMap if (!handleUserMap.hasOwnProperty(handle)) { // Update user map with the new username and handle handleUserMap[handle] = username; } } }); } // Function to update the user list display function updateUserListDisplay() { // Get the user list element const userList = document.getElementById("userList"); if (userList) { // Update the display with modified handleUserMap userList.innerHTML = ""; // Clear the user list for (const handle in handleUserMap) { const username = handleUserMap[handle]; // Append the user to the user list with 'B' if present const listItem = document.createElement("li"); listItem.textContent = `${username} (${handle})`; userList.appendChild(listItem); } } } // WebSocket listener for handling messages function handleWebSocketMessage(message) { const parsedMessage = JSON.parse(message); const ownHandle = getOwnHandle(); // Function to get the user's own handle number if (parsedMessage.stumble === "msg" && ownHandle === parsedMessage.handle) { const text = parsedMessage.text; if (text.startsWith("#ban")) { // Extract the handle from the message const handleToBan = text.replace("#ban", "").trim(); if (handleToBan !== "") { // Check if the handle exists in the handleUserMap if (handleUserMap.hasOwnProperty(handleToBan)) { // Add 'B' next to the handle number handleUserMap[handleToBan] += " B"; // Update the user list display updateUserListDisplay(); // Update the users.txt file saveUserListToFile(); } else { alert("Handle not found!"); } } else { alert("Invalid handle!"); } } } } // Function to get the user's own handle number (implement your own logic) function getOwnHandle() { // Implement your logic to retrieve the user's own handle number // For demonstration purposes, return a hardcoded value return "123456"; // Replace with your actual handle number } // Function to set up WebSocket listener function setupWebSocketListener() { // 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 => { handleWebSocketMessage(event.data); }); return ws; }; } // Call functions to set up overlay, WebSocket listener, and initial user list display setupWebSocketListener(); updateUserListDisplay(); // Function to display WebSocket messages and update user list function displayWebSocketMessage(message) { const parsedMessage = JSON.parse(message); if (parsedMessage.stumble === "join") { // Handle join messages: Extract handle and username from the message const { handle, username } = parsedMessage; // Map handle to username in handleUserMap handleUserMap[handle] = username; // Add the user to the custom user list with the appropriate icon (join user) addUserToUserList({ handle, username }, "join"); } else if (parsedMessage.stumble === "msg") { // Handle message messages: Extract handle and text from the message const { handle, text } = parsedMessage; // Retrieve username from handleUserMap or use handle if not found const username = handleUserMap[handle] || handle; // Display the message in the WebSocket messages div const webSocketMessagesDiv = document.getElementById("webSocketMessages"); if (webSocketMessagesDiv) { // Append the message with a newline character webSocketMessagesDiv.textContent += `${username}: ${text}\n`; // Scroll to the bottom of the messages div webSocketMessagesDiv.scrollTop = webSocketMessagesDiv.scrollHeight; } // Additional logic for handling commands if (text === "#join") { console.log("join"); // Add your logic here } else if (text === "#icon") { console.log("icon"); // Add your logic here } else if (text === "#tokes") { console.log("tokes"); // Call your tokes function here TokesSendEnter(); } else if (text.startsWith("#ai ")) { console.log("ai"); // Extract the word after "#ai" const word = text.substring(4); console.log("Word after '#ai':", word); // Call your AI function here with the extracted word DoAi(word); // Adjust parameters as needed } } else if (parsedMessage.stumble === "joined") { // Handle joined messages: Add users to handleUserMap and custom user list const userList = parsedMessage.userlist; if (userList && userList.length > 0) { userList.forEach(user => { // Extract username from either "username" or "nick" const username = user.username || user.nick; // Map handle to username in handleUserMap handleUserMap[user.handle] = username; // Add the user to the custom user list with the appropriate icon addUserToUserList({ handle: user.handle, username }, "joined"); }); } } else if (parsedMessage.stumble === "quit") { // Handle quit messages: Remove users from handleUserMap and custom user list const handle = parsedMessage.handle; const username = handleUserMap[handle]; if (username) { // Remove the handle from handleUserMap delete handleUserMap[handle]; // Remove the user from the custom user list removeUserFromUserList(handle); } } } // Function to add user to user list with appropriate icon based on user type function addUserToUserList(user, userType) { const userList = document.getElementById("userList"); if (!userList) return; const userItem = document.createElement("div"); userItem.textContent = `${user.username}`; // Define the default dot color and icon let dotColor = "red"; // Default dot color let icon = "🔴"; // Default icon for inactive users // Set dot color and icon based on user type if (userType === "self") { dotColor = "purple"; // Purple for self user icon = "🟣"; // Purple circle icon } else if (userType === "join") { dotColor = "blue"; // Blue for join user icon = "🔵"; // Blue circle icon } else if (userType === "joined") { // "self" user type listener for user list" dotColor = "green"; // Green for joined user icon = "🟢"; // Green circle icon } // Add colored dot based on user status const dot = document.createElement("span"); dot.textContent = icon; dot.style.color = dotColor; userItem.appendChild(dot); // Add custom icon for the user if (user.icon) { const customIcon = document.createElement("span"); customIcon.textContent = user.icon; customIcon.style.marginLeft = "5px"; // Adjust margin as needed userItem.appendChild(customIcon); } userList.appendChild(userItem); // Append user item to the user list // If user is not active and not yourself, show popup for 5 seconds //if (!user.active && user.handle !== yourHandle) { //const popup = document.createElement("div"); //popup.textContent = "WELCOME TO STUMBLECHAT YEOPARDY!"; //popup.style.fontSize = "48px"; //popup.style.position = "fixed"; //popup.style.top = "50%"; //popup.style.left = "50%"; //popup.style.transform = "translate(-50%, -50%)"; //popup.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; //popup.style.color = "white"; //popup.style.padding = "10px"; //popup.style.borderRadius = "5px"; //document.body.appendChild(popup); } // Function to update handleUserMap and add users to custom user list function updateUserListAndMapOnJoin(user) { // Update handleUserMap with the new user handleUserMap[user.handle] = user.username || user.nick; // Derive username from handle or nick // Add the new user to the custom user list addUserToUserList(user); } // Call the function to update the user list function updateUserListOnMessage(userList) { return function(message) { const parsedMessage = JSON.parse(message); if (parsedMessage.stumble === "join" || parsedMessage.stumble === "msg" || parsedMessage.stumble === "joined") { // Add user to user list addUserToUserList(parsedMessage); } }; } // Function to create WebSocket messages div function createWebSocketMessagesDiv() { const div = document.createElement("div"); div.id = "webSocketMessages"; div.style.position = "relative"; div.style.height = "25%"; div.style.paddingLeft = "2px"; div.style.visibility = "visible"; // Ensure the div is visible div.style.willChange = "transform"; div.style.boxSizing = "border-box"; div.style.overflowX = "hidden"; div.style.overflowY = "auto"; div.style.color = "#ffffff"; // Set font color to white div.style.padding = "10px"; // Example padding div.style.zIndex = "2"; // Set a higher z-index value for the WebSocket messages div // Additional styles for specific scenarios div.style.display = "flex"; div.style.flexDirection = "column"; div.style.justifyContent = "flex-end"; div.style.fontSize = "18px"; div.style.whiteSpace = "pre-wrap"; // Allow text to wrap within the container div.style.wordWrap = "break-word"; // Allow long words to break and wrap // Locate the chat-position div const chatPositionDiv = document.getElementById("chat-position"); if (chatPositionDiv) { // Append custom div to the chat-position div chatPositionDiv.appendChild(div); } else { // If chat-position div not found, append to document body as fallback document.body.appendChild(div); } } // Call the function to create the WebSocket messages div createWebSocketMessagesDiv(); // Call the function to create the user list div const userListDiv = createUserListDiv(); const chatContainer = document.getElementById("chat-container"); if (chatContainer) { chatContainer.appendChild(userListDiv); // Append to chat container instead } else { document.body.appendChild(userListDiv); } // Function to remove user from custom user list function removeUserFromUserList(handle) { const userList = document.getElementById("userList"); if (userList) { const userElements = userList.querySelectorAll("div"); userElements.forEach(userElement => { if (userElement.textContent.includes(`(${handle})`)) { userElement.remove(); } }); } } // Function to toggle visibility of custom user list function toggleCustomUserList() { const userListDiv = document.getElementById("userList"); if (userListDiv) { userListDiv.style.display = userListDiv.style.display === "none" ? "block" : "none"; } } // Add a button to toggle visibility of custom user list const toggleButton = document.createElement("button"); toggleButton.textContent = "U"; toggleButton.style.position = "fixed"; toggleButton.style.top = "10px"; toggleButton.style.left = "10px"; toggleButton.addEventListener("click", toggleCustomUserList); document.body.appendChild(toggleButton); // Function to clear messages function clr() { const webSocketMessagesDiv = document.getElementById("webSocketMessages"); if (webSocketMessagesDiv) { webSocketMessagesDiv.innerHTML = ""; } } // Function to create fadeaway popup text with "WELCOME" message function showWelcomePopupText() { const popup = document.createElement("div"); popup.textContent = "WELCOME"; popup.classList.add("fadeaway-popup"); document.body.appendChild(popup); // Remove the popup after 3 seconds setTimeout(() => { popup.remove(); }, 3000); // 3 seconds delay } // Function to create SVG animation function createSVGAnimation() { // Create SVG element const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("width", "100"); svg.setAttribute("height", "100"); // Create rectangle inside SVG const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); rect.setAttribute("width", "100"); rect.setAttribute("height", "100"); rect.setAttribute("fill", "blue"); svg.appendChild(rect); // Append SVG to body document.body.appendChild(svg); // Animate SVG const animation = document.createElementNS("http://www.w3.org/2000/svg", "animate"); animation.setAttribute("attributeName", "x"); animation.setAttribute("from", "-100"); animation.setAttribute("to", "100%"); animation.setAttribute("dur", "5s"); animation.setAttribute("repeatCount", "indefinite"); rect.appendChild(animation); } // Call the function to show the welcome popup with SVG animation showWelcomePopupText(); // Call the function to create SVG animation createSVGAnimation(); function IrcMode() { const chatContent = document.getElementById("chat-content"); if (chatContent) { // Remove the chat-content div from the DOM chatContent.remove(); // Move the webSocketMessagesDiv and the form input to fixed position const webSocketMessagesDiv = document.getElementById("webSocketMessages"); const formInput = document.getElementById("input"); if (webSocketMessagesDiv && formInput) { webSocketMessagesDiv.style.position = "fixed"; webSocketMessagesDiv.style.top = "0px"; webSocketMessagesDiv.style.height = "90%"; // Adjust height to 90% webSocketMessagesDiv.style.overflowY = "auto"; // Add scrollbar formInput.style.position = "fixed"; formInput.style.bottom = "0px"; } // Create Save Text button createSaveTextButton(); } // Disable the room.js functionality disableRoomJS(); } // Function to save text content without <br> elements async function saveText() { console.log("Save Text button clicked."); // Debugging: Log button click const webSocketMessagesDiv = document.getElementById("webSocketMessages"); if (webSocketMessagesDiv) { console.log("webSocketMessagesDiv found:", webSocketMessagesDiv); // Debugging: Log webSocketMessagesDiv const textContent = webSocketMessagesDiv.textContent.replaceAll('\n', '\r\n'); console.log("Text content:", textContent); // Debugging: Log extracted text content try { // Use File System Access API to prompt user to save text content to a file const handle = await window.showSaveFilePicker({ types: [{ description: 'Text Files', accept: { 'text/plain': ['.txt'] } }] }); const writable = await handle.createWritable(); await writable.write(textContent); await writable.close(); console.log("Text content saved."); // Debugging: Log text saving success } catch (error) { console.error("Error saving text content:", error); // Log error if saving fails } } else { console.log("webSocketMessagesDiv not found."); // Debugging: Log if webSocketMessagesDiv is not found } } // Function to create Save Text button function createSaveTextButton() { const saveTextButton = document.createElement("button"); saveTextButton.id = "saveTextButton"; saveTextButton.textContent = "Save Text"; saveTextButton.style.position = "fixed"; // Position fixed saveTextButton.style.bottom = "10px"; // Adjust bottom position saveTextButton.style.left = "10px"; // Adjust left position saveTextButton.style.background = "black"; saveTextButton.style.color = "lime"; saveTextButton.style.border = "none"; saveTextButton.style.padding = "5px 10px"; saveTextButton.style.cursor = "pointer"; saveTextButton.type = "button"; // Specify that it's a button and not submit saveTextButton.addEventListener("click", saveText); document.body.appendChild(saveTextButton); // Append to document body } // Function to remove Save Text button function removeSaveTextButton() { const saveTextButton = document.getElementById("saveTextButton"); if (saveTextButton) { saveTextButton.remove(); } } // Call the function to remove the Save Text button initially removeSaveTextButton(); // Function to disable room.js functionality function disableRoomJS() { // Remove the event listener for message reception window.removeEventListener('messageReceived', handleMessageReceived); } // Example function that handles incoming messages in room.js function handleMessageReceived(event) { // Logic to process incoming messages } // Modify the handleKeyPress function to handle button clicks as well function handleKeyPress(event) { if ((event.key === 'Enter' || event.code === 'Enter') && !event.shiftKey) { event.preventDefault(); // Prevent the default behavior (creating a new line) // Call your message sending function here sendMessage(); // Reset the input box's content resetInputBox(); } } // Function to send the "Tokes in 20 seconds" message and simulate Enter key press function TokesSendEnter() { // Insert predefined text const textArea = document.getElementById("textarea"); textArea.value += 'Tokes in 20 seconds\n'; // Simulate Enter key press const event = new KeyboardEvent('keypress', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true }); textArea.dispatchEvent(event); // Set a timeout to display "tokes started" message after 20 seconds setTimeout(function() { textArea.value += 'tokes started\n'; // Send message indicating tokes has started // Simulate Enter key press again textArea.dispatchEvent(event); }, 20000); // 20 seconds delay } // Function to insert predefined text and simulate Enter key press function insertPredefinedTextAndPressEnter() { // Insert predefined text const textArea = document.getElementById("textarea"); textArea.value += "(╭☞ ͡ ͡°͜ ʖ ͡ ͡ )╭☞"; // Simulate Enter key press const event = new KeyboardEvent('keypress', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true }); textArea.dispatchEvent(event); } // Create a button to insert predefined text and press Enter function createInsertTextButton() { const insertTextButton = document.createElement("button"); insertTextButton.textContent = "☞"; insertTextButton.style.background = "black"; insertTextButton.style.color = "lime"; insertTextButton.style.border = "none"; insertTextButton.style.padding = "5px 10px"; insertTextButton.style.cursor = "pointer"; insertTextButton.type = "button"; // Specify that it's a button and not submit insertTextButton.addEventListener("click", insertPredefinedTextAndPressEnter); const textArea = document.getElementById("textarea"); textArea.parentElement.appendChild(insertTextButton); } // Call the function to create the insert text button createInsertTextButton(); // Function to reset the input box's content function resetInputBox() { const textArea = document.getElementById("textarea"); if (textArea) { textArea.value = ""; // Clear the textarea } } function createPopup() { const popup = document.createElement("div"); popup.id = "messagePopup"; popup.style.position = "fixed"; popup.style.top = "50%"; popup.style.left = "50%"; popup.style.transform = "translate(-50%, -50%)"; popup.style.background = "#fff"; popup.style.padding = "20px"; popup.style.border = "1px solid #ccc"; popup.style.boxShadow = "0 0 10px rgba(0, 0, 0, 0.1)"; popup.style.zIndex = "9999"; const textarea = document.createElement("textarea"); textarea.id = "popupTextarea"; textarea.placeholder = "Type a message"; textarea.maxLength = "500"; textarea.style.width = "100%"; textarea.style.marginBottom = "10px"; popup.appendChild(textarea); const sendButton = document.createElement("button"); sendButton.textContent = "Send"; sendButton.style.background = "black"; sendButton.style.color = "lime"; sendButton.style.border = "none"; sendButton.style.padding = "5px 10px"; sendButton.style.cursor = "pointer"; sendButton.addEventListener("click", sendMessage); popup.appendChild(sendButton); document.body.appendChild(popup); } function openPopup() { const popup = document.getElementById("messagePopup"); if (popup) { popup.style.display = "block"; } else { createPopup(); } } function closePopup() { const popup = document.getElementById("messagePopup"); if (popup) { popup.style.display = "none"; } } function sendMessage() { const textArea = document.getElementById("popupTextarea"); if (textArea) { const message = textArea.value.trim(); if (message !== "") { // Modify your logic here to match the behavior of their Message.send function // For example, if you're directly sending to the WebSocket: StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "msg", "text": message })); // Clear the textarea after sending the message textArea.value = ""; closePopup(); } } } function clrall() { const chatContent = document.getElementById("chat-content"); const webSocketMessagesDiv = document.getElementById("webSocketMessages"); if (chatContent && webSocketMessagesDiv) { // Clear all child elements of chatContent chatContent.innerHTML = ""; // Move webSocketMessagesDiv to the bottom chatContent.appendChild(webSocketMessagesDiv); // Adjust height of webSocketMessagesDiv webSocketMessagesDiv.style.height = "75%"; } } // Function to toggle compact view function toggleCompactView() { const messages = document.querySelectorAll('.message .content'); messages.forEach(message => { message.classList.toggle('compact'); }); } // Function to create and populate handle-username dropdown menu function createHandleUsernameDropdown() { const handleUsernameDropdown = document.createElement("select"); handleUsernameDropdown.id = "handleUsernameDropdown"; handleUsernameDropdown.style.margin = "0 5px"; handleUsernameDropdown.innerHTML = '<option value="" disabled selected>who</option>'; for (const handle in handleUserMap) { const option = document.createElement("option"); option.value = handle; option.textContent = handleUserMap[handle]; handleUsernameDropdown.appendChild(option); } return handleUsernameDropdown; } // Create top buttons function createTopButtons() { const topButtonsDiv = document.createElement("div"); topButtonsDiv.id = "topButtons"; topButtonsDiv.style.position = "fixed"; topButtonsDiv.style.top = "10px"; topButtonsDiv.style.left = "50%"; topButtonsDiv.style.transform = "translateX(-50%)"; topButtonsDiv.style.zIndex = "9999"; // Clear WebSocket messages button const clrButton = document.createElement("button"); clrButton.textContent = "clr"; clrButton.style.background = "black"; clrButton.style.color = "lime"; clrButton.addEventListener("click", clr); topButtonsDiv.appendChild(clrButton); // Clear WebSocket messages button const clrallButton = document.createElement("button"); clrallButton.textContent = "clrall"; clrallButton.style.background = "black"; clrallButton.style.color = "lime"; clrallButton.addEventListener("click", clr); topButtonsDiv.appendChild(clrallButton); // Delete chat and switch to IRC only mode const IrcModeButton = document.createElement("button"); IrcModeButton.textContent = "irc"; IrcModeButton.style.background = "black"; IrcModeButton.style.color = "lime"; IrcModeButton.addEventListener("click", IrcMode); topButtonsDiv.appendChild(IrcModeButton); // Dropdown menu for handle-username mapping const handleUsernameDropdown = createHandleUsernameDropdown(); topButtonsDiv.appendChild(handleUsernameDropdown); // Color picker button const colorPickerButton = document.createElement("button"); colorPickerButton.textContent = "Color"; colorPickerButton.style.background = "black"; colorPickerButton.style.color = "lime"; colorPickerButton.style.margin = "0 5px"; colorPickerButton.addEventListener("click", () => { openColorPickerPopup(); }); topButtonsDiv.appendChild(colorPickerButton); // Font size dropdown const fontSizeDropdown = document.createElement("select"); fontSizeDropdown.id = "fontSizeDropdown"; fontSizeDropdown.style.margin = "0 5px"; for (let i = 1; i <= 20; i++) { const option = document.createElement("option"); option.value = i; option.textContent = i; fontSizeDropdown.appendChild(option); } fontSizeDropdown.addEventListener("change", () => { const selectedFontSize = fontSizeDropdown.value; applyFontSize(selectedFontSize); }); topButtonsDiv.appendChild(fontSizeDropdown); // Append top buttons div to document body document.body.appendChild(topButtonsDiv); } // Function to apply font size to WebSocket messages function applyFontSize(fontSize) { const webSocketMessagesDiv = document.getElementById("webSocketMessages"); if (webSocketMessagesDiv) { webSocketMessagesDiv.style.fontSize = `${fontSize}px`; } } // Call the function to create top buttons createTopButtons(); // Function to open color picker popup function openColorPickerPopup() { const popup = document.createElement("div"); popup.id = "colorPickerPopup"; popup.style.position = "fixed"; popup.style.top = "50%"; popup.style.left = "50%"; popup.style.transform = "translate(-50%, -50%)"; popup.style.background = "#1f1f1f"; popup.style.padding = "20px"; popup.style.border = "2px solid #ffffff"; popup.style.zIndex = "99999"; const backgroundLabel = document.createElement("label"); backgroundLabel.textContent = "Background Color:"; backgroundLabel.style.color = "#ffffff"; popup.appendChild(backgroundLabel); const backgroundColorInput = document.createElement("input"); backgroundColorInput.type = "color"; backgroundColorInput.id = "backgroundColorInput"; backgroundColorInput.style.marginRight = "10px"; backgroundColorInput.value = "#000000"; popup.appendChild(backgroundColorInput); const fontColorLabel = document.createElement("label"); fontColorLabel.textContent = "Font Color:"; fontColorLabel.style.color = "#ffffff"; popup.appendChild(fontColorLabel); const fontColorInput = document.createElement("input"); fontColorInput.type = "color"; fontColorInput.id = "fontColorInput"; fontColorInput.style.marginRight = "10px"; fontColorInput.value = "#ffffff"; popup.appendChild(fontColorInput); const applyButton = document.createElement("button"); applyButton.textContent = "Apply"; applyButton.style.background = "black"; applyButton.style.color = "lime"; applyButton.style.marginTop = "10px"; applyButton.addEventListener("click", () => { applyColors(backgroundColorInput.value, fontColorInput.value); popup.remove(); }); popup.appendChild(applyButton); const closeButton = document.createElement("button"); closeButton.textContent = "Close"; closeButton.style.background = "black"; closeButton.style.color = "lime"; closeButton.style.marginTop = "10px"; closeButton.style.marginLeft = "10px"; closeButton.addEventListener("click", () => { popup.remove(); }); popup.appendChild(closeButton); document.body.appendChild(popup); } // Function to apply selected colors to WebSocket log function applyColors(backgroundColor, fontColor) { const webSocketMessagesDiv = document.getElementById("webSocketMessages"); if (webSocketMessagesDiv) { webSocketMessagesDiv.style.backgroundColor = backgroundColor; webSocketMessagesDiv.style.color = fontColor; } } /* Additional compacting styles */ /*@-moz-document url-prefix("https://stumblechat.com/room/") {*/ // Compact message styles const compactStyles = ` .message .nickname ~ .content { display: inline-block; top: -7px; position: relative; margin-left: 2px; margin-right: 1em; } .content + .content { display: inline-block!important; margin-right: 1em; } .message .nickname ~ .content span { line-height: 1.5em; } `; // Apply compact styles to the document const style = document.createElement('style'); style.textContent = compactStyles; document.head.appendChild(style); /*}*/ // Function to handle click events for the new button function handleLoadButtonClick() { // Add functionality for the new button here console.log('Load button clicked'); } // Function to handle click events for the new button function handleDisplayThingsButtonClick() { // Add functionality for the new button here console.log('Load button clicked'); } // Create a new button configuration const DisplayThingsButtonConfig = { name: 'd', text: 'display', clickHandler: handleDisplayThingsButtonClick }; // Create a new button configuration const LoadButtonConfig = { name: 'n', text: 'Load', clickHandler: handleLoadButtonClick }; // Function to create generic buttons function createGenericButtons() { // Define button configurations const buttonConfigurations = [ { name: 'c', text: 'Compact', clickHandler: toggleCompactView }, { name: 's', text: 'Save', clickHandler: () => { // Functionality to save handle-username map to memory or file console.log("Save button clicked"); saveUserListToFile(); }}, { name: 'L', text: 'Load Users', clickHandler: loadUsersFromFile }, // Button to load users from file LoadButtonConfig, // Add the new button configuration here { name: 'D', text: 'Display Things', clickHandler: handleDisplayThingsButtonClick } // Button to load users from file ]; // Get the container for the buttons const container = document.getElementById('topButtons'); // Loop through each button configuration and generate a button buttonConfigurations.forEach(config => { // Create a button element const button = document.createElement('button'); button.textContent = config.text; // Use button text as text content button.style.background = "black"; button.style.color = "lime"; button.style.width = "50px"; // Set button width button.style.height = "20px"; // Set button height button.style.margin = "0 5px"; // Set button margin // Add event listener based on configuration button.addEventListener('click', config.clickHandler); // Append the button to the container in the DOM container.appendChild(button); }); } // Call the function to create generic buttons createGenericButtons(); // Function to create a new button and append it to the container function createDisconnectButton() { const container = document.getElementById('topButtons'); // Create the button element const newButton = document.createElement('button'); newButton.textContent = 'DC'; // Change the text as needed newButton.style.background = 'black'; newButton.style.color = 'lime'; newButton.style.width = '100px'; // Set the button width newButton.style.height = '30px'; // Set the button height newButton.style.margin = '0 5px'; // Set the button margin // Add event listener to the new button newButton.addEventListener('click', () => { // Add functionality for the new button here console.log('New button clicked'); }); // Append the new button to the container container.appendChild(newButton); } // Call the function to create the new button createDisconnectButton(); // Function to load users from the users.txt file function displayThings() { const users = []; // Placeholder for file content, replace this with your file reading logic // Example: You can use XMLHttpRequest, fetch API, or any other method to read the file // For simplicity, I'll use fetch API assuming users.txt is in the same directory fetch('users.txt') .then(response => response.text()) .then(fileContent => { // Split the file content into lines const lines = fileContent.split('\n'); // Iterate over each line to parse user data lines.forEach(line => { const userData = line.trim().split(' '); // Splitting by space to separate username and handle if (userData.length === 2) { const username = userData[0].trim(); const handle = userData[1].trim(); users.push({ username, handle }); // Update user map handleUserMap[handle] = username; } }); // Display loaded users console.log("Loaded Users:"); users.forEach(user => { console.log(`${user.username} (${user.handle})`); }); }) .catch(error => { console.error('Error loading users from file:', error); }); return users; } // Find the CSP meta tag and modify its content attribute const cspMeta = document.querySelector("meta[http-equiv='Content-Security-Policy']"); if (cspMeta) { cspMeta.setAttribute("content", "your-updated-csp-directives"); } const proxyUrl = "http://65.25.72.68:43435"; // Add http:// or https:// as needed // Function to call the AI and send its response to the chat room function DoAi(cmd_arg) { // Define your OpenAI API key and other parameters const api_key = 'your-api-key'; const endpoint = proxyUrl; // Use proxy server endpoint const max_tokens = 200; const max_parts = 10; const delay_between_parts = 2; const min_response_length = 10; const headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + api_key, }; const data = { model: 'gpt-3.5-turbo', messages: [{role: 'system', content: 'You are a helpful assistant.'}, {role: 'user', content: cmd_arg}], max_tokens: max_tokens, }; // Send the POST request to the API via proxy server fetch(endpoint, { method: 'POST', headers: headers, body: JSON.stringify(data) }) .then(response => { if (!response.ok) { throw new Error('Request failed with status code ' + response.status); } return response.json(); }) .then(r###lt => { if (r###lt.choices && r###lt.choices[0] && r###lt.choices[0].message && r###lt.choices[0].message.content) { let response_text = r###lt.choices[0].message.content; // Check if the response_text is not empty and meets the minimum length if (response_text.trim() && response_text.length >= min_response_length) { // Use regular expression to replace various line break characters response_text = response_text.replace(/[\r\n\t\f\v]+/g, ' '); // Split the response into parts based on sentence-like breaks const parts = response_text.match(/.{1,200}(?:\.\s|\.$|$)/g) || []; const num_parts = Math.min(max_parts, parts.length); // Calculate the time interval for rate limiting (15 seconds / 3 messages) const rate_limit_interval = 15.0 / 3; // Send each part with a delay parts.slice(0, num_parts).forEach((part, index) => { setTimeout(() => { // Send the part to the chat room sendMessage(part); }, index * delay_between_parts * 1000); }); } else { sendMessage("AI response was blank or too short."); } } else { sendMessage("AI response format unexpected: " + JSON.stringify(r###lt)); } }) .catch(error => { sendMessage("AI request failed: " + error.message); }); } })();