Exploring the roots and future of Internet Relay Chat

Scripting en mIRC: guía completa de aliases, eventos, hash tables y sockets

Aprendí a programar con mIRC script. No con C, no con Basic, no con ningún lenguaje "de verdad". Tenía 16 años y quería un bot que protegiera mi canal de floods. Abrí el editor de scripts (Alt+R), copié un ejemplo de un foro, lo modifiqué sin entender nada, y cuando funcionó sentí que había descifrado un código secreto. Veinte años después, programo en Python, Go y Rust. Pero el razonamiento lógico lo aprendí en ese editor de mIRC.

Fundamentos: dónde va el código

mIRC tiene tres secciones de scripting accesibles desde Alt+R (Script Editor):

Aliases: comandos personalizados. Cuando escribes /algo, mIRC busca primero si existe un alias llamado algo. Si existe, lo ejecuta. Si no, lo envía al servidor como comando IRC.

Remote: eventos y respuestas automáticas. Aquí defines qué pasa cuando alguien habla, entra a un canal, te envía un mensaje privado, o cualquier otro evento IRC.

Popups: menús contextuales personalizados. Click derecho en la lista de nicks, en un canal, o en el status — puedes añadir opciones propias.

; === ALIASES (pestaña Aliases) ===
; Se escriben directamente como /nombre

; Alias simple: saludo rápido
alias hola msg $active Hola a todos, ¿qué tal?

; Alias con parámetros: $1 es el primer argumento
; Uso: /saludar Marco
alias saludar msg $active Hey $1 $+ , bienvenido.

; Alias multilínea con lógica
alias info {
  echo -a Servidor: $server
  echo -a Nick: $me
  echo -a Canales: $chan(0)
  echo -a Hora: $time(HH:nn:ss)
}

; === REMOTE (pestaña Remote) ===
; Formato: on NIVEL:EVENTO:PATRON:DONDE:{ código }

; Responder cuando alguien dice "hola" en un canal
on *:TEXT:*hola*:#:{
  msg $chan Hola $nick $+ , ¿cómo vas?
}

; Bienvenida automática al entrar a tu canal
on *:JOIN:#micabal:{
  if ($nick != $me) {
    notice $nick Bienvenido a $chan $+ . Lee el /topic.
  }
}

El punto y coma (;) marca comentarios. Todo lo que sigue en esa línea se ignora. Úsalos generosamente. Tu yo del futuro te lo agradecerá cuando intentes entender un script que escribiste hace tres años a las 2 de la mañana.

Aliases: comandos personalizados

Los aliases son la puerta de entrada al scripting. Empiezas reemplazando comandos largos con atajos, y antes de darte cuenta estás escribiendo funciones complejas con control de flujo.

; Alias con condicionales
alias op {
  if ($me isop $chan) {
    mode $chan +o $1
  }
  else {
    echo -a No tengo op en $chan
  }
}

; Alias que devuelve un valor (función)
; Los aliases que empiezan con $ devuelven valores
alias invertir {
  var %resultado
  var %i = $len($1)
  while (%i > 0) {
    %resultado = %resultado $+ $mid($1,%i,1)
    dec %i
  }
  return %resultado
}
; Uso: //echo -a $invertir(Marco) → ocraM

; Alias con bucle: kickear todos los clones
alias kickclones {
  var %i = 1
  while (%i <= $nick($chan,0)) {
    var %n = $nick($chan,%i)
    if ($count($address(%n,2),$address($1,2)) > 0 && %n != $1) {
      kick $chan %n Clon detectado
    }
    inc %i
  }
}

; Alias con input del usuario
alias pregunta {
  var %respuesta = $$?="¿Cuál es tu ciudad?"
  msg $active Soy de %respuesta
}

El operador $+ concatena sin espacios. Es uno de los operadores más usados en mIRC script. Hola $nick produce "Hola Marco". Hola $nick $+ ! produce "Hola Marco!" — sin el espacio antes de la exclamación. Parece menor, pero si no entiendes $+ tus scripts van a tener espacios raros por todas partes.

Remote events: reaccionar a lo que pasa

Los eventos son donde mIRC script se convierte en algo poderoso. Puedes interceptar y responder a cualquier cosa que ocurra en tu sesión IRC.

; Formato general:
; on NIVEL:EVENTO:FILTRO:DONDE:{ código }
;
; NIVEL: * (todos), número (nivel de acceso)
; EVENTO: TEXT, JOIN, PART, KICK, NICK, MODE, NOTICE, etc.
; FILTRO: patrón de texto (para TEXT)
; DONDE: # (cualquier canal), #canal (canal específico), ? (privado)

; Anti-flood básico: kick si 5+ mensajes en 3 segundos
on *:TEXT:*:#:{
  if (!%flood. [ $+ [ $nick ] ]) {
    set -u3 %flood. [ $+ [ $nick ] ] 1
  }
  else {
    inc %flood. [ $+ [ $nick ] ]
    if (%flood. [ $+ [ $nick ] ] >= 5) {
      kick $chan $nick Flood detectado
      ban $chan $nick 2
      unset %flood. [ $+ [ $nick ] ]
    }
  }
}

; Registrar entradas y salidas
on *:JOIN:#:{
  write logs\ $+ $chan $+ .log [ $date $time ] JOIN: $nick ( $+ $address $+ )
}
on *:PART:#:{
  write logs\ $+ $chan $+ .log [ $date $time ] PART: $nick ( $+ $1- $+ )
}
on *:QUIT:{
  write logs\quit.log [ $date $time ] QUIT: $nick ( $+ $1- $+ )
}

; Responder a CTCP VERSION con respuesta personalizada
ctcp *:VERSION:*:{
  ctcpreply $nick VERSION mIRC con superpoderes v3.0
  halt
}

; Detectar cambio de nick de alguien específico
on *:NICK:{
  if ($nick == EseBot) {
    echo -a ¡Atención! EseBot cambió su nick a $newnick
  }
}

El script anti-flood merece explicación. set -u3 crea una variable que se autodestruye en 3 segundos. Cada vez que un usuario habla, incrementamos su contador. Si llega a 5 en esos 3 segundos, es flood. Cuando la variable se autodestruye (después de 3 segundos sin actividad), el contador vuelve a cero. Es elegante en su simplicidad.

Consejo: El comando halt detiene el procesamiento de eventos. Si tienes múltiples eventos que coinciden con el mismo trigger, el primero que ejecute halt impide que los siguientes se ejecuten. Úsalo en respuestas CTCP para evitar que mIRC envíe su respuesta por defecto además de la tuya.

Variables, identificadores y operadores

Las variables en mIRC script empiezan con %. Hay dos tipos: locales (solo existen dentro del alias o evento donde se crean) y globales (persisten entre sesiones).

; Variables locales: var %nombre
alias ejemplo {
  var %x = 10
  var %nombre = Marco
  echo -a %nombre tiene %x puntos
  ; %x y %nombre dejan de existir al terminar el alias
}

; Variables globales: set %nombre
alias guardar {
  set %puntos.marco 100     ; Persiste hasta que la borres
  set -u60 %temporal algo   ; Se borra sola en 60 segundos
}

; Identificadores: valores de solo lectura
; $nick      → nick del usuario que disparó el evento
; $chan      → canal donde ocurrió
; $me       → tu nick actual
; $server   → servidor conectado
; $time     → hora actual
; $date     → fecha actual
; $rand(a,b) → número aleatorio entre a y b
; $len(texto) → longitud del texto
; $left(texto,n) → primeros n caracteres
; $right(texto,n) → últimos n caracteres
; $mid(texto,pos,n) → n caracteres desde pos
; $upper(texto) → mayúsculas
; $lower(texto) → minúsculas
; $replace(texto,buscar,reemplazo) → sustituir
; $calc(expr) → evaluar expresión matemática

; Ejemplo práctico: dado con cualquier número de caras
alias dado {
  var %caras = $iif($1,$1,6)
  var %resultado = $rand(1,%caras)
  msg $active Lanzas un d $+ %caras y sacas %resultado
}

; $iif es el operador ternario:
; $iif(condición, valor_si_true, valor_si_false)
alias estado {
  msg $active Estoy $iif($away,ausente,disponible)
}

El sistema de evaluación de $calc soporta operaciones matemáticas completas: suma, resta, multiplicación, división, módulo, potencia. $calc(2 ** 10) devuelve 1024. No necesitas librerías externas para matemáticas básicas.

Hash tables: datos en memoria

Las hash tables fueron un cambio radical. Antes, almacenar datos significaba escribir y leer archivos de texto con $read y /write. Lento, frágil, y con problemas de concurrencia. Las hash tables almacenan pares clave-valor en memoria con acceso instantáneo.

; Crear una hash table
hmake puntos 100           ; Nombre: puntos, tamaño: 100 buckets

; Añadir/modificar datos
hadd puntos Marco 250
hadd puntos Lucia 340
hadd puntos Andrea 180

; Leer datos
$hget(puntos, Marco)       ; → 250
$hget(puntos, 0)           ; → 3 (número de items)
$hget(puntos, 0).item      ; → número de items

; Borrar datos
hdel puntos Andrea

; Guardar a disco (persistencia)
hsave puntos puntos.hsh

; Cargar desde disco al iniciar
hmake puntos 100
hload puntos puntos.hsh

; Iterar sobre todos los items
alias listar.puntos {
  var %i = 1
  while ($hget(puntos,%i).item) {
    var %nick = $hget(puntos,%i).item
    var %valor = $hget(puntos,%i).data
    echo -a %nick $+ : %valor puntos
    inc %i
  }
}

; Sistema de puntos completo con hash table
alias puntos.sistema {
  if (!$hget(puntos)) {
    hmake puntos 100
    if ($isfile(puntos.hsh)) { hload puntos puntos.hsh }
  }
}

on *:TEXT:!puntos*:#:{
  puntos.sistema
  if ($2) {
    ; !puntos nick → ver puntos de otro
    var %p = $iif($hget(puntos,$2),$v1,0)
    msg $chan $2 tiene %p puntos.
  }
  else {
    ; !puntos → ver tus propios puntos
    var %p = $iif($hget(puntos,$nick),$v1,0)
    msg $chan $nick $+ : tienes %p puntos.
  }
}

on *:TEXT:!dar *:#:{
  puntos.sistema
  if ($nick isop $chan) {
    var %actual = $iif($hget(puntos,$2),$v1,0)
    hadd puntos $2 $calc(%actual + $3)
    hsave puntos puntos.hsh
    msg $chan $2 ahora tiene $hget(puntos,$2) puntos.
  }
}

El truco de $iif($hget(puntos,$nick),$v1,0) merece explicación. $hget devuelve $null si la clave no existe. $iif evalúa eso como falso y devuelve el valor alternativo (0). $v1 es una variable especial que contiene el resultado de la última evaluación exitosa. Es un patrón que verás en todo script de mIRC que maneje hash tables.

Advertencia: Las hash tables viven en memoria. Si mIRC se cierra sin ejecutar hsave, pierdes todos los cambios desde el último guardado. Usa un timer para guardar periódicamente: .timer 0 300 hsave puntos puntos.hsh guarda cada 5 minutos. También puedes guardar en el evento ON DISCONNECT.

Sockets TCP: más allá del IRC

mIRC puede abrir conexiones TCP arbitrarias. Esto permite crear clientes HTTP, conectar a APIs, o incluso implementar servidores básicos dentro de mIRC.

; Consultar una API HTTP
alias clima {
  if (!$1) { echo -a Uso: /clima ciudad | return }
  sockopen clima wttr.in 80
  set %clima.ciudad $1-
}

on *:SOCKOPEN:clima:{
  sockwrite -n $sockname GET / $+ %clima.ciudad $+ ?format=3 HTTP/1.1
  sockwrite -n $sockname Host: wttr.in
  sockwrite -n $sockname User-Agent: mIRC-Bot/1.0
  sockwrite -n $sockname Connection: close
  sockwrite -n $sockname
}

on *:SOCKREAD:clima:{
  var %linea
  sockread %linea
  ; Buscar la línea con los datos (después de headers HTTP)
  if (%linea && !$regex(%linea,/^(HTTP|Date|Content|Server|Access)/)) {
    if ($len(%linea) > 2) {
      msg $active Clima: %linea
    }
  }
}

on *:SOCKCLOSE:clima:{
  unset %clima.*
}

; Socket listener: servidor básico
alias miservidor {
  socklisten miserver 8080
  echo -a Servidor escuchando en puerto 8080
}

on *:SOCKLISTEN:miserver:{
  var %id = cliente. $+ $ticks
  sockaccept %id
}

on *:SOCKREAD:cliente.*:{
  var %data
  sockread %data
  echo -a Recibido de $sockname $+ : %data
  sockwrite -n $sockname Respuesta desde mIRC
  sockclose $sockname
}

¿Es buena idea implementar un servidor HTTP en mIRC? No. ¿Funciona? Sí. ¿La gente lo hace? Más de lo que imaginas. He visto bots de mIRC que servían páginas web con estadísticas de canal. Técnicamente impresionante, operativamente cuestionable.

Los sockets son útiles para cosas legítimas: consultar APIs de clima, buscar en Google, verificar si un sitio web está online, consultar bases de datos remotas. La limitación es que todo es asíncrono (los eventos SOCKREAD/SOCKOPEN son callbacks) y no hay soporte nativo para HTTPS. Para HTTPS necesitas un proxy local o la librería mIRC-SSL.

Dialogs: interfaces gráficas

mIRC tiene un sistema de diálogos que permite crear ventanas con botones, campos de texto, listas, checkboxes y más. Es como hacer una aplicación Windows dentro de mIRC.

; Definir un diálogo
dialog config {
  title "Configuración del Bot"
  size -1 -1 250 200
  option dbu

  text "Nick del bot:", 1, 10 10 80 10
  edit "", 2, 95 10 140 12

  text "Canal principal:", 3, 10 30 80 10
  edit "", 4, 95 30 140 12

  text "Prefijo de comandos:", 5, 10 50 80 10
  edit "!", 6, 95 50 140 12

  check "Activar anti-flood", 7, 10 70 120 10
  check "Activar logging", 8, 10 85 120 10
  check "Activar puntos", 9, 10 100 120 10

  button "Guardar", 10, 50 170 60 15, ok
  button "Cancelar", 11, 130 170 60 15, cancel
}

; Evento cuando se abre el diálogo
on *:DIALOG:config:init:*:{
  did -a config 2 %bot.nick
  did -a config 4 %bot.canal
  did -a config 6 %bot.prefijo
  if (%bot.antiflood) did -c config 7
  if (%bot.logging) did -c config 8
  if (%bot.puntos) did -c config 9
}

; Evento cuando se pulsa "Guardar"
on *:DIALOG:config:sclick:10:{
  set %bot.nick $did(config,2)
  set %bot.canal $did(config,4)
  set %bot.prefijo $did(config,6)
  set %bot.antiflood $did(config,7).state
  set %bot.logging $did(config,8).state
  set %bot.puntos $did(config,9).state
  echo -a Configuración guardada.
}

; Abrir el diálogo
alias config dialog -m config config

Los diálogos no son bonitos. Usan la API de Windows clásica, así que parecen algo de Windows 98. Pero funcionan. Para scripts que necesitan configuración por parte del usuario, un diálogo es infinitamente mejor que editar variables a mano en el script.

Cuando escribí mi primer diálogo tenía 17 años y me sentía como si hubiera creado una aplicación de escritorio. En cierto sentido, lo había hecho. Era una ventana de Windows con controles interactivos que hacía algo útil. Que estuviera dentro de un cliente IRC era lo de menos.

Preguntas frecuentes

¿Los scripts de mIRC funcionan en versiones recientes?

En general sí. mIRC mantiene muy buena compatibilidad hacia atrás. Scripts escritos para mIRC 6.x generalmente funcionan en mIRC 7.x sin cambios. Los únicos problemas surgen con scripts muy antiguos que usaban funcionalidades no documentadas o bugs como features. La documentación oficial de mIRC incluye notas sobre cambios de comportamiento entre versiones.

¿Puedo usar mIRC script para hacer un bot serio de moderación?

Puedes, pero hay opciones mejores. Para un bot de moderación básico (anti-flood, anti-spam, comandos simples), mIRC script funciona bien. Para algo más complejo (base de datos SQL, APIs REST, procesamiento de lenguaje natural), Python con una librería IRC es más apropiado. mIRC script no tiene soporte nativo para JSON, bases de datos SQL, o HTTPS, lo que limita las integraciones modernas.

¿Dónde encuentro scripts de mIRC ya hechos?

Los repositorios principales son mircscripts.org y Hawkee.com. También hay scripts en foros como mIRCscripting.info. Ten precaución con scripts de fuentes desconocidas: revisa el código antes de cargarlo. Scripts maliciosos existen y pueden enviar tu contraseña de NickServ a terceros, unirse a canales sin tu permiso, o ejecutar comandos en tu máquina.