Changes to the snippet API
Each line says what changed for people writing actions. Adding an event, a field or a member keeps the version; changing or removing one starts a new version, and actions written for the old one keep working.
The rest of this folder is generated from src/core/api/schema.rs: change the schema, run VOVO_BLESS=1 cargo test, and add a line here, in one commit.
API 1
- First version. Simple events
follow,sub,raid,chatandtip, the same on every platform; the Twitch events they are made from, plustwitch.redemptionandtwitch.hypetrain;button,hotkey,timer,webhookandobs.scene. vovo.on,vovo.show,vovo.emitandvovo.state.- Templates with
data-on,data-nameanddata-seconds;{field}filled as plain text. - The
--vovo-accentCSS variable. - Permissions
chat.sendandwebhook. media.track: what plays on the computer, with its cover.obs.sceneandmedia.trackare current values: an action that loads later gets the latest one at once.vovo.draw(entries): the app draws one, fairly, and the audit records it.vovo.say(text, { voice }): speech on the stream, made by the app.persona.answer: the persona's approved answers.twitch.viewers: how many watch the stream, about once a minute while it is live; a current value too.audio.levelandscreen.color: the microphone's loudness and the screen's colour, many times a second, read only while an action listens.vovo.screen.place(element)andscreen.shared: what the streamer shares from the share page (a screen, a window or a tab) shown where an action says, with thescreen.showpermission.vovo.chat.send(text): a line in the live's chat, with thechat.sendpermission, at the pace the app keeps.timergoes off at the interval its trigger'severycondition sets, andhotkeyat the combination itskeyscondition names.- Controls: an action declares in its manifest what the pad can change while it runs (
controls: on or off, a choice, a counter, a text), each kept invovo.stateunder its key. A change arrives ascontrol, with the key and the new value, trigger or not. vovo.webhook.send(name, data): the app posts JSON to one of the profile's outbound webhooks, by name, with thewebhookpermission.twitch.redemption.resolved: a redemption in a reward's queue approved or rejected, withstatus;twitch.redemptionand it carry the redemption's id asredemption.partsonchatandtwitch.chat: the message in parts, its emotes as pictures Vovó serves;vovo.chat.parts(e)makes them into nodes, words as text and emotes as images.sound.playedandvideo.played: a pad's sound or video button played, with thefileit played, which of several when the button draws one.overlay.connected: OBS loaded or reloaded one of the active profile's scenes.- An action's manifest may say
"operator": true: it is then set off only by the pad, hotkeys, timers, its controls and what OBS and the computer say, never by viewers, chat, rewards, webhooks or another action's event. vovo.media.play(link),vovo.media.place(element)andvovo.media.stop(): a Twitch clip, a Twitch video or a YouTube video on the stage, in its official player, with themedia.playpermission; asked by an action anyone may set off, it waits for approval.vovo.say'svoicenames a voice in Piper's folder aspiper:<voice>.twitch.redemptionandtwitch.redemption.resolvedcarryreward_id, Twitch's id for the reward, which survives renaming it: a condition on it keeps working when the reward's title changes.vovo.pad.play(label), with thepad.playpermission: one of the pad's sound or video buttons pressed by the action, so a reward or a chat command plays a sound the streamer put on the pad.persona.answercarriesmood: a word in brackets at the answer's start or end ([dancing] we won!), taken off the answer that goes to chat and to speech, so a persona drawn by an action can act as it speaks.vovo.say's optionspitch,ringandsmall: a character's voice (higher or lower at the same length, a metallic edge, smaller) from any voice.- An action's manifest may declare a
panel, drawn by the app in the drawer's Extensions: headings, notes, its controls, buttons (asking twice withconfirm), forms and lists read from its state with buttons on each line. What is done there arrives aspanel, with the name, a form'svalues, and a line'sitemandindex. vovo.media.playtells the app which event it was handled for, like the other calls: a moderator's chat message may then let its link through at once, when the profile says so.vovo.obs.source(scene, source, on?)andvovo.obs.filter(source, filter, on?), with theobs.togglepermission: a source shown or hidden in an OBS scene, a filter turned on or off; withouton, switched.eventin the options ofvovo.chat.send,vovo.pad.play,vovo.webhook.send,vovo.draw,vovo.media.play,vovo.obs.sourceandvovo.obs.filter: the event a call answers, for a call made after its listener returned (after anawait, in a timer), so two pages still ask once and a moderator's link still plays at once.input.move: how the streamer moves in a game, for a scene that sways with the camera: the mouse's movement (dx,dy), where W, A, S and D point (walk,strafe) andjump; a signal, read only while an action listens. The "Camera sway" example uses it.input.movealso comes from the arrows and from a controller (the left stick as the direction, the right one as the camera's turn, A as the jump);walkandstrafego from -1 to 1, a stick as far as it is pushed.remote.talk: someone talked on air from their phone, holding its button as with a walkie-talkie (name, the phone's;seconds, how long the voice lasts), for a scene that shows who is talking while they talk.input.movegoes on from the mouse and a controller while Vovó's window is in front, unless the computer pauses it; the keys still stop there.speech.text: what the streamer said into the microphone, a phrase at a time, for captions (text); a signal, read only while an action listens, written down by Whisper on the computer or by OpenAI when chosen.- Voice calls with an AI model, on air, with the
callpermission:vovo.call.startopens one (only from something done by hand by whoever runs the live),vovo.call.answeropens the microphone and has the model speak first,vovo.call.telltells it something,vovo.call.endhangs up;call.started,call.answered,call.textandcall.endedsay what happens, with no trigger needed. - The
tts.spokenevent: the app read a chat message or a reward's text aloud on air, withpersonatrue for the persona's own line. vovo.pad.busy(label, seconds, { lock }): one of the action's own buttons shown at work on the pad, its foot draining as the time goes; locked, a press of it waits for the end.sound.playedandvideo.playedsay how long the file plays (seconds), as the pad shows their buttons at work for that long.vovo.pad.lock(label, locked): one of the action's own buttons held, faded and not to be pressed, as a state of the action, with nothing draining.- A
panelmay hold several extensions:{ "kind": "extension", "label", "icon" }starts another, an entry of its own in Extensions with its name and its icon (one of Vovó's icons by name, or an emoji), and the pieces before the first show at the top of every one.tabthen splits an extension into sections, up to twelve in each. A panel that declares none is one extension, as before, and names stay the action's. - Settings an action declares (
settingsinaction.json: a colour, a number, on or off, a choice, a text, a file, a font), chosen in Customize at the computer:vovo.settings, thesettingsevent, the--vovo-<key>CSS variables and thedata-vovo-<key>attributes. - What an action shows whoever runs the live is called a panel, in Vovó and in the manifest:
{ "kind": "panel", "label", "icon" }starts another, an entry of its own in Panels, and Vovó writespanelfrom now on."kind": "extension", its first name, is read as the same for good, in packages already handed over and in actions already kept. An action that declares several panels this way is refused by a Vovó older than this, as any addition to the manifest is. vovo.screen.place(element, { background }): a colour (#000000) for the roomcontainleaves in the place when the shared screen is another shape. Without it that room stays see-through, as before, and shows what is behind the scene.screen.sharedalso sayswindoworscreenfor what Vovó captures itself, with no sound, and comes again withonstill true when something else takes the place of what was shared.action.jsonandpad.jsondescribed key by key, generated from Vovó's own code like this reference: a page of the help (api/json.*.md), and JSON Schemas for editors,api/action.schema.json, whichvovo devwrites beside an action's parts, andapi/pad.schema.json. Nothing in either file changed.vovo.emit(name, data, { event }): an action's own event is set off once however many pages show the action, as its other calls of the app are, by the event it answers (the one being handled, oreventfor a call made later) or, with none behind it, by its name and data within 5 seconds. Until now each page's call was an event of its own, so a scene open in OBS and in the preview window had what listened do its part twice.vovo.say(text, { event }): speech an action asks for is made once however many pages show the action, and each page plays the one file, by the event it answers (the one being handled, oreventfor a call made later) or, with none behind it, by its text, voice and pitch within 5 seconds. Until now it was made once for each page, so a scene open in OBS and in the preview window had two voices made for one sentence, which with OpenAI's are two requests that may not sound the same.action.jsonhasid: a name of its maker's choosing, the maker's and the action's with a dot between them (example.raffle), the same in every version. A package brought in finds the action it is a version of by it, whatever that action was renamed to, and no longer takes the place of another maker's action of the same name; without one, an action is found by its name, as before. A Vovó older than this passes the key over.versionis one line of 32 characters at most, and when a package takes an action's place the two versions are said, read as numbers when they are written as numbers (1.10.0after1.9.2,1.0.0-beta.1before1.0.0), with the package being the same or older said and never refused.action.jsonhaslicense: on what terms the action is handed over, as its maker says them, a licence's name (MIT,CC-BY-4.0) or a line of one's own, 100 characters at most, shown as the action is brought in and in the list of actions. A package may carry the licence's whole text beside the manifest asLICENSE(read too asLICENSE.mdandLICENSE.txt, and as each withLICENCE), 64 KB of text at most: it is kept with the action, read from the import's dialog before the action comes in, and written back asLICENSE. Vovó says what is written and holds nobody to it. A Vovó older than this passes both over.- A setting of the kind
camera: one of the computer's cameras, chosen in Customize by whoever uses the action, four at most. An action comes with none, andvovo.settings,--vovo-<key>anddata-vovo-<key>say only whether one is chosen. vovo.camera.place(element, { camera, fit, radius, background, mirror }): shows that camera where the element is, under the action's own drawing, asvovo.screen.placeshows the shared screen; with thecamera.showpermission. The action never sees its pictures.camera: a camera the action placed began to show, or stopped; heard without a trigger by an action that may show one.- A chat message's
partsmay carry more pictures: with a service switched on in Integrations (7TV, BetterTTV, FrankerFaceZ), a word of the message that is one of its emotes is a part with animage, as Twitch's own emotes are. Nothing changes for an action:vovo.chat.parts(e)shows them, and with every switch off the parts are what they were. vovo.chat.send(text, { as: "persona" }): the line goes through the persona's own Twitch account, as the persona's own and not the streamer's; while that account is not connected it is refused and nothing is written as the streamer in its place. Withoutas, nothing changes.twitch.chat'spersona: true when the persona's own account wrote the line, so an action leaves the persona's lines out of what it draws and never answers them.music.request: a viewer asked for a song of Vovó's music player, by its reward or its chat command, and what became of it (waiting, queued, playing, discarded, or refused and why), so an action answers in chat or shows who asked for what plays.