@plasosdk/plaso-electron-sdk 1.0.6

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/index.js ADDED
@@ -0,0 +1,6 @@
1
+ const { ipcMain } = require('electron');
2
+ if (ipcMain) {
3
+ module.exports = require('./js/main.js');
4
+ } else {
5
+ module.exports = require('./js/render.js');
6
+ }
package/js/code.js ADDED
@@ -0,0 +1,34 @@
1
+ const ERROR_CODE = {
2
+ /** 非 electron 环境 */
3
+ NO_ELECTRON_ENVIRONMENT: -1,
4
+ COMMOM_ERROR: -99,
5
+ };
6
+
7
+ const LESSON_TYPE = {
8
+ /** 课堂 */
9
+ LIVECLASS: 'liveClass',
10
+ /** 备课 */
11
+ PREPARE_LESSONS: 'prepareLesson',
12
+ };
13
+
14
+ /** 课堂窗口与外部窗口通讯的消息 */
15
+ const CLASS_WINDOW_MESG_TYPE = {
16
+ /** 课堂dom渲染成功后告知外部应用窗口,传参用户信息 */
17
+ LIVE_WINDOW_READY: 'liveWindowReady',
18
+ /** 离开课堂 */
19
+ ON_CLASS_FINISHED: 'onClassFinished',
20
+ };
21
+
22
+ const LEVEL = {
23
+ error: 3,
24
+ warn: 2,
25
+ info: 1,
26
+ debug: 0,
27
+ };
28
+
29
+ module.exports = {
30
+ LESSON_TYPE,
31
+ ERROR_CODE,
32
+ CLASS_WINDOW_MESG_TYPE,
33
+ LEVEL
34
+ };
package/js/common.js ADDED
@@ -0,0 +1,99 @@
1
+ function versionComp(newVersion, oldVersion) {
2
+ const newVersionList = (newVersion || '0').split('.');
3
+ const oldVersionList = (oldVersion || '0').split('.');
4
+ const length = newVersionList.length > oldVersionList.length ? newVersionList.length : oldVersionList.length;
5
+ for (let i = 0; i < length; i++) {
6
+ const newVersionValue = newVersionList[i] == undefined ? 0 : parseInt(newVersionList[i]);
7
+ const oldVersionValue = oldVersionList[i] == undefined ? 0 : parseInt(oldVersionList[i]);
8
+ const res = newVersionValue - oldVersionValue;
9
+ if (res !== 0) {
10
+ return res;
11
+ }
12
+ }
13
+ return 0;
14
+ }
15
+
16
+ function getElectronRemote() {
17
+ let _remote;
18
+ try {
19
+ _remote = window.require('electron').remote;
20
+ } catch (e) {
21
+ try {
22
+ _remote = window.require('@electron/remote');
23
+ } catch (err) {
24
+ console.error(err);
25
+ throw new Error('illegal call, non electron environment');
26
+ }
27
+ }
28
+ return _remote;
29
+ }
30
+
31
+ function parseUrlParams(url) {
32
+ const params = {};
33
+ const queryString = url.split('?')[1];
34
+
35
+ if (!queryString) return params;
36
+
37
+ queryString.split('&').forEach((pair) => {
38
+ const [key, value] = pair.split('=');
39
+ let decodedValue = decodeURIComponent(value || '');
40
+ if (decodedValue === 'true' || decodedValue === 'false') {
41
+ decodedValue = decodedValue === 'true';
42
+ }
43
+ params[key] = decodedValue;
44
+ });
45
+
46
+ return params;
47
+ }
48
+
49
+ function getEnvironment(url) {
50
+ const host = url ?? location.host
51
+ .replace('wwwr', 'www')
52
+ .replace('devai', 'dev')
53
+ .replace('testai', 'test')
54
+ .replace('itestai', 'itest')
55
+ .replace('bai', 'b')
56
+ .replace('ai-cdn', 'www')
57
+ .replace('ai.', 'www.')
58
+ .toLocaleUpperCase();
59
+ const index = host.indexOf('.');
60
+ let environment = '';
61
+ //先根据url判断环境。这里single页面访问会用到
62
+ if (/^192\.|localhost/.test(host)) {
63
+ environment = 'local';
64
+ } else {
65
+ environment = host.substring(0, index);
66
+ }
67
+ return environment;
68
+ }
69
+
70
+ /**
71
+ * 获取当前BrowserWindow实例
72
+ */
73
+ function getCurrentWindow() {
74
+ const remote = getElectronRemote();
75
+ if (remote) {
76
+ return remote.getCurrentWindow();
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 获取窗口所属的屏幕(当应用跨屏幕时,应该属于占用面积超过一半的那块屏幕)
82
+ */
83
+ function getDisplayMatching() {
84
+ const remote = getElectronRemote();
85
+ const currentWindow = getCurrentWindow();
86
+ if (remote && currentWindow) {
87
+ const { screen } = remote;
88
+ const currentWindowBounds = currentWindow.getBounds();
89
+ return screen.getDisplayMatching(currentWindowBounds);
90
+ }
91
+ }
92
+
93
+ module.exports = {
94
+ versionComp,
95
+ getElectronRemote,
96
+ parseUrlParams,
97
+ getEnvironment,
98
+ getDisplayMatching
99
+ };
package/js/main.js ADDED
@@ -0,0 +1,23 @@
1
+ const isElectron = !!process.versions['electron'];
2
+ if (isElectron) {
3
+ try {
4
+ require('@plasosdk/winproxy');
5
+ require('@plasosdk/screenshot');
6
+ require('@plasosdk/rtmpplayer');
7
+
8
+ const { versionComp } = require('./common.js');
9
+ const electronVersion = process.versions['electron'];
10
+ const { app } = require('electron');
11
+
12
+ if (electronVersion && versionComp(electronVersion, '14.0.0') >= 0) {
13
+ const electronStore = require('@electron/remote/main');
14
+ const isInitialized = electronStore.isInitialized();
15
+ if (!isInitialized) electronStore.initialize();
16
+ }
17
+ // 首次添加此开关是为了解决一些GPU导致的渲染问题的,比如进课堂白屏,历史课堂播放进度条不动。
18
+ // 支持虚拟声卡需要添加此开关
19
+ app.commandLine.appendSwitch('--no-sandbox');
20
+ } catch (e) {
21
+ console.error(e);
22
+ }
23
+ }
package/js/render.js ADDED
@@ -0,0 +1,210 @@
1
+ const LogFormatter = require('../scripts/logger');
2
+ const logger = new LogFormatter();
3
+ logger.init();
4
+ const getConfig = require('../scripts/getConfig');
5
+
6
+ const { platform } = getConfig();
7
+
8
+ const isMac = platform === 'darwin';
9
+
10
+ const { ERROR_CODE, LESSON_TYPE, CLASS_WINDOW_MESG_TYPE } = require('./code');
11
+
12
+ const { getElectronRemote, parseUrlParams, getEnvironment, getDisplayMatching } = require('./common');
13
+
14
+ /**
15
+ * @typedef {Object} windowOptionType
16
+ * @property {boolean} [autoMaximized] - 控制窗口是否在初始化时自动最大化
17
+ * @property {boolean} [debug] - 是否开启课堂窗口debug模式
18
+ * @property {boolean} [fullScreenable] - 课堂最大化按钮是切换 全屏模式or最大化窗口
19
+ * @property {boolean} useTransparent - 是否开启透明窗口
20
+ * @property {string} [windowTopic] - 课堂窗口标题
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} liveClassWindowType
25
+ * @property {string} classUrl
26
+ * @property {windowOptionType} windowOptions
27
+ * @property {Object} [electronWinOptions] 自定义electron自己的窗口参数
28
+ * @property {(winId: number)=>void} [onClassWindowReadyCb] 课堂窗口打开渲染成功后的回调
29
+ * @property {()=>void} [onClassWindowFinishedCb] 课堂窗口关闭后的回调
30
+ */
31
+
32
+ /**
33
+ * @param {liveClassWindowType} liveClassWindowProps
34
+ * @returns
35
+ */
36
+ function ceratLiveClassWindow({ classUrl, windowOptions, electronWinOptions, onClassWindowReadyCb, onClassWindowFinishedCb }) {
37
+ logger.info(`课堂窗口创建信息: classUrl is ${classUrl}, windowOptions is ${JSON.stringify(windowOptions)},electronWinOptions is ${JSON.stringify(electronWinOptions)}`);
38
+
39
+ const isElectron = !!process.versions['electron'];
40
+ if (isElectron) {
41
+ const appProxy = require('@plasosdk/winproxy');
42
+ const remote = getElectronRemote();
43
+ const displayInfo = getDisplayMatching();
44
+ const { ipcRenderer } = window.require('electron');
45
+
46
+ if (remote && displayInfo) {
47
+ const classInfo = parseUrlParams(classUrl);
48
+ let _path = classUrl;
49
+ const autoMaximized = windowOptions?.autoMaximized ?? true;
50
+ const _classInfo = {
51
+ customTitleBar: true,
52
+ maximized: autoMaximized,
53
+ /**
54
+ * 传参数到课堂窗口,让课堂窗口执行全屏逻辑,没有直接使用BrowserWindow初始化参数中的fullscreen,
55
+ * 直接使用BrowserWindow的fullscreen参数会有个问题,在windows上当任务栏隐藏状态的时候,进入课堂透明窗口的透明会失效,看到的是全黑的背景。
56
+ * 猜测是electron内部全屏API调用太早导致的。
57
+ *
58
+ * 默认简单全屏进入课堂,保留顶部自定义的标题栏
59
+ */
60
+ autoSimpleFullScreen: true,
61
+ fullScreenable: windowOptions?.fullScreenable ?? false,
62
+ ...classInfo,
63
+ };
64
+
65
+ const environment = getEnvironment(classUrl);
66
+ let rhost;
67
+ if (environment == 'local') {
68
+ rhost = 'http://127.0.0.1:4399/';
69
+ } else if (environment == 'dev' || environment == 'test' || environment == 'itest' || environment == 'ftest') {
70
+ rhost = `https://${environment}.plaso.cn/static/yxtsdk/`;
71
+ } else {
72
+ rhost = `https://wwwr.plaso.cn/static/sdk/styleupime/${classInfo.version}/`;
73
+ }
74
+ const dhost = classInfo.dhost;
75
+ const appinfo = {
76
+ appType: classInfo.appType ?? 'yxtlivesdk',
77
+ rhost: rhost,
78
+ dhost: dhost,
79
+ markString: environment,
80
+ env: classInfo.dev ?? environment,
81
+ clsinfo: JSON.stringify(_classInfo),
82
+ classType: classInfo.classType ?? LESSON_TYPE.LIVECLASS,
83
+ loggerPath: logger.loggerPath ?? '',
84
+ clientType: 'electron',
85
+ enableAgoraV4: true,
86
+ };
87
+ for (const key in appinfo) {
88
+ if (key && classInfo[key] === undefined) _path += `&${key}=${encodeURIComponent(appinfo[key])}`;
89
+ }
90
+ const win = remote.getCurrentWindow();
91
+ const webContents = remote.getCurrentWebContents();
92
+ _path += `&openerId=${webContents.id}`;
93
+
94
+ const bounds = win.getBounds();
95
+ const screenWidth = displayInfo.size.width;
96
+ const screenWorkAreaWidth = displayInfo.workAreaSize.width;
97
+ const screenHeight = displayInfo.size.height;
98
+ const screenWorkAreaHeight = displayInfo.workAreaSize.height;
99
+
100
+ const changeBoundsDate = (ischangeWidth, baseWidthOrHeight) => {
101
+ const newWidthOrHeight = baseWidthOrHeight - 10;
102
+ if (ischangeWidth) {
103
+ bounds.height = Math.round((bounds.height * newWidthOrHeight) / bounds.width);
104
+ bounds.width = newWidthOrHeight;
105
+ } else {
106
+ bounds.width = Math.round((bounds.width * newWidthOrHeight) / bounds.height);
107
+ bounds.height = newWidthOrHeight;
108
+ }
109
+ };
110
+ // 课堂窗口创建时的宽或高和 屏幕宽高或屏幕工作区宽高 一致时,此时透明窗口会失效,需要调整进课堂时的窗口宽高
111
+ if (bounds.width === screenWidth || bounds.width === screenWorkAreaWidth) {
112
+ changeBoundsDate(true, Math.min(screenWidth, screenWorkAreaWidth));
113
+ }
114
+ if (bounds.height === screenHeight || bounds.height === screenWorkAreaHeight) {
115
+ changeBoundsDate(false, Math.min(screenHeight, screenWorkAreaHeight));
116
+ }
117
+
118
+ const defaultElecteonWinOptions = {
119
+ frame: false,
120
+ /**
121
+ * electron 12.0.18之后,resizable设为true才能全屏和最大化,
122
+ * 而课堂窗口不允许通过electron自身的缩放行为来改变大小,因此进入课堂后会将resizable设为false
123
+ */
124
+ resizable: true,
125
+ /** 设置为true,mac上setFullScreen(true)才生效,setSimpleFullScreen(true)不依赖此参数 */
126
+ fullscreenable: true,
127
+ ...bounds,
128
+ webPreferences: {
129
+ nodeIntegration: true,
130
+ enableRemoteModule: true,
131
+ contextIsolation: false,
132
+ nodeIntegrationInWorker: true,
133
+ },
134
+ };
135
+ if (isMac) {
136
+ // 在Mac下要显式设置fullscreen为false,防止客户端全屏时进入课堂,课堂窗口也默认全屏,
137
+ // 导致部分按钮失效,以及独立窗口打开异常
138
+ defaultElecteonWinOptions.fullscreen = false;
139
+ }
140
+ // 学生无需使用透明窗口(透明窗口问题多),减少影响
141
+ if (windowOptions?.useTransparent) {
142
+ defaultElecteonWinOptions.transparent = true;
143
+ defaultElecteonWinOptions.backgroundColor = '#00ffffff';
144
+ }
145
+ if (windowOptions?.windowTopic) defaultElecteonWinOptions.title = windowOptions.windowTopic;
146
+
147
+ const _electeonWinOptions = electronWinOptions
148
+ ? {
149
+ ...defaultElecteonWinOptions,
150
+ ...electronWinOptions,
151
+ }
152
+ : defaultElecteonWinOptions;
153
+
154
+ if (_path) {
155
+ let currentWinId = null;
156
+
157
+ const onClassWindowReady = () => {
158
+ logger.info(`课堂窗口ready,id:${currentWinId}`);
159
+ if (onClassWindowReadyCb && currentWinId) onClassWindowReadyCb(currentWinId);
160
+ };
161
+
162
+ ipcRenderer.on(CLASS_WINDOW_MESG_TYPE.LIVE_WINDOW_READY, onClassWindowReady);
163
+ appProxy.createWindow(
164
+ {
165
+ path: _path,
166
+ debug: windowOptions?.debug ?? false,
167
+ maximize: autoMaximized,
168
+ windowOptions: _electeonWinOptions,
169
+ },
170
+ async (id) => {
171
+ currentWinId = id;
172
+ appProxy.addWinEventListener(id, 'closed', () => {
173
+ logger.info(`课堂窗口关闭,id:${currentWinId}`);
174
+
175
+ currentWinId = null;
176
+ if (onClassWindowFinishedCb) onClassWindowFinishedCb();
177
+ ipcRenderer.removeListener(CLASS_WINDOW_MESG_TYPE.LIVE_WINDOW_READY, onClassWindowReady);
178
+ });
179
+ },
180
+ );
181
+ }
182
+ }
183
+ } else {
184
+ logger.error('非Electron环境');
185
+ return ERROR_CODE.NO_ELECTRON_ENVIRONMENT;
186
+ }
187
+ }
188
+
189
+ function getVersion() {
190
+ try {
191
+ const packageJson = require('../package.json');
192
+ return packageJson.version;
193
+ } catch (error) {
194
+ logger.error(`getVersion error is: ${JSON.stringify(error)}}`);
195
+ return ERROR_CODE.COMMOM_ERROR;
196
+ }
197
+ }
198
+
199
+ /** 日志文件地址 */
200
+ function initLogConfig(logFilePath) {
201
+ logger.initLoggerFilePath(logFilePath);
202
+ }
203
+
204
+ const PlasoElectronSdk = {
205
+ ceratLiveClassWindow: ceratLiveClassWindow,
206
+ getVersion: getVersion,
207
+ initLogConfig: initLogConfig,
208
+ };
209
+
210
+ module.exports = PlasoElectronSdk;
package/lib/lame/lame ADDED
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@plasosdk/plaso-electron-sdk",
3
+ "version": "1.0.6",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "electron .",
8
+ "install": "npm run download",
9
+ "download": "node ./scripts/downloadPrebuild.js"
10
+ },
11
+ "keywords": [
12
+ "electron",
13
+ "windows",
14
+ "mac"
15
+ ],
16
+ "dependencies": {
17
+ "adm-zip": "^0.5.16",
18
+ "fs-extra": "^11.1.1",
19
+ "minimist": "^1.2.5"
20
+ },
21
+ "peerDependencies": {
22
+ "@electron/remote": ">=2.1.2",
23
+ "@plasosdk/plasoffmpeg": "^1.1.0",
24
+ "@plasosdk/rbtusbaddon": "^1.0.1",
25
+ "@plasosdk/rbtwifiaddon": "^1.0.2",
26
+ "@plasosdk/rtmpplayer": "^2.0.0",
27
+ "@plasosdk/screenshot": "^1.3.2",
28
+ "@plasosdk/winproxy": "^1.1.3"
29
+ },
30
+ "author": "",
31
+ "license": "ISC"
32
+ }
package/readme.md ADDED
@@ -0,0 +1,65 @@
1
+ # 支持的环境与electron版本
2
+
3
+ - macOs支持 x64 、arm64
4
+ - windows支持 ia32 、 x64
5
+ - electron支持 12.0.18~22.3.27
6
+
7
+
8
+
9
+ # 1、接入步骤
10
+
11
+ ## 1.1、下载
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+ # 2、进课堂参数说明
20
+
21
+ ## 2.1、窗口相关参数说明
22
+
23
+ | 参数 | 类型 | 是否必传 | 默认值 | 说明 |
24
+ | -------------- | ------- | -------- | ------ | ------------------------------------------------------------ |
25
+ | autoMaximized | Boolean | 否 | true | 控制窗口是否在初始化时自动最大化 |
26
+ | debug | Boolean | 否 | false | 是否开启课堂窗口debug模式 |
27
+ | fullScreenable | Boolean | 否 | false | true:课堂最大化按钮是切换全屏模式<br />false:课堂最大化按钮是最大化窗口;<br />建议仅学生和游客切换全屏,老师切换最大化 |
28
+ | useTransparent | Boolean | 是 | false | 是否开启透明窗口,影响新桌面共享的使用;<br />建议仅老师、助教开启; |
29
+ | windowTopic | string | 否 | 无 | 课堂窗口标题 |
30
+
31
+
32
+
33
+ ## 2.2、课堂相关参数说明
34
+
35
+ | 参数 | 类型 | 是否必传 | 默认值 | 说明 |
36
+ | --------- | ------ | -------- | ----------- | ----------------------------------------- |
37
+ | version | string | 是 | 无 | 指定课堂对应的web版本,格式为:x.xx.xxx; |
38
+ | classType | string | 否 | ‘liveClass’ | 课堂窗口类型,暂仅支持 liveClass |
39
+
40
+
41
+
42
+ ## 2.3、功能相关参数
43
+
44
+ 具体课堂内相关功能对应的参数见
45
+
46
+
47
+
48
+
49
+
50
+ # 3、对外暴露的方法
51
+
52
+ ### 3.1、initLogConfig
53
+
54
+
55
+
56
+ ### 3.2、ceratLiveClassWindow
57
+
58
+
59
+
60
+ ### 3.3、getVersion
61
+
62
+
63
+
64
+ # 4、错误code
65
+
@@ -0,0 +1,133 @@
1
+ /* eslint-disable camelcase */
2
+
3
+ const path = require('path');
4
+ const fs = require('fs-extra');
5
+ const https = require('https');
6
+ const { exec } = require('child_process');
7
+
8
+ const AdmZip = require('adm-zip');
9
+
10
+ const getConfig = require('./getConfig');
11
+ const LogFormatter = require('./logger');
12
+ const logger = new LogFormatter();
13
+
14
+ const { platform, packageVersion, arch } = getConfig();
15
+
16
+ const agora_electron_sdk_v4_x32_in_win32 =
17
+ 'npm install agora-electron-sdk@4.2.6-build.153-rc.1 --agora_electron_sdk_arch=ia32 --agora_electron_sdk_platform=win32 --global-style --no-save --no-package-lock';
18
+ const agora_electron_sdk_v4_x64_in_win32 =
19
+ 'npm install agora-electron-sdk@4.2.6-build.153-rc.1 --agora_electron_sdk_arch=x64 --agora_electron_sdk_platform=win32 --global-style --no-save --no-package-lock';
20
+ const agora_electron_sdk_v4_in_darwin =
21
+ 'npm install agora-electron-sdk@4.2.6-build.153-rc.1 --agora_electron_sdk_arch=x64 --agora_electron_sdk_platform=darwin --global-style --no-save --no-package-lock';
22
+
23
+ const trtc_electron_sdk_x32_in_win32 =
24
+ 'npm install trtc-electron-sdk@11.8.112-beta.6 --trtc_electron_arch=ia32 --trtc_electron_platform=win32 --global-style --no-save --no-package-lock';
25
+ const trtc_electron_sdk_x64_in_win32 =
26
+ 'npm install trtc-electron-sdk@11.8.112-beta.6 --trtc_electron_arch=x64 --trtc_electron_platform=win32 --global-style --no-save --no-package-lock';
27
+ const trtc_electron_sdk_in_darwin =
28
+ 'npm install trtc-electron-sdk@11.8.112-beta.6 --trtc_electron_arch=x64 --trtc_electron_platform=darwin --global-style --no-save --no-package-lock';
29
+
30
+ const PLATFORM_TYPE = {
31
+ DARWIN: 'darwin',
32
+ WIN32: 'win32',
33
+ };
34
+
35
+ const ARCH_TYPE = {
36
+ X64: 'x64',
37
+ IA32: 'ia32',
38
+ ARM64: 'arm64',
39
+ };
40
+
41
+ const oldAgoraV4Path = path.join(__dirname, '../node_modules', 'agora-electron-sdk');
42
+ const newAgoraV4Path = path.join(__dirname, '../../../', 'agora-electron-sdk-v4');
43
+
44
+ const oldTrtcPath = path.join(__dirname, '../node_modules', 'trtc-electron-sdk');
45
+ const newTrtcPath = path.join(__dirname, '../../../', 'trtc-electron-sdk');
46
+
47
+ const getFlameshotURL = () => {
48
+ let flameshotZipName = 'win_flameshot';
49
+ let flameshotZipUrl = 'https://hz-public-files.oss-cn-hangzhou.aliyuncs.com/static/flameshot/win_flameshot.zip';
50
+ if (platform === PLATFORM_TYPE.DARWIN) {
51
+ if (arch.includes('arm')) {
52
+ flameshotZipName = 'arm64_flameshot.app';
53
+ flameshotZipUrl = 'https://hz-public-files.oss-cn-hangzhou.aliyuncs.com/static/flameshot/arm64_flameshot.app.zip';
54
+ } else {
55
+ flameshotZipName = 'x64_flameshot.app';
56
+ flameshotZipUrl = 'https://hz-public-files.oss-cn-hangzhou.aliyuncs.com/static/flameshot/x64_flameshot.app.zip';
57
+ }
58
+ }
59
+ return [flameshotZipUrl, flameshotZipName];
60
+ };
61
+
62
+ const npmInstallRtc = () => {
63
+ let agora_electron_sdk_v4 = agora_electron_sdk_v4_x32_in_win32;
64
+ let trtc_electron_sdk = trtc_electron_sdk_x32_in_win32;
65
+ if (platform === PLATFORM_TYPE.DARWIN) {
66
+ agora_electron_sdk_v4 = agora_electron_sdk_v4_in_darwin;
67
+ trtc_electron_sdk = trtc_electron_sdk_in_darwin;
68
+ } else if (arch === ARCH_TYPE.X64) {
69
+ agora_electron_sdk_v4 = agora_electron_sdk_v4_x64_in_win32;
70
+ trtc_electron_sdk = trtc_electron_sdk_x64_in_win32;
71
+ }
72
+
73
+ const installCb = (url, error, stdout, stderr) => {
74
+ logger.info(`installCb 信息: ${url}, ${error?.message}, ${stdout}, ${stderr}`);
75
+ };
76
+ exec(agora_electron_sdk_v4, async (error, stdout, stderr) => {
77
+ installCb(agora_electron_sdk_v4, error, stdout, stderr);
78
+ fs.move(oldAgoraV4Path, newAgoraV4Path, { overwrite: true }, (err) => {
79
+ if (!err) {
80
+ logger.info('更新agora_electron_sdk_v4成功');
81
+ }
82
+ });
83
+ });
84
+ exec(trtc_electron_sdk, (error, stdout, stderr) => {
85
+ installCb(trtc_electron_sdk, error, stdout, stderr);
86
+ fs.move(oldTrtcPath, newTrtcPath, { overwrite: true }, (err) => {
87
+ if (!err) {
88
+ logger.info('移动trtc_electron_sdk成功');
89
+ }
90
+ });
91
+ });
92
+ };
93
+
94
+ const downloadFile = (fileUrl, downloadFilePath, outputFilePath) => {
95
+ logger.info(`will downloadFile: ${fileUrl}, downloadFilePath is ${downloadFilePath}, outputFilePath is ${outputFilePath}`);
96
+ https
97
+ .get(fileUrl, (response) => {
98
+ const file = fs.createWriteStream(downloadFilePath);
99
+ response.pipe(file);
100
+ file.on('finish', () => {
101
+ file.close(() => {
102
+ logger.info(`文件${fileUrl}写入完成`);
103
+ // 解压缩
104
+ if (outputFilePath) {
105
+ const zip = new AdmZip(downloadFilePath);
106
+ zip.extractAllTo(outputFilePath, true);
107
+ logger.info(`文件${fileUrl}解压完成`);
108
+ fs.unlink(downloadFilePath, () => {});
109
+ }
110
+ });
111
+ });
112
+ })
113
+ .on('error', (err) => {
114
+ // 删除不完整的文件
115
+ fs.unlink(downloadFilePath, () => {});
116
+ logger.error(`文件${fileUrl}下载失败,删除不完整的文件`, err.message);
117
+ });
118
+ };
119
+
120
+ const downloadPrebuild = async () => {
121
+ npmInstallRtc();
122
+ const [flameshotUrl, flameshotZipName] = getFlameshotURL();
123
+
124
+ /** start download */
125
+ logger.info('Package Version: %s', packageVersion);
126
+ logger.info('Platform: %s', platform);
127
+ if (arch) logger.info('Arch: %s', arch);
128
+ const flameshotFilePath = path.join(__dirname, `../lib/${flameshotZipName}.zip`);
129
+ const flameshotZipOutputDir = path.join(__dirname, '../lib');
130
+
131
+ downloadFile(flameshotUrl, flameshotFilePath, flameshotZipOutputDir);
132
+ };
133
+ downloadPrebuild();
@@ -0,0 +1,26 @@
1
+
2
+ const LogFormatter = require('./logger');
3
+ const path = require('path');
4
+
5
+ const minimist = require('minimist');
6
+ const logger = new LogFormatter();
7
+
8
+
9
+ const { INIT_CWD } = minimist(process.argv.slice(2));
10
+ logger.info(`pass INIT_CWD ${INIT_CWD}`);
11
+ logger.info(`__dirname ${__dirname}`);
12
+
13
+ const getConfig = () => {
14
+ const { version } = require(path.join(__dirname, '../package.json'));
15
+ var os = require('os');
16
+ const platform = process.env.npm_config_plaso_electron_sdk_platform || os.platform();
17
+ const arch = process.env.npm_config_plaso_electron_sdk_arch || os.arch();
18
+ logger.info(`platform is ${platform}, arch is ${arch}`);
19
+
20
+ return {
21
+ platform,
22
+ arch,
23
+ packageVersion: version,
24
+ };
25
+ };
26
+ module.exports = getConfig;
@@ -0,0 +1,138 @@
1
+ const { LEVEL } = require('../js/code');
2
+ const LEVEL_FORMAT_LENGTH = Math.max(...Object.keys(LEVEL).map((key) => key.length)) + 1;
3
+
4
+ class LogFormatter {
5
+ constructor(loggerPath) {
6
+ this.loggerPath = loggerPath ? loggerPath.replace(/\\/g, '/') : '';
7
+ this.fs;
8
+ this.util;
9
+ this.newLogTime;
10
+ this.ws = null;
11
+ }
12
+
13
+ init() {
14
+ try {
15
+ this.fs = window.require('fs');
16
+ this.util = window.require('util');
17
+
18
+ const process = window.require('process');
19
+ process.on('uncaughtException', (error) => this.write(LEVEL.error, error ? error.stack : {}));
20
+ } catch (error) {
21
+ console.error('log error', error);
22
+ }
23
+ }
24
+
25
+ initLoggerFilePath(_loggerPath) {
26
+ this.loggerPath = _loggerPath ? _loggerPath.replace(/\\/g, '/') : '';
27
+ }
28
+
29
+ createWS() {
30
+ if (this.fs && this.loggerPath && this.newLogTime) {
31
+ const logFileName = `${this.loggerPath}/plasoElectronSdk_${this.newLogTime}.log`;
32
+ this.ws = this.fs.createWriteStream(logFileName, { flags: 'a' });
33
+ this.ws.write(`Start log: ${new Date()}\n\n`);
34
+ }
35
+ }
36
+
37
+ _writeLog(prefix, logContent) {
38
+ if (this.ws) {
39
+ this.ws.write(prefix);
40
+ this.ws.write(logContent);
41
+ this.ws.write('\n');
42
+ }
43
+ }
44
+
45
+ write(level, ...format) {
46
+ try {
47
+ if (!this.fs || !this.util) {
48
+ return;
49
+ }
50
+ const today = new Date();
51
+ const newLogTime = `${today.getFullYear()}-${today.getMonth() + 1}-${today.getDate()}`;
52
+ if (newLogTime !== this.newLogTime) {
53
+ this.newLogTime = newLogTime;
54
+ if (this.ws !== null) {
55
+ this.ws.end();
56
+ this.ws = null;
57
+ }
58
+ }
59
+ if (this.ws == null) {
60
+ this.createWS();
61
+ }
62
+ const maxContentSize = 10 * 1024;
63
+ let logContent = this.util.format(...format);
64
+ const logContentSize = logContent.length;
65
+ // 单条日志长度超过10K则进行截取
66
+ if (logContentSize > maxContentSize) {
67
+ logContent =
68
+ logContent.slice(0, maxContentSize) +
69
+ ` <<< more (${((logContentSize - maxContentSize) / 1024).toFixed(1)}KB)`;
70
+ }
71
+ const logTime = `[${today.toLocaleTimeString('en-US', { hour12: false })}.${today
72
+ .getMilliseconds()
73
+ .toString()
74
+ .padStart(3, '0')}]`;
75
+ let logLevel = '';
76
+ switch (level) {
77
+ case LEVEL.ERROR:
78
+ logLevel = 'ERROR';
79
+ break;
80
+ case LEVEL.WARN:
81
+ logLevel = 'WARN';
82
+ break;
83
+ case LEVEL.INFO:
84
+ logLevel = 'INFO';
85
+ break;
86
+ case LEVEL.DEBUG:
87
+ logLevel = 'DEBUG';
88
+ break;
89
+ }
90
+ const prefix = `${logLevel.padEnd(LEVEL_FORMAT_LENGTH, ' ')} ${logTime} `;
91
+
92
+ this._writeLog(prefix, logContent);
93
+ } catch (e) {
94
+ console.error('log write error', e);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * @param {any[]} content
100
+ */
101
+ info(...content) {
102
+ this.log('info', ...content);
103
+ }
104
+
105
+ /**
106
+ * @param {any[]} content
107
+ */
108
+ debug(...content) {
109
+ this.log('debug', ...content);
110
+ }
111
+ /**
112
+ * @param {any[]} content
113
+ */
114
+ warn(...content) {
115
+ this.log('warn', ...content);
116
+ }
117
+ /**
118
+ * @param {any[]} content
119
+ */
120
+ error(...content) {
121
+ this.log('error', ...content);
122
+ }
123
+
124
+ /**
125
+ * @private
126
+ * @param {'info' | 'debug' | 'error' | 'warn'} level
127
+ * @param {any[]} content
128
+ */
129
+ log(level, ...content) {
130
+ if (this.loggerPath) {
131
+ this.write(LEVEL[level], ...content);
132
+ } else {
133
+ console[level](...content);
134
+ }
135
+ }
136
+ }
137
+
138
+ module.exports = LogFormatter;