gologin 2.0.30 → 2.1.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/.eslintrc.json CHANGED
@@ -1,257 +1,290 @@
1
1
  {
2
- "env": {
3
- "browser": true,
4
- "es2021": true,
5
- "node": true
6
- },
7
- "extends": "eslint:recommended",
8
- "overrides": [
9
- ],
10
- "parserOptions": {
11
- "ecmaVersion": "latest",
12
- "sourceType": "module"
13
- },
14
- "plugins": [
15
- "simple-import-sort"
16
- ],
17
- "rules": {
18
- "padding-line-between-statements": [
19
- "warn",
20
- { "blankLine": "always", "prev": ["if", "switch", "while", "function", "multiline-const", "try"], "next": "*" },
21
- { "blankLine": "always", "prev": "*", "next": ["return"] }
22
- ],
23
- "indent": [
24
- "warn",
2
+ "env": {
3
+ "browser": true,
4
+ "es2021": true,
5
+ "node": true
6
+ },
7
+ "extends": "eslint:recommended",
8
+ "overrides": [
9
+ ],
10
+ "parserOptions": {
11
+ "ecmaVersion": "latest",
12
+ "sourceType": "module"
13
+ },
14
+ "plugins": [
15
+ "simple-import-sort"
16
+ ],
17
+ "rules": {
18
+ "padding-line-between-statements": [
19
+ "warn",
20
+ {
21
+ "blankLine": "always",
22
+ "prev": [
23
+ "if",
24
+ "switch",
25
+ "while",
26
+ "function",
27
+ "multiline-const",
28
+ "try"
29
+ ],
30
+ "next": "*"
31
+ },
32
+ {
33
+ "blankLine": "always",
34
+ "prev": "*",
35
+ "next": [
36
+ "return"
37
+ ]
38
+ }
39
+ ],
40
+ "indent": [
41
+ "warn",
42
+ 2,
43
+ {
44
+ "SwitchCase": 1,
45
+ "ignoredNodes": [
46
+ "ClassBody.body > PropertyDefinition[decorators.length > 0] > .key"
47
+ ]
48
+ }
49
+ ],
50
+ "linebreak-style": 0,
51
+ "quotes": [
52
+ "warn",
53
+ "single"
54
+ ],
55
+ "semi": [
56
+ "warn",
57
+ "always"
58
+ ],
59
+ "array-callback-return": [
60
+ "warn"
61
+ ],
62
+ "no-await-in-loop": [
63
+ "off"
64
+ ],
65
+ "no-duplicate-imports": [
66
+ "warn"
67
+ ],
68
+ "arrow-body-style": [
69
+ "warn",
70
+ "as-needed"
71
+ ],
72
+ "curly": [
73
+ "warn",
74
+ "all"
75
+ ],
76
+ "default-case": [
77
+ "warn"
78
+ ],
79
+ "default-case-last": [
80
+ "warn"
81
+ ],
82
+ "dot-notation": [
83
+ "warn"
84
+ ],
85
+ "eqeqeq": [
86
+ "warn",
87
+ "always"
88
+ ],
89
+ "id-length": [
90
+ "warn",
91
+ {
92
+ "min": 1,
93
+ "max": 40,
94
+ "properties": "never"
95
+ }
96
+ ],
97
+ "max-depth": [
98
+ "warn",
99
+ {
100
+ "max": 4
101
+ }
102
+ ],
103
+ "max-lines": [
104
+ "warn",
105
+ 1500
106
+ ],
107
+ "no-else-return": [
108
+ "warn",
109
+ {
110
+ "allowElseIf": true
111
+ }
112
+ ],
113
+ "no-unused-vars": [
114
+ "warn",
115
+ {
116
+ "vars": "all",
117
+ "args": "after-used",
118
+ "ignoreRestSiblings": false,
119
+ "varsIgnorePattern": "^_"
120
+ }
121
+ ],
122
+ "keyword-spacing": [
123
+ "error",
124
+ {
125
+ "before": true,
126
+ "after": true
127
+ }
128
+ ],
129
+ "no-empty-function": [
130
+ "warn",
131
+ {
132
+ "allow": [
133
+ "constructors"
134
+ ]
135
+ }
136
+ ],
137
+ "no-inline-comments": [
138
+ "warn"
139
+ ],
140
+ "no-labels": [
141
+ "warn"
142
+ ],
143
+ "no-lone-blocks": [
144
+ "warn"
145
+ ],
146
+ "no-lonely-if": [
147
+ "warn"
148
+ ],
149
+ "no-magic-numbers": [
150
+ "off",
151
+ {
152
+ "ignoreArrayIndexes": true,
153
+ "ignoreDefaultValues": true,
154
+ "ignore": [
155
+ 1,
25
156
  2,
26
- {
27
- "SwitchCase": 1,
28
- "ignoredNodes": [
29
- "ClassBody.body > PropertyDefinition[decorators.length > 0] > .key"
30
- ]
31
- }
32
- ],
33
- "linebreak-style": 0,
34
- "quotes": [
35
- "warn",
36
- "single"
37
- ],
38
- "semi": [
39
- "warn",
40
- "always"
41
- ],
42
- "array-callback-return": [
43
- "warn"
44
- ],
45
- "no-await-in-loop": [
46
- "off"
47
- ],
48
- "no-duplicate-imports": [
49
- "warn"
50
- ],
51
- "arrow-body-style": [
52
- "warn",
53
- "as-needed"
54
- ],
55
- "curly": [
56
- "warn",
57
- "all"
58
- ],
59
- "default-case": [
60
- "warn"
61
- ],
62
- "default-case-last": [
63
- "warn"
64
- ],
65
- "dot-notation": [
66
- "warn"
67
- ],
68
- "eqeqeq": [
69
- "warn",
70
- "always"
71
- ],
72
- "id-length": [
73
- "warn",
74
- {
75
- "min": 1,
76
- "max": 40,
77
- "properties": "never"
78
- }
79
- ],
80
- "max-depth": [
81
- "warn",
82
- {
83
- "max": 4
84
- }
85
- ],
86
- "max-lines": [
87
- "warn",
88
- 1500
89
- ],
90
- "no-else-return": [
91
- "warn",
92
- {
93
- "allowElseIf": true
94
- }
95
- ],
96
- "no-unused-vars": [
97
- "warn", {
98
- "vars": "all",
99
- "args": "after-used",
100
- "ignoreRestSiblings": false,
101
- "varsIgnorePattern": "^_"
102
- }
103
- ],
104
- "keyword-spacing": [
105
- "error", {
106
- "before": true,
107
- "after": true
108
- }
109
- ],
110
- "no-empty-function": [
111
- "warn",
112
- {
113
- "allow": ["constructors"]
114
- }
115
- ],
116
- "no-inline-comments": [
117
- "warn"
118
- ],
119
- "no-labels": [
120
- "warn"
121
- ],
122
- "no-lone-blocks": [
123
- "warn"
124
- ],
125
- "no-lonely-if": [
126
- "warn"
127
- ],
128
- "no-magic-numbers": [
129
- "off",
130
- {
131
- "ignoreArrayIndexes": true,
132
- "ignoreDefaultValues": true,
133
- "ignore": [1, 2, 3, 10, 1000, -1, 0]
134
- }
135
- ],
136
- "no-multi-assign": [
137
- "warn"
138
- ],
139
- "no-multi-str": [
140
- "warn"
141
- ],
142
- "no-nested-ternary": [
143
- "warn"
144
- ],
145
- "no-return-assign": [
146
- "warn"
147
- ],
148
- "no-return-await": [
149
- "warn"
150
- ],
151
- "no-sequences": [
152
- "warn"
153
- ],
154
- "no-shadow": [
155
- "warn"
156
- ],
157
- "no-undefined": [
158
- "warn"
159
- ],
160
- "no-underscore-dangle": [
161
- "warn",
162
- {
163
- "allow": ["_id"]
164
- }
165
- ],
166
- "no-unneeded-ternary": [
167
- "warn"
168
- ],
169
- "no-unused-expressions": [
170
- "warn",
171
- {
172
- "allowShortCircuit": true,
173
- "allowTernary": true
174
- }
175
- ],
176
- "no-useless-return": [
177
- "warn"
178
- ],
179
- "object-shorthand": [
180
- "warn",
181
- "always"
182
- ],
183
- "prefer-arrow-callback": [
184
- "warn"
185
- ],
186
- "prefer-const": [
187
- "warn"
188
- ],
189
- "prefer-destructuring": [
190
- "warn"
191
- ],
192
- "prefer-object-spread": [
193
- "warn"
194
- ],
195
- "prefer-spread": [
196
- "warn"
197
- ],
198
- "prefer-template": [
199
- "off"
200
- ],
201
- "spaced-comment": [
202
- "warn"
203
- ],
204
- "yoda": [
205
- "warn"
206
- ],
207
- "arrow-spacing": [
208
- "warn"
209
- ],
210
- "brace-style": [
211
- "warn",
212
- "1tbs",
213
- { "allowSingleLine": false }
214
- ],
215
- "comma-dangle": [
216
- "warn",
217
- "always-multiline"
218
- ],
219
- "dot-location": [
220
- "warn",
221
- "property"
222
- ],
223
- "eol-last": [
224
- "warn"
225
- ],
226
- "no-extra-parens": [
227
- "off"
228
- ],
229
- "no-multiple-empty-lines": [
230
- "warn",
231
- {
232
- "max": 1
233
- }
234
- ],
235
- "no-trailing-spaces": [
236
- "warn"
237
- ],
238
- "no-whitespace-before-property": [
239
- "warn"
240
- ],
241
- "object-curly-spacing": [
242
- "warn",
243
- "always"
244
- ],
245
- "space-in-parens": [
246
- "warn"
247
- ],
248
- "template-curly-spacing": [
249
- "warn"
250
- ],
251
- "max-len": [
252
- "warn",
253
- 150
254
- ],
255
- "simple-import-sort/imports": "warn"
256
- }
157
+ 3,
158
+ 10,
159
+ 1000,
160
+ -1,
161
+ 0
162
+ ]
163
+ }
164
+ ],
165
+ "no-multi-assign": [
166
+ "warn"
167
+ ],
168
+ "no-multi-str": [
169
+ "warn"
170
+ ],
171
+ "no-nested-ternary": [
172
+ "warn"
173
+ ],
174
+ "no-return-assign": [
175
+ "warn"
176
+ ],
177
+ "no-return-await": [
178
+ "warn"
179
+ ],
180
+ "no-sequences": [
181
+ "warn"
182
+ ],
183
+ "no-shadow": [
184
+ "warn"
185
+ ],
186
+ "no-undefined": [
187
+ "warn"
188
+ ],
189
+ "no-underscore-dangle": [
190
+ "warn",
191
+ {
192
+ "allow": [
193
+ "_id"
194
+ ]
195
+ }
196
+ ],
197
+ "no-unneeded-ternary": [
198
+ "warn"
199
+ ],
200
+ "no-unused-expressions": [
201
+ "warn",
202
+ {
203
+ "allowShortCircuit": true,
204
+ "allowTernary": true
205
+ }
206
+ ],
207
+ "no-useless-return": [
208
+ "warn"
209
+ ],
210
+ "object-shorthand": [
211
+ "warn",
212
+ "always"
213
+ ],
214
+ "prefer-arrow-callback": [
215
+ "warn"
216
+ ],
217
+ "prefer-const": [
218
+ "warn"
219
+ ],
220
+ "prefer-destructuring": [
221
+ "warn"
222
+ ],
223
+ "prefer-object-spread": [
224
+ "warn"
225
+ ],
226
+ "prefer-spread": [
227
+ "warn"
228
+ ],
229
+ "prefer-template": [
230
+ "off"
231
+ ],
232
+ "spaced-comment": [
233
+ "warn"
234
+ ],
235
+ "yoda": [
236
+ "warn"
237
+ ],
238
+ "arrow-spacing": [
239
+ "warn"
240
+ ],
241
+ "brace-style": [
242
+ "warn",
243
+ "1tbs",
244
+ {
245
+ "allowSingleLine": false
246
+ }
247
+ ],
248
+ "comma-dangle": [
249
+ "warn",
250
+ "always-multiline"
251
+ ],
252
+ "dot-location": [
253
+ "warn",
254
+ "property"
255
+ ],
256
+ "eol-last": [
257
+ "warn"
258
+ ],
259
+ "no-extra-parens": [
260
+ "off"
261
+ ],
262
+ "no-multiple-empty-lines": [
263
+ "warn",
264
+ {
265
+ "max": 1
266
+ }
267
+ ],
268
+ "no-trailing-spaces": [
269
+ "warn"
270
+ ],
271
+ "no-whitespace-before-property": [
272
+ "warn"
273
+ ],
274
+ "object-curly-spacing": [
275
+ "warn",
276
+ "always"
277
+ ],
278
+ "space-in-parens": [
279
+ "warn"
280
+ ],
281
+ "template-curly-spacing": [
282
+ "warn"
283
+ ],
284
+ "max-len": [
285
+ "warn",
286
+ 150
287
+ ],
288
+ "simple-import-sort/imports": "warn"
289
+ }
257
290
  }
@@ -0,0 +1,17 @@
1
+ import { exitAll, GologinApi } from '../src/gologin-api.js';
2
+
3
+ const token = process.env.GOLOGIN_API_TOKEN; // get token https://app.gologin.com/personalArea/TokenApi
4
+ const gologin = GologinApi({ token });
5
+
6
+ async function main() {
7
+ const { browser } = await gologin.launch();
8
+ const page = await browser.newPage();
9
+ await page.goto('https://iphey.com/', { waitUntil: 'networkidle2' });
10
+ const status = await page.$eval('.trustworthy-status:not(.hide)', (elt) =>
11
+ elt?.innerText?.trim(),
12
+ );
13
+
14
+ return status; // Expecting 'Trustworthy'
15
+ }
16
+
17
+ main().catch(console.error).then(console.info).finally(exitAll);
package/index.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ import { type Browser } from 'puppeteer-core/lib/Browser';
2
+
3
+ export const OPERATING_SYSTEMS = {
4
+ win: 'win',
5
+ lin: 'lin',
6
+ mac: 'mac',
7
+ android: 'android',
8
+ } as const;
9
+ export type OsType = (typeof OPERATING_SYSTEMS)[keyof typeof OPERATING_SYSTEMS];
10
+
11
+ type CloudLaunchParams = {
12
+ cloud: true;
13
+
14
+ /**
15
+ * Format: 'dataCenter:DE'
16
+ */
17
+ geolocation?: string;
18
+ };
19
+ type LocalLaunchParams = {
20
+ cloud: false;
21
+ headless: boolean;
22
+ };
23
+
24
+ type ExistingProfileLaunchParams = {
25
+ profileId: string;
26
+ };
27
+ type NewProfileLaunchParams = {
28
+ proxyGeolocation: string;
29
+ };
30
+
31
+ type LaunchParams =
32
+ | CloudLaunchParams
33
+ | LocalLaunchParams
34
+ | ExistingProfileLaunchParams
35
+ | NewProfileLaunchParams
36
+ | {
37
+ /**
38
+ * default delay, 250
39
+ */
40
+ defaultDelay: number;
41
+
42
+ /**
43
+ * Operating system
44
+ */
45
+ os: OsType;
46
+ };
47
+
48
+ type LaunchFn = (params?: LaunchParams) => Promise<{ browser: Browser }>;
49
+
50
+ type GologinApiType = {
51
+ launch: LaunchFn;
52
+ exit: (status = 0) => Promise<void>;
53
+ delay: (ms: number) => Promise<void>;
54
+ };
55
+
56
+ type GologinApiParams = {
57
+ token: string;
58
+ };
59
+
60
+ export declare function GologinApi(params: GologinApiParams): GologinApiType;
61
+ export declare function exitAll(): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "gologin",
3
- "version": "2.0.30",
3
+ "version": "2.1.1",
4
4
  "description": "A high-level API to control Orbita browser over GoLogin API",
5
+ "types": "./index.d.ts",
5
6
  "main": "./src/gologin.js",
6
7
  "repository": {
7
8
  "type": "git",
@@ -41,6 +42,8 @@
41
42
  "eslint-plugin-simple-import-sort": "^8.0.0"
42
43
  },
43
44
  "scripts": {
44
- "test": "echo \"Error: no test specified\" && exit 1"
45
+ "test": "echo \"Error: no test specified\" && exit 1",
46
+ "format": "npx prettier --single-quote src/* --write",
47
+ "iphey": "GOLOGIN_PROFILE_ID= GOLOGIN_API_TOKEN= node examples/example-iphey "
45
48
  }
46
49
  }
@@ -63,7 +63,7 @@ export class BrowserChecker {
63
63
  // console.log('executableFilePath:', executableFilePath);
64
64
  }
65
65
 
66
- async checkBrowser(autoUpdateBrowser = false) {
66
+ async checkBrowser(autoUpdateBrowser = false, checkBrowserUpdate = true) {
67
67
  const browserFolderExists = await access(this.#executableFilePath).then(() => true).catch(() => false);
68
68
 
69
69
  const { latestVersion: browserLatestVersion, browserDownloadUrl } = await this.getLatestBrowserVersion();
@@ -75,7 +75,7 @@ export class BrowserChecker {
75
75
  const currentVersionReq = await this.getCurrentVersion();
76
76
  const currentVersion = (currentVersionReq?.stdout || '').replace(/(\r\n|\n|\r)/gm, '');
77
77
 
78
- if (browserLatestVersion === currentVersion) {
78
+ if (browserLatestVersion === currentVersion || !checkBrowserUpdate) {
79
79
  return;
80
80
  }
81
81
 
@@ -357,6 +357,7 @@ export class BrowserChecker {
357
357
  timeout: 15 * 1000,
358
358
  headers: {
359
359
  'Content-Type': 'application/json',
360
+ 'User-Agent': 'gologin-api',
360
361
  },
361
362
  }, (res) => {
362
363
  res.setEncoding('utf8');
@@ -0,0 +1,110 @@
1
+ import puppeteer from 'puppeteer-core';
2
+
3
+ import GoLogin from './gologin.js';
4
+
5
+ export function getDefaultParams() {
6
+ return {
7
+ token: process.env.GOLOGIN_API_TOKEN,
8
+ profile_id: process.env.GOLOGIN_PROFILE_ID,
9
+ executablePath: process.env.GOLOGIN_EXECUTABLE_PATH,
10
+ autoUpdateBrowser: true,
11
+ };
12
+ }
13
+
14
+ const createLegacyGologin = ({ profileId, ...params }) => {
15
+ const defaults = getDefaultParams();
16
+ const mergedParams = {
17
+ ...defaults,
18
+ ...params,
19
+ };
20
+
21
+ mergedParams.profile_id = profileId ?? mergedParams.profile_id;
22
+
23
+ console.log({ mergedParams });
24
+
25
+ return new GoLogin(mergedParams);
26
+ };
27
+
28
+ const createdApis = [];
29
+
30
+ export const delay = (ms = 250) => new Promise((res) => setTimeout(res, ms));
31
+
32
+ export function GologinApi({ token }) {
33
+ if (!token) {
34
+ throw new Error('GoLogin API token is missing');
35
+ }
36
+
37
+ const browsers = [];
38
+ const legacyGls = [];
39
+
40
+ const launchLocal = async (params) => {
41
+ const legacyGologin = createLegacyGologin({
42
+ ...params,
43
+ token,
44
+ });
45
+
46
+ if (!params.profileId) {
47
+ const { id } = await legacyGologin.quickCreateProfile();
48
+ await legacyGologin.setProfileId(id);
49
+ }
50
+
51
+ const started = await legacyGologin.start();
52
+ const browser = await puppeteer.connect({
53
+ browserWSEndpoint: started.wsUrl,
54
+ ignoreHTTPSErrors: true,
55
+ });
56
+
57
+ browsers.push(browser);
58
+ legacyGls.push(legacyGologin);
59
+
60
+ return { browser };
61
+ };
62
+
63
+ const launchCloudProfile = async (params) => {
64
+ const profileParam = params.profileId
65
+ ? `&profile=${params.profileId}`
66
+ : '';
67
+
68
+ const geolocationParam = params.geolocation
69
+ ? `&geolocation=${params.geolocation}`
70
+ : '';
71
+
72
+ const browserWSEndpoint = `https://cloud.gologin.com/connect?token=${token}${profileParam}${geolocationParam}`;
73
+ const browser = await puppeteer.connect({
74
+ browserWSEndpoint,
75
+ ignoreHTTPSErrors: true,
76
+ });
77
+
78
+ browsers.push(browser);
79
+
80
+ return { browser };
81
+ };
82
+
83
+ const api = {
84
+ async launch(params = {}) {
85
+ if (params.cloud) {
86
+ return launchCloudProfile(params);
87
+ }
88
+
89
+ return launchLocal(params);
90
+ },
91
+
92
+ async exit(status = 0) {
93
+ Promise.allSettled(browsers.map((browser) => browser.close()));
94
+ Promise.allSettled(
95
+ legacyGls.map((gl) => gl.stopLocal({ posting: false })),
96
+ );
97
+ process.exit(status);
98
+ },
99
+
100
+ delay,
101
+ };
102
+
103
+ createdApis.push(api);
104
+
105
+ return api;
106
+ }
107
+
108
+ export function exitAll() {
109
+ Promise.allSettled(createdApis.map((api) => api.exit()));
110
+ }
package/src/gologin.js CHANGED
@@ -2,7 +2,7 @@ import { execFile, spawn } from 'child_process';
2
2
  import debugDefault from 'debug';
3
3
  import decompress from 'decompress';
4
4
  import decompressUnzip from 'decompress-unzip';
5
- import { existsSync, mkdirSync, promises as _promises } from 'fs';
5
+ import { existsSync, mkdirSync,promises as _promises } from 'fs';
6
6
  import { get as _get } from 'https';
7
7
  import { tmpdir } from 'os';
8
8
  import { dirname, join, resolve as _resolve, sep } from 'path';
@@ -26,9 +26,10 @@ import {
26
26
  import ExtensionsManager from './extensions/extensions-manager.js';
27
27
  import { archiveProfile } from './profile/profile-archiver.js';
28
28
  import { checkAutoLang } from './utils/browser.js';
29
- import { API_URL } from './utils/common.js';
29
+ import { API_URL, getOsAdvanced } from './utils/common.js';
30
30
  import { STORAGE_GATEWAY_BASE_URL } from './utils/constants.js';
31
31
  import { get, isPortReachable } from './utils/utils.js';
32
+ export { exitAll, GologinApi } from './gologin-api.js';
32
33
 
33
34
  const { access, unlink, writeFile, readFile } = _promises;
34
35
 
@@ -55,19 +56,14 @@ export class GoLogin {
55
56
  this.is_stopping = false;
56
57
  this.differentOs = false;
57
58
  this.profileOs = 'lin';
58
- this.waitWebsocket = true;
59
- if (options.waitWebsocket === false) {
60
- this.waitWebsocket = false;
61
- }
59
+ this.waitWebsocket = options.waitWebsocket ?? true;
62
60
 
63
61
  this.isCloudHeadless = options.isCloudHeadless ?? true;
64
- this.isNewCloudBrowser = true;
65
- if (options.isNewCloudBrowser === false) {
66
- this.isNewCloudBrowser = false;
67
- }
62
+ this.isNewCloudBrowser = options.isNewCloudBrowser ?? true;
68
63
 
69
64
  this.tmpdir = tmpdir();
70
65
  this.autoUpdateBrowser = !!options.autoUpdateBrowser;
66
+ this.checkBrowserUpdate = options.checkBrowserUpdate ?? true;
71
67
  this.browserChecker = new BrowserChecker(options.skipOrbitaHashChecking);
72
68
  this.uploadCookiesToServer = options.uploadCookiesToServer || false;
73
69
  this.writeCookiesFromServer = options.writeCookiesFromServer;
@@ -93,7 +89,7 @@ export class GoLogin {
93
89
  }
94
90
 
95
91
  async checkBrowser() {
96
- return this.browserChecker.checkBrowser(this.autoUpdateBrowser);
92
+ return this.browserChecker.checkBrowser(this.autoUpdateBrowser, this.checkBrowserUpdate);
97
93
  }
98
94
 
99
95
  async setProfileId(profile_id) {
@@ -152,6 +148,7 @@ export class GoLogin {
152
148
  const profileResponse = await requests.get(`${API_URL}/browser/${id}`, {
153
149
  headers: {
154
150
  'Authorization': `Bearer ${this.access_token}`,
151
+ 'User-Agent': 'gologin-api',
155
152
  },
156
153
  });
157
154
 
@@ -161,9 +158,9 @@ export class GoLogin {
161
158
  const backendErrorHeader = 'backend@error::';
162
159
  if (errorBody.includes(backendErrorHeader)) {
163
160
  const errorData =
164
- errorBody
165
- .replace(backendErrorHeader, '')
166
- .slice(1, -1);
161
+ errorBody
162
+ .replace(backendErrorHeader, '')
163
+ .slice(1, -1);
167
164
 
168
165
  throw new Error(errorData);
169
166
  }
@@ -269,7 +266,7 @@ export class GoLogin {
269
266
  }
270
267
 
271
268
  if (get(preferences, 'navigator.deviceMemory')) {
272
- preferences.deviceMemory = get(preferences, 'navigator.deviceMemory')*1024;
269
+ preferences.deviceMemory = get(preferences, 'navigator.deviceMemory') * 1024;
273
270
  }
274
271
 
275
272
  if (get(preferences, 'navigator.language')) {
@@ -355,14 +352,14 @@ export class GoLogin {
355
352
  );
356
353
  }
357
354
 
358
- async createStartup(local=false) {
355
+ async createStartup(local = false) {
359
356
  const profilePath = join(this.tmpdir, `gologin_profile_${this.profile_id}`);
360
357
  let profile;
361
358
  let profile_folder;
362
359
  await rimraf(profilePath, () => null);
363
360
  debug('-', profilePath, 'dropped');
364
361
  profile = await this.getProfile();
365
- const { navigator = {}, fonts, os: profileOs } = profile;
362
+ const { navigator = {}, fonts, os: profileOs } = profile;
366
363
  this.fontsMasking = fonts?.enableMasking;
367
364
  this.profileOs = profileOs;
368
365
  this.differentOs =
@@ -449,7 +446,7 @@ export class GoLogin {
449
446
  ExtensionsManagerInst.apiUrl = API_URL;
450
447
  await ExtensionsManagerInst.init()
451
448
  .then(() => ExtensionsManagerInst.updateExtensions())
452
- .catch(() => {});
449
+ .catch(() => { });
453
450
  ExtensionsManagerInst.accessToken = this.access_token;
454
451
 
455
452
  await ExtensionsManagerInst.getExtensionsPolicies();
@@ -516,7 +513,6 @@ export class GoLogin {
516
513
  profile.proxy.username = get(profile, 'autoProxyUsername');
517
514
  profile.proxy.password = get(profile, 'autoProxyPassword');
518
515
  }
519
- // console.log('proxy=', proxy);
520
516
 
521
517
  if (proxy.mode === 'geolocation') {
522
518
  proxy.mode = 'http';
@@ -560,7 +556,7 @@ export class GoLogin {
560
556
 
561
557
  const audioContext = profile.audioContext || {};
562
558
  const { mode: audioCtxMode = 'off', noise: audioCtxNoise } = audioContext;
563
- if (profile.timezone.fillBasedOnIp==false) {
559
+ if (profile.timezone.fillBasedOnIp === false) {
564
560
  profile.timezone = { id: profile.timezone.timezone };
565
561
  } else {
566
562
  profile.timezone = { id: this._tz.timezone };
@@ -612,7 +608,7 @@ export class GoLogin {
612
608
 
613
609
  const languages = this.language.replace(/;|q=[\d\.]+/img, '');
614
610
 
615
- if (preferences.gologin==null) {
611
+ if (preferences.gologin == null) {
616
612
  preferences.gologin = {};
617
613
  }
618
614
 
@@ -777,7 +773,6 @@ export class GoLogin {
777
773
  }).on('error', (err) => reject(err));
778
774
  });
779
775
 
780
- // console.log('checkData:', checkData);
781
776
  body = checkData.body || {};
782
777
  if (!body.ip && checkData.statusCode.toString().startsWith('4')) {
783
778
  throw checkData;
@@ -799,6 +794,7 @@ export class GoLogin {
799
794
  Object.keys(process.env).forEach((key) => {
800
795
  env[key] = process.env[key];
801
796
  });
797
+
802
798
  const tz = await this.getTimeZone(this.proxy).catch((e) => {
803
799
  console.error('Proxy Error. Check it and try again.');
804
800
  throw e;
@@ -841,6 +837,7 @@ export class GoLogin {
841
837
  Object.keys(process.env).forEach((key) => {
842
838
  env[key] = process.env[key];
843
839
  });
840
+
844
841
  const tz = await this.getTimeZone(this.proxy).catch((e) => {
845
842
  console.error('Proxy Error. Check it and try again.');
846
843
  throw e;
@@ -857,7 +854,6 @@ export class GoLogin {
857
854
  { env },
858
855
  );
859
856
  } else {
860
-
861
857
  let params = [
862
858
  `--remote-debugging-port=${remote_debugging_port}`,
863
859
  `--user-data-dir=${profile_path}`,
@@ -1079,6 +1075,7 @@ export class GoLogin {
1079
1075
  const profileResponse = await requests.post(`${API_URL}/browser`, {
1080
1076
  headers: {
1081
1077
  'Authorization': `Bearer ${this.access_token}`,
1078
+ 'User-Agent': 'gologin-api',
1082
1079
  },
1083
1080
  json: {
1084
1081
 
@@ -1106,7 +1103,7 @@ export class GoLogin {
1106
1103
  url += '&isM1=true';
1107
1104
  }
1108
1105
 
1109
- const fingerprint = await requests.get(url,{
1106
+ const fingerprint = await requests.get(url, {
1110
1107
  headers: {
1111
1108
  'Authorization': `Bearer ${this.access_token}`,
1112
1109
  'User-Agent': 'gologin-api',
@@ -1136,7 +1133,7 @@ export class GoLogin {
1136
1133
  deviceMemory = 1;
1137
1134
  }
1138
1135
 
1139
- navigator.deviceMemory = deviceMemory*1024;
1136
+ navigator.deviceMemory = deviceMemory * 1024;
1140
1137
  webGLMetadata.mode = webGLMetadata.mode === 'noise' ? 'mask' : 'off';
1141
1138
 
1142
1139
  const json = {
@@ -1171,8 +1168,6 @@ export class GoLogin {
1171
1168
  json.navigator.userAgent = orig_user_agent;
1172
1169
  }
1173
1170
 
1174
- // console.log('profileOptions', json);
1175
-
1176
1171
  const response = await requests.post(`${API_URL}/browser`, {
1177
1172
  headers: {
1178
1173
  'Authorization': `Bearer ${this.access_token}`,
@@ -1217,6 +1212,25 @@ export class GoLogin {
1217
1212
  return response.body.id;
1218
1213
  }
1219
1214
 
1215
+ async quickCreateProfile(name = '') {
1216
+ const osInfo = await getOsAdvanced();
1217
+ const { os, osSpec } = osInfo;
1218
+ const resultName = name || 'api-generated';
1219
+
1220
+ return requests.post(`${API_URL}/browser/quick`, {
1221
+ headers: {
1222
+ 'Authorization': `Bearer ${this.access_token}`,
1223
+ 'User-Agent': 'gologin-api',
1224
+ },
1225
+ json: {
1226
+ os,
1227
+ osSpec,
1228
+ name: resultName,
1229
+ },
1230
+ })
1231
+ .then(res => res.body);
1232
+ }
1233
+
1220
1234
  async delete(pid) {
1221
1235
  const profile_id = pid || this.profile_id;
1222
1236
  await requests.delete(`${API_URL}/browser/${profile_id}`, {
@@ -1233,19 +1247,20 @@ export class GoLogin {
1233
1247
 
1234
1248
  if (options.navigator) {
1235
1249
  Object.keys(options.navigator).map((e) => {
1236
- profile.navigator[e]=options.navigator[e];
1250
+ profile.navigator[e] = options.navigator[e];
1237
1251
  });
1238
1252
  }
1239
1253
 
1240
- Object.keys(options).filter(e => e !== 'navigator').map((e) => {
1241
- profile[e]=options[e];
1254
+ Object.keys(options).filter(el => el !== 'navigator').forEach((el) => {
1255
+ profile[el] = options[el];
1242
1256
  });
1243
1257
 
1244
1258
  debug('update profile', profile);
1245
- const response = await requests.put(`${API_URL}/browser/${options.id}`,{
1259
+ const response = await requests.put(`${API_URL}/browser/${options.id}`, {
1246
1260
  json: profile,
1247
1261
  headers: {
1248
1262
  'Authorization': `Bearer ${this.access_token}`,
1263
+ 'User-Agent': 'gologin-api',
1249
1264
  },
1250
1265
  });
1251
1266
 
@@ -1403,7 +1418,7 @@ export class GoLogin {
1403
1418
  await this.stopAndCommit(opts, true);
1404
1419
  }
1405
1420
 
1406
- async waitDebuggingUrl(delay_ms, try_count=0, remoteOrbitaUrl) {
1421
+ async waitDebuggingUrl(delay_ms, try_count = 0, remoteOrbitaUrl) {
1407
1422
  await delay(delay_ms);
1408
1423
  const url = `${remoteOrbitaUrl}/json/version`;
1409
1424
  console.log('try_count=', try_count, 'url=', url);
@@ -1443,7 +1458,7 @@ export class GoLogin {
1443
1458
 
1444
1459
  const profile = await this.getProfile();
1445
1460
  const profileResponse = await requests.post(`${API_URL}/browser/${this.profile_id}/web`, {
1446
- headers: { 'Authorization': `Bearer ${this.access_token}` },
1461
+ headers: { 'Authorization': `Bearer ${this.access_token}`, 'User-Agent': 'gologin-api', },
1447
1462
  json: { isNewCloudBrowser: this.isNewCloudBrowser, isHeadless: this.isCloudHeadless },
1448
1463
  }).catch(() => null);
1449
1464
 
@@ -1471,7 +1486,7 @@ export class GoLogin {
1471
1486
  remoteOrbitaUrl = profileResponse.body.remoteOrbitaUrl;
1472
1487
  }
1473
1488
 
1474
- const { navigator = {}, fonts, os: profileOs } = profile;
1489
+ const { navigator = {}, fonts, os: profileOs } = profile;
1475
1490
  this.fontsMasking = fonts?.enableMasking;
1476
1491
  this.profileOs = profileOs;
1477
1492
  this.differentOs =
@@ -1504,7 +1519,10 @@ export class GoLogin {
1504
1519
  async stopRemote() {
1505
1520
  debug(`stopRemote ${this.profile_id}`);
1506
1521
  const profileResponse = await requests.delete(`${API_URL}/browser/${this.profile_id}/web?isNewCloudBrowser=${this.isNewCloudBrowser}`, {
1507
- headers: { 'Authorization': `Bearer ${this.access_token}` },
1522
+ headers: {
1523
+ 'Authorization': `Bearer ${this.access_token}`,
1524
+ 'User-Agent': 'gologin-api',
1525
+ },
1508
1526
  });
1509
1527
 
1510
1528
  console.log(`stopRemote ${profileResponse.body}`);
@@ -1,5 +1,7 @@
1
+ import { exec } from 'child_process';
1
2
  import { homedir } from 'os';
2
3
  import { join, sep } from 'path';
4
+ import { promisify } from 'util';
3
5
 
4
6
  import { deleteExtensionArchive, extractExtension } from '../extensions/extensions-extractor.js';
5
7
 
@@ -21,6 +23,31 @@ const composeExtractionPromises = (filteredArchives, destPath = CHROME_EXTENSION
21
23
  })
22
24
  );
23
25
 
26
+ const getMacArmSpec = async () => {
27
+ const doExec = promisify(exec);
28
+
29
+ const { stdout } = await doExec('sysctl machdep.cpu');
30
+ const regExp = /Apple M\d/;
31
+ const [match] = stdout.match(regExp);
32
+ const [_, armVersion] = match.split(' ');
33
+
34
+ return armVersion;
35
+ };
36
+
37
+ const getOsAdvanced = async () => {
38
+ const os = getOS();
39
+ if (!['mac', 'macM1'].includes(os)) {
40
+ return { os, osSpec: '' };
41
+ }
42
+
43
+ const osSpec = await getMacArmSpec();
44
+
45
+ return {
46
+ os: 'mac',
47
+ osSpec,
48
+ };
49
+ };
50
+
24
51
  const getOS = () => {
25
52
  if (process.platform === 'win32') {
26
53
  return 'win';
@@ -35,9 +62,15 @@ const getOS = () => {
35
62
 
36
63
  const _composeExtractionPromises = composeExtractionPromises;
37
64
  export { _composeExtractionPromises as composeExtractionPromises };
65
+
38
66
  const _getOS = getOS;
39
67
  export { _getOS as getOS };
68
+
69
+ const _getOsAdvanced = getOsAdvanced;
70
+ export { _getOsAdvanced as getOsAdvanced };
71
+
40
72
  const _USER_EXTENSIONS_PATH = USER_EXTENSIONS_PATH;
41
73
  export { _USER_EXTENSIONS_PATH as USER_EXTENSIONS_PATH };
74
+
42
75
  const _CHROME_EXTENSIONS_PATH = CHROME_EXTENSIONS_PATH;
43
76
  export { _CHROME_EXTENSIONS_PATH as CHROME_EXTENSIONS_PATH };
@@ -3,9 +3,9 @@ import net from 'node:net';
3
3
  import { join } from 'node:path';
4
4
 
5
5
  export const get = (value, path, defaultValue) =>
6
- String(path).split('.').reduce((acc, v) => {
6
+ String(path).split('.').reduce((acc, val) => {
7
7
  try {
8
- acc = acc[v] ? acc[v] : defaultValue;
8
+ acc = acc[val] ? acc[val] : defaultValue;
9
9
  } catch (e) {
10
10
  return defaultValue;
11
11
  }