您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Interfaz gráfica completa, draggable y funcional para crear y usar grupos de chat privados en Drawaria.
// ==UserScript== // @name Chat Privado Grupal Drawaria.online // @namespace http://tampermonkey.net/ // @version 1.0 // @description Interfaz gráfica completa, draggable y funcional para crear y usar grupos de chat privados en Drawaria. // @author YouTubeDrawaria & videogamebmo // @match https://drawaria.online/* // @grant none // @run-at document-idle // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online // ==/UserScript== (function() { 'use strict'; // --- ESTADO GLOBAL Y CONFIGURACIÓN --- let grupos = {}; let chatHistory = {}; let currentUser = { id: null, name: null }; let activeChatGroup = null; let botMessageTimer = null; // Para el temporizador de mensajes del bot let typingIndicatorTimer = null; // Para el temporizador del indicador de "escribiendo" let loadingTimer = null; // Nuevo temporizador para la simulación de la pantalla de carga // --- CONFIGURACIÓN DEL BOT DE DEMOSTRACIÓN --- const BOT_MESSAGE_DELAY_MIN = 3000; // Mínimo 3 segundos antes de que el bot piense en responder (respuesta no inmediata) const BOT_MESSAGE_DELAY_MAX = 8000; // Máximo 8 segundos const TYPING_DURATION_MIN = 1200; // Mínimo 1.2 segundos que el bot "escribe" const TYPING_DURATION_MAX = 3500; // Máximo 3.5 segundos const BOT_MESSAGES = [ "Hola!", "Qué tal?", "Ok", "Entendido.", "Estoy aquí!", "Jeje", "Sí", "No", "Gracias", "De nada", "Qué dibujas?", "Buena idea!", "Me gusta el chat!", "Genial!", ":)", "xD", "Interesante...", "Cuéntame más.", "De acuerdo.", "Perfecto.", "Cómo va todo?", "Claro!", "Increíble!", "Qué divertido es esto!" ]; // --- INICIALIZACIÓN DEL LOCALSTORAGE --- try { grupos = JSON.parse(localStorage.getItem("grupos_v3") || "{}"); chatHistory = JSON.parse(localStorage.getItem("chatHistory_v3") || "{}"); } catch (e) { console.error("Error al analizar localStorage, limpiando datos corruptos:", e); localStorage.removeItem("grupos_v3"); localStorage.removeItem("chatHistory_v3"); grupos = {}; chatHistory = {}; } // --- LÓGICA DE INICIALIZACIÓN --- const maxAttempts = 20; // Intentar durante 10 segundos let attemptCount = 0; const waitForGameAPI = setInterval(() => { attemptCount++; const playernameInput = document.getElementById('playername'); const currentPlayerName = playernameInput ? playernameInput.value.trim() : null; console.log(`Intento ${attemptCount}: Verificando window.playerid, nombre de usuario y elementos de la lista de amigos...`); if (window.playerid && currentPlayerName && document.querySelector("#friends-tabfriendlist")) { clearInterval(waitForGameAPI); initialize(); } else if (attemptCount >= maxAttempts) { clearInterval(waitForGameAPI); initializeFallback(); } }, 500); function initialize() { try { console.log("Iniciando Super Chat de Grupos..."); currentUser.id = window.playerid; const playernameInput = document.getElementById('playername'); currentUser.name = playernameInput ? playernameInput.value.trim() : "Tú"; console.log(`Usuario actual: ${currentUser.name} (ID: ${currentUser.id})`); injectStyles(); injectGUI(); showLoadingScreen(); simulateLoading(); } catch (e) { console.error("Error durante la inicialización:", e); } } function initializeFallback() { try { console.log("Bienvenido al chat privado de Drawaria.online"); currentUser.id = "fallback-user-" + Math.random().toString(36).slice(2); currentUser.name = "Amigo"; console.log(`Usuario actual (fallback): ${currentUser.name} (ID: ${currentUser.id})`); injectStyles(); injectGUI(); showLoadingScreen(); simulateLoading(); } catch (e) { console.error("Error en inicialización parcial:", e); } } // --- LÓGICA DE LA PANTALLA DE CARGA --- const loadingMessages = [ "Iniciando módulos de chat...", "Verificando la integridad de los datos locales...", "Cargando historial de grupos y mensajes...", "Estableciendo conexión simulada con el servidor...", // Mensaje más 'pro' "Actualizando lista de amigos de Drawaria...", "Optimizando recursos gráficos y de rendimiento...", "Sincronizando estado de la aplicación...", "Preparando la interfaz de usuario...", "Casi listo para chatear..." ]; let loadingProgress = 0; function showLoadingScreen() { const loadingScreen = document.getElementById('chat-loading-screen'); if (loadingScreen) { loadingScreen.style.display = 'flex'; loadingProgress = 0; updateLoadingProgress(0, loadingMessages[0]); } } function hideLoadingScreen() { const loadingScreen = document.getElementById('chat-loading-screen'); if (loadingScreen) { loadingScreen.style.opacity = '0'; // Fundido setTimeout(() => { loadingScreen.style.display = 'none'; loadingScreen.style.opacity = '1'; // Reset para la próxima vez }, 500); // Duración del fundido } } function updateLoadingProgress(progress, message, currentStep, totalSteps) { const progressBar = document.getElementById('loading-progress-bar'); const progressText = document.getElementById('loading-text'); const progressStepCount = document.getElementById('loading-step-count'); if (progressBar && progressText && progressStepCount) { progressBar.style.width = `${progress}%`; progressText.textContent = message; progressStepCount.textContent = `Paso ${currentStep + 1} de ${totalSteps}`; // Muestra el paso actual } } function simulateLoading() { if (loadingTimer) clearTimeout(loadingTimer); let step = 0; const totalSteps = loadingMessages.length; const intervalTime = 600; // Tiempo por mensaje de carga const loadStep = () => { if (step < totalSteps) { loadingProgress = Math.floor((step / (totalSteps - 1)) * 100); // Distribución más uniforme if (step === totalSteps - 1) loadingProgress = 100; // Asegurar 100% en el último paso updateLoadingProgress(loadingProgress, loadingMessages[step], step, totalSteps); step++; loadingTimer = setTimeout(loadStep, intervalTime); } else { updateLoadingProgress(100, "Carga completa.", totalSteps, totalSteps); // Mensaje final loadingTimer = setTimeout(() => { hideLoadingScreen(); finalizeInitialization(); }, 700); // Pequeño retraso después del 100% y antes de ocultar } }; loadStep(); } function finalizeInitialization() { setupEventListeners(); ensureVisibility(); loadFriendsList(); renderGroupList(); console.log("Chat Privado Grupal Drawaria.online, Disfrute la experiencia."); } function ensureVisibility() { const chatWindow = document.getElementById('group-chat-window'); if (chatWindow) { chatWindow.style.display = 'flex'; chatWindow.style.zIndex = '10000'; chatWindow.style.position = 'fixed'; console.log("Para usar el chat tienes un boton para mostrarlo visible y ocultarlo"); } else { console.error("No se encontró '#group-chat-window', intentando reinyección..."); return; } } // --- INYECCIÓN DE UI Y ESTILOS --- function injectStyles() { const styles = ` #group-chat-window { position: fixed !important; top: 50px !important; right: 20px !important; width: 600px !important; max-width: 90vw !important; height: 600px !important; max-height: 80vh !important; background: #fff !important; border-radius: 8px !important; box-shadow: 0 5px 20px rgba(0,0,0,0.3) !important; display: none; /* Oculto por defecto, se muestra después de la carga */ flex-direction: column !important; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; } #chat-loading-screen { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; background: rgba(255,255,255,0.95) !important; /* Más claro */ z-index: 10001 !important; display: none; flex-direction: column !important; justify-content: center !important; align-items: center !important; color: #333 !important; /* Texto oscuro para fondo claro */ font-size: 1.2em !important; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; transition: opacity 0.5s ease-out !important; /* Transición para fundido */ } #loading-box { background: #ffffff !important; /* Color blanco */ padding: 40px !important; border-radius: 12px !important; box-shadow: 0 8px 25px rgba(0,0,0,0.1) !important; /* Sombra más suave */ text-align: center !important; min-width: 380px !important; /* Ancho mínimo ligeramente mayor */ max-width: 90% !important; border: 1px solid #e0e0e0 !important; /* Borde sutil */ display: flex; /* Para flexbox */ flex-direction: column; /* Apila elementos verticalmente */ align-items: center; /* Centra horizontalmente */ gap: 15px; /* Espacio entre elementos */ } #loading-box h2 { margin: 0 !important; /* Reset margin for gap */ color: #4a90e2 !important; /* Color del título */ font-size: 1.8em !important; } #loading-text { margin: 0 !important; /* Reset margin for gap */ font-size: 1.1em !important; color: #333 !important; /* Texto oscuro */ } #loading-step-count { font-size: 0.9em !important; color: #666 !important; /* Texto ligeramente más claro */ margin: 0 !important; /* Reset margin for gap */ } #loading-progress-bar-container { width: 100% !important; background-color: #e9ecef !important; /* Fondo de barra claro */ border-radius: 5px !important; overflow: hidden !important; height: 12px !important; /* Barra un poco más alta */ } #loading-progress-bar { height: 100% !important; width: 0% !important; background-color: #4a90e2 !important; border-radius: 5px !important; transition: width 0.4s ease-in-out !important; } .spinner { border: 4px solid rgba(0, 0, 0, 0.1) !important; /* Más sutil para fondo claro */ border-top: 4px solid #4a90e2 !important; border-radius: 50% !important; width: 40px !important; height: 40px !important; animation: spin 1s linear infinite !important; margin: 0 !important; /* Reset margin for gap */ } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Resto de estilos del chat, sin cambios */ #group-chat-header { background: #4a90e2 !important; color: white !important; padding: 10px 15px !important; border-radius: 8px 8px 0 0 !important; cursor: move !important; user-select: none !important; display: flex !important; justify-content: space-between !important; align-items: center !important; } #group-chat-header h5 { margin: 0 !important; font-size: 16px !important; } #group-chat-close-btn { background: none !important; border: none !important; color: white !important; font-size: 24px !important; cursor: pointer !important; line-height: 1 !important; } #group-chat-body { display: flex !important; flex-grow: 1 !important; overflow: hidden !important; } #group-chat-sidebar { width: 180px !important; background: #f5f5f5 !important; border-right: 1px solid #ddd !important; display: flex !important; flex-direction: column !important; } #group-chat-main { flex-grow: 1 !important; display: flex !important; flex-direction: column !important; } .sidebar-section { padding: 10px !important; border-bottom: 1px solid #ddd !important; } .sidebar-section h6 { margin-top: 0 !important; margin-bottom: 10px !important; color: #333 !important; font-size: 14px !important; } .item-list { list-style: none !important; padding: 0 !important; margin: 0 !important; max-height: 160px !important; overflow-y: auto !important; } .item-list li { padding: 8px 10px !important; cursor: pointer !important; border-bottom: 1px solid #eee !important; font-size: 14px !important; display: flex !important; justify-content: space-between !important; align-items: center !important; } .item-list li:hover { background: #e9e9e9 !important; } .item-list li.active { background: #d1e7fd !important; font-weight: bold !important; } #chat-view { flex-grow: 1 !important; padding: 10px !important; overflow-y: auto !important; background: #e5ddd5 !important; display: flex !important; flex-direction: column !important; } #typing-indicator { display: none; /* Oculto por defecto */ padding: 5px 10px 0 10px !important; font-style: italic !important; color: #888 !important; font-size: 13px !important; } #chat-input-area { padding: 10px !important; border-top: 1px solid #ccc !important; display: flex !important; } #chat-input { flex-grow: 1 !important; border: 1px solid #ccc !important; border-radius: 15px !important; padding: 8px 12px !important; } #chat-send-btn { margin-left: 10px !important; border: none !important; background: #4a90e2 !important; color: white !important; padding: 8px 15px !important; border-radius: 15px !important; cursor: pointer !important; } .chat-message { display: table !important; margin-bottom: 10px !important; padding: 8px 12px !important; border-radius: 12px !important; max-width: 80% !important; word-wrap: break-word !important; } .chat-message.self { background: #dcf8c6 !important; margin-left: auto !important; } .chat-message.other { background: #fff !important; margin-right: auto !important; } .chat-message .sender { font-weight: bold !important; color: #075e54 !important; font-size: 13px !important; } .chat-message .text { font-size: 14px !important; margin-top: 4px !important; } .chat-message.system { background: #f0f0f0 !important; text-align: center !important; margin-left: auto !important; margin-right: auto !important; width: fit-content !important; color: #666 !important; font-style: italic !important; font-size: 12px !important; padding: 5px 10px !important; border-radius: 8px !important; } #group-chat-trigger { position: fixed !important; top: 50% !important; right: 10px !important; transform: translateY(-50%) !important; background: #4a90e2 !important; color: white !important; padding: 12px !important; border-radius: 8px 0 0 8px !important; cursor: pointer !important; z-index: 9999 !important; box-shadow: -2px 2px 8px rgba(0,0,0,0.2) !important; } .invite-btn { font-size: 12px !important; color: #4a90e2 !important; opacity: 0.5 !important; } .invite-btn:hover { opacity: 1 !important; } .input-group { display: flex !important; } .form-control { flex-grow: 1 !important; padding: 5px !important; border: 1px solid #ccc !important; border-radius: 4px !important; } .btn { padding: 5px 10px !important; border: none !important; border-radius: 4px !important; cursor: pointer !important; } .btn-outline-secondary { background: transparent !important; border: 1px solid #6c757d !important; color: #6c757d !important; } .btn-warning { background: #ffc107 !important; color: #212529 !important; } .fas { font-family: "Font Awesome 5 Free" !important; } `; const styleElement = document.createElement('style'); styleElement.textContent = styles; document.head.appendChild(styleElement); } function injectGUI() { let container = document.body; if (!container) { console.warn("document.body no disponible, intentando document.documentElement..."); container = document.documentElement; } // HTML para la pantalla de carga (mejorada) const loadingScreenHTML = ` <div id="chat-loading-screen"> <div id="loading-box"> <h2>Iniciando Chat de Grupos</h2> <div class="spinner"></div> <div id="loading-text">Cargando...</div> <div id="loading-step-count"></div> <div id="loading-progress-bar-container"> <div id="loading-progress-bar"></div> </div> </div> </div> `; // HTML para la GUI principal del chat (sin cambios en estructura) const guiHTML = ` <div id="group-chat-window"> <div id="group-chat-header"> <h5 id="chat-window-title">Chat de Drawaria.online</h5> <button id="group-chat-close-btn" title="Cerrar">×</button> </div> <div id="group-chat-body"> <div id="group-chat-sidebar"> <div class="sidebar-section"> <h6>Grupos</h6> <ul id="group-list" class="item-list"></ul> <div class="input-group input-group-sm mt-2"> <input type="text" id="new-group-name" class="form-control" placeholder="Nuevo grupo..."> <button id="create-group-btn" class="btn btn-sm btn-outline-secondary" title="Crear"><i class="fas fa-plus"></i></button> </div> </div> <div class="sidebar-section"> <h6>Amigos</h6> <ul id="friend-list" class="item-list"></ul> </div> </div> <div id="group-chat-main"> <div id="chat-view"> <p style="text-align:center; color:#888; margin-top: 20px;">Selecciona un grupo para chatear.</p> </div> <div id="typing-indicator"> <span id="typing-username"></span> está escribiendo... </div> <div id="chat-input-area" style="display:none;"> <input type="text" id="chat-input" placeholder="Escribe un mensaje..."> <button id="chat-send-btn"><i class="fas fa-paper-plane"></i></button> </div> </div> </div> </div> <div id="group-chat-trigger" title="Abrir/Cerrar Chat de Grupos"><i class="fas fa-users"></i></div> `; // Inyectar ambos elementos container.insertAdjacentHTML('beforeend', loadingScreenHTML + guiHTML); // Inyectar FontAwesome (asegurarse de que solo se cargue una vez) if (!document.querySelector('link[href*="fontawesome"]')) { const faLink = document.createElement('link'); faLink.rel = 'stylesheet'; faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css'; faLink.onerror = () => console.error("Error al cargar FontAwesome"); faLink.onload = () => console.log("FontAwesome cargado correctamente"); document.head.appendChild(faLink); } } // --- MANEJADORES DE EVENTOS --- function setupEventListeners() { const gui = document.getElementById('group-chat-window'); const trigger = document.getElementById('group-chat-trigger'); if (!gui || !trigger) { console.error("No se encontraron elementos GUI, no se pueden configurar los eventos."); return; } trigger.addEventListener('click', () => { const isVisible = gui.style.display === 'flex'; gui.style.display = isVisible ? 'none' : 'flex'; if (!isVisible) { loadFriendsList(); renderGroupList(); if (activeChatGroup) { startBotSimulation(); } } else { stopBotSimulation(); hideTypingIndicator(); } }); document.getElementById('group-chat-close-btn')?.addEventListener('click', () => { gui.style.display = 'none'; stopBotSimulation(); hideTypingIndicator(); }); if (document.getElementById('group-chat-header')) { makeDraggable(gui, document.getElementById('group-chat-header')); } document.getElementById('create-group-btn')?.addEventListener('click', crearGrupo); document.getElementById('chat-send-btn')?.addEventListener('click', enviarMensajeActual); document.getElementById('chat-input')?.addEventListener('keydown', (e) => { if (e.key === 'Enter') { enviarMensajeActual(); e.preventDefault(); } }); } // --- FUNCIONES AUXILIARES --- function makeDraggable(el, handle) { let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; handle.onmousedown = (e) => { e.preventDefault(); pos3 = e.clientX; pos4 = e.clientY; document.onmouseup = () => { document.onmouseup = null; document.onmousemove = null; }; document.onmousemove = (ev) => { ev.preventDefault(); pos1 = pos3 - ev.clientX; pos2 = pos4 - ev.clientY; pos3 = ev.clientX; pos4 = ev.clientY; el.style.top = Math.max(0, el.offsetTop - pos2) + "px"; el.style.left = Math.max(0, el.offsetLeft - pos1) + "px"; }; }; } // --- LÓGICA DE GRUPOS Y CHAT --- function loadFriendsList() { const list = document.getElementById('friend-list'); if (!list) return; list.innerHTML = ''; const friends = document.querySelectorAll("#friends-tabfriendlist .tabrow") || []; friends.forEach(row => { const friendId = row.dataset.playeruid; const friendName = row.querySelector(".playername")?.innerText || "Desconocido"; if (friendId === currentUser.id) return; const li = document.createElement('li'); li.innerHTML = `<span>${friendName}</span><button class="btn btn-sm invite-btn"><i class="fas fa-plus"></i></button>`; li.title = `Invitar a ${friendName} a un grupo`; li.onclick = () => invitarAmigo(friendId, friendName); list.appendChild(li); }); } function renderGroupList() { const list = document.getElementById('group-list'); if (!list) return; list.innerHTML = ''; for (const nombreGrupo in grupos) { const li = document.createElement('li'); li.dataset.grupo = nombreGrupo; if (nombreGrupo === activeChatGroup) li.classList.add('active'); const groupNameSpan = document.createElement('span'); groupNameSpan.textContent = nombreGrupo; groupNameSpan.onclick = () => selectGroupChat(nombreGrupo); li.appendChild(groupNameSpan); const leaveBtn = document.createElement('button'); leaveBtn.innerHTML = '<i class="fas fa-sign-out-alt"></i>'; leaveBtn.className = "btn btn-sm btn-warning"; leaveBtn.title = grupos[nombreGrupo].owner === currentUser.id ? "Eliminar Grupo" : "Abandonar Grupo"; leaveBtn.onclick = (e) => { e.stopPropagation(); if (grupos[nombreGrupo].owner === currentUser.id) { if (confirm(`¿Estás seguro de que quieres ELIMINAR el grupo "${nombreGrupo}"? Esta acción no se puede deshacer.`)) { eliminarGrupo(nombreGrupo); } } else { if (confirm(`¿Estás seguro de que quieres ABANDONAR el grupo "${nombreGrupo}"?`)) { dejarGrupo(nombreGrupo); } } }; li.appendChild(leaveBtn); list.appendChild(li); } } function selectGroupChat(nombreGrupo) { stopBotSimulation(); hideTypingIndicator(); activeChatGroup = nombreGrupo; document.getElementById('chat-window-title').textContent = `Chat: ${nombreGrupo}`; renderGroupList(); renderChatView(); document.getElementById('chat-input-area').style.display = 'flex'; startBotSimulation(); } function renderChatView() { const chatView = document.getElementById('chat-view'); if (!chatView) return; chatView.innerHTML = ''; const history = chatHistory[activeChatGroup] || []; history.forEach(msg => { const sender = grupos[activeChatGroup]?.members.find(m => m.id === msg.senderId); const senderName = msg.senderId === currentUser.id ? 'Tú' : (sender?.name || 'Ex-miembro'); const msgDiv = document.createElement('div'); if (msg.senderId === 'system') { msgDiv.className = `chat-message system`; msgDiv.innerHTML = `<div class="text">${escapeHTML(msg.text)}</div>`; } else { msgDiv.className = `chat-message ${msg.senderId === currentUser.id ? 'self' : 'other'}`; msgDiv.innerHTML = `<div class="sender">${senderName}</div><div class="text">${escapeHTML(msg.text)}</div>`; } chatView.appendChild(msgDiv); }); chatView.scrollTop = chatView.scrollHeight; } function escapeHTML(str) { const p = document.createElement("p"); p.appendChild(document.createTextNode(str)); return p.innerHTML; } function crearGrupo() { const nombre = document.getElementById('new-group-name')?.value.trim(); if (nombre && !grupos[nombre]) { grupos[nombre] = { owner: currentUser.id, members: [{ id: currentUser.id, name: currentUser.name }] }; localStorage.setItem("grupos_v3", JSON.stringify(grupos)); document.getElementById('new-group-name').value = ''; renderGroupList(); selectGroupChat(nombre); addSystemMessage(nombre, `"${nombre}" fue creado por ${currentUser.name}.`); } else if (nombre && grupos[nombre]) { alert(`El grupo "${nombre}" ya existe.`); } } function eliminarGrupo(nombreGrupo) { addSystemMessage(nombreGrupo, `${currentUser.name} eliminó el grupo "${nombreGrupo}".`); setTimeout(() => { delete grupos[nombreGrupo]; delete chatHistory[nombreGrupo]; localStorage.setItem("grupos_v3", JSON.stringify(grupos)); localStorage.setItem("chatHistory_v3", JSON.stringify(chatHistory)); if (activeChatGroup === nombreGrupo) { activeChatGroup = null; stopBotSimulation(); hideTypingIndicator(); } renderGroupList(); renderChatView(); document.getElementById('chat-input-area').style.display = 'none'; document.getElementById('chat-window-title').textContent = 'Chat de Drawaria.online'; }, 100); } function dejarGrupo(nombreGrupo) { addSystemMessage(nombreGrupo, `${currentUser.name} ha abandonado el grupo "${nombreGrupo}".`); setTimeout(() => { grupos[nombreGrupo].members = grupos[nombreGrupo].members.filter(m => m.id !== currentUser.id); if (!grupos[nombreGrupo].members.length) { delete grupos[nombreGrupo]; delete chatHistory[nombreGrupo]; } localStorage.setItem("grupos_v3", JSON.stringify(grupos)); localStorage.setItem("chatHistory_v3", JSON.stringify(chatHistory)); if (activeChatGroup === nombreGrupo) { activeChatGroup = null; stopBotSimulation(); hideTypingIndicator(); } renderGroupList(); renderChatView(); document.getElementById('chat-input-area').style.display = 'none'; document.getElementById('chat-window-title').textContent = 'Chat de Drawaria.online'; }, 100); } function invitarAmigo(friendId, friendName) { if (!activeChatGroup) { alert("Selecciona un grupo primero para invitar amigos."); return; } const grupo = grupos[activeChatGroup]; if (!grupo) { alert("El grupo seleccionado no existe."); return; } if (!grupo.members.some(m => m.id === friendId)) { grupo.members.push({ id: friendId, name: friendName }); localStorage.setItem("grupos_v3", JSON.stringify(grupos)); renderGroupList(); addSystemMessage(activeChatGroup, `${currentUser.name} invitó a ${friendName} al grupo.`); renderChatView(); startBotSimulation(); } else { alert(`${friendName} ya es miembro de este grupo.`); } } function enviarMensajeActual() { const input = document.getElementById('chat-input'); const text = input?.value.trim(); if (text && activeChatGroup) { const msg = { senderId: currentUser.id, text, timestamp: Date.now() }; chatHistory[activeChatGroup] = chatHistory[activeChatGroup] || []; chatHistory[activeChatGroup].push(msg); localStorage.setItem("chatHistory_v3", JSON.stringify(chatHistory)); input.value = ''; renderChatView(); startBotSimulation(true); // Pasa 'true' para indicar una respuesta inmediata } } function addSystemMessage(groupName, messageText) { if (!chatHistory[groupName]) chatHistory[groupName] = []; chatHistory[groupName].push({ senderId: "system", text: messageText, timestamp: Date.now() }); localStorage.setItem("chatHistory_v3", JSON.stringify(chatHistory)); } // --- FUNCIONALIDAD DEL BOT DE DEMOSTRACIÓN (CON TYPING INDICATOR) --- function displayTypingIndicator(username) { const indicator = document.getElementById('typing-indicator'); const typingUsername = document.getElementById('typing-username'); if (indicator && typingUsername && activeChatGroup) { typingUsername.textContent = username; indicator.style.display = 'block'; const chatView = document.getElementById('chat-view'); chatView.scrollTop = chatView.scrollHeight; } } function hideTypingIndicator() { const indicator = document.getElementById('typing-indicator'); if (indicator) { indicator.style.display = 'none'; } } function stopBotSimulation() { if (botMessageTimer) { clearTimeout(botMessageTimer); botMessageTimer = null; } if (typingIndicatorTimer) { clearTimeout(typingIndicatorTimer); typingIndicatorTimer = null; } hideTypingIndicator(); } function startBotSimulation(immediateResponse = false) { stopBotSimulation(); if (!activeChatGroup || !grupos[activeChatGroup]) return; const currentGroup = grupos[activeChatGroup]; const otherMembers = currentGroup.members.filter(m => m.id !== currentUser.id); if (otherMembers.length === 0) { return; } const randomMember = otherMembers[Math.floor(Math.random() * otherMembers.length)]; const delayBeforeTyping = immediateResponse ? Math.random() * 800 + 300 : // 0.3 a 1.1 segundos si es una respuesta inmediata Math.random() * (BOT_MESSAGE_DELAY_MAX - BOT_MESSAGE_DELAY_MIN) + BOT_MESSAGE_DELAY_MIN; const typingDuration = Math.random() * (TYPING_DURATION_MAX - TYPING_DURATION_MIN) + TYPING_DURATION_MIN; botMessageTimer = setTimeout(() => { if (activeChatGroup === currentGroup.name) { displayTypingIndicator(randomMember.name); typingIndicatorTimer = setTimeout(() => { hideTypingIndicator(); if (activeChatGroup === currentGroup.name) { const randomMessage = BOT_MESSAGES[Math.floor(Math.random() * BOT_MESSAGES.length)]; const msg = { senderId: randomMember.id, text: randomMessage, timestamp: Date.now() }; chatHistory[activeChatGroup].push(msg); localStorage.setItem("chatHistory_v3", JSON.stringify(chatHistory)); renderChatView(); } startBotSimulation(); }, typingDuration); } }, delayBeforeTyping); } })();