您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add an option to copy the public room link to the context menu of the friends list in Drawaria.online.
// ==UserScript== // @name Drawaria Copy Room Friend List // @namespace http://tampermonkey.net/ // @version 1.3 // @description Add an option to copy the public room link to the context menu of the friends list in Drawaria.online. // @author YouTubeDrawaria // @match https://drawaria.online/* // @grant none // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online // ==/UserScript== (function() { 'use strict'; if (typeof jQuery === 'undefined') { console.error("jQuery no está disponible. El script no se ejecutará."); return; } // Función para manejar la copia del enlace de la sala async function copyRoomLink(playerUid, $button) { // Guarda el contenido original del botón/enlace para restaurarlo después const originalContent = $button.html(); // Muestra un indicador de carga/trabajo y deshabilita el botón temporalmente $button.html('<i class="fas fa-spinner fa-spin"></i>').addClass('disabled'); try { // Replicar la llamada a la API que friends.js hace para obtener la sala const response = await new Promise((resolve, reject) => { jQuery.post("/friendsapi/getfriendroom", { uid: playerUid }, function(data) { if (data && !data.error) { resolve(data.res); // Si es pública, devuelve el ID de la sala } else { // Si hay un error, rechaza con el mensaje de error o un error genérico reject(data ? data.error : "Unknown error"); } }, "json").fail(function(jqXHR, textStatus, errorThrown) { // Manejo de errores de red o del servidor reject(textStatus || errorThrown); }); }); // Si la respuesta es un ID de sala válido (no '1', que indica sala privada) if (response && response !== 1) { // '1' es el código para "habitación privada" según friends.js const roomLink = `https://drawaria.online/room/${response}`; await navigator.clipboard.writeText(roomLink); // Feedback visual de éxito $button.html('<i class="fas fa-check"></i>').removeClass('disabled'); console.log(`Enlace de sala copiado: ${roomLink}`); } else if (response === 1) { // Caso específico para sala privada $button.html('<i class="fas fa-times"></i>').removeClass('disabled'); // Icono de error console.log("Este jugador está en una sala privada. No se puede copiar el enlace."); } else { // Otros casos de error (jugador no encontrado, etc.) $button.html('<i class="fas fa-times"></i>').removeClass('disabled'); // Icono de error console.log("No se pudo obtener el enlace de la sala. El jugador podría estar desconectado o en un estado no unible."); } } catch (error) { console.error("Error al copiar el enlace de la sala:", error); $button.html('<i class="fas fa-times"></i>').removeClass('disabled'); // Icono de error } finally { // Restaura el contenido original del botón después de un breve retraso setTimeout(() => { $button.html(originalContent).removeClass('disabled'); }, 2000); } } // Cuando el DOM esté completamente cargado jQuery(function() { const $friendMenu = jQuery("#tabfriendlist-rowmenu"); if ($friendMenu.length) { // Crea el nuevo elemento del menú para "Copiar Enlace de Sala" const $copyRoomItem = jQuery( `<a class="dropdown-item" href="#" id="tabfriendlist-rowmenu-copyroom">Copiar Enlace de Sala <i class="fas fa-copy" style="margin-left: 5px;"></i></a>` ); // Inserta el nuevo elemento justo después de "Join room" y añade un nuevo divisor $friendMenu.find("#tabfriendlist-rowmenu-joinroom").after( $copyRoomItem, `<div class="dropdown-divider" id="divider-copyroom-link"></div>` // Nuevo divisor ); // Adjunta el event listener al nuevo elemento del menú $copyRoomItem.on("click", function(event) { event.preventDefault(); // Previene el comportamiento predeterminado del enlace event.stopPropagation(); // Detiene la propagación para evitar que el menú se cierre inmediatamente const $targetRow = $friendMenu.data("target"); // Este es el elemento .tabrow del amigo if ($targetRow && !$copyRoomItem.hasClass('disabled')) { // Solo procede si el botón no está deshabilitado const playerUid = $targetRow.data("playeruid"); copyRoomLink(playerUid, $copyRoomItem); } }); // Escucha cuándo se muestra el menú desplegable para habilitar/deshabilitar la opción $friendMenu.on("show.bs.dropdown", function() { const $joinRoomItem = $friendMenu.find("#tabfriendlist-rowmenu-joinroom"); const $targetRow = $friendMenu.data("target"); // El elemento .tabrow del amigo if ($targetRow && $targetRow.hasClass('inroom')) { // Si el amigo está en una sala, verifica si la opción "Join room" está activa (no disabled) if (!$joinRoomItem.hasClass('disabled')) { // Si "Join room" NO está deshabilitado, es una sala pública $copyRoomItem.removeClass("disabled").css("cursor", "pointer"); $copyRoomItem.show(); // Asegura que el botón sea visible $friendMenu.find("#divider-copyroom-link").show(); } else { // Está en sala, pero "Join room" está deshabilitado, lo que implica sala privada $copyRoomItem.addClass("disabled").css("cursor", "not-allowed"); $copyRoomItem.show(); // Mostrarlo pero deshabilitado $friendMenu.find("#divider-copyroom-link").show(); } } else { // Si el amigo no está en una sala, deshabilita y oculta la opción $copyRoomItem.addClass("disabled").css("cursor", "not-allowed"); $copyRoomItem.hide(); // Oculta el botón si no está en una sala $friendMenu.find("#divider-copyroom-link").hide(); } }); // Restablece el estado del botón cuando el menú se oculta $friendMenu.on('hidden.bs.dropdown', function () { $copyRoomItem.html('Copy Room Link <i class="fas fa-copy" style="margin-left: 5px;"></i>'); $copyRoomItem.removeClass('disabled'); }); } else { console.warn("No se encontró el elemento #tabfriendlist-rowmenu. El script no funcionará como se espera."); } }); // --- Esperar a que jQuery esté disponible --- function waitForjQuery(callback) { if (typeof window.jQuery !== 'undefined') { callback(window.jQuery); } else { setTimeout(() => waitForjQuery(callback), 50); } } waitForjQuery(function($) { // jQuery ($) está garantizado aquí. // Función para obtener el UID de la URL de la página de perfil actual function getProfileUidFromUrl() { const urlParams = new URLSearchParams(window.location.search); return urlParams.get('uid'); } // Función para manejar la copia del enlace de la sala async function copyRoomLink(playerUid, $button) { if (!playerUid) { console.error("No se proporcionó el UID del jugador para copiar el enlace de la sala."); return; } // Guarda el contenido original del botón para restaurarlo después const originalContent = $button.html(); // Muestra un indicador de carga/trabajo y deshabilita el botón temporalmente $button.html('<i class="fas fa-spinner fa-spin"></i>').prop('disabled', true); // .prop('disabled', true) para botones HTML try { const response = await new Promise((resolve, reject) => { $.post("/friendsapi/getfriendroom", { uid: playerUid }, function(data) { if (data && !data.error) { resolve(data.res); } else { reject(data ? data.error : "Unknown error"); } }, "json").fail(function(jqXHR, textStatus, errorThrown) { reject(textStatus || errorThrown); }); }); if (response && response !== 1) { // '1' es el código para "habitación privada" const roomLink = `https://drawaria.online/room/${response}`; await navigator.clipboard.writeText(roomLink); $button.html('<i class="fas fa-check"></i>'); // Icono de éxito console.log(`Enlace de sala copiado: ${roomLink}`); } else if (response === 1) { $button.html('<i class="fas fa-times"></i>'); // Icono de error console.log("Este jugador está en una sala privada. No se puede copiar el enlace."); } else { $button.html('<i class="fas fa-times"></i>'); // Icono de error console.log("No se pudo obtener el enlace de la sala. El jugador podría estar desconectado o en un estado no unible."); } } catch (error) { console.error("Error al copiar el enlace de la sala:", error); $button.html('<i class="fas fa-times"></i>'); // Icono de error } finally { // Restaura el contenido original del botón y habilita después de un breve retraso setTimeout(() => { $button.html(originalContent).prop('disabled', false); }, 2000); } } // Función para inicializar el botón flotante en páginas de perfil function initFloatingCopyButton() { // Solo agregar el botón si estamos en una URL de perfil if (!window.location.pathname.startsWith('/profile/')) { return; } const profileUid = getProfileUidFromUrl(); if (!profileUid) { console.warn("No se pudo obtener el UID del perfil de la URL. El botón flotante no se agregará."); return; } // Evitar duplicados si el script se recarga por alguna razón if ($("#floating-copy-room-button").length > 0) { return; } const $floatingButton = $(` <button id="floating-copy-room-button" style=" position: fixed; bottom: 20px; right: 20px; background-color: #007bff; /* Color azul de Bootstrap primary */ color: white; border: none; border-radius: 50%; width: 50px; height: 50px; font-size: 24px; display: flex; justify-content: center; align-items: center; cursor: pointer; box-shadow: 0 4px 8px rgba(0,0,0,0.2); z-index: 1000; opacity: 0.9; transition: opacity 0.3s ease; " title="Copiar Enlace de Sala del Perfil"> <i class="fas fa-copy"></i> </button> `); $('body').append($floatingButton); $floatingButton.on('click', function() { copyRoomLink(profileUid, $floatingButton); }); // Pequeño efecto hover $floatingButton.hover( function() { $(this).css('opacity', '1'); }, function() { $(this).css('opacity', '0.9'); } ); } // Cuando el DOM esté completamente cargado $(function() { // Llamamos a esta función sin importar la URL, ella misma se encargará de la comprobación initFloatingCopyButton(); }); }); })();