Discord Message Logger

logs deleted discord messages

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name        Discord Message Logger
// @namespace   -
// @match         https://discordapp.com/activ*
// @match         https://discordapp.com/channel*
// @match         https://discord.com/activ*
// @match         https://discord.com/channel*
// @match         https://discord.com/channels/*
// @include       https://discord.com/*
// @grant         none
// @version       1.0
// @author        Koyd
// @description   logs deleted discord messages
// @run-at        document-start
// @compatible    chrome
// @compatible    firefox
// @compatible    opera
// @compatible    edge
// @compatible    safari
// @license       MIT
// ==/UserScript==

var allObservers = [];
var currentParent = null;

function disconnectAllObservers() {
    allObservers.forEach(function(observer) {
        observer.disconnect();
    });
    // Clear the array after disconnecting all observers
    allObservers = [];
}


function formatLoggedNode(node) {
    var text = "";

    var mediaContentNode = node.querySelector('.container_dbadf5');

    if (mediaContentNode) {
        // Convert all of it into plain text
        var mediaContentText = mediaContentNode.innerHTML;

        // Use regex to find links like 'https://cdn.discordapp.com/attachments*'
        var linkRegex = /https:\/\/cdn\.discordapp\.com\/attachments\/[^'"\s]*/g;
        var matches = mediaContentText.match(linkRegex);

        // Append the links to the text variable
        if (matches) {
            text += matches.join("\n");
        }

        // Delete the mediaContentNode from the main node
        mediaContentNode.remove();
    }

    var messageContentNode = node.querySelector('.contents_f41bb2')
    var textContentNode = messageContentNode.querySelector('.markup_a7e664.messageContent__21e69');
    textContentNode.style.color = 'red';

    var spanElement = textContentNode.querySelector('span');

    if (spanElement) {
        textContentNode.querySelector('span').innerHTML += "\n" + text;
    } else {
        // If span doesn't exist, create one and append text
        textContentNode.innerHTML = '<span>' + text + '</span>' + textContentNode.innerHTML;
    }

    return node;
};


function setupMutationObserver(parent) {
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.removedNodes.length > 0) {
                Array.from(mutation.removedNodes).forEach(function(node) {
                    if (node.classList && node.classList.contains('messageListItem__6a4fb')) {
                        // Check if the removed node has the specified class
                        var messageContentNode = node.querySelector('.contents_f41bb2')

                        var subTextNode = messageContentNode.querySelector('.markup_a7e664.messageContent__21e69');
                        
                         // Check if "isSending__6e109" class doesn't exist in the subnode
                        if (subTextNode && subTextNode.classList.contains('isSending__6e109')) {
                            return;
                        }

                        // Get the deleted message ID
                        var deletedIdMatch = node.id.match(/chat-messages-\d+-(\d+)/);
                        var deletedMessageId = deletedIdMatch ? parseInt(deletedIdMatch[1]) : null;

                        // Find the smallest index whose ID is greater than the deleted one
                        var minIndex = Array.from(parent.children).reduce(function(minIndex, child) {
                            var childIdMatch = child.id.match(/chat-messages-\d+-(\d+)/);
                            var childMessageId = childIdMatch ? parseInt(childIdMatch[1]) : null;

                            if (!isNaN(childMessageId) && childMessageId > deletedMessageId) {
                                return Math.min(minIndex, Array.from(parent.children).indexOf(child));
                            }

                            return minIndex;
                        }, Number.MAX_SAFE_INTEGER);

                        // Modify the node
                        node = formatLoggedNode(node);

                        // Append the modified node back to the parent at the calculated index
                        if (minIndex < Number.MAX_SAFE_INTEGER) {
                            parent.insertBefore(node, parent.children[minIndex]);
                        } else {
                            parent.insertBefore(node, parent.children[parent.children.length - 1]);
                        }
                    }
                });
            }
        });

      allObservers.push(observer)
    });


    // Configuration of the observer:
    var config = { childList: true };

    // Pass in the target node, as well as the observer options
    observer.observe(parent, config);
}

setInterval(function () {
    // Check if the URL is in the form https://discord.com/channels*
    if (!/^https:\/\/discord\.com\/channels/.test(window.location.href)) {
        // If not, disconnect observers and return
        disconnectAllObservers();
        currentParent = null;
        return;
    }

    var parent = document.querySelector('[data-list-id="chat-messages"]');

    if (!parent) {
        currentParent = null; // Set currentParent to null if the parent doesn't exist
        return;
    }

    if (parent !== currentParent) {
        // Disconnect observers only if the parent node has changed
        disconnectAllObservers();
        setupMutationObserver(parent);
        currentParent = parent; // Update the current parent
    }
}, 1000); // Check every 1000 milliseconds (1 second)