action.json et pad.json
Chaque clé des deux fichiers que Vovó lit dans un dossier ou un zip, générée à partir du code de Vovó, donc toujours conforme à cette version. Vovó vérifie chaque fichier à son arrivée et le refuse avec une phrase qui dit ce qui ne va pas ; une clé qu'elle ne connaît pas est ignorée sans un mot, et un éditeur qui lit le schéma la souligne.
Une clé est faite de lettres minuscules, de chiffres et de _, et un nom peut aussi avoir -, chacun de 32 caractères au plus.
Pour qu'un éditeur complète les clés et souligne les erreurs, nommez le schéma en tête du fichier, comme le font les exemples. vovo dev écrit action.schema.json à côté des parties d'une action ; le code source de Vovó contient les deux dans son dossier api.
action.json
Le manifeste d'une action : son nom, ce qu'elle écoute, ce qu'elle demande et ce qu'elle offre à la personne qui mène le live. Il se trouve à côté de index.html, style.css, script.js et files/, dans un paquet ou un dossier.
{
"$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(texte): Où un éditeur trouve le schéma de ce fichier :./action.schema.json, quevovo devécrit à côté. Vovó n'y lit rien.name(texte; obligatoire): Son nom, unique dans le profil : une action importée avec le nom d'une action déjà présente propose de prendre sa place, ou arrive sous le nom « Raffle 2 ».id(texte, une ligne, au plus 64 caractères): Un nom que son auteur lui donne une fois et ne change jamais : le nom de l'auteur et celui de l'action séparés par un point, commeexample.raffle, en lettres minuscules, chiffres et-. Une version plus récente importée retrouve grâce à lui l'action qu'elle met à jour, quel que soit le nom de cette action à ce moment-là ; sans lui, par son nom. Une copie faite dans Vovó ne le conserve pas.version(texte, une ligne, au plus 32 caractères): Sa propre version, affichée dans la liste des actions et, quand un paquet prend la place d'une action, à côté de celle que cette action avait, en signalant quand le paquet est la même version ou une plus ancienne. Les nombres séparés par des points sont lus comme des nombres (1.10.0est plus récente que1.9.2, et1.0.0-beta.1vient avant1.0.0) ; écrites autrement, deux versions sont seulement identiques ou non.1.0.0sans elle.api(nombre entier, 1 ou plus; obligatoire): La version de l'API pour laquelle elle a été écrite :1. Une version plus récente que celle de cette Vovó est refusée, avec ce qu'il faut faire.triggers(liste d'événements): Les événements qu'elle écoute : ceux de l'API, ou des noms à elle, quevovo.emitetvovo emitdéclenchent. Un nom proche d'un nom de l'API est refusé, avec celui qui était voulu.control,settingsetpanelparviennent à une action qui déclare des contrôles, des réglages ou un panneau sans être listés.bindings(liste): Les conditions des déclencheurs.permissions(liste d'autorisations): Ce qu'elle peut demander à Vovó, montré à la personne qui l'importe. Une autorisation que Vovó ne connaît pas est refusée, avec celle qui était voulue.persistent(vrai ou faux): Si elle reste à l'écran (un chat, une barre d'objectif) plutôt que d'apparaître quand ses événements arrivent, ce qui est le nom que lui donnent l'éditeur et la liste des actions. Cela ne change rien à son fonctionnement.operator(vrai ou faux): Seulement pour la personne qui mène le live : elle écoute le pad, les raccourcis, les minuteurs, ses contrôles et ce que disent OBS et l'ordinateur, jamais les spectateurs, le chat, les récompenses, les webhooks ou l'événement d'une autre action. Un déclencheur que quelqu'un d'autre pourrait activer est refusé.controls(liste, au plus 32): Ce que le pad change pendant qu'elle tourne.settings(liste, au plus 32): Ce que la personne qui l'utilise peut changer sans son code.panel(liste): Ce qu'elle montre à la personne qui mène le live, dans Panneaux.author(texte, une ligne, au plus 80 caractères): Qui l'a faite.site(adresse web, au plus 200 caractères): Où en lire davantage, sur elle ou sur la personne qui l'a faite.description(texte, une ligne, au plus 300 caractères): Ce qu'elle fait, en une ligne, affiché quand elle est importée.license(texte, une ligne, au plus 100 caractères): À quelles conditions elle est remise, telles que son auteur les énonce : le nom d'une licence (MIT,CC-BY-4.0) ou une ligne à soi, affichée à l'import et dans la liste des actions. Le texte complet de la licence se place à côté de ce fichier sous le nomLICENSE(ouLICENSE.md,LICENSE.txt), 64 Ko de texte au maximum, et se lit depuis la boîte de dialogue d'import avant que l'action n'arrive. Vovó dit ce qui est écrit et n'y contraint personne : elle ne vérifie ni clé, ni compte, ni achat.
Conditions
Chaque déclencheur à nouveau, avec les conditions qui doivent toutes être remplies pour qu'il active l'action, tel que l'éditeur les enregistre. Un pour chaque nom de triggers, dans n'importe quel ordre : s'ils ne correspondent pas un à un, toutes les conditions sont laissées de côté sans un mot et chaque déclencheur se déclenche sur tout.
event(événement; obligatoire): L'un des noms detriggers.filter(liste): Ses conditions ; sans aucune, chaque événement de ce type la déclenche.
Une condition
L'un des champs de l'événement comparé à une valeur. Les textes sont comparés sans tenir compte de la casse ; un nombre écrit comme texte est lu comme un nombre.
field(texte; obligatoire): Le champ de l'événement, tel que la référence de l'API le nomme :viewers,reward,text. L'intervalle d'untimerest le champevery(secondes, 5 ou plus), et la combinaison d'unhotkeyle champkeys, chacun avecis.op(l'un deis,not,above,atleast,below,atmost,contains,starts; obligatoire): Comment ils sont comparés :isetnottels quels,above,atleast,belowetatmostcomme des nombres,containsetstartscomme des textes.value(texte, nombre, ou vrai ou faux; obligatoire): Ce à quoi le champ est comparé.
Contrôles
Ce que le pad change pendant que l'action tourne : chacun gardé dans vovo.state sous sa clé et signalé à l'action par l'événement control, qu'elle écoute sans le lister.
key(clé; obligatoire): Oùvovo.statele garde ; deux contrôles n'en partagent pas une.label(texte; obligatoire): Comment le pad l'appelle.kind(l'un detoggle,choice,counter,text; obligatoire): Activé ou désactivé ; l'une de ses options ; un nombre entier, un de plus ou de moins à la fois ; ou une ligne de texte, de 300 caractères au plus.options(liste de textes): Les options d'un choix, deux ou plus.max(nombre): L'objectif d'un compteur, affiché à côté de son compte.
Réglages
Ce que la personne qui utilise l'action peut changer sans son code, dans Personnaliser : lu comme vovo.settings.<key>, comme --vovo-<key> dans son CSS et, pour activé ou désactivé et un choix, comme data-vovo-<key> sur son document. Ce qui est choisi reste avec l'action, et un paquet n'emporte que les valeurs par défaut. Huit d'entre eux au plus sont des textes.
kind(l'un decolor,number,toggle,choice,text,file,font,camera; obligatoire): Ce que c'est, comme le disent les parties ci-dessous.key(clé; obligatoire): Comment l'action le lit ; deux réglages n'en partagent pas une, et aucune n'estaccent.label(texte, au plus 60 caractères; obligatoire): Comment Personnaliser l'appelle.
Réglages: color
Une couleur ; le bordeaux de Vovó, #840926, sauf si l'action en dit une autre.
default(couleur,#RRGGBB): Tel que l'action arrive ; sans elle, celle du type.
Réglages: number
Un nombre d'un minimum à un maximum, par pas ; le minimum sauf si l'action en dit un autre.
min(nombre; obligatoire): Le minimum.max(nombre; obligatoire): Le maximum, au-dessus du minimum.step(nombre): La taille de chaque pas, au-dessus de 0 ; 1 sans lui.unit(l'un depx,%,s,ms,em,deg): L'unité que porte sa variable CSS ; sans elle, un simple nombre.default(nombre): Tel que l'action arrive ; sans elle, celle du type.
Réglages: toggle
Activé ou désactivé ; désactivé sauf si l'action dit autre chose.
default(vrai ou faux): Tel que l'action arrive ; sans elle, celle du type.
Réglages: choice
L'une de ses options ; la première sauf si l'action en dit une autre.
options(liste de textes, de 2 à 12; obligatoire): Les options, chacune une fois.default(texte): Tel que l'action arrive ; sans elle, celle du type.
Réglages: text
Une ligne de texte ; vide sauf si l'action en dit une autre.
default(texte, une ligne, au plus 200 caractères): Tel que l'action arrive ; sans elle, celle du type.
Réglages: file
Une image, un son ou une vidéo que choisit la personne qui l'utilise, de 50 Mo au plus ; tel que l'action arrive, l'un de ses propres fichiers, par son chemin, ou aucun.
accept(l'un deimage,sound,video): Ce que cela peut être : une image sauf si l'action dit autre chose.default(chemin d'un fichier, ounull): Tel que l'action arrive ; sans elle, celle du type.
Réglages: font
L'une des polices de l'ordinateur, par sa famille ; Segoe UI sauf si l'action en dit une autre.
default(texte, une ligne, au plus 64 caractères): Tel que l'action arrive ; sans elle, celle du type.
Réglages: camera
L'une des caméras de l'ordinateur, que choisit dans Personnaliser qui utilise l'action, montrée là où l'action la place (vovo.camera.place, avec l'autorisation camera.show) ; quatre au maximum. Elle vient sans caméra, elle n'a donc pas de valeur par défaut.
Panneau
Ce que l'action montre à la personne qui mène le live dans Panneaux, dans la barre latérale : des pièces dans l'ordre, chacune désignée par son kind, dessinées par Vovó. Ce qui y est fait parvient à l'action par l'événement panel, qu'elle écoute sans le lister. Une pièce panel commence un autre panneau, avec les pièces qui suivent jusqu'au prochain, et les pièces avant le premier apparaissent sur chacun ; un tab découpe un panneau en sections de la même façon. Les noms des boutons, des formulaires et des boutons d'une liste sont uniques dans l'action. Une action déclare 24 panneaux au plus, chacun avec 40 pièces et 12 onglets au plus.
kind(l'un depanel,tab,heading,note,control,button,form,list; obligatoire): Ce que c'est, comme le disent les parties ci-dessous.
Panneau: panel
Un autre panneau commence ici, avec sa propre entrée dans Panneaux.
label(texte, au plus 30 caractères; obligatoire): Son nom dans Panneaux.icon(texte, au plus 32 caractères): L'une des icônes de Vovó par son nom, ou un emoji ; sans elle, l'icône du premier bouton de l'action sur le pad.
Panneau: tab
Une section du panneau : les pièces qui suivent, jusqu'au prochain onglet.
label(texte, au plus 30 caractères; obligatoire): Son nom.
Panneau: heading
Un titre au-dessus des pièces qui suivent, qui partagent une carte.
label(texte, au plus 60 caractères; obligatoire): Son texte.
Panneau: note
Une ligne qui dit quelque chose.
label(texte, au plus 60 caractères; obligatoire): Son texte.
Panneau: control
L'un des contrôles de l'action, manié ici comme sur le pad.
key(clé; obligatoire): La clé du contrôle.
Panneau: button
Un bouton.
name(nom; obligatoire): Ce que l'événementpaneldit avoir été pressé.label(texte, au plus 60 caractères; obligatoire): Son texte.confirm(vrai ou faux): La première pression demande, la seconde agit.
Panneau: form
Quelques champs et un bouton : ce qui est saisi part avec la pression, dans les values de l'événement. Un formulaire d'un seul champ se remplit dans le panneau même.
name(nom; obligatoire): Ce que l'événementpaneldit avoir été envoyé.label(texte, au plus 60 caractères; obligatoire): Son texte.button(texte): Le texte du bouton.fields(liste, de 1 à 4; obligatoire): Ses champs.
Champs d'un formulaire
Chacun une ligne saisie dans le panneau, envoyée avec le formulaire sous sa clé.
key(nom; obligatoire): Sa clé dans lesvaluesde l'événement, une seule fois dans le formulaire.label(texte, au plus 60 caractères; obligatoire): Le nom du champ.
Panneau: list
Une liste lue dans l'état de l'action, une ligne par élément, qui peuvent être des milliers ; une liste de plus de huit lignes a sa propre recherche.
key(texte; obligatoire): La clé devovo.statequi la contient.path(texte): À l'intérieur, les clés jusqu'à la liste, reliées par des points :round.names.label(texte, au plus 60 caractères; obligatoire): Son nom.show(texte): Pour les éléments qui sont des objets : le champ qu'une ligne affiche, ou une ligne avec des{field}remplis à partir de chaque élément.empty(texte): Ce qu'elle dit tant qu'elle est vide.buttons(liste, au plus 3): Des boutons sur chaque ligne : une pression donne à l'action l'itemet l'indexde la ligne.
Boutons d'une liste
Des boutons sur chaque ligne de la liste.
name(nom; obligatoire): Ce que l'événementpaneldit avoir été pressé.label(texte, au plus 60 caractères; obligatoire): Son texte.confirm(vrai ou faux): La première pression demande, la seconde agit.
pad.json
Un paquet de boutons pour le pad : un zip ou un dossier de sons et de vidéos, avec pad.json à la racine indiquant les groupes et leurs boutons ; sans lui, chaque dossier est un groupe et chaque son ou vidéo un bouton au nom de son fichier. Importé de nouveau, il met à jour ce qu'il nomme et laisse le reste tel quel.
{
"$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(texte): Où un éditeur trouve le schéma de ce fichier, par exemple un./pad.schema.jsonà côté. Vovó n'y lit rien.groups(liste; obligatoire): Les groupes, dans l'ordre.
Groupes
Un groupe du pad et ses boutons, dans l'ordre.
name(texte, au plus 60 caractères; obligatoire): Son nom : un groupe du profil portant ce nom, quelle que soit la casse, est mis à jour.color(couleur,#RRGGBB): Sa couleur ; sans elle, un groupe déjà présent garde la sienne et un nouveau prend la suivante.buttons(liste): Ses boutons.
Boutons
Un bouton et ce qu'il fait : Vovó lit le premier de ceux-ci qu'elle trouve, dans cet ordre : sound ; video ; action avec control ; action ; source avec filter, ou scene avec source ; scene. Un paquet apporte 2 000 boutons au plus.
label(texte, au plus 60 caractères; obligatoire): Son nom sur le pad : un bouton de son groupe portant ce nom, quelle que soit la casse, est mis à jour.icon(texte): L'une des icônes de Vovó par son nom, ou un emoji.sound(chemin d'un fichier): Un son du paquet, par son chemin dedans : MP3, OGG, WAV, M4A, WEBM ou FLAC, de 20 Mo au plus.video(chemin d'un fichier): Une vidéo du paquet, par son chemin dedans : MP4 ou M4V, de 200 Mo au plus ; elle passe sur toute la scène.key(texte): Ce qui est retiré de la vidéo, comme le font les filtres d'OBS :none,luma(noir),chroma(vert) ouchroma:#RRGGBB.loop(vrai ou faux): La vidéo tourne en boucle, jusqu'à ce que son bouton soit pressé de nouveau.action(texte): L'une des actions du profil, par son nom, déclenchée comme son événementbutton.control(clé): Avecaction: l'un de ses contrôles, par sa clé, manié comme le fait son bouton sur le pad.value(texte): Aveccontrol, pour un choix : l'option qu'il choisit ; sans elle, il les parcourt l'une après l'autre.scene(texte): Une scène OBS, par son nom, mise à l'antenne.source(texte): Avecscene: une source de cette scène, affichée ou masquée. Avecfilter: la source qui porte le filtre.filter(texte): Avecsource: l'un de ses filtres, activé ou désactivé.team(texte, au plus 300 caractères): Une ligne qu'il écrit dans la conversation de l'équipe au nom du streamer, jamais dans le live ni le chat ; le pad d'un appareil n'a jamais ce bouton.favorite(vrai ou faux): Dans les Favoris ou non ; sans cela, un bouton déjà présent garde ce qu'il a.hotkey(texte): La combinaison qui le presse depuis n'importe quel programme, telle qu'on l'écrit :F13,Ctrl+Shift+1. Deux boutons du profil n'en partagent pas une.volume(nombre entier, de 0 à 150): Le volume d'un son ou d'une vidéo, en pourcentage de son fichier ; sans lui, un bouton déjà présent garde le sien.