Addon + for Bodega Bot

Adds functionality to Bodega Bot Users

目前為 2024-08-10 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Addon + for Bodega Bot
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Adds functionality to Bodega Bot Users
// @author       Bort
// @license
// @icon         https://media1.giphy.com/avatars/FeedMe1219/aBrdzB77IQ5c.gif
// @match        https://tinychat.com/room/*
// @match        https://tinychat.com/*
// @exclude      https://tinychat.com/settings/*
// @exclude      https://tinychat.com/subscription/*
// @exclude      https://tinychat.com/promote/*
// @exclude      https://tinychat.com/coins/*
// @exclude      https://tinychat.com/gifts*
// @grant        GM_setClipboard
// @require      https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
// ==/UserScript==

(function() {
    'use strict';

    // Create container for the floating button
    const container = document.createElement('div');
    container.style.position = 'fixed';
    container.style.width = '100%';
    container.style.height = '100%';
    container.style.top = '0';
    container.style.left = '0';
    container.style.zIndex = '9999';
    container.style.pointerEvents = 'none';
    document.body.appendChild(container);

    // Create main floating button
    const mainButton = document.createElement('button');
    mainButton.className = 'floating-button';
    mainButton.innerText = '⚙️';
    mainButton.title = 'Open Settings';
    mainButton.style.position = 'fixed';
    mainButton.style.bottom = '20px';
    mainButton.style.left = '20px';
    mainButton.style.width = '40px';
    mainButton.style.height = '40px';
    mainButton.style.backgroundColor = 'rgb(0 0 0 / 20%)';
    mainButton.style.color = 'white';
    mainButton.style.border = 'none';
    mainButton.style.borderRadius = '50%';
    mainButton.style.cursor = 'pointer';
    mainButton.style.transition = 'all 0.3s';
    mainButton.style.zIndex = '10000';
    mainButton.style.fontSize = '20px';
    mainButton.style.display = 'flex';
    mainButton.style.alignItems = 'center';
    mainButton.style.justifyContent = 'center';
    mainButton.style.pointerEvents = 'auto';
    container.appendChild(mainButton);

    // Create container for additional buttons
    const additionalButtons = document.createElement('div');
    additionalButtons.className = 'additional-buttons';
    additionalButtons.style.display = 'none';
    additionalButtons.style.flexDirection = 'column';
    additionalButtons.style.position = 'fixed';
    additionalButtons.style.left = '20px';
    additionalButtons.style.bottom = '70px';
    additionalButtons.style.zIndex = '10001';
    additionalButtons.style.pointerEvents = 'auto';
    container.appendChild(additionalButtons);

    // Array of additional button configurations
    const buttonConfigs = [
        { label: '📷', action: takeScreenshot, title: 'Take Screenshot' },
        { label: '📺', action: toggleGroupTube, title: 'Toggle GroupTube' },
        { label: '🔍+', action: () => resizeGroupTube(1.1), title: 'Increase GroupTube Size' },
        { label: '🔍-', action: () => resizeGroupTube(0.9), title: 'Decrease GroupTube Size' },
        { label: '🔄', action: reloadGroupTube, title: 'Reload GroupTube' },
        { label: '📝', action: showCommands, title: 'Show Commands' }
    ];

    // Create additional buttons
    buttonConfigs.forEach(config => {
        const button = document.createElement('button');
        button.className = 'additional-button';
        button.innerText = config.label;
        button.title = config.title;
        button.style.backgroundColor = 'rgb(0 0 0 / 20%)';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.margin = '5px';
        button.style.padding = '10px';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';
        button.style.transition = 'all 0.3s';
        button.style.width = '40px';
        button.style.height = '40px';
        button.style.fontSize = '16px';
        button.style.display = 'flex';
        button.style.alignItems = 'center';
        button.style.justifyContent = 'center';
        additionalButtons.appendChild(button);

        // Add click event listener
        button.addEventListener('click', () => {
            config.action();

            // Provide visual feedback
            const originalColor = button.style.backgroundColor;
            button.style.backgroundColor = 'rgb(0 0 0 / 20%)';
            setTimeout(() => {
                button.style.backgroundColor = originalColor;
            }, 200);
        });

        // Hover effect for additional buttons
        button.addEventListener('mouseover', () => {
            button.style.backgroundColor = 'rgb(0 0 0 / 30%)';
        });
        button.addEventListener('mouseout', () => {
            button.style.backgroundColor = 'rgb(0 0 0 / 20%)';
        });
    });

    // Toggle additional buttons display on main button click
    mainButton.addEventListener('click', function() {
        const isExpanded = additionalButtons.style.display === 'flex';
        additionalButtons.style.display = isExpanded ? 'none' : 'flex';
        mainButton.style.transform = isExpanded ? 'rotate(0deg)' : 'rotate(180deg)';
    });

    // Allow dragging of the main button
    let isDraggingMain = false;
    let mainOffsetX, mainOffsetY;

    mainButton.addEventListener('mousedown', (e) => {
        isDraggingMain = true;
        mainOffsetX = e.clientX - mainButton.getBoundingClientRect().left;
        mainOffsetY = e.clientY - mainButton.getBoundingClientRect().top;
    });

    document.addEventListener('mousemove', (e) => {
        if (isDraggingMain) {
            const x = e.clientX - mainOffsetX;
            const y = e.clientY - mainOffsetY;

            // Confine within viewport
            const maxX = window.innerWidth - mainButton.offsetWidth;
            const maxY = window.innerHeight - mainButton.offsetHeight;

            mainButton.style.left = Math.max(0, Math.min(x, maxX)) + 'px';
            mainButton.style.bottom = Math.max(0, Math.min(window.innerHeight - y - mainButton.offsetHeight, maxY)) + 'px';

            // Move additional buttons along with the main button
            additionalButtons.style.left = mainButton.style.left;
            additionalButtons.style.bottom = (parseInt(mainButton.style.bottom) + mainButton.offsetHeight + 10) + 'px';
        }
    });

    document.addEventListener('mouseup', () => {
        isDraggingMain = false;
    });

    // Screenshot functionality
    function takeScreenshot() {
        html2canvas(document.body).then(canvas => {
            const link = document.createElement('a');
            link.download = 'screenshot.png';
            link.href = canvas.toDataURL();
            link.click();

            // Provide user feedback
            alerat('Screenshot saved!');
        });
    }

    // GroupTube functionality
    let groupTubeWindow = null;
    let isDragging = false;

    function toggleGroupTube() {
        if (groupTubeWindow) {
            groupTubeWindow.style.display = groupTubeWindow.style.display === 'none' ? 'block' : 'none';
            // Provide user feedback
            const status = groupTubeWindow.style.display === 'none' ? 'hidden' : 'visible';
            const feedbackButton = Array.from(additionalButtons.children).find(button => button.title === 'Toggle GroupTube');
            if (feedbackButton) {
                feedbackButton.title = `GroupTube is now ${status}`;
            }
            return;
        }

        groupTubeWindow = document.createElement('div');
        groupTubeWindow.style.position = 'fixed';
        groupTubeWindow.style.top = '10%';
        groupTubeWindow.style.left = '10%';
        groupTubeWindow.style.width = '80%';
        groupTubeWindow.style.height = '80%';
        groupTubeWindow.style.backgroundColor = '#222';
        groupTubeWindow.style.border = '2px solid rgb(0 0 0 / 20%)';
        groupTubeWindow.style.borderRadius = '10px';
        groupTubeWindow.style.zIndex = '10002';
        groupTubeWindow.style.overflow = 'hidden';
        groupTubeWindow.style.pointerEvents = 'auto';

        const iframe = document.createElement('iframe');
        iframe.src = 'https://group.tube/group/70d02ed5-df92-424b-bdcd-d0c60f8ad574?join';
        iframe.style.width = '100%';
        iframe.style.height = 'calc(100% - 30px)';
        iframe.style.border = 'none';
        iframe.style.pointerEvents = 'auto';
        groupTubeWindow.appendChild(iframe);

        const closeButton = document.createElement('button');
        closeButton.innerText = 'X';
        closeButton.style.position = 'absolute';
        closeButton.style.top = '1px';
        closeButton.style.right = '1px';
        closeButton.style.backgroundColor = 'rgb(0 0 0 / 20%)';
        closeButton.style.border = 'none';
        closeButton.style.color = '#fff';
        closeButton.style.fontSize = '1px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.padding = '1px 1px';
        closeButton.style.borderRadius = '1px';
        closeButton.onclick = () => groupTubeWindow.style.display = 'none';
        groupTubeWindow.appendChild(closeButton);

        container.appendChild(groupTubeWindow);

        // Add drag functionality to GroupTube window
        const dragHandle = document.createElement('div');
        dragHandle.style.position = 'absolute';
        dragHandle.style.top = '0';
        dragHandle.style.left = '0';
        dragHandle.style.width = '100%';
        dragHandle.style.height = '12px';
        dragHandle.style.cursor = 'move';
        groupTubeWindow.appendChild(dragHandle);

        dragHandle.addEventListener('mousedown', initDrag, false);
        window.addEventListener('mousemove', doDrag, false);
        window.addEventListener('mouseup', stopDrag, false);

        let startX, startY;

        function initDrag(e) {
            startX = e.clientX - groupTubeWindow.offsetLeft;
            startY = e.clientY - groupTubeWindow.offsetTop;
            isDragging = true;
        }

        function doDrag(e) {
            if (isDragging) {
                groupTubeWindow.style.left = (e.clientX - startX) + 'px';
                groupTubeWindow.style.top = (e.clientY - startY) + 'px';
            }
        }

        function stopDrag() {
            isDragging = false;
        }
    }

    function resizeGroupTube(factor) {
        if (groupTubeWindow) {
            const currentWidth = groupTubeWindow.offsetWidth;
            const currentHeight = groupTubeWindow.offsetHeight;
            groupTubeWindow.style.width = (currentWidth * factor) + 'px';
            groupTubeWindow.style.height = (currentHeight * factor) + 'px';
        }
    }

    function reloadGroupTube() {
        if (groupTubeWindow) {
            const iframe = groupTubeWindow.querySelector('iframe');
            if (iframe) {
                iframe.src = iframe.src;
            }
        }
    }

    // Command functionality
    const commands = {
        'Owner Commands': [
          "!raid tc link",
          "!camsweep 5 - 30",
          "!closeall",
          "!kickall",
          "!version",
          "!whoisbot",
          "!bot",
          "!autokick (be careful!)",
          "!autoban (be careful!)"
        ],
        'Main Toggles': [
          "!greenroomtoggle",
          "!publiccommandtoggle",
          "!bottoggle",
          "!votetoggle",
          "!greetmodetoggle",
          "!imgurtoggle",
          "!raidtoggle",
          "!avatartoggle",
          "!notificationtoggle",
          "!popuptoggle",
          "!soundmetertoggle",
          "!timestamptoggle",
          "!remindertoggle"
        ],
        'User Management': [
          "!autokick (be careful!)",
          "!autoban (be careful!)",
          "!userban user",
          "!nickban nick",
          "!userkick user",
          "!nickkick nick",
          "!userclose user",
          "!nickclose nick"
        ],
        'Green Room': [
          "!greenroomlist",
          "!greenroomlistclear",
          "!greenroomadd user",
          "!greenroomremove #",
          "!greenroomignorelist",
          "!greenroomignorelistclear",
          "!greenroomignoreadd user",
          "!greenroomignoreremove #"
        ],
        'YouTube Controls': [
          "!ytapi apikey",
          "!ytbypass link (no playlists)",
          "!yt link | keyword",
          "!ytskip",
          "!ytclear",
          "!ytlink",
          "!ytkeyword",
          "!ytqueue"
        ],
        'Ban Management': [
          "!userbanlist",
          "!userbanlistclear",
          "!userbanadd user",
          "!userbanremove #",
          "!nickbanlist",
          "!nickbanlistclear",
          "!nickbanadd nick",
          "!nickbanremove #",
          "!bankeywordlist",
          "!bankeywordlistclear",
          "!bankeywordadd keyword | phrase",
          "!bankeywordremove #"
        ],
        'Kick Management': [
          "!userkicklist",
          "!userkicklistclear",
          "!userkickadd user",
          "!userkickremove #",
          "!nickkicklist",
          "!nickkicklistclear",
          "!nickkickadd nick",
          "!nickkickremove #",
          "!kickkeywordlist",
          "!kickkeywordlistclear",
          "!kickkeywordadd keyword | phrase",
          "!kickkeywordremove #"
        ],
        'Operator Management': [
          "!oplist",
          "!oplistclear",
          "!opadd user | -all",
          "!opremove #",
          "!optoggle"
        ],
        'Moderator Management': [
          "!modlist",
          "!modlistclear",
          "!modadd user",
          "!modremove #"
        ],
        'Jr. Moderator Commands': [
          "!userban user",
          "!nickban nick",
          "!userkick user",
          "!nickkick nick",
          "!userclose user",
          "!nickclose nick"
        ],
        'List Management': [
          "!lists",
          "!listsclear",
          "!userlist",
          "!mentionlist",
          "!mentionlistclear",
          "!mentionadd keyword",
          "!mentionremove #",
          "!ignorelist",
          "!ignorelistclear",
          "!ignoreadd user",
          "!ignoreremove #",
          "!hiddencameralist",
          "!hiddencameralistclear",
          "!hiddencameraadd user",
          "!hiddencameraremove #",
          "!greetlist",
          "!greetlistclear",
          "!greetadd user | -all",
          "!greetremove #",
          "!ttslist",
          "!ttslistclear",
          "!ttsadd user | -all | -event",
          "!ttsremove #",
          "!highlightlist",
          "!highlightlistclear",
          "!highlightadd user",
          "!highlightremove #",
          "!reminderlist",
          "!reminderlistclear",
          "!reminderadd user",
          "!reminderremove #",
          "!safelist",
          "!safelistclear",
          "!safeadd user",
          "!saferemove #"
        ],
        'Settings and Utilities': [
          "!fps 1 - 60",
          "!clr",
          "!clrall",
          "!settings",
          "!share"
        ],
        'Fun Commands': [
          "!coin",
          "!advice",
          "!8ball question",
          "!roll #",
          "!chuck",
          "!dad",
          "!vote user"
        ],
        'Trivia Game': [
          "!gameview",
          "!trivia",
          "!triviahelp",
          "!triviahost",
          "!triviaskip",
          "!triviaend",
          "!triviascore",
          "!triviaplayerlist",
          "!triviaplayerlistclear",
          "!triviaadd question answer",
          "!triviaremove #",
          "!triviaplayeradd player",
          "!triviaplayerremove player"
        ],
        'Fish Game': [
          "!gameview",
          "!fish",
          "!fishhelp",
          "!fishhost",
          "!fishupgrade",
          "!fishstop",
          "!fishstats",
          "!fishinventory",
          "!fishequip bait | rod",
          "!fishevent",
          "!fishleaderboard"
        ]
    };

    let commandWindow = null;

    function showCommands() {
        if (commandWindow) {
            commandWindow.style.display = commandWindow.style.display === 'none' ? 'block' : 'none';
            return;
        }

        commandWindow = document.createElement('div');
        commandWindow.style.position = 'fixed';
        commandWindow.style.top = '50%';
        commandWindow.style.left = '50%';
        commandWindow.style.transform = 'translate(-50%, -50%)';
        commandWindow.style.width = '90%';
        commandWindow.style.height = '80%';
        commandWindow.style.maxWidth = '800px';
        commandWindow.style.maxHeight = '600px';
        commandWindow.style.overflowY = 'auto';
        commandWindow.style.backgroundColor = 'rgba(34, 34, 34, 0.9)';
        commandWindow.style.color = '#fff';
        commandWindow.style.padding = '20px';
        commandWindow.style.borderRadius = '10px';
        commandWindow.style.zIndex = '10002';
        commandWindow.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
        commandWindow.style.pointerEvents = 'auto';

        // Add custom scrollbar styles
        commandWindow.style.scrollbarWidth = 'thin';
        commandWindow.style.scrollbarColor = 'rgba(85, 85, 85, 0.5) rgba(34, 34, 34, 0.3)';

        // For Webkit browsers (Chrome, Safari)
        const styleElement = document.createElement('style');
        styleElement.textContent = `
            #commandWindow::-webkit-scrollbar {
                width: 8px;
            }
            #commandWindow::-webkit-scrollbar-track {
                background: rgba(34, 34, 34, 0.3);
            }
            #commandWindow::-webkit-scrollbar-thumb {
                background-color: rgba(85, 85, 85, 0.5);
                border-radius: 4px;
            }
        `;
        document.head.appendChild(styleElement);
        commandWindow.id = 'commandWindow';

        const closeButton = document.createElement('button');
        closeButton.innerText = 'X';
        closeButton.style.position = 'absolute';
        closeButton.style.top = '10px';
        closeButton.style.right = '10px';
        closeButton.style.backgroundColor = 'transparent';
        closeButton.style.border = 'none';
        closeButton.style.color = '#fff';
        closeButton.style.fontSize = '20px';
        closeButton.style.cursor = 'pointer';
        closeButton.onclick = () => commandWindow.style.display = 'none';
        commandWindow.appendChild(closeButton);

        for (const [category, categoryCommands] of Object.entries(commands)) {
            const categoryTitle = document.createElement('h3');
            categoryTitle.innerText = category;
            categoryTitle.style.marginTop = '20px';
            categoryTitle.style.marginBottom = '10px';
            categoryTitle.style.fontSize = '18px';
            categoryTitle.style.color = '#007bff';
            commandWindow.appendChild(categoryTitle);

            categoryCommands.forEach(command => {
                const commandButton = document.createElement('button');
                commandButton.innerText = command;
                commandButton.style.display = 'block';
                commandButton.style.width = '100%';
                commandButton.style.padding = '10px';
                commandButton.style.marginBottom = '5px';
                commandButton.style.backgroundColor = 'rgba(68, 68, 68, 0.8)';
                commandButton.style.border = 'none';
                commandButton.style.color = '#fff';
                commandButton.style.textAlign = 'left';
                commandButton.style.cursor = 'pointer';
                commandButton.style.borderRadius = '5px';
                commandButton.style.transition = 'all 0.3s';
                commandButton.style.fontSize = '14px';

                commandButton.addEventListener('mouseover', () => {
                    commandButton.style.backgroundColor = 'rgba(85, 85, 85, 0.8)';
                });

                commandButton.addEventListener('mouseout', () => {
                    commandButton.style.backgroundColor = 'rgba(68, 68, 68, 0.8)';
                });

                commandButton.onclick = () => {
                    GM_setClipboard(command);
                    commandButton.style.backgroundColor = 'rgba(0, 123, 255, 0.8)';
                    commandButton.innerText = 'Copied!';
                    setTimeout(() => {
                        commandButton.style.backgroundColor = 'rgba(68, 68, 68, 0.8)';
                        commandButton.innerText = command;
                    }, 1000);
                };

                commandWindow.appendChild(commandButton);
            });
        }

        container.appendChild(commandWindow);

        // Make command window draggable
        let isDraggingCmd = false;
        let cmdStartX, cmdStartY;

        const cmdDragHandle = document.createElement('div');
        cmdDragHandle.style.position = 'absolute';
        cmdDragHandle.style.top = '0';
        cmdDragHandle.style.left = '0';
        cmdDragHandle.style.width = '100%';
        cmdDragHandle.style.height = '30px';
        cmdDragHandle.style.cursor = 'move';
        cmdDragHandle.style.backgroundColor = 'rgb(0 0 0 / 20%)';
        commandWindow.insertBefore(cmdDragHandle, commandWindow.firstChild);

        cmdDragHandle.addEventListener('mousedown', initCmdDrag, false);
        window.addEventListener('mousemove', doCmdDrag, false);
        window.addEventListener('mouseup', stopCmdDrag, false);

        function initCmdDrag(e) {
            isDraggingCmd = true;
            cmdStartX = e.clientX - commandWindow.offsetLeft;
            cmdStartY = e.clientY - commandWindow.offsetTop;
        }

        function doCmdDrag(e) {
            if (!isDraggingCmd) return;

            let newX = e.clientX - cmdStartX;
            let newY = e.clientY - cmdStartY;

            // Confine the window within the viewport
            const rect = commandWindow.getBoundingClientRect();
            newX = Math.max(0, Math.min(newX, window.innerWidth - rect.width));
            newY = Math.max(0, Math.min(newY, window.innerHeight - rect.height));

            commandWindow.style.left = newX + 'px';
            commandWindow.style.top = newY + 'px';
            commandWindow.style.transform = 'none';
        }

        function stopCmdDrag() {
            isDraggingCmd = false;
        }
    }

    // Ensure the window stays within bounds when the browser is resized
    window.addEventListener('resize', adjustCommandWindowPosition);
    function adjustCommandWindowPosition() {
        if (commandWindow) {
            const rect = commandWindow.getBoundingClientRect();
            let newX = rect.left;
            let newY = rect.top;

            if (rect.right > window.innerWidth) {
                newX = window.innerWidth - rect.width;
            }
            if (rect.bottom > window.innerHeight) {
                newY = window.innerHeight - rect.height;
            }

            newX = Math.max(0, newX);
            newY = Math.max(0, newY);

            commandWindow.style.left = newX + 'px';
            commandWindow.style.top = newY + 'px';
        }
    }

})();