@churchapps/content-providers 0.9.1 → 0.9.3
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 +51 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +51 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -71,13 +71,15 @@ function navigateToPath(instructions, path) {
|
|
|
71
71
|
|
|
72
72
|
// src/helpers/TokenHelper.ts
|
|
73
73
|
function toAuthData(data, fallbacks) {
|
|
74
|
+
const planTypeId = data.plan_type_id || fallbacks?.planTypeId;
|
|
74
75
|
return {
|
|
75
76
|
access_token: data.access_token,
|
|
76
77
|
refresh_token: data.refresh_token || fallbacks?.refreshToken || "",
|
|
77
78
|
token_type: data.token_type || "Bearer",
|
|
78
79
|
created_at: Math.floor(Date.now() / 1e3),
|
|
79
80
|
expires_in: data.expires_in,
|
|
80
|
-
scope: data.scope || fallbacks?.scope || ""
|
|
81
|
+
scope: data.scope || fallbacks?.scope || "",
|
|
82
|
+
...planTypeId ? { planTypeId } : {}
|
|
81
83
|
};
|
|
82
84
|
}
|
|
83
85
|
var TokenHelper = class {
|
|
@@ -105,7 +107,8 @@ var TokenHelper = class {
|
|
|
105
107
|
return null;
|
|
106
108
|
}
|
|
107
109
|
const data = await response.json();
|
|
108
|
-
|
|
110
|
+
const planTypeId = auth.planTypeId;
|
|
111
|
+
return toAuthData(data, { refreshToken: auth.refresh_token, scope: auth.scope, planTypeId });
|
|
109
112
|
} catch {
|
|
110
113
|
return null;
|
|
111
114
|
}
|
|
@@ -242,7 +245,8 @@ var ApiHelper = class {
|
|
|
242
245
|
const options = { method, headers, ...body ? { body: JSON.stringify(body) } : {} };
|
|
243
246
|
const response = await fetch(url, options);
|
|
244
247
|
if (!response.ok) {
|
|
245
|
-
|
|
248
|
+
const detail = await response.text().catch(() => "");
|
|
249
|
+
console.warn(`[${providerId}] apiRequest failed: ${method} ${url} \u2192 HTTP ${response.status} ${response.statusText}${detail ? ` ${detail.slice(0, 500)}` : ""}`);
|
|
246
250
|
return null;
|
|
247
251
|
}
|
|
248
252
|
return await response.json();
|
|
@@ -303,16 +307,19 @@ var IMAGE_EXTENSIONS = [
|
|
|
303
307
|
".tiff",
|
|
304
308
|
".tif"
|
|
305
309
|
];
|
|
310
|
+
var AUDIO_EXTENSIONS = [".mp3", ".m4a", ".aac", ".wav", ".flac", ".oga"];
|
|
306
311
|
function detectMediaType(url, explicitType) {
|
|
307
312
|
if (explicitType === "video" || explicitType?.startsWith("video/")) return "video";
|
|
308
313
|
if (explicitType === "image" || explicitType?.startsWith("image/")) return "image";
|
|
314
|
+
if (explicitType === "audio" || explicitType?.startsWith("audio/")) return "audio";
|
|
309
315
|
const lower = url.toLowerCase();
|
|
310
316
|
if (VIDEO_EXTENSIONS.some((p) => lower.includes(p)) || lower.includes("stream.mux.com")) return "video";
|
|
317
|
+
if (AUDIO_EXTENSIONS.some((p) => lower.includes(p))) return "audio";
|
|
311
318
|
return "image";
|
|
312
319
|
}
|
|
313
320
|
function isMediaFile(filename) {
|
|
314
321
|
const lower = filename.toLowerCase();
|
|
315
|
-
return [...VIDEO_EXTENSIONS, ...IMAGE_EXTENSIONS].some((ext) => lower.endsWith(ext));
|
|
322
|
+
return [...VIDEO_EXTENSIONS, ...IMAGE_EXTENSIONS, ...AUDIO_EXTENSIONS].some((ext) => lower.endsWith(ext));
|
|
316
323
|
}
|
|
317
324
|
function createFolder(id, title, path, thumbnail, isLeaf) {
|
|
318
325
|
return { type: "folder", id, title, path, thumbnail, isLeaf };
|
|
@@ -592,13 +599,45 @@ var SignPresenterProvider = class extends BaseProvider {
|
|
|
592
599
|
isLeaf: true
|
|
593
600
|
}));
|
|
594
601
|
}
|
|
602
|
+
/** image and video/stream slides play directly; web slides only when the url is itself a media file. html/pdf/multi_zone and generic web pages aren't playable in ChurchApps. */
|
|
603
|
+
slideMediaType(slideType, url) {
|
|
604
|
+
if (slideType === "image") return "image";
|
|
605
|
+
if (slideType === "video" || slideType === "stream") return "video";
|
|
606
|
+
if (slideType === "web" && isMediaFile(url)) return detectMediaType(url);
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
/** The documented player contract; /content/playlists/:id/messages only covers templates 1 and 3 so most playlists come back empty there. */
|
|
595
610
|
async getMessages(playlistId, auth) {
|
|
611
|
+
const response = await this.apiRequest(`/v2/playlists/${playlistId}`, auth);
|
|
612
|
+
const messages = this.extractList(response, "messages");
|
|
613
|
+
if (messages.length === 0) return this.getLegacyMessages(playlistId, auth);
|
|
614
|
+
const files = [];
|
|
615
|
+
messages.forEach((msg, messageIndex) => {
|
|
616
|
+
const slides = Array.isArray(msg.slides) ? msg.slides : [];
|
|
617
|
+
slides.forEach((slide, slideIndex) => {
|
|
618
|
+
const data = slide.data || {};
|
|
619
|
+
const url = typeof data.url === "string" ? data.url.trim() : "";
|
|
620
|
+
const mediaType = url ? this.slideMediaType(slide.type, url) : null;
|
|
621
|
+
if (!mediaType) return;
|
|
622
|
+
const file = createFile(`${playlistId}-${messageIndex}-${slideIndex}`, msg.name, url, {
|
|
623
|
+
mediaType,
|
|
624
|
+
thumbnail: msg.thumbnail,
|
|
625
|
+
seconds: slide.seconds,
|
|
626
|
+
loop: data.loop
|
|
627
|
+
});
|
|
628
|
+
file.downloadUrl = url;
|
|
629
|
+
files.push(file);
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
return files;
|
|
633
|
+
}
|
|
634
|
+
async getLegacyMessages(playlistId, auth) {
|
|
596
635
|
const response = await this.apiRequest(`/content/playlists/${playlistId}/messages`, auth);
|
|
597
636
|
if (!response) return [];
|
|
598
637
|
const files = [];
|
|
599
638
|
for (const msg of this.extractList(response, "messages")) {
|
|
600
|
-
|
|
601
|
-
|
|
639
|
+
const url = [msg.url, msg.thumbnail, msg.image].map((v) => typeof v === "string" ? v.trim() : "").find(Boolean) || "";
|
|
640
|
+
if (!url) continue;
|
|
602
641
|
const file = createFile(msg.id, msg.name, url, {
|
|
603
642
|
mediaType: detectMediaType(url, msg.mediaType),
|
|
604
643
|
thumbnail: msg.thumbnail || msg.image,
|
|
@@ -1447,9 +1486,7 @@ var B1ChurchProvider = class extends BaseProvider {
|
|
|
1447
1486
|
setPairingData(data) {
|
|
1448
1487
|
if (data && typeof data === "object" && "planTypeId" in data) {
|
|
1449
1488
|
const planTypeId = data.planTypeId;
|
|
1450
|
-
|
|
1451
|
-
} else {
|
|
1452
|
-
this.planTypeId = null;
|
|
1489
|
+
if (typeof planTypeId === "string") this.planTypeId = planTypeId;
|
|
1453
1490
|
}
|
|
1454
1491
|
}
|
|
1455
1492
|
async getCurrentPlan(authData) {
|
|
@@ -17812,7 +17849,9 @@ var GoogleDriveProvider = class extends BaseProvider {
|
|
|
17812
17849
|
orderBy: "folder,name_natural",
|
|
17813
17850
|
pageSize: "1000",
|
|
17814
17851
|
supportsAllDrives: "true",
|
|
17815
|
-
includeItemsFromAllDrives
|
|
17852
|
+
// corpora=user (not includeItemsFromAllDrives) — "root" is only meaningful in the user's own corpus, and
|
|
17853
|
+
// combining it with an all-drives search makes Google reject the query, which browse saw as an empty folder.
|
|
17854
|
+
corpora: "user"
|
|
17816
17855
|
});
|
|
17817
17856
|
if (pageToken) params.set("pageToken", pageToken);
|
|
17818
17857
|
const response = await this.apiRequest(`/files?${params.toString()}`, auth);
|
|
@@ -17826,7 +17865,7 @@ var GoogleDriveProvider = class extends BaseProvider {
|
|
|
17826
17865
|
async childItems(folderId, auth) {
|
|
17827
17866
|
const entries = await this.listFiles(`'${folderId}' in parents and trashed=false`, auth);
|
|
17828
17867
|
const folders = entries.filter((e) => e.mimeType === FOLDER_MIME);
|
|
17829
|
-
const mediaFiles = entries.filter((e) => e.mimeType.startsWith("video/")
|
|
17868
|
+
const mediaFiles = entries.filter((e) => e.mimeType !== FOLDER_MIME && !e.mimeType.startsWith("application/vnd.google-apps") && (["video/", "image/", "audio/"].some((prefix) => e.mimeType.startsWith(prefix)) || isMediaFile(e.name)));
|
|
17830
17869
|
return { folders, mediaFiles };
|
|
17831
17870
|
}
|
|
17832
17871
|
/** One batched query marks which sibling folders have subfolders; null = unknown (isLeaf omitted). */
|
|
@@ -17983,7 +18022,7 @@ function getAvailableProviders(ids) {
|
|
|
17983
18022
|
}
|
|
17984
18023
|
|
|
17985
18024
|
// src/index.ts
|
|
17986
|
-
var VERSION = true ? "0.9.
|
|
18025
|
+
var VERSION = true ? "0.9.3" : "dev";
|
|
17987
18026
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17988
18027
|
0 && (module.exports = {
|
|
17989
18028
|
APlayProvider,
|