Meklin Shutdownchat Script

Modified Shutdownchat, unmatched scripts, brace to be thunderstruck

当前为 2023-12-30 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Meklin Shutdownchat Script
  3. // @version 1.3
  4. // @description Modified Shutdownchat, unmatched scripts, brace to be thunderstruck
  5. // @author MeKLiN
  6. // @namespace https://greasyfork.org/en/scripts/483405-meklin-shutdownchat-script
  7. // @match https://www.shutdown.chat/rooms*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=shutdown.chat
  9. // @license MIT
  10. // @grant none
  11. // @exclude https://www.shutdown.chat/profiles*
  12. // @exclude https://www.shutdown.chat/manage*
  13. // @run-at document-start
  14. // @require https://cdnjs.cloudflare.com/ajax/libs/jshint/2.9.7/jshint.js
  15. // @require https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.5/es6-shim.min.js
  16. // ==/UserScript==
  17. console.log("MSS 1.1 STARTED");
  18. debugger;
  19.  
  20. // Function to create a button to clear the JSON local saved cache
  21. function createClearCacheButton() {
  22. console.log("createClearCacheButton function is called");
  23. var clearCacheButton = document.createElement("button");
  24.  
  25. // Set the inner text with a smaller font size
  26. clearCacheButton.innerText = "Clear Cache/Refresh";
  27. clearCacheButton.style.fontSize = "12px"; // Adjust the font size as needed
  28.  
  29. clearCacheButton.style.position = "fixed";
  30. clearCacheButton.style.top = "50px";
  31. clearCacheButton.style.left = "10px";
  32. clearCacheButton.addEventListener("click", function () {
  33. // Clear the JSON local saved cache
  34. localStorage.removeItem('blocked_uuids');
  35. // Reload the page to apply changes
  36. location.reload();
  37. });
  38.  
  39. document.body.appendChild(clearCacheButton);
  40. }
  41.  
  42. // Call the function to create the clear cache button
  43. createClearCacheButton();
  44.  
  45. // Function to create a button to collapse the view
  46. function createCollapseButton() {
  47. console.log("createCollapseButton function is called");
  48. var collapseButton = document.createElement("button");
  49.  
  50. // Set the inner HTML with an SVG and additional text
  51. collapseButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
  52. <path fill="none" d="M0 0h24v24H0z"/>
  53. <path d="M8 4v5l-2.5-1.5L3 9V4l5-2zm8 0l5 2v5l-2.5-1.5L16 9V4zM3 11l3.5-1.5L8 11V9L3 7zm13 0l3.5-1.5L21 11V9l-5-2z"/>
  54. </svg> Collapse View`;
  55.  
  56. // Adjust the font size of the text
  57. collapseButton.style.fontSize = "12px"; // Adjust the font size as needed
  58.  
  59. collapseButton.style.position = "fixed";
  60. collapseButton.style.top = "90px";
  61. collapseButton.style.left = "10px";
  62. collapseButton.addEventListener("click", function () {
  63. // Toggle visibility of the chatbox
  64. var chatbox = document.querySelector('.chatbox');
  65. chatbox.style.display = (chatbox.style.display === 'none' || chatbox.style.display === '') ? 'block' : 'none';
  66. });
  67.  
  68. document.body.appendChild(collapseButton);
  69. }
  70.  
  71. // Call the function to create the collapse button
  72. createCollapseButton();
  73.  
  74. var blocked_uuids = JSON.parse(localStorage.getItem('blocked_uuids')) || [];
  75.  
  76. function getNickname(fcuserSpan) {
  77. if (!fcuserSpan) return;
  78.  
  79. // Check if fcuserSpan is a direct child of p
  80. var isDirectChild = fcuserSpan.parentNode.nodeName === "P";
  81. var nickname;
  82.  
  83. if (isDirectChild) {
  84. nickname = fcuserSpan.innerText.replace(/[:\-]/g, '').trim();
  85. } else {
  86. // If not a direct child, assume it's under an anchor tag (a) in the user list
  87. nickname = fcuserSpan.parentNode.querySelector('.fcuser').innerText.replace(/[:\-]/g, '').trim();
  88. }
  89.  
  90. return nickname;
  91. }
  92.  
  93. // Function to handle the new chat messages
  94. function handleNewChatMessages() {
  95. var chatboxElems = document.querySelector('.chatbox').getElementsByTagName('p');
  96. for (var i = 0; i < chatboxElems.length; i++) {
  97. var chatElem = chatboxElems[i];
  98. if (!chatElem.handled) {
  99. chatElem.handled = true;
  100. var fcuserSpan = chatElem.querySelector('.nm.fcuser');
  101. var uuid = fcuserSpan ? fcuserSpan.dataset.uuid : null;
  102. if (blocked_uuids.includes(uuid)) {
  103. chatElem.style.display = 'none'; // hide the message
  104. }
  105. }
  106. }
  107. }
  108.  
  109. // Call the handleNewChatMessages function on page load and whenever the chatbox is updated
  110. handleNewChatMessages();
  111. document.querySelector('.chatbox').addEventListener('DOMNodeInserted', handleNewChatMessages);
  112.  
  113.  
  114. // Get the chatbox element
  115. var chatbox = document.querySelector(".chatbox");
  116.  
  117. // Create a mutation observer to monitor changes in the chatbox
  118. var observer = new MutationObserver(function(mutations) {
  119. mutations.forEach(function(mutation) {
  120. mutation.addedNodes.forEach(function(node) {
  121. // Check if the node is a chat message
  122. if (node.nodeName === "P" && node.dataset.t === "c") {
  123. // Get the uuid of the user who sent the message
  124. var uuidElement = node.querySelector(".nm.fcuser");
  125. if (uuidElement) {
  126. var uuid = uuidElement.dataset.uuid;
  127. console.log("Found message with UUID:", uuid);
  128.  
  129. // Check if the uuid is in the blocked list
  130. if (blocked_uuids.includes(uuid)) {
  131. console.log("Blocking message with UUID:", uuid);
  132. // Hide the message
  133. node.style.display = "none";
  134. }
  135. } else {
  136. console.log("Could not find UUID element in message:", node);
  137. }
  138. }
  139. });
  140. });
  141. });
  142.  
  143. // Start observing the chatbox
  144. observer.observe(chatbox, { childList: true });
  145.  
  146. // Function to show a notification
  147. function showNotification(message) {
  148. var notification = document.createElement("div");
  149. notification.innerHTML = `<div style="position: fixed; bottom: 10px; left: 10px; background-color: #000000; padding: 10px; border: 1px solid #ccc; border-radius: 5px; font-size: 12px; color: #C0FF00; opacity: 1; transition: opacity 2s ease-in-out;">${message}</div>`;
  150. document.body.appendChild(notification);
  151.  
  152. // Set a timeout to fade out the notification
  153. setTimeout(function () {
  154. notification.style.opacity = 0;
  155. }, 2000); // Adjust the timeout value as needed
  156.  
  157. // Remove the notification from the DOM after fading out
  158. setTimeout(function () {
  159. document.body.removeChild(notification);
  160. }, 3000); // Adjust the timeout value to match the fade-out duration
  161. }
  162.  
  163. // Function to block/unblock a user
  164. function blockUser(uuid) {
  165. console.log("blockUser function is called");
  166. var index = blocked_uuids.indexOf(uuid);
  167. if (index !== -1) {
  168. // User is already blocked, so unblock
  169. blocked_uuids.splice(index, 1);
  170. showNotification("User unblocked!");
  171. } else {
  172. // User is not blocked, so block
  173. blocked_uuids.push(uuid);
  174. showNotification("User blocked!");
  175. }
  176.  
  177. // Save the updated blocked_uuids to localStorage
  178. localStorage.setItem('blocked_uuids', JSON.stringify(blocked_uuids));
  179. }
  180.  
  181. // Function to create a button to view the ignore list
  182. function createIgnoreListButton() {
  183. console.log("createIgnoreListButton function is called");
  184. var ignoreListButton = document.createElement("button");
  185. ignoreListButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 18V8a6 6 0 0 0-12 0v10h12zM12 2C6.48 2 2 6.48 2 12v10h2V12a5.978 5.978 0 0 1 5.985-6H12V2zm8.293 2.293a1 1 0 0 1 1.414 0l1.414 1.414a1 1 0 0 1 0 1.414L19.414 10l3.707 3.707a1 1 0 0 1 0 1.414l-1.414 1.414a1 1 0 0 1-1.414 0L18 13.414l-3.707 3.707a1 1 0 0 1-1.414 0l-1.414-1.414a1 1 0 0 1 0-1.414L14.586 12 10.88 8.293a1 1 0 0 1 0-1.414L12.294 5.465a1 1 0 0 1 1.414 0z"/></svg> View Ignore List`;
  186. ignoreListButton.style.position = "fixed";
  187. ignoreListButton.style.top = "10px";
  188. ignoreListButton.style.left = "10px";
  189. ignoreListButton.addEventListener("click", function () {
  190. // Display the ignore list (you can customize this part)
  191. alert("Ignore List:\n" + blocked_uuids.join(", "));
  192. });
  193.  
  194. document.body.appendChild(ignoreListButton);
  195. }
  196.  
  197. // Call the function to create the ignore list button
  198. createIgnoreListButton();
  199.  
  200.  
  201. // Get the user list element
  202. var userlist = document.querySelector(".userlist");
  203.  
  204. // Create the block and ignore buttons and append them to each user
  205. var users = userlist.querySelectorAll(".fcuser");
  206. users.forEach(function (user) {
  207. var uuid = user.dataset.uuid;
  208.  
  209. // Create the block button
  210. var blockButton = document.createElement("button");
  211. blockButton.innerText = "Block";
  212. blockButton.addEventListener("click", function() {
  213. blockUser(uuid);
  214. });
  215.  
  216. // Create the ignore button with a unique class
  217. var ignoreButton = document.createElement("button");
  218. ignoreButton.innerText = "Ignore";
  219. ignoreButton.setAttribute("data-btntype", "ignore"); // Set a new attribute for identification
  220. ignoreButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 18V8a6 6 0 0 0-12 0v10h12zM12 2C6.48 2 2 6.48 2 12v10h2V12a5.978 5.978 0 0 1 5.985-6H12V2zm8.293 2.293a1 1 0 0 1 1.414 0l1.414 1.414a1 1 0 0 1 0 1.414L19.414 10l3.707 3.707a1 1 0 0 1 0 1.414l-1.414 1.414a1 1 0 0 1-1.414 0L18 13.414l-3.707 3.707a1 1 0 0 1-1.414 0l-1.414-1.414a1 1 0 0 1 0-1.414L14.586 12 10.88 8.293a1 1 0 0 1 0-1.414L12.294 5.465a1 1 0 0 1 1.414 0z"/></svg>`;
  221. ignoreButton.style.marginLeft = "5px";
  222. ignoreButton.style.cursor = "pointer";
  223. // Add a unique class to the ignore button
  224. ignoreButton.classList.add("ignoreButtonClass");
  225.  
  226. ignoreButton.addEventListener("click", function () {
  227. // Dynamically fetch the user UUID when the "Ignore" button is clicked
  228. var clickedUserUUID = user.dataset.uuid;
  229. blockUser(clickedUserUUID);
  230. });
  231.  
  232. // Create a container div for the buttons
  233. var buttonContainer = document.createElement("div");
  234. buttonContainer.style.display = "flex";
  235. buttonContainer.style.alignItems = "center";
  236.  
  237. // Append the buttons to the container
  238. buttonContainer.appendChild(blockButton);
  239. buttonContainer.appendChild(ignoreButton);
  240.  
  241. // Append the container to the user element
  242. user.parentElement.appendChild(buttonContainer);
  243. });
  244.  
  245. // usermenu block button event listener:
  246. document.querySelector('.usermenu button[data-btntype="block"]').addEventListener('click', function() {
  247. console.log("User menu block button clicked");
  248.  
  249. // Get the parent element of the button, assuming it contains user-related data
  250. var userContainer = this.closest('.user-container');
  251.  
  252. // Assuming the user UUID is stored in a data attribute called data-uuid
  253. var userUUID = userContainer ? userContainer.dataset.uuid : null;
  254.  
  255. // Check if userUUID is not null before blocking
  256. if (userUUID) {
  257. // Now you have the user UUID, and you can proceed to block the user
  258. blockUser(userUUID);
  259. } else {
  260. console.error("User UUID not found. Unable to block user.");
  261. }
  262. });
  263.  
  264. // Function to create an ignore button in the user menu
  265. function createIgnoreButton(username, uuid) {
  266. console.log("createIgnoreButton function is called");
  267.  
  268. var ignoreButton = document.createElement("button");
  269. ignoreButton.innerText = "Ignore";
  270. ignoreButton.setAttribute("data-btntype", "ignore"); // Set a new attribute for identification
  271. ignoreButton.style.display = "block";
  272. ignoreButton.style.marginTop = "5px"; // Adjust the styling as needed
  273.  
  274.  
  275. // Insert the ignore button into the user menu
  276. var userMenu = document.querySelector('.usermenu');
  277. if (userMenu) {
  278. userMenu.insertBefore(ignoreButton, userMenu.firstChild);
  279.  
  280.  
  281. // Add click event directly to the button
  282. ignoreButton.addEventListener("click", function () {
  283. // Log to console to check if the button click is being registered
  284. console.log("Ignore button clicked");
  285.  
  286. // Traverse the DOM to find the user UUID dynamically within FreeChat context
  287. var userUUID = getUserUUIDFromUserList();
  288.  
  289. // Check if the user UUID is found
  290. if (userUUID) {
  291. blockUser(userUUID, username);
  292. } else {
  293. console.error("User UUID not found. Ignoring user without blocking.");
  294. }
  295. });
  296. } else {
  297. console.error("User menu not found.");
  298. }
  299. }
  300.  
  301. // Function to get the user UUID from the user list within FreeChat context
  302. function getUserUUIDFromUserList() {
  303. var userContainer = document.querySelector("#chat > div.fc > div.gridbox_list > div.userlist p.user.fcuser[data-uuid]");
  304.  
  305. if (userContainer) {
  306. return userContainer.dataset.uuid;
  307. } else {
  308. // If user container is not found, set up a MutationObserver to wait for changes
  309. var observer = new MutationObserver(function (mutations) {
  310. userContainer = document.querySelector("#chat > div.fc > div.gridbox_list > div.userlist p.user.fcuser[data-uuid]");
  311. if (userContainer) {
  312. console.log("User container found after mutation.");
  313. console.log("User UUID: ", userContainer.dataset.uuid);
  314. // Stop observing once the user container is found
  315. observer.disconnect();
  316. }
  317. });
  318.  
  319. // Start observing changes in the user list
  320. observer.observe(document.querySelector("#chat > div.fc > div.gridbox_list > div.userlist"), { childList: true, subtree: true });
  321.  
  322. console.error("User container not found in the user list within FreeChat context. Waiting for mutations...");
  323. return null;
  324. }
  325. }
  326.  
  327. // Call the function to create the ignore button in the user menu
  328. createIgnoreButton();
  329.  
  330. // Create the ignore list div once and append the content dynamically
  331. var ignoreListDiv = document.createElement("div");
  332. ignoreListDiv.style.position = "fixed";
  333. ignoreListDiv.style.bottom = "10px"; // Move to the bottom
  334. ignoreListDiv.style.left = "10px";
  335. ignoreListDiv.style.backgroundColor = "white"; // Adjust styling as needed
  336. ignoreListDiv.style.padding = "10px";
  337. ignoreListDiv.style.border = "1px solid black"; // Add border for visibility
  338. ignoreListDiv.style.fontSize = "12px"; // Set font size to 12px
  339.  
  340.  
  341. // Create a heading for the ignore list
  342. var ignoreListHeading = document.createElement("h3");
  343. ignoreListHeading.innerText = "Ignore List";
  344. ignoreListDiv.appendChild(ignoreListHeading);
  345.  
  346. // Create a list to display ignored users
  347. var ignoreList = document.createElement("ul");
  348. ignoreList.style.listStyleType = "none"; // Remove default list styling
  349. ignoreListDiv.appendChild(ignoreList);
  350.  
  351. // Append the ignore list div to the body
  352. document.body.appendChild(ignoreListDiv);
  353.  
  354. // Function to create a list item with the ignore list entry and remove button
  355. function createIgnoreListItem(uuid, username) {
  356. var listItem = document.createElement("li");
  357. listItem.innerText = `${username} (${uuid})`;
  358.  
  359. // Create a remove button for each entry
  360. var removeButton = document.createElement("button");
  361. removeButton.innerText = "Remove";
  362. removeButton.addEventListener("click", function () {
  363. // Remove the entry when the button is clicked
  364. removeIgnoreEntry(uuid);
  365. });
  366.  
  367. // Append the remove button to the list item
  368. listItem.appendChild(removeButton);
  369.  
  370. // Append the list item to the ignore list
  371. ignoreList.appendChild(listItem);
  372. }
  373.  
  374.  
  375. // Function to refresh the ignore list display
  376. function refreshIgnoreList() {
  377. // Clear the existing content
  378. ignoreList.innerHTML = "";
  379.  
  380. // Populate the ignore list with entries and remove buttons
  381. blocked_uuids.forEach(function (uuid) {
  382. createIgnoreListItem(uuid);
  383. });
  384. }
  385.  
  386. // Populate the ignore list with entries and remove buttons
  387. blocked_uuids.forEach(function (uuid) {
  388. createIgnoreListItem(uuid);
  389. });
  390.  
  391. // Function to handle removing an entry from the ignore list
  392. function removeIgnoreEntry(uuid) {
  393. var index = blocked_uuids.indexOf(uuid);
  394. if (index !== -1) {
  395. // Remove the entry from the ignore list
  396. blocked_uuids.splice(index, 1);
  397. // Refresh the ignore list display after removal
  398. refreshIgnoreList();
  399. }
  400. }
  401.  
  402.  
  403. // Function to save blocked_uuids to a text file
  404. function saveToTextFile() {
  405. var textToSave = blocked_uuids.join('\n');
  406. var blob = new Blob([textToSave], { type: 'text/plain' });
  407. var link = document.createElement('a');
  408. link.download = 'ignore_list.txt';
  409. link.href = window.URL.createObjectURL(blob);
  410. link.onclick = function () {
  411. document.body.removeChild(link);
  412. };
  413. link.style.display = 'none';
  414. document.body.appendChild(link);
  415. link.click();
  416. }
  417.  
  418. // Function to load blocked_uuids from a text file
  419. function loadFromTextFile() {
  420. var input = document.createElement('input');
  421. input.type = 'file';
  422. input.accept = '.txt';
  423. input.onchange = function (event) {
  424. var file = event.target.files[0];
  425. if (file) {
  426. var reader = new FileReader();
  427. reader.onload = function (e) {
  428. // Parse the content of the file and update blocked_uuids
  429. blocked_uuids = e.target.result.split('\n').map(function (uuid) {
  430. return uuid.trim();
  431. });
  432. // Update the ignore list display
  433. refreshIgnoreList();
  434. };
  435. reader.readAsText(file);
  436. }
  437. };
  438. input.click();
  439. }
  440.  
  441. // Function to create a button to save and load ignore list
  442. function createSaveLoadButtons() {
  443. var saveButton = document.createElement("button");
  444. saveButton.innerText = "Save to Text File";
  445. saveButton.addEventListener("click", function () {
  446. saveToTextFile();
  447. });
  448.  
  449. var loadButton = document.createElement("button");
  450. loadButton.innerText = "Load from Text File";
  451. loadButton.addEventListener("click", function () {
  452. loadFromTextFile();
  453. });
  454.  
  455. var buttonContainer = document.createElement("div");
  456. buttonContainer.style.marginTop = "10px";
  457. buttonContainer.appendChild(saveButton);
  458. buttonContainer.appendChild(loadButton);
  459.  
  460. // Append the button container to the ignore list div
  461. ignoreListDiv.appendChild(buttonContainer);
  462. }
  463.  
  464. // Call the function to create the save and load buttons
  465. createSaveLoadButtons();