action.json y pad.json
Cada clave de los dos archivos que Vovó lee de una carpeta o un zip, generada desde el propio código de Vovó, así que siempre coincide con esta versión. Vovó revisa cada archivo al llegar y lo rechaza con una frase que dice qué está mal; una clave que no conoce se pasa por alto sin decir nada, y un editor que lee el schema la subraya.
Una clave lleva letras minúsculas, dígitos y _, y un nombre puede llevar también -, cada uno de 32 caracteres como máximo.
Para que un editor complete las claves y subraye los errores, nombra el schema al principio del archivo, como hacen los ejemplos. vovo dev escribe action.schema.json junto a las partes de una acción; el código fuente de Vovó tiene ambos en su carpeta api.
action.json
El manifiesto de una acción: cómo se llama, qué escucha, qué pide y qué ofrece a quien lleva el directo. Va junto a index.html, style.css, script.js y files/, en un paquete o una carpeta.
{
"$schema": "./action.schema.json",
"name": "Raffle",
"id": "example.raffle",
"version": "1.2.0",
"api": 1,
"author": "A maker",
"site": "https://example.com/raffle",
"description": "!join in chat joins the wheel; the panel draws the winner.",
"license": "MIT",
"triggers": ["chat", "timer"],
"bindings": [
{ "event": "chat", "filter": [{ "field": "text", "op": "starts", "value": "!join" }] },
{ "event": "timer", "filter": [{ "field": "every", "op": "is", "value": 300 }] }
],
"permissions": ["chat.send"],
"controls": [
{ "key": "open", "label": "Entries open", "kind": "toggle" },
{ "key": "prize", "label": "Prize", "kind": "text" }
],
"settings": [
{ "key": "color", "label": "Wheel colour", "kind": "color", "default": "#840926" },
{ "key": "size", "label": "Size", "kind": "number", "min": 200, "max": 800, "step": 10, "unit": "px", "default": 420 },
{ "key": "side", "label": "Side", "kind": "choice", "options": ["Left", "Right"], "default": "Right" }
],
"panel": [
{ "kind": "control", "key": "open" },
{ "kind": "control", "key": "prize" },
{ "kind": "form", "name": "add", "label": "Put someone in", "button": "Put", "fields": [{ "key": "who", "label": "Name" }] },
{ "kind": "button", "name": "draw", "label": "Draw", "confirm": true },
{ "kind": "list", "key": "names", "label": "In the wheel", "empty": "Nobody yet", "buttons": [{ "name": "out", "label": "Take out", "confirm": true }] }
]
}
$schema(texto): Dónde encuentra un editor el schema de este archivo:./action.schema.json, quevovo devescribe a su lado. Vovó no lee nada aquí.name(texto; obligatorio): Su nombre, único en el perfil: una acción importada con el nombre de otra que ya está ofrece ocupar su lugar, o entra como "Raffle 2".id(texto, una línea, como máximo 64 caracteres): Un nombre que quien la hizo le da una vez y nunca cambia: el nombre de quien la hizo y el de la acción con un punto entre los dos, comoexample.raffle, en letras minúsculas, dígitos y-. Una versión más reciente que se importa encuentra por él la acción que actualiza, se llame como se llame entonces; sin él, por su nombre. Una copia hecha en Vovó no lo conserva.version(texto, una línea, como máximo 32 caracteres): Su propia versión, mostrada en la lista de acciones y, cuando un paquete ocupa el lugar de una acción, junto a la que esa acción tenía, avisando cuando el paquete es la misma versión o una anterior. Los números separados por puntos se leen como números (1.10.0es más reciente que1.9.2, y1.0.0-beta.1va antes que1.0.0); escritas de cualquier otra forma, dos versiones solo son iguales o no.1.0.0si falta.api(número entero, 1 o más; obligatorio): La versión de la API para la que se escribió:1. Una más nueva que la de esta Vovó se rechaza, con lo que hay que hacer.triggers(lista de eventos): Los eventos que escucha: los de la API, o nombres propios suyos, que disparanvovo.emityvovo emit. Un nombre parecido a uno de la API se rechaza, con el que se quería decir.control,settingsypanelllegan a una acción que declara controles, ajustes o un panel sin estar en la lista.bindings(lista): Las condiciones de los disparadores.permissions(lista de permisos): Lo que puede pedirle a Vovó, mostrado a quien la importa. Uno que Vovó no conoce se rechaza, con el que se quería decir.persistent(verdadero o falso): Si se queda en pantalla (un chat, una barra de meta) en lugar de aparecer cuando llegan sus eventos, que es como la llaman el editor y la lista de acciones. No cambia nada de cómo funciona.operator(verdadero o falso): Solo para quien lleva el directo: escucha el pad, los atajos, los temporizadores, sus controles y lo que dicen OBS y el ordenador, nunca a los espectadores, el chat, las recompensas, los webhooks o el evento de otra acción. Se rechaza un disparador que otra persona podría activar.controls(lista, como máximo 32): Lo que el pad cambia mientras funciona.settings(lista, como máximo 32): Lo que quien la usa puede cambiar sin su código.panel(lista): Lo que muestra a quien lleva el directo, en Paneles.author(texto, una línea, como máximo 80 caracteres): Quién la hizo.site(dirección web, como máximo 200 caracteres): Dónde leer más sobre ella, o sobre quien la hizo.description(texto, una línea, como máximo 300 caracteres): Lo que hace, en una línea, mostrado al importarla.license(texto, una línea, como máximo 100 caracteres): En qué condiciones se entrega, tal como lo dice quien la hizo: el nombre de una licencia (MIT,CC-BY-4.0) o una línea propia, mostrada al importarla y en la lista de acciones. El texto completo de la licencia va junto a este archivo comoLICENSE(oLICENSE.md,LICENSE.txt), con 64 KB de texto como máximo, y se lee desde el diálogo de importación antes de que la acción entre. Vovó dice lo que está escrito y no obliga a nadie a nada: no comprueba ninguna clave, cuenta ni compra.
Condiciones
Cada disparador otra vez, con las condiciones que deben cumplirse todas para que active la acción, como las guarda el editor. Uno por cada nombre de triggers, en cualquier orden: si no coinciden uno a uno, todas las condiciones se descartan sin decir nada y cada disparador se activa con todo.
event(evento; obligatorio): Uno de los nombres detriggers.filter(lista): Sus condiciones; sin ninguna, todo evento así la activa.
Una condición
Uno de los campos del evento comparado con un valor. Los textos se comparan sin distinguir mayúsculas; un número escrito como texto se lee como número.
field(texto; obligatorio): El campo del evento, como lo nombra la referencia de la API:viewers,reward,text. El intervalo de untimeres el campoevery(segundos, 5 o más), y la combinación de unhotkeyel campokeys, cada uno conis.op(uno deis,not,above,atleast,below,atmost,contains,starts; obligatorio): Cómo se comparan:isynottal cual,above,atleast,belowyatmostcomo números,containsystartscomo textos.value(texto, número, o verdadero o falso; obligatorio): Con qué se compara el campo.
Controles
Lo que el pad cambia mientras la acción funciona: cada uno guardado en vovo.state bajo su clave y comunicado a la acción como el evento control, que escucha sin tenerlo en la lista.
key(clave; obligatorio): Dónde lo guardavovo.state; dos controles no comparten una.label(texto; obligatorio): Cómo lo llama el pad.kind(uno detoggle,choice,counter,text; obligatorio): Activado o desactivado; una de sus opciones; un número entero, de uno en uno hacia arriba o abajo; o una línea de texto, de 300 caracteres como máximo.options(lista de textos): Las opciones de una elección, dos o más.max(número): La meta de un contador, mostrada junto a su cuenta.
Ajustes
Lo que quien usa la acción puede cambiar sin su código, en Personalizar: se lee como vovo.settings.<key>, como --vovo-<key> en su CSS y, para activado o desactivado y una elección, como data-vovo-<key> en su documento. Lo elegido se queda con la acción, y un paquete lleva solo los valores por defecto. Como máximo ocho son textos.
kind(uno decolor,number,toggle,choice,text,file,font,camera; obligatorio): Qué es, como dicen las partes de abajo.key(clave; obligatorio): Cómo lo lee la acción; dos ajustes no comparten una, y ninguna esaccent.label(texto, como máximo 60 caracteres; obligatorio): Cómo lo llama Personalizar.
Ajustes: color
Un color; el vino de Vovó, #840926, si la acción no dice otro.
default(color,#RRGGBB): Como viene la acción; sin él, el del tipo.
Ajustes: number
Un número de un mínimo a un máximo, por pasos; el mínimo si la acción no dice otro.
min(número; obligatorio): El mínimo.max(número; obligatorio): El máximo, por encima del mínimo.step(número): Cuánto avanza cada paso, por encima de 0; 1 si falta.unit(uno depx,%,s,ms,em,deg): La unidad que lleva su variable CSS; sin ella, un número simple.default(número): Como viene la acción; sin él, el del tipo.
Ajustes: toggle
Activado o desactivado; desactivado si la acción no dice otra cosa.
default(verdadero o falso): Como viene la acción; sin él, el del tipo.
Ajustes: choice
Una de sus opciones; la primera si la acción no dice otra.
options(lista de textos, de 2 a 12; obligatorio): Las opciones, cada una una vez.default(texto): Como viene la acción; sin él, el del tipo.
Ajustes: text
Una línea de texto; vacía si la acción no dice otra.
default(texto, una línea, como máximo 200 caracteres): Como viene la acción; sin él, el del tipo.
Ajustes: file
Una imagen, un sonido o un vídeo que elige quien la usa, de 50 MB como máximo; como viene la acción, uno de sus propios archivos, por su ruta, o ninguno.
accept(uno deimage,sound,video): Qué puede ser: una imagen si la acción no dice otra cosa.default(ruta de un archivo, onull): Como viene la acción; sin él, el del tipo.
Ajustes: font
Una de las fuentes del ordenador, por su familia; Segoe UI si la acción no dice otra.
default(texto, una línea, como máximo 64 caracteres): Como viene la acción; sin él, el del tipo.
Ajustes: camera
Una de las cámaras del equipo, que quien usa la acción elige en Personalizar, mostrada donde la acción la coloca (vovo.camera.place, con el permiso camera.show); cuatro como máximo. Viene sin ninguna, así que no tiene valor predeterminado.
Panel
Lo que la acción muestra a quien lleva el directo en Paneles, en la barra lateral: piezas en orden, cada una indicada por su kind, dibujadas por Vovó. Lo que se hace allí llega a la acción como el evento panel, que escucha sin tenerlo en la lista. Una pieza panel empieza otro panel, con las piezas que siguen hasta la próxima, y las piezas antes de la primera aparecen en todos; una tab divide un panel en secciones de la misma forma. Los nombres de botones, formularios y botones de una lista son únicos en la acción. Una acción declara como máximo 24 paneles, cada uno con 40 piezas y 12 pestañas como máximo.
kind(uno depanel,tab,heading,note,control,button,form,list; obligatorio): Qué es, como dicen las partes de abajo.
Panel: panel
Aquí empieza otro panel, con una entrada propia en Paneles.
label(texto, como máximo 30 caracteres; obligatorio): Su nombre en Paneles.icon(texto, como máximo 32 caracteres): Uno de los iconos de Vovó por su nombre, o un emoji; sin él, el icono del primer botón de la acción en el pad.
Panel: tab
Una sección del panel: las piezas que siguen, hasta la próxima pestaña.
label(texto, como máximo 30 caracteres; obligatorio): Su nombre.
Panel: heading
Un título sobre las piezas que siguen, que comparten una tarjeta.
label(texto, como máximo 60 caracteres; obligatorio): Su texto.
Panel: note
Una línea que dice algo.
label(texto, como máximo 60 caracteres; obligatorio): Su texto.
Panel: control
Uno de los controles de la acción, que se mueve aquí como en el pad.
key(clave; obligatorio): La clave del control.
Panel: button
Un botón.
name(nombre; obligatorio): Lo que el eventopaneldice que se pulsó.label(texto, como máximo 60 caracteres; obligatorio): Su texto.confirm(verdadero o falso): La primera pulsación pregunta y la segunda lo hace.
Panel: form
Unos campos y un botón: lo que se escribe va con la pulsación, en los values del evento. Un formulario de un campo se escribe en el propio panel.
name(nombre; obligatorio): Lo que el eventopaneldice que se envió.label(texto, como máximo 60 caracteres; obligatorio): Su texto.button(texto): El texto del botón.fields(lista, de 1 a 4; obligatorio): Sus campos.
Campos de un formulario
Cada uno, una línea escrita en el panel, enviada con el formulario por su clave.
key(nombre; obligatorio): Su clave en losvaluesdel evento, una sola vez en el formulario.label(texto, como máximo 60 caracteres; obligatorio): Cómo se llama el campo.
Panel: list
Una lista leída del estado de la acción, una línea por elemento, que pueden ser miles; una con más de ocho líneas tiene búsqueda propia.
key(texto; obligatorio): La clave devovo.stateque la guarda.path(texto): Dentro de ella, las claves hasta la lista, unidas por puntos:round.names.label(texto, como máximo 60 caracteres; obligatorio): Su nombre.show(texto): Para elementos que son objetos: el campo que muestra una línea, o una línea con{field}s rellenados con cada elemento.empty(texto): Lo que dice mientras está vacía.buttons(lista, como máximo 3): Botones en cada línea: una pulsación le dice a la acción elitemy elindexde la línea.
Botones de una lista
Botones en cada línea de la lista.
name(nombre; obligatorio): Lo que el eventopaneldice que se pulsó.label(texto, como máximo 60 caracteres; obligatorio): Su texto.confirm(verdadero o falso): La primera pulsación pregunta y la segunda lo hace.
pad.json
Un paquete de botones para el pad: un zip o una carpeta de sonidos y vídeos, con pad.json en la raíz indicando los grupos y sus botones; sin él, cada carpeta es un grupo y cada sonido o vídeo un botón con el nombre de su archivo. Importado otra vez, actualiza lo que nombra y deja el resto como está.
{
"$schema": "./pad.schema.json",
"groups": [
{
"name": "Sounds",
"color": "#2F6FDB",
"buttons": [
{ "label": "Applause", "icon": "👏", "sound": "sounds/applause.mp3", "favorite": true, "hotkey": "F13" },
{ "label": "Drum roll", "sound": "sounds/drums.ogg", "volume": 130 },
{ "label": "Rain", "video": "videos/rain.mp4", "key": "luma", "loop": true }
]
},
{
"name": "Live",
"buttons": [
{ "label": "Raffle", "action": "Raffle" },
{ "label": "Entries", "action": "Raffle", "control": "open" },
{ "label": "Starting", "scene": "Starting soon" },
{ "label": "Camera", "scene": "Game", "source": "Camera" },
{ "label": "Blur", "source": "Camera", "filter": "Blur" },
{ "label": "One minute", "team": "One minute, then I'm back." }
]
}
]
}
$schema(texto): Dónde encuentra un editor el schema de este archivo, como un./pad.schema.jsona su lado. Vovó no lee nada aquí.groups(lista; obligatorio): Los grupos, en orden.
Grupos
Un grupo del pad y sus botones, en orden.
name(texto, como máximo 60 caracteres; obligatorio): Su nombre: un grupo del perfil con ese nombre, sin distinguir mayúsculas, se actualiza.color(color,#RRGGBB): Su color; sin él, un grupo que ya está conserva el suyo y uno nuevo toma el siguiente.buttons(lista): Sus botones.
Botones
Un botón y lo que hace: Vovó lee el primero de estos que encuentre, en este orden: sound; video; action con control; action; source con filter, o scene con source; scene. Un paquete trae como máximo 2000 botones.
label(texto, como máximo 60 caracteres; obligatorio): Su nombre en el pad: un botón de su grupo con ese nombre, sin distinguir mayúsculas, se actualiza.icon(texto): Uno de los iconos de Vovó por su nombre, o un emoji.sound(ruta de un archivo): Un sonido del paquete, por su ruta dentro de él: MP3, OGG, WAV, M4A, WEBM o FLAC, de 20 MB como máximo.video(ruta de un archivo): Un vídeo del paquete, por su ruta dentro de él: MP4 o M4V, de 200 MB como máximo; se reproduce sobre todo el escenario.key(texto): Qué se quita del vídeo, como hacen los filtros de OBS:none,luma(negro),chroma(verde) ochroma:#RRGGBB.loop(verdadero o falso): El vídeo se repite sin parar, hasta que se vuelve a pulsar su botón.action(texto): Una de las acciones del perfil, por su nombre, activada como su eventobutton.control(clave): Conaction: uno de sus controles, por su clave, que se mueve como lo mueve su botón en el pad.value(texto): Concontrol, para una elección: la opción que elige; sin él, va pasando por ellas.scene(texto): Una escena de OBS, por su nombre, puesta al aire.source(texto): Conscene: una fuente en ella, mostrada u ocultada. Confilter: la fuente en la que está el filtro.filter(texto): Consource: uno de sus filtros, activado o desactivado.team(texto, como máximo 300 caracteres): Una línea que escribe en la conversación del equipo como quien hace el directo, nunca en el directo ni en el chat; el pad de un dispositivo nunca tiene el botón.favorite(verdadero o falso): En Favoritos o no; sin esto, un botón que ya está conserva lo que tiene.hotkey(texto): La combinación que lo pulsa desde cualquier programa, como se escribe:F13,Ctrl+Shift+1. Dos botones del perfil no comparten una.volume(número entero, de 0 a 150): El volumen al que suena un sonido o un vídeo, como porcentaje de su archivo; sin él, un botón que ya está conserva el suyo.