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.
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.
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.