arn-browser 0.0.2 → 0.0.3
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/dist/__main__.d.ts +2 -0
- package/dist/__main__.js +127 -0
- package/dist/__version__.d.ts +11 -0
- package/dist/__version__.js +16 -0
- package/dist/addons.d.ts +17 -0
- package/dist/addons.js +70 -0
- package/dist/data-files/territoryInfo.xml +2024 -0
- package/dist/data-files/webgl_data.db +0 -0
- package/dist/exceptions.d.ts +76 -0
- package/dist/exceptions.js +153 -0
- package/dist/fingerprints.d.ts +4 -0
- package/dist/fingerprints.js +82 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/ip.d.ts +25 -0
- package/dist/ip.js +90 -0
- package/dist/locale.d.ts +26 -0
- package/dist/locale.js +280 -0
- package/dist/mappings/browserforge.config.d.ts +47 -0
- package/dist/mappings/browserforge.config.js +72 -0
- package/dist/mappings/fonts.config.d.ts +6 -0
- package/dist/mappings/fonts.config.js +822 -0
- package/dist/mappings/warnings.config.d.ts +16 -0
- package/dist/mappings/warnings.config.js +28 -0
- package/dist/pkgman.d.ts +62 -0
- package/dist/pkgman.js +347 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +9 -0
- package/dist/sync_api.d.ts +7 -0
- package/dist/sync_api.js +27 -0
- package/dist/utils.d.ts +88 -0
- package/dist/utils.js +500 -0
- package/dist/virtdisplay.d.ts +20 -0
- package/dist/virtdisplay.js +123 -0
- package/dist/warnings.d.ts +4 -0
- package/dist/warnings.js +30 -0
- package/dist/webgl/db-compat.d.ts +9 -0
- package/dist/webgl/db-compat.js +44 -0
- package/dist/webgl/sample.d.ts +19 -0
- package/dist/webgl/sample.js +85 -0
- package/package.json +2 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
navigator: string;
|
|
3
|
+
locale: string;
|
|
4
|
+
geolocation: string;
|
|
5
|
+
"header-ua": string;
|
|
6
|
+
viewport: string;
|
|
7
|
+
custom_fingerprint: string;
|
|
8
|
+
proxy_without_geoip: string;
|
|
9
|
+
ff_version: string;
|
|
10
|
+
no_region: string;
|
|
11
|
+
block_webgl: string;
|
|
12
|
+
block_images: string;
|
|
13
|
+
custom_fonts_only: string;
|
|
14
|
+
disable_coop: string;
|
|
15
|
+
};
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
navigator: "Manually setting navigator properties is not recommended." +
|
|
3
|
+
" Device information is automatically generated within Camoufox" +
|
|
4
|
+
" based on the provided `os`.",
|
|
5
|
+
locale: "Use the `locale` parameter in Camoufox instead of setting the config manually.",
|
|
6
|
+
geolocation: "Please use the `geoip` parameter in Camoufox instead of setting your geolocation manually." +
|
|
7
|
+
" This can lead to detection if your target geolocation does not match your IP." +
|
|
8
|
+
" Pass `geoip=True` or a target IP (ex: geoip='123.45.67.89') to let Camoufox populate this data for you.",
|
|
9
|
+
"header-ua": "Do not set the header.User-Agent manually. Camoufox will generate a User-Agent for you.",
|
|
10
|
+
viewport: "Manually setting screen & window properties is not recommended." +
|
|
11
|
+
" Screen dimensions are randomly generated within Camoufox" +
|
|
12
|
+
" based on the provided screen constraints. See here:" +
|
|
13
|
+
" https://github.com/daijro/camoufox/tree/main/pythonlib#browserforge-integration.",
|
|
14
|
+
custom_fingerprint: "Passing your own fingerprint is not recommended." +
|
|
15
|
+
" BrowserForge fingerprints are automatically generated within Camoufox" +
|
|
16
|
+
" based on the provided `os` and `screen` constraints.",
|
|
17
|
+
proxy_without_geoip: "When using a proxy, it is heavily recommended that you pass `geoip=True`.",
|
|
18
|
+
ff_version: "Spoofing the Firefox version will likely lead to detection." +
|
|
19
|
+
" If rotating the Firefox version is absolutely necessary, it would be more advisable to" +
|
|
20
|
+
" rotate between older versions of Camoufox instead.",
|
|
21
|
+
no_region: "Because you did not pass in a locale region, Camoufox will generate one for you." +
|
|
22
|
+
" This can cause suspicion if your IP does not match your locale region.",
|
|
23
|
+
block_webgl: "Disabling WebGL is not recommended. Many WAFs will check if WebGL is enabled.",
|
|
24
|
+
block_images: "Blocking image requests has been reported to cause detection issues on major WAFs.",
|
|
25
|
+
custom_fonts_only: "Disabling OS-specific fonts while spoofing your OS will make your browser fingerprint inconsistent." +
|
|
26
|
+
" WAFs can detect this mismatch between your claimed OS and available system fonts.",
|
|
27
|
+
disable_coop: "Disabling Cross-Origin-Opener-Policy (COOP) handling can potentially be detected by sophisticated WAFs.",
|
|
28
|
+
};
|
package/dist/pkgman.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { PathLike } from "node:fs";
|
|
2
|
+
import type { Writable } from "node:stream";
|
|
3
|
+
export declare const OS_NAME: "mac" | "win" | "lin";
|
|
4
|
+
export declare const INSTALL_DIR: PathLike;
|
|
5
|
+
export declare const LOCAL_DATA: PathLike;
|
|
6
|
+
export declare const OS_ARCH_MATRIX: {
|
|
7
|
+
[key: string]: string[];
|
|
8
|
+
};
|
|
9
|
+
declare class Version {
|
|
10
|
+
release: string;
|
|
11
|
+
version?: string;
|
|
12
|
+
sorted_rel: number[];
|
|
13
|
+
constructor(release: string, version?: string);
|
|
14
|
+
private buildSortedRel;
|
|
15
|
+
get fullString(): string;
|
|
16
|
+
equals(other: Version): boolean;
|
|
17
|
+
lessThan(other: Version): boolean;
|
|
18
|
+
isSupported(): boolean;
|
|
19
|
+
static fromPath(filePath?: PathLike): Version;
|
|
20
|
+
static isSupportedPath(path: PathLike): boolean;
|
|
21
|
+
static buildMinMax(): [Version, Version];
|
|
22
|
+
}
|
|
23
|
+
export declare class GitHubDownloader {
|
|
24
|
+
githubRepo: string;
|
|
25
|
+
apiUrl: string;
|
|
26
|
+
constructor(githubRepo: string);
|
|
27
|
+
checkAsset(asset: any): any;
|
|
28
|
+
missingAssetError(): void;
|
|
29
|
+
getAsset({ retries }?: {
|
|
30
|
+
retries: number;
|
|
31
|
+
}): Promise<any>;
|
|
32
|
+
}
|
|
33
|
+
export declare class CamoufoxFetcher extends GitHubDownloader {
|
|
34
|
+
arch: string;
|
|
35
|
+
_version_obj?: Version;
|
|
36
|
+
pattern: RegExp;
|
|
37
|
+
_url?: string;
|
|
38
|
+
constructor();
|
|
39
|
+
init(): Promise<void>;
|
|
40
|
+
checkAsset(asset: any): [Version, string] | null;
|
|
41
|
+
missingAssetError(): void;
|
|
42
|
+
static getPlatformArch(): string;
|
|
43
|
+
fetchLatest(): Promise<void>;
|
|
44
|
+
static downloadFile(url: string): Promise<Buffer>;
|
|
45
|
+
extractZip(zipFile: string | Buffer): Promise<void>;
|
|
46
|
+
static cleanup(): boolean;
|
|
47
|
+
setVersion(): void;
|
|
48
|
+
install(): Promise<void>;
|
|
49
|
+
get url(): string;
|
|
50
|
+
get version(): string;
|
|
51
|
+
get release(): string;
|
|
52
|
+
get verstr(): string;
|
|
53
|
+
}
|
|
54
|
+
export declare function installedVerStr(): string;
|
|
55
|
+
export declare function camoufoxPath(downloadIfMissing?: boolean): PathLike;
|
|
56
|
+
export declare function getPath(file: string): string;
|
|
57
|
+
export declare function launchPath(): string;
|
|
58
|
+
export declare function webdl(url: string, desc?: string, bar?: boolean, buffer?: Writable | null, { retries }?: {
|
|
59
|
+
retries: number;
|
|
60
|
+
}): Promise<Buffer>;
|
|
61
|
+
export declare function unzip(zipFile: Buffer, extractPath: string, desc?: string, bar?: boolean): Promise<void>;
|
|
62
|
+
export {};
|
package/dist/pkgman.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { setTimeout } from "node:timers/promises";
|
|
6
|
+
import AdmZip from "adm-zip";
|
|
7
|
+
import ProgressBar from "progress";
|
|
8
|
+
import { CONSTRAINTS } from "./__version__.js";
|
|
9
|
+
import { CamoufoxNotInstalled, FileNotFoundError, MissingRelease, UnsupportedArchitecture, UnsupportedOS, UnsupportedVersion, } from "./exceptions.js";
|
|
10
|
+
const ARCH_MAP = {
|
|
11
|
+
x64: "x86_64",
|
|
12
|
+
ia32: "i686",
|
|
13
|
+
arm64: "arm64",
|
|
14
|
+
arm: "arm64",
|
|
15
|
+
};
|
|
16
|
+
const OS_MAP = {
|
|
17
|
+
darwin: "mac",
|
|
18
|
+
linux: "lin",
|
|
19
|
+
win32: "win",
|
|
20
|
+
};
|
|
21
|
+
if (!(process.platform in OS_MAP)) {
|
|
22
|
+
throw new UnsupportedOS(`OS ${process.platform} is not supported`);
|
|
23
|
+
}
|
|
24
|
+
export const OS_NAME = OS_MAP[process.platform];
|
|
25
|
+
export const INSTALL_DIR = userCacheDir("camoufox");
|
|
26
|
+
export const LOCAL_DATA = path.join(import.meta.dirname, "data-files");
|
|
27
|
+
export const OS_ARCH_MATRIX = {
|
|
28
|
+
win: ["x86_64", "i686"],
|
|
29
|
+
mac: ["x86_64", "arm64"],
|
|
30
|
+
lin: ["x86_64", "arm64", "i686"],
|
|
31
|
+
};
|
|
32
|
+
const LAUNCH_FILE = {
|
|
33
|
+
win: "camoufox.exe",
|
|
34
|
+
mac: "../MacOS/camoufox",
|
|
35
|
+
lin: "camoufox-bin",
|
|
36
|
+
};
|
|
37
|
+
class Version {
|
|
38
|
+
release;
|
|
39
|
+
version;
|
|
40
|
+
sorted_rel;
|
|
41
|
+
constructor(release, version) {
|
|
42
|
+
this.release = release;
|
|
43
|
+
this.version = version;
|
|
44
|
+
this.sorted_rel = this.buildSortedRel();
|
|
45
|
+
}
|
|
46
|
+
buildSortedRel() {
|
|
47
|
+
const parts = this.release
|
|
48
|
+
.split(".")
|
|
49
|
+
.map((x) => Number.isNaN(Number(x)) ? x.charCodeAt(0) - 1024 : Number(x));
|
|
50
|
+
while (parts.length < 5) {
|
|
51
|
+
parts.push(0);
|
|
52
|
+
}
|
|
53
|
+
return parts;
|
|
54
|
+
}
|
|
55
|
+
get fullString() {
|
|
56
|
+
return `${this.version}-${this.release}`;
|
|
57
|
+
}
|
|
58
|
+
equals(other) {
|
|
59
|
+
return this.sorted_rel.join(".") === other.sorted_rel.join(".");
|
|
60
|
+
}
|
|
61
|
+
lessThan(other) {
|
|
62
|
+
for (let i = 0; i < this.sorted_rel.length; i++) {
|
|
63
|
+
if (this.sorted_rel[i] < other.sorted_rel[i])
|
|
64
|
+
return true;
|
|
65
|
+
if (this.sorted_rel[i] > other.sorted_rel[i])
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
isSupported() {
|
|
71
|
+
return VERSION_MIN.lessThan(this) && this.lessThan(VERSION_MAX);
|
|
72
|
+
}
|
|
73
|
+
static fromPath(filePath = INSTALL_DIR) {
|
|
74
|
+
const versionPath = path.join(filePath.toString(), "version.json");
|
|
75
|
+
if (!fs.existsSync(versionPath)) {
|
|
76
|
+
throw new FileNotFoundError(`Version information not found at ${versionPath}. Please run \`camoufox fetch\` to install.`);
|
|
77
|
+
}
|
|
78
|
+
const versionData = JSON.parse(fs.readFileSync(versionPath, "utf-8"));
|
|
79
|
+
return new Version(versionData.release, versionData.version);
|
|
80
|
+
}
|
|
81
|
+
static isSupportedPath(path) {
|
|
82
|
+
return Version.fromPath(path).isSupported();
|
|
83
|
+
}
|
|
84
|
+
static buildMinMax() {
|
|
85
|
+
return [
|
|
86
|
+
new Version(CONSTRAINTS.MIN_VERSION),
|
|
87
|
+
new Version(CONSTRAINTS.MAX_VERSION),
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const [VERSION_MIN, VERSION_MAX] = Version.buildMinMax();
|
|
92
|
+
export class GitHubDownloader {
|
|
93
|
+
githubRepo;
|
|
94
|
+
apiUrl;
|
|
95
|
+
constructor(githubRepo) {
|
|
96
|
+
this.githubRepo = githubRepo;
|
|
97
|
+
this.apiUrl = `https://api.github.com/repos/${githubRepo}/releases`;
|
|
98
|
+
}
|
|
99
|
+
checkAsset(asset) {
|
|
100
|
+
return asset.browser_download_url;
|
|
101
|
+
}
|
|
102
|
+
missingAssetError() {
|
|
103
|
+
throw new MissingRelease(`Could not find a release asset in ${this.githubRepo}.`);
|
|
104
|
+
}
|
|
105
|
+
async getAsset({ retries } = { retries: 5 }) {
|
|
106
|
+
let attempts = 0;
|
|
107
|
+
let response;
|
|
108
|
+
while (attempts < retries) {
|
|
109
|
+
try {
|
|
110
|
+
response = await fetch(this.apiUrl);
|
|
111
|
+
if (response.ok)
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
console.error(e, `retrying (${attempts + 1}/${retries})...`);
|
|
116
|
+
await setTimeout(5e3);
|
|
117
|
+
}
|
|
118
|
+
attempts++;
|
|
119
|
+
}
|
|
120
|
+
if (!response || !response.ok) {
|
|
121
|
+
throw new Error(`Failed to fetch releases from ${this.apiUrl} after ${retries} attempts`);
|
|
122
|
+
}
|
|
123
|
+
const releases = await response.json();
|
|
124
|
+
for (const release of releases) {
|
|
125
|
+
for (const asset of release.assets) {
|
|
126
|
+
const data = this.checkAsset(asset);
|
|
127
|
+
if (data) {
|
|
128
|
+
return data;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
this.missingAssetError();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export class CamoufoxFetcher extends GitHubDownloader {
|
|
136
|
+
arch;
|
|
137
|
+
_version_obj;
|
|
138
|
+
pattern;
|
|
139
|
+
_url;
|
|
140
|
+
constructor() {
|
|
141
|
+
super("daijro/camoufox");
|
|
142
|
+
this.arch = CamoufoxFetcher.getPlatformArch();
|
|
143
|
+
this.pattern = new RegExp(`camoufox-(.+)-(.+)-${OS_NAME}\\.${this.arch}\\.zip`);
|
|
144
|
+
}
|
|
145
|
+
async init() {
|
|
146
|
+
await this.fetchLatest();
|
|
147
|
+
}
|
|
148
|
+
checkAsset(asset) {
|
|
149
|
+
const match = asset.name.match(this.pattern);
|
|
150
|
+
if (!match)
|
|
151
|
+
return null;
|
|
152
|
+
const version = new Version(match[2], match[1]);
|
|
153
|
+
if (!version.isSupported())
|
|
154
|
+
return null;
|
|
155
|
+
return [version, asset.browser_download_url];
|
|
156
|
+
}
|
|
157
|
+
missingAssetError() {
|
|
158
|
+
throw new MissingRelease(`No matching release found for ${OS_NAME} ${this.arch} in the supported range: (${CONSTRAINTS.asRange()}). Please update the library.`);
|
|
159
|
+
}
|
|
160
|
+
static getPlatformArch() {
|
|
161
|
+
const platArch = os.arch().toLowerCase();
|
|
162
|
+
if (!(platArch in ARCH_MAP)) {
|
|
163
|
+
throw new UnsupportedArchitecture(`Architecture ${platArch} is not supported`);
|
|
164
|
+
}
|
|
165
|
+
const arch = ARCH_MAP[platArch];
|
|
166
|
+
if (!OS_ARCH_MATRIX[OS_NAME].includes(arch)) {
|
|
167
|
+
throw new UnsupportedArchitecture(`Architecture ${arch} is not supported for ${OS_NAME}`);
|
|
168
|
+
}
|
|
169
|
+
return arch;
|
|
170
|
+
}
|
|
171
|
+
async fetchLatest() {
|
|
172
|
+
if (this._version_obj)
|
|
173
|
+
return;
|
|
174
|
+
const releaseData = await this.getAsset();
|
|
175
|
+
this._version_obj = releaseData[0];
|
|
176
|
+
this._url = releaseData[1];
|
|
177
|
+
}
|
|
178
|
+
static async downloadFile(url) {
|
|
179
|
+
const response = await fetch(url);
|
|
180
|
+
return Buffer.from(await response.arrayBuffer());
|
|
181
|
+
}
|
|
182
|
+
async extractZip(zipFile) {
|
|
183
|
+
const zip = new AdmZip(zipFile);
|
|
184
|
+
zip.extractAllTo(INSTALL_DIR.toString(), true);
|
|
185
|
+
}
|
|
186
|
+
static cleanup() {
|
|
187
|
+
if (fs.existsSync(INSTALL_DIR)) {
|
|
188
|
+
fs.rmSync(INSTALL_DIR, { recursive: true });
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
setVersion() {
|
|
194
|
+
fs.writeFileSync(path.join(INSTALL_DIR.toString(), "version.json"), JSON.stringify({ version: this.version, release: this.release }));
|
|
195
|
+
}
|
|
196
|
+
async install() {
|
|
197
|
+
await this.init();
|
|
198
|
+
await CamoufoxFetcher.cleanup();
|
|
199
|
+
try {
|
|
200
|
+
fs.mkdirSync(INSTALL_DIR, { recursive: true });
|
|
201
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "camoufox-"));
|
|
202
|
+
const tempFilePath = path.join(tempDir, "camoufox.zip");
|
|
203
|
+
const tempFileStream = fs.createWriteStream(tempFilePath);
|
|
204
|
+
await webdl(this.url, "Downloading Camoufox...", true, tempFileStream);
|
|
205
|
+
await new Promise((r) => tempFileStream.close(r));
|
|
206
|
+
await this.extractZip(tempFilePath);
|
|
207
|
+
this.setVersion();
|
|
208
|
+
if (OS_NAME !== "win") {
|
|
209
|
+
execSync(`chmod -R 755 ${INSTALL_DIR}`);
|
|
210
|
+
}
|
|
211
|
+
console.log("Camoufox successfully installed.");
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
console.error(`Error installing Camoufox: ${e}`);
|
|
215
|
+
await CamoufoxFetcher.cleanup();
|
|
216
|
+
throw e;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
get url() {
|
|
220
|
+
if (!this._url) {
|
|
221
|
+
throw new Error("Url is not available. Make sure to run fetchLatest first.");
|
|
222
|
+
}
|
|
223
|
+
return this._url;
|
|
224
|
+
}
|
|
225
|
+
get version() {
|
|
226
|
+
if (!this._version_obj || !this._version_obj.version) {
|
|
227
|
+
throw new Error("Version is not available. Make sure to run fetchLatest first.");
|
|
228
|
+
}
|
|
229
|
+
return this._version_obj.version;
|
|
230
|
+
}
|
|
231
|
+
get release() {
|
|
232
|
+
if (!this._version_obj) {
|
|
233
|
+
throw new Error("Release information is not available. Make sure to run the installation first.");
|
|
234
|
+
}
|
|
235
|
+
return this._version_obj.release;
|
|
236
|
+
}
|
|
237
|
+
get verstr() {
|
|
238
|
+
if (!this._version_obj) {
|
|
239
|
+
throw new Error("Version is not available. Make sure to run the installation first.");
|
|
240
|
+
}
|
|
241
|
+
return this._version_obj.fullString;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function userCacheDir(appName) {
|
|
245
|
+
if (OS_NAME === "win") {
|
|
246
|
+
return path.join(os.homedir(), "AppData", "Local", appName, appName, "Cache");
|
|
247
|
+
}
|
|
248
|
+
else if (OS_NAME === "mac") {
|
|
249
|
+
return path.join(os.homedir(), "Library", "Caches", appName);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
return path.join(os.homedir(), ".cache", appName);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
export function installedVerStr() {
|
|
256
|
+
return Version.fromPath().fullString;
|
|
257
|
+
}
|
|
258
|
+
export function camoufoxPath(downloadIfMissing = true) {
|
|
259
|
+
// Ensure the directory exists and is not empty
|
|
260
|
+
if (!fs.existsSync(INSTALL_DIR) || fs.readdirSync(INSTALL_DIR).length === 0) {
|
|
261
|
+
if (!downloadIfMissing) {
|
|
262
|
+
throw new Error(`Camoufox executable not found at ${INSTALL_DIR}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else if (fs.existsSync(INSTALL_DIR) &&
|
|
266
|
+
Version.isSupportedPath(INSTALL_DIR)) {
|
|
267
|
+
return INSTALL_DIR;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
if (!downloadIfMissing) {
|
|
271
|
+
throw new UnsupportedVersion("Camoufox executable is outdated.");
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Install and recheck
|
|
275
|
+
const fetcher = new CamoufoxFetcher();
|
|
276
|
+
fetcher.install().then(() => camoufoxPath());
|
|
277
|
+
return INSTALL_DIR;
|
|
278
|
+
}
|
|
279
|
+
export function getPath(file) {
|
|
280
|
+
if (OS_NAME === "mac") {
|
|
281
|
+
return path.resolve(camoufoxPath().toString(), "Camoufox.app", "Contents", "Resources", file);
|
|
282
|
+
}
|
|
283
|
+
return path.join(camoufoxPath().toString(), file);
|
|
284
|
+
}
|
|
285
|
+
export function launchPath() {
|
|
286
|
+
const launchPath = getPath(LAUNCH_FILE[OS_NAME]);
|
|
287
|
+
if (!fs.existsSync(launchPath)) {
|
|
288
|
+
throw new CamoufoxNotInstalled(`Camoufox is not installed at ${camoufoxPath()}. Please run \`camoufox fetch\` to install.`);
|
|
289
|
+
}
|
|
290
|
+
return launchPath;
|
|
291
|
+
}
|
|
292
|
+
export async function webdl(url, desc = "", bar = true, buffer = null, { retries } = { retries: 5 }) {
|
|
293
|
+
let attempts = 0;
|
|
294
|
+
let response;
|
|
295
|
+
while (attempts < retries) {
|
|
296
|
+
try {
|
|
297
|
+
response = await fetch(url);
|
|
298
|
+
if (response.ok)
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
catch (e) {
|
|
302
|
+
console.error(e, `retrying (${attempts + 1}/${retries})...`);
|
|
303
|
+
await setTimeout(5e3);
|
|
304
|
+
}
|
|
305
|
+
attempts++;
|
|
306
|
+
}
|
|
307
|
+
if (!response || !response.ok) {
|
|
308
|
+
throw new Error(`Failed to download from ${url} after ${retries} attempts`);
|
|
309
|
+
}
|
|
310
|
+
const totalSize = parseInt(response.headers.get("content-length") || "0", 10);
|
|
311
|
+
const progressBar = bar
|
|
312
|
+
? new ProgressBar(`${desc} [:bar] :percent :etas`, {
|
|
313
|
+
total: totalSize,
|
|
314
|
+
width: 40,
|
|
315
|
+
})
|
|
316
|
+
: null;
|
|
317
|
+
const chunks = [];
|
|
318
|
+
for await (const chunk of response.body) {
|
|
319
|
+
if (buffer) {
|
|
320
|
+
buffer.write(chunk);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
chunks.push(chunk);
|
|
324
|
+
}
|
|
325
|
+
if (progressBar) {
|
|
326
|
+
progressBar.tick(chunk.length, "X");
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const fileBuffer = Buffer.concat(chunks);
|
|
330
|
+
return fileBuffer;
|
|
331
|
+
}
|
|
332
|
+
export async function unzip(zipFile, extractPath, desc, bar = true) {
|
|
333
|
+
const zip = new AdmZip(zipFile);
|
|
334
|
+
const zipEntries = zip.getEntries();
|
|
335
|
+
if (bar) {
|
|
336
|
+
console.log(desc || "Extracting files...");
|
|
337
|
+
}
|
|
338
|
+
for (const entry of zipEntries) {
|
|
339
|
+
if (bar) {
|
|
340
|
+
console.log(`Extracting ${entry.entryName}`);
|
|
341
|
+
}
|
|
342
|
+
zip.extractEntryTo(entry, extractPath, false, true);
|
|
343
|
+
}
|
|
344
|
+
if (bar) {
|
|
345
|
+
console.log("Extraction complete.");
|
|
346
|
+
}
|
|
347
|
+
}
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { firefox } from "playwright-core";
|
|
2
|
+
import { launchOptions } from "./utils.js";
|
|
3
|
+
export async function launchServer({ port, ws_path, ...options }) {
|
|
4
|
+
return firefox.launchServer({
|
|
5
|
+
...(await launchOptions(options)),
|
|
6
|
+
port,
|
|
7
|
+
wsPath: ws_path,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Browser, type BrowserContext, type BrowserType } from "playwright-core";
|
|
2
|
+
import { type LaunchOptions } from "./utils.js";
|
|
3
|
+
export declare function Camoufox<UserDataDir extends string | undefined = undefined, ReturnType = UserDataDir extends string ? BrowserContext : Browser>(launch_options?: LaunchOptions | {
|
|
4
|
+
headless?: boolean | "virtual";
|
|
5
|
+
user_data_dir: UserDataDir;
|
|
6
|
+
}): Promise<ReturnType>;
|
|
7
|
+
export declare function NewBrowser<UserDataDir extends string | false = false, ReturnType = UserDataDir extends string ? BrowserContext : Browser>(playwright: BrowserType<Browser>, headless?: boolean | "virtual", fromOptions?: Record<string, any>, userDataDir?: UserDataDir, debug?: boolean, launch_options?: LaunchOptions): Promise<ReturnType>;
|
package/dist/sync_api.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { firefox, } from "playwright-core";
|
|
2
|
+
import { launchOptions, syncAttachVD } from "./utils.js";
|
|
3
|
+
import { VirtualDisplay } from "./virtdisplay.js";
|
|
4
|
+
export async function Camoufox(launch_options = {}) {
|
|
5
|
+
const { headless, user_data_dir, ...launchOptions } = launch_options;
|
|
6
|
+
return NewBrowser(firefox, headless, {}, user_data_dir ?? false, false, launchOptions);
|
|
7
|
+
}
|
|
8
|
+
export async function NewBrowser(playwright, headless = false, fromOptions = {}, userDataDir = false, debug = false, launch_options = {}) {
|
|
9
|
+
let virtualDisplay = null;
|
|
10
|
+
if (headless === "virtual") {
|
|
11
|
+
virtualDisplay = new VirtualDisplay(debug);
|
|
12
|
+
launch_options.virtual_display = virtualDisplay.get();
|
|
13
|
+
launch_options.headless = false;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
launch_options.headless ||= headless;
|
|
17
|
+
}
|
|
18
|
+
if (!fromOptions || Object.keys(fromOptions).length === 0) {
|
|
19
|
+
fromOptions = await launchOptions({ debug, ...launch_options });
|
|
20
|
+
}
|
|
21
|
+
if (typeof userDataDir === "string") {
|
|
22
|
+
const context = await playwright.launchPersistentContext(userDataDir, fromOptions);
|
|
23
|
+
return syncAttachVD(context, virtualDisplay);
|
|
24
|
+
}
|
|
25
|
+
const browser = await playwright.launch(fromOptions);
|
|
26
|
+
return syncAttachVD(browser, virtualDisplay);
|
|
27
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type PathLike } from "node:fs";
|
|
2
|
+
import type { Fingerprint, FingerprintGeneratorOptions } from "fingerprint-generator";
|
|
3
|
+
import type { LaunchOptions as PlaywrightLaunchOptions } from "playwright-core";
|
|
4
|
+
import { type DefaultAddons } from "./addons.js";
|
|
5
|
+
import { SUPPORTED_OS } from "./fingerprints.js";
|
|
6
|
+
import type { VirtualDisplay } from "./virtdisplay.js";
|
|
7
|
+
type Screen = FingerprintGeneratorOptions["screen"];
|
|
8
|
+
export declare function getAsBooleanFromENV(name: string, defaultValue?: boolean | undefined): boolean;
|
|
9
|
+
export declare function syncAttachVD(browser: any, virtualDisplay?: VirtualDisplay | null): any;
|
|
10
|
+
export interface LaunchOptions {
|
|
11
|
+
/** Operating system to use for the fingerprint generation.
|
|
12
|
+
* Can be "windows", "macos", "linux", or a list to randomly choose from.
|
|
13
|
+
* Default: ["windows", "macos", "linux"]
|
|
14
|
+
*/
|
|
15
|
+
os?: (typeof SUPPORTED_OS)[number] | (typeof SUPPORTED_OS)[number][];
|
|
16
|
+
/** Whether to block all images. */
|
|
17
|
+
block_images?: boolean;
|
|
18
|
+
/** Whether to block WebRTC entirely. */
|
|
19
|
+
block_webrtc?: boolean;
|
|
20
|
+
/** Whether to block WebGL. To prevent leaks, only use this for special cases. */
|
|
21
|
+
block_webgl?: boolean;
|
|
22
|
+
/** Disables the Cross-Origin-Opener-Policy, allowing elements in cross-origin iframes to be clicked. */
|
|
23
|
+
disable_coop?: boolean;
|
|
24
|
+
/** Calculate longitude, latitude, timezone, country, & locale based on the IP address.
|
|
25
|
+
* Pass the target IP address to use, or `true` to find the IP address automatically.
|
|
26
|
+
*/
|
|
27
|
+
geoip?: string | boolean;
|
|
28
|
+
/** Humanize the cursor movement.
|
|
29
|
+
* Takes either `true`, or the MAX duration in seconds of the cursor movement.
|
|
30
|
+
* The cursor typically takes up to 1.5 seconds to move across the window.
|
|
31
|
+
*/
|
|
32
|
+
humanize?: boolean | number;
|
|
33
|
+
/** Locale(s) to use. The first listed locale will be used for the Intl API. */
|
|
34
|
+
locale?: string | string[];
|
|
35
|
+
/** List of Firefox addons to use. */
|
|
36
|
+
addons?: string[];
|
|
37
|
+
/** Fonts to load into the browser (in addition to the default fonts for the target `os`).
|
|
38
|
+
* Takes a list of font family names that are installed on the system.
|
|
39
|
+
*/
|
|
40
|
+
fonts?: string[];
|
|
41
|
+
/** If enabled, OS-specific system fonts will not be passed to the browser. */
|
|
42
|
+
custom_fonts_only?: boolean;
|
|
43
|
+
/** Default addons to exclude. Passed as a list of `DefaultAddons` enums. */
|
|
44
|
+
exclude_addons?: (keyof typeof DefaultAddons)[];
|
|
45
|
+
/** Constrains the screen dimensions of the generated fingerprint. */
|
|
46
|
+
screen?: Screen;
|
|
47
|
+
/** Set a fixed window size instead of generating a random one. */
|
|
48
|
+
window?: [number, number];
|
|
49
|
+
/** Use a custom BrowserForge fingerprint. If not provided, a random fingerprint will be generated
|
|
50
|
+
* based on the provided `os` & `screen` constraints.
|
|
51
|
+
*/
|
|
52
|
+
fingerprint?: Fingerprint;
|
|
53
|
+
/** Firefox version to use. Defaults to the current Camoufox version.
|
|
54
|
+
* To prevent leaks, only use this for special cases.
|
|
55
|
+
*/
|
|
56
|
+
ff_version?: number;
|
|
57
|
+
/** Whether to run the browser in headless mode. Defaults to `false`.
|
|
58
|
+
*/
|
|
59
|
+
headless?: boolean;
|
|
60
|
+
/** Whether to enable running scripts in the main world.
|
|
61
|
+
* To use this, prepend "mw:" to the script: `page.evaluate("mw:" + script)`.
|
|
62
|
+
*/
|
|
63
|
+
main_world_eval?: boolean;
|
|
64
|
+
/** Custom browser executable path. */
|
|
65
|
+
executable_path?: string | PathLike;
|
|
66
|
+
/** Firefox user preferences to set. */
|
|
67
|
+
firefox_user_prefs?: Record<string, any>;
|
|
68
|
+
/** Proxy to use for the browser.
|
|
69
|
+
* Note: If `geoip` is `true`, a request will be sent through this proxy to find the target IP.
|
|
70
|
+
*/
|
|
71
|
+
proxy?: string | PlaywrightLaunchOptions["proxy"];
|
|
72
|
+
/** Cache previous pages, requests, etc. (uses more memory). */
|
|
73
|
+
enable_cache?: boolean;
|
|
74
|
+
/** Arguments to pass to the browser. */
|
|
75
|
+
args?: string[];
|
|
76
|
+
/** Environment variables to set. */
|
|
77
|
+
env?: Record<string, string | number | boolean>;
|
|
78
|
+
/** Prints the config being sent to Camoufox. */
|
|
79
|
+
debug?: boolean;
|
|
80
|
+
/** Virtual display number. Example: `":99"`. This is handled by Camoufox & AsyncCamoufox. */
|
|
81
|
+
virtual_display?: string;
|
|
82
|
+
/** Use a specific WebGL vendor/renderer pair. Passed as a tuple of `[vendor, renderer]`. */
|
|
83
|
+
webgl_config?: [string, string];
|
|
84
|
+
/** Additional Firefox launch options. */
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
}
|
|
87
|
+
export declare function launchOptions({ config, os, block_images, block_webrtc, block_webgl, disable_coop, webgl_config, geoip, humanize, locale, addons, fonts, custom_fonts_only, exclude_addons, screen, window, fingerprint, ff_version, headless, main_world_eval, executable_path, firefox_user_prefs, proxy, enable_cache, args, env, i_know_what_im_doing, debug, virtual_display, ...launch_options }: LaunchOptions): Promise<Record<string, any>>;
|
|
88
|
+
export {};
|