gologin-commonjs 2.1.13 → 2.1.14
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/src/gologin.js +874 -516
- package/gologin/src/gologin.js +611 -389
- package/package.json +1 -1
package/gologin/src/gologin.js
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
|
-
import { execFile, spawn } from
|
|
2
|
-
import debugDefault from
|
|
3
|
-
import decompress from
|
|
4
|
-
import decompressUnzip from
|
|
5
|
-
import { existsSync, mkdirSync,promises as _promises } from
|
|
6
|
-
import { get as _get } from
|
|
7
|
-
import { tmpdir } from
|
|
8
|
-
import { dirname, join, resolve as _resolve, sep } from
|
|
9
|
-
import requests from
|
|
10
|
-
import rimraf from
|
|
11
|
-
import { SocksProxyAgent } from
|
|
12
|
-
|
|
13
|
-
import { fontsCollection } from
|
|
14
|
-
import { getCurrentProfileBookmarks } from
|
|
15
|
-
import { updateProfileBookmarks, updateProfileProxy, updateProfileResolution, updateProfileUserAgent } from './browser/browser-api.js';
|
|
16
|
-
import BrowserChecker from './browser/browser-checker.js';
|
|
1
|
+
import { execFile, spawn } from "child_process";
|
|
2
|
+
import debugDefault from "debug";
|
|
3
|
+
import decompress from "decompress";
|
|
4
|
+
import decompressUnzip from "decompress-unzip";
|
|
5
|
+
import { existsSync, mkdirSync, promises as _promises } from "fs";
|
|
6
|
+
import { get as _get } from "https";
|
|
7
|
+
import { tmpdir } from "os";
|
|
8
|
+
import { dirname, join, resolve as _resolve, sep } from "path";
|
|
9
|
+
import requests from "requestretry";
|
|
10
|
+
import rimraf from "rimraf";
|
|
11
|
+
import { SocksProxyAgent } from "socks-proxy-agent";
|
|
12
|
+
|
|
13
|
+
import { fontsCollection } from "../fonts.js";
|
|
14
|
+
import { getCurrentProfileBookmarks } from "./bookmarks/utils.js";
|
|
17
15
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
updateProfileBookmarks,
|
|
17
|
+
updateProfileProxy,
|
|
18
|
+
updateProfileResolution,
|
|
19
|
+
updateProfileUserAgent,
|
|
20
|
+
} from "./browser/browser-api.js";
|
|
21
|
+
import BrowserChecker from "./browser/browser-checker.js";
|
|
22
|
+
import {
|
|
23
|
+
composeFonts,
|
|
24
|
+
downloadCookies,
|
|
25
|
+
setExtPathsAndRemoveDeleted,
|
|
26
|
+
setOriginalExtPaths,
|
|
27
|
+
uploadCookies,
|
|
28
|
+
} from "./browser/browser-user-data-manager.js";
|
|
20
29
|
import {
|
|
21
30
|
createDBFile,
|
|
22
31
|
getChunckedInsertValues,
|
|
@@ -24,29 +33,29 @@ import {
|
|
|
24
33
|
getDB,
|
|
25
34
|
getUniqueCookies,
|
|
26
35
|
loadCookiesFromFile,
|
|
27
|
-
} from
|
|
28
|
-
import ExtensionsManager from
|
|
29
|
-
import { archiveProfile } from
|
|
30
|
-
import { checkAutoLang } from
|
|
31
|
-
import { API_URL, getOsAdvanced } from
|
|
32
|
-
import { STORAGE_GATEWAY_BASE_URL } from
|
|
33
|
-
import { get, isPortReachable } from
|
|
34
|
-
export { exitAll, GologinApi } from
|
|
35
|
-
import { zeroProfileBookmarks } from
|
|
36
|
-
import { zeroProfilePreferences } from
|
|
36
|
+
} from "./cookies/cookies-manager.js";
|
|
37
|
+
import ExtensionsManager from "./extensions/extensions-manager.js";
|
|
38
|
+
import { archiveProfile } from "./profile/profile-archiver.js";
|
|
39
|
+
import { checkAutoLang } from "./utils/browser.js";
|
|
40
|
+
import { API_URL, getOsAdvanced } from "./utils/common.js";
|
|
41
|
+
import { STORAGE_GATEWAY_BASE_URL } from "./utils/constants.js";
|
|
42
|
+
import { get, isPortReachable } from "./utils/utils.js";
|
|
43
|
+
export { exitAll, GologinApi } from "./gologin-api.js";
|
|
44
|
+
import { zeroProfileBookmarks } from "./utils/zero-profile-bookmarks.js";
|
|
45
|
+
import { zeroProfilePreferences } from "./utils/zero-profile-preferences.js";
|
|
37
46
|
const { access, unlink, writeFile, readFile, mkdir, copyFile } = _promises;
|
|
38
47
|
|
|
39
48
|
const SEPARATOR = sep;
|
|
40
49
|
const OS_PLATFORM = process.platform;
|
|
41
|
-
const TIMEZONE_URL =
|
|
42
|
-
const PROXY_NONE =
|
|
50
|
+
const TIMEZONE_URL = "https://geo.myip.link";
|
|
51
|
+
const PROXY_NONE = "none";
|
|
43
52
|
|
|
44
|
-
const debug = debugDefault(
|
|
53
|
+
const debug = debugDefault("gologin");
|
|
45
54
|
const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
46
55
|
|
|
47
56
|
export class GoLogin {
|
|
48
57
|
constructor(options = {}) {
|
|
49
|
-
this.browserLang =
|
|
58
|
+
this.browserLang = "en-US";
|
|
50
59
|
this.access_token = options.token;
|
|
51
60
|
this.profile_id = options.profile_id;
|
|
52
61
|
this.password = options.password;
|
|
@@ -57,7 +66,7 @@ export class GoLogin {
|
|
|
57
66
|
this.is_active = false;
|
|
58
67
|
this.is_stopping = false;
|
|
59
68
|
this.differentOs = false;
|
|
60
|
-
this.profileOs =
|
|
69
|
+
this.profileOs = "lin";
|
|
61
70
|
this.waitWebsocket = options.waitWebsocket ?? true;
|
|
62
71
|
this.isEmptyFonts = false;
|
|
63
72
|
this.isFirstSession = false;
|
|
@@ -80,25 +89,38 @@ export class GoLogin {
|
|
|
80
89
|
if (options.tmpdir) {
|
|
81
90
|
this.tmpdir = options.tmpdir;
|
|
82
91
|
if (!existsSync(this.tmpdir)) {
|
|
83
|
-
debug(
|
|
92
|
+
debug("making tmpdir", this.tmpdir);
|
|
84
93
|
mkdirSync(this.tmpdir, { recursive: true });
|
|
85
94
|
}
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
this.profile_zip_path = join(this.tmpdir, `gologin_${this.profile_id}.zip`);
|
|
89
|
-
this.bookmarksFilePath = join(
|
|
90
|
-
|
|
98
|
+
this.bookmarksFilePath = join(
|
|
99
|
+
this.tmpdir,
|
|
100
|
+
`gologin_profile_${this.profile_id}`,
|
|
101
|
+
"Default",
|
|
102
|
+
"Bookmarks"
|
|
103
|
+
);
|
|
104
|
+
debug("INIT GOLOGIN", this.profile_id);
|
|
91
105
|
}
|
|
92
106
|
|
|
93
107
|
async checkBrowser() {
|
|
94
|
-
return this.browserChecker.checkBrowser(
|
|
108
|
+
return this.browserChecker.checkBrowser(
|
|
109
|
+
this.autoUpdateBrowser,
|
|
110
|
+
this.checkBrowserUpdate
|
|
111
|
+
);
|
|
95
112
|
}
|
|
96
113
|
|
|
97
114
|
async setProfileId(profile_id) {
|
|
98
115
|
this.profile_id = profile_id;
|
|
99
116
|
this.cookiesFilePath = await getCookiesFilePath(profile_id, this.tmpdir);
|
|
100
117
|
this.profile_zip_path = join(this.tmpdir, `gologin_${this.profile_id}.zip`);
|
|
101
|
-
this.bookmarksFilePath = join(
|
|
118
|
+
this.bookmarksFilePath = join(
|
|
119
|
+
this.tmpdir,
|
|
120
|
+
`gologin_profile_${this.profile_id}`,
|
|
121
|
+
"Default",
|
|
122
|
+
"Bookmarks"
|
|
123
|
+
);
|
|
102
124
|
}
|
|
103
125
|
|
|
104
126
|
async getToken(username, password) {
|
|
@@ -109,21 +131,28 @@ export class GoLogin {
|
|
|
109
131
|
},
|
|
110
132
|
});
|
|
111
133
|
|
|
112
|
-
if (!Reflect.has(data,
|
|
113
|
-
throw new Error(
|
|
134
|
+
if (!Reflect.has(data, "body.access_token")) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`gologin auth failed with status code, ${
|
|
137
|
+
data.statusCode
|
|
138
|
+
} DATA ${JSON.stringify(data)}`
|
|
139
|
+
);
|
|
114
140
|
}
|
|
115
141
|
}
|
|
116
142
|
|
|
117
143
|
async getNewFingerPrint(os) {
|
|
118
|
-
debug(
|
|
144
|
+
debug("GETTING FINGERPRINT");
|
|
119
145
|
|
|
120
|
-
const fpResponse = await requests.get(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
146
|
+
const fpResponse = await requests.get(
|
|
147
|
+
`${API_URL}/browser/fingerprint?os=${os}`,
|
|
148
|
+
{
|
|
149
|
+
json: true,
|
|
150
|
+
headers: {
|
|
151
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
152
|
+
"User-Agent": "gologin-api",
|
|
153
|
+
},
|
|
154
|
+
}
|
|
155
|
+
);
|
|
127
156
|
|
|
128
157
|
return fpResponse?.body || {};
|
|
129
158
|
}
|
|
@@ -131,14 +160,13 @@ export class GoLogin {
|
|
|
131
160
|
async profiles() {
|
|
132
161
|
const profilesResponse = await requests.get(`${API_URL}/browser/v2`, {
|
|
133
162
|
headers: {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
163
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
164
|
+
"User-Agent": "gologin-api",
|
|
137
165
|
},
|
|
138
166
|
});
|
|
139
167
|
|
|
140
168
|
if (profilesResponse.statusCode !== 200) {
|
|
141
|
-
throw new Error(
|
|
169
|
+
throw new Error("Gologin /browser response error");
|
|
142
170
|
}
|
|
143
171
|
|
|
144
172
|
return JSON.parse(profilesResponse.body);
|
|
@@ -146,23 +174,23 @@ export class GoLogin {
|
|
|
146
174
|
|
|
147
175
|
async getProfile(profile_id) {
|
|
148
176
|
const id = profile_id || this.profile_id;
|
|
149
|
-
debug(
|
|
150
|
-
const profileResponse = await requests.get(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
177
|
+
debug("getProfile", this.access_token, id);
|
|
178
|
+
const profileResponse = await requests.get(
|
|
179
|
+
`${API_URL}/browser/features/${id}/info-for-run`,
|
|
180
|
+
{
|
|
181
|
+
headers: {
|
|
182
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
183
|
+
"User-Agent": "gologin-api",
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
);
|
|
156
187
|
|
|
157
|
-
debug(
|
|
188
|
+
debug("profileResponse", profileResponse.statusCode, profileResponse.body);
|
|
158
189
|
|
|
159
|
-
const { body: errorBody =
|
|
160
|
-
const backendErrorHeader =
|
|
190
|
+
const { body: errorBody = "" } = profileResponse;
|
|
191
|
+
const backendErrorHeader = "backend@error::";
|
|
161
192
|
if (errorBody.includes(backendErrorHeader)) {
|
|
162
|
-
const errorData =
|
|
163
|
-
errorBody
|
|
164
|
-
.replace(backendErrorHeader, '')
|
|
165
|
-
.slice(1, -1);
|
|
193
|
+
const errorData = errorBody.replace(backendErrorHeader, "").slice(1, -1);
|
|
166
194
|
|
|
167
195
|
throw new Error(errorData);
|
|
168
196
|
}
|
|
@@ -176,25 +204,29 @@ export class GoLogin {
|
|
|
176
204
|
}
|
|
177
205
|
|
|
178
206
|
if (profileResponse.statusCode !== 200) {
|
|
179
|
-
throw new Error(
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Gologin /browser/${id} response error ${profileResponse.statusCode} INVALID TOKEN OR PROFILE NOT FOUND`
|
|
209
|
+
);
|
|
180
210
|
}
|
|
181
211
|
|
|
182
212
|
if (profileResponse.statusCode === 401) {
|
|
183
|
-
throw new Error(
|
|
213
|
+
throw new Error("invalid token");
|
|
184
214
|
}
|
|
185
215
|
|
|
186
216
|
return JSON.parse(profileResponse.body);
|
|
187
217
|
}
|
|
188
218
|
|
|
189
219
|
async emptyProfile() {
|
|
190
|
-
return readFile(_resolve(__dirname,
|
|
220
|
+
return readFile(_resolve(__dirname, "gologin_zeroprofile.b64")).then(
|
|
221
|
+
(res) => res.toString()
|
|
222
|
+
);
|
|
191
223
|
}
|
|
192
224
|
|
|
193
225
|
async getProfileS3() {
|
|
194
226
|
const token = this.access_token;
|
|
195
|
-
debug(
|
|
227
|
+
debug("getProfileS3 token=", token, "profile=", this.profile_id);
|
|
196
228
|
const downloadURL = `${STORAGE_GATEWAY_BASE_URL}/download`;
|
|
197
|
-
debug(
|
|
229
|
+
debug("loading profile from public s3 bucket, url=", downloadURL);
|
|
198
230
|
|
|
199
231
|
const profileResponse = await fetch(downloadURL, {
|
|
200
232
|
headers: {
|
|
@@ -206,28 +238,30 @@ export class GoLogin {
|
|
|
206
238
|
const profileResponseBody = await profileResponse.arrayBuffer();
|
|
207
239
|
|
|
208
240
|
if (profileResponse.status !== 200) {
|
|
209
|
-
debug(
|
|
241
|
+
debug(
|
|
242
|
+
`Gologin S3 BUCKET ${downloadURL} response error ${profileResponse.statusCode} - use empty`
|
|
243
|
+
);
|
|
210
244
|
|
|
211
|
-
return
|
|
245
|
+
return "";
|
|
212
246
|
}
|
|
213
247
|
|
|
214
248
|
return Buffer.from(profileResponseBody);
|
|
215
249
|
}
|
|
216
250
|
|
|
217
251
|
async postFile(fileName, fileBuff) {
|
|
218
|
-
debug(
|
|
219
|
-
debug(
|
|
252
|
+
debug("POSTING FILE", fileBuff.length);
|
|
253
|
+
debug("Getting signed URL for S3");
|
|
220
254
|
const apiUrl = `${STORAGE_GATEWAY_BASE_URL}/upload`;
|
|
221
255
|
|
|
222
256
|
const bodyBufferBiteLength = Buffer.byteLength(fileBuff);
|
|
223
|
-
console.log(
|
|
257
|
+
console.log("BUFFER SIZE", bodyBufferBiteLength);
|
|
224
258
|
|
|
225
259
|
await requests.put(apiUrl, {
|
|
226
260
|
headers: {
|
|
227
261
|
Authorization: `Bearer ${this.access_token}`,
|
|
228
262
|
browserId: this.profile_id,
|
|
229
|
-
|
|
230
|
-
|
|
263
|
+
"Content-Type": "application/zip",
|
|
264
|
+
"Content-Length": bodyBufferBiteLength,
|
|
231
265
|
},
|
|
232
266
|
body: fileBuff,
|
|
233
267
|
maxBodyLength: Infinity,
|
|
@@ -238,51 +272,61 @@ export class GoLogin {
|
|
|
238
272
|
fullResponse: false,
|
|
239
273
|
});
|
|
240
274
|
|
|
241
|
-
console.log(
|
|
275
|
+
console.log("Profile has been uploaded to S3 successfully");
|
|
242
276
|
}
|
|
243
277
|
|
|
244
278
|
async emptyProfileFolder() {
|
|
245
|
-
debug(
|
|
279
|
+
debug("get emptyProfileFolder");
|
|
246
280
|
const currentDir = dirname(new URL(import.meta.url).pathname);
|
|
247
|
-
const zeroProfilePath = join(currentDir,
|
|
281
|
+
const zeroProfilePath = join(currentDir, "..", "zero_profile.zip");
|
|
248
282
|
const profile = await readFile(_resolve(zeroProfilePath));
|
|
249
|
-
debug(
|
|
283
|
+
debug("emptyProfileFolder LENGTH ::", profile.length);
|
|
250
284
|
|
|
251
285
|
return profile;
|
|
252
286
|
}
|
|
253
287
|
|
|
254
288
|
convertPreferences(preferences) {
|
|
255
|
-
if (get(preferences,
|
|
256
|
-
preferences.userAgent = get(preferences,
|
|
289
|
+
if (get(preferences, "navigator.userAgent")) {
|
|
290
|
+
preferences.userAgent = get(preferences, "navigator.userAgent");
|
|
257
291
|
}
|
|
258
292
|
|
|
259
|
-
if (get(preferences,
|
|
260
|
-
preferences.doNotTrack = get(preferences,
|
|
293
|
+
if (get(preferences, "navigator.doNotTrack")) {
|
|
294
|
+
preferences.doNotTrack = get(preferences, "navigator.doNotTrack");
|
|
261
295
|
}
|
|
262
296
|
|
|
263
|
-
if (get(preferences,
|
|
264
|
-
preferences.hardwareConcurrency = get(
|
|
297
|
+
if (get(preferences, "navigator.hardwareConcurrency")) {
|
|
298
|
+
preferences.hardwareConcurrency = get(
|
|
299
|
+
preferences,
|
|
300
|
+
"navigator.hardwareConcurrency"
|
|
301
|
+
);
|
|
265
302
|
}
|
|
266
303
|
|
|
267
|
-
if (get(preferences,
|
|
268
|
-
preferences.deviceMemory =
|
|
304
|
+
if (get(preferences, "navigator.deviceMemory")) {
|
|
305
|
+
preferences.deviceMemory =
|
|
306
|
+
get(preferences, "navigator.deviceMemory") * 1024;
|
|
269
307
|
}
|
|
270
308
|
|
|
271
|
-
if (get(preferences,
|
|
272
|
-
preferences.langHeader = get(preferences,
|
|
273
|
-
preferences.languages = get(preferences,
|
|
309
|
+
if (get(preferences, "navigator.language")) {
|
|
310
|
+
preferences.langHeader = get(preferences, "navigator.language");
|
|
311
|
+
preferences.languages = get(preferences, "navigator.language").replace(
|
|
312
|
+
/;|q=[\d\.]+/gim,
|
|
313
|
+
""
|
|
314
|
+
);
|
|
274
315
|
}
|
|
275
316
|
|
|
276
|
-
if (get(preferences,
|
|
277
|
-
preferences.navigator.max_touch_points = get(
|
|
317
|
+
if (get(preferences, "navigator.maxTouchPoints")) {
|
|
318
|
+
preferences.navigator.max_touch_points = get(
|
|
319
|
+
preferences,
|
|
320
|
+
"navigator.maxTouchPoints"
|
|
321
|
+
);
|
|
278
322
|
}
|
|
279
323
|
|
|
280
|
-
if (get(preferences,
|
|
281
|
-
preferences.is_m1 = get(preferences,
|
|
324
|
+
if (get(preferences, "isM1")) {
|
|
325
|
+
preferences.is_m1 = get(preferences, "isM1");
|
|
282
326
|
}
|
|
283
327
|
|
|
284
|
-
if (get(preferences,
|
|
285
|
-
const devicePixelRatio = get(preferences,
|
|
328
|
+
if (get(preferences, "os") == "android") {
|
|
329
|
+
const devicePixelRatio = get(preferences, "devicePixelRatio");
|
|
286
330
|
const deviceScaleFactorCeil = Math.ceil(devicePixelRatio || 3.5);
|
|
287
331
|
let deviceScaleFactor = devicePixelRatio;
|
|
288
332
|
if (deviceScaleFactorCeil === devicePixelRatio) {
|
|
@@ -306,8 +350,8 @@ export class GoLogin {
|
|
|
306
350
|
|
|
307
351
|
preferences.webRtc = {
|
|
308
352
|
...preferences.webRtc,
|
|
309
|
-
fill_based_on_ip: !!get(preferences,
|
|
310
|
-
local_ip_masking: !!get(preferences,
|
|
353
|
+
fill_based_on_ip: !!get(preferences, "webRTC.fillBasedOnIp"),
|
|
354
|
+
local_ip_masking: !!get(preferences, "webRTC.local_ip_masking"),
|
|
311
355
|
};
|
|
312
356
|
|
|
313
357
|
return preferences;
|
|
@@ -315,68 +359,68 @@ export class GoLogin {
|
|
|
315
359
|
|
|
316
360
|
async createBrowserExtension() {
|
|
317
361
|
const that = this;
|
|
318
|
-
debug(
|
|
362
|
+
debug("start createBrowserExtension");
|
|
319
363
|
await rimraf(this.orbitaExtensionPath(), () => null);
|
|
320
364
|
const extPath = this.orbitaExtensionPath();
|
|
321
|
-
debug(
|
|
322
|
-
const extension_source = _resolve(__dirname,
|
|
323
|
-
await decompress(extension_source, extPath,
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
},
|
|
328
|
-
)
|
|
365
|
+
debug("extension folder sanitized");
|
|
366
|
+
const extension_source = _resolve(__dirname, "gologin-browser-ext.zip");
|
|
367
|
+
await decompress(extension_source, extPath, {
|
|
368
|
+
plugins: [decompressUnzip()],
|
|
369
|
+
filter: (file) => !file.path.endsWith("/"),
|
|
370
|
+
})
|
|
329
371
|
.then(() => {
|
|
330
|
-
debug(
|
|
331
|
-
debug(
|
|
372
|
+
debug("extraction done");
|
|
373
|
+
debug("create uid.json");
|
|
332
374
|
|
|
333
|
-
return writeFile(
|
|
334
|
-
|
|
375
|
+
return writeFile(
|
|
376
|
+
join(extPath, "uid.json"),
|
|
377
|
+
JSON.stringify({ uid: that.profile_id }, null, 2)
|
|
378
|
+
).then(() => extPath);
|
|
335
379
|
})
|
|
336
380
|
.catch(async (e) => {
|
|
337
|
-
debug(
|
|
381
|
+
debug("orbita extension error", e);
|
|
338
382
|
});
|
|
339
383
|
|
|
340
|
-
debug(
|
|
384
|
+
debug("createBrowserExtension done");
|
|
341
385
|
}
|
|
342
386
|
|
|
343
387
|
extractProfile(path, zipfile) {
|
|
344
388
|
debug(`extactProfile ${zipfile}, ${path}`);
|
|
345
389
|
|
|
346
|
-
return decompress(zipfile, path,
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
},
|
|
351
|
-
);
|
|
390
|
+
return decompress(zipfile, path, {
|
|
391
|
+
plugins: [decompressUnzip()],
|
|
392
|
+
filter: (file) => !file.path.endsWith("/"),
|
|
393
|
+
});
|
|
352
394
|
}
|
|
353
395
|
|
|
354
396
|
async downloadProfileAndExtract(profile, local) {
|
|
355
397
|
let profile_folder;
|
|
356
398
|
const profilePath = join(this.tmpdir, `gologin_profile_${this.profile_id}`);
|
|
357
|
-
const profileZipExists = await access(this.profile_zip_path)
|
|
399
|
+
const profileZipExists = await access(this.profile_zip_path)
|
|
400
|
+
.then(() => true)
|
|
401
|
+
.catch(() => false);
|
|
358
402
|
|
|
359
403
|
if (!(local && profileZipExists)) {
|
|
360
404
|
try {
|
|
361
405
|
profile_folder = await this.getProfileS3();
|
|
362
406
|
} catch (e) {
|
|
363
|
-
debug(
|
|
407
|
+
debug("Cannot get profile - using empty", e);
|
|
364
408
|
}
|
|
365
409
|
|
|
366
|
-
debug(
|
|
410
|
+
debug("FILE READY", this.profile_zip_path);
|
|
367
411
|
|
|
368
412
|
await writeFile(this.profile_zip_path, profile_folder);
|
|
369
413
|
|
|
370
|
-
debug(
|
|
414
|
+
debug("PROFILE LENGTH", profile_folder.length);
|
|
371
415
|
} else {
|
|
372
|
-
debug(
|
|
416
|
+
debug("PROFILE LOCAL HAVING", this.profile_zip_path);
|
|
373
417
|
}
|
|
374
418
|
|
|
375
|
-
debug(
|
|
419
|
+
debug("Cleaning up..", profilePath);
|
|
376
420
|
|
|
377
421
|
try {
|
|
378
422
|
await this.extractProfile(profilePath, this.profile_zip_path);
|
|
379
|
-
debug(
|
|
423
|
+
debug("extraction done");
|
|
380
424
|
} catch (e) {
|
|
381
425
|
console.trace(e);
|
|
382
426
|
profile_folder = await this.emptyProfileFolder();
|
|
@@ -384,28 +428,36 @@ export class GoLogin {
|
|
|
384
428
|
await this.extractProfile(profilePath, this.profile_zip_path);
|
|
385
429
|
}
|
|
386
430
|
|
|
387
|
-
const singletonLockPath = join(profilePath,
|
|
388
|
-
const singletonLockExists = await access(singletonLockPath)
|
|
431
|
+
const singletonLockPath = join(profilePath, "SingletonLock");
|
|
432
|
+
const singletonLockExists = await access(singletonLockPath)
|
|
433
|
+
.then(() => true)
|
|
434
|
+
.catch(() => false);
|
|
389
435
|
if (singletonLockExists) {
|
|
390
|
-
debug(
|
|
436
|
+
debug("removing SingletonLock");
|
|
391
437
|
await unlink(singletonLockPath);
|
|
392
|
-
debug(
|
|
438
|
+
debug("SingletonLock removed");
|
|
393
439
|
}
|
|
394
440
|
}
|
|
395
441
|
|
|
396
442
|
async createZeroProfile(createCookiesTableQuery) {
|
|
397
443
|
const profilePath = join(this.tmpdir, `gologin_profile_${this.profile_id}`);
|
|
398
|
-
const defaultFilePath = _resolve(profilePath,
|
|
399
|
-
const preferencesFilePath = _resolve(defaultFilePath,
|
|
400
|
-
const bookmarksFilePath = _resolve(defaultFilePath,
|
|
401
|
-
const cookiesFilePath = _resolve(defaultFilePath,
|
|
402
|
-
const cookiesFileSecondPath = _resolve(defaultFilePath,
|
|
444
|
+
const defaultFilePath = _resolve(profilePath, "Default");
|
|
445
|
+
const preferencesFilePath = _resolve(defaultFilePath, "Preferences");
|
|
446
|
+
const bookmarksFilePath = _resolve(defaultFilePath, "Bookmarks");
|
|
447
|
+
const cookiesFilePath = _resolve(defaultFilePath, "Network", "Cookies");
|
|
448
|
+
const cookiesFileSecondPath = _resolve(defaultFilePath, "Cookies");
|
|
403
449
|
|
|
404
|
-
await mkdir(_resolve(defaultFilePath,
|
|
450
|
+
await mkdir(_resolve(defaultFilePath, "Network"), {
|
|
451
|
+
recursive: true,
|
|
452
|
+
}).catch(console.log);
|
|
405
453
|
|
|
406
454
|
await Promise.all([
|
|
407
|
-
writeFile(preferencesFilePath, JSON.stringify(zeroProfilePreferences), {
|
|
408
|
-
|
|
455
|
+
writeFile(preferencesFilePath, JSON.stringify(zeroProfilePreferences), {
|
|
456
|
+
mode: 0o666,
|
|
457
|
+
}),
|
|
458
|
+
writeFile(bookmarksFilePath, JSON.stringify(zeroProfileBookmarks), {
|
|
459
|
+
mode: 0o666,
|
|
460
|
+
}),
|
|
409
461
|
createDBFile({
|
|
410
462
|
cookiesFilePath,
|
|
411
463
|
cookiesFileSecondPath,
|
|
@@ -417,25 +469,21 @@ export class GoLogin {
|
|
|
417
469
|
async createStartup(local = false) {
|
|
418
470
|
const profilePath = join(this.tmpdir, `gologin_profile_${this.profile_id}`);
|
|
419
471
|
await rimraf(profilePath, () => null);
|
|
420
|
-
debug(
|
|
472
|
+
debug("-", profilePath, "dropped");
|
|
421
473
|
const profile = await this.getProfile();
|
|
422
474
|
const { navigator = {}, fonts, os: profileOs } = profile;
|
|
423
475
|
this.fontsMasking = fonts?.enableMasking;
|
|
424
476
|
this.profileOs = profileOs;
|
|
425
477
|
this.differentOs =
|
|
426
|
-
profileOs !==
|
|
427
|
-
|
|
428
|
-
OS_PLATFORM ===
|
|
429
|
-
OS_PLATFORM ===
|
|
430
|
-
);
|
|
478
|
+
profileOs !== "android" &&
|
|
479
|
+
((OS_PLATFORM === "win32" && profileOs !== "win") ||
|
|
480
|
+
(OS_PLATFORM === "darwin" && profileOs !== "mac") ||
|
|
481
|
+
(OS_PLATFORM === "linux" && profileOs !== "lin"));
|
|
431
482
|
|
|
432
|
-
const {
|
|
433
|
-
resolution = '1920x1080',
|
|
434
|
-
language = 'en-US,en;q=0.9',
|
|
435
|
-
} = navigator;
|
|
483
|
+
const { resolution = "1920x1080", language = "en-US,en;q=0.9" } = navigator;
|
|
436
484
|
|
|
437
485
|
this.language = language;
|
|
438
|
-
const [screenWidth, screenHeight] = resolution.split(
|
|
486
|
+
const [screenWidth, screenHeight] = resolution.split("x");
|
|
439
487
|
this.resolution = {
|
|
440
488
|
width: parseInt(screenWidth, 10),
|
|
441
489
|
height: parseInt(screenHeight, 10),
|
|
@@ -448,21 +496,27 @@ export class GoLogin {
|
|
|
448
496
|
await this.downloadProfileAndExtract(profile, local);
|
|
449
497
|
}
|
|
450
498
|
|
|
451
|
-
const pref_file_name = join(profilePath,
|
|
452
|
-
debug(
|
|
499
|
+
const pref_file_name = join(profilePath, "Default", "Preferences");
|
|
500
|
+
debug("reading", pref_file_name);
|
|
453
501
|
|
|
454
|
-
const prefFileExists = await access(pref_file_name)
|
|
502
|
+
const prefFileExists = await access(pref_file_name)
|
|
503
|
+
.then(() => true)
|
|
504
|
+
.catch(() => false);
|
|
455
505
|
if (!prefFileExists) {
|
|
456
|
-
debug(
|
|
457
|
-
|
|
506
|
+
debug(
|
|
507
|
+
"Preferences file not exists waiting",
|
|
508
|
+
pref_file_name,
|
|
509
|
+
". Using empty profile"
|
|
510
|
+
);
|
|
511
|
+
await writeFile(pref_file_name, "{}");
|
|
458
512
|
}
|
|
459
513
|
|
|
460
514
|
const preferences_raw = await readFile(pref_file_name);
|
|
461
515
|
const preferences = JSON.parse(preferences_raw.toString());
|
|
462
|
-
let proxy = get(profile,
|
|
463
|
-
const name = get(profile,
|
|
464
|
-
const chromeExtensions = get(profile,
|
|
465
|
-
const userChromeExtensions = get(profile,
|
|
516
|
+
let proxy = get(profile, "proxy");
|
|
517
|
+
const name = get(profile, "name");
|
|
518
|
+
const chromeExtensions = get(profile, "chromeExtensions") || [];
|
|
519
|
+
const userChromeExtensions = get(profile, "userChromeExtensions") || [];
|
|
466
520
|
const allExtensions = [...chromeExtensions, ...userChromeExtensions];
|
|
467
521
|
|
|
468
522
|
if (allExtensions.length) {
|
|
@@ -470,7 +524,7 @@ export class GoLogin {
|
|
|
470
524
|
ExtensionsManagerInst.apiUrl = API_URL;
|
|
471
525
|
await ExtensionsManagerInst.init()
|
|
472
526
|
.then(() => ExtensionsManagerInst.updateExtensions())
|
|
473
|
-
.catch(() => {
|
|
527
|
+
.catch(() => {});
|
|
474
528
|
ExtensionsManagerInst.accessToken = this.access_token;
|
|
475
529
|
|
|
476
530
|
await ExtensionsManagerInst.getExtensionsPolicies();
|
|
@@ -479,16 +533,19 @@ export class GoLogin {
|
|
|
479
533
|
if (ExtensionsManagerInst.useLocalExtStorage) {
|
|
480
534
|
const promises = [
|
|
481
535
|
ExtensionsManagerInst.checkChromeExtensions(allExtensions)
|
|
482
|
-
.then(res => ({ profileExtensionsCheckRes: res }))
|
|
536
|
+
.then((res) => ({ profileExtensionsCheckRes: res }))
|
|
483
537
|
.catch((e) => {
|
|
484
|
-
console.log(
|
|
538
|
+
console.log("checkChromeExtensions error: ", e);
|
|
485
539
|
|
|
486
540
|
return { profileExtensionsCheckRes: [] };
|
|
487
541
|
}),
|
|
488
|
-
ExtensionsManagerInst.checkLocalUserChromeExtensions(
|
|
489
|
-
|
|
542
|
+
ExtensionsManagerInst.checkLocalUserChromeExtensions(
|
|
543
|
+
userChromeExtensions,
|
|
544
|
+
this.profile_id
|
|
545
|
+
)
|
|
546
|
+
.then((res) => ({ profileUserExtensionsCheckRes: res }))
|
|
490
547
|
.catch((error) => {
|
|
491
|
-
console.log(
|
|
548
|
+
console.log("checkUserChromeExtensions error: ", error);
|
|
492
549
|
|
|
493
550
|
return null;
|
|
494
551
|
}),
|
|
@@ -496,22 +553,43 @@ export class GoLogin {
|
|
|
496
553
|
|
|
497
554
|
const extensionsResult = await Promise.all(promises);
|
|
498
555
|
|
|
499
|
-
const profileExtensionPathRes =
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
556
|
+
const profileExtensionPathRes =
|
|
557
|
+
extensionsResult.find((el) => "profileExtensionsCheckRes" in el) ||
|
|
558
|
+
{};
|
|
559
|
+
const profileUserExtensionPathRes = extensionsResult.find(
|
|
560
|
+
(el) => "profileUserExtensionsCheckRes" in el
|
|
561
|
+
);
|
|
562
|
+
profileExtensionsCheckRes = (
|
|
563
|
+
profileExtensionPathRes?.profileExtensionsCheckRes || []
|
|
564
|
+
).concat(
|
|
565
|
+
profileUserExtensionPathRes?.profileUserExtensionsCheckRes || []
|
|
566
|
+
);
|
|
503
567
|
}
|
|
504
568
|
|
|
505
569
|
let extSettings;
|
|
506
570
|
if (ExtensionsManagerInst.useLocalExtStorage) {
|
|
507
|
-
extSettings = await setExtPathsAndRemoveDeleted(
|
|
571
|
+
extSettings = await setExtPathsAndRemoveDeleted(
|
|
572
|
+
preferences,
|
|
573
|
+
profileExtensionsCheckRes,
|
|
574
|
+
this.profile_id
|
|
575
|
+
);
|
|
508
576
|
} else {
|
|
509
|
-
const originalExtensionsFolder = join(
|
|
510
|
-
|
|
577
|
+
const originalExtensionsFolder = join(
|
|
578
|
+
profilePath,
|
|
579
|
+
"Default",
|
|
580
|
+
"Extensions"
|
|
581
|
+
);
|
|
582
|
+
extSettings = await setOriginalExtPaths(
|
|
583
|
+
preferences,
|
|
584
|
+
originalExtensionsFolder
|
|
585
|
+
);
|
|
511
586
|
}
|
|
512
587
|
|
|
513
588
|
this.extensionPathsToInstall =
|
|
514
|
-
ExtensionsManagerInst.getExtensionsToInstall(
|
|
589
|
+
ExtensionsManagerInst.getExtensionsToInstall(
|
|
590
|
+
extSettings,
|
|
591
|
+
profileExtensionsCheckRes
|
|
592
|
+
);
|
|
515
593
|
|
|
516
594
|
if (extSettings) {
|
|
517
595
|
const currentExtSettings = preferences.extensions || {};
|
|
@@ -520,26 +598,26 @@ export class GoLogin {
|
|
|
520
598
|
}
|
|
521
599
|
}
|
|
522
600
|
|
|
523
|
-
if (proxy.mode ===
|
|
524
|
-
const autoProxyServer = get(profile,
|
|
525
|
-
const splittedAutoProxyServer = autoProxyServer.split(
|
|
526
|
-
const splittedProxyAddress = splittedAutoProxyServer[1].split(
|
|
601
|
+
if (proxy.mode === "gologin" || proxy.mode === "tor") {
|
|
602
|
+
const autoProxyServer = get(profile, "autoProxyServer");
|
|
603
|
+
const splittedAutoProxyServer = autoProxyServer.split("://");
|
|
604
|
+
const splittedProxyAddress = splittedAutoProxyServer[1].split(":");
|
|
527
605
|
const port = splittedProxyAddress[1];
|
|
528
606
|
|
|
529
607
|
proxy = {
|
|
530
|
-
|
|
531
|
-
|
|
608
|
+
mode: splittedAutoProxyServer[0],
|
|
609
|
+
host: splittedProxyAddress[0],
|
|
532
610
|
port,
|
|
533
|
-
|
|
534
|
-
|
|
611
|
+
username: get(profile, "autoProxyUsername"),
|
|
612
|
+
password: get(profile, "autoProxyPassword"),
|
|
535
613
|
};
|
|
536
614
|
|
|
537
|
-
profile.proxy.username = get(profile,
|
|
538
|
-
profile.proxy.password = get(profile,
|
|
615
|
+
profile.proxy.username = get(profile, "autoProxyUsername");
|
|
616
|
+
profile.proxy.password = get(profile, "autoProxyPassword");
|
|
539
617
|
}
|
|
540
618
|
|
|
541
|
-
if (proxy.mode ===
|
|
542
|
-
proxy.mode =
|
|
619
|
+
if (proxy.mode === "geolocation") {
|
|
620
|
+
proxy.mode = "http";
|
|
543
621
|
}
|
|
544
622
|
|
|
545
623
|
if (proxy.mode === PROXY_NONE) {
|
|
@@ -549,7 +627,7 @@ export class GoLogin {
|
|
|
549
627
|
this.proxy = proxy;
|
|
550
628
|
|
|
551
629
|
await this.getTimeZone(proxy).catch((e) => {
|
|
552
|
-
console.error(
|
|
630
|
+
console.error("Proxy Error. Check it and try again.");
|
|
553
631
|
throw new Error(`Proxy Error. ${e.message}`);
|
|
554
632
|
});
|
|
555
633
|
|
|
@@ -563,23 +641,31 @@ export class GoLogin {
|
|
|
563
641
|
accuracy,
|
|
564
642
|
};
|
|
565
643
|
|
|
566
|
-
profile.geoLocation = this.getGeolocationParams(
|
|
644
|
+
profile.geoLocation = this.getGeolocationParams(
|
|
645
|
+
profileGeolocation,
|
|
646
|
+
tzGeoLocation
|
|
647
|
+
);
|
|
567
648
|
profile.name = name;
|
|
568
|
-
profile.name_base64 = Buffer.from(name).toString(
|
|
649
|
+
profile.name_base64 = Buffer.from(name).toString("base64");
|
|
569
650
|
profile.profile_id = this.profile_id;
|
|
570
651
|
|
|
571
652
|
profile.webRtc = {
|
|
572
|
-
mode:
|
|
573
|
-
|
|
574
|
-
|
|
653
|
+
mode:
|
|
654
|
+
get(profile, "webRTC.mode") === "alerted"
|
|
655
|
+
? "public"
|
|
656
|
+
: get(profile, "webRTC.mode"),
|
|
657
|
+
publicIP: get(profile, "webRTC.fillBasedOnIp")
|
|
658
|
+
? this._tz.ip
|
|
659
|
+
: get(profile, "webRTC.publicIp"),
|
|
660
|
+
localIps: get(profile, "webRTC.localIps", []),
|
|
575
661
|
};
|
|
576
662
|
|
|
577
|
-
debug(
|
|
578
|
-
debug(
|
|
579
|
-
debug(
|
|
663
|
+
debug("profile.webRtc=", profile.webRtc);
|
|
664
|
+
debug("profile.timezone=", profile.timezone);
|
|
665
|
+
debug("profile.mediaDevices=", profile.mediaDevices);
|
|
580
666
|
|
|
581
667
|
const audioContext = profile.audioContext || {};
|
|
582
|
-
const { mode: audioCtxMode =
|
|
668
|
+
const { mode: audioCtxMode = "off", noise: audioCtxNoise } = audioContext;
|
|
583
669
|
if (profile.timezone.fillBasedOnIp === false) {
|
|
584
670
|
profile.timezone = { id: profile.timezone.timezone };
|
|
585
671
|
} else {
|
|
@@ -591,14 +677,14 @@ export class GoLogin {
|
|
|
591
677
|
profile.canvasMode = profile.canvas.mode;
|
|
592
678
|
profile.canvasNoise = profile.canvas.noise;
|
|
593
679
|
profile.audioContext = {
|
|
594
|
-
enable: audioCtxMode !==
|
|
680
|
+
enable: audioCtxMode !== "off",
|
|
595
681
|
noiseValue: audioCtxNoise,
|
|
596
682
|
};
|
|
597
683
|
profile.webgl = {
|
|
598
684
|
metadata: {
|
|
599
|
-
vendor: get(profile,
|
|
600
|
-
renderer: get(profile,
|
|
601
|
-
mode: get(profile,
|
|
685
|
+
vendor: get(profile, "webGLMetadata.vendor"),
|
|
686
|
+
renderer: get(profile, "webGLMetadata.renderer"),
|
|
687
|
+
mode: get(profile, "webGLMetadata.mode") === "mask",
|
|
602
688
|
},
|
|
603
689
|
};
|
|
604
690
|
|
|
@@ -608,11 +694,17 @@ export class GoLogin {
|
|
|
608
694
|
|
|
609
695
|
const gologin = this.convertPreferences(profile);
|
|
610
696
|
|
|
611
|
-
debug(
|
|
697
|
+
debug(
|
|
698
|
+
`Writing profile for screenWidth ${profilePath}`,
|
|
699
|
+
JSON.stringify(gologin)
|
|
700
|
+
);
|
|
612
701
|
gologin.screenWidth = this.resolution.width;
|
|
613
702
|
gologin.screenHeight = this.resolution.height;
|
|
614
|
-
debug(
|
|
615
|
-
this.cookiesFilePath = await getCookiesFilePath(
|
|
703
|
+
debug("writeCookiesFromServer", this.writeCookiesFromServer);
|
|
704
|
+
this.cookiesFilePath = await getCookiesFilePath(
|
|
705
|
+
this.profile_id,
|
|
706
|
+
this.tmpdir
|
|
707
|
+
);
|
|
616
708
|
|
|
617
709
|
if (this.writeCookiesFromServer) {
|
|
618
710
|
await this.writeCookiesToFile(profile.cookies?.cookies);
|
|
@@ -631,7 +723,7 @@ export class GoLogin {
|
|
|
631
723
|
}
|
|
632
724
|
}
|
|
633
725
|
|
|
634
|
-
const languages = this.language.replace(/;|q=[\d\.]+/
|
|
726
|
+
const languages = this.language.replace(/;|q=[\d\.]+/gim, "");
|
|
635
727
|
|
|
636
728
|
if (preferences.gologin == null) {
|
|
637
729
|
preferences.gologin = {};
|
|
@@ -640,24 +732,41 @@ export class GoLogin {
|
|
|
640
732
|
preferences.gologin.langHeader = gologin.navigator.language;
|
|
641
733
|
preferences.gologin.language = languages;
|
|
642
734
|
|
|
643
|
-
const [splittedLangs] = gologin.navigator.language.split(
|
|
644
|
-
const [browserLang] = splittedLangs.split(
|
|
735
|
+
const [splittedLangs] = gologin.navigator.language.split(";");
|
|
736
|
+
const [browserLang] = splittedLangs.split(",");
|
|
645
737
|
gologin.browserLang = browserLang;
|
|
646
738
|
|
|
647
|
-
const isMAC = OS_PLATFORM ===
|
|
739
|
+
const isMAC = OS_PLATFORM === "darwin";
|
|
648
740
|
const checkAutoLangResult = checkAutoLang(gologin, this._tz);
|
|
649
|
-
this.browserLang = isMAC ?
|
|
650
|
-
|
|
651
|
-
await writeFile(
|
|
652
|
-
|
|
653
|
-
|
|
741
|
+
this.browserLang = isMAC ? "en-US" : checkAutoLangResult;
|
|
742
|
+
|
|
743
|
+
await writeFile(
|
|
744
|
+
join(profilePath, "Default", "Preferences"),
|
|
745
|
+
JSON.stringify(
|
|
746
|
+
Object.assign(preferences, {
|
|
747
|
+
gologin,
|
|
748
|
+
})
|
|
749
|
+
)
|
|
750
|
+
);
|
|
654
751
|
|
|
655
|
-
const bookmarksParsedData = await getCurrentProfileBookmarks(
|
|
752
|
+
const bookmarksParsedData = await getCurrentProfileBookmarks(
|
|
753
|
+
this.bookmarksFilePath
|
|
754
|
+
);
|
|
656
755
|
const bookmarksFromDb = profile.bookmarks?.bookmark_bar;
|
|
657
|
-
bookmarksParsedData.roots = bookmarksFromDb
|
|
658
|
-
|
|
756
|
+
bookmarksParsedData.roots = bookmarksFromDb
|
|
757
|
+
? profile.bookmarks
|
|
758
|
+
: bookmarksParsedData.roots;
|
|
759
|
+
await writeFile(
|
|
760
|
+
this.bookmarksFilePath,
|
|
761
|
+
JSON.stringify(bookmarksParsedData)
|
|
762
|
+
);
|
|
659
763
|
|
|
660
|
-
debug(
|
|
764
|
+
debug(
|
|
765
|
+
"Profile ready. Path: ",
|
|
766
|
+
profilePath,
|
|
767
|
+
"PROXY",
|
|
768
|
+
JSON.stringify(get(preferences, "gologin.proxy"))
|
|
769
|
+
);
|
|
661
770
|
|
|
662
771
|
return profilePath;
|
|
663
772
|
}
|
|
@@ -665,21 +774,21 @@ export class GoLogin {
|
|
|
665
774
|
async commitProfile() {
|
|
666
775
|
const dataBuff = await this.getProfileDataToUpdate();
|
|
667
776
|
|
|
668
|
-
debug(
|
|
777
|
+
debug("begin updating", dataBuff.length);
|
|
669
778
|
if (!dataBuff.length) {
|
|
670
|
-
debug(
|
|
779
|
+
debug("WARN: profile zip data empty - SKIPPING PROFILE COMMIT");
|
|
671
780
|
|
|
672
781
|
return;
|
|
673
782
|
}
|
|
674
783
|
|
|
675
784
|
try {
|
|
676
|
-
debug(
|
|
677
|
-
await this.postFile(
|
|
785
|
+
debug("Patching profile");
|
|
786
|
+
await this.postFile("profile", dataBuff);
|
|
678
787
|
} catch (e) {
|
|
679
|
-
debug(
|
|
788
|
+
debug("CANNOT COMMIT PROFILE", e);
|
|
680
789
|
}
|
|
681
790
|
|
|
682
|
-
debug(
|
|
791
|
+
debug("COMMIT COMPLETED");
|
|
683
792
|
}
|
|
684
793
|
|
|
685
794
|
profilePath() {
|
|
@@ -698,10 +807,10 @@ export class GoLogin {
|
|
|
698
807
|
}
|
|
699
808
|
|
|
700
809
|
async checkPortAvailable(port) {
|
|
701
|
-
debug(
|
|
810
|
+
debug("CHECKING PORT AVAILABLE", port);
|
|
702
811
|
|
|
703
812
|
try {
|
|
704
|
-
const portAvailable = await isPortReachable(port, { host:
|
|
813
|
+
const portAvailable = await isPortReachable(port, { host: "localhost" });
|
|
705
814
|
if (portAvailable) {
|
|
706
815
|
debug(`PORT ${port} IS OPEN`);
|
|
707
816
|
|
|
@@ -728,10 +837,10 @@ export class GoLogin {
|
|
|
728
837
|
}
|
|
729
838
|
|
|
730
839
|
async getTimeZone(proxy) {
|
|
731
|
-
debug(
|
|
840
|
+
debug("getting timeZone proxy=", proxy);
|
|
732
841
|
|
|
733
842
|
if (this.timezone) {
|
|
734
|
-
debug(
|
|
843
|
+
debug("getTimeZone from options", this.timezone);
|
|
735
844
|
this._tz = this.timezone;
|
|
736
845
|
|
|
737
846
|
return this._tz.timezone;
|
|
@@ -739,50 +848,64 @@ export class GoLogin {
|
|
|
739
848
|
|
|
740
849
|
let data = null;
|
|
741
850
|
if (proxy && proxy.mode !== PROXY_NONE) {
|
|
742
|
-
if (proxy.mode.includes(
|
|
851
|
+
if (proxy.mode.includes("socks")) {
|
|
743
852
|
for (let i = 0; i < 5; i++) {
|
|
744
853
|
try {
|
|
745
|
-
debug(
|
|
854
|
+
debug("getting timeZone socks try", i + 1);
|
|
746
855
|
|
|
747
856
|
return this.getTimezoneWithSocks(proxy);
|
|
748
857
|
} catch (e) {
|
|
749
858
|
console.log(e.message);
|
|
750
859
|
}
|
|
751
860
|
}
|
|
752
|
-
throw new Error(
|
|
861
|
+
throw new Error("Socks proxy connection timed out");
|
|
753
862
|
}
|
|
754
863
|
|
|
755
864
|
const proxyUrl = `${proxy.mode}://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`;
|
|
756
865
|
debug(`getTimeZone start ${TIMEZONE_URL}`, proxyUrl);
|
|
757
|
-
data = await requests.get(TIMEZONE_URL, {
|
|
866
|
+
data = await requests.get(TIMEZONE_URL, {
|
|
867
|
+
proxy: proxyUrl,
|
|
868
|
+
timeout: 20 * 1000,
|
|
869
|
+
maxAttempts: 3,
|
|
870
|
+
});
|
|
758
871
|
} else {
|
|
759
|
-
data =
|
|
872
|
+
data = {
|
|
873
|
+
body: JSON.stringify({
|
|
874
|
+
country: "ID",
|
|
875
|
+
stateProv: "Jakarta",
|
|
876
|
+
city: "Jakarta",
|
|
877
|
+
timezone: "Asia/Jakarta",
|
|
878
|
+
ll: ["-6.21140", "106.84460"],
|
|
879
|
+
languages: "id",
|
|
880
|
+
accuracy: 100,
|
|
881
|
+
}),
|
|
882
|
+
};
|
|
760
883
|
}
|
|
761
884
|
|
|
762
|
-
debug(
|
|
885
|
+
debug("getTimeZone finish", data.body);
|
|
763
886
|
this._tz = JSON.parse(data.body);
|
|
764
887
|
|
|
765
888
|
return this._tz.timezone;
|
|
766
889
|
}
|
|
767
890
|
|
|
768
891
|
async getTimezoneWithSocks(params) {
|
|
769
|
-
const { host, port, username =
|
|
892
|
+
const { host, port, username = "", password = "" } = params;
|
|
770
893
|
let body;
|
|
771
894
|
|
|
772
|
-
let proxy =
|
|
895
|
+
let proxy = "socks://";
|
|
773
896
|
if (username) {
|
|
774
|
-
const resultPassword = password ?
|
|
897
|
+
const resultPassword = password ? ":" + password + "@" : "@";
|
|
775
898
|
proxy += username + resultPassword;
|
|
776
899
|
}
|
|
777
900
|
|
|
778
|
-
proxy += host +
|
|
901
|
+
proxy += host + ":" + port;
|
|
779
902
|
const agent = new SocksProxyAgent(proxy);
|
|
780
903
|
const checkData = await new Promise((resolve, reject) => {
|
|
781
904
|
_get(TIMEZONE_URL, { agent, timeout: 10000 }, (res) => {
|
|
782
|
-
let resultResponse =
|
|
783
|
-
res.on(
|
|
905
|
+
let resultResponse = "";
|
|
906
|
+
res.on("data", (data) => (resultResponse += data));
|
|
784
907
|
|
|
785
|
-
res.on(
|
|
908
|
+
res.on("end", () => {
|
|
786
909
|
let parsedData;
|
|
787
910
|
try {
|
|
788
911
|
parsedData = JSON.parse(resultResponse);
|
|
@@ -795,15 +918,15 @@ export class GoLogin {
|
|
|
795
918
|
body: parsedData,
|
|
796
919
|
});
|
|
797
920
|
});
|
|
798
|
-
}).on(
|
|
921
|
+
}).on("error", (err) => reject(err));
|
|
799
922
|
});
|
|
800
923
|
|
|
801
924
|
body = checkData.body || {};
|
|
802
|
-
if (!body.ip && checkData.statusCode.toString().startsWith(
|
|
925
|
+
if (!body.ip && checkData.statusCode.toString().startsWith("4")) {
|
|
803
926
|
throw checkData;
|
|
804
927
|
}
|
|
805
928
|
|
|
806
|
-
debug(
|
|
929
|
+
debug("getTimeZone finish", body.body);
|
|
807
930
|
this._tz = body;
|
|
808
931
|
|
|
809
932
|
return this._tz.timezone;
|
|
@@ -821,13 +944,19 @@ export class GoLogin {
|
|
|
821
944
|
});
|
|
822
945
|
|
|
823
946
|
const tz = await this.getTimeZone(this.proxy).catch((e) => {
|
|
824
|
-
console.error(
|
|
947
|
+
console.error("Proxy Error. Check it and try again.");
|
|
825
948
|
throw e;
|
|
826
949
|
});
|
|
827
950
|
|
|
828
951
|
env.TZ = tz;
|
|
829
952
|
|
|
830
|
-
let params = [
|
|
953
|
+
let params = [
|
|
954
|
+
`--proxy-server=${proxy}`,
|
|
955
|
+
`--user-data-dir=${profile_path}`,
|
|
956
|
+
"--password-store=basic",
|
|
957
|
+
`--tz=${tz}`,
|
|
958
|
+
"--lang=en",
|
|
959
|
+
];
|
|
831
960
|
if (Array.isArray(this.extra_params) && this.extra_params.length) {
|
|
832
961
|
params = params.concat(this.extra_params);
|
|
833
962
|
}
|
|
@@ -848,7 +977,7 @@ export class GoLogin {
|
|
|
848
977
|
const profile_path = this.profilePath();
|
|
849
978
|
|
|
850
979
|
let { proxy } = this;
|
|
851
|
-
let proxy_host =
|
|
980
|
+
let proxy_host = "";
|
|
852
981
|
if (proxy) {
|
|
853
982
|
proxy_host = this.proxy.host;
|
|
854
983
|
proxy = `${proxy.mode}://${proxy.host}:${proxy.port}`;
|
|
@@ -856,7 +985,8 @@ export class GoLogin {
|
|
|
856
985
|
|
|
857
986
|
this.port = remote_debugging_port;
|
|
858
987
|
|
|
859
|
-
const ORBITA_BROWSER =
|
|
988
|
+
const ORBITA_BROWSER =
|
|
989
|
+
this.executablePath || this.browserChecker.getOrbitaPath;
|
|
860
990
|
debug(`ORBITA_BROWSER=${ORBITA_BROWSER}`);
|
|
861
991
|
const env = {};
|
|
862
992
|
Object.keys(process.env).forEach((key) => {
|
|
@@ -864,25 +994,40 @@ export class GoLogin {
|
|
|
864
994
|
});
|
|
865
995
|
|
|
866
996
|
const tz = await this.getTimeZone(this.proxy).catch((e) => {
|
|
867
|
-
console.error(
|
|
997
|
+
console.error("Proxy Error. Check it and try again.");
|
|
868
998
|
throw e;
|
|
869
999
|
});
|
|
870
1000
|
|
|
871
1001
|
env.TZ = tz;
|
|
872
1002
|
|
|
873
1003
|
if (this.vnc_port) {
|
|
874
|
-
const script_path = _resolve(__dirname,
|
|
875
|
-
debug(
|
|
1004
|
+
const script_path = _resolve(__dirname, "./run.sh");
|
|
1005
|
+
debug(
|
|
1006
|
+
"RUNNING",
|
|
1007
|
+
script_path,
|
|
1008
|
+
ORBITA_BROWSER,
|
|
1009
|
+
remote_debugging_port,
|
|
1010
|
+
proxy,
|
|
1011
|
+
profile_path,
|
|
1012
|
+
this.vnc_port
|
|
1013
|
+
);
|
|
876
1014
|
execFile(
|
|
877
1015
|
script_path,
|
|
878
|
-
[
|
|
879
|
-
|
|
1016
|
+
[
|
|
1017
|
+
ORBITA_BROWSER,
|
|
1018
|
+
remote_debugging_port,
|
|
1019
|
+
proxy,
|
|
1020
|
+
profile_path,
|
|
1021
|
+
this.vnc_port,
|
|
1022
|
+
tz,
|
|
1023
|
+
],
|
|
1024
|
+
{ env }
|
|
880
1025
|
);
|
|
881
1026
|
} else {
|
|
882
1027
|
let params = [
|
|
883
1028
|
`--remote-debugging-port=${remote_debugging_port}`,
|
|
884
1029
|
`--user-data-dir=${profile_path}`,
|
|
885
|
-
|
|
1030
|
+
"--password-store=basic",
|
|
886
1031
|
`--tz=${tz}`,
|
|
887
1032
|
`--lang=${this.browserLang}`,
|
|
888
1033
|
];
|
|
@@ -890,28 +1035,33 @@ export class GoLogin {
|
|
|
890
1035
|
if (this.extensionPathsToInstall.length) {
|
|
891
1036
|
if (Array.isArray(this.extra_params) && this.extra_params.length) {
|
|
892
1037
|
this.extra_params.forEach((param, index) => {
|
|
893
|
-
if (!param.includes(
|
|
1038
|
+
if (!param.includes("--load-extension=")) {
|
|
894
1039
|
return;
|
|
895
1040
|
}
|
|
896
1041
|
|
|
897
|
-
const [_, extPathsString] = param.split(
|
|
898
|
-
const extPathsArray = extPathsString.split(
|
|
899
|
-
this.extensionPathsToInstall = [
|
|
1042
|
+
const [_, extPathsString] = param.split("=");
|
|
1043
|
+
const extPathsArray = extPathsString.split(",");
|
|
1044
|
+
this.extensionPathsToInstall = [
|
|
1045
|
+
...this.extensionPathsToInstall,
|
|
1046
|
+
...extPathsArray,
|
|
1047
|
+
];
|
|
900
1048
|
this.extra_params.splice(index, 1);
|
|
901
1049
|
});
|
|
902
1050
|
}
|
|
903
1051
|
|
|
904
|
-
params.push(
|
|
1052
|
+
params.push(
|
|
1053
|
+
`--load-extension=${this.extensionPathsToInstall.join(",")}`
|
|
1054
|
+
);
|
|
905
1055
|
}
|
|
906
1056
|
|
|
907
1057
|
if (this.fontsMasking) {
|
|
908
|
-
let arg =
|
|
1058
|
+
let arg = "--font-masking-mode=2";
|
|
909
1059
|
if (this.differentOs) {
|
|
910
|
-
arg =
|
|
1060
|
+
arg = "--font-masking-mode=3";
|
|
911
1061
|
}
|
|
912
1062
|
|
|
913
|
-
if (this.profileOs ===
|
|
914
|
-
arg =
|
|
1063
|
+
if (this.profileOs === "android" || this.isEmptyFonts) {
|
|
1064
|
+
arg = "--font-masking-mode=1";
|
|
915
1065
|
}
|
|
916
1066
|
|
|
917
1067
|
params.push(arg);
|
|
@@ -928,7 +1078,7 @@ export class GoLogin {
|
|
|
928
1078
|
}
|
|
929
1079
|
|
|
930
1080
|
if (!this.isFirstSession && this.restoreLastSession) {
|
|
931
|
-
params.push(
|
|
1081
|
+
params.push("--restore-last-session");
|
|
932
1082
|
}
|
|
933
1083
|
|
|
934
1084
|
params.push(...new Set(customArgs));
|
|
@@ -937,21 +1087,24 @@ export class GoLogin {
|
|
|
937
1087
|
const child = execFile(ORBITA_BROWSER, params, { env });
|
|
938
1088
|
this.processSpawned = child;
|
|
939
1089
|
// const child = spawn(ORBITA_BROWSER, params, { env, shell: true });
|
|
940
|
-
child.stdout.on(
|
|
941
|
-
debug(
|
|
1090
|
+
child.stdout.on("data", (data) => debug(data.toString()));
|
|
1091
|
+
debug("SPAWN CMD", ORBITA_BROWSER, params.join(" "));
|
|
942
1092
|
}
|
|
943
1093
|
|
|
944
1094
|
if (this.waitWebsocket) {
|
|
945
|
-
debug(
|
|
946
|
-
const data = await requests.get(
|
|
1095
|
+
debug("GETTING WS URL FROM BROWSER");
|
|
1096
|
+
const data = await requests.get(
|
|
1097
|
+
`http://127.0.0.1:${remote_debugging_port}/json/version`,
|
|
1098
|
+
{ json: true }
|
|
1099
|
+
);
|
|
947
1100
|
|
|
948
|
-
debug(
|
|
1101
|
+
debug("WS IS", get(data, "body.webSocketDebuggerUrl", ""));
|
|
949
1102
|
this.is_active = true;
|
|
950
1103
|
|
|
951
|
-
return get(data,
|
|
1104
|
+
return get(data, "body.webSocketDebuggerUrl", "");
|
|
952
1105
|
}
|
|
953
1106
|
|
|
954
|
-
return
|
|
1107
|
+
return "";
|
|
955
1108
|
}
|
|
956
1109
|
|
|
957
1110
|
async createStartupAndSpawnBrowser() {
|
|
@@ -961,8 +1114,14 @@ export class GoLogin {
|
|
|
961
1114
|
}
|
|
962
1115
|
|
|
963
1116
|
async clearProfileFiles() {
|
|
964
|
-
await rimraf(
|
|
965
|
-
|
|
1117
|
+
await rimraf(
|
|
1118
|
+
join(this.tmpdir, `gologin_profile_${this.profile_id}`),
|
|
1119
|
+
() => null
|
|
1120
|
+
);
|
|
1121
|
+
await rimraf(
|
|
1122
|
+
join(this.tmpdir, `gologin_${this.profile_id}_upload.zip`),
|
|
1123
|
+
() => null
|
|
1124
|
+
);
|
|
966
1125
|
}
|
|
967
1126
|
|
|
968
1127
|
async stopAndCommit(options, local = false) {
|
|
@@ -970,7 +1129,8 @@ export class GoLogin {
|
|
|
970
1129
|
return true;
|
|
971
1130
|
}
|
|
972
1131
|
|
|
973
|
-
const is_posting =
|
|
1132
|
+
const is_posting =
|
|
1133
|
+
options.posting ||
|
|
974
1134
|
options.postings || // backward compability
|
|
975
1135
|
false;
|
|
976
1136
|
|
|
@@ -992,7 +1152,10 @@ export class GoLogin {
|
|
|
992
1152
|
await this.clearProfileFiles();
|
|
993
1153
|
|
|
994
1154
|
if (!local) {
|
|
995
|
-
await rimraf(
|
|
1155
|
+
await rimraf(
|
|
1156
|
+
join(this.tmpdir, `gologin_${this.profile_id}.zip`),
|
|
1157
|
+
() => null
|
|
1158
|
+
);
|
|
996
1159
|
}
|
|
997
1160
|
|
|
998
1161
|
debug(`PROFILE ${this.profile_id} STOPPED AND CLEAR`);
|
|
@@ -1002,20 +1165,14 @@ export class GoLogin {
|
|
|
1002
1165
|
|
|
1003
1166
|
async stopBrowser() {
|
|
1004
1167
|
if (!this.port) {
|
|
1005
|
-
throw new Error(
|
|
1168
|
+
throw new Error("Empty GoLogin port");
|
|
1006
1169
|
}
|
|
1007
1170
|
|
|
1008
|
-
const ls = await spawn(
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
`-n tcp ${this.port}`,
|
|
1012
|
-
],
|
|
1013
|
-
{
|
|
1014
|
-
shell: true,
|
|
1015
|
-
},
|
|
1016
|
-
);
|
|
1171
|
+
const ls = await spawn("fuser", ["-k TERM", `-n tcp ${this.port}`], {
|
|
1172
|
+
shell: true,
|
|
1173
|
+
});
|
|
1017
1174
|
|
|
1018
|
-
debug(
|
|
1175
|
+
debug("browser killed");
|
|
1019
1176
|
}
|
|
1020
1177
|
|
|
1021
1178
|
killBrowser() {
|
|
@@ -1025,7 +1182,7 @@ export class GoLogin {
|
|
|
1025
1182
|
|
|
1026
1183
|
try {
|
|
1027
1184
|
this.processSpawned.kill();
|
|
1028
|
-
debug(
|
|
1185
|
+
debug("browser killed");
|
|
1029
1186
|
} catch (error) {
|
|
1030
1187
|
console.error(error);
|
|
1031
1188
|
}
|
|
@@ -1064,33 +1221,37 @@ export class GoLogin {
|
|
|
1064
1221
|
|
|
1065
1222
|
const that = this;
|
|
1066
1223
|
|
|
1067
|
-
await Promise.all(
|
|
1068
|
-
|
|
1224
|
+
await Promise.all(
|
|
1225
|
+
remove_dirs.map((d) => {
|
|
1226
|
+
const path_to_remove = `${that.profilePath()}${d}`;
|
|
1069
1227
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1228
|
+
return new Promise((resolve) => {
|
|
1229
|
+
debug("DROPPING", path_to_remove);
|
|
1230
|
+
rimraf(path_to_remove, { maxBusyTries: 100 }, (e) => {
|
|
1231
|
+
// debug('DROPPING RESULT', e);
|
|
1232
|
+
resolve();
|
|
1233
|
+
});
|
|
1075
1234
|
});
|
|
1076
|
-
})
|
|
1077
|
-
|
|
1235
|
+
})
|
|
1236
|
+
);
|
|
1078
1237
|
}
|
|
1079
1238
|
|
|
1080
1239
|
async getProfileDataToUpdate() {
|
|
1081
1240
|
const zipPath = join(this.tmpdir, `gologin_${this.profile_id}_upload.zip`);
|
|
1082
|
-
const zipExists = await access(zipPath)
|
|
1241
|
+
const zipExists = await access(zipPath)
|
|
1242
|
+
.then(() => true)
|
|
1243
|
+
.catch(() => false);
|
|
1083
1244
|
if (zipExists) {
|
|
1084
1245
|
await unlink(zipPath);
|
|
1085
1246
|
}
|
|
1086
1247
|
|
|
1087
1248
|
await this.sanitizeProfile();
|
|
1088
|
-
debug(
|
|
1249
|
+
debug("profile sanitized");
|
|
1089
1250
|
|
|
1090
1251
|
const profilePath = this.profilePath();
|
|
1091
1252
|
const fileBuff = await archiveProfile(profilePath);
|
|
1092
1253
|
|
|
1093
|
-
debug(
|
|
1254
|
+
debug("PROFILE ZIP CREATED", profilePath, zipPath);
|
|
1094
1255
|
|
|
1095
1256
|
return fileBuff;
|
|
1096
1257
|
}
|
|
@@ -1098,25 +1259,23 @@ export class GoLogin {
|
|
|
1098
1259
|
async profileExists() {
|
|
1099
1260
|
const profileResponse = await requests.post(`${API_URL}/browser`, {
|
|
1100
1261
|
headers: {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
},
|
|
1104
|
-
json: {
|
|
1105
|
-
|
|
1262
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1263
|
+
"User-Agent": "gologin-api",
|
|
1106
1264
|
},
|
|
1265
|
+
json: {},
|
|
1107
1266
|
});
|
|
1108
1267
|
|
|
1109
1268
|
if (profileResponse.statusCode !== 200) {
|
|
1110
1269
|
return false;
|
|
1111
1270
|
}
|
|
1112
1271
|
|
|
1113
|
-
debug(
|
|
1272
|
+
debug("profile is", profileResponse.body);
|
|
1114
1273
|
|
|
1115
1274
|
return true;
|
|
1116
1275
|
}
|
|
1117
1276
|
|
|
1118
1277
|
async getRandomFingerprint(options) {
|
|
1119
|
-
let os =
|
|
1278
|
+
let os = "lin";
|
|
1120
1279
|
|
|
1121
1280
|
if (options.os) {
|
|
1122
1281
|
os = options.os;
|
|
@@ -1124,13 +1283,13 @@ export class GoLogin {
|
|
|
1124
1283
|
|
|
1125
1284
|
let url = `${API_URL}/browser/fingerprint?os=${os}`;
|
|
1126
1285
|
if (options.isM1) {
|
|
1127
|
-
url +=
|
|
1286
|
+
url += "&isM1=true";
|
|
1128
1287
|
}
|
|
1129
1288
|
|
|
1130
1289
|
const fingerprint = await requests.get(url, {
|
|
1131
1290
|
headers: {
|
|
1132
|
-
|
|
1133
|
-
|
|
1291
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1292
|
+
"User-Agent": "gologin-api",
|
|
1134
1293
|
},
|
|
1135
1294
|
});
|
|
1136
1295
|
|
|
@@ -1138,17 +1297,17 @@ export class GoLogin {
|
|
|
1138
1297
|
}
|
|
1139
1298
|
|
|
1140
1299
|
async create(options) {
|
|
1141
|
-
debug(
|
|
1300
|
+
debug("createProfile", options);
|
|
1142
1301
|
|
|
1143
1302
|
const fingerprint = await this.getRandomFingerprint(options);
|
|
1144
|
-
debug(
|
|
1303
|
+
debug("fingerprint=", fingerprint);
|
|
1145
1304
|
|
|
1146
1305
|
if (fingerprint.statusCode === 500) {
|
|
1147
|
-
throw new Error(
|
|
1306
|
+
throw new Error("no valid random fingerprint check os param");
|
|
1148
1307
|
}
|
|
1149
1308
|
|
|
1150
1309
|
if (fingerprint.statusCode === 401) {
|
|
1151
|
-
throw new Error(
|
|
1310
|
+
throw new Error("invalid token");
|
|
1152
1311
|
}
|
|
1153
1312
|
|
|
1154
1313
|
const { navigator, fonts, webGLMetadata, webRTC } = fingerprint;
|
|
@@ -1158,28 +1317,28 @@ export class GoLogin {
|
|
|
1158
1317
|
}
|
|
1159
1318
|
|
|
1160
1319
|
navigator.deviceMemory = deviceMemory * 1024;
|
|
1161
|
-
webGLMetadata.mode = webGLMetadata.mode ===
|
|
1320
|
+
webGLMetadata.mode = webGLMetadata.mode === "noise" ? "mask" : "off";
|
|
1162
1321
|
|
|
1163
1322
|
const json = {
|
|
1164
1323
|
...fingerprint,
|
|
1165
1324
|
navigator,
|
|
1166
1325
|
webGLMetadata,
|
|
1167
|
-
browserType:
|
|
1168
|
-
name:
|
|
1169
|
-
notes:
|
|
1326
|
+
browserType: "chrome",
|
|
1327
|
+
name: "default_name",
|
|
1328
|
+
notes: "auto generated",
|
|
1170
1329
|
fonts: {
|
|
1171
1330
|
families: fonts,
|
|
1172
1331
|
},
|
|
1173
1332
|
webRTC: {
|
|
1174
1333
|
...webRTC,
|
|
1175
|
-
mode:
|
|
1334
|
+
mode: "alerted",
|
|
1176
1335
|
},
|
|
1177
1336
|
};
|
|
1178
1337
|
|
|
1179
1338
|
const user_agent = options.navigator?.userAgent;
|
|
1180
1339
|
const orig_user_agent = json.navigator.userAgent;
|
|
1181
1340
|
Object.keys(options).forEach((key) => {
|
|
1182
|
-
if (typeof json[key] ===
|
|
1341
|
+
if (typeof json[key] === "object") {
|
|
1183
1342
|
json[key] = { ...json[key], ...options[key] };
|
|
1184
1343
|
|
|
1185
1344
|
return;
|
|
@@ -1188,24 +1347,30 @@ export class GoLogin {
|
|
|
1188
1347
|
json[key] = options[key];
|
|
1189
1348
|
});
|
|
1190
1349
|
|
|
1191
|
-
if (user_agent ===
|
|
1350
|
+
if (user_agent === "random") {
|
|
1192
1351
|
json.navigator.userAgent = orig_user_agent;
|
|
1193
1352
|
}
|
|
1194
1353
|
|
|
1195
1354
|
const response = await requests.post(`${API_URL}/browser`, {
|
|
1196
1355
|
headers: {
|
|
1197
|
-
|
|
1198
|
-
|
|
1356
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1357
|
+
"User-Agent": "gologin-api",
|
|
1199
1358
|
},
|
|
1200
1359
|
json,
|
|
1201
1360
|
});
|
|
1202
1361
|
|
|
1203
1362
|
if (response.statusCode === 400) {
|
|
1204
|
-
throw new Error(
|
|
1363
|
+
throw new Error(
|
|
1364
|
+
`gologin failed account creation with status code, ${
|
|
1365
|
+
response.statusCode
|
|
1366
|
+
} DATA ${JSON.stringify(response.body.message)}`
|
|
1367
|
+
);
|
|
1205
1368
|
}
|
|
1206
1369
|
|
|
1207
1370
|
if (response.statusCode === 500) {
|
|
1208
|
-
throw new Error(
|
|
1371
|
+
throw new Error(
|
|
1372
|
+
`gologin failed account creation with status code, ${response.statusCode}`
|
|
1373
|
+
);
|
|
1209
1374
|
}
|
|
1210
1375
|
|
|
1211
1376
|
debug(JSON.stringify(response.body));
|
|
@@ -1214,21 +1379,27 @@ export class GoLogin {
|
|
|
1214
1379
|
}
|
|
1215
1380
|
|
|
1216
1381
|
async createCustom(options) {
|
|
1217
|
-
debug(
|
|
1382
|
+
debug("createCustomProfile", options);
|
|
1218
1383
|
const response = await requests.post(`${API_URL}/browser/custom`, {
|
|
1219
1384
|
headers: {
|
|
1220
|
-
|
|
1221
|
-
|
|
1385
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1386
|
+
"User-Agent": "gologin-api",
|
|
1222
1387
|
},
|
|
1223
1388
|
json: options,
|
|
1224
1389
|
});
|
|
1225
1390
|
|
|
1226
1391
|
if (response.statusCode === 400) {
|
|
1227
|
-
throw new Error(
|
|
1392
|
+
throw new Error(
|
|
1393
|
+
`gologin failed account creation with status code, ${
|
|
1394
|
+
response.statusCode
|
|
1395
|
+
} DATA ${JSON.stringify(response.body.message)}`
|
|
1396
|
+
);
|
|
1228
1397
|
}
|
|
1229
1398
|
|
|
1230
1399
|
if (response.statusCode === 500) {
|
|
1231
|
-
throw new Error(
|
|
1400
|
+
throw new Error(
|
|
1401
|
+
`gologin failed account creation with status code, ${response.statusCode}`
|
|
1402
|
+
);
|
|
1232
1403
|
}
|
|
1233
1404
|
|
|
1234
1405
|
debug(JSON.stringify(response));
|
|
@@ -1236,31 +1407,32 @@ export class GoLogin {
|
|
|
1236
1407
|
return response.body.id;
|
|
1237
1408
|
}
|
|
1238
1409
|
|
|
1239
|
-
async quickCreateProfile(name =
|
|
1410
|
+
async quickCreateProfile(name = "") {
|
|
1240
1411
|
const osInfo = await getOsAdvanced();
|
|
1241
1412
|
const { os, osSpec } = osInfo;
|
|
1242
|
-
const resultName = name ||
|
|
1243
|
-
|
|
1244
|
-
return requests
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1413
|
+
const resultName = name || "api-generated";
|
|
1414
|
+
|
|
1415
|
+
return requests
|
|
1416
|
+
.post(`${API_URL}/browser/quick`, {
|
|
1417
|
+
headers: {
|
|
1418
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1419
|
+
"User-Agent": "gologin-api",
|
|
1420
|
+
},
|
|
1421
|
+
json: {
|
|
1422
|
+
os,
|
|
1423
|
+
osSpec,
|
|
1424
|
+
name: resultName,
|
|
1425
|
+
},
|
|
1426
|
+
})
|
|
1427
|
+
.then((res) => res.body);
|
|
1256
1428
|
}
|
|
1257
1429
|
|
|
1258
1430
|
async delete(pid) {
|
|
1259
1431
|
const profile_id = pid || this.profile_id;
|
|
1260
1432
|
await requests.delete(`${API_URL}/browser/${profile_id}`, {
|
|
1261
1433
|
headers: {
|
|
1262
|
-
|
|
1263
|
-
|
|
1434
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1435
|
+
"User-Agent": "gologin-api",
|
|
1264
1436
|
},
|
|
1265
1437
|
});
|
|
1266
1438
|
}
|
|
@@ -1275,20 +1447,22 @@ export class GoLogin {
|
|
|
1275
1447
|
});
|
|
1276
1448
|
}
|
|
1277
1449
|
|
|
1278
|
-
Object.keys(options)
|
|
1279
|
-
|
|
1280
|
-
|
|
1450
|
+
Object.keys(options)
|
|
1451
|
+
.filter((el) => el !== "navigator")
|
|
1452
|
+
.forEach((el) => {
|
|
1453
|
+
profile[el] = options[el];
|
|
1454
|
+
});
|
|
1281
1455
|
|
|
1282
|
-
debug(
|
|
1456
|
+
debug("update profile", profile);
|
|
1283
1457
|
const response = await requests.put(`${API_URL}/browser/${options.id}`, {
|
|
1284
1458
|
json: profile,
|
|
1285
1459
|
headers: {
|
|
1286
|
-
|
|
1287
|
-
|
|
1460
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1461
|
+
"User-Agent": "gologin-api",
|
|
1288
1462
|
},
|
|
1289
1463
|
});
|
|
1290
1464
|
|
|
1291
|
-
debug(
|
|
1465
|
+
debug("response", JSON.stringify(response.body));
|
|
1292
1466
|
|
|
1293
1467
|
return response.body;
|
|
1294
1468
|
}
|
|
@@ -1320,9 +1494,13 @@ export class GoLogin {
|
|
|
1320
1494
|
}
|
|
1321
1495
|
|
|
1322
1496
|
async postCookies(profileId, cookies) {
|
|
1323
|
-
const formattedCookies = cookies.map(cookie => {
|
|
1324
|
-
if (
|
|
1325
|
-
|
|
1497
|
+
const formattedCookies = cookies.map((cookie) => {
|
|
1498
|
+
if (
|
|
1499
|
+
!["no_restriction", "lax", "strict", "unspecified"].includes(
|
|
1500
|
+
cookie.sameSite
|
|
1501
|
+
)
|
|
1502
|
+
) {
|
|
1503
|
+
cookie.sameSite = "unspecified";
|
|
1326
1504
|
}
|
|
1327
1505
|
|
|
1328
1506
|
return cookie;
|
|
@@ -1339,7 +1517,11 @@ export class GoLogin {
|
|
|
1339
1517
|
return response.body;
|
|
1340
1518
|
}
|
|
1341
1519
|
|
|
1342
|
-
return {
|
|
1520
|
+
return {
|
|
1521
|
+
status: "failure",
|
|
1522
|
+
status_code: response.statusCode,
|
|
1523
|
+
body: response.body,
|
|
1524
|
+
};
|
|
1343
1525
|
}
|
|
1344
1526
|
|
|
1345
1527
|
async getCookies(profileId) {
|
|
@@ -1353,12 +1535,12 @@ export class GoLogin {
|
|
|
1353
1535
|
}
|
|
1354
1536
|
|
|
1355
1537
|
getCookiePath(defaultFilePath) {
|
|
1356
|
-
let primary = join(defaultFilePath,
|
|
1357
|
-
let secondary = join(defaultFilePath,
|
|
1538
|
+
let primary = join(defaultFilePath, "Cookies");
|
|
1539
|
+
let secondary = join(defaultFilePath, "Network", "Cookies");
|
|
1358
1540
|
|
|
1359
1541
|
if (!existsSync(primary)) {
|
|
1360
|
-
primary = join(defaultFilePath,
|
|
1361
|
-
secondary = join(defaultFilePath,
|
|
1542
|
+
primary = join(defaultFilePath, "Network", "Cookies");
|
|
1543
|
+
secondary = join(defaultFilePath, "Cookies");
|
|
1362
1544
|
}
|
|
1363
1545
|
|
|
1364
1546
|
return { primary, secondary };
|
|
@@ -1373,15 +1555,21 @@ export class GoLogin {
|
|
|
1373
1555
|
return;
|
|
1374
1556
|
}
|
|
1375
1557
|
|
|
1376
|
-
const resultCookies = cookies.map((el) => ({
|
|
1558
|
+
const resultCookies = cookies.map((el) => ({
|
|
1559
|
+
...el,
|
|
1560
|
+
value: Buffer.from(el.value),
|
|
1561
|
+
}));
|
|
1377
1562
|
let db;
|
|
1378
1563
|
const profilePath = join(this.tmpdir, `gologin_profile_${this.profile_id}`);
|
|
1379
1564
|
|
|
1380
|
-
const defaultFilePath = _resolve(profilePath,
|
|
1565
|
+
const defaultFilePath = _resolve(profilePath, "Default");
|
|
1381
1566
|
const cookiesPaths = this.getCookiePath(defaultFilePath);
|
|
1382
1567
|
try {
|
|
1383
1568
|
db = await getDB(cookiesPaths.primary, false);
|
|
1384
|
-
const cookiesToInsert = await getUniqueCookies(
|
|
1569
|
+
const cookiesToInsert = await getUniqueCookies(
|
|
1570
|
+
resultCookies,
|
|
1571
|
+
cookiesPaths.primary
|
|
1572
|
+
);
|
|
1385
1573
|
if (cookiesToInsert.length) {
|
|
1386
1574
|
const chunckInsertValues = getChunckedInsertValues(cookiesToInsert);
|
|
1387
1575
|
for (const [query, queryParams] of chunckInsertValues) {
|
|
@@ -1393,8 +1581,10 @@ export class GoLogin {
|
|
|
1393
1581
|
} catch (error) {
|
|
1394
1582
|
console.log(error.message);
|
|
1395
1583
|
} finally {
|
|
1396
|
-
db && await db.close();
|
|
1397
|
-
await copyFile(cookiesPaths.primary, cookiesPaths.secondary).catch(
|
|
1584
|
+
db && (await db.close());
|
|
1585
|
+
await copyFile(cookiesPaths.primary, cookiesPaths.secondary).catch(
|
|
1586
|
+
console.log
|
|
1587
|
+
);
|
|
1398
1588
|
}
|
|
1399
1589
|
}
|
|
1400
1590
|
|
|
@@ -1408,9 +1598,15 @@ export class GoLogin {
|
|
|
1408
1598
|
}
|
|
1409
1599
|
|
|
1410
1600
|
async saveBookmarksToDb() {
|
|
1411
|
-
const bookmarksData = await getCurrentProfileBookmarks(
|
|
1601
|
+
const bookmarksData = await getCurrentProfileBookmarks(
|
|
1602
|
+
this.bookmarksFilePath
|
|
1603
|
+
);
|
|
1412
1604
|
const bookmarks = bookmarksData.roots || {};
|
|
1413
|
-
await updateProfileBookmarks(
|
|
1605
|
+
await updateProfileBookmarks(
|
|
1606
|
+
[this.profile_id],
|
|
1607
|
+
this.access_token,
|
|
1608
|
+
bookmarks
|
|
1609
|
+
);
|
|
1414
1610
|
}
|
|
1415
1611
|
|
|
1416
1612
|
async start() {
|
|
@@ -1418,11 +1614,16 @@ export class GoLogin {
|
|
|
1418
1614
|
await this.checkBrowser();
|
|
1419
1615
|
}
|
|
1420
1616
|
|
|
1421
|
-
const ORBITA_BROWSER =
|
|
1617
|
+
const ORBITA_BROWSER =
|
|
1618
|
+
this.executablePath || this.browserChecker.getOrbitaPath;
|
|
1422
1619
|
|
|
1423
|
-
const orbitaBrowserExists = await access(ORBITA_BROWSER)
|
|
1620
|
+
const orbitaBrowserExists = await access(ORBITA_BROWSER)
|
|
1621
|
+
.then(() => true)
|
|
1622
|
+
.catch(() => false);
|
|
1424
1623
|
if (!orbitaBrowserExists) {
|
|
1425
|
-
throw new Error(
|
|
1624
|
+
throw new Error(
|
|
1625
|
+
`Orbita browser is not exists on path ${ORBITA_BROWSER}, check executablePath param`
|
|
1626
|
+
);
|
|
1426
1627
|
}
|
|
1427
1628
|
|
|
1428
1629
|
await this.createStartup();
|
|
@@ -1430,7 +1631,7 @@ export class GoLogin {
|
|
|
1430
1631
|
const wsUrl = await this.spawnBrowser();
|
|
1431
1632
|
this.setActive(true);
|
|
1432
1633
|
|
|
1433
|
-
return { status:
|
|
1634
|
+
return { status: "success", wsUrl };
|
|
1434
1635
|
}
|
|
1435
1636
|
|
|
1436
1637
|
async startLocal() {
|
|
@@ -1439,11 +1640,11 @@ export class GoLogin {
|
|
|
1439
1640
|
const wsUrl = await this.spawnBrowser();
|
|
1440
1641
|
this.setActive(true);
|
|
1441
1642
|
|
|
1442
|
-
return { status:
|
|
1643
|
+
return { status: "success", wsUrl };
|
|
1443
1644
|
}
|
|
1444
1645
|
|
|
1445
1646
|
async stop() {
|
|
1446
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
1647
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1447
1648
|
|
|
1448
1649
|
await this.stopAndCommit({ posting: true }, false);
|
|
1449
1650
|
}
|
|
@@ -1456,10 +1657,10 @@ export class GoLogin {
|
|
|
1456
1657
|
async waitDebuggingUrl(delay_ms, try_count = 0, remoteOrbitaUrl) {
|
|
1457
1658
|
await delay(delay_ms);
|
|
1458
1659
|
const url = `${remoteOrbitaUrl}/json/version`;
|
|
1459
|
-
console.log(
|
|
1660
|
+
console.log("try_count=", try_count, "url=", url);
|
|
1460
1661
|
const response = await requests.get(url);
|
|
1461
|
-
let wsUrl =
|
|
1462
|
-
console.log(
|
|
1662
|
+
let wsUrl = "";
|
|
1663
|
+
console.log("response", response.body);
|
|
1463
1664
|
|
|
1464
1665
|
if (!response.body) {
|
|
1465
1666
|
return wsUrl;
|
|
@@ -1473,23 +1674,36 @@ export class GoLogin {
|
|
|
1473
1674
|
return this.waitDebuggingUrl(delay_ms, try_count + 1, remoteOrbitaUrl);
|
|
1474
1675
|
}
|
|
1475
1676
|
|
|
1476
|
-
return {
|
|
1677
|
+
return {
|
|
1678
|
+
status: "failure",
|
|
1679
|
+
wsUrl,
|
|
1680
|
+
message: "Check proxy settings",
|
|
1681
|
+
profile_id: this.profile_id,
|
|
1682
|
+
};
|
|
1477
1683
|
}
|
|
1478
1684
|
|
|
1479
|
-
const remoteOrbitaUrlWithoutProtocol = remoteOrbitaUrl.replace(
|
|
1480
|
-
|
|
1685
|
+
const remoteOrbitaUrlWithoutProtocol = remoteOrbitaUrl.replace(
|
|
1686
|
+
"https://",
|
|
1687
|
+
""
|
|
1688
|
+
);
|
|
1689
|
+
wsUrl = wsUrl
|
|
1690
|
+
.replace("ws://", "wss://")
|
|
1691
|
+
.replace("127.0.0.1", remoteOrbitaUrlWithoutProtocol);
|
|
1481
1692
|
|
|
1482
1693
|
return wsUrl;
|
|
1483
1694
|
}
|
|
1484
1695
|
|
|
1485
1696
|
async stopRemote() {
|
|
1486
1697
|
debug(`stopRemote ${this.profile_id}`);
|
|
1487
|
-
const profileResponse = await requests.delete(
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1698
|
+
const profileResponse = await requests.delete(
|
|
1699
|
+
`${API_URL}/browser/${this.profile_id}/web`,
|
|
1700
|
+
{
|
|
1701
|
+
headers: {
|
|
1702
|
+
Authorization: `Bearer ${this.access_token}`,
|
|
1703
|
+
"User-Agent": "gologin-api",
|
|
1704
|
+
},
|
|
1705
|
+
}
|
|
1706
|
+
);
|
|
1493
1707
|
|
|
1494
1708
|
console.log(`stopRemote ${profileResponse.body}`);
|
|
1495
1709
|
if (profileResponse.body) {
|
|
@@ -1499,16 +1713,24 @@ export class GoLogin {
|
|
|
1499
1713
|
|
|
1500
1714
|
getAvailableFonts() {
|
|
1501
1715
|
return fontsCollection
|
|
1502
|
-
.filter(elem => elem.fileNames)
|
|
1503
|
-
.map(elem => elem.name);
|
|
1716
|
+
.filter((elem) => elem.fileNames)
|
|
1717
|
+
.map((elem) => elem.name);
|
|
1504
1718
|
}
|
|
1505
1719
|
|
|
1506
1720
|
async changeProfileResolution(resolution) {
|
|
1507
|
-
return updateProfileResolution(
|
|
1721
|
+
return updateProfileResolution(
|
|
1722
|
+
this.profile_id,
|
|
1723
|
+
this.access_token,
|
|
1724
|
+
resolution
|
|
1725
|
+
);
|
|
1508
1726
|
}
|
|
1509
1727
|
|
|
1510
1728
|
async changeProfileUserAgent(userAgent) {
|
|
1511
|
-
return updateProfileUserAgent(
|
|
1729
|
+
return updateProfileUserAgent(
|
|
1730
|
+
this.profile_id,
|
|
1731
|
+
this.access_token,
|
|
1732
|
+
userAgent
|
|
1733
|
+
);
|
|
1512
1734
|
}
|
|
1513
1735
|
|
|
1514
1736
|
async changeProfileProxy(proxyData) {
|