@churchapps/content-providers 0.4.1 → 0.5.1
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/README.md +14 -16
- package/dist/index.cjs +441 -846
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -148
- package/dist/index.d.ts +78 -148
- package/dist/index.js +436 -845
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -22,13 +22,16 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
APlayProvider: () => APlayProvider,
|
|
24
24
|
B1ChurchProvider: () => B1ChurchProvider,
|
|
25
|
+
BaseProvider: () => BaseProvider,
|
|
25
26
|
BibleProjectProvider: () => BibleProjectProvider,
|
|
26
27
|
CbnProvider: () => CbnProvider,
|
|
28
|
+
DeviceFlowHelper: () => DeviceFlowHelper,
|
|
27
29
|
DropboxProvider: () => DropboxProvider,
|
|
28
30
|
HighVoltageKidsProvider: () => HighVoltageKidsProvider,
|
|
29
31
|
JesusFilmProvider: () => JesusFilmProvider,
|
|
30
32
|
LessonsChurchProvider: () => LessonsChurchProvider,
|
|
31
33
|
LifeChurchProvider: () => LifeChurchProvider,
|
|
34
|
+
OAuthHelper: () => OAuthHelper,
|
|
32
35
|
PlanningCenterProvider: () => PlanningCenterProvider,
|
|
33
36
|
SignPresenterProvider: () => SignPresenterProvider,
|
|
34
37
|
TokenHelper: () => TokenHelper,
|
|
@@ -40,7 +43,8 @@ __export(index_exports, {
|
|
|
40
43
|
isContentFile: () => isContentFile,
|
|
41
44
|
isContentFolder: () => isContentFolder,
|
|
42
45
|
navigateToPath: () => navigateToPath,
|
|
43
|
-
registerProvider: () => registerProvider
|
|
46
|
+
registerProvider: () => registerProvider,
|
|
47
|
+
toAuthData: () => toAuthData
|
|
44
48
|
});
|
|
45
49
|
module.exports = __toCommonJS(index_exports);
|
|
46
50
|
|
|
@@ -64,33 +68,81 @@ function navigateToPath(instructions, path) {
|
|
|
64
68
|
return current;
|
|
65
69
|
}
|
|
66
70
|
|
|
71
|
+
// src/helpers/TokenHelper.ts
|
|
72
|
+
function toAuthData(data, fallbacks) {
|
|
73
|
+
return {
|
|
74
|
+
access_token: data.access_token,
|
|
75
|
+
refresh_token: data.refresh_token || fallbacks?.refreshToken || "",
|
|
76
|
+
token_type: data.token_type || "Bearer",
|
|
77
|
+
created_at: Math.floor(Date.now() / 1e3),
|
|
78
|
+
expires_in: data.expires_in,
|
|
79
|
+
scope: data.scope || fallbacks?.scope || ""
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
var TokenHelper = class {
|
|
83
|
+
isAuthValid(auth) {
|
|
84
|
+
if (!auth) return false;
|
|
85
|
+
return !this.isTokenExpired(auth);
|
|
86
|
+
}
|
|
87
|
+
isTokenExpired(auth) {
|
|
88
|
+
if (!auth.created_at || !auth.expires_in) return true;
|
|
89
|
+
const expiresAt = (auth.created_at + auth.expires_in) * 1e3;
|
|
90
|
+
return Date.now() > expiresAt - 5 * 60 * 1e3;
|
|
91
|
+
}
|
|
92
|
+
async refreshToken(config, auth) {
|
|
93
|
+
if (!auth.refresh_token) return null;
|
|
94
|
+
try {
|
|
95
|
+
const params = new URLSearchParams({
|
|
96
|
+
grant_type: "refresh_token",
|
|
97
|
+
refresh_token: auth.refresh_token,
|
|
98
|
+
client_id: config.clientId
|
|
99
|
+
});
|
|
100
|
+
const response = await fetch(`${config.oauthBase}/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() });
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
console.warn(`[TokenHelper] Token refresh failed: ${response.status} ${response.statusText}`);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const data = await response.json();
|
|
106
|
+
return toAuthData(data, { refreshToken: auth.refresh_token, scope: auth.scope });
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
67
113
|
// src/helpers/OAuthHelper.ts
|
|
114
|
+
function generateCodeVerifier() {
|
|
115
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
|
|
116
|
+
const length = 64;
|
|
117
|
+
const array = new Uint8Array(length);
|
|
118
|
+
crypto.getRandomValues(array);
|
|
119
|
+
let result = "";
|
|
120
|
+
for (let i = 0; i < length; i++) {
|
|
121
|
+
result += chars.charAt(array[i] % chars.length);
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
async function generateCodeChallenge(verifier) {
|
|
126
|
+
const encoder = new TextEncoder();
|
|
127
|
+
const data = encoder.encode(verifier);
|
|
128
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
129
|
+
const hashArray = new Uint8Array(hashBuffer);
|
|
130
|
+
let binary = "";
|
|
131
|
+
for (let i = 0; i < hashArray.length; i++) {
|
|
132
|
+
binary += String.fromCharCode(hashArray[i]);
|
|
133
|
+
}
|
|
134
|
+
const base64 = btoa(binary);
|
|
135
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
136
|
+
}
|
|
68
137
|
var OAuthHelper = class {
|
|
69
138
|
generateCodeVerifier() {
|
|
70
|
-
|
|
71
|
-
const length = 64;
|
|
72
|
-
const array = new Uint8Array(length);
|
|
73
|
-
crypto.getRandomValues(array);
|
|
74
|
-
let result = "";
|
|
75
|
-
for (let i = 0; i < length; i++) {
|
|
76
|
-
result += chars.charAt(array[i] % chars.length);
|
|
77
|
-
}
|
|
78
|
-
return result;
|
|
139
|
+
return generateCodeVerifier();
|
|
79
140
|
}
|
|
80
141
|
async generateCodeChallenge(verifier) {
|
|
81
|
-
|
|
82
|
-
const data = encoder.encode(verifier);
|
|
83
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
84
|
-
const hashArray = new Uint8Array(hashBuffer);
|
|
85
|
-
let binary = "";
|
|
86
|
-
for (let i = 0; i < hashArray.length; i++) {
|
|
87
|
-
binary += String.fromCharCode(hashArray[i]);
|
|
88
|
-
}
|
|
89
|
-
const base64 = btoa(binary);
|
|
90
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
142
|
+
return generateCodeChallenge(verifier);
|
|
91
143
|
}
|
|
92
144
|
async buildAuthUrl(config, codeVerifier, redirectUri, state) {
|
|
93
|
-
const codeChallenge = await
|
|
145
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
94
146
|
const params = new URLSearchParams({
|
|
95
147
|
response_type: "code",
|
|
96
148
|
client_id: config.clientId,
|
|
@@ -117,39 +169,7 @@ var OAuthHelper = class {
|
|
|
117
169
|
return null;
|
|
118
170
|
}
|
|
119
171
|
const data = await response.json();
|
|
120
|
-
return
|
|
121
|
-
} catch {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
// src/helpers/TokenHelper.ts
|
|
128
|
-
var TokenHelper = class {
|
|
129
|
-
isAuthValid(auth) {
|
|
130
|
-
if (!auth) return false;
|
|
131
|
-
return !this.isTokenExpired(auth);
|
|
132
|
-
}
|
|
133
|
-
isTokenExpired(auth) {
|
|
134
|
-
if (!auth.created_at || !auth.expires_in) return true;
|
|
135
|
-
const expiresAt = (auth.created_at + auth.expires_in) * 1e3;
|
|
136
|
-
return Date.now() > expiresAt - 5 * 60 * 1e3;
|
|
137
|
-
}
|
|
138
|
-
async refreshToken(config, auth) {
|
|
139
|
-
if (!auth.refresh_token) return null;
|
|
140
|
-
try {
|
|
141
|
-
const params = new URLSearchParams({
|
|
142
|
-
grant_type: "refresh_token",
|
|
143
|
-
refresh_token: auth.refresh_token,
|
|
144
|
-
client_id: config.clientId
|
|
145
|
-
});
|
|
146
|
-
const response = await fetch(`${config.oauthBase}/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() });
|
|
147
|
-
if (!response.ok) {
|
|
148
|
-
console.warn(`[TokenHelper] Token refresh failed: ${response.status} ${response.statusText}`);
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
const data = await response.json();
|
|
152
|
-
return { access_token: data.access_token, refresh_token: data.refresh_token || auth.refresh_token, token_type: data.token_type || "Bearer", created_at: Math.floor(Date.now() / 1e3), expires_in: data.expires_in, scope: data.scope || auth.scope };
|
|
172
|
+
return toAuthData(data, { scope: config.scopes.join(" ") });
|
|
153
173
|
} catch {
|
|
154
174
|
return null;
|
|
155
175
|
}
|
|
@@ -176,7 +196,7 @@ var DeviceFlowHelper = class {
|
|
|
176
196
|
const response = await fetch(`${config.oauthBase}/token`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ grant_type: "urn:ietf:params:oauth:grant-type:device_code", device_code: deviceCode, client_id: config.clientId }) });
|
|
177
197
|
if (response.ok) {
|
|
178
198
|
const data = await response.json();
|
|
179
|
-
return
|
|
199
|
+
return toAuthData(data, { scope: config.scopes.join(" ") });
|
|
180
200
|
}
|
|
181
201
|
const errorData = await response.json();
|
|
182
202
|
switch (errorData.error) {
|
|
@@ -226,6 +246,19 @@ var ApiHelper = class {
|
|
|
226
246
|
}
|
|
227
247
|
};
|
|
228
248
|
|
|
249
|
+
// src/providers/BaseProvider.ts
|
|
250
|
+
var BaseProvider = class {
|
|
251
|
+
constructor() {
|
|
252
|
+
this.apiHelper = new ApiHelper();
|
|
253
|
+
}
|
|
254
|
+
apiRequest(path, auth, method = "GET", body) {
|
|
255
|
+
return this.apiHelper.apiRequest(this.config, this.id, path, auth, method, body);
|
|
256
|
+
}
|
|
257
|
+
supportsDeviceFlow() {
|
|
258
|
+
return !!this.config.supportsDeviceFlow && !!this.config.deviceAuthEndpoint;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
229
262
|
// src/pathUtils.ts
|
|
230
263
|
function parsePath(path) {
|
|
231
264
|
if (!path || path === "/" || path === "") {
|
|
@@ -239,26 +272,6 @@ function getSegment(path, index) {
|
|
|
239
272
|
return segments[index] ?? null;
|
|
240
273
|
}
|
|
241
274
|
|
|
242
|
-
// src/providers/aPlay/APlayApi.ts
|
|
243
|
-
var API_BASE = "https://api-prod.amazingkids.app";
|
|
244
|
-
async function checkMediaLicense(mediaId, auth) {
|
|
245
|
-
if (!auth) return null;
|
|
246
|
-
try {
|
|
247
|
-
const url = `${API_BASE}/prod/reports/media/license-check`;
|
|
248
|
-
const response = await fetch(url, { method: "POST", headers: { "Authorization": `Bearer ${auth.access_token}`, "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify({ mediaIds: [mediaId] }) });
|
|
249
|
-
if (!response.ok) return null;
|
|
250
|
-
const data = await response.json();
|
|
251
|
-
const licenseData = Array.isArray(data) ? data : data.data || [];
|
|
252
|
-
const result = licenseData.find((item) => item.mediaId === mediaId);
|
|
253
|
-
if (result?.isLicensed) {
|
|
254
|
-
return { mediaId, status: "valid", message: "Media is licensed for playback", expiresAt: result.expiresAt };
|
|
255
|
-
}
|
|
256
|
-
return { mediaId, status: "not_licensed", message: "Media is not licensed" };
|
|
257
|
-
} catch {
|
|
258
|
-
return { mediaId, status: "unknown", message: "Unable to verify license status" };
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
275
|
// src/utils.ts
|
|
263
276
|
var IMAGE_DURATION_SECONDS = 15;
|
|
264
277
|
function slugify(text) {
|
|
@@ -296,6 +309,31 @@ function createFile(id, title, url, options) {
|
|
|
296
309
|
function generateId() {
|
|
297
310
|
return "gen-" + Math.random().toString(36).substring(2, 11);
|
|
298
311
|
}
|
|
312
|
+
function fileToActionItem(file) {
|
|
313
|
+
return {
|
|
314
|
+
id: file.id + "-action",
|
|
315
|
+
itemType: "action",
|
|
316
|
+
label: file.title,
|
|
317
|
+
actionType: "play",
|
|
318
|
+
seconds: file.seconds || void 0,
|
|
319
|
+
children: [
|
|
320
|
+
{
|
|
321
|
+
id: file.id,
|
|
322
|
+
itemType: "file",
|
|
323
|
+
label: file.title,
|
|
324
|
+
seconds: file.seconds || void 0,
|
|
325
|
+
downloadUrl: file.downloadUrl || file.url,
|
|
326
|
+
thumbnail: file.thumbnail,
|
|
327
|
+
mediaType: file.mediaType
|
|
328
|
+
}
|
|
329
|
+
]
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
function filesToInstructions(name, files, section) {
|
|
333
|
+
const actions = files.map(fileToActionItem);
|
|
334
|
+
const items = section ? [{ id: section.id, itemType: "section", label: section.label ?? name, children: actions }] : actions;
|
|
335
|
+
return { name, items };
|
|
336
|
+
}
|
|
299
337
|
function instructionsToPlaylist(instructions) {
|
|
300
338
|
const files = [];
|
|
301
339
|
function extractFiles(items) {
|
|
@@ -310,6 +348,26 @@ function instructionsToPlaylist(instructions) {
|
|
|
310
348
|
return files;
|
|
311
349
|
}
|
|
312
350
|
|
|
351
|
+
// src/providers/aPlay/APlayApi.ts
|
|
352
|
+
var API_BASE = "https://api-prod.amazingkids.app";
|
|
353
|
+
async function checkMediaLicense(mediaId, auth) {
|
|
354
|
+
if (!auth) return null;
|
|
355
|
+
try {
|
|
356
|
+
const url = `${API_BASE}/prod/reports/media/license-check`;
|
|
357
|
+
const response = await fetch(url, { method: "POST", headers: { "Authorization": `Bearer ${auth.access_token}`, "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify({ mediaIds: [mediaId] }) });
|
|
358
|
+
if (!response.ok) return null;
|
|
359
|
+
const data = await response.json();
|
|
360
|
+
const licenseData = Array.isArray(data) ? data : data.data || [];
|
|
361
|
+
const result = licenseData.find((item) => item.mediaId === mediaId);
|
|
362
|
+
if (result?.isLicensed) {
|
|
363
|
+
return { mediaId, status: "valid", message: "Media is licensed for playback", expiresAt: result.expiresAt };
|
|
364
|
+
}
|
|
365
|
+
return { mediaId, status: "not_licensed", message: "Media is not licensed" };
|
|
366
|
+
} catch {
|
|
367
|
+
return { mediaId, status: "unknown", message: "Unable to verify license status" };
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
313
371
|
// src/providers/aPlay/APlayConverters.ts
|
|
314
372
|
function extractLibraryId(path) {
|
|
315
373
|
const { segments, depth } = parsePath(path);
|
|
@@ -376,25 +434,6 @@ function convertProductsToFolders(products, currentPath) {
|
|
|
376
434
|
return createFolder(id, p.title || p.name, `${currentPath}/products/${id}`, p.image);
|
|
377
435
|
});
|
|
378
436
|
}
|
|
379
|
-
function convertFilesToInstructions(files, _libraryId) {
|
|
380
|
-
const items = files.map((file) => ({
|
|
381
|
-
id: file.id + "-action",
|
|
382
|
-
itemType: "action",
|
|
383
|
-
label: file.title,
|
|
384
|
-
actionType: "play",
|
|
385
|
-
children: [
|
|
386
|
-
{
|
|
387
|
-
id: file.id,
|
|
388
|
-
itemType: "file",
|
|
389
|
-
label: file.title,
|
|
390
|
-
seconds: file.seconds,
|
|
391
|
-
downloadUrl: file.url,
|
|
392
|
-
thumbnail: file.thumbnail
|
|
393
|
-
}
|
|
394
|
-
]
|
|
395
|
-
}));
|
|
396
|
-
return { name: "Library", items };
|
|
397
|
-
}
|
|
398
437
|
|
|
399
438
|
// src/providers/aPlay/APlayProvider.ts
|
|
400
439
|
function extractArray(response, ...keys) {
|
|
@@ -407,20 +446,17 @@ function extractArray(response, ...keys) {
|
|
|
407
446
|
}
|
|
408
447
|
return [];
|
|
409
448
|
}
|
|
410
|
-
var APlayProvider = class {
|
|
449
|
+
var APlayProvider = class extends BaseProvider {
|
|
411
450
|
constructor() {
|
|
412
|
-
|
|
451
|
+
super(...arguments);
|
|
413
452
|
this.id = "aplay";
|
|
414
453
|
this.name = "APlay";
|
|
415
454
|
this.logos = { light: "https://www.joinamazing.com/_assets/v11/3ba846c5afd7e73d27bc4d87b63d423e7ae2dc73.svg", dark: "https://www.joinamazing.com/_assets/v11/3ba846c5afd7e73d27bc4d87b63d423e7ae2dc73.svg" };
|
|
416
|
-
this.config = { id: "aplay", name: "APlay", apiBase: API_BASE, oauthBase: "https://api.joinamazing.com/prod/aims/oauth", clientId: "xFJFq7yNYuXXXMx0YBiQ", scopes: ["openid", "profile", "email"]
|
|
455
|
+
this.config = { id: "aplay", name: "APlay", apiBase: API_BASE, oauthBase: "https://api.joinamazing.com/prod/aims/oauth", clientId: "xFJFq7yNYuXXXMx0YBiQ", scopes: ["openid", "profile", "email"] };
|
|
417
456
|
this.requiresAuth = true;
|
|
418
457
|
this.authTypes = ["oauth_pkce"];
|
|
419
458
|
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: true };
|
|
420
459
|
}
|
|
421
|
-
async apiRequest(path, auth) {
|
|
422
|
-
return this.apiHelper.apiRequest(this.config, this.id, path, auth);
|
|
423
|
-
}
|
|
424
460
|
async browse(path, auth) {
|
|
425
461
|
const { segments, depth } = parsePath(path);
|
|
426
462
|
if (depth === 0) {
|
|
@@ -436,12 +472,12 @@ var APlayProvider = class {
|
|
|
436
472
|
return [];
|
|
437
473
|
}
|
|
438
474
|
async getModules(auth) {
|
|
439
|
-
const response = await this.apiRequest(
|
|
475
|
+
const response = await this.apiRequest("/prod/curriculum/modules", auth);
|
|
440
476
|
const modules = extractArray(response, "data", "modules");
|
|
441
477
|
return convertModulesToFolders(modules);
|
|
442
478
|
}
|
|
443
479
|
async getModuleContent(moduleId, currentPath, auth) {
|
|
444
|
-
const response = await this.apiRequest(
|
|
480
|
+
const response = await this.apiRequest("/prod/curriculum/modules", auth);
|
|
445
481
|
const modules = extractArray(response, "data", "modules");
|
|
446
482
|
const module2 = modules.find((m) => (m.id || m.moduleId) === moduleId);
|
|
447
483
|
if (!module2) return [];
|
|
@@ -457,14 +493,12 @@ var APlayProvider = class {
|
|
|
457
493
|
}
|
|
458
494
|
}
|
|
459
495
|
async getLibraryFolders(productId, currentPath, auth) {
|
|
460
|
-
const
|
|
461
|
-
const response = await this.apiRequest(pathFn(productId), auth);
|
|
496
|
+
const response = await this.apiRequest(`/prod/curriculum/modules/products/${productId}/libraries`, auth);
|
|
462
497
|
const libraries = extractArray(response, "data", "libraries");
|
|
463
498
|
return convertLibrariesToFolders(libraries, currentPath);
|
|
464
499
|
}
|
|
465
500
|
async getMediaFiles(libraryId, auth) {
|
|
466
|
-
const
|
|
467
|
-
const response = await this.apiRequest(pathFn(libraryId), auth);
|
|
501
|
+
const response = await this.apiRequest(`/prod/creators/libraries/${libraryId}/media`, auth);
|
|
468
502
|
const mediaItems = extractArray(response, "data", "media");
|
|
469
503
|
return convertMediaToFiles(mediaItems);
|
|
470
504
|
}
|
|
@@ -479,63 +513,47 @@ var APlayProvider = class {
|
|
|
479
513
|
if (!libraryId) return null;
|
|
480
514
|
const files = await this.getMediaFiles(libraryId, auth);
|
|
481
515
|
if (files.length === 0) return null;
|
|
482
|
-
return
|
|
516
|
+
return filesToInstructions("Library", files);
|
|
483
517
|
}
|
|
484
518
|
async checkMediaLicense(mediaId, auth) {
|
|
485
519
|
return checkMediaLicense(mediaId, auth);
|
|
486
520
|
}
|
|
487
|
-
supportsDeviceFlow() {
|
|
488
|
-
return false;
|
|
489
|
-
}
|
|
490
521
|
};
|
|
491
522
|
|
|
492
523
|
// src/providers/signPresenter/SignPresenterProvider.ts
|
|
493
|
-
var SignPresenterProvider = class {
|
|
524
|
+
var SignPresenterProvider = class extends BaseProvider {
|
|
494
525
|
constructor() {
|
|
495
|
-
|
|
526
|
+
super(...arguments);
|
|
496
527
|
this.oauthHelper = new OAuthHelper();
|
|
497
528
|
this.deviceFlowHelper = new DeviceFlowHelper();
|
|
498
529
|
this.id = "signpresenter";
|
|
499
530
|
this.name = "SignPresenter";
|
|
500
531
|
this.logos = { light: "https://signpresenter.com/files/shared/images/logo.png", dark: "https://signpresenter.com/files/shared/images/logo.png" };
|
|
501
|
-
this.config = { id: "signpresenter", name: "SignPresenter", apiBase: "https://api.signpresenter.com", oauthBase: "https://api.signpresenter.com/oauth", clientId: "lessonsscreen-tv", scopes: ["openid", "profile", "content"], supportsDeviceFlow: true, deviceAuthEndpoint: "/device/authorize"
|
|
532
|
+
this.config = { id: "signpresenter", name: "SignPresenter", apiBase: "https://api.signpresenter.com", oauthBase: "https://api.signpresenter.com/oauth", clientId: "lessonsscreen-tv", scopes: ["openid", "profile", "content"], supportsDeviceFlow: true, deviceAuthEndpoint: "/device/authorize" };
|
|
502
533
|
this.requiresAuth = true;
|
|
503
534
|
this.authTypes = ["oauth_pkce", "device_flow"];
|
|
504
535
|
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
505
536
|
}
|
|
506
|
-
async apiRequest(path, auth) {
|
|
507
|
-
return this.apiHelper.apiRequest(this.config, this.id, path, auth);
|
|
508
|
-
}
|
|
509
537
|
async browse(path, auth) {
|
|
510
538
|
const { segments, depth } = parsePath(path);
|
|
511
539
|
if (depth === 0) {
|
|
512
|
-
return [
|
|
513
|
-
{
|
|
514
|
-
type: "folder",
|
|
515
|
-
id: "playlists-root",
|
|
516
|
-
title: "Playlists",
|
|
517
|
-
path: "/playlists"
|
|
518
|
-
}
|
|
519
|
-
];
|
|
520
|
-
}
|
|
521
|
-
const root = segments[0];
|
|
522
|
-
if (root !== "playlists") return [];
|
|
523
|
-
if (depth === 1) {
|
|
524
|
-
return this.getPlaylists(auth);
|
|
525
|
-
}
|
|
526
|
-
if (depth === 2) {
|
|
527
|
-
const playlistId = segments[1];
|
|
528
|
-
return this.getMessages(playlistId, auth);
|
|
540
|
+
return [{ type: "folder", id: "playlists-root", title: "Playlists", path: "/playlists" }];
|
|
529
541
|
}
|
|
542
|
+
if (segments[0] !== "playlists") return [];
|
|
543
|
+
if (depth === 1) return this.getPlaylists(auth);
|
|
544
|
+
if (depth === 2) return this.getMessages(segments[1], auth);
|
|
530
545
|
return [];
|
|
531
546
|
}
|
|
547
|
+
extractList(response, key) {
|
|
548
|
+
if (Array.isArray(response)) return response;
|
|
549
|
+
const record = response;
|
|
550
|
+
const list = record?.data || record?.[key] || [];
|
|
551
|
+
return Array.isArray(list) ? list : [];
|
|
552
|
+
}
|
|
532
553
|
async getPlaylists(auth) {
|
|
533
|
-
const
|
|
534
|
-
const response = await this.apiRequest(apiPath, auth);
|
|
554
|
+
const response = await this.apiRequest("/content/playlists", auth);
|
|
535
555
|
if (!response) return [];
|
|
536
|
-
|
|
537
|
-
if (!Array.isArray(playlists)) return [];
|
|
538
|
-
return playlists.map((p) => ({
|
|
556
|
+
return this.extractList(response, "playlists").map((p) => ({
|
|
539
557
|
type: "folder",
|
|
540
558
|
id: p.id,
|
|
541
559
|
title: p.name,
|
|
@@ -545,26 +563,17 @@ var SignPresenterProvider = class {
|
|
|
545
563
|
}));
|
|
546
564
|
}
|
|
547
565
|
async getMessages(playlistId, auth) {
|
|
548
|
-
const
|
|
549
|
-
const response = await this.apiRequest(pathFn(playlistId), auth);
|
|
566
|
+
const response = await this.apiRequest(`/content/playlists/${playlistId}/messages`, auth);
|
|
550
567
|
if (!response) return [];
|
|
551
|
-
const messages = Array.isArray(response) ? response : response.data || response.messages || [];
|
|
552
|
-
if (!Array.isArray(messages)) return [];
|
|
553
568
|
const files = [];
|
|
554
|
-
for (const msg of messages) {
|
|
569
|
+
for (const msg of this.extractList(response, "messages")) {
|
|
555
570
|
if (!msg.url) continue;
|
|
556
571
|
const url = msg.url;
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
msg.
|
|
560
|
-
msg.
|
|
561
|
-
|
|
562
|
-
{
|
|
563
|
-
mediaType: detectMediaType(url, msg.mediaType),
|
|
564
|
-
thumbnail: msg.thumbnail || msg.image,
|
|
565
|
-
seconds
|
|
566
|
-
}
|
|
567
|
-
);
|
|
572
|
+
const file = createFile(msg.id, msg.name, url, {
|
|
573
|
+
mediaType: detectMediaType(url, msg.mediaType),
|
|
574
|
+
thumbnail: msg.thumbnail || msg.image,
|
|
575
|
+
seconds: msg.seconds
|
|
576
|
+
});
|
|
568
577
|
file.downloadUrl = url;
|
|
569
578
|
files.push(file);
|
|
570
579
|
}
|
|
@@ -573,8 +582,7 @@ var SignPresenterProvider = class {
|
|
|
573
582
|
async getPlaylist(path, auth, _resolution) {
|
|
574
583
|
const { segments, depth } = parsePath(path);
|
|
575
584
|
if (depth < 2 || segments[0] !== "playlists") return null;
|
|
576
|
-
const
|
|
577
|
-
const files = await this.getMessages(playlistId, auth);
|
|
585
|
+
const files = await this.getMessages(segments[1], auth);
|
|
578
586
|
return files.length > 0 ? files : null;
|
|
579
587
|
}
|
|
580
588
|
async getInstructions(path, auth) {
|
|
@@ -584,42 +592,9 @@ var SignPresenterProvider = class {
|
|
|
584
592
|
const files = await this.getMessages(playlistId, auth);
|
|
585
593
|
if (files.length === 0) return null;
|
|
586
594
|
const playlists = await this.getPlaylists(auth);
|
|
587
|
-
const
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
id: file.id + "-action",
|
|
591
|
-
itemType: "action",
|
|
592
|
-
label: file.title,
|
|
593
|
-
actionType: "play",
|
|
594
|
-
seconds: file.seconds,
|
|
595
|
-
children: [
|
|
596
|
-
{
|
|
597
|
-
id: file.id,
|
|
598
|
-
itemType: "file",
|
|
599
|
-
label: file.title,
|
|
600
|
-
seconds: file.seconds,
|
|
601
|
-
downloadUrl: file.downloadUrl || file.url,
|
|
602
|
-
thumbnail: file.thumbnail
|
|
603
|
-
}
|
|
604
|
-
]
|
|
605
|
-
}));
|
|
606
|
-
const sectionItem = {
|
|
607
|
-
id: playlistId + "-section",
|
|
608
|
-
itemType: "section",
|
|
609
|
-
label: title,
|
|
610
|
-
children: actionItems
|
|
611
|
-
};
|
|
612
|
-
const headerItem = {
|
|
613
|
-
id: playlistId + "-header",
|
|
614
|
-
itemType: "header",
|
|
615
|
-
label: title,
|
|
616
|
-
children: [sectionItem]
|
|
617
|
-
};
|
|
618
|
-
return { name: title, items: [headerItem] };
|
|
619
|
-
}
|
|
620
|
-
// Auth methods
|
|
621
|
-
supportsDeviceFlow() {
|
|
622
|
-
return this.deviceFlowHelper.supportsDeviceFlow(this.config);
|
|
595
|
+
const title = playlists.find((p) => p.id === playlistId)?.title || "Playlist";
|
|
596
|
+
const instructions = filesToInstructions(title, files, { id: playlistId + "-section", label: title });
|
|
597
|
+
return { name: title, items: [{ id: playlistId + "-header", itemType: "header", label: title, children: instructions.items }] };
|
|
623
598
|
}
|
|
624
599
|
generateCodeVerifier() {
|
|
625
600
|
return this.oauthHelper.generateCodeVerifier();
|
|
@@ -667,6 +642,23 @@ function truncateForLabel(text) {
|
|
|
667
642
|
const truncated = text.length > cutoff ? text.substring(0, cutoff) : text;
|
|
668
643
|
return stripMarkdown(truncated) + (text.length > cutoff ? "..." : "");
|
|
669
644
|
}
|
|
645
|
+
function getEmbedUrl(apiType, relatedId) {
|
|
646
|
+
if (!relatedId) return void 0;
|
|
647
|
+
const baseUrl = "https://lessons.church";
|
|
648
|
+
switch (apiType) {
|
|
649
|
+
case "action":
|
|
650
|
+
case "lessonAction":
|
|
651
|
+
return `${baseUrl}/embed/action/${relatedId}`;
|
|
652
|
+
case "addon":
|
|
653
|
+
case "lessonAddOn":
|
|
654
|
+
return `${baseUrl}/embed/addon/${relatedId}`;
|
|
655
|
+
case "section":
|
|
656
|
+
case "lessonSection":
|
|
657
|
+
return `${baseUrl}/embed/section/${relatedId}`;
|
|
658
|
+
default:
|
|
659
|
+
return void 0;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
670
662
|
async function convertAddOnToFile(addOn) {
|
|
671
663
|
const apiPath = `/addOns/public/${addOn.id}`;
|
|
672
664
|
const detail = await apiRequest(apiPath);
|
|
@@ -813,12 +805,13 @@ async function convertAddOnCategoryToInstructions(category) {
|
|
|
813
805
|
}
|
|
814
806
|
|
|
815
807
|
// src/providers/lessonsChurch/LessonsChurchProvider.ts
|
|
816
|
-
var LessonsChurchProvider = class {
|
|
808
|
+
var LessonsChurchProvider = class extends BaseProvider {
|
|
817
809
|
constructor() {
|
|
810
|
+
super(...arguments);
|
|
818
811
|
this.id = "lessonschurch";
|
|
819
812
|
this.name = "Lessons.church";
|
|
820
813
|
this.logos = { light: "https://lessons.church/images/logo.png", dark: "https://lessons.church/images/logo-dark.png" };
|
|
821
|
-
this.config = { id: "lessonschurch", name: "Lessons.church", apiBase: API_BASE2, oauthBase: "", clientId: "", scopes: []
|
|
814
|
+
this.config = { id: "lessonschurch", name: "Lessons.church", apiBase: API_BASE2, oauthBase: "", clientId: "", scopes: [] };
|
|
822
815
|
this.requiresAuth = false;
|
|
823
816
|
this.authTypes = ["none"];
|
|
824
817
|
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
@@ -874,28 +867,25 @@ var LessonsChurchProvider = class {
|
|
|
874
867
|
return [];
|
|
875
868
|
}
|
|
876
869
|
async getPrograms() {
|
|
877
|
-
const response = await apiRequest(
|
|
870
|
+
const response = await apiRequest("/programs/public");
|
|
878
871
|
if (!response) return [];
|
|
879
872
|
const programs = Array.isArray(response) ? response : [];
|
|
880
873
|
return programs.map((p) => createFolder(p.id, p.name, `/lessons/${p.id}`, p.image));
|
|
881
874
|
}
|
|
882
875
|
async getStudies(programId, currentPath) {
|
|
883
|
-
const
|
|
884
|
-
const response = await apiRequest(pathFn(programId));
|
|
876
|
+
const response = await apiRequest(`/studies/public/program/${programId}`);
|
|
885
877
|
if (!response) return [];
|
|
886
878
|
const studies = Array.isArray(response) ? response : [];
|
|
887
879
|
return studies.map((s) => createFolder(s.id, s.name, `${currentPath}/${s.id}`, s.image)).sort((a, b) => a.title.localeCompare(b.title));
|
|
888
880
|
}
|
|
889
881
|
async getLessons(studyId, currentPath) {
|
|
890
|
-
const
|
|
891
|
-
const response = await apiRequest(pathFn(studyId));
|
|
882
|
+
const response = await apiRequest(`/lessons/public/study/${studyId}`);
|
|
892
883
|
if (!response) return [];
|
|
893
884
|
const lessons = Array.isArray(response) ? response : [];
|
|
894
885
|
return lessons.map((l) => createFolder(l.id, l.name || l.title, `${currentPath}/${l.id}`, l.image));
|
|
895
886
|
}
|
|
896
887
|
async getVenues(lessonId, currentPath) {
|
|
897
|
-
const
|
|
898
|
-
const response = await apiRequest(pathFn(lessonId));
|
|
888
|
+
const response = await apiRequest(`/venues/public/lesson/${lessonId}`);
|
|
899
889
|
if (!response) return [];
|
|
900
890
|
const lessonResponse = await apiRequest(`/lessons/public/${lessonId}`);
|
|
901
891
|
const lessonImage = lessonResponse?.image;
|
|
@@ -918,7 +908,7 @@ var LessonsChurchProvider = class {
|
|
|
918
908
|
return file ? [file] : [];
|
|
919
909
|
}
|
|
920
910
|
async getAddOnCategories() {
|
|
921
|
-
const response = await apiRequest(
|
|
911
|
+
const response = await apiRequest("/addOns/public");
|
|
922
912
|
if (!response) return [];
|
|
923
913
|
const addOns = Array.isArray(response) ? response : [];
|
|
924
914
|
const categories = Array.from(new Set(addOns.map((a) => a.category).filter(Boolean)));
|
|
@@ -926,7 +916,7 @@ var LessonsChurchProvider = class {
|
|
|
926
916
|
}
|
|
927
917
|
async getAddOnsByCategory(category, currentPath) {
|
|
928
918
|
const decodedCategory = decodeURIComponent(category);
|
|
929
|
-
const response = await apiRequest(
|
|
919
|
+
const response = await apiRequest("/addOns/public");
|
|
930
920
|
if (!response) return [];
|
|
931
921
|
const allAddOns = Array.isArray(response) ? response : [];
|
|
932
922
|
const filtered = allAddOns.filter((a) => a.category === decodedCategory);
|
|
@@ -969,9 +959,6 @@ var LessonsChurchProvider = class {
|
|
|
969
959
|
}
|
|
970
960
|
return null;
|
|
971
961
|
}
|
|
972
|
-
supportsDeviceFlow() {
|
|
973
|
-
return false;
|
|
974
|
-
}
|
|
975
962
|
};
|
|
976
963
|
|
|
977
964
|
// src/providers/registry.ts
|
|
@@ -987,18 +974,6 @@ function registerProvider(provider) {
|
|
|
987
974
|
}
|
|
988
975
|
|
|
989
976
|
// src/providers/b1Church/B1ChurchAuth.ts
|
|
990
|
-
async function generateCodeChallenge(verifier) {
|
|
991
|
-
const encoder = new TextEncoder();
|
|
992
|
-
const data = encoder.encode(verifier);
|
|
993
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
994
|
-
const hashArray = new Uint8Array(hashBuffer);
|
|
995
|
-
let binary = "";
|
|
996
|
-
for (let i = 0; i < hashArray.length; i++) {
|
|
997
|
-
binary += String.fromCharCode(hashArray[i]);
|
|
998
|
-
}
|
|
999
|
-
const base64 = btoa(binary);
|
|
1000
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1001
|
-
}
|
|
1002
977
|
async function buildB1AuthUrl(config, appBase, redirectUri, codeVerifier, state) {
|
|
1003
978
|
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
1004
979
|
const oauthParams = new URLSearchParams({
|
|
@@ -1022,7 +997,7 @@ async function exchangeCodeForTokensWithPKCE(config, code, redirectUri, codeVeri
|
|
|
1022
997
|
return null;
|
|
1023
998
|
}
|
|
1024
999
|
const data = await response.json();
|
|
1025
|
-
return
|
|
1000
|
+
return toAuthData(data, { scope: config.scopes.join(" ") });
|
|
1026
1001
|
} catch {
|
|
1027
1002
|
return null;
|
|
1028
1003
|
}
|
|
@@ -1036,7 +1011,7 @@ async function exchangeCodeForTokensWithSecret(config, code, redirectUri, client
|
|
|
1036
1011
|
return null;
|
|
1037
1012
|
}
|
|
1038
1013
|
const data = await response.json();
|
|
1039
|
-
return
|
|
1014
|
+
return toAuthData(data, { scope: config.scopes.join(" ") });
|
|
1040
1015
|
} catch {
|
|
1041
1016
|
return null;
|
|
1042
1017
|
}
|
|
@@ -1048,7 +1023,7 @@ async function refreshTokenWithSecret(config, auth, clientSecret) {
|
|
|
1048
1023
|
const response = await fetch(`${config.oauthBase}/token`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(params) });
|
|
1049
1024
|
if (!response.ok) return null;
|
|
1050
1025
|
const data = await response.json();
|
|
1051
|
-
return
|
|
1026
|
+
return toAuthData(data, { refreshToken: auth.refresh_token, scope: auth.scope });
|
|
1052
1027
|
} catch {
|
|
1053
1028
|
return null;
|
|
1054
1029
|
}
|
|
@@ -1073,78 +1048,32 @@ async function authFetch(url, auth) {
|
|
|
1073
1048
|
}
|
|
1074
1049
|
}
|
|
1075
1050
|
async function fetchMinistries(auth) {
|
|
1076
|
-
|
|
1077
|
-
return result || [];
|
|
1051
|
+
return await authFetch(`${API_BASE3}/membership/groups/tag/ministry`, auth) || [];
|
|
1078
1052
|
}
|
|
1079
1053
|
async function fetchPlanTypes(ministryId, auth) {
|
|
1080
|
-
|
|
1081
|
-
return result || [];
|
|
1054
|
+
return await authFetch(`${API_BASE3}/doing/planTypes/ministryId/${ministryId}`, auth) || [];
|
|
1082
1055
|
}
|
|
1083
1056
|
async function fetchPlans(planTypeId, auth) {
|
|
1084
|
-
|
|
1085
|
-
return result || [];
|
|
1057
|
+
return await authFetch(`${API_BASE3}/doing/plans/types/${planTypeId}`, auth) || [];
|
|
1086
1058
|
}
|
|
1087
|
-
var DOING_API_BASE = "https://api.churchapps.org/doing";
|
|
1088
1059
|
async function fetchCurrentPlanByType(planTypeId) {
|
|
1089
|
-
|
|
1090
|
-
const response = await fetch(`${DOING_API_BASE}/plans/public/current/${planTypeId}`, { method: "GET", headers: { Accept: "application/json" } });
|
|
1091
|
-
if (!response.ok) {
|
|
1092
|
-
console.warn(`[B1Church] fetchCurrentPlanByType failed: HTTP ${response.status} for planTypeId=${planTypeId}`);
|
|
1093
|
-
return null;
|
|
1094
|
-
}
|
|
1095
|
-
return await response.json();
|
|
1096
|
-
} catch (err) {
|
|
1097
|
-
console.error(`[B1Church] fetchCurrentPlanByType error: planTypeId=${planTypeId}`, err);
|
|
1098
|
-
return null;
|
|
1099
|
-
}
|
|
1060
|
+
return authFetch(`${API_BASE3}/doing/plans/public/current/${planTypeId}`);
|
|
1100
1061
|
}
|
|
1101
1062
|
async function fetchPlanItems(churchId, planId) {
|
|
1102
|
-
|
|
1103
|
-
const response = await fetch(`${DOING_API_BASE}/planItems/presenter/${churchId}/${planId}`, { method: "GET", headers: { Accept: "application/json" } });
|
|
1104
|
-
if (!response.ok) return [];
|
|
1105
|
-
return await response.json() || [];
|
|
1106
|
-
} catch {
|
|
1107
|
-
return [];
|
|
1108
|
-
}
|
|
1063
|
+
return await authFetch(`${API_BASE3}/doing/planItems/presenter/${churchId}/${planId}`) || [];
|
|
1109
1064
|
}
|
|
1110
1065
|
async function fetchVenueFeed(venueId) {
|
|
1111
|
-
|
|
1112
|
-
const response = await fetch(`${LESSONS_API_BASE}/venues/public/feed/${venueId}`, { method: "GET", headers: { Accept: "application/json" } });
|
|
1113
|
-
if (!response.ok) {
|
|
1114
|
-
console.warn(`[B1Church] fetchVenueFeed failed: HTTP ${response.status} for venueId=${venueId}`);
|
|
1115
|
-
return null;
|
|
1116
|
-
}
|
|
1117
|
-
return await response.json();
|
|
1118
|
-
} catch (err) {
|
|
1119
|
-
console.error(`[B1Church] fetchVenueFeed error: venueId=${venueId}`, err);
|
|
1120
|
-
return null;
|
|
1121
|
-
}
|
|
1066
|
+
return authFetch(`${LESSONS_API_BASE}/venues/public/feed/${venueId}`);
|
|
1122
1067
|
}
|
|
1123
1068
|
async function fetchVenueActions(venueId) {
|
|
1124
|
-
|
|
1125
|
-
const response = await fetch(`${LESSONS_API_BASE}/venues/public/actions/${venueId}`, { method: "GET", headers: { Accept: "application/json" } });
|
|
1126
|
-
if (!response.ok) {
|
|
1127
|
-
console.warn(`[B1Church] fetchVenueActions failed: HTTP ${response.status} for venueId=${venueId}`);
|
|
1128
|
-
return null;
|
|
1129
|
-
}
|
|
1130
|
-
return await response.json();
|
|
1131
|
-
} catch (err) {
|
|
1132
|
-
console.error(`[B1Church] fetchVenueActions error: venueId=${venueId}`, err);
|
|
1133
|
-
return null;
|
|
1134
|
-
}
|
|
1069
|
+
return authFetch(`${LESSONS_API_BASE}/venues/public/actions/${venueId}`);
|
|
1135
1070
|
}
|
|
1136
1071
|
async function fetchVenueImages(venueIds) {
|
|
1137
1072
|
const map = /* @__PURE__ */ new Map();
|
|
1138
1073
|
if (venueIds.length === 0) return map;
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
if (!response.ok) return map;
|
|
1143
|
-
const data = await response.json();
|
|
1144
|
-
for (const row of data) {
|
|
1145
|
-
if (row.venueId && row.lessonImage) map.set(row.venueId, row.lessonImage);
|
|
1146
|
-
}
|
|
1147
|
-
} catch {
|
|
1074
|
+
const data = await authFetch(`${LESSONS_API_BASE}/venues/public/images?ids=${venueIds.join(",")}`);
|
|
1075
|
+
for (const row of data || []) {
|
|
1076
|
+
if (row.venueId && row.lessonImage) map.set(row.venueId, row.lessonImage);
|
|
1148
1077
|
}
|
|
1149
1078
|
return map;
|
|
1150
1079
|
}
|
|
@@ -1233,18 +1162,7 @@ function getFileFromProviderFileItem(item) {
|
|
|
1233
1162
|
};
|
|
1234
1163
|
}
|
|
1235
1164
|
function planItemToInstruction(item, thumbnail) {
|
|
1236
|
-
|
|
1237
|
-
switch (item.itemType) {
|
|
1238
|
-
case "lessonSection":
|
|
1239
|
-
itemType = "section";
|
|
1240
|
-
break;
|
|
1241
|
-
case "lessonAction":
|
|
1242
|
-
itemType = "action";
|
|
1243
|
-
break;
|
|
1244
|
-
case "lessonAddOn":
|
|
1245
|
-
itemType = "action";
|
|
1246
|
-
break;
|
|
1247
|
-
}
|
|
1165
|
+
const itemType = normalizeItemType(item.itemType);
|
|
1248
1166
|
const isFileType = itemType === "file" || item.link && !item.children?.length;
|
|
1249
1167
|
return {
|
|
1250
1168
|
id: item.id,
|
|
@@ -1258,23 +1176,6 @@ function planItemToInstruction(item, thumbnail) {
|
|
|
1258
1176
|
children: item.children?.map((child) => planItemToInstruction(child, thumbnail))
|
|
1259
1177
|
};
|
|
1260
1178
|
}
|
|
1261
|
-
function getEmbedUrl(apiType, relatedId) {
|
|
1262
|
-
if (!relatedId) return void 0;
|
|
1263
|
-
const baseUrl = "https://lessons.church";
|
|
1264
|
-
switch (apiType) {
|
|
1265
|
-
case "action":
|
|
1266
|
-
case "lessonAction":
|
|
1267
|
-
return `${baseUrl}/embed/action/${relatedId}`;
|
|
1268
|
-
case "addon":
|
|
1269
|
-
case "lessonAddOn":
|
|
1270
|
-
return `${baseUrl}/embed/addon/${relatedId}`;
|
|
1271
|
-
case "section":
|
|
1272
|
-
case "lessonSection":
|
|
1273
|
-
return `${baseUrl}/embed/section/${relatedId}`;
|
|
1274
|
-
default:
|
|
1275
|
-
return void 0;
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
1179
|
function buildSectionActionsMap2(actionsResponse, thumbnail) {
|
|
1279
1180
|
const sectionActionsMap = /* @__PURE__ */ new Map();
|
|
1280
1181
|
if (actionsResponse?.sections) {
|
|
@@ -1388,9 +1289,9 @@ function isExternalProviderItem(item) {
|
|
|
1388
1289
|
const itemType = item.itemType || "";
|
|
1389
1290
|
return itemType.startsWith("provider");
|
|
1390
1291
|
}
|
|
1391
|
-
var B1ChurchProvider = class {
|
|
1292
|
+
var B1ChurchProvider = class extends BaseProvider {
|
|
1392
1293
|
constructor() {
|
|
1393
|
-
|
|
1294
|
+
super(...arguments);
|
|
1394
1295
|
this.deviceFlowHelper = new DeviceFlowHelper();
|
|
1395
1296
|
// Unified cache for external provider data to avoid duplicate calls across methods
|
|
1396
1297
|
this.externalContentCache = {
|
|
@@ -1401,16 +1302,13 @@ var B1ChurchProvider = class {
|
|
|
1401
1302
|
this.id = "b1church";
|
|
1402
1303
|
this.name = "B1.Church";
|
|
1403
1304
|
this.logos = { light: "https://b1.church/b1-church-logo.png", dark: "https://b1.church/b1-church-logo.png" };
|
|
1404
|
-
this.config = { id: "b1church", name: "B1.Church", apiBase: `${API_BASE3}/doing`, oauthBase: `${API_BASE3}/membership/oauth`, clientId: "nsowldn58dk", scopes: ["plans"], supportsDeviceFlow: true, deviceAuthEndpoint: "/device/authorize"
|
|
1305
|
+
this.config = { id: "b1church", name: "B1.Church", apiBase: `${API_BASE3}/doing`, oauthBase: `${API_BASE3}/membership/oauth`, clientId: "nsowldn58dk", scopes: ["plans"], supportsDeviceFlow: true, deviceAuthEndpoint: "/device/authorize" };
|
|
1405
1306
|
this.appBase = "https://admin.b1.church";
|
|
1406
1307
|
this.requiresAuth = true;
|
|
1407
1308
|
this.authTypes = ["oauth_pkce", "device_flow"];
|
|
1408
1309
|
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
1409
1310
|
this.planTypeId = null;
|
|
1410
1311
|
}
|
|
1411
|
-
async apiRequest(path, authData) {
|
|
1412
|
-
return this.apiHelper.apiRequest(this.config, this.id, path, authData);
|
|
1413
|
-
}
|
|
1414
1312
|
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
1415
1313
|
return buildB1AuthUrl(this.config, this.appBase, redirectUri, codeVerifier, state);
|
|
1416
1314
|
}
|
|
@@ -1556,8 +1454,7 @@ var B1ChurchProvider = class {
|
|
|
1556
1454
|
console.warn("[B1Church getInstructions] planFolder missing churchId:", planFolder.id);
|
|
1557
1455
|
return null;
|
|
1558
1456
|
}
|
|
1559
|
-
const
|
|
1560
|
-
const planItems = await this.apiRequest(pathFn(churchId, planId), authData);
|
|
1457
|
+
const planItems = await this.apiRequest(`/planFeed/presenter/${churchId}/${planId}`, authData);
|
|
1561
1458
|
if ((!planItems || planItems.length === 0) && planFolder.providerId && planFolder.providerPlanId) {
|
|
1562
1459
|
const externalInstructions = await fetchFromProviderProxy(
|
|
1563
1460
|
"getInstructions",
|
|
@@ -1665,8 +1562,7 @@ var B1ChurchProvider = class {
|
|
|
1665
1562
|
console.warn("[B1Church] getPlaylist: planFolder missing churchId:", planFolder.id);
|
|
1666
1563
|
return null;
|
|
1667
1564
|
}
|
|
1668
|
-
const
|
|
1669
|
-
const planItems = await this.apiRequest(pathFn(churchId, planId), authData);
|
|
1565
|
+
const planItems = await this.apiRequest(`/planFeed/presenter/${churchId}/${planId}`, authData);
|
|
1670
1566
|
if ((!planItems || planItems.length === 0) && planFolder.providerId && planFolder.providerPlanId) {
|
|
1671
1567
|
const externalFiles = await fetchFromProviderProxy(
|
|
1672
1568
|
"getPlaylist",
|
|
@@ -1761,9 +1657,6 @@ var B1ChurchProvider = class {
|
|
|
1761
1657
|
}
|
|
1762
1658
|
return files;
|
|
1763
1659
|
}
|
|
1764
|
-
supportsDeviceFlow() {
|
|
1765
|
-
return !!this.config.supportsDeviceFlow;
|
|
1766
|
-
}
|
|
1767
1660
|
};
|
|
1768
1661
|
|
|
1769
1662
|
// src/providers/dropbox/DropboxConverters.ts
|
|
@@ -1789,38 +1682,13 @@ function filterMediaEntries(entries) {
|
|
|
1789
1682
|
}
|
|
1790
1683
|
return { folders, mediaFiles };
|
|
1791
1684
|
}
|
|
1792
|
-
function buildInstructionsFromFiles(files, folderName) {
|
|
1793
|
-
const actionItems = files.map((file) => ({
|
|
1794
|
-
id: file.id + "-action",
|
|
1795
|
-
itemType: "action",
|
|
1796
|
-
label: file.title,
|
|
1797
|
-
actionType: "play",
|
|
1798
|
-
children: [
|
|
1799
|
-
{
|
|
1800
|
-
id: file.id,
|
|
1801
|
-
itemType: "file",
|
|
1802
|
-
label: file.title,
|
|
1803
|
-
seconds: file.seconds,
|
|
1804
|
-
downloadUrl: file.downloadUrl || file.url,
|
|
1805
|
-
thumbnail: file.thumbnail
|
|
1806
|
-
}
|
|
1807
|
-
]
|
|
1808
|
-
}));
|
|
1809
|
-
const sectionItem = {
|
|
1810
|
-
id: "dropbox-section",
|
|
1811
|
-
itemType: "section",
|
|
1812
|
-
label: folderName,
|
|
1813
|
-
children: actionItems
|
|
1814
|
-
};
|
|
1815
|
-
return { name: folderName, items: [sectionItem] };
|
|
1816
|
-
}
|
|
1817
1685
|
|
|
1818
1686
|
// src/providers/dropbox/DropboxProvider.ts
|
|
1819
1687
|
var MAX_PAGINATION_CALLS = 50;
|
|
1820
|
-
var DropboxProvider = class {
|
|
1688
|
+
var DropboxProvider = class extends BaseProvider {
|
|
1821
1689
|
constructor() {
|
|
1690
|
+
super(...arguments);
|
|
1822
1691
|
this.oauthHelper = new OAuthHelper();
|
|
1823
|
-
this.apiHelper = new ApiHelper();
|
|
1824
1692
|
this.id = "dropbox";
|
|
1825
1693
|
this.name = "Dropbox";
|
|
1826
1694
|
this.logos = {
|
|
@@ -1833,12 +1701,7 @@ var DropboxProvider = class {
|
|
|
1833
1701
|
apiBase: "https://api.dropboxapi.com",
|
|
1834
1702
|
oauthBase: "https://www.dropbox.com/oauth2",
|
|
1835
1703
|
clientId: "9io0q0q9angdz9j",
|
|
1836
|
-
scopes: []
|
|
1837
|
-
endpoints: {
|
|
1838
|
-
listFolder: "/2/files/list_folder",
|
|
1839
|
-
listFolderContinue: "/2/files/list_folder/continue",
|
|
1840
|
-
getTemporaryLink: "/2/files/get_temporary_link"
|
|
1841
|
-
}
|
|
1704
|
+
scopes: []
|
|
1842
1705
|
};
|
|
1843
1706
|
this.requiresAuth = true;
|
|
1844
1707
|
this.authTypes = ["oauth_pkce"];
|
|
@@ -1849,18 +1712,17 @@ var DropboxProvider = class {
|
|
|
1849
1712
|
mediaLicensing: false
|
|
1850
1713
|
};
|
|
1851
1714
|
}
|
|
1852
|
-
// -- Pagination helper --
|
|
1853
1715
|
dropboxPost(endpoint, body, auth) {
|
|
1854
1716
|
if (!auth) {
|
|
1855
1717
|
console.error("[Dropbox] No auth token provided");
|
|
1856
1718
|
return Promise.resolve(null);
|
|
1857
1719
|
}
|
|
1858
|
-
return this.
|
|
1720
|
+
return this.apiRequest(endpoint, auth, "POST", body);
|
|
1859
1721
|
}
|
|
1860
1722
|
async listAllEntries(dropboxPath, auth) {
|
|
1861
1723
|
const allEntries = [];
|
|
1862
1724
|
const response = await this.dropboxPost(
|
|
1863
|
-
|
|
1725
|
+
"/2/files/list_folder",
|
|
1864
1726
|
{ path: dropboxPath, recursive: false, include_media_info: false },
|
|
1865
1727
|
auth
|
|
1866
1728
|
);
|
|
@@ -1871,7 +1733,7 @@ var DropboxProvider = class {
|
|
|
1871
1733
|
let calls = 0;
|
|
1872
1734
|
while (hasMore && calls < MAX_PAGINATION_CALLS) {
|
|
1873
1735
|
const cont = await this.dropboxPost(
|
|
1874
|
-
|
|
1736
|
+
"/2/files/list_folder/continue",
|
|
1875
1737
|
{ cursor },
|
|
1876
1738
|
auth
|
|
1877
1739
|
);
|
|
@@ -1883,7 +1745,6 @@ var DropboxProvider = class {
|
|
|
1883
1745
|
}
|
|
1884
1746
|
return allEntries;
|
|
1885
1747
|
}
|
|
1886
|
-
// -- File link helpers --
|
|
1887
1748
|
async getSharedLink(filePath, auth) {
|
|
1888
1749
|
if (!auth) return null;
|
|
1889
1750
|
try {
|
|
@@ -1921,7 +1782,7 @@ var DropboxProvider = class {
|
|
|
1921
1782
|
}
|
|
1922
1783
|
async getTemporaryLink(filePath, auth) {
|
|
1923
1784
|
const response = await this.dropboxPost(
|
|
1924
|
-
|
|
1785
|
+
"/2/files/get_temporary_link",
|
|
1925
1786
|
{ path: filePath },
|
|
1926
1787
|
auth
|
|
1927
1788
|
);
|
|
@@ -1939,17 +1800,15 @@ var DropboxProvider = class {
|
|
|
1939
1800
|
);
|
|
1940
1801
|
return results.filter((r) => r.viewUrl || r.downloadUrl).map((r) => fileEntryToContentFile(r.entry, r.viewUrl || r.downloadUrl, r.downloadUrl));
|
|
1941
1802
|
}
|
|
1942
|
-
// -- Leaf detection --
|
|
1943
1803
|
async checkIsLeaf(folderPath, auth) {
|
|
1944
1804
|
const response = await this.dropboxPost(
|
|
1945
|
-
|
|
1805
|
+
"/2/files/list_folder",
|
|
1946
1806
|
{ path: folderPath, recursive: false, include_media_info: false },
|
|
1947
1807
|
auth
|
|
1948
1808
|
);
|
|
1949
1809
|
if (!response) return false;
|
|
1950
1810
|
return !response.entries.some((e) => e[".tag"] === "folder");
|
|
1951
1811
|
}
|
|
1952
|
-
// -- IProvider methods --
|
|
1953
1812
|
async browse(path, auth) {
|
|
1954
1813
|
const dropboxPath = path && path !== "/" ? path.startsWith("/") ? path : "/" + path : "";
|
|
1955
1814
|
const allEntries = await this.listAllEntries(dropboxPath, auth);
|
|
@@ -1961,30 +1820,26 @@ var DropboxProvider = class {
|
|
|
1961
1820
|
const fileItems = await this.resolveFileLinks(mediaFiles, auth);
|
|
1962
1821
|
return [...folderItems, ...fileItems];
|
|
1963
1822
|
}
|
|
1964
|
-
async
|
|
1823
|
+
async resolveMediaFiles(path, auth) {
|
|
1965
1824
|
if (!path || path === "/") return null;
|
|
1966
1825
|
const dropboxPath = path.startsWith("/") ? path : "/" + path;
|
|
1967
1826
|
const allEntries = await this.listAllEntries(dropboxPath, auth);
|
|
1968
1827
|
const { mediaFiles } = filterMediaEntries(allEntries);
|
|
1969
1828
|
if (mediaFiles.length === 0) return null;
|
|
1970
1829
|
const files = await this.resolveFileLinks(mediaFiles, auth);
|
|
1971
|
-
|
|
1830
|
+
if (files.length === 0) return null;
|
|
1831
|
+
return { files, dropboxPath };
|
|
1832
|
+
}
|
|
1833
|
+
async getPlaylist(path, auth, _resolution) {
|
|
1834
|
+
const resolved = await this.resolveMediaFiles(path, auth);
|
|
1835
|
+
return resolved?.files ?? null;
|
|
1972
1836
|
}
|
|
1973
1837
|
async getInstructions(path, auth) {
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
const
|
|
1977
|
-
const { mediaFiles } = filterMediaEntries(allEntries);
|
|
1978
|
-
if (mediaFiles.length === 0) return null;
|
|
1979
|
-
const files = await this.resolveFileLinks(mediaFiles, auth);
|
|
1980
|
-
if (files.length === 0) return null;
|
|
1981
|
-
const segments = dropboxPath.split("/").filter(Boolean);
|
|
1838
|
+
const resolved = await this.resolveMediaFiles(path, auth);
|
|
1839
|
+
if (!resolved) return null;
|
|
1840
|
+
const segments = resolved.dropboxPath.split("/").filter(Boolean);
|
|
1982
1841
|
const folderName = segments[segments.length - 1] || "Dropbox";
|
|
1983
|
-
return
|
|
1984
|
-
}
|
|
1985
|
-
// -- Auth methods --
|
|
1986
|
-
supportsDeviceFlow() {
|
|
1987
|
-
return false;
|
|
1842
|
+
return filesToInstructions(folderName, resolved.files, { id: "dropbox-section", label: folderName });
|
|
1988
1843
|
}
|
|
1989
1844
|
generateCodeVerifier() {
|
|
1990
1845
|
return this.oauthHelper.generateCodeVerifier();
|
|
@@ -2022,61 +1877,43 @@ var DropboxProvider = class {
|
|
|
2022
1877
|
body: params.toString()
|
|
2023
1878
|
});
|
|
2024
1879
|
if (!response.ok) return null;
|
|
2025
|
-
|
|
2026
|
-
return {
|
|
2027
|
-
access_token: data.access_token,
|
|
2028
|
-
refresh_token: data.refresh_token,
|
|
2029
|
-
token_type: data.token_type || "Bearer",
|
|
2030
|
-
created_at: Math.floor(Date.now() / 1e3),
|
|
2031
|
-
expires_in: data.expires_in,
|
|
2032
|
-
scope: data.scope || ""
|
|
2033
|
-
};
|
|
1880
|
+
return toAuthData(await response.json());
|
|
2034
1881
|
} catch {
|
|
2035
1882
|
return null;
|
|
2036
1883
|
}
|
|
2037
1884
|
}
|
|
2038
1885
|
};
|
|
2039
1886
|
|
|
2040
|
-
// src/providers/planningCenter/
|
|
2041
|
-
var
|
|
1887
|
+
// src/providers/planningCenter/PlanningCenterProvider.ts
|
|
1888
|
+
var ONE_WEEK_MS = 6048e5;
|
|
2042
1889
|
function formatDate(dateString) {
|
|
2043
|
-
|
|
2044
|
-
return date.toISOString().slice(0, 10);
|
|
1890
|
+
return new Date(dateString).toISOString().slice(0, 10);
|
|
2045
1891
|
}
|
|
2046
|
-
|
|
2047
|
-
// src/providers/planningCenter/PlanningCenterProvider.ts
|
|
2048
|
-
var PlanningCenterProvider = class {
|
|
1892
|
+
var PlanningCenterProvider = class extends BaseProvider {
|
|
2049
1893
|
constructor() {
|
|
2050
|
-
|
|
1894
|
+
super(...arguments);
|
|
2051
1895
|
this.id = "planningcenter";
|
|
2052
1896
|
this.name = "Planning Center";
|
|
2053
1897
|
this.logos = { light: "https://www.planningcenter.com/icons/icon-512x512.png", dark: "https://www.planningcenter.com/icons/icon-512x512.png" };
|
|
2054
|
-
this.config = { id: "planningcenter", name: "Planning Center", apiBase: "https://api.planningcenteronline.com", oauthBase: "https://api.planningcenteronline.com/oauth", clientId: "", scopes: ["services"]
|
|
2055
|
-
this.ONE_WEEK_MS = 6048e5;
|
|
1898
|
+
this.config = { id: "planningcenter", name: "Planning Center", apiBase: "https://api.planningcenteronline.com", oauthBase: "https://api.planningcenteronline.com/oauth", clientId: "", scopes: ["services"] };
|
|
2056
1899
|
this.requiresAuth = true;
|
|
2057
1900
|
this.authTypes = ["oauth_pkce"];
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
async apiRequest(path, auth) {
|
|
2061
|
-
return this.apiHelper.apiRequest(this.config, this.id, path, auth);
|
|
1901
|
+
// Plan items come back without media URLs, so playlist/instructions are not actually supported yet.
|
|
1902
|
+
this.capabilities = { browse: true, playlist: false, instructions: false, mediaLicensing: false };
|
|
2062
1903
|
}
|
|
2063
1904
|
async browse(path, auth) {
|
|
2064
1905
|
const { segments, depth } = parsePath(path);
|
|
2065
1906
|
if (depth === 0) {
|
|
2066
1907
|
return [{ type: "folder", id: "serviceTypes-root", title: "Service Types", path: "/serviceTypes" }];
|
|
2067
1908
|
}
|
|
2068
|
-
|
|
2069
|
-
if (root !== "serviceTypes") return [];
|
|
1909
|
+
if (segments[0] !== "serviceTypes") return [];
|
|
2070
1910
|
if (depth === 1) return this.getServiceTypes(auth);
|
|
2071
1911
|
if (depth === 2) return this.getPlans(segments[1], path, auth);
|
|
2072
1912
|
if (depth === 3) return this.getPlanItems(segments[1], segments[2], auth);
|
|
2073
1913
|
return [];
|
|
2074
1914
|
}
|
|
2075
1915
|
async getServiceTypes(auth) {
|
|
2076
|
-
const response = await this.apiRequest(
|
|
2077
|
-
this.config.endpoints.serviceTypes,
|
|
2078
|
-
auth
|
|
2079
|
-
);
|
|
1916
|
+
const response = await this.apiRequest("/services/v2/service_types", auth);
|
|
2080
1917
|
if (!response?.data) return [];
|
|
2081
1918
|
return response.data.map((serviceType) => ({
|
|
2082
1919
|
type: "folder",
|
|
@@ -2086,9 +1923,8 @@ var PlanningCenterProvider = class {
|
|
|
2086
1923
|
}));
|
|
2087
1924
|
}
|
|
2088
1925
|
async getPlans(serviceTypeId, currentPath, auth) {
|
|
2089
|
-
const pathFn = this.config.endpoints.plans;
|
|
2090
1926
|
const response = await this.apiRequest(
|
|
2091
|
-
|
|
1927
|
+
`/services/v2/service_types/${serviceTypeId}/plans?filter=future&order=sort_date`,
|
|
2092
1928
|
auth
|
|
2093
1929
|
);
|
|
2094
1930
|
if (!response?.data) return [];
|
|
@@ -2096,7 +1932,7 @@ var PlanningCenterProvider = class {
|
|
|
2096
1932
|
const filteredPlans = response.data.filter((plan) => {
|
|
2097
1933
|
if (plan.attributes.items_count === 0) return false;
|
|
2098
1934
|
const planDate = new Date(plan.attributes.sort_date).getTime();
|
|
2099
|
-
return planDate < now +
|
|
1935
|
+
return planDate < now + ONE_WEEK_MS;
|
|
2100
1936
|
});
|
|
2101
1937
|
return filteredPlans.map((plan) => ({
|
|
2102
1938
|
type: "folder",
|
|
@@ -2107,17 +1943,13 @@ var PlanningCenterProvider = class {
|
|
|
2107
1943
|
}));
|
|
2108
1944
|
}
|
|
2109
1945
|
async getPlanItems(serviceTypeId, planId, auth) {
|
|
2110
|
-
const pathFn = this.config.endpoints.planItems;
|
|
2111
1946
|
const response = await this.apiRequest(
|
|
2112
|
-
|
|
1947
|
+
`/services/v2/service_types/${serviceTypeId}/plans/${planId}/items?per_page=100`,
|
|
2113
1948
|
auth
|
|
2114
1949
|
);
|
|
2115
1950
|
if (!response?.data) return [];
|
|
2116
1951
|
return response.data.map((item) => ({ type: "file", id: item.id, title: item.attributes.title || "", mediaType: "image", url: "" }));
|
|
2117
1952
|
}
|
|
2118
|
-
supportsDeviceFlow() {
|
|
2119
|
-
return false;
|
|
2120
|
-
}
|
|
2121
1953
|
};
|
|
2122
1954
|
|
|
2123
1955
|
// src/providers/bibleProject/data.json
|
|
@@ -4512,8 +4344,9 @@ var data_default = {
|
|
|
4512
4344
|
};
|
|
4513
4345
|
|
|
4514
4346
|
// src/providers/bibleProject/BibleProjectProvider.ts
|
|
4515
|
-
var BibleProjectProvider = class {
|
|
4347
|
+
var BibleProjectProvider = class extends BaseProvider {
|
|
4516
4348
|
constructor() {
|
|
4349
|
+
super(...arguments);
|
|
4517
4350
|
this.id = "bibleproject";
|
|
4518
4351
|
this.name = "The Bible Project";
|
|
4519
4352
|
this.logos = {
|
|
@@ -4526,10 +4359,8 @@ var BibleProjectProvider = class {
|
|
|
4526
4359
|
apiBase: "https://bibleproject.com",
|
|
4527
4360
|
oauthBase: "",
|
|
4528
4361
|
clientId: "",
|
|
4529
|
-
scopes: []
|
|
4530
|
-
endpoints: { downloads: "/downloads/" }
|
|
4362
|
+
scopes: []
|
|
4531
4363
|
};
|
|
4532
|
-
this.data = data_default;
|
|
4533
4364
|
this.requiresAuth = false;
|
|
4534
4365
|
this.authTypes = ["none"];
|
|
4535
4366
|
this.capabilities = {
|
|
@@ -4538,133 +4369,71 @@ var BibleProjectProvider = class {
|
|
|
4538
4369
|
instructions: true,
|
|
4539
4370
|
mediaLicensing: false
|
|
4540
4371
|
};
|
|
4372
|
+
this.data = data_default;
|
|
4541
4373
|
}
|
|
4542
4374
|
getMuxThumbnail(muxPlaybackId, width = 400, height = 225) {
|
|
4543
4375
|
return `https://image.mux.com/${muxPlaybackId}/thumbnail.jpg?width=${width}&height=${height}`;
|
|
4544
4376
|
}
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
return this.getCollections();
|
|
4549
|
-
}
|
|
4550
|
-
if (depth === 1) {
|
|
4551
|
-
const collectionSlug = segments[0];
|
|
4552
|
-
return this.getLessonFolders(collectionSlug, path);
|
|
4553
|
-
}
|
|
4554
|
-
if (depth === 2) {
|
|
4555
|
-
const collectionSlug = segments[0];
|
|
4556
|
-
const videoId = segments[1];
|
|
4557
|
-
return this.getVideoFile(collectionSlug, videoId);
|
|
4558
|
-
}
|
|
4559
|
-
return [];
|
|
4560
|
-
}
|
|
4561
|
-
getCollections() {
|
|
4562
|
-
return this.data.collections.filter((collection) => collection.videos.length > 0).map((collection) => ({
|
|
4563
|
-
type: "folder",
|
|
4564
|
-
id: slugify(collection.name),
|
|
4565
|
-
title: collection.name,
|
|
4566
|
-
thumbnail: collection.image || void 0,
|
|
4567
|
-
path: `/${slugify(collection.name)}`
|
|
4568
|
-
}));
|
|
4569
|
-
}
|
|
4570
|
-
getLessonFolders(collectionSlug, currentPath) {
|
|
4571
|
-
const collection = this.data.collections.find((c) => slugify(c.name) === collectionSlug);
|
|
4572
|
-
if (!collection) return [];
|
|
4573
|
-
return collection.videos.map((video) => ({
|
|
4574
|
-
type: "folder",
|
|
4575
|
-
id: video.id,
|
|
4576
|
-
title: video.title,
|
|
4377
|
+
videoToFile(video) {
|
|
4378
|
+
return createFile(video.id, video.title, video.videoUrl, {
|
|
4379
|
+
mediaType: "video",
|
|
4577
4380
|
thumbnail: this.getMuxThumbnail(video.muxPlaybackId),
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
})
|
|
4581
|
-
}
|
|
4582
|
-
getVideoFile(collectionSlug, videoId) {
|
|
4583
|
-
const collection = this.data.collections.find((c) => slugify(c.name) === collectionSlug);
|
|
4584
|
-
if (!collection) return [];
|
|
4585
|
-
const video = collection.videos.find((v) => v.id === videoId);
|
|
4586
|
-
if (!video) return [];
|
|
4587
|
-
return [createFile(video.id, video.title, video.videoUrl, { mediaType: "video", muxPlaybackId: video.muxPlaybackId, seconds: 0 })];
|
|
4381
|
+
muxPlaybackId: video.muxPlaybackId,
|
|
4382
|
+
seconds: 0
|
|
4383
|
+
});
|
|
4588
4384
|
}
|
|
4589
|
-
|
|
4385
|
+
/** Resolve a path to its collection and files: all videos at depth 1, a single video at depth 2. */
|
|
4386
|
+
resolve(path) {
|
|
4590
4387
|
const { segments, depth } = parsePath(path);
|
|
4591
|
-
if (depth < 1) return null;
|
|
4592
|
-
const
|
|
4593
|
-
const collection = this.data.collections.find((c) => slugify(c.name) === collectionSlug);
|
|
4388
|
+
if (depth < 1 || depth > 2) return null;
|
|
4389
|
+
const collection = this.data.collections.find((c) => slugify(c.name) === segments[0]);
|
|
4594
4390
|
if (!collection) return null;
|
|
4595
4391
|
if (depth === 1) {
|
|
4596
|
-
|
|
4597
|
-
return files.length > 0 ? files : null;
|
|
4392
|
+
return { collection, files: collection.videos.map((v) => this.videoToFile(v)), name: collection.name };
|
|
4598
4393
|
}
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
if (!video) return null;
|
|
4603
|
-
return [{ type: "file", id: video.id, title: video.title, mediaType: "video", url: video.videoUrl, thumbnail: this.getMuxThumbnail(video.muxPlaybackId), muxPlaybackId: video.muxPlaybackId, seconds: 0 }];
|
|
4604
|
-
}
|
|
4605
|
-
return null;
|
|
4394
|
+
const video = collection.videos.find((v) => v.id === segments[1]);
|
|
4395
|
+
if (!video) return null;
|
|
4396
|
+
return { collection, files: [this.videoToFile(video)], name: video.title };
|
|
4606
4397
|
}
|
|
4607
|
-
async
|
|
4398
|
+
async browse(path, _auth) {
|
|
4608
4399
|
const { segments, depth } = parsePath(path);
|
|
4609
|
-
if (depth
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4400
|
+
if (depth === 0) {
|
|
4401
|
+
return this.data.collections.filter((collection) => collection.videos.length > 0).map((collection) => ({
|
|
4402
|
+
type: "folder",
|
|
4403
|
+
id: slugify(collection.name),
|
|
4404
|
+
title: collection.name,
|
|
4405
|
+
thumbnail: collection.image || void 0,
|
|
4406
|
+
path: `/${slugify(collection.name)}`
|
|
4407
|
+
}));
|
|
4408
|
+
}
|
|
4613
4409
|
if (depth === 1) {
|
|
4614
|
-
const
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
label: video.title,
|
|
4624
|
-
downloadUrl: video.videoUrl,
|
|
4625
|
-
thumbnail: this.getMuxThumbnail(video.muxPlaybackId)
|
|
4626
|
-
}
|
|
4627
|
-
]
|
|
4410
|
+
const collection = this.data.collections.find((c) => slugify(c.name) === segments[0]);
|
|
4411
|
+
if (!collection) return [];
|
|
4412
|
+
return collection.videos.map((video) => ({
|
|
4413
|
+
type: "folder",
|
|
4414
|
+
id: video.id,
|
|
4415
|
+
title: video.title,
|
|
4416
|
+
thumbnail: this.getMuxThumbnail(video.muxPlaybackId),
|
|
4417
|
+
isLeaf: true,
|
|
4418
|
+
path: `${path}/${video.id}`
|
|
4628
4419
|
}));
|
|
4629
|
-
const sectionItem = {
|
|
4630
|
-
id: slugify(collection.name) + "-section",
|
|
4631
|
-
itemType: "section",
|
|
4632
|
-
label: collection.name,
|
|
4633
|
-
children: actionItems
|
|
4634
|
-
};
|
|
4635
|
-
return { name: collection.name, items: [sectionItem] };
|
|
4636
4420
|
}
|
|
4637
4421
|
if (depth === 2) {
|
|
4638
|
-
|
|
4639
|
-
const video = collection.videos.find((v) => v.id === videoId);
|
|
4640
|
-
if (!video) return null;
|
|
4641
|
-
const actionItem = {
|
|
4642
|
-
id: video.id + "-action",
|
|
4643
|
-
itemType: "action",
|
|
4644
|
-
label: video.title,
|
|
4645
|
-
actionType: "play",
|
|
4646
|
-
children: [
|
|
4647
|
-
{
|
|
4648
|
-
id: video.id,
|
|
4649
|
-
itemType: "file",
|
|
4650
|
-
label: video.title,
|
|
4651
|
-
downloadUrl: video.videoUrl,
|
|
4652
|
-
thumbnail: this.getMuxThumbnail(video.muxPlaybackId)
|
|
4653
|
-
}
|
|
4654
|
-
]
|
|
4655
|
-
};
|
|
4656
|
-
const sectionItem = {
|
|
4657
|
-
id: slugify(collection.name) + "-section",
|
|
4658
|
-
itemType: "section",
|
|
4659
|
-
label: collection.name,
|
|
4660
|
-
children: [actionItem]
|
|
4661
|
-
};
|
|
4662
|
-
return { name: video.title, items: [sectionItem] };
|
|
4422
|
+
return this.resolve(path)?.files ?? [];
|
|
4663
4423
|
}
|
|
4664
|
-
return
|
|
4424
|
+
return [];
|
|
4665
4425
|
}
|
|
4666
|
-
|
|
4667
|
-
|
|
4426
|
+
async getPlaylist(path, _auth, _resolution) {
|
|
4427
|
+
const resolved = this.resolve(path);
|
|
4428
|
+
return resolved && resolved.files.length > 0 ? resolved.files : null;
|
|
4429
|
+
}
|
|
4430
|
+
async getInstructions(path, _auth) {
|
|
4431
|
+
const resolved = this.resolve(path);
|
|
4432
|
+
if (!resolved) return null;
|
|
4433
|
+
return filesToInstructions(resolved.name, resolved.files, {
|
|
4434
|
+
id: slugify(resolved.collection.name) + "-section",
|
|
4435
|
+
label: resolved.collection.name
|
|
4436
|
+
});
|
|
4668
4437
|
}
|
|
4669
4438
|
};
|
|
4670
4439
|
|
|
@@ -12288,8 +12057,9 @@ function buildLessonInstructions(lesson) {
|
|
|
12288
12057
|
}
|
|
12289
12058
|
|
|
12290
12059
|
// src/providers/highVoltage/HighVoltageKidsProvider.ts
|
|
12291
|
-
var HighVoltageKidsProvider = class {
|
|
12060
|
+
var HighVoltageKidsProvider = class extends BaseProvider {
|
|
12292
12061
|
constructor() {
|
|
12062
|
+
super(...arguments);
|
|
12293
12063
|
this.id = "highvoltagekids";
|
|
12294
12064
|
this.name = "High Voltage Kids";
|
|
12295
12065
|
this.logos = {
|
|
@@ -12302,8 +12072,7 @@ var HighVoltageKidsProvider = class {
|
|
|
12302
12072
|
apiBase: "https://highvoltagekids.com",
|
|
12303
12073
|
oauthBase: "",
|
|
12304
12074
|
clientId: "",
|
|
12305
|
-
scopes: []
|
|
12306
|
-
endpoints: { downloads: "/membership-downloads/" }
|
|
12075
|
+
scopes: []
|
|
12307
12076
|
};
|
|
12308
12077
|
this.data = data_default2;
|
|
12309
12078
|
this.requiresAuth = false;
|
|
@@ -12353,9 +12122,6 @@ var HighVoltageKidsProvider = class {
|
|
|
12353
12122
|
}
|
|
12354
12123
|
return null;
|
|
12355
12124
|
}
|
|
12356
|
-
supportsDeviceFlow() {
|
|
12357
|
-
return false;
|
|
12358
|
-
}
|
|
12359
12125
|
};
|
|
12360
12126
|
|
|
12361
12127
|
// src/providers/jesusFilm/JesusFilmProvider.ts
|
|
@@ -12367,8 +12133,14 @@ var CATEGORY_MAP = {
|
|
|
12367
12133
|
"series": "series",
|
|
12368
12134
|
"collections": "collection"
|
|
12369
12135
|
};
|
|
12370
|
-
var
|
|
12136
|
+
var CATEGORY_NAMES = {
|
|
12137
|
+
"feature-films": "Feature Films",
|
|
12138
|
+
"series": "Series",
|
|
12139
|
+
"collections": "Collections"
|
|
12140
|
+
};
|
|
12141
|
+
var JesusFilmProvider = class extends BaseProvider {
|
|
12371
12142
|
constructor() {
|
|
12143
|
+
super(...arguments);
|
|
12372
12144
|
this.id = "jesusfilm";
|
|
12373
12145
|
this.name = "Jesus Film Project";
|
|
12374
12146
|
this.logos = {
|
|
@@ -12381,8 +12153,7 @@ var JesusFilmProvider = class {
|
|
|
12381
12153
|
apiBase: API_BASE4,
|
|
12382
12154
|
oauthBase: "",
|
|
12383
12155
|
clientId: "",
|
|
12384
|
-
scopes: []
|
|
12385
|
-
endpoints: { watch: "/watch" }
|
|
12156
|
+
scopes: []
|
|
12386
12157
|
};
|
|
12387
12158
|
this.requiresAuth = false;
|
|
12388
12159
|
this.authTypes = ["none"];
|
|
@@ -12393,6 +12164,7 @@ var JesusFilmProvider = class {
|
|
|
12393
12164
|
mediaLicensing: false
|
|
12394
12165
|
};
|
|
12395
12166
|
}
|
|
12167
|
+
// Not ApiHelper: Arclight needs the apiKey query param and callers rely on throw-on-error.
|
|
12396
12168
|
async fetchApi(path) {
|
|
12397
12169
|
const separator = path.includes("?") ? "&" : "?";
|
|
12398
12170
|
const url = `${API_BASE4}${path}${separator}apiKey=${API_KEY}`;
|
|
@@ -12400,6 +12172,12 @@ var JesusFilmProvider = class {
|
|
|
12400
12172
|
if (!response.ok) throw new Error(`Arclight API error: ${response.status}`);
|
|
12401
12173
|
return response.json();
|
|
12402
12174
|
}
|
|
12175
|
+
async fetchCategoryComponents(subType) {
|
|
12176
|
+
const data = await this.fetchApi(
|
|
12177
|
+
`/media-components?filter=master&subTypes=${subType}&languageIds=${LANGUAGE_ID}&limit=100`
|
|
12178
|
+
);
|
|
12179
|
+
return data._embedded.mediaComponents;
|
|
12180
|
+
}
|
|
12403
12181
|
async browse(path, _auth) {
|
|
12404
12182
|
const { segments, depth } = parsePath(path);
|
|
12405
12183
|
if (depth === 0) return this.getCategories();
|
|
@@ -12422,19 +12200,14 @@ var JesusFilmProvider = class {
|
|
|
12422
12200
|
async getItemsInCategory(category) {
|
|
12423
12201
|
const subType = CATEGORY_MAP[category];
|
|
12424
12202
|
if (!subType) return [];
|
|
12425
|
-
const
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
`/${category}/${item.mediaComponentId}`,
|
|
12434
|
-
item.imageUrls.mobileCinematicHigh || item.imageUrls.videoStill || item.imageUrls.thumbnail,
|
|
12435
|
-
isLeaf
|
|
12436
|
-
);
|
|
12437
|
-
});
|
|
12203
|
+
const components = await this.fetchCategoryComponents(subType);
|
|
12204
|
+
return components.map((item) => createFolder(
|
|
12205
|
+
item.mediaComponentId,
|
|
12206
|
+
item.title,
|
|
12207
|
+
`/${category}/${item.mediaComponentId}`,
|
|
12208
|
+
item.imageUrls.mobileCinematicHigh || item.imageUrls.videoStill || item.imageUrls.thumbnail,
|
|
12209
|
+
item.containsCount === 0
|
|
12210
|
+
));
|
|
12438
12211
|
}
|
|
12439
12212
|
async getVideoFile(mediaComponentId) {
|
|
12440
12213
|
const variant = await this.fetchApi(
|
|
@@ -12449,11 +12222,10 @@ var JesusFilmProvider = class {
|
|
|
12449
12222
|
const title = component?.title || mediaComponentId;
|
|
12450
12223
|
const seconds = component ? Math.round(component.lengthInMilliseconds / 1e3) : 0;
|
|
12451
12224
|
const thumbnail = component?.imageUrls.mobileCinematicHigh || component?.imageUrls.videoStill;
|
|
12452
|
-
const muxPlaybackId = this.extractMuxPlaybackId(downloadUrl);
|
|
12453
12225
|
return [
|
|
12454
12226
|
createFile(mediaComponentId, title, downloadUrl, {
|
|
12455
12227
|
mediaType: "video",
|
|
12456
|
-
muxPlaybackId,
|
|
12228
|
+
muxPlaybackId: this.extractMuxPlaybackId(downloadUrl),
|
|
12457
12229
|
seconds,
|
|
12458
12230
|
thumbnail
|
|
12459
12231
|
})
|
|
@@ -12465,9 +12237,8 @@ var JesusFilmProvider = class {
|
|
|
12465
12237
|
);
|
|
12466
12238
|
const childIds = linksData.linkedMediaComponentIds?.contains;
|
|
12467
12239
|
if (!childIds || childIds.length === 0) return [];
|
|
12468
|
-
const idsParam = childIds.join(",");
|
|
12469
12240
|
const childrenData = await this.fetchApi(
|
|
12470
|
-
`/media-components?ids=${
|
|
12241
|
+
`/media-components?ids=${childIds.join(",")}&languageIds=${LANGUAGE_ID}`
|
|
12471
12242
|
);
|
|
12472
12243
|
if (!childrenData._embedded?.mediaComponents) return [];
|
|
12473
12244
|
return childrenData._embedded.mediaComponents.map((item) => createFolder(
|
|
@@ -12482,36 +12253,6 @@ var JesusFilmProvider = class {
|
|
|
12482
12253
|
const match = url.match(/stream\.mux\.com\/([^/]+)/);
|
|
12483
12254
|
return match ? match[1] : void 0;
|
|
12484
12255
|
}
|
|
12485
|
-
async getPlaylist(path, _auth, _resolution) {
|
|
12486
|
-
const { segments, depth } = parsePath(path);
|
|
12487
|
-
if (depth < 1) return null;
|
|
12488
|
-
const category = segments[0];
|
|
12489
|
-
if (depth >= 3) {
|
|
12490
|
-
const lastId = segments[depth - 1];
|
|
12491
|
-
const items = await this.getVideoFile(lastId);
|
|
12492
|
-
const files2 = items.filter((item) => item.type === "file");
|
|
12493
|
-
if (files2.length > 0) return files2;
|
|
12494
|
-
const containerFiles = await this.fetchContainerVideoFiles(lastId);
|
|
12495
|
-
return containerFiles.length > 0 ? containerFiles : null;
|
|
12496
|
-
}
|
|
12497
|
-
if (depth === 2) {
|
|
12498
|
-
if (category === "feature-films") {
|
|
12499
|
-
const items = await this.getVideoFile(segments[1]);
|
|
12500
|
-
if (items.length === 0) return null;
|
|
12501
|
-
return items.filter((item) => item.type === "file");
|
|
12502
|
-
}
|
|
12503
|
-
const files2 = await this.fetchContainerVideoFiles(segments[1]);
|
|
12504
|
-
return files2.length > 0 ? files2 : null;
|
|
12505
|
-
}
|
|
12506
|
-
const subType = CATEGORY_MAP[category];
|
|
12507
|
-
if (!subType) return null;
|
|
12508
|
-
const data = await this.fetchApi(
|
|
12509
|
-
`/media-components?filter=master&subTypes=${subType}&languageIds=${LANGUAGE_ID}&limit=100`
|
|
12510
|
-
);
|
|
12511
|
-
const contentComponents = data._embedded.mediaComponents.filter((item) => item.containsCount === 0);
|
|
12512
|
-
const files = await this.fetchVideoFiles(contentComponents);
|
|
12513
|
-
return files.length > 0 ? files : null;
|
|
12514
|
-
}
|
|
12515
12256
|
async fetchVideoFiles(components) {
|
|
12516
12257
|
const files = [];
|
|
12517
12258
|
for (const component of components) {
|
|
@@ -12542,9 +12283,8 @@ var JesusFilmProvider = class {
|
|
|
12542
12283
|
);
|
|
12543
12284
|
const childIds = linksData.linkedMediaComponentIds?.contains;
|
|
12544
12285
|
if (!childIds || childIds.length === 0) return [];
|
|
12545
|
-
const idsParam = childIds.join(",");
|
|
12546
12286
|
const childrenData = await this.fetchApi(
|
|
12547
|
-
`/media-components?ids=${
|
|
12287
|
+
`/media-components?ids=${childIds.join(",")}&languageIds=${LANGUAGE_ID}`
|
|
12548
12288
|
);
|
|
12549
12289
|
if (!childrenData._embedded?.mediaComponents) return [];
|
|
12550
12290
|
const contentItems = childrenData._embedded.mediaComponents.filter((c) => c.containsCount === 0);
|
|
@@ -12556,64 +12296,47 @@ var JesusFilmProvider = class {
|
|
|
12556
12296
|
}
|
|
12557
12297
|
return files;
|
|
12558
12298
|
}
|
|
12299
|
+
async getPlaylist(path, _auth, _resolution) {
|
|
12300
|
+
const { segments, depth } = parsePath(path);
|
|
12301
|
+
if (depth < 1) return null;
|
|
12302
|
+
const category = segments[0];
|
|
12303
|
+
if (depth >= 3) {
|
|
12304
|
+
const lastId = segments[depth - 1];
|
|
12305
|
+
const items = await this.getVideoFile(lastId);
|
|
12306
|
+
const files2 = items.filter((item) => item.type === "file");
|
|
12307
|
+
if (files2.length > 0) return files2;
|
|
12308
|
+
const containerFiles = await this.fetchContainerVideoFiles(lastId);
|
|
12309
|
+
return containerFiles.length > 0 ? containerFiles : null;
|
|
12310
|
+
}
|
|
12311
|
+
if (depth === 2) {
|
|
12312
|
+
if (category === "feature-films") {
|
|
12313
|
+
const items = await this.getVideoFile(segments[1]);
|
|
12314
|
+
if (items.length === 0) return null;
|
|
12315
|
+
return items.filter((item) => item.type === "file");
|
|
12316
|
+
}
|
|
12317
|
+
const files2 = await this.fetchContainerVideoFiles(segments[1]);
|
|
12318
|
+
return files2.length > 0 ? files2 : null;
|
|
12319
|
+
}
|
|
12320
|
+
const subType = CATEGORY_MAP[category];
|
|
12321
|
+
if (!subType) return null;
|
|
12322
|
+
const components = await this.fetchCategoryComponents(subType);
|
|
12323
|
+
const files = await this.fetchVideoFiles(components.filter((item) => item.containsCount === 0));
|
|
12324
|
+
return files.length > 0 ? files : null;
|
|
12325
|
+
}
|
|
12559
12326
|
async buildVideoInstructions(mediaComponentId, category) {
|
|
12560
12327
|
const items = await this.getVideoFile(mediaComponentId);
|
|
12561
|
-
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
const actionItem = {
|
|
12565
|
-
id: mediaComponentId + "-action",
|
|
12566
|
-
itemType: "action",
|
|
12567
|
-
label: file.title,
|
|
12568
|
-
actionType: "play",
|
|
12569
|
-
children: [
|
|
12570
|
-
{
|
|
12571
|
-
id: mediaComponentId,
|
|
12572
|
-
itemType: "file",
|
|
12573
|
-
label: file.title,
|
|
12574
|
-
downloadUrl: file.url,
|
|
12575
|
-
thumbnail: file.thumbnail
|
|
12576
|
-
}
|
|
12577
|
-
]
|
|
12578
|
-
};
|
|
12579
|
-
const sectionItem = {
|
|
12580
|
-
id: category + "-section",
|
|
12581
|
-
itemType: "section",
|
|
12582
|
-
label: file.title,
|
|
12583
|
-
children: [actionItem]
|
|
12584
|
-
};
|
|
12585
|
-
return { name: file.title, items: [sectionItem] };
|
|
12328
|
+
const file = items.find((item) => item.type === "file");
|
|
12329
|
+
if (!file) return null;
|
|
12330
|
+
return filesToInstructions(file.title, [file], { id: category + "-section", label: file.title });
|
|
12586
12331
|
}
|
|
12587
|
-
async buildContainerInstructions(containerId
|
|
12332
|
+
async buildContainerInstructions(containerId) {
|
|
12588
12333
|
const containerData = await this.fetchApi(
|
|
12589
12334
|
`/media-components?ids=${containerId}&languageIds=${LANGUAGE_ID}`
|
|
12590
12335
|
);
|
|
12591
|
-
const
|
|
12592
|
-
const containerName = container?.title || containerId;
|
|
12336
|
+
const containerName = containerData._embedded?.mediaComponents?.[0]?.title || containerId;
|
|
12593
12337
|
const videoFiles = await this.fetchContainerVideoFiles(containerId);
|
|
12594
12338
|
if (videoFiles.length === 0) return { name: containerName, items: [] };
|
|
12595
|
-
|
|
12596
|
-
id: file.id + "-action",
|
|
12597
|
-
itemType: "action",
|
|
12598
|
-
label: file.title,
|
|
12599
|
-
actionType: "play",
|
|
12600
|
-
children: [
|
|
12601
|
-
{
|
|
12602
|
-
id: file.id,
|
|
12603
|
-
itemType: "file",
|
|
12604
|
-
label: file.title,
|
|
12605
|
-
downloadUrl: file.url,
|
|
12606
|
-
thumbnail: file.thumbnail
|
|
12607
|
-
}
|
|
12608
|
-
]
|
|
12609
|
-
}));
|
|
12610
|
-
const sectionItem = {
|
|
12611
|
-
id: containerId + "-section",
|
|
12612
|
-
itemType: "section",
|
|
12613
|
-
label: containerName,
|
|
12614
|
-
children: actionItems
|
|
12615
|
-
};
|
|
12616
|
-
return { name: containerName, items: [sectionItem] };
|
|
12339
|
+
return filesToInstructions(containerName, videoFiles, { id: containerId + "-section", label: containerName });
|
|
12617
12340
|
}
|
|
12618
12341
|
async getInstructions(path, _auth) {
|
|
12619
12342
|
const { segments, depth } = parsePath(path);
|
|
@@ -12622,61 +12345,19 @@ var JesusFilmProvider = class {
|
|
|
12622
12345
|
const subType = CATEGORY_MAP[category];
|
|
12623
12346
|
if (!subType) return null;
|
|
12624
12347
|
if (depth === 1) {
|
|
12625
|
-
const
|
|
12626
|
-
|
|
12627
|
-
);
|
|
12628
|
-
|
|
12629
|
-
const actionItems = await Promise.all(
|
|
12630
|
-
data._embedded.mediaComponents.map(async (component) => {
|
|
12631
|
-
let downloadUrl;
|
|
12632
|
-
if (component.containsCount === 0) {
|
|
12633
|
-
try {
|
|
12634
|
-
const variant = await this.fetchApi(
|
|
12635
|
-
`/media-components/${component.mediaComponentId}/languages/${LANGUAGE_ID}?platform=web`
|
|
12636
|
-
);
|
|
12637
|
-
downloadUrl = variant.downloadUrls.high?.url || variant.downloadUrls.low?.url;
|
|
12638
|
-
} catch {
|
|
12639
|
-
}
|
|
12640
|
-
}
|
|
12641
|
-
return {
|
|
12642
|
-
id: component.mediaComponentId + "-action",
|
|
12643
|
-
itemType: "action",
|
|
12644
|
-
label: component.title,
|
|
12645
|
-
actionType: "play",
|
|
12646
|
-
children: downloadUrl ? [
|
|
12647
|
-
{
|
|
12648
|
-
id: component.mediaComponentId,
|
|
12649
|
-
itemType: "file",
|
|
12650
|
-
label: component.title,
|
|
12651
|
-
downloadUrl,
|
|
12652
|
-
thumbnail: component.imageUrls.mobileCinematicHigh || component.imageUrls.videoStill
|
|
12653
|
-
}
|
|
12654
|
-
] : []
|
|
12655
|
-
};
|
|
12656
|
-
})
|
|
12657
|
-
);
|
|
12658
|
-
const sectionItem = {
|
|
12659
|
-
id: category + "-section",
|
|
12660
|
-
itemType: "section",
|
|
12661
|
-
label: categoryName,
|
|
12662
|
-
children: actionItems.filter((a) => a.children && a.children.length > 0)
|
|
12663
|
-
};
|
|
12664
|
-
return { name: categoryName, items: [sectionItem] };
|
|
12348
|
+
const categoryName = CATEGORY_NAMES[category];
|
|
12349
|
+
const components = await this.fetchCategoryComponents(subType);
|
|
12350
|
+
const files = await this.fetchVideoFiles(components.filter((c) => c.containsCount === 0));
|
|
12351
|
+
return filesToInstructions(categoryName, files, { id: category + "-section", label: categoryName });
|
|
12665
12352
|
}
|
|
12666
12353
|
if (depth === 2) {
|
|
12667
12354
|
if (category === "feature-films") return this.buildVideoInstructions(segments[1], category);
|
|
12668
|
-
return this.buildContainerInstructions(segments[1]
|
|
12669
|
-
}
|
|
12670
|
-
if (depth >= 3) {
|
|
12671
|
-
const lastId = segments[depth - 1];
|
|
12672
|
-
const videoResult = await this.buildVideoInstructions(lastId, category);
|
|
12673
|
-
if (videoResult) return videoResult;
|
|
12674
|
-
return this.buildContainerInstructions(lastId, category);
|
|
12355
|
+
return this.buildContainerInstructions(segments[1]);
|
|
12675
12356
|
}
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
return
|
|
12357
|
+
const lastId = segments[depth - 1];
|
|
12358
|
+
const videoResult = await this.buildVideoInstructions(lastId, category);
|
|
12359
|
+
if (videoResult) return videoResult;
|
|
12360
|
+
return this.buildContainerInstructions(lastId);
|
|
12680
12361
|
}
|
|
12681
12362
|
};
|
|
12682
12363
|
|
|
@@ -12720,35 +12401,15 @@ function convertPlaylistToFiles(playlist) {
|
|
|
12720
12401
|
return file;
|
|
12721
12402
|
});
|
|
12722
12403
|
}
|
|
12723
|
-
function convertPlaylistToInstructions(playlist) {
|
|
12724
|
-
const files = convertPlaylistToFiles(playlist);
|
|
12725
|
-
const items = files.map((file) => ({
|
|
12726
|
-
id: file.id + "-action",
|
|
12727
|
-
itemType: "action",
|
|
12728
|
-
label: file.title,
|
|
12729
|
-
actionType: "play",
|
|
12730
|
-
children: [
|
|
12731
|
-
{
|
|
12732
|
-
id: file.id,
|
|
12733
|
-
itemType: "file",
|
|
12734
|
-
label: file.title,
|
|
12735
|
-
seconds: file.seconds,
|
|
12736
|
-
downloadUrl: file.url,
|
|
12737
|
-
thumbnail: file.thumbnail
|
|
12738
|
-
}
|
|
12739
|
-
]
|
|
12740
|
-
}));
|
|
12741
|
-
return { name: playlist.lesson_title || "Lesson", items };
|
|
12742
|
-
}
|
|
12743
12404
|
|
|
12744
12405
|
// src/providers/cbn/logo.ts
|
|
12745
12406
|
var CBN_LOGO = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDcuMi1jMDAwIDc5LjFiNjVhNzliNCwgMjAyMi8wNi8xMy0yMjowMTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjVEMjA4OTI0OTNCRkRCMTE5MTRBODU5MEQzMTUwOEM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjczNTFDMjdFNENEMDExRURCNUVBQkI4RUVDOUM5MkUwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjczNTFDMjdENENEMDExRURCNUVBQkI4RUVDOUM5MkUwIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIElsbHVzdHJhdG9yIENDIDIwMTcgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0idXVpZDo4NGJiYzc1OC1iNjBhLTFlNGQtODJlMS1mYTQyNzhlMmZhMTciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OTQzMjNlNWMtYjBlMS00YTliLWJjZWUtODljYjRlOGVjZjAwIi8+IDxkYzp0aXRsZT4gPHJkZjpBbHQ+IDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+Q0JOLUZMQU1FPC9yZGY6bGk+IDwvcmRmOkFsdD4gPC9kYzp0aXRsZT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz40pvOUAAAC2VBMVEUdmtYhnNf8/v/7/f4emtb9/v8fm9by+f0nntjU7Pf6/f4gm9b2+/0lntfk8/q43/L3+/5Nr9/5/P4poNg1pdovotnj8voknddQsd84ptsqoNjp9fve8PnX7fgpn9hRsd/1+/3M6Pba7vhmuuO/4vMinNfG5vUtodmGyenm9Pq64PKOzOrz+f2c0+15w+fw+PyVz+zx+fyq2fCl1+9tvuREq91ateGx3PHv+Pz4/P6d0+0mnthxwOXf8fng8fkroNlhuOI3pduk1u7B4/Ts9/zq9ftAqdxHrd54w+ft9/yu2/CKy+pOsN88qNxft+I+qdy74fNIrd7n9PtDq93z+v1Ws+BrveTS6/eW0OxCq91/xuiz3fFvvuXN6fYzpNqZ0e2Ly+oxo9q94fO94vPc7/nF5fSn2O/o9ft2wuYwotk2pdtVs+Du9/ySzutqvOQjnddPsN8uotl3wubY7vjC5PSEyOl1weZpvORSsuBctuHl9Po5p9vT6/eMzOo7p9uBx+iv2/GTz+vh8vq03fFguOLs9vvV7Pe23/JXtOBkuuMon9i+4vOQzetfuOKg1e6Jyurr9vvi8vp+xuhnu+Op2e/R6vf0+v3c8Pnb7/h+xehLr946p9ssodmj1u40pNqUz+zd8PlJrt57xOdXtOFdt+Kw3PFAqtxbtuG33/J8xOd6xOet2vDI5vW54PJwv+VBqt1FrN2a0u1luuOAxuhsveSh1e6s2vCNzOqt2/Ci1e7E5PTJ5/XH5vXL6PY9qNx0weZ9xedYteHK5/WFyOmCx+hnu+TQ6vZovOS13vLD5PSb0u1Mr9/O6fay3fG84fPZ7vhiueNKrt5zwObP6vZZteFjueOm1+9TsuCf1O6o2O+DyOhUs+DF5fWPzeuX0ezW7fhGrN0wo9qOzetet+IypNqr2fC13vGY0exvv+WRzuue1O2IyumHyulywOVuvuU/qdye0+3A4/T///96A0GMAAAA83RSTlP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wB12P98AAAWOklEQVR42uzd5YMUx9YG8JpZN3ZZdHFblg3u7u7uGtzdITgkwUJCsBCc4CRA8BASEgJxtxtPbpKrr52/4EUvK3VqWk5V9+ye5+vOdE3Xb2e6u1QAx1cRXAUMwmEQBuEwCINwGIRBOAzCIBwG4TAIg3AYhEE4DMIgHAZhEA6DcBiEQTgMwiAcBmEQDoMwCIdBOAzCIBwGYRAOgzAIh0EYhMMgHAZhEA6DMAiHQRiEwyAMwmEQDoMwCIdBsmdfcwbxVeLWt2EQX2WT2BrDID7KcCGWDWQQH2WKEOnjGcQ/eU/cyZAgg/gm9e+KfFmTQfyS8XdBRM/9DOKTpBS5J1KkPIP4JFXugYikxxjEH1kVeV8k+iKD+COHxYM0YRBf5PRDEFGLQfyQ4F7/i+Sv5vd/C9+L5C+Q/Y9AxE8M4oOUzSJyhUG8z1+ygIgVDOJ5+jXNAhJoyyCeZ0DWr0jsLQbxOqOzgohfizKIx4kokk1kcAyDeJwT2UDE0SCDeJvy2UHEmwzicdJyiFxkEG8zJAdIsYEM4ml+yAEi0qYyiKf3WS/mFNnEIJ7mXE4QMZJBvMzIXCCBWwziYT7MBSKWVWMQDy8igdwiExnEwwzODSJGM4h3eUcCMmIqg3iWJyQgoh6DeJY2MhCxgUG8ymkpSFoig3iU4VIQ8TaDeJSf5SAJcQziTYrKQcQ3DOIvELGaQfwFsqQxg3iRChiIWMkgXmQgChLbjkE8yHsoiBjCIB7kJA5SLJNBzGcfDiI6MYj5dFKABJoziPFMUYCI+QxiPBkqkEBJBjGckkKZ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";
|
|
12746
12407
|
|
|
12747
12408
|
// src/providers/cbn/CbnProvider.ts
|
|
12748
12409
|
var API_BASE5 = "https://sbamemberdev.wpenginepowered.com/wp-json/superbook/v1";
|
|
12749
|
-
var CbnProvider = class {
|
|
12410
|
+
var CbnProvider = class extends BaseProvider {
|
|
12750
12411
|
constructor() {
|
|
12751
|
-
|
|
12412
|
+
super(...arguments);
|
|
12752
12413
|
this.deviceFlowHelper = new DeviceFlowHelper();
|
|
12753
12414
|
this.id = "cbn";
|
|
12754
12415
|
this.name = "CBN";
|
|
@@ -12761,66 +12422,48 @@ var CbnProvider = class {
|
|
|
12761
12422
|
clientId: "freeplay",
|
|
12762
12423
|
scopes: [],
|
|
12763
12424
|
supportsDeviceFlow: true,
|
|
12764
|
-
deviceAuthEndpoint: "/device"
|
|
12765
|
-
endpoints: {
|
|
12766
|
-
catalog: "/catalog",
|
|
12767
|
-
courseDetail: (courseId) => `/catalog/${courseId}`,
|
|
12768
|
-
lessonPlaylist: (lessonId) => `/lesson-playlist/${lessonId}`
|
|
12769
|
-
}
|
|
12425
|
+
deviceAuthEndpoint: "/device"
|
|
12770
12426
|
};
|
|
12771
12427
|
this.requiresAuth = true;
|
|
12772
12428
|
this.authTypes = ["device_flow"];
|
|
12773
12429
|
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
12774
12430
|
}
|
|
12775
|
-
async apiRequest(path, auth) {
|
|
12776
|
-
return this.apiHelper.apiRequest(this.config, this.id, path, auth);
|
|
12777
|
-
}
|
|
12778
12431
|
async browse(path, auth) {
|
|
12779
12432
|
const { segments, depth } = parsePath(path);
|
|
12780
12433
|
if (depth === 0) {
|
|
12781
12434
|
return [{ type: "folder", id: "catalog-root", title: "Catalog", path: "/catalog" }];
|
|
12782
12435
|
}
|
|
12783
12436
|
if (segments[0] !== "catalog") return [];
|
|
12784
|
-
if (depth === 1)
|
|
12785
|
-
|
|
12786
|
-
|
|
12437
|
+
if (depth === 1) {
|
|
12438
|
+
const response = await this.apiRequest("/catalog", auth);
|
|
12439
|
+
return Array.isArray(response) ? convertCoursesToFolders(response) : [];
|
|
12440
|
+
}
|
|
12441
|
+
if (depth === 2) {
|
|
12442
|
+
const response = await this.apiRequest(`/catalog/${segments[1]}`, auth);
|
|
12443
|
+
return response?.lessons ? convertLessonsToFolders(response.lessons, path) : [];
|
|
12444
|
+
}
|
|
12445
|
+
if (depth === 3) {
|
|
12446
|
+
const resolved = await this.resolveFiles(path, auth);
|
|
12447
|
+
return resolved?.files ?? [];
|
|
12448
|
+
}
|
|
12787
12449
|
return [];
|
|
12788
12450
|
}
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
if (!Array.isArray(response)) return [];
|
|
12792
|
-
return convertCoursesToFolders(response);
|
|
12793
|
-
}
|
|
12794
|
-
async getLessons(courseId, coursePath, auth) {
|
|
12795
|
-
const pathFn = this.config.endpoints.courseDetail;
|
|
12796
|
-
const response = await this.apiRequest(pathFn(courseId), auth);
|
|
12797
|
-
if (!response?.lessons) return [];
|
|
12798
|
-
return convertLessonsToFolders(response.lessons, coursePath);
|
|
12799
|
-
}
|
|
12800
|
-
async getVideos(lessonId, auth) {
|
|
12801
|
-
const playlist = await this.fetchPlaylist(lessonId, auth);
|
|
12802
|
-
return playlist ? convertPlaylistToFiles(playlist) : [];
|
|
12803
|
-
}
|
|
12804
|
-
async fetchPlaylist(lessonId, auth) {
|
|
12805
|
-
const pathFn = this.config.endpoints.lessonPlaylist;
|
|
12806
|
-
return this.apiRequest(pathFn(lessonId), auth);
|
|
12807
|
-
}
|
|
12808
|
-
async getPlaylist(path, auth, _resolution) {
|
|
12451
|
+
/** Resolve a leaf path (/catalog/{courseId}/{lessonId}) to its playlist files. */
|
|
12452
|
+
async resolveFiles(path, auth) {
|
|
12809
12453
|
const { segments, depth } = parsePath(path);
|
|
12810
12454
|
if (depth !== 3 || segments[0] !== "catalog") return null;
|
|
12811
|
-
const playlist = await this.
|
|
12455
|
+
const playlist = await this.apiRequest(`/lesson-playlist/${segments[2]}`, auth);
|
|
12812
12456
|
if (!playlist || playlist.playlist.length === 0) return null;
|
|
12813
|
-
return convertPlaylistToFiles(playlist);
|
|
12457
|
+
return { files: convertPlaylistToFiles(playlist), lessonTitle: playlist.lesson_title };
|
|
12814
12458
|
}
|
|
12815
|
-
async
|
|
12816
|
-
const
|
|
12817
|
-
|
|
12818
|
-
const playlist = await this.fetchPlaylist(segments[2], auth);
|
|
12819
|
-
if (!playlist || playlist.playlist.length === 0) return null;
|
|
12820
|
-
return convertPlaylistToInstructions(playlist);
|
|
12459
|
+
async getPlaylist(path, auth, _resolution) {
|
|
12460
|
+
const resolved = await this.resolveFiles(path, auth);
|
|
12461
|
+
return resolved?.files ?? null;
|
|
12821
12462
|
}
|
|
12822
|
-
|
|
12823
|
-
|
|
12463
|
+
async getInstructions(path, auth) {
|
|
12464
|
+
const resolved = await this.resolveFiles(path, auth);
|
|
12465
|
+
if (!resolved) return null;
|
|
12466
|
+
return filesToInstructions(resolved.lessonTitle || "Lesson", resolved.files);
|
|
12824
12467
|
}
|
|
12825
12468
|
async initiateDeviceFlow() {
|
|
12826
12469
|
return this.deviceFlowHelper.initiateDeviceFlow(this.config);
|
|
@@ -16451,8 +16094,9 @@ var data_default3 = {
|
|
|
16451
16094
|
};
|
|
16452
16095
|
|
|
16453
16096
|
// src/providers/lifeChurch/LifeChurchProvider.ts
|
|
16454
|
-
var LifeChurchProvider = class {
|
|
16097
|
+
var LifeChurchProvider = class extends BaseProvider {
|
|
16455
16098
|
constructor() {
|
|
16099
|
+
super(...arguments);
|
|
16456
16100
|
this.id = "lifechurch";
|
|
16457
16101
|
this.name = "Life.Church";
|
|
16458
16102
|
this.logos = {
|
|
@@ -16465,8 +16109,7 @@ var LifeChurchProvider = class {
|
|
|
16465
16109
|
apiBase: "https://www.life.church",
|
|
16466
16110
|
oauthBase: "",
|
|
16467
16111
|
clientId: "",
|
|
16468
|
-
scopes: []
|
|
16469
|
-
endpoints: {}
|
|
16112
|
+
scopes: []
|
|
16470
16113
|
};
|
|
16471
16114
|
this.requiresAuth = false;
|
|
16472
16115
|
this.authTypes = ["none"];
|
|
@@ -16481,20 +16124,14 @@ var LifeChurchProvider = class {
|
|
|
16481
16124
|
findSeries(seriesId) {
|
|
16482
16125
|
return this.data.series.find((s) => s.id === seriesId);
|
|
16483
16126
|
}
|
|
16484
|
-
findUnit(series, unitId) {
|
|
16485
|
-
return series.units.find((u) => u.id === unitId);
|
|
16486
|
-
}
|
|
16487
|
-
findLesson(unit, lessonId) {
|
|
16488
|
-
return unit.lessons.find((l) => l.id === lessonId);
|
|
16489
|
-
}
|
|
16490
16127
|
findScheduled(scheduledId) {
|
|
16491
16128
|
return this.data.scheduledLessons?.find((s) => s.id === scheduledId);
|
|
16492
16129
|
}
|
|
16493
16130
|
/** Resolve a scheduled-lesson reference to the underlying lesson + unit + series. */
|
|
16494
16131
|
resolveScheduled(sched) {
|
|
16495
16132
|
const series = this.findSeries(sched.seriesId);
|
|
16496
|
-
const unit = series
|
|
16497
|
-
const lesson = unit
|
|
16133
|
+
const unit = series?.units.find((u) => u.id === sched.unitId);
|
|
16134
|
+
const lesson = unit?.lessons.find((l) => l.id === sched.lessonId);
|
|
16498
16135
|
if (!series || !unit || !lesson) return null;
|
|
16499
16136
|
return { series, unit, lesson };
|
|
16500
16137
|
}
|
|
@@ -16509,17 +16146,40 @@ var LifeChurchProvider = class {
|
|
|
16509
16146
|
providerData: { sourceUrl: lesson.sourceUrl }
|
|
16510
16147
|
};
|
|
16511
16148
|
}
|
|
16149
|
+
/** Resolve a leaf-or-unit path to its files plus the name/section used for instructions. */
|
|
16150
|
+
resolve(path) {
|
|
16151
|
+
const { segments, depth } = parsePath(path);
|
|
16152
|
+
if (segments[0] === "scheduled") {
|
|
16153
|
+
if (depth !== 2) return null;
|
|
16154
|
+
const sched = this.findScheduled(segments[1]);
|
|
16155
|
+
const resolved = sched && this.resolveScheduled(sched);
|
|
16156
|
+
if (!sched || !resolved) return null;
|
|
16157
|
+
const label = `${sched.ageGroup} \u2014 ${resolved.lesson.title}`;
|
|
16158
|
+
return {
|
|
16159
|
+
files: [this.lessonToFile(resolved.lesson, label)],
|
|
16160
|
+
name: label,
|
|
16161
|
+
section: { id: `scheduled-${sched.id}-section`, label: "This Sunday" }
|
|
16162
|
+
};
|
|
16163
|
+
}
|
|
16164
|
+
const series = this.findSeries(segments[0]);
|
|
16165
|
+
const unit = series?.units.find((u) => u.id === segments[1]);
|
|
16166
|
+
if (!unit) return null;
|
|
16167
|
+
if (depth === 2) {
|
|
16168
|
+
return { files: unit.lessons.map((l) => this.lessonToFile(l)), name: unit.name, section: { id: `${unit.id}-section`, label: unit.name } };
|
|
16169
|
+
}
|
|
16170
|
+
if (depth === 3) {
|
|
16171
|
+
const lesson = unit.lessons.find((l) => l.id === segments[2]);
|
|
16172
|
+
if (!lesson) return null;
|
|
16173
|
+
return { files: [this.lessonToFile(lesson)], name: lesson.title, section: { id: `${unit.id}-section`, label: unit.name } };
|
|
16174
|
+
}
|
|
16175
|
+
return null;
|
|
16176
|
+
}
|
|
16512
16177
|
async browse(path, _auth) {
|
|
16513
16178
|
const { segments, depth } = parsePath(path);
|
|
16514
16179
|
if (depth === 0) {
|
|
16515
16180
|
const items = [];
|
|
16516
16181
|
if (this.data.scheduledLessons && this.data.scheduledLessons.length > 0) {
|
|
16517
|
-
items.push({
|
|
16518
|
-
type: "folder",
|
|
16519
|
-
id: "scheduled",
|
|
16520
|
-
title: "This Sunday",
|
|
16521
|
-
path: "/scheduled"
|
|
16522
|
-
});
|
|
16182
|
+
items.push({ type: "folder", id: "scheduled", title: "This Sunday", path: "/scheduled" });
|
|
16523
16183
|
}
|
|
16524
16184
|
for (const s of this.data.series) {
|
|
16525
16185
|
items.push({ type: "folder", id: s.id, title: s.name, thumbnail: s.thumbnail, path: `/${s.id}` });
|
|
@@ -16540,13 +16200,7 @@ var LifeChurchProvider = class {
|
|
|
16540
16200
|
};
|
|
16541
16201
|
});
|
|
16542
16202
|
}
|
|
16543
|
-
|
|
16544
|
-
const sched = this.findScheduled(segments[1]);
|
|
16545
|
-
const resolved = sched && this.resolveScheduled(sched);
|
|
16546
|
-
if (!sched || !resolved) return [];
|
|
16547
|
-
return [this.lessonToFile(resolved.lesson, `${sched.ageGroup} \u2014 ${resolved.lesson.title}`)];
|
|
16548
|
-
}
|
|
16549
|
-
return [];
|
|
16203
|
+
return this.resolve(path)?.files ?? [];
|
|
16550
16204
|
}
|
|
16551
16205
|
if (depth === 1) {
|
|
16552
16206
|
const series = this.findSeries(segments[0]);
|
|
@@ -16561,8 +16215,8 @@ var LifeChurchProvider = class {
|
|
|
16561
16215
|
}
|
|
16562
16216
|
if (depth === 2) {
|
|
16563
16217
|
const series = this.findSeries(segments[0]);
|
|
16564
|
-
const unit = series
|
|
16565
|
-
if (!
|
|
16218
|
+
const unit = series?.units.find((u) => u.id === segments[1]);
|
|
16219
|
+
if (!unit) return [];
|
|
16566
16220
|
return unit.lessons.map((l) => ({
|
|
16567
16221
|
type: "folder",
|
|
16568
16222
|
id: l.id,
|
|
@@ -16573,78 +16227,18 @@ var LifeChurchProvider = class {
|
|
|
16573
16227
|
}));
|
|
16574
16228
|
}
|
|
16575
16229
|
if (depth === 3) {
|
|
16576
|
-
|
|
16577
|
-
const unit = series && this.findUnit(series, segments[1]);
|
|
16578
|
-
const lesson = unit && this.findLesson(unit, segments[2]);
|
|
16579
|
-
if (!lesson) return [];
|
|
16580
|
-
return [this.lessonToFile(lesson)];
|
|
16230
|
+
return this.resolve(path)?.files ?? [];
|
|
16581
16231
|
}
|
|
16582
16232
|
return [];
|
|
16583
16233
|
}
|
|
16584
16234
|
async getPlaylist(path, _auth, _resolution) {
|
|
16585
|
-
const
|
|
16586
|
-
|
|
16587
|
-
const sched = this.findScheduled(segments[1]);
|
|
16588
|
-
const resolved = sched && this.resolveScheduled(sched);
|
|
16589
|
-
return resolved ? [this.lessonToFile(resolved.lesson, `${sched.ageGroup} \u2014 ${resolved.lesson.title}`)] : null;
|
|
16590
|
-
}
|
|
16591
|
-
if (depth === 3) {
|
|
16592
|
-
const series = this.findSeries(segments[0]);
|
|
16593
|
-
const unit = series && this.findUnit(series, segments[1]);
|
|
16594
|
-
const lesson = unit && this.findLesson(unit, segments[2]);
|
|
16595
|
-
return lesson ? [this.lessonToFile(lesson)] : null;
|
|
16596
|
-
}
|
|
16597
|
-
if (depth === 2 && segments[0] !== "scheduled") {
|
|
16598
|
-
const series = this.findSeries(segments[0]);
|
|
16599
|
-
const unit = series && this.findUnit(series, segments[1]);
|
|
16600
|
-
if (!unit) return null;
|
|
16601
|
-
const files = unit.lessons.map((l) => this.lessonToFile(l));
|
|
16602
|
-
return files.length > 0 ? files : null;
|
|
16603
|
-
}
|
|
16604
|
-
return null;
|
|
16235
|
+
const resolved = this.resolve(path);
|
|
16236
|
+
return resolved && resolved.files.length > 0 ? resolved.files : null;
|
|
16605
16237
|
}
|
|
16606
16238
|
async getInstructions(path, _auth) {
|
|
16607
|
-
const
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
itemType: "action",
|
|
16611
|
-
label: label ?? lesson.title,
|
|
16612
|
-
actionType: "play",
|
|
16613
|
-
children: [
|
|
16614
|
-
{
|
|
16615
|
-
id: lesson.id,
|
|
16616
|
-
itemType: "file",
|
|
16617
|
-
label: label ?? lesson.title,
|
|
16618
|
-
downloadUrl: lesson.videoUrl,
|
|
16619
|
-
thumbnail: lesson.thumbnail,
|
|
16620
|
-
mediaType: "video"
|
|
16621
|
-
}
|
|
16622
|
-
]
|
|
16623
|
-
});
|
|
16624
|
-
if (segments[0] === "scheduled" && depth === 2) {
|
|
16625
|
-
const sched = this.findScheduled(segments[1]);
|
|
16626
|
-
const resolved = sched && this.resolveScheduled(sched);
|
|
16627
|
-
if (!sched || !resolved) return null;
|
|
16628
|
-
const label = `${sched.ageGroup} \u2014 ${resolved.lesson.title}`;
|
|
16629
|
-
return {
|
|
16630
|
-
name: label,
|
|
16631
|
-
items: [{ id: `scheduled-${sched.id}-section`, itemType: "section", label: "This Sunday", children: [buildItem(resolved.lesson, label)] }]
|
|
16632
|
-
};
|
|
16633
|
-
}
|
|
16634
|
-
if (depth === 3) {
|
|
16635
|
-
const series = this.findSeries(segments[0]);
|
|
16636
|
-
const unit = series && this.findUnit(series, segments[1]);
|
|
16637
|
-
const lesson = unit && this.findLesson(unit, segments[2]);
|
|
16638
|
-
if (!series || !unit || !lesson) return null;
|
|
16639
|
-
return { name: lesson.title, items: [{ id: `${unit.id}-section`, itemType: "section", label: unit.name, children: [buildItem(lesson)] }] };
|
|
16640
|
-
}
|
|
16641
|
-
if (depth === 2 && segments[0] !== "scheduled") {
|
|
16642
|
-
const series = this.findSeries(segments[0]);
|
|
16643
|
-
const unit = series && this.findUnit(series, segments[1]);
|
|
16644
|
-
if (!unit) return null;
|
|
16645
|
-
return { name: unit.name, items: [{ id: `${unit.id}-section`, itemType: "section", label: unit.name, children: unit.lessons.map((l) => buildItem(l)) }] };
|
|
16646
|
-
}
|
|
16647
|
-
return null;
|
|
16239
|
+
const resolved = this.resolve(path);
|
|
16240
|
+
if (!resolved) return null;
|
|
16241
|
+
return filesToInstructions(resolved.name, resolved.files, resolved.section);
|
|
16648
16242
|
}
|
|
16649
16243
|
/**
|
|
16650
16244
|
* Returns the most recent scheduled lesson from data.scheduledLessons.
|
|
@@ -16672,9 +16266,6 @@ var LifeChurchProvider = class {
|
|
|
16672
16266
|
]
|
|
16673
16267
|
};
|
|
16674
16268
|
}
|
|
16675
|
-
supportsDeviceFlow() {
|
|
16676
|
-
return false;
|
|
16677
|
-
}
|
|
16678
16269
|
};
|
|
16679
16270
|
|
|
16680
16271
|
// src/providers/index.ts
|
|
@@ -16769,18 +16360,21 @@ function getAvailableProviders(ids) {
|
|
|
16769
16360
|
}
|
|
16770
16361
|
|
|
16771
16362
|
// src/index.ts
|
|
16772
|
-
var VERSION = true ? "0.
|
|
16363
|
+
var VERSION = true ? "0.5.1" : "dev";
|
|
16773
16364
|
// Annotate the CommonJS export names for ESM import in node:
|
|
16774
16365
|
0 && (module.exports = {
|
|
16775
16366
|
APlayProvider,
|
|
16776
16367
|
B1ChurchProvider,
|
|
16368
|
+
BaseProvider,
|
|
16777
16369
|
BibleProjectProvider,
|
|
16778
16370
|
CbnProvider,
|
|
16371
|
+
DeviceFlowHelper,
|
|
16779
16372
|
DropboxProvider,
|
|
16780
16373
|
HighVoltageKidsProvider,
|
|
16781
16374
|
JesusFilmProvider,
|
|
16782
16375
|
LessonsChurchProvider,
|
|
16783
16376
|
LifeChurchProvider,
|
|
16377
|
+
OAuthHelper,
|
|
16784
16378
|
PlanningCenterProvider,
|
|
16785
16379
|
SignPresenterProvider,
|
|
16786
16380
|
TokenHelper,
|
|
@@ -16792,6 +16386,7 @@ var VERSION = true ? "0.4.1" : "dev";
|
|
|
16792
16386
|
isContentFile,
|
|
16793
16387
|
isContentFolder,
|
|
16794
16388
|
navigateToPath,
|
|
16795
|
-
registerProvider
|
|
16389
|
+
registerProvider,
|
|
16390
|
+
toAuthData
|
|
16796
16391
|
});
|
|
16797
16392
|
//# sourceMappingURL=index.cjs.map
|