@hussra/logos-proclaim 0.0.0-stage → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +48 -2
- package/dist/proclaim-api.d.ts +111 -0
- package/dist/proclaim-api.d.ts.map +1 -0
- package/dist/proclaim-api.js +574 -0
- package/dist/proclaim-api.js.map +1 -0
- package/dist/proclaim-status.d.ts +153 -0
- package/dist/proclaim-status.d.ts.map +1 -0
- package/dist/proclaim-status.js +313 -0
- package/dist/proclaim-status.js.map +1 -0
- package/dist/proclaim-types.d.ts +195 -0
- package/dist/proclaim-types.d.ts.map +1 -0
- package/dist/proclaim-types.js +105 -0
- package/dist/proclaim-types.js.map +1 -0
- package/package.json +50 -3
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
import { request, Agent, setGlobalDispatcher, errors } from 'undici';
|
|
2
|
+
import { LogLevel, ProclaimStatus } from './proclaim-status.js';
|
|
3
|
+
import { IndexedAppCommand, ServiceItemKind, ServicePart, SimpleAppCommand, } from './proclaim-types.js';
|
|
4
|
+
export * from './proclaim-types.js';
|
|
5
|
+
export * from './proclaim-status.js';
|
|
6
|
+
// Reduce the connect timeout for UnDici connections
|
|
7
|
+
setGlobalDispatcher(new Agent({
|
|
8
|
+
connectTimeout: 500,
|
|
9
|
+
}));
|
|
10
|
+
/**
|
|
11
|
+
* Encapsulate the Proclaim API connections
|
|
12
|
+
*/
|
|
13
|
+
export class ProclaimAPI {
|
|
14
|
+
#ip;
|
|
15
|
+
#password;
|
|
16
|
+
#pollInterval;
|
|
17
|
+
#statusPromise;
|
|
18
|
+
#status = new ProclaimStatus();
|
|
19
|
+
/**
|
|
20
|
+
* The IP address of the computer where Proclaim is running
|
|
21
|
+
*/
|
|
22
|
+
get ip() {
|
|
23
|
+
return this.#ip;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The password to use to connection to the App Command API
|
|
27
|
+
*/
|
|
28
|
+
get password() {
|
|
29
|
+
return this.#password;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Authentication is required for IPs other than 127.0.0.1
|
|
33
|
+
*/
|
|
34
|
+
get authRequired() {
|
|
35
|
+
return this.#ip !== '127.0.0.1';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The status object representing the current state of the API connection and any on-air presentation
|
|
39
|
+
*/
|
|
40
|
+
get status() {
|
|
41
|
+
return this.#status;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Config is valid if we have an IP address, and (unless IP is 127.0.0.1) we have a password specified
|
|
45
|
+
* @returns boolean
|
|
46
|
+
*/
|
|
47
|
+
configIsValid() {
|
|
48
|
+
if (!this.#ip || this.#ip.trim() === '') {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (this.authRequired) {
|
|
52
|
+
if (!this.#password || this.#password.trim() === '') {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Configure this ProclaimAPI instance
|
|
60
|
+
* @param ip - IP address where Proclaim is running
|
|
61
|
+
* @param password - Proclaim local remote password - required if ip is other than 127.0.0.1
|
|
62
|
+
*/
|
|
63
|
+
async configure(ip, password) {
|
|
64
|
+
this.#status.emit('log', {
|
|
65
|
+
level: LogLevel.INFO,
|
|
66
|
+
message: `Configuring Proclaim API with IP ${ip} and password ${password ? '***' : '(none)'}`,
|
|
67
|
+
});
|
|
68
|
+
this.#ip = ip || '127.0.0.1';
|
|
69
|
+
this.#password = password || '';
|
|
70
|
+
this.#status.configured = true;
|
|
71
|
+
this.#status.configValid = this.configIsValid();
|
|
72
|
+
this.addEventListeners();
|
|
73
|
+
if (this.#pollInterval !== undefined) {
|
|
74
|
+
clearInterval(this.#pollInterval);
|
|
75
|
+
}
|
|
76
|
+
await this.initOnAirPolling();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Add internal event listeners for ProclaimStatus events - these listeners respond
|
|
80
|
+
* to our own state changes triggering further internal actions
|
|
81
|
+
*/
|
|
82
|
+
addEventListeners() {
|
|
83
|
+
// When we get connected to Proclaim, get an auth token if required
|
|
84
|
+
this.#status.on('connected', async ({ data }) => {
|
|
85
|
+
if (data && this.authRequired) {
|
|
86
|
+
await this.getAppCommandAPIAuthToken();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// When we get a new session ID set on-air status, set the current step to 0, fetch the
|
|
90
|
+
// presentation data, and get an auth token for the Local Wi-Fi API
|
|
91
|
+
this.#status.on('sessionId', async ({ data }) => {
|
|
92
|
+
if (data !== '') {
|
|
93
|
+
// Gone on air - set step to 0 and load presentation data
|
|
94
|
+
this.#status.onAir = true;
|
|
95
|
+
this.#status.step = 0;
|
|
96
|
+
await this.loadPresentation();
|
|
97
|
+
await this.getLocalWiFiRemoteAuthToken();
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Gone off air - clear presentation data
|
|
101
|
+
this.#status.onAir = false;
|
|
102
|
+
this.#status.presentation = null;
|
|
103
|
+
this.#status.itemId = '';
|
|
104
|
+
this.#status.itemCount = 0;
|
|
105
|
+
this.#status.songCount = 0;
|
|
106
|
+
this.#status.localWiFiAPIAuthenticated = false;
|
|
107
|
+
this.#status.localWifiAPIAuthToken = '';
|
|
108
|
+
this.#status.localWiFiAPIConnectionId = '';
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// When we load a new presentation, note its local revision and start checking presentation status
|
|
112
|
+
this.#status.on('presentation', async ({ data }) => {
|
|
113
|
+
// Just return if the presentation data got cleared
|
|
114
|
+
if (data === null) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.#status.presentationLocalRevision = data.localRevision;
|
|
118
|
+
this.#status.itemCount = data.serviceItems.length;
|
|
119
|
+
this.#status.songCount = data.serviceItems.filter((item) => item.kind === ServiceItemKind.SongLyrics).length;
|
|
120
|
+
// If we already have a current itemId, we should recalculate status properties that depend on it
|
|
121
|
+
if (this.#status.itemId && this.#status.itemId !== '') {
|
|
122
|
+
this.setItemProperties(this.#status.itemId);
|
|
123
|
+
}
|
|
124
|
+
// If we don't already have a #statusPromise, create another (after a short pause)
|
|
125
|
+
if (!this.#statusPromise) {
|
|
126
|
+
await this.sleep(1000);
|
|
127
|
+
this.#statusPromise = this.getPresentationStatus();
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
// When the presentation local revision changes, reload the whole presentation
|
|
131
|
+
this.#status.on('presentationLocalRevision', ({ data }) => {
|
|
132
|
+
// First check if we already have this location revision - this will be
|
|
133
|
+
// the case if presentationLocalRevision was changed because the presentation
|
|
134
|
+
// itself was just loaded
|
|
135
|
+
if (this.#status.presentation?.localRevision !== data) {
|
|
136
|
+
this.loadPresentation();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// When the selected item ID changes, load details of that item
|
|
140
|
+
this.#status.on('itemId', ({ data }) => {
|
|
141
|
+
if (data === '00000000-0000-0000-0000-000000000000') {
|
|
142
|
+
// This seems to happen when a custom quick screen is active, or the on screen Bible - ignore
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
this.setItemProperties(data);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Calculate status properties that depend on the currently live service item:
|
|
150
|
+
* itemIndex, itemTitle, itemKind, itemSlideCount, servicePart
|
|
151
|
+
* @param data - ID of live service item
|
|
152
|
+
*/
|
|
153
|
+
setItemProperties(data) {
|
|
154
|
+
const itemIndex = this.#status.presentation?.serviceItems.findIndex((item) => item.id === data) ?? -1;
|
|
155
|
+
const item = this.#status.presentation?.serviceItems[itemIndex];
|
|
156
|
+
if (item) {
|
|
157
|
+
this.#status.itemIndex = itemIndex;
|
|
158
|
+
this.#status.itemTitle = item?.title;
|
|
159
|
+
this.#status.itemKind = item?.kind;
|
|
160
|
+
this.#status.itemSlideCount = item?.slides.length;
|
|
161
|
+
const warmupStartIndex = this.#status.presentation?.warmupStartIndex ?? -1;
|
|
162
|
+
const serviceStartIndex = this.#status.presentation?.serviceStartIndex ?? -1;
|
|
163
|
+
const postServiceStartIndex = this.#status.presentation?.postServiceStartIndex ?? -1;
|
|
164
|
+
if (itemIndex < warmupStartIndex) {
|
|
165
|
+
this.#status.servicePart = ServicePart.PreService;
|
|
166
|
+
}
|
|
167
|
+
else if (itemIndex < serviceStartIndex) {
|
|
168
|
+
this.#status.servicePart = ServicePart.Warmup;
|
|
169
|
+
}
|
|
170
|
+
else if (itemIndex < postServiceStartIndex) {
|
|
171
|
+
this.#status.servicePart = ServicePart.Service;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
this.#status.servicePart = ServicePart.PostService;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
this.#status.itemIndex = -1;
|
|
179
|
+
this.#status.itemTitle = '';
|
|
180
|
+
this.#status.itemKind = null;
|
|
181
|
+
this.#status.itemSlideCount = 0;
|
|
182
|
+
this.#status.servicePart = null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Initialise polling to check if Proclaim has gone on air - every 1 second
|
|
187
|
+
*/
|
|
188
|
+
async initOnAirPolling() {
|
|
189
|
+
this.#pollInterval = setInterval(() => {
|
|
190
|
+
void this.onAirPoll();
|
|
191
|
+
}, 1000);
|
|
192
|
+
void this.onAirPoll();
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Poll to see whether Proclaim has gone on air. If already on air, does nothing - going off
|
|
196
|
+
* air is detected by presentation status changes
|
|
197
|
+
*/
|
|
198
|
+
async onAirPoll() {
|
|
199
|
+
// Only poll if we are off air - if we are on air, getPresentationStatus() will detect going off air
|
|
200
|
+
if (this.#status.onAir)
|
|
201
|
+
return;
|
|
202
|
+
const url = `http://${this.#ip}:52195/onair/session`;
|
|
203
|
+
try {
|
|
204
|
+
const { statusCode, body } = await request(url, {
|
|
205
|
+
method: 'GET',
|
|
206
|
+
headers: {
|
|
207
|
+
Accept: 'text/plain',
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
211
|
+
const text = await body.text();
|
|
212
|
+
this.#status.connected = true;
|
|
213
|
+
this.#status.sessionId = statusCode === 200 ? text : '';
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Some other unexpected status code - set disconnected, clear session ID
|
|
217
|
+
this.#status.connected = false;
|
|
218
|
+
this.#status.sessionId = '';
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
// Some unexpected error
|
|
223
|
+
const undiciError = error;
|
|
224
|
+
// Don't bother logging connection refused errors, connect timeout errors, or host down/unreachable errors.
|
|
225
|
+
// These are expected if Proclaim is not running.
|
|
226
|
+
if (undiciError.code !== 'ECONNREFUSED' &&
|
|
227
|
+
undiciError.code !== 'UND_ERR_CONNECT_TIMEOUT' &&
|
|
228
|
+
undiciError.code !== 'EHOSTDOWN' &&
|
|
229
|
+
undiciError.code !== 'EHOSTUNREACH') {
|
|
230
|
+
this.#status.emit('log', {
|
|
231
|
+
level: LogLevel.ERROR,
|
|
232
|
+
message: `Error polling onAir session`,
|
|
233
|
+
error: error,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
// Set disconnected, clear session ID
|
|
237
|
+
this.#status.connected = false;
|
|
238
|
+
this.#status.sessionId = '';
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Load details of the on-air presentation
|
|
243
|
+
*/
|
|
244
|
+
async loadPresentation() {
|
|
245
|
+
if (this.#status.sessionId.length === 0) {
|
|
246
|
+
this.#status.emit('log', { level: LogLevel.ERROR, message: `No sessionId available, cannot fetch presentation` });
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
const url = `http://${this.#ip}:52195/presentations/onair`;
|
|
250
|
+
try {
|
|
251
|
+
const { statusCode, body } = await request(url, {
|
|
252
|
+
method: 'GET',
|
|
253
|
+
headers: {
|
|
254
|
+
Accept: 'application/json',
|
|
255
|
+
Onairsessionid: this.#status.sessionId,
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
if (statusCode === 200) {
|
|
259
|
+
// Return the actual presentation
|
|
260
|
+
const presentation = (await body.json());
|
|
261
|
+
this.#status.presentation = presentation;
|
|
262
|
+
}
|
|
263
|
+
else if (statusCode === 404) {
|
|
264
|
+
// Off air - clear session ID
|
|
265
|
+
this.#status.sessionId = '';
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
// Some other unexpected status code - set disconnected & clear session ID
|
|
269
|
+
this.#status.connected = false;
|
|
270
|
+
this.#status.sessionId = '';
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
// Some unexpected error - set disconnected, & clear session ID
|
|
275
|
+
const undiciError = error;
|
|
276
|
+
if (undiciError.code !== 'ECONNREFUSED' && undiciError.code !== 'UND_ERR_CONNECT_TIMEOUT') {
|
|
277
|
+
this.#status.emit('log', {
|
|
278
|
+
level: LogLevel.ERROR,
|
|
279
|
+
message: `Error retrieving presentation data`,
|
|
280
|
+
error: error,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
this.#status.connected = false;
|
|
284
|
+
this.#status.sessionId = '';
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Call /onair/statusChanged to get current presentation status, passing the current session ID, presentation
|
|
289
|
+
* local revision and step. If the details sent are all current, Proclaim will long-poll for up to a minute
|
|
290
|
+
* before responding.
|
|
291
|
+
*/
|
|
292
|
+
async getPresentationStatus() {
|
|
293
|
+
const url = `http://${this.#ip}:52195/onair/statusChanged?localrevision=${this.#status.presentationLocalRevision}&step=${this.#status.step}`;
|
|
294
|
+
try {
|
|
295
|
+
const { statusCode, body } = await request(url, {
|
|
296
|
+
method: 'GET',
|
|
297
|
+
headers: {
|
|
298
|
+
Accept: 'application/json',
|
|
299
|
+
Onairsessionid: this.#status.sessionId,
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
if (statusCode === 200) {
|
|
303
|
+
// Return the actual presentation
|
|
304
|
+
const status = (await body.json());
|
|
305
|
+
// Sometimes we seem to get a 200 status but an empty body.
|
|
306
|
+
// If so, try again.
|
|
307
|
+
if (status === null) {
|
|
308
|
+
this.#status.emit('log', {
|
|
309
|
+
level: LogLevel.WARN,
|
|
310
|
+
message: `/onair/statusChanged returned no data, will back off and try again`,
|
|
311
|
+
});
|
|
312
|
+
await this.sleep(1000);
|
|
313
|
+
this.#statusPromise = this.getPresentationStatus();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// Update the current local revision and step
|
|
317
|
+
this.#status.step = status.status.revision;
|
|
318
|
+
this.#status.presentationLocalRevision = status.presentationLocalRevision;
|
|
319
|
+
// Update other status properties
|
|
320
|
+
this.#status.itemId = status.status.itemId; // This will trigger recalculation of other item properties
|
|
321
|
+
this.#status.slideIndex = status.status.slideIndex;
|
|
322
|
+
this.#status.quickScreenKind = status.status.quickScreenKind;
|
|
323
|
+
this.#status.mediaState = status.status.mediaState;
|
|
324
|
+
// Call getPresentationStatus() again to get the next status update
|
|
325
|
+
this.#statusPromise = this.getPresentationStatus();
|
|
326
|
+
}
|
|
327
|
+
else if (statusCode === 404) {
|
|
328
|
+
// Off air - clear session ID, clear status promise
|
|
329
|
+
this.#status.sessionId = '';
|
|
330
|
+
this.#statusPromise = null;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// Some other unexpected status code - set disconnected, clear session ID, clear status promise
|
|
334
|
+
this.#status.connected = false;
|
|
335
|
+
this.#status.sessionId = '';
|
|
336
|
+
this.#statusPromise = null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
// Some unexpected error - set disconnected, clear session ID, clear status promise
|
|
341
|
+
const undiciError = error;
|
|
342
|
+
if (undiciError.code !== 'ECONNREFUSED' && undiciError.code !== 'UND_ERR_CONNECT_TIMEOUT') {
|
|
343
|
+
this.#status.emit('log', {
|
|
344
|
+
level: LogLevel.ERROR,
|
|
345
|
+
message: `Connection refused retrieving presentation status`,
|
|
346
|
+
error: error,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
this.#status.connected = false;
|
|
350
|
+
this.#status.sessionId = '';
|
|
351
|
+
this.#statusPromise = null;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get an auth token for the App Command API
|
|
356
|
+
*/
|
|
357
|
+
async getAppCommandAPIAuthToken() {
|
|
358
|
+
const url = `http://${this.#ip}:52195/appCommand/authenticate`;
|
|
359
|
+
try {
|
|
360
|
+
const { statusCode, body } = await request(url, {
|
|
361
|
+
method: 'POST',
|
|
362
|
+
headers: {
|
|
363
|
+
'content-type': 'application/json',
|
|
364
|
+
},
|
|
365
|
+
body: JSON.stringify({
|
|
366
|
+
Password: this.#password,
|
|
367
|
+
}),
|
|
368
|
+
});
|
|
369
|
+
if (statusCode !== 200) {
|
|
370
|
+
this.#status.emit('log', {
|
|
371
|
+
level: LogLevel.ERROR,
|
|
372
|
+
message: `Authentication error in getAuthToken(): ${statusCode}`,
|
|
373
|
+
});
|
|
374
|
+
if (this.authRequired) {
|
|
375
|
+
this.#status.appCommandAPIAuthenticated = false;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const data = (await body.json());
|
|
379
|
+
this.#status.appCommandAPIAuthToken = data?.proclaimAuthToken;
|
|
380
|
+
this.#status.appCommandAPIAuthenticated = true;
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
this.#status.emit('log', {
|
|
384
|
+
level: LogLevel.ERROR,
|
|
385
|
+
message: `Authentication error in getAuthToken()`,
|
|
386
|
+
error: error,
|
|
387
|
+
});
|
|
388
|
+
if (this.authRequired) {
|
|
389
|
+
this.#status.appCommandAPIAuthenticated = false;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Refresh auth tokens for App Command and Local Wi-Fi APIs
|
|
395
|
+
*/
|
|
396
|
+
async reconnect() {
|
|
397
|
+
if (this.authRequired) {
|
|
398
|
+
await this.getAppCommandAPIAuthToken();
|
|
399
|
+
}
|
|
400
|
+
await this.getLocalWiFiRemoteAuthToken();
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Send any App Command to Proclaim
|
|
404
|
+
* @param command - The App Command to send: see documentation at
|
|
405
|
+
* https://support.proclaim.logos.com/hc/en-us/articles/19864456647053-Proclaim-App-Command-API
|
|
406
|
+
* @param index - For certain App Commands (annotated with an * at the API reference), the index to use (1-254)
|
|
407
|
+
* e.g. service item number, slide number, verse number etc.
|
|
408
|
+
* @returns Whether the command was sent successfully
|
|
409
|
+
*/
|
|
410
|
+
async sendAppCommand(cmd) {
|
|
411
|
+
const command = cmd.command;
|
|
412
|
+
const index = 'index' in cmd ? cmd.index : undefined;
|
|
413
|
+
this.#status.emit('log', {
|
|
414
|
+
level: LogLevel.INFO,
|
|
415
|
+
message: `Sending App Command ${command}${index !== undefined ? ` with index ${index}` : ''}`,
|
|
416
|
+
});
|
|
417
|
+
let url = `http://${this.#ip}:52195/appCommand/perform?appCommandName=${command}`;
|
|
418
|
+
if (index !== undefined) {
|
|
419
|
+
url = `${url}&index=${index}`;
|
|
420
|
+
}
|
|
421
|
+
try {
|
|
422
|
+
const { statusCode, body } = await request(url, {
|
|
423
|
+
headers: {
|
|
424
|
+
'Content-Type': 'application/json',
|
|
425
|
+
...(this.authRequired && this.#status.appCommandAPIAuthenticated
|
|
426
|
+
? { ProclaimAuthToken: this.#status.appCommandAPIAuthToken }
|
|
427
|
+
: {}),
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
const data = await body.text();
|
|
431
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
432
|
+
this.#status.emit('log', {
|
|
433
|
+
level: LogLevel.ERROR,
|
|
434
|
+
message: `Proclaim authentication failed: ${statusCode} ${data}`,
|
|
435
|
+
});
|
|
436
|
+
this.#status.appCommandAPIAuthenticated = false;
|
|
437
|
+
this.#status.appCommandAPIAuthToken = '';
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
else if (statusCode !== 200) {
|
|
441
|
+
this.#status.emit('log', { level: LogLevel.ERROR, message: `Proclaim command failed: ${statusCode} ${data}` });
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
if (data !== 'success') {
|
|
445
|
+
this.#status.emit('log', { level: LogLevel.ERROR, message: `Unexpected response from Proclaim: ${data}` });
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
catch (error) {
|
|
450
|
+
this.#status.emit('log', { level: LogLevel.ERROR, message: `Proclaim command failed`, error: error });
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Get an auth token for the Local Wi-Fi API
|
|
457
|
+
*/
|
|
458
|
+
async getLocalWiFiRemoteAuthToken() {
|
|
459
|
+
const url = `http://${this.#ip}:52195/auth/control`;
|
|
460
|
+
try {
|
|
461
|
+
const { statusCode, body } = await request(url, {
|
|
462
|
+
method: 'POST',
|
|
463
|
+
headers: {
|
|
464
|
+
'content-type': 'application/json',
|
|
465
|
+
OnAirSessionId: this.#status.sessionId,
|
|
466
|
+
},
|
|
467
|
+
body: JSON.stringify({
|
|
468
|
+
FaithlifeUserId: null,
|
|
469
|
+
UserName: null,
|
|
470
|
+
RemoteDeviceName: 'companion-module-logos-proclaim',
|
|
471
|
+
Password: 'Proclaim',
|
|
472
|
+
}),
|
|
473
|
+
});
|
|
474
|
+
if (statusCode !== 200) {
|
|
475
|
+
this.#status.emit('log', {
|
|
476
|
+
level: LogLevel.ERROR,
|
|
477
|
+
message: `Unable to authenticate to Local Wi-Fi API: ${statusCode}`,
|
|
478
|
+
});
|
|
479
|
+
this.#status.localWiFiAPIAuthenticated = false;
|
|
480
|
+
this.#status.localWifiAPIAuthToken = '';
|
|
481
|
+
this.#status.localWiFiAPIConnectionId = '';
|
|
482
|
+
}
|
|
483
|
+
const data = (await body.json());
|
|
484
|
+
this.#status.localWiFiAPIAuthenticated = true;
|
|
485
|
+
this.#status.localWifiAPIAuthToken = data.authenticationToken;
|
|
486
|
+
this.#status.localWiFiAPIConnectionId = data.connectionId;
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
this.#status.emit('log', {
|
|
490
|
+
level: LogLevel.ERROR,
|
|
491
|
+
message: `Error taking Local Wi-Fi control`,
|
|
492
|
+
error: error,
|
|
493
|
+
});
|
|
494
|
+
this.#status.localWiFiAPIAuthenticated = false;
|
|
495
|
+
this.#status.localWifiAPIAuthToken = '';
|
|
496
|
+
this.#status.localWiFiAPIConnectionId = '';
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Jump to a specific service item by ID, and optionally a specific slide number
|
|
501
|
+
* @param itemId - ID of the service item to jump to
|
|
502
|
+
* @param slideIndex - slide number to jump to within that service item (0-based)
|
|
503
|
+
* @returns Whether the command was sent successfully
|
|
504
|
+
*/
|
|
505
|
+
async goToServiceItemAndSlide(itemId, slideIndex = 0) {
|
|
506
|
+
this.#status.emit('log', {
|
|
507
|
+
level: LogLevel.INFO,
|
|
508
|
+
message: `Jumping to service item ${itemId} and slide ${slideIndex}`,
|
|
509
|
+
});
|
|
510
|
+
const url = `http://${this.#ip}:52195/onair/statusChanged`;
|
|
511
|
+
try {
|
|
512
|
+
const { statusCode, body } = await request(url, {
|
|
513
|
+
method: 'POST',
|
|
514
|
+
headers: {
|
|
515
|
+
'content-type': 'application/json',
|
|
516
|
+
OnAirSessionId: this.#status.sessionId,
|
|
517
|
+
ProclaimAuthToken: this.#status.localWifiAPIAuthToken,
|
|
518
|
+
},
|
|
519
|
+
body: JSON.stringify({
|
|
520
|
+
PresentationId: this.#status.presentation?.id,
|
|
521
|
+
PresentationLocalRevision: this.#status.presentationLocalRevision,
|
|
522
|
+
Status: {
|
|
523
|
+
Revision: this.#status.step,
|
|
524
|
+
ItemId: itemId,
|
|
525
|
+
SlideIndex: slideIndex,
|
|
526
|
+
QuickScreen: '',
|
|
527
|
+
QuickScreenData: '',
|
|
528
|
+
QuickScreenKind: 'None',
|
|
529
|
+
MediaState: this.#status.mediaState,
|
|
530
|
+
},
|
|
531
|
+
}),
|
|
532
|
+
});
|
|
533
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
534
|
+
this.#status.emit('log', {
|
|
535
|
+
level: LogLevel.ERROR,
|
|
536
|
+
message: `Proclaim authentication failed: ${statusCode} ${body.text()}`,
|
|
537
|
+
});
|
|
538
|
+
this.#status.localWiFiAPIAuthenticated = false;
|
|
539
|
+
this.#status.localWifiAPIAuthToken = '';
|
|
540
|
+
this.#status.localWiFiAPIConnectionId = '';
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
if (statusCode !== 200) {
|
|
544
|
+
this.#status.emit('log', {
|
|
545
|
+
level: LogLevel.ERROR,
|
|
546
|
+
message: `Unexpected response from Proclaim: ${statusCode} ${body.text()}`,
|
|
547
|
+
});
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
this.#status.emit('log', { level: LogLevel.ERROR, message: `Proclaim command failed`, error: error });
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* On being destroyed, clear the on-air polling interval
|
|
559
|
+
*/
|
|
560
|
+
destroy() {
|
|
561
|
+
if (this.#pollInterval !== undefined) {
|
|
562
|
+
clearInterval(this.#pollInterval);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Sleep
|
|
567
|
+
* @param ms - number of milliseconds to sleep
|
|
568
|
+
* @returns Promise that will resolve after the specified time
|
|
569
|
+
*/
|
|
570
|
+
sleep(ms) {
|
|
571
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
//# sourceMappingURL=proclaim-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proclaim-api.js","sourceRoot":"","sources":["../src/proclaim-api.ts"],"names":[],"mappings":"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"}
|