@churchapps/content-providers 0.13.1 → 0.15.0
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 +180 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -1
- package/dist/index.d.ts +95 -1
- package/dist/index.js +179 -117
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
DropboxProvider: () => DropboxProvider,
|
|
30
30
|
FREESHOW_REST_PORT: () => FREESHOW_REST_PORT,
|
|
31
31
|
FreeShowProvider: () => FreeShowProvider,
|
|
32
|
+
GoCurriculumProvider: () => GoCurriculumProvider,
|
|
32
33
|
HighVoltageKidsProvider: () => HighVoltageKidsProvider,
|
|
33
34
|
JesusFilmProvider: () => JesusFilmProvider,
|
|
34
35
|
LessonsChurchProvider: () => LessonsChurchProvider,
|
|
@@ -12794,6 +12795,183 @@ var FreeShowProvider = class extends BaseProvider {
|
|
|
12794
12795
|
}
|
|
12795
12796
|
};
|
|
12796
12797
|
|
|
12798
|
+
// src/providers/goCurriculum/GoCurriculumProvider.ts
|
|
12799
|
+
var GROUPS = [
|
|
12800
|
+
{ id: "elementary", name: "Elementary" },
|
|
12801
|
+
{ id: "preschool", name: "Preschool" }
|
|
12802
|
+
];
|
|
12803
|
+
var CATALOG_TTL_MS = 60 * 60 * 1e3;
|
|
12804
|
+
var SMALL_GROUP = "small-group";
|
|
12805
|
+
function guideAction(item, id, lesson) {
|
|
12806
|
+
const plain = (item.content || "").replace(/\*+/g, "").trim();
|
|
12807
|
+
const label = plain.length > 100 ? plain.slice(0, 100).trimEnd() + "\u2026" : plain;
|
|
12808
|
+
const files = (item.files || []).map((f) => ({
|
|
12809
|
+
id: slugify(f.file),
|
|
12810
|
+
itemType: "file",
|
|
12811
|
+
label: lesson.playlist.find((p) => p.url === f.url)?.title || f.file,
|
|
12812
|
+
seconds: f.seconds,
|
|
12813
|
+
downloadUrl: f.url,
|
|
12814
|
+
mediaType: detectMediaType(`${f.url} ${f.file}`, f.mediaType),
|
|
12815
|
+
thumbnail: f.thumbnail || lesson.thumbnail
|
|
12816
|
+
}));
|
|
12817
|
+
return { id, itemType: "action", actionType: item.type, label, content: item.content !== label ? item.content : void 0, seconds: files[0]?.seconds, children: files.length ? files : void 0 };
|
|
12818
|
+
}
|
|
12819
|
+
function guideToInstructions(name, guide, prefix, lesson) {
|
|
12820
|
+
const items = guide.sections.map((s, i) => ({
|
|
12821
|
+
id: `${prefix}-${i}`,
|
|
12822
|
+
itemType: "section",
|
|
12823
|
+
label: s.name,
|
|
12824
|
+
children: s.items.map((a, j) => guideAction(a, `${prefix}-${i}-${j}`, lesson))
|
|
12825
|
+
}));
|
|
12826
|
+
return { name, items };
|
|
12827
|
+
}
|
|
12828
|
+
async function loadFromFeed(groupId) {
|
|
12829
|
+
let url;
|
|
12830
|
+
try {
|
|
12831
|
+
url = JSON.parse(getProviderSecret("gocurriculumFeeds") || "{}")[groupId];
|
|
12832
|
+
} catch {
|
|
12833
|
+
return null;
|
|
12834
|
+
}
|
|
12835
|
+
if (!url) return null;
|
|
12836
|
+
const response = await fetch(url);
|
|
12837
|
+
return response.ok ? await response.json() : null;
|
|
12838
|
+
}
|
|
12839
|
+
var GoCurriculumProvider = class extends BaseProvider {
|
|
12840
|
+
constructor() {
|
|
12841
|
+
super(...arguments);
|
|
12842
|
+
this.oauthHelper = new OAuthHelper();
|
|
12843
|
+
this.verifiedTokens = /* @__PURE__ */ new Set();
|
|
12844
|
+
this.id = "gocurriculum";
|
|
12845
|
+
this.name = "Go Curriculum";
|
|
12846
|
+
this.logos = {
|
|
12847
|
+
light: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png",
|
|
12848
|
+
dark: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png"
|
|
12849
|
+
};
|
|
12850
|
+
this.config = {
|
|
12851
|
+
id: "gocurriculum",
|
|
12852
|
+
name: "Go Curriculum",
|
|
12853
|
+
apiBase: "https://gocurriculum.com",
|
|
12854
|
+
oauthBase: "https://gocurriculum.com/oauth",
|
|
12855
|
+
clientId: "Rdrvz9jz9nTNf8rCsbpuAgVLdoWHZmcjdmmrP0Bw",
|
|
12856
|
+
// supplied at runtime via setProviderSecret("gocurriculum", ...) — never commit the value
|
|
12857
|
+
get clientSecret() {
|
|
12858
|
+
return getProviderSecret("gocurriculum");
|
|
12859
|
+
},
|
|
12860
|
+
scopes: ["basic"]
|
|
12861
|
+
};
|
|
12862
|
+
this.data = {};
|
|
12863
|
+
this.dataFetchedAt = 0;
|
|
12864
|
+
this.loadCatalog = loadFromFeed;
|
|
12865
|
+
this.requiresAuth = true;
|
|
12866
|
+
this.authTypes = ["oauth_pkce"];
|
|
12867
|
+
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
12868
|
+
}
|
|
12869
|
+
setCatalogLoader(loader) {
|
|
12870
|
+
this.loadCatalog = loader;
|
|
12871
|
+
this.dataFetchedAt = 0;
|
|
12872
|
+
}
|
|
12873
|
+
async getData(groupId, auth) {
|
|
12874
|
+
if (Date.now() - this.dataFetchedAt >= CATALOG_TTL_MS) {
|
|
12875
|
+
await Promise.all(GROUPS.map(async (g) => {
|
|
12876
|
+
try {
|
|
12877
|
+
const data = await this.loadCatalog(g.id, auth);
|
|
12878
|
+
if (data) this.data[g.id] = data;
|
|
12879
|
+
} catch {
|
|
12880
|
+
}
|
|
12881
|
+
}));
|
|
12882
|
+
if (GROUPS.every((g) => this.data[g.id])) this.dataFetchedAt = Date.now();
|
|
12883
|
+
}
|
|
12884
|
+
return this.data[groupId];
|
|
12885
|
+
}
|
|
12886
|
+
async getCollection(segments, auth) {
|
|
12887
|
+
return (await this.getData(segments[0], auth))?.catalog.find((c) => c.id === segments[1]);
|
|
12888
|
+
}
|
|
12889
|
+
// what a server host returns to a device host's setCatalogLoader
|
|
12890
|
+
async getCatalog(groupId, auth) {
|
|
12891
|
+
if (!auth || !await this.verifyAuth(auth)) return null;
|
|
12892
|
+
return await this.getData(groupId, auth) || null;
|
|
12893
|
+
}
|
|
12894
|
+
// ponytail: any valid login unlocks everything for the pilot — per-tier (MemberPress) filtering waits on Go's membership endpoint
|
|
12895
|
+
async verifyAuth(auth) {
|
|
12896
|
+
const token = auth?.access_token;
|
|
12897
|
+
if (!token) return false;
|
|
12898
|
+
if (this.verifiedTokens.has(token)) return true;
|
|
12899
|
+
try {
|
|
12900
|
+
const response = await fetch(`${this.config.oauthBase}/me`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ access_token: token }).toString() });
|
|
12901
|
+
if (!response.ok) return false;
|
|
12902
|
+
this.verifiedTokens.add(token);
|
|
12903
|
+
return true;
|
|
12904
|
+
} catch {
|
|
12905
|
+
return false;
|
|
12906
|
+
}
|
|
12907
|
+
}
|
|
12908
|
+
async browse(path, auth) {
|
|
12909
|
+
if (!auth || !await this.verifyAuth(auth)) return [];
|
|
12910
|
+
const { segments, depth } = parsePath(path);
|
|
12911
|
+
if (depth === 0) return GROUPS.map((g) => createFolder(g.id, g.name, `/${g.id}`));
|
|
12912
|
+
if (depth === 1) return ((await this.getData(segments[0], auth))?.catalog || []).map((c) => createFolder(c.id, c.name, `/${segments[0]}/${c.id}`, c.thumbnail));
|
|
12913
|
+
const collection = await this.getCollection(segments, auth);
|
|
12914
|
+
if (!collection) return [];
|
|
12915
|
+
const base = `/${segments[0]}/${collection.id}`;
|
|
12916
|
+
if (depth === 2) {
|
|
12917
|
+
const lessons = collection.lessons.map((l) => createFolder(l.id, l.name, `${base}/${l.id}`, l.thumbnail || collection.thumbnail, true));
|
|
12918
|
+
return collection.lessons.some((l) => l.smallGroup) ? [createFolder(SMALL_GROUP, "Small Group Guides", `${base}/${SMALL_GROUP}`, collection.thumbnail), ...lessons] : lessons;
|
|
12919
|
+
}
|
|
12920
|
+
if (depth === 3 && segments[2] === SMALL_GROUP) return collection.lessons.filter((l) => l.smallGroup).map((l) => createFolder(l.id, l.name, `${base}/${SMALL_GROUP}/${l.id}`, l.thumbnail || collection.thumbnail, true));
|
|
12921
|
+
if (depth === 3) return this.getLessonFiles(collection, segments[2]);
|
|
12922
|
+
return [];
|
|
12923
|
+
}
|
|
12924
|
+
getLessonFiles(collection, lessonId) {
|
|
12925
|
+
const lesson = collection.lessons.find((l) => l.id === lessonId);
|
|
12926
|
+
if (!lesson) return [];
|
|
12927
|
+
return lesson.playlist.map((f) => createFile(slugify(f.file), f.title, f.url, { mediaType: detectMediaType(`${f.url} ${f.file}`, f.mediaType), thumbnail: f.thumbnail || lesson.thumbnail || collection.thumbnail, seconds: f.duration }));
|
|
12928
|
+
}
|
|
12929
|
+
async getPlaylist(path, auth, _resolution) {
|
|
12930
|
+
if (!auth || !await this.verifyAuth(auth)) return null;
|
|
12931
|
+
const { segments, depth } = parsePath(path);
|
|
12932
|
+
if (depth !== 3) return null;
|
|
12933
|
+
const collection = await this.getCollection(segments, auth);
|
|
12934
|
+
if (!collection) return null;
|
|
12935
|
+
const files = this.getLessonFiles(collection, segments[2]);
|
|
12936
|
+
return files.length > 0 ? files : null;
|
|
12937
|
+
}
|
|
12938
|
+
async getInstructions(path, auth) {
|
|
12939
|
+
if (!auth || !await this.verifyAuth(auth)) return null;
|
|
12940
|
+
const { segments, depth } = parsePath(path);
|
|
12941
|
+
const smallGroup = depth === 4 && segments[2] === SMALL_GROUP;
|
|
12942
|
+
if (depth !== 3 && !smallGroup) return null;
|
|
12943
|
+
const collection = await this.getCollection(segments, auth);
|
|
12944
|
+
const lesson = collection?.lessons.find((l) => l.id === segments[depth - 1]);
|
|
12945
|
+
if (!collection || !lesson) return null;
|
|
12946
|
+
let instructions;
|
|
12947
|
+
if (smallGroup) {
|
|
12948
|
+
if (!lesson.smallGroup?.sections?.length) return null;
|
|
12949
|
+
instructions = guideToInstructions(`${lesson.name} - Small Group`, lesson.smallGroup, "sg", lesson);
|
|
12950
|
+
} else if (lesson.script?.sections?.length) {
|
|
12951
|
+
instructions = guideToInstructions(lesson.name, lesson.script, "lg", lesson);
|
|
12952
|
+
} else {
|
|
12953
|
+
const files = this.getLessonFiles(collection, lesson.id);
|
|
12954
|
+
if (files.length === 0) return null;
|
|
12955
|
+
instructions = filesToInstructions(lesson.name, files);
|
|
12956
|
+
}
|
|
12957
|
+
const downloads = (lesson.resources || []).filter((r) => r.url && !isPlaylistMedia(r.url, void 0, r.file)).map((r) => ({ id: slugify(r.file || r.title), title: r.title || r.file, url: r.url }));
|
|
12958
|
+
if (downloads.length > 0) instructions.downloads = downloads;
|
|
12959
|
+
return instructions;
|
|
12960
|
+
}
|
|
12961
|
+
generateCodeVerifier() {
|
|
12962
|
+
return this.oauthHelper.generateCodeVerifier();
|
|
12963
|
+
}
|
|
12964
|
+
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
12965
|
+
return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
|
|
12966
|
+
}
|
|
12967
|
+
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
12968
|
+
return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
|
|
12969
|
+
}
|
|
12970
|
+
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
12971
|
+
return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
|
|
12972
|
+
}
|
|
12973
|
+
};
|
|
12974
|
+
|
|
12797
12975
|
// src/providers/lifeChurch/data.json
|
|
12798
12976
|
var data_default3 = {
|
|
12799
12977
|
generatedAt: "2026-05-09T20:14:53.089Z",
|
|
@@ -16601,122 +16779,6 @@ function registerProvider(provider) {
|
|
|
16601
16779
|
providerRegistry.set(provider.id, provider);
|
|
16602
16780
|
}
|
|
16603
16781
|
|
|
16604
|
-
// src/providers/goCurriculum/GoCurriculumProvider.ts
|
|
16605
|
-
var FEEDS = [
|
|
16606
|
-
{ id: "elementary", name: "Elementary", url: "https://dl.dropboxusercontent.com/scl/fi/xortbrs2nk49wemscubpu/data.json?rlkey=gnzxyrauhud7xtjlejrs8ysp7" },
|
|
16607
|
-
{ id: "preschool", name: "Preschool", url: "https://dl.dropboxusercontent.com/scl/fi/1cdovbglp5rpfmb9mdg2s/data.json?rlkey=miwsssb0o7i2wdijrdc7jjqcl" }
|
|
16608
|
-
];
|
|
16609
|
-
var CATALOG_TTL_MS = 60 * 60 * 1e3;
|
|
16610
|
-
var GoCurriculumProvider = class extends BaseProvider {
|
|
16611
|
-
constructor() {
|
|
16612
|
-
super(...arguments);
|
|
16613
|
-
this.oauthHelper = new OAuthHelper();
|
|
16614
|
-
this.verifiedTokens = /* @__PURE__ */ new Set();
|
|
16615
|
-
this.id = "gocurriculum";
|
|
16616
|
-
this.name = "Go Curriculum";
|
|
16617
|
-
this.logos = {
|
|
16618
|
-
light: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png",
|
|
16619
|
-
dark: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png"
|
|
16620
|
-
};
|
|
16621
|
-
this.config = {
|
|
16622
|
-
id: "gocurriculum",
|
|
16623
|
-
name: "Go Curriculum",
|
|
16624
|
-
apiBase: "https://gocurriculum.com",
|
|
16625
|
-
oauthBase: "https://gocurriculum.com/oauth",
|
|
16626
|
-
clientId: "Rdrvz9jz9nTNf8rCsbpuAgVLdoWHZmcjdmmrP0Bw",
|
|
16627
|
-
// supplied at runtime via setProviderSecret("gocurriculum", ...) — never commit the value
|
|
16628
|
-
get clientSecret() {
|
|
16629
|
-
return getProviderSecret("gocurriculum");
|
|
16630
|
-
},
|
|
16631
|
-
scopes: ["basic"]
|
|
16632
|
-
};
|
|
16633
|
-
this.data = {};
|
|
16634
|
-
this.dataFetchedAt = 0;
|
|
16635
|
-
this.requiresAuth = true;
|
|
16636
|
-
this.authTypes = ["oauth_pkce"];
|
|
16637
|
-
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
16638
|
-
}
|
|
16639
|
-
async getData(groupId) {
|
|
16640
|
-
if (Date.now() - this.dataFetchedAt >= CATALOG_TTL_MS) {
|
|
16641
|
-
await Promise.all(FEEDS.map(async (f) => {
|
|
16642
|
-
try {
|
|
16643
|
-
const response = await fetch(f.url);
|
|
16644
|
-
if (response.ok) this.data[f.id] = await response.json();
|
|
16645
|
-
} catch {
|
|
16646
|
-
}
|
|
16647
|
-
}));
|
|
16648
|
-
if (FEEDS.every((f) => this.data[f.id])) this.dataFetchedAt = Date.now();
|
|
16649
|
-
}
|
|
16650
|
-
return this.data[groupId];
|
|
16651
|
-
}
|
|
16652
|
-
async getCollection(segments) {
|
|
16653
|
-
return (await this.getData(segments[0]))?.catalog.find((c) => c.id === segments[1]);
|
|
16654
|
-
}
|
|
16655
|
-
// ponytail: any valid login unlocks everything for the pilot — per-tier (MemberPress) filtering waits on Go's membership endpoint
|
|
16656
|
-
async verifyAuth(auth) {
|
|
16657
|
-
const token = auth?.access_token;
|
|
16658
|
-
if (!token) return false;
|
|
16659
|
-
if (this.verifiedTokens.has(token)) return true;
|
|
16660
|
-
try {
|
|
16661
|
-
const response = await fetch(`${this.config.oauthBase}/me`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ access_token: token }).toString() });
|
|
16662
|
-
if (!response.ok) return false;
|
|
16663
|
-
this.verifiedTokens.add(token);
|
|
16664
|
-
return true;
|
|
16665
|
-
} catch {
|
|
16666
|
-
return false;
|
|
16667
|
-
}
|
|
16668
|
-
}
|
|
16669
|
-
async browse(path, auth) {
|
|
16670
|
-
if (!await this.verifyAuth(auth)) return [];
|
|
16671
|
-
const { segments, depth } = parsePath(path);
|
|
16672
|
-
if (depth === 0) return FEEDS.map((f) => createFolder(f.id, f.name, `/${f.id}`));
|
|
16673
|
-
if (depth === 1) return ((await this.getData(segments[0]))?.catalog || []).map((c) => createFolder(c.id, c.name, `/${segments[0]}/${c.id}`, c.thumbnail));
|
|
16674
|
-
const collection = await this.getCollection(segments);
|
|
16675
|
-
if (!collection) return [];
|
|
16676
|
-
if (depth === 2) return collection.lessons.map((l) => createFolder(l.id, l.name, `/${segments[0]}/${collection.id}/${l.id}`, l.thumbnail || collection.thumbnail, true));
|
|
16677
|
-
if (depth === 3) return this.getLessonFiles(collection, segments[2]);
|
|
16678
|
-
return [];
|
|
16679
|
-
}
|
|
16680
|
-
getLessonFiles(collection, lessonId) {
|
|
16681
|
-
const lesson = collection.lessons.find((l) => l.id === lessonId);
|
|
16682
|
-
if (!lesson) return [];
|
|
16683
|
-
return lesson.playlist.map((f) => createFile(slugify(f.file), f.title, f.url, { mediaType: detectMediaType(`${f.url} ${f.file}`, f.mediaType), thumbnail: f.thumbnail || lesson.thumbnail || collection.thumbnail, seconds: f.duration }));
|
|
16684
|
-
}
|
|
16685
|
-
async getPlaylist(path, auth, _resolution) {
|
|
16686
|
-
if (!await this.verifyAuth(auth)) return null;
|
|
16687
|
-
const { segments, depth } = parsePath(path);
|
|
16688
|
-
if (depth !== 3) return null;
|
|
16689
|
-
const collection = await this.getCollection(segments);
|
|
16690
|
-
if (!collection) return null;
|
|
16691
|
-
const files = this.getLessonFiles(collection, segments[2]);
|
|
16692
|
-
return files.length > 0 ? files : null;
|
|
16693
|
-
}
|
|
16694
|
-
async getInstructions(path, auth) {
|
|
16695
|
-
const { segments, depth } = parsePath(path);
|
|
16696
|
-
if (depth !== 3) return null;
|
|
16697
|
-
const files = await this.getPlaylist(path, auth);
|
|
16698
|
-
if (!files) return null;
|
|
16699
|
-
const collection = await this.getCollection(segments);
|
|
16700
|
-
const lesson = collection?.lessons.find((l) => l.id === segments[2]);
|
|
16701
|
-
const instructions = filesToInstructions(lesson?.name || "Lesson", files);
|
|
16702
|
-
const downloads = (lesson?.resources || []).filter((r) => r.url && !isPlaylistMedia(r.url, void 0, r.file)).map((r) => ({ id: slugify(r.file || r.title), title: r.title || r.file, url: r.url }));
|
|
16703
|
-
if (downloads.length > 0) instructions.downloads = downloads;
|
|
16704
|
-
return instructions;
|
|
16705
|
-
}
|
|
16706
|
-
generateCodeVerifier() {
|
|
16707
|
-
return this.oauthHelper.generateCodeVerifier();
|
|
16708
|
-
}
|
|
16709
|
-
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
16710
|
-
return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
|
|
16711
|
-
}
|
|
16712
|
-
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
16713
|
-
return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
|
|
16714
|
-
}
|
|
16715
|
-
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
16716
|
-
return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
|
|
16717
|
-
}
|
|
16718
|
-
};
|
|
16719
|
-
|
|
16720
16782
|
// src/providers/googledrive/GoogleDriveProvider.ts
|
|
16721
16783
|
var FOLDER_MIME = "application/vnd.google-apps.folder";
|
|
16722
16784
|
var MAX_PAGINATION_CALLS2 = 10;
|
|
@@ -17061,7 +17123,7 @@ function getAvailableProviders(ids) {
|
|
|
17061
17123
|
}
|
|
17062
17124
|
|
|
17063
17125
|
// src/index.ts
|
|
17064
|
-
var VERSION = true ? "0.
|
|
17126
|
+
var VERSION = true ? "0.15.0" : "dev";
|
|
17065
17127
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17066
17128
|
0 && (module.exports = {
|
|
17067
17129
|
APlayProvider,
|
|
@@ -17073,6 +17135,7 @@ var VERSION = true ? "0.13.1" : "dev";
|
|
|
17073
17135
|
DropboxProvider,
|
|
17074
17136
|
FREESHOW_REST_PORT,
|
|
17075
17137
|
FreeShowProvider,
|
|
17138
|
+
GoCurriculumProvider,
|
|
17076
17139
|
HighVoltageKidsProvider,
|
|
17077
17140
|
JesusFilmProvider,
|
|
17078
17141
|
LessonsChurchProvider,
|