offcourse 0.0.2 → 1.0.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.
Files changed (139) hide show
  1. package/README.md +255 -20
  2. package/dist/cli/commands/config.d.ts +13 -0
  3. package/dist/cli/commands/config.d.ts.map +1 -0
  4. package/dist/cli/commands/config.js +66 -0
  5. package/dist/cli/commands/config.js.map +1 -0
  6. package/dist/cli/commands/inspect.d.ts +11 -0
  7. package/dist/cli/commands/inspect.d.ts.map +1 -0
  8. package/dist/cli/commands/inspect.js +365 -0
  9. package/dist/cli/commands/inspect.js.map +1 -0
  10. package/dist/cli/commands/login.d.ts +12 -0
  11. package/dist/cli/commands/login.d.ts.map +1 -0
  12. package/dist/cli/commands/login.js +55 -0
  13. package/dist/cli/commands/login.js.map +1 -0
  14. package/dist/cli/commands/status.d.ts +15 -0
  15. package/dist/cli/commands/status.d.ts.map +1 -0
  16. package/dist/cli/commands/status.js +118 -0
  17. package/dist/cli/commands/status.js.map +1 -0
  18. package/dist/cli/commands/sync.d.ts +15 -0
  19. package/dist/cli/commands/sync.d.ts.map +1 -0
  20. package/dist/cli/commands/sync.js +921 -0
  21. package/dist/cli/commands/sync.js.map +1 -0
  22. package/dist/cli/commands/syncHighLevel.d.ts +23 -0
  23. package/dist/cli/commands/syncHighLevel.d.ts.map +1 -0
  24. package/dist/cli/commands/syncHighLevel.js +479 -0
  25. package/dist/cli/commands/syncHighLevel.js.map +1 -0
  26. package/dist/cli/index.d.ts +3 -0
  27. package/dist/cli/index.d.ts.map +1 -0
  28. package/dist/cli/index.js +106 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/config/configManager.d.ts +31 -0
  31. package/dist/config/configManager.d.ts.map +1 -0
  32. package/dist/config/configManager.js +68 -0
  33. package/dist/config/configManager.js.map +1 -0
  34. package/dist/config/paths.d.ts +21 -0
  35. package/dist/config/paths.d.ts.map +1 -0
  36. package/dist/config/paths.js +33 -0
  37. package/dist/config/paths.js.map +1 -0
  38. package/dist/config/schema.d.ts +60 -0
  39. package/dist/config/schema.d.ts.map +1 -0
  40. package/dist/config/schema.js +50 -0
  41. package/dist/config/schema.js.map +1 -0
  42. package/dist/downloader/hlsDownloader.d.ts +58 -0
  43. package/dist/downloader/hlsDownloader.d.ts.map +1 -0
  44. package/dist/downloader/hlsDownloader.js +263 -0
  45. package/dist/downloader/hlsDownloader.js.map +1 -0
  46. package/dist/downloader/hlsValidator.d.ts +35 -0
  47. package/dist/downloader/hlsValidator.d.ts.map +1 -0
  48. package/dist/downloader/hlsValidator.js +152 -0
  49. package/dist/downloader/hlsValidator.js.map +1 -0
  50. package/dist/downloader/index.d.ts +29 -0
  51. package/dist/downloader/index.d.ts.map +1 -0
  52. package/dist/downloader/index.js +55 -0
  53. package/dist/downloader/index.js.map +1 -0
  54. package/dist/downloader/loomDownloader.d.ts +56 -0
  55. package/dist/downloader/loomDownloader.d.ts.map +1 -0
  56. package/dist/downloader/loomDownloader.js +562 -0
  57. package/dist/downloader/loomDownloader.js.map +1 -0
  58. package/dist/downloader/queue.d.ts +56 -0
  59. package/dist/downloader/queue.d.ts.map +1 -0
  60. package/dist/downloader/queue.js +88 -0
  61. package/dist/downloader/queue.js.map +1 -0
  62. package/dist/downloader/vimeoDownloader.d.ts +52 -0
  63. package/dist/downloader/vimeoDownloader.d.ts.map +1 -0
  64. package/dist/downloader/vimeoDownloader.js +569 -0
  65. package/dist/downloader/vimeoDownloader.js.map +1 -0
  66. package/dist/scraper/extractor.d.ts +53 -0
  67. package/dist/scraper/extractor.d.ts.map +1 -0
  68. package/dist/scraper/extractor.js +627 -0
  69. package/dist/scraper/extractor.js.map +1 -0
  70. package/dist/scraper/highlevel/extractor.d.ts +89 -0
  71. package/dist/scraper/highlevel/extractor.d.ts.map +1 -0
  72. package/dist/scraper/highlevel/extractor.js +373 -0
  73. package/dist/scraper/highlevel/extractor.js.map +1 -0
  74. package/dist/scraper/highlevel/index.d.ts +3 -0
  75. package/dist/scraper/highlevel/index.d.ts.map +1 -0
  76. package/dist/scraper/highlevel/index.js +3 -0
  77. package/dist/scraper/highlevel/index.js.map +1 -0
  78. package/dist/scraper/highlevel/navigator.d.ts +86 -0
  79. package/dist/scraper/highlevel/navigator.d.ts.map +1 -0
  80. package/dist/scraper/highlevel/navigator.js +505 -0
  81. package/dist/scraper/highlevel/navigator.js.map +1 -0
  82. package/dist/scraper/highlevel/schemas.d.ts +188 -0
  83. package/dist/scraper/highlevel/schemas.d.ts.map +1 -0
  84. package/dist/scraper/highlevel/schemas.js +139 -0
  85. package/dist/scraper/highlevel/schemas.js.map +1 -0
  86. package/dist/scraper/navigator.d.ts +68 -0
  87. package/dist/scraper/navigator.d.ts.map +1 -0
  88. package/dist/scraper/navigator.js +257 -0
  89. package/dist/scraper/navigator.js.map +1 -0
  90. package/dist/scraper/schemas.d.ts +57 -0
  91. package/dist/scraper/schemas.d.ts.map +1 -0
  92. package/dist/scraper/schemas.js +135 -0
  93. package/dist/scraper/schemas.js.map +1 -0
  94. package/dist/scraper/videoInterceptor.d.ts +23 -0
  95. package/dist/scraper/videoInterceptor.d.ts.map +1 -0
  96. package/dist/scraper/videoInterceptor.js +330 -0
  97. package/dist/scraper/videoInterceptor.js.map +1 -0
  98. package/dist/shared/auth.d.ts +58 -0
  99. package/dist/shared/auth.d.ts.map +1 -0
  100. package/dist/shared/auth.js +197 -0
  101. package/dist/shared/auth.js.map +1 -0
  102. package/dist/shared/firebase.d.ts +60 -0
  103. package/dist/shared/firebase.d.ts.map +1 -0
  104. package/dist/shared/firebase.js +102 -0
  105. package/dist/shared/firebase.js.map +1 -0
  106. package/dist/shared/fs.d.ts +31 -0
  107. package/dist/shared/fs.d.ts.map +1 -0
  108. package/dist/shared/fs.js +77 -0
  109. package/dist/shared/fs.js.map +1 -0
  110. package/dist/shared/http.d.ts +15 -0
  111. package/dist/shared/http.d.ts.map +1 -0
  112. package/dist/shared/http.js +31 -0
  113. package/dist/shared/http.js.map +1 -0
  114. package/dist/shared/index.d.ts +7 -0
  115. package/dist/shared/index.d.ts.map +1 -0
  116. package/dist/shared/index.js +7 -0
  117. package/dist/shared/index.js.map +1 -0
  118. package/dist/shared/slug.d.ts +11 -0
  119. package/dist/shared/slug.d.ts.map +1 -0
  120. package/dist/shared/slug.js +25 -0
  121. package/dist/shared/slug.js.map +1 -0
  122. package/dist/shared/url.d.ts +43 -0
  123. package/dist/shared/url.d.ts.map +1 -0
  124. package/dist/shared/url.js +54 -0
  125. package/dist/shared/url.js.map +1 -0
  126. package/dist/state/database.d.ts +246 -0
  127. package/dist/state/database.d.ts.map +1 -0
  128. package/dist/state/database.js +679 -0
  129. package/dist/state/database.js.map +1 -0
  130. package/dist/state/index.d.ts +2 -0
  131. package/dist/state/index.d.ts.map +1 -0
  132. package/dist/state/index.js +2 -0
  133. package/dist/state/index.js.map +1 -0
  134. package/dist/storage/fileSystem.d.ts +56 -0
  135. package/dist/storage/fileSystem.d.ts.map +1 -0
  136. package/dist/storage/fileSystem.js +129 -0
  137. package/dist/storage/fileSystem.js.map +1 -0
  138. package/package.json +71 -11
  139. package/cli.js +0 -45
@@ -0,0 +1,627 @@
1
+ import TurndownService from "turndown";
2
+ import { parseNextData, extractVideoFromNextData as extractVideoFromNextDataSchema, } from "./schemas.js";
3
+ // Initialize Turndown for HTML to Markdown conversion
4
+ const turndown = new TurndownService({
5
+ headingStyle: "atx",
6
+ codeBlockStyle: "fenced",
7
+ bulletListMarker: "-",
8
+ });
9
+ // Custom rule to handle images
10
+ turndown.addRule("images", {
11
+ filter: "img",
12
+ replacement: (_content, node) => {
13
+ const img = node;
14
+ const alt = img.alt || "";
15
+ const src = img.src || "";
16
+ return `![${alt}](${src})`;
17
+ },
18
+ });
19
+ // Custom rule to preserve links
20
+ turndown.addRule("links", {
21
+ filter: "a",
22
+ replacement: (content, node) => {
23
+ const anchor = node;
24
+ const href = anchor.href || "";
25
+ if (!href || href === content) {
26
+ return content;
27
+ }
28
+ return `[${content}](${href})`;
29
+ },
30
+ });
31
+ // Browser automation functions - require Playwright
32
+ /* v8 ignore start */
33
+ /**
34
+ * Checks if there's a video preview/thumbnail that needs to be clicked to load the video.
35
+ */
36
+ async function tryClickVideoPreview(page) {
37
+ // First, try Skool's specific styled-components pattern for video players
38
+ // These have classes like "styled__VideoPlayerWrapper-sc-xxx" and "styled__PlaybackButton-sc-xxx"
39
+ // Strategy 0: Direct click on Skool's VideoPlayerWrapper or PlaybackButton
40
+ const skoolClicked = await page.evaluate(() => {
41
+ // Find the playback button directly
42
+ const playbackButton = document.querySelector('[class*="PlaybackButton"]');
43
+ if (playbackButton && playbackButton instanceof HTMLElement) {
44
+ const rect = playbackButton.getBoundingClientRect();
45
+ if (rect.width > 0 && rect.height > 0) {
46
+ playbackButton.click();
47
+ return { clicked: true, selector: "PlaybackButton" };
48
+ }
49
+ }
50
+ // Or try clicking the video player wrapper
51
+ const videoWrapper = document.querySelector('[class*="VideoPlayerWrapper"]');
52
+ if (videoWrapper && videoWrapper instanceof HTMLElement) {
53
+ const rect = videoWrapper.getBoundingClientRect();
54
+ if (rect.width > 200 && rect.height > 100) {
55
+ videoWrapper.click();
56
+ return { clicked: true, selector: "VideoPlayerWrapper" };
57
+ }
58
+ }
59
+ // Try styled-components video patterns
60
+ const styledVideo = document.querySelector('[class*="styled__Video"]');
61
+ if (styledVideo && styledVideo instanceof HTMLElement) {
62
+ styledVideo.click();
63
+ return { clicked: true, selector: "styled__Video" };
64
+ }
65
+ return { clicked: false };
66
+ });
67
+ if (skoolClicked.clicked) {
68
+ // Wait for iframe to appear after click
69
+ try {
70
+ await page.waitForSelector('iframe[src*="loom.com"], iframe[src*="vimeo"], iframe[src*="youtube"], video', {
71
+ timeout: 5000,
72
+ });
73
+ }
74
+ catch {
75
+ // Timeout is fine, we'll check for video anyway
76
+ }
77
+ // Extra wait for iframe content to load
78
+ await page.waitForTimeout(1000);
79
+ return true;
80
+ }
81
+ // Strategy 1: Look for elements that contain "loom" in href or data attributes
82
+ const loomClicked = await page.evaluate(() => {
83
+ // Find any anchor or element with loom URL
84
+ const loomLink = document.querySelector('a[href*="loom.com"]');
85
+ if (loomLink && loomLink instanceof HTMLElement) {
86
+ // Try to find a parent container that might be the video preview
87
+ let container = loomLink.parentElement;
88
+ for (let i = 0; i < 5 && container; i++) {
89
+ const rect = container.getBoundingClientRect();
90
+ if (rect.width > 300 && rect.height > 150) {
91
+ container.click();
92
+ return true;
93
+ }
94
+ container = container.parentElement;
95
+ }
96
+ loomLink.click();
97
+ return true;
98
+ }
99
+ // Look for elements with loom-related classes or data
100
+ const loomElements = Array.from(document.querySelectorAll('[class*="loom"], [data-loom], [data-video-provider="loom"]'));
101
+ for (const el of loomElements) {
102
+ if (el instanceof HTMLElement) {
103
+ const rect = el.getBoundingClientRect();
104
+ if (rect.width > 100 && rect.height > 50) {
105
+ el.click();
106
+ return true;
107
+ }
108
+ }
109
+ }
110
+ return false;
111
+ });
112
+ if (loomClicked) {
113
+ await page.waitForTimeout(2500);
114
+ return true;
115
+ }
116
+ // Strategy 2: Look for play button overlays on large elements
117
+ const playClicked = await page.evaluate(() => {
118
+ // Find all elements that look like play buttons (including styled-components patterns)
119
+ const playButtons = Array.from(document.querySelectorAll('[class*="play" i], [class*="Play"], [class*="Playback"], svg[class*="play" i], [aria-label*="play" i]'));
120
+ for (const btn of playButtons) {
121
+ if (btn instanceof HTMLElement || btn instanceof SVGElement) {
122
+ const rect = btn.getBoundingClientRect();
123
+ // Play buttons are usually visible and reasonably sized
124
+ if (rect.width > 20 && rect.height > 20 && rect.top > 0 && rect.left > 0) {
125
+ // Check if this is inside a large container (video preview)
126
+ let parent = btn.parentElement;
127
+ for (let i = 0; i < 5 && parent; i++) {
128
+ const parentRect = parent.getBoundingClientRect();
129
+ if (parentRect.width > 300 && parentRect.height > 150) {
130
+ // This looks like a video container - click the play button
131
+ if (btn instanceof HTMLElement) {
132
+ btn.click();
133
+ }
134
+ else {
135
+ // For SVG, try to click the parent
136
+ parent.click();
137
+ }
138
+ return true;
139
+ }
140
+ parent = parent.parentElement;
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return false;
146
+ });
147
+ if (playClicked) {
148
+ await page.waitForTimeout(2500);
149
+ return true;
150
+ }
151
+ // Strategy 3: Look for large clickable images/thumbnails
152
+ const thumbnailClicked = await page.evaluate(() => {
153
+ // Find large images that might be video thumbnails
154
+ const images = Array.from(document.querySelectorAll("img"));
155
+ for (const img of images) {
156
+ const rect = img.getBoundingClientRect();
157
+ // Video thumbnails are typically 16:9 or similar aspect ratio
158
+ if (rect.width > 400 && rect.height > 200) {
159
+ // Check if image has a sibling or parent with play icon
160
+ const parent = img.parentElement;
161
+ if (parent) {
162
+ const hasPLay = parent.querySelector('[class*="play" i], svg');
163
+ if (hasPLay || parent.className.toLowerCase().includes("video")) {
164
+ parent.click();
165
+ return true;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ return false;
171
+ });
172
+ if (thumbnailClicked) {
173
+ await page.waitForTimeout(2500);
174
+ return true;
175
+ }
176
+ // Strategy 4: Common patterns for video preview overlays
177
+ const previewSelectors = [
178
+ // Skool-specific patterns
179
+ '[class*="VideoWrapper"]',
180
+ '[class*="video-wrapper"]',
181
+ '[class*="video-container"]',
182
+ '[class*="VideoContainer"]',
183
+ '[class*="player-wrapper"]',
184
+ '[class*="embed-wrapper"]',
185
+ // Generic patterns
186
+ '[class*="video-preview"]',
187
+ '[class*="VideoPreview"]',
188
+ '[class*="video-thumbnail"]',
189
+ '[class*="poster"]',
190
+ // Data attribute patterns
191
+ "[data-video-id]",
192
+ "[data-video-url]",
193
+ "[data-embed]",
194
+ ];
195
+ for (const selector of previewSelectors) {
196
+ try {
197
+ const element = await page.$(selector);
198
+ if (element) {
199
+ const isVisible = await element.isVisible();
200
+ if (isVisible) {
201
+ const box = await element.boundingBox();
202
+ if (box && box.width > 200 && box.height > 100) {
203
+ await element.click();
204
+ await page.waitForTimeout(2500);
205
+ return true;
206
+ }
207
+ }
208
+ }
209
+ }
210
+ catch {
211
+ // Selector not found or not clickable, try next
212
+ }
213
+ }
214
+ return false;
215
+ }
216
+ /**
217
+ * Extracts the video URL from the current lesson page.
218
+ * Supports Loom, Vimeo, YouTube, Wistia, and native video.
219
+ *
220
+ * For Vimeo: Prefers iframe src (has auth params) over __NEXT_DATA__ URL.
221
+ * For others: Uses __NEXT_DATA__ first, then falls back to DOM inspection.
222
+ */
223
+ export async function extractVideoUrl(page) {
224
+ // First: Check for iframe with full URL (includes auth params for Vimeo)
225
+ const iframeVideo = await extractVideoFromIframe(page);
226
+ // If it's Vimeo, prefer iframe URL as it has the auth hash
227
+ if (iframeVideo.url && iframeVideo.type === "vimeo") {
228
+ return iframeVideo;
229
+ }
230
+ // Try extracting from __NEXT_DATA__ (Skool embeds video URLs here)
231
+ const nextDataVideo = await extractVideoFromNextData(page);
232
+ if (nextDataVideo.url) {
233
+ // For Vimeo, check if iframe has additional params we're missing
234
+ if (nextDataVideo.type === "vimeo" && iframeVideo.url) {
235
+ return iframeVideo; // iframe has the full URL with hash
236
+ }
237
+ return nextDataVideo;
238
+ }
239
+ // Check for already loaded video in DOM
240
+ let videoInfo = await findVideoInPage(page);
241
+ // If no video found, try clicking preview to trigger lazy load
242
+ if (!videoInfo.url) {
243
+ const clicked = await tryClickVideoPreview(page);
244
+ if (clicked) {
245
+ // Re-check for video after clicking
246
+ videoInfo = await findVideoInPage(page);
247
+ }
248
+ }
249
+ return videoInfo;
250
+ }
251
+ /**
252
+ * Extracts video URL directly from iframe src attribute.
253
+ * This captures the full URL including auth parameters.
254
+ */
255
+ async function extractVideoFromIframe(page) {
256
+ return page.evaluate(() => {
257
+ // Check for Vimeo iframe (prioritize this for auth params)
258
+ const vimeoIframe = document.querySelector('iframe[src*="vimeo.com"]');
259
+ if (vimeoIframe) {
260
+ const src = vimeoIframe.src;
261
+ if (src) {
262
+ return { url: src, type: "vimeo" };
263
+ }
264
+ }
265
+ // Check for Loom iframe
266
+ const loomIframe = document.querySelector('iframe[src*="loom.com"]');
267
+ if (loomIframe) {
268
+ const src = loomIframe.src;
269
+ if (src) {
270
+ return { url: src, type: "loom" };
271
+ }
272
+ }
273
+ // Check for YouTube iframe
274
+ const ytIframe = document.querySelector('iframe[src*="youtube.com"], iframe[src*="youtu.be"]');
275
+ if (ytIframe) {
276
+ const src = ytIframe.src;
277
+ if (src) {
278
+ return { url: src, type: "youtube" };
279
+ }
280
+ }
281
+ return { url: null, type: null };
282
+ });
283
+ }
284
+ /**
285
+ * Extracts video URL from Skool's __NEXT_DATA__ JSON.
286
+ * This is the most reliable method as Skool stores video metadata here.
287
+ *
288
+ * IMPORTANT: __NEXT_DATA__ is only updated on full page loads, not SPA navigation.
289
+ * Our sync uses page.goto() which triggers full loads, so this is fine.
290
+ * We also verify the module ID matches the current URL to detect stale data.
291
+ */
292
+ async function extractVideoFromNextData(page) {
293
+ // Get raw data from browser
294
+ const { nextDataJson, urlModuleId } = await page.evaluate(() => {
295
+ const nextDataScript = document.querySelector("#__NEXT_DATA__");
296
+ const json = nextDataScript?.textContent ?? null;
297
+ // Get URL module ID to verify freshness
298
+ const urlParams = new URLSearchParams(window.location.search);
299
+ const urlMd = urlParams.get("md");
300
+ return {
301
+ nextDataJson: json,
302
+ urlModuleId: urlMd,
303
+ };
304
+ });
305
+ if (!nextDataJson) {
306
+ return { url: null, type: null };
307
+ }
308
+ // Parse and validate in Node context
309
+ const parsed = parseNextData(nextDataJson);
310
+ if (!parsed) {
311
+ return { url: null, type: null };
312
+ }
313
+ const selectedModuleId = parsed.props?.pageProps?.selectedModule;
314
+ if (!selectedModuleId) {
315
+ return { url: null, type: null };
316
+ }
317
+ // Verify this matches the current URL (detect stale __NEXT_DATA__ from SPA navigation)
318
+ if (urlModuleId && urlModuleId !== selectedModuleId) {
319
+ // __NEXT_DATA__ is stale (SPA navigation happened), don't trust it
320
+ return { url: null, type: null };
321
+ }
322
+ // Extract video using validated data
323
+ const videoInfo = extractVideoFromNextDataSchema(parsed, selectedModuleId);
324
+ if (videoInfo) {
325
+ return { url: videoInfo.url, type: videoInfo.type };
326
+ }
327
+ return { url: null, type: null };
328
+ }
329
+ /**
330
+ * Finds video URL in the current page state.
331
+ */
332
+ async function findVideoInPage(page) {
333
+ const videoInfo = await page.evaluate(() => {
334
+ // Check for Loom iframe (most common on Skool)
335
+ const loomIframe = document.querySelector('iframe[src*="loom.com"]');
336
+ if (loomIframe) {
337
+ return { url: loomIframe.src, type: "loom" };
338
+ }
339
+ // Check for Loom embed link (sometimes used instead of iframe)
340
+ const loomLinks = Array.from(document.querySelectorAll('a[href*="loom.com"]'));
341
+ for (const link of loomLinks) {
342
+ const href = link.href;
343
+ if (href.includes("/share/") || href.includes("/embed/")) {
344
+ // Convert share URL to embed URL
345
+ const embedUrl = href.replace("/share/", "/embed/");
346
+ return { url: embedUrl, type: "loom" };
347
+ }
348
+ }
349
+ // Check for Loom data attributes
350
+ const loomEmbed = document.querySelector("[data-loom-id]");
351
+ if (loomEmbed) {
352
+ const loomId = loomEmbed.getAttribute("data-loom-id");
353
+ if (loomId) {
354
+ return { url: `https://www.loom.com/embed/${loomId}`, type: "loom" };
355
+ }
356
+ }
357
+ // Check for Loom URLs in any element's attributes or content
358
+ const allElements = Array.from(document.querySelectorAll("*"));
359
+ for (const el of allElements) {
360
+ // Check data attributes
361
+ const attrs = Array.from(el.attributes);
362
+ for (const attr of attrs) {
363
+ if (attr.value.includes("loom.com/share/") || attr.value.includes("loom.com/embed/")) {
364
+ const match = /loom\.com\/(share|embed)\/([a-f0-9]+)/.exec(attr.value);
365
+ if (match?.[2]) {
366
+ return { url: `https://www.loom.com/embed/${match[2]}`, type: "loom" };
367
+ }
368
+ }
369
+ }
370
+ }
371
+ // Check for Vimeo iframe
372
+ const vimeoIframe = document.querySelector('iframe[src*="vimeo.com"]');
373
+ if (vimeoIframe) {
374
+ return { url: vimeoIframe.src, type: "vimeo" };
375
+ }
376
+ // Check for YouTube iframe
377
+ const youtubeIframe = document.querySelector('iframe[src*="youtube.com"], iframe[src*="youtu.be"]');
378
+ if (youtubeIframe) {
379
+ return { url: youtubeIframe.src, type: "youtube" };
380
+ }
381
+ // Check for Wistia
382
+ const wistiaVideo = document.querySelector('[class*="wistia"]');
383
+ if (wistiaVideo) {
384
+ const wistiaId = /wistia_embed wistia_async_(\w+)/.exec(wistiaVideo.className);
385
+ if (wistiaId?.[1]) {
386
+ return {
387
+ url: `https://fast.wistia.net/embed/medias/${wistiaId[1]}`,
388
+ type: "wistia",
389
+ };
390
+ }
391
+ }
392
+ // Check for HTML5 video
393
+ const videoElement = document.querySelector("video");
394
+ if (videoElement) {
395
+ const source = videoElement.querySelector("source");
396
+ const src = source?.src ?? videoElement.src;
397
+ if (src) {
398
+ return { url: src, type: "native" };
399
+ }
400
+ }
401
+ // Check for any iframe that might be a video player
402
+ const iframes = Array.from(document.querySelectorAll("iframe"));
403
+ for (const iframe of iframes) {
404
+ const src = iframe.src;
405
+ if (src &&
406
+ !src.includes("stripe.com") &&
407
+ (src.includes("embed") || src.includes("player") || src.includes("video"))) {
408
+ return { url: src, type: "unknown" };
409
+ }
410
+ }
411
+ // Last resort: search page HTML for loom URLs
412
+ const pageHtml = document.documentElement.outerHTML;
413
+ const loomMatch = /loom\.com\/(share|embed)\/([a-f0-9]{32})/.exec(pageHtml);
414
+ if (loomMatch?.[2]) {
415
+ return { url: `https://www.loom.com/embed/${loomMatch[2]}`, type: "loom" };
416
+ }
417
+ // Try to find explicit Loom video IDs in script tags
418
+ const scripts = Array.from(document.querySelectorAll("script"));
419
+ for (const script of scripts) {
420
+ const content = script.textContent ?? "";
421
+ // Look for explicit loom URL patterns in scripts
422
+ const loomUrlMatch = /loom\.com\/(share|embed)\/([a-f0-9]{32})/.exec(content);
423
+ if (loomUrlMatch?.[2]) {
424
+ return { url: `https://www.loom.com/embed/${loomUrlMatch[2]}`, type: "loom" };
425
+ }
426
+ // Look for loom video ID near "loom" keyword
427
+ const loomContextMatch = /["']loom["'][^}]*["']([a-f0-9]{32})["']/i.exec(content);
428
+ if (loomContextMatch?.[1]) {
429
+ return { url: `https://www.loom.com/embed/${loomContextMatch[1]}`, type: "loom" };
430
+ }
431
+ }
432
+ return { url: null, type: null };
433
+ });
434
+ return videoInfo;
435
+ }
436
+ /**
437
+ * Extracts the text content from the lesson page.
438
+ */
439
+ export async function extractTextContent(page) {
440
+ const html = await page.evaluate(() => {
441
+ // Skool lesson content is typically in a styled div below the video
442
+ // Look for common content container patterns
443
+ const contentSelectors = [
444
+ '[class*="LessonContent"]',
445
+ '[class*="PostContent"]',
446
+ '[class*="ContentWrapper"]',
447
+ '[class*="content-body"]',
448
+ "article",
449
+ '[class*="prose"]',
450
+ ];
451
+ for (const selector of contentSelectors) {
452
+ const element = document.querySelector(selector);
453
+ if (element?.textContent && element.textContent.trim().length > 50) {
454
+ // Clone to avoid modifying the actual page
455
+ const clone = element.cloneNode(true);
456
+ // Remove unwanted elements
457
+ const unwanted = clone.querySelectorAll("script, style, nav, [class*='video'], [class*='Video'], iframe, [class*='player'], [class*='Player']");
458
+ unwanted.forEach((el) => {
459
+ el.remove();
460
+ });
461
+ return clone.innerHTML;
462
+ }
463
+ }
464
+ // Fallback: Try to find the main content area by structure
465
+ // Skool typically has: Header -> Video -> Content
466
+ const mainContent = document.querySelector("main, [class*='Main']");
467
+ if (mainContent) {
468
+ const clone = mainContent.cloneNode(true);
469
+ // Remove video player and navigation
470
+ const unwanted = clone.querySelectorAll("script, style, nav, header, [class*='video'], [class*='Video'], iframe, [class*='Sidebar'], [class*='sidebar']");
471
+ unwanted.forEach((el) => {
472
+ el.remove();
473
+ });
474
+ // Get remaining text content
475
+ const textContent = clone.innerHTML;
476
+ if (textContent.trim().length > 100) {
477
+ return textContent;
478
+ }
479
+ }
480
+ return "";
481
+ });
482
+ const markdown = html ? turndown.turndown(html) : "";
483
+ return { html, markdown };
484
+ }
485
+ /**
486
+ * File extensions we want to download.
487
+ */
488
+ const DOWNLOADABLE_EXTENSIONS = [
489
+ "pdf",
490
+ "doc",
491
+ "docx",
492
+ "xls",
493
+ "xlsx",
494
+ "ppt",
495
+ "pptx",
496
+ "zip",
497
+ "rar",
498
+ "7z",
499
+ "txt",
500
+ "csv",
501
+ "epub",
502
+ "mobi",
503
+ ];
504
+ /* v8 ignore stop */
505
+ /**
506
+ * Gets the file type from extension.
507
+ */
508
+ export function getFileType(ext) {
509
+ const lowerExt = ext.toLowerCase();
510
+ if (lowerExt === "pdf")
511
+ return "pdf";
512
+ if (lowerExt === "doc")
513
+ return "doc";
514
+ if (lowerExt === "docx")
515
+ return "docx";
516
+ if (lowerExt === "xls")
517
+ return "xls";
518
+ if (lowerExt === "xlsx")
519
+ return "xlsx";
520
+ if (lowerExt === "ppt")
521
+ return "ppt";
522
+ if (lowerExt === "pptx")
523
+ return "pptx";
524
+ if (["zip", "rar", "7z"].includes(lowerExt))
525
+ return "zip";
526
+ return "other";
527
+ }
528
+ /* v8 ignore start */
529
+ /**
530
+ * Extracts downloadable file links from the page content.
531
+ */
532
+ export async function extractDownloadableFiles(page) {
533
+ const files = await page.evaluate((extensions) => {
534
+ const results = [];
535
+ const seen = new Set();
536
+ // Find all links in the page
537
+ const links = document.querySelectorAll("a[href]");
538
+ for (const link of Array.from(links)) {
539
+ const href = link.href;
540
+ if (!href || seen.has(href))
541
+ continue;
542
+ // Check if the URL ends with a downloadable extension
543
+ const urlWithoutQuery = href.split("?")[0] ?? href;
544
+ const ext = urlWithoutQuery.split(".").pop()?.toLowerCase() ?? "";
545
+ if (extensions.includes(ext)) {
546
+ seen.add(href);
547
+ // Try to get filename from link text, download attribute, or URL
548
+ let filename = link.download;
549
+ if (!filename) {
550
+ filename = link.textContent?.trim() ?? "";
551
+ }
552
+ if (!filename || filename.length > 100) {
553
+ // Extract from URL
554
+ const urlParts = urlWithoutQuery.split("/");
555
+ filename = urlParts[urlParts.length - 1] ?? `file.${ext}`;
556
+ }
557
+ // Ensure filename has the correct extension
558
+ if (!filename.toLowerCase().endsWith(`.${ext}`)) {
559
+ filename = `${filename}.${ext}`;
560
+ }
561
+ // Sanitize filename
562
+ filename = filename.replace(/[<>:"/\\|?*]/g, "_").trim();
563
+ results.push({ url: href, filename, ext });
564
+ }
565
+ }
566
+ return results;
567
+ }, DOWNLOADABLE_EXTENSIONS);
568
+ return files.map((f) => ({
569
+ url: f.url,
570
+ filename: f.filename,
571
+ type: getFileType(f.ext),
572
+ }));
573
+ }
574
+ /**
575
+ * Extracts all content from a lesson page.
576
+ */
577
+ export async function extractLessonContent(page, lessonUrl) {
578
+ const currentUrl = page.url();
579
+ if (currentUrl !== lessonUrl) {
580
+ await page.goto(lessonUrl, { timeout: 30000 });
581
+ await page.waitForLoadState("domcontentloaded");
582
+ await page.waitForTimeout(2000);
583
+ }
584
+ const title = await page.title();
585
+ const { url: videoUrl, type: videoType } = await extractVideoUrl(page);
586
+ const { html: htmlContent, markdown: markdownContent } = await extractTextContent(page);
587
+ const downloadableFiles = await extractDownloadableFiles(page);
588
+ // Clean up title: "1. Lesson Name - Module Name · Course Name" -> "1. Lesson Name"
589
+ const cleanTitle = title.split(" - ")[0]?.trim() ?? title;
590
+ return {
591
+ title: cleanTitle,
592
+ videoUrl,
593
+ videoType,
594
+ htmlContent,
595
+ markdownContent,
596
+ downloadableFiles,
597
+ };
598
+ }
599
+ /* v8 ignore stop */
600
+ /**
601
+ * Extracts the Loom video ID from an embed URL.
602
+ */
603
+ export function extractLoomVideoId(embedUrl) {
604
+ const match = /loom\.com\/embed\/([a-f0-9]+)/.exec(embedUrl);
605
+ return match?.[1] ?? null;
606
+ }
607
+ /**
608
+ * Cleans and formats the markdown content.
609
+ */
610
+ export function formatMarkdown(title, content, videoUrl, videoType) {
611
+ const lines = [`# ${title}`, ""];
612
+ if (videoUrl) {
613
+ const videoLabel = videoType
614
+ ? `${videoType.charAt(0).toUpperCase()}${videoType.slice(1)}`
615
+ : "Video";
616
+ lines.push(`> 📺 ${videoLabel}: ${videoUrl}`, "");
617
+ }
618
+ if (content.trim()) {
619
+ lines.push(content);
620
+ }
621
+ // Clean up excessive newlines
622
+ return lines
623
+ .join("\n")
624
+ .replace(/\n{3,}/g, "\n\n")
625
+ .trim();
626
+ }
627
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/scraper/extractor.ts"],"names":[],"mappings":"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"}