arn-browser 0.0.3 → 0.0.4

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.
Files changed (62) hide show
  1. package/README.md +3 -2
  2. package/package.json +28 -49
  3. package/rowser_automation_env.js +32 -0
  4. package/src/all_routes/routeWithSuperagent.d.ts +67 -0
  5. package/src/all_routes/routeWithSuperagent.js +322 -0
  6. package/src/index.d.ts +19 -0
  7. package/src/index.js +15 -0
  8. package/src/others/totp-generator.d.ts +15 -0
  9. package/src/others/totp-generator.js +86 -0
  10. package/src/utility/deleteDirectory.js +105 -0
  11. package/src/utility/launchBrowser.d.ts +221 -0
  12. package/src/utility/launchBrowser.js +868 -0
  13. package/src/utility/multilogin_token_manager.js +186 -0
  14. package/src/utility/playwright-helper.d.ts +61 -0
  15. package/src/utility/playwright-helper.js +129 -0
  16. package/src/utility/proxy-utility/custom-proxy.d.ts +93 -0
  17. package/src/utility/proxy-utility/custom-proxy.js +669 -0
  18. package/src/utility/proxy-utility/proxy-chain.d.ts +123 -0
  19. package/src/utility/proxy-utility/proxy-chain.js +337 -0
  20. package/src/utility/proxy-utility/proxy-helper.d.ts +91 -0
  21. package/src/utility/proxy-utility/proxy-helper.js +245 -0
  22. package/dist/__main__.d.ts +0 -2
  23. package/dist/__main__.js +0 -127
  24. package/dist/__version__.d.ts +0 -11
  25. package/dist/__version__.js +0 -16
  26. package/dist/addons.d.ts +0 -17
  27. package/dist/addons.js +0 -70
  28. package/dist/data-files/territoryInfo.xml +0 -2024
  29. package/dist/data-files/webgl_data.db +0 -0
  30. package/dist/exceptions.d.ts +0 -76
  31. package/dist/exceptions.js +0 -153
  32. package/dist/fingerprints.d.ts +0 -4
  33. package/dist/fingerprints.js +0 -82
  34. package/dist/index.d.ts +0 -3
  35. package/dist/index.js +0 -3
  36. package/dist/ip.d.ts +0 -25
  37. package/dist/ip.js +0 -90
  38. package/dist/locale.d.ts +0 -26
  39. package/dist/locale.js +0 -280
  40. package/dist/mappings/browserforge.config.d.ts +0 -47
  41. package/dist/mappings/browserforge.config.js +0 -72
  42. package/dist/mappings/fonts.config.d.ts +0 -6
  43. package/dist/mappings/fonts.config.js +0 -822
  44. package/dist/mappings/warnings.config.d.ts +0 -16
  45. package/dist/mappings/warnings.config.js +0 -28
  46. package/dist/pkgman.d.ts +0 -62
  47. package/dist/pkgman.js +0 -347
  48. package/dist/server.d.ts +0 -6
  49. package/dist/server.js +0 -9
  50. package/dist/sync_api.d.ts +0 -7
  51. package/dist/sync_api.js +0 -27
  52. package/dist/utils.d.ts +0 -88
  53. package/dist/utils.js +0 -500
  54. package/dist/virtdisplay.d.ts +0 -20
  55. package/dist/virtdisplay.js +0 -123
  56. package/dist/warnings.d.ts +0 -4
  57. package/dist/warnings.js +0 -30
  58. package/dist/webgl/db-compat.d.ts +0 -9
  59. package/dist/webgl/db-compat.js +0 -44
  60. package/dist/webgl/sample.d.ts +0 -19
  61. package/dist/webgl/sample.js +0 -85
  62. /package/{LICENSE.md → LICENSE} +0 -0
@@ -0,0 +1,245 @@
1
+ import { setTimeout as sleep } from "timers/promises";
2
+ import randomstring from "randomstring";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { pathToFileURL } from "url";
6
+ import { getMultiloginToken } from "../multilogin_token_manager.js";
7
+ // Assuming fetchAwsProxy is in the same directory or adjust path accordingly
8
+ import { getActiveProxyWithStartStop as fetchAwsProxy } from "./custom-proxy.js";
9
+
10
+ // Global configuration cache
11
+ let config = null;
12
+
13
+ // ==========================================
14
+ // SECTION 1: CONFIGURATION & UTILITIES
15
+ // ==========================================
16
+
17
+ /**
18
+ * Dynamically loads 'browser_automation_env.js' from the user's project root.
19
+ */
20
+ async function loadUserConfig() {
21
+ if (config) return config;
22
+
23
+ try {
24
+ const projectRoot = process.cwd();
25
+ const envPath = path.join(projectRoot, "utility", "browser_automation_env.js");
26
+
27
+ if (!fs.existsSync(envPath)) {
28
+ throw new Error(`Could not find configuration file at: ${envPath}`);
29
+ }
30
+
31
+ const envUrl = pathToFileURL(envPath).href;
32
+ const userEnv = await import(envUrl);
33
+
34
+ // Validate required exports
35
+ const requiredKeys = [
36
+ "arn",
37
+ "query",
38
+ "PACKETSTREAM_USER",
39
+ "PACKETSTREAM_PASS_KEY",
40
+ "PACKETSTREAM_HOST",
41
+ "PACKETSTREAM_PORT",
42
+ ];
43
+
44
+ const missing = requiredKeys.filter((key) => !userEnv[key]);
45
+
46
+ if (missing.length > 0) {
47
+ throw new Error(`[Proxy Manager] 'browser_automation_env.js' is missing exports: ${missing.join(", ")}`);
48
+ }
49
+
50
+ config = userEnv;
51
+ return config;
52
+ } catch (error) {
53
+ console.error("❌ Config Error:", error.message);
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ // ==========================================
59
+ // SECTION 2: MULTILOGIN PROXY
60
+ // ==========================================
61
+
62
+ /**
63
+ * Fetches and parses a Multilogin proxy using Native Fetch.
64
+ */
65
+ export async function get_multilogin_proxy({
66
+ country = "us",
67
+ sessionType = "sticky",
68
+ protocol = "http",
69
+ region = "",
70
+ city = "",
71
+ IPTTL = 1800,
72
+ strictMode = false,
73
+ } = {}) {
74
+ try {
75
+ // 1. Get Token
76
+ const token = await getMultiloginToken();
77
+
78
+ // 2. Prepare Data
79
+ const data = { country, sessionType, protocol, region, city, IPTTL, count: 1 };
80
+ Object.keys(data).forEach((k) => (data[k] === "" || data[k] === 0 || data[k] == null) && delete data[k]);
81
+
82
+ // 3. Setup Timeout
83
+ const controller = new AbortController();
84
+ const timeoutId = setTimeout(() => controller.abort(), 20000);
85
+
86
+ try {
87
+ const response = await fetch("https://profile-proxy.multilogin.com/v1/proxy/connection_url", {
88
+ method: "POST",
89
+ headers: {
90
+ Authorization: `Bearer ${token}`,
91
+ "X-Strict-Mode": strictMode ? "true" : "false",
92
+ "Content-Type": "application/json",
93
+ },
94
+ body: JSON.stringify(data),
95
+ signal: controller.signal,
96
+ });
97
+
98
+ if (!response.ok) {
99
+ const errText = await response.text();
100
+ throw new Error(`HTTP ${response.status}: ${errText}`);
101
+ }
102
+
103
+ const json = await response.json();
104
+
105
+ let proxyStr = json?.data;
106
+ if (Array.isArray(proxyStr)) proxyStr = proxyStr[0];
107
+
108
+ if (!proxyStr || typeof proxyStr !== "string") {
109
+ console.error("Multilogin proxy API: Unexpected format", json);
110
+ return null;
111
+ }
112
+
113
+ // Format: host:port:user:pass
114
+ const parts = proxyStr.split(":");
115
+ if (parts.length < 4) {
116
+ console.error("Unexpected Multilogin proxy string:", proxyStr);
117
+ return null;
118
+ }
119
+
120
+ const [host, port, user, ...passParts] = parts;
121
+ const pass = passParts.join(":");
122
+
123
+ const temp_proxy = {
124
+ type: protocol,
125
+ host,
126
+ port: parseInt(port, 10),
127
+ user,
128
+ pass,
129
+ };
130
+
131
+ console.log("Multilogin Proxy:", temp_proxy);
132
+ return temp_proxy;
133
+ } finally {
134
+ clearTimeout(timeoutId);
135
+ }
136
+ } catch (error) {
137
+ console.error("Failed to get Multilogin proxy:", error.message);
138
+ return null;
139
+ }
140
+ }
141
+
142
+ // ==========================================
143
+ // SECTION 3: PACKETSTREAM PROXY
144
+ // ==========================================
145
+
146
+ /**
147
+ * Generates a PacketStream proxy object with a random session ID using credentials from config.
148
+ */
149
+ export async function get_packetstream_proxy() {
150
+ // 1. Load config dynamically
151
+ const { PACKETSTREAM_USER, PACKETSTREAM_PASS_KEY, PACKETSTREAM_HOST, PACKETSTREAM_PORT } = await loadUserConfig();
152
+
153
+ // 2. Generate Random Session ID
154
+ const proxy_session_id = randomstring.generate({
155
+ length: 8,
156
+ charset: "alphanumeric",
157
+ capitalization: "both",
158
+ readable: false,
159
+ });
160
+
161
+ // 3. Construct the proxy object
162
+ const temp_proxy = {
163
+ type: "http",
164
+ host: PACKETSTREAM_HOST,
165
+ port: Number(PACKETSTREAM_PORT),
166
+ user: PACKETSTREAM_USER,
167
+ pass: `${PACKETSTREAM_PASS_KEY}-${proxy_session_id}`,
168
+ };
169
+
170
+ console.log("PacketStream Proxy:", temp_proxy);
171
+ return temp_proxy;
172
+ }
173
+
174
+ // ==========================================
175
+ // SECTION 4: DATABASE PROXY (X_ACCOUNTS)
176
+ // ==========================================
177
+
178
+ export async function get_x_proxy({ provider }) {
179
+ const { arn, query } = await loadUserConfig();
180
+
181
+ const { data: [proxyInstance] = [], error: getProxy_error } = await arn.single(
182
+ query("x_accounts_proxy")
183
+ .update({
184
+ total_used: query.raw("total_used + 1"),
185
+ last_used_time: new Date().toISOString(),
186
+ })
187
+ .where("id", function () {
188
+ let subquery = this.select("id").from("x_accounts_proxy").where("status", 1);
189
+
190
+ if (provider) {
191
+ subquery = subquery.where("provider", provider);
192
+ }
193
+
194
+ subquery = subquery
195
+ .andWhere(
196
+ query.raw("COALESCE(last_used_time, '1970-01-01T00:00:00.000Z') < ?", [
197
+ new Date(Date.now() - 60 * 60 * 1000).toISOString(),
198
+ ])
199
+ )
200
+ .orderBy("total_used", "asc")
201
+ .limit(1);
202
+ return subquery;
203
+ })
204
+ .returning("*")
205
+ );
206
+
207
+ if (getProxy_error || !proxyInstance) {
208
+ console.error(getProxy_error || "No proxy instances found");
209
+ await sleep(30000);
210
+ return null;
211
+ }
212
+
213
+ return proxyInstance;
214
+ }
215
+
216
+ // ==========================================
217
+ // SECTION 5: AWS PROXY ROTATION
218
+ // ==========================================
219
+
220
+ export function fetchNextProxy(proxies) {
221
+ if (proxies.isFetching) return;
222
+
223
+ proxies.isFetching = true;
224
+
225
+ fetchAwsProxy({
226
+ instance_name: proxies.proxyInstance,
227
+ })
228
+ .then((newProxyIp) => {
229
+ if (newProxyIp) {
230
+ proxies.proxy = {
231
+ host: newProxyIp,
232
+ port: 9002,
233
+ };
234
+ proxies.proxyUsed = 0;
235
+ console.log(`Successfully prepared next proxy: ${newProxyIp}`);
236
+ } else {
237
+ console.log("Next proxy fetch returned null");
238
+ }
239
+ proxies.isFetching = false;
240
+ })
241
+ .catch((error) => {
242
+ console.error(`Error fetching next proxy ${proxies.proxyInstance}:`, error.message);
243
+ proxies.isFetching = false;
244
+ });
245
+ }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/__main__.js DELETED
@@ -1,127 +0,0 @@
1
- #!/usr/bin/env node
2
- import { existsSync, rmSync } from "node:fs";
3
- import { Command } from "commander";
4
- import { DefaultAddons, maybeDownloadAddons } from "./addons.js";
5
- import { ALLOW_GEOIP, downloadMMDB, removeMMDB } from "./locale.js";
6
- import { CamoufoxFetcher, INSTALL_DIR, installedVerStr } from "./pkgman.js";
7
- import { launchServer } from "./server.js";
8
- import { Camoufox } from "./sync_api.js";
9
- import { getAsBooleanFromENV } from "./utils.js";
10
- class CamoufoxUpdate extends CamoufoxFetcher {
11
- currentVerStr;
12
- constructor() {
13
- super();
14
- this.currentVerStr = null;
15
- try {
16
- this.currentVerStr = installedVerStr();
17
- }
18
- catch (error) {
19
- if (error instanceof Error && error.name === "FileNotFoundError") {
20
- this.currentVerStr = null;
21
- }
22
- else {
23
- throw error;
24
- }
25
- }
26
- }
27
- static async create() {
28
- const updater = new CamoufoxUpdate();
29
- await updater.init();
30
- return updater;
31
- }
32
- isUpdateNeeded() {
33
- if (getAsBooleanFromENV("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD", false)) {
34
- console.log("Skipping browser download / update check due to PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD set!");
35
- return false;
36
- }
37
- return this.currentVerStr === null || this.currentVerStr !== this.verstr;
38
- }
39
- async update() {
40
- if (!this.isUpdateNeeded()) {
41
- console.log("Camoufox binaries up to date!");
42
- console.log(`Current version: v${this.currentVerStr}`);
43
- return;
44
- }
45
- if (this.currentVerStr !== null) {
46
- console.log(`Updating Camoufox binaries from v${this.currentVerStr} => v${this.verstr}`, "yellow");
47
- }
48
- else {
49
- console.log(`Fetching Camoufox binaries...`);
50
- }
51
- await this.install();
52
- }
53
- async cleanup() {
54
- if (!existsSync(INSTALL_DIR)) {
55
- return false;
56
- }
57
- await rmSync(INSTALL_DIR, { recursive: true, force: true });
58
- console.log("Camoufox binaries removed!");
59
- return true;
60
- }
61
- }
62
- const program = new Command();
63
- program.command("fetch").action(async () => {
64
- const updater = await CamoufoxUpdate.create();
65
- await updater.update();
66
- if (ALLOW_GEOIP) {
67
- downloadMMDB();
68
- }
69
- maybeDownloadAddons(DefaultAddons);
70
- });
71
- program.command("remove").action(async () => {
72
- const updater = await CamoufoxUpdate.create();
73
- if (!(await updater.cleanup())) {
74
- console.log("Camoufox binaries not found!", "red");
75
- }
76
- removeMMDB();
77
- });
78
- program
79
- .command("test")
80
- .argument("[url]", "URL to open", null)
81
- .action(async (url) => {
82
- const browser = await Camoufox({
83
- headless: false,
84
- env: process.env,
85
- config: { showcursor: true },
86
- humanize: 0.5,
87
- geoip: true,
88
- });
89
- const page = await browser.newPage();
90
- if (url) {
91
- await page.goto(url);
92
- }
93
- await page.pause();
94
- });
95
- program.command("server").action(async () => {
96
- const server = await launchServer({});
97
- console.log(`Camoufox server started at ${server.wsEndpoint()}`);
98
- console.log();
99
- console.log(`You can connect to it using Playwright's BrowserType.connect() method.`);
100
- console.log(`To stop the server, press Ctrl+C or close this terminal.`);
101
- });
102
- program.command("path").action(() => {
103
- console.log(INSTALL_DIR);
104
- });
105
- program.command("version").action(async () => {
106
- try {
107
- const pkgVersion = require("pkg-version");
108
- console.log(`Pip package:\tv${pkgVersion("camoufox")}`);
109
- }
110
- catch (_error) {
111
- console.log("Pip package:\tNot installed!", "red");
112
- }
113
- const updater = await CamoufoxUpdate.create();
114
- const binVer = updater.currentVerStr;
115
- if (!binVer) {
116
- console.log("Camoufox:\tNot downloaded!", "red");
117
- return;
118
- }
119
- console.log(`Camoufox:\tv${binVer} `, "green", false);
120
- if (updater.isUpdateNeeded()) {
121
- console.log(`(Latest supported: v${updater.verstr})`, "red");
122
- }
123
- else {
124
- console.log("(Up to date!)", "yellow");
125
- }
126
- });
127
- program.parse(process.argv);
@@ -1,11 +0,0 @@
1
- /**
2
- * Camoufox version constants.
3
- */
4
- export declare class CONSTRAINTS {
5
- /**
6
- * The minimum and maximum supported versions of the Camoufox browser.
7
- */
8
- static readonly MIN_VERSION: string;
9
- static readonly MAX_VERSION: string;
10
- static asRange(): string;
11
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Camoufox version constants.
3
- */
4
- export class CONSTRAINTS {
5
- /**
6
- * The minimum and maximum supported versions of the Camoufox browser.
7
- */
8
- static MIN_VERSION = "beta.19";
9
- static MAX_VERSION = "1";
10
- static asRange() {
11
- /**
12
- * Returns the version range as a string.
13
- */
14
- return `>=${CONSTRAINTS.MIN_VERSION}, <${CONSTRAINTS.MAX_VERSION}`;
15
- }
16
- }
package/dist/addons.d.ts DELETED
@@ -1,17 +0,0 @@
1
- export declare const DefaultAddons: {
2
- /**
3
- * Default addons to be downloaded
4
- */
5
- UBO: string;
6
- };
7
- export declare function confirmPaths(paths: string[]): void;
8
- export declare function addDefaultAddons(_addonsList: string[], _excludeList?: (keyof typeof DefaultAddons)[]): void;
9
- /**
10
- * Downloads and extracts an addon from a given URL to a specified path
11
- */
12
- export declare function downloadAndExtract(url: string, extractPath: string, name: string): Promise<void>;
13
- /**
14
- * Downloads and extracts addons from a given dictionary to a specified list
15
- * Skips downloading if the addon is already downloaded
16
- */
17
- export declare function maybeDownloadAddons(addons: Record<string, string>, addonsList?: string[]): void;
package/dist/addons.js DELETED
@@ -1,70 +0,0 @@
1
- import fs from "node:fs";
2
- import { join } from "node:path";
3
- import { InvalidAddonPath } from "./exceptions.js";
4
- import { getPath, unzip, webdl } from "./pkgman.js";
5
- import { getAsBooleanFromENV } from "./utils.js";
6
- export const DefaultAddons = {
7
- /**
8
- * Default addons to be downloaded
9
- */
10
- UBO: "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi",
11
- };
12
- export function confirmPaths(paths) {
13
- /**
14
- * Confirms that the addon paths are valid
15
- */
16
- for (const path of paths) {
17
- if (!fs.existsSync(path) || !fs.lstatSync(path).isDirectory()) {
18
- throw new InvalidAddonPath(path);
19
- }
20
- if (!fs.existsSync(join(path, "manifest.json"))) {
21
- throw new InvalidAddonPath("manifest.json is missing. Addon path must be a path to an extracted addon.");
22
- }
23
- }
24
- }
25
- export function addDefaultAddons(_addonsList, _excludeList = []) {
26
- // TODO - enable addons
27
- /**
28
- * Adds default addons, minus any specified in excludeList, to addonsList
29
- */
30
- // const addons = Object.values(DefaultAddons).filter(addon => !excludeList.includes(addon as keyof typeof DefaultAddons));
31
- // maybeDownloadAddons(addons, addonsList);
32
- }
33
- /**
34
- * Downloads and extracts an addon from a given URL to a specified path
35
- */
36
- export async function downloadAndExtract(url, extractPath, name) {
37
- const buffer = await webdl(url, `Downloading addon (${name})`, false);
38
- unzip(buffer, extractPath, `Extracting addon (${name})`, false);
39
- }
40
- /**
41
- * Returns a path to the addon
42
- */
43
- function getAddonPath(addonName) {
44
- return getPath(join("addons", addonName));
45
- }
46
- /**
47
- * Downloads and extracts addons from a given dictionary to a specified list
48
- * Skips downloading if the addon is already downloaded
49
- */
50
- export function maybeDownloadAddons(addons, addonsList = []) {
51
- if (getAsBooleanFromENV("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD", false)) {
52
- console.log("Skipping addon download due to PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD set!");
53
- return;
54
- }
55
- for (const addonName in addons) {
56
- const addonPath = getAddonPath(addonName);
57
- if (fs.existsSync(addonPath)) {
58
- addonsList.push(addonPath);
59
- continue;
60
- }
61
- try {
62
- fs.mkdirSync(addonPath, { recursive: true });
63
- downloadAndExtract(addons[addonName], addonPath, addonName);
64
- addonsList.push(addonPath);
65
- }
66
- catch (e) {
67
- console.error(`Failed to download and extract ${addonName}: ${e}`);
68
- }
69
- }
70
- }