Gartic Anonimbiri Bot Panel

Advanced bot control panel for gartic.io with cute anime theme, player list and spam features

当前为 2025-04-20 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Gartic Anonimbiri Bot Panel
// @name:tr      Gartic Anonimbiri Bot Paneli
// @namespace    http://tampermonkey.net/
// @version      2025-04-20
// @description  Advanced bot control panel for gartic.io with cute anime theme, player list and spam features
// @description:tr Sevimli anime teması, oyuncu listesi ve spam özellikleri ile gartic.io için gelişmiş bot kontrol paneli
// @author       anonimbiri
// @license      MIT
// @match        https://gartic.io/anonimbiri
// @icon         https://cdn.jsdelivr.net/gh/Gartic-Developers/Kawaii-Helper@refs/heads/main/Assets/kawaii-logo.png
// @grant        GM_cookie
// ==/UserScript==

(function() {
    'use strict';

    // Custom console logging
    const log = (msg, error = false) => {
        console.log(`%c[anonimbiri] ${msg}`, `color:${error ? '#ff5555' : '#55ff55'};font-weight:bold;font-family:monospace;background:#222;padding:2px 4px;border-radius:3px`);
    };

    // Delete garticio cookie on page load
    GM_cookie.delete({ name: 'garticio' }, (error) => {
        log(error ? '✖ garticio çerezi silinirken hata oluştu!' : '✔ garticio çerezi başarıyla silindi!');
    });

    // Replace page with cute anime theme
    document.documentElement.innerHTML = `
        <style>
            @import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;700&display=swap');

            * {
                box-sizing: border-box;
                margin: 0;
                padding: 0;
            }

            body {
                margin: 0;
                background: linear-gradient(135deg, #ffcef3, #a6c1ff);
                color: #6e2252;
                font-family: 'Quicksand', sans-serif;
                min-height: 100vh;
                display: flex;
                justify-content: center;
                align-items: center;
                padding: 20px;
                overflow: auto;
            }

            .hearts {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                pointer-events: none;
                z-index: -1;
            }

            .heart {
                position: absolute;
                width: 10px;
                height: 10px;
                background-color: rgba(255, 182, 193, 0.7);
                transform: rotate(45deg);
                animation: float 15s infinite linear;
            }

            .heart::before, .heart::after {
                content: '';
                position: absolute;
                width: 10px;
                height: 10px;
                background-color: rgba(255, 182, 193, 0.7);
                border-radius: 50%;
            }

            .heart::before {
                top: -5px;
                left: 0;
            }

            .heart::after {
                top: 0;
                left: -5px;
            }

            @keyframes float {
                0% { transform: rotate(45deg) translateY(0) translateX(0); opacity: 1; }
                100% { transform: rotate(45deg) translateY(-100vh) translateX(100vw); opacity: 0; }
            }

            .container {
                display: flex;
                max-width: 1200px;
                width: 100%;
                gap: 20px;
                flex-wrap: wrap;
                justify-content: center;
                align-items: flex-start;
            }

            .panel {
                background: rgba(255, 255, 255, 0.9);
                padding: 25px;
                border-radius: 24px;
                box-shadow: 0 10px 30px rgba(122, 137, 247, 0.5);
                width: 320px;
                text-align: center;
                position: relative;
                border: 3px solid #a6c1ff;
                overflow: hidden;
                flex-shrink: 0;
                min-height: 400px;
            }

            .panel::before {
                content: '';
                position: absolute;
                top: -50%;
                left: -50%;
                width: 200%;
                height: 200%;
                background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.3), transparent);
                transform: rotate(45deg);
                animation: shine 3s infinite;
            }

            @keyframes shine {
                0% { transform: translateX(-100%) rotate(45deg); }
                100% { transform: translateX(100%) rotate(45deg); }
            }

            h3 {
                color: #7a6ed9;
                margin: 0 0 20px;
                font-size: 22px;
                font-weight: 700;
                text-shadow: 0 2px 4px rgba(122, 110, 217, 0.2);
                position: relative;
                display: inline-block;
            }

            h3::after {
                content: '';
                position: absolute;
                bottom: -6px;
                left: 0;
                width: 100%;
                height: 3px;
                background: linear-gradient(90deg, transparent, #a6c1ff, transparent);
            }

            .input-group {
                margin: 15px 0;
                position: relative;
            }

            label {
                display: block;
                text-align: left;
                margin-bottom: 6px;
                color: #7a6ed9;
                font-weight: 500;
                font-size: 14px;
            }

            input, select {
                width: 100%;
                padding: 10px 15px;
                border: 2px solid #c4d3ff;
                border-radius: 12px;
                background: #fff;
                color: #7a6ed9;
                font-family: 'Quicksand', sans-serif;
                font-size: 15px;
                transition: all 0.3s;
                font-weight: 500;
            }

            input:focus, select:focus {
                border-color: #7a6ed9;
                box-shadow: 0 0 0 3px rgba(122, 110, 217, 0.2);
                outline: none;
            }

            input::placeholder, select::placeholder {
                color: #c4d3ff;
            }

            button {
                background: linear-gradient(45deg, #7a6ed9, #a6c1ff);
                border: none;
                padding: 12px 20px;
                margin-top: 15px;
                border-radius: 12px;
                color: white;
                font-weight: 700;
                font-size: 16px;
                font-family: 'Quicksand', sans-serif;
                cursor: pointer;
                transition: all 0.3s;
                width: 100%;
                box-shadow: 0 4px 10px rgba(122, 110, 217, 0.3);
            }

            button:hover {
                background: linear-gradient(45deg, #6659c8, #8aa3f7);
                transform: translateY(-2px);
                box-shadow: 0 6px 15px rgba(122, 110, 217, 0.4);
            }

            button:active {
                transform: translateY(1px);
                box-shadow: 0 2px 5px rgba(122, 110, 217, 0.4);
            }

            .status {
                margin-top: 15px;
                padding: 10px;
                border-radius: 12px;
                background: rgba(245, 249, 255, 0.8);
                max-height: 120px;
                overflow-y: auto;
                font-size: 13px;
                text-align: left;
                color: #5d5393;
                border: 1px solid #d4e1ff;
            }

            .status::-webkit-scrollbar {
                width: 6px;
            }

            .status::-webkit-scrollbar-track {
                background: #d4e1ff;
                border-radius: 10px;
            }

            .status::-webkit-scrollbar-thumb {
                background: #a6c1ff;
                border-radius: 10px;
            }

            .kawaii-text {
                font-size: 12px;
                color: #7a6ed9;
                margin-top: 15px;
                font-weight: 500;
            }

            /* Player list styles */
            .player-panel {
                background: rgba(255, 255, 255, 0.9);
                padding: 25px;
                border-radius: 24px;
                box-shadow: 0 10px 30px rgba(122, 137, 247, 0.5);
                width: 320px;
                position: relative;
                border: 3px solid #a6c1ff;
                overflow: hidden;
                flex-shrink: 0;
                min-height: 400px;
            }

            .player-panel::before {
                content: '';
                position: absolute;
                top: -50%;
                left: -50%;
                width: 200%;
                height: 200%;
                background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.3), transparent);
                transform: rotate(45deg);
                animation: shine 3s infinite;
            }

            .player-list {
                overflow-y: auto;
                max-height: 250px;
                margin-top: 10px;
            }

            .player-list::-webkit-scrollbar {
                width: 6px;
            }

            .player-list::-webkit-scrollbar-track {
                background: #d4e1ff;
                border-radius: 10px;
            }

            .player-list::-webkit-scrollbar-thumb {
                background: #a6c1ff;
                border-radius: 10px;
            }

            .player-item {
                display: flex;
                align-items: center;
                padding: 8px 12px;
                margin-bottom: 8px;
                background: rgba(245, 249, 255, 0.8);
                border-radius: 10px;
                border: 1px solid #d4e1ff;
                transition: all 0.2s;
            }

            .player-item:hover {
                background: rgba(216, 230, 255, 0.8);
                transform: translateY(-2px);
                box-shadow: 0 4px 8px rgba(122, 110, 217, 0.2);
            }

            .player-avatar {
                width: 32px;
                height: 32px;
                border-radius: 50%;
                margin-right: 12px;
                background-size: cover;
                background-position: center;
                border: 2px solid #a6c1ff;
                flex-shrink: 0;
            }

            .player-info {
                flex-grow: 1;
                text-align: left;
            }

            .player-name {
                font-weight: 700;
                color: #7a6ed9;
                font-size: 15px;
                display: block;
            }

            .player-stats {
                display: flex;
                gap: 10px;
                font-size: 12px;
                color: #5d5393;
            }

            .player-actions {
                display: flex;
                gap: 5px;
            }

            .kick-btn, .report-btn {
                background: linear-gradient(45deg, #7a6ed9, #a6c1ff);
                border: none;
                padding: 5px 10px;
                border-radius: 8px;
                color: white;
                font-weight: 700;
                font-size: 12px;
                font-family: 'Quicksand', sans-serif;
                cursor: pointer;
                transition: all 0.3s;
                box-shadow: 0 2px 5px rgba(122, 110, 217, 0.3);
                margin-left: 5px;
            }

            .kick-btn:hover, .report-btn:hover {
                background: linear-gradient(45deg, #6659c8, #8aa3f7);
                transform: translateY(-2px);
                box-shadow: 0 4px 8px rgba(122, 110, 217, 0.4);
            }

            .room-info {
                text-align: left;
                margin-bottom: 15px;
                padding-bottom: 10px;
                border-bottom: 1px dashed #d4e1ff;
            }

            .room-code {
                font-weight: 700;
                color: #7a6ed9;
                font-size: 16px;
            }

            .room-theme {
                font-size: 14px;
                color: #5d5393;
                margin-top: 5px;
            }

            .empty-list {
                text-align: center;
                padding: 20px;
                color: #5d5393;
                font-style: italic;
            }

            .anime-mascot {
                position: fixed;
                bottom: 10px;
                right: 10px;
                width: 180px;
                height: 180px;
                background-size: contain;
                background-repeat: no-repeat;
                opacity: 0.9;
                pointer-events: none;
                z-index: 10;
            }

            .spam-panel {
                flex: 1;
                min-width: 320px;
            }
        </style>

        <div class="hearts" id="hearts"></div>

        <div class="container">
            <div class="panel player-panel">
                <h3>Odadaki Oyuncular</h3>
                <div class="room-info">
                    <div class="room-code" id="roomCodeDisplay">Oda: Henüz bağlanılmadı</div>
                    <div class="room-theme" id="roomTheme">Tema: -</div>
                </div>
                <div class="player-list" id="playerList">
                    <div class="empty-list">Henüz oyuncu bilgisi yok...</div>
                </div>
            </div>

            <div class="panel">
                <h3>Gartic Bot Control</h3>
                <div class="input-group">
                    <label>Bot Sayısı:</label>
                    <input type="number" id="botCount" min="1" value="5">
                </div>
                <div class="input-group">
                    <label>Oda Kodu:</label>
                    <input type="text" id="roomCode" placeholder="Örn. 32v1sA">
                </div>
                <button id="startBots">Botları Başlat</button>
                <div class="status" id="statusLog">Durum: Botlar hazır, başlatmak için butona tıklayın...</div>
                <div class="kawaii-text">✧・゚: *✧・゚:* Cute Gartic Bots *:・゚✧*:・゚✧</div>
            </div>

            <div class="panel spam-panel">
                <h3>Bot Spam Kontrol</h3>
                <div class="input-group">
                    <label>Spam Metni:</label>
                    <input type="text" id="spamText" placeholder="Gönderilecek mesaj">
                </div>
                <div class="input-group">
                    <label>Spam Kanalı:</label>
                    <select id="spamChannel">
                        <option value="answers">Cevaplar (42[13])</option>
                        <option value="chat">Sohbet (42[11])</option>
                    </select>
                </div>
                <div class="input-group">
                    <label>Spam Aralığı (ms):</label>
                    <input type="number" id="spamInterval" min="100" value="1000">
                </div>
                <button id="startSpam">Spam Başlat</button>
                <button id="reportDrawing" style="background: linear-gradient(45deg, #ff5555, #a6c1ff);">Çizimi Raporla</button>
                <div class="status" id="spamStatus">Durum: Spam kapalı</div>
            </div>
        </div>

        <div class="anime-mascot" style="background-image: url('https://cdn.jsdelivr.net/gh/Gartic-Developers/Kawaii-Helper@refs/heads/main/Assets/kawaii-logo.png');"></div>
    `;

    // Status log function
    const statusLog = (msg) => {
        const logEl = document.getElementById('statusLog');
        logEl.innerHTML += `<div>→ ${msg}</div>`;
        logEl.scrollTop = logEl.scrollHeight;
    };

    // Spam status log function
    const spamLog = (msg) => {
        const logEl = document.getElementById('spamStatus');
        logEl.innerHTML += `<div>→ ${msg}</div>`;
        logEl.scrollTop = logEl.scrollHeight;
    };

    // Global variables
    let token, sala, botCount, roomCode, roomId;
    let websocketUrl = null;
    let playerList = [];
    let socketList = [];
    let botsCreated = 0;
    let botQueue = [];
    let isCreatingBot = false;
    let currentIframe = null;
    let spamInterval = null;
    let isSpamming = false;
    const startBotsButton = document.getElementById('startBots');

    // Attach event listeners
    startBotsButton.addEventListener('click', () => {
        if (startBotsButton.textContent === 'Botları Başlat') {
            startBots();
        } else {
            deleteAllBots();
        }
    });

    document.getElementById('startSpam').addEventListener('click', () => {
        const startSpamButton = document.getElementById('startSpam');
        if (startSpamButton.textContent === 'Spam Başlat') {
            startSpam();
        } else {
            stopSpam();
        }
    });

    document.getElementById('reportDrawing').addEventListener('click', () => {
        reportDrawing();
    });

    // Start spam function
    function startSpam() {
        if (socketList.length === 0) {
            spamLog("Spam için aktif bot bulunamadı!");
            return;
        }

        const spamText = document.getElementById('spamText').value.trim();
        const spamChannel = document.getElementById('spamChannel').value;
        const spamIntervalValue = parseInt(document.getElementById('spamInterval').value) || 1000;

        if (!spamText) {
            spamLog("Lütfen bir spam metni girin!");
            return;
        }

        isSpamming = true;
        document.getElementById('startSpam').textContent = 'Spam Durdur';
        document.getElementById('startSpam').style.background = 'linear-gradient(45deg, #ff5555, #a6c1ff)';

        spamLog(`Spam başlatıldı: "${spamText}" (${spamChannel === "answers" ? "Cevaplar" : "Sohbet"} kanalı)`);

        const commandCode = spamChannel === "answers" ? "13" : "11";

        clearInterval(spamInterval);
        spamInterval = setInterval(() => {
            socketList.forEach((socket, index) => {
                if (socket.readyState === WebSocket.OPEN && socket.playerId) {
                    socket.send(`42[${commandCode},${socket.playerId},"${spamText}"]`);
                    log(`Spam message sent from socket ${index} (${commandCode}): ${spamText}`);
                }
            });
        }, spamIntervalValue);
    }

    // Stop spam function
    function stopSpam() {
        clearInterval(spamInterval);
        isSpamming = false;
        document.getElementById('startSpam').textContent = 'Spam Başlat';
        document.getElementById('startSpam').style.background = 'linear-gradient(45deg, #7a6ed9, #a6c1ff)';
        spamLog("Spam durduruldu.");
    }

    // Start bots function
    function startBots() {
        botCount = parseInt(document.getElementById('botCount').value) || 5;
        roomCode = document.getElementById('roomCode').value.trim();
        roomId = roomCode;
        botsCreated = 0;
        botQueue = Array.from({ length: botCount }, (_, i) => i);
        isCreatingBot = false;

        if (!roomCode) return alert('Lütfen bir oda kodu girin!');

        log(`Starting ${botCount} bots for room ${roomCode}`);
        statusLog(`${botCount} bot başlatılıyor... Oda: ${roomCode}`);

        document.getElementById('roomCodeDisplay').textContent = `Oda: ${roomCode}`;

        createNextBot();
        startPeriodicMessage();
    }

    // Function to delete all bots
    function deleteAllBots() {
        if (socketList.length === 0) {
            statusLog("Silinecek aktif bot bulunamadı!");
            return;
        }

        if (isSpamming) {
            stopSpam();
        }

        socketList.forEach((socket, index) => {
            if (socket.readyState === WebSocket.OPEN && socket.playerId) {
                socket.send(`42[24,${socket.playerId}]`);
                log(`Sent leave command for socket ${index} with playerId ${socket.playerId}`);
                statusLog(`Bot ${index + 1} ayrılma komutu gönderildi: ${socket.playerId}`);
            }
        });
    }

    // Create next bot from queue
    function createNextBot() {
        if (botQueue.length === 0 || isCreatingBot) return;

        isCreatingBot = true;
        const index = botQueue.shift();
        setTimeout(() => createIframe(index), 1000);
    }

    // Create iframe for bot
    function createIframe(index) {
        statusLog(`Bot ${index + 1} oluşturuluyor...`);

        const iframe = document.createElement('iframe');
        iframe.src = `https://gartic.io/${roomCode}`;
        iframe.style = 'display:none';
        document.body.appendChild(iframe);
        currentIframe = iframe;

        iframe.onload = () => {
            const iw = iframe.contentWindow;
            const id = iframe.contentDocument;

            setTimeout(() => {
                const playButton = id.querySelector('.ic-playHome');
                if (playButton) {
                    playButton.click();
                    log(`Bot ${index}: Clicked ic-playHome`);
                    statusLog(`Bot ${index + 1}: Oyun butonuna tıklandı`);
                } else {
                    log(`Bot ${index}: Play button not found`, true);
                    statusLog(`Bot ${index + 1}: Oyun butonu bulunamadı`);
                    cleanupIframe();
                    isCreatingBot = false;
                    botsCreated++;
                    createNextBot();
                    return;
                }

                GM_cookie.delete({ name: 'garticio' }, (error) => {
                    log(error ? `Bot ${index}: Cookie deletion error` : `Bot ${index}: Cookie deleted`);
                });

                const originalXHROpen = iw.XMLHttpRequest.prototype.open;
                iw.XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
                    if (url.includes('server?check=')) {
                        this.isServerCheck = true;
                    }
                    return originalXHROpen.apply(this, arguments);
                };

                const originalXHRSend = iw.XMLHttpRequest.prototype.send;
                iw.XMLHttpRequest.prototype.send = function(body) {
                    if (this.isServerCheck) {
                        this.addEventListener('readystatechange', function() {
                            if (this.readyState === 4 && this.status === 200) {
                                try {
                                    const response = this.responseText;
                                    const match = response.match(/(https:\/\/[^?]+)\?c=([^&]+)/);
                                    if (match) {
                                        const server = match[1].replace('https://', '');
                                        const cParam = match[2];
                                        websocketUrl = `wss://${server}/socket.io/?c=${cParam}&EIO=3&transport=websocket`;
                                        log(`WebSocket URL constructed: ${websocketUrl}`);
                                        statusLog(`WebSocket URL oluşturuldu: ${websocketUrl}`);
                                        createBotSocket(index, websocketUrl, index === 0);
                                    } else {
                                        log(`WebSocket URL parsing failed for response: ${response}`, true);
                                        statusLog(`WebSocket URL ayrıştırma hatası: ${response}`);
                                        cleanupIframe();
                                        isCreatingBot = false;
                                        botsCreated++;
                                        createNextBot();
                                    }
                                } catch (e) {
                                    log(`Error processing server check response: ${e}`, true);
                                    statusLog(`Sunucu kontrol yanıtı işlenirken hata: ${e}`);
                                    cleanupIframe();
                                    isCreatingBot = false;
                                    botsCreated++;
                                    createNextBot();
                                }
                            }
                        });
                    }
                    return originalXHRSend.apply(this, arguments);
                };

                const originalSend = iw.WebSocket.prototype.send;
                iw.WebSocket.prototype.send = function(data) {
                    if (typeof data === 'string' && data.startsWith('42[3,{')) {
                        try {
                            const parsed = JSON.parse(data.substring(2));
                            if (parsed[1]?.token) {
                                token = parsed[1].token;
                                sala = parsed[1].sala || roomCode;
                                roomId = sala;
                                log(`Bot ${index}: Token=${token}, Sala=${sala}`);
                                statusLog(`Bot ${index + 1}: Kimlik bilgileri alındı`);
                                document.getElementById('roomCodeDisplay').textContent = `Oda: ${sala}`;
                                return;
                            }
                        } catch (e) {
                            log(`Bot ${index}: JSON parse error`, true);
                            statusLog(`Bot ${index + 1}: JSON ayrıştırma hatası`);
                            cleanupIframe();
                            isCreatingBot = false;
                            botsCreated++;
                            createNextBot();
                        }
                    }
                    return originalSend.apply(this, arguments);
                };
            }, 1500);
        };

        iframe.onerror = () => {
            log(`Bot ${index}: Iframe loading error`, true);
            statusLog(`Bot ${index + 1}: Iframe yükleme hatası`);
            cleanupIframe();
            isCreatingBot = false;
            botsCreated++;
            createNextBot();
        };
    }

    // Iframe cleanup function
    function cleanupIframe() {
        if (currentIframe) {
            currentIframe.remove();
            currentIframe = null;
            log('Iframe removed');
            statusLog('Iframe kaldırıldı');
        }
    }

    // Invisible characters list
    const invisibleChars = ['\u200B', '\u200C', '\u200D', '\u2061', '\u2062', '\u2063', '\u2064', '\u2066', '\u17b4', '\u17b5', '\u2068', '\u2069'];

    // Function to insert a random invisible character at a random position
    function insertInvisibleChar(nick) {
        const randomChar = invisibleChars[Math.floor(Math.random() * invisibleChars.length)];
        const insertPos = Math.floor(Math.random() * (nick.length + 1));
        return nick.slice(0, insertPos) + randomChar + nick.slice(insertPos);
    }

    // Function to check if a player is a bot
    function isBot(player) {
        if (!player.nick) return false;
        const cleanNick = player.nick.replace(/[\u200B-\u200D\u2061-\u2069\u17b4-\u17b5]/g, '');
        return cleanNick === 'anonimbiri' || cleanNick === 'Observer';
    }

    // Create WebSocket for bot
    function createBotSocket(index, wsUrl, isObserver = false) {
        if (!wsUrl) {
            log(`Bot ${index}: WebSocket URL not available`, true);
            statusLog(`Bot ${index + 1}: WebSocket URL bulunamadı`);
            cleanupIframe();
            isCreatingBot = false;
            botsCreated++;
            createNextBot();
            return;
        }

        statusLog(`Bot ${index + 1}: Oyun sunucusuna bağlanıyor...`);
        const ws = new WebSocket(wsUrl);
        ws.index = index;
        socketList.push(ws);

        ws.onopen = () => {
            log(`Bot ${index}: WebSocket connection opened`);
            statusLog(`Bot ${index + 1}: Bağlantı açıldı`);
        };

        ws.onmessage = (e) => {
            if (e.data === '40') {
                const baseNick = isObserver ? 'Observer' : 'anonimbiri';
                const nick = insertInvisibleChar(baseNick);
                ws.send(`42[3,{"v":20000,"token":"${token}","nick":"${nick}","avatar":"","platform":0,"sala":"${sala}"}]`);
                log(`Bot ${index}: Joined as ${nick}`);
                statusLog(`Bot ${index + 1}: "${nick}" olarak katıldı`);
            }

            if (e.data.startsWith('42["5",')) {
                try {
                    const parsed = JSON.parse(e.data.substring(2));
                    const playerId = parsed[2];
                    ws.send(`42[46,${playerId}]`);
                    log(`Bot ${index}: Player ID = ${playerId}`);
                    statusLog(`Bot ${index + 1}: Aktif ve hazır`);
                    ws.playerId = playerId;

                    if (parsed[2] && Array.isArray(parsed[5])) {
                        const roomInfo = parsed[4];
                        const newPlayers = parsed[5].filter(player => !isBot(player));
                        playerList = updatePlayerListNoDuplicates(newPlayers);
                        document.getElementById('roomTheme').textContent = `Tema: ${roomInfo.tema || '-'}`;
                        updatePlayerListUI();
                    }

                    cleanupIframe();
                    isCreatingBot = false;
                    botsCreated++;
                    log(`Bot ${index}: Bot created, total created: ${botsCreated}/${botCount}`);

                    if (botsCreated >= botCount) {
                        startBotsButton.textContent = 'Tüm Botları Sil';
                        startBotsButton.style.background = 'linear-gradient(45deg, #ff5555, #ff9dc4)';
                    }

                    if (botsCreated < botCount) {
                        createNextBot();
                    } else {
                        statusLog(`Tüm botlar (${botCount}) başarıyla başlatıldı! ✨`);
                    }
                } catch (e) {
                    log(`Bot ${index}: Error parsing response: ${e}`, true);
                    statusLog(`Bot ${index + 1}: Oyun verisi ayrıştırma hatası`);
                    cleanupIframe();
                    isCreatingBot = false;
                    botsCreated++;
                    createNextBot();
                }
            }

            if (e.data === '42["6",null]') {
                log(`Bot ${index}: Leave confirmed, removing socket`);
                statusLog(`Bot ${index + 1}: Ayrılma onaylandı, soket kaldırılıyor`);
                socketList = socketList.filter(s => s !== ws);
                if (ws.readyState === WebSocket.OPEN) {
                    ws.close();
                }
                if (socketList.length === 0) {
                    startBotsButton.textContent = 'Botları Başlat';
                    startBotsButton.style.background = 'linear-gradient(45deg, #7a6ed9, #a6c1ff)';
                    statusLog('Tüm botlar silindi, yeni botlar başlatılabilir.');
                }
            }

            if (typeof e.data === 'string') {
                try {
                    if (e.data.startsWith('42["23",')) {
                        const parsed = JSON.parse(e.data.substring(2));
                        if (parsed[1] && parsed[1].id && !isBot(parsed[1])) {
                            const newPlayer = parsed[1];
                            if (!playerList.some(p => String(p.id) === String(newPlayer.id))) {
                                playerList.push(newPlayer);
                                updatePlayerListUI();
                                log(`New player joined: ${newPlayer.nick}`);
                                statusLog(`Yeni oyuncu: ${newPlayer.nick}`);
                            }
                        }
                    }

                    if (e.data.startsWith('42["24",')) {
                        const parsed = JSON.parse(e.data.substring(2));
                        const leftPlayerId = parsed[1];
                        playerList = playerList.filter(p => String(p.id) !== String(leftPlayerId));
                        updatePlayerListUI();
                        log(`Player left: ${leftPlayerId}`);
                        statusLog(`Oyuncu ayrıldı: ID ${leftPlayerId}`);
                    }
                } catch (e) {
                    log(`Bot ${index}: Error parsing player update: ${e}`, true);
                }
            }
        };

        ws.onerror = () => {
            log(`Bot ${index}: WebSocket error`, true);
            statusLog(`Bot ${index + 1}: Bağlantı hatası`);
            socketList = socketList.filter(s => s !== ws);
            cleanupIframe();
            isCreatingBot = false;
            botsCreated++;
            createNextBot();
        };

        ws.onclose = () => {
            log(`Bot ${index}: WebSocket closed`);
            statusLog(`Bot ${index + 1}: Bağlantı kapandı`);
            socketList = socketList.filter(s => s !== ws);
            cleanupIframe();
            isCreatingBot = false;
            createNextBot();
        };
    }

    // Function to update player list without duplicates
    function updatePlayerListNoDuplicates(newPlayers) {
        const existingIds = new Set(playerList.map(p => String(p.id)));
        const updatedList = [...playerList];

        newPlayers.forEach(player => {
            if (!existingIds.has(String(player.id))) {
                updatedList.push(player);
                existingIds.add(String(player.id));
            }
        });

        return updatedList;
    }

    // Update player list from data
    function updatePlayerList(players) {
        if (players && Array.isArray(players)) {
            const filteredPlayers = players.filter(player => !isBot(player));
            playerList = updatePlayerListNoDuplicates(filteredPlayers);
            updatePlayerListUI();
        }
    }

    // Update player list UI
    function updatePlayerListUI() {
        const playerListElement = document.getElementById('playerList');

        if (!playerList || playerList.length === 0) {
            playerListElement.innerHTML = `<div class="empty-list">Henüz oyuncu bilgisi yok...</div>`;
            return;
        }

        let html = '';

        playerList.forEach(player => {
            let avatarUrl = getAvatarUrl(player);

            html += `
                <div class="player-item" data-id="${player.id}">
                    <div class="player-avatar" style="background-image: url('${avatarUrl}')"></div>
                    <div class="player-info">
                        <span class="player-name">${player.nick}</span>
                        <div class="player-stats">
                            <span>Puan: ${player.pontos || 0}</span>
                            <span>Galibiyetler: ${player.vitorias || 0}</span>
                        </div>
                    </div>
                    <button class="kick-btn" data-id="${player.id}">Kick</button>
                </div>
            `;
        });

        playerListElement.innerHTML = html;

        document.querySelectorAll('.kick-btn').forEach(btn => {
            btn.addEventListener('click', function() {
                const playerId = this.getAttribute('data-id');
                kickPlayer(playerId);
            });
        });
    }

    // Kick player function
    function kickPlayer(playerId) {
        if (socketList.length === 0) {
            statusLog("Kick işlemi için aktif bağlantı bulunamadı!");
            return;
        }

        if (playerId) {
            socketList.forEach((socket, index) => {
                if (socket.readyState === WebSocket.OPEN && socket.playerId) {
                    socket.send(`42[45,${socket.playerId},["${playerId}",true]]`);
                    log(`Kick request sent for player ${playerId} from socket ${index} with playerId ${socket.playerId}`);
                    statusLog(`Oyuncu kick işlemi gönderildi: ${playerId} (Soket ${index + 1})`);
                }
            });
        } else {
            log("Kick failed: Missing player ID", true);
            statusLog("Kick başarısız: Oyuncu ID eksik");
        }
    }

    // Report drawing function
    function reportDrawing() {
        if (socketList.length === 0) {
            statusLog("Raporlama işlemi için aktif bağlantı bulunamadı!");
            return;
        }

        socketList.forEach((socket, index) => {
            if (socket.readyState === WebSocket.OPEN && socket.playerId) {
                socket.send(`42[35,${socket.playerId}]`);
                log(`Report drawing request sent from socket ${index} with playerId ${socket.playerId}`);
                statusLog(`Çizim raporlama işlemi gönderildi (Soket ${index + 1})`);
            }
        });
    }

    // Add avatar URL helper function
    function getAvatarUrl(player) {
        if (player.foto) {
            return player.foto;
        } else if (player.avatar !== undefined && player.avatar !== null) {
            return `https://gartic.io/static/images/avatar/svg/${player.avatar}.svg`;
        } else {
            return 'https://gartic.io/static/images/avatar/svg/0.svg';
        }
    }

    // Periodic message sender
    function startPeriodicMessage() {
        setInterval(() => {
            socketList.forEach((socket, index) => {
                if (socket.readyState === WebSocket.OPEN && socket.playerId) {
                    socket.send(`42[42,${socket.playerId}]`);
                    log(`Sent periodic message from socket ${index} with playerId ${socket.playerId}`);
                }
            });
        }, 2000);
    }

    // Initialize animations and effects
    function initAnimations() {
        const heartsContainer = document.querySelector('.hearts');
        let heartsHTML = '';

        for (let i = 0; i < 20; i++) {
            heartsHTML += `<div class="heart" style="
                left: ${Math.random() * 100}vw;
                top: ${Math.random() * 100}vh;
                opacity: ${0.3 + Math.random() * 0.7};
                transform: scale(${0.5 + Math.random() * 1.5}) rotate(45deg);
                animation-duration: ${10 + Math.random() * 20}s;
                animation-delay: ${Math.random() * 10}s;
            "></div>`;
        }

        heartsContainer.innerHTML = heartsHTML;
    }

    // Run initialization
    initAnimations();

    // Add room code input value extraction from URL
    (function extractRoomCodeFromUrl() {
        const url = window.location.href;
        if (url) {
            const urlParts = url.split('/');
            if (urlParts.length > 0) {
                const lastPart = urlParts[urlParts.length - 1];
                if (lastPart && lastPart !== 'anonimbiri') {
                    document.getElementById('roomCode').value = lastPart;
                    log(`Room code extracted from URL: ${lastPart}`);
                    statusLog(`URL'den oda kodu çıkarıldı: ${lastPart}`);
                }
            }
        }
    })();

    // Log startup message
    log("Gartic Anonimbiri Bot Panel v2025-04-20 başlatıldı");
    statusLog("Bot paneli aktif! Botları başlatmak için üstteki butona tıklayın.");
})();