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.
- package/.github/workflows/ci.yml +50 -0
- package/.husky/commit-msg +2 -0
- package/.husky/pre-commit +1 -0
- package/.husky/pre-push +3 -0
- package/.prettierrc +8 -0
- package/.release-it.json +23 -0
- package/ARCHITECTURE.md +233 -0
- package/CHANGELOG.md +78 -0
- package/README.md +256 -16
- package/commitlint.config.js +4 -0
- package/dist/ai/openRouter.d.ts +47 -0
- package/dist/ai/openRouter.d.ts.map +1 -0
- package/dist/ai/openRouter.js +116 -0
- package/dist/ai/openRouter.js.map +1 -0
- package/dist/ai/transcriptPolisher.d.ts +24 -0
- package/dist/ai/transcriptPolisher.d.ts.map +1 -0
- package/dist/ai/transcriptPolisher.js +89 -0
- package/dist/ai/transcriptPolisher.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +66 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/enrich.d.ts +14 -0
- package/dist/cli/commands/enrich.d.ts.map +1 -0
- package/dist/cli/commands/enrich.js +271 -0
- package/dist/cli/commands/enrich.js.map +1 -0
- package/dist/cli/commands/inspect.d.ts +11 -0
- package/dist/cli/commands/inspect.d.ts.map +1 -0
- package/dist/cli/commands/inspect.js +365 -0
- package/dist/cli/commands/inspect.js.map +1 -0
- package/dist/cli/commands/login.d.ts +12 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +55 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/status.d.ts +15 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +118 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +16 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +922 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/syncGhl.d.ts +20 -0
- package/dist/cli/commands/syncGhl.d.ts.map +1 -0
- package/dist/cli/commands/syncGhl.js +483 -0
- package/dist/cli/commands/syncGhl.js.map +1 -0
- package/dist/cli/commands/syncHighLevel.d.ts +24 -0
- package/dist/cli/commands/syncHighLevel.d.ts.map +1 -0
- package/dist/cli/commands/syncHighLevel.js +483 -0
- package/dist/cli/commands/syncHighLevel.js.map +1 -0
- package/dist/cli/commands/syncHighLevel.test.d.ts +2 -0
- package/dist/cli/commands/syncHighLevel.test.d.ts.map +1 -0
- package/dist/cli/commands/syncHighLevel.test.js +102 -0
- package/dist/cli/commands/syncHighLevel.test.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +106 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/configManager.d.ts +31 -0
- package/dist/config/configManager.d.ts.map +1 -0
- package/dist/config/configManager.js +64 -0
- package/dist/config/configManager.js.map +1 -0
- package/dist/config/paths.d.ts +21 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +33 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/paths.test.d.ts +2 -0
- package/dist/config/paths.test.d.ts.map +1 -0
- package/dist/config/paths.test.js +70 -0
- package/dist/config/paths.test.js.map +1 -0
- package/dist/config/schema.d.ts +60 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +50 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/schema.test.d.ts +2 -0
- package/dist/config/schema.test.d.ts.map +1 -0
- package/dist/config/schema.test.js +151 -0
- package/dist/config/schema.test.js.map +1 -0
- package/dist/downloader/hlsDownloader.d.ts +58 -0
- package/dist/downloader/hlsDownloader.d.ts.map +1 -0
- package/dist/downloader/hlsDownloader.js +254 -0
- package/dist/downloader/hlsDownloader.js.map +1 -0
- package/dist/downloader/hlsDownloader.test.d.ts +2 -0
- package/dist/downloader/hlsDownloader.test.d.ts.map +1 -0
- package/dist/downloader/hlsDownloader.test.js +116 -0
- package/dist/downloader/hlsDownloader.test.js.map +1 -0
- package/dist/downloader/hlsValidator.d.ts +35 -0
- package/dist/downloader/hlsValidator.d.ts.map +1 -0
- package/dist/downloader/hlsValidator.js +148 -0
- package/dist/downloader/hlsValidator.js.map +1 -0
- package/dist/downloader/index.d.ts +26 -0
- package/dist/downloader/index.d.ts.map +1 -0
- package/dist/downloader/index.js +52 -0
- package/dist/downloader/index.js.map +1 -0
- package/dist/downloader/loomDownloader.d.ts +56 -0
- package/dist/downloader/loomDownloader.d.ts.map +1 -0
- package/dist/downloader/loomDownloader.js +559 -0
- package/dist/downloader/loomDownloader.js.map +1 -0
- package/dist/downloader/loomDownloader.test.d.ts +2 -0
- package/dist/downloader/loomDownloader.test.d.ts.map +1 -0
- package/dist/downloader/loomDownloader.test.js +36 -0
- package/dist/downloader/loomDownloader.test.js.map +1 -0
- package/dist/downloader/queue.d.ts +56 -0
- package/dist/downloader/queue.d.ts.map +1 -0
- package/dist/downloader/queue.js +88 -0
- package/dist/downloader/queue.js.map +1 -0
- package/dist/downloader/queue.test.d.ts +2 -0
- package/dist/downloader/queue.test.d.ts.map +1 -0
- package/dist/downloader/queue.test.js +158 -0
- package/dist/downloader/queue.test.js.map +1 -0
- package/dist/downloader/videoDownloader.d.ts +32 -0
- package/dist/downloader/videoDownloader.d.ts.map +1 -0
- package/dist/downloader/videoDownloader.js +173 -0
- package/dist/downloader/videoDownloader.js.map +1 -0
- package/dist/downloader/vimeoDownloader.d.ts +52 -0
- package/dist/downloader/vimeoDownloader.d.ts.map +1 -0
- package/dist/downloader/vimeoDownloader.js +565 -0
- package/dist/downloader/vimeoDownloader.js.map +1 -0
- package/dist/downloader/vimeoDownloader.test.d.ts +2 -0
- package/dist/downloader/vimeoDownloader.test.d.ts.map +1 -0
- package/dist/downloader/vimeoDownloader.test.js +51 -0
- package/dist/downloader/vimeoDownloader.test.js.map +1 -0
- package/dist/scraper/auth.d.ts +29 -0
- package/dist/scraper/auth.d.ts.map +1 -0
- package/dist/scraper/auth.js +115 -0
- package/dist/scraper/auth.js.map +1 -0
- package/dist/scraper/extractor.d.ts +49 -0
- package/dist/scraper/extractor.d.ts.map +1 -0
- package/dist/scraper/extractor.js +627 -0
- package/dist/scraper/extractor.js.map +1 -0
- package/dist/scraper/extractor.test.d.ts +2 -0
- package/dist/scraper/extractor.test.d.ts.map +1 -0
- package/dist/scraper/extractor.test.js +65 -0
- package/dist/scraper/extractor.test.js.map +1 -0
- package/dist/scraper/ghl/auth.d.ts +25 -0
- package/dist/scraper/ghl/auth.d.ts.map +1 -0
- package/dist/scraper/ghl/auth.js +187 -0
- package/dist/scraper/ghl/auth.js.map +1 -0
- package/dist/scraper/ghl/extractor.d.ts +96 -0
- package/dist/scraper/ghl/extractor.d.ts.map +1 -0
- package/dist/scraper/ghl/extractor.js +345 -0
- package/dist/scraper/ghl/extractor.js.map +1 -0
- package/dist/scraper/ghl/index.d.ts +4 -0
- package/dist/scraper/ghl/index.d.ts.map +1 -0
- package/dist/scraper/ghl/index.js +4 -0
- package/dist/scraper/ghl/index.js.map +1 -0
- package/dist/scraper/ghl/navigator.d.ts +93 -0
- package/dist/scraper/ghl/navigator.d.ts.map +1 -0
- package/dist/scraper/ghl/navigator.js +447 -0
- package/dist/scraper/ghl/navigator.js.map +1 -0
- package/dist/scraper/highlevel/auth.d.ts +25 -0
- package/dist/scraper/highlevel/auth.d.ts.map +1 -0
- package/dist/scraper/highlevel/auth.js +189 -0
- package/dist/scraper/highlevel/auth.js.map +1 -0
- package/dist/scraper/highlevel/extractor.d.ts +97 -0
- package/dist/scraper/highlevel/extractor.d.ts.map +1 -0
- package/dist/scraper/highlevel/extractor.js +386 -0
- package/dist/scraper/highlevel/extractor.js.map +1 -0
- package/dist/scraper/highlevel/extractor.test.d.ts +2 -0
- package/dist/scraper/highlevel/extractor.test.d.ts.map +1 -0
- package/dist/scraper/highlevel/extractor.test.js +101 -0
- package/dist/scraper/highlevel/extractor.test.js.map +1 -0
- package/dist/scraper/highlevel/index.d.ts +3 -0
- package/dist/scraper/highlevel/index.d.ts.map +1 -0
- package/dist/scraper/highlevel/index.js +3 -0
- package/dist/scraper/highlevel/index.js.map +1 -0
- package/dist/scraper/highlevel/navigator.d.ts +93 -0
- package/dist/scraper/highlevel/navigator.d.ts.map +1 -0
- package/dist/scraper/highlevel/navigator.js +492 -0
- package/dist/scraper/highlevel/navigator.js.map +1 -0
- package/dist/scraper/highlevel/navigator.test.d.ts +2 -0
- package/dist/scraper/highlevel/navigator.test.d.ts.map +1 -0
- package/dist/scraper/highlevel/navigator.test.js +78 -0
- package/dist/scraper/highlevel/navigator.test.js.map +1 -0
- package/dist/scraper/navigator.d.ts +65 -0
- package/dist/scraper/navigator.d.ts.map +1 -0
- package/dist/scraper/navigator.js +300 -0
- package/dist/scraper/navigator.js.map +1 -0
- package/dist/scraper/navigator.test.d.ts +2 -0
- package/dist/scraper/navigator.test.d.ts.map +1 -0
- package/dist/scraper/navigator.test.js +63 -0
- package/dist/scraper/navigator.test.js.map +1 -0
- package/dist/scraper/skoolApi.d.ts +17 -0
- package/dist/scraper/skoolApi.d.ts.map +1 -0
- package/dist/scraper/skoolApi.js +72 -0
- package/dist/scraper/skoolApi.js.map +1 -0
- package/dist/scraper/videoInterceptor.d.ts +19 -0
- package/dist/scraper/videoInterceptor.d.ts.map +1 -0
- package/dist/scraper/videoInterceptor.js +315 -0
- package/dist/scraper/videoInterceptor.js.map +1 -0
- package/dist/shared/auth.d.ts +58 -0
- package/dist/shared/auth.d.ts.map +1 -0
- package/dist/shared/auth.js +211 -0
- package/dist/shared/auth.js.map +1 -0
- package/dist/shared/fs.d.ts +31 -0
- package/dist/shared/fs.d.ts.map +1 -0
- package/dist/shared/fs.js +73 -0
- package/dist/shared/fs.js.map +1 -0
- package/dist/shared/http.d.ts +15 -0
- package/dist/shared/http.d.ts.map +1 -0
- package/dist/shared/http.js +31 -0
- package/dist/shared/http.js.map +1 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/state/database.d.ts +245 -0
- package/dist/state/database.d.ts.map +1 -0
- package/dist/state/database.js +676 -0
- package/dist/state/database.js.map +1 -0
- package/dist/state/database.test.d.ts +2 -0
- package/dist/state/database.test.d.ts.map +1 -0
- package/dist/state/database.test.js +34 -0
- package/dist/state/database.test.js.map +1 -0
- package/dist/state/index.d.ts +2 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +2 -0
- package/dist/state/index.js.map +1 -0
- package/dist/storage/fileSystem.d.ts +56 -0
- package/dist/storage/fileSystem.d.ts.map +1 -0
- package/dist/storage/fileSystem.js +121 -0
- package/dist/storage/fileSystem.js.map +1 -0
- package/dist/transcription/whisperService.d.ts +27 -0
- package/dist/transcription/whisperService.d.ts.map +1 -0
- package/dist/transcription/whisperService.js +102 -0
- package/dist/transcription/whisperService.js.map +1 -0
- package/eslint.config.js +55 -0
- package/package.json +68 -11
- package/src/__fixtures__/highlevel-post-response.json +68 -0
- package/src/__fixtures__/hls-master-playlist.m3u8 +24 -0
- package/src/cli/commands/__snapshots__/syncHighLevel.test.ts.snap +38 -0
- package/src/cli/commands/config.ts +74 -0
- package/src/cli/commands/inspect.ts +441 -0
- package/src/cli/commands/login.ts +68 -0
- package/src/cli/commands/status.ts +147 -0
- package/src/cli/commands/sync.ts +1235 -0
- package/src/cli/commands/syncHighLevel.test.ts +144 -0
- package/src/cli/commands/syncHighLevel.ts +639 -0
- package/src/cli/index.ts +121 -0
- package/src/config/configManager.ts +75 -0
- package/src/config/paths.test.ts +83 -0
- package/src/config/paths.ts +36 -0
- package/src/config/schema.test.ts +173 -0
- package/src/config/schema.ts +65 -0
- package/src/downloader/hlsDownloader.test.ts +148 -0
- package/src/downloader/hlsDownloader.ts +327 -0
- package/src/downloader/hlsValidator.ts +196 -0
- package/src/downloader/index.ts +122 -0
- package/src/downloader/loomDownloader.test.ts +43 -0
- package/src/downloader/loomDownloader.ts +742 -0
- package/src/downloader/queue.test.ts +199 -0
- package/src/downloader/queue.ts +118 -0
- package/src/downloader/vimeoDownloader.test.ts +62 -0
- package/src/downloader/vimeoDownloader.ts +722 -0
- package/src/scraper/extractor.test.ts +124 -0
- package/src/scraper/extractor.ts +757 -0
- package/src/scraper/highlevel/__snapshots__/extractor.test.ts.snap +41 -0
- package/src/scraper/highlevel/extractor.test.ts +134 -0
- package/src/scraper/highlevel/extractor.ts +537 -0
- package/src/scraper/highlevel/index.ts +2 -0
- package/src/scraper/highlevel/navigator.test.ts +110 -0
- package/src/scraper/highlevel/navigator.ts +668 -0
- package/src/scraper/highlevel/schemas.ts +183 -0
- package/src/scraper/navigator.test.ts +122 -0
- package/src/scraper/navigator.ts +355 -0
- package/src/scraper/schemas.ts +177 -0
- package/src/scraper/videoInterceptor.ts +435 -0
- package/src/shared/auth.test.ts +58 -0
- package/src/shared/auth.ts +251 -0
- package/src/shared/firebase.ts +151 -0
- package/src/shared/fs.ts +80 -0
- package/src/shared/http.ts +34 -0
- package/src/shared/index.ts +6 -0
- package/src/shared/slug.ts +26 -0
- package/src/shared/url.test.ts +122 -0
- package/src/shared/url.ts +57 -0
- package/src/state/database.test.ts +49 -0
- package/src/state/database.ts +919 -0
- package/src/state/index.ts +14 -0
- package/src/storage/fileSystem.test.ts +64 -0
- package/src/storage/fileSystem.ts +175 -0
- package/tsconfig.json +28 -0
- package/vitest.config.ts +29 -0
- package/cli.js +0 -45
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
16
|
+
node-version: [22, 24]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout repository
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup Node.js ${{ matrix.node-version }}
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: ${{ matrix.node-version }}
|
|
26
|
+
cache: "npm"
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: npm ci
|
|
30
|
+
|
|
31
|
+
- name: Type check
|
|
32
|
+
run: npm run typecheck
|
|
33
|
+
|
|
34
|
+
- name: Lint
|
|
35
|
+
run: npm run lint
|
|
36
|
+
|
|
37
|
+
- name: Run tests with coverage
|
|
38
|
+
run: npm run test:coverage
|
|
39
|
+
|
|
40
|
+
- name: Upload coverage to Codecov
|
|
41
|
+
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 22
|
|
42
|
+
uses: codecov/codecov-action@v5
|
|
43
|
+
with:
|
|
44
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
45
|
+
files: ./coverage/lcov.info
|
|
46
|
+
fail_ci_if_error: false
|
|
47
|
+
verbose: true
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
package/.husky/pre-push
ADDED
package/.prettierrc
ADDED
package/.release-it.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"git": {
|
|
3
|
+
"commitMessage": "chore: release v${version}",
|
|
4
|
+
"tagName": "v${version}",
|
|
5
|
+
"requireBranch": "main"
|
|
6
|
+
},
|
|
7
|
+
"github": {
|
|
8
|
+
"release": true,
|
|
9
|
+
"releaseName": "v${version}"
|
|
10
|
+
},
|
|
11
|
+
"npm": {
|
|
12
|
+
"publish": true
|
|
13
|
+
},
|
|
14
|
+
"plugins": {
|
|
15
|
+
"@release-it/conventional-changelog": {
|
|
16
|
+
"preset": "conventionalcommits",
|
|
17
|
+
"infile": "CHANGELOG.md"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"hooks": {
|
|
21
|
+
"before:init": ["npm run lint", "npm run typecheck", "npm test run"]
|
|
22
|
+
}
|
|
23
|
+
}
|
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Offcourse is a modular CLI tool for downloading online courses. The architecture is designed to support multiple learning platforms through a plugin-like pattern.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ CLI Layer │
|
|
10
|
+
│ (commands: login, sync, sync-skool, sync-highlevel, etc.) │
|
|
11
|
+
└─────────────────────────────────────────────────────────────┘
|
|
12
|
+
│
|
|
13
|
+
┌───────────────────┼───────────────────┐
|
|
14
|
+
▼ ▼ ▼
|
|
15
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
16
|
+
│ Scraper │ │ Downloader │ │ Storage │
|
|
17
|
+
│ (per platform) │ │ (per video host)│ │ (file system) │
|
|
18
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
19
|
+
│ │ │
|
|
20
|
+
└───────────────────┼───────────────────┘
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────┐
|
|
23
|
+
│ Config │
|
|
24
|
+
│ (Zod schemas) │
|
|
25
|
+
└─────────────────┘
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Directory Structure
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
src/
|
|
32
|
+
├── cli/ # Command-line interface
|
|
33
|
+
│ ├── index.ts # Entry point, command registration
|
|
34
|
+
│ └── commands/
|
|
35
|
+
│ ├── config.ts # Configuration management
|
|
36
|
+
│ ├── inspect.ts # Page analysis for debugging
|
|
37
|
+
│ ├── login.ts # Authentication flow
|
|
38
|
+
│ ├── sync.ts # Skool download orchestration
|
|
39
|
+
│ └── syncHighLevel.ts # HighLevel download orchestration
|
|
40
|
+
│
|
|
41
|
+
├── config/ # Configuration management
|
|
42
|
+
│ ├── schema.ts # Zod schemas for all config types
|
|
43
|
+
│ ├── configManager.ts # Load/save configuration
|
|
44
|
+
│ └── paths.ts # Path resolution utilities
|
|
45
|
+
│
|
|
46
|
+
├── scraper/ # Platform-specific extraction
|
|
47
|
+
│ ├── auth.ts # Session management (Playwright) - Skool
|
|
48
|
+
│ ├── navigator.ts # Course structure discovery - Skool
|
|
49
|
+
│ ├── extractor.ts # Content extraction - Skool
|
|
50
|
+
│ ├── videoInterceptor.ts # Network interception for video URLs
|
|
51
|
+
│ └── highlevel/ # HighLevel (GoHighLevel) scraper
|
|
52
|
+
│ ├── auth.ts # Firebase auth, session management
|
|
53
|
+
│ ├── navigator.ts # Course structure via API
|
|
54
|
+
│ ├── extractor.ts # Video/content extraction
|
|
55
|
+
│ └── index.ts # Exports
|
|
56
|
+
│
|
|
57
|
+
├── downloader/ # Video download handlers
|
|
58
|
+
│ ├── index.ts # Download dispatcher by video type
|
|
59
|
+
│ ├── queue.ts # Async queue with concurrency control
|
|
60
|
+
│ ├── loomDownloader.ts # Loom-specific HLS download
|
|
61
|
+
│ ├── vimeoDownloader.ts # Vimeo-specific download
|
|
62
|
+
│ └── hlsDownloader.ts # Generic HLS download (ffmpeg-based)
|
|
63
|
+
│
|
|
64
|
+
├── state/ # State management
|
|
65
|
+
│ ├── index.ts # State exports
|
|
66
|
+
│ └── database.ts # SQLite database for sync state
|
|
67
|
+
│
|
|
68
|
+
└── storage/ # File system operations
|
|
69
|
+
└── fileSystem.ts # Directory creation, file saving
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Key Components
|
|
73
|
+
|
|
74
|
+
### CLI Layer (`src/cli/`)
|
|
75
|
+
|
|
76
|
+
Handles user interaction via Commander.js. Each command is a separate module.
|
|
77
|
+
|
|
78
|
+
- **login**: Opens browser for interactive authentication, saves session
|
|
79
|
+
- **sync**: Auto-detects platform and delegates to appropriate handler
|
|
80
|
+
- **sync-skool**: Skool-specific sync (uses `sync.ts`)
|
|
81
|
+
- **sync-highlevel**: HighLevel-specific sync (uses `syncHighLevel.ts`)
|
|
82
|
+
- **inspect**: Debug tool for analyzing page structure
|
|
83
|
+
- **config**: Read/write configuration values
|
|
84
|
+
|
|
85
|
+
### Scraper (`src/scraper/`)
|
|
86
|
+
|
|
87
|
+
Platform-specific logic for extracting course content.
|
|
88
|
+
|
|
89
|
+
#### Skool Scraper (root level)
|
|
90
|
+
|
|
91
|
+
- **auth.ts**: Manages Playwright browser sessions, session persistence
|
|
92
|
+
- **navigator.ts**: Discovers course structure (modules, lessons, URLs)
|
|
93
|
+
- **extractor.ts**: Extracts video URLs and text content from lesson pages
|
|
94
|
+
- **videoInterceptor.ts**: Intercepts network requests to capture video URLs
|
|
95
|
+
|
|
96
|
+
#### HighLevel Scraper (`src/scraper/highlevel/`)
|
|
97
|
+
|
|
98
|
+
- **auth.ts**: Firebase authentication, session management with token refresh
|
|
99
|
+
- **navigator.ts**: Extracts course structure via API interception
|
|
100
|
+
- **extractor.ts**: Extracts HLS video URLs, embedded videos (Vimeo, Loom), and content
|
|
101
|
+
|
|
102
|
+
To add a new platform, create a new directory under `src/scraper/` with the same interfaces.
|
|
103
|
+
|
|
104
|
+
### Downloader (`src/downloader/`)
|
|
105
|
+
|
|
106
|
+
Video download handlers. Each video host needs its own implementation.
|
|
107
|
+
|
|
108
|
+
- **queue.ts**: Generic async queue with concurrency control and retry logic
|
|
109
|
+
- **loomDownloader.ts**: Handles Loom's HLS streaming format
|
|
110
|
+
- **vimeoDownloader.ts**: Handles Vimeo video downloads
|
|
111
|
+
- **hlsDownloader.ts**: Generic HLS download using ffmpeg (used for HighLevel native videos)
|
|
112
|
+
- **index.ts**: Dispatcher that routes downloads by video type
|
|
113
|
+
|
|
114
|
+
### State (`src/state/`)
|
|
115
|
+
|
|
116
|
+
Persistent state management using SQLite.
|
|
117
|
+
|
|
118
|
+
- **database.ts**: Manages sync state, tracks downloaded content
|
|
119
|
+
- Enables resume functionality for interrupted syncs
|
|
120
|
+
|
|
121
|
+
### Storage (`src/storage/`)
|
|
122
|
+
|
|
123
|
+
File system abstraction for saving content.
|
|
124
|
+
|
|
125
|
+
- Creates directory structure mirroring course hierarchy
|
|
126
|
+
- Saves markdown content and video files
|
|
127
|
+
- Tracks sync state to enable resume
|
|
128
|
+
|
|
129
|
+
### Config (`src/config/`)
|
|
130
|
+
|
|
131
|
+
Centralized configuration with Zod validation.
|
|
132
|
+
|
|
133
|
+
- **schema.ts**: Type-safe schemas for all configuration
|
|
134
|
+
- **configManager.ts**: Persists config to `~/.offcourse/`
|
|
135
|
+
- **paths.ts**: Path resolution utilities
|
|
136
|
+
|
|
137
|
+
## Data Flow
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
1. User runs: offcourse sync <url>
|
|
141
|
+
│
|
|
142
|
+
2. Auto-detect │
|
|
143
|
+
platform ────────────► Skool? HighLevel? Unknown?
|
|
144
|
+
│
|
|
145
|
+
3. Load config │
|
|
146
|
+
▼
|
|
147
|
+
4. Authenticate ─────────► Browser session (cached or interactive)
|
|
148
|
+
│
|
|
149
|
+
5. Navigate ────────────► Extract course structure (modules, lessons)
|
|
150
|
+
│
|
|
151
|
+
6. For each lesson: │
|
|
152
|
+
├─► Extract ─────────► Get video URL + text content
|
|
153
|
+
├─► Save content ────► Write Markdown to disk
|
|
154
|
+
└─► Queue video ─────► Add to download queue
|
|
155
|
+
│
|
|
156
|
+
7. Process queue ───────► Download videos with concurrency control
|
|
157
|
+
│
|
|
158
|
+
8. Done ────────────────► Summary output
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Platform-Specific Details
|
|
162
|
+
|
|
163
|
+
### Skool
|
|
164
|
+
|
|
165
|
+
- **Auth**: Standard session-based, browser login
|
|
166
|
+
- **Structure**: DOM-based extraction via Playwright selectors
|
|
167
|
+
- **Videos**: Loom, Vimeo, native video elements
|
|
168
|
+
|
|
169
|
+
### HighLevel (GoHighLevel)
|
|
170
|
+
|
|
171
|
+
- **Auth**: Firebase authentication via `sso.clientclub.net`
|
|
172
|
+
- **Structure**: API-based extraction (`services.leadconnectorhq.com`)
|
|
173
|
+
- **Videos**: Native HLS streams, Vimeo, Loom embeds
|
|
174
|
+
- **Special**: Requires ffmpeg for native video downloads
|
|
175
|
+
|
|
176
|
+
## Adding a New Platform
|
|
177
|
+
|
|
178
|
+
1. **Create scraper directory**: `src/scraper/<platform>/`
|
|
179
|
+
2. **Implement modules**:
|
|
180
|
+
- `auth.ts` - Authentication flow
|
|
181
|
+
- `navigator.ts` - Course structure extraction
|
|
182
|
+
- `extractor.ts` - Content/video extraction
|
|
183
|
+
- `index.ts` - Exports
|
|
184
|
+
3. **Create CLI command**: `src/cli/commands/sync<Platform>.ts`
|
|
185
|
+
4. **Register in CLI**: Add to `src/cli/index.ts`
|
|
186
|
+
5. **Add auto-detection**: Update `sync` command's platform detection
|
|
187
|
+
|
|
188
|
+
## Adding a New Video Host
|
|
189
|
+
|
|
190
|
+
1. **Create downloader**: Implement in `src/downloader/<host>Downloader.ts`
|
|
191
|
+
2. **Export from index**: Add to `src/downloader/index.ts` dispatcher
|
|
192
|
+
3. **Update extractor**: Add detection in platform-specific `extractVideoUrl()`
|
|
193
|
+
|
|
194
|
+
## Technology Choices
|
|
195
|
+
|
|
196
|
+
| Purpose | Technology | Rationale |
|
|
197
|
+
|---------|------------|-----------|
|
|
198
|
+
| Browser automation | Playwright | Reliable, handles SPAs, session persistence |
|
|
199
|
+
| CLI framework | Commander.js | Standard, declarative command definition |
|
|
200
|
+
| Validation | Zod | Runtime validation with TypeScript inference |
|
|
201
|
+
| HTML → Markdown | Turndown | Mature, configurable |
|
|
202
|
+
| Styling | Chalk + Ora | Clean terminal output with spinners |
|
|
203
|
+
| Database | better-sqlite3 | Fast, embedded SQLite for state management |
|
|
204
|
+
| HLS downloads | ffmpeg | Industry standard for HLS stream processing |
|
|
205
|
+
|
|
206
|
+
## Development Tooling
|
|
207
|
+
|
|
208
|
+
| Tool | Purpose | Configuration |
|
|
209
|
+
|------|---------|---------------|
|
|
210
|
+
| TypeScript | Type safety | `tsconfig.json` |
|
|
211
|
+
| ESLint | Linting | `eslint.config.js` |
|
|
212
|
+
| Prettier | Code formatting | `.prettierrc` (defaults) |
|
|
213
|
+
| Vitest | Testing | `vitest.config.ts` |
|
|
214
|
+
| Husky | Git hooks | `.husky/` |
|
|
215
|
+
| lint-staged | Pre-commit formatting | `package.json` |
|
|
216
|
+
| commitlint | Commit message validation | `commitlint.config.js` |
|
|
217
|
+
| release-it | Release management | `.release-it.json` |
|
|
218
|
+
|
|
219
|
+
### Git Hooks
|
|
220
|
+
|
|
221
|
+
- **pre-commit**: Formats staged files with Prettier via lint-staged
|
|
222
|
+
- **pre-push**: Runs ESLint and TypeScript type checking
|
|
223
|
+
- **commit-msg**: Validates conventional commit format
|
|
224
|
+
|
|
225
|
+
### Release Process
|
|
226
|
+
|
|
227
|
+
Releases use [release-it](https://github.com/release-it/release-it) with the conventional changelog plugin:
|
|
228
|
+
|
|
229
|
+
1. Validates code (lint, typecheck, test)
|
|
230
|
+
2. Determines version bump from commit history
|
|
231
|
+
3. Updates `CHANGELOG.md` with categorized changes
|
|
232
|
+
4. Creates Git tag and GitHub release
|
|
233
|
+
5. Publishes to npm
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0 (2025-12-22)
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* The 'enrich' command for transcribing videos is no longer available
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add --resume flag and fix HLS URL handling in downloaders ([163055b](https://github.com/sebastian-software/offcourse/commit/163055b343345aa60bf3babd1b4bb33443d61616))
|
|
12
|
+
* add detailed error reporting and retry logic for Loom downloads ([177e92d](https://github.com/sebastian-software/offcourse/commit/177e92d5b5a30d959b6582327fb16d6337916ea1))
|
|
13
|
+
* add fast mode to skip images, fonts, CSS during scraping ([bc7a128](https://github.com/sebastian-software/offcourse/commit/bc7a12836470b914bd1b515ab04fda5a5c6e705b))
|
|
14
|
+
* add HighLevel (GoHighLevel) course scraper support ([04c15f8](https://github.com/sebastian-software/offcourse/commit/04c15f832381d3fbfde82e3f0847bf32f7e590c2))
|
|
15
|
+
* add network interception fallback for video URL capture ([fc36f6d](https://github.com/sebastian-software/offcourse/commit/fc36f6d03e5d17f681114fea791454453c5e819f))
|
|
16
|
+
* add OpenRouter integration for transcript polishing ([22487f2](https://github.com/sebastian-software/offcourse/commit/22487f2300bc1b9ac1b5be98db695094cca4bf54))
|
|
17
|
+
* add tsx for dev, detect locked lessons ([809c9fd](https://github.com/sebastian-software/offcourse/commit/809c9fdd6ae9a06e2fa038d020bdff18f275505c))
|
|
18
|
+
* add video transcription with Whisper ([06f9edd](https://github.com/sebastian-software/offcourse/commit/06f9eddf56c4181e4d7530c7a39ca23c25d1a0f0))
|
|
19
|
+
* add video type prefix [LOOM], [VIMEO] etc. to output ([bba70e7](https://github.com/sebastian-software/offcourse/commit/bba70e7581c39b9fd3e9934496cd2b50106418c6))
|
|
20
|
+
* add Vimeo video download support ([64ecde7](https://github.com/sebastian-software/offcourse/commit/64ecde76081749ff232732493ede602e7013be44))
|
|
21
|
+
* add Zod schemas for API response validation ([1fec40f](https://github.com/sebastian-software/offcourse/commit/1fec40f49a0bd6900b46eeab5d95cbf6381e01ca))
|
|
22
|
+
* beautiful multi-progress bars for parallel downloads ([cfe6e01](https://github.com/sebastian-software/offcourse/commit/cfe6e012eb70d283475e8963e0be08bbf24d7501))
|
|
23
|
+
* **cli:** add Commander-based CLI with sync, login, inspect commands ([53b53e1](https://github.com/sebastian-software/offcourse/commit/53b53e10de11d3ceefabe16f17a3b1a50cec73c4))
|
|
24
|
+
* **config:** add configuration system with Zod validation ([552e5c8](https://github.com/sebastian-software/offcourse/commit/552e5c8d3bebb60d443275b8bcf8e0bec44d38df))
|
|
25
|
+
* detect and track locked lessons separately ([8a62c9a](https://github.com/sebastian-software/offcourse/commit/8a62c9aa860e375dee8853aeecaa244668e88fd4))
|
|
26
|
+
* download linked PDF and Office files from lessons ([6e838be](https://github.com/sebastian-software/offcourse/commit/6e838beabc1f4e75505cffa2712f567c39be4941))
|
|
27
|
+
* **downloader:** add HLS streaming support for Loom videos ([2dfcae1](https://github.com/sebastian-software/offcourse/commit/2dfcae1a746075bc68882efc26c49b21aeaf7796))
|
|
28
|
+
* **downloader:** add native video downloader with queue system ([8c6e236](https://github.com/sebastian-software/offcourse/commit/8c6e23620682c72fd403eb4360931ce91c4fb5ec))
|
|
29
|
+
* extract Vimeo URLs from running player in iframe ([ba68bbe](https://github.com/sebastian-software/offcourse/commit/ba68bbe2db305531bfcda0b8a10d4d845715603b))
|
|
30
|
+
* format transcripts with paragraphs ([cd16eb8](https://github.com/sebastian-software/offcourse/commit/cd16eb8d3f0205802927a0623ad124a7407dff9b))
|
|
31
|
+
* improve download progress display and file size reporting ([c5a548c](https://github.com/sebastian-software/offcourse/commit/c5a548c0c601c7c493a616eb44a982aee70ba56a))
|
|
32
|
+
* improve locked lesson detection using hasAccess from JSON ([6b2e3e8](https://github.com/sebastian-software/offcourse/commit/6b2e3e80fe8a425e032dff8179389bb0963e920f))
|
|
33
|
+
* improved logging for unsupported video providers ([f808169](https://github.com/sebastian-software/offcourse/commit/f808169ef88bda9006cf12955f3e0b154fdc9ae6))
|
|
34
|
+
* parallel downloads for faster video syncing ([95d12f2](https://github.com/sebastian-software/offcourse/commit/95d12f2071281544523bd069980c1449c47acf7e))
|
|
35
|
+
* progress bar for Phase 1 (course structure scanning) ([2017425](https://github.com/sebastian-software/offcourse/commit/201742583b4842ebe6f1d01a39c4280988e15ba2))
|
|
36
|
+
* progress bars for validation and content extraction phases ([324be59](https://github.com/sebastian-software/offcourse/commit/324be597ed04e1d04f70e4c58139b2dc65648129))
|
|
37
|
+
* remove AI transcription and enrich feature ([7ba6327](https://github.com/sebastian-software/offcourse/commit/7ba632753a5e08d67a653ff24452d83bd3406eb7))
|
|
38
|
+
* **scraper:** add Playwright-based Skool scraper ([b9b111f](https://github.com/sebastian-software/offcourse/commit/b9b111f6e22ad03c78fe14d040caeee0d510a901))
|
|
39
|
+
* separate summary.md and transcript.md, add module summaries ([fc49a60](https://github.com/sebastian-software/offcourse/commit/fc49a6097cf612ac3a63f6c060060febd0f6b8ed))
|
|
40
|
+
* SQLite state management, improved video detection, graceful shutdown ([fc001d7](https://github.com/sebastian-software/offcourse/commit/fc001d7a82705b59ed4973d66d7ca8a0406c7dd4))
|
|
41
|
+
* **storage:** add filesystem utilities for course output ([ef18545](https://github.com/sebastian-software/offcourse/commit/ef185453a9afc6d0ff373e8dd58ce812514d6b46))
|
|
42
|
+
* support domain-restricted Vimeo videos via browser context ([2b16e0c](https://github.com/sebastian-software/offcourse/commit/2b16e0c21f483ecbac3b22a9e09b5f8835367d79))
|
|
43
|
+
* use CDP network interception to capture video URLs from iframes ([b49a873](https://github.com/sebastian-software/offcourse/commit/b49a873a6a1f4db7285e673f80de85683f548332))
|
|
44
|
+
* use readable titles in summary and transcript files ([ad1377d](https://github.com/sebastian-software/offcourse/commit/ad1377d83bb07611adca439546969fb9c7fdc5b7))
|
|
45
|
+
|
|
46
|
+
### Bug Fixes
|
|
47
|
+
|
|
48
|
+
* --force flag now also resets error lessons for retry ([d20e7fb](https://github.com/sebastian-software/offcourse/commit/d20e7fb95ed98d7cd9d70d798baa888ce1cd60f5))
|
|
49
|
+
* --resume --retry-errors now works correctly ([bbe732d](https://github.com/sebastian-software/offcourse/commit/bbe732d36e43a421ff3faa9e81f2ccfc35841fd3))
|
|
50
|
+
* add autoplay=1 to embed URLs to trigger HLS fetch ([1ffa068](https://github.com/sebastian-software/offcourse/commit/1ffa068ece40553118d573b0b55ff14fecfb41f2))
|
|
51
|
+
* add conventional-changelog-conventionalcommits peer dependency ([84f4502](https://github.com/sebastian-software/offcourse/commit/84f45029e5a81e76ab16a5f38beae16197701664))
|
|
52
|
+
* add missing await to saveMarkdown call ([da6e1e7](https://github.com/sebastian-software/offcourse/commit/da6e1e7dc50de9441c7ff7fc2bb5f95ddbdbb3a9))
|
|
53
|
+
* capture Loom/Vimeo HLS by navigating to embed page ([6608bd9](https://github.com/sebastian-software/offcourse/commit/6608bd9f9eee6107912af259340fb68ce86701e0))
|
|
54
|
+
* clean download progress display - remove completed bars ([8334894](https://github.com/sebastian-software/offcourse/commit/83348940a44859dc3cd915c8415d473829f3d2d0))
|
|
55
|
+
* extract full iframe URLs with auth params for Vimeo ([e8fcec3](https://github.com/sebastian-software/offcourse/commit/e8fcec308c3208ba2fd1a47b012926d77d199acf))
|
|
56
|
+
* formatting ([4491c00](https://github.com/sebastian-software/offcourse/commit/4491c00ed610997b55314ed4d456e42325de5f3f))
|
|
57
|
+
* handle direct HLS URLs in Loom downloader ([974b7d6](https://github.com/sebastian-software/offcourse/commit/974b7d6e7024f2f711abd3be815f3fee64bd4b10))
|
|
58
|
+
* **highlevel:** correctly parse product API response for course name ([697ab07](https://github.com/sebastian-software/offcourse/commit/697ab07575e61e6cd85481743c79a2f1ca74cbfb))
|
|
59
|
+
* **highlevel:** fix video detection and default to headless mode ([e4dcf51](https://github.com/sebastian-software/offcourse/commit/e4dcf513b0b81ddfdfec9539ae4fa8ea1f0bb0ed))
|
|
60
|
+
* migrate to Zod 4 API for url and datetime validation ([7519b2c](https://github.com/sebastian-software/offcourse/commit/7519b2c3f5155a938d2ec55e8a5c7e70c371659b))
|
|
61
|
+
* mute videos during extraction to avoid audio output ([9150dc0](https://github.com/sebastian-software/offcourse/commit/9150dc09cac1e7c70eb9a9dd257a9e4f6fd924b9))
|
|
62
|
+
* mute videos during extraction to avoid audio output ([ee43c1c](https://github.com/sebastian-software/offcourse/commit/ee43c1c18c138aa014bdd913db871593adcd0dda))
|
|
63
|
+
* **navigator:** correctly handle module URLs vs classroom URLs ([a0e8763](https://github.com/sebastian-software/offcourse/commit/a0e8763c982a65ba7a38d59c9571dbeee577ac3f))
|
|
64
|
+
* prefix unused parameter with underscore in queue test ([076f9c4](https://github.com/sebastian-software/offcourse/commit/076f9c4f1906358075d4061c81b31aa1b579b8da))
|
|
65
|
+
* resolve lint errors in syncHighLevel.ts ([4af50d5](https://github.com/sebastian-software/offcourse/commit/4af50d5615ab260de7778e2248cf3fb0bedda851))
|
|
66
|
+
* simplify release-it preset config for v10 compatibility ([9f9748f](https://github.com/sebastian-software/offcourse/commit/9f9748f829f1a92b9c397d5ff4ab690ac044f8f7))
|
|
67
|
+
* use Playwright request API for Vimeo (avoids CORS) ([09a2386](https://github.com/sebastian-software/offcourse/commit/09a23867115bded76521e27e0afbda76970b50d2))
|
|
68
|
+
* use response listener instead of route interception ([cb63eee](https://github.com/sebastian-software/offcourse/commit/cb63eeeeb2d2e13f3d0cba22ed702b35c1b88525))
|
|
69
|
+
* use URL slug for output directory name ([804e4fb](https://github.com/sebastian-software/offcourse/commit/804e4fb9d99615feccf6973b1fc603f02336146a))
|
|
70
|
+
* version ([d17bbc7](https://github.com/sebastian-software/offcourse/commit/d17bbc7497e660634262af2d8047f96781ff4ac2))
|
|
71
|
+
|
|
72
|
+
### Performance Improvements
|
|
73
|
+
|
|
74
|
+
* reduce wait times and improve content extraction ([e306be2](https://github.com/sebastian-software/offcourse/commit/e306be27d8d021a273801c0f5739639cab3599f7))
|
|
75
|
+
|
|
76
|
+
All notable changes to this project will be documented in this file.
|
|
77
|
+
|
|
78
|
+
This changelog is automatically generated based on [Conventional Commits](https://www.conventionalcommits.org/).
|