Files
ProdDash/modules/overflow-tap/module.json
Waters ChurchandClaude Fable 5.1 459d8b9c38 Overflow Tap: speak Overflow's Dashboard API, as its own helper app does
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>
2026-10-11 10:25:02 -04:00

113 lines
3.3 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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
}
}
}