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,676 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { CACHE_DIR } from "../config/paths.js";
|
|
5
|
+
/**
|
|
6
|
+
* Lesson sync status.
|
|
7
|
+
*/
|
|
8
|
+
export const LessonStatus = {
|
|
9
|
+
PENDING: "pending",
|
|
10
|
+
SCANNED: "scanned",
|
|
11
|
+
VALIDATED: "validated",
|
|
12
|
+
DOWNLOADED: "downloaded",
|
|
13
|
+
ERROR: "error",
|
|
14
|
+
SKIPPED: "skipped",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Video types supported by the tool.
|
|
18
|
+
*/
|
|
19
|
+
export const VideoType = {
|
|
20
|
+
LOOM: "loom",
|
|
21
|
+
VIMEO: "vimeo",
|
|
22
|
+
YOUTUBE: "youtube",
|
|
23
|
+
WISTIA: "wistia",
|
|
24
|
+
NATIVE: "native",
|
|
25
|
+
UNKNOWN: "unknown",
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Get the database directory path.
|
|
29
|
+
*/
|
|
30
|
+
export function getDbDir() {
|
|
31
|
+
return CACHE_DIR;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the database file path for a course.
|
|
35
|
+
*/
|
|
36
|
+
export function getDbPath(communitySlug) {
|
|
37
|
+
const safeSlug = communitySlug.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
38
|
+
return join(getDbDir(), `${safeSlug}.db`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract community slug from a Skool URL.
|
|
42
|
+
*/
|
|
43
|
+
export function extractCommunitySlug(url) {
|
|
44
|
+
const match = /skool\.com\/([^/]+)/.exec(url);
|
|
45
|
+
return match?.[1] ?? "unknown";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Database manager for course state persistence.
|
|
49
|
+
*/
|
|
50
|
+
export class CourseDatabase {
|
|
51
|
+
db;
|
|
52
|
+
constructor(communitySlug) {
|
|
53
|
+
const dbPath = getDbPath(communitySlug);
|
|
54
|
+
// Ensure directory exists
|
|
55
|
+
const dir = dirname(dbPath);
|
|
56
|
+
if (!existsSync(dir)) {
|
|
57
|
+
mkdirSync(dir, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
this.db = new Database(dbPath);
|
|
60
|
+
this.db.pragma("journal_mode = WAL");
|
|
61
|
+
this.initSchema();
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Initialize database schema.
|
|
65
|
+
*/
|
|
66
|
+
initSchema() {
|
|
67
|
+
this.db.exec(`
|
|
68
|
+
CREATE TABLE IF NOT EXISTS metadata (
|
|
69
|
+
key TEXT PRIMARY KEY,
|
|
70
|
+
value TEXT NOT NULL
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
CREATE TABLE IF NOT EXISTS modules (
|
|
74
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
75
|
+
slug TEXT UNIQUE NOT NULL,
|
|
76
|
+
name TEXT NOT NULL,
|
|
77
|
+
position INTEGER NOT NULL,
|
|
78
|
+
is_locked INTEGER DEFAULT 0,
|
|
79
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
80
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
CREATE TABLE IF NOT EXISTS lessons (
|
|
84
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
85
|
+
module_id INTEGER NOT NULL,
|
|
86
|
+
slug TEXT NOT NULL,
|
|
87
|
+
name TEXT NOT NULL,
|
|
88
|
+
url TEXT NOT NULL,
|
|
89
|
+
position INTEGER NOT NULL,
|
|
90
|
+
is_locked INTEGER DEFAULT 0,
|
|
91
|
+
status TEXT DEFAULT 'pending',
|
|
92
|
+
video_type TEXT,
|
|
93
|
+
video_url TEXT,
|
|
94
|
+
hls_url TEXT,
|
|
95
|
+
error_message TEXT,
|
|
96
|
+
error_code TEXT,
|
|
97
|
+
last_scanned_at TEXT,
|
|
98
|
+
last_downloaded_at TEXT,
|
|
99
|
+
video_file_size INTEGER,
|
|
100
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
101
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
102
|
+
FOREIGN KEY (module_id) REFERENCES modules(id),
|
|
103
|
+
UNIQUE(module_id, slug)
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_lessons_status ON lessons(status);
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_lessons_module ON lessons(module_id);
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_lessons_locked ON lessons(is_locked);
|
|
109
|
+
`);
|
|
110
|
+
// Run migrations for existing databases
|
|
111
|
+
this.runMigrations();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Run database migrations for schema updates.
|
|
115
|
+
*/
|
|
116
|
+
runMigrations() {
|
|
117
|
+
const tableInfo = this.db.prepare("PRAGMA table_info(lessons)").all();
|
|
118
|
+
// Migration: Add is_locked column if it doesn't exist
|
|
119
|
+
const hasIsLocked = tableInfo.some((col) => col.name === "is_locked");
|
|
120
|
+
if (!hasIsLocked) {
|
|
121
|
+
this.db.exec("ALTER TABLE lessons ADD COLUMN is_locked INTEGER DEFAULT 0");
|
|
122
|
+
}
|
|
123
|
+
// Migration: Add retry_count column if it doesn't exist
|
|
124
|
+
const hasRetryCount = tableInfo.some((col) => col.name === "retry_count");
|
|
125
|
+
if (!hasRetryCount) {
|
|
126
|
+
this.db.exec("ALTER TABLE lessons ADD COLUMN retry_count INTEGER DEFAULT 0");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Close the database connection.
|
|
131
|
+
*/
|
|
132
|
+
close() {
|
|
133
|
+
this.db.close();
|
|
134
|
+
}
|
|
135
|
+
// ============================================
|
|
136
|
+
// Metadata Operations
|
|
137
|
+
// ============================================
|
|
138
|
+
/**
|
|
139
|
+
* Set a metadata value.
|
|
140
|
+
*/
|
|
141
|
+
setMetadata(key, value) {
|
|
142
|
+
const stmt = this.db.prepare(`
|
|
143
|
+
INSERT INTO metadata (key, value) VALUES (?, ?)
|
|
144
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
145
|
+
`);
|
|
146
|
+
stmt.run(key, value);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get a metadata value.
|
|
150
|
+
*/
|
|
151
|
+
getMetadata(key) {
|
|
152
|
+
const stmt = this.db.prepare("SELECT value FROM metadata WHERE key = ?");
|
|
153
|
+
const row = stmt.get(key);
|
|
154
|
+
return row?.value ?? null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get all course metadata.
|
|
158
|
+
*/
|
|
159
|
+
getCourseMetadata() {
|
|
160
|
+
return {
|
|
161
|
+
name: this.getMetadata("course_name") ?? "Unknown Course",
|
|
162
|
+
url: this.getMetadata("course_url") ?? "",
|
|
163
|
+
lastSyncAt: this.getMetadata("last_sync_at"),
|
|
164
|
+
totalModules: this.getModuleCount(),
|
|
165
|
+
totalLessons: this.getLessonCount(),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Update course metadata after sync.
|
|
170
|
+
*/
|
|
171
|
+
updateCourseMetadata(name, url) {
|
|
172
|
+
this.setMetadata("course_name", name);
|
|
173
|
+
this.setMetadata("course_url", url);
|
|
174
|
+
this.setMetadata("last_sync_at", new Date().toISOString());
|
|
175
|
+
}
|
|
176
|
+
// ============================================
|
|
177
|
+
// Module Operations
|
|
178
|
+
// ============================================
|
|
179
|
+
/**
|
|
180
|
+
* Upsert a module (insert or update).
|
|
181
|
+
*/
|
|
182
|
+
upsertModule(slug, name, position, isLocked = false) {
|
|
183
|
+
const stmt = this.db.prepare(`
|
|
184
|
+
INSERT INTO modules (slug, name, position, is_locked, updated_at)
|
|
185
|
+
VALUES (?, ?, ?, ?, datetime('now'))
|
|
186
|
+
ON CONFLICT(slug) DO UPDATE SET
|
|
187
|
+
name = excluded.name,
|
|
188
|
+
position = excluded.position,
|
|
189
|
+
is_locked = excluded.is_locked,
|
|
190
|
+
updated_at = datetime('now')
|
|
191
|
+
RETURNING *
|
|
192
|
+
`);
|
|
193
|
+
const row = stmt.get(slug, name, position, isLocked ? 1 : 0);
|
|
194
|
+
return this.mapModuleRow(row);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get all modules.
|
|
198
|
+
*/
|
|
199
|
+
getModules() {
|
|
200
|
+
const stmt = this.db.prepare("SELECT * FROM modules ORDER BY position");
|
|
201
|
+
const rows = stmt.all();
|
|
202
|
+
return rows.map((row) => this.mapModuleRow(row));
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get module count.
|
|
206
|
+
*/
|
|
207
|
+
getModuleCount() {
|
|
208
|
+
const stmt = this.db.prepare("SELECT COUNT(*) as count FROM modules");
|
|
209
|
+
const row = stmt.get();
|
|
210
|
+
return row.count;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get module by slug.
|
|
214
|
+
*/
|
|
215
|
+
getModuleBySlug(slug) {
|
|
216
|
+
const stmt = this.db.prepare("SELECT * FROM modules WHERE slug = ?");
|
|
217
|
+
const row = stmt.get(slug);
|
|
218
|
+
return row ? this.mapModuleRow(row) : null;
|
|
219
|
+
}
|
|
220
|
+
mapModuleRow(row) {
|
|
221
|
+
return {
|
|
222
|
+
id: row.id,
|
|
223
|
+
slug: row.slug,
|
|
224
|
+
name: row.name,
|
|
225
|
+
position: row.position,
|
|
226
|
+
isLocked: row.is_locked === 1,
|
|
227
|
+
createdAt: row.created_at,
|
|
228
|
+
updatedAt: row.updated_at,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
// ============================================
|
|
232
|
+
// Lesson Operations
|
|
233
|
+
// ============================================
|
|
234
|
+
/**
|
|
235
|
+
* Upsert a lesson (insert or update).
|
|
236
|
+
*/
|
|
237
|
+
upsertLesson(moduleId, slug, name, url, position, isLocked = false) {
|
|
238
|
+
const stmt = this.db.prepare(`
|
|
239
|
+
INSERT INTO lessons (module_id, slug, name, url, position, is_locked, updated_at)
|
|
240
|
+
VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
|
|
241
|
+
ON CONFLICT(module_id, slug) DO UPDATE SET
|
|
242
|
+
name = excluded.name,
|
|
243
|
+
url = excluded.url,
|
|
244
|
+
position = excluded.position,
|
|
245
|
+
is_locked = excluded.is_locked,
|
|
246
|
+
updated_at = datetime('now')
|
|
247
|
+
RETURNING *
|
|
248
|
+
`);
|
|
249
|
+
const row = stmt.get(moduleId, slug, name, url, position, isLocked ? 1 : 0);
|
|
250
|
+
return this.mapLessonRow(row);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Update lesson scan results.
|
|
254
|
+
*/
|
|
255
|
+
updateLessonScan(lessonId, videoType, videoUrl, hlsUrl, status, errorMessage, errorCode) {
|
|
256
|
+
const stmt = this.db.prepare(`
|
|
257
|
+
UPDATE lessons SET
|
|
258
|
+
video_type = ?,
|
|
259
|
+
video_url = ?,
|
|
260
|
+
hls_url = ?,
|
|
261
|
+
status = ?,
|
|
262
|
+
error_message = ?,
|
|
263
|
+
error_code = ?,
|
|
264
|
+
last_scanned_at = datetime('now'),
|
|
265
|
+
updated_at = datetime('now')
|
|
266
|
+
WHERE id = ?
|
|
267
|
+
`);
|
|
268
|
+
stmt.run(videoType, videoUrl, hlsUrl, status, errorMessage ?? null, errorCode ?? null, lessonId);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Mark lesson as downloaded.
|
|
272
|
+
*/
|
|
273
|
+
markLessonDownloaded(lessonId, fileSize) {
|
|
274
|
+
const stmt = this.db.prepare(`
|
|
275
|
+
UPDATE lessons SET
|
|
276
|
+
status = 'downloaded',
|
|
277
|
+
last_downloaded_at = datetime('now'),
|
|
278
|
+
video_file_size = ?,
|
|
279
|
+
error_message = NULL,
|
|
280
|
+
error_code = NULL,
|
|
281
|
+
updated_at = datetime('now')
|
|
282
|
+
WHERE id = ?
|
|
283
|
+
`);
|
|
284
|
+
stmt.run(fileSize ?? null, lessonId);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Mark lesson as error.
|
|
288
|
+
*/
|
|
289
|
+
markLessonError(lessonId, errorMessage, errorCode) {
|
|
290
|
+
const stmt = this.db.prepare(`
|
|
291
|
+
UPDATE lessons SET
|
|
292
|
+
status = 'error',
|
|
293
|
+
error_message = ?,
|
|
294
|
+
error_code = ?,
|
|
295
|
+
updated_at = datetime('now')
|
|
296
|
+
WHERE id = ?
|
|
297
|
+
`);
|
|
298
|
+
stmt.run(errorMessage, errorCode ?? null, lessonId);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Mark lesson as skipped (no video).
|
|
302
|
+
*/
|
|
303
|
+
markLessonSkipped(lessonId, reason) {
|
|
304
|
+
const stmt = this.db.prepare(`
|
|
305
|
+
UPDATE lessons SET
|
|
306
|
+
status = 'skipped',
|
|
307
|
+
error_message = ?,
|
|
308
|
+
error_code = NULL,
|
|
309
|
+
updated_at = datetime('now')
|
|
310
|
+
WHERE id = ?
|
|
311
|
+
`);
|
|
312
|
+
stmt.run(reason ?? null, lessonId);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Update lesson video type.
|
|
316
|
+
*/
|
|
317
|
+
updateLessonVideoType(lessonId, videoType) {
|
|
318
|
+
const stmt = this.db.prepare(`
|
|
319
|
+
UPDATE lessons SET
|
|
320
|
+
video_type = ?,
|
|
321
|
+
updated_at = datetime('now')
|
|
322
|
+
WHERE id = ?
|
|
323
|
+
`);
|
|
324
|
+
stmt.run(videoType, lessonId);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Increment retry count for a lesson.
|
|
328
|
+
*/
|
|
329
|
+
incrementRetryCount(lessonId) {
|
|
330
|
+
const stmt = this.db.prepare(`
|
|
331
|
+
UPDATE lessons SET
|
|
332
|
+
retry_count = retry_count + 1,
|
|
333
|
+
updated_at = datetime('now')
|
|
334
|
+
WHERE id = ?
|
|
335
|
+
`);
|
|
336
|
+
stmt.run(lessonId);
|
|
337
|
+
// Return the new retry count
|
|
338
|
+
const getStmt = this.db.prepare("SELECT retry_count FROM lessons WHERE id = ?");
|
|
339
|
+
const row = getStmt.get(lessonId);
|
|
340
|
+
return row?.retry_count ?? 0;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Reset retry count for a lesson.
|
|
344
|
+
*/
|
|
345
|
+
resetRetryCount(lessonId) {
|
|
346
|
+
const stmt = this.db.prepare(`
|
|
347
|
+
UPDATE lessons SET
|
|
348
|
+
retry_count = 0,
|
|
349
|
+
updated_at = datetime('now')
|
|
350
|
+
WHERE id = ?
|
|
351
|
+
`);
|
|
352
|
+
stmt.run(lessonId);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get lessons that failed but can still be retried (retry_count < maxRetries).
|
|
356
|
+
* Only returns retryable errors (not UNSUPPORTED_PROVIDER).
|
|
357
|
+
*/
|
|
358
|
+
getLessonsToRetry(maxRetries = 3) {
|
|
359
|
+
const stmt = this.db.prepare(`
|
|
360
|
+
SELECT
|
|
361
|
+
l.*,
|
|
362
|
+
m.name as module_name,
|
|
363
|
+
m.slug as module_slug,
|
|
364
|
+
m.position as module_position
|
|
365
|
+
FROM lessons l
|
|
366
|
+
JOIN modules m ON l.module_id = m.id
|
|
367
|
+
WHERE l.status = 'error'
|
|
368
|
+
AND l.retry_count < ?
|
|
369
|
+
AND (l.error_code IS NULL OR l.error_code NOT IN ('UNSUPPORTED_PROVIDER'))
|
|
370
|
+
ORDER BY m.position, l.position
|
|
371
|
+
`);
|
|
372
|
+
const rows = stmt.all(maxRetries);
|
|
373
|
+
return rows.map((row) => ({
|
|
374
|
+
...this.mapLessonRow(row),
|
|
375
|
+
moduleName: row.module_name,
|
|
376
|
+
moduleSlug: row.module_slug,
|
|
377
|
+
modulePosition: row.module_position,
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Mark a lesson for retry by setting it back to pending/validated status.
|
|
382
|
+
*/
|
|
383
|
+
queueForRetry(lessonId, targetStatus = LessonStatus.PENDING) {
|
|
384
|
+
const stmt = this.db.prepare(`
|
|
385
|
+
UPDATE lessons SET
|
|
386
|
+
status = ?,
|
|
387
|
+
error_message = NULL,
|
|
388
|
+
error_code = NULL,
|
|
389
|
+
updated_at = datetime('now')
|
|
390
|
+
WHERE id = ?
|
|
391
|
+
`);
|
|
392
|
+
stmt.run(targetStatus, lessonId);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Get all lessons.
|
|
396
|
+
*/
|
|
397
|
+
getLessons() {
|
|
398
|
+
const stmt = this.db.prepare("SELECT * FROM lessons ORDER BY module_id, position");
|
|
399
|
+
const rows = stmt.all();
|
|
400
|
+
return rows.map((row) => this.mapLessonRow(row));
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Get lessons with module info.
|
|
404
|
+
*/
|
|
405
|
+
getLessonsWithModules() {
|
|
406
|
+
const stmt = this.db.prepare(`
|
|
407
|
+
SELECT
|
|
408
|
+
l.*,
|
|
409
|
+
m.name as module_name,
|
|
410
|
+
m.slug as module_slug,
|
|
411
|
+
m.position as module_position
|
|
412
|
+
FROM lessons l
|
|
413
|
+
JOIN modules m ON l.module_id = m.id
|
|
414
|
+
ORDER BY m.position, l.position
|
|
415
|
+
`);
|
|
416
|
+
const rows = stmt.all();
|
|
417
|
+
return rows.map((row) => ({
|
|
418
|
+
...this.mapLessonRow(row),
|
|
419
|
+
moduleName: row.module_name,
|
|
420
|
+
moduleSlug: row.module_slug,
|
|
421
|
+
modulePosition: row.module_position,
|
|
422
|
+
}));
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Get lessons by status.
|
|
426
|
+
*/
|
|
427
|
+
getLessonsByStatus(status) {
|
|
428
|
+
const stmt = this.db.prepare(`
|
|
429
|
+
SELECT
|
|
430
|
+
l.*,
|
|
431
|
+
m.name as module_name,
|
|
432
|
+
m.slug as module_slug,
|
|
433
|
+
m.position as module_position
|
|
434
|
+
FROM lessons l
|
|
435
|
+
JOIN modules m ON l.module_id = m.id
|
|
436
|
+
WHERE l.status = ?
|
|
437
|
+
ORDER BY m.position, l.position
|
|
438
|
+
`);
|
|
439
|
+
const rows = stmt.all(status);
|
|
440
|
+
return rows.map((row) => ({
|
|
441
|
+
...this.mapLessonRow(row),
|
|
442
|
+
moduleName: row.module_name,
|
|
443
|
+
moduleSlug: row.module_slug,
|
|
444
|
+
modulePosition: row.module_position,
|
|
445
|
+
}));
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Get lessons that need scanning (pending or never scanned).
|
|
449
|
+
*/
|
|
450
|
+
getLessonsToScan() {
|
|
451
|
+
const stmt = this.db.prepare(`
|
|
452
|
+
SELECT
|
|
453
|
+
l.*,
|
|
454
|
+
m.name as module_name,
|
|
455
|
+
m.slug as module_slug,
|
|
456
|
+
m.position as module_position
|
|
457
|
+
FROM lessons l
|
|
458
|
+
JOIN modules m ON l.module_id = m.id
|
|
459
|
+
WHERE (l.status = 'pending' OR l.last_scanned_at IS NULL)
|
|
460
|
+
AND l.is_locked = 0
|
|
461
|
+
ORDER BY m.position, l.position
|
|
462
|
+
`);
|
|
463
|
+
const rows = stmt.all();
|
|
464
|
+
return rows.map((row) => ({
|
|
465
|
+
...this.mapLessonRow(row),
|
|
466
|
+
moduleName: row.module_name,
|
|
467
|
+
moduleSlug: row.module_slug,
|
|
468
|
+
modulePosition: row.module_position,
|
|
469
|
+
}));
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Get lessons that need validation (scanned but not validated, with video).
|
|
473
|
+
*/
|
|
474
|
+
getLessonsToValidate() {
|
|
475
|
+
const stmt = this.db.prepare(`
|
|
476
|
+
SELECT
|
|
477
|
+
l.*,
|
|
478
|
+
m.name as module_name,
|
|
479
|
+
m.slug as module_slug,
|
|
480
|
+
m.position as module_position
|
|
481
|
+
FROM lessons l
|
|
482
|
+
JOIN modules m ON l.module_id = m.id
|
|
483
|
+
WHERE l.status = 'scanned'
|
|
484
|
+
AND l.video_url IS NOT NULL
|
|
485
|
+
AND l.is_locked = 0
|
|
486
|
+
ORDER BY m.position, l.position
|
|
487
|
+
`);
|
|
488
|
+
const rows = stmt.all();
|
|
489
|
+
return rows.map((row) => ({
|
|
490
|
+
...this.mapLessonRow(row),
|
|
491
|
+
moduleName: row.module_name,
|
|
492
|
+
moduleSlug: row.module_slug,
|
|
493
|
+
modulePosition: row.module_position,
|
|
494
|
+
}));
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Get lessons that are ready for download (validated with HLS URL).
|
|
498
|
+
*/
|
|
499
|
+
getLessonsToDownload() {
|
|
500
|
+
const stmt = this.db.prepare(`
|
|
501
|
+
SELECT
|
|
502
|
+
l.*,
|
|
503
|
+
m.name as module_name,
|
|
504
|
+
m.slug as module_slug,
|
|
505
|
+
m.position as module_position
|
|
506
|
+
FROM lessons l
|
|
507
|
+
JOIN modules m ON l.module_id = m.id
|
|
508
|
+
WHERE l.status = 'validated' AND l.hls_url IS NOT NULL
|
|
509
|
+
ORDER BY m.position, l.position
|
|
510
|
+
`);
|
|
511
|
+
const rows = stmt.all();
|
|
512
|
+
return rows.map((row) => ({
|
|
513
|
+
...this.mapLessonRow(row),
|
|
514
|
+
moduleName: row.module_name,
|
|
515
|
+
moduleSlug: row.module_slug,
|
|
516
|
+
modulePosition: row.module_position,
|
|
517
|
+
}));
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Get lesson count.
|
|
521
|
+
*/
|
|
522
|
+
getLessonCount() {
|
|
523
|
+
const stmt = this.db.prepare("SELECT COUNT(*) as count FROM lessons");
|
|
524
|
+
const row = stmt.get();
|
|
525
|
+
return row.count;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Get lesson by URL.
|
|
529
|
+
*/
|
|
530
|
+
getLessonByUrl(url) {
|
|
531
|
+
const stmt = this.db.prepare("SELECT * FROM lessons WHERE url = ?");
|
|
532
|
+
const row = stmt.get(url);
|
|
533
|
+
return row ? this.mapLessonRow(row) : null;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Get status summary.
|
|
537
|
+
*/
|
|
538
|
+
getStatusSummary() {
|
|
539
|
+
const stmt = this.db.prepare(`
|
|
540
|
+
SELECT status, COUNT(*) as count FROM lessons GROUP BY status
|
|
541
|
+
`);
|
|
542
|
+
const rows = stmt.all();
|
|
543
|
+
const summary = {
|
|
544
|
+
pending: 0,
|
|
545
|
+
scanned: 0,
|
|
546
|
+
validated: 0,
|
|
547
|
+
downloaded: 0,
|
|
548
|
+
error: 0,
|
|
549
|
+
skipped: 0,
|
|
550
|
+
locked: 0,
|
|
551
|
+
};
|
|
552
|
+
for (const row of rows) {
|
|
553
|
+
summary[row.status] = row.count;
|
|
554
|
+
}
|
|
555
|
+
// Count locked lessons separately
|
|
556
|
+
const lockedStmt = this.db.prepare(`SELECT COUNT(*) as count FROM lessons WHERE is_locked = 1`);
|
|
557
|
+
const lockedRow = lockedStmt.get();
|
|
558
|
+
summary.locked = lockedRow.count;
|
|
559
|
+
return summary;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Reset all error lessons to pending for retry.
|
|
563
|
+
*/
|
|
564
|
+
resetErrorLessons() {
|
|
565
|
+
const stmt = this.db.prepare(`
|
|
566
|
+
UPDATE lessons SET
|
|
567
|
+
status = 'pending',
|
|
568
|
+
error_message = NULL,
|
|
569
|
+
error_code = NULL,
|
|
570
|
+
updated_at = datetime('now')
|
|
571
|
+
WHERE status = 'error'
|
|
572
|
+
`);
|
|
573
|
+
const result = stmt.run();
|
|
574
|
+
return result.changes;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Reset ALL lessons to pending (for --force full rescan).
|
|
578
|
+
* Preserves locked status.
|
|
579
|
+
*/
|
|
580
|
+
resetAllLessonsToPending() {
|
|
581
|
+
const stmt = this.db.prepare(`
|
|
582
|
+
UPDATE lessons SET
|
|
583
|
+
status = 'pending',
|
|
584
|
+
video_type = NULL,
|
|
585
|
+
video_url = NULL,
|
|
586
|
+
hls_url = NULL,
|
|
587
|
+
error_message = NULL,
|
|
588
|
+
error_code = NULL,
|
|
589
|
+
retry_count = 0,
|
|
590
|
+
updated_at = datetime('now')
|
|
591
|
+
WHERE is_locked = 0
|
|
592
|
+
`);
|
|
593
|
+
const result = stmt.run();
|
|
594
|
+
return result.changes;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Reset error lessons to validated (for --resume --retry-errors).
|
|
598
|
+
* Only resets lessons that already have an HLS URL.
|
|
599
|
+
*/
|
|
600
|
+
resetErrorLessonsForResume() {
|
|
601
|
+
const stmt = this.db.prepare(`
|
|
602
|
+
UPDATE lessons SET
|
|
603
|
+
status = 'validated',
|
|
604
|
+
error_message = NULL,
|
|
605
|
+
error_code = NULL,
|
|
606
|
+
updated_at = datetime('now')
|
|
607
|
+
WHERE status = 'error' AND hls_url IS NOT NULL
|
|
608
|
+
`);
|
|
609
|
+
const result = stmt.run();
|
|
610
|
+
return result.changes;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Get lessons by error code.
|
|
614
|
+
*/
|
|
615
|
+
getLessonsByErrorCode(errorCode) {
|
|
616
|
+
const stmt = this.db.prepare(`
|
|
617
|
+
SELECT
|
|
618
|
+
l.*,
|
|
619
|
+
m.name as module_name,
|
|
620
|
+
m.slug as module_slug,
|
|
621
|
+
m.position as module_position
|
|
622
|
+
FROM lessons l
|
|
623
|
+
JOIN modules m ON l.module_id = m.id
|
|
624
|
+
WHERE l.error_code = ?
|
|
625
|
+
ORDER BY m.position, l.position
|
|
626
|
+
`);
|
|
627
|
+
const rows = stmt.all(errorCode);
|
|
628
|
+
return rows.map((row) => ({
|
|
629
|
+
...this.mapLessonRow(row),
|
|
630
|
+
moduleName: row.module_name,
|
|
631
|
+
moduleSlug: row.module_slug,
|
|
632
|
+
modulePosition: row.module_position,
|
|
633
|
+
}));
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Get count of lessons grouped by video type.
|
|
637
|
+
*/
|
|
638
|
+
getVideoTypeSummary() {
|
|
639
|
+
const stmt = this.db.prepare(`
|
|
640
|
+
SELECT video_type, COUNT(*) as count
|
|
641
|
+
FROM lessons
|
|
642
|
+
WHERE video_type IS NOT NULL
|
|
643
|
+
GROUP BY video_type
|
|
644
|
+
`);
|
|
645
|
+
const rows = stmt.all();
|
|
646
|
+
const summary = {};
|
|
647
|
+
for (const row of rows) {
|
|
648
|
+
summary[row.video_type] = row.count;
|
|
649
|
+
}
|
|
650
|
+
return summary;
|
|
651
|
+
}
|
|
652
|
+
mapLessonRow(row) {
|
|
653
|
+
return {
|
|
654
|
+
id: row.id,
|
|
655
|
+
moduleId: row.module_id,
|
|
656
|
+
slug: row.slug,
|
|
657
|
+
name: row.name,
|
|
658
|
+
url: row.url,
|
|
659
|
+
position: row.position,
|
|
660
|
+
isLocked: row.is_locked === 1,
|
|
661
|
+
status: row.status,
|
|
662
|
+
videoType: row.video_type,
|
|
663
|
+
videoUrl: row.video_url,
|
|
664
|
+
hlsUrl: row.hls_url,
|
|
665
|
+
errorMessage: row.error_message,
|
|
666
|
+
errorCode: row.error_code,
|
|
667
|
+
retryCount: row.retry_count ?? 0,
|
|
668
|
+
lastScannedAt: row.last_scanned_at,
|
|
669
|
+
lastDownloadedAt: row.last_downloaded_at,
|
|
670
|
+
videoFileSize: row.video_file_size,
|
|
671
|
+
createdAt: row.created_at,
|
|
672
|
+
updatedAt: row.updated_at,
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/state/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.test.d.ts","sourceRoot":"","sources":["../../src/state/database.test.ts"],"names":[],"mappings":""}
|