gologin-commonjs 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/babel.config.json +17 -0
  2. package/dist/README.md +163 -0
  3. package/dist/example.js +35 -0
  4. package/dist/examples/example-amazon-cloud-browser.js +52 -0
  5. package/dist/examples/example-amazon-headless.js +56 -0
  6. package/dist/examples/example-amazon.js +53 -0
  7. package/dist/examples/example-create-custom-profile.js +42 -0
  8. package/dist/examples/example-create-profile.js +43 -0
  9. package/dist/examples/example-custom-args.js +34 -0
  10. package/dist/examples/example-fast-profile-settings.js +59 -0
  11. package/dist/examples/example-gmail.js +82 -0
  12. package/dist/examples/example-iphey.js +19 -0
  13. package/dist/examples/example-local-profile.js +28 -0
  14. package/dist/examples/example-login-walmart.js +38 -0
  15. package/dist/examples/example-startremote.js +29 -0
  16. package/dist/examples/example-stopremote.js +22 -0
  17. package/dist/examples/example-timezone.js +51 -0
  18. package/dist/fonts.js +3339 -0
  19. package/dist/fonts_config +104 -0
  20. package/dist/gologin-browser-ext.zip +0 -0
  21. package/dist/gologin_zeroprofile.b64 +1 -0
  22. package/dist/index.d.ts +61 -0
  23. package/dist/profile_export_example.csv +2 -0
  24. package/dist/run.sh +1 -0
  25. package/dist/src/bookmarks/utils.js +23 -0
  26. package/dist/src/browser/browser-api.js +106 -0
  27. package/dist/src/browser/browser-checker.js +336 -0
  28. package/dist/src/browser/browser-user-data-manager.js +306 -0
  29. package/dist/src/cookies/cookies-manager.js +164 -0
  30. package/dist/src/extensions/extensions-extractor.js +50 -0
  31. package/dist/src/extensions/extensions-manager.js +301 -0
  32. package/dist/src/extensions/user-extensions-manager.js +246 -0
  33. package/dist/src/gologin-api.js +103 -0
  34. package/dist/src/gologin.js +1319 -0
  35. package/dist/src/profile/profile-archiver.js +68 -0
  36. package/dist/src/profile/profile-directories-to-remove.js +71 -0
  37. package/dist/src/utils/browser.js +59 -0
  38. package/dist/src/utils/common.js +60 -0
  39. package/dist/src/utils/constants.js +7 -0
  40. package/dist/src/utils/utils.js +53 -0
  41. package/dist/test.html +1 -0
  42. package/dist/zero_profile.zip +0 -0
  43. package/gologin/.eslintrc.json +290 -0
  44. package/gologin/.sentry-native/a65389b2-9a7d-41ed-7de5-95c4570f0d3d.run.lock +0 -0
  45. package/gologin/README.md +163 -0
  46. package/gologin/example.js +36 -0
  47. package/gologin/examples/example-amazon-cloud-browser.js +44 -0
  48. package/gologin/examples/example-amazon-headless.js +50 -0
  49. package/gologin/examples/example-amazon.js +47 -0
  50. package/gologin/examples/example-create-custom-profile.js +39 -0
  51. package/gologin/examples/example-create-profile.js +40 -0
  52. package/gologin/examples/example-custom-args.js +34 -0
  53. package/gologin/examples/example-fast-profile-settings.js +69 -0
  54. package/gologin/examples/example-gmail.js +67 -0
  55. package/gologin/examples/example-iphey.js +17 -0
  56. package/gologin/examples/example-local-profile.js +26 -0
  57. package/gologin/examples/example-login-walmart.js +35 -0
  58. package/gologin/examples/example-startremote.js +25 -0
  59. package/gologin/examples/example-stopremote.js +20 -0
  60. package/gologin/examples/example-timezone.js +44 -0
  61. package/gologin/fonts.js +3339 -0
  62. package/gologin/fonts_config +104 -0
  63. package/gologin/gologin-browser-ext.zip +0 -0
  64. package/gologin/gologin_zeroprofile.b64 +1 -0
  65. package/gologin/index.d.ts +61 -0
  66. package/gologin/package.json +49 -0
  67. package/gologin/profile_export_example.csv +2 -0
  68. package/gologin/run.sh +1 -0
  69. package/gologin/src/bookmarks/utils.js +16 -0
  70. package/gologin/src/browser/browser-api.js +95 -0
  71. package/gologin/src/browser/browser-checker.js +392 -0
  72. package/gologin/src/browser/browser-user-data-manager.js +335 -0
  73. package/gologin/src/cookies/cookies-manager.js +189 -0
  74. package/gologin/src/extensions/extensions-extractor.js +56 -0
  75. package/gologin/src/extensions/extensions-manager.js +384 -0
  76. package/gologin/src/extensions/user-extensions-manager.js +295 -0
  77. package/gologin/src/gologin-api.js +110 -0
  78. package/gologin/src/gologin.js +1553 -0
  79. package/gologin/src/profile/profile-archiver.js +86 -0
  80. package/gologin/src/profile/profile-directories-to-remove.js +75 -0
  81. package/gologin/src/utils/browser.js +62 -0
  82. package/gologin/src/utils/common.js +76 -0
  83. package/gologin/src/utils/constants.js +1 -0
  84. package/gologin/src/utils/utils.js +49 -0
  85. package/gologin/test.html +1 -0
  86. package/gologin/zero_profile.zip +0 -0
  87. package/package.json +46 -0
  88. package/tes.js +35 -0
@@ -0,0 +1,1319 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.GoLogin = void 0;
7
+ Object.defineProperty(exports, "GologinApi", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _gologinApi.GologinApi;
11
+ }
12
+ });
13
+ exports.default = void 0;
14
+ Object.defineProperty(exports, "exitAll", {
15
+ enumerable: true,
16
+ get: function () {
17
+ return _gologinApi.exitAll;
18
+ }
19
+ });
20
+ var _child_process = require("child_process");
21
+ var _debug = _interopRequireDefault(require("debug"));
22
+ var _decompress = _interopRequireDefault(require("decompress"));
23
+ var _decompressUnzip = _interopRequireDefault(require("decompress-unzip"));
24
+ var _fs = require("fs");
25
+ var _https = require("https");
26
+ var _os = require("os");
27
+ var _path = require("path");
28
+ var _requestretry = _interopRequireDefault(require("requestretry"));
29
+ var _rimraf = _interopRequireDefault(require("rimraf"));
30
+ var _socksProxyAgent = require("socks-proxy-agent");
31
+ var _fonts = require("../fonts.js");
32
+ var _utils = require("./bookmarks/utils.js");
33
+ var _browserApi = require("./browser/browser-api.js");
34
+ var _browserChecker = _interopRequireDefault(require("./browser/browser-checker.js"));
35
+ var _browserUserDataManager = require("./browser/browser-user-data-manager.js");
36
+ var _cookiesManager = require("./cookies/cookies-manager.js");
37
+ var _extensionsManager = _interopRequireDefault(require("./extensions/extensions-manager.js"));
38
+ var _profileArchiver = require("./profile/profile-archiver.js");
39
+ var _browser = require("./utils/browser.js");
40
+ var _common = require("./utils/common.js");
41
+ var _constants = require("./utils/constants.js");
42
+ var _utils2 = require("./utils/utils.js");
43
+ var _gologinApi = require("./gologin-api.js");
44
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
45
+ const {
46
+ access,
47
+ unlink,
48
+ writeFile,
49
+ readFile
50
+ } = _fs.promises;
51
+ const SEPARATOR = _path.sep;
52
+ const OS_PLATFORM = process.platform;
53
+ const TIMEZONE_URL = 'https://geo.myip.link';
54
+ const PROXY_NONE = 'none';
55
+ const debug = (0, _debug.default)('gologin');
56
+ const delay = time => new Promise(resolve => setTimeout(resolve, time));
57
+ class GoLogin {
58
+ constructor(options = {}) {
59
+ this.browserLang = 'en-US';
60
+ this.is_remote = options.remote || false;
61
+ this.access_token = options.token;
62
+ this.profile_id = options.profile_id;
63
+ this.password = options.password;
64
+ this.extra_params = options.extra_params;
65
+ this.executablePath = options.executablePath;
66
+ this.vnc_port = options.vncPort;
67
+ this.fontsMasking = false;
68
+ this.is_active = false;
69
+ this.is_stopping = false;
70
+ this.differentOs = false;
71
+ this.profileOs = 'lin';
72
+ this.waitWebsocket = options.waitWebsocket ?? true;
73
+ this.isCloudHeadless = options.isCloudHeadless ?? true;
74
+ this.isNewCloudBrowser = options.isNewCloudBrowser ?? true;
75
+ this.tmpdir = (0, _os.tmpdir)();
76
+ this.autoUpdateBrowser = !!options.autoUpdateBrowser;
77
+ this.checkBrowserUpdate = options.checkBrowserUpdate ?? true;
78
+ this.browserChecker = new _browserChecker.default(options.skipOrbitaHashChecking);
79
+ this.uploadCookiesToServer = options.uploadCookiesToServer || false;
80
+ this.writeCookiesFromServer = options.writeCookiesFromServer;
81
+ this.remote_debugging_port = options.remote_debugging_port || 0;
82
+ this.timezone = options.timezone;
83
+ this.extensionPathsToInstall = [];
84
+ this.customArgs = options.args || [];
85
+ this.restoreLastSession = options.restoreLastSession || false;
86
+ this.processSpawned = null;
87
+ this.processKillTimeout = 1 * 1000;
88
+ if (options.tmpdir) {
89
+ this.tmpdir = options.tmpdir;
90
+ if (!(0, _fs.existsSync)(this.tmpdir)) {
91
+ debug('making tmpdir', this.tmpdir);
92
+ (0, _fs.mkdirSync)(this.tmpdir, {
93
+ recursive: true
94
+ });
95
+ }
96
+ }
97
+ this.profile_zip_path = (0, _path.join)(this.tmpdir, `gologin_${this.profile_id}.zip`);
98
+ this.bookmarksFilePath = (0, _path.join)(this.tmpdir, `gologin_profile_${this.profile_id}`, 'Default', 'Bookmarks');
99
+ debug('INIT GOLOGIN', this.profile_id);
100
+ }
101
+ async checkBrowser() {
102
+ return this.browserChecker.checkBrowser(this.autoUpdateBrowser, this.checkBrowserUpdate);
103
+ }
104
+ async setProfileId(profile_id) {
105
+ this.profile_id = profile_id;
106
+ this.cookiesFilePath = await (0, _cookiesManager.getCookiesFilePath)(profile_id, this.tmpdir);
107
+ this.profile_zip_path = (0, _path.join)(this.tmpdir, `gologin_${this.profile_id}.zip`);
108
+ this.bookmarksFilePath = (0, _path.join)(this.tmpdir, `gologin_profile_${this.profile_id}`, 'Default', 'Bookmarks');
109
+ }
110
+ async getToken(username, password) {
111
+ const data = await _requestretry.default.post(`${_common.API_URL}/user/login`, {
112
+ json: {
113
+ username,
114
+ password
115
+ }
116
+ });
117
+ if (!Reflect.has(data, 'body.access_token')) {
118
+ throw new Error(`gologin auth failed with status code, ${data.statusCode} DATA ${JSON.stringify(data)}`);
119
+ }
120
+ }
121
+ async getNewFingerPrint(os) {
122
+ debug('GETTING FINGERPRINT');
123
+ const fpResponse = await _requestretry.default.get(`${_common.API_URL}/browser/fingerprint?os=${os}`, {
124
+ json: true,
125
+ headers: {
126
+ 'Authorization': `Bearer ${this.access_token}`,
127
+ 'User-Agent': 'gologin-api'
128
+ }
129
+ });
130
+ return fpResponse?.body || {};
131
+ }
132
+ async profiles() {
133
+ const profilesResponse = await _requestretry.default.get(`${_common.API_URL}/browser/v2`, {
134
+ headers: {
135
+ 'Authorization': `Bearer ${this.access_token}`,
136
+ 'User-Agent': 'gologin-api'
137
+ }
138
+ });
139
+ if (profilesResponse.statusCode !== 200) {
140
+ throw new Error('Gologin /browser response error');
141
+ }
142
+ return JSON.parse(profilesResponse.body);
143
+ }
144
+ async getProfile(profile_id) {
145
+ const id = profile_id || this.profile_id;
146
+ debug('getProfile', this.access_token, id);
147
+ const profileResponse = await _requestretry.default.get(`${_common.API_URL}/browser/${id}`, {
148
+ headers: {
149
+ 'Authorization': `Bearer ${this.access_token}`,
150
+ 'User-Agent': 'gologin-api'
151
+ }
152
+ });
153
+ debug('profileResponse', profileResponse.statusCode, profileResponse.body);
154
+ const {
155
+ body: errorBody = ''
156
+ } = profileResponse;
157
+ const backendErrorHeader = 'backend@error::';
158
+ if (errorBody.includes(backendErrorHeader)) {
159
+ const errorData = errorBody.replace(backendErrorHeader, '').slice(1, -1);
160
+ throw new Error(errorData);
161
+ }
162
+ if (profileResponse.statusCode === 404) {
163
+ throw new Error(JSON.parse(profileResponse.body).message);
164
+ }
165
+ if (profileResponse.statusCode === 403) {
166
+ throw new Error(JSON.parse(profileResponse.body).message);
167
+ }
168
+ if (profileResponse.statusCode !== 200) {
169
+ throw new Error(`Gologin /browser/${id} response error ${profileResponse.statusCode} INVALID TOKEN OR PROFILE NOT FOUND`);
170
+ }
171
+ if (profileResponse.statusCode === 401) {
172
+ throw new Error('invalid token');
173
+ }
174
+ return JSON.parse(profileResponse.body);
175
+ }
176
+ async emptyProfile() {
177
+ return readFile((0, _path.resolve)(__dirname, 'gologin_zeroprofile.b64')).then(res => res.toString());
178
+ }
179
+ async getProfileS3(s3path) {
180
+ if (!s3path) {
181
+ throw new Error('s3path not found');
182
+ }
183
+ const token = this.access_token;
184
+ debug('getProfileS3 token=', token, 'profile=', this.profile_id, 's3path=', s3path);
185
+ const downloadURL = `${_constants.STORAGE_GATEWAY_BASE_URL}/download`;
186
+ debug('loading profile from public s3 bucket, url=', downloadURL);
187
+ const profileResponse = await _requestretry.default.get(downloadURL, {
188
+ encoding: null,
189
+ headers: {
190
+ Authorization: `Bearer ${token}`,
191
+ browserId: this.profile_id
192
+ }
193
+ });
194
+ if (profileResponse.statusCode !== 200) {
195
+ debug(`Gologin S3 BUCKET ${downloadURL} response error ${profileResponse.statusCode} - use empty`);
196
+ return '';
197
+ }
198
+ return Buffer.from(profileResponse.body);
199
+ }
200
+ async postFile(fileName, fileBuff) {
201
+ debug('POSTING FILE', fileBuff.length);
202
+ debug('Getting signed URL for S3');
203
+ const apiUrl = `${_constants.STORAGE_GATEWAY_BASE_URL}/upload`;
204
+ const bodyBufferBiteLength = Buffer.byteLength(fileBuff);
205
+ console.log('BUFFER SIZE', bodyBufferBiteLength);
206
+ await _requestretry.default.put(apiUrl, {
207
+ headers: {
208
+ Authorization: `Bearer ${this.access_token}`,
209
+ browserId: this.profile_id,
210
+ 'Content-Type': 'application/zip',
211
+ 'Content-Length': bodyBufferBiteLength
212
+ },
213
+ body: fileBuff,
214
+ maxBodyLength: Infinity,
215
+ maxContentLength: Infinity,
216
+ maxAttempts: 3,
217
+ retryDelay: 2000,
218
+ timeout: 30 * 1000,
219
+ fullResponse: false
220
+ });
221
+ console.log('Profile has been uploaded to S3 successfully');
222
+ }
223
+ async emptyProfileFolder() {
224
+ debug('get emptyProfileFolder');
225
+ const currentDir = (0, _path.dirname)(new URL(require('url').pathToFileURL(__filename).toString()).pathname);
226
+ const zeroProfilePath = (0, _path.join)(currentDir, '..', 'zero_profile.zip');
227
+ const profile = await readFile((0, _path.resolve)(zeroProfilePath));
228
+ debug('emptyProfileFolder LENGTH ::', profile.length);
229
+ return profile;
230
+ }
231
+ convertPreferences(preferences) {
232
+ if ((0, _utils2.get)(preferences, 'navigator.userAgent')) {
233
+ preferences.userAgent = (0, _utils2.get)(preferences, 'navigator.userAgent');
234
+ }
235
+ if ((0, _utils2.get)(preferences, 'navigator.doNotTrack')) {
236
+ preferences.doNotTrack = (0, _utils2.get)(preferences, 'navigator.doNotTrack');
237
+ }
238
+ if ((0, _utils2.get)(preferences, 'navigator.hardwareConcurrency')) {
239
+ preferences.hardwareConcurrency = (0, _utils2.get)(preferences, 'navigator.hardwareConcurrency');
240
+ }
241
+ if ((0, _utils2.get)(preferences, 'navigator.deviceMemory')) {
242
+ preferences.deviceMemory = (0, _utils2.get)(preferences, 'navigator.deviceMemory') * 1024;
243
+ }
244
+ if ((0, _utils2.get)(preferences, 'navigator.language')) {
245
+ preferences.langHeader = (0, _utils2.get)(preferences, 'navigator.language');
246
+ preferences.languages = (0, _utils2.get)(preferences, 'navigator.language').replace(/;|q=[\d\.]+/img, '');
247
+ }
248
+ if ((0, _utils2.get)(preferences, 'navigator.maxTouchPoints')) {
249
+ preferences.navigator.max_touch_points = (0, _utils2.get)(preferences, 'navigator.maxTouchPoints');
250
+ }
251
+ if ((0, _utils2.get)(preferences, 'isM1')) {
252
+ preferences.is_m1 = (0, _utils2.get)(preferences, 'isM1');
253
+ }
254
+ if ((0, _utils2.get)(preferences, 'os') == 'android') {
255
+ const devicePixelRatio = (0, _utils2.get)(preferences, 'devicePixelRatio');
256
+ const deviceScaleFactorCeil = Math.ceil(devicePixelRatio || 3.5);
257
+ let deviceScaleFactor = devicePixelRatio;
258
+ if (deviceScaleFactorCeil === devicePixelRatio) {
259
+ deviceScaleFactor += 0.00000001;
260
+ }
261
+ preferences.mobile = {
262
+ enable: true,
263
+ width: parseInt(this.resolution.width, 10),
264
+ height: parseInt(this.resolution.height, 10),
265
+ device_scale_factor: deviceScaleFactor
266
+ };
267
+ }
268
+ preferences.mediaDevices = {
269
+ enable: preferences.mediaDevices.enableMasking,
270
+ videoInputs: preferences.mediaDevices.videoInputs,
271
+ audioInputs: preferences.mediaDevices.audioInputs,
272
+ audioOutputs: preferences.mediaDevices.audioOutputs
273
+ };
274
+ preferences.webRtc = {
275
+ ...preferences.webRtc,
276
+ fill_based_on_ip: !!(0, _utils2.get)(preferences, 'webRTC.fillBasedOnIp'),
277
+ local_ip_masking: !!(0, _utils2.get)(preferences, 'webRTC.local_ip_masking')
278
+ };
279
+ return preferences;
280
+ }
281
+ async createBrowserExtension() {
282
+ const that = this;
283
+ debug('start createBrowserExtension');
284
+ await (0, _rimraf.default)(this.orbitaExtensionPath(), () => null);
285
+ const extPath = this.orbitaExtensionPath();
286
+ debug('extension folder sanitized');
287
+ const extension_source = (0, _path.resolve)(__dirname, 'gologin-browser-ext.zip');
288
+ await (0, _decompress.default)(extension_source, extPath, {
289
+ plugins: [(0, _decompressUnzip.default)()],
290
+ filter: file => !file.path.endsWith('/')
291
+ }).then(() => {
292
+ debug('extraction done');
293
+ debug('create uid.json');
294
+ return writeFile((0, _path.join)(extPath, 'uid.json'), JSON.stringify({
295
+ uid: that.profile_id
296
+ }, null, 2)).then(() => extPath);
297
+ }).catch(async e => {
298
+ debug('orbita extension error', e);
299
+ });
300
+ debug('createBrowserExtension done');
301
+ }
302
+ extractProfile(path, zipfile) {
303
+ debug(`extactProfile ${zipfile}, ${path}`);
304
+ return (0, _decompress.default)(zipfile, path, {
305
+ plugins: [(0, _decompressUnzip.default)()],
306
+ filter: file => !file.path.endsWith('/')
307
+ });
308
+ }
309
+ async createStartup(local = false) {
310
+ const profilePath = (0, _path.join)(this.tmpdir, `gologin_profile_${this.profile_id}`);
311
+ let profile;
312
+ let profile_folder;
313
+ await (0, _rimraf.default)(profilePath, () => null);
314
+ debug('-', profilePath, 'dropped');
315
+ profile = await this.getProfile();
316
+ const {
317
+ navigator = {},
318
+ fonts,
319
+ os: profileOs
320
+ } = profile;
321
+ this.fontsMasking = fonts?.enableMasking;
322
+ this.profileOs = profileOs;
323
+ this.differentOs = profileOs !== 'android' && (OS_PLATFORM === 'win32' && profileOs !== 'win' || OS_PLATFORM === 'darwin' && profileOs !== 'mac' || OS_PLATFORM === 'linux' && profileOs !== 'lin');
324
+ const {
325
+ resolution = '1920x1080',
326
+ language = 'en-US,en;q=0.9'
327
+ } = navigator;
328
+ this.language = language;
329
+ const [screenWidth, screenHeight] = resolution.split('x');
330
+ this.resolution = {
331
+ width: parseInt(screenWidth, 10),
332
+ height: parseInt(screenHeight, 10)
333
+ };
334
+ const profileZipExists = await access(this.profile_zip_path).then(() => true).catch(() => false);
335
+ if (!(local && profileZipExists)) {
336
+ try {
337
+ profile_folder = await this.getProfileS3((0, _utils2.get)(profile, 's3Path', ''));
338
+ } catch (e) {
339
+ debug('Cannot get profile - using empty', e);
340
+ }
341
+ debug('FILE READY', this.profile_zip_path);
342
+ if (!profile_folder.length) {
343
+ profile_folder = await this.emptyProfileFolder();
344
+ }
345
+ await writeFile(this.profile_zip_path, profile_folder);
346
+ debug('PROFILE LENGTH', profile_folder.length);
347
+ } else {
348
+ debug('PROFILE LOCAL HAVING', this.profile_zip_path);
349
+ }
350
+ debug('Cleaning up..', profilePath);
351
+ try {
352
+ await this.extractProfile(profilePath, this.profile_zip_path);
353
+ debug('extraction done');
354
+ } catch (e) {
355
+ console.trace(e);
356
+ profile_folder = await this.emptyProfileFolder();
357
+ await writeFile(this.profile_zip_path, profile_folder);
358
+ await this.extractProfile(profilePath, this.profile_zip_path);
359
+ }
360
+ const singletonLockPath = (0, _path.join)(profilePath, 'SingletonLock');
361
+ const singletonLockExists = await access(singletonLockPath).then(() => true).catch(() => false);
362
+ if (singletonLockExists) {
363
+ debug('removing SingletonLock');
364
+ await unlink(singletonLockPath);
365
+ debug('SingletonLock removed');
366
+ }
367
+ const pref_file_name = (0, _path.join)(profilePath, 'Default', 'Preferences');
368
+ debug('reading', pref_file_name);
369
+ const prefFileExists = await access(pref_file_name).then(() => true).catch(() => false);
370
+ if (!prefFileExists) {
371
+ debug('Preferences file not exists waiting', pref_file_name, '. Using empty profile');
372
+ profile_folder = await this.emptyProfileFolder();
373
+ await writeFile(this.profile_zip_path, profile_folder);
374
+ await this.extractProfile(profilePath, this.profile_zip_path);
375
+ await writeFile(pref_file_name, '{}');
376
+ }
377
+ const preferences_raw = await readFile(pref_file_name);
378
+ const preferences = JSON.parse(preferences_raw.toString());
379
+ let proxy = (0, _utils2.get)(profile, 'proxy');
380
+ const name = (0, _utils2.get)(profile, 'name');
381
+ const chromeExtensions = (0, _utils2.get)(profile, 'chromeExtensions') || [];
382
+ const userChromeExtensions = (0, _utils2.get)(profile, 'userChromeExtensions') || [];
383
+ const allExtensions = [...chromeExtensions, ...userChromeExtensions];
384
+ if (allExtensions.length) {
385
+ const ExtensionsManagerInst = new _extensionsManager.default();
386
+ ExtensionsManagerInst.apiUrl = _common.API_URL;
387
+ await ExtensionsManagerInst.init().then(() => ExtensionsManagerInst.updateExtensions()).catch(() => {});
388
+ ExtensionsManagerInst.accessToken = this.access_token;
389
+ await ExtensionsManagerInst.getExtensionsPolicies();
390
+ let profileExtensionsCheckRes = [];
391
+ if (ExtensionsManagerInst.useLocalExtStorage) {
392
+ const promises = [ExtensionsManagerInst.checkChromeExtensions(allExtensions).then(res => ({
393
+ profileExtensionsCheckRes: res
394
+ })).catch(e => {
395
+ console.log('checkChromeExtensions error: ', e);
396
+ return {
397
+ profileExtensionsCheckRes: []
398
+ };
399
+ }), ExtensionsManagerInst.checkLocalUserChromeExtensions(userChromeExtensions, this.profile_id).then(res => ({
400
+ profileUserExtensionsCheckRes: res
401
+ })).catch(error => {
402
+ console.log('checkUserChromeExtensions error: ', error);
403
+ return null;
404
+ })];
405
+ const extensionsResult = await Promise.all(promises);
406
+ const profileExtensionPathRes = extensionsResult.find(el => 'profileExtensionsCheckRes' in el) || {};
407
+ const profileUserExtensionPathRes = extensionsResult.find(el => 'profileUserExtensionsCheckRes' in el);
408
+ profileExtensionsCheckRes = (profileExtensionPathRes?.profileExtensionsCheckRes || []).concat(profileUserExtensionPathRes?.profileUserExtensionsCheckRes || []);
409
+ }
410
+ let extSettings;
411
+ if (ExtensionsManagerInst.useLocalExtStorage) {
412
+ extSettings = await (0, _browserUserDataManager.setExtPathsAndRemoveDeleted)(preferences, profileExtensionsCheckRes, this.profile_id);
413
+ } else {
414
+ const originalExtensionsFolder = (0, _path.join)(profilePath, 'Default', 'Extensions');
415
+ extSettings = await (0, _browserUserDataManager.setOriginalExtPaths)(preferences, originalExtensionsFolder);
416
+ }
417
+ this.extensionPathsToInstall = ExtensionsManagerInst.getExtensionsToInstall(extSettings, profileExtensionsCheckRes);
418
+ if (extSettings) {
419
+ const currentExtSettings = preferences.extensions || {};
420
+ currentExtSettings.settings = extSettings;
421
+ preferences.extensions = currentExtSettings;
422
+ }
423
+ }
424
+ if (proxy.mode === 'gologin' || proxy.mode === 'tor') {
425
+ const autoProxyServer = (0, _utils2.get)(profile, 'autoProxyServer');
426
+ const splittedAutoProxyServer = autoProxyServer.split('://');
427
+ const splittedProxyAddress = splittedAutoProxyServer[1].split(':');
428
+ const port = splittedProxyAddress[1];
429
+ proxy = {
430
+ 'mode': splittedAutoProxyServer[0],
431
+ 'host': splittedProxyAddress[0],
432
+ port,
433
+ 'username': (0, _utils2.get)(profile, 'autoProxyUsername'),
434
+ 'password': (0, _utils2.get)(profile, 'autoProxyPassword')
435
+ };
436
+ profile.proxy.username = (0, _utils2.get)(profile, 'autoProxyUsername');
437
+ profile.proxy.password = (0, _utils2.get)(profile, 'autoProxyPassword');
438
+ }
439
+ if (proxy.mode === 'geolocation') {
440
+ proxy.mode = 'http';
441
+ }
442
+ if (proxy.mode === PROXY_NONE) {
443
+ proxy = null;
444
+ }
445
+ this.proxy = proxy;
446
+ await this.getTimeZone(proxy).catch(e => {
447
+ console.error('Proxy Error. Check it and try again.');
448
+ throw e;
449
+ });
450
+ const [latitude, longitude] = this._tz.ll;
451
+ const {
452
+ accuracy
453
+ } = this._tz;
454
+ const profileGeolocation = profile.geolocation;
455
+ const tzGeoLocation = {
456
+ latitude,
457
+ longitude,
458
+ accuracy
459
+ };
460
+ profile.geoLocation = this.getGeolocationParams(profileGeolocation, tzGeoLocation);
461
+ profile.name = name;
462
+ profile.name_base64 = Buffer.from(name).toString('base64');
463
+ profile.profile_id = this.profile_id;
464
+ profile.webRtc = {
465
+ mode: (0, _utils2.get)(profile, 'webRTC.mode') === 'alerted' ? 'public' : (0, _utils2.get)(profile, 'webRTC.mode'),
466
+ publicIP: (0, _utils2.get)(profile, 'webRTC.fillBasedOnIp') ? this._tz.ip : (0, _utils2.get)(profile, 'webRTC.publicIp'),
467
+ localIps: (0, _utils2.get)(profile, 'webRTC.localIps', [])
468
+ };
469
+ debug('profile.webRtc=', profile.webRtc);
470
+ debug('profile.timezone=', profile.timezone);
471
+ debug('profile.mediaDevices=', profile.mediaDevices);
472
+ const audioContext = profile.audioContext || {};
473
+ const {
474
+ mode: audioCtxMode = 'off',
475
+ noise: audioCtxNoise
476
+ } = audioContext;
477
+ if (profile.timezone.fillBasedOnIp === false) {
478
+ profile.timezone = {
479
+ id: profile.timezone.timezone
480
+ };
481
+ } else {
482
+ profile.timezone = {
483
+ id: this._tz.timezone
484
+ };
485
+ }
486
+ profile.webgl_noise_value = profile.webGL.noise;
487
+ profile.get_client_rects_noise = profile.webGL.getClientRectsNoise;
488
+ profile.canvasMode = profile.canvas.mode;
489
+ profile.canvasNoise = profile.canvas.noise;
490
+ profile.audioContext = {
491
+ enable: audioCtxMode !== 'off',
492
+ noiseValue: audioCtxNoise
493
+ };
494
+ profile.webgl = {
495
+ metadata: {
496
+ vendor: (0, _utils2.get)(profile, 'webGLMetadata.vendor'),
497
+ renderer: (0, _utils2.get)(profile, 'webGLMetadata.renderer'),
498
+ mode: (0, _utils2.get)(profile, 'webGLMetadata.mode') === 'mask'
499
+ }
500
+ };
501
+ profile.custom_fonts = {
502
+ enable: !!fonts?.enableMasking
503
+ };
504
+ const gologin = this.convertPreferences(profile);
505
+ debug(`Writing profile for screenWidth ${profilePath}`, JSON.stringify(gologin));
506
+ gologin.screenWidth = this.resolution.width;
507
+ gologin.screenHeight = this.resolution.height;
508
+ debug('writeCookiesFromServer', this.writeCookiesFromServer);
509
+ this.cookiesFilePath = await (0, _cookiesManager.getCookiesFilePath)(this.profile_id, this.tmpdir);
510
+ if (this.writeCookiesFromServer) {
511
+ await this.writeCookiesToFile();
512
+ }
513
+ if (this.fontsMasking) {
514
+ const families = fonts?.families || [];
515
+ if (!families.length) {
516
+ throw new Error('No fonts list provided');
517
+ }
518
+ try {
519
+ await (0, _browserUserDataManager.composeFonts)(families, profilePath, this.differentOs);
520
+ } catch (e) {
521
+ console.trace(e);
522
+ }
523
+ }
524
+ const languages = this.language.replace(/;|q=[\d\.]+/img, '');
525
+ if (preferences.gologin == null) {
526
+ preferences.gologin = {};
527
+ }
528
+ preferences.gologin.langHeader = gologin.navigator.language;
529
+ preferences.gologin.language = languages;
530
+ const [splittedLangs] = gologin.navigator.language.split(';');
531
+ const [browserLang] = splittedLangs.split(',');
532
+ gologin.browserLang = browserLang;
533
+ const isMAC = OS_PLATFORM === 'darwin';
534
+ const checkAutoLangResult = (0, _browser.checkAutoLang)(gologin, this._tz);
535
+ this.browserLang = isMAC ? 'en-US' : checkAutoLangResult;
536
+ await writeFile((0, _path.join)(profilePath, 'Default', 'Preferences'), JSON.stringify(Object.assign(preferences, {
537
+ gologin
538
+ })));
539
+ const bookmarksParsedData = await (0, _utils.getCurrentProfileBookmarks)(this.bookmarksFilePath);
540
+ const bookmarksFromDb = profile.bookmarks?.bookmark_bar;
541
+ bookmarksParsedData.roots = bookmarksFromDb ? profile.bookmarks : bookmarksParsedData.roots;
542
+ await writeFile(this.bookmarksFilePath, JSON.stringify(bookmarksParsedData));
543
+ debug('Profile ready. Path: ', profilePath, 'PROXY', JSON.stringify((0, _utils2.get)(preferences, 'gologin.proxy')));
544
+ return profilePath;
545
+ }
546
+ async commitProfile() {
547
+ const dataBuff = await this.getProfileDataToUpdate();
548
+ debug('begin updating', dataBuff.length);
549
+ if (!dataBuff.length) {
550
+ debug('WARN: profile zip data empty - SKIPPING PROFILE COMMIT');
551
+ return;
552
+ }
553
+ try {
554
+ debug('Patching profile');
555
+ await this.postFile('profile', dataBuff);
556
+ } catch (e) {
557
+ debug('CANNOT COMMIT PROFILE', e);
558
+ }
559
+ debug('COMMIT COMPLETED');
560
+ }
561
+ profilePath() {
562
+ return (0, _path.join)(this.tmpdir, `gologin_profile_${this.profile_id}`);
563
+ }
564
+ orbitaExtensionPath() {
565
+ return (0, _path.join)(this.tmpdir, `orbita_extension_${this.profile_id}`);
566
+ }
567
+ getRandomInt(min, max) {
568
+ min = Math.ceil(min);
569
+ max = Math.floor(max);
570
+ return Math.floor(Math.random() * (max - min + 1)) + min;
571
+ }
572
+ async checkPortAvailable(port) {
573
+ debug('CHECKING PORT AVAILABLE', port);
574
+ try {
575
+ const portAvailable = await (0, _utils2.isPortReachable)(port, {
576
+ host: 'localhost'
577
+ });
578
+ if (portAvailable) {
579
+ debug(`PORT ${port} IS OPEN`);
580
+ return true;
581
+ }
582
+ } catch (e) {
583
+ console.log(e);
584
+ }
585
+ debug(`PORT ${port} IS BUSY`);
586
+ return false;
587
+ }
588
+ async getRandomPort() {
589
+ let port = this.getRandomInt(20000, 40000);
590
+ let portAvailable = await this.checkPortAvailable(port);
591
+ while (!portAvailable) {
592
+ port = this.getRandomInt(20000, 40000);
593
+ portAvailable = await this.checkPortAvailable(port);
594
+ }
595
+ return port;
596
+ }
597
+ async getTimeZone(proxy) {
598
+ debug('getting timeZone proxy=', proxy);
599
+ if (this.timezone) {
600
+ debug('getTimeZone from options', this.timezone);
601
+ this._tz = this.timezone;
602
+ return this._tz.timezone;
603
+ }
604
+ let data = null;
605
+ if (proxy && proxy.mode !== PROXY_NONE) {
606
+ if (proxy.mode.includes('socks')) {
607
+ for (let i = 0; i < 5; i++) {
608
+ try {
609
+ debug('getting timeZone socks try', i + 1);
610
+ return this.getTimezoneWithSocks(proxy);
611
+ } catch (e) {
612
+ console.log(e.message);
613
+ }
614
+ }
615
+ throw new Error('Socks proxy connection timed out');
616
+ }
617
+ const proxyUrl = `${proxy.mode}://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`;
618
+ debug(`getTimeZone start ${TIMEZONE_URL}`, proxyUrl);
619
+ data = await _requestretry.default.get(TIMEZONE_URL, {
620
+ proxy: proxyUrl,
621
+ timeout: 20 * 1000,
622
+ maxAttempts: 5
623
+ });
624
+ } else {
625
+ data = await _requestretry.default.get(TIMEZONE_URL, {
626
+ timeout: 20 * 1000,
627
+ maxAttempts: 5
628
+ });
629
+ }
630
+ debug('getTimeZone finish', data.body);
631
+ this._tz = JSON.parse(data.body);
632
+ return this._tz.timezone;
633
+ }
634
+ async getTimezoneWithSocks(params) {
635
+ const {
636
+ host,
637
+ port,
638
+ username = '',
639
+ password = ''
640
+ } = params;
641
+ let body;
642
+ let proxy = 'socks://';
643
+ if (username) {
644
+ const resultPassword = password ? ':' + password + '@' : '@';
645
+ proxy += username + resultPassword;
646
+ }
647
+ proxy += host + ':' + port;
648
+ const agent = new _socksProxyAgent.SocksProxyAgent(proxy);
649
+ const checkData = await new Promise((resolve, reject) => {
650
+ (0, _https.get)(TIMEZONE_URL, {
651
+ agent,
652
+ timeout: 10000
653
+ }, res => {
654
+ let resultResponse = '';
655
+ res.on('data', data => resultResponse += data);
656
+ res.on('end', () => {
657
+ let parsedData;
658
+ try {
659
+ parsedData = JSON.parse(resultResponse);
660
+ } catch (e) {
661
+ reject(e);
662
+ }
663
+ resolve({
664
+ ...res,
665
+ body: parsedData
666
+ });
667
+ });
668
+ }).on('error', err => reject(err));
669
+ });
670
+ body = checkData.body || {};
671
+ if (!body.ip && checkData.statusCode.toString().startsWith('4')) {
672
+ throw checkData;
673
+ }
674
+ debug('getTimeZone finish', body.body);
675
+ this._tz = body;
676
+ return this._tz.timezone;
677
+ }
678
+ async spawnArguments() {
679
+ const profile_path = this.profilePath();
680
+ let {
681
+ proxy
682
+ } = this;
683
+ proxy = `${proxy.mode}://${proxy.host}:${proxy.port}`;
684
+ const env = {};
685
+ Object.keys(process.env).forEach(key => {
686
+ env[key] = process.env[key];
687
+ });
688
+ const tz = await this.getTimeZone(this.proxy).catch(e => {
689
+ console.error('Proxy Error. Check it and try again.');
690
+ throw e;
691
+ });
692
+ env.TZ = tz;
693
+ let params = [`--proxy-server=${proxy}`, `--user-data-dir=${profile_path}`, '--password-store=basic', `--tz=${tz}`, '--lang=en'];
694
+ if (Array.isArray(this.extra_params) && this.extra_params.length) {
695
+ params = params.concat(this.extra_params);
696
+ }
697
+ if (this.remote_debugging_port) {
698
+ params.push(`--remote-debugging-port=${this.remote_debugging_port}`);
699
+ }
700
+ return params;
701
+ }
702
+ async spawnBrowser() {
703
+ let {
704
+ remote_debugging_port,
705
+ customArgs
706
+ } = this;
707
+ if (!remote_debugging_port) {
708
+ remote_debugging_port = await this.getRandomPort();
709
+ }
710
+ const profile_path = this.profilePath();
711
+ let {
712
+ proxy
713
+ } = this;
714
+ let proxy_host = '';
715
+ if (proxy) {
716
+ proxy_host = this.proxy.host;
717
+ proxy = `${proxy.mode}://${proxy.host}:${proxy.port}`;
718
+ }
719
+ this.port = remote_debugging_port;
720
+ const ORBITA_BROWSER = this.executablePath || this.browserChecker.getOrbitaPath;
721
+ debug(`ORBITA_BROWSER=${ORBITA_BROWSER}`);
722
+ const env = {};
723
+ Object.keys(process.env).forEach(key => {
724
+ env[key] = process.env[key];
725
+ });
726
+ const tz = await this.getTimeZone(this.proxy).catch(e => {
727
+ console.error('Proxy Error. Check it and try again.');
728
+ throw e;
729
+ });
730
+ env.TZ = tz;
731
+ if (this.vnc_port) {
732
+ const script_path = (0, _path.resolve)(__dirname, './run.sh');
733
+ debug('RUNNING', script_path, ORBITA_BROWSER, remote_debugging_port, proxy, profile_path, this.vnc_port);
734
+ (0, _child_process.execFile)(script_path, [ORBITA_BROWSER, remote_debugging_port, proxy, profile_path, this.vnc_port, tz], {
735
+ env
736
+ });
737
+ } else {
738
+ let params = [`--remote-debugging-port=${remote_debugging_port}`, `--user-data-dir=${profile_path}`, '--password-store=basic', `--tz=${tz}`, `--lang=${this.browserLang}`];
739
+ if (this.extensionPathsToInstall.length) {
740
+ if (Array.isArray(this.extra_params) && this.extra_params.length) {
741
+ this.extra_params.forEach((param, index) => {
742
+ if (!param.includes('--load-extension=')) {
743
+ return;
744
+ }
745
+ const [_, extPathsString] = param.split('=');
746
+ const extPathsArray = extPathsString.split(',');
747
+ this.extensionPathsToInstall = [...this.extensionPathsToInstall, ...extPathsArray];
748
+ this.extra_params.splice(index, 1);
749
+ });
750
+ }
751
+ params.push(`--load-extension=${this.extensionPathsToInstall.join(',')}`);
752
+ }
753
+ if (this.fontsMasking) {
754
+ let arg = '--font-masking-mode=2';
755
+ if (this.differentOs) {
756
+ arg = '--font-masking-mode=3';
757
+ }
758
+ if (this.profileOs === 'android') {
759
+ arg = '--font-masking-mode=1';
760
+ }
761
+ params.push(arg);
762
+ }
763
+ if (proxy) {
764
+ const hr_rules = `"MAP * 0.0.0.0 , EXCLUDE ${proxy_host}"`;
765
+ params.push(`--proxy-server=${proxy}`);
766
+ params.push(`--host-resolver-rules=${hr_rules}`);
767
+ }
768
+ if (Array.isArray(this.extra_params) && this.extra_params.length) {
769
+ params = params.concat(this.extra_params);
770
+ }
771
+ if (this.restoreLastSession) {
772
+ params.push('--restore-last-session');
773
+ }
774
+ params.push(...new Set(customArgs));
775
+ console.log(params);
776
+ const child = (0, _child_process.execFile)(ORBITA_BROWSER, params, {
777
+ env
778
+ });
779
+ this.processSpawned = child;
780
+ // const child = spawn(ORBITA_BROWSER, params, { env, shell: true });
781
+ child.stdout.on('data', data => debug(data.toString()));
782
+ debug('SPAWN CMD', ORBITA_BROWSER, params.join(' '));
783
+ }
784
+ if (this.waitWebsocket) {
785
+ debug('GETTING WS URL FROM BROWSER');
786
+ const data = await _requestretry.default.get(`http://127.0.0.1:${remote_debugging_port}/json/version`, {
787
+ json: true
788
+ });
789
+ debug('WS IS', (0, _utils2.get)(data, 'body.webSocketDebuggerUrl', ''));
790
+ this.is_active = true;
791
+ return (0, _utils2.get)(data, 'body.webSocketDebuggerUrl', '');
792
+ }
793
+ return '';
794
+ }
795
+ async createStartupAndSpawnBrowser() {
796
+ await this.createStartup();
797
+ return this.spawnBrowser();
798
+ }
799
+ async clearProfileFiles() {
800
+ await (0, _rimraf.default)((0, _path.join)(this.tmpdir, `gologin_profile_${this.profile_id}`), () => null);
801
+ await (0, _rimraf.default)((0, _path.join)(this.tmpdir, `gologin_${this.profile_id}_upload.zip`), () => null);
802
+ }
803
+ async stopAndCommit(options, local = false) {
804
+ if (this.is_stopping) {
805
+ return true;
806
+ }
807
+ const is_posting = options.posting || options.postings ||
808
+ // backward compability
809
+ false;
810
+ if (this.uploadCookiesToServer) {
811
+ await this.uploadProfileCookiesToServer();
812
+ }
813
+ await this.saveBookmarksToDb();
814
+ this.is_stopping = true;
815
+ await this.sanitizeProfile();
816
+ if (is_posting) {
817
+ await this.commitProfile();
818
+ }
819
+ this.is_stopping = false;
820
+ this.is_active = false;
821
+ await delay(3000);
822
+ await this.clearProfileFiles();
823
+ if (!local) {
824
+ await (0, _rimraf.default)((0, _path.join)(this.tmpdir, `gologin_${this.profile_id}.zip`), () => null);
825
+ }
826
+ debug(`PROFILE ${this.profile_id} STOPPED AND CLEAR`);
827
+ return false;
828
+ }
829
+ async stopBrowser() {
830
+ if (!this.port) {
831
+ throw new Error('Empty GoLogin port');
832
+ }
833
+ const ls = await (0, _child_process.spawn)('fuser', ['-k TERM', `-n tcp ${this.port}`], {
834
+ shell: true
835
+ });
836
+ debug('browser killed');
837
+ }
838
+ killBrowser() {
839
+ if (!this.processSpawned.pid) {
840
+ return;
841
+ }
842
+ try {
843
+ this.processSpawned.kill();
844
+ debug('browser killed');
845
+ } catch (error) {
846
+ console.error(error);
847
+ }
848
+ }
849
+ async killAndCommit(options, local = false) {
850
+ this.killBrowser();
851
+ await delay(this.processKillTimeout);
852
+ await this.stopAndCommit(options, local).catch(console.error);
853
+ }
854
+ async sanitizeProfile() {
855
+ const remove_dirs = [`${SEPARATOR}Default${SEPARATOR}Cache`, `${SEPARATOR}Default${SEPARATOR}Service Worker`, `${SEPARATOR}Default${SEPARATOR}Code Cache`, `${SEPARATOR}Default${SEPARATOR}GPUCache`, `${SEPARATOR}Default${SEPARATOR}Extensions`, `${SEPARATOR}Default${SEPARATOR}IndexedDB`, `${SEPARATOR}Default${SEPARATOR}GPUCache`, `${SEPARATOR}Default${SEPARATOR}DawnCache`, `${SEPARATOR}Default${SEPARATOR}fonts_config`, `${SEPARATOR}GrShaderCache`, `${SEPARATOR}ShaderCache`, `${SEPARATOR}biahpgbdmdkfgndcmfiipgcebobojjkp`, `${SEPARATOR}afalakplffnnnlkncjhbmahjfjhmlkal`, `${SEPARATOR}cffkpbalmllkdoenhmdmpbkajipdjfam`, `${SEPARATOR}Dictionaries`, `${SEPARATOR}enkheaiicpeffbfgjiklngbpkilnbkoi`, `${SEPARATOR}oofiananboodjbbmdelgdommihjbkfag`, `${SEPARATOR}SafetyTips`, `${SEPARATOR}fonts`, `${SEPARATOR}BrowserMetrics`, `${SEPARATOR}BrowserMetrics-spare.pma`];
856
+ const that = this;
857
+ await Promise.all(remove_dirs.map(d => {
858
+ const path_to_remove = `${that.profilePath()}${d}`;
859
+ return new Promise(resolve => {
860
+ debug('DROPPING', path_to_remove);
861
+ (0, _rimraf.default)(path_to_remove, {
862
+ maxBusyTries: 100
863
+ }, e => {
864
+ // debug('DROPPING RESULT', e);
865
+ resolve();
866
+ });
867
+ });
868
+ }));
869
+ }
870
+ async getProfileDataToUpdate() {
871
+ const zipPath = (0, _path.join)(this.tmpdir, `gologin_${this.profile_id}_upload.zip`);
872
+ const zipExists = await access(zipPath).then(() => true).catch(() => false);
873
+ if (zipExists) {
874
+ await unlink(zipPath);
875
+ }
876
+ await this.sanitizeProfile();
877
+ debug('profile sanitized');
878
+ const profilePath = this.profilePath();
879
+ const fileBuff = await (0, _profileArchiver.archiveProfile)(profilePath);
880
+ debug('PROFILE ZIP CREATED', profilePath, zipPath);
881
+ return fileBuff;
882
+ }
883
+ async profileExists() {
884
+ const profileResponse = await _requestretry.default.post(`${_common.API_URL}/browser`, {
885
+ headers: {
886
+ 'Authorization': `Bearer ${this.access_token}`,
887
+ 'User-Agent': 'gologin-api'
888
+ },
889
+ json: {}
890
+ });
891
+ if (profileResponse.statusCode !== 200) {
892
+ return false;
893
+ }
894
+ debug('profile is', profileResponse.body);
895
+ return true;
896
+ }
897
+ async getRandomFingerprint(options) {
898
+ let os = 'lin';
899
+ if (options.os) {
900
+ os = options.os;
901
+ }
902
+ let url = `${_common.API_URL}/browser/fingerprint?os=${os}`;
903
+ if (options.isM1) {
904
+ url += '&isM1=true';
905
+ }
906
+ const fingerprint = await _requestretry.default.get(url, {
907
+ headers: {
908
+ 'Authorization': `Bearer ${this.access_token}`,
909
+ 'User-Agent': 'gologin-api'
910
+ }
911
+ });
912
+ return JSON.parse(fingerprint.body);
913
+ }
914
+ async create(options) {
915
+ debug('createProfile', options);
916
+ const fingerprint = await this.getRandomFingerprint(options);
917
+ debug('fingerprint=', fingerprint);
918
+ if (fingerprint.statusCode === 500) {
919
+ throw new Error('no valid random fingerprint check os param');
920
+ }
921
+ if (fingerprint.statusCode === 401) {
922
+ throw new Error('invalid token');
923
+ }
924
+ const {
925
+ navigator,
926
+ fonts,
927
+ webGLMetadata,
928
+ webRTC
929
+ } = fingerprint;
930
+ let deviceMemory = navigator.deviceMemory || 2;
931
+ if (deviceMemory < 1) {
932
+ deviceMemory = 1;
933
+ }
934
+ navigator.deviceMemory = deviceMemory * 1024;
935
+ webGLMetadata.mode = webGLMetadata.mode === 'noise' ? 'mask' : 'off';
936
+ const json = {
937
+ ...fingerprint,
938
+ navigator,
939
+ webGLMetadata,
940
+ browserType: 'chrome',
941
+ name: 'default_name',
942
+ notes: 'auto generated',
943
+ fonts: {
944
+ families: fonts
945
+ },
946
+ webRTC: {
947
+ ...webRTC,
948
+ mode: 'alerted'
949
+ }
950
+ };
951
+ const user_agent = options.navigator?.userAgent;
952
+ const orig_user_agent = json.navigator.userAgent;
953
+ Object.keys(options).forEach(key => {
954
+ if (typeof json[key] === 'object') {
955
+ json[key] = {
956
+ ...json[key],
957
+ ...options[key]
958
+ };
959
+ return;
960
+ }
961
+ json[key] = options[key];
962
+ });
963
+ if (user_agent === 'random') {
964
+ json.navigator.userAgent = orig_user_agent;
965
+ }
966
+ const response = await _requestretry.default.post(`${_common.API_URL}/browser`, {
967
+ headers: {
968
+ 'Authorization': `Bearer ${this.access_token}`,
969
+ 'User-Agent': 'gologin-api'
970
+ },
971
+ json
972
+ });
973
+ if (response.statusCode === 400) {
974
+ throw new Error(`gologin failed account creation with status code, ${response.statusCode} DATA ${JSON.stringify(response.body.message)}`);
975
+ }
976
+ if (response.statusCode === 500) {
977
+ throw new Error(`gologin failed account creation with status code, ${response.statusCode}`);
978
+ }
979
+ debug(JSON.stringify(response.body));
980
+ return response.body.id;
981
+ }
982
+ async createCustom(options) {
983
+ debug('createCustomProfile', options);
984
+ const response = await _requestretry.default.post(`${_common.API_URL}/browser/custom`, {
985
+ headers: {
986
+ 'Authorization': `Bearer ${this.access_token}`,
987
+ 'User-Agent': 'gologin-api'
988
+ },
989
+ json: options
990
+ });
991
+ if (response.statusCode === 400) {
992
+ throw new Error(`gologin failed account creation with status code, ${response.statusCode} DATA ${JSON.stringify(response.body.message)}`);
993
+ }
994
+ if (response.statusCode === 500) {
995
+ throw new Error(`gologin failed account creation with status code, ${response.statusCode}`);
996
+ }
997
+ debug(JSON.stringify(response));
998
+ return response.body.id;
999
+ }
1000
+ async quickCreateProfile(name = '') {
1001
+ const osInfo = await (0, _common.getOsAdvanced)();
1002
+ const {
1003
+ os,
1004
+ osSpec
1005
+ } = osInfo;
1006
+ const resultName = name || 'api-generated';
1007
+ return _requestretry.default.post(`${_common.API_URL}/browser/quick`, {
1008
+ headers: {
1009
+ 'Authorization': `Bearer ${this.access_token}`,
1010
+ 'User-Agent': 'gologin-api'
1011
+ },
1012
+ json: {
1013
+ os,
1014
+ osSpec,
1015
+ name: resultName
1016
+ }
1017
+ }).then(res => res.body);
1018
+ }
1019
+ async delete(pid) {
1020
+ const profile_id = pid || this.profile_id;
1021
+ await _requestretry.default.delete(`${_common.API_URL}/browser/${profile_id}`, {
1022
+ headers: {
1023
+ 'Authorization': `Bearer ${this.access_token}`,
1024
+ 'User-Agent': 'gologin-api'
1025
+ }
1026
+ });
1027
+ }
1028
+ async update(options) {
1029
+ this.profile_id = options.id;
1030
+ const profile = await this.getProfile();
1031
+ if (options.navigator) {
1032
+ Object.keys(options.navigator).map(e => {
1033
+ profile.navigator[e] = options.navigator[e];
1034
+ });
1035
+ }
1036
+ Object.keys(options).filter(el => el !== 'navigator').forEach(el => {
1037
+ profile[el] = options[el];
1038
+ });
1039
+ debug('update profile', profile);
1040
+ const response = await _requestretry.default.put(`${_common.API_URL}/browser/${options.id}`, {
1041
+ json: profile,
1042
+ headers: {
1043
+ 'Authorization': `Bearer ${this.access_token}`,
1044
+ 'User-Agent': 'gologin-api'
1045
+ }
1046
+ });
1047
+ debug('response', JSON.stringify(response.body));
1048
+ return response.body;
1049
+ }
1050
+ setActive(is_active) {
1051
+ this.is_active = is_active;
1052
+ }
1053
+ getGeolocationParams(profileGeolocationParams, tzGeolocationParams) {
1054
+ if (profileGeolocationParams.fillBasedOnIp) {
1055
+ return {
1056
+ mode: profileGeolocationParams.mode,
1057
+ latitude: Number(tzGeolocationParams.latitude),
1058
+ longitude: Number(tzGeolocationParams.longitude),
1059
+ accuracy: Number(tzGeolocationParams.accuracy)
1060
+ };
1061
+ }
1062
+ return {
1063
+ mode: profileGeolocationParams.mode,
1064
+ latitude: profileGeolocationParams.latitude,
1065
+ longitude: profileGeolocationParams.longitude,
1066
+ accuracy: profileGeolocationParams.accuracy
1067
+ };
1068
+ }
1069
+ getViewPort() {
1070
+ return {
1071
+ ...this.resolution
1072
+ };
1073
+ }
1074
+ async postCookies(profileId, cookies) {
1075
+ const formattedCookies = cookies.map(cookie => {
1076
+ if (!['no_restriction', 'lax', 'strict', 'unspecified'].includes(cookie.sameSite)) {
1077
+ cookie.sameSite = 'unspecified';
1078
+ }
1079
+ return cookie;
1080
+ });
1081
+ const response = await (0, _browserUserDataManager.uploadCookies)({
1082
+ profileId,
1083
+ cookies: formattedCookies,
1084
+ API_BASE_URL: _common.API_URL,
1085
+ ACCESS_TOKEN: this.access_token
1086
+ });
1087
+ if (response.statusCode === 200) {
1088
+ return response.body;
1089
+ }
1090
+ return {
1091
+ status: 'failure',
1092
+ status_code: response.statusCode,
1093
+ body: response.body
1094
+ };
1095
+ }
1096
+ async getCookies(profileId) {
1097
+ const response = await (0, _browserUserDataManager.downloadCookies)({
1098
+ profileId,
1099
+ API_BASE_URL: _common.API_URL,
1100
+ ACCESS_TOKEN: this.access_token
1101
+ });
1102
+ return response.body;
1103
+ }
1104
+ async writeCookiesToFile() {
1105
+ const cookies = await this.getCookies(this.profile_id);
1106
+ const resultCookies = cookies.map(el => ({
1107
+ ...el,
1108
+ value: Buffer.from(el.value)
1109
+ }));
1110
+ let db;
1111
+ try {
1112
+ db = await (0, _cookiesManager.getDB)(this.cookiesFilePath, false);
1113
+ if (resultCookies.length) {
1114
+ const chunckInsertValues = (0, _cookiesManager.getChunckedInsertValues)(resultCookies);
1115
+ for (const [query, queryParams] of chunckInsertValues) {
1116
+ const insertStmt = await db.prepare(query);
1117
+ await insertStmt.run(queryParams);
1118
+ await insertStmt.finalize();
1119
+ }
1120
+ } else {
1121
+ const query = 'delete from cookies';
1122
+ const insertStmt = await db.prepare(query);
1123
+ await insertStmt.run();
1124
+ await insertStmt.finalize();
1125
+ }
1126
+ } catch (error) {
1127
+ console.log(error.message);
1128
+ } finally {
1129
+ db && (await db.close());
1130
+ }
1131
+ }
1132
+ async uploadProfileCookiesToServer() {
1133
+ const cookies = await (0, _cookiesManager.loadCookiesFromFile)(this.cookiesFilePath);
1134
+ if (!cookies.length) {
1135
+ return;
1136
+ }
1137
+ return this.postCookies(this.profile_id, cookies);
1138
+ }
1139
+ async saveBookmarksToDb() {
1140
+ const bookmarksData = await (0, _utils.getCurrentProfileBookmarks)(this.bookmarksFilePath);
1141
+ const bookmarks = bookmarksData.roots || {};
1142
+ await (0, _browserApi.updateProfileBookmarks)([this.profile_id], this.access_token, bookmarks);
1143
+ }
1144
+ async start() {
1145
+ if (this.is_remote) {
1146
+ return this.startRemote();
1147
+ }
1148
+ if (!this.executablePath) {
1149
+ await this.checkBrowser();
1150
+ }
1151
+ const ORBITA_BROWSER = this.executablePath || this.browserChecker.getOrbitaPath;
1152
+ const orbitaBrowserExists = await access(ORBITA_BROWSER).then(() => true).catch(() => false);
1153
+ if (!orbitaBrowserExists) {
1154
+ throw new Error(`Orbita browser is not exists on path ${ORBITA_BROWSER}, check executablePath param`);
1155
+ }
1156
+ await this.createStartup();
1157
+ // await this.createBrowserExtension();
1158
+ const wsUrl = await this.spawnBrowser();
1159
+ this.setActive(true);
1160
+ return {
1161
+ status: 'success',
1162
+ wsUrl
1163
+ };
1164
+ }
1165
+ async startLocal() {
1166
+ await this.createStartup(true);
1167
+ // await this.createBrowserExtension();
1168
+ const wsUrl = await this.spawnBrowser();
1169
+ this.setActive(true);
1170
+ return {
1171
+ status: 'success',
1172
+ wsUrl
1173
+ };
1174
+ }
1175
+ async stop() {
1176
+ await new Promise(resolve => setTimeout(resolve, 500));
1177
+ if (this.is_remote) {
1178
+ return this.stopRemote();
1179
+ }
1180
+ await this.stopAndCommit({
1181
+ posting: true
1182
+ }, false);
1183
+ }
1184
+ async stopLocal(options) {
1185
+ const opts = options || {
1186
+ posting: false
1187
+ };
1188
+ await this.stopAndCommit(opts, true);
1189
+ }
1190
+ async waitDebuggingUrl(delay_ms, try_count = 0, remoteOrbitaUrl) {
1191
+ await delay(delay_ms);
1192
+ const url = `${remoteOrbitaUrl}/json/version`;
1193
+ console.log('try_count=', try_count, 'url=', url);
1194
+ const response = await _requestretry.default.get(url);
1195
+ let wsUrl = '';
1196
+ console.log('response', response.body);
1197
+ if (!response.body) {
1198
+ return wsUrl;
1199
+ }
1200
+ try {
1201
+ const parsedBody = JSON.parse(response.body);
1202
+ wsUrl = parsedBody.webSocketDebuggerUrl;
1203
+ } catch (e) {
1204
+ if (try_count < 3) {
1205
+ return this.waitDebuggingUrl(delay_ms, try_count + 1, remoteOrbitaUrl);
1206
+ }
1207
+ return {
1208
+ status: 'failure',
1209
+ wsUrl,
1210
+ message: 'Check proxy settings',
1211
+ 'profile_id': this.profile_id
1212
+ };
1213
+ }
1214
+ const remoteOrbitaUrlWithoutProtocol = remoteOrbitaUrl.replace('https://', '');
1215
+ wsUrl = wsUrl.replace('ws://', 'wss://').replace('127.0.0.1', remoteOrbitaUrlWithoutProtocol);
1216
+ return wsUrl;
1217
+ }
1218
+ async startRemote(delay_ms = 10000) {
1219
+ debug(`startRemote ${this.profile_id}`);
1220
+
1221
+ /*
1222
+ if (profileResponse.statusCode !== 202) {
1223
+ return {'status': 'failure', 'code': profileResponse.statusCode};
1224
+ }
1225
+ */
1226
+
1227
+ const profile = await this.getProfile();
1228
+ const profileResponse = await _requestretry.default.post(`${_common.API_URL}/browser/${this.profile_id}/web`, {
1229
+ headers: {
1230
+ 'Authorization': `Bearer ${this.access_token}`,
1231
+ 'User-Agent': 'gologin-api'
1232
+ },
1233
+ json: {
1234
+ isNewCloudBrowser: this.isNewCloudBrowser,
1235
+ isHeadless: this.isCloudHeadless
1236
+ }
1237
+ }).catch(() => null);
1238
+ if (!profileResponse) {
1239
+ throw new Error('invalid request');
1240
+ }
1241
+ const {
1242
+ body,
1243
+ statusCode
1244
+ } = profileResponse;
1245
+ debug('profileResponse', statusCode, body);
1246
+ if (profileResponse.statusCode === 401) {
1247
+ throw new Error('invalid token');
1248
+ }
1249
+ if (body.status === 'profileStatuses.pending') {
1250
+ return {
1251
+ status: 'pending',
1252
+ message: 'remote browser is being prepared, please try in 1 minute.'
1253
+ };
1254
+ }
1255
+ let remoteOrbitaUrl = `https://${this.profile_id}.orbita.gologin.com`;
1256
+ if (this.isNewCloudBrowser) {
1257
+ if (!profileResponse.body.remoteOrbitaUrl) {
1258
+ throw new Error('Couldn\' start the remote browser');
1259
+ }
1260
+ remoteOrbitaUrl = profileResponse.body.remoteOrbitaUrl;
1261
+ }
1262
+ const {
1263
+ navigator = {},
1264
+ fonts,
1265
+ os: profileOs
1266
+ } = profile;
1267
+ this.fontsMasking = fonts?.enableMasking;
1268
+ this.profileOs = profileOs;
1269
+ this.differentOs = profileOs !== 'android' && (OS_PLATFORM === 'win32' && profileOs !== 'win' || OS_PLATFORM === 'darwin' && profileOs !== 'mac' || OS_PLATFORM === 'linux' && profileOs !== 'lin');
1270
+ const {
1271
+ resolution = '1920x1080',
1272
+ language = 'en-US,en;q=0.9'
1273
+ } = navigator;
1274
+ this.language = language;
1275
+ const [screenWidth, screenHeight] = resolution.split('x');
1276
+ this.resolution = {
1277
+ width: parseInt(screenWidth, 10),
1278
+ height: parseInt(screenHeight, 10)
1279
+ };
1280
+ const wsUrl = await this.waitDebuggingUrl(delay_ms, 0, remoteOrbitaUrl);
1281
+ if (wsUrl !== '') {
1282
+ return {
1283
+ status: 'success',
1284
+ wsUrl
1285
+ };
1286
+ }
1287
+ return {
1288
+ status: 'failure',
1289
+ message: body
1290
+ };
1291
+ }
1292
+ async stopRemote() {
1293
+ debug(`stopRemote ${this.profile_id}`);
1294
+ const profileResponse = await _requestretry.default.delete(`${_common.API_URL}/browser/${this.profile_id}/web?isNewCloudBrowser=${this.isNewCloudBrowser}`, {
1295
+ headers: {
1296
+ 'Authorization': `Bearer ${this.access_token}`,
1297
+ 'User-Agent': 'gologin-api'
1298
+ }
1299
+ });
1300
+ console.log(`stopRemote ${profileResponse.body}`);
1301
+ if (profileResponse.body) {
1302
+ return JSON.parse(profileResponse.body);
1303
+ }
1304
+ }
1305
+ getAvailableFonts() {
1306
+ return _fonts.fontsCollection.filter(elem => elem.fileNames).map(elem => elem.name);
1307
+ }
1308
+ async changeProfileResolution(resolution) {
1309
+ return (0, _browserApi.updateProfileResolution)(this.profile_id, this.access_token, resolution);
1310
+ }
1311
+ async changeProfileUserAgent(userAgent) {
1312
+ return (0, _browserApi.updateProfileUserAgent)(this.profile_id, this.access_token, userAgent);
1313
+ }
1314
+ async changeProfileProxy(proxyData) {
1315
+ return (0, _browserApi.updateProfileProxy)(this.profile_id, this.access_token, proxyData);
1316
+ }
1317
+ }
1318
+ exports.GoLogin = GoLogin;
1319
+ var _default = exports.default = GoLogin;