entrox-bypass 0.2.0 → 0.3.1
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 +248 -149
- package/dist/index.cjs +407 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +388 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/types/index.d.ts +84 -2
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -22,6 +32,15 @@ var index_exports = {};
|
|
|
22
32
|
__export(index_exports, {
|
|
23
33
|
automateLogin: () => automateLogin,
|
|
24
34
|
default: () => index_default,
|
|
35
|
+
delay: () => delay,
|
|
36
|
+
executeWithRandomDelay: () => executeWithRandomDelay,
|
|
37
|
+
isRetryable: () => isRetryable,
|
|
38
|
+
loadCookies: () => loadCookies,
|
|
39
|
+
randomBetween: () => randomBetween,
|
|
40
|
+
retry: () => retry,
|
|
41
|
+
saveCookies: () => saveCookies,
|
|
42
|
+
sendWebhook: () => sendWebhook,
|
|
43
|
+
setupProxy: () => setupProxy,
|
|
25
44
|
solveCaptchaFromPage: () => solveCaptchaFromPage
|
|
26
45
|
});
|
|
27
46
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -116,8 +135,62 @@ validateConfig(config);
|
|
|
116
135
|
import_cloudinary.v2.config(config);
|
|
117
136
|
var cloudinary_default = import_cloudinary.v2;
|
|
118
137
|
|
|
138
|
+
// src/utils/retry.ts
|
|
139
|
+
var RETRYABLE_ERROR_NAMES = /* @__PURE__ */ new Set([
|
|
140
|
+
"TimeoutError",
|
|
141
|
+
"NetworkError",
|
|
142
|
+
"PlaywrightError",
|
|
143
|
+
"LlmError",
|
|
144
|
+
"CloudinaryError",
|
|
145
|
+
"FetchError",
|
|
146
|
+
"RateLimitError",
|
|
147
|
+
"RetryableError"
|
|
148
|
+
]);
|
|
149
|
+
function isRetryable(error) {
|
|
150
|
+
if (!error || typeof error !== "object") return false;
|
|
151
|
+
const err = error;
|
|
152
|
+
if (err.name && RETRYABLE_ERROR_NAMES.has(err.name)) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if (typeof err.message === "string") {
|
|
156
|
+
const lowerMessage = err.message.toLowerCase();
|
|
157
|
+
if (lowerMessage.includes("timeout") || lowerMessage.includes("network") || lowerMessage.includes("refused") || lowerMessage.includes("reset") || lowerMessage.includes("rate limit") || lowerMessage.includes("too many requests") || lowerMessage.includes("unavailable")) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
async function retry(fn, options) {
|
|
164
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
|
165
|
+
const initialDelay = options?.delayMs ?? 1e3;
|
|
166
|
+
const multiplier = options?.multiplier ?? 2;
|
|
167
|
+
const onRetry = options?.onRetry;
|
|
168
|
+
let lastError;
|
|
169
|
+
let totalDelay = 0;
|
|
170
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
171
|
+
try {
|
|
172
|
+
return await fn();
|
|
173
|
+
} catch (error) {
|
|
174
|
+
lastError = error;
|
|
175
|
+
if (!isRetryable(error) || attempt >= maxAttempts) {
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
const waitTime = initialDelay * Math.pow(multiplier, attempt - 1);
|
|
179
|
+
totalDelay += waitTime;
|
|
180
|
+
if (onRetry) {
|
|
181
|
+
onRetry(attempt, error, totalDelay);
|
|
182
|
+
}
|
|
183
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
throw lastError;
|
|
187
|
+
}
|
|
188
|
+
|
|
119
189
|
// src/captchaSolve.ts
|
|
120
|
-
async function solveCaptchaFromPage(page, captchaSelector = "img.captcha-image", outputScreenshotPath) {
|
|
190
|
+
async function solveCaptchaFromPage(page, captchaSelector = "img.captcha-image", outputScreenshotPath, options) {
|
|
191
|
+
const maxRetries = options?.maxRetries ?? 3;
|
|
192
|
+
const retryDelay = options?.retryDelayMs ?? 1e3;
|
|
193
|
+
const retryMultiplier = options?.retryMultiplier ?? 2;
|
|
121
194
|
const captchaImage = page.locator(captchaSelector);
|
|
122
195
|
try {
|
|
123
196
|
await captchaImage.waitFor({ state: "visible" });
|
|
@@ -129,37 +202,54 @@ async function solveCaptchaFromPage(page, captchaSelector = "img.captcha-image",
|
|
|
129
202
|
}
|
|
130
203
|
let imageData;
|
|
131
204
|
try {
|
|
132
|
-
imageData = await
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
205
|
+
imageData = await retry(
|
|
206
|
+
async () => {
|
|
207
|
+
return await captchaImage.evaluate(async (img) => {
|
|
208
|
+
const response = await fetch(img.src);
|
|
209
|
+
if (!response.ok) {
|
|
210
|
+
throw new Error(`Image fetch failed: ${response.status}`);
|
|
211
|
+
}
|
|
212
|
+
const blob = await response.blob();
|
|
213
|
+
return new Promise((resolve, reject) => {
|
|
214
|
+
const reader = new FileReader();
|
|
215
|
+
reader.onload = () => {
|
|
216
|
+
const result = reader.result;
|
|
217
|
+
resolve({
|
|
218
|
+
mimeType: blob.type || "image/png",
|
|
219
|
+
base64: result.split(",")[1]
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
reader.onerror = reject;
|
|
223
|
+
reader.readAsDataURL(blob);
|
|
146
224
|
});
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
maxAttempts: maxRetries,
|
|
229
|
+
delayMs: retryDelay,
|
|
230
|
+
multiplier: retryMultiplier
|
|
231
|
+
}
|
|
232
|
+
);
|
|
152
233
|
} catch (error) {
|
|
153
234
|
throw new Error(`Failed to extract CAPTCHA image: ${error}`);
|
|
154
235
|
}
|
|
155
236
|
let uploadResult;
|
|
156
237
|
try {
|
|
157
|
-
uploadResult = await
|
|
158
|
-
|
|
238
|
+
uploadResult = await retry(
|
|
239
|
+
async () => {
|
|
240
|
+
return await cloudinary_default.uploader.upload(
|
|
241
|
+
`data:${imageData.mimeType};base64,${imageData.base64}`,
|
|
242
|
+
{
|
|
243
|
+
folder: "playwright-captcha-images",
|
|
244
|
+
resource_type: "image",
|
|
245
|
+
type: "auth"
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
},
|
|
159
249
|
{
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
250
|
+
maxAttempts: maxRetries,
|
|
251
|
+
delayMs: retryDelay,
|
|
252
|
+
multiplier: retryMultiplier
|
|
163
253
|
}
|
|
164
254
|
);
|
|
165
255
|
} catch (error) {
|
|
@@ -167,7 +257,16 @@ async function solveCaptchaFromPage(page, captchaSelector = "img.captcha-image",
|
|
|
167
257
|
}
|
|
168
258
|
const imageUrl = uploadResult.secure_url;
|
|
169
259
|
try {
|
|
170
|
-
const result = await
|
|
260
|
+
const result = await retry(
|
|
261
|
+
async () => {
|
|
262
|
+
return await llm_default(imageUrl);
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
maxAttempts: maxRetries,
|
|
266
|
+
delayMs: retryDelay,
|
|
267
|
+
multiplier: retryMultiplier
|
|
268
|
+
}
|
|
269
|
+
);
|
|
171
270
|
return result;
|
|
172
271
|
} catch (error) {
|
|
173
272
|
throw new Error(`Failed to solve CAPTCHA using AI: ${error}`);
|
|
@@ -176,62 +275,266 @@ async function solveCaptchaFromPage(page, captchaSelector = "img.captcha-image",
|
|
|
176
275
|
|
|
177
276
|
// src/login.ts
|
|
178
277
|
var import_playwright = require("playwright");
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
278
|
+
|
|
279
|
+
// src/utils/humanDelay.ts
|
|
280
|
+
function randomBetween(min, max) {
|
|
281
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
282
|
+
}
|
|
283
|
+
function delay(ms) {
|
|
284
|
+
const jittered = ms + Math.floor((Math.random() * 0.4 - 0.2) * ms);
|
|
285
|
+
const actualDelay = Math.max(0, jittered);
|
|
286
|
+
return new Promise((resolve) => setTimeout(resolve, actualDelay));
|
|
287
|
+
}
|
|
288
|
+
async function executeWithRandomDelay(action, minDelay = 500, maxDelay = 1500) {
|
|
289
|
+
const result = await action();
|
|
290
|
+
const delayMs = randomBetween(minDelay, maxDelay);
|
|
291
|
+
await delay(delayMs);
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/login.ts
|
|
296
|
+
var fs = __toESM(require("fs"), 1);
|
|
297
|
+
var path = __toESM(require("path"), 1);
|
|
298
|
+
async function validateEnv(options) {
|
|
299
|
+
const email = options.email || process.env.EMAIL || "";
|
|
300
|
+
const password = options.password || process.env.PASSWORD || "";
|
|
301
|
+
if (email === "" || email === "dev@example.com") {
|
|
302
|
+
console.warn(
|
|
303
|
+
`Warning: EMAIL is set to default or missing. ${options.email ? "Override via LoginOptions.email." : "Set EMAIL env var."}`
|
|
304
|
+
);
|
|
183
305
|
}
|
|
184
|
-
if (
|
|
185
|
-
|
|
306
|
+
if (password === "" || password === "22222222") {
|
|
307
|
+
console.warn(
|
|
308
|
+
`Warning: PASSWORD is set to default or missing. ${options.password ? "Override via LoginOptions.password." : "Set PASSWORD env var."}`
|
|
309
|
+
);
|
|
186
310
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
311
|
+
}
|
|
312
|
+
async function sendWebhook(url, payload) {
|
|
313
|
+
try {
|
|
314
|
+
await fetch(url, {
|
|
315
|
+
method: "POST",
|
|
316
|
+
headers: { "Content-Type": "application/json" },
|
|
317
|
+
body: JSON.stringify(payload),
|
|
318
|
+
signal: AbortSignal.timeout(1e4)
|
|
319
|
+
});
|
|
320
|
+
return true;
|
|
321
|
+
} catch {
|
|
322
|
+
try {
|
|
323
|
+
await fetch(url, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: { "Content-Type": "application/json" },
|
|
326
|
+
body: JSON.stringify(payload),
|
|
327
|
+
signal: AbortSignal.timeout(1e4)
|
|
328
|
+
});
|
|
329
|
+
return true;
|
|
330
|
+
} catch {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
191
333
|
}
|
|
192
334
|
}
|
|
335
|
+
async function saveCookies(context, filePath) {
|
|
336
|
+
const cookies = await context.cookies();
|
|
337
|
+
const dir = path.dirname(filePath);
|
|
338
|
+
if (dir && !fs.existsSync(dir)) {
|
|
339
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
340
|
+
}
|
|
341
|
+
fs.writeFileSync(filePath, JSON.stringify(cookies, null, 2), "utf-8");
|
|
342
|
+
}
|
|
343
|
+
async function loadCookies(context, filePath) {
|
|
344
|
+
if (!fs.existsSync(filePath)) return;
|
|
345
|
+
const data = fs.readFileSync(filePath, "utf-8");
|
|
346
|
+
const cookies = JSON.parse(data);
|
|
347
|
+
await context.addCookies(cookies);
|
|
348
|
+
}
|
|
349
|
+
function setupProxy(proxyConfig) {
|
|
350
|
+
if (!proxyConfig) return void 0;
|
|
351
|
+
return {
|
|
352
|
+
server: proxyConfig.server,
|
|
353
|
+
username: proxyConfig.username,
|
|
354
|
+
password: proxyConfig.password
|
|
355
|
+
};
|
|
356
|
+
}
|
|
193
357
|
async function automateLogin(options) {
|
|
194
358
|
let browser = null;
|
|
195
359
|
let context = null;
|
|
196
360
|
let page = null;
|
|
197
361
|
try {
|
|
198
|
-
await validateEnv();
|
|
199
|
-
|
|
362
|
+
await validateEnv(options);
|
|
363
|
+
const retryCount = options.retryCount ?? 2;
|
|
364
|
+
const baseRetryDelay = options.baseRetryDelay ?? 1e3;
|
|
365
|
+
const delayRange = options.delayRange ?? { min: 500, max: 1500 };
|
|
366
|
+
const proxySettings = setupProxy(options.proxy);
|
|
367
|
+
const launchOpts = {
|
|
200
368
|
headless: options.headless ?? false
|
|
201
|
-
}
|
|
202
|
-
|
|
369
|
+
};
|
|
370
|
+
if (proxySettings) {
|
|
371
|
+
launchOpts.proxy = proxySettings;
|
|
372
|
+
}
|
|
373
|
+
browser = await import_playwright.chromium.launch(launchOpts);
|
|
374
|
+
const contextOptions = {};
|
|
375
|
+
if (proxySettings && !launchOpts.proxy) {
|
|
376
|
+
contextOptions.proxy = proxySettings;
|
|
377
|
+
}
|
|
378
|
+
if (options.cookieFile) {
|
|
379
|
+
contextOptions.storageState = options.cookieFile;
|
|
380
|
+
}
|
|
381
|
+
if (options.videoPath) {
|
|
382
|
+
const videoDir = path.isAbsolute(options.videoPath) ? path.dirname(options.videoPath) : path.join(process.cwd(), path.dirname(options.videoPath));
|
|
383
|
+
contextOptions.recordVideo = {
|
|
384
|
+
dir: videoDir,
|
|
385
|
+
size: { width: 1280, height: 720 }
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
context = await browser.newContext(contextOptions);
|
|
203
389
|
page = await context.newPage();
|
|
204
|
-
await page.goto(options.url, { waitUntil: "domcontentloaded" });
|
|
205
390
|
const loginSelector = options.loginSelector || "#login";
|
|
206
391
|
const passwordSelector = options.passwordSelector || "#password";
|
|
207
392
|
const captchaSelector = "img.captcha-image";
|
|
208
393
|
const captchaInputSelector = options.captchaInputSelector || "#captcha";
|
|
209
394
|
const submitButtonSelector = options.submitButtonSelector || "button[type='submit']";
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
options.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
395
|
+
const attemptLogin = async () => {
|
|
396
|
+
await executeWithRandomDelay(
|
|
397
|
+
async () => page.goto(options.url, { waitUntil: "domcontentloaded" }),
|
|
398
|
+
...Object.values(delayRange)
|
|
399
|
+
);
|
|
400
|
+
const emailVal = options.email || process.env.EMAIL || "";
|
|
401
|
+
const passwordVal = options.password || process.env.PASSWORD || "";
|
|
402
|
+
await executeWithRandomDelay(
|
|
403
|
+
async () => page.locator(loginSelector).fill(emailVal),
|
|
404
|
+
...Object.values(delayRange)
|
|
405
|
+
);
|
|
406
|
+
await executeWithRandomDelay(
|
|
407
|
+
async () => page.locator(passwordSelector).fill(passwordVal),
|
|
408
|
+
...Object.values(delayRange)
|
|
409
|
+
);
|
|
410
|
+
const captchaResult = await solveCaptchaFromPage(
|
|
411
|
+
page,
|
|
412
|
+
captchaSelector,
|
|
413
|
+
options.outputScreenshotPath ? void 0 : void 0
|
|
414
|
+
);
|
|
415
|
+
await executeWithRandomDelay(
|
|
416
|
+
async () => page.locator(captchaInputSelector).fill(captchaResult.text),
|
|
417
|
+
...Object.values(delayRange)
|
|
418
|
+
);
|
|
419
|
+
await executeWithRandomDelay(
|
|
420
|
+
async () => page.locator(submitButtonSelector).click(),
|
|
421
|
+
...Object.values(delayRange)
|
|
422
|
+
);
|
|
423
|
+
try {
|
|
424
|
+
await page.waitForLoadState("domcontentloaded", { timeout: 15e3 });
|
|
425
|
+
if (options.screenshotDelay) {
|
|
426
|
+
await page.waitForTimeout(options.screenshotDelay);
|
|
427
|
+
}
|
|
428
|
+
if (options.outputScreenshotPath) {
|
|
429
|
+
await page.screenshot({ path: options.outputScreenshotPath, fullPage: true });
|
|
430
|
+
}
|
|
431
|
+
} catch {
|
|
432
|
+
console.warn("Warning: Could not wait for post-login state");
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
success: true,
|
|
436
|
+
url: page.url(),
|
|
437
|
+
title: await page.title(),
|
|
438
|
+
page
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
let result;
|
|
219
442
|
try {
|
|
220
|
-
await
|
|
221
|
-
|
|
222
|
-
|
|
443
|
+
result = await retry(attemptLogin, {
|
|
444
|
+
maxAttempts: retryCount + 1,
|
|
445
|
+
// +1 for the initial attempt
|
|
446
|
+
delayMs: baseRetryDelay,
|
|
447
|
+
multiplier: 2,
|
|
448
|
+
onRetry: (attempt, error, totalDelay) => {
|
|
449
|
+
console.warn(
|
|
450
|
+
`[retry] Attempt ${attempt} failed: ${error instanceof Error ? error.message : error}. Total backoff: ${totalDelay}ms`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
} catch (error) {
|
|
455
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
456
|
+
let pageTitle = "";
|
|
457
|
+
if (page) {
|
|
458
|
+
try {
|
|
459
|
+
pageTitle = await page.title();
|
|
460
|
+
} catch {
|
|
461
|
+
pageTitle = "failed to get title";
|
|
462
|
+
}
|
|
223
463
|
}
|
|
224
|
-
if (options.
|
|
225
|
-
|
|
464
|
+
if (options.cookieFile && context) {
|
|
465
|
+
try {
|
|
466
|
+
await saveCookies(context, options.cookieFile);
|
|
467
|
+
} catch {
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
if (options.webhookUrl) {
|
|
471
|
+
await sendWebhook(options.webhookUrl, {
|
|
472
|
+
content: "\u{1F534} **Login Failed**",
|
|
473
|
+
embeds: [
|
|
474
|
+
{
|
|
475
|
+
title: "Login Automation Failed",
|
|
476
|
+
fields: [
|
|
477
|
+
{ name: "URL", value: options.url, inline: true },
|
|
478
|
+
{
|
|
479
|
+
name: "Error",
|
|
480
|
+
value: error instanceof Error ? error.message : String(error),
|
|
481
|
+
inline: false
|
|
482
|
+
}
|
|
483
|
+
],
|
|
484
|
+
color: 16734223
|
|
485
|
+
}
|
|
486
|
+
]
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
success: false,
|
|
491
|
+
url: page?.url() || "",
|
|
492
|
+
title: pageTitle,
|
|
493
|
+
page,
|
|
494
|
+
error: errorMessage
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
if (options.cookieFile && context) {
|
|
498
|
+
try {
|
|
499
|
+
await saveCookies(context, options.cookieFile);
|
|
500
|
+
} catch (err) {
|
|
501
|
+
console.warn("Warning: Could not save cookies:", err);
|
|
226
502
|
}
|
|
227
|
-
}
|
|
228
|
-
|
|
503
|
+
}
|
|
504
|
+
if (options.videoPath && page) {
|
|
505
|
+
try {
|
|
506
|
+
const videoObj = page.video();
|
|
507
|
+
if (videoObj) {
|
|
508
|
+
const outputPath = path.isAbsolute(options.videoPath) ? options.videoPath : path.join(process.cwd(), options.videoPath);
|
|
509
|
+
await delay(500);
|
|
510
|
+
await videoObj.saveAs(outputPath);
|
|
511
|
+
console.log(`Video saved to ${outputPath}`);
|
|
512
|
+
}
|
|
513
|
+
} catch (err) {
|
|
514
|
+
console.warn("Warning: Could not save video recording:", err);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (options.webhookUrl) {
|
|
518
|
+
await sendWebhook(options.webhookUrl, {
|
|
519
|
+
content: "\u2705 **Login Successful**",
|
|
520
|
+
embeds: [
|
|
521
|
+
{
|
|
522
|
+
title: "Login Automation Succeeded",
|
|
523
|
+
fields: [
|
|
524
|
+
{ name: "URL", value: options.url, inline: true },
|
|
525
|
+
{ name: "Final URL", value: result.url, inline: true },
|
|
526
|
+
{ name: "Title", value: result.title, inline: false }
|
|
527
|
+
],
|
|
528
|
+
color: 5763719
|
|
529
|
+
}
|
|
530
|
+
]
|
|
531
|
+
});
|
|
229
532
|
}
|
|
230
533
|
return {
|
|
231
534
|
success: true,
|
|
232
|
-
url:
|
|
233
|
-
title:
|
|
234
|
-
page
|
|
535
|
+
url: result.url,
|
|
536
|
+
title: result.title,
|
|
537
|
+
page: result.page
|
|
235
538
|
};
|
|
236
539
|
} catch (error) {
|
|
237
540
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -243,6 +546,31 @@ async function automateLogin(options) {
|
|
|
243
546
|
pageTitle = "failed to get title";
|
|
244
547
|
}
|
|
245
548
|
}
|
|
549
|
+
if (options.cookieFile && context) {
|
|
550
|
+
try {
|
|
551
|
+
await saveCookies(context, options.cookieFile);
|
|
552
|
+
} catch {
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (options.webhookUrl) {
|
|
556
|
+
await sendWebhook(options.webhookUrl, {
|
|
557
|
+
content: "\u{1F534} **Login Error**",
|
|
558
|
+
embeds: [
|
|
559
|
+
{
|
|
560
|
+
title: "Unexpected Login Error",
|
|
561
|
+
fields: [
|
|
562
|
+
{ name: "URL", value: options.url, inline: true },
|
|
563
|
+
{
|
|
564
|
+
name: "Error",
|
|
565
|
+
value: error instanceof Error ? error.message : String(error),
|
|
566
|
+
inline: false
|
|
567
|
+
}
|
|
568
|
+
],
|
|
569
|
+
color: 16734223
|
|
570
|
+
}
|
|
571
|
+
]
|
|
572
|
+
});
|
|
573
|
+
}
|
|
246
574
|
return {
|
|
247
575
|
success: false,
|
|
248
576
|
url: page?.url() || "",
|
|
@@ -261,11 +589,29 @@ async function automateLogin(options) {
|
|
|
261
589
|
// src/index.ts
|
|
262
590
|
var index_default = {
|
|
263
591
|
solveCaptchaFromPage,
|
|
264
|
-
automateLogin
|
|
592
|
+
automateLogin,
|
|
593
|
+
sendWebhook,
|
|
594
|
+
saveCookies,
|
|
595
|
+
loadCookies,
|
|
596
|
+
setupProxy,
|
|
597
|
+
randomBetween,
|
|
598
|
+
delay,
|
|
599
|
+
executeWithRandomDelay,
|
|
600
|
+
retry,
|
|
601
|
+
isRetryable
|
|
265
602
|
};
|
|
266
603
|
// Annotate the CommonJS export names for ESM import in node:
|
|
267
604
|
0 && (module.exports = {
|
|
268
605
|
automateLogin,
|
|
606
|
+
delay,
|
|
607
|
+
executeWithRandomDelay,
|
|
608
|
+
isRetryable,
|
|
609
|
+
loadCookies,
|
|
610
|
+
randomBetween,
|
|
611
|
+
retry,
|
|
612
|
+
saveCookies,
|
|
613
|
+
sendWebhook,
|
|
614
|
+
setupProxy,
|
|
269
615
|
solveCaptchaFromPage
|
|
270
616
|
});
|
|
271
617
|
//# sourceMappingURL=index.cjs.map
|