The first cut guessed a write route on Overflow's public API, which documents
only reads for Tap. With the helper app's bundle in hand (Overflow ProPresenter
Integration 1.2.3, read 2026-10-11) the module now makes exactly the calls the
helper makes, against the Dashboard's own backend:
POST /nonprofit-dashboard/authentication/login/jwt a Dashboard sign-in → JWT
GET /nonprofit-dashboard/propresenter/nonprofits/{id}/keywords
the Keyword Mappings
POST …/nonprofits/{id}/keywords?syncNonprofit=true { keywords } = the switch
So the keyword → destination → Tap groups mapping stays where Overflow keeps
it (Dashboard › Integrations › ProPresenter › Keyword Mappings) and is read
from there: on start, every five minutes, on the tile's refresh button, and
from every trigger's answer. Admin config shrinks to the ProPresenter endpoint,
the Overflow Dashboard login (plus a Nonprofit ID only for an @overflow.co
staff login) and the alert switch; the API-key, Tap-groups, keyword-text and
match-mode fields are gone.
Behaviour follows the helper: both the presentation layer (/v1/status/slide)
and the announcement layer (/v1/announcement/slide_index + /active) are
watched; when a layer's set of matched keywords changes to a non-empty set it
is sent; matching is per word, case-insensitive, punctuation around the word
ignored. The session token is cached across re-inits for the same login so an
admin saving config repeatedly cannot trip Overflow's "too many attempts";
a 401 signs in again once; a refused sign-in is not retried within 20 s.
tools/overflow-tap-mock.js now plays the Dashboard API (any email/password
signs in; --fail-switch, --expire=<s>, --login=<email>:<password>) and gives
the mock ProPresenter an announcement layer (--no-announcements for an older
one). Verified against it: sign-in, keyword load, triggers on both layers,
token expiry → re-login, 500 → NOT SWITCHED + alert + retries, wrong login →
the reason on the tile and in the health line, and recovery. keywords.selftest.js
pins the matching rule (8 cases).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
113 lines
3.3 KiB
JSON
113 lines
3.3 KiB
JSON
{
|
||
"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 (and the announcement layer's) are read — nothing on the stage screens changes."
|
||
},
|
||
"Overflow": {
|
||
"collapsed": "whenSet",
|
||
"help": "An Overflow Dashboard login with Tap access — what Overflow's own ProPresenter helper app signs in with. Google sign-in does not work here: the account needs a password (Forgot Your Password? on the Dashboard sets one). The keywords, their destinations and their Tap groups are managed in the Dashboard under Integrations › ProPresenter › Keyword Mappings and read from there; after changing them, press the tile's refresh button or wait a few minutes."
|
||
},
|
||
"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."
|
||
},
|
||
"overflowEmail": {
|
||
"type": "string",
|
||
"label": "Email",
|
||
"group": "Overflow",
|
||
"default": ""
|
||
},
|
||
"overflowPassword": {
|
||
"type": "password",
|
||
"label": "Password",
|
||
"group": "Overflow",
|
||
"default": ""
|
||
},
|
||
"nonprofitId": {
|
||
"type": "string",
|
||
"label": "Nonprofit ID",
|
||
"group": "Overflow",
|
||
"default": "",
|
||
"help": "Leave blank: a church login carries its own. Only an @overflow.co staff login needs one."
|
||
},
|
||
"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
|
||
}
|
||
}
|
||
}
|