gologin 2.1.29 → 2.1.31

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Combined changelog for GoLogin node.js SDK
4
4
 
5
+ ## [2.1.31] 2025-09-01
6
+
7
+
8
+ ### Fixes
9
+
10
+ * Orbita downloading doesnt break the flow if major version is skipped
11
+ * Languages passing now works correctly
12
+
5
13
  ## [2.1.29] 2025-07-11
6
14
 
7
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gologin",
3
- "version": "2.1.29",
3
+ "version": "2.1.31",
4
4
  "description": "A high-level API to control Orbita browser over GoLogin API",
5
5
  "types": "./index.d.ts",
6
6
  "main": "./src/gologin.js",
@@ -71,7 +71,7 @@ export class BrowserChecker {
71
71
  // return this.getBrowserExecutablePath(majorVersion);
72
72
  // }
73
73
 
74
-
74
+
75
75
 
76
76
  // return new Promise(resolve => {
77
77
  // const rl = createInterface(process.stdin, process.stdout);
@@ -139,7 +139,7 @@ export class BrowserChecker {
139
139
  .then(() => writeFile(join(this.#browserPath, 'orbita-browser', 'version', 'latest-version.txt'), latestVersion));
140
140
  }
141
141
 
142
- downloadBrowserArchive(link, pathStr) {
142
+ async downloadBrowserArchive(link, pathStr) {
143
143
  return new Promise((resolve, reject) => {
144
144
  const writableStream = createWriteStream(pathStr);
145
145
  writableStream.on('error', async err => {
@@ -153,6 +153,11 @@ export class BrowserChecker {
153
153
  }, (res) => {
154
154
  const len = parseInt(res.headers['content-length'], 10);
155
155
  const formattedLen = len / 1024 / 1024;
156
+ if (isNaN(formattedLen)) {
157
+ reject(new Error('Error downloading browser'));
158
+ return;
159
+ }
160
+
156
161
  const bar = new ProgressBar('Orbita downloading [:bar] :rate/mps :downloadedMb/:fullMbMB :percent :etas', {
157
162
  complete: '=',
158
163
  incomplete: ' ',
@@ -299,13 +304,13 @@ export class BrowserChecker {
299
304
 
300
305
  async replaceBrowser(majorVersion) {
301
306
  console.log('Copy Orbita to target path');
302
- if (PLATFORM === 'darwin') {
303
- return rename(join(this.#browserPath, EXTRACTED_FOLDER), join(this.#browserPath, `orbita-browser-${majorVersion}`));
304
- }
305
-
306
307
  const targetBrowserPath = join(this.#browserPath, `orbita-browser-${majorVersion}`);
307
308
  await this.deleteDir(targetBrowserPath);
308
309
 
310
+ if (PLATFORM === 'darwin') {
311
+ return rename(join(this.#browserPath, EXTRACTED_FOLDER), targetBrowserPath);
312
+ }
313
+
309
314
  await this.copyDir(
310
315
  join(this.#browserPath, EXTRACTED_FOLDER, 'orbita-browser'),
311
316
  targetBrowserPath,
@@ -67,13 +67,15 @@ export const downloadFonts = async (fontsList = [], profilePath) => {
67
67
  const files = await readdir(browserFontsPath);
68
68
  const fontsToDownload = fontsList.filter(font => !files.includes(font));
69
69
 
70
- let promises = fontsToDownload.map(font => makeRequest(FONTS_URL + font, {
71
- maxAttempts: 5,
72
- retryDelay: 2000,
73
- timeout: 30 * 1000,
74
- })
75
- .pipe(createWriteStream(join(browserFontsPath, font))),
76
- );
70
+ let promises = fontsToDownload.map(async font => {
71
+ const body = await makeRequest(FONTS_URL + font, {
72
+ maxAttempts: 5,
73
+ retryDelay: 2000,
74
+ timeout: 30 * 1000,
75
+ });
76
+
77
+ await writeFile(join(browserFontsPath, font), body);
78
+ });
77
79
 
78
80
  if (promises.length) {
79
81
  await Promise.all(promises);
@@ -55,9 +55,9 @@ export const createDBFile = async ({
55
55
 
56
56
  export const getUniqueCookies = async (cookiesArr, cookiesFilePath) => {
57
57
  const cookiesInFile = await loadCookiesFromFile(cookiesFilePath);
58
- const existingCookieNames = new Set(cookiesInFile.map(c => `${c.name}-${c.value.toString('base64')}`));
58
+ const existingCookieNames = new Set(cookiesInFile.map(c => `${c.name}-${c.domain}-${c.path}`));
59
59
 
60
- return cookiesArr.filter(cookie => !existingCookieNames.has(`${cookie.name}-${cookie.value.toString('base64')}`));
60
+ return cookiesArr.filter(cookie => !existingCookieNames.has(`${cookie.name}-${cookie.domain}-${cookie.path}`));
61
61
  };
62
62
 
63
63
  export const getChunckedInsertValues = (cookiesArr) => {
@@ -114,9 +114,21 @@ export const getChunckedInsertValues = (cookiesArr) => {
114
114
  });
115
115
  };
116
116
 
117
- export const loadCookiesFromFile = async (filePath) => {
117
+ export const loadCookiesFromFile = async (filePath, isSecondTry = false, profileId, tmpdir) => {
118
118
  let db;
119
119
  const cookies = [];
120
+ let secondCookiesFilePath;
121
+ try {
122
+ const isNetworkFolder = filePath.includes('Network');
123
+ secondCookiesFilePath = isNetworkFolder ?
124
+ join(tmpdir, `gologin_profile_${profileId}`, 'Default', 'Cookies') :
125
+ join(tmpdir, `gologin_profile_${profileId}`, 'Default', 'Network', 'Cookies');
126
+ } catch (error) {
127
+ console.log(error);
128
+ console.log('error in loadCookiesFromFile', error.message);
129
+ }
130
+
131
+ console.log(1);
120
132
 
121
133
  try {
122
134
  db = await getDB(filePath);
@@ -151,11 +163,18 @@ export const loadCookiesFromFile = async (filePath) => {
151
163
  });
152
164
  }
153
165
  } catch (error) {
154
- console.log(error);
166
+ console.log('error in loadCookiesFromFile', error.message);
167
+ if (!isSecondTry) {
168
+ return await loadCookiesFromFile(secondCookiesFilePath, true, profileId, tmpdir);
169
+ }
155
170
  } finally {
156
171
  db && await db.close();
157
172
  }
158
173
 
174
+ if (!cookies.length && !isSecondTry) {
175
+ return loadCookiesFromFile(secondCookiesFilePath, true, profileId, tmpdir);
176
+ }
177
+
159
178
  return cookies;
160
179
  };
161
180
 
package/src/gologin.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  } from './cookies/cookies-manager.js';
28
28
  import ExtensionsManager from './extensions/extensions-manager.js';
29
29
  import { archiveProfile } from './profile/profile-archiver.js';
30
- import { checkAutoLang } from './utils/browser.js';
30
+ import { checkAutoLang, getIntlProfileConfig } from './utils/browser.js';
31
31
  import { API_URL, ensureDirectoryExists, FALLBACK_API_URL, getOsAdvanced } from './utils/common.js';
32
32
  import { STORAGE_GATEWAY_BASE_URL } from './utils/constants.js';
33
33
  import { get, isPortReachable } from './utils/utils.js';
@@ -82,6 +82,7 @@ export class GoLogin {
82
82
  this.newProxyOrbbitaMajorVersion = 135;
83
83
  this.proxyCheckTimeout = options.proxyCheckTimeout || 13 * 1000;
84
84
  this.proxyCheckAttempts = options.proxyCheckAttempts || 3;
85
+ this.browserLatestMajorVersion = 137;
85
86
 
86
87
  if (process.env.DISABLE_TELEMETRY !== 'true') {
87
88
  Sentry.init({
@@ -120,9 +121,7 @@ export class GoLogin {
120
121
  if (!(Array.isArray(versionsToDownload) && versionsToDownload.length)) {
121
122
  versionsToDownload = [];
122
123
 
123
- const { latestVersion: browserLatestVersion } = await this.browserChecker.getLatestBrowserVersion();
124
- const [latestBrowserMajorVersion] = browserLatestVersion.split('.');
125
- const latestVersionNumber = Number(latestBrowserMajorVersion);
124
+ const latestVersionNumber = await this.getLatestBrowserVersion();
126
125
 
127
126
  for (let i = latestVersionNumber; i > latestVersionNumber - lastActualCount; i--) {
128
127
  versionsToDownload.push(i.toString());
@@ -134,10 +133,21 @@ export class GoLogin {
134
133
  autoUpdateBrowser: true,
135
134
  checkBrowserUpdate: true,
136
135
  majorVersion,
136
+ }).catch((error) => {
137
+ console.log('Error Downloading Browser version', majorVersion, error);
137
138
  });
138
139
  }
139
140
  }
140
141
 
142
+ async getLatestBrowserVersion() {
143
+ const { latestVersion: browserLatestVersion } = await this.browserChecker.getLatestBrowserVersion();
144
+ const [latestBrowserMajorVersion] = browserLatestVersion.split('.');
145
+ const latestVersionNumber = Number(latestBrowserMajorVersion);
146
+ this.latestBrowserMajorVersion = latestVersionNumber;
147
+
148
+ return latestVersionNumber;
149
+ }
150
+
141
151
  async setProfileId(profile_id) {
142
152
  this.profile_id = profile_id;
143
153
  this.cookiesFilePath = await getCookiesFilePath(profile_id, this.tmpdir);
@@ -222,8 +232,6 @@ export class GoLogin {
222
232
  const [screenWidth, screenHeight] = resolution.split('x').map(Number);
223
233
  const langHeader = (profileData.navigator && profileData.navigator.language) || '';
224
234
  const splittedLangs = langHeader ? langHeader.split(',')[0] : 'en-US';
225
- const [browserMajorVersion] = profileData.navigator.userAgent.split('Chrome/')[1].split('.');
226
- this.browserMajorVersion = browserMajorVersion;
227
235
 
228
236
  const startupUrl = (profileData.startUrl || '').trim().split(',')[0];
229
237
  const startupUrls = (profileData.startUrl || '').split(',')
@@ -315,7 +323,7 @@ export class GoLogin {
315
323
  },
316
324
  };
317
325
 
318
- if (browserMajorVersion >= this.newProxyOrbbitaMajorVersion && profileData.proxy?.mode !== 'none') {
326
+ if (this.browserMajorVersion >= this.newProxyOrbbitaMajorVersion && profileData.proxy?.mode !== 'none') {
319
327
  let proxyServer = `${profileData.proxy.mode}://`;
320
328
  if (profileData.proxy.username) {
321
329
  const encodedUsername = encodeURIComponent(profileData.proxy.username || '');
@@ -455,8 +463,15 @@ export class GoLogin {
455
463
 
456
464
  if (!this.executablePath) {
457
465
  const { userAgent } = profile.navigator;
458
- const [browserMajorVersion] = userAgent.split('Chrome/')[1].split('.');
459
- await this.checkBrowser(browserMajorVersion);
466
+ try {
467
+ const [browserMajorVersion] = userAgent.split('Chrome/')[1].split('.');
468
+ this.browserMajorVersion = Number(browserMajorVersion);
469
+ await this.checkBrowser(browserMajorVersion);
470
+ } catch (e) {
471
+ const latestVersionNumber = await this.getLatestBrowserVersion();
472
+ this.browserMajorVersion = latestVersionNumber;
473
+ await this.checkBrowser(latestVersionNumber);
474
+ }
460
475
  }
461
476
 
462
477
  const { navigator = {}, fonts, os: profileOs } = profile;
@@ -626,9 +641,12 @@ export class GoLogin {
626
641
  }
627
642
 
628
643
  const isMAC = OS_PLATFORM === 'darwin';
629
- const checkAutoLangResult = checkAutoLang(gologin, this._tz);
630
- this.browserLang = isMAC ? 'en-US' : checkAutoLangResult;
644
+ const checkAutoLangResult = checkAutoLang(gologin, this._tz, profile.autoLang);
645
+ const intlConfig = getIntlProfileConfig(profile, this._tz, profile.autoLang);
631
646
 
647
+ await writeFile(join(profilePath, 'orbita.config'), JSON.stringify({ intl: intlConfig }, null, '\t'), { encoding: 'utf-8' }).catch(console.log);
648
+
649
+ this.browserLang = isMAC ? 'en-US' : checkAutoLangResult;
632
650
  const prefsToWrite = Object.assign(preferences, { gologin });
633
651
  if (this.browserMajorVersion >= this.newProxyOrbbitaMajorVersion && this.proxy?.mode !== 'none') {
634
652
  prefsToWrite.proxy = {
@@ -1020,7 +1038,7 @@ export class GoLogin {
1020
1038
  }
1021
1039
 
1022
1040
  async uploadProfileDataToServer() {
1023
- const cookies = await loadCookiesFromFile(this.cookiesFilePath);
1041
+ const cookies = await loadCookiesFromFile(this.cookiesFilePath, false, this.profile_id, this.tmpdir);
1024
1042
  const bookmarks = await getCurrentProfileBookmarks(this.bookmarksFilePath);
1025
1043
 
1026
1044
  const body = {
@@ -1375,15 +1393,6 @@ export class GoLogin {
1375
1393
  }
1376
1394
  }
1377
1395
 
1378
- async uploadProfileCookiesToServer() {
1379
- const cookies = await loadCookiesFromFile(this.cookiesFilePath);
1380
- if (!cookies.length) {
1381
- return;
1382
- }
1383
-
1384
- return this.postCookies(this.profile_id, cookies);
1385
- }
1386
-
1387
1396
  async saveBookmarksToDb() {
1388
1397
  const bookmarksData = await getCurrentProfileBookmarks(this.bookmarksFilePath);
1389
1398
  const bookmarks = bookmarksData.roots || {};
@@ -1420,6 +1429,7 @@ export class GoLogin {
1420
1429
 
1421
1430
  async stopLocal(options) {
1422
1431
  const opts = options || { posting: false };
1432
+ await new Promise(resolve => setTimeout(resolve, 1000));
1423
1433
  await this.stopAndCommit(opts, true);
1424
1434
  }
1425
1435
 
@@ -1,5 +1,5 @@
1
- export const checkAutoLang = (profileData, timezoneCheckResult) => {
2
- if (!profileData.autoLang) {
1
+ export const checkAutoLang = (profileData, timezoneCheckResult, autoLang) => {
2
+ if (!autoLang) {
3
3
  return checkBrowserLang(profileData);
4
4
  }
5
5
 
@@ -27,7 +27,7 @@ export const checkAutoLang = (profileData, timezoneCheckResult) => {
27
27
  return acc;
28
28
  }
29
29
 
30
- const qualityParam = 10-index;
30
+ const qualityParam = 10 - index;
31
31
  if (qualityParam > 0) {
32
32
  const separator = (resultLangsArr.length - index) < 2 ? '' : ',';
33
33
  gologinLangsArr.push(cur);
@@ -60,3 +60,61 @@ const checkBrowserLang = (profileData, defaultLocale = 'en-US') => {
60
60
 
61
61
  return defaultLocale;
62
62
  };
63
+
64
+ export const getIntlProfileConfig = (profileData, timezoneCheckResult, autoLang) => {
65
+ if (!autoLang) {
66
+ return checkBrowserLang(profileData);
67
+ }
68
+
69
+ let timezoneLang = '';
70
+ const { country: timezoneCountry = '', languages } = timezoneCheckResult;
71
+ if (!languages) {
72
+ return checkBrowserLang(profileData);
73
+ }
74
+
75
+ const [firstDetectedLangLocale] = languages.split(',');
76
+ // если есть languages, значит есть и timezoneCountry, иначе в languages пришла бы пустая строка
77
+ timezoneLang = `${firstDetectedLangLocale}-${timezoneCountry}` || '';
78
+
79
+ let resultLangsArr = [];
80
+ const [lang = '', country = ''] = timezoneLang.split('-');
81
+ if (country) {
82
+ resultLangsArr.push([lang, country].join('-'));
83
+ }
84
+
85
+ resultLangsArr.push(lang, 'en-US', 'en');
86
+ resultLangsArr = [...new Set(resultLangsArr)];
87
+
88
+ const mainLanguage = getMainLanguage(resultLangsArr);
89
+
90
+ return {
91
+ accept_languages: resultLangsArr.join(','),
92
+ selected_languages: resultLangsArr.join(','),
93
+ app_locale: mainLanguage,
94
+ forced_languages: [
95
+ mainLanguage,
96
+ ],
97
+ };
98
+ };
99
+
100
+ const mainLocaleList = ['af', 'am', 'ar', 'as', 'az', 'be', 'bg', 'bn', 'bs', 'ca', 'cs', 'cy', 'da', 'de', 'el', 'en-GB',
101
+ 'es-419', 'fr', 'fr-CA', 'gl', 'gu', 'he', 'hi', 'hr', 'hu', 'hy', 'id', 'is', 'it', 'ja', 'ka', 'kk', 'km', 'kn', 'ko', 'ky', 'lo', 'lt', 'lv',
102
+ 'ml', 'mn', 'mr', 'ms', 'my', 'nb', 'ne', 'nl', 'or', 'pa', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'si', 'sk', 'sl', 'sq', 'sr', 'sr-Latn', 'sv', 'sw',
103
+ 'ta', 'te', 'th', 'tr', 'uk', 'ur', 'uz', 'vi', 'zh-CN', 'zh-HK', 'zh-TW', 'zu', 'es', 'en-US', 'mk',
104
+ ];
105
+
106
+ const getMainLanguage = (langArr) => {
107
+ for (const lang of langArr) {
108
+ if (mainLocaleList.includes(lang)) {
109
+ return lang;
110
+ }
111
+
112
+ const [locale] = lang.split('-');
113
+ if (mainLocaleList.includes(locale)) {
114
+ return locale;
115
+ }
116
+ }
117
+
118
+ return '';
119
+ };
120
+
@@ -1,7 +1,7 @@
1
1
  import { exec } from 'child_process';
2
2
  import { promises as fsPromises } from 'fs';
3
3
  import { homedir } from 'os';
4
- import { join, sep } from 'path';
4
+ import { dirname, join, sep } from 'path';
5
5
  import { promisify } from 'util';
6
6
 
7
7
  import { deleteExtensionArchive, extractExtension } from '../extensions/extensions-extractor.js';
@@ -38,8 +38,10 @@ const getMacArmSpec = async () => {
38
38
 
39
39
  export const ensureDirectoryExists = async (filePath) => {
40
40
  try {
41
- const directory = filePath.substring(0, filePath.lastIndexOf('/'));
42
- await fsPromises.mkdir(directory, { recursive: true });
41
+ const directory = dirname(filePath);
42
+ if (directory && directory !== '.') {
43
+ await fsPromises.mkdir(directory, { recursive: true, force: true });
44
+ }
43
45
  } catch (error) {
44
46
  if (error.code !== 'EEXIST') {
45
47
  console.error('Error creating directory:', error.message);