// ==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!');
});
GM_cookie.delete({ name: 'cf_clearance' }, (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();
createIframe(index);
}
// 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`);
});
GM_cookie.delete({ name: 'cf_clearance' }, (error) => {
log(error ? '✖ garticio çerezi silinirken hata oluştu!' : '✔ garticio çerezi başarıyla silindi!');
});
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}`);
}
if (e.data.startsWith('42["16",')) {
try {
const parsed = JSON.parse(e.data.substring(2));
const options = [parsed[1], parsed[3]];
const choiceIndex = Math.floor(Math.random() * 2);
const choice = options[choiceIndex];
log(`Bot ${index}: Received options ${options.join(' vs ')}, chose ${choice} (${choiceIndex})`);
setTimeout(() => {
if (ws.readyState === WebSocket.OPEN && ws.playerId) {
ws.send(`42[34,${ws.playerId},${choiceIndex}]`);
log(`Bot ${index}: Sent choice ${choiceIndex} for ${choice}`);
} else {
log(`Bot ${index}: Socket closed or no playerId, cannot send choice`, true);
}
}, 8000);
} catch (e) {
log(`Bot ${index}: Error parsing 16 message: ${e}`, true);
}
}
if (e.data.startsWith('42["34",')) {
try {
if (ws.readyState === WebSocket.OPEN && ws.playerId) {
ws.send(`42[30,${ws.playerId}]`);
ws.send(`42[30,${ws.playerId}]`);
ws.send(`42[30,${ws.playerId}]`);
ws.send(`42[30,${ws.playerId}]`);
log(`Bot ${index}: Received 34 message, sent 42[30,${ws.playerId}]`);
} else {
log(`Bot ${index}: Socket closed or no playerId, cannot send 30 message`, true);
}
} catch (e) {
log(`Bot ${index}: Error processing 34 message: ${e}`, true);
}
}
} 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.");
})();