123-lang 2.1.13 → 2.1.15

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 (18) hide show
  1. package/package.json +1 -1
  2. package/source/Customization/electron/last/electron-configuration/BitHideRoot.crt +21 -0
  3. package/source/Customization/electron/last/electron-configuration/Wallet.crt +20 -0
  4. package/source/Customization/electron/last/electron-configuration/configuration.js +121 -0
  5. package/source/Customization/electron/last/electron-configuration/configuration_.js +120 -0
  6. package/source/Customization/electron/last/electron-configuration/default-assets.js +16 -0
  7. package/source/Customization/electron/last/electron-configuration/messages.js +41 -0
  8. package/source/Customization/electron/last/electron-configuration/modules/WhiteLabelUpdater /342/200/223 default.js" +259 -0
  9. package/source/Customization/electron/last/electron-configuration/modules/WhiteLabelUpdater.js +273 -0
  10. package/source/Customization/electron/last/electron.js +335 -0
  11. package/source/Customization/electron/updated/electron-configuration/BitHideRoot.crt +21 -0
  12. package/source/Customization/electron/updated/electron-configuration/Wallet.crt +20 -0
  13. package/source/Customization/electron/updated/electron-configuration/configuration.js +121 -0
  14. package/source/Customization/electron/updated/electron-configuration/configuration_.js +120 -0
  15. package/source/Customization/electron/updated/electron-configuration/default-assets.js +16 -0
  16. package/source/Customization/electron/updated/electron-configuration/messages.js +41 -0
  17. package/source/Customization/electron/updated/electron-configuration/modules/WhiteLabelUpdater.js +259 -0
  18. package/source/Customization/electron/updated/electron.js +357 -0
@@ -0,0 +1,41 @@
1
+ const languages = ['en', 'ru', 'uk'];
2
+ const messages = {
3
+ en: {
4
+ 'Update is available': 'Update is available',
5
+ 'Now application will start updating and restart.': 'Now application will start updating and restart.',
6
+ Ok: 'Ok',
7
+ Later: 'Later',
8
+ 'There was a problem updating the application': 'There was a problem updating the application',
9
+ Cancel: 'Cancel',
10
+ 'Download manual': 'Download manual',
11
+ 'Download installer': 'Download installer',
12
+ },
13
+ ru: {
14
+ 'Update is available': 'Доступно обновление',
15
+ 'Now application will start updating and restart.': 'Сейчас будет произведено обновление и перезапуск приложения.',
16
+ Ok: 'Ок',
17
+ Later: 'Позже',
18
+ 'There was a problem updating the application': 'Возникла проблема с обновлением приложения',
19
+ Cancel: 'Закрыть',
20
+ 'Download manual': 'Скачать инструкцию',
21
+ 'Download installer': 'Скачать установщик',
22
+ },
23
+ uk: {
24
+ 'Update is available': 'Доступне оновлення',
25
+ 'Now application will start updating and restart.': 'Зараз буде виконано оновлення та перезавантаження додатку.',
26
+ Ok: 'Ок',
27
+ Later: 'Пiзнiше',
28
+ 'There was a problem updating the application': 'Під час оновлення програми виникла проблема',
29
+ Cancel: 'Закрити',
30
+ 'Download manual': 'Завантажити інструкцію',
31
+ 'Download installer': 'Завантажити інсталятор',
32
+ },
33
+ };
34
+
35
+ const t = (translation = '', lang = 'en') => messages[lang][translation];
36
+
37
+ module.exports = {
38
+ languages,
39
+ messages,
40
+ t,
41
+ };
@@ -0,0 +1,259 @@
1
+ const fs = require('fs');
2
+ const fsPromises = require('fs/promises');
3
+ const path = require('path');
4
+ const crypto = require('crypto');
5
+ const { app, nativeImage, shell } = require('electron');
6
+ const log = require('electron-log');
7
+ const { localStorage } = require('electron-browser-storage');
8
+ const os = require('os');
9
+ const axios = require('axios');
10
+
11
+ const { whiteLabelUpdaterConfiguration, config } = require('../configuration');
12
+
13
+ class WhiteLabelUpdater {
14
+ constructor() {
15
+ this.cachePath = path.join(
16
+ app.getPath(whiteLabelUpdaterConfiguration?.systemDir),
17
+ whiteLabelUpdaterConfiguration?.cacheDirName,
18
+ );
19
+ this.ensureDir();
20
+ }
21
+
22
+ ensureDir() {
23
+ if (!fs.existsSync(this.cachePath)) {
24
+ fs.mkdirSync(this.cachePath, { recursive: true });
25
+ }
26
+ }
27
+
28
+ getFilePath(serverUrl) {
29
+ const hash = crypto.createHash('md5').update(serverUrl).digest('hex');
30
+ return path.join(
31
+ this.cachePath,
32
+ `${hash}.${whiteLabelUpdaterConfiguration?.fileExtension?.json}`,
33
+ );
34
+ }
35
+
36
+ async safeWrite(filePath, data) {
37
+ const tempPath = `${filePath}.${whiteLabelUpdaterConfiguration?.fileExtension?.tmp}`;
38
+ await fsPromises.writeFile(tempPath, JSON.stringify(data), 'utf8');
39
+ await fsPromises.rename(tempPath, filePath);
40
+ }
41
+
42
+ async fetchWithTimeout(url) {
43
+ const controller = new AbortController();
44
+ const id = setTimeout(
45
+ () => controller.abort(),
46
+ whiteLabelUpdaterConfiguration?.timeOutMs,
47
+ );
48
+ try {
49
+ const response = await fetch(url, { signal: controller.signal });
50
+ clearTimeout(id);
51
+ return response;
52
+ } catch (error) {
53
+ clearTimeout(id);
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ async getWhiteLabelData(serverUrl) {
59
+ console.log('[WL] Get White Label Data');
60
+ if (!serverUrl) return whiteLabelUpdaterConfiguration?.defaultResult;
61
+
62
+ const normalizedUrl = serverUrl.replace(/\/$/, '');
63
+ const cacheFilePath = this.getFilePath(normalizedUrl);
64
+ console.log('[WL] normalizedUrl', normalizedUrl);
65
+ console.log('[WL] chacheFilePath', cacheFilePath);
66
+
67
+ let localCache = null;
68
+ try {
69
+ const raw = await fsPromises.readFile(cacheFilePath, 'utf8');
70
+ localCache = JSON.parse(raw);
71
+ } catch (e) {
72
+ console.error('[WL] There is something wrong with the cache');
73
+ }
74
+ let remoteConfig = null;
75
+ try {
76
+ console.log(
77
+ '[WL] fetch data',
78
+ `${normalizedUrl}${whiteLabelUpdaterConfiguration?.internalAssetsDir}${whiteLabelUpdaterConfiguration?.configFileName}`,
79
+ { timeout: 2000 },
80
+ );
81
+ const res = await axios.get(
82
+ `${normalizedUrl}${whiteLabelUpdaterConfiguration?.internalAssetsDir}${whiteLabelUpdaterConfiguration?.configFileName}`,
83
+ { timeout: 2000 },
84
+ );
85
+ console.log('[WL] data response', res);
86
+ remoteConfig = res.data;
87
+ console.log('[WL] remote config', remoteConfig);
88
+ } catch (e) {
89
+ console.error('[WL] Server unavailable, using cache fallback.');
90
+ }
91
+
92
+ if (!remoteConfig) {
93
+ return localCache
94
+ ? localCache.data
95
+ : whiteLabelUpdaterConfiguration?.defaultResult;
96
+ }
97
+
98
+ if (
99
+ localCache &&
100
+ localCache.data.version === remoteConfig.version &&
101
+ localCache.data.assets
102
+ ) {
103
+ console.info('[WL] Version match. Serving from cache.');
104
+
105
+ return { ...remoteConfig, assets: localCache.data.assets };
106
+ }
107
+
108
+ console.info(
109
+ '[WL] New version detected or no cache. Downloading assets...',
110
+ );
111
+
112
+ if (remoteConfig.enabled === false) {
113
+ const cleanData = {
114
+ ...whiteLabelUpdaterConfiguration?.defaultResult,
115
+ ...remoteConfig,
116
+ assets: { ...whiteLabelUpdaterConfiguration?.defaultResult?.assets },
117
+ };
118
+ await this.safeWrite(cacheFilePath, {
119
+ timestamp: Date.now(),
120
+ data: cleanData,
121
+ });
122
+ return cleanData;
123
+ }
124
+ const assets = { ...whiteLabelUpdaterConfiguration?.defaultResult?.assets };
125
+
126
+ // Replace your existing Promise.all block with this:
127
+ const assetResults = await Promise.all(
128
+ whiteLabelUpdaterConfiguration?.assetFiles?.map(async file => {
129
+ try {
130
+ const res = await axios.get(
131
+ `${normalizedUrl}${whiteLabelUpdaterConfiguration?.internalAssetsDir}${file}`,
132
+ { responseType: 'arraybuffer' },
133
+ );
134
+
135
+ const buffer = Buffer.from(res.data);
136
+ const ext = path.extname(file).toLowerCase().replace('.', '');
137
+
138
+ const mimeTypes = {
139
+ svg: 'image/svg+xml',
140
+ ico: 'image/x-icon',
141
+ png: 'image/png',
142
+ jpg: 'image/jpeg',
143
+ jpeg: 'image/jpeg',
144
+ };
145
+
146
+ const mime = mimeTypes[ext] || `image/${ext}`;
147
+ const b64 = buffer.toString('base64');
148
+
149
+ // Return an object representing this file's result
150
+ return { file, data: `data:${mime};base64,${b64}` };
151
+ } catch (err) {
152
+ console.error(`[WL] Failed to download asset: ${file}`, err.message);
153
+ return null; // Return null so we can filter it out
154
+ }
155
+ }),
156
+ );
157
+
158
+ // Map the results back into your assets object
159
+ assetResults.forEach(result => {
160
+ if (result) {
161
+ assets[result.file] = result.data;
162
+ }
163
+ });
164
+
165
+ const freshData = {
166
+ ...whiteLabelUpdaterConfiguration?.defaultResult,
167
+ ...remoteConfig,
168
+ assets: assets,
169
+ };
170
+ console.log(freshData);
171
+ await this.safeWrite(cacheFilePath, {
172
+ timestamp: Date.now(),
173
+ data: freshData,
174
+ });
175
+
176
+ return freshData;
177
+ }
178
+
179
+ async sendWhiteLabelDataForWeb(whiteLabelData) {
180
+ try {
181
+ await localStorage.setItem(
182
+ whiteLabelUpdaterConfiguration?.localStorageConfigName,
183
+ JSON.stringify(whiteLabelData),
184
+ );
185
+ log.info('[WL] Info successful send to web localstorage');
186
+ } catch (e) {
187
+ log.error('[WL] Error of saving to web localstorage', e);
188
+ }
189
+ }
190
+
191
+ createAppIcon(iconBase64String) {
192
+ try {
193
+ if (iconBase64String) {
194
+ const image = nativeImage.createFromDataURL(iconBase64String);
195
+ return image.resize(whiteLabelUpdaterConfiguration?.imageSize);
196
+ }
197
+ } catch (e) {
198
+ log.error('[WL] Unable to generate app icon', e);
199
+ }
200
+ return null;
201
+ }
202
+
203
+ updateShortcutWithBase64(base64String) {
204
+ const cleanBase64 = base64String.replace(/^data:.*?;base64,/, '');
205
+ const userDataPath = app.getPath(whiteLabelUpdaterConfiguration?.systemDir);
206
+ const uniqueIconName = `${
207
+ whiteLabelUpdaterConfiguration?.tempIconPrefix
208
+ }${Date.now()}.${whiteLabelUpdaterConfiguration?.fileExtension?.ico}`;
209
+ const iconPath = path.join(userDataPath, uniqueIconName);
210
+
211
+ try {
212
+ const files = fs.readdirSync(userDataPath);
213
+ files.forEach(file => {
214
+ if (
215
+ file.startsWith(whiteLabelUpdaterConfiguration?.tempIconPrefix) &&
216
+ file.endsWith(
217
+ `.${whiteLabelUpdaterConfiguration?.fileExtension?.ico}`,
218
+ )
219
+ ) {
220
+ fs.unlinkSync(path.join(userDataPath, file));
221
+ }
222
+ });
223
+
224
+ fs.writeFileSync(
225
+ iconPath,
226
+ cleanBase64,
227
+ whiteLabelUpdaterConfiguration?.fileExtension?.base64,
228
+ );
229
+
230
+ const desktopPath = path.join(
231
+ os.homedir(),
232
+ whiteLabelUpdaterConfiguration?.desktopDir,
233
+ `${config?.mainWindow?.title}.${whiteLabelUpdaterConfiguration?.fileExtension?.lnk}`,
234
+ );
235
+
236
+ const success = shell.writeShortcutLink(desktopPath, 'replace', {
237
+ target: process.execPath,
238
+ icon: iconPath,
239
+ iconIndex: 0,
240
+ cwd: path.dirname(process.execPath),
241
+ });
242
+
243
+ if (success) {
244
+ const now = new Date();
245
+ fs.utimesSync(desktopPath, now, now);
246
+
247
+ log.info(
248
+ `[WL] Shortcut successfully replaced and redrawn with: ${uniqueIconName}`,
249
+ );
250
+ } else {
251
+ log.info('[WL] Failed to replace the shortcut.');
252
+ }
253
+ } catch (e) {
254
+ log.error('[WL] Failed to update shortcut:', e);
255
+ }
256
+ }
257
+ }
258
+
259
+ module.exports = new WhiteLabelUpdater();
@@ -0,0 +1,273 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { app, nativeImage, shell } = require('electron');
4
+ const log = require('electron-log');
5
+ const { localStorage } = require('electron-browser-storage');
6
+ const os = require('os');
7
+ const axios = require('axios');
8
+
9
+ const { whiteLabelUpdaterConfiguration, config } = require('../configuration');
10
+
11
+ class WhiteLabelUpdater {
12
+ constructor() {
13
+ this.initStore().then();
14
+ }
15
+
16
+ async initStore() {
17
+ try {
18
+ const { default: Store } = await import('electron-store');
19
+ let store = new Store();
20
+ if (!store?.has('cache')) {
21
+ store.set('cache.default', {
22
+ ...whiteLabelUpdaterConfiguration?.defaultResult,
23
+ });
24
+ }
25
+ log.info('[WL] Store was created successful');
26
+ this.store = store;
27
+ } catch (err) {
28
+ log.error('[WL] There is some error on Store creation', err);
29
+ }
30
+ }
31
+
32
+ async checkLoginDomain() {
33
+ try {
34
+ const domainURL = await localStorage.getItem(config.storageNames.domain);
35
+ log.info('[WL] Domain checked', domainURL);
36
+ return domainURL;
37
+ } catch (err) {
38
+ log.error('[WL] There is an error on checking domain', err);
39
+ return null;
40
+ }
41
+ }
42
+
43
+ async getWhiteLabelStatus() {
44
+ const domain = await this.checkLoginDomain();
45
+ return this.readCache(domain);
46
+ }
47
+
48
+ async runWhiteLabelUpdater() {
49
+ const domain = await this.checkLoginDomain();
50
+ await this.cacheCheck(domain);
51
+ }
52
+
53
+ async cacheCheck(domain) {
54
+ try {
55
+ await this.writeCache(domain);
56
+ } catch (err) {
57
+ log.error('[WL] No information in cache', err);
58
+ }
59
+ }
60
+
61
+ async fetchConfig(domain) {
62
+ try {
63
+ log.info(
64
+ '[WL] fetch data',
65
+ `${domain}${whiteLabelUpdaterConfiguration?.internalAssetsDir}${whiteLabelUpdaterConfiguration?.configFileName}`,
66
+ );
67
+ const res = await axios.get(
68
+ `${domain}${whiteLabelUpdaterConfiguration?.internalAssetsDir}${whiteLabelUpdaterConfiguration?.configFileName}`,
69
+ { timeout: whiteLabelUpdaterConfiguration?.timeOutMs },
70
+ );
71
+ if (res.status === 200) {
72
+ log.info('[WL] response', res.status);
73
+ const remoteConfig = res.data;
74
+ log.info('[WL] remote config', remoteConfig);
75
+ return remoteConfig;
76
+ }
77
+ } catch (err) {
78
+ log.error('[WL] Server unavailable, using cache fallback.', err);
79
+ return null;
80
+ }
81
+ }
82
+
83
+ async fetchAssetsData(domain) {
84
+ const assets = { ...this.store.get('cache.default.assets') };
85
+
86
+ const assetResults = await Promise.all(
87
+ whiteLabelUpdaterConfiguration?.assetFiles?.map(async file => {
88
+ try {
89
+ const res = await axios.get(
90
+ `${domain}${whiteLabelUpdaterConfiguration?.internalAssetsDir}${file}`,
91
+ {
92
+ responseType: 'arraybuffer',
93
+ timeout: whiteLabelUpdaterConfiguration?.timeOutMs,
94
+ },
95
+ );
96
+
97
+ const buffer = Buffer.from(res.data);
98
+ const ext = path.extname(file).toLowerCase().replace('.', '');
99
+
100
+ const mimeTypes = {
101
+ svg: 'image/svg+xml',
102
+ ico: 'image/x-icon',
103
+ png: 'image/png',
104
+ jpg: 'image/jpeg',
105
+ jpeg: 'image/jpeg',
106
+ };
107
+
108
+ const mime = mimeTypes[ext] || `image/${ext}`;
109
+ const b64 = buffer.toString('base64');
110
+
111
+ return { file, data: `data:${mime};base64,${b64}` };
112
+ } catch (err) {
113
+ log.error(`[WL] Failed to download asset: ${file}`, err.message);
114
+ return null;
115
+ }
116
+ }),
117
+ );
118
+
119
+ assetResults.forEach(result => {
120
+ if (result) {
121
+ assets[result.file] = result.data;
122
+ }
123
+ });
124
+
125
+ return assets;
126
+ }
127
+
128
+ async writeCache(domain) {
129
+ if (!this.isValidUrl(domain)) return;
130
+ log.info('writeCache', domain);
131
+
132
+ const encodedDomain = this.encodeUrl(domain);
133
+ const config = await this.fetchConfig(domain);
134
+
135
+ if (this.store.has(`cache.${encodedDomain}`)) {
136
+ log.info('[WL] cache exists');
137
+ const currentConfig = this.store.get(`cache.${encodedDomain}`);
138
+ log.info(
139
+ '[WL] compare caches: ',
140
+ currentConfig?.version,
141
+ config?.version,
142
+ );
143
+ if (config !== null && config?.version > currentConfig?.version) {
144
+ log.info('[WL] cache updating ...', domain);
145
+ const remoteAssets = await this.fetchAssetsData(domain);
146
+ this.store.set(`cache.${encodedDomain}`, {
147
+ ...config,
148
+ assets: { ...remoteAssets },
149
+ });
150
+ }
151
+ } else {
152
+ log.info('[WL] cache not exists');
153
+ if (config !== null) {
154
+ log.info('[WL] cache creating ...', domain);
155
+ const remoteAssets = await this.fetchAssetsData(domain);
156
+ this.store.set(`cache.${encodedDomain}`, {
157
+ ...config,
158
+ assets: { ...remoteAssets },
159
+ });
160
+ }
161
+ }
162
+ }
163
+
164
+ readCache(domain) {
165
+ const encodedDomain = this.encodeUrl(domain);
166
+ return this.store.has(`cache.${encodedDomain}`)
167
+ ? this.store.get(`cache.${encodedDomain}`)
168
+ : this.store.get('cache.default');
169
+ }
170
+
171
+ encodeUrl(url) {
172
+ return Array.from(new TextEncoder().encode(url))
173
+ .map(byte => byte.toString(16).padStart(2, '0'))
174
+ .join('');
175
+ }
176
+
177
+ decodeUrl(hexString) {
178
+ const bytes = new Uint8Array(
179
+ hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)),
180
+ );
181
+ return new TextDecoder().decode(bytes);
182
+ }
183
+
184
+ isValidUrl(string) {
185
+ try {
186
+ new URL(string);
187
+ return true;
188
+ } catch (err) {
189
+ return false;
190
+ }
191
+ }
192
+
193
+ async sendWhiteLabelDataForWeb(whiteLabelData) {
194
+ try {
195
+ await localStorage.setItem(
196
+ whiteLabelUpdaterConfiguration?.localStorageConfigName,
197
+ JSON.stringify(whiteLabelData),
198
+ );
199
+ log.info('[WL] Info successful send to web localstorage');
200
+ } catch (e) {
201
+ log.error('[WL] Error of saving to web localstorage', e);
202
+ }
203
+ }
204
+
205
+ createAppIcon(iconBase64String) {
206
+ try {
207
+ if (iconBase64String) {
208
+ const image = nativeImage.createFromDataURL(iconBase64String);
209
+ return image.resize(whiteLabelUpdaterConfiguration?.imageSize);
210
+ }
211
+ } catch (e) {
212
+ log.error('[WL] Unable to generate app icon', e);
213
+ }
214
+ return null;
215
+ }
216
+
217
+ updateShortcutWithBase64(base64String) {
218
+ const cleanBase64 = base64String.replace(/^data:.*?;base64,/, '');
219
+ const userDataPath = app.getPath(whiteLabelUpdaterConfiguration?.systemDir);
220
+ const uniqueIconName = `${
221
+ whiteLabelUpdaterConfiguration?.tempIconPrefix
222
+ }${Date.now()}.${whiteLabelUpdaterConfiguration?.fileExtension?.ico}`;
223
+ const iconPath = path.join(userDataPath, uniqueIconName);
224
+
225
+ try {
226
+ const files = fs.readdirSync(userDataPath);
227
+ files.forEach(file => {
228
+ if (
229
+ file.startsWith(whiteLabelUpdaterConfiguration?.tempIconPrefix) &&
230
+ file.endsWith(
231
+ `.${whiteLabelUpdaterConfiguration?.fileExtension?.ico}`,
232
+ )
233
+ ) {
234
+ fs.unlinkSync(path.join(userDataPath, file));
235
+ }
236
+ });
237
+
238
+ fs.writeFileSync(
239
+ iconPath,
240
+ cleanBase64,
241
+ whiteLabelUpdaterConfiguration?.fileExtension?.base64,
242
+ );
243
+
244
+ const desktopPath = path.join(
245
+ os.homedir(),
246
+ whiteLabelUpdaterConfiguration?.desktopDir,
247
+ `${config?.mainWindow?.title}.${whiteLabelUpdaterConfiguration?.fileExtension?.lnk}`,
248
+ );
249
+
250
+ const success = shell.writeShortcutLink(desktopPath, 'replace', {
251
+ target: process.execPath,
252
+ icon: iconPath,
253
+ iconIndex: 0,
254
+ cwd: path.dirname(process.execPath),
255
+ });
256
+
257
+ if (success) {
258
+ const now = new Date();
259
+ fs.utimesSync(desktopPath, now, now);
260
+
261
+ log.info(
262
+ `[WL] Shortcut successfully replaced and redrawn with: ${uniqueIconName}`,
263
+ );
264
+ } else {
265
+ log.info('[WL] Failed to replace the shortcut.');
266
+ }
267
+ } catch (e) {
268
+ log.error('[WL] Failed to update shortcut:', e);
269
+ }
270
+ }
271
+ }
272
+
273
+ module.exports = new WhiteLabelUpdater();