Overflow Tap 1.0.0: switch Overflow Tap destinations from keywords in ProPresenter slide notes
A new module that does what Overflow's "ProPresenter Integration" helper app
does, inside ProdDash: the live slide's notes are read from ProPresenter
(GET /v1/status/slide, twice a second) and when they carry one of the admin
page's keywords, the chosen Overflow Tap groups are pointed at that keyword's
destination. One tile: the keyword Tap is on (and since when), its
destination and the groups moved, a chip saying whether the slide on screen
carries a keyword, and the last four switches. A failed switch turns the tile
red with the reason, retries three times, and can flash an alert channel.
Admin config: ProPresenter endpoint + password; Overflow client ID + API key
(x-client-id / x-api-key, the public API's two headers); Tap groups to switch
(multiselect read from the account over /groups); keywords as text, one per
line (`give = Give Online`, optionally `@ Lobby, Kids Wing`); match mode
(whole word / anywhere / own line); alerts switch + channel.
The one unverified piece: Overflow's public API documents only reads for Tap
(OpenAPI checked 2026-10-07), while Overflow's helper uses the Dashboard's
private API. The switch is sent as PATCH /api/v3/tap/groups/{id} with the new
destinationId — the natural shape for this API — and every switch is confirmed
by reading the group back, so a refusal shows on the tile instead of passing
silently. overflow.js is the one place to change if Overflow names a
different route.
Also: tools/overflow-tap-mock.js (a ProPresenter whose slide notes carry
keywords on :1602 plus the Overflow Tap API on :24720, --read-only to fail
every switch), keywords.selftest.js (14 cases), README + CLAUDE.md entries.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
c9e03398a6
commit
6b51044be6
@@ -0,0 +1,144 @@
|
||||
{
|
||||
"id": "overflow-tap",
|
||||
"name": "Overflow Tap",
|
||||
"version": "1.0.0",
|
||||
"proddash": ">=1.11.0",
|
||||
"description": "Switches Overflow Tap destinations from keywords in ProPresenter slide notes",
|
||||
"permissions": [
|
||||
{
|
||||
"kind": "local-network",
|
||||
"reason": "Reaching ProPresenter on this network"
|
||||
}
|
||||
],
|
||||
"client": "client.js",
|
||||
"server": "server.js",
|
||||
"style": "style.css",
|
||||
"minSize": {
|
||||
"w": 2,
|
||||
"h": 2
|
||||
},
|
||||
"defaultSize": {
|
||||
"w": 4,
|
||||
"h": 3
|
||||
},
|
||||
"configGroups": {
|
||||
"ProPresenter": {
|
||||
"help": "The ProPresenter whose slide notes carry the keywords. Enable the network in ProPresenter's Preferences › Network and enter the host and port shown there. Only the live slide's notes are read — nothing on the stage screens changes."
|
||||
},
|
||||
"Overflow": {
|
||||
"collapsed": "whenSet",
|
||||
"help": "API credentials from the Overflow Dashboard: Developers › API Keys (a READ_WRITE key). Tap groups and destinations are read from the account once these are saved; the groups list below fills in from there."
|
||||
},
|
||||
"Keywords": {
|
||||
"help": "One keyword per line, as `keyword = Destination name` — the destination exactly as it is named in Overflow's Tap module (or its id). Add ` @ Group A, Group B` to a line to switch only those groups instead of the ones chosen above. When a slide's notes carry one of these keywords, every chosen group is pointed at that destination; a slide without a keyword changes nothing. When several match, the first line wins."
|
||||
},
|
||||
"Alerts": {
|
||||
"toggle": "alertEnabled",
|
||||
"collapsed": true,
|
||||
"help": "Flash the dashboards listening on this channel when a switch fails — Overflow unreachable or refusing the change — so someone can fix Tap by hand before the moment passes."
|
||||
}
|
||||
},
|
||||
"configSchema": {
|
||||
"propresenter": {
|
||||
"type": "endpoint",
|
||||
"label": "ProPresenter",
|
||||
"group": "ProPresenter",
|
||||
"default": {
|
||||
"host": "",
|
||||
"port": 1025
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"type": "password",
|
||||
"label": "API password",
|
||||
"group": "ProPresenter",
|
||||
"default": "",
|
||||
"help": "Only if a password is set in ProPresenter's network preferences."
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string",
|
||||
"label": "Client ID",
|
||||
"group": "Overflow",
|
||||
"default": ""
|
||||
},
|
||||
"apiKey": {
|
||||
"type": "password",
|
||||
"label": "API key",
|
||||
"group": "Overflow",
|
||||
"default": ""
|
||||
},
|
||||
"groups": {
|
||||
"type": "multiselect",
|
||||
"label": "Tap groups",
|
||||
"group": "Overflow",
|
||||
"default": [],
|
||||
"optionsRoute": "/groups",
|
||||
"help": "The groups a keyword switches. None chosen means every group on the account."
|
||||
},
|
||||
"keywords": {
|
||||
"type": "text",
|
||||
"label": "Keywords",
|
||||
"group": "Keywords",
|
||||
"default": "",
|
||||
"help": "One per line — give = Give Online"
|
||||
},
|
||||
"matching": {
|
||||
"type": "select",
|
||||
"label": "Match",
|
||||
"group": "Keywords",
|
||||
"default": "word",
|
||||
"options": [
|
||||
{
|
||||
"value": "word",
|
||||
"label": "Whole word in the notes"
|
||||
},
|
||||
{
|
||||
"value": "anywhere",
|
||||
"label": "Anywhere in the notes"
|
||||
},
|
||||
{
|
||||
"value": "line",
|
||||
"label": "On its own line"
|
||||
}
|
||||
],
|
||||
"help": "Whole word keeps `give` from firing on `forgiveness`; anywhere is what Overflow's own helper does."
|
||||
},
|
||||
"alertEnabled": {
|
||||
"type": "switch",
|
||||
"label": "Alert when a switch fails",
|
||||
"group": "Alerts",
|
||||
"default": false
|
||||
},
|
||||
"alertChannel": {
|
||||
"type": "number",
|
||||
"label": "Channel",
|
||||
"group": "Alerts",
|
||||
"default": 1,
|
||||
"min": 1,
|
||||
"max": 6,
|
||||
"help": "1–6; each dashboard chooses the channels it listens to in its Layouts menu."
|
||||
}
|
||||
},
|
||||
"instanceSchema": {
|
||||
"showDestination": {
|
||||
"type": "switch",
|
||||
"label": "Destination",
|
||||
"default": true
|
||||
},
|
||||
"showGroups": {
|
||||
"type": "switch",
|
||||
"label": "Groups",
|
||||
"default": true
|
||||
},
|
||||
"showSlide": {
|
||||
"type": "switch",
|
||||
"label": "Slide match",
|
||||
"default": true
|
||||
},
|
||||
"showHistory": {
|
||||
"type": "switch",
|
||||
"label": "History",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user