Rumble Unique Chatters and Number of Messages for Live Streams

Displays the number of unique chatters and messages in Rumble live streams.

当前为 2024-10-01 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Rumble Unique Chatters and Number of Messages for Live Streams
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Displays the number of unique chatters and messages in Rumble live streams.
// @match        https://rumble.com/*
// @grant        none
// @run-at       document-idle
// @license.     MIT
// ==/UserScript==

(function() {
    'use strict';

    /**
     * Utility function to wait for a specific element to appear in the DOM.
     * @param {string} selector - CSS selector of the target element.
     * @param {number} timeout - Maximum time to wait in milliseconds.
     * @returns {Promise<Element>} - Resolves with the found element or rejects on timeout.
     */
    function waitForElement(selector, timeout = 10000) {
        return new Promise((resolve, reject) => {
            const element = document.querySelector(selector);
            if (element) {
                return resolve(element);
            }

            const observer = new MutationObserver(() => {
                const elem = document.querySelector(selector);
                if (elem) {
                    observer.disconnect();
                    resolve(elem);
                }
            });

            observer.observe(document.body, { childList: true, subtree: true });

            // Timeout after specified milliseconds
            setTimeout(() => {
                observer.disconnect();
                reject(new Error(`Element ${selector} not found within ${timeout}ms`));
            }, timeout);
        });
    }

    async function init() {
        try {
            // Check if the live info element exists
            const liveInfoSelector = "div.video-header-live-info";
            try {
                const liveInfoElement = await waitForElement(liveInfoSelector, 5000);
                console.log("[Chat User Monitor] Live info element found:", liveInfoElement);
            } catch (error) {
                console.warn("[Chat User Monitor] Live info element not found within 5 seconds. Exiting script.");
                return; // Exit the script if the live info element is not found
            }

            // Wait for the chat box element to be available
            const chatBoxSelector = "#chat-history-list";
            const chatBox = await waitForElement(chatBoxSelector);
            console.log("[Chat User Monitor] Chat box found:", chatBox);

            // Wait for the chat controls container to append the user count display
            const chatControlsSelector = "form#chat-message-form > div.chat-message-form-section.chat-message-form-section-justify-between > div.chat--rant-row:nth-of-type(1)";
            const chatControlsContainer = await waitForElement(chatControlsSelector);
            console.log("[Chat User Monitor] Chat controls container found:", chatControlsContainer);

            // Initialize Sets to track unique users and messages
            const seenUsers = new Set();
            const seenMessages = new Set();

            // Create a container for displaying the user count with SVG
            const userCountDisplay = document.createElement("div");
            userCountDisplay.id = "user-count-container";
            userCountDisplay.classList.add("video-category-tag");
            userCountDisplay.title = "Number of unique users in the chat";

            // Insert the user SVG icon
            const userIconContainer = document.createElement("div");
            userIconContainer.innerHTML = `
                <svg width="20px" height="20px" viewBox="0 0 16 16" fill="currentColor">
                    <path d="M8 7C9.65685 7 11 5.65685 11 4C11 2.34315 9.65685 1 8 1C6.34315 1 5 2.34315 5 4C5 5.65685 6.34315 7 8 7Z"/>
                    <path d="M14 12C14 10.3431 12.6569 9 11 9H5C3.34315 9 2 10.3431 2 12V15H14V12Z"/>
                </svg>
            `;
            userIconContainer.style.marginRight = "8px";

            // Create the user count element
            const userCountElement = document.createElement("span");
            userCountElement.id = "seen-users-count";
            userCountElement.textContent = "0";
            userCountElement.style.fontSize = "12px";

            // Append SVG and user count to the container
            userCountDisplay.appendChild(userIconContainer);
            userCountDisplay.appendChild(userCountElement);

            // Append the container to the chat controls container
            chatControlsContainer.appendChild(userCountDisplay);
            console.log("[Chat User Monitor] User count display appended.");

            // Create a container for displaying the message count with SVG
            const messageCountDisplay = document.createElement("div");
            messageCountDisplay.id = "message-count-container";
            messageCountDisplay.style.display = "flex";
            messageCountDisplay.style.alignItems = "center";
            messageCountDisplay.style.marginLeft = "16px";
            messageCountDisplay.title = "Number of messages in the chat";

            // Insert the message SVG icon
            const messageIconContainer = document.createElement("div");
            messageIconContainer.innerHTML = `
                <svg width="20px" height="20px" viewBox="0 0 24 24" fill="currentColor">
                    <path d="M21.0039 12C21.0039 16.9706 16.9745 21 12.0039 21C9.9675 21 3.00463 21 3.00463 21C3.00463 21 4.56382 17.2561 3.93982 16.0008C3.34076 14.7956 3.00391 13.4372 3.00391 12C3.00391 7.02944 7.03334 3 12.0039 3C16.9745 3 21.0039 7.02944 21.0039 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
            `;
            messageIconContainer.style.marginRight = "8px";

            // Create the message count element
            const messageCountElement = document.createElement("span");
            messageCountElement.id = "seen-messages-count";
            messageCountElement.textContent = "0";
            messageCountElement.style.fontSize = "12px";

            // Append SVG and message count to the message container
            messageCountDisplay.appendChild(messageIconContainer);
            messageCountDisplay.appendChild(messageCountElement);

            // Append the message count container to the user count container
            userCountDisplay.appendChild(messageCountDisplay);
            console.log("[Chat User Monitor] Message count display appended.");

            /**
             * Updates the displayed counts of users and messages.
             */
            const updateCounts = () => {
                userCountElement.textContent = seenUsers.size;
                messageCountElement.textContent = seenMessages.size;
            };

            /**
             * Observes the chat box for new messages and users.
             */
            const observeChat = () => {
                const observer = new MutationObserver(mutations => {
                    mutations.forEach(mutation => {
                        mutation.addedNodes.forEach(node => {
                            if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('chat-history--row')) {
                                try {
                                    const messageId = node.getAttribute("data-message-id");
                                    const userId = node.getAttribute("data-message-user-id");

                                    // Track unique messages
                                    if (messageId && !seenMessages.has(messageId)) {
                                        seenMessages.add(messageId);
                                    }

                                    // Track unique users
                                    if (userId && !seenUsers.has(userId)) {
                                        seenUsers.add(userId);
                                        console.log(`[Chat User Monitor] New user ID added: ${userId}`);
                                    }

                                    // Update the displayed counts
                                    updateCounts();
                                } catch (error) {
                                    console.error("[Chat User Monitor] Error processing message:", error);
                                }
                            }
                        });
                    });
                });

                observer.observe(chatBox, { childList: true });
                console.log("[Chat User Monitor] Started observing chat box for new messages.");
            };

            // Start observing the chat
            observeChat();

        } catch (error) {
            console.error("[Chat User Monitor] Initialization failed:", error);
        }
    }

    // Start the initialization process
    init();

})();