BotMenu Client Indev

Интерфейс для управления командами ботов с поддержкой категорий и сортировки

Verzia zo dňa 19.03.2025. Pozri najnovšiu verziu.

// ==UserScript==
// @name         BotMenu Client Indev
// @namespace    http://tampermonkey.net/
// @version      4.0
// @description  Интерфейс для управления командами ботов с поддержкой категорий и сортировки
// @author       gtnntg
// @match        *://multiplayerpiano.net/*
// @license      MIT
// @grant        none
// ==/UserScript==

/*global MPP*/
(function () {
    'use strict';

    const botsData = {}; // Хранение данных ботов { botId: { name, categories } }

    // Создаём контейнер для вкладок и кнопок
    const container = document.createElement('div');
    container.id = 'bot-menu';
    container.style.position = 'fixed';
    container.style.bottom = '20px';
    container.style.right = '10px';
    container.style.width = '300px';
    container.style.maxHeight = '500px';
    container.style.minHeight = '50px';
    container.style.backgroundColor = '#121212';
    container.style.color = '#fff';
    container.style.border = '1px solid #333';
    container.style.borderRadius = '8px';
    container.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.5)';
    container.style.padding = '10px';
    container.style.overflowY = 'auto';
    container.style.zIndex = '10000';
    container.style.display = 'block';
    document.body.appendChild(container);

    // Кнопка сворачивания
    const toggleButton = document.createElement('button');
    toggleButton.innerText = '⮝';
    toggleButton.style.alignSelf = 'flex-end';
    toggleButton.style.backgroundColor = '#333';
    toggleButton.style.color = '#fff';
    toggleButton.style.border = 'none';
    toggleButton.style.borderRadius = '4px';
    toggleButton.style.cursor = 'pointer';
    toggleButton.style.marginBottom = '10px';
    toggleButton.onclick = toggleContainer;
    container.appendChild(toggleButton);

    const QButton = document.createElement('button');
    QButton.innerText = 'Запросить команды';
    QButton.style.alignSelf = 'flex';
    QButton.style.backgroundColor = '#333';
    QButton.style.color = '#fff';
    QButton.style.border = 'none';
    QButton.style.borderRadius = '4px';
    QButton.style.marginLeft = '10px';
    QButton.style.cursor = 'pointer';
    QButton.style.marginBottom = '10px';
    QButton.onclick = Requestcommands;
    container.appendChild(QButton);

    const tabs = document.createElement('div'); // Контейнер для вкладок
    tabs.id = 'bot-tabs';
    tabs.style.display = 'flex';
    tabs.style.flexWrap = 'wrap';
    tabs.style.marginBottom = '10px';
    container.appendChild(tabs);

    const commandsContainer = document.createElement('div'); // Контейнер для кнопок команд
    commandsContainer.id = 'commands-container';
    commandsContainer.style.display = 'none';
    commandsContainer.style.padding = '10px';
    commandsContainer.style.borderTop = '1px solid #555';
    commandsContainer.style.marginTop = '10px';
    container.appendChild(commandsContainer);

    let isCollapsed = false;

    // Сворачивание/разворачивание контейнера
    function toggleContainer() {
        isCollapsed = !isCollapsed;
        if (isCollapsed) {
            tabs.style.display = 'none';
            commandsContainer.style.display = 'none';
            toggleButton.innerText = '⮟';
            container.style.maxHeight = '50px';
        } else {
            tabs.style.display = 'flex';
            toggleButton.innerText = '⮝';
            container.style.maxHeight = '500px';
        }
    }

    function Requestcommands(botId) {
      MPP.client.sendArray([{
          m: "custom",
          data: {
              m: "BotMenuClient",
              language: localStorage.getItem('language'),
              type: "Requestcommands"
          },
          target: { mode: "subscribed" },
      }]);
      sendmsg('Запрос на команды был отправлен всем ботам находящиеся в данной комнате','Bot Menu Client','Bot Menu Client','#0066ff')
    }

    function sendmsg(msg,name,id,color) {
      MPP.chat.receive({
                    "m": "a",
                    "t": Date.now(),
                    "a": msg,
                    "p": {
                        "_id": id,
                        "name": name,
                        "color": color,
                        "id": id
                    }
                });
    }

    // Функция для добавления новой вкладки
    function addTab(botId, botName) {
        const tab = document.createElement('button');
        tab.innerText = botName;
        tab.style.padding = '5px 10px';
        tab.style.margin = '5px 5px 0 0';
        tab.style.border = '1px solid #444';
        tab.style.borderRadius = '5px';
        tab.style.backgroundColor = '#2e2e2e';
        tab.style.color = '#fff';
        tab.style.cursor = 'pointer';
        tab.style.flex = '1 0 auto';
        tab.setAttribute('data-id', botId); // Присваиваем data-id для идентификации
        tab.onclick = () => showCommands(botId);
        tabs.appendChild(tab);
    }

    // Функция для отображения команд
    function showCommands(botId) {
    commandsContainer.innerHTML = ''; // Очищаем контейнер команд
    commandsContainer.style.display = 'block'; // Показываем контейнер

    const botData = botsData[botId];
    if (!botData) return; // Если данных нет, выходим

   /* const title = document.createElement('h3');
    title.innerText = `${botData.name}`;
    title.style.marginBottom = '10px';
    commandsContainer.appendChild(title);*/

    // Сортируем категории по позиции
    botData.categories.sort((a, b) => a.position - b.position);

    // Обрабатываем каждую категорию
    botData.categories.forEach((category) => {
        const categoryTitle = document.createElement('h4');
        categoryTitle.innerText = category.name; // Название категории
        categoryTitle.style.marginTop = '10px';
        categoryTitle.style.color = category.categoryColor ? category.categoryColor : '#aaa';
        commandsContainer.appendChild(categoryTitle);

        // Обрабатываем команды внутри категории
        category.commands.forEach((cmd) => {
            const commandBlock = document.createElement('div'); // Блок для команды
            commandBlock.style.display = 'flex';
            commandBlock.style.flexDirection = 'column';
            commandBlock.style.marginBottom = '10px';

            const btn = document.createElement('button'); // Кнопка команды
            btn.innerText = cmd.label;
            btn.title = cmd.description;
            btn.style.padding = '8px';
            btn.style.border = '1px solid #ccc';
            btn.style.borderRadius = '5px';
            btn.style.backgroundColor = '#e0e0e0';
            btn.style.cursor = 'pointer';

            const inputs = []; // Массив для хранения полей ввода

            // Если команда имеет параметры, создаем поля ввода
            if (cmd.parameters && cmd.parameters.length > 0) {
                cmd.parameters.forEach(param => {
                    const Input = document.createElement('input');
                    Input.type = 'text';
                    Input.placeholder = `Введите ${param}`;
                    Input.style.marginBottom = '5px';
                    Input.style.backgroundColor = '#333';
                    Input.style.color = '#fff';
                    Input.style.borderRadius = '4px';
                    commandBlock.appendChild(Input);
                    inputs.push(Input); // Добавляем поле в массив
                });
            }

            // Обработчик нажатия на кнопку
            btn.onclick = () => {
                let finalCommand = cmd.command; // Изначальная команда

                // Проверяем, заполнены ли все параметры
                for (let i = 0; i < inputs.length; i++) {
                    const value = inputs[i].value.trim();
                    if (!value) {
                        sendmsg(`Параметр "${cmd.parameters[i]}" не может быть пустым!`,'Bot Menu Client (Error)','Bot Menu Client','#0066ff')
                        return; // Отменяем выполнение, если параметр пуст
                    }
                    finalCommand = finalCommand.replace(`[${cmd.parameters[i]}]`, value); // Заменяем параметр
                }

                // Вставляем готовую команду в чат
                const chatInput = document.querySelector('#chat-input');
                if (chatInput) {
                    chatInput.value = finalCommand;
                    chatInput.focus(); // Устанавливаем фокус на чат
                } else {
                    console.error('Chat input not found!');
                }
            };

            commandBlock.appendChild(btn); // Добавляем кнопку в блок команды
            commandsContainer.appendChild(commandBlock); // Добавляем блок команды в контейнер
        });
    });
}
    /* Поле поиска
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.marginBottom = '10px';
searchInput.placeholder = 'Поиск команд';
searchInput.style.marginBottom = '10px';
searchInput.style.backgroundColor = '#333';
searchInput.style.color = '#fff';
searchInput.style.borderRadius = '4px';
searchInput.oninput = filterCommands;
container.appendChild(searchInput);

function filterCommands() {
    const query = searchInput.value.toLowerCase();
    Array.from(commandsContainer.children).forEach(child => {
        if (child.innerText.toLowerCase().includes(query)) {
            child.style.display = 'block';
        } else {
            child.style.display = 'none';
        }
    });
}*/

    // Делает контейнер перетаскиваемым
    class BotChatPanel {
    constructor() {
        this.createPanel();
    }

    createPanel() {
        this.panel = document.createElement("div");
        this.panel.id = "bot-chat-panel";
        this.panel.style.position = "fixed";
        this.panel.style.bottom = "20px";
        this.panel.style.right = "20px";
        this.panel.style.width = "300px";
        this.panel.style.height = "400px";
        this.panel.style.background = "#222";
        this.panel.style.color = "#fff";
        this.panel.style.borderRadius = "10px";
        this.panel.style.padding = "10px";
        this.panel.style.overflowY = "auto";
        this.panel.style.display = "none";
        this.panel.style.boxShadow = "0 0 10px rgba(0,0,0,0.5)";

        const closeButton = document.createElement("button");
        closeButton.innerText = "✖";
        closeButton.style.position = "absolute";
        closeButton.style.top = "5px";
        closeButton.style.right = "5px";
        closeButton.style.background = "transparent";
        closeButton.style.color = "#fff";
        closeButton.style.border = "none";
        closeButton.style.cursor = "pointer";
        closeButton.onclick = () => this.panel.style.display = "none";
        this.panel.appendChild(closeButton);
        document.body.appendChild(this.panel);
    }

    showMessage(botName, botColor, message) {
        const messageDiv = document.createElement("div");
        messageDiv.style.padding = "5px";
        messageDiv.style.borderBottom = "1px solid #444";

        const botLabel = document.createElement("span");
        botLabel.innerText = `[${botName}] `;
        botLabel.style.color = botColor;
        botLabel.style.fontWeight = "bold";

        const textSpan = document.createElement("span");
        textSpan.innerText = message;

        messageDiv.appendChild(botLabel);
        messageDiv.appendChild(textSpan);
        this.panel.appendChild(messageDiv);

        this.panel.style.display = "block";
    }
}

// Создаем панель
const botChat = new BotChatPanel();

// Функция для обработки сообщений с directsend
function handleCommandResponse(response) {
    if (response.directsend === "true") {
        botChat.showMessage(response.botName, response.botColor, response.message);
    } else {
        console.log("Обычный ответ в чат", response.message);
    }
}

    function makeDraggable(element) {
        let offsetX = 0, offsetY = 0, mouseDown = false;

        element.addEventListener('mousedown', (e) => {
            mouseDown = true;
            offsetX = e.clientX - element.offsetLeft;
            offsetY = e.clientY - element.offsetTop;
        });

        document.addEventListener('mousemove', (e) => {
            if (!mouseDown) return;
            element.style.left = `${e.clientX - offsetX}px`;
            element.style.top = `${e.clientY - offsetY}px`;
        });

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

    makeDraggable(container);

    // Обработчик входящих сообщений
    MPP.client.on('custom', (data) => {
        if (!data.data || data.data.m !== 'BotMenu') return;

        const { botName, categories } = data.data;
        const botId = data.p;

        if (!botId || !botName || !Array.isArray(categories)) {
            console.debug('Invalid bot data received:', data.data);
            return;
        }

        // Проверяем, есть ли данные для бота
        if (!botsData[botId]) {
            botsData[botId] = { name: botName, categories: [] };

            // Обрабатываем категории
            categories.forEach((category) => {
                const { categoryName, position, commands } = category;

                botsData[botId].categories.push({
                    name: categoryName,
                    position,
                    commands,
                });
            });

            addTab(botId, botName); // Добавляем вкладку для бота
            sendmsg(`Данные были получены с ${botName}`,'Bot Menu Client','Bot Menu Client','#0066ff')
        } else {
            // Обновляем существующие данные
            botsData[botId].categories = categories.map((category) => ({
                name: category.categoryName,
                position: category.position,
                commands: category.commands,
            }));
            sendmsg(`Данные бота ${botName} были обновлены`,'Bot Menu Client','Bot Menu Client','#0066ff');
        }
    });
    if (localStorage.getItem('language') === null){
        const tryi18nextLng = confirm("try i18nextLng for language?")
        if (tryi18nextLng === true){
            localStorage.setItem('language', localStorage.getItem('i18nextLng'));
            alert('successfully')
        }else{

        }
    }
    // При подключении отправляем +custom
    MPP.client.on('hi', () => {
        const language = localStorage.getItem('language');
        MPP.client.sendArray([{ m: '+custom' }]);
    });
})();