Backend / WebACTIVE· según último push

Twitch Commands

Endpoints HTTP para bots de Twitch (Nightbot/StreamElements/Botrix): !ruleta, !duelo, !8ball, !adivinanza, !ruletarusa y más

lang
JavaScript 96%
files
89
since
2025.07

Descriptionfuente: README.md

Colección de endpoints HTTP listos para conectarse a bots de chat de Twitch (Nightbot, StreamElements, Botrix, u otros). El bot llama al endpoint desde el chat con !comando, recibe una respuesta en texto plano y la escupe al canal. Sin instalar nada del lado del streamer.

Technologyfuente: manifiestos · topics · lenguajes

Languages
JavaScript
Frontend
ReactNext.jsTailwind CSSRadix UI
Data
SQLitelibSQL / Turso
Tooling
Vercel
  • JavaScript 96.2 %
  • CSS 3.8 %

Architecturefuente: README.md

twitch_commands/
├── pages/
│   ├── index.js           # Landing, generada desde commands/index.js
│   └── api/               # Un handler por comando (55)
├── commands/index.js      # Catálogo: grupos, visibilidad y ejemplos Nightbot
├── utils/
│   ├── functions.js       # Esquema, usuarios, ruleta y duelos
│   ├── mercado.js         # Comprar, vender, equipar, inventario
│   ├── economia.js        # trabajar, diario, dormir, ranking, regalar…
│   ├── diversion.js       # Los 40 comandos sin estado
│   ├── aleatorio.js       # Hash estable, azar puro, barras y tramos
│   ├── listas.js          # Textos de los comandos sin estado
│   ├── dados.js           # Notación de tiradas (2d6+3)
│   ├── respond.js         # Formato de respuesta para bots de chat
│   └── const.js           # Textos, premios y catálogo de items
└── components/            # UI de la landing

Hecho con ❤️ por Sack.

README.md

Leer documento fuente →

Twitch Commands — Endpoints HTTP para comandos de bot en Twitch

Colección de endpoints HTTP listos para conectarse a bots de chat de Twitch (Nightbot, StreamElements, Botrix, u otros). El bot llama al endpoint desde el chat con !comando, recibe una respuesta en texto plano y la escupe al canal. Sin instalar nada del lado del streamer.

Todas las respuestas salen como text/plain; charset=utf-8 y en una sola línea, que es lo que los bots saben pegar en el chat.

55 comandos, en dos grupos: 40 públicos, que no tocan la base de datos y se anuncian en la portada, y 15 con estado —la economía del canal—, que existen pero sólo se documentan aquí.


Persistencia

Los comandos con estado guardan monedas, inventario, rachas y estadísticas en libSQL (@libsql/client), que habla el mismo SQL que SQLite.

EntornoDónde escribePersiste
Local, sin configurar./database.dbSí, en tu disco
Producción con Tursolibsql://…Sí
Producción sin Tursofichero efímeroNo

Antes esto usaba sqlite3 contra un fichero del disco. En Vercel el sistema de ficheros es de solo lectura salvo /tmp, que es propio de cada instancia y se destruye sola: con 14 comandos de economía, las monedas y las rachas desaparecían sin dar ningún error. Por eso la migración.

Configurar Turso

turso db create twitchcommands
turso db show twitchcommands            # da la URL libsql://…
turso db tokens create twitchcommands   # da el token

Y en .env.local (y en las variables de entorno de tu despliegue):

TURSO_DATABASE_URL=libsql://tu-base-tu-org.turso.io
TURSO_AUTH_TOKEN=eyJhbGci...

La URL no es secreta; el token sí — da acceso de escritura. Nunca lo subas al repositorio: .gitignore ya cubre .env*.

Sin esas dos variables el proyecto arranca igual contra un fichero local, así que se puede desarrollar sin cuenta de Turso. Si falta la configuración en producción, se avisa por consola en lugar de fallar en silencio.

Las tablas y sus migraciones se crean solas al arrancar, en Turso o en local.

Comandos públicos

Los 40 de aquí no tocan la base de datos: son funciones puras que reciben texto y devuelven texto. Son los únicos que se anuncian en la portada y los únicos que devuelve /api/comandos.

/api/comandos sin argumento lista los grupos; con uno (/api/comandos?grupo=medidor) lista ese grupo. La lista entera no cabe en los 480 caracteres de un mensaje de Twitch.

Los medidores (!amor, !iq, !suerte, !simp, !cordura, !ship, !nombrerpg, !tarot, !horoscopo) usan un hash estable, no Math.random(): el mismo nombre da siempre el mismo resultado. Con azar puro el chat repite el comando hasta que sale el número que le gusta y la broma se muere. Los que llevan "de hoy" cambian con la fecha; el resto no cambian nunca.

🎲 Azar y decisiones

ComandoEndpointQué devuelve
!8ball/api/8ballBola 8 mágica: responde a lo que le preguntes.
!adivinanza/api/adivinanzaUna adivinanza con su pista.
!carta/api/cartaSaca una carta de la baraja francesa.
!dado/api/dado?tirada=Tira dados: !dado, !dado d20, !dado 2d6+3.
!elige/api/elige?opciones=Elige por ti: !elige pizza, sushi, tacos.
!flip/api/flipCara o cruz.
!numero/api/numero?rango=Número al azar: !numero, !numero 100, !numero 5-30.
!ppt/api/ppt?jugada=Piedra, papel o tijera contra el bot.

📊 Medidores

ComandoEndpointQué devuelve
!amor/api/amor?usuario=&otro=Compatibilidad entre dos nombres. Siempre da lo mismo.
!cordura/api/cordura?usuario=Cuánta cordura te queda hoy.
!facha/api/fachaTu porcentaje de facha.
!iq/api/iq?usuario=Tu cociente intelectual, fijo de por vida.
!memide/api/memideUna medida con emoji.
!ship/api/ship?usuario=&otro=Fusiona dos nombres y les pone nota.
!simp/api/simp?usuario=Tu nivel de simp del día.
!suerte/api/suerte?usuario=Tu suerte de hoy. Mañana es otra.

🔤 Juegos de texto

ComandoEndpointQué devuelve
!aesthetic/api/aesthetic?texto=Espacia el texto.
!alreves/api/alreves?texto=Le da la vuelta al texto, emoji incluidos.
!contar/api/contar?texto=Cuenta palabras y caracteres.
!morse/api/morse?texto=Traduce a código morse.
!uwu/api/uwu?texto=Twaduce ew texto a uwu.

⚔️ Rol y fantasía

ComandoEndpointQué devuelve
!animal/api/animalUn animal inventado, en texto.
!clase/api/claseUna clase de rol con su trasfondo.
!loot/api/lootUn botín al azar. Sólo narrativo.
!mazmorra/api/mazmorraGenera una sala con habitante y recompensa.
!nombrerpg/api/nombrerpg?usuario=Tu nombre de personaje, siempre el mismo.
!superhero/api/superheroUn superhéroe inventado.
!tarot/api/tarot?usuario=Tu carta del tarot de hoy.

📺 Para el directo

ComandoEndpointQué devuelve
!excusa/api/excusaUna excusa para haber perdido.
!pregunta/api/preguntaUna pregunta para animar el chat.
!reto/api/retoUn reto para la siguiente partida.
!titulo/api/titulo?juego=Un título clickbait para el stream.

🤝 Interacción

ComandoEndpointQué devuelve
!abrazo/api/abrazo?usuario=&destino=Abraza a otro chatter.
!cumplido/api/cumplidoUn cumplido al azar.
!insulto/api/insultoUn insulto en tono cómico.
!zape/api/zape?usuario=&destino=Dale un zape a otro chatter.

🧰 Utilidades

ComandoEndpointQué devuelve
!comandos/api/comandosEsta misma lista.
!cuentaatras/api/cuentaatras?fecha=Días que faltan: !cuentaatras 2026-12-25.
!factos/api/factosUn dato curioso.
!horoscopo/api/horoscopo?signo=El horóscopo del día por signo.

!dice pasó a llamarse !dado, y acepta hasta 50 dados de hasta 1000 caras con modificador (3d8+2). En d20 marca crítico y pifia.

Comandos con estado

Leen y escriben en la base de datos. Sin los parámetros obligatorios responden 400. El usuario se crea solo la primera vez, con 1000 monedas.

Éstos no se anuncian en la portada ni los devuelve /api/comandos: se documentan sólo aquí.

Los endpoints existen y funcionan igual; lo que se quita es el escaparate. Quien llega al sitio desde Google no encuentra !trabajar y no se pone a crear usuarios en una economía que es de un canal concreto.

Esto no es seguridad. /api/trabajar sigue siendo una URL pública que responde a cualquiera que la escriba, y cualquiera que mire el chat del canal ve el comando en cuanto alguien lo usa. Reduce el descubrimiento casual —que es de donde sale casi todo el ruido en un canal pequeño—, no el abuso decidido. Para eso hay que exigir un secreto compartido en estos endpoints; ver Sin autenticación.

ComandoEndpointQué hace
!apostar/api/apostar?usuario=X&cantidad=NDoble o nada al 50 %. Acepta cantidad=todo.
!diario/api/diario?usuario=X200💰 al día + 50 por día de racha (tope 7).
!dormir/api/dormir?usuario=XRecupera 30-60 de energía y baja 10 de estrés.
!duelo/api/duelo?retador=X&retado=Y[&monedas=N]Duelo por estadísticas y equipo. Cooldown de 5 min.
!inventario/api/inventario?usuario=XLo que tienes y lo que llevas puesto.
!mercado/api/mercado?usuario=X&accion=&item=ver, comprar, vender, equipar, desequipar.
!perfil/api/perfil?usuario=XMonedas, estadísticas y equipo.
!ranking/api/ranking?top=NTop de monedas del canal (máx. 10).
!regalar/api/regalar?usuario=X&destino=Y&cantidad=NTransfiere monedas. Va en transacción.
!robar/api/robar?usuario=X&victima=Y40 % de éxito; si fallas, 100💰 de multa.
!ruleta/api/ruleta?usuario=XRuleta de premios y castigos.
!ruletarusa/api/ruletarusa?usuario=X1 bala entre 6.
!stats/api/stats?usuario=XTu récord de victorias y derrotas en duelos.
!trabajar/api/trabajar?usuario=XTrabajo aleatorio por monedas. Una vez por hora.

El mercado

Cada día se sortean 5 items del catálogo, con más probabilidad cuanto más común es la rareza. Se compran, se equipan (una pieza por categoría: arma, armadura, amuleto, accesorio y mascota) y se venden por la mitad. Lo equipado suma ataque, defensa y suerte en los duelos.

Los nombres se buscan sin distinguir mayúsculas ni tildes: !mercado comprar cinturon de fuerza encuentra "Cinturón de Fuerza".

Cómo integrar en tu bot

Nightbot

!addcom !ruleta $(urlfetch https://twitchcomm.vercel.app/api/ruleta?usuario=$(user))

StreamElements

!command add ruleta ${urlfetch https://twitchcomm.vercel.app/api/ruleta?usuario=${user}}

Botrix

!custom add ruleta ${webhook:https://twitchcomm.vercel.app/api/ruleta?usuario=${sender}}

La portada del sitio genera el !addcom exacto de cada comando, ya con los parámetros correctos.

Ojo con los comandos de varios datos. Nightbot solo tiene una variable para el resto del mensaje, $(querystring). Repartirla entre dos parámetros la duplica: !mercado comprar Hacha acabaría mandando accion=comprar Hacha&item=comprar Hacha. Por eso esos comandos aceptan todo junto en q y lo parten en el servidor:

!addcom !mercado $(urlfetch https://twitchcomm.vercel.app/api/mercado?usuario=$(user)&q=$(querystring))
!addcom !duelo   $(urlfetch https://twitchcomm.vercel.app/api/duelo?retador=$(user)&q=$(querystring))
!addcom !regalar $(urlfetch https://twitchcomm.vercel.app/api/regalar?usuario=$(user)&q=$(querystring))

Bajo el capó

  • Framework: Next.js 15 (Pages Router) con React 19.
  • Persistencia: libSQL (@libsql/client): fichero local en desarrollo, Turso en producción.
  • UI de la landing: TailwindCSS 4, sin librería de componentes.
  • Estructura: cada comando es un handler en pages/api/<comando>.js; la lógica vive en utils/ (functions.js para usuarios y duelos, mercado.js, economia.js, dados.js, diversion.js para los comandos sin estado) y las respuestas se formatean en utils/respond.js.

Sin autenticación

Los endpoints con estado identifican al usuario solo por el parámetro usuario de la URL. Cualquiera que conozca la dirección puede jugar en nombre de otro, o hacer peticiones en bucle. Para un bot de chat de un canal pequeño puede bastar, pero conviene saberlo: no es un sistema de cuentas, es un contador con nombre. Si el canal crece, toca añadir un token compartido con el bot y un límite de peticiones por IP.


Setup local

npm install
npm run dev            # http://localhost:3000

La base de datos y sus tablas se crean solas al arrancar. database.db no se versiona: es estado de ejecución, no código.

Variables opcionales:

VariablePara qué
TURSO_DATABASE_URLBase de Turso. Sin ella se usa un fichero local.
TURSO_AUTH_TOKENToken de escritura de esa base. Secreto.
DATABASE_PATHRuta del fichero local. Por defecto ./database.db.

Estructura

twitch_commands/
├── pages/
│   ├── index.js           # Landing, generada desde commands/index.js
│   └── api/               # Un handler por comando (55)
├── commands/index.js      # Catálogo: grupos, visibilidad y ejemplos Nightbot
├── utils/
│   ├── functions.js       # Esquema, usuarios, ruleta y duelos
│   ├── mercado.js         # Comprar, vender, equipar, inventario
│   ├── economia.js        # trabajar, diario, dormir, ranking, regalar…
│   ├── diversion.js       # Los 40 comandos sin estado
│   ├── aleatorio.js       # Hash estable, azar puro, barras y tramos
│   ├── listas.js          # Textos de los comandos sin estado
│   ├── dados.js           # Notación de tiradas (2d6+3)
│   ├── respond.js         # Formato de respuesta para bots de chat
│   └── const.js           # Textos, premios y catálogo de items
└── components/            # UI de la landing

Hecho con ❤️ por Sack.

Next project telebot