skool-cli 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/LICENSE +21 -0
- package/README.md +179 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +33 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/create-folder.d.ts +3 -0
- package/dist/commands/create-folder.d.ts.map +1 -0
- package/dist/commands/create-folder.js +24 -0
- package/dist/commands/create-folder.js.map +1 -0
- package/dist/commands/create-lesson.d.ts +3 -0
- package/dist/commands/create-lesson.d.ts.map +1 -0
- package/dist/commands/create-lesson.js +35 -0
- package/dist/commands/create-lesson.js.map +1 -0
- package/dist/commands/create-post.d.ts +3 -0
- package/dist/commands/create-post.d.ts.map +1 -0
- package/dist/commands/create-post.js +36 -0
- package/dist/commands/create-post.js.map +1 -0
- package/dist/commands/debug-api.d.ts +3 -0
- package/dist/commands/debug-api.d.ts.map +1 -0
- package/dist/commands/debug-api.js +112 -0
- package/dist/commands/debug-api.js.map +1 -0
- package/dist/commands/debug-manual.d.ts +3 -0
- package/dist/commands/debug-manual.d.ts.map +1 -0
- package/dist/commands/debug-manual.js +66 -0
- package/dist/commands/debug-manual.js.map +1 -0
- package/dist/commands/debug.d.ts +3 -0
- package/dist/commands/debug.d.ts.map +1 -0
- package/dist/commands/debug.js +114 -0
- package/dist/commands/debug.js.map +1 -0
- package/dist/commands/delete-lesson.d.ts +3 -0
- package/dist/commands/delete-lesson.d.ts.map +1 -0
- package/dist/commands/delete-lesson.js +17 -0
- package/dist/commands/delete-lesson.js.map +1 -0
- package/dist/commands/get-categories.d.ts +3 -0
- package/dist/commands/get-categories.d.ts.map +1 -0
- package/dist/commands/get-categories.js +34 -0
- package/dist/commands/get-categories.js.map +1 -0
- package/dist/commands/get-members.d.ts +3 -0
- package/dist/commands/get-members.d.ts.map +1 -0
- package/dist/commands/get-members.js +35 -0
- package/dist/commands/get-members.js.map +1 -0
- package/dist/commands/get-posts.d.ts +3 -0
- package/dist/commands/get-posts.d.ts.map +1 -0
- package/dist/commands/get-posts.js +41 -0
- package/dist/commands/get-posts.js.map +1 -0
- package/dist/commands/list-lessons.d.ts +3 -0
- package/dist/commands/list-lessons.d.ts.map +1 -0
- package/dist/commands/list-lessons.js +45 -0
- package/dist/commands/list-lessons.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +30 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/test-api.d.ts +3 -0
- package/dist/commands/test-api.d.ts.map +1 -0
- package/dist/commands/test-api.js +143 -0
- package/dist/commands/test-api.js.map +1 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +17 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/core/browser-manager.d.ts +25 -0
- package/dist/core/browser-manager.d.ts.map +1 -0
- package/dist/core/browser-manager.js +104 -0
- package/dist/core/browser-manager.js.map +1 -0
- package/dist/core/config.d.ts +15 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +17 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/html-generator.d.ts +15 -0
- package/dist/core/html-generator.d.ts.map +1 -0
- package/dist/core/html-generator.js +254 -0
- package/dist/core/html-generator.js.map +1 -0
- package/dist/core/page-ops.d.ts +69 -0
- package/dist/core/page-ops.d.ts.map +1 -0
- package/dist/core/page-ops.js +511 -0
- package/dist/core/page-ops.js.map +1 -0
- package/dist/core/skool-api.d.ts +74 -0
- package/dist/core/skool-api.d.ts.map +1 -0
- package/dist/core/skool-api.js +389 -0
- package/dist/core/skool-api.js.map +1 -0
- package/dist/core/skool-client.d.ts +63 -0
- package/dist/core/skool-client.d.ts.map +1 -0
- package/dist/core/skool-client.js +501 -0
- package/dist/core/skool-client.js.map +1 -0
- package/dist/core/types.d.ts +58 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 UNIKPROMPT Technologies LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# skool-cli
|
|
2
|
+
|
|
3
|
+
CLI and programmatic API for [Skool.com](https://www.skool.com) automation. Create classroom lessons, community posts, and manage your Skool groups from the terminal.
|
|
4
|
+
|
|
5
|
+
**Skool has no public API.** This tool uses browser automation (Playwright) to give you full programmatic access to Skool's features.
|
|
6
|
+
|
|
7
|
+
## Killer Feature: Classroom Lessons
|
|
8
|
+
|
|
9
|
+
Create rich HTML lessons in Skool's classroom with a single command. Supports headers, lists, code blocks, bold, italic, links, and images via TipTap editor injection.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
skool create-lesson \
|
|
13
|
+
--group my-community \
|
|
14
|
+
--module "Getting Started" \
|
|
15
|
+
--title "Your First Lesson" \
|
|
16
|
+
--file lesson.md
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Install globally
|
|
23
|
+
npm install -g skool-cli
|
|
24
|
+
|
|
25
|
+
# Or run directly with npx
|
|
26
|
+
npx skool-cli login --email you@email.com --password yourpass
|
|
27
|
+
|
|
28
|
+
# Install browser (first time only)
|
|
29
|
+
npx playwright install chromium
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
### Authentication
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Login (saves session for future use)
|
|
38
|
+
skool login --email you@email.com --password yourpass
|
|
39
|
+
|
|
40
|
+
# Check session status
|
|
41
|
+
skool whoami --group my-community
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Classroom (Lessons)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Create lesson from markdown file
|
|
48
|
+
skool create-lesson -g my-community -m "Module Name" -t "Lesson Title" -f lesson.md
|
|
49
|
+
|
|
50
|
+
# Create lesson from HTML
|
|
51
|
+
skool create-lesson -g my-community -m "Module Name" -t "Lesson Title" --html lesson.html
|
|
52
|
+
|
|
53
|
+
# Create lesson from content JSON (with skool_class structure)
|
|
54
|
+
skool create-lesson -g my-community -m "Module Name" -t "Lesson Title" -f content.json
|
|
55
|
+
|
|
56
|
+
# Inline markdown
|
|
57
|
+
skool create-lesson -g my-community -m "Module Name" -t "Quick Tip" --markdown "## Hello\n\nThis is a lesson."
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Community (Posts)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Create a post
|
|
64
|
+
skool create-post -g my-community -t "Welcome!" -b "Hello everyone..."
|
|
65
|
+
|
|
66
|
+
# Create a post from file
|
|
67
|
+
skool create-post -g my-community -t "Weekly Update" -f post.txt -c "General"
|
|
68
|
+
|
|
69
|
+
# List posts
|
|
70
|
+
skool get-posts -g my-community
|
|
71
|
+
skool get-posts -g my-community --json
|
|
72
|
+
|
|
73
|
+
# List categories
|
|
74
|
+
skool get-categories -g my-community
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Members
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# List members
|
|
81
|
+
skool get-members -g my-community
|
|
82
|
+
|
|
83
|
+
# Search members
|
|
84
|
+
skool get-members -g my-community --search "mario"
|
|
85
|
+
|
|
86
|
+
# JSON output
|
|
87
|
+
skool get-members -g my-community --json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Programmatic API
|
|
91
|
+
|
|
92
|
+
Use `skool-cli` as a library in your Node.js projects:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { SkoolClient } from 'skool-cli';
|
|
96
|
+
|
|
97
|
+
const client = new SkoolClient();
|
|
98
|
+
|
|
99
|
+
// Login
|
|
100
|
+
await client.login('you@email.com', 'yourpass');
|
|
101
|
+
|
|
102
|
+
// Create a lesson
|
|
103
|
+
await client.createLesson({
|
|
104
|
+
group: 'my-community',
|
|
105
|
+
module: 'Getting Started',
|
|
106
|
+
title: 'Lesson 1',
|
|
107
|
+
markdownContent: '## Hello\n\nThis is a lesson.',
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Create a post
|
|
111
|
+
await client.createPost({
|
|
112
|
+
group: 'my-community',
|
|
113
|
+
title: 'Welcome!',
|
|
114
|
+
body: 'Hello everyone...',
|
|
115
|
+
category: 'General',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Read data
|
|
119
|
+
const { posts } = await client.getPosts('my-community');
|
|
120
|
+
const { categories } = await client.getCategories('my-community');
|
|
121
|
+
const { members } = await client.getMembers('my-community');
|
|
122
|
+
|
|
123
|
+
// Cleanup
|
|
124
|
+
await client.close();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Environment Variables
|
|
128
|
+
|
|
129
|
+
| Variable | Description |
|
|
130
|
+
|----------|-------------|
|
|
131
|
+
| `SKOOL_EMAIL` | Default email for login |
|
|
132
|
+
| `SKOOL_PASSWORD` | Default password for login |
|
|
133
|
+
| `SKOOL_GROUP` | Default group slug (avoids passing `--group` every time) |
|
|
134
|
+
| `SKOOL_CLI_HEADLESS` | Set to `false` for visible browser (debugging) |
|
|
135
|
+
| `SKOOL_CLI_DATA_DIR` | Custom data directory (default: `~/.skool-cli/`) |
|
|
136
|
+
| `SKOOL_CLI_TIMEOUT` | Operation timeout in ms (default: 30000) |
|
|
137
|
+
|
|
138
|
+
## How It Works
|
|
139
|
+
|
|
140
|
+
1. **Login**: Playwright opens a headless Chromium browser and logs into Skool
|
|
141
|
+
2. **Session persistence**: Browser profile is saved to `~/.skool-cli/browser-data/`, so subsequent runs reuse the session without re-logging in
|
|
142
|
+
3. **Operations**: Each command navigates to the appropriate Skool page and interacts with it programmatically
|
|
143
|
+
4. **TipTap injection**: For classroom lessons, HTML is injected directly into Skool's TipTap editor via `editor.commands.setContent()`
|
|
144
|
+
|
|
145
|
+
## Supported Content Formats
|
|
146
|
+
|
|
147
|
+
The `create-lesson` command accepts:
|
|
148
|
+
|
|
149
|
+
- **Markdown** (`.md`): Converted to TipTap-compatible HTML automatically
|
|
150
|
+
- **HTML** (`.html`): Injected directly into the editor
|
|
151
|
+
- **JSON** (`.json`): Extracts `skool_class` structure and converts to HTML (compatible with content pipeline JSONs)
|
|
152
|
+
|
|
153
|
+
### Supported HTML Elements
|
|
154
|
+
|
|
155
|
+
Headers (h1-h4), paragraphs, bold, italic, strikethrough, inline code, code blocks, ordered/unordered lists, blockquotes, horizontal rules, links, images.
|
|
156
|
+
|
|
157
|
+
**Not supported by Skool's editor**: Tables, iframes (except video embeds), forms.
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
| Issue | Solution |
|
|
162
|
+
|-------|----------|
|
|
163
|
+
| "Browser not found" | Run `npx playwright install chromium` |
|
|
164
|
+
| Login fails | Check email/password. Try `SKOOL_CLI_HEADLESS=false` to see the browser |
|
|
165
|
+
| Session expired | Run `skool login` again |
|
|
166
|
+
| SAVE button not working | Known Skool quirk. The CLI handles this automatically with a dirty-state trigger |
|
|
167
|
+
| Title too long | Automatically truncated to 50 characters |
|
|
168
|
+
| Community posts look plain | Skool community posts only support plain text (no HTML) |
|
|
169
|
+
|
|
170
|
+
## Learn More
|
|
171
|
+
|
|
172
|
+
- [TikTok @unikprompt](https://tiktok.com/@unikprompt) - Automation tutorials
|
|
173
|
+
- [Facebook: Claude Code en Espanol](https://facebook.com/groups/claudecodeenespanol) - Free community
|
|
174
|
+
- [Skool: Operadores Aumentados](https://skool.com/operadores-aumentados) - Premium community
|
|
175
|
+
- [UNIKPROMPT](https://unikprompt.com) - More tools and resources
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { loginCommand } from "./commands/login.js";
|
|
4
|
+
import { whoamiCommand } from "./commands/whoami.js";
|
|
5
|
+
import { createLessonCommand } from "./commands/create-lesson.js";
|
|
6
|
+
import { createFolderCommand } from "./commands/create-folder.js";
|
|
7
|
+
import { createPostCommand } from "./commands/create-post.js";
|
|
8
|
+
import { getPostsCommand } from "./commands/get-posts.js";
|
|
9
|
+
import { getCategoriesCommand } from "./commands/get-categories.js";
|
|
10
|
+
import { getMembersCommand } from "./commands/get-members.js";
|
|
11
|
+
import { deleteLessonCommand } from "./commands/delete-lesson.js";
|
|
12
|
+
import { listLessonsCommand } from "./commands/list-lessons.js";
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name("skool")
|
|
16
|
+
.description("CLI for Skool.com automation — create lessons, posts, and manage communities")
|
|
17
|
+
.version("1.0.0");
|
|
18
|
+
// Auth
|
|
19
|
+
program.addCommand(loginCommand);
|
|
20
|
+
program.addCommand(whoamiCommand);
|
|
21
|
+
// Classroom
|
|
22
|
+
program.addCommand(createLessonCommand);
|
|
23
|
+
program.addCommand(createFolderCommand);
|
|
24
|
+
program.addCommand(deleteLessonCommand);
|
|
25
|
+
program.addCommand(listLessonsCommand);
|
|
26
|
+
// Community
|
|
27
|
+
program.addCommand(createPostCommand);
|
|
28
|
+
program.addCommand(getPostsCommand);
|
|
29
|
+
program.addCommand(getCategoriesCommand);
|
|
30
|
+
// Members
|
|
31
|
+
program.addCommand(getMembersCommand);
|
|
32
|
+
program.parse();
|
|
33
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CACV,8EAA8E,CAC/E;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;AACP,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,YAAY;AACZ,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAEvC,YAAY;AACZ,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AAEzC,UAAU;AACV,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAEtC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-folder.d.ts","sourceRoot":"","sources":["../../src/commands/create-folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,mBAAmB,SAmB5B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { SkoolClient } from "../core/skool-client.js";
|
|
3
|
+
export const createFolderCommand = new Command("create-folder")
|
|
4
|
+
.description("Create a new folder (module) in a Skool classroom course")
|
|
5
|
+
.requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
|
|
6
|
+
.requiredOption("-t, --title <title>", "Folder name (max 50 chars)")
|
|
7
|
+
.option("--course <name>", "Course name (if multiple courses exist)")
|
|
8
|
+
.action(async (opts) => {
|
|
9
|
+
const client = new SkoolClient();
|
|
10
|
+
try {
|
|
11
|
+
console.log(`Creating folder "${opts.title}"...`);
|
|
12
|
+
const result = await client.createFolder({
|
|
13
|
+
group: opts.group,
|
|
14
|
+
title: opts.title,
|
|
15
|
+
course: opts.course,
|
|
16
|
+
});
|
|
17
|
+
console.log(result.success ? `OK: ${result.message}` : `FAIL: ${result.message}`);
|
|
18
|
+
process.exit(result.success ? 0 : 1);
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
await client.close();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=create-folder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-folder.js","sourceRoot":"","sources":["../../src/commands/create-folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC;KAC5D,WAAW,CAAC,0DAA0D,CAAC;KACvE,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACjF,cAAc,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;KACnE,MAAM,CAAC,iBAAiB,EAAE,yCAAyC,CAAC;KACpE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-lesson.d.ts","sourceRoot":"","sources":["../../src/commands/create-lesson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,mBAAmB,SA8B5B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { SkoolClient } from "../core/skool-client.js";
|
|
3
|
+
export const createLessonCommand = new Command("create-lesson")
|
|
4
|
+
.description("Create a new lesson in a Skool classroom module")
|
|
5
|
+
.requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
|
|
6
|
+
.requiredOption("-m, --module <name>", "Module name (exact match)")
|
|
7
|
+
.requiredOption("-t, --title <title>", "Lesson title (max 50 chars)")
|
|
8
|
+
.option("--course <name>", "Course name (if multiple courses exist)")
|
|
9
|
+
.option("--folder <name>", "Folder/module name to create the lesson in")
|
|
10
|
+
.option("--folder-id <id>", "Folder ID directly (from create-folder output)")
|
|
11
|
+
.option("-f, --file <path>", "Content file (.md, .html, or .json with skool_class)")
|
|
12
|
+
.option("--html <path>", "HTML file to inject directly")
|
|
13
|
+
.option("--markdown <text>", "Inline markdown content")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
const client = new SkoolClient();
|
|
16
|
+
try {
|
|
17
|
+
console.log(`Creating lesson "${opts.title}" in module "${opts.module}"...`);
|
|
18
|
+
const result = await client.createLesson({
|
|
19
|
+
group: opts.group,
|
|
20
|
+
module: opts.module,
|
|
21
|
+
title: opts.title,
|
|
22
|
+
course: opts.course,
|
|
23
|
+
folder: opts.folder,
|
|
24
|
+
folderId: opts.folderId,
|
|
25
|
+
filePath: opts.file || opts.html,
|
|
26
|
+
markdownContent: opts.markdown,
|
|
27
|
+
});
|
|
28
|
+
console.log(result.success ? `OK: ${result.message}` : `FAIL: ${result.message}`);
|
|
29
|
+
process.exit(result.success ? 0 : 1);
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await client.close();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=create-lesson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-lesson.js","sourceRoot":"","sources":["../../src/commands/create-lesson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC;KAC5D,WAAW,CAAC,iDAAiD,CAAC;KAC9D,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACjF,cAAc,CAAC,qBAAqB,EAAE,2BAA2B,CAAC;KAClE,cAAc,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;KACpE,MAAM,CAAC,iBAAiB,EAAE,yCAAyC,CAAC;KACpE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,mBAAmB,EAAE,sDAAsD,CAAC;KACnF,MAAM,CAAC,eAAe,EAAE,8BAA8B,CAAC;KACvD,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,gBAAgB,IAAI,CAAC,MAAM,MAAM,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI;YAChC,eAAe,EAAE,IAAI,CAAC,QAAQ;SAC/B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-post.d.ts","sourceRoot":"","sources":["../../src/commands/create-post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,iBAAiB,SA+B1B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { SkoolClient } from "../core/skool-client.js";
|
|
4
|
+
export const createPostCommand = new Command("create-post")
|
|
5
|
+
.description("Create a new community post in Skool")
|
|
6
|
+
.requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
|
|
7
|
+
.requiredOption("-t, --title <title>", "Post title")
|
|
8
|
+
.option("-b, --body <text>", "Post body text")
|
|
9
|
+
.option("-f, --file <path>", "Read post body from file")
|
|
10
|
+
.option("-c, --category <name>", "Post category")
|
|
11
|
+
.action(async (opts) => {
|
|
12
|
+
let body = opts.body;
|
|
13
|
+
if (!body && opts.file) {
|
|
14
|
+
body = readFileSync(opts.file, "utf-8");
|
|
15
|
+
}
|
|
16
|
+
if (!body) {
|
|
17
|
+
console.error("Error: Post body required. Use --body or --file.");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const client = new SkoolClient();
|
|
21
|
+
try {
|
|
22
|
+
console.log(`Creating post "${opts.title}"...`);
|
|
23
|
+
const result = await client.createPost({
|
|
24
|
+
group: opts.group,
|
|
25
|
+
title: opts.title,
|
|
26
|
+
body,
|
|
27
|
+
category: opts.category,
|
|
28
|
+
});
|
|
29
|
+
console.log(result.success ? `OK: ${result.message}` : `FAIL: ${result.message}`);
|
|
30
|
+
process.exit(result.success ? 0 : 1);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await client.close();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=create-post.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-post.js","sourceRoot":"","sources":["../../src/commands/create-post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC;KACxD,WAAW,CAAC,sCAAsC,CAAC;KACnD,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACjF,cAAc,CAAC,qBAAqB,EAAE,YAAY,CAAC;KACnD,MAAM,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;KAC7C,MAAM,CAAC,mBAAmB,EAAE,0BAA0B,CAAC;KACvD,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACrB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;YACrC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-api.d.ts","sourceRoot":"","sources":["../../src/commands/debug-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,eAAe,SAsHxB,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { BrowserManager } from "../core/browser-manager.js";
|
|
3
|
+
import { PageOps } from "../core/page-ops.js";
|
|
4
|
+
import { writeFileSync } from "node:fs";
|
|
5
|
+
export const debugApiCommand = new Command("debug-api")
|
|
6
|
+
.description("Intercept Skool API calls during classroom operations")
|
|
7
|
+
.requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
|
|
8
|
+
.option("--course <name>", "Course name", "Fundamentos de IA y Claude")
|
|
9
|
+
.action(async (opts) => {
|
|
10
|
+
const browser = new BrowserManager();
|
|
11
|
+
const ops = new PageOps(browser);
|
|
12
|
+
const apiLog = [];
|
|
13
|
+
try {
|
|
14
|
+
const page = await browser.getPage();
|
|
15
|
+
// Intercept ALL requests and responses
|
|
16
|
+
page.on("request", (req) => {
|
|
17
|
+
const url = req.url();
|
|
18
|
+
const method = req.method();
|
|
19
|
+
// Only log non-static requests (API calls, not images/css/js)
|
|
20
|
+
if (url.includes("/api/") ||
|
|
21
|
+
url.includes("graphql") ||
|
|
22
|
+
(method !== "GET" && !url.includes(".js") && !url.includes(".css") && !url.includes(".png") && !url.includes(".woff"))) {
|
|
23
|
+
const postData = req.postData();
|
|
24
|
+
const line = `>>> ${method} ${url}${postData ? `\n BODY: ${postData.slice(0, 500)}` : ""}`;
|
|
25
|
+
apiLog.push(line);
|
|
26
|
+
console.log(line);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
page.on("response", async (res) => {
|
|
30
|
+
const url = res.url();
|
|
31
|
+
const status = res.status();
|
|
32
|
+
if (url.includes("/api/") ||
|
|
33
|
+
url.includes("graphql") ||
|
|
34
|
+
(status >= 200 && status < 400 && !url.includes(".js") && !url.includes(".css") && !url.includes(".png") && !url.includes(".woff") && res.request().method() !== "GET")) {
|
|
35
|
+
let body = "";
|
|
36
|
+
try {
|
|
37
|
+
body = await res.text();
|
|
38
|
+
if (body.length > 1000)
|
|
39
|
+
body = body.slice(0, 1000) + "...";
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
body = "(could not read body)";
|
|
43
|
+
}
|
|
44
|
+
const line = `<<< ${status} ${url}\n RESPONSE: ${body}`;
|
|
45
|
+
apiLog.push(line);
|
|
46
|
+
console.log(line);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// Also capture ALL fetch/XHR by intercepting at the page level
|
|
50
|
+
await page.addInitScript(() => {
|
|
51
|
+
const origFetch = window.fetch;
|
|
52
|
+
window.fetch = async (...args) => {
|
|
53
|
+
const url = typeof args[0] === "string" ? args[0] : args[0].url;
|
|
54
|
+
const opts = args[1];
|
|
55
|
+
console.log(`[FETCH] ${opts?.method || "GET"} ${url}`);
|
|
56
|
+
if (opts?.body) {
|
|
57
|
+
console.log(`[FETCH BODY] ${String(opts.body).slice(0, 500)}`);
|
|
58
|
+
}
|
|
59
|
+
return origFetch.apply(window, args);
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
console.log("\n=== Step 1: Navigate to classroom ===\n");
|
|
63
|
+
await ops.gotoClassroom(opts.group);
|
|
64
|
+
console.log("\n=== Step 2: Enter course ===\n");
|
|
65
|
+
await page.getByText(opts.course, { exact: false }).first().click();
|
|
66
|
+
await page.waitForTimeout(3000);
|
|
67
|
+
console.log("\n=== Step 3: Click '...' menu ===\n");
|
|
68
|
+
const courseTopArea = page.locator('div[class*="CourseMenuTop"]').first();
|
|
69
|
+
await courseTopArea.hover();
|
|
70
|
+
await page.waitForTimeout(500);
|
|
71
|
+
// Click "..." via JS
|
|
72
|
+
await page.evaluate(() => {
|
|
73
|
+
const topArea = document.querySelector('div[class*="CourseMenuTop"]');
|
|
74
|
+
if (!topArea)
|
|
75
|
+
return;
|
|
76
|
+
topArea.querySelectorAll("div, button, span, svg").forEach((el) => {
|
|
77
|
+
const rect = el.getBoundingClientRect();
|
|
78
|
+
const text = el.textContent?.trim() || "";
|
|
79
|
+
if (rect.width > 10 && rect.width < 50 && rect.height > 10 && rect.height < 50 && text.length < 4) {
|
|
80
|
+
el.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
await page.waitForTimeout(800);
|
|
85
|
+
console.log("\n=== Step 4: Click 'Add page' ===\n");
|
|
86
|
+
try {
|
|
87
|
+
await page.getByText("Add page", { exact: true }).click({ timeout: 5000 });
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
await page.getByText("Add page", { exact: true }).click({ force: true, timeout: 5000 });
|
|
91
|
+
}
|
|
92
|
+
await page.waitForTimeout(5000);
|
|
93
|
+
console.log("\n=== Step 5: Capture current URL and page state ===\n");
|
|
94
|
+
console.log(`Current URL: ${page.url()}`);
|
|
95
|
+
// Also capture all cookies for reference
|
|
96
|
+
const context = page.context();
|
|
97
|
+
const cookies = await context.cookies();
|
|
98
|
+
const skoolCookies = cookies
|
|
99
|
+
.filter((c) => c.domain.includes("skool"))
|
|
100
|
+
.map((c) => `${c.name}=${c.value.slice(0, 20)}...`)
|
|
101
|
+
.join("; ");
|
|
102
|
+
console.log(`Skool cookies: ${skoolCookies}`);
|
|
103
|
+
// Save log
|
|
104
|
+
const logPath = "/tmp/skool-api-log.txt";
|
|
105
|
+
writeFileSync(logPath, apiLog.join("\n\n"));
|
|
106
|
+
console.log(`\nAPI log saved to: ${logPath} (${apiLog.length} entries)`);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
await browser.close();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=debug-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-api.js","sourceRoot":"","sources":["../../src/commands/debug-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-manual.d.ts","sourceRoot":"","sources":["../../src/commands/debug-manual.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,kBAAkB,SA8D3B,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { BrowserManager } from "../core/browser-manager.js";
|
|
3
|
+
import { PageOps } from "../core/page-ops.js";
|
|
4
|
+
import { writeFileSync } from "node:fs";
|
|
5
|
+
import { createInterface } from "node:readline";
|
|
6
|
+
export const debugManualCommand = new Command("debug-manual")
|
|
7
|
+
.description("Open browser with API interception — waits for you to interact manually")
|
|
8
|
+
.requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
|
|
9
|
+
.action(async (opts) => {
|
|
10
|
+
const browser = new BrowserManager();
|
|
11
|
+
const ops = new PageOps(browser);
|
|
12
|
+
const apiLog = [];
|
|
13
|
+
try {
|
|
14
|
+
const page = await browser.getPage();
|
|
15
|
+
// Intercept API calls
|
|
16
|
+
page.on("request", (req) => {
|
|
17
|
+
const url = req.url();
|
|
18
|
+
const method = req.method();
|
|
19
|
+
if (url.includes("api2.skool.com")) {
|
|
20
|
+
const body = req.postData();
|
|
21
|
+
const line = `>>> ${method} ${url}\n BODY: ${body || "(none)"}`;
|
|
22
|
+
apiLog.push(line);
|
|
23
|
+
console.log(line);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
page.on("response", async (res) => {
|
|
27
|
+
const url = res.url();
|
|
28
|
+
if (url.includes("api2.skool.com")) {
|
|
29
|
+
let body = "";
|
|
30
|
+
try {
|
|
31
|
+
body = await res.text();
|
|
32
|
+
if (body.length > 2000)
|
|
33
|
+
body = body.slice(0, 2000) + "...";
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
body = "(unreadable)";
|
|
37
|
+
}
|
|
38
|
+
const line = `<<< ${res.status()} ${url}\n RESPONSE: ${body}`;
|
|
39
|
+
apiLog.push(line);
|
|
40
|
+
console.log(line);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// Navigate to classroom
|
|
44
|
+
console.log("Opening classroom...\n");
|
|
45
|
+
await ops.gotoClassroom(opts.group);
|
|
46
|
+
// Wait for user to interact
|
|
47
|
+
console.log("=======================================================");
|
|
48
|
+
console.log("Browser is open with API interception active.");
|
|
49
|
+
console.log("Go to a lesson, click the pencil, edit, and click SAVE.");
|
|
50
|
+
console.log("All api2.skool.com calls will be logged here.");
|
|
51
|
+
console.log("Press ENTER when done to close the browser.");
|
|
52
|
+
console.log("=======================================================\n");
|
|
53
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
54
|
+
await new Promise((resolve) => {
|
|
55
|
+
rl.question("", () => { rl.close(); resolve(); });
|
|
56
|
+
});
|
|
57
|
+
// Save log
|
|
58
|
+
const logPath = "/tmp/skool-api-manual-log.txt";
|
|
59
|
+
writeFileSync(logPath, apiLog.join("\n\n"));
|
|
60
|
+
console.log(`\nAPI log saved to: ${logPath} (${apiLog.length} entries)`);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
await browser.close();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=debug-manual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-manual.js","sourceRoot":"","sources":["../../src/commands/debug-manual.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,YAAY,SA0GrB,CAAC"}
|