@churchapps/content-providers 0.1.4 → 0.1.6
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/dist/index.cjs +113 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +113 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -620,7 +620,7 @@ declare class HighVoltageKidsProvider implements IProvider {
|
|
|
620
620
|
* / -> categories (Feature Films, Series, Collections)
|
|
621
621
|
* /{category} -> list items in category
|
|
622
622
|
* /{category}/{id} -> single video (feature film) or container children (series/collection)
|
|
623
|
-
* /{category}/{
|
|
623
|
+
* /{category}/{...containerIds}/{id} -> nested containers or single video (supports arbitrary depth)
|
|
624
624
|
*/
|
|
625
625
|
declare class JesusFilmProvider implements IProvider {
|
|
626
626
|
readonly id = "jesusfilm";
|
package/dist/index.d.ts
CHANGED
|
@@ -620,7 +620,7 @@ declare class HighVoltageKidsProvider implements IProvider {
|
|
|
620
620
|
* / -> categories (Feature Films, Series, Collections)
|
|
621
621
|
* /{category} -> list items in category
|
|
622
622
|
* /{category}/{id} -> single video (feature film) or container children (series/collection)
|
|
623
|
-
* /{category}/{
|
|
623
|
+
* /{category}/{...containerIds}/{id} -> nested containers or single video (supports arbitrary depth)
|
|
624
624
|
*/
|
|
625
625
|
declare class JesusFilmProvider implements IProvider {
|
|
626
626
|
readonly id = "jesusfilm";
|
package/dist/index.js
CHANGED
|
@@ -486,13 +486,18 @@ var ApiHelper = class {
|
|
|
486
486
|
const headers = { Accept: "application/json" };
|
|
487
487
|
if (auth) headers["Authorization"] = `Bearer ${auth.access_token}`;
|
|
488
488
|
if (body) headers["Content-Type"] = "application/json";
|
|
489
|
+
console.log(`[B1Church] apiRequest: ${method} ${url}`);
|
|
489
490
|
const options = { method, headers, ...body ? { body: JSON.stringify(body) } : {} };
|
|
490
491
|
const response = await fetch(url, options);
|
|
491
492
|
if (!response.ok) {
|
|
493
|
+
console.warn(`[B1Church] apiRequest failed: ${method} ${url} \u2192 HTTP ${response.status} ${response.statusText}`);
|
|
492
494
|
return null;
|
|
493
495
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
+
const data = await response.json();
|
|
497
|
+
console.log(`[B1Church] apiRequest OK: ${method} ${url} \u2192 ${Array.isArray(data) ? data.length + " items" : typeof data}`);
|
|
498
|
+
return data;
|
|
499
|
+
} catch (err) {
|
|
500
|
+
console.error(`[B1Church] apiRequest error: ${method} ${config.apiBase}${path}`, err);
|
|
496
501
|
return null;
|
|
497
502
|
}
|
|
498
503
|
}
|
|
@@ -1367,10 +1372,17 @@ async function authFetch(url, auth) {
|
|
|
1367
1372
|
if (auth) {
|
|
1368
1373
|
headers["Authorization"] = `Bearer ${auth.access_token}`;
|
|
1369
1374
|
}
|
|
1375
|
+
console.log(`[B1Church] authFetch: ${url}`);
|
|
1370
1376
|
const response = await fetch(url, { method: "GET", headers });
|
|
1371
|
-
if (!response.ok)
|
|
1372
|
-
|
|
1373
|
-
|
|
1377
|
+
if (!response.ok) {
|
|
1378
|
+
console.warn(`[B1Church] authFetch failed: ${url} \u2192 HTTP ${response.status} ${response.statusText}`);
|
|
1379
|
+
return null;
|
|
1380
|
+
}
|
|
1381
|
+
const data = await response.json();
|
|
1382
|
+
console.log(`[B1Church] authFetch OK: ${url} \u2192 ${Array.isArray(data) ? data.length + " items" : typeof data}`);
|
|
1383
|
+
return data;
|
|
1384
|
+
} catch (err) {
|
|
1385
|
+
console.error(`[B1Church] authFetch error: ${url}`, err);
|
|
1374
1386
|
return null;
|
|
1375
1387
|
}
|
|
1376
1388
|
}
|
|
@@ -1389,20 +1401,34 @@ async function fetchPlans(planTypeId, auth) {
|
|
|
1389
1401
|
async function fetchVenueFeed(venueId) {
|
|
1390
1402
|
try {
|
|
1391
1403
|
const url = `${LESSONS_API_BASE}/venues/public/feed/${venueId}`;
|
|
1404
|
+
console.log(`[B1Church] fetchVenueFeed: ${url}`);
|
|
1392
1405
|
const response = await fetch(url, { method: "GET", headers: { Accept: "application/json" } });
|
|
1393
|
-
if (!response.ok)
|
|
1394
|
-
|
|
1395
|
-
|
|
1406
|
+
if (!response.ok) {
|
|
1407
|
+
console.warn(`[B1Church] fetchVenueFeed failed: HTTP ${response.status} ${response.statusText} for venueId=${venueId}`);
|
|
1408
|
+
return null;
|
|
1409
|
+
}
|
|
1410
|
+
const data = await response.json();
|
|
1411
|
+
console.log(`[B1Church] fetchVenueFeed OK: venueId=${venueId}, sections=${data?.sections?.length ?? "none"}`);
|
|
1412
|
+
return data;
|
|
1413
|
+
} catch (err) {
|
|
1414
|
+
console.error(`[B1Church] fetchVenueFeed error: venueId=${venueId}`, err);
|
|
1396
1415
|
return null;
|
|
1397
1416
|
}
|
|
1398
1417
|
}
|
|
1399
1418
|
async function fetchVenueActions(venueId) {
|
|
1400
1419
|
try {
|
|
1401
1420
|
const url = `${LESSONS_API_BASE}/venues/public/actions/${venueId}`;
|
|
1421
|
+
console.log(`[B1Church] fetchVenueActions: ${url}`);
|
|
1402
1422
|
const response = await fetch(url, { method: "GET", headers: { Accept: "application/json" } });
|
|
1403
|
-
if (!response.ok)
|
|
1404
|
-
|
|
1405
|
-
|
|
1423
|
+
if (!response.ok) {
|
|
1424
|
+
console.warn(`[B1Church] fetchVenueActions failed: HTTP ${response.status} ${response.statusText} for venueId=${venueId}`);
|
|
1425
|
+
return null;
|
|
1426
|
+
}
|
|
1427
|
+
const data = await response.json();
|
|
1428
|
+
console.log(`[B1Church] fetchVenueActions OK: venueId=${venueId}`);
|
|
1429
|
+
return data;
|
|
1430
|
+
} catch (err) {
|
|
1431
|
+
console.error(`[B1Church] fetchVenueActions error: venueId=${venueId}`, err);
|
|
1406
1432
|
return null;
|
|
1407
1433
|
}
|
|
1408
1434
|
}
|
|
@@ -1418,14 +1444,21 @@ async function fetchFromProviderProxy(method, ministryId, providerId, path, auth
|
|
|
1418
1444
|
}
|
|
1419
1445
|
const body = { ministryId, providerId, path };
|
|
1420
1446
|
if (resolution !== void 0) body.resolution = resolution;
|
|
1447
|
+
console.log(`[B1Church] providerProxy: ${method} providerId=${providerId} path=${path}`);
|
|
1421
1448
|
const response = await fetch(url, {
|
|
1422
1449
|
method: "POST",
|
|
1423
1450
|
headers,
|
|
1424
1451
|
body: JSON.stringify(body)
|
|
1425
1452
|
});
|
|
1426
|
-
if (!response.ok)
|
|
1427
|
-
|
|
1428
|
-
|
|
1453
|
+
if (!response.ok) {
|
|
1454
|
+
console.warn(`[B1Church] providerProxy failed: ${method} \u2192 HTTP ${response.status} ${response.statusText}`);
|
|
1455
|
+
return null;
|
|
1456
|
+
}
|
|
1457
|
+
const data = await response.json();
|
|
1458
|
+
console.log(`[B1Church] providerProxy OK: ${method} \u2192 ${Array.isArray(data) ? data.length + " items" : typeof data}`);
|
|
1459
|
+
return data;
|
|
1460
|
+
} catch (err) {
|
|
1461
|
+
console.error(`[B1Church] providerProxy error: ${method}`, err);
|
|
1429
1462
|
return null;
|
|
1430
1463
|
}
|
|
1431
1464
|
}
|
|
@@ -1853,23 +1886,35 @@ var B1ChurchProvider = class {
|
|
|
1853
1886
|
return null;
|
|
1854
1887
|
}
|
|
1855
1888
|
async getPlaylist(path, authData, resolution) {
|
|
1889
|
+
console.log(`[B1Church] getPlaylist called with path=${path}`);
|
|
1856
1890
|
const { segments, depth } = parsePath(path);
|
|
1857
|
-
if (depth < 4 || segments[0] !== "ministries")
|
|
1891
|
+
if (depth < 4 || segments[0] !== "ministries") {
|
|
1892
|
+
console.warn(`[B1Church] getPlaylist: invalid path depth=${depth} segments=${JSON.stringify(segments)}`);
|
|
1893
|
+
return null;
|
|
1894
|
+
}
|
|
1858
1895
|
const ministryId = segments[1];
|
|
1859
1896
|
const planId = segments[3];
|
|
1860
1897
|
const planTypeId = segments[2];
|
|
1898
|
+
console.log(`[B1Church] getPlaylist: ministryId=${ministryId}, planTypeId=${planTypeId}, planId=${planId}`);
|
|
1861
1899
|
const plans = await fetchPlans(planTypeId, authData);
|
|
1900
|
+
console.log(`[B1Church] getPlaylist: fetchPlans returned ${plans.length} plans`);
|
|
1862
1901
|
const planFolder = plans.find((p) => p.id === planId);
|
|
1863
|
-
if (!planFolder)
|
|
1902
|
+
if (!planFolder) {
|
|
1903
|
+
console.warn(`[B1Church] getPlaylist: plan ${planId} not found in ${plans.length} plans (ids: ${plans.map((p) => p.id).join(", ")})`);
|
|
1904
|
+
return null;
|
|
1905
|
+
}
|
|
1864
1906
|
const churchId = planFolder.churchId;
|
|
1865
1907
|
const venueId = planFolder.contentId;
|
|
1908
|
+
console.log(`[B1Church] getPlaylist: planFolder found \u2014 churchId=${churchId}, venueId=${venueId}, providerId=${planFolder.providerId}, providerPlanId=${planFolder.providerPlanId}`);
|
|
1866
1909
|
if (!churchId) {
|
|
1867
1910
|
console.warn("[B1Church getPlaylist] planFolder missing churchId:", planFolder.id);
|
|
1868
1911
|
return null;
|
|
1869
1912
|
}
|
|
1870
1913
|
const pathFn = this.config.endpoints.planItems;
|
|
1871
1914
|
const planItems = await this.apiRequest(pathFn(churchId, planId), authData);
|
|
1915
|
+
console.log(`[B1Church] getPlaylist: planItems=${planItems ? Array.isArray(planItems) ? planItems.length + " sections" : typeof planItems : "null"}`);
|
|
1872
1916
|
if ((!planItems || planItems.length === 0) && planFolder.providerId && planFolder.providerPlanId) {
|
|
1917
|
+
console.log(`[B1Church] getPlaylist: no planItems, trying external provider ${planFolder.providerId} with path ${planFolder.providerPlanId}`);
|
|
1873
1918
|
const externalFiles = await fetchFromProviderProxy(
|
|
1874
1919
|
"getPlaylist",
|
|
1875
1920
|
ministryId,
|
|
@@ -1878,17 +1923,30 @@ var B1ChurchProvider = class {
|
|
|
1878
1923
|
authData,
|
|
1879
1924
|
resolution
|
|
1880
1925
|
);
|
|
1926
|
+
console.log(`[B1Church] getPlaylist: external provider returned ${externalFiles ? Array.isArray(externalFiles) ? externalFiles.length + " files" : typeof externalFiles : "null"}`);
|
|
1881
1927
|
return externalFiles || null;
|
|
1882
1928
|
}
|
|
1883
|
-
if (!planItems || !Array.isArray(planItems))
|
|
1929
|
+
if (!planItems || !Array.isArray(planItems)) {
|
|
1930
|
+
console.warn(`[B1Church] getPlaylist: planItems is null/not-array and no external provider fallback. providerId=${planFolder.providerId}, providerPlanId=${planFolder.providerPlanId}`);
|
|
1931
|
+
return null;
|
|
1932
|
+
}
|
|
1933
|
+
console.log(`[B1Church] getPlaylist: processing ${planItems.length} sections, venueId=${venueId || "none"}`);
|
|
1884
1934
|
const venueFeed = venueId ? await fetchVenueFeed(venueId) : null;
|
|
1935
|
+
if (venueId && !venueFeed) {
|
|
1936
|
+
console.warn(`[B1Church] getPlaylist: venueFeed is null for venueId=${venueId}`);
|
|
1937
|
+
}
|
|
1885
1938
|
const files = [];
|
|
1886
1939
|
for (const sectionItem of planItems) {
|
|
1940
|
+
console.log(`[B1Church] getPlaylist: section "${sectionItem.label || sectionItem.id}" has ${sectionItem.children?.length || 0} children`);
|
|
1887
1941
|
for (const child of sectionItem.children || []) {
|
|
1888
1942
|
const childItemType = child.itemType;
|
|
1943
|
+
console.log(`[B1Church] getPlaylist: child itemType=${childItemType}, relatedId=${child.relatedId}, providerId=${child.providerId}, providerPath=${child.providerPath}, link=${child.link ? "yes" : "no"}`);
|
|
1889
1944
|
const isSectionType = childItemType === "section" || childItemType === "lessonSection" || childItemType === "providerSection";
|
|
1890
1945
|
const canExpandLocally = isSectionType && venueFeed && child.relatedId;
|
|
1891
|
-
if (
|
|
1946
|
+
if (canExpandLocally) {
|
|
1947
|
+
const itemFiles = getFilesFromVenueFeed(venueFeed, childItemType, child.relatedId);
|
|
1948
|
+
files.push(...itemFiles);
|
|
1949
|
+
} else if (isExternalProviderItem(child) && child.providerId && child.providerPath) {
|
|
1892
1950
|
const cacheKey = `${child.providerId}:${child.providerPath}`;
|
|
1893
1951
|
if (child.providerContentPath) {
|
|
1894
1952
|
let externalPlan = this.externalContentCache.plans.get(cacheKey);
|
|
@@ -1936,9 +1994,6 @@ var B1ChurchProvider = class {
|
|
|
1936
1994
|
files.push(...externalFiles);
|
|
1937
1995
|
}
|
|
1938
1996
|
}
|
|
1939
|
-
} else if (canExpandLocally) {
|
|
1940
|
-
const itemFiles = getFilesFromVenueFeed(venueFeed, childItemType, child.relatedId);
|
|
1941
|
-
files.push(...itemFiles);
|
|
1942
1997
|
} else if ((childItemType === "providerFile" || childItemType === "providerPresentation") && child.link) {
|
|
1943
1998
|
const file = getFileFromProviderFileItem(child);
|
|
1944
1999
|
if (file) files.push(file);
|
|
@@ -1948,6 +2003,10 @@ var B1ChurchProvider = class {
|
|
|
1948
2003
|
}
|
|
1949
2004
|
}
|
|
1950
2005
|
}
|
|
2006
|
+
console.log(`[B1Church] getPlaylist: total files collected = ${files.length}`);
|
|
2007
|
+
if (files.length === 0) {
|
|
2008
|
+
console.warn(`[B1Church] getPlaylist: returning null \u2014 no files found for path=${path}`);
|
|
2009
|
+
}
|
|
1951
2010
|
return files.length > 0 ? files : null;
|
|
1952
2011
|
}
|
|
1953
2012
|
supportsDeviceFlow() {
|
|
@@ -12441,13 +12500,13 @@ var JesusFilmProvider = class {
|
|
|
12441
12500
|
const { segments, depth } = parsePath(path);
|
|
12442
12501
|
if (depth === 0) return this.getCategories();
|
|
12443
12502
|
if (depth === 1) return this.getItemsInCategory(segments[0]);
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
if (
|
|
12450
|
-
return
|
|
12503
|
+
const category = segments[0];
|
|
12504
|
+
const lastId = segments[depth - 1];
|
|
12505
|
+
if (depth === 2 && category === "feature-films") return this.getVideoFile(lastId);
|
|
12506
|
+
const pathPrefix = "/" + segments.join("/");
|
|
12507
|
+
const children = await this.getContainerChildren(lastId, pathPrefix);
|
|
12508
|
+
if (children.length > 0) return children;
|
|
12509
|
+
return this.getVideoFile(lastId);
|
|
12451
12510
|
}
|
|
12452
12511
|
getCategories() {
|
|
12453
12512
|
return [
|
|
@@ -12496,7 +12555,7 @@ var JesusFilmProvider = class {
|
|
|
12496
12555
|
})
|
|
12497
12556
|
];
|
|
12498
12557
|
}
|
|
12499
|
-
async getContainerChildren(containerId,
|
|
12558
|
+
async getContainerChildren(containerId, pathPrefix) {
|
|
12500
12559
|
const linksData = await this.fetchApi(
|
|
12501
12560
|
`/media-component-links/${containerId}`
|
|
12502
12561
|
);
|
|
@@ -12510,9 +12569,9 @@ var JesusFilmProvider = class {
|
|
|
12510
12569
|
return childrenData._embedded.mediaComponents.map((item) => createFolder(
|
|
12511
12570
|
item.mediaComponentId,
|
|
12512
12571
|
item.title,
|
|
12513
|
-
|
|
12572
|
+
`${pathPrefix}/${item.mediaComponentId}`,
|
|
12514
12573
|
item.imageUrls.mobileCinematicHigh || item.imageUrls.videoStill || item.imageUrls.thumbnail,
|
|
12515
|
-
|
|
12574
|
+
item.containsCount === 0
|
|
12516
12575
|
));
|
|
12517
12576
|
}
|
|
12518
12577
|
extractMuxPlaybackId(url) {
|
|
@@ -12523,10 +12582,13 @@ var JesusFilmProvider = class {
|
|
|
12523
12582
|
const { segments, depth } = parsePath(path);
|
|
12524
12583
|
if (depth < 1) return null;
|
|
12525
12584
|
const category = segments[0];
|
|
12526
|
-
if (depth
|
|
12527
|
-
const
|
|
12528
|
-
|
|
12529
|
-
|
|
12585
|
+
if (depth >= 3) {
|
|
12586
|
+
const lastId = segments[depth - 1];
|
|
12587
|
+
const items = await this.getVideoFile(lastId);
|
|
12588
|
+
const files2 = items.filter((item) => item.type === "file");
|
|
12589
|
+
if (files2.length > 0) return files2;
|
|
12590
|
+
const containerFiles = await this.fetchContainerVideoFiles(lastId);
|
|
12591
|
+
return containerFiles.length > 0 ? containerFiles : null;
|
|
12530
12592
|
}
|
|
12531
12593
|
if (depth === 2) {
|
|
12532
12594
|
if (category === "feature-films") {
|
|
@@ -12542,7 +12604,7 @@ var JesusFilmProvider = class {
|
|
|
12542
12604
|
const data = await this.fetchApi(
|
|
12543
12605
|
`/media-components?filter=master&subTypes=${subType}&languageIds=${LANGUAGE_ID}&limit=100`
|
|
12544
12606
|
);
|
|
12545
|
-
const contentComponents = data._embedded.mediaComponents.filter((item) => item.
|
|
12607
|
+
const contentComponents = data._embedded.mediaComponents.filter((item) => item.containsCount === 0);
|
|
12546
12608
|
const files = await this.fetchVideoFiles(contentComponents);
|
|
12547
12609
|
return files.length > 0 ? files : null;
|
|
12548
12610
|
}
|
|
@@ -12581,7 +12643,14 @@ var JesusFilmProvider = class {
|
|
|
12581
12643
|
`/media-components?ids=${idsParam}&languageIds=${LANGUAGE_ID}`
|
|
12582
12644
|
);
|
|
12583
12645
|
if (!childrenData._embedded?.mediaComponents) return [];
|
|
12584
|
-
|
|
12646
|
+
const contentItems = childrenData._embedded.mediaComponents.filter((c) => c.containsCount === 0);
|
|
12647
|
+
const containerItems = childrenData._embedded.mediaComponents.filter((c) => c.containsCount > 0);
|
|
12648
|
+
const files = await this.fetchVideoFiles(contentItems);
|
|
12649
|
+
for (const container of containerItems) {
|
|
12650
|
+
const nested = await this.fetchContainerVideoFiles(container.mediaComponentId);
|
|
12651
|
+
files.push(...nested);
|
|
12652
|
+
}
|
|
12653
|
+
return files;
|
|
12585
12654
|
}
|
|
12586
12655
|
async buildVideoInstructions(mediaComponentId, category) {
|
|
12587
12656
|
const items = await this.getVideoFile(mediaComponentId);
|
|
@@ -12656,7 +12725,7 @@ var JesusFilmProvider = class {
|
|
|
12656
12725
|
const actionItems = await Promise.all(
|
|
12657
12726
|
data._embedded.mediaComponents.map(async (component) => {
|
|
12658
12727
|
let downloadUrl;
|
|
12659
|
-
if (component.
|
|
12728
|
+
if (component.containsCount === 0) {
|
|
12660
12729
|
try {
|
|
12661
12730
|
const variant = await this.fetchApi(
|
|
12662
12731
|
`/media-components/${component.mediaComponentId}/languages/${LANGUAGE_ID}?platform=web`
|
|
@@ -12694,7 +12763,12 @@ var JesusFilmProvider = class {
|
|
|
12694
12763
|
if (category === "feature-films") return this.buildVideoInstructions(segments[1], category);
|
|
12695
12764
|
return this.buildContainerInstructions(segments[1], category);
|
|
12696
12765
|
}
|
|
12697
|
-
if (depth
|
|
12766
|
+
if (depth >= 3) {
|
|
12767
|
+
const lastId = segments[depth - 1];
|
|
12768
|
+
const videoResult = await this.buildVideoInstructions(lastId, category);
|
|
12769
|
+
if (videoResult) return videoResult;
|
|
12770
|
+
return this.buildContainerInstructions(lastId, category);
|
|
12771
|
+
}
|
|
12698
12772
|
return null;
|
|
12699
12773
|
}
|
|
12700
12774
|
supportsDeviceFlow() {
|