arn-browser 0.1.5 → 0.1.7
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/bin/cli.js +43 -0
- package/bin/install.js +412 -0
- package/package.json +8 -3
- package/src/index.d.ts +16 -6
- package/src/index.js +7 -4
- package/src/utility/deleteDirectory.js +2 -2
- package/src/utility/{multilogin_token_manager.js → mlx_token.js} +32 -43
- package/src/utility/{launchBrowser.d.ts → playwright/pwLaunch.d.ts} +25 -18
- package/src/utility/{launchBrowser.js → playwright/pwLaunch.js} +221 -137
- package/src/{all_routes/routeWithSuperagent.d.ts → utility/playwright/routes/pwRoute.d.ts} +4 -4
- package/src/{all_routes/routeWithSuperagent.js → utility/playwright/routes/pwRoute.js} +2 -2
- package/src/utility/proxy-utility/proxy-chain.js +30 -3
- package/src/utility/proxy-utility/proxy-helper.js +1 -1
- package/src/utility/puppeteer/ppLaunch.d.ts +199 -0
- package/src/utility/puppeteer/ppLaunch.js +723 -0
- package/src/utility/puppeteer/routes/ppRoute.d.ts +64 -0
- package/src/utility/puppeteer/routes/ppRoute.js +326 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/HumanCursor.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/bezier.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/index.d.ts +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/index.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/randomizer.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/tweening.js +0 -0
- /package/src/utility/{playwright-helper.d.ts → playwright/playwright-helper.d.ts} +0 -0
- /package/src/utility/{playwright-helper.js → playwright/playwright-helper.js} +0 -0
|
@@ -1,61 +1,51 @@
|
|
|
1
|
-
//
|
|
1
|
+
// mlx_token.js
|
|
2
2
|
|
|
3
3
|
import crypto from "crypto";
|
|
4
4
|
import { arn, query } from "arn-knexjs";
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
const MULTILOGIN_PASSWORD = process.env.MULTILOGIN_PASSWORD;
|
|
9
|
-
const MULTILOGIN_WORKSPACE_ID = process.env.MULTILOGIN_WORKSPACE_ID;
|
|
10
|
-
const MULTILOGIN_ROW_ID = process.env.MULTILOGIN_ROW_ID;
|
|
6
|
+
// Module-level cache for credentials (fetched once per process)
|
|
7
|
+
let _credentials = null;
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
|
-
*
|
|
10
|
+
* Loads Multilogin credentials from the database.
|
|
11
|
+
* Queries `api_multilogin_token` for a single row where `status = 1`.
|
|
12
|
+
* Results are cached in-memory so the DB is only hit once per process.
|
|
13
|
+
* @returns {Promise<{id: string, email: string, password: string, workspace_id: string, data: object}>}
|
|
14
14
|
*/
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
MULTILOGIN_EMAIL,
|
|
18
|
-
MULTILOGIN_PASSWORD,
|
|
19
|
-
MULTILOGIN_WORKSPACE_ID,
|
|
20
|
-
MULTILOGIN_ROW_ID,
|
|
21
|
-
};
|
|
15
|
+
async function loadCredentials() {
|
|
16
|
+
if (_credentials) return _credentials;
|
|
22
17
|
|
|
23
|
-
const
|
|
24
|
-
.
|
|
25
|
-
|
|
18
|
+
const { data: [row] = [], error } = await arn.single(
|
|
19
|
+
query("api_multilogin_token").select("*").where({ status: 1 }).orderByRaw("random()").limit(1)
|
|
20
|
+
);
|
|
26
21
|
|
|
27
|
-
if (
|
|
28
|
-
throw new Error(
|
|
22
|
+
if (error || !row) {
|
|
23
|
+
throw new Error("[TokenManager] No active Multilogin credentials found (status = 1).");
|
|
29
24
|
}
|
|
25
|
+
|
|
26
|
+
_credentials = row;
|
|
27
|
+
return _credentials;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
async function saveTokens(tokens) {
|
|
33
|
-
|
|
31
|
+
const creds = await loadCredentials();
|
|
34
32
|
|
|
35
33
|
await arn.single(
|
|
36
34
|
query("api_multilogin_token")
|
|
37
35
|
.update({
|
|
38
36
|
data: JSON.stringify(tokens, null, 2),
|
|
39
37
|
})
|
|
40
|
-
.where({ id:
|
|
38
|
+
.where({ id: creds.id })
|
|
41
39
|
);
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
async function loadTokens() {
|
|
45
43
|
try {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const { data: [data] = [], error } = await arn.single(
|
|
49
|
-
query("api_multilogin_token").select("*").where({ id: MULTILOGIN_ROW_ID }).limit(1)
|
|
50
|
-
);
|
|
51
|
-
if (error) {
|
|
52
|
-
console.error("Error loading tokens:", error);
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
if (!data || !data.data) {
|
|
44
|
+
const creds = await loadCredentials();
|
|
45
|
+
if (!creds.data || Object.keys(creds.data).length === 0) {
|
|
56
46
|
return null;
|
|
57
47
|
}
|
|
58
|
-
return
|
|
48
|
+
return creds.data;
|
|
59
49
|
} catch (err) {
|
|
60
50
|
return null;
|
|
61
51
|
}
|
|
@@ -73,11 +63,11 @@ function isJwtExpired(token) {
|
|
|
73
63
|
}
|
|
74
64
|
|
|
75
65
|
async function loginAndSaveTokens() {
|
|
76
|
-
|
|
66
|
+
const creds = await loadCredentials();
|
|
77
67
|
|
|
78
|
-
const passwordHash = crypto.createHash("md5").update(
|
|
68
|
+
const passwordHash = crypto.createHash("md5").update(creds.password).digest("hex");
|
|
79
69
|
const data = {
|
|
80
|
-
email:
|
|
70
|
+
email: creds.email,
|
|
81
71
|
password: passwordHash,
|
|
82
72
|
};
|
|
83
73
|
|
|
@@ -98,8 +88,8 @@ async function loginAndSaveTokens() {
|
|
|
98
88
|
await saveTokens({
|
|
99
89
|
token,
|
|
100
90
|
refresh_token,
|
|
101
|
-
email:
|
|
102
|
-
workspace_id:
|
|
91
|
+
email: creds.email,
|
|
92
|
+
workspace_id: creds.workspace_id,
|
|
103
93
|
});
|
|
104
94
|
|
|
105
95
|
console.log("[LOGIN] Tokens updated and saved.");
|
|
@@ -107,12 +97,12 @@ async function loginAndSaveTokens() {
|
|
|
107
97
|
}
|
|
108
98
|
|
|
109
99
|
async function refreshAndSaveTokens(refresh_token) {
|
|
110
|
-
|
|
100
|
+
const creds = await loadCredentials();
|
|
111
101
|
|
|
112
102
|
const data = {
|
|
113
|
-
email:
|
|
103
|
+
email: creds.email,
|
|
114
104
|
refresh_token: refresh_token,
|
|
115
|
-
workspace_id:
|
|
105
|
+
workspace_id: creds.workspace_id,
|
|
116
106
|
};
|
|
117
107
|
|
|
118
108
|
const res = await fetch("https://api.multilogin.com/user/refresh_token", {
|
|
@@ -132,8 +122,8 @@ async function refreshAndSaveTokens(refresh_token) {
|
|
|
132
122
|
await saveTokens({
|
|
133
123
|
token,
|
|
134
124
|
refresh_token: new_refresh,
|
|
135
|
-
email:
|
|
136
|
-
workspace_id:
|
|
125
|
+
email: creds.email,
|
|
126
|
+
workspace_id: creds.workspace_id,
|
|
137
127
|
});
|
|
138
128
|
|
|
139
129
|
console.log("[REFRESH] Tokens refreshed and saved.");
|
|
@@ -141,7 +131,6 @@ async function refreshAndSaveTokens(refresh_token) {
|
|
|
141
131
|
}
|
|
142
132
|
|
|
143
133
|
async function getMultiloginToken() {
|
|
144
|
-
validateEnv();
|
|
145
134
|
let tokens = await loadTokens();
|
|
146
135
|
|
|
147
136
|
if (tokens && tokens.token && !isJwtExpired(tokens.token)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Browser, BrowserContext, Page } from "playwright";
|
|
2
2
|
import type { FingerprintGeneratorOptions } from "fingerprint-generator";
|
|
3
|
-
import type { HumanPage, CreateCursorOptions } from "
|
|
3
|
+
import type { HumanPage, CreateCursorOptions } from "./human-cursor/index";
|
|
4
4
|
type Screen = FingerprintGeneratorOptions["screen"];
|
|
5
5
|
/**
|
|
6
6
|
* Proxy configuration object.
|
|
@@ -119,7 +119,7 @@ export interface MultiloginOptions {
|
|
|
119
119
|
/**
|
|
120
120
|
* Options for launching the browser.
|
|
121
121
|
*/
|
|
122
|
-
export interface
|
|
122
|
+
export interface PwLaunchOptions {
|
|
123
123
|
// ========================================================================
|
|
124
124
|
// 1. GENERAL & NETWORK
|
|
125
125
|
// ========================================================================
|
|
@@ -141,7 +141,15 @@ export interface LaunchOptions {
|
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* Which browser engine to launch.
|
|
144
|
-
*
|
|
144
|
+
*
|
|
145
|
+
* - `"chromium"`: Playwright's bundled Chromium
|
|
146
|
+
* - `"chrome"`: Alias for Chromium
|
|
147
|
+
* - `"firefox"`: Playwright's bundled Firefox
|
|
148
|
+
* - `"brave"`: Brave Browser (requires local binary)
|
|
149
|
+
* - `"camoufox"`: Camoufox anti-detect Firefox (requires local binary)
|
|
150
|
+
* - `"multilogin"`: Multilogin anti-detect browser (via API)
|
|
151
|
+
*
|
|
152
|
+
* Default: `"chromium"`
|
|
145
153
|
*/
|
|
146
154
|
which_browser?: "chromium" | "chrome" | "firefox" | "brave" | "braveLauncher" | "camoufox" | "multilogin";
|
|
147
155
|
|
|
@@ -150,23 +158,22 @@ export interface LaunchOptions {
|
|
|
150
158
|
// ========================================================================
|
|
151
159
|
|
|
152
160
|
/**
|
|
153
|
-
* Path to a
|
|
161
|
+
* Path to a persistent profile.
|
|
154
162
|
* - If absolute path: Uses that path exactly (no prefix added).
|
|
155
|
-
* - If folder name: Creates inside `~/.arn-browser/
|
|
156
|
-
* - If null: Creates a temporary, random profile
|
|
157
|
-
*
|
|
158
|
-
* When combined with `cleanupMinutes`, named profiles can be auto-deleted
|
|
159
|
-
* after a period of inactivity (based on `_profile_meta.json`).
|
|
163
|
+
* - If folder name: Creates inside `~/.arn-browser/pw/persistent/` AND adds a browser prefix (e.g., `brave_myProfile`).
|
|
164
|
+
* - If null: Creates a temporary, random profile in `~/.arn-browser/pw/temp/`.
|
|
160
165
|
*/
|
|
161
166
|
profile_path?: string | null;
|
|
162
167
|
|
|
163
168
|
/**
|
|
164
|
-
* Auto-
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
169
|
+
* Auto-cleanup profiles after X minutes since last launch.
|
|
170
|
+
*
|
|
171
|
+
* **Persistent profiles:** Cleaned after X minutes since last launch. Default: 0 (never clean).
|
|
172
|
+
* **Temp profiles:** Default: 15 minutes if not specified.
|
|
173
|
+
*
|
|
174
|
+
* Each profile stores a `_profile_meta.json` with `created_at`, `last_launched_at`,
|
|
175
|
+
* and `cleanup_minutes`. The profile currently being launched is always skipped during cleanup.
|
|
176
|
+
*
|
|
170
177
|
* Default: 0
|
|
171
178
|
*/
|
|
172
179
|
cleanupMinutes?: number;
|
|
@@ -232,7 +239,7 @@ export interface LaunchOptions {
|
|
|
232
239
|
humanize_options?: HumanizeOptions;
|
|
233
240
|
|
|
234
241
|
// ========================================================================
|
|
235
|
-
//
|
|
242
|
+
// 6. LOGGING
|
|
236
243
|
// ========================================================================
|
|
237
244
|
|
|
238
245
|
/**
|
|
@@ -294,9 +301,9 @@ export interface BrowserControllerError {
|
|
|
294
301
|
* The object returned by launchBrowser.
|
|
295
302
|
* Check launchError to discriminate between success and failure states.
|
|
296
303
|
*/
|
|
297
|
-
export type
|
|
304
|
+
export type PwBrowserController = BrowserControllerSuccess | BrowserControllerError;
|
|
298
305
|
|
|
299
306
|
/**
|
|
300
307
|
* Launches a browser based on the provided options.
|
|
301
308
|
*/
|
|
302
|
-
export function
|
|
309
|
+
export function pwLaunch(options?: PwLaunchOptions): Promise<PwBrowserController>;
|