StumbleTube

Play youtube videos from the chat box on StumbleChat

当前为 2025-02-09 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         StumbleTube
// @namespace    StumbleTube
// @version      1.0
// @description  Play youtube videos from the chat box on StumbleChat
// @author       Goji
// @match        https://stumblechat.com/room/*
// ==/UserScript==

(function () {
    // Save the original WebSocket send method to allow overriding
    WebSocket.prototype._send = WebSocket.prototype.send;

    // Override the WebSocket send method to attach a custom message handler
    WebSocket.prototype.send = function (data) {
        this._send(data); // Call the original send method

        // Ensure the message handler is added only once per WebSocket instance
        if (!this._messageHandlerAdded) {
            this.addEventListener('message', handleMessage.bind(this), false);
            this._messageHandlerAdded = true;
        }
    };

    /**
     * Handles incoming WebSocket messages to process YouTube-related commands.
     * @param {MessageEvent} msg - The incoming WebSocket message.
     */
    function handleMessage(msg) {
        // Safely parse the incoming message data as JSON
        const wsmsg = safeJSONParse(msg.data);

        // If the message is not valid JSON, log an error and exit
        if (!wsmsg) {
            console.error('Invalid JSON message received:', msg.data);
            return;
        }

        // Define an array of keywords to detect YouTube-related commands
        var keywords = ['.youtube', '.video', '.play', '.yt'];

        /**
         * Converts various YouTube URL formats into a standard format.
         * @param {string} url - The YouTube URL to be converted.
         * @returns {string|null} - The standardized YouTube link or null if invalid.
         */
        function convertToRegularYouTubeLink(url) {
            // Regular expression to extract the video ID from different YouTube URL formats
            var videoIdRegex = /(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/|.*[?&]v=))([\w-]+)/;
            var match = url.match(videoIdRegex);

            // If a video ID is found, return the standardized link
            if (match && match[1]) {
                return 'https://www.youtube.com/watch?v=' + match[1];
            }

            // Return null if the URL does not match the expected formats
            return null;
        }

        // Loop through the defined keywords to check for a match in the message text
        for (var i = 0; i < keywords.length; i++) {
            // Check if the "text" property of the message starts with a keyword
            if (wsmsg['text'].startsWith(keywords[i])) {
                // Extract the query part of the message after the keyword
                var query = wsmsg['text'].substring(keywords[i].length).trim();

                // Ensure the query is not empty before proceeding
                if (query) {
                    // Attempt to convert the query into a standardized YouTube link
                    var regularLink = convertToRegularYouTubeLink(query);

                    // If the query is a valid YouTube link, send it in a formatted message
                    if (regularLink) {
                        this._send('{"stumble": "youtube","type": "add","id": "' + regularLink + '","time": 0}');
                    } else {
                        // For non-URL queries, treat them as search terms and send as is
                        this._send('{"stumble": "youtube","type": "add","id": "' + query + '","time": 0}');
                    }
                }

                // Exit the loop once the query has been processed
                break;
            }
        }
    }

    /**
     * Safely parses a JSON string, logging an error if parsing fails.
     * @param {string} jsonString - The JSON string to parse.
     * @returns {Object|null} - The parsed JSON object or null if parsing fails.
     */
    function safeJSONParse(jsonString) {
        try {
            return JSON.parse(jsonString);
        } catch (error) {
            console.error('Error parsing JSON:', error);
            return null;
        }
    }
})();