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