devusman commited on
Commit
7a6e7ae
Β·
1 Parent(s): 158a13b

feat: fixing the performance issues

Browse files
Files changed (4) hide show
  1. package-lock.json +168 -674
  2. package.json +2 -3
  3. server copy.js +35 -26
  4. server.js +46 -38
package-lock.json CHANGED
@@ -9,13 +9,12 @@
9
  "version": "1.0.0",
10
  "dependencies": {
11
  "axios": "^1.11.0",
 
12
  "cors": "^2.8.5",
13
  "express": "^5.1.0",
14
- "pdfkit": "^0.17.1",
15
  "puppeteer": "^24.16.2",
16
  "puppeteer-extra": "^3.3.6",
17
- "puppeteer-extra-plugin-stealth": "^2.11.2",
18
- "sharp": "^0.34.3"
19
  },
20
  "devDependencies": {
21
  "nodemon": "^3.1.10",
@@ -46,434 +45,6 @@
46
  "node": ">=6.9.0"
47
  }
48
  },
49
- "node_modules/@emnapi/runtime": {
50
- "version": "1.4.5",
51
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz",
52
- "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==",
53
- "license": "MIT",
54
- "optional": true,
55
- "dependencies": {
56
- "tslib": "^2.4.0"
57
- }
58
- },
59
- "node_modules/@img/sharp-darwin-arm64": {
60
- "version": "0.34.3",
61
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz",
62
- "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==",
63
- "cpu": [
64
- "arm64"
65
- ],
66
- "license": "Apache-2.0",
67
- "optional": true,
68
- "os": [
69
- "darwin"
70
- ],
71
- "engines": {
72
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
73
- },
74
- "funding": {
75
- "url": "https://opencollective.com/libvips"
76
- },
77
- "optionalDependencies": {
78
- "@img/sharp-libvips-darwin-arm64": "1.2.0"
79
- }
80
- },
81
- "node_modules/@img/sharp-darwin-x64": {
82
- "version": "0.34.3",
83
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz",
84
- "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==",
85
- "cpu": [
86
- "x64"
87
- ],
88
- "license": "Apache-2.0",
89
- "optional": true,
90
- "os": [
91
- "darwin"
92
- ],
93
- "engines": {
94
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
95
- },
96
- "funding": {
97
- "url": "https://opencollective.com/libvips"
98
- },
99
- "optionalDependencies": {
100
- "@img/sharp-libvips-darwin-x64": "1.2.0"
101
- }
102
- },
103
- "node_modules/@img/sharp-libvips-darwin-arm64": {
104
- "version": "1.2.0",
105
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz",
106
- "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==",
107
- "cpu": [
108
- "arm64"
109
- ],
110
- "license": "LGPL-3.0-or-later",
111
- "optional": true,
112
- "os": [
113
- "darwin"
114
- ],
115
- "funding": {
116
- "url": "https://opencollective.com/libvips"
117
- }
118
- },
119
- "node_modules/@img/sharp-libvips-darwin-x64": {
120
- "version": "1.2.0",
121
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz",
122
- "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==",
123
- "cpu": [
124
- "x64"
125
- ],
126
- "license": "LGPL-3.0-or-later",
127
- "optional": true,
128
- "os": [
129
- "darwin"
130
- ],
131
- "funding": {
132
- "url": "https://opencollective.com/libvips"
133
- }
134
- },
135
- "node_modules/@img/sharp-libvips-linux-arm": {
136
- "version": "1.2.0",
137
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz",
138
- "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==",
139
- "cpu": [
140
- "arm"
141
- ],
142
- "license": "LGPL-3.0-or-later",
143
- "optional": true,
144
- "os": [
145
- "linux"
146
- ],
147
- "funding": {
148
- "url": "https://opencollective.com/libvips"
149
- }
150
- },
151
- "node_modules/@img/sharp-libvips-linux-arm64": {
152
- "version": "1.2.0",
153
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz",
154
- "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==",
155
- "cpu": [
156
- "arm64"
157
- ],
158
- "license": "LGPL-3.0-or-later",
159
- "optional": true,
160
- "os": [
161
- "linux"
162
- ],
163
- "funding": {
164
- "url": "https://opencollective.com/libvips"
165
- }
166
- },
167
- "node_modules/@img/sharp-libvips-linux-ppc64": {
168
- "version": "1.2.0",
169
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz",
170
- "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==",
171
- "cpu": [
172
- "ppc64"
173
- ],
174
- "license": "LGPL-3.0-or-later",
175
- "optional": true,
176
- "os": [
177
- "linux"
178
- ],
179
- "funding": {
180
- "url": "https://opencollective.com/libvips"
181
- }
182
- },
183
- "node_modules/@img/sharp-libvips-linux-s390x": {
184
- "version": "1.2.0",
185
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz",
186
- "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==",
187
- "cpu": [
188
- "s390x"
189
- ],
190
- "license": "LGPL-3.0-or-later",
191
- "optional": true,
192
- "os": [
193
- "linux"
194
- ],
195
- "funding": {
196
- "url": "https://opencollective.com/libvips"
197
- }
198
- },
199
- "node_modules/@img/sharp-libvips-linux-x64": {
200
- "version": "1.2.0",
201
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz",
202
- "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==",
203
- "cpu": [
204
- "x64"
205
- ],
206
- "license": "LGPL-3.0-or-later",
207
- "optional": true,
208
- "os": [
209
- "linux"
210
- ],
211
- "funding": {
212
- "url": "https://opencollective.com/libvips"
213
- }
214
- },
215
- "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
216
- "version": "1.2.0",
217
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz",
218
- "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==",
219
- "cpu": [
220
- "arm64"
221
- ],
222
- "license": "LGPL-3.0-or-later",
223
- "optional": true,
224
- "os": [
225
- "linux"
226
- ],
227
- "funding": {
228
- "url": "https://opencollective.com/libvips"
229
- }
230
- },
231
- "node_modules/@img/sharp-libvips-linuxmusl-x64": {
232
- "version": "1.2.0",
233
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz",
234
- "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==",
235
- "cpu": [
236
- "x64"
237
- ],
238
- "license": "LGPL-3.0-or-later",
239
- "optional": true,
240
- "os": [
241
- "linux"
242
- ],
243
- "funding": {
244
- "url": "https://opencollective.com/libvips"
245
- }
246
- },
247
- "node_modules/@img/sharp-linux-arm": {
248
- "version": "0.34.3",
249
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz",
250
- "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==",
251
- "cpu": [
252
- "arm"
253
- ],
254
- "license": "Apache-2.0",
255
- "optional": true,
256
- "os": [
257
- "linux"
258
- ],
259
- "engines": {
260
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
261
- },
262
- "funding": {
263
- "url": "https://opencollective.com/libvips"
264
- },
265
- "optionalDependencies": {
266
- "@img/sharp-libvips-linux-arm": "1.2.0"
267
- }
268
- },
269
- "node_modules/@img/sharp-linux-arm64": {
270
- "version": "0.34.3",
271
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz",
272
- "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==",
273
- "cpu": [
274
- "arm64"
275
- ],
276
- "license": "Apache-2.0",
277
- "optional": true,
278
- "os": [
279
- "linux"
280
- ],
281
- "engines": {
282
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
283
- },
284
- "funding": {
285
- "url": "https://opencollective.com/libvips"
286
- },
287
- "optionalDependencies": {
288
- "@img/sharp-libvips-linux-arm64": "1.2.0"
289
- }
290
- },
291
- "node_modules/@img/sharp-linux-ppc64": {
292
- "version": "0.34.3",
293
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz",
294
- "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==",
295
- "cpu": [
296
- "ppc64"
297
- ],
298
- "license": "Apache-2.0",
299
- "optional": true,
300
- "os": [
301
- "linux"
302
- ],
303
- "engines": {
304
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
305
- },
306
- "funding": {
307
- "url": "https://opencollective.com/libvips"
308
- },
309
- "optionalDependencies": {
310
- "@img/sharp-libvips-linux-ppc64": "1.2.0"
311
- }
312
- },
313
- "node_modules/@img/sharp-linux-s390x": {
314
- "version": "0.34.3",
315
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz",
316
- "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==",
317
- "cpu": [
318
- "s390x"
319
- ],
320
- "license": "Apache-2.0",
321
- "optional": true,
322
- "os": [
323
- "linux"
324
- ],
325
- "engines": {
326
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
327
- },
328
- "funding": {
329
- "url": "https://opencollective.com/libvips"
330
- },
331
- "optionalDependencies": {
332
- "@img/sharp-libvips-linux-s390x": "1.2.0"
333
- }
334
- },
335
- "node_modules/@img/sharp-linux-x64": {
336
- "version": "0.34.3",
337
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz",
338
- "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==",
339
- "cpu": [
340
- "x64"
341
- ],
342
- "license": "Apache-2.0",
343
- "optional": true,
344
- "os": [
345
- "linux"
346
- ],
347
- "engines": {
348
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
349
- },
350
- "funding": {
351
- "url": "https://opencollective.com/libvips"
352
- },
353
- "optionalDependencies": {
354
- "@img/sharp-libvips-linux-x64": "1.2.0"
355
- }
356
- },
357
- "node_modules/@img/sharp-linuxmusl-arm64": {
358
- "version": "0.34.3",
359
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz",
360
- "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==",
361
- "cpu": [
362
- "arm64"
363
- ],
364
- "license": "Apache-2.0",
365
- "optional": true,
366
- "os": [
367
- "linux"
368
- ],
369
- "engines": {
370
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
371
- },
372
- "funding": {
373
- "url": "https://opencollective.com/libvips"
374
- },
375
- "optionalDependencies": {
376
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.0"
377
- }
378
- },
379
- "node_modules/@img/sharp-linuxmusl-x64": {
380
- "version": "0.34.3",
381
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz",
382
- "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==",
383
- "cpu": [
384
- "x64"
385
- ],
386
- "license": "Apache-2.0",
387
- "optional": true,
388
- "os": [
389
- "linux"
390
- ],
391
- "engines": {
392
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
393
- },
394
- "funding": {
395
- "url": "https://opencollective.com/libvips"
396
- },
397
- "optionalDependencies": {
398
- "@img/sharp-libvips-linuxmusl-x64": "1.2.0"
399
- }
400
- },
401
- "node_modules/@img/sharp-wasm32": {
402
- "version": "0.34.3",
403
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz",
404
- "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==",
405
- "cpu": [
406
- "wasm32"
407
- ],
408
- "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
409
- "optional": true,
410
- "dependencies": {
411
- "@emnapi/runtime": "^1.4.4"
412
- },
413
- "engines": {
414
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
415
- },
416
- "funding": {
417
- "url": "https://opencollective.com/libvips"
418
- }
419
- },
420
- "node_modules/@img/sharp-win32-arm64": {
421
- "version": "0.34.3",
422
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz",
423
- "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==",
424
- "cpu": [
425
- "arm64"
426
- ],
427
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
428
- "optional": true,
429
- "os": [
430
- "win32"
431
- ],
432
- "engines": {
433
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
434
- },
435
- "funding": {
436
- "url": "https://opencollective.com/libvips"
437
- }
438
- },
439
- "node_modules/@img/sharp-win32-ia32": {
440
- "version": "0.34.3",
441
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz",
442
- "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==",
443
- "cpu": [
444
- "ia32"
445
- ],
446
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
447
- "optional": true,
448
- "os": [
449
- "win32"
450
- ],
451
- "engines": {
452
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
453
- },
454
- "funding": {
455
- "url": "https://opencollective.com/libvips"
456
- }
457
- },
458
- "node_modules/@img/sharp-win32-x64": {
459
- "version": "0.34.3",
460
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz",
461
- "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==",
462
- "cpu": [
463
- "x64"
464
- ],
465
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
466
- "optional": true,
467
- "os": [
468
- "win32"
469
- ],
470
- "engines": {
471
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
472
- },
473
- "funding": {
474
- "url": "https://opencollective.com/libvips"
475
- }
476
- },
477
  "node_modules/@puppeteer/browsers": {
478
  "version": "2.10.6",
479
  "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.6.tgz",
@@ -495,15 +66,6 @@
495
  "node": ">=18"
496
  }
497
  },
498
- "node_modules/@swc/helpers": {
499
- "version": "0.5.17",
500
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
501
- "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
502
- "license": "Apache-2.0",
503
- "dependencies": {
504
- "tslib": "^2.8.0"
505
- }
506
- },
507
  "node_modules/@tootallnate/quickjs-emscripten": {
508
  "version": "0.23.0",
509
  "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
@@ -733,26 +295,6 @@
733
  }
734
  }
735
  },
736
- "node_modules/base64-js": {
737
- "version": "1.5.1",
738
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
739
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
740
- "funding": [
741
- {
742
- "type": "github",
743
- "url": "https://github.com/sponsors/feross"
744
- },
745
- {
746
- "type": "patreon",
747
- "url": "https://www.patreon.com/feross"
748
- },
749
- {
750
- "type": "consulting",
751
- "url": "https://feross.org/support"
752
- }
753
- ],
754
- "license": "MIT"
755
- },
756
  "node_modules/basic-ftp": {
757
  "version": "5.0.5",
758
  "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
@@ -818,15 +360,6 @@
818
  "node": ">=8"
819
  }
820
  },
821
- "node_modules/brotli": {
822
- "version": "1.3.3",
823
- "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
824
- "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
825
- "license": "MIT",
826
- "dependencies": {
827
- "base64-js": "^1.1.2"
828
- }
829
- },
830
  "node_modules/buffer-crc32": {
831
  "version": "0.2.13",
832
  "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
@@ -935,15 +468,6 @@
935
  "node": ">=12"
936
  }
937
  },
938
- "node_modules/clone": {
939
- "version": "2.1.2",
940
- "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
941
- "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
942
- "license": "MIT",
943
- "engines": {
944
- "node": ">=0.8"
945
- }
946
- },
947
  "node_modules/clone-deep": {
948
  "version": "0.2.4",
949
  "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz",
@@ -960,17 +484,16 @@
960
  "node": ">=0.10.0"
961
  }
962
  },
963
- "node_modules/color": {
964
- "version": "4.2.3",
965
- "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
966
- "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
967
- "license": "MIT",
968
  "dependencies": {
969
- "color-convert": "^2.0.1",
970
- "color-string": "^1.9.0"
971
  },
972
  "engines": {
973
- "node": ">=12.5.0"
974
  }
975
  },
976
  "node_modules/color-convert": {
@@ -991,16 +514,6 @@
991
  "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
992
  "license": "MIT"
993
  },
994
- "node_modules/color-string": {
995
- "version": "1.9.1",
996
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
997
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
998
- "license": "MIT",
999
- "dependencies": {
1000
- "color-name": "^1.0.0",
1001
- "simple-swizzle": "^0.2.2"
1002
- }
1003
- },
1004
  "node_modules/combined-stream": {
1005
  "version": "1.0.8",
1006
  "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1112,11 +625,18 @@
1112
  "node": ">= 8"
1113
  }
1114
  },
1115
- "node_modules/crypto-js": {
1116
- "version": "4.2.0",
1117
- "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
1118
- "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
1119
- "license": "MIT"
 
 
 
 
 
 
 
1120
  },
1121
  "node_modules/data-uri-to-buffer": {
1122
  "version": "6.0.2",
@@ -1185,27 +705,12 @@
1185
  "node": ">= 0.8"
1186
  }
1187
  },
1188
- "node_modules/detect-libc": {
1189
- "version": "2.0.4",
1190
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
1191
- "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
1192
- "license": "Apache-2.0",
1193
- "engines": {
1194
- "node": ">=8"
1195
- }
1196
- },
1197
  "node_modules/devtools-protocol": {
1198
  "version": "0.0.1475386",
1199
  "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1475386.tgz",
1200
  "integrity": "sha512-RQ809ykTfJ+dgj9bftdeL2vRVxASAuGU+I9LEx9Ij5TXU5HrgAQVmzi72VA+mkzscE12uzlRv5/tWWv9R9J1SA==",
1201
  "license": "BSD-3-Clause"
1202
  },
1203
- "node_modules/dfa": {
1204
- "version": "1.2.0",
1205
- "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
1206
- "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
1207
- "license": "MIT"
1208
- },
1209
  "node_modules/dunder-proto": {
1210
  "version": "1.0.1",
1211
  "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -1227,6 +732,16 @@
1227
  "dev": true,
1228
  "license": "MIT"
1229
  },
 
 
 
 
 
 
 
 
 
 
1230
  "node_modules/ee-first": {
1231
  "version": "1.1.1",
1232
  "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1320,6 +835,46 @@
1320
  "node": ">= 0.4"
1321
  }
1322
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1323
  "node_modules/escalade": {
1324
  "version": "3.2.0",
1325
  "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -1356,6 +911,21 @@
1356
  "source-map": "~0.6.1"
1357
  }
1358
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1359
  "node_modules/esprima": {
1360
  "version": "4.0.1",
1361
  "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
@@ -1396,6 +966,16 @@
1396
  "node": ">= 0.6"
1397
  }
1398
  },
 
 
 
 
 
 
 
 
 
 
1399
  "node_modules/event-stream": {
1400
  "version": "3.3.4",
1401
  "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
@@ -1454,6 +1034,15 @@
1454
  "url": "https://opencollective.com/express"
1455
  }
1456
  },
 
 
 
 
 
 
 
 
 
1457
  "node_modules/extract-zip": {
1458
  "version": "2.0.1",
1459
  "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -1474,12 +1063,6 @@
1474
  "@types/yauzl": "^2.9.1"
1475
  }
1476
  },
1477
- "node_modules/fast-deep-equal": {
1478
- "version": "3.1.3",
1479
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1480
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1481
- "license": "MIT"
1482
- },
1483
  "node_modules/fast-fifo": {
1484
  "version": "1.3.2",
1485
  "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
@@ -1545,23 +1128,6 @@
1545
  }
1546
  }
1547
  },
1548
- "node_modules/fontkit": {
1549
- "version": "2.0.4",
1550
- "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
1551
- "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
1552
- "license": "MIT",
1553
- "dependencies": {
1554
- "@swc/helpers": "^0.5.12",
1555
- "brotli": "^1.3.2",
1556
- "clone": "^2.1.2",
1557
- "dfa": "^1.2.0",
1558
- "fast-deep-equal": "^3.1.3",
1559
- "restructure": "^3.0.0",
1560
- "tiny-inflate": "^1.0.3",
1561
- "unicode-properties": "^1.4.0",
1562
- "unicode-trie": "^2.0.0"
1563
- }
1564
- },
1565
  "node_modules/for-in": {
1566
  "version": "1.0.2",
1567
  "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -2096,12 +1662,6 @@
2096
  "node": ">=0.10.0"
2097
  }
2098
  },
2099
- "node_modules/jpeg-exif": {
2100
- "version": "1.1.4",
2101
- "resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz",
2102
- "integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==",
2103
- "license": "MIT"
2104
- },
2105
  "node_modules/js-tokens": {
2106
  "version": "4.0.0",
2107
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -2159,31 +1719,30 @@
2159
  "node": ">=0.10.0"
2160
  }
2161
  },
2162
- "node_modules/linebreak": {
2163
- "version": "1.1.0",
2164
- "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
2165
- "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
2166
- "license": "MIT",
2167
- "dependencies": {
2168
- "base64-js": "0.0.8",
2169
- "unicode-trie": "^2.0.0"
2170
- }
2171
- },
2172
- "node_modules/linebreak/node_modules/base64-js": {
2173
- "version": "0.0.8",
2174
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
2175
- "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
2176
- "license": "MIT",
2177
- "engines": {
2178
- "node": ">= 0.4"
2179
- }
2180
- },
2181
  "node_modules/lines-and-columns": {
2182
  "version": "1.2.4",
2183
  "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
2184
  "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
2185
  "license": "MIT"
2186
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2187
  "node_modules/lru-cache": {
2188
  "version": "7.18.3",
2189
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
@@ -2304,6 +1863,21 @@
2304
  "node": ">=0.10.0"
2305
  }
2306
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2307
  "node_modules/ms": {
2308
  "version": "2.1.3",
2309
  "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -2328,6 +1902,12 @@
2328
  "node": ">= 0.4.0"
2329
  }
2330
  },
 
 
 
 
 
 
2331
  "node_modules/node-cleanup": {
2332
  "version": "2.1.2",
2333
  "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz",
@@ -2448,12 +2028,6 @@
2448
  "node": ">= 14"
2449
  }
2450
  },
2451
- "node_modules/pako": {
2452
- "version": "0.2.9",
2453
- "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
2454
- "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
2455
- "license": "MIT"
2456
- },
2457
  "node_modules/parent-module": {
2458
  "version": "1.0.1",
2459
  "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -2534,19 +2108,6 @@
2534
  "through": "~2.3"
2535
  }
2536
  },
2537
- "node_modules/pdfkit": {
2538
- "version": "0.17.1",
2539
- "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.17.1.tgz",
2540
- "integrity": "sha512-Kkf1I9no14O/uo593DYph5u3QwiMfby7JsBSErN1WqeyTgCBNJE3K4pXBn3TgkdKUIVu+buSl4bYUNC+8Up4xg==",
2541
- "license": "MIT",
2542
- "dependencies": {
2543
- "crypto-js": "^4.2.0",
2544
- "fontkit": "^2.0.4",
2545
- "jpeg-exif": "^1.1.4",
2546
- "linebreak": "^1.1.0",
2547
- "png-js": "^1.0.0"
2548
- }
2549
- },
2550
  "node_modules/pend": {
2551
  "version": "1.2.0",
2552
  "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -2572,11 +2133,6 @@
2572
  "url": "https://github.com/sponsors/jonschlinkert"
2573
  }
2574
  },
2575
- "node_modules/png-js": {
2576
- "version": "1.0.0",
2577
- "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz",
2578
- "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g=="
2579
- },
2580
  "node_modules/progress": {
2581
  "version": "2.0.3",
2582
  "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -2901,12 +2457,6 @@
2901
  "node": ">=4"
2902
  }
2903
  },
2904
- "node_modules/restructure": {
2905
- "version": "3.0.2",
2906
- "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
2907
- "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
2908
- "license": "MIT"
2909
- },
2910
  "node_modules/rimraf": {
2911
  "version": "3.0.2",
2912
  "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -3056,48 +2606,6 @@
3056
  "node": ">=0.10.0"
3057
  }
3058
  },
3059
- "node_modules/sharp": {
3060
- "version": "0.34.3",
3061
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz",
3062
- "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==",
3063
- "hasInstallScript": true,
3064
- "license": "Apache-2.0",
3065
- "dependencies": {
3066
- "color": "^4.2.3",
3067
- "detect-libc": "^2.0.4",
3068
- "semver": "^7.7.2"
3069
- },
3070
- "engines": {
3071
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
3072
- },
3073
- "funding": {
3074
- "url": "https://opencollective.com/libvips"
3075
- },
3076
- "optionalDependencies": {
3077
- "@img/sharp-darwin-arm64": "0.34.3",
3078
- "@img/sharp-darwin-x64": "0.34.3",
3079
- "@img/sharp-libvips-darwin-arm64": "1.2.0",
3080
- "@img/sharp-libvips-darwin-x64": "1.2.0",
3081
- "@img/sharp-libvips-linux-arm": "1.2.0",
3082
- "@img/sharp-libvips-linux-arm64": "1.2.0",
3083
- "@img/sharp-libvips-linux-ppc64": "1.2.0",
3084
- "@img/sharp-libvips-linux-s390x": "1.2.0",
3085
- "@img/sharp-libvips-linux-x64": "1.2.0",
3086
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.0",
3087
- "@img/sharp-libvips-linuxmusl-x64": "1.2.0",
3088
- "@img/sharp-linux-arm": "0.34.3",
3089
- "@img/sharp-linux-arm64": "0.34.3",
3090
- "@img/sharp-linux-ppc64": "0.34.3",
3091
- "@img/sharp-linux-s390x": "0.34.3",
3092
- "@img/sharp-linux-x64": "0.34.3",
3093
- "@img/sharp-linuxmusl-arm64": "0.34.3",
3094
- "@img/sharp-linuxmusl-x64": "0.34.3",
3095
- "@img/sharp-wasm32": "0.34.3",
3096
- "@img/sharp-win32-arm64": "0.34.3",
3097
- "@img/sharp-win32-ia32": "0.34.3",
3098
- "@img/sharp-win32-x64": "0.34.3"
3099
- }
3100
- },
3101
  "node_modules/shebang-command": {
3102
  "version": "2.0.0",
3103
  "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -3193,21 +2701,6 @@
3193
  "url": "https://github.com/sponsors/ljharb"
3194
  }
3195
  },
3196
- "node_modules/simple-swizzle": {
3197
- "version": "0.2.2",
3198
- "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
3199
- "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
3200
- "license": "MIT",
3201
- "dependencies": {
3202
- "is-arrayish": "^0.3.1"
3203
- }
3204
- },
3205
- "node_modules/simple-swizzle/node_modules/is-arrayish": {
3206
- "version": "0.3.2",
3207
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
3208
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
3209
- "license": "MIT"
3210
- },
3211
  "node_modules/simple-update-notifier": {
3212
  "version": "2.0.0",
3213
  "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
@@ -3282,6 +2775,18 @@
3282
  "node": "*"
3283
  }
3284
  },
 
 
 
 
 
 
 
 
 
 
 
 
3285
  "node_modules/statuses": {
3286
  "version": "2.0.2",
3287
  "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
@@ -3404,12 +2909,6 @@
3404
  "dev": true,
3405
  "license": "MIT"
3406
  },
3407
- "node_modules/tiny-inflate": {
3408
- "version": "1.0.3",
3409
- "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
3410
- "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
3411
- "license": "MIT"
3412
- },
3413
  "node_modules/to-regex-range": {
3414
  "version": "5.0.1",
3415
  "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -3470,6 +2969,12 @@
3470
  "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
3471
  "license": "0BSD"
3472
  },
 
 
 
 
 
 
3473
  "node_modules/type-is": {
3474
  "version": "2.0.1",
3475
  "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -3518,24 +3023,13 @@
3518
  "license": "MIT",
3519
  "optional": true
3520
  },
3521
- "node_modules/unicode-properties": {
3522
- "version": "1.4.1",
3523
- "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
3524
- "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
3525
- "license": "MIT",
3526
- "dependencies": {
3527
- "base64-js": "^1.3.0",
3528
- "unicode-trie": "^2.0.0"
3529
- }
3530
- },
3531
- "node_modules/unicode-trie": {
3532
- "version": "2.0.0",
3533
- "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
3534
- "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
3535
- "license": "MIT",
3536
  "dependencies": {
3537
- "pako": "^0.2.5",
3538
- "tiny-inflate": "^1.0.0"
3539
  }
3540
  },
3541
  "node_modules/universalify": {
 
9
  "version": "1.0.0",
10
  "dependencies": {
11
  "axios": "^1.11.0",
12
+ "cluster": "^0.7.7",
13
  "cors": "^2.8.5",
14
  "express": "^5.1.0",
 
15
  "puppeteer": "^24.16.2",
16
  "puppeteer-extra": "^3.3.6",
17
+ "puppeteer-extra-plugin-stealth": "^2.11.2"
 
18
  },
19
  "devDependencies": {
20
  "nodemon": "^3.1.10",
 
45
  "node": ">=6.9.0"
46
  }
47
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  "node_modules/@puppeteer/browsers": {
49
  "version": "2.10.6",
50
  "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.6.tgz",
 
66
  "node": ">=18"
67
  }
68
  },
 
 
 
 
 
 
 
 
 
69
  "node_modules/@tootallnate/quickjs-emscripten": {
70
  "version": "0.23.0",
71
  "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
 
295
  }
296
  }
297
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  "node_modules/basic-ftp": {
299
  "version": "5.0.5",
300
  "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
 
360
  "node": ">=8"
361
  }
362
  },
 
 
 
 
 
 
 
 
 
363
  "node_modules/buffer-crc32": {
364
  "version": "0.2.13",
365
  "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
 
468
  "node": ">=12"
469
  }
470
  },
 
 
 
 
 
 
 
 
 
471
  "node_modules/clone-deep": {
472
  "version": "0.2.4",
473
  "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz",
 
484
  "node": ">=0.10.0"
485
  }
486
  },
487
+ "node_modules/cluster": {
488
+ "version": "0.7.7",
489
+ "resolved": "https://registry.npmjs.org/cluster/-/cluster-0.7.7.tgz",
490
+ "integrity": "sha512-16LzEZSoBUgRHSN7NA46ntGnI9tf0NnxTm3KCDvHd6aj4EsBqUbYDN3ImCfjYegBXJZiutULF5rWkcRusMIozQ==",
 
491
  "dependencies": {
492
+ "log": ">= 1.2.0",
493
+ "mkdirp": ">= 0.0.1"
494
  },
495
  "engines": {
496
+ "node": "*"
497
  }
498
  },
499
  "node_modules/color-convert": {
 
514
  "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
515
  "license": "MIT"
516
  },
 
 
 
 
 
 
 
 
 
 
517
  "node_modules/combined-stream": {
518
  "version": "1.0.8",
519
  "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 
625
  "node": ">= 8"
626
  }
627
  },
628
+ "node_modules/d": {
629
+ "version": "1.0.2",
630
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
631
+ "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
632
+ "license": "ISC",
633
+ "dependencies": {
634
+ "es5-ext": "^0.10.64",
635
+ "type": "^2.7.2"
636
+ },
637
+ "engines": {
638
+ "node": ">=0.12"
639
+ }
640
  },
641
  "node_modules/data-uri-to-buffer": {
642
  "version": "6.0.2",
 
705
  "node": ">= 0.8"
706
  }
707
  },
 
 
 
 
 
 
 
 
 
708
  "node_modules/devtools-protocol": {
709
  "version": "0.0.1475386",
710
  "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1475386.tgz",
711
  "integrity": "sha512-RQ809ykTfJ+dgj9bftdeL2vRVxASAuGU+I9LEx9Ij5TXU5HrgAQVmzi72VA+mkzscE12uzlRv5/tWWv9R9J1SA==",
712
  "license": "BSD-3-Clause"
713
  },
 
 
 
 
 
 
714
  "node_modules/dunder-proto": {
715
  "version": "1.0.1",
716
  "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
 
732
  "dev": true,
733
  "license": "MIT"
734
  },
735
+ "node_modules/duration": {
736
+ "version": "0.2.2",
737
+ "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz",
738
+ "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==",
739
+ "license": "ISC",
740
+ "dependencies": {
741
+ "d": "1",
742
+ "es5-ext": "~0.10.46"
743
+ }
744
+ },
745
  "node_modules/ee-first": {
746
  "version": "1.1.1",
747
  "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 
835
  "node": ">= 0.4"
836
  }
837
  },
838
+ "node_modules/es5-ext": {
839
+ "version": "0.10.64",
840
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
841
+ "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
842
+ "hasInstallScript": true,
843
+ "license": "ISC",
844
+ "dependencies": {
845
+ "es6-iterator": "^2.0.3",
846
+ "es6-symbol": "^3.1.3",
847
+ "esniff": "^2.0.1",
848
+ "next-tick": "^1.1.0"
849
+ },
850
+ "engines": {
851
+ "node": ">=0.10"
852
+ }
853
+ },
854
+ "node_modules/es6-iterator": {
855
+ "version": "2.0.3",
856
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
857
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
858
+ "license": "MIT",
859
+ "dependencies": {
860
+ "d": "1",
861
+ "es5-ext": "^0.10.35",
862
+ "es6-symbol": "^3.1.1"
863
+ }
864
+ },
865
+ "node_modules/es6-symbol": {
866
+ "version": "3.1.4",
867
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
868
+ "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
869
+ "license": "ISC",
870
+ "dependencies": {
871
+ "d": "^1.0.2",
872
+ "ext": "^1.7.0"
873
+ },
874
+ "engines": {
875
+ "node": ">=0.12"
876
+ }
877
+ },
878
  "node_modules/escalade": {
879
  "version": "3.2.0",
880
  "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
 
911
  "source-map": "~0.6.1"
912
  }
913
  },
914
+ "node_modules/esniff": {
915
+ "version": "2.0.1",
916
+ "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
917
+ "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
918
+ "license": "ISC",
919
+ "dependencies": {
920
+ "d": "^1.0.1",
921
+ "es5-ext": "^0.10.62",
922
+ "event-emitter": "^0.3.5",
923
+ "type": "^2.7.2"
924
+ },
925
+ "engines": {
926
+ "node": ">=0.10"
927
+ }
928
+ },
929
  "node_modules/esprima": {
930
  "version": "4.0.1",
931
  "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
 
966
  "node": ">= 0.6"
967
  }
968
  },
969
+ "node_modules/event-emitter": {
970
+ "version": "0.3.5",
971
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
972
+ "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
973
+ "license": "MIT",
974
+ "dependencies": {
975
+ "d": "1",
976
+ "es5-ext": "~0.10.14"
977
+ }
978
+ },
979
  "node_modules/event-stream": {
980
  "version": "3.3.4",
981
  "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
 
1034
  "url": "https://opencollective.com/express"
1035
  }
1036
  },
1037
+ "node_modules/ext": {
1038
+ "version": "1.7.0",
1039
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
1040
+ "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
1041
+ "license": "ISC",
1042
+ "dependencies": {
1043
+ "type": "^2.7.2"
1044
+ }
1045
+ },
1046
  "node_modules/extract-zip": {
1047
  "version": "2.0.1",
1048
  "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
 
1063
  "@types/yauzl": "^2.9.1"
1064
  }
1065
  },
 
 
 
 
 
 
1066
  "node_modules/fast-fifo": {
1067
  "version": "1.3.2",
1068
  "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
 
1128
  }
1129
  }
1130
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1131
  "node_modules/for-in": {
1132
  "version": "1.0.2",
1133
  "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
 
1662
  "node": ">=0.10.0"
1663
  }
1664
  },
 
 
 
 
 
 
1665
  "node_modules/js-tokens": {
1666
  "version": "4.0.0",
1667
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
 
1719
  "node": ">=0.10.0"
1720
  }
1721
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1722
  "node_modules/lines-and-columns": {
1723
  "version": "1.2.4",
1724
  "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
1725
  "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
1726
  "license": "MIT"
1727
  },
1728
+ "node_modules/log": {
1729
+ "version": "6.3.2",
1730
+ "resolved": "https://registry.npmjs.org/log/-/log-6.3.2.tgz",
1731
+ "integrity": "sha512-ek8NRg/OPvS9ISOJNWNAz5vZcpYacWNFDWNJjj5OXsc6YuKacfey6wF04cXz/tOJIVrZ2nGSkHpAY5qKtF6ISg==",
1732
+ "license": "ISC",
1733
+ "dependencies": {
1734
+ "d": "^1.0.2",
1735
+ "duration": "^0.2.2",
1736
+ "es5-ext": "^0.10.64",
1737
+ "event-emitter": "^0.3.5",
1738
+ "sprintf-kit": "^2.0.2",
1739
+ "type": "^2.7.3",
1740
+ "uni-global": "^1.0.0"
1741
+ },
1742
+ "engines": {
1743
+ "node": ">=0.12"
1744
+ }
1745
+ },
1746
  "node_modules/lru-cache": {
1747
  "version": "7.18.3",
1748
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
 
1863
  "node": ">=0.10.0"
1864
  }
1865
  },
1866
+ "node_modules/mkdirp": {
1867
+ "version": "3.0.1",
1868
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
1869
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
1870
+ "license": "MIT",
1871
+ "bin": {
1872
+ "mkdirp": "dist/cjs/src/bin.js"
1873
+ },
1874
+ "engines": {
1875
+ "node": ">=10"
1876
+ },
1877
+ "funding": {
1878
+ "url": "https://github.com/sponsors/isaacs"
1879
+ }
1880
+ },
1881
  "node_modules/ms": {
1882
  "version": "2.1.3",
1883
  "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
 
1902
  "node": ">= 0.4.0"
1903
  }
1904
  },
1905
+ "node_modules/next-tick": {
1906
+ "version": "1.1.0",
1907
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
1908
+ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
1909
+ "license": "ISC"
1910
+ },
1911
  "node_modules/node-cleanup": {
1912
  "version": "2.1.2",
1913
  "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz",
 
2028
  "node": ">= 14"
2029
  }
2030
  },
 
 
 
 
 
 
2031
  "node_modules/parent-module": {
2032
  "version": "1.0.1",
2033
  "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
 
2108
  "through": "~2.3"
2109
  }
2110
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
2111
  "node_modules/pend": {
2112
  "version": "1.2.0",
2113
  "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
 
2133
  "url": "https://github.com/sponsors/jonschlinkert"
2134
  }
2135
  },
 
 
 
 
 
2136
  "node_modules/progress": {
2137
  "version": "2.0.3",
2138
  "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
 
2457
  "node": ">=4"
2458
  }
2459
  },
 
 
 
 
 
 
2460
  "node_modules/rimraf": {
2461
  "version": "3.0.2",
2462
  "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
 
2606
  "node": ">=0.10.0"
2607
  }
2608
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2609
  "node_modules/shebang-command": {
2610
  "version": "2.0.0",
2611
  "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
 
2701
  "url": "https://github.com/sponsors/ljharb"
2702
  }
2703
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2704
  "node_modules/simple-update-notifier": {
2705
  "version": "2.0.0",
2706
  "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
 
2775
  "node": "*"
2776
  }
2777
  },
2778
+ "node_modules/sprintf-kit": {
2779
+ "version": "2.0.2",
2780
+ "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz",
2781
+ "integrity": "sha512-lnapdj6W4LflHZGKvl9eVkz5YF0xaTrqpRWVA4cNVOTedwqifIP8ooGImldzT/4IAN5KXFQAyXTdLidYVQdyag==",
2782
+ "license": "ISC",
2783
+ "dependencies": {
2784
+ "es5-ext": "^0.10.64"
2785
+ },
2786
+ "engines": {
2787
+ "node": ">=0.12"
2788
+ }
2789
+ },
2790
  "node_modules/statuses": {
2791
  "version": "2.0.2",
2792
  "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
 
2909
  "dev": true,
2910
  "license": "MIT"
2911
  },
 
 
 
 
 
 
2912
  "node_modules/to-regex-range": {
2913
  "version": "5.0.1",
2914
  "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
 
2969
  "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
2970
  "license": "0BSD"
2971
  },
2972
+ "node_modules/type": {
2973
+ "version": "2.7.3",
2974
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
2975
+ "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==",
2976
+ "license": "ISC"
2977
+ },
2978
  "node_modules/type-is": {
2979
  "version": "2.0.1",
2980
  "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
 
3023
  "license": "MIT",
3024
  "optional": true
3025
  },
3026
+ "node_modules/uni-global": {
3027
+ "version": "1.0.0",
3028
+ "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz",
3029
+ "integrity": "sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw==",
3030
+ "license": "ISC",
 
 
 
 
 
 
 
 
 
 
3031
  "dependencies": {
3032
+ "type": "^2.5.0"
 
3033
  }
3034
  },
3035
  "node_modules/universalify": {
package.json CHANGED
@@ -5,13 +5,12 @@
5
  "type": "commonjs",
6
  "dependencies": {
7
  "axios": "^1.11.0",
 
8
  "cors": "^2.8.5",
9
  "express": "^5.1.0",
10
- "pdfkit": "^0.17.1",
11
  "puppeteer": "^24.16.2",
12
  "puppeteer-extra": "^3.3.6",
13
- "puppeteer-extra-plugin-stealth": "^2.11.2",
14
- "sharp": "^0.34.3"
15
  },
16
  "devDependencies": {
17
  "nodemon": "^3.1.10",
 
5
  "type": "commonjs",
6
  "dependencies": {
7
  "axios": "^1.11.0",
8
+ "cluster": "^0.7.7",
9
  "cors": "^2.8.5",
10
  "express": "^5.1.0",
 
11
  "puppeteer": "^24.16.2",
12
  "puppeteer-extra": "^3.3.6",
13
+ "puppeteer-extra-plugin-stealth": "^2.11.2"
 
14
  },
15
  "devDependencies": {
16
  "nodemon": "^3.1.10",
server copy.js CHANGED
@@ -244,7 +244,6 @@ const applyPrintStyles = async (page, progressTracker) => {
244
  background: white !important;
245
  color: black !important;
246
  }
247
-
248
  /* Remove all unwanted elements like headers, footers, sidebars, etc. */
249
  header, footer, nav, aside, .no-print, .ads, .sidebar, .premium-banner,
250
  [class*="Header"], [class*="Footer"], [class*="Sidebar"], [id*="Header"],
@@ -255,14 +254,12 @@ const applyPrintStyles = async (page, progressTracker) => {
255
  .Layout_sidebar-wrapper__unavM, .Layout_is-open__9DQr4 {
256
  display: none !important;
257
  }
258
-
259
  /* Force all elements to have a transparent background and no shadow */
260
  * {
261
  box-shadow: none !important;
262
  background: transparent !important;
263
  color: inherit !important;
264
  }
265
-
266
  /*
267
  * KEY FIX: Target the main document container.
268
  * Force it to be a block element, remove any transforms or max-widths,
@@ -279,7 +276,6 @@ const applyPrintStyles = async (page, progressTracker) => {
279
  box-sizing: border-box; /* Include padding in width calculation */
280
  transform: none !important;
281
  }
282
-
283
  /* Ensure individual pages and images within the document use the full width */
284
  [data-page], .page, .document-page, img {
285
  page-break-after: always !important;
@@ -306,7 +302,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
306
  progressTracker?.updateProgress(0, 'initializing', 'Starting browser...');
307
 
308
  console.log("πŸš€ Launching browser with enhanced stealth configuration...");
309
- browser = await puppeteerExtra.launch({
310
  headless: true,
311
  args: [
312
  '--no-sandbox',
@@ -330,29 +326,26 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
330
  ],
331
  ignoreHTTPSErrors: true,
332
  timeout: 300000,
333
- // --- FIX: Increased protocolTimeout for long-running operations ---
334
- protocolTimeout: 600000 // 10 minutes, increased from the default 30 seconds
335
  });
336
 
337
  const page = await browser.newPage();
338
 
339
- // --- FIX: Increase default navigation and action timeouts ---
340
- page.setDefaultNavigationTimeout(180000); // 3 minutes for navigation
341
- page.setDefaultTimeout(180000); // 3 minutes for other actions (e.g., waitForSelector)
342
-
343
  progressTracker?.updateProgress(2, 'initializing', 'Configuring browser settings...');
344
 
345
  await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36');
346
  await page.setViewport({ width: 794, height: 1122 }); // A4 size in pixels at 96 DPI
347
 
 
348
  await page.evaluateOnNewDocument(() => {
349
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
350
  Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
351
  Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
352
  });
353
 
 
354
  await bypassCookiesAndRestrictions(page, progressTracker);
355
 
 
356
  await page.setRequestInterception(true);
357
  page.on('request', (req) => {
358
  const resourceType = req.resourceType();
@@ -374,7 +367,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
374
  reqUrl.includes('mixpanel') ||
375
  reqUrl.includes('onetrust') ||
376
  reqUrl.includes('cookielaw') ||
377
- (resourceType === 'other' && reqUrl.includes('/track/'))
378
  ) {
379
  req.abort();
380
  } else {
@@ -382,18 +375,19 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
382
  }
383
  });
384
 
 
385
  if (options.email && options.password) {
386
  progressTracker?.updateProgress(12, 'authenticating', 'Logging into StuDocu...');
387
 
388
  console.log("πŸ”‘ Logging in to StuDocu...");
389
- await page.goto('https://www.studocu.com/en-us/login', { waitUntil: 'domcontentloaded' });
390
- await page.waitForSelector('#email');
391
  await page.type('#email', options.email);
392
  await page.type('#password', options.password);
393
  await page.click('button[type="submit"]');
394
  try {
395
- await page.waitForNavigation({ waitUntil: 'networkidle2' });
396
- await page.waitForSelector('.user-profile, [data-testid="user-menu"]');
397
  console.log("βœ… Login successful.");
398
  progressTracker?.updateProgress(18, 'authenticated', 'Login successful');
399
  } catch (e) {
@@ -404,8 +398,8 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
404
 
405
  progressTracker?.updateProgress(25, 'navigating', 'Navigating to homepage first for session setup...');
406
  console.log(`πŸ“„ Navigating to homepage to simulate natural session...`);
407
- await page.goto('https://www.studocu.com/en-us', { waitUntil: 'domcontentloaded' });
408
- await new Promise(resolve => setTimeout(resolve, 3000));
409
 
410
  progressTracker?.updateProgress(30, 'navigating', 'Navigating to document...');
411
  console.log(`πŸ“„ Navigating to ${url}...`);
@@ -418,20 +412,22 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
418
  attempts++;
419
  progressTracker?.updateProgress(30 + (attempts * 5), 'navigating', `Navigation attempt ${attempts}/${maxAttempts}`);
420
  console.log(`Navigation attempt ${attempts}/${maxAttempts}`);
421
- await page.goto(url, { waitUntil: 'domcontentloaded' });
422
  navigationSuccess = true;
423
  } catch (e) {
424
  console.log(`Navigation attempt ${attempts} failed:`, e.message);
425
  if (attempts >= maxAttempts) throw e;
426
- await new Promise(resolve => setTimeout(resolve, 15000));
427
  }
428
  }
429
 
430
  progressTracker?.updateProgress(40, 'loading', 'Page loaded, waiting for content...');
431
  await new Promise(resolve => setTimeout(resolve, 5000));
432
 
 
433
  await unblurContent(page, progressTracker);
434
 
 
435
  progressTracker?.updateProgress(45, 'loading', 'Waiting for document content...');
436
  console.log("⏳ Waiting for document content to load...");
437
 
@@ -442,7 +438,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
442
  let contentFound = false;
443
  for (const selector of contentSelectors) {
444
  try {
445
- await page.waitForSelector(selector);
446
  console.log(`βœ… Found content with selector: ${selector}`);
447
  contentFound = true;
448
  break;
@@ -455,6 +451,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
455
  console.log("⚠️ No specific content selector found, proceeding with page content...");
456
  }
457
 
 
458
  progressTracker?.updateProgress(50, 'scrolling', 'Loading all document pages...');
459
  console.log("πŸ“œ Loading all document pages with enhanced slow scroll...");
460
 
@@ -480,8 +477,10 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
480
 
481
  progressTracker?.updateProgress(70, 'processing', 'Processing loaded content...');
482
 
 
483
  await unblurContent(page, progressTracker);
484
 
 
485
  progressTracker?.updateProgress(75, 'loading_images', 'Loading images...');
486
  console.log("πŸ–ΌοΈ Waiting for all images to load...");
487
 
@@ -500,6 +499,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
500
  await new Promise(resolve => setTimeout(resolve, 5000));
501
  progressTracker?.updateProgress(80, 'finalizing', 'Preparing document for PDF generation...');
502
 
 
503
  await page.evaluate(() => {
504
  const getDocumentHeight = () => Math.max(
505
  document.body.scrollHeight, document.body.offsetHeight,
@@ -511,6 +511,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
511
  document.body.style.overflow = 'hidden !important';
512
  });
513
 
 
514
  const contentCheck = await page.evaluate(() => {
515
  const textContent = document.body.textContent || '';
516
  const images = document.querySelectorAll('img');
@@ -537,6 +538,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
537
  console.warn("⚠️ Warning: Limited document content detected.");
538
  }
539
 
 
540
  await applyPrintStyles(page, progressTracker);
541
  await page.emulateMediaType('print');
542
 
@@ -545,10 +547,9 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
545
 
546
  const pdfBuffer = await page.pdf({
547
  printBackground: true,
548
- preferCSSPageSize: true,
549
  displayHeaderFooter: false,
550
- // --- FIX: Increased PDF generation timeout ---
551
- timeout: 600000, // 10 minutes, increased from the default 30 seconds
552
  scale: 1,
553
  omitBackground: false
554
  });
@@ -588,16 +589,20 @@ app.post('/api/request-download', (req, res) => {
588
 
589
  console.log(`🎯 Processing request for: ${url} [Session: ${sessionId}]`);
590
 
 
591
  res.json({ sessionId });
592
 
 
593
  studocuDownloader(url, { email, password }, progressTracker)
594
  .then(pdfBuffer => {
 
595
  downloadJobs.set(sessionId, { status: 'completed', buffer: pdfBuffer });
596
- progressTrackers.delete(sessionId);
597
  })
598
  .catch(error => {
 
599
  downloadJobs.set(sessionId, { status: 'error', message: error.message });
600
- progressTrackers.delete(sessionId);
601
  });
602
  });
603
 
@@ -606,6 +611,7 @@ app.get('/api/progress/:sessionId', (req, res) => {
606
  const tracker = progressTrackers.get(sessionId);
607
 
608
  if (tracker) {
 
609
  return res.json({
610
  sessionId,
611
  progress: tracker.progress,
@@ -617,6 +623,7 @@ app.get('/api/progress/:sessionId', (req, res) => {
617
 
618
  const job = downloadJobs.get(sessionId);
619
  if (job) {
 
620
  if (job.status === 'completed') {
621
  return res.json({ sessionId, progress: 100, status: 'completed', message: 'PDF generated successfully!' });
622
  }
@@ -648,6 +655,8 @@ app.get('/api/download/:sessionId', (req, res) => {
648
  res.setHeader('Content-Type', 'application/pdf');
649
  res.setHeader('Content-Disposition', 'attachment; filename=studocu-document.pdf');
650
  res.send(job.buffer);
 
 
651
  } else {
652
  res.status(500).json({ error: 'An unknown error occurred.' });
653
  }
 
244
  background: white !important;
245
  color: black !important;
246
  }
 
247
  /* Remove all unwanted elements like headers, footers, sidebars, etc. */
248
  header, footer, nav, aside, .no-print, .ads, .sidebar, .premium-banner,
249
  [class*="Header"], [class*="Footer"], [class*="Sidebar"], [id*="Header"],
 
254
  .Layout_sidebar-wrapper__unavM, .Layout_is-open__9DQr4 {
255
  display: none !important;
256
  }
 
257
  /* Force all elements to have a transparent background and no shadow */
258
  * {
259
  box-shadow: none !important;
260
  background: transparent !important;
261
  color: inherit !important;
262
  }
 
263
  /*
264
  * KEY FIX: Target the main document container.
265
  * Force it to be a block element, remove any transforms or max-widths,
 
276
  box-sizing: border-box; /* Include padding in width calculation */
277
  transform: none !important;
278
  }
 
279
  /* Ensure individual pages and images within the document use the full width */
280
  [data-page], .page, .document-page, img {
281
  page-break-after: always !important;
 
302
  progressTracker?.updateProgress(0, 'initializing', 'Starting browser...');
303
 
304
  console.log("πŸš€ Launching browser with enhanced stealth configuration...");
305
+ browser = await puppeteerExtra.launch({ // UPDATED: Use puppeteerExtra
306
  headless: true,
307
  args: [
308
  '--no-sandbox',
 
326
  ],
327
  ignoreHTTPSErrors: true,
328
  timeout: 300000,
 
 
329
  });
330
 
331
  const page = await browser.newPage();
332
 
 
 
 
 
333
  progressTracker?.updateProgress(2, 'initializing', 'Configuring browser settings...');
334
 
335
  await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36');
336
  await page.setViewport({ width: 794, height: 1122 }); // A4 size in pixels at 96 DPI
337
 
338
+ // NOTE: Stealth plugin handles most of this, but keeping for extra safety
339
  await page.evaluateOnNewDocument(() => {
340
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
341
  Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
342
  Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
343
  });
344
 
345
+ // Set up cookie and content bypass
346
  await bypassCookiesAndRestrictions(page, progressTracker);
347
 
348
+ // Block unnecessary resources (UPDATED: Always continue for 'document' to prevent navigation failures)
349
  await page.setRequestInterception(true);
350
  page.on('request', (req) => {
351
  const resourceType = req.resourceType();
 
367
  reqUrl.includes('mixpanel') ||
368
  reqUrl.includes('onetrust') ||
369
  reqUrl.includes('cookielaw') ||
370
+ (resourceType === 'other' && reqUrl.includes('/track/')) // UPDATED: More specific to avoid over-blocking
371
  ) {
372
  req.abort();
373
  } else {
 
375
  }
376
  });
377
 
378
+ // Login if credentials provided
379
  if (options.email && options.password) {
380
  progressTracker?.updateProgress(12, 'authenticating', 'Logging into StuDocu...');
381
 
382
  console.log("πŸ”‘ Logging in to StuDocu...");
383
+ await page.goto('https://www.studocu.com/en-us/login', { waitUntil: 'domcontentloaded', timeout: 120000 });
384
+ await page.waitForSelector('#email', { timeout: 15000 });
385
  await page.type('#email', options.email);
386
  await page.type('#password', options.password);
387
  await page.click('button[type="submit"]');
388
  try {
389
+ await page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 30000 });
390
+ await page.waitForSelector('.user-profile, [data-testid="user-menu"]', { timeout: 10000 });
391
  console.log("βœ… Login successful.");
392
  progressTracker?.updateProgress(18, 'authenticated', 'Login successful');
393
  } catch (e) {
 
398
 
399
  progressTracker?.updateProgress(25, 'navigating', 'Navigating to homepage first for session setup...');
400
  console.log(`πŸ“„ Navigating to homepage to simulate natural session...`);
401
+ await page.goto('https://www.studocu.com/en-us', { waitUntil: 'domcontentloaded', timeout: 150000 }); // NEW: Preliminary homepage visit
402
+ await new Promise(resolve => setTimeout(resolve, 3000)); // Short delay for session stabilization
403
 
404
  progressTracker?.updateProgress(30, 'navigating', 'Navigating to document...');
405
  console.log(`πŸ“„ Navigating to ${url}...`);
 
412
  attempts++;
413
  progressTracker?.updateProgress(30 + (attempts * 5), 'navigating', `Navigation attempt ${attempts}/${maxAttempts}`);
414
  console.log(`Navigation attempt ${attempts}/${maxAttempts}`);
415
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 150000 }); // UPDATED: Increased timeout to 2.5 min
416
  navigationSuccess = true;
417
  } catch (e) {
418
  console.log(`Navigation attempt ${attempts} failed:`, e.message);
419
  if (attempts >= maxAttempts) throw e;
420
+ await new Promise(resolve => setTimeout(resolve, 15000)); // UPDATED: Increased retry delay to 15s
421
  }
422
  }
423
 
424
  progressTracker?.updateProgress(40, 'loading', 'Page loaded, waiting for content...');
425
  await new Promise(resolve => setTimeout(resolve, 5000));
426
 
427
+ // Apply content unblurring
428
  await unblurContent(page, progressTracker);
429
 
430
+ // Wait for document content
431
  progressTracker?.updateProgress(45, 'loading', 'Waiting for document content...');
432
  console.log("⏳ Waiting for document content to load...");
433
 
 
438
  let contentFound = false;
439
  for (const selector of contentSelectors) {
440
  try {
441
+ await page.waitForSelector(selector, { timeout: 20000 });
442
  console.log(`βœ… Found content with selector: ${selector}`);
443
  contentFound = true;
444
  break;
 
451
  console.log("⚠️ No specific content selector found, proceeding with page content...");
452
  }
453
 
454
+ // Enhanced scrolling to load all content
455
  progressTracker?.updateProgress(50, 'scrolling', 'Loading all document pages...');
456
  console.log("πŸ“œ Loading all document pages with enhanced slow scroll...");
457
 
 
477
 
478
  progressTracker?.updateProgress(70, 'processing', 'Processing loaded content...');
479
 
480
+ // Re-apply unblur after loading new content
481
  await unblurContent(page, progressTracker);
482
 
483
+ // Wait for all images to load
484
  progressTracker?.updateProgress(75, 'loading_images', 'Loading images...');
485
  console.log("πŸ–ΌοΈ Waiting for all images to load...");
486
 
 
499
  await new Promise(resolve => setTimeout(resolve, 5000));
500
  progressTracker?.updateProgress(80, 'finalizing', 'Preparing document for PDF generation...');
501
 
502
+ // Set exact height
503
  await page.evaluate(() => {
504
  const getDocumentHeight = () => Math.max(
505
  document.body.scrollHeight, document.body.offsetHeight,
 
511
  document.body.style.overflow = 'hidden !important';
512
  });
513
 
514
+ // Content verification
515
  const contentCheck = await page.evaluate(() => {
516
  const textContent = document.body.textContent || '';
517
  const images = document.querySelectorAll('img');
 
538
  console.warn("⚠️ Warning: Limited document content detected.");
539
  }
540
 
541
+ // Apply print styles and generate PDF
542
  await applyPrintStyles(page, progressTracker);
543
  await page.emulateMediaType('print');
544
 
 
547
 
548
  const pdfBuffer = await page.pdf({
549
  printBackground: true,
550
+ preferCSSPageSize: true, // Use the @page size
551
  displayHeaderFooter: false,
552
+ timeout: 180000,
 
553
  scale: 1,
554
  omitBackground: false
555
  });
 
589
 
590
  console.log(`🎯 Processing request for: ${url} [Session: ${sessionId}]`);
591
 
592
+ // Respond to the client immediately with the session ID
593
  res.json({ sessionId });
594
 
595
+ // --- Start the PDF generation in the background ---
596
  studocuDownloader(url, { email, password }, progressTracker)
597
  .then(pdfBuffer => {
598
+ // Store the successful result
599
  downloadJobs.set(sessionId, { status: 'completed', buffer: pdfBuffer });
600
+ progressTrackers.delete(sessionId); // Clean up live tracker
601
  })
602
  .catch(error => {
603
+ // Store the error
604
  downloadJobs.set(sessionId, { status: 'error', message: error.message });
605
+ progressTrackers.delete(sessionId); // Clean up live tracker
606
  });
607
  });
608
 
 
611
  const tracker = progressTrackers.get(sessionId);
612
 
613
  if (tracker) {
614
+ // Job is in progress, return live data
615
  return res.json({
616
  sessionId,
617
  progress: tracker.progress,
 
623
 
624
  const job = downloadJobs.get(sessionId);
625
  if (job) {
626
+ // Job is finished, return final state
627
  if (job.status === 'completed') {
628
  return res.json({ sessionId, progress: 100, status: 'completed', message: 'PDF generated successfully!' });
629
  }
 
655
  res.setHeader('Content-Type', 'application/pdf');
656
  res.setHeader('Content-Disposition', 'attachment; filename=studocu-document.pdf');
657
  res.send(job.buffer);
658
+ // Optional: Clean up the job after download to save memory
659
+ // downloadJobs.delete(sessionId);
660
  } else {
661
  res.status(500).json({ error: 'An unknown error occurred.' });
662
  }
server.js CHANGED
@@ -213,8 +213,8 @@ const unblurContent = async (page, progressTracker) => {
213
  };
214
 
215
  removeRestrictions();
216
- const intervalId = setInterval(removeRestrictions, 2000);
217
- setTimeout(() => clearInterval(intervalId), 60000);
218
  });
219
 
220
  progressTracker?.updateProgress(20, 'unblurring', 'Content restrictions removed');
@@ -244,7 +244,6 @@ const applyPrintStyles = async (page, progressTracker) => {
244
  background: white !important;
245
  color: black !important;
246
  }
247
-
248
  /* Remove all unwanted elements like headers, footers, sidebars, etc. */
249
  header, footer, nav, aside, .no-print, .ads, .sidebar, .premium-banner,
250
  [class*="Header"], [class*="Footer"], [class*="Sidebar"], [id*="Header"],
@@ -255,14 +254,12 @@ const applyPrintStyles = async (page, progressTracker) => {
255
  .Layout_sidebar-wrapper__unavM, .Layout_is-open__9DQr4 {
256
  display: none !important;
257
  }
258
-
259
  /* Force all elements to have a transparent background and no shadow */
260
  * {
261
  box-shadow: none !important;
262
  background: transparent !important;
263
  color: inherit !important;
264
  }
265
-
266
  /*
267
  * KEY FIX: Target the main document container.
268
  * Force it to be a block element, remove any transforms or max-widths,
@@ -279,7 +276,6 @@ const applyPrintStyles = async (page, progressTracker) => {
279
  box-sizing: border-box; /* Include padding in width calculation */
280
  transform: none !important;
281
  }
282
-
283
  /* Ensure individual pages and images within the document use the full width */
284
  [data-page], .page, .document-page, img {
285
  page-break-after: always !important;
@@ -306,7 +302,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
306
  progressTracker?.updateProgress(0, 'initializing', 'Starting browser...');
307
 
308
  console.log("πŸš€ Launching browser with enhanced stealth configuration...");
309
- browser = await puppeteerExtra.launch({
310
  headless: true,
311
  args: [
312
  '--no-sandbox',
@@ -330,29 +326,26 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
330
  ],
331
  ignoreHTTPSErrors: true,
332
  timeout: 300000,
333
- // --- FIX: Increased protocolTimeout for long-running operations ---
334
- protocolTimeout: 600000 // 10 minutes, increased from the default 30 seconds
335
  });
336
 
337
  const page = await browser.newPage();
338
 
339
- // --- FIX: Increase default navigation and action timeouts ---
340
- page.setDefaultNavigationTimeout(180000); // 3 minutes for navigation
341
- page.setDefaultTimeout(180000); // 3 minutes for other actions (e.g., waitForSelector)
342
-
343
  progressTracker?.updateProgress(2, 'initializing', 'Configuring browser settings...');
344
 
345
  await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36');
346
  await page.setViewport({ width: 794, height: 1122 }); // A4 size in pixels at 96 DPI
347
 
 
348
  await page.evaluateOnNewDocument(() => {
349
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
350
  Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
351
  Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
352
  });
353
 
 
354
  await bypassCookiesAndRestrictions(page, progressTracker);
355
 
 
356
  await page.setRequestInterception(true);
357
  page.on('request', (req) => {
358
  const resourceType = req.resourceType();
@@ -364,6 +357,9 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
364
  }
365
 
366
  if (
 
 
 
367
  reqUrl.includes('doubleclick') ||
368
  reqUrl.includes('googletagmanager') ||
369
  reqUrl.includes('facebook.com') ||
@@ -382,18 +378,19 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
382
  }
383
  });
384
 
 
385
  if (options.email && options.password) {
386
  progressTracker?.updateProgress(12, 'authenticating', 'Logging into StuDocu...');
387
 
388
  console.log("πŸ”‘ Logging in to StuDocu...");
389
- await page.goto('https://www.studocu.com/en-us/login', { waitUntil: 'domcontentloaded' });
390
- await page.waitForSelector('#email');
391
  await page.type('#email', options.email);
392
  await page.type('#password', options.password);
393
  await page.click('button[type="submit"]');
394
  try {
395
- await page.waitForNavigation({ waitUntil: 'networkidle2' });
396
- await page.waitForSelector('.user-profile, [data-testid="user-menu"]');
397
  console.log("βœ… Login successful.");
398
  progressTracker?.updateProgress(18, 'authenticated', 'Login successful');
399
  } catch (e) {
@@ -402,36 +399,34 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
402
  }
403
  }
404
 
405
- progressTracker?.updateProgress(25, 'navigating', 'Navigating to homepage first for session setup...');
406
- console.log(`πŸ“„ Navigating to homepage to simulate natural session...`);
407
- await page.goto('https://www.studocu.com/en-us', { waitUntil: 'domcontentloaded' });
408
- await new Promise(resolve => setTimeout(resolve, 3000));
409
-
410
  progressTracker?.updateProgress(30, 'navigating', 'Navigating to document...');
411
  console.log(`πŸ“„ Navigating to ${url}...`);
412
 
413
  let navigationSuccess = false;
414
  let attempts = 0;
415
- const maxAttempts = 5;
416
  while (!navigationSuccess && attempts < maxAttempts) {
417
  try {
418
  attempts++;
419
  progressTracker?.updateProgress(30 + (attempts * 5), 'navigating', `Navigation attempt ${attempts}/${maxAttempts}`);
420
  console.log(`Navigation attempt ${attempts}/${maxAttempts}`);
421
- await page.goto(url, { waitUntil: 'domcontentloaded' });
422
  navigationSuccess = true;
423
  } catch (e) {
424
  console.log(`Navigation attempt ${attempts} failed:`, e.message);
425
  if (attempts >= maxAttempts) throw e;
426
- await new Promise(resolve => setTimeout(resolve, 15000));
427
  }
428
  }
429
 
430
  progressTracker?.updateProgress(40, 'loading', 'Page loaded, waiting for content...');
431
- await new Promise(resolve => setTimeout(resolve, 5000));
432
 
 
433
  await unblurContent(page, progressTracker);
434
 
 
435
  progressTracker?.updateProgress(45, 'loading', 'Waiting for document content...');
436
  console.log("⏳ Waiting for document content to load...");
437
 
@@ -442,7 +437,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
442
  let contentFound = false;
443
  for (const selector of contentSelectors) {
444
  try {
445
- await page.waitForSelector(selector);
446
  console.log(`βœ… Found content with selector: ${selector}`);
447
  contentFound = true;
448
  break;
@@ -455,6 +450,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
455
  console.log("⚠️ No specific content selector found, proceeding with page content...");
456
  }
457
 
 
458
  progressTracker?.updateProgress(50, 'scrolling', 'Loading all document pages...');
459
  console.log("πŸ“œ Loading all document pages with enhanced slow scroll...");
460
 
@@ -463,25 +459,27 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
463
  let scrollHeight = document.body.scrollHeight;
464
  while (true) {
465
  let totalHeight = 0;
466
- const distance = 300;
467
  while (totalHeight < scrollHeight) {
468
  window.scrollBy(0, distance);
469
  totalHeight += distance;
470
- await delay(500);
471
  }
472
- await delay(2000);
473
  const newHeight = document.body.scrollHeight;
474
  if (newHeight === scrollHeight) break;
475
  scrollHeight = newHeight;
476
  }
477
  window.scrollTo({ top: 0, behavior: "smooth" });
478
- await delay(1000);
479
  });
480
 
481
  progressTracker?.updateProgress(70, 'processing', 'Processing loaded content...');
482
 
 
483
  await unblurContent(page, progressTracker);
484
 
 
485
  progressTracker?.updateProgress(75, 'loading_images', 'Loading images...');
486
  console.log("πŸ–ΌοΈ Waiting for all images to load...");
487
 
@@ -492,14 +490,15 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
492
  return new Promise((resolve) => {
493
  img.addEventListener('load', resolve);
494
  img.addEventListener('error', resolve);
495
- setTimeout(resolve, 15000);
496
  });
497
  }));
498
  });
499
 
500
- await new Promise(resolve => setTimeout(resolve, 5000));
501
  progressTracker?.updateProgress(80, 'finalizing', 'Preparing document for PDF generation...');
502
 
 
503
  await page.evaluate(() => {
504
  const getDocumentHeight = () => Math.max(
505
  document.body.scrollHeight, document.body.offsetHeight,
@@ -511,6 +510,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
511
  document.body.style.overflow = 'hidden !important';
512
  });
513
 
 
514
  const contentCheck = await page.evaluate(() => {
515
  const textContent = document.body.textContent || '';
516
  const images = document.querySelectorAll('img');
@@ -537,6 +537,7 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
537
  console.warn("⚠️ Warning: Limited document content detected.");
538
  }
539
 
 
540
  await applyPrintStyles(page, progressTracker);
541
  await page.emulateMediaType('print');
542
 
@@ -545,10 +546,9 @@ const studocuDownloader = async (url, options = {}, progressTracker = null) => {
545
 
546
  const pdfBuffer = await page.pdf({
547
  printBackground: true,
548
- preferCSSPageSize: true,
549
  displayHeaderFooter: false,
550
- // --- FIX: Increased PDF generation timeout ---
551
- timeout: 600000, // 10 minutes, increased from the default 30 seconds
552
  scale: 1,
553
  omitBackground: false
554
  });
@@ -588,16 +588,20 @@ app.post('/api/request-download', (req, res) => {
588
 
589
  console.log(`🎯 Processing request for: ${url} [Session: ${sessionId}]`);
590
 
 
591
  res.json({ sessionId });
592
 
 
593
  studocuDownloader(url, { email, password }, progressTracker)
594
  .then(pdfBuffer => {
 
595
  downloadJobs.set(sessionId, { status: 'completed', buffer: pdfBuffer });
596
- progressTrackers.delete(sessionId);
597
  })
598
  .catch(error => {
 
599
  downloadJobs.set(sessionId, { status: 'error', message: error.message });
600
- progressTrackers.delete(sessionId);
601
  });
602
  });
603
 
@@ -606,6 +610,7 @@ app.get('/api/progress/:sessionId', (req, res) => {
606
  const tracker = progressTrackers.get(sessionId);
607
 
608
  if (tracker) {
 
609
  return res.json({
610
  sessionId,
611
  progress: tracker.progress,
@@ -617,6 +622,7 @@ app.get('/api/progress/:sessionId', (req, res) => {
617
 
618
  const job = downloadJobs.get(sessionId);
619
  if (job) {
 
620
  if (job.status === 'completed') {
621
  return res.json({ sessionId, progress: 100, status: 'completed', message: 'PDF generated successfully!' });
622
  }
@@ -648,6 +654,8 @@ app.get('/api/download/:sessionId', (req, res) => {
648
  res.setHeader('Content-Type', 'application/pdf');
649
  res.setHeader('Content-Disposition', 'attachment; filename=studocu-document.pdf');
650
  res.send(job.buffer);
 
 
651
  } else {
652
  res.status(500).json({ error: 'An unknown error occurred.' });
653
  }
 
213
  };
214
 
215
  removeRestrictions();
216
+ const intervalId = setInterval(removeRestrictions, 1000); // Reduced from 2000ms to 1000ms
217
+ setTimeout(() => clearInterval(intervalId), 30000); // Reduced from 60000ms to 30000ms
218
  });
219
 
220
  progressTracker?.updateProgress(20, 'unblurring', 'Content restrictions removed');
 
244
  background: white !important;
245
  color: black !important;
246
  }
 
247
  /* Remove all unwanted elements like headers, footers, sidebars, etc. */
248
  header, footer, nav, aside, .no-print, .ads, .sidebar, .premium-banner,
249
  [class*="Header"], [class*="Footer"], [class*="Sidebar"], [id*="Header"],
 
254
  .Layout_sidebar-wrapper__unavM, .Layout_is-open__9DQr4 {
255
  display: none !important;
256
  }
 
257
  /* Force all elements to have a transparent background and no shadow */
258
  * {
259
  box-shadow: none !important;
260
  background: transparent !important;
261
  color: inherit !important;
262
  }
 
263
  /*
264
  * KEY FIX: Target the main document container.
265
  * Force it to be a block element, remove any transforms or max-widths,
 
276
  box-sizing: border-box; /* Include padding in width calculation */
277
  transform: none !important;
278
  }
 
279
  /* Ensure individual pages and images within the document use the full width */
280
  [data-page], .page, .document-page, img {
281
  page-break-after: always !important;
 
302
  progressTracker?.updateProgress(0, 'initializing', 'Starting browser...');
303
 
304
  console.log("πŸš€ Launching browser with enhanced stealth configuration...");
305
+ browser = await puppeteerExtra.launch({ // UPDATED: Use puppeteerExtra
306
  headless: true,
307
  args: [
308
  '--no-sandbox',
 
326
  ],
327
  ignoreHTTPSErrors: true,
328
  timeout: 300000,
 
 
329
  });
330
 
331
  const page = await browser.newPage();
332
 
 
 
 
 
333
  progressTracker?.updateProgress(2, 'initializing', 'Configuring browser settings...');
334
 
335
  await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36');
336
  await page.setViewport({ width: 794, height: 1122 }); // A4 size in pixels at 96 DPI
337
 
338
+ // NOTE: Stealth plugin handles most of this, but keeping for extra safety
339
  await page.evaluateOnNewDocument(() => {
340
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
341
  Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
342
  Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
343
  });
344
 
345
+ // Set up cookie and content bypass
346
  await bypassCookiesAndRestrictions(page, progressTracker);
347
 
348
+ // Block unnecessary resources (UPDATED: Block more aggressively, including scripts, fonts, and stylesheets if not critical)
349
  await page.setRequestInterception(true);
350
  page.on('request', (req) => {
351
  const resourceType = req.resourceType();
 
357
  }
358
 
359
  if (
360
+ ['image', 'media', 'font', 'stylesheet'].includes(resourceType) && // Block non-essential images/media/fonts/styles early if not core
361
+ !reqUrl.includes('document') && !reqUrl.includes('page') && !reqUrl.includes('studocu') || // Allow core document images
362
+ resourceType === 'script' && !reqUrl.includes('studocu') || // Block third-party scripts
363
  reqUrl.includes('doubleclick') ||
364
  reqUrl.includes('googletagmanager') ||
365
  reqUrl.includes('facebook.com') ||
 
378
  }
379
  });
380
 
381
+ // Login if credentials provided
382
  if (options.email && options.password) {
383
  progressTracker?.updateProgress(12, 'authenticating', 'Logging into StuDocu...');
384
 
385
  console.log("πŸ”‘ Logging in to StuDocu...");
386
+ await page.goto('https://www.studocu.com/en-us/login', { waitUntil: 'domcontentloaded', timeout: 60000 }); // Reduced timeout from 120000
387
+ await page.waitForSelector('#email', { timeout: 10000 }); // Reduced from 15000
388
  await page.type('#email', options.email);
389
  await page.type('#password', options.password);
390
  await page.click('button[type="submit"]');
391
  try {
392
+ await page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 }); // Reduced from 30000
393
+ await page.waitForSelector('.user-profile, [data-testid="user-menu"]', { timeout: 5000 }); // Reduced from 10000
394
  console.log("βœ… Login successful.");
395
  progressTracker?.updateProgress(18, 'authenticated', 'Login successful');
396
  } catch (e) {
 
399
  }
400
  }
401
 
402
+ // Removed homepage visit as it's not strictly necessary for session setup; directly navigate to URL
 
 
 
 
403
  progressTracker?.updateProgress(30, 'navigating', 'Navigating to document...');
404
  console.log(`πŸ“„ Navigating to ${url}...`);
405
 
406
  let navigationSuccess = false;
407
  let attempts = 0;
408
+ const maxAttempts = 3; // Reduced from 5 to minimize retries
409
  while (!navigationSuccess && attempts < maxAttempts) {
410
  try {
411
  attempts++;
412
  progressTracker?.updateProgress(30 + (attempts * 5), 'navigating', `Navigation attempt ${attempts}/${maxAttempts}`);
413
  console.log(`Navigation attempt ${attempts}/${maxAttempts}`);
414
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 }); // Reduced timeout from 150000
415
  navigationSuccess = true;
416
  } catch (e) {
417
  console.log(`Navigation attempt ${attempts} failed:`, e.message);
418
  if (attempts >= maxAttempts) throw e;
419
+ await new Promise(resolve => setTimeout(resolve, 5000)); // Reduced retry delay from 15000 to 5000ms
420
  }
421
  }
422
 
423
  progressTracker?.updateProgress(40, 'loading', 'Page loaded, waiting for content...');
424
+ await new Promise(resolve => setTimeout(resolve, 2000)); // Reduced from 5000ms
425
 
426
+ // Apply content unblurring
427
  await unblurContent(page, progressTracker);
428
 
429
+ // Wait for document content
430
  progressTracker?.updateProgress(45, 'loading', 'Waiting for document content...');
431
  console.log("⏳ Waiting for document content to load...");
432
 
 
437
  let contentFound = false;
438
  for (const selector of contentSelectors) {
439
  try {
440
+ await page.waitForSelector(selector, { timeout: 10000 }); // Reduced from 20000
441
  console.log(`βœ… Found content with selector: ${selector}`);
442
  contentFound = true;
443
  break;
 
450
  console.log("⚠️ No specific content selector found, proceeding with page content...");
451
  }
452
 
453
+ // Enhanced scrolling to load all content (Optimized: Increased scroll distance, reduced delays)
454
  progressTracker?.updateProgress(50, 'scrolling', 'Loading all document pages...');
455
  console.log("πŸ“œ Loading all document pages with enhanced slow scroll...");
456
 
 
459
  let scrollHeight = document.body.scrollHeight;
460
  while (true) {
461
  let totalHeight = 0;
462
+ const distance = 600; // Increased from 300 for faster coverage
463
  while (totalHeight < scrollHeight) {
464
  window.scrollBy(0, distance);
465
  totalHeight += distance;
466
+ await delay(200); // Reduced from 500ms
467
  }
468
+ await delay(1000); // Reduced from 2000ms
469
  const newHeight = document.body.scrollHeight;
470
  if (newHeight === scrollHeight) break;
471
  scrollHeight = newHeight;
472
  }
473
  window.scrollTo({ top: 0, behavior: "smooth" });
474
+ await delay(500); // Reduced from 1000ms
475
  });
476
 
477
  progressTracker?.updateProgress(70, 'processing', 'Processing loaded content...');
478
 
479
+ // Re-apply unblur after loading new content
480
  await unblurContent(page, progressTracker);
481
 
482
+ // Wait for all images to load (Optimized: Reduced per-image timeout, parallel wait)
483
  progressTracker?.updateProgress(75, 'loading_images', 'Loading images...');
484
  console.log("πŸ–ΌοΈ Waiting for all images to load...");
485
 
 
490
  return new Promise((resolve) => {
491
  img.addEventListener('load', resolve);
492
  img.addEventListener('error', resolve);
493
+ setTimeout(resolve, 5000); // Reduced from 15000ms
494
  });
495
  }));
496
  });
497
 
498
+ await new Promise(resolve => setTimeout(resolve, 2000)); // Reduced from 5000ms
499
  progressTracker?.updateProgress(80, 'finalizing', 'Preparing document for PDF generation...');
500
 
501
+ // Set exact height
502
  await page.evaluate(() => {
503
  const getDocumentHeight = () => Math.max(
504
  document.body.scrollHeight, document.body.offsetHeight,
 
510
  document.body.style.overflow = 'hidden !important';
511
  });
512
 
513
+ // Content verification (Unchanged, as it's quick)
514
  const contentCheck = await page.evaluate(() => {
515
  const textContent = document.body.textContent || '';
516
  const images = document.querySelectorAll('img');
 
537
  console.warn("⚠️ Warning: Limited document content detected.");
538
  }
539
 
540
+ // Apply print styles and generate PDF
541
  await applyPrintStyles(page, progressTracker);
542
  await page.emulateMediaType('print');
543
 
 
546
 
547
  const pdfBuffer = await page.pdf({
548
  printBackground: true,
549
+ preferCSSPageSize: true, // Use the @page size
550
  displayHeaderFooter: false,
551
+ timeout: 60000, // Reduced from 180000
 
552
  scale: 1,
553
  omitBackground: false
554
  });
 
588
 
589
  console.log(`🎯 Processing request for: ${url} [Session: ${sessionId}]`);
590
 
591
+ // Respond to the client immediately with the session ID
592
  res.json({ sessionId });
593
 
594
+ // --- Start the PDF generation in the background ---
595
  studocuDownloader(url, { email, password }, progressTracker)
596
  .then(pdfBuffer => {
597
+ // Store the successful result
598
  downloadJobs.set(sessionId, { status: 'completed', buffer: pdfBuffer });
599
+ progressTrackers.delete(sessionId); // Clean up live tracker
600
  })
601
  .catch(error => {
602
+ // Store the error
603
  downloadJobs.set(sessionId, { status: 'error', message: error.message });
604
+ progressTrackers.delete(sessionId); // Clean up live tracker
605
  });
606
  });
607
 
 
610
  const tracker = progressTrackers.get(sessionId);
611
 
612
  if (tracker) {
613
+ // Job is in progress, return live data
614
  return res.json({
615
  sessionId,
616
  progress: tracker.progress,
 
622
 
623
  const job = downloadJobs.get(sessionId);
624
  if (job) {
625
+ // Job is finished, return final state
626
  if (job.status === 'completed') {
627
  return res.json({ sessionId, progress: 100, status: 'completed', message: 'PDF generated successfully!' });
628
  }
 
654
  res.setHeader('Content-Type', 'application/pdf');
655
  res.setHeader('Content-Disposition', 'attachment; filename=studocu-document.pdf');
656
  res.send(job.buffer);
657
+ // Optional: Clean up the job after download to save memory
658
+ // downloadJobs.delete(sessionId);
659
  } else {
660
  res.status(500).json({ error: 'An unknown error occurred.' });
661
  }