Carga un subscript en el contexto del script actual. El archivo debe estar en la misma carpeta del script.
print("cargando helpers.js...");
include("helpers.js");
API de scripting estilo cb0t/Ares para personalizar el comportamiento de cada sala. Los scripts viven en scripts/{roomId}/{nombre}/{nombre}.js y se ejecutan en un contexto aislado sin acceso a módulos del sistema.
async, await, Promise, setImmediate, queueMicrotask.scripts/{roomId}/{nombre}/data/.require, process, global, fetch, XMLHttpRequest, WebSocket.Carga un subscript en el contexto del script actual. El archivo debe estar en la misma carpeta del script.
print("cargando helpers.js...");
include("helpers.js");
Incluye todos los archivos .js presentes en la carpeta del script.
print("cargando todos los subscripts...");
includeAll();
Envía texto de anuncio a todos, a un vroom o a un usuario específico. No renderiza HTML. Acepta códigos de color: \x03 para color de fuente, \x05 para fondo, seguidos de dos dígitos (00=blanco … 15=gris claro). Formatos: \x06 negrita · \x07 subrayado · \x09 cursiva.
// a todos los usuarios
print("hola");
// solo al vroom 0
print(0, "hola");
// a un usuario específico
print(user(0), "hola");
// con color (rojo=04, verde=03, azul=02, negrita=\x06)
print("\x0304texto en rojo");
print("\x06texto en negrita\x06");
Devuelve el nombre de la carpeta del script en ejecución.
print("este script se llama " + scriptName());
Envía un mensaje de emote público. Si target es un usuario válido, solo él lo recibe; si es null o no se resuelve, se hace broadcast.
// a un usuario específico
sendEmote(user(0), Room.botName, "hola");
// broadcast
sendEmote(null, Room.botName, "aparece misteriosamente");
Envía un mensaje privado a un usuario específico.
sendPM(user(0), Room.botName, "mensaje privado");
Envía un mensaje público. Si target no se resuelve, se hace broadcast.
// a un usuario
sendText(user(0), Room.botName, "hola");
// broadcast
sendText(null, Room.botName, "hola sala");
Devuelve el timestamp Unix en milisegundos (equivalente a Date.now()).
var ticks = tickCount();
Busca un usuario por ID numérico, nombre exacto o subcadena de nombre. Devuelve null si no se encuentra.
var u = user(0); // por ID
var u = user("anon"); // por nombre o subcadena
Codifica texto a Base64.
var encoded = Base64.encode("hola mundo");
Decodifica una cadena Base64 a texto UTF-8.
var decoded = Base64.decode(encoded);
Indica si hay una base de datos de canales disponible. Siempre devuelve false en este servidor.
Indica si la búsqueda de salas está activada. Siempre devuelve false en este servidor.
Los archivos se guardan en scripts/{roomId}/{nombre}/data/. Las rutas se validan; no se puede salir de esa carpeta.
Guarda el contenido de una cadena en un archivo (sobreescribe si ya existe). Crea la carpeta data/ si no existe.
File.save("config.txt", "valor=123");
Carga el contenido de un archivo como cadena. Devuelve null si el archivo no existe.
var str = File.load("config.txt");
if (str != null) print(str);
Indica si un archivo de datos existe.
if (!File.exists("config.txt"))
print("archivo no encontrado");
Elimina un archivo de datos.
File.kill("temporal.txt");
Agrega texto al final de un archivo (lo crea si no existe).
File.append("log.txt", "nueva entrada\n");
Indica si el servidor tiene soporte de linking. Siempre devuelve false en este servidor.
Indica si el servidor está conectado a un hub. Siempre devuelve false en este servidor.
Almacena pares clave/valor como strings, persistidos en registry.json dentro de la carpeta del script. Los valores siempre se convierten a string al guardar.
Obtiene el valor de una clave. Devuelve null si no existe.
var valor = Registry.getValue("puntos");
print(valor);
Establece el valor de una clave. El valor se convierte a string automáticamente.
Registry.setValue("puntos", "100");
Elimina una clave del registro.
Registry.deleteValue("puntos");
Indica si una clave existe en el registro.
if (Registry.exists("puntos"))
print("la clave existe");
Devuelve un array con todas las claves del registro del script.
var keys = Registry.getKeys();
for (var i = 0; i < keys.length; i++)
print(keys[i] + " = " + Registry.getValue(keys[i]));
Elimina todas las entradas del registro.
Registry.clear();
Nombre de la sala, usado como nombre del bot.
print("el bot se llama " + Room.botName);
Nombre de la sala. Equivale a Room.botName.
Tema principal de la sala. Al asignarlo se notifica a todos los usuarios.
Room.topic = "bienvenidos";
print("tema actual: " + Room.topic);
Timestamp Unix en segundos del momento en que se cargó el script.
print("iniciado: " + new Date(Room.startTime * 1000));
Versión del modelo de objetos del servidor. Devuelve 1.
No disponibles en este servidor. externalIp y hashlink devuelven cadena vacía; port devuelve 0.
Obtiene o establece si los usuarios pueden tener nombres personalizados. Leer siempre devuelve true.
Room.customNames = true;
Agrega una entrada de URL al tag de la sala.
Room.setUrl("https://ejemplo.com", "mi sitio");
Limpia el tag de URL de la sala.
Room.clearUrl();
Envía una imagen scribble a todos los usuarios del vroom 0.
var img = new Scribble().load("imagen.jpg");
Room.scribble(img);
Envía un audio a todos los usuarios del vroom 0.
var audio = new Audio().load("sonido.mp3");
Room.audio(audio);
Indica si el corrector ortográfico está disponible. Siempre devuelve false en este servidor.
Indica si el servidor soporta hashlinks. Siempre devuelve false en este servidor.
Todas las propiedades son de solo lectura y devuelven double.
Usuarios actualmente conectados.
Total de mensajes públicos recibidos.
Total de usuarios que se han conectado.
Total de usuarios que se han desconectado.
Pico máximo de usuarios conectados simultáneamente.
Bytes totales enviados por el servidor.
Bytes totales recibidos por el servidor.
Cantidad de usuarios expulsados por flood.
Cantidad de mensajes privados recibidos.
Cantidad de usuarios rechazados al intentar unirse.
Cantidad de intentos de login fallidos.
print("usuarios: " + Stats.userCount + " / pico: " + Stats.peakUserCount);
Ejecuta una función para cada usuario local conectado.
Users.local(function (u) {
u.sendText("hola " + u.name);
});
Ejecuta una función para cada usuario en la lista de baneados.
Users.banned(function (u) {
if (u.name.indexOf("anon") == 0)
u.unban();
});
Ejecuta una función para cada cuenta registrada en la sala.
Users.records(function (u) {
print(u.guid);
});
Itera sobre usuarios enlazados. No disponible (stub) en este servidor.
Comprime una cadena usando deflate y devuelve el resultado en Base64.
var c = Zip.compress("texto largo...");
Descomprime una cadena Base64 comprimida con deflate.
var original = Zip.uncompress(c);
Convierte &, <, >, " a entidades HTML.
var safe = Entities.encode("<script>alert(1)</script>");
Convierte entidades HTML de vuelta a caracteres (&→&, <→<, >→>, "→").
var text = Entities.decode("<b>hola</b>");
Calcula el hash MD5 de una cadena. Devuelve un CryptoResult.
var hash = Crypto.md5hash("hola mundo");
print(hash.toHex);
Calcula el hash SHA-1 de una cadena. Devuelve un CryptoResult.
var hash = Crypto.sha1hash("hola mundo");
print(hash.toBase64);
Obtenido mediante userobj.avatar.
Devuelve true si el objeto contiene un avatar válido.
if (userobj.avatar.exists)
print(userobj.name + " tiene avatar");
Guarda el avatar del usuario como archivo binario en la carpeta data/ del script. Devuelve false si el usuario no tiene avatar.
function onJoin(userobj) {
if (userobj.avatar.exists)
userobj.avatar.save("avatar_" + userobj.name + ".bin");
}
Convierte el avatar en un objeto { __data, exists } compatible con Room.scribble() y userobj.scribble(). Devuelve { __data: null, exists: false } si el usuario no tiene avatar.
function onJoin(userobj) {
if (userobj.avatar.exists)
Room.scribble(userobj.avatar.toScribble());
}
Obtenido mediante Users.banned(fn).
Nombre del usuario baneado.
GUID del usuario baneado.
IP del usuario baneado. Ambas devuelven el mismo valor en este servidor.
Puerto. Devuelve 0 en este servidor.
Versión del cliente. Devuelve cadena vacía en este servidor.
Desbanea al usuario.
Users.banned(function (u) { u.unban(); }); // desbanear todos
Devuelto por Crypto.md5hash() y Crypto.sha1hash().
Hash como cadena hexadecimal.
Hash como cadena Base64.
Hash como array de bytes.
var h = Crypto.sha1hash("clave");
print(h.toHex);
print(h.toBase64);
print(h.toArray.join(","));
Objeto recibido en el callback oncomplete de HttpRequest cuando la descarga tiene éxito. Si hay error, el callback recibe false.
El contenido descargado de la URL.
El argumento pasado a download(arg).
Obtenido mediante userobj.ignores. Cada elemento tiene una propiedad name y un método toString().
Número de usuarios ignorados.
var ig = userobj.ignores;
for (var i = 0; i < ig.length; i++)
print("ignorando a " + ig[i].name);
Cuentas registradas en la sala. Se itera con Users.records(fn).
GUID del usuario registrado. Los demás campos dependen de los datos almacenados en la cuenta.
Array de strings devuelto por Registry.getKeys().
var keys = Registry.getKeys();
for (var i = 0; i < keys.length; i++)
print(keys[i] + " = " + Registry.getValue(keys[i]));
Obtenido mediante user(), Users.local() o desde eventos. Todos los usuarios son clientes web en este servidor — webClient siempre devuelve true y externalIp/localIp devuelven el mismo valor.
Nombre del usuario. Al asignarlo se notifica el cambio a todos los usuarios de la sala.
user(0).name = "nuevonombre";ID numérico único de la sesión actual.
Identificador único persistente del usuario.
Nivel de administrador (0=invitado, 1=moderador, 2=admin, 3+=owner). Al asignarlo se notifica a todos.
user(0).level = 1; // dar moderadorSala virtual actual del usuario.
true si el usuario está en estado inactivo.
Dirección IP del usuario. Ambas devuelven el mismo valor en este servidor.
Timestamp Unix (ms) del momento en que el usuario se conectó. Devuelve 0 si no está disponible.
Mensaje personal del usuario. Al asignarlo se notifica a todos.
Nombre personalizado del usuario.
true si el usuario tiene level ≥ 3.
true si el usuario tiene cuenta registrada en esta sala.
Colección de nombres ignorados por este usuario.
Avatar del usuario. Asignar null restaura el avatar por defecto de la sala.
user(0).avatar = null;Nombre original del usuario. Igual a name en este servidor.
Siempre true — todos los usuarios son clientes web en este servidor.
Siempre devuelven cadena vacía en este servidor.
Siempre devuelven 0 en este servidor.
linked, browsable, fastPing, ghost, customClient siempre devuelven false. visible siempre devuelve true.
Indica si el usuario está silenciado. Sus mensajes llegan solo a usuarios con nivel > 0; los demás no los ven. Al enviar un mensaje, el usuario silenciado recibe una notificación de bloqueo.
user(0).muzzled = true; // silenciar
user(0).muzzled = false; // desilenciar
Stub — siempre devuelve false; asignar no tiene efecto en este servidor.
Banea al usuario y lo desconecta.
user(0).ban();Desconecta al usuario.
user(0).disconnect();Envía un anuncio de sistema (texto de servidor) visible solo para este usuario. A diferencia del sendText global, aquí no se especifica remitente.
user(0).sendText("solo tú ves este mensaje");
Envía un emote privado a este usuario, con el nombre de la sala como remitente.
user(0).sendEmote("hola mundo");
Envía un mensaje privado desde la sala (bot) a este usuario.
user(0).sendPM("mensaje privado desde el bot");
Establece el tema de la sala y lo notifica a todos los usuarios.
user(0).setTopic("nuevo tema");
Agrega una URL a la lista de URLs de la sala.
user(0).setUrl("https://ejemplo.com", "enlace");
Envía un scribble privado a este usuario. El remitente es el nombre de la sala.
var img = new Scribble().load("imagen.jpg");
user(0).scribble(img);
Envía audio a todos los usuarios del mismo vroom que este usuario. El remitente es el nombre de la sala.
var audio = new Audio().load("sonido.mp3");
user(0).audio(audio);
Stubs — no tienen efecto en este servidor.
Carga un archivo de audio desde la carpeta data/ del script o lo descarga desde una URL. Usar con Room.audio() o userobj.audio().
Carga un archivo desde la carpeta data/. Devuelve la misma instancia para encadenar.
function onJoin(userobj) {
var audio = new Audio().load("bienvenida.mp3");
Room.audio(audio);
}
URL del audio a descargar. Se usa junto con download().
Callback ejecutado al terminar la descarga. Si fue exitosa, this.__data contiene los datos en Base64. Si falló, this.__data es null.
Descarga el audio desde la URL en src. Sujeto a los mismos límites que HttpRequest (máx 5 concurrentes, 10 s timeout, 1 MB). Devuelve false si se alcanzó el límite de concurrencia.
var snd = new Audio();
snd.src = "https://ejemplo.com/sonido.mp3";
snd.oncomplete = function () {
if (this.__data) Room.audio(this);
};
snd.download();
Máximo 5 solicitudes concurrentes por script · timeout 10 s · límite 1 MB por respuesta. Soporta HTTP y HTTPS.
var http = new HttpRequest();
http.src = "https://api.ejemplo.com/datos";
http.oncomplete = function (e) {
if (e)
print(e.page);
else
print("error en la solicitud");
};
http.download();
URL de la solicitud.
Método HTTP: "GET" (por defecto) o "POST".
Cuerpo de la solicitud para POST.
Encabezado Accept.
Encabezado User-Agent.
Encabezado Host.
Codificación de la respuesta: true para UTF-8 (por defecto), false para Latin-1.
Callback ejecutado al terminar. Recibe false en error, o un objeto { page, arg } en éxito.
Agrega un encabezado HTTP personalizado.
http.header("Authorization", "Bearer mi_token");
Inicia la descarga. El argumento opcional se pasa de vuelta en e.arg del callback.
http.download(); // sin arg
http.download("dato"); // con arg
Colección dinámica de elementos mixtos con acceso por índice numérico (list[0]).
var lista = new List();
lista.addRange(1, 2, 3, 4, 5);
lista.removeAll(function (q) { return q > 3; });
print(lista.join(", ")); // "1, 2, 3"
Agrega un elemento al final. Devuelve el nuevo tamaño.
Agrega múltiples elementos al final.
Elimina todos los elementos.
Número de elementos en la lista.
Primer elemento que cumple la condición, o null.
Nueva List con todos los elementos que cumplen la condición.
Índice del primer elemento que cumple la condición (-1 si no se encuentra).
Índice del último elemento que cumple la condición.
Sublista desde start de longitud count.
Índice de la primera ocurrencia del elemento.
Índice de la última ocurrencia del elemento.
Inserta un elemento en la posición indicada.
Inserta múltiples elementos a partir de la posición indicada.
Elimina la primera ocurrencia del elemento.
Elimina todos los elementos que cumplen la condición.
Elimina el elemento en la posición indicada.
Elimina count elementos a partir de start.
Invierte el orden de la lista en su lugar.
Ordena la lista según una función de comparación.
lista.sort(function (x, y) { return x > y ? 1 : x < y ? -1 : 0; });
Une todos los elementos con un separador. Por defecto usa coma.
print(lista.join(":")); // "1:2:3"
Devuelve una copia de los elementos como array nativo de JavaScript.
Carga una imagen desde la carpeta data/ del script o la descarga desde una URL. Usar con Room.scribble() o userobj.scribble().
Carga un archivo de imagen desde la carpeta data/. Devuelve la misma instancia para encadenar.
function onJoin(userobj) {
var img = new Scribble().load("bienvenida.jpg");
Room.scribble(img);
}
URL de la imagen a descargar. Se usa junto con download().
Callback ejecutado al terminar la descarga. Si la descarga fue exitosa, this.__data contiene los datos en Base64. Si falló, this.__data es null.
Descarga la imagen desde la URL en src. Sujeto a los mismos límites que HttpRequest (máx 5 concurrentes, 10 s timeout, 1 MB). Devuelve false si se alcanzó el límite de concurrencia.
var img = new Scribble();
img.src = "https://ejemplo.com/imagen.png";
img.oncomplete = function () {
if (this.__data) Room.scribble(this);
};
img.download();
Máximo 20 timers activos por script. Los timers se detienen automáticamente cuando el script se descarga.
var ciclos = 0;
var timer = new Timer();
timer.interval = 2000;
timer.oncomplete = function () {
print("tick " + (++ciclos));
if (ciclos >= 10)
timer.stop();
else
timer.start();
};
timer.start();
Intervalo en milisegundos. Por defecto: 1000.
Función ejecutada en cada intervalo.
Inicia el timer. Si ya estaba activo, lo reinicia.
Detiene el timer y lo elimina de la cuenta de timers activos.
Define estas funciones en tu script para reaccionar a eventos de la sala. Los eventos booleanos devuelven true para permitir y false para cancelar. Los eventos de transformación de texto devuelven un string modificado, false para cancelar, o nada para pasar el texto sin cambios.
// ── Ciclo de vida del script ──────────────────────────────────────────────
// Se ejecuta cuando el script termina de cargarse
function onLoad() { }
// Se ejecuta cada 1 segundo en todos los scripts
function onTimer() { }
// ── Usuarios: entrada y salida ────────────────────────────────────────────
// Antes de permitir que un usuario se una. Retornar false para rechazarlo.
function onJoinCheck(userobj) { return true; }
// Después de que un usuario se une
function onJoin(userobj) { }
// Cuando un usuario es rechazado al intentar unirse
function onRejected(userobj) { }
// Antes de que un usuario se desconecte
function onPartBefore(userobj) { }
// Después de que un usuario se desconecta
function onPart(userobj) { }
// ── Mensajes de texto público ─────────────────────────────────────────────
// Cuando se recibe texto público (sin alterar)
function onTextReceived(userobj, text) { }
// Antes de mostrar texto público.
// Retornar string para modificarlo, false para cancelarlo, o nada para dejarlo pasar.
function onTextBefore(userobj, text) { return text; }
// Después de mostrar texto público
function onTextAfter(userobj, text) { }
// ── Mensajes de emote ─────────────────────────────────────────────────────
// Cuando se recibe un emote (sin alterar)
function onEmoteReceived(userobj, text) { }
// Antes de mostrar un emote. Mismo comportamiento que onTextBefore.
function onEmoteBefore(userobj, text) { return text; }
// Después de mostrar un emote
function onEmoteAfter(userobj, text) { }
// ── Mensajes privados ─────────────────────────────────────────────────────
// Antes de enviar un PM. pm es un objeto modificable:
// pm.contains(str) → bool
// pm.remove(str) → elimina todas las ocurrencias de str
// pm.replace(a, b) → reemplaza todas las ocurrencias de a por b
// Retornar false para cancelarlo.
function onPMBefore(userobj, targetName, pm) { return true; }
// Cuando el bot (la sala) recibe un PM directamente. Retornar false para cancelar.
function onBotPM(userobj, text) { return true; }
// Después de que se muestra un PM
function onPM(userobj, targetName) { }
// ── Comandos ─────────────────────────────────────────────────────────────
// Cuando un usuario usa un comando (/ o #).
// command: nombre en minúsculas (ej. "paint")
// target: segunda palabra del comando
// args: resto del texto
function onCommand(userobj, command, target, args) { }
// Cuando un usuario usa #help
function onHelp(userobj) { }
// ── Perfil de usuario ─────────────────────────────────────────────────────
// Cuando un usuario sube un mensaje personal. Retornar false para cancelarlo.
function onPersonalMessage(userobj, msg) { return true; }
// Cuando un usuario sube un avatar. Retornar false para rechazarlo.
function onAvatar(userobj) { return true; }
// ── Flood ─────────────────────────────────────────────────────────────────
// Antes de expulsar a un usuario por flood. Retornar false para cancelarlo.
function onFloodBefore(userobj, msg) { return true; }
// Después de que un usuario es expulsado por flood
function onFlood(userobj) { }
// ── Ignorar ──────────────────────────────────────────────────────────────
// Antes de que un usuario ignore a alguien. Retornar false para cancelarlo.
function onIgnoring(userobj, targetName) { return true; }
// Después de que cambia el estado de ignorar/designorar.
// ignored=true: ignoró, ignored=false: designoró.
function onIgnoredStateChanged(userobj, targetName, ignored) { }
// ── Login y administración ────────────────────────────────────────────────
// Después de un login exitoso
function onLoginGranted(userobj) { }
// Después de un intento de login fallido
function onInvalidLoginAttempt(userobj) { }
// Después de un logout
function onLogout(userobj) { }
// Cuando cambia el nivel de administrador de un usuario
function onAdminLevelChanged(userobj) { }
// ── Vrooms ───────────────────────────────────────────────────────────────
// Antes de que un usuario cambie de vroom. Retornar false para cancelarlo.
function onVroomJoinCheck(userobj, vroom) { return true; }
// Después de que un usuario cambia de vroom
function onVroomJoin(userobj) { }
// ── Actividad ────────────────────────────────────────────────────────────
// Cuando un usuario pasa a estado inactivo (idle)
function onIdled(userobj) { }
// Cuando un usuario vuelve del estado inactivo.
// seconds = segundos que estuvo inactivo.
function onUnidled(userobj, seconds) { }
// ── Multimedia ───────────────────────────────────────────────────────────
// Cuando un usuario envía un buzz/nudge a otro
function onBuzz(userobj, targetName) { }
// Cuando un usuario envía un scribble a la sala
function onScribble(userobj) { }
// Cuando un usuario envía un audio a la sala
function onAudio(userobj) { }
// Cuando un usuario envía un scribble privado a otro
function onPMScribble(userobj, targetName) { }
// Cuando un usuario envía un audio privado a otro
function onPMAudio(userobj, targetName) { }
Diferencias respecto a la API de referencia cb0t/Ares.
| Característica | Estado | Notas |
|---|---|---|
Channels.search() | No disponible | available y enabled devuelven false |
Link (connect, disconnect, leaf…) | No disponible | available y linked devuelven false |
Spelling (check, confirm, suggest) | No disponible | available devuelve false |
Hashlink (encode, decode) | Stub | Solo expone available: false |
Query · Sql · XmlParser | No disponible | No implementados |
Constructor Avatar | No disponible | Usar Scribble o Audio en su lugar |
User.nudge() · User.redirect() · User.restoreAvatar() · User.sendHTML() | Stub | No tienen efecto |
User.cloaked | Stub | Siempre false; asignar no tiene efecto |
User.muzzled | Disponible | Lectura/escritura funcional |
AvatarImage.save() · .toScribble() | Disponible | Ambos implementados; devuelven false/{ exists:false } si no hay avatar |
onPMBefore — parámetro pm | Extensión | Objeto con .contains(), .remove(), .replace() (modifica el texto antes de enviarlo) |
Room.audio() · User.audio() | Extensión | Envío de audio, no existe en cb0t |
Scribble.download() · Audio.download() | Extensión | Descarga de imagen/audio desde URL, no existe en cb0t |
onBuzz · onScribble · onAudio · onPMScribble · onPMAudio | Extensión | Eventos propios de este servidor |
User.webClient | Siempre true | Todos los usuarios son clientes web |
User.externalIp / localIp | Mismo valor | No se distinguen en este servidor |
Constructor Audio | Disponible | Similar a Scribble |
onLoad · onTimer · onJoin · onPart · onCommand | Disponible | Funcionan igual que en cb0t |
File · Registry · Base64 · Zip · Entities · Crypto | Disponible | API completa disponible |
Timer · List · HttpRequest · Scribble | Disponible | API completa disponible |