notebooklm-sdk 0.1.7 → 0.2.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/README.md +85 -242
- package/dist/{auth-Ba2hsZW_.d.cts → auth-Dxsm8894.d.cts} +1 -1
- package/dist/{auth-Ba2hsZW_.d.ts → auth-Dxsm8894.d.ts} +1 -1
- package/dist/auth.cjs +45 -25
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +8 -4
- package/dist/auth.d.ts +8 -4
- package/dist/auth.js +45 -27
- package/dist/auth.js.map +1 -1
- package/dist/bin.cjs +170 -31
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +172 -33
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +199 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -26
- package/dist/index.d.ts +42 -26
- package/dist/index.js +200 -87
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# notebooklm-sdk
|
|
2
2
|
|
|
3
|
+
### Automate NotebookLM from your code.
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/notebooklm-sdk)
|
|
4
6
|

|
|
5
7
|

|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
Works in **Node.js, Bun, and Deno**.
|
|
9
|
+
Generate AI podcasts, chat with documents, run web research, and manage notebooks programmatically — from Node.js, Bun, or Deno.
|
|
9
10
|
|
|
10
|
-
> This SDK
|
|
11
|
+
> ⚠️ **Unofficial.** This SDK reverse-engineers the NotebookLM internal API. It may break when Google updates their service. Not affiliated with Google.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
TypeScript port of [notebooklm-py](https://github.com/teng-lin/notebooklm-py).
|
|
13
14
|
|
|
14
|
-
##
|
|
15
|
+
## Install
|
|
15
16
|
|
|
16
17
|
```bash
|
|
17
18
|
npm install notebooklm-sdk
|
|
@@ -19,289 +20,131 @@ npm install notebooklm-sdk
|
|
|
19
20
|
bun add notebooklm-sdk
|
|
20
21
|
```
|
|
21
22
|
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
### Quick Login (Recommended)
|
|
25
|
-
|
|
26
|
-
First, install playwright:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
bun add -d playwright
|
|
30
|
-
bunx playwright install chromium
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Then, authenticate using the CLI:
|
|
23
|
+
## Quickstart
|
|
34
24
|
|
|
35
25
|
```bash
|
|
26
|
+
# Run once to authenticate
|
|
36
27
|
npx notebooklm-sdk login
|
|
37
|
-
# or
|
|
38
|
-
bun x notebooklm-sdk login
|
|
39
28
|
```
|
|
40
29
|
|
|
41
|
-
This opens a real browser for Google sign-in and generates a
|
|
42
|
-
`storage_state.json` file you can reuse.
|
|
43
|
-
|
|
44
|
-
Then connect using the file:
|
|
45
|
-
|
|
46
30
|
```ts
|
|
47
31
|
import { NotebookLMClient } from "notebooklm-sdk";
|
|
48
32
|
|
|
49
|
-
const client = await NotebookLMClient.connect(
|
|
50
|
-
cookiesFile: "./storage_state.json",
|
|
51
|
-
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
<details>
|
|
55
|
-
<summary>Manual Authentication</summary>
|
|
56
|
-
|
|
57
|
-
You can authenticate in multiple ways depending on your setup.
|
|
58
|
-
|
|
59
|
-
#### 1. Use `.env` Cookie String
|
|
60
|
-
|
|
61
|
-
Copy the `Cookie` header from DevTools → Network and store it:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
NOTEBOOKLM_COOKIE="SID=...; HSID=..."
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Then:
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
const client = await NotebookLMClient.connect({
|
|
71
|
-
cookies: process.env.NOTEBOOKLM_COOKIE,
|
|
72
|
-
});
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
---
|
|
33
|
+
const client = await NotebookLMClient.connect(); // uses ~/.notebooklm/session.json
|
|
76
34
|
|
|
77
|
-
|
|
35
|
+
// Create a notebook and add a source
|
|
36
|
+
const { id } = await client.notebooks.create("My Research");
|
|
37
|
+
await client.sources.addUrl(id, "https://en.wikipedia.org/wiki/TypeScript");
|
|
78
38
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const client = await NotebookLMClient.connect({
|
|
83
|
-
cookiesFile: "./storage_state.json",
|
|
39
|
+
// Generate a podcast and download it
|
|
40
|
+
const { artifactId } = await client.artifacts.createAudio(id, {
|
|
41
|
+
format: "deep_dive",
|
|
84
42
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
#### 3. Pass Cookies Directly
|
|
43
|
+
const audio = await client.artifacts.waitUntilReady(id, artifactId);
|
|
44
|
+
const mp3 = await client.artifacts.downloadAudio(id, audio.id);
|
|
90
45
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const client = await NotebookLMClient.connect({
|
|
95
|
-
cookies: "SID=...; HSID=...",
|
|
96
|
-
});
|
|
46
|
+
// Chat with the sources
|
|
47
|
+
const res = await client.chat.ask(id, "Summarize the key points.");
|
|
48
|
+
console.log(res.answer);
|
|
97
49
|
```
|
|
98
50
|
|
|
99
|
-
|
|
51
|
+
## Use cases
|
|
100
52
|
|
|
101
|
-
|
|
53
|
+
- **Blog & content generation** — research a topic, import sources, generate a blog post or briefing doc automatically
|
|
54
|
+
- **Content pipelines** — ingest articles or reports, generate a podcast or briefing doc on a schedule
|
|
55
|
+
- **Research automation** — run web research, import results, and query them via chat
|
|
56
|
+
- **Document Q&A bots** — feed documents into a notebook and build a chat interface on top
|
|
57
|
+
- **Batch artifact generation** — generate quizzes, flashcards, or study guides from a library of sources
|
|
58
|
+
- **Notebook management tools** — create, organize, and share notebooks programmatically
|
|
102
59
|
|
|
103
|
-
##
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
const notebooks = await client.notebooks.list();
|
|
107
|
-
const nb = await client.notebooks.get(id);
|
|
60
|
+
## Authentication
|
|
108
61
|
|
|
109
|
-
|
|
62
|
+
### Login (recommended)
|
|
110
63
|
|
|
111
|
-
|
|
112
|
-
await client.notebooks.delete(newId);
|
|
64
|
+
Install Playwright once:
|
|
113
65
|
|
|
114
|
-
|
|
115
|
-
|
|
66
|
+
```bash
|
|
67
|
+
bun add -d playwright
|
|
68
|
+
bunx playwright install chromium
|
|
116
69
|
```
|
|
117
70
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
## Sources
|
|
71
|
+
Authenticate:
|
|
121
72
|
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const { sourceId } = await client.sources.addUrl(
|
|
126
|
-
notebookId,
|
|
127
|
-
"https://example.com",
|
|
128
|
-
);
|
|
129
|
-
const { sourceId } = await client.sources.addText(notebookId, "Text", "Title");
|
|
130
|
-
const { sourceId } = await client.sources.addFile(
|
|
131
|
-
notebookId,
|
|
132
|
-
buffer,
|
|
133
|
-
"file.pdf",
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
await client.sources.waitUntilReady(notebookId, sourceId);
|
|
137
|
-
|
|
138
|
-
await client.sources.delete(notebookId, sourceId);
|
|
73
|
+
```bash
|
|
74
|
+
npx notebooklm-sdk login
|
|
139
75
|
```
|
|
140
76
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
## Artifacts
|
|
77
|
+
Opens a real Chrome window for Google sign-in. Session is saved to `~/.notebooklm/session.json` and auto-discovered on every `connect()` — no config needed.
|
|
144
78
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
```ts
|
|
148
|
-
const { artifactId } = await client.artifacts.createAudio(notebookId, {
|
|
149
|
-
format: AudioFormat.DEEP_DIVE,
|
|
150
|
-
length: AudioLength.DEFAULT,
|
|
151
|
-
language: "en",
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const { artifactId } = await client.artifacts.createVideo(notebookId, {
|
|
155
|
-
format: VideoFormat.EXPLAINER,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
const { artifactId } = await client.artifacts.createQuiz(notebookId);
|
|
159
|
-
const { artifactId } = await client.artifacts.createFlashcards(notebookId);
|
|
160
|
-
|
|
161
|
-
const { artifactId } = await client.artifacts.createReport(notebookId, {
|
|
162
|
-
format: "briefing_doc",
|
|
163
|
-
});
|
|
79
|
+
```bash
|
|
80
|
+
npx notebooklm-sdk whoami # verify session is valid
|
|
164
81
|
```
|
|
165
82
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
```ts
|
|
169
|
-
await client.artifacts.waitUntilReady(notebookId, artifactId);
|
|
83
|
+
### CI / Server
|
|
170
84
|
|
|
171
|
-
|
|
172
|
-
const video = await client.artifacts.downloadVideo(notebookId, artifactId);
|
|
85
|
+
Pass cookies via environment variable:
|
|
173
86
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
artifactId,
|
|
177
|
-
);
|
|
178
|
-
const html = await client.artifacts.getInteractiveHtml(notebookId, artifactId);
|
|
87
|
+
```bash
|
|
88
|
+
NOTEBOOKLM_COOKIES="SID=...; HSID=..."
|
|
179
89
|
```
|
|
180
90
|
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## Chat
|
|
184
|
-
|
|
185
91
|
```ts
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const follow = await client.chat.ask(notebookId, "Tell me more.", {
|
|
190
|
-
conversationId: res.conversationId,
|
|
92
|
+
const client = await NotebookLMClient.connect({
|
|
93
|
+
cookies: process.env.NOTEBOOKLM_COOKIES,
|
|
191
94
|
});
|
|
192
|
-
|
|
193
|
-
const convId = await client.chat.getLastConversationId(notebookId);
|
|
194
|
-
const turns = await client.chat.getConversationTurns(notebookId, convId);
|
|
195
95
|
```
|
|
196
96
|
|
|
197
|
-
|
|
97
|
+
> To get cookie values: open NotebookLM in Chrome → DevTools → Network → any request → copy the `Cookie` header.
|
|
198
98
|
|
|
199
|
-
##
|
|
99
|
+
## What you can build
|
|
200
100
|
|
|
201
|
-
|
|
202
|
-
|
|
101
|
+
| API | What it does |
|
|
102
|
+
| ----------- | ------------------------------------------------------- |
|
|
103
|
+
| `notebooks` | Create, rename, delete, list notebooks |
|
|
104
|
+
| `sources` | Add URLs, text, files; wait for processing |
|
|
105
|
+
| `artifacts` | Generate and download AI outputs (see below) |
|
|
106
|
+
| `chat` | Ask questions, follow-up conversations |
|
|
107
|
+
| `research` | Run web research, import results as sources |
|
|
108
|
+
| `notes` | Create and manage saved notes |
|
|
109
|
+
| `sharing` | Control public access and per-user permissions |
|
|
110
|
+
| `settings` | Get/set output language |
|
|
203
111
|
|
|
204
|
-
|
|
205
|
-
await client.notes.delete(notebookId, noteId);
|
|
206
|
-
```
|
|
112
|
+
**Artifact types**
|
|
207
113
|
|
|
208
|
-
|
|
114
|
+
| Artifact | Method | Output |
|
|
115
|
+
| -------------- | -------------------- | ----------------- |
|
|
116
|
+
| Audio Overview | `createAudio()` | Downloadable MP3 |
|
|
117
|
+
| Video Overview | `createVideo()` | Downloadable MP4 |
|
|
118
|
+
| Slide Deck | `createSlideDeck()` | PDF / PPTX download |
|
|
119
|
+
| Infographic | `createInfographic()`| PNG download |
|
|
120
|
+
| Mind Map | `createMindMap()` | JSON download |
|
|
121
|
+
| Reports | `createReport()` | Markdown download |
|
|
122
|
+
| Flashcards | `createFlashcards()` | Interactive HTML |
|
|
123
|
+
| Quiz | `createQuiz()` | Interactive HTML |
|
|
124
|
+
| Data Table | `createDataTable()` | CSV (headers + rows) |
|
|
209
125
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
```ts
|
|
213
|
-
const task = await client.research.start(
|
|
214
|
-
notebookId,
|
|
215
|
-
"Latest advances in quantum computing",
|
|
216
|
-
"web",
|
|
217
|
-
"deep",
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
const result = await client.research.poll(notebookId);
|
|
221
|
-
|
|
222
|
-
if (result.status === "completed") {
|
|
223
|
-
await client.research.importSources(
|
|
224
|
-
notebookId,
|
|
225
|
-
result.taskId,
|
|
226
|
-
result.sources.slice(0, 2),
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## Sharing
|
|
234
|
-
|
|
235
|
-
```ts
|
|
236
|
-
await client.sharing.setPublic(notebookId, true);
|
|
237
|
-
|
|
238
|
-
await client.sharing.addUser(
|
|
239
|
-
notebookId,
|
|
240
|
-
"user@example.com",
|
|
241
|
-
SharePermission.VIEWER,
|
|
242
|
-
);
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Settings
|
|
248
|
-
|
|
249
|
-
```ts
|
|
250
|
-
const lang = await client.settings.getOutputLanguage();
|
|
251
|
-
await client.settings.setOutputLanguage("ja");
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
---
|
|
126
|
+
→ [Full API reference](./DOCS.md)
|
|
255
127
|
|
|
256
128
|
## Examples
|
|
257
129
|
|
|
258
|
-
Runnable scripts are in [`examples/`](./examples).
|
|
259
|
-
|
|
260
|
-
**Setup:**
|
|
261
|
-
|
|
262
|
-
1. `npm run login` to create `storage_state.json`.
|
|
263
|
-
2. Run any example below.
|
|
264
|
-
|
|
265
130
|
```bash
|
|
266
|
-
|
|
267
|
-
bun run login
|
|
268
|
-
bun run examples/basic.ts
|
|
269
|
-
|
|
270
|
-
# for manual cookie
|
|
271
|
-
bunx dotenv -e .env -- bunx tsx examples/basic.ts
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## Error Handling
|
|
277
|
-
|
|
278
|
-
All errors extend `NotebookLMError`.
|
|
279
|
-
|
|
280
|
-
```ts
|
|
281
|
-
try {
|
|
282
|
-
await client.artifacts.downloadAudio(notebookId, artifactId);
|
|
283
|
-
} catch (err) {
|
|
284
|
-
if (err instanceof ArtifactNotReadyError) {
|
|
285
|
-
// still processing
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## Project Structure
|
|
131
|
+
npx notebooklm-sdk login
|
|
293
132
|
|
|
133
|
+
bun run examples/basic.ts # list notebooks and sources
|
|
134
|
+
bun run examples/chat.ts # ask questions, follow-up conversations
|
|
135
|
+
bun run examples/audio.ts # generate and download a podcast
|
|
136
|
+
bun run examples/report.ts # generate and download a briefing doc
|
|
137
|
+
bun run examples/slide-deck.ts # generate and download PDF / PPTX
|
|
138
|
+
bun run examples/infographic.ts # generate and download a PNG infographic
|
|
139
|
+
bun run examples/mind-map.ts # generate and download mind map JSON
|
|
140
|
+
bun run examples/data-table.ts # generate and download a CSV data table
|
|
141
|
+
bun run examples/notes.ts # create, update, list, and delete notes
|
|
142
|
+
bun run examples/research.ts # web research and import sources
|
|
143
|
+
bun run examples/research-and-chat.ts # research → import → chat
|
|
144
|
+
bun run examples/full-lifecycle.ts # create, add sources, chat, delete
|
|
145
|
+
bun run examples/download.ts # download all completed artifacts
|
|
294
146
|
```
|
|
295
|
-
src/
|
|
296
|
-
client.ts
|
|
297
|
-
auth.ts
|
|
298
|
-
api/
|
|
299
|
-
rpc/
|
|
300
|
-
types/
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
---
|
|
304
147
|
|
|
305
148
|
## License
|
|
306
149
|
|
|
307
|
-
MIT
|
|
150
|
+
MIT · TypeScript port of [notebooklm-py](https://github.com/teng-lin/notebooklm-py)
|
|
@@ -50,6 +50,6 @@ interface ConnectOptions {
|
|
|
50
50
|
}>;
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
declare function connect(opts
|
|
53
|
+
declare function connect(opts?: ConnectOptions): Promise<AuthTokens>;
|
|
54
54
|
|
|
55
55
|
export { type AuthTokens as A, type CookieMap as C, type ConnectOptions as a, buildCookieHeader as b, buildGoogleCookieHeader as c, connect as d, loadCookiesFromMap as e, fetchTokens as f, loadCookiesFromObject as g, loadCookiesFromString as h, loadCookiesFromFile as l };
|
|
@@ -50,6 +50,6 @@ interface ConnectOptions {
|
|
|
50
50
|
}>;
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
declare function connect(opts
|
|
53
|
+
declare function connect(opts?: ConnectOptions): Promise<AuthTokens>;
|
|
54
54
|
|
|
55
55
|
export { type AuthTokens as A, type CookieMap as C, type ConnectOptions as a, buildCookieHeader as b, buildGoogleCookieHeader as c, connect as d, loadCookiesFromMap as e, fetchTokens as f, loadCookiesFromObject as g, loadCookiesFromString as h, loadCookiesFromFile as l };
|
package/dist/auth.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fs = require('fs');
|
|
4
|
+
var os = require('os');
|
|
5
|
+
var path = require('path');
|
|
4
6
|
var playwright = require('playwright');
|
|
5
7
|
|
|
6
8
|
// src/auth.ts
|
|
@@ -29,15 +31,14 @@ var AuthError = class extends RPCError {
|
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
// src/auth.ts
|
|
34
|
+
var DEFAULT_SESSION_FILE = path.join(os.homedir(), ".notebooklm", "session.json");
|
|
32
35
|
function loadCookiesFromFile(filePath) {
|
|
33
36
|
let raw;
|
|
34
37
|
try {
|
|
35
38
|
raw = fs.readFileSync(filePath, "utf-8");
|
|
36
39
|
} catch {
|
|
37
|
-
throw new AuthError(
|
|
38
|
-
|
|
39
|
-
Provide valid Playwright storage state JSON.`
|
|
40
|
-
);
|
|
40
|
+
throw new AuthError(`Session file not found: ${filePath}
|
|
41
|
+
Run: npx notebooklm-sdk login`);
|
|
41
42
|
}
|
|
42
43
|
return extractCookiesFromStorageState(JSON.parse(raw));
|
|
43
44
|
}
|
|
@@ -80,7 +81,7 @@ function extractCookiesFromStorageState(storageState) {
|
|
|
80
81
|
}
|
|
81
82
|
if (!cookies["SID"]) {
|
|
82
83
|
throw new AuthError(
|
|
83
|
-
"Missing required cookie: SID.
|
|
84
|
+
"Missing required cookie: SID. Session may be invalid or expired.\nRun: npx notebooklm-sdk login"
|
|
84
85
|
);
|
|
85
86
|
}
|
|
86
87
|
return cookies;
|
|
@@ -120,7 +121,7 @@ function extractCsrfToken(html, finalUrl) {
|
|
|
120
121
|
const match = /"SNlM0e"\s*:\s*"([^"]+)"/.exec(html);
|
|
121
122
|
if (!match?.[1]) {
|
|
122
123
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
123
|
-
throw new AuthError("
|
|
124
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
124
125
|
}
|
|
125
126
|
throw new AuthError("CSRF token (SNlM0e) not found in NotebookLM page HTML.");
|
|
126
127
|
}
|
|
@@ -130,7 +131,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
130
131
|
const match = /"FdrFJe"\s*:\s*"([^"]+)"/.exec(html);
|
|
131
132
|
if (!match?.[1]) {
|
|
132
133
|
if (isGoogleAuthRedirect(finalUrl) || html.includes("accounts.google.com")) {
|
|
133
|
-
throw new AuthError("
|
|
134
|
+
throw new AuthError("Session expired or invalid.\nRun: npx notebooklm-sdk login");
|
|
134
135
|
}
|
|
135
136
|
throw new AuthError("Session ID (FdrFJe) not found in NotebookLM page HTML.");
|
|
136
137
|
}
|
|
@@ -139,7 +140,7 @@ function extractSessionId(html, finalUrl) {
|
|
|
139
140
|
function isGoogleAuthRedirect(url) {
|
|
140
141
|
return url.includes("accounts.google.com") || url.includes("signin");
|
|
141
142
|
}
|
|
142
|
-
async function connect(opts) {
|
|
143
|
+
async function connect(opts = {}) {
|
|
143
144
|
let cookieMap;
|
|
144
145
|
let googleCookieHeader = null;
|
|
145
146
|
if (opts.cookies) {
|
|
@@ -156,12 +157,23 @@ async function connect(opts) {
|
|
|
156
157
|
}
|
|
157
158
|
} else {
|
|
158
159
|
const envCookies = process.env["NOTEBOOKLM_COOKIES"];
|
|
159
|
-
|
|
160
|
+
const envFile = process.env["NOTEBOOKLM_COOKIES_FILE"];
|
|
161
|
+
if (envFile) {
|
|
162
|
+
cookieMap = loadCookiesFromFile(envFile);
|
|
163
|
+
} else if (fs.existsSync(DEFAULT_SESSION_FILE)) {
|
|
164
|
+
const raw = fs.readFileSync(DEFAULT_SESSION_FILE, "utf-8");
|
|
165
|
+
const storageState = JSON.parse(raw);
|
|
166
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
167
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
168
|
+
} else if (fs.existsSync("storage_state.json")) {
|
|
169
|
+
const raw = fs.readFileSync("storage_state.json", "utf-8");
|
|
170
|
+
const storageState = JSON.parse(raw);
|
|
171
|
+
cookieMap = loadCookiesFromObject(storageState);
|
|
172
|
+
googleCookieHeader = buildGoogleCookieHeader(storageState);
|
|
173
|
+
} else if (envCookies) {
|
|
160
174
|
cookieMap = loadCookiesFromString(envCookies);
|
|
161
175
|
} else {
|
|
162
|
-
throw new AuthError(
|
|
163
|
-
"No cookies provided. Pass cookies, cookiesFile, or cookiesObject to connect()."
|
|
164
|
-
);
|
|
176
|
+
throw new AuthError("No session found. Run: npx notebooklm-sdk login");
|
|
165
177
|
}
|
|
166
178
|
}
|
|
167
179
|
const { csrfToken, sessionId } = await fetchTokens(cookieMap);
|
|
@@ -174,27 +186,33 @@ async function connect(opts) {
|
|
|
174
186
|
googleCookieHeader: googleCookieHeader ?? cookieHeader
|
|
175
187
|
};
|
|
176
188
|
}
|
|
189
|
+
var DEFAULT_SESSION_DIR = path.join(os.homedir(), ".notebooklm");
|
|
190
|
+
var DEFAULT_SESSION_FILE2 = path.join(DEFAULT_SESSION_DIR, "session.json");
|
|
177
191
|
var NOTEBOOKLM_URL2 = "https://notebooklm.google.com/";
|
|
178
192
|
var GOOGLE_ACCOUNTS_URL = "https://accounts.google.com/";
|
|
179
193
|
async function login(opts = {}) {
|
|
180
|
-
const {
|
|
194
|
+
const {
|
|
195
|
+
persistFolder = path.join(DEFAULT_SESSION_DIR, ".auth_profile"),
|
|
196
|
+
headless = false,
|
|
197
|
+
browserType = "chromium"
|
|
198
|
+
} = opts;
|
|
199
|
+
try {
|
|
200
|
+
playwright.chromium.executablePath();
|
|
201
|
+
} catch {
|
|
202
|
+
throw new Error("Playwright browser not found. Run: npx playwright install chromium");
|
|
203
|
+
}
|
|
204
|
+
if (!fs.existsSync(DEFAULT_SESSION_DIR)) {
|
|
205
|
+
fs.mkdirSync(DEFAULT_SESSION_DIR, { recursive: true });
|
|
206
|
+
}
|
|
181
207
|
let context;
|
|
182
208
|
const launchOptions = {
|
|
183
209
|
headless,
|
|
184
210
|
args: ["--disable-blink-features=AutomationControlled"]
|
|
185
211
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
191
|
-
} else {
|
|
192
|
-
const browser = await playwright.chromium.launch({
|
|
193
|
-
...launchOptions,
|
|
194
|
-
channel: browserType === "msedge" ? "msedge" : void 0
|
|
195
|
-
});
|
|
196
|
-
context = await browser.newContext();
|
|
197
|
-
}
|
|
212
|
+
context = await playwright.chromium.launchPersistentContext(persistFolder, {
|
|
213
|
+
...launchOptions,
|
|
214
|
+
channel: browserType === "msedge" ? "msedge" : void 0
|
|
215
|
+
});
|
|
198
216
|
const page = context.pages()[0] || await context.newPage();
|
|
199
217
|
await page.goto(NOTEBOOKLM_URL2);
|
|
200
218
|
if (page.url().includes("accounts.google.com")) {
|
|
@@ -218,6 +236,8 @@ async function login(opts = {}) {
|
|
|
218
236
|
};
|
|
219
237
|
}
|
|
220
238
|
|
|
239
|
+
exports.DEFAULT_SESSION_DIR = DEFAULT_SESSION_DIR;
|
|
240
|
+
exports.DEFAULT_SESSION_FILE = DEFAULT_SESSION_FILE2;
|
|
221
241
|
exports.buildCookieHeader = buildCookieHeader;
|
|
222
242
|
exports.buildGoogleCookieHeader = buildGoogleCookieHeader;
|
|
223
243
|
exports.connect = connect;
|