MetaMod

Screensaver

  1. // ==UserScript==
  2. // @name MetaMod
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.96
  5. // @description Screensaver
  6. // @author MeKLiN
  7. // @match https://stumblechat.com/room/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=stumblechat.com
  9. // @grant none
  10. // @license MIT
  11.  
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16. let websocketUrl = null; // Initialize websocketUrl variable
  17. const handleUserMap = {}; // Initialize handleUserMap as an empty object
  18. // Define yourHandle variable
  19. const yourHandle = "myHandle"; // Replace "myHandle" with the actual handle
  20.  
  21. function parseWebSocketMessage(message) {
  22. const parsedMessage = JSON.parse(message);
  23. if (parsedMessage.stumble === "joined") {
  24. const userList = parsedMessage.userlist;
  25. if (userList && userList.length > 0) {
  26. userList.forEach(user => {
  27. const username = user.username || user.nick;
  28. handleUserMap[user.handle] = username;
  29. addUserToUserList({ handle: user.handle, username });
  30. });
  31. }
  32. const joinMessage = "A user or users joined the chat."; // Example join message
  33. displayWebSocketMessage(joinMessage);
  34. } else if (parsedMessage.stumble === "join") {
  35. const { handle, username } = parsedMessage;
  36. handleUserMap[handle] = username;
  37. addUserToUserList({ handle, username });
  38. const joinMessage = `${username} joined the chat.`;
  39. displayWebSocketMessage(joinMessage);
  40. } else if (parsedMessage.stumble === "quit") {
  41. const handle = parsedMessage.handle;
  42. const username = handleUserMap[handle];
  43. if (username) {
  44. delete handleUserMap[handle];
  45. removeUserFromUserList(handle);
  46. const quitMessage = `${username} left the chat.`;
  47. displayWebSocketMessage(quitMessage);
  48. }
  49. } else if (parsedMessage.stumble === "msg") {
  50. // Handle additional changes to the user list for specific "msg" messages
  51.  
  52. }
  53. }
  54.  
  55. // Function to send ban message to WebSocket listener using the URL from wss.txt
  56. function ban(handle) {
  57. // Fetch the WebSocket URL from the wss.txt file
  58. fetch('wss.txt')
  59. .then(response => {
  60. if (response.ok) {
  61. // Read the contents of wss.txt
  62. return response.text();
  63. }
  64. throw new Error('Failed to read WebSocket URL from wss.txt');
  65. })
  66. .then(webSocketUrl => {
  67. // Establish WebSocket connection using the URL from wss.txt
  68. const socket = new WebSocket(webSocketUrl);
  69. // Event listener for when the WebSocket connection is open
  70. socket.addEventListener('open', () => {
  71. // Send the ban message using the WebSocket connection
  72. socket.send(JSON.stringify({
  73. "stumble": "ban",
  74. "handle": handle
  75. }));
  76. });
  77. // Event listener for errors
  78. socket.addEventListener('error', error => {
  79. console.error('WebSocket connection error:', error);
  80. });
  81. })
  82. .catch(error => {
  83. console.error('Error reading WebSocket URL:', error);
  84. });
  85. }
  86.  
  87. // Function to set up WebSocket listener
  88. function setupWebSocketListener() {
  89. // Override WebSocket constructor to intercept WebSocket creation
  90. const originalWebSocket = window.WebSocket;
  91. window.WebSocket = function(url, protocols) {
  92. // Store the WebSocket URL when the connection is established
  93. websocketUrl = url;
  94. console.log('WebSocket URL:', websocketUrl);
  95.  
  96. // Save the WebSocket URL to a file
  97. saveWebSocketUrlToFile(websocketUrl);
  98.  
  99. // Call original WebSocket constructor
  100. const ws = new originalWebSocket(url, protocols);
  101.  
  102. // Event listener for receiving messages
  103. ws.addEventListener('message', event => {
  104. handleWebSocketMessage(event.data);
  105. });
  106.  
  107. return ws;
  108. };
  109. }
  110.  
  111. // Function to save WebSocket URL to a file
  112. function saveWebSocketUrlToFile(url) {
  113. // Check if the file already exists
  114. fetch('wss.txt')
  115. .then(response => {
  116. // If the file exists, do nothing
  117. if (response.ok) {
  118. console.log('File already exists. Skipping saving.');
  119. return;
  120. }
  121. // If the file does not exist, save it
  122. const blob = new Blob([url], { type: 'text/plain' });
  123. const anchor = document.createElement('a');
  124. anchor.download = 'wss.txt';
  125. anchor.href = window.URL.createObjectURL(blob);
  126. anchor.click();
  127. window.URL.revokeObjectURL(anchor.href);
  128. })
  129. .catch(error => {
  130. // Handle errors
  131. console.error('Error checking file existence:', error);
  132. });
  133. }
  134.  
  135. // WebSocket Listener: Override WebSocket constructor to intercept WebSocket creation
  136. const originalWebSocket = window.WebSocket;
  137. window.WebSocket = function(url, protocols) {
  138.  
  139. // Call original WebSocket constructor
  140. const ws = new originalWebSocket(url, protocols);
  141.  
  142. // Event listener for receiving messages
  143. ws.addEventListener('message', event => {
  144. const parsedMessage = JSON.parse(event.data);
  145. // Check if the message is a "joined" message
  146. if (parsedMessage.stumble === "joined") {
  147. // Extracting our own handle from the "self" object in the message
  148. const selfHandle = parsedMessage.self.handle;
  149. // Update handleUserMap and custom user list when a user joins
  150. const userList = parsedMessage.userlist;
  151. if (userList && userList.length > 0) {
  152. userList.forEach(user => {
  153. // Check if the user being added is ourselves
  154. const isSelf = user.handle === selfHandle;
  155. // If it's our own user, update handleUserMap and display our own handle in the user list
  156. if (isSelf) {
  157. // Update handleUserMap with our own handle and username
  158. handleUserMap[user.handle] = user.username || user.nick;
  159. // Add our own handle to the custom user list with purple icon
  160. addUserToUserList({
  161. username: user.username,
  162. handle: user.handle,
  163. active: true, // We just joined, so we're considered active
  164. icon: "🟣" // Purple icon for our own user entry
  165. }, "self");
  166. } else {
  167. // If it's not our own user, proceed as usual and add them to the user list
  168. updateUserListAndMapOnJoin(user);
  169. }
  170. });
  171. }
  172. } else if (parsedMessage.stumble === "join") {
  173. // Handle join messages
  174. const { handle, username } = parsedMessage;
  175. // Check if the user being added is not ourselves
  176. if (handle !== yourHandle) {
  177. handleUserMap[handle] = username;
  178. addUserToUserList({ handle, username }, "join");
  179. }
  180. } else if (parsedMessage.stumble === "quit") {
  181. // Handle quit messages
  182. const handle = parsedMessage.handle;
  183. const username = handleUserMap[handle];
  184. if (username) {
  185. delete handleUserMap[handle];
  186. removeUserFromUserList(handle);
  187. setTimeout(() => {
  188. removeUserFromUserList(handle);
  189. }, 30000); // 30 seconds delay
  190. addUserToUserList({ handle, username }, "quit");
  191. }
  192. } else if (parsedMessage.stumble === "msg") {
  193. // Handle message messages
  194. const { handle, text } = parsedMessage;
  195. const username = handleUserMap[handle] || handle;
  196. displayWebSocketMessage(event.data);
  197. }
  198.  
  199. // Check if the message is a system message
  200. if (parsedMessage.stumble === "system") {
  201. const systemMessage = parsedMessage.message;
  202.  
  203. // Check if the system message contains the client version
  204. if (systemMessage.startsWith('"Client Version:')) {
  205. // Save the user list to a file
  206. console.log("sysmsgdetected");
  207. }
  208. }
  209. });
  210.  
  211. return ws;
  212. };
  213.  
  214. // Function to create user list div
  215. function createUserListDiv() {
  216. const userListDiv = document.createElement("div");
  217. userListDiv.id = "userList";
  218. userListDiv.style.position = "absolute"; // Change to absolute positioning
  219. userListDiv.style.top = "100px"; // Adjust top position as needed
  220. userListDiv.style.left = "10px"; // Adjust left position as needed
  221. userListDiv.style.height = "calc(100% - 100px)"; // Adjust height to fill remaining space
  222. userListDiv.style.overflowY = "auto";
  223. userListDiv.style.color = "#ffffff";
  224. userListDiv.style.padding = "10px";
  225. userListDiv.style.zIndex = "2"; // Set a higher z-index value
  226. userListDiv.style.display = "none"; // Hide the custom user list by default
  227.  
  228. // Add CSS to change cursor to pointer on hover
  229. userListDiv.style.cursor = "pointer";
  230.  
  231. // Add hover effect to change background color
  232. userListDiv.addEventListener("mouseenter", () => {
  233. userListDiv.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
  234. });
  235.  
  236. userListDiv.addEventListener("mouseleave", () => {
  237. userListDiv.style.backgroundColor = "transparent";
  238. });
  239.  
  240. return userListDiv;
  241. }
  242.  
  243. // Function to add user to user list with appropriate icon based on user type
  244. function addUserToUserList(user, userType) {
  245. const userList = document.getElementById("userList");
  246. if (!userList) return;
  247.  
  248. const userItem = document.createElement("div");
  249. userItem.textContent = `${user.username}`;
  250.  
  251. // Define the default dot color and icon
  252. let dotColor = "red"; // Default dot color
  253. let icon = "🔴"; // Default icon for inactive users
  254.  
  255. // Set dot color and icon based on user type
  256. if (userType === "self") {
  257. dotColor = "purple"; // Purple for self user
  258. icon = "🟣"; // Purple circle icon
  259. } else if (userType === "join") {
  260. dotColor = "blue"; // Blue for join user
  261. icon = "🔵"; // Blue circle icon
  262. } else if (userType === "joined") { // "#join msg listener for game
  263. dotColor = "green"; // Green for joined user
  264. icon = "🟢"; // Green circle icon
  265. }
  266.  
  267. // Add colored dot based on user status
  268. const dot = document.createElement("span");
  269. dot.textContent = icon;
  270. dot.style.color = dotColor;
  271.  
  272. // Attach a click listener to the colored circle
  273. dot.addEventListener("click", () => {
  274. // Pass the handle to the ban function
  275. ban(user.handle);
  276. });
  277.  
  278. userItem.appendChild(dot);
  279.  
  280. // Add custom icon for the user
  281. if (user.icon) {
  282. const customIcon = document.createElement("span");
  283. customIcon.textContent = user.icon;
  284. customIcon.style.marginLeft = "5px"; // Adjust margin as needed
  285. userItem.appendChild(customIcon);
  286. }
  287.  
  288. userList.appendChild(userItem); // Append user item to the user list
  289. }
  290.  
  291. // If user is not active and not yourself, show popup for 5 seconds
  292. //if (!user.active && user.handle !== yourHandle) { //this activates on anyone joining or leaving
  293. //const popup = document.createElement("div"); /the yeopardy script has svg animates for it
  294. //popup.textContent = "WELCOME TO STUMBLECHAT YEOPARDY!";
  295. //popup.style.fontSize = "48px";
  296. //popup.style.position = "fixed";
  297. //popup.style.top = "50%";
  298. //popup.style.left = "50%";
  299. //popup.style.transform = "translate(-50%, -50%)";
  300. //popup.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
  301. //popup.style.color = "white";
  302. //popup.style.padding = "10px";
  303. //popup.style.borderRadius = "5px";
  304. //document.body.appendChild(popup);
  305.  
  306. // Call the function to create the user list div
  307. const userListDiv = createUserListDiv();
  308.  
  309. const chatContainer = document.getElementById("chat-container");
  310. if (chatContainer) {
  311. chatContainer.appendChild(userListDiv); // Append to chat container instead
  312. } else {
  313. document.body.appendChild(userListDiv);
  314. }
  315.  
  316. // Call the function to attach click listener to colored Unicode circles
  317. attachClickListenerToCircles();
  318.  
  319. // Call functions to set up overlay, WebSocket listener, and initial user list display
  320. setupWebSocketListener();
  321. updateUserListDisplay();
  322.  
  323. // Function to update handleUserMap with user data from the loaded file
  324. function updateHandleUserMap(fileContent) {
  325. // Split the file content into lines
  326. const lines = fileContent.split('\n');
  327.  
  328. // Iterate over each line to parse user data
  329. lines.forEach(line => {
  330. const userData = line.trim().split(' '); // Splitting by space to separate username and handle
  331. if (userData.length === 2) {
  332. const username = userData[0].trim();
  333. const handle = userData[1].trim();
  334.  
  335. // Check if the handle already exists in the handleUserMap
  336. if (!handleUserMap.hasOwnProperty(handle)) {
  337. // Update user map with the new username and handle
  338. handleUserMap[handle] = username;
  339. }
  340. }
  341. });
  342. }
  343.  
  344. // Function to attach click listener to colored Unicode circles
  345. function attachClickListenerToCircles() {
  346. // Get all elements with class 'colored-circle'
  347. const coloredCircles = document.querySelectorAll('.colored-circle');
  348.  
  349. // Loop through each colored circle element
  350. coloredCircles.forEach(circle => {
  351. // Attach click listener
  352. circle.addEventListener('click', function() {
  353. // Get the handle associated with the clicked circle
  354. const handle = this.getAttribute('data-handle');
  355. // Log the handle to the console
  356. console.log('Clicked handle:', handle);
  357. // Call the banUser function with the WebSocket URL and handle
  358. ban(handle);
  359. });
  360. });
  361. }
  362.  
  363. // Function to update the user list display
  364. function updateUserListDisplay() {
  365. // Get the user list element
  366. const userList = document.getElementById("userList");
  367. if (userList) {
  368. // Update the display with modified handleUserMap
  369. userList.innerHTML = ""; // Clear the user list
  370. for (const handle in handleUserMap) {
  371. const username = handleUserMap[handle];
  372. // Append the user to the user list with 'B' if present
  373. const listItem = document.createElement("li");
  374. listItem.textContent = `${username} (${handle})`;
  375. userList.appendChild(listItem);
  376. }
  377. }
  378. }
  379.  
  380. // Function to get the user's own handle number (implement your own logic)
  381. function getOwnHandle() {
  382. // Implement your logic to retrieve the user's own handle number
  383. // For demonstration purposes, return a hardcoded value
  384. return "123456"; // Replace with your actual handle number
  385. }
  386.  
  387. // WebSocket listener for handling messages
  388. function handleWebSocketMessage(message) {
  389. const parsedMessage = JSON.parse(message);
  390. const ownHandle = getOwnHandle(); // Function to get the user's own handle number
  391.  
  392. if (parsedMessage.stumble === "msg" && ownHandle === parsedMessage.handle) {
  393. const text = parsedMessage.text;
  394. if (text.startsWith("#ban")) {
  395. // Extract the handle from the message
  396. const handleToBan = text.replace("#ban", "").trim();
  397. if (handleToBan !== "") {
  398. // Check if the handle exists in the handleUserMap
  399. if (handleUserMap.hasOwnProperty(handleToBan)) {
  400. // Add 'B' next to the handle number
  401. handleUserMap[handleToBan] += " B";
  402. // Update the user list display
  403. updateUserListDisplay();
  404. // Update the users.txt file
  405. //saveUserListToFile();
  406. } else {
  407. alert("Handle not found!");
  408. }
  409. } else {
  410. alert("Invalid handle!");
  411. }
  412. }
  413. }
  414. }
  415.  
  416. // Function to display WebSocket messages and update user list
  417. function displayWebSocketMessage(message) {
  418. const parsedMessage = JSON.parse(message);
  419. if (parsedMessage.stumble === "join") {
  420. // Handle join messages: Extract handle and username from the message
  421. const { handle, username } = parsedMessage;
  422. // Map handle to username in handleUserMap
  423. handleUserMap[handle] = username;
  424. // Add the user to the custom user list with the appropriate icon (join user)
  425. addUserToUserList({ handle, username }, "join");
  426. } else if (parsedMessage.stumble === "msg") {
  427. // Handle message messages: Extract handle and text from the message
  428. const { handle, text } = parsedMessage;
  429. // Retrieve username from handleUserMap or use handle if not found
  430. const username = handleUserMap[handle] || handle;
  431. // Display the message in the WebSocket messages div
  432. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  433. if (webSocketMessagesDiv) {
  434. // Append the message with a newline character
  435. webSocketMessagesDiv.textContent += `${username}: ${text}\n`;
  436. // Scroll to the bottom of the messages div
  437. webSocketMessagesDiv.scrollTop = webSocketMessagesDiv.scrollHeight;
  438. }
  439.  
  440. // Additional logic for handling commands
  441. if (text === "#join") {
  442. console.log("join");
  443. // Add your logic here
  444. } else if (text === "#icon") {
  445. console.log("icon");
  446. // Add your logic here
  447. } else if (text === "#tokes") {
  448. console.log("tokes");
  449. // Call your tokes function here
  450. //TokesSendEnter();
  451. } else if (text.startsWith("#ai ")) {
  452. console.log("ai");
  453. // Extract the word after "#ai"
  454. const word = text.substring(4);
  455. console.log("Word after '#ai':", word);
  456. // Call your AI function here with the extracted word
  457. //DoAi(word); // Adjust parameters as needed
  458. }
  459. } else if (parsedMessage.stumble === "joined") {
  460. // Handle joined messages: Add users to handleUserMap and custom user list
  461. const userList = parsedMessage.userlist;
  462. if (userList && userList.length > 0) {
  463. userList.forEach(user => {
  464. // Extract username from either "username" or "nick"
  465. const username = user.username || user.nick;
  466. // Map handle to username in handleUserMap
  467. handleUserMap[user.handle] = username;
  468. // Add the user to the custom user list with the appropriate icon
  469. addUserToUserList({ handle: user.handle, username }, "joined");
  470. });
  471. }
  472. } else if (parsedMessage.stumble === "quit") {
  473. // Handle quit messages: Remove users from handleUserMap and custom user list
  474. const handle = parsedMessage.handle;
  475. const username = handleUserMap[handle];
  476. if (username) {
  477. // Remove the handle from handleUserMap
  478. delete handleUserMap[handle];
  479. // Remove the user from the custom user list
  480. removeUserFromUserList(handle);
  481. }
  482. }
  483. }
  484.  
  485. // Function to update handleUserMap and add users to custom user list
  486. function updateUserListAndMapOnJoin(user) {
  487. // Update handleUserMap with the new user
  488. handleUserMap[user.handle] = user.username || user.nick; // Derive username from handle or nick
  489. // Add the new user to the custom user list
  490. addUserToUserList(user);
  491. }
  492.  
  493. // Call the function to update the user list
  494. function updateUserListOnMessage(userList) {
  495. return function(message) {
  496. const parsedMessage = JSON.parse(message);
  497. if (parsedMessage.stumble === "join" || parsedMessage.stumble === "msg" || parsedMessage.stumble === "joined") {
  498. // Add user to user list
  499. addUserToUserList(parsedMessage);
  500. }
  501. };
  502. }
  503.  
  504. // Function to create WebSocket messages div
  505. function createWebSocketMessagesDiv() {
  506. const div = document.createElement("div");
  507. div.id = "webSocketMessages";
  508. div.style.position = "relative";
  509. div.style.height = "25%";
  510. div.style.paddingLeft = "2px";
  511. div.style.visibility = "visible"; // Ensure the div is visible
  512. div.style.willChange = "transform";
  513. div.style.boxSizing = "border-box";
  514. div.style.overflowX = "hidden";
  515. div.style.overflowY = "auto";
  516. div.style.color = "#ffffff"; // Set font color to white
  517. div.style.padding = "10px"; // Example padding
  518. div.style.zIndex = "2"; // Set a higher z-index value for the WebSocket messages div
  519.  
  520. // Additional styles for specific scenarios
  521. div.style.display = "flex";
  522. div.style.flexDirection = "column";
  523. div.style.justifyContent = "flex-end";
  524. div.style.fontSize = "18px";
  525.  
  526. div.style.whiteSpace = "pre-wrap"; // Allow text to wrap within the container
  527. div.style.wordWrap = "break-word"; // Allow long words to break and wrap
  528.  
  529. // Locate the chat-position div
  530. const chatPositionDiv = document.getElementById("chat-position");
  531. if (chatPositionDiv) {
  532. // Append custom div to the chat-position div
  533. chatPositionDiv.appendChild(div);
  534. } else {
  535. // If chat-position div not found, append to document body as fallback
  536. document.body.appendChild(div);
  537. }
  538. }
  539.  
  540. // Call the function to create the WebSocket messages div
  541. createWebSocketMessagesDiv();
  542.  
  543. // Function to remove user from custom user list
  544. function removeUserFromUserList(handle) {
  545. const userList = document.getElementById("userList");
  546. if (userList) {
  547. const userElements = userList.querySelectorAll("div");
  548. userElements.forEach(userElement => {
  549. if (userElement.textContent.includes(`(${handle})`)) {
  550. userElement.remove();
  551. }
  552. });
  553. }
  554. }
  555.  
  556. // Function to toggle visibility of custom user list
  557. function toggleCustomUserList() {
  558. const userListDiv = document.getElementById("userList");
  559. if (userListDiv) {
  560. userListDiv.style.display = userListDiv.style.display === "none" ? "block" : "none";
  561. }
  562. }
  563.  
  564. // Add a button to toggle visibility of custom user list
  565. const usersButton = document.createElement("button");
  566. usersButton.textContent = "U";
  567. usersButton.style.position = "fixed";
  568. usersButton.style.top = "10px";
  569. usersButton.style.left = "10px";
  570. usersButton.addEventListener("click", toggleCustomUserList);
  571. document.body.appendChild(usersButton);
  572.  
  573.  
  574.  
  575. /* Additional compacting styles */
  576. /*@-moz-document url-prefix("https://stumblechat.com/room/") {*/
  577. // Compact message styles
  578. const compactStyles = `
  579. .message .nickname ~ .content {
  580. display: inline-block;
  581. top: -7px;
  582. position: relative;
  583. margin-left: 2px;
  584. margin-right: 1em;
  585. }
  586. .content + .content {
  587. display: inline-block!important;
  588. margin-right: 1em;
  589. }
  590. .message .nickname ~ .content span {
  591. line-height: 1.5em;
  592. }
  593. `;
  594.  
  595. // Apply compact styles to the document
  596. const style = document.createElement('style');
  597. style.textContent = compactStyles;
  598. document.head.appendChild(style);
  599. /*}*/
  600.  
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609. // Define a function to display surreal visuals within a toggleable overlay
  610. function createSurrealVisuals() {
  611. // Select the HTML element to display visuals
  612. const visualsContainer = document.createElement('div');
  613. visualsContainer.id = 'surreal-visuals-overlay';
  614. visualsContainer.style.position = 'fixed';
  615. visualsContainer.style.top = '0';
  616. visualsContainer.style.left = '0';
  617. visualsContainer.style.width = '100%';
  618. visualsContainer.style.height = '100%';
  619. visualsContainer.style.zIndex = '999'; // Set a high z-index
  620. visualsContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  621. visualsContainer.style.display = 'none'; // Initially hide the overlay
  622.  
  623. // Array of shapes and colors for surreal visuals
  624. const shapes = ['circle', 'square', 'triangle'];
  625. const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff'];
  626.  
  627. // Function to create surreal visuals
  628. function createVisuals() {
  629. // Clear existing visuals
  630. visualsContainer.innerHTML = '';
  631.  
  632. // Create new visuals
  633. for (let i = 0; i < 10; i++) {
  634. const shape = shapes[Math.floor(Math.random() * shapes.length)];
  635. const color = colors[Math.floor(Math.random() * colors.length)];
  636.  
  637. const visual = document.createElement('div');
  638. visual.classList.add('surreal-visual');
  639. visual.style.width = '50px';
  640. visual.style.height = '50px';
  641. visual.style.backgroundColor = color;
  642. visual.style.position = 'absolute';
  643. visual.style.top = Math.random() * window.innerHeight + 'px';
  644. visual.style.left = Math.random() * window.innerWidth + 'px';
  645.  
  646. visualsContainer.appendChild(visual);
  647. }
  648. }
  649.  
  650. // Call the function to create surreal visuals initially
  651. createVisuals();
  652.  
  653. // Set interval to update visuals periodically
  654. const intervalId = setInterval(createVisuals, 5000); // Update every 5 seconds
  655.  
  656. // Append the visuals container to the document body
  657. document.body.appendChild(visualsContainer);
  658.  
  659. // Function to clear the interval when the overlay is closed
  660. visualsContainer.addEventListener('transitionend', function(event) {
  661. if (event.propertyName === 'display' && visualsContainer.style.display === 'none') {
  662. clearInterval(intervalId); // Stop updating visuals when overlay is closed
  663. }
  664. });
  665. }
  666.  
  667.  
  668. // Define a function to display cryptic messages within a toggleable overlay
  669. function displayCrypticMessages() {
  670. // Select the HTML element to display messages
  671. const overlayContainer = document.createElement('div');
  672. overlayContainer.id = 'cryptic-messages-overlay';
  673. overlayContainer.style.position = 'fixed';
  674. overlayContainer.style.top = '20%';
  675. overlayContainer.style.left = '50%';
  676. overlayContainer.style.width = '90%';
  677. overlayContainer.style.transform = 'translate(-50%, -50%)';
  678. overlayContainer.style.height = '100%';
  679. overlayContainer.style.zIndex = '1000';
  680. overlayContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  681. overlayContainer.style.display = 'none'; // Initially hide the overlay
  682.  
  683. // Array of cryptic messages
  684. const messages = [
  685. '“It’s better to face madness with a plan than to sit still and let it take you in pieces.” ― Josh Malerman, "Bird Box"',
  686. '“What an excellent day for an exorcism.” — Demon, “The Exorcist”',
  687. '“Vampires, werewolves, fallen angels and fairies lurk in the shadows, their intentions far from honorable.” — Jeaniene Frost',
  688. '“If you gaze long enough into an abyss, the abyss will gaze back into you.” — Friedrich Nietzsche',
  689. '“Beware the dark pool at the bottom of our hearts. In its icy, black depths dwell strange and twisted creatures it is best not to disturb.” — Sue Grafton, “I is for Innocent”',
  690. '“Am I walking away from something I should be running away from?” — Shirley Jackson, “The Haunting of Hill House”',
  691. '“Sometimes dead is better.” — Stephen King, “Pet Sematary”',
  692. '“I was a newborn vampire, weeping at the beauty of the night.” — Anne Rice, “Interview with the Vampire”',
  693. '“All that we see or seem is but a dream within a dream.” — Edgar Allan Poe',
  694. '“Unfathomable to mere mortals is the lore of fiends.” — Nathaniel Hawthorne, “Young Goodman Brown”',
  695. '“Love will have its sacrifices. No sacrifice without blood.” — J. Sheridan Le Fanu, “Carmilla”',
  696. '“Everybody is a book of blood; wherever we’re opened, we’re red.” — Clive Barker, “Books of Blood”',
  697. '“Where there is no imagination, there is no horror.” — Arthur Conan Doyle',
  698. '“Would you like to see a magic trick?” — The Grabber, “The Black Phone”',
  699. '“Horror is like a serpent; always shedding its skin, always changing. And it will always come back.” — Dario Argento',
  700. '“There is something at work in my soul which I do not understand.” — Mary Shelley, “Frankenstein”',
  701. '“I’m scared to close my eyes, I’m scared to open them. We’re gonna die out here.” — Heather Donahue, “The Blair Witch Project”',
  702. '“Is there someone inside you?” — Psychiatrist, “The Exorcist”',
  703. '“I know of witches who whistle at different pitches, calling things that don’t have names.” — Helen Oyeyemi, “White is for Witching”',
  704. '“This is all it takes for people to plunge into insanity: one night alone with themselves and what they fear the most.” — Thomas Olde Heuvelt, “Hex”',
  705. '“They’re here.” — Carol Anne, “Poltergeist”',
  706. '“Come, dear. It’ll be easier for you than it was for Jason.” — Mrs. Voorhees, “Friday the 13th”',
  707. '“I knew nothing but shadows and I thought them to be real.” -Oscar Wilde, “The Picture of Dorian Gray”',
  708. '“Let’s talk, you and I. Let’s talk about fear.” — Stephen King, “Night Shift”',
  709. '“Dementors are vicious creatures. They will not distinguish between the one they hunt and the one who gets in their way.” — Albus Dumbledore, “Harry Potter and the Prisoner of Azkaban”',
  710. '“Evil thenceforth became my good.” — Mary Shelley, “Frankenstein”',
  711. '“Evil has only the power that we give it.” — Ray Bradbury, “Something Wicked This Way Comes”',
  712. '“When shall we meet again? In thunder, lightening, or in rain?” — William Shakespeare, “Macbeth”',
  713. '“I’m not gonna hurt ya. You didn’t let me finish my sentence. I said, ‘I’m not gonna hurt ya. I’m just going to bash your brains in!’” — Jack Torrance, “The Shining”',
  714. '“I shall never forget the afternoon when first I stumbled upon the half-hidden house of the dead.” — H.P. Lovecraft, “The Tomb”',
  715. '“Once upon a time, there was a girl and the girl had a shadow.” — Red, “Us”',
  716. '“I don’t know who he is, but he’s burned, and he wears a weird hat and a red and green sweater, really dirty. And he uses these knives, like giant fingernails.” — Nancy Thompson, “A Nightmare on Elm Street”',
  717. '“In this town, Michael Myers is a myth. He’s the Boogeyman. A ghost story to scare kids. But this Boogeyman is real. An evil like his never stops, it just grows older. Darker.” — Laurie Strode, “Halloween (2018)”',
  718. '“Out for a little walk … in the moonlight, are we?” — Severus Snape, “Harry Potter and the Prisoner of Azkaban”',
  719. '“People who cease to believe in God or goodness altogether still believe in the devil. I don’t know why. No, I do indeed know why. Evil is always possible.” — Anne Rice, “Interview with the Vampire”',
  720. '“They look exactly like us. They think like us. They know where we are. We need to move and keep moving. They won’t stop until they kill us ... or we kill them.” — Adelaide Wilson, “Us”',
  721. '“A deep sleep fell upon me — a sleep like that of death.” — Edgar Allan Poe, “The Pit and the Pendulum”',
  722. '“Every fairytale had a bloody lining. Every one had teeth and claws.” — Alice Hoffman, “The Ice Queen”',
  723. '“There’s a monster outside my room, can I have a glass of water?” — Bo Hess, “Signs”',
  724. '“Someone once told her that the stars were merely sewing pins, holding the black sky up so that it did not come down on the world and suffocate it.” — Alma Katsu, “The Deep”',
  725. '“ He’s not like us. He smiles a lot. But I think there might be worms inside him, making him smile.” — Stephen King, “The Stand”',
  726. '“I would die for her. I would kill for her. Either way, what bliss.” — Gomez, “The Addams Family”',
  727. '“It is only when a man feels himself face to face with such horrors that he can understand their true import.” — Bram Stoker, “Dracula”',
  728. '“One, two, Freddy’s coming for you. Three, four, better lock your door.” — Children, “A Nightmare on Elm Street”',
  729. '“A census taker once tried to test me. I ate his liver with some fava beans and a nice Chianti.” — Hannibal Lecter, “The Silence of the Lambs”',
  730. '“But the most frightening thing of all was the wind howling among the trees. Ichabod was sure that it was the sound of the Headless Horseman out looking for his head.” — Washington Irving, “The Legend of Sleepy Hollow',
  731. '“Its probably wrong to believe there can be any limit to the horror which the human mind can experience ...and the most terrifying question of all may be just how much horror the human mind can stand and still maintain a wakeful, staring, unrelenting sanity.” — Stephen King, “Pet Sematary”',
  732. '“Now, sink into the floor.” — Missy Armitage, “Get Out”',
  733. '“I am the writing on the walls. I am the sweet smell of blood on the street. The buzz that echoes in the alleyways.” — Anthony McCoy, “Candyman (2021)”',
  734. '“When the music stops, you’ll see him in the mirror standing behind you.” — April, “The Conjuring”',
  735. '“It was a death cry, rising until it seemed it could go no higher, then dwindling into a mournful, hopeless, ghastly farewell.” — Louise Morgan, “A Secret History of Witches”',
  736. '“A witch never gets caught. Don’t forget that she has magic in her fingers and devilry dancing in her blood.” — Roald Dahl, “The Witches”',
  737. '“Hate the smell of dampness, don’t you? It’s such a, I don’t know, creepy smell.” — Norman Bates, “Psycho”',
  738. '“I see dead people.” — Cole Sear, “The Sixth Sense”',
  739. '“I looked upon the sea; it was to be my grave.” — Mary Shelley, “Frankenstein”',
  740. '“Where are you, beautiful? Come out, come out, wherever you are!” — Frank, “Hellraiser”',
  741. '“Be warned: I sleep as the earth sleeps beneath the night sky or the winter’s snow; and once awakened, I am servant to no man.” — Anne Rice, “The Mummy”',
  742. '“You ever feel prickly things on the back of your neck?”— Cole Sear, “The Sixth Sense”',
  743. '“Something bumped into me — something soft and plump. It must have been the rats; the vicious, gelatinous, ravenous army that feast on the dead and the living.” — H.P. Lovecraft, “The Rats in the Walls”',
  744. '“Hell is empty and all the devils are here.” — William Shakespeare, “The Tempest”',
  745. '“Souls and memories can do strange things during trance.” — Bram Stoker, “Dracula”',
  746. '“The Further is a world far beyond our own, yet it’s all around us. A place without time as we know it. It’s a dark realm filled with the tortured souls of the dead. A place not meant for the living.” — Elise Reiner, “Insidious”',
  747. '“He knew what the wind was doing to them, where it was taking them, to all the secret places that were never so secret again in life.” — Ray Bradbury, “Something Wicked This Way Comes”',
  748. '“A black cat crossed my path, and I stopped to dance around it widdershins and to sing the rhyme, Ou va-ti mistigri? Passe sans faire de mai ici.” — Joanne Harris, “Chocolat”',
  749. 'Embrace the chaos within...',
  750. 'Seek truth in the depths of darkness...',
  751. 'Transcend reality and enter the void...'
  752. ];
  753.  
  754. // Create a message element
  755. const messageElement = document.createElement('div');
  756. messageElement.style.color = '#ffffff'; // Set font color to white
  757. messageElement.style.fontSize = '44px'; // Set font size as needed
  758. messageElement.style.textAlign = 'center'; // Center-align the message
  759. messageElement.style.marginTop = '20%'; // Adjust margin top to center vertically
  760.  
  761. // Append the message to the overlay container
  762. overlayContainer.appendChild(messageElement);
  763.  
  764. // Function to update the message content
  765. function updateMessage() {
  766. const randomIndex = Math.floor(Math.random() * messages.length);
  767. const message = messages[randomIndex];
  768. messageElement.textContent = message;
  769. }
  770.  
  771. // Call the function to update the message content initially
  772. updateMessage();
  773.  
  774. // Set interval to update message content periodically
  775. const intervalId = setInterval(updateMessage, 10000); // Update every 5 seconds
  776.  
  777. // Append the overlay container to the document body
  778. document.body.appendChild(overlayContainer);
  779.  
  780. // Function to clear the interval when the overlay is closed
  781. overlayContainer.addEventListener('transitionend', function(event) {
  782. if (event.propertyName === 'display' && overlayContainer.style.display === 'none') {
  783. clearInterval(intervalId); // Stop updating messages when overlay is closed
  784. }
  785. });
  786. }
  787.  
  788. // Function to toggle both overlays on or off
  789. function toggleOverlays() {
  790. const visualsOverlay = document.getElementById('surreal-visuals-overlay');
  791. const messagesOverlay = document.getElementById('cryptic-messages-overlay');
  792.  
  793. if (visualsOverlay.style.display === 'none') {
  794. visualsOverlay.style.display = 'block';
  795. messagesOverlay.style.display = 'block';
  796. } else {
  797. visualsOverlay.style.display = 'none';
  798. messagesOverlay.style.display = 'none';
  799. }
  800. }
  801.  
  802. // Call functions to create surreal visuals and display cryptic messages
  803. createSurrealVisuals();
  804. displayCrypticMessages();
  805.  
  806. // Create a button to toggle both overlays on or off
  807. const toggleButton = document.createElement('button');
  808. toggleButton.textContent = 'O';
  809. toggleButton.style.position = 'fixed';
  810. toggleButton.style.top = '10px';
  811. toggleButton.style.left = '20px';
  812. toggleButton.style.zIndex = '1001';
  813.  
  814. // Add event listener to toggle the overlays visibility
  815. toggleButton.addEventListener('click', toggleOverlays);
  816.  
  817. // Append the toggle button to the document body
  818. document.body.appendChild(toggleButton);
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853. })();