Advertisement
MeKLiN2

hunter original good

Mar 22nd, 2024
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 57.71 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Hunter
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.94
  5. // @description Blacklist
  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. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15. const handleUserMap = {}; // Initialize handleUserMap as an empty object
  16. // Define yourHandle variable
  17. const yourHandle = "myHandle"; // Replace "myHandle" with the actual handle
  18.  
  19. function parseWebSocketMessage(message) {
  20. const parsedMessage = JSON.parse(message);
  21. if (parsedMessage.stumble === "joined") {
  22. const userList = parsedMessage.userlist;
  23. if (userList && userList.length > 0) {
  24. userList.forEach(user => {
  25. const username = user.username || user.nick;
  26. handleUserMap[user.handle] = username;
  27. addUserToUserList({ handle: user.handle, username });
  28. });
  29. }
  30. const joinMessage = "A user or users joined the chat."; // Example join message
  31. displayWebSocketMessage(joinMessage);
  32. } else if (parsedMessage.stumble === "join") {
  33. const { handle, username } = parsedMessage;
  34. handleUserMap[handle] = username;
  35. addUserToUserList({ handle, username });
  36. const joinMessage = `${username} joined the chat.`;
  37. displayWebSocketMessage(joinMessage);
  38. } else if (parsedMessage.stumble === "quit") {
  39. const handle = parsedMessage.handle;
  40. const username = handleUserMap[handle];
  41. if (username) {
  42. delete handleUserMap[handle];
  43. removeUserFromUserList(handle);
  44. const quitMessage = `${username} left the chat.`;
  45. displayWebSocketMessage(quitMessage);
  46. }
  47. } else if (parsedMessage.stumble === "msg") {
  48. // Handle additional changes to the user list for specific "msg" messages
  49.  
  50. }
  51. }
  52.  
  53. // WebSocket Listener: Override WebSocket constructor to intercept WebSocket creation
  54. const originalWebSocket = window.WebSocket;
  55. window.WebSocket = function(url, protocols) {
  56. console.log('WebSocket URL:', url);
  57.  
  58. // Call original WebSocket constructor
  59. const ws = new originalWebSocket(url, protocols);
  60.  
  61. // Event listener for receiving messages
  62. ws.addEventListener('message', event => {
  63. const parsedMessage = JSON.parse(event.data);
  64. // Check if the message is a "joined" message
  65. if (parsedMessage.stumble === "joined") {
  66. // Extracting our own handle from the "self" object in the message
  67. const selfHandle = parsedMessage.self.handle;
  68. // Update handleUserMap and custom user list when a user joins
  69. const userList = parsedMessage.userlist;
  70. if (userList && userList.length > 0) {
  71. userList.forEach(user => {
  72. // Check if the user being added is ourselves
  73. const isSelf = user.handle === selfHandle;
  74. // If it's our own user, update handleUserMap and display our own handle in the user list
  75. if (isSelf) {
  76. // Update handleUserMap with our own handle and username
  77. handleUserMap[user.handle] = user.username || user.nick;
  78. // Add our own handle to the custom user list with purple icon
  79. addUserToUserList({
  80. username: user.username,
  81. handle: user.handle,
  82. active: true, // We just joined, so we're considered active
  83. icon: "🟣" // Purple icon for our own user entry
  84. }, "self");
  85. } else {
  86. // If it's not our own user, proceed as usual and add them to the user list
  87. updateUserListAndMapOnJoin(user);
  88. }
  89. });
  90. }
  91. } else if (parsedMessage.stumble === "join") {
  92. // Handle join messages
  93. const { handle, username } = parsedMessage;
  94. // Check if the user being added is not ourselves
  95. if (handle !== yourHandle) {
  96. handleUserMap[handle] = username;
  97. addUserToUserList({ handle, username }, "join");
  98. }
  99. } else if (parsedMessage.stumble === "quit") {
  100. // Handle quit messages
  101. const handle = parsedMessage.handle;
  102. const username = handleUserMap[handle];
  103. if (username) {
  104. delete handleUserMap[handle];
  105. removeUserFromUserList(handle);
  106. setTimeout(() => {
  107. removeUserFromUserList(handle);
  108. }, 30000); // 30 seconds delay
  109. addUserToUserList({ handle, username }, "quit");
  110. }
  111. } else if (parsedMessage.stumble === "msg") {
  112. // Handle message messages
  113. const { handle, text } = parsedMessage;
  114. const username = handleUserMap[handle] || handle;
  115. displayWebSocketMessage(event.data);
  116. }
  117.  
  118. // Check if the message is a system message
  119. if (parsedMessage.stumble === "system") {
  120. const systemMessage = parsedMessage.message;
  121.  
  122. // Check if the system message contains the client version
  123. if (systemMessage.startsWith('"Client Version:')) {
  124. // Save the user list to a file
  125. console.log("sysmsgdetected");
  126. }
  127. }
  128. });
  129.  
  130. return ws;
  131. };
  132.  
  133. // Function to create user list div
  134. function createUserListDiv() {
  135. const userListDiv = document.createElement("div");
  136. userListDiv.id = "userList";
  137. userListDiv.style.position = "absolute"; // Change to absolute positioning
  138. userListDiv.style.top = "100px"; // Adjust top position as needed
  139. userListDiv.style.left = "10px"; // Adjust left position as needed
  140. userListDiv.style.height = "calc(100% - 100px)"; // Adjust height to fill remaining space
  141. userListDiv.style.overflowY = "auto";
  142. userListDiv.style.color = "#ffffff";
  143. userListDiv.style.padding = "10px";
  144. userListDiv.style.zIndex = "2"; // Set a higher z-index value
  145. userListDiv.style.display = "none"; // Hide the custom user list by default
  146. return userListDiv;
  147. }
  148.  
  149. // Function to append new content to users.txt file
  150. function appendToUserListFile(newContent) {
  151. // Create a Blob object containing the new content
  152. const blob = new Blob([newContent], { type: "text/plain" });
  153.  
  154. // Create a temporary anchor element to trigger the download
  155. const a = document.createElement("a");
  156. const url = URL.createObjectURL(blob);
  157. a.href = url;
  158. a.download = "users.txt";
  159.  
  160. // Simulate a click on the anchor element to start the download
  161. document.body.appendChild(a);
  162. a.click();
  163.  
  164. // Remove the temporary anchor element
  165. document.body.removeChild(a);
  166.  
  167. // Release the Object URL
  168. URL.revokeObjectURL(url);
  169. }
  170.  
  171. // Function to save user list to users.txt file
  172. function saveUserListToFile() {
  173. // Extracting user information from handleUserMap
  174. const users = [];
  175. for (const handle in handleUserMap) {
  176. const username = handleUserMap[handle];
  177. users.push(`${username} (${handle}) B`); // Append 'B' to the handle
  178. }
  179.  
  180. // Convert the user list to a string
  181. const userListString = users.join("\n");
  182.  
  183. // Append the new content to the existing users.txt file
  184. appendToUserListFile(userListString);
  185. }
  186.  
  187. // Function to display the user list (handle map)
  188. function displayUserList() {
  189. const userList = document.getElementById("userListDisplay");
  190. if (userList) {
  191. // Clear the user list before updating
  192. userList.innerHTML = "";
  193. // Iterate over the handleUserMap and display each handle and username
  194. for (const handle in handleUserMap) {
  195. const username = handleUserMap[handle];
  196. const listItem = document.createElement("li");
  197. listItem.textContent = `${username} (${handle})`;
  198. userList.appendChild(listItem);
  199. }
  200. }
  201. }
  202.  
  203. // Function to create and append the pop-up window overlay with input menu and close button
  204. function createUserOverlay() {
  205. const overlay = document.createElement("div");
  206. overlay.id = "overlay";
  207. overlay.style.position = "fixed";
  208. overlay.style.top = "50%";
  209. overlay.style.width = "80%"; // container width
  210. overlay.style.left = "50%";
  211. overlay.style.transform = "translate(-50%, -50%)";
  212. overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
  213. overlay.style.zIndex = "9999";
  214. overlay.style.padding = "20px";
  215. overlay.style.textAlign = "center";
  216.  
  217. const closeButton = document.createElement("button");
  218. closeButton.textContent = "Close";
  219. closeButton.style.position = "absolute";
  220. closeButton.style.top = "10px";
  221. closeButton.style.right = "10px";
  222. closeButton.addEventListener("click", () => {
  223. overlay.remove(); // Remove the overlay when the close button is clicked
  224. });
  225. overlay.appendChild(closeButton);
  226.  
  227. const userListContainer = document.createElement("div");
  228. userListContainer.style.display = "flex";
  229. userListContainer.style.justifyContent = "space-between"; // Align columns to left and right edges
  230. overlay.appendChild(userListContainer);
  231.  
  232. const userListHandleMap = document.createElement("ul");
  233. userListHandleMap.id = "userListHandleMap";
  234. userListHandleMap.style.listStyleType = "none";
  235. userListHandleMap.style.padding = "0";
  236. userListHandleMap.style.width = "50%"; // Adjust the percentage based on your layout needs
  237. userListHandleMap.style.color = "lime";
  238. userListHandleMap.style.backgroundColor = "black";
  239. userListContainer.appendChild(userListHandleMap);
  240.  
  241. // Second column for data from loadUsersFromFile() function
  242. const userListLoadedFromFile = document.createElement("ul");
  243. userListLoadedFromFile.id = "userListLoadedFromFile"; // Add an id to reference the user list later
  244. userListLoadedFromFile.style.listStyleType = "none";
  245. userListLoadedFromFile.style.padding = "0";
  246. userListLoadedFromFile.style.color = "cyan"; // Set font color to cyan
  247. userListLoadedFromFile.style.backgroundColor = "black"; // Set background color to black
  248. userListLoadedFromFile.style.flex = "1"; // Use flex to make the column expand to fill available space
  249. userListLoadedFromFile.style.marginLeft = "10px"; // Add margin to separate from the first column
  250. userListContainer.appendChild(userListLoadedFromFile);
  251.  
  252. function populateUserListHandleMap() {
  253. userListHandleMap.innerHTML = "";
  254. for (const handle in handleUserMap) {
  255. if (handleUserMap.hasOwnProperty(handle)) {
  256. const listItem = document.createElement("li");
  257. listItem.textContent = `${handleUserMap[handle]} (${handle})`;
  258. listItem.style.marginBottom = "5px";
  259. userListHandleMap.appendChild(listItem);
  260. }
  261. }
  262. }
  263.  
  264. function populateUserListLoadedFromFile(loadedUsers) {
  265. userListLoadedFromFile.innerHTML = "";
  266. loadedUsers.forEach(user => {
  267. const listItem = document.createElement("li");
  268. listItem.textContent = `${user.username} (${user.handle})`;
  269. listItem.style.marginBottom = "5px";
  270. userListLoadedFromFile.appendChild(listItem);
  271. });
  272. }
  273.  
  274. populateUserListHandleMap();
  275.  
  276. const inputLabel = document.createElement("label");
  277. inputLabel.textContent = "Add 'B' to user handles:";
  278. inputLabel.style.color = "#ffffff";
  279. inputLabel.style.marginTop = "20px";
  280. overlay.appendChild(inputLabel);
  281.  
  282. const inputField = document.createElement("input");
  283. inputField.id = "handleInput";
  284. inputField.type = "text";
  285. inputField.style.margin = "10px auto";
  286. inputField.style.display = "block";
  287. overlay.appendChild(inputField);
  288.  
  289. const applyButton = document.createElement("button");
  290. applyButton.textContent = "Apply";
  291. applyButton.style.margin = "10px auto";
  292. applyButton.style.display = "block";
  293. overlay.appendChild(applyButton);
  294.  
  295. document.body.appendChild(overlay);
  296. }
  297.  
  298.  
  299.  
  300. // Function to create and append the input box overlay with user list display
  301. function createTartOverlay() {
  302. const overlay = document.createElement("div");
  303. overlay.id = "overlay";
  304. overlay.style.position = "fixed";
  305. overlay.style.bottom = "50px";
  306. overlay.style.left = "0px";
  307. overlay.style.zIndex = "9999";
  308. overlay.style.display = "flex";
  309. overlay.style.flexDirection = "column";
  310. overlay.style.alignItems = "flex-start";
  311.  
  312. const userList = document.createElement("ul");
  313. userList.id = "userList";
  314. userList.style.listStyleType = "none";
  315. overlay.appendChild(userList);
  316.  
  317. const inputField = document.createElement("input");
  318. inputField.id = "commandInput";
  319. inputField.type = "text";
  320. inputField.placeholder = "Type command here...";
  321. inputField.style.margin = "10px";
  322. inputField.style.width = "200px"; // Adjust width as needed
  323. overlay.appendChild(inputField);
  324.  
  325. // Listen for input changes
  326. inputField.addEventListener("input", () => {
  327. const command = inputField.value.trim();
  328. if (command.startsWith("#ban")) {
  329. const handle = command.replace("#ban", "").trim();
  330. if (handle !== "") {
  331. addBToHandleOrUsername(handle);
  332. inputField.value = ""; // Clear input field after processing command
  333. }
  334. }
  335. // Add more command listeners here as needed
  336. });
  337.  
  338. document.body.appendChild(overlay);
  339. }
  340.  
  341. // Function to create buttons for other overlays
  342. function createButtonsForOverlays() {
  343. // Create button for Tart overlay
  344. const tartButton = document.createElement("button");
  345. tartButton.textContent = "Open Tart Overlay";
  346. tartButton.style.position = "fixed";
  347. tartButton.style.bottom = "50px";
  348. tartButton.style.left = "210px"; // Adjust position as needed
  349. tartButton.style.zIndex = "9999";
  350. tartButton.addEventListener("click", createTartOverlay);
  351. document.body.appendChild(tartButton);
  352.  
  353. // Create button for User overlay
  354. const userButton = document.createElement("button");
  355. userButton.textContent = "Open User Overlay";
  356. userButton.style.position = "fixed";
  357. userButton.style.bottom = "50px";
  358. userButton.style.left = "420px"; // Adjust position as needed
  359. userButton.style.zIndex = "9999";
  360. userButton.addEventListener("click", createUserOverlay);
  361. document.body.appendChild(userButton);
  362. }
  363.  
  364. // Call the function to create buttons for other overlays
  365. createButtonsForOverlays();
  366.  
  367. // Function to create and append the input box overlay
  368. function createBox() {
  369. const overlay = document.createElement("div");
  370. overlay.id = "overlay";
  371. overlay.style.position = "fixed";
  372. overlay.style.bottom = "50px";
  373. overlay.style.left = "0px";
  374. overlay.style.zIndex = "9999";
  375.  
  376. const inputField = document.createElement("input");
  377. inputField.id = "commandInput";
  378. inputField.type = "text";
  379. inputField.placeholder = "Type command here...";
  380. inputField.style.margin = "10px";
  381. inputField.style.width = "200px"; // Adjust width as needed
  382. overlay.appendChild(inputField);
  383.  
  384. let commandBuffer = ""; // Buffer to store the command until Enter is pressed
  385.  
  386. // Listen for input changes
  387. inputField.addEventListener("input", () => {
  388. commandBuffer = inputField.value.trim(); // Update command buffer with current input
  389. });
  390.  
  391. // Listen for keydown event
  392. inputField.addEventListener("keydown", (event) => {
  393. if (event.key === "Enter") {
  394. // Process the command when Enter key is pressed
  395. if (commandBuffer.startsWith("#ban ")) {
  396. const usernameOrHandle = commandBuffer.replace("#ban ", "").trim();
  397. if (usernameOrHandle !== "") {
  398. addBToHandleOrUsername(usernameOrHandle);
  399. inputField.value = ""; // Clear input field after processing command
  400. } else {
  401. alert("Username or handle not provided!");
  402. }
  403. } else {
  404. alert("Invalid command! Please use '#ban usernameOrHandle'");
  405. }
  406. commandBuffer = ""; // Clear the command buffer after processing
  407. }
  408. });
  409.  
  410. document.body.appendChild(overlay);
  411. }
  412.  
  413. // Call the function to create the input box overlay
  414. createBox();
  415.  
  416. function addBToHandleOrUsername(handleOrUsername) {
  417. let handle = handleOrUsername;
  418. let found = false;
  419.  
  420. // Check if the handle exists in the handleUserMap
  421. if (handleUserMap.hasOwnProperty(handleOrUsername)) {
  422. handle = handleOrUsername;
  423. found = true;
  424. }
  425.  
  426. if (found) {
  427. // Add 'B' next to the handle number
  428. handleUserMap[handle] += " B";
  429. // Update the user list display
  430. displayUserList();
  431. // Save the updated user list to the file
  432. saveUserListToFile();
  433. } else {
  434. alert("User not found!");
  435. }
  436. }
  437.  
  438. // Function to load users from the users.txt file
  439. function loadUsersFromFile() {
  440. const fileInput = document.createElement('input');
  441. fileInput.type = 'file';
  442. fileInput.accept = '.txt';
  443.  
  444. fileInput.addEventListener('change', function() {
  445. const file = fileInput.files[0];
  446. const reader = new FileReader();
  447.  
  448. reader.onload = function(event) {
  449. const fileContent = event.target.result;
  450. // Update handleUserMap with user data from the loaded file
  451. updateHandleUserMap(fileContent);
  452. // Display loaded users
  453. console.log("Loaded Users:");
  454. for (const handle in handleUserMap) {
  455. if (handleUserMap.hasOwnProperty(handle)) {
  456. console.log(`${handleUserMap[handle]} (${handle})`);
  457. }
  458. }
  459. // Define and populate loadedUsers based on handleUserMap
  460. const loadedUsers = Object.keys(handleUserMap).map(handle => ({
  461. handle: handle,
  462. username: handleUserMap[handle]
  463. }));
  464. // Example usage of addBToHandleOrUsername with loadedUsers
  465. addBToHandleOrUsername("handleOrUsername", loadedUsers);
  466. };
  467.  
  468. reader.readAsText(file);
  469. });
  470.  
  471. fileInput.click();
  472. }
  473.  
  474. // Function to update handleUserMap with user data from the loaded file
  475. function updateHandleUserMap(fileContent) {
  476. // Split the file content into lines
  477. const lines = fileContent.split('\n');
  478.  
  479. // Iterate over each line to parse user data
  480. lines.forEach(line => {
  481. const userData = line.trim().split(' '); // Splitting by space to separate username and handle
  482. if (userData.length === 2) {
  483. const username = userData[0].trim();
  484. const handle = userData[1].trim();
  485.  
  486. // Check if the handle already exists in the handleUserMap
  487. if (!handleUserMap.hasOwnProperty(handle)) {
  488. // Update user map with the new username and handle
  489. handleUserMap[handle] = username;
  490. }
  491. }
  492. });
  493. }
  494.  
  495.  
  496. // Function to update the user list display
  497. function updateUserListDisplay() {
  498. // Get the user list element
  499. const userList = document.getElementById("userList");
  500. if (userList) {
  501. // Update the display with modified handleUserMap
  502. userList.innerHTML = ""; // Clear the user list
  503. for (const handle in handleUserMap) {
  504. const username = handleUserMap[handle];
  505. // Append the user to the user list with 'B' if present
  506. const listItem = document.createElement("li");
  507. listItem.textContent = `${username} (${handle})`;
  508. userList.appendChild(listItem);
  509. }
  510. }
  511. }
  512.  
  513. // WebSocket listener for handling messages
  514. function handleWebSocketMessage(message) {
  515. const parsedMessage = JSON.parse(message);
  516. const ownHandle = getOwnHandle(); // Function to get the user's own handle number
  517.  
  518. if (parsedMessage.stumble === "msg" && ownHandle === parsedMessage.handle) {
  519. const text = parsedMessage.text;
  520. if (text.startsWith("#ban")) {
  521. // Extract the handle from the message
  522. const handleToBan = text.replace("#ban", "").trim();
  523. if (handleToBan !== "") {
  524. // Check if the handle exists in the handleUserMap
  525. if (handleUserMap.hasOwnProperty(handleToBan)) {
  526. // Add 'B' next to the handle number
  527. handleUserMap[handleToBan] += " B";
  528. // Update the user list display
  529. updateUserListDisplay();
  530. // Update the users.txt file
  531. saveUserListToFile();
  532. } else {
  533. alert("Handle not found!");
  534. }
  535. } else {
  536. alert("Invalid handle!");
  537. }
  538. }
  539. }
  540. }
  541. // Function to get the user's own handle number (implement your own logic)
  542. function getOwnHandle() {
  543. // Implement your logic to retrieve the user's own handle number
  544. // For demonstration purposes, return a hardcoded value
  545. return "123456"; // Replace with your actual handle number
  546. }
  547. // Function to set up WebSocket listener
  548. function setupWebSocketListener() {
  549. // Override WebSocket constructor to intercept WebSocket creation
  550. const originalWebSocket = window.WebSocket;
  551. window.WebSocket = function(url, protocols) {
  552. console.log('WebSocket URL:', url);
  553.  
  554. // Call original WebSocket constructor
  555. const ws = new originalWebSocket(url, protocols);
  556.  
  557. // Event listener for receiving messages
  558. ws.addEventListener('message', event => {
  559. handleWebSocketMessage(event.data);
  560. });
  561.  
  562. return ws;
  563. };
  564. }
  565.  
  566. // Call functions to set up overlay, WebSocket listener, and initial user list display
  567.  
  568. setupWebSocketListener();
  569. updateUserListDisplay();
  570.  
  571. // Function to display WebSocket messages and update user list
  572. function displayWebSocketMessage(message) {
  573. const parsedMessage = JSON.parse(message);
  574. if (parsedMessage.stumble === "join") {
  575. // Handle join messages: Extract handle and username from the message
  576. const { handle, username } = parsedMessage;
  577. // Map handle to username in handleUserMap
  578. handleUserMap[handle] = username;
  579. // Add the user to the custom user list with the appropriate icon (join user)
  580. addUserToUserList({ handle, username }, "join");
  581. } else if (parsedMessage.stumble === "msg") {
  582. // Handle message messages: Extract handle and text from the message
  583. const { handle, text } = parsedMessage;
  584. // Retrieve username from handleUserMap or use handle if not found
  585. const username = handleUserMap[handle] || handle;
  586. // Display the message in the WebSocket messages div
  587. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  588. if (webSocketMessagesDiv) {
  589. // Append the message with a newline character
  590. webSocketMessagesDiv.textContent += `${username}: ${text}\n`;
  591. // Scroll to the bottom of the messages div
  592. webSocketMessagesDiv.scrollTop = webSocketMessagesDiv.scrollHeight;
  593. }
  594.  
  595. // Additional logic for handling commands
  596. if (text === "#join") {
  597. console.log("join");
  598. // Add your logic here
  599. } else if (text === "#icon") {
  600. console.log("icon");
  601. // Add your logic here
  602. } else if (text === "#tokes") {
  603. console.log("tokes");
  604. // Call your tokes function here
  605. TokesSendEnter();
  606. } else if (text.startsWith("#ai ")) {
  607. console.log("ai");
  608. // Extract the word after "#ai"
  609. const word = text.substring(4);
  610. console.log("Word after '#ai':", word);
  611. // Call your AI function here with the extracted word
  612. DoAi(word); // Adjust parameters as needed
  613. }
  614. } else if (parsedMessage.stumble === "joined") {
  615. // Handle joined messages: Add users to handleUserMap and custom user list
  616. const userList = parsedMessage.userlist;
  617. if (userList && userList.length > 0) {
  618. userList.forEach(user => {
  619. // Extract username from either "username" or "nick"
  620. const username = user.username || user.nick;
  621. // Map handle to username in handleUserMap
  622. handleUserMap[user.handle] = username;
  623. // Add the user to the custom user list with the appropriate icon
  624. addUserToUserList({ handle: user.handle, username }, "joined");
  625. });
  626. }
  627. } else if (parsedMessage.stumble === "quit") {
  628. // Handle quit messages: Remove users from handleUserMap and custom user list
  629. const handle = parsedMessage.handle;
  630. const username = handleUserMap[handle];
  631. if (username) {
  632. // Remove the handle from handleUserMap
  633. delete handleUserMap[handle];
  634. // Remove the user from the custom user list
  635. removeUserFromUserList(handle);
  636. }
  637. }
  638. }
  639.  
  640.  
  641.  
  642. // Function to add user to user list with appropriate icon based on user type
  643. function addUserToUserList(user, userType) {
  644. const userList = document.getElementById("userList");
  645. if (!userList) return;
  646.  
  647. const userItem = document.createElement("div");
  648. userItem.textContent = `${user.username}`;
  649.  
  650. // Define the default dot color and icon
  651. let dotColor = "red"; // Default dot color
  652. let icon = "🔴"; // Default icon for inactive users
  653.  
  654. // Set dot color and icon based on user type
  655. if (userType === "self") {
  656. dotColor = "purple"; // Purple for self user
  657. icon = "🟣"; // Purple circle icon
  658. } else if (userType === "join") {
  659. dotColor = "blue"; // Blue for join user
  660. icon = "🔵"; // Blue circle icon
  661. } else if (userType === "joined") { // "self" user type listener for user list"
  662. dotColor = "green"; // Green for joined user
  663. icon = "🟢"; // Green circle icon
  664. }
  665.  
  666. // Add colored dot based on user status
  667. const dot = document.createElement("span");
  668. dot.textContent = icon;
  669. dot.style.color = dotColor;
  670. userItem.appendChild(dot);
  671.  
  672. // Add custom icon for the user
  673. if (user.icon) {
  674. const customIcon = document.createElement("span");
  675. customIcon.textContent = user.icon;
  676. customIcon.style.marginLeft = "5px"; // Adjust margin as needed
  677. userItem.appendChild(customIcon);
  678. }
  679.  
  680. userList.appendChild(userItem); // Append user item to the user list
  681.  
  682. // If user is not active and not yourself, show popup for 5 seconds
  683. //if (!user.active && user.handle !== yourHandle) {
  684. //const popup = document.createElement("div");
  685. //popup.textContent = "WELCOME TO STUMBLECHAT YEOPARDY!";
  686. //popup.style.fontSize = "48px";
  687. //popup.style.position = "fixed";
  688. //popup.style.top = "50%";
  689. //popup.style.left = "50%";
  690. //popup.style.transform = "translate(-50%, -50%)";
  691. //popup.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
  692. //popup.style.color = "white";
  693. //popup.style.padding = "10px";
  694. //popup.style.borderRadius = "5px";
  695. //document.body.appendChild(popup);
  696.  
  697. }
  698. // Function to update handleUserMap and add users to custom user list
  699. function updateUserListAndMapOnJoin(user) {
  700. // Update handleUserMap with the new user
  701. handleUserMap[user.handle] = user.username || user.nick; // Derive username from handle or nick
  702. // Add the new user to the custom user list
  703. addUserToUserList(user);
  704. }
  705.  
  706. // Call the function to update the user list
  707. function updateUserListOnMessage(userList) {
  708. return function(message) {
  709. const parsedMessage = JSON.parse(message);
  710. if (parsedMessage.stumble === "join" || parsedMessage.stumble === "msg" || parsedMessage.stumble === "joined") {
  711. // Add user to user list
  712. addUserToUserList(parsedMessage);
  713. }
  714. };
  715. }
  716.  
  717. // Function to create WebSocket messages div
  718. function createWebSocketMessagesDiv() {
  719. const div = document.createElement("div");
  720. div.id = "webSocketMessages";
  721. div.style.position = "relative";
  722. div.style.height = "25%";
  723. div.style.paddingLeft = "2px";
  724. div.style.visibility = "visible"; // Ensure the div is visible
  725. div.style.willChange = "transform";
  726. div.style.boxSizing = "border-box";
  727. div.style.overflowX = "hidden";
  728. div.style.overflowY = "auto";
  729. div.style.color = "#ffffff"; // Set font color to white
  730. div.style.padding = "10px"; // Example padding
  731. div.style.zIndex = "2"; // Set a higher z-index value for the WebSocket messages div
  732.  
  733. // Additional styles for specific scenarios
  734. div.style.display = "flex";
  735. div.style.flexDirection = "column";
  736. div.style.justifyContent = "flex-end";
  737. div.style.fontSize = "18px";
  738.  
  739. div.style.whiteSpace = "pre-wrap"; // Allow text to wrap within the container
  740. div.style.wordWrap = "break-word"; // Allow long words to break and wrap
  741.  
  742. // Locate the chat-position div
  743. const chatPositionDiv = document.getElementById("chat-position");
  744. if (chatPositionDiv) {
  745. // Append custom div to the chat-position div
  746. chatPositionDiv.appendChild(div);
  747. } else {
  748. // If chat-position div not found, append to document body as fallback
  749. document.body.appendChild(div);
  750. }
  751. }
  752.  
  753. // Call the function to create the WebSocket messages div
  754. createWebSocketMessagesDiv();
  755.  
  756. // Call the function to create the user list div
  757. const userListDiv = createUserListDiv();
  758. const chatContainer = document.getElementById("chat-container");
  759. if (chatContainer) {
  760. chatContainer.appendChild(userListDiv); // Append to chat container instead
  761. } else {
  762. document.body.appendChild(userListDiv);
  763. }
  764.  
  765. // Function to remove user from custom user list
  766. function removeUserFromUserList(handle) {
  767. const userList = document.getElementById("userList");
  768. if (userList) {
  769. const userElements = userList.querySelectorAll("div");
  770. userElements.forEach(userElement => {
  771. if (userElement.textContent.includes(`(${handle})`)) {
  772. userElement.remove();
  773. }
  774. });
  775. }
  776. }
  777.  
  778. // Function to toggle visibility of custom user list
  779. function toggleCustomUserList() {
  780. const userListDiv = document.getElementById("userList");
  781. if (userListDiv) {
  782. userListDiv.style.display = userListDiv.style.display === "none" ? "block" : "none";
  783. }
  784. }
  785.  
  786. // Add a button to toggle visibility of custom user list
  787. const toggleButton = document.createElement("button");
  788. toggleButton.textContent = "U";
  789. toggleButton.style.position = "fixed";
  790. toggleButton.style.top = "10px";
  791. toggleButton.style.left = "10px";
  792. toggleButton.addEventListener("click", toggleCustomUserList);
  793. document.body.appendChild(toggleButton);
  794.  
  795. // Function to clear messages
  796. function clr() {
  797. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  798. if (webSocketMessagesDiv) {
  799. webSocketMessagesDiv.innerHTML = "";
  800. }
  801. }
  802.  
  803. // Function to create fadeaway popup text with "WELCOME" message
  804. function showWelcomePopupText() {
  805. const popup = document.createElement("div");
  806. popup.textContent = "WELCOME";
  807. popup.classList.add("fadeaway-popup");
  808. document.body.appendChild(popup);
  809.  
  810. // Remove the popup after 3 seconds
  811. setTimeout(() => {
  812. popup.remove();
  813. }, 3000); // 3 seconds delay
  814. }
  815.  
  816. // Function to create SVG animation
  817. function createSVGAnimation() {
  818. // Create SVG element
  819. const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  820. svg.setAttribute("width", "100");
  821. svg.setAttribute("height", "100");
  822.  
  823. // Create rectangle inside SVG
  824. const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
  825. rect.setAttribute("width", "100");
  826. rect.setAttribute("height", "100");
  827. rect.setAttribute("fill", "blue");
  828. svg.appendChild(rect);
  829.  
  830. // Append SVG to body
  831. document.body.appendChild(svg);
  832.  
  833. // Animate SVG
  834. const animation = document.createElementNS("http://www.w3.org/2000/svg", "animate");
  835. animation.setAttribute("attributeName", "x");
  836. animation.setAttribute("from", "-100");
  837. animation.setAttribute("to", "100%");
  838. animation.setAttribute("dur", "5s");
  839. animation.setAttribute("repeatCount", "indefinite");
  840. rect.appendChild(animation);
  841. }
  842. // Call the function to show the welcome popup with SVG animation
  843. showWelcomePopupText();
  844. // Call the function to create SVG animation
  845. createSVGAnimation();
  846.  
  847. function IrcMode() {
  848. const chatContent = document.getElementById("chat-content");
  849. if (chatContent) {
  850. // Remove the chat-content div from the DOM
  851. chatContent.remove();
  852. // Move the webSocketMessagesDiv and the form input to fixed position
  853. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  854. const formInput = document.getElementById("input");
  855. if (webSocketMessagesDiv && formInput) {
  856. webSocketMessagesDiv.style.position = "fixed";
  857. webSocketMessagesDiv.style.top = "0px";
  858. webSocketMessagesDiv.style.height = "90%"; // Adjust height to 90%
  859. webSocketMessagesDiv.style.overflowY = "auto"; // Add scrollbar
  860. formInput.style.position = "fixed";
  861. formInput.style.bottom = "0px";
  862. }
  863. // Create Save Text button
  864. createSaveTextButton();
  865. }
  866. // Disable the room.js functionality
  867. disableRoomJS();
  868. }
  869.  
  870. // Function to save text content without <br> elements
  871. async function saveText() {
  872. console.log("Save Text button clicked."); // Debugging: Log button click
  873. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  874. if (webSocketMessagesDiv) {
  875. console.log("webSocketMessagesDiv found:", webSocketMessagesDiv); // Debugging: Log webSocketMessagesDiv
  876. const textContent = webSocketMessagesDiv.textContent.replaceAll('\n', '\r\n');
  877. console.log("Text content:", textContent); // Debugging: Log extracted text content
  878. try {
  879. // Use File System Access API to prompt user to save text content to a file
  880. const handle = await window.showSaveFilePicker({
  881. types: [{
  882. description: 'Text Files',
  883. accept: {
  884. 'text/plain': ['.txt']
  885. }
  886. }]
  887. });
  888. const writable = await handle.createWritable();
  889. await writable.write(textContent);
  890. await writable.close();
  891. console.log("Text content saved."); // Debugging: Log text saving success
  892. } catch (error) {
  893. console.error("Error saving text content:", error); // Log error if saving fails
  894. }
  895. } else {
  896. console.log("webSocketMessagesDiv not found."); // Debugging: Log if webSocketMessagesDiv is not found
  897. }
  898. }
  899.  
  900. // Function to create Save Text button
  901. function createSaveTextButton() {
  902. const saveTextButton = document.createElement("button");
  903. saveTextButton.id = "saveTextButton";
  904. saveTextButton.textContent = "Save Text";
  905. saveTextButton.style.position = "fixed"; // Position fixed
  906. saveTextButton.style.bottom = "10px"; // Adjust bottom position
  907. saveTextButton.style.left = "10px"; // Adjust left position
  908. saveTextButton.style.background = "black";
  909. saveTextButton.style.color = "lime";
  910. saveTextButton.style.border = "none";
  911. saveTextButton.style.padding = "5px 10px";
  912. saveTextButton.style.cursor = "pointer";
  913. saveTextButton.type = "button"; // Specify that it's a button and not submit
  914. saveTextButton.addEventListener("click", saveText);
  915. document.body.appendChild(saveTextButton); // Append to document body
  916. }
  917.  
  918. // Function to remove Save Text button
  919. function removeSaveTextButton() {
  920. const saveTextButton = document.getElementById("saveTextButton");
  921. if (saveTextButton) {
  922. saveTextButton.remove();
  923. }
  924. }
  925.  
  926. // Call the function to remove the Save Text button initially
  927. removeSaveTextButton();
  928.  
  929. // Function to disable room.js functionality
  930. function disableRoomJS() {
  931. // Remove the event listener for message reception
  932. window.removeEventListener('messageReceived', handleMessageReceived);
  933. }
  934.  
  935.  
  936.  
  937. // Example function that handles incoming messages in room.js
  938. function handleMessageReceived(event) {
  939. // Logic to process incoming messages
  940. }
  941.  
  942. // Modify the handleKeyPress function to handle button clicks as well
  943. function handleKeyPress(event) {
  944. if ((event.key === 'Enter' || event.code === 'Enter') && !event.shiftKey) {
  945. event.preventDefault(); // Prevent the default behavior (creating a new line)
  946. // Call your message sending function here
  947. sendMessage();
  948. // Reset the input box's content
  949. resetInputBox();
  950. }
  951. }
  952.  
  953. // Function to send the "Tokes in 20 seconds" message and simulate Enter key press
  954. function TokesSendEnter() {
  955. // Insert predefined text
  956. const textArea = document.getElementById("textarea");
  957. textArea.value += 'Tokes in 20 seconds\n';
  958.  
  959. // Simulate Enter key press
  960. const event = new KeyboardEvent('keypress', {
  961. key: 'Enter',
  962. code: 'Enter',
  963. keyCode: 13,
  964. which: 13,
  965. bubbles: true
  966. });
  967. textArea.dispatchEvent(event);
  968.  
  969. // Set a timeout to display "tokes started" message after 20 seconds
  970. setTimeout(function() {
  971. textArea.value += 'tokes started\n'; // Send message indicating tokes has started
  972.  
  973. // Simulate Enter key press again
  974. textArea.dispatchEvent(event);
  975. }, 20000); // 20 seconds delay
  976. }
  977.  
  978.  
  979. // Function to insert predefined text and simulate Enter key press
  980. function insertPredefinedTextAndPressEnter() {
  981. // Insert predefined text
  982. const textArea = document.getElementById("textarea");
  983. textArea.value += "(╭☞ ͡ ͡°͜ ʖ ͡ ͡ )╭☞";
  984.  
  985. // Simulate Enter key press
  986. const event = new KeyboardEvent('keypress', {
  987. key: 'Enter',
  988. code: 'Enter',
  989. keyCode: 13,
  990. which: 13,
  991. bubbles: true
  992. });
  993. textArea.dispatchEvent(event);
  994. }
  995.  
  996. // Create a button to insert predefined text and press Enter
  997. function createInsertTextButton() {
  998. const insertTextButton = document.createElement("button");
  999. insertTextButton.textContent = "☞";
  1000. insertTextButton.style.background = "black";
  1001. insertTextButton.style.color = "lime";
  1002. insertTextButton.style.border = "none";
  1003. insertTextButton.style.padding = "5px 10px";
  1004. insertTextButton.style.cursor = "pointer";
  1005. insertTextButton.type = "button"; // Specify that it's a button and not submit
  1006. insertTextButton.addEventListener("click", insertPredefinedTextAndPressEnter);
  1007. const textArea = document.getElementById("textarea");
  1008. textArea.parentElement.appendChild(insertTextButton);
  1009. }
  1010.  
  1011. // Call the function to create the insert text button
  1012. createInsertTextButton();
  1013.  
  1014. // Function to reset the input box's content
  1015. function resetInputBox() {
  1016. const textArea = document.getElementById("textarea");
  1017. if (textArea) {
  1018. textArea.value = ""; // Clear the textarea
  1019. }
  1020. }
  1021.  
  1022. function createPopup() {
  1023. const popup = document.createElement("div");
  1024. popup.id = "messagePopup";
  1025. popup.style.position = "fixed";
  1026. popup.style.top = "50%";
  1027. popup.style.left = "50%";
  1028. popup.style.transform = "translate(-50%, -50%)";
  1029. popup.style.background = "#fff";
  1030. popup.style.padding = "20px";
  1031. popup.style.border = "1px solid #ccc";
  1032. popup.style.boxShadow = "0 0 10px rgba(0, 0, 0, 0.1)";
  1033. popup.style.zIndex = "9999";
  1034.  
  1035. const textarea = document.createElement("textarea");
  1036. textarea.id = "popupTextarea";
  1037. textarea.placeholder = "Type a message";
  1038. textarea.maxLength = "500";
  1039. textarea.style.width = "100%";
  1040. textarea.style.marginBottom = "10px";
  1041. popup.appendChild(textarea);
  1042.  
  1043. const sendButton = document.createElement("button");
  1044. sendButton.textContent = "Send";
  1045. sendButton.style.background = "black";
  1046. sendButton.style.color = "lime";
  1047. sendButton.style.border = "none";
  1048. sendButton.style.padding = "5px 10px";
  1049. sendButton.style.cursor = "pointer";
  1050. sendButton.addEventListener("click", sendMessage);
  1051. popup.appendChild(sendButton);
  1052.  
  1053. document.body.appendChild(popup);
  1054. }
  1055.  
  1056. function openPopup() {
  1057. const popup = document.getElementById("messagePopup");
  1058. if (popup) {
  1059. popup.style.display = "block";
  1060. } else {
  1061. createPopup();
  1062. }
  1063. }
  1064.  
  1065. function closePopup() {
  1066. const popup = document.getElementById("messagePopup");
  1067. if (popup) {
  1068. popup.style.display = "none";
  1069. }
  1070. }
  1071.  
  1072. function sendMessage() {
  1073. const textArea = document.getElementById("popupTextarea");
  1074. if (textArea) {
  1075. const message = textArea.value.trim();
  1076. if (message !== "") {
  1077. // Modify your logic here to match the behavior of their Message.send function
  1078. // For example, if you're directly sending to the WebSocket:
  1079. StumbleChat.WebSocket.send(JSON.stringify({
  1080. "stumble": "msg",
  1081. "text": message
  1082. }));
  1083. // Clear the textarea after sending the message
  1084. textArea.value = "";
  1085. closePopup();
  1086. }
  1087. }
  1088. }
  1089.  
  1090. function clrall() {
  1091. const chatContent = document.getElementById("chat-content");
  1092. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  1093. if (chatContent && webSocketMessagesDiv) {
  1094. // Clear all child elements of chatContent
  1095. chatContent.innerHTML = "";
  1096. // Move webSocketMessagesDiv to the bottom
  1097. chatContent.appendChild(webSocketMessagesDiv);
  1098. // Adjust height of webSocketMessagesDiv
  1099. webSocketMessagesDiv.style.height = "75%";
  1100. }
  1101. }
  1102.  
  1103. // Function to toggle compact view
  1104. function toggleCompactView() {
  1105. const messages = document.querySelectorAll('.message .content');
  1106. messages.forEach(message => {
  1107. message.classList.toggle('compact');
  1108. });
  1109. }
  1110.  
  1111. // Function to create and populate handle-username dropdown menu
  1112. function createHandleUsernameDropdown() {
  1113. const handleUsernameDropdown = document.createElement("select");
  1114. handleUsernameDropdown.id = "handleUsernameDropdown";
  1115. handleUsernameDropdown.style.margin = "0 5px";
  1116. handleUsernameDropdown.innerHTML = '<option value="" disabled selected>who</option>';
  1117. for (const handle in handleUserMap) {
  1118. const option = document.createElement("option");
  1119. option.value = handle;
  1120. option.textContent = handleUserMap[handle];
  1121. handleUsernameDropdown.appendChild(option);
  1122. }
  1123. return handleUsernameDropdown;
  1124. }
  1125.  
  1126. // Create top buttons
  1127. function createTopButtons() {
  1128. const topButtonsDiv = document.createElement("div");
  1129. topButtonsDiv.id = "topButtons";
  1130. topButtonsDiv.style.position = "fixed";
  1131. topButtonsDiv.style.top = "10px";
  1132. topButtonsDiv.style.left = "50%";
  1133. topButtonsDiv.style.transform = "translateX(-50%)";
  1134. topButtonsDiv.style.zIndex = "9999";
  1135.  
  1136. // Clear WebSocket messages button
  1137. const clrButton = document.createElement("button");
  1138. clrButton.textContent = "clr";
  1139. clrButton.style.background = "black";
  1140. clrButton.style.color = "lime";
  1141. clrButton.addEventListener("click", clr);
  1142. topButtonsDiv.appendChild(clrButton);
  1143.  
  1144. // Clear WebSocket messages button
  1145. const clrallButton = document.createElement("button");
  1146. clrallButton.textContent = "clrall";
  1147. clrallButton.style.background = "black";
  1148. clrallButton.style.color = "lime";
  1149. clrallButton.addEventListener("click", clr);
  1150. topButtonsDiv.appendChild(clrallButton);
  1151.  
  1152. // Delete chat and switch to IRC only mode
  1153. const IrcModeButton = document.createElement("button");
  1154. IrcModeButton.textContent = "irc";
  1155. IrcModeButton.style.background = "black";
  1156. IrcModeButton.style.color = "lime";
  1157. IrcModeButton.addEventListener("click", IrcMode);
  1158. topButtonsDiv.appendChild(IrcModeButton);
  1159.  
  1160. // Dropdown menu for handle-username mapping
  1161. const handleUsernameDropdown = createHandleUsernameDropdown();
  1162. topButtonsDiv.appendChild(handleUsernameDropdown);
  1163.  
  1164. // Color picker button
  1165. const colorPickerButton = document.createElement("button");
  1166. colorPickerButton.textContent = "Color";
  1167. colorPickerButton.style.background = "black";
  1168. colorPickerButton.style.color = "lime";
  1169. colorPickerButton.style.margin = "0 5px";
  1170. colorPickerButton.addEventListener("click", () => {
  1171. openColorPickerPopup();
  1172. });
  1173. topButtonsDiv.appendChild(colorPickerButton);
  1174.  
  1175. // Font size dropdown
  1176. const fontSizeDropdown = document.createElement("select");
  1177. fontSizeDropdown.id = "fontSizeDropdown";
  1178. fontSizeDropdown.style.margin = "0 5px";
  1179. for (let i = 1; i <= 20; i++) {
  1180. const option = document.createElement("option");
  1181. option.value = i;
  1182. option.textContent = i;
  1183. fontSizeDropdown.appendChild(option);
  1184. }
  1185. fontSizeDropdown.addEventListener("change", () => {
  1186. const selectedFontSize = fontSizeDropdown.value;
  1187. applyFontSize(selectedFontSize);
  1188. });
  1189. topButtonsDiv.appendChild(fontSizeDropdown);
  1190.  
  1191. // Append top buttons div to document body
  1192. document.body.appendChild(topButtonsDiv);
  1193. }
  1194.  
  1195. // Function to apply font size to WebSocket messages
  1196. function applyFontSize(fontSize) {
  1197. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  1198. if (webSocketMessagesDiv) {
  1199. webSocketMessagesDiv.style.fontSize = `${fontSize}px`;
  1200. }
  1201. }
  1202.  
  1203. // Call the function to create top buttons
  1204. createTopButtons();
  1205.  
  1206. // Function to open color picker popup
  1207. function openColorPickerPopup() {
  1208. const popup = document.createElement("div");
  1209. popup.id = "colorPickerPopup";
  1210. popup.style.position = "fixed";
  1211. popup.style.top = "50%";
  1212. popup.style.left = "50%";
  1213. popup.style.transform = "translate(-50%, -50%)";
  1214. popup.style.background = "#1f1f1f";
  1215. popup.style.padding = "20px";
  1216. popup.style.border = "2px solid #ffffff";
  1217. popup.style.zIndex = "99999";
  1218.  
  1219. const backgroundLabel = document.createElement("label");
  1220. backgroundLabel.textContent = "Background Color:";
  1221. backgroundLabel.style.color = "#ffffff";
  1222. popup.appendChild(backgroundLabel);
  1223.  
  1224. const backgroundColorInput = document.createElement("input");
  1225. backgroundColorInput.type = "color";
  1226. backgroundColorInput.id = "backgroundColorInput";
  1227. backgroundColorInput.style.marginRight = "10px";
  1228. backgroundColorInput.value = "#000000";
  1229. popup.appendChild(backgroundColorInput);
  1230.  
  1231. const fontColorLabel = document.createElement("label");
  1232. fontColorLabel.textContent = "Font Color:";
  1233. fontColorLabel.style.color = "#ffffff";
  1234. popup.appendChild(fontColorLabel);
  1235.  
  1236. const fontColorInput = document.createElement("input");
  1237. fontColorInput.type = "color";
  1238. fontColorInput.id = "fontColorInput";
  1239. fontColorInput.style.marginRight = "10px";
  1240. fontColorInput.value = "#ffffff";
  1241. popup.appendChild(fontColorInput);
  1242.  
  1243. const applyButton = document.createElement("button");
  1244. applyButton.textContent = "Apply";
  1245. applyButton.style.background = "black";
  1246. applyButton.style.color = "lime";
  1247. applyButton.style.marginTop = "10px";
  1248. applyButton.addEventListener("click", () => {
  1249. applyColors(backgroundColorInput.value, fontColorInput.value);
  1250. popup.remove();
  1251. });
  1252. popup.appendChild(applyButton);
  1253.  
  1254. const closeButton = document.createElement("button");
  1255. closeButton.textContent = "Close";
  1256. closeButton.style.background = "black";
  1257. closeButton.style.color = "lime";
  1258. closeButton.style.marginTop = "10px";
  1259. closeButton.style.marginLeft = "10px";
  1260. closeButton.addEventListener("click", () => {
  1261. popup.remove();
  1262. });
  1263. popup.appendChild(closeButton);
  1264.  
  1265. document.body.appendChild(popup);
  1266. }
  1267.  
  1268. // Function to apply selected colors to WebSocket log
  1269. function applyColors(backgroundColor, fontColor) {
  1270. const webSocketMessagesDiv = document.getElementById("webSocketMessages");
  1271. if (webSocketMessagesDiv) {
  1272. webSocketMessagesDiv.style.backgroundColor = backgroundColor;
  1273. webSocketMessagesDiv.style.color = fontColor;
  1274. }
  1275. }
  1276.  
  1277. /* Additional compacting styles */
  1278. /*@-moz-document url-prefix("https://stumblechat.com/room/") {*/
  1279. // Compact message styles
  1280. const compactStyles = `
  1281. .message .nickname ~ .content {
  1282. display: inline-block;
  1283. top: -7px;
  1284. position: relative;
  1285. margin-left: 2px;
  1286. margin-right: 1em;
  1287. }
  1288. .content + .content {
  1289. display: inline-block!important;
  1290. margin-right: 1em;
  1291. }
  1292. .message .nickname ~ .content span {
  1293. line-height: 1.5em;
  1294. }
  1295. `;
  1296.  
  1297. // Apply compact styles to the document
  1298. const style = document.createElement('style');
  1299. style.textContent = compactStyles;
  1300. document.head.appendChild(style);
  1301. /*}*/
  1302.  
  1303.  
  1304. // Function to handle click events for the new button
  1305. function handleLoadButtonClick() {
  1306. // Add functionality for the new button here
  1307. console.log('Load button clicked');
  1308. }
  1309.  
  1310. // Function to handle click events for the new button
  1311. function handleDisplayThingsButtonClick() {
  1312. // Add functionality for the new button here
  1313. console.log('Load button clicked');
  1314. }
  1315.  
  1316. // Create a new button configuration
  1317. const DisplayThingsButtonConfig = { name: 'd', text: 'display', clickHandler: handleDisplayThingsButtonClick };
  1318.  
  1319. // Create a new button configuration
  1320. const LoadButtonConfig = { name: 'n', text: 'Load', clickHandler: handleLoadButtonClick };
  1321.  
  1322. // Function to create generic buttons
  1323. function createGenericButtons() {
  1324. // Define button configurations
  1325. const buttonConfigurations = [
  1326. { name: 'c', text: 'Compact', clickHandler: toggleCompactView },
  1327. { name: 's', text: 'Save', clickHandler: () => {
  1328. // Functionality to save handle-username map to memory or file
  1329. console.log("Save button clicked");
  1330. saveUserListToFile();
  1331. }},
  1332. { name: 'L', text: 'Load Users', clickHandler: loadUsersFromFile }, // Button to load users from file
  1333. LoadButtonConfig, // Add the new button configuration here
  1334. { name: 'D', text: 'Display Things', clickHandler: handleDisplayThingsButtonClick } // Button to load users from file
  1335. ];
  1336.  
  1337. // Get the container for the buttons
  1338. const container = document.getElementById('topButtons');
  1339.  
  1340. // Loop through each button configuration and generate a button
  1341. buttonConfigurations.forEach(config => {
  1342. // Create a button element
  1343. const button = document.createElement('button');
  1344. button.textContent = config.text; // Use button text as text content
  1345. button.style.background = "black";
  1346. button.style.color = "lime";
  1347. button.style.width = "50px"; // Set button width
  1348. button.style.height = "20px"; // Set button height
  1349. button.style.margin = "0 5px"; // Set button margin
  1350.  
  1351. // Add event listener based on configuration
  1352. button.addEventListener('click', config.clickHandler);
  1353.  
  1354. // Append the button to the container in the DOM
  1355. container.appendChild(button);
  1356. });
  1357. }
  1358.  
  1359. // Call the function to create generic buttons
  1360. createGenericButtons();
  1361.  
  1362.  
  1363. // Function to create a new button and append it to the container
  1364. function createDisconnectButton() {
  1365. const container = document.getElementById('topButtons');
  1366.  
  1367. // Create the button element
  1368. const newButton = document.createElement('button');
  1369. newButton.textContent = 'DC'; // Change the text as needed
  1370. newButton.style.background = 'black';
  1371. newButton.style.color = 'lime';
  1372. newButton.style.width = '100px'; // Set the button width
  1373. newButton.style.height = '30px'; // Set the button height
  1374. newButton.style.margin = '0 5px'; // Set the button margin
  1375.  
  1376. // Add event listener to the new button
  1377. newButton.addEventListener('click', () => {
  1378. // Add functionality for the new button here
  1379. console.log('New button clicked');
  1380. });
  1381.  
  1382. // Append the new button to the container
  1383. container.appendChild(newButton);
  1384. }
  1385.  
  1386. // Call the function to create the new button
  1387. createDisconnectButton();
  1388.  
  1389. // Function to load users from the users.txt file
  1390. function displayThings() {
  1391. const users = [];
  1392. // Placeholder for file content, replace this with your file reading logic
  1393. // Example: You can use XMLHttpRequest, fetch API, or any other method to read the file
  1394. // For simplicity, I'll use fetch API assuming users.txt is in the same directory
  1395. fetch('users.txt')
  1396. .then(response => response.text())
  1397. .then(fileContent => {
  1398. // Split the file content into lines
  1399. const lines = fileContent.split('\n');
  1400.  
  1401. // Iterate over each line to parse user data
  1402. lines.forEach(line => {
  1403. const userData = line.trim().split(' '); // Splitting by space to separate username and handle
  1404. if (userData.length === 2) {
  1405. const username = userData[0].trim();
  1406. const handle = userData[1].trim();
  1407. users.push({ username, handle });
  1408. // Update user map
  1409. handleUserMap[handle] = username;
  1410. }
  1411. });
  1412.  
  1413. // Display loaded users
  1414. console.log("Loaded Users:");
  1415. users.forEach(user => {
  1416. console.log(`${user.username} (${user.handle})`);
  1417. });
  1418. })
  1419. .catch(error => {
  1420. console.error('Error loading users from file:', error);
  1421. });
  1422.  
  1423. return users;
  1424. }
  1425.  
  1426. // Find the CSP meta tag and modify its content attribute
  1427. const cspMeta = document.querySelector("meta[http-equiv='Content-Security-Policy']");
  1428. if (cspMeta) {
  1429. cspMeta.setAttribute("content", "your-updated-csp-directives");
  1430. }
  1431.  
  1432. const proxyUrl = "http://65.25.72.68:43435"; // Add http:// or https:// as needed
  1433.  
  1434. // Function to call the AI and send its response to the chat room
  1435. function DoAi(cmd_arg) {
  1436. // Define your OpenAI API key and other parameters
  1437. const api_key = 'your-api-key';
  1438. const endpoint = proxyUrl; // Use proxy server endpoint
  1439. const max_tokens = 200;
  1440. const max_parts = 10;
  1441. const delay_between_parts = 2;
  1442. const min_response_length = 10;
  1443.  
  1444. const headers = {
  1445. 'Content-Type': 'application/json',
  1446. 'Authorization': 'Bearer ' + api_key,
  1447. };
  1448.  
  1449. const data = {
  1450. model: 'gpt-3.5-turbo',
  1451. messages: [{role: 'system', content: 'You are a helpful assistant.'},
  1452. {role: 'user', content: cmd_arg}],
  1453. max_tokens: max_tokens,
  1454. };
  1455.  
  1456. // Send the POST request to the API via proxy server
  1457. fetch(endpoint, {
  1458. method: 'POST',
  1459. headers: headers,
  1460. body: JSON.stringify(data)
  1461. })
  1462. .then(response => {
  1463. if (!response.ok) {
  1464. throw new Error('Request failed with status code ' + response.status);
  1465. }
  1466. return response.json();
  1467. })
  1468. .then(result => {
  1469. if (result.choices && result.choices[0] && result.choices[0].message && result.choices[0].message.content) {
  1470. let response_text = result.choices[0].message.content;
  1471.  
  1472. // Check if the response_text is not empty and meets the minimum length
  1473. if (response_text.trim() && response_text.length >= min_response_length) {
  1474. // Use regular expression to replace various line break characters
  1475. response_text = response_text.replace(/[\r\n\t\f\v]+/g, ' ');
  1476.  
  1477. // Split the response into parts based on sentence-like breaks
  1478. const parts = response_text.match(/.{1,200}(?:\.\s|\.$|$)/g) || [];
  1479.  
  1480. const num_parts = Math.min(max_parts, parts.length);
  1481.  
  1482. // Calculate the time interval for rate limiting (15 seconds / 3 messages)
  1483. const rate_limit_interval = 15.0 / 3;
  1484.  
  1485. // Send each part with a delay
  1486. parts.slice(0, num_parts).forEach((part, index) => {
  1487. setTimeout(() => {
  1488. // Send the part to the chat room
  1489. sendMessage(part);
  1490. }, index * delay_between_parts * 1000);
  1491. });
  1492. } else {
  1493. sendMessage("AI response was blank or too short.");
  1494. }
  1495. } else {
  1496. sendMessage("AI response format unexpected: " + JSON.stringify(result));
  1497. }
  1498. })
  1499. .catch(error => {
  1500. sendMessage("AI request failed: " + error.message);
  1501. });
  1502. }
  1503.  
  1504.  
  1505. })();
  1506.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement