Meklin Shutdownchat Script

Modified Shutdownchat, unmatched scripts, brace to be thunderstruck

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Meklin Shutdownchat Script
// @version      1.3
// @description  Modified Shutdownchat, unmatched scripts, brace to be thunderstruck
// @author       MeKLiN
// @namespace    https://greasyfork.org/en/scripts/483405-meklin-shutdownchat-script
// @match        https://www.shutdown.chat/rooms*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=shutdown.chat
// @license      MIT
// @grant        none
// @exclude      https://www.shutdown.chat/profiles*
// @exclude      https://www.shutdown.chat/manage*
// @run-at       document-start
// @require      https://cdnjs.cloudflare.com/ajax/libs/jshint/2.9.7/jshint.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.5/es6-shim.min.js
// ==/UserScript==
console.log("MSS 1.1 STARTED");
debugger;

// Function to create a button to clear the JSON local saved cache
function createClearCacheButton() {
    console.log("createClearCacheButton function is called");
    var clearCacheButton = document.createElement("button");

    // Set the inner text with a smaller font size
    clearCacheButton.innerText = "Clear Cache/Refresh";
    clearCacheButton.style.fontSize = "12px"; // Adjust the font size as needed

    clearCacheButton.style.position = "fixed";
    clearCacheButton.style.top = "50px";
    clearCacheButton.style.left = "10px";
    clearCacheButton.addEventListener("click", function () {
        // Clear the JSON local saved cache
        localStorage.removeItem('blocked_uuids');
        // Reload the page to apply changes
        location.reload();
    });

    document.body.appendChild(clearCacheButton);
}

// Call the function to create the clear cache button
createClearCacheButton();

// Function to create a button to collapse the view
function createCollapseButton() {
    console.log("createCollapseButton function is called");
    var collapseButton = document.createElement("button");

    // Set the inner HTML with an SVG and additional text
    collapseButton.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="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"/>
        </svg> Collapse View`;

    // Adjust the font size of the text
    collapseButton.style.fontSize = "12px"; // Adjust the font size as needed

    collapseButton.style.position = "fixed";
    collapseButton.style.top = "90px";
    collapseButton.style.left = "10px";
    collapseButton.addEventListener("click", function () {
        // Toggle visibility of the chatbox
        var chatbox = document.querySelector('.chatbox');
        chatbox.style.display = (chatbox.style.display === 'none' || chatbox.style.display === '') ? 'block' : 'none';
    });

    document.body.appendChild(collapseButton);
}

// Call the function to create the collapse button
createCollapseButton();

var blocked_uuids = JSON.parse(localStorage.getItem('blocked_uuids')) || [];

function getNickname(fcuserSpan) {
    if (!fcuserSpan) return;

    // Check if fcuserSpan is a direct child of p
    var isDirectChild = fcuserSpan.parentNode.nodeName === "P";
    var nickname;

    if (isDirectChild) {
        nickname = fcuserSpan.innerText.replace(/[:\-]/g, '').trim();
    } else {
        // If not a direct child, assume it's under an anchor tag (a) in the user list
        nickname = fcuserSpan.parentNode.querySelector('.fcuser').innerText.replace(/[:\-]/g, '').trim();
    }

    return nickname;
}

// Function to handle the new chat messages
function handleNewChatMessages() {
    var chatboxElems = document.querySelector('.chatbox').getElementsByTagName('p');
    for (var i = 0; i < chatboxElems.length; i++) {
        var chatElem = chatboxElems[i];
        if (!chatElem.handled) {
            chatElem.handled = true;
            var fcuserSpan = chatElem.querySelector('.nm.fcuser');
            var uuid = fcuserSpan ? fcuserSpan.dataset.uuid : null;
            if (blocked_uuids.includes(uuid)) {
                chatElem.style.display = 'none'; // hide the message
            }
        }
    }
}

// Call the handleNewChatMessages function on page load and whenever the chatbox is updated
handleNewChatMessages();
document.querySelector('.chatbox').addEventListener('DOMNodeInserted', handleNewChatMessages);


// Get the chatbox element
var chatbox = document.querySelector(".chatbox");

// Create a mutation observer to monitor changes in the chatbox
var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        mutation.addedNodes.forEach(function(node) {
            // Check if the node is a chat message
            if (node.nodeName === "P" && node.dataset.t === "c") {
                // Get the uuid of the user who sent the message
                var uuidElement = node.querySelector(".nm.fcuser");
                if (uuidElement) {
                    var uuid = uuidElement.dataset.uuid;
                    console.log("Found message with UUID:", uuid);

                    // Check if the uuid is in the blocked list
                    if (blocked_uuids.includes(uuid)) {
                        console.log("Blocking message with UUID:", uuid);
                        // Hide the message
                        node.style.display = "none";
                    }
                } else {
                    console.log("Could not find UUID element in message:", node);
                }
            }
        });
    });
});

// Start observing the chatbox
observer.observe(chatbox, { childList: true });

// Function to show a notification
function showNotification(message) {
    var notification = document.createElement("div");
    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>`;
    document.body.appendChild(notification);

    // Set a timeout to fade out the notification
    setTimeout(function () {
        notification.style.opacity = 0;
    }, 2000); // Adjust the timeout value as needed

    // Remove the notification from the DOM after fading out
    setTimeout(function () {
        document.body.removeChild(notification);
    }, 3000); // Adjust the timeout value to match the fade-out duration
}

// Function to block/unblock a user
function blockUser(uuid) {
    console.log("blockUser function is called");
    var index = blocked_uuids.indexOf(uuid);
    if (index !== -1) {
        // User is already blocked, so unblock
        blocked_uuids.splice(index, 1);
        showNotification("User unblocked!");
    } else {
        // User is not blocked, so block
        blocked_uuids.push(uuid);
        showNotification("User blocked!");
    }

    // Save the updated blocked_uuids to localStorage
    localStorage.setItem('blocked_uuids', JSON.stringify(blocked_uuids));
}

// Function to create a button to view the ignore list
function createIgnoreListButton() {
    console.log("createIgnoreListButton function is called");
    var ignoreListButton = document.createElement("button");
    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`;
    ignoreListButton.style.position = "fixed";
    ignoreListButton.style.top = "10px";
    ignoreListButton.style.left = "10px";
    ignoreListButton.addEventListener("click", function () {
        // Display the ignore list (you can customize this part)
        alert("Ignore List:\n" + blocked_uuids.join(", "));
    });

    document.body.appendChild(ignoreListButton);
}

// Call the function to create the ignore list button
createIgnoreListButton();


// Get the user list element
var userlist = document.querySelector(".userlist");

// Create the block and ignore buttons and append them to each user
var users = userlist.querySelectorAll(".fcuser");
users.forEach(function (user) {
    var uuid = user.dataset.uuid;

    // Create the block button
    var blockButton = document.createElement("button");
    blockButton.innerText = "Block";
    blockButton.addEventListener("click", function() {
        blockUser(uuid);
    });

    // Create the ignore button with a unique class
    var ignoreButton = document.createElement("button");
    ignoreButton.innerText = "Ignore";
    ignoreButton.setAttribute("data-btntype", "ignore"); // Set a new attribute for identification
    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>`;
    ignoreButton.style.marginLeft = "5px";
    ignoreButton.style.cursor = "pointer";
    // Add a unique class to the ignore button
    ignoreButton.classList.add("ignoreButtonClass");

    ignoreButton.addEventListener("click", function () {
        // Dynamically fetch the user UUID when the "Ignore" button is clicked
        var clickedUserUUID = user.dataset.uuid;
        blockUser(clickedUserUUID);
    });

    // Create a container div for the buttons
    var buttonContainer = document.createElement("div");
    buttonContainer.style.display = "flex";
    buttonContainer.style.alignItems = "center";

    // Append the buttons to the container
    buttonContainer.appendChild(blockButton);
    buttonContainer.appendChild(ignoreButton);

    // Append the container to the user element
    user.parentElement.appendChild(buttonContainer);
});

// usermenu block button event listener:
document.querySelector('.usermenu button[data-btntype="block"]').addEventListener('click', function() {
    console.log("User menu block button clicked");

    // Get the parent element of the button, assuming it contains user-related data
    var userContainer = this.closest('.user-container');

    // Assuming the user UUID is stored in a data attribute called data-uuid
    var userUUID = userContainer ? userContainer.dataset.uuid : null;

    // Check if userUUID is not null before blocking
    if (userUUID) {
        // Now you have the user UUID, and you can proceed to block the user
        blockUser(userUUID);
    } else {
        console.error("User UUID not found. Unable to block user.");
    }
});

// Function to create an ignore button in the user menu
function createIgnoreButton(username, uuid) {
    console.log("createIgnoreButton function is called");

    var ignoreButton = document.createElement("button");
    ignoreButton.innerText = "Ignore";
    ignoreButton.setAttribute("data-btntype", "ignore"); // Set a new attribute for identification
    ignoreButton.style.display = "block";
    ignoreButton.style.marginTop = "5px"; // Adjust the styling as needed


    // Insert the ignore button into the user menu
    var userMenu = document.querySelector('.usermenu');
    if (userMenu) {
        userMenu.insertBefore(ignoreButton, userMenu.firstChild);


        // Add click event directly to the button
        ignoreButton.addEventListener("click", function () {
            // Log to console to check if the button click is being registered
            console.log("Ignore button clicked");

            // Traverse the DOM to find the user UUID dynamically within FreeChat context
            var userUUID = getUserUUIDFromUserList();

            // Check if the user UUID is found
            if (userUUID) {
                blockUser(userUUID, username);
            } else {
                console.error("User UUID not found. Ignoring user without blocking.");
            }
        });
    } else {
        console.error("User menu not found.");
    }
}

// Function to get the user UUID from the user list within FreeChat context
function getUserUUIDFromUserList() {
    var userContainer = document.querySelector("#chat > div.fc > div.gridbox_list > div.userlist p.user.fcuser[data-uuid]");

    if (userContainer) {
        return userContainer.dataset.uuid;
    } else {
        // If user container is not found, set up a MutationObserver to wait for changes
        var observer = new MutationObserver(function (mutations) {
            userContainer = document.querySelector("#chat > div.fc > div.gridbox_list > div.userlist p.user.fcuser[data-uuid]");
            if (userContainer) {
                console.log("User container found after mutation.");
                console.log("User UUID: ", userContainer.dataset.uuid);
                // Stop observing once the user container is found
                observer.disconnect();
            }
        });

        // Start observing changes in the user list
        observer.observe(document.querySelector("#chat > div.fc > div.gridbox_list > div.userlist"), { childList: true, subtree: true });

        console.error("User container not found in the user list within FreeChat context. Waiting for mutations...");
        return null;
    }
}

// Call the function to create the ignore button in the user menu
createIgnoreButton();

// Create the ignore list div once and append the content dynamically
var ignoreListDiv = document.createElement("div");
ignoreListDiv.style.position = "fixed";
ignoreListDiv.style.bottom = "10px"; // Move to the bottom
ignoreListDiv.style.left = "10px";
ignoreListDiv.style.backgroundColor = "white"; // Adjust styling as needed
ignoreListDiv.style.padding = "10px";
ignoreListDiv.style.border = "1px solid black"; // Add border for visibility
ignoreListDiv.style.fontSize = "12px"; // Set font size to 12px


// Create a heading for the ignore list
var ignoreListHeading = document.createElement("h3");
ignoreListHeading.innerText = "Ignore List";
ignoreListDiv.appendChild(ignoreListHeading);

// Create a list to display ignored users
var ignoreList = document.createElement("ul");
ignoreList.style.listStyleType = "none"; // Remove default list styling
ignoreListDiv.appendChild(ignoreList);

// Append the ignore list div to the body
document.body.appendChild(ignoreListDiv);

// Function to create a list item with the ignore list entry and remove button
function createIgnoreListItem(uuid, username) {
    var listItem = document.createElement("li");
    listItem.innerText = `${username} (${uuid})`;

    // Create a remove button for each entry
    var removeButton = document.createElement("button");
    removeButton.innerText = "Remove";
    removeButton.addEventListener("click", function () {
        // Remove the entry when the button is clicked
        removeIgnoreEntry(uuid);
    });

    // Append the remove button to the list item
    listItem.appendChild(removeButton);

    // Append the list item to the ignore list
    ignoreList.appendChild(listItem);
}


// Function to refresh the ignore list display
function refreshIgnoreList() {
    // Clear the existing content
    ignoreList.innerHTML = "";

    // Populate the ignore list with entries and remove buttons
    blocked_uuids.forEach(function (uuid) {
        createIgnoreListItem(uuid);
    });
}

// Populate the ignore list with entries and remove buttons
blocked_uuids.forEach(function (uuid) {
    createIgnoreListItem(uuid);
});

// Function to handle removing an entry from the ignore list
function removeIgnoreEntry(uuid) {
    var index = blocked_uuids.indexOf(uuid);
    if (index !== -1) {
        // Remove the entry from the ignore list
        blocked_uuids.splice(index, 1);
        // Refresh the ignore list display after removal
        refreshIgnoreList();
    }
}


// Function to save blocked_uuids to a text file
function saveToTextFile() {
    var textToSave = blocked_uuids.join('\n');
    var blob = new Blob([textToSave], { type: 'text/plain' });
    var link = document.createElement('a');
    link.download = 'ignore_list.txt';
    link.href = window.URL.createObjectURL(blob);
    link.onclick = function () {
        document.body.removeChild(link);
    };
    link.style.display = 'none';
    document.body.appendChild(link);
    link.click();
}

// Function to load blocked_uuids from a text file
function loadFromTextFile() {
    var input = document.createElement('input');
    input.type = 'file';
    input.accept = '.txt';
    input.onchange = function (event) {
        var file = event.target.files[0];
        if (file) {
            var reader = new FileReader();
            reader.onload = function (e) {
                // Parse the content of the file and update blocked_uuids
                blocked_uuids = e.target.result.split('\n').map(function (uuid) {
                    return uuid.trim();
                });
                // Update the ignore list display
                refreshIgnoreList();
            };
            reader.readAsText(file);
        }
    };
    input.click();
}

// Function to create a button to save and load ignore list
function createSaveLoadButtons() {
    var saveButton = document.createElement("button");
    saveButton.innerText = "Save to Text File";
    saveButton.addEventListener("click", function () {
        saveToTextFile();
    });

    var loadButton = document.createElement("button");
    loadButton.innerText = "Load from Text File";
    loadButton.addEventListener("click", function () {
        loadFromTextFile();
    });

    var buttonContainer = document.createElement("div");
    buttonContainer.style.marginTop = "10px";
    buttonContainer.appendChild(saveButton);
    buttonContainer.appendChild(loadButton);

    // Append the button container to the ignore list div
    ignoreListDiv.appendChild(buttonContainer);
}

// Call the function to create the save and load buttons
createSaveLoadButtons();