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