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,164 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.unixToLDAP = exports.loadCookiesFromFile = exports.ldapToUnix = exports.getDB = exports.getCookiesFilePath = exports.getChunckedInsertValues = exports.chunk = exports.buildCookieURL = void 0;
7
+ var _sqlite = require("sqlite");
8
+ var _sqlite2 = _interopRequireDefault(require("sqlite3"));
9
+ var _fs = require("fs");
10
+ var _path = require("path");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ const {
13
+ access
14
+ } = _fs.promises;
15
+ const {
16
+ Database,
17
+ OPEN_READONLY
18
+ } = _sqlite2.default;
19
+ const MAX_SQLITE_VARIABLES = 76;
20
+ const SAME_SITE = {
21
+ '-1': 'unspecified',
22
+ 0: 'no_restriction',
23
+ 1: 'lax',
24
+ 2: 'strict'
25
+ };
26
+ const getDB = (filePath, readOnly = true) => {
27
+ const connectionOpts = {
28
+ filename: filePath,
29
+ driver: Database
30
+ };
31
+ if (readOnly) {
32
+ connectionOpts.mode = OPEN_READONLY;
33
+ }
34
+ return (0, _sqlite.open)(connectionOpts);
35
+ };
36
+ exports.getDB = getDB;
37
+ const getChunckedInsertValues = cookiesArr => {
38
+ const todayUnix = Math.floor(new Date().getTime() / 1000.0);
39
+ const chunckedCookiesArr = chunk(cookiesArr, MAX_SQLITE_VARIABLES);
40
+ return chunckedCookiesArr.map(cookies => {
41
+ const queryPlaceholders = cookies.map(() => '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').join(', ');
42
+ const query = `insert or replace into cookies (creation_utc, host_key, top_frame_site_key, name, value, encrypted_value, path, expires_utc, is_secure, is_httponly, last_access_utc, has_expires, is_persistent, priority, samesite, source_scheme, source_port, is_same_party, last_update_utc) values ${queryPlaceholders}`;
43
+ const queryParams = cookies.flatMap(cookie => {
44
+ const creationDate = cookie.creationDate ? cookie.creationDate : unixToLDAP(todayUnix);
45
+ let expirationDate = cookie.session ? 0 : unixToLDAP(cookie.expirationDate);
46
+ const encryptedValue = cookie.value;
47
+ const samesite = Object.keys(SAME_SITE).find(key => SAME_SITE[key] === (cookie.sameSite || '-1'));
48
+ const isSecure = cookie.name.startsWith('__Host-') || cookie.name.startsWith('__Secure-') ? 1 : Number(cookie.secure);
49
+ const sourceScheme = isSecure === 1 ? 2 : 1;
50
+ const sourcePort = isSecure === 1 ? 443 : 80;
51
+ // eslint-disable-next-line no-undefined
52
+ let isPersistent = [undefined, null].includes(cookie.session) ? Number(expirationDate !== 0) : Number(!cookie.session);
53
+ if (/^(\.)?mail.google.com$/.test(cookie.domain) && cookie.name === 'COMPASS') {
54
+ expirationDate = 0;
55
+ isPersistent = 0;
56
+ }
57
+ return [creationDate, cookie.domain, '',
58
+ // top_frame_site_key
59
+ cookie.name, '',
60
+ // value
61
+ encryptedValue, cookie.path, expirationDate, isSecure, Number(cookie.httpOnly), 0,
62
+ // last_access_utc
63
+ expirationDate === 0 ? 0 : 1,
64
+ // has_expires
65
+ isPersistent, 1,
66
+ // default priority value (https://github.com/chromium/chromium/blob/main/net/cookies/cookie_constants.h)
67
+ samesite, sourceScheme, sourcePort, 0,
68
+ // is_same_party
69
+ 0 // last_update_utc
70
+ ];
71
+ });
72
+ return [query, queryParams];
73
+ });
74
+ };
75
+ exports.getChunckedInsertValues = getChunckedInsertValues;
76
+ const loadCookiesFromFile = async filePath => {
77
+ let db;
78
+ const cookies = [];
79
+ try {
80
+ db = await getDB(filePath);
81
+ const cookiesRows = await db.all('select * from cookies');
82
+ for (const row of cookiesRows) {
83
+ const {
84
+ host_key,
85
+ name,
86
+ encrypted_value,
87
+ path,
88
+ is_secure,
89
+ is_httponly,
90
+ expires_utc,
91
+ is_persistent,
92
+ samesite,
93
+ creation_utc
94
+ } = row;
95
+ cookies.push({
96
+ url: buildCookieURL(host_key, is_secure, path),
97
+ domain: host_key,
98
+ name,
99
+ value: encrypted_value,
100
+ path,
101
+ sameSite: SAME_SITE[samesite],
102
+ secure: Boolean(is_secure),
103
+ httpOnly: Boolean(is_httponly),
104
+ hostOnly: !host_key.startsWith('.'),
105
+ session: !is_persistent,
106
+ expirationDate: ldapToUnix(expires_utc),
107
+ creationDate: ldapToUnix(creation_utc)
108
+ });
109
+ }
110
+ } catch (error) {
111
+ console.log(error);
112
+ } finally {
113
+ db && (await db.close());
114
+ }
115
+ return cookies;
116
+ };
117
+ exports.loadCookiesFromFile = loadCookiesFromFile;
118
+ const unixToLDAP = unixtime => {
119
+ if (unixtime === 0) {
120
+ return unixtime;
121
+ }
122
+ const win32filetime = new Date(Date.UTC(1601, 0, 1)).getTime() / 1000;
123
+ const sum = unixtime - win32filetime;
124
+ return sum * 1000000;
125
+ };
126
+ exports.unixToLDAP = unixToLDAP;
127
+ const ldapToUnix = ldap => {
128
+ const ldapLength = ldap.toString().length;
129
+ if (ldap === 0 || ldapLength > 18) {
130
+ return ldap;
131
+ }
132
+ let _ldap = ldap;
133
+ if (ldapLength < 18) {
134
+ _ldap = Number(_ldap + '0'.repeat(18 - ldapLength));
135
+ }
136
+ const win32filetime = new Date(Date.UTC(1601, 0, 1)).getTime();
137
+ return (_ldap / 10000 + win32filetime) / 1000;
138
+ };
139
+ exports.ldapToUnix = ldapToUnix;
140
+ const buildCookieURL = (domain, secure, path) => {
141
+ let domainWithoutDot = domain;
142
+ if (domain.startsWith('.')) {
143
+ domainWithoutDot = domain.substr(1);
144
+ }
145
+ return 'http' + (secure ? 's' : '') + '://' + domainWithoutDot + path;
146
+ };
147
+ exports.buildCookieURL = buildCookieURL;
148
+ const chunk = (arr, chunkSize = 1, cache = []) => {
149
+ const tmp = [...arr];
150
+ if (chunkSize <= 0) {
151
+ return cache;
152
+ }
153
+ while (tmp.length) {
154
+ cache.push(tmp.splice(0, chunkSize));
155
+ }
156
+ return cache;
157
+ };
158
+ exports.chunk = chunk;
159
+ const getCookiesFilePath = async (profileId, tmpdir) => {
160
+ const baseCookiesFilePath = (0, _path.join)(tmpdir, `gologin_profile_${profileId}`, 'Default', 'Cookies');
161
+ const bypassCookiesFilePath = (0, _path.join)(tmpdir, `gologin_profile_${profileId}`, 'Default', 'Network', 'Cookies');
162
+ return access(baseCookiesFilePath).then(() => baseCookiesFilePath).catch(() => access(bypassCookiesFilePath).then(() => bypassCookiesFilePath).catch(() => baseCookiesFilePath));
163
+ };
164
+ exports.getCookiesFilePath = getCookiesFilePath;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.extractExtension = exports.deleteExtensionArchive = void 0;
7
+ var _decompress = _interopRequireDefault(require("decompress"));
8
+ var _decompressUnzip = _interopRequireDefault(require("decompress-unzip"));
9
+ var _fs = require("fs");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const {
12
+ access,
13
+ unlink
14
+ } = _fs.promises;
15
+ const extractExtension = (source, dest) => {
16
+ if (!(source && dest)) {
17
+ throw new Error('Missing parameter');
18
+ }
19
+ return access(source).then(() => withRetry({
20
+ fn() {
21
+ return (0, _decompress.default)(source, dest, {
22
+ plugins: [(0, _decompressUnzip.default)()],
23
+ filter: file => !file.path.endsWith('/')
24
+ });
25
+ }
26
+ }));
27
+ };
28
+ exports.extractExtension = extractExtension;
29
+ const deleteExtensionArchive = dest => {
30
+ if (!dest) {
31
+ throw new Error('Missing parameter');
32
+ }
33
+ return access(dest).then(() => unlink(dest), () => Promise.resolve());
34
+ };
35
+ exports.deleteExtensionArchive = deleteExtensionArchive;
36
+ const withRetry = optionsOrUndefined => {
37
+ const opts = optionsOrUndefined || {};
38
+ const callCounter = opts.callCounter || 1;
39
+ const fnToProducePromise = opts.fn;
40
+ const callLimit = opts.limit || 5;
41
+ delete opts.callCounter;
42
+ return fnToProducePromise(opts).catch(err => {
43
+ console.error(err);
44
+ if (callCounter >= callLimit) {
45
+ return Promise.reject(err);
46
+ }
47
+ opts.callCounter = callCounter + 1;
48
+ return new Promise(resolve => process.nextTick(resolve)).then(() => withRetry(opts));
49
+ });
50
+ };
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.ExtensionsManager = void 0;
7
+ var _fs = require("fs");
8
+ var _path = require("path");
9
+ var _requestretry = _interopRequireDefault(require("requestretry"));
10
+ var _common = require("../utils/common.js");
11
+ var _userExtensionsManager = _interopRequireDefault(require("./user-extensions-manager.js"));
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ const {
14
+ mkdir,
15
+ readdir,
16
+ rmdir,
17
+ unlink
18
+ } = _fs.promises;
19
+ const EXTENSION_URL = 'https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D{ext_id}%26uc&prodversion=97.0.4692.71';
20
+ class ExtensionsManager extends _userExtensionsManager.default {
21
+ #existedChromeExtensions = [];
22
+ #inited = false;
23
+ #useLocalExtStorage = false;
24
+ #useCookiesExt = false;
25
+ #deleteProfileExtFolders = false;
26
+ #extensionsUpdating = true;
27
+ constructor() {
28
+ super();
29
+ if (!ExtensionsManager.instance) {
30
+ ExtensionsManager.instance = this;
31
+ }
32
+ return ExtensionsManager.instance;
33
+ }
34
+ async init() {
35
+ if (this.#inited) {
36
+ return Promise.resolve();
37
+ }
38
+ const promises = [mkdir(_common.CHROME_EXTENSIONS_PATH, {
39
+ recursive: true
40
+ }).then(() => readdir(_common.CHROME_EXTENSIONS_PATH)).then(filesList => {
41
+ this.#existedChromeExtensions = filesList.filter(extPath => !extPath.includes('.zip'));
42
+ return filesList.map(fileName => fileName.includes('.zip') ? unlink((0, _path.join)(_common.CHROME_EXTENSIONS_PATH, fileName)) : Promise.resolve());
43
+ }).then(promisesToDelete => Promise.all(promisesToDelete)).catch(e => console.log('ExtensionsManager init error:', e)), mkdir(_common.USER_EXTENSIONS_PATH, {
44
+ recursive: true
45
+ }).then(() => readdir(_common.USER_EXTENSIONS_PATH)).then(filesList => {
46
+ this.existedUserExtensions = filesList.filter(extPath => !extPath.includes('.zip'));
47
+ return filesList.map(fileName => fileName.includes('.zip') ? unlink((0, _path.join)(_common.USER_EXTENSIONS_PATH, fileName)) : Promise.resolve());
48
+ }).then(promisesToDelete => Promise.all(promisesToDelete)).catch(e => console.log('error creating user extensions folder:', e))];
49
+ return Promise.all(promises).then(() => this.#inited = true);
50
+ }
51
+ get isInited() {
52
+ return this.#inited;
53
+ }
54
+ get useLocalExtStorage() {
55
+ return this.#useLocalExtStorage;
56
+ }
57
+ get deleteProfileExtFolders() {
58
+ return this.#deleteProfileExtFolders;
59
+ }
60
+ get useCookiesExt() {
61
+ return this.#useCookiesExt;
62
+ }
63
+ get existedChromeExtensionsList() {
64
+ return this.#existedChromeExtensions;
65
+ }
66
+ async checkChromeExtensions(profileExtensions = []) {
67
+ if (!(Array.isArray(profileExtensions) && profileExtensions.length)) {
68
+ return [];
69
+ }
70
+ const extensionsToDownload = this.#getExtensionsToDownload(profileExtensions);
71
+ const downloadedArchives = await this.downloadChromeExtensions(extensionsToDownload);
72
+ const filteredArchives = downloadedArchives.filter(Boolean);
73
+ if (filteredArchives.length) {
74
+ const [downloadedFolders] = filteredArchives.map(archivePath => archivePath.split(_path.sep).reverse());
75
+ this.#existedChromeExtensions = [...this.#existedChromeExtensions, ...downloadedFolders];
76
+ const promises = (0, _common.composeExtractionPromises)(filteredArchives);
77
+ await Promise.all(promises);
78
+ }
79
+ return this.getExtensionsStrToIncludeAsOrbitaParam(profileExtensions);
80
+ }
81
+ #getExtensionsToDownload(profileExtensions) {
82
+ const existedExtensionsFolders = [...this.#existedChromeExtensions, ...this.existedUserExtensions];
83
+ const existedOriginalIds = existedExtensionsFolders.map(val => {
84
+ const [originalId] = val.split('@');
85
+ return originalId;
86
+ });
87
+ return profileExtensions.reduce((res, val) => {
88
+ const [originalId] = val.split('@');
89
+ const extensionExists = existedOriginalIds.includes(originalId);
90
+ if (!extensionExists) {
91
+ res.push(val);
92
+ }
93
+ return res;
94
+ }, []);
95
+ }
96
+ async downloadChromeExtensions(idsToDownload = []) {
97
+ if (!(Array.isArray(idsToDownload) && idsToDownload.length)) {
98
+ return [];
99
+ }
100
+ const promises = idsToDownload.map(async id => {
101
+ const [originalId] = id.split('@');
102
+ const extUrl = EXTENSION_URL.replace('{ext_id}', originalId);
103
+ const uploadedProfileMetadata = await getExtMetadata(extUrl);
104
+ const reqPath = uploadedProfileMetadata.req.path;
105
+ const extVer = getExtVersion(reqPath);
106
+ const buffer = await new Promise(res => {
107
+ const chunks = [];
108
+ _requestretry.default.get(extUrl, {
109
+ maxAttempts: 3,
110
+ retryDelay: 1000,
111
+ timeout: 8 * 1000,
112
+ fullResponse: false
113
+ }).on('data', data => chunks.push(data)).on('end', () => res(Buffer.concat(chunks)));
114
+ });
115
+ let zipExt;
116
+ try {
117
+ zipExt = crxToZip(buffer);
118
+ } catch (e) {
119
+ console.log(e);
120
+ return '';
121
+ }
122
+ const archiveZipPath = (0, _path.join)(_common.CHROME_EXTENSIONS_PATH, originalId + '@' + extVer + '.zip');
123
+ const archiveZip = (0, _fs.createWriteStream)(archiveZipPath);
124
+ archiveZip.write(zipExt);
125
+ archiveZip.close();
126
+ return new Promise(r => archiveZip.on('close', () => r(archiveZipPath)));
127
+ });
128
+ return Promise.all(promises);
129
+ }
130
+ async getExtensionsPolicies() {
131
+ const globalExtConfig = await _requestretry.default.get(`${this.apiBaseUrl}/gologin-settings/chrome_ext_policies`, {
132
+ headers: {
133
+ Authorization: `Bearer ${this.accessToken}`,
134
+ 'user-agent': this.userAgent,
135
+ 'x-two-factor-token': this.twoFaKey || ''
136
+ },
137
+ json: true,
138
+ maxAttempts: 2,
139
+ retryDelay: 1000,
140
+ timeout: 10 * 1000,
141
+ fullResponse: false
142
+ });
143
+ const chromeExtPolicies = globalExtConfig?.chromeExtPolicies || {};
144
+ const {
145
+ useLocalExtStorage = false,
146
+ deleteProfileExtFolders = false,
147
+ useCookiesExt = true
148
+ } = chromeExtPolicies;
149
+ this.#useLocalExtStorage = useLocalExtStorage;
150
+ this.#deleteProfileExtFolders = deleteProfileExtFolders;
151
+ this.#useCookiesExt = useCookiesExt;
152
+ }
153
+ async updateExtensions() {
154
+ const fileList = await readdir(_common.CHROME_EXTENSIONS_PATH).catch(() => []);
155
+ if (!fileList.length) {
156
+ return;
157
+ }
158
+ const oldFolders = [];
159
+ const versionCheckPromises = fileList.map(async extension => {
160
+ if (!extension.includes('@') || extension.includes('.zip')) {
161
+ return '';
162
+ }
163
+ const [originalId, currentVersion] = extension.split('@');
164
+ const extUrl = EXTENSION_URL.replace('{ext_id}', originalId);
165
+ const uploadedProfileMetadata = await getExtMetadata(extUrl);
166
+ const reqPath = uploadedProfileMetadata.req.path;
167
+ const availableVersion = getExtVersion(reqPath);
168
+ if (currentVersion === availableVersion) {
169
+ return '';
170
+ }
171
+ oldFolders.push((0, _path.join)(_common.CHROME_EXTENSIONS_PATH, extension));
172
+ return originalId;
173
+ });
174
+ const extensionsNames = (await Promise.all(versionCheckPromises)).filter(Boolean);
175
+ const archivesPaths = (await this.downloadChromeExtensions(extensionsNames)).filter(Boolean);
176
+ const extractionPromises = (0, _common.composeExtractionPromises)(archivesPaths);
177
+ await Promise.all(extractionPromises);
178
+ const removeFoldersPromises = oldFolders.map(folder => rmdir(folder, {
179
+ recursive: true,
180
+ maxRetries: 3
181
+ }).catch(() => {}));
182
+ await Promise.all(removeFoldersPromises).then(() => this.#extensionsUpdating = false);
183
+ }
184
+ async checkLocalExtensions() {
185
+ if (this.#extensionsUpdating || !this.accessToken) {
186
+ return;
187
+ }
188
+ const fileList = await readdir(_common.CHROME_EXTENSIONS_PATH).catch(() => []);
189
+ if (!fileList.length) {
190
+ return;
191
+ }
192
+ const extensionsIds = fileList.filter(folderName => folderName.includes('@') && !folderName.includes('.zip')).map(folderName => {
193
+ const [name] = folderName.split('@');
194
+ return name;
195
+ });
196
+ if (!extensionsIds.length) {
197
+ return;
198
+ }
199
+ this.insertExtensionsToDb(extensionsIds);
200
+ }
201
+ async insertExtensionsToDb(extensionsIds, pathToExtensions = _common.CHROME_EXTENSIONS_PATH) {
202
+ if (!extensionsIds?.length) {
203
+ return;
204
+ }
205
+ const checkResponse = await (0, _requestretry.default)(`${this.apiBaseUrl}/extensions/check`, {
206
+ method: 'POST',
207
+ headers: {
208
+ Authorization: `Bearer ${this.accessToken}`,
209
+ 'user-agent': this.userAgent,
210
+ 'x-two-factor-token': this.twoFaKey || ''
211
+ },
212
+ body: {
213
+ extensionsIds
214
+ },
215
+ json: true
216
+ });
217
+ const {
218
+ extensionsToAdd = []
219
+ } = checkResponse.body;
220
+ if (!extensionsToAdd.length) {
221
+ return;
222
+ }
223
+ const extensionsToUpdate = await this.getExtensionsNameAndImage(extensionsToAdd, pathToExtensions);
224
+ (0, _requestretry.default)(`${this.apiBaseUrl}/extensions/create`, {
225
+ method: 'POST',
226
+ headers: {
227
+ Authorization: `Bearer ${this.accessToken}`,
228
+ 'user-agent': this.userAgent,
229
+ 'x-two-factor-token': this.twoFaKey || ''
230
+ },
231
+ body: {
232
+ extensionsInfo: extensionsToUpdate
233
+ },
234
+ json: true
235
+ });
236
+ }
237
+ getExtensionsToInstall(extensionsFromPref, extensionsFromDB) {
238
+ if (!extensionsFromPref) {
239
+ return [];
240
+ }
241
+ const objectEntries = Object.entries(extensionsFromPref);
242
+ const extensionsInPref = objectEntries?.map(([_, settings]) => {
243
+ const [extFolderName] = settings.path.split(_path.sep).reverse();
244
+ const [originalId] = extFolderName.split('@');
245
+ return originalId;
246
+ }) || [];
247
+ return extensionsFromDB.reduce((acc, extension) => {
248
+ const [extFolderName] = extension.split(_path.sep).reverse();
249
+ const [originalId] = extFolderName.split('@');
250
+ if (!extensionsInPref.includes(originalId)) {
251
+ acc.push(extension);
252
+ }
253
+ return acc;
254
+ }, []);
255
+ }
256
+ }
257
+ exports.ExtensionsManager = ExtensionsManager;
258
+ const crxToZip = buf => {
259
+ if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4) {
260
+ return buf;
261
+ }
262
+ if (!(buf[0] === 67 || buf[1] === 114 || buf[2] === 50 || buf[3] === 52)) {
263
+ throw new Error('Invalid header: Does not start with Cr24');
264
+ }
265
+ const isV3 = buf[4] === 3;
266
+ const isV2 = buf[4] === 2;
267
+ if (!(isV2 || isV3) || buf[5] || buf[6] || buf[7]) {
268
+ throw new Error('Unexpected crx format version number.');
269
+ }
270
+ if (isV2) {
271
+ const publicKeyLength = calcLength(buf[8], buf[9], buf[10], buf[11]);
272
+ const signatureLength = calcLength(buf[12], buf[13], buf[14], buf[15]);
273
+ const zipStartOffset = 16 + publicKeyLength + signatureLength;
274
+ return buf.slice(zipStartOffset, buf.length);
275
+ }
276
+ const headerSize = calcLength(buf[8], buf[9], buf[10], buf[11]);
277
+ const zipStartOffset = 12 + headerSize;
278
+ return buf.slice(zipStartOffset, buf.length);
279
+ };
280
+ const calcLength = (a, b, c, d) => {
281
+ let length = 0;
282
+ length += a << 0;
283
+ length += b << 8;
284
+ length += c << 16;
285
+ length += d << 24 >>> 0;
286
+ return length;
287
+ };
288
+ const getExtMetadata = extUrl => _requestretry.default.head(extUrl, {
289
+ maxAttempts: 3,
290
+ retryDelay: 2000,
291
+ timeout: 2 * 1000,
292
+ fullResponse: true
293
+ });
294
+ const getExtVersion = metadata => {
295
+ const [extFullName = ''] = metadata.split('/').reverse();
296
+ const [extName = ''] = extFullName.split('.');
297
+ const splitExtName = extName.split('_');
298
+ splitExtName.shift();
299
+ return splitExtName.join('_');
300
+ };
301
+ var _default = exports.default = ExtensionsManager;