@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.d.cts
CHANGED
|
@@ -610,6 +610,100 @@ declare function servicesToInstances(services: MdnsService[], port?: number): Pr
|
|
|
610
610
|
declare function networkInstanceToAuth(instance: NetworkInstance): ContentProviderAuthData;
|
|
611
611
|
declare function authToNetworkInstance(auth?: ContentProviderAuthData | null): NetworkInstance | null;
|
|
612
612
|
|
|
613
|
+
interface GoCurriculumPlaylistItem {
|
|
614
|
+
title: string;
|
|
615
|
+
file: string;
|
|
616
|
+
url: string;
|
|
617
|
+
mediaType?: string;
|
|
618
|
+
duration?: number;
|
|
619
|
+
thumbnail?: string;
|
|
620
|
+
shareUrl?: string;
|
|
621
|
+
}
|
|
622
|
+
interface GoCurriculumResource {
|
|
623
|
+
title: string;
|
|
624
|
+
file: string;
|
|
625
|
+
url: string;
|
|
626
|
+
shareUrl?: string;
|
|
627
|
+
}
|
|
628
|
+
interface GoCurriculumGuideFile {
|
|
629
|
+
file: string;
|
|
630
|
+
url: string;
|
|
631
|
+
mediaType?: string;
|
|
632
|
+
thumbnail?: string;
|
|
633
|
+
seconds?: number;
|
|
634
|
+
}
|
|
635
|
+
interface GoCurriculumGuideItem {
|
|
636
|
+
type: string;
|
|
637
|
+
content: string;
|
|
638
|
+
files?: GoCurriculumGuideFile[];
|
|
639
|
+
}
|
|
640
|
+
interface GoCurriculumGuideSection {
|
|
641
|
+
name: string;
|
|
642
|
+
role?: string;
|
|
643
|
+
items: GoCurriculumGuideItem[];
|
|
644
|
+
}
|
|
645
|
+
interface GoCurriculumGuide {
|
|
646
|
+
source?: string;
|
|
647
|
+
sections: GoCurriculumGuideSection[];
|
|
648
|
+
}
|
|
649
|
+
interface GoCurriculumLesson {
|
|
650
|
+
id: string;
|
|
651
|
+
name: string;
|
|
652
|
+
thumbnail?: string;
|
|
653
|
+
bigIdea?: string;
|
|
654
|
+
bibleBasis?: string;
|
|
655
|
+
keyVerse?: string;
|
|
656
|
+
playlist: GoCurriculumPlaylistItem[];
|
|
657
|
+
resources?: GoCurriculumResource[];
|
|
658
|
+
script?: GoCurriculumGuide;
|
|
659
|
+
smallGroup?: GoCurriculumGuide;
|
|
660
|
+
}
|
|
661
|
+
interface GoCurriculumCollection {
|
|
662
|
+
id: string;
|
|
663
|
+
name: string;
|
|
664
|
+
thumbnail?: string;
|
|
665
|
+
lessons: GoCurriculumLesson[];
|
|
666
|
+
}
|
|
667
|
+
interface GoCurriculumData {
|
|
668
|
+
generatedAt?: string;
|
|
669
|
+
provider?: {
|
|
670
|
+
name?: string;
|
|
671
|
+
};
|
|
672
|
+
catalog: GoCurriculumCollection[];
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
type GoCurriculumCatalogLoader = (groupId: string, auth: ContentProviderAuthData) => Promise<GoCurriculumData | null>;
|
|
676
|
+
declare class GoCurriculumProvider extends BaseProvider {
|
|
677
|
+
private readonly oauthHelper;
|
|
678
|
+
private readonly verifiedTokens;
|
|
679
|
+
readonly id = "gocurriculum";
|
|
680
|
+
readonly name = "Go Curriculum";
|
|
681
|
+
readonly logos: ProviderLogos;
|
|
682
|
+
readonly config: ContentProviderConfig;
|
|
683
|
+
private data;
|
|
684
|
+
private dataFetchedAt;
|
|
685
|
+
private loadCatalog;
|
|
686
|
+
setCatalogLoader(loader: GoCurriculumCatalogLoader): void;
|
|
687
|
+
private getData;
|
|
688
|
+
private getCollection;
|
|
689
|
+
getCatalog(groupId: string, auth?: ContentProviderAuthData | null): Promise<GoCurriculumData | null>;
|
|
690
|
+
readonly requiresAuth = true;
|
|
691
|
+
readonly authTypes: AuthType[];
|
|
692
|
+
readonly capabilities: ProviderCapabilities;
|
|
693
|
+
private verifyAuth;
|
|
694
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
695
|
+
private getLessonFiles;
|
|
696
|
+
getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
697
|
+
getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
698
|
+
generateCodeVerifier(): string;
|
|
699
|
+
buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
700
|
+
url: string;
|
|
701
|
+
challengeMethod: string;
|
|
702
|
+
}>;
|
|
703
|
+
buildAuthUrlFromChallenge(codeChallenge: string, redirectUri: string, state: string): string;
|
|
704
|
+
exchangeCodeForTokens(code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
|
|
705
|
+
}
|
|
706
|
+
|
|
613
707
|
/** Browses Life.Church's kids curriculum from a static catalog (series → units → lessons), plus a weekly scheduled lesson index. */
|
|
614
708
|
declare class LifeChurchProvider extends BaseProvider {
|
|
615
709
|
readonly id = "lifechurch";
|
|
@@ -653,4 +747,4 @@ declare function getAvailableProviders(ids?: string[]): ProviderInfo[];
|
|
|
653
747
|
*/
|
|
654
748
|
declare const VERSION: string;
|
|
655
749
|
|
|
656
|
-
export { APlayProvider, type AuthType, B1ChurchProvider, BaseProvider, BibleProjectProvider, CbnProvider, type ContentDownload, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, FREESHOW_REST_PORT, type FeedActionInterface, type FeedDownloadInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, type FreeShowDiscoverer, FreeShowProvider, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MdnsService, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, type NetworkInstance, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, authIsExpired, authToNetworkInstance, servicesToInstances as freeShowServicesToInstances, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, networkInstanceToAuth, registerProvider, setProviderSecret, toAuthData };
|
|
750
|
+
export { APlayProvider, type AuthType, B1ChurchProvider, BaseProvider, BibleProjectProvider, CbnProvider, type ContentDownload, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, FREESHOW_REST_PORT, type FeedActionInterface, type FeedDownloadInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, type FreeShowDiscoverer, FreeShowProvider, type GoCurriculumCatalogLoader, type GoCurriculumData, GoCurriculumProvider, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MdnsService, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, type NetworkInstance, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, authIsExpired, authToNetworkInstance, servicesToInstances as freeShowServicesToInstances, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, networkInstanceToAuth, registerProvider, setProviderSecret, toAuthData };
|
package/dist/index.d.ts
CHANGED
|
@@ -610,6 +610,100 @@ declare function servicesToInstances(services: MdnsService[], port?: number): Pr
|
|
|
610
610
|
declare function networkInstanceToAuth(instance: NetworkInstance): ContentProviderAuthData;
|
|
611
611
|
declare function authToNetworkInstance(auth?: ContentProviderAuthData | null): NetworkInstance | null;
|
|
612
612
|
|
|
613
|
+
interface GoCurriculumPlaylistItem {
|
|
614
|
+
title: string;
|
|
615
|
+
file: string;
|
|
616
|
+
url: string;
|
|
617
|
+
mediaType?: string;
|
|
618
|
+
duration?: number;
|
|
619
|
+
thumbnail?: string;
|
|
620
|
+
shareUrl?: string;
|
|
621
|
+
}
|
|
622
|
+
interface GoCurriculumResource {
|
|
623
|
+
title: string;
|
|
624
|
+
file: string;
|
|
625
|
+
url: string;
|
|
626
|
+
shareUrl?: string;
|
|
627
|
+
}
|
|
628
|
+
interface GoCurriculumGuideFile {
|
|
629
|
+
file: string;
|
|
630
|
+
url: string;
|
|
631
|
+
mediaType?: string;
|
|
632
|
+
thumbnail?: string;
|
|
633
|
+
seconds?: number;
|
|
634
|
+
}
|
|
635
|
+
interface GoCurriculumGuideItem {
|
|
636
|
+
type: string;
|
|
637
|
+
content: string;
|
|
638
|
+
files?: GoCurriculumGuideFile[];
|
|
639
|
+
}
|
|
640
|
+
interface GoCurriculumGuideSection {
|
|
641
|
+
name: string;
|
|
642
|
+
role?: string;
|
|
643
|
+
items: GoCurriculumGuideItem[];
|
|
644
|
+
}
|
|
645
|
+
interface GoCurriculumGuide {
|
|
646
|
+
source?: string;
|
|
647
|
+
sections: GoCurriculumGuideSection[];
|
|
648
|
+
}
|
|
649
|
+
interface GoCurriculumLesson {
|
|
650
|
+
id: string;
|
|
651
|
+
name: string;
|
|
652
|
+
thumbnail?: string;
|
|
653
|
+
bigIdea?: string;
|
|
654
|
+
bibleBasis?: string;
|
|
655
|
+
keyVerse?: string;
|
|
656
|
+
playlist: GoCurriculumPlaylistItem[];
|
|
657
|
+
resources?: GoCurriculumResource[];
|
|
658
|
+
script?: GoCurriculumGuide;
|
|
659
|
+
smallGroup?: GoCurriculumGuide;
|
|
660
|
+
}
|
|
661
|
+
interface GoCurriculumCollection {
|
|
662
|
+
id: string;
|
|
663
|
+
name: string;
|
|
664
|
+
thumbnail?: string;
|
|
665
|
+
lessons: GoCurriculumLesson[];
|
|
666
|
+
}
|
|
667
|
+
interface GoCurriculumData {
|
|
668
|
+
generatedAt?: string;
|
|
669
|
+
provider?: {
|
|
670
|
+
name?: string;
|
|
671
|
+
};
|
|
672
|
+
catalog: GoCurriculumCollection[];
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
type GoCurriculumCatalogLoader = (groupId: string, auth: ContentProviderAuthData) => Promise<GoCurriculumData | null>;
|
|
676
|
+
declare class GoCurriculumProvider extends BaseProvider {
|
|
677
|
+
private readonly oauthHelper;
|
|
678
|
+
private readonly verifiedTokens;
|
|
679
|
+
readonly id = "gocurriculum";
|
|
680
|
+
readonly name = "Go Curriculum";
|
|
681
|
+
readonly logos: ProviderLogos;
|
|
682
|
+
readonly config: ContentProviderConfig;
|
|
683
|
+
private data;
|
|
684
|
+
private dataFetchedAt;
|
|
685
|
+
private loadCatalog;
|
|
686
|
+
setCatalogLoader(loader: GoCurriculumCatalogLoader): void;
|
|
687
|
+
private getData;
|
|
688
|
+
private getCollection;
|
|
689
|
+
getCatalog(groupId: string, auth?: ContentProviderAuthData | null): Promise<GoCurriculumData | null>;
|
|
690
|
+
readonly requiresAuth = true;
|
|
691
|
+
readonly authTypes: AuthType[];
|
|
692
|
+
readonly capabilities: ProviderCapabilities;
|
|
693
|
+
private verifyAuth;
|
|
694
|
+
browse(path?: string | null, auth?: ContentProviderAuthData | null): Promise<ContentItem[]>;
|
|
695
|
+
private getLessonFiles;
|
|
696
|
+
getPlaylist(path: string, auth?: ContentProviderAuthData | null, _resolution?: number): Promise<ContentFile[] | null>;
|
|
697
|
+
getInstructions(path: string, auth?: ContentProviderAuthData | null): Promise<Instructions | null>;
|
|
698
|
+
generateCodeVerifier(): string;
|
|
699
|
+
buildAuthUrl(codeVerifier: string, redirectUri: string, state?: string): Promise<{
|
|
700
|
+
url: string;
|
|
701
|
+
challengeMethod: string;
|
|
702
|
+
}>;
|
|
703
|
+
buildAuthUrlFromChallenge(codeChallenge: string, redirectUri: string, state: string): string;
|
|
704
|
+
exchangeCodeForTokens(code: string, codeVerifier: string, redirectUri: string): Promise<ContentProviderAuthData | null>;
|
|
705
|
+
}
|
|
706
|
+
|
|
613
707
|
/** Browses Life.Church's kids curriculum from a static catalog (series → units → lessons), plus a weekly scheduled lesson index. */
|
|
614
708
|
declare class LifeChurchProvider extends BaseProvider {
|
|
615
709
|
readonly id = "lifechurch";
|
|
@@ -653,4 +747,4 @@ declare function getAvailableProviders(ids?: string[]): ProviderInfo[];
|
|
|
653
747
|
*/
|
|
654
748
|
declare const VERSION: string;
|
|
655
749
|
|
|
656
|
-
export { APlayProvider, type AuthType, B1ChurchProvider, BaseProvider, BibleProjectProvider, CbnProvider, type ContentDownload, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, FREESHOW_REST_PORT, type FeedActionInterface, type FeedDownloadInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, type FreeShowDiscoverer, FreeShowProvider, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MdnsService, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, type NetworkInstance, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, authIsExpired, authToNetworkInstance, servicesToInstances as freeShowServicesToInstances, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, networkInstanceToAuth, registerProvider, setProviderSecret, toAuthData };
|
|
750
|
+
export { APlayProvider, type AuthType, B1ChurchProvider, BaseProvider, BibleProjectProvider, CbnProvider, type ContentDownload, type ContentFile, type ContentFolder, type ContentItem, type ContentProviderAuthData, type ContentProviderConfig, type CurrentPlan, type DeviceAuthorizationResponse, DeviceFlowHelper, type DeviceFlowPollResult, type DeviceFlowState, DropboxProvider, type EndpointValue, type EndpointsConfig, FREESHOW_REST_PORT, type FeedActionInterface, type FeedDownloadInterface, type FeedFileInterface, type FeedSectionInterface, type FeedVenueInterface, type FreeShowDiscoverer, FreeShowProvider, type GoCurriculumCatalogLoader, type GoCurriculumData, GoCurriculumProvider, HighVoltageKidsProvider, type IProvider, type InstructionItem, type Instructions, JesusFilmProvider, LessonsChurchProvider, LifeChurchProvider, type MdnsService, type MediaLicenseResult, type MediaLicenseStatus, type MessageFileInterface, type NetworkInstance, OAuthHelper, type Plan, type PlanPresentation, type PlanSection, type PlanTimelineItem, PlanningCenterProvider, type ProviderCapabilities, type ProviderInfo, type ProviderLogos, SignPresenterProvider, TokenHelper, VERSION, type VenueActionInterface, type VenueActionsResponseInterface, type VenueSectionActionsInterface, authIsExpired, authToNetworkInstance, servicesToInstances as freeShowServicesToInstances, getAllProviders, getAvailableProviders, getProvider, getProviderConfig, isContentFile, isContentFolder, navigateToPath, networkInstanceToAuth, registerProvider, setProviderSecret, toAuthData };
|
package/dist/index.js
CHANGED
|
@@ -12737,6 +12737,183 @@ var FreeShowProvider = class extends BaseProvider {
|
|
|
12737
12737
|
}
|
|
12738
12738
|
};
|
|
12739
12739
|
|
|
12740
|
+
// src/providers/goCurriculum/GoCurriculumProvider.ts
|
|
12741
|
+
var GROUPS = [
|
|
12742
|
+
{ id: "elementary", name: "Elementary" },
|
|
12743
|
+
{ id: "preschool", name: "Preschool" }
|
|
12744
|
+
];
|
|
12745
|
+
var CATALOG_TTL_MS = 60 * 60 * 1e3;
|
|
12746
|
+
var SMALL_GROUP = "small-group";
|
|
12747
|
+
function guideAction(item, id, lesson) {
|
|
12748
|
+
const plain = (item.content || "").replace(/\*+/g, "").trim();
|
|
12749
|
+
const label = plain.length > 100 ? plain.slice(0, 100).trimEnd() + "\u2026" : plain;
|
|
12750
|
+
const files = (item.files || []).map((f) => ({
|
|
12751
|
+
id: slugify(f.file),
|
|
12752
|
+
itemType: "file",
|
|
12753
|
+
label: lesson.playlist.find((p) => p.url === f.url)?.title || f.file,
|
|
12754
|
+
seconds: f.seconds,
|
|
12755
|
+
downloadUrl: f.url,
|
|
12756
|
+
mediaType: detectMediaType(`${f.url} ${f.file}`, f.mediaType),
|
|
12757
|
+
thumbnail: f.thumbnail || lesson.thumbnail
|
|
12758
|
+
}));
|
|
12759
|
+
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 };
|
|
12760
|
+
}
|
|
12761
|
+
function guideToInstructions(name, guide, prefix, lesson) {
|
|
12762
|
+
const items = guide.sections.map((s, i) => ({
|
|
12763
|
+
id: `${prefix}-${i}`,
|
|
12764
|
+
itemType: "section",
|
|
12765
|
+
label: s.name,
|
|
12766
|
+
children: s.items.map((a, j) => guideAction(a, `${prefix}-${i}-${j}`, lesson))
|
|
12767
|
+
}));
|
|
12768
|
+
return { name, items };
|
|
12769
|
+
}
|
|
12770
|
+
async function loadFromFeed(groupId) {
|
|
12771
|
+
let url;
|
|
12772
|
+
try {
|
|
12773
|
+
url = JSON.parse(getProviderSecret("gocurriculumFeeds") || "{}")[groupId];
|
|
12774
|
+
} catch {
|
|
12775
|
+
return null;
|
|
12776
|
+
}
|
|
12777
|
+
if (!url) return null;
|
|
12778
|
+
const response = await fetch(url);
|
|
12779
|
+
return response.ok ? await response.json() : null;
|
|
12780
|
+
}
|
|
12781
|
+
var GoCurriculumProvider = class extends BaseProvider {
|
|
12782
|
+
constructor() {
|
|
12783
|
+
super(...arguments);
|
|
12784
|
+
this.oauthHelper = new OAuthHelper();
|
|
12785
|
+
this.verifiedTokens = /* @__PURE__ */ new Set();
|
|
12786
|
+
this.id = "gocurriculum";
|
|
12787
|
+
this.name = "Go Curriculum";
|
|
12788
|
+
this.logos = {
|
|
12789
|
+
light: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png",
|
|
12790
|
+
dark: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png"
|
|
12791
|
+
};
|
|
12792
|
+
this.config = {
|
|
12793
|
+
id: "gocurriculum",
|
|
12794
|
+
name: "Go Curriculum",
|
|
12795
|
+
apiBase: "https://gocurriculum.com",
|
|
12796
|
+
oauthBase: "https://gocurriculum.com/oauth",
|
|
12797
|
+
clientId: "Rdrvz9jz9nTNf8rCsbpuAgVLdoWHZmcjdmmrP0Bw",
|
|
12798
|
+
// supplied at runtime via setProviderSecret("gocurriculum", ...) — never commit the value
|
|
12799
|
+
get clientSecret() {
|
|
12800
|
+
return getProviderSecret("gocurriculum");
|
|
12801
|
+
},
|
|
12802
|
+
scopes: ["basic"]
|
|
12803
|
+
};
|
|
12804
|
+
this.data = {};
|
|
12805
|
+
this.dataFetchedAt = 0;
|
|
12806
|
+
this.loadCatalog = loadFromFeed;
|
|
12807
|
+
this.requiresAuth = true;
|
|
12808
|
+
this.authTypes = ["oauth_pkce"];
|
|
12809
|
+
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
12810
|
+
}
|
|
12811
|
+
setCatalogLoader(loader) {
|
|
12812
|
+
this.loadCatalog = loader;
|
|
12813
|
+
this.dataFetchedAt = 0;
|
|
12814
|
+
}
|
|
12815
|
+
async getData(groupId, auth) {
|
|
12816
|
+
if (Date.now() - this.dataFetchedAt >= CATALOG_TTL_MS) {
|
|
12817
|
+
await Promise.all(GROUPS.map(async (g) => {
|
|
12818
|
+
try {
|
|
12819
|
+
const data = await this.loadCatalog(g.id, auth);
|
|
12820
|
+
if (data) this.data[g.id] = data;
|
|
12821
|
+
} catch {
|
|
12822
|
+
}
|
|
12823
|
+
}));
|
|
12824
|
+
if (GROUPS.every((g) => this.data[g.id])) this.dataFetchedAt = Date.now();
|
|
12825
|
+
}
|
|
12826
|
+
return this.data[groupId];
|
|
12827
|
+
}
|
|
12828
|
+
async getCollection(segments, auth) {
|
|
12829
|
+
return (await this.getData(segments[0], auth))?.catalog.find((c) => c.id === segments[1]);
|
|
12830
|
+
}
|
|
12831
|
+
// what a server host returns to a device host's setCatalogLoader
|
|
12832
|
+
async getCatalog(groupId, auth) {
|
|
12833
|
+
if (!auth || !await this.verifyAuth(auth)) return null;
|
|
12834
|
+
return await this.getData(groupId, auth) || null;
|
|
12835
|
+
}
|
|
12836
|
+
// ponytail: any valid login unlocks everything for the pilot — per-tier (MemberPress) filtering waits on Go's membership endpoint
|
|
12837
|
+
async verifyAuth(auth) {
|
|
12838
|
+
const token = auth?.access_token;
|
|
12839
|
+
if (!token) return false;
|
|
12840
|
+
if (this.verifiedTokens.has(token)) return true;
|
|
12841
|
+
try {
|
|
12842
|
+
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() });
|
|
12843
|
+
if (!response.ok) return false;
|
|
12844
|
+
this.verifiedTokens.add(token);
|
|
12845
|
+
return true;
|
|
12846
|
+
} catch {
|
|
12847
|
+
return false;
|
|
12848
|
+
}
|
|
12849
|
+
}
|
|
12850
|
+
async browse(path, auth) {
|
|
12851
|
+
if (!auth || !await this.verifyAuth(auth)) return [];
|
|
12852
|
+
const { segments, depth } = parsePath(path);
|
|
12853
|
+
if (depth === 0) return GROUPS.map((g) => createFolder(g.id, g.name, `/${g.id}`));
|
|
12854
|
+
if (depth === 1) return ((await this.getData(segments[0], auth))?.catalog || []).map((c) => createFolder(c.id, c.name, `/${segments[0]}/${c.id}`, c.thumbnail));
|
|
12855
|
+
const collection = await this.getCollection(segments, auth);
|
|
12856
|
+
if (!collection) return [];
|
|
12857
|
+
const base = `/${segments[0]}/${collection.id}`;
|
|
12858
|
+
if (depth === 2) {
|
|
12859
|
+
const lessons = collection.lessons.map((l) => createFolder(l.id, l.name, `${base}/${l.id}`, l.thumbnail || collection.thumbnail, true));
|
|
12860
|
+
return collection.lessons.some((l) => l.smallGroup) ? [createFolder(SMALL_GROUP, "Small Group Guides", `${base}/${SMALL_GROUP}`, collection.thumbnail), ...lessons] : lessons;
|
|
12861
|
+
}
|
|
12862
|
+
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));
|
|
12863
|
+
if (depth === 3) return this.getLessonFiles(collection, segments[2]);
|
|
12864
|
+
return [];
|
|
12865
|
+
}
|
|
12866
|
+
getLessonFiles(collection, lessonId) {
|
|
12867
|
+
const lesson = collection.lessons.find((l) => l.id === lessonId);
|
|
12868
|
+
if (!lesson) return [];
|
|
12869
|
+
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 }));
|
|
12870
|
+
}
|
|
12871
|
+
async getPlaylist(path, auth, _resolution) {
|
|
12872
|
+
if (!auth || !await this.verifyAuth(auth)) return null;
|
|
12873
|
+
const { segments, depth } = parsePath(path);
|
|
12874
|
+
if (depth !== 3) return null;
|
|
12875
|
+
const collection = await this.getCollection(segments, auth);
|
|
12876
|
+
if (!collection) return null;
|
|
12877
|
+
const files = this.getLessonFiles(collection, segments[2]);
|
|
12878
|
+
return files.length > 0 ? files : null;
|
|
12879
|
+
}
|
|
12880
|
+
async getInstructions(path, auth) {
|
|
12881
|
+
if (!auth || !await this.verifyAuth(auth)) return null;
|
|
12882
|
+
const { segments, depth } = parsePath(path);
|
|
12883
|
+
const smallGroup = depth === 4 && segments[2] === SMALL_GROUP;
|
|
12884
|
+
if (depth !== 3 && !smallGroup) return null;
|
|
12885
|
+
const collection = await this.getCollection(segments, auth);
|
|
12886
|
+
const lesson = collection?.lessons.find((l) => l.id === segments[depth - 1]);
|
|
12887
|
+
if (!collection || !lesson) return null;
|
|
12888
|
+
let instructions;
|
|
12889
|
+
if (smallGroup) {
|
|
12890
|
+
if (!lesson.smallGroup?.sections?.length) return null;
|
|
12891
|
+
instructions = guideToInstructions(`${lesson.name} - Small Group`, lesson.smallGroup, "sg", lesson);
|
|
12892
|
+
} else if (lesson.script?.sections?.length) {
|
|
12893
|
+
instructions = guideToInstructions(lesson.name, lesson.script, "lg", lesson);
|
|
12894
|
+
} else {
|
|
12895
|
+
const files = this.getLessonFiles(collection, lesson.id);
|
|
12896
|
+
if (files.length === 0) return null;
|
|
12897
|
+
instructions = filesToInstructions(lesson.name, files);
|
|
12898
|
+
}
|
|
12899
|
+
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 }));
|
|
12900
|
+
if (downloads.length > 0) instructions.downloads = downloads;
|
|
12901
|
+
return instructions;
|
|
12902
|
+
}
|
|
12903
|
+
generateCodeVerifier() {
|
|
12904
|
+
return this.oauthHelper.generateCodeVerifier();
|
|
12905
|
+
}
|
|
12906
|
+
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
12907
|
+
return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
|
|
12908
|
+
}
|
|
12909
|
+
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
12910
|
+
return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
|
|
12911
|
+
}
|
|
12912
|
+
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
12913
|
+
return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
|
|
12914
|
+
}
|
|
12915
|
+
};
|
|
12916
|
+
|
|
12740
12917
|
// src/providers/lifeChurch/data.json
|
|
12741
12918
|
var data_default3 = {
|
|
12742
12919
|
generatedAt: "2026-05-09T20:14:53.089Z",
|
|
@@ -16544,122 +16721,6 @@ function registerProvider(provider) {
|
|
|
16544
16721
|
providerRegistry.set(provider.id, provider);
|
|
16545
16722
|
}
|
|
16546
16723
|
|
|
16547
|
-
// src/providers/goCurriculum/GoCurriculumProvider.ts
|
|
16548
|
-
var FEEDS = [
|
|
16549
|
-
{ id: "elementary", name: "Elementary", url: "https://dl.dropboxusercontent.com/scl/fi/xortbrs2nk49wemscubpu/data.json?rlkey=gnzxyrauhud7xtjlejrs8ysp7" },
|
|
16550
|
-
{ id: "preschool", name: "Preschool", url: "https://dl.dropboxusercontent.com/scl/fi/1cdovbglp5rpfmb9mdg2s/data.json?rlkey=miwsssb0o7i2wdijrdc7jjqcl" }
|
|
16551
|
-
];
|
|
16552
|
-
var CATALOG_TTL_MS = 60 * 60 * 1e3;
|
|
16553
|
-
var GoCurriculumProvider = class extends BaseProvider {
|
|
16554
|
-
constructor() {
|
|
16555
|
-
super(...arguments);
|
|
16556
|
-
this.oauthHelper = new OAuthHelper();
|
|
16557
|
-
this.verifiedTokens = /* @__PURE__ */ new Set();
|
|
16558
|
-
this.id = "gocurriculum";
|
|
16559
|
-
this.name = "Go Curriculum";
|
|
16560
|
-
this.logos = {
|
|
16561
|
-
light: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png",
|
|
16562
|
-
dark: "https://gocurriculum.com/wp-content/uploads/go-logo-curriculum-v2.png"
|
|
16563
|
-
};
|
|
16564
|
-
this.config = {
|
|
16565
|
-
id: "gocurriculum",
|
|
16566
|
-
name: "Go Curriculum",
|
|
16567
|
-
apiBase: "https://gocurriculum.com",
|
|
16568
|
-
oauthBase: "https://gocurriculum.com/oauth",
|
|
16569
|
-
clientId: "Rdrvz9jz9nTNf8rCsbpuAgVLdoWHZmcjdmmrP0Bw",
|
|
16570
|
-
// supplied at runtime via setProviderSecret("gocurriculum", ...) — never commit the value
|
|
16571
|
-
get clientSecret() {
|
|
16572
|
-
return getProviderSecret("gocurriculum");
|
|
16573
|
-
},
|
|
16574
|
-
scopes: ["basic"]
|
|
16575
|
-
};
|
|
16576
|
-
this.data = {};
|
|
16577
|
-
this.dataFetchedAt = 0;
|
|
16578
|
-
this.requiresAuth = true;
|
|
16579
|
-
this.authTypes = ["oauth_pkce"];
|
|
16580
|
-
this.capabilities = { browse: true, playlist: true, instructions: true, mediaLicensing: false };
|
|
16581
|
-
}
|
|
16582
|
-
async getData(groupId) {
|
|
16583
|
-
if (Date.now() - this.dataFetchedAt >= CATALOG_TTL_MS) {
|
|
16584
|
-
await Promise.all(FEEDS.map(async (f) => {
|
|
16585
|
-
try {
|
|
16586
|
-
const response = await fetch(f.url);
|
|
16587
|
-
if (response.ok) this.data[f.id] = await response.json();
|
|
16588
|
-
} catch {
|
|
16589
|
-
}
|
|
16590
|
-
}));
|
|
16591
|
-
if (FEEDS.every((f) => this.data[f.id])) this.dataFetchedAt = Date.now();
|
|
16592
|
-
}
|
|
16593
|
-
return this.data[groupId];
|
|
16594
|
-
}
|
|
16595
|
-
async getCollection(segments) {
|
|
16596
|
-
return (await this.getData(segments[0]))?.catalog.find((c) => c.id === segments[1]);
|
|
16597
|
-
}
|
|
16598
|
-
// ponytail: any valid login unlocks everything for the pilot — per-tier (MemberPress) filtering waits on Go's membership endpoint
|
|
16599
|
-
async verifyAuth(auth) {
|
|
16600
|
-
const token = auth?.access_token;
|
|
16601
|
-
if (!token) return false;
|
|
16602
|
-
if (this.verifiedTokens.has(token)) return true;
|
|
16603
|
-
try {
|
|
16604
|
-
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() });
|
|
16605
|
-
if (!response.ok) return false;
|
|
16606
|
-
this.verifiedTokens.add(token);
|
|
16607
|
-
return true;
|
|
16608
|
-
} catch {
|
|
16609
|
-
return false;
|
|
16610
|
-
}
|
|
16611
|
-
}
|
|
16612
|
-
async browse(path, auth) {
|
|
16613
|
-
if (!await this.verifyAuth(auth)) return [];
|
|
16614
|
-
const { segments, depth } = parsePath(path);
|
|
16615
|
-
if (depth === 0) return FEEDS.map((f) => createFolder(f.id, f.name, `/${f.id}`));
|
|
16616
|
-
if (depth === 1) return ((await this.getData(segments[0]))?.catalog || []).map((c) => createFolder(c.id, c.name, `/${segments[0]}/${c.id}`, c.thumbnail));
|
|
16617
|
-
const collection = await this.getCollection(segments);
|
|
16618
|
-
if (!collection) return [];
|
|
16619
|
-
if (depth === 2) return collection.lessons.map((l) => createFolder(l.id, l.name, `/${segments[0]}/${collection.id}/${l.id}`, l.thumbnail || collection.thumbnail, true));
|
|
16620
|
-
if (depth === 3) return this.getLessonFiles(collection, segments[2]);
|
|
16621
|
-
return [];
|
|
16622
|
-
}
|
|
16623
|
-
getLessonFiles(collection, lessonId) {
|
|
16624
|
-
const lesson = collection.lessons.find((l) => l.id === lessonId);
|
|
16625
|
-
if (!lesson) return [];
|
|
16626
|
-
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 }));
|
|
16627
|
-
}
|
|
16628
|
-
async getPlaylist(path, auth, _resolution) {
|
|
16629
|
-
if (!await this.verifyAuth(auth)) return null;
|
|
16630
|
-
const { segments, depth } = parsePath(path);
|
|
16631
|
-
if (depth !== 3) return null;
|
|
16632
|
-
const collection = await this.getCollection(segments);
|
|
16633
|
-
if (!collection) return null;
|
|
16634
|
-
const files = this.getLessonFiles(collection, segments[2]);
|
|
16635
|
-
return files.length > 0 ? files : null;
|
|
16636
|
-
}
|
|
16637
|
-
async getInstructions(path, auth) {
|
|
16638
|
-
const { segments, depth } = parsePath(path);
|
|
16639
|
-
if (depth !== 3) return null;
|
|
16640
|
-
const files = await this.getPlaylist(path, auth);
|
|
16641
|
-
if (!files) return null;
|
|
16642
|
-
const collection = await this.getCollection(segments);
|
|
16643
|
-
const lesson = collection?.lessons.find((l) => l.id === segments[2]);
|
|
16644
|
-
const instructions = filesToInstructions(lesson?.name || "Lesson", files);
|
|
16645
|
-
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 }));
|
|
16646
|
-
if (downloads.length > 0) instructions.downloads = downloads;
|
|
16647
|
-
return instructions;
|
|
16648
|
-
}
|
|
16649
|
-
generateCodeVerifier() {
|
|
16650
|
-
return this.oauthHelper.generateCodeVerifier();
|
|
16651
|
-
}
|
|
16652
|
-
async buildAuthUrl(codeVerifier, redirectUri, state) {
|
|
16653
|
-
return this.oauthHelper.buildAuthUrl(this.config, codeVerifier, redirectUri, state || this.id);
|
|
16654
|
-
}
|
|
16655
|
-
buildAuthUrlFromChallenge(codeChallenge, redirectUri, state) {
|
|
16656
|
-
return this.oauthHelper.buildAuthUrlFromChallenge(this.config, codeChallenge, redirectUri, state);
|
|
16657
|
-
}
|
|
16658
|
-
async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
|
|
16659
|
-
return this.oauthHelper.exchangeCodeForTokens(this.config, this.id, code, codeVerifier, redirectUri);
|
|
16660
|
-
}
|
|
16661
|
-
};
|
|
16662
|
-
|
|
16663
16724
|
// src/providers/googledrive/GoogleDriveProvider.ts
|
|
16664
16725
|
var FOLDER_MIME = "application/vnd.google-apps.folder";
|
|
16665
16726
|
var MAX_PAGINATION_CALLS2 = 10;
|
|
@@ -17004,7 +17065,7 @@ function getAvailableProviders(ids) {
|
|
|
17004
17065
|
}
|
|
17005
17066
|
|
|
17006
17067
|
// src/index.ts
|
|
17007
|
-
var VERSION = true ? "0.
|
|
17068
|
+
var VERSION = true ? "0.15.0" : "dev";
|
|
17008
17069
|
export {
|
|
17009
17070
|
APlayProvider,
|
|
17010
17071
|
B1ChurchProvider,
|
|
@@ -17015,6 +17076,7 @@ export {
|
|
|
17015
17076
|
DropboxProvider,
|
|
17016
17077
|
FREESHOW_REST_PORT,
|
|
17017
17078
|
FreeShowProvider,
|
|
17079
|
+
GoCurriculumProvider,
|
|
17018
17080
|
HighVoltageKidsProvider,
|
|
17019
17081
|
JesusFilmProvider,
|
|
17020
17082
|
LessonsChurchProvider,
|