node-automator 1.4.10 → 1.4.12

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.
@@ -7,7 +7,8 @@ const fs = require("fs");
7
7
  const path = require("path");
8
8
  const {
9
9
  success,
10
- error
10
+ error,
11
+ warn
11
12
  } = require('../utils/log_tool');
12
13
  const {
13
14
  parse,
@@ -50,6 +51,10 @@ class BackupCommand extends BaseCommand {
50
51
  backupData = backupData[key];
51
52
  }
52
53
  }
54
+ if (backupData === undefined) {
55
+ warn(`未找到 ${filename} 的 ${sourceKeys} 字段`)
56
+ return;
57
+ }
53
58
  if (backupFormat) {
54
59
  backupData = await stringify(backupData, backupFormat);
55
60
  }
@@ -10,6 +10,7 @@ class CompressCommand extends BaseCommand {
10
10
  const dst = get_full_path(data.dst, "FILE");
11
11
  const options = data.options || {};
12
12
  let image = await Jimp.read(src);
13
+ image.scale(options.scale || 1);
13
14
  image.quality(options.quality || 80);
14
15
  await image.writeAsync(dst);
15
16
  }
package/commands/mgr.js CHANGED
@@ -118,6 +118,8 @@ const { DeobfuscateCommand } = require('./deobfuscate');
118
118
  const { AliOssCommand } = require('./ali_oss');
119
119
  const { BackupCommand } = require('./backup');
120
120
  const { CompressCommand } = require('./compress');
121
+ const { Word2txtCommand } = require('./word2txt');
122
+ const { ObfuscateCommand } = require('./obfuscate');
121
123
 
122
124
  const globalData = {
123
125
  "executed_cfg": [], // 执行过的配置文件
@@ -134,7 +136,7 @@ const commandMap = {};
134
136
  */
135
137
  const commandPool = {};
136
138
  const showLogs = {
137
-
139
+
138
140
  };
139
141
 
140
142
 
@@ -208,7 +210,7 @@ async function execSingle(commandCfg) {
208
210
  let totalRetryTimes = commandCfg.retry || 0;
209
211
  let retryTimes = 0;
210
212
  let ret = null;
211
- while(true) {
213
+ while (true) {
212
214
  if (retryTimes > 0) { // 仅在重试时,重置错误
213
215
  setLastError(null);
214
216
  }
@@ -293,9 +295,9 @@ async function _execSingle(commandCfg, depth, progressData) {
293
295
  return;
294
296
  }
295
297
  if (commandCfg.show_progress /* !== false */ && progressData && shareData.$COMPRESS_PROGERSS <= 0) {
296
- progress(progressData.curr, progressData.total, {depth: depth, desc: `> ${commandCfg.title || commandCfg.type}`, color: "white"});
298
+ progress(progressData.curr, progressData.total, { depth: depth, desc: `> ${commandCfg.title || commandCfg.type}`, color: "white" });
297
299
  }
298
-
300
+
299
301
  if (showLogs[commandCfg.type]) {
300
302
  log("");
301
303
  }
@@ -336,14 +338,14 @@ async function _execSingle(commandCfg, depth, progressData) {
336
338
  is_first = false;
337
339
  } while (!ret && commandCfg.required);
338
340
  recyleCommand(command);
339
-
341
+
340
342
  if (!getLastError()) {
341
343
  if (commandCfg.show_progress /* !== false */ && progressData && shareData.$COMPRESS_PROGERSS <= 0) {
342
- progress(progressData.curr + 1, progressData.total, {depth: depth, desc: `✔ ${commandCfg.title || commandCfg.type}`['cyan']});
344
+ progress(progressData.curr + 1, progressData.total, { depth: depth, desc: `✔ ${commandCfg.title || commandCfg.type}`['cyan'] });
343
345
  }
344
346
  } else {
345
347
  if (commandCfg.show_progress /* !== false */ && progressData && shareData.$COMPRESS_PROGERSS <= 0) {
346
- progress(progressData.curr + 1, progressData.total, {depth: depth, desc: `✖ ${commandCfg.title || commandCfg.type}`['red']});
348
+ progress(progressData.curr + 1, progressData.total, { depth: depth, desc: `✖ ${commandCfg.title || commandCfg.type}`['red'] });
347
349
  }
348
350
  if (commandCfg.ignore_error) {
349
351
  resetError(commandCfg.ignore_error);
@@ -479,6 +481,8 @@ function init() {
479
481
  register("ali_oss", AliOssCommand, false);
480
482
  register("backup", BackupCommand, false);
481
483
  register("compress", CompressCommand, false);
484
+ register("word2txt", Word2txtCommand, false);
485
+ register("obfuscate", ObfuscateCommand, false);
482
486
  }
483
487
 
484
488
  module.exports = {
@@ -0,0 +1,79 @@
1
+ const { BaseCommand } = require("./base");
2
+ const JavaScriptObfuscator = require('javascript-obfuscator');
3
+
4
+ class ObfuscateCommand extends BaseCommand {
5
+ async execute() {
6
+ const PRESET_OPTIONS = {
7
+ "optionsPreset": "default",
8
+ "compact": true,
9
+ "selfDefending": false,
10
+ "disableConsoleOutput": false,
11
+ "debugProtection": false,
12
+ "debugProtectionInterval": 0,
13
+ "splitStrings": false,
14
+ "splitStringsChunkLength": 10,
15
+ "splitStringsChunkLengthEnabled": false,
16
+ "stringArray": true,
17
+ "stringArrayRotate": true,
18
+ "stringArrayRotateEnabled": true,
19
+ "stringArrayShuffle": true,
20
+ "stringArrayShuffleEnabled": true,
21
+ "simplify": true,
22
+ "stringArrayThreshold": 0.75,
23
+ "stringArrayThresholdEnabled": true,
24
+ "stringArrayIndexesType": [
25
+ "hexadecimal-number"
26
+ ],
27
+ "stringArrayIndexShift": true,
28
+ "stringArrayCallsTransform": false,
29
+ "stringArrayCallsTransformThreshold": 0.5,
30
+ "stringArrayEncoding": [
31
+ "none"
32
+ ],
33
+ "stringArrayEncodingEnabled": true,
34
+ "stringArrayWrappersCount": 1,
35
+ "stringArrayWrappersChainedCalls": true,
36
+ "stringArrayWrappersParametersMaxCount": 2,
37
+ "stringArrayWrappersType": "variable",
38
+ "numbersToExpressions": false,
39
+ "sourceMap": false,
40
+ "sourceMapBaseUrl": "",
41
+ "sourceMapFileName": "",
42
+ "domainLock": [],
43
+ "domainLockRedirectUrl": "about:blank",
44
+ "domainLockEnabled": true,
45
+ "forceTransformStrings": [],
46
+ "reservedNames": [],
47
+ "reservedStrings": [],
48
+ "seed": 0,
49
+ "controlFlowFlatteningThreshold": 0.75,
50
+ "controlFlowFlattening": false,
51
+ "deadCodeInjectionThreshold": 0.4,
52
+ "deadCodeInjection": false,
53
+ "unicodeEscapeSequence": false,
54
+ "renameGlobals": false,
55
+ "renameProperties": false,
56
+ "renamePropertiesMode": "safe",
57
+ "target": "browser",
58
+ "identifierNamesGenerator": "hexadecimal",
59
+ "identifiersDictionary": [],
60
+ "identifiersPrefix": "",
61
+ "transformObjectKeys": false,
62
+ "ignoreImports": false
63
+ };
64
+ const options = {
65
+ ...PRESET_OPTIONS,
66
+ ...this.selfData.options,
67
+ }
68
+ const result = JavaScriptObfuscator.obfuscate(this.content, options);
69
+ return result.getObfuscatedCode();
70
+ }
71
+
72
+ getRequireContent() {
73
+ return true;
74
+ }
75
+ }
76
+
77
+ module.exports = {
78
+ ObfuscateCommand,
79
+ };
@@ -0,0 +1,42 @@
1
+ const {
2
+ get_fst_file
3
+ } = require('../utils/file_tool');
4
+ const {
5
+ BaseCommand
6
+ } = require("./base");
7
+ const fs = require('fs');
8
+ const mammoth = require('mammoth');
9
+
10
+ class Word2txtCommand extends BaseCommand {
11
+ async execute() {
12
+ const data = this.selfData;
13
+ const wordFilePath = get_fst_file(data.src);
14
+ return new Promise((resolve, reject) => {
15
+ // 读取 Word 文件
16
+ fs.readFile(wordFilePath, (err, data) => {
17
+ if (err) {
18
+ reject(err);
19
+ return console.error("读取文件时出错:", err);
20
+ }
21
+
22
+ // 将 Word 文件转换为纯文本
23
+ mammoth.extractRawText({
24
+ buffer: data
25
+ })
26
+ .then((result) => {
27
+ const text = result.value; // 纯文本内容
28
+ console.log("转换后的文本内容:", text);
29
+ resolve(text);
30
+ })
31
+ .catch((err) => {
32
+ console.error("转换过程中出错:", err);
33
+ reject(err);
34
+ });
35
+ });
36
+ })
37
+ }
38
+ }
39
+
40
+ module.exports = {
41
+ Word2txtCommand,
42
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-automator",
3
- "version": "1.4.10",
3
+ "version": "1.4.12",
4
4
  "description": "Execute automation with yaml configuration(compatible with json)",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -34,6 +34,7 @@
34
34
  "html-to-text": "^8.2.0",
35
35
  "iconv-lite": "^0.6.2",
36
36
  "image-size": "^1.0.0",
37
+ "javascript-obfuscator": "^4.1.1",
37
38
  "jimp": "^0.22.12",
38
39
  "json-stable-stringify": "^1.0.1",
39
40
  "jwt-js": "^0.5.0",
@@ -41,6 +42,7 @@
41
42
  "log4js": "^6.3.0",
42
43
  "luaparse": "^0.3.1",
43
44
  "mail-watcher": "^0.6.1",
45
+ "mammoth": "^1.8.0",
44
46
  "markdown-table": "^2.0.0",
45
47
  "mysql": "^2.18.1",
46
48
  "node-localstorage": "^2.1.6",
@@ -83,7 +83,7 @@ async function pause(prompt = "", countdown) {
83
83
  }
84
84
  }
85
85
  };
86
- let timeout = 0;
86
+ let timeout = 0;
87
87
  if (needCountDown) {
88
88
  timeout = setInterval(() => {
89
89
  leftTime -= 1;
@@ -181,22 +181,22 @@ function showOptions(viewOptions, filteredViewOptions, selectedIndices, focusedI
181
181
  }, 0);
182
182
  clearLine();
183
183
  info(`当前选择: ${typeof selectedIndices === "number" ? (selectedIndices == -1 ? 0 : 1) : selectedIndices.length} / ${filteredViewOptions.length}`);
184
- write(`${begIndex == 0 ? "" : "▲"['magenta'] }${clear_line_end}\n`);
184
+ write(`${begIndex == 0 ? "" : "▲"['magenta']}${clear_line_end}\n`);
185
185
  for (let i = 0; i < numPerPage; ++i) {
186
- // for (let index = begIndex; index < begIndex + numShow; index++) {
186
+ // for (let index = begIndex; index < begIndex + numShow; index++) {
187
187
  let index = begIndex + i;
188
188
  let viewOption = filteredViewOptions[index];
189
189
  if (viewOption == undefined) {
190
190
  write(clear_line_end + "\n");
191
191
  continue;
192
192
  }
193
- let viewOptionStr = `${alignStr(viewOption.key, maxKeyLength, {alignment: alignment})} - ${viewOption.value?.toString().replace(new RegExp(LINE_EXPRESSION, "g"), "")}`;
193
+ let viewOptionStr = `${alignStr(viewOption.showKey, maxKeyLength, { alignment: alignment })} - ${viewOption.value?.toString().replace(new RegExp(LINE_EXPRESSION, "g"), "")}`;
194
194
  let indicator;
195
195
  let optionColor;
196
196
  let selected = selectedIndices === index || selectedIndices instanceof Array && selectedIndices.includes(index);
197
197
  let focused = focusedIndex === index;
198
198
  let filtered = filteredViewOptions && filteredViewOptions.length != filteredViewOptions.length && filteredViewOptions.includes(viewOption);
199
- indicator = focused ? `${indicator_char} ` [selectColor] : " ";
199
+ indicator = focused ? `${indicator_char} `[selectColor] : " ";
200
200
  if (selected) {
201
201
  optionColor = selectColor;
202
202
  } else if (filtered) {
@@ -215,7 +215,7 @@ function showOptions(viewOptions, filteredViewOptions, selectedIndices, focusedI
215
215
  write(`${indicator}${preview[optionColor]}`);
216
216
  write('\n');
217
217
  }
218
- write(`${begIndex + numShow >= filteredViewOptions.length ? "" : "▼"['magenta'] }${clear_line_end}\n`);
218
+ write(`${begIndex + numShow >= filteredViewOptions.length ? "" : "▼"['magenta']}${clear_line_end}\n`);
219
219
  }
220
220
 
221
221
  module.exports = {
@@ -10,7 +10,7 @@ const { hash } = require('./hash_tool');
10
10
  async function doRequest(data) {
11
11
  const request = require("request");
12
12
  const request_progress = require("request-progress");
13
-
13
+
14
14
  let url = data.src || data?.target?.url;
15
15
  let urlObj = new URL(url);
16
16
  /** 是否启用 http 缓存 */
@@ -112,7 +112,7 @@ async function doRequest(data) {
112
112
  resolve(res.headers);
113
113
  } else {
114
114
  resolve(result);
115
- }
115
+ }
116
116
  }
117
117
  }
118
118
  });
@@ -121,14 +121,16 @@ async function doRequest(data) {
121
121
  });
122
122
  request_progress(
123
123
  req.on('progress', function (state) {
124
- sizeTotal = state.size.total;
124
+ sizeTotal = state.size.total;
125
+ if (!quiet) {
125
126
  hasProgress = true;
126
- !quiet && progress(state.size.transferred, state.size.total, {
127
- desc: `请求中...(elapsed: ${transform_tool.formatTimeInSec(state.time.elapsed)}, speed: ${transform_tool.formatByteSize(state.speed)}/s, ETA: ${transform_tool.formatTimeInSec(state.time.remaining)})`,
128
- format_bytes: true,
129
- color: "cyan"
130
- }, true);
131
127
  }
128
+ !quiet && progress(state.size.transferred, state.size.total, {
129
+ desc: `请求中...(elapsed: ${transform_tool.formatTimeInSec(state.time.elapsed)}, speed: ${transform_tool.formatByteSize(state.speed)}/s, ETA: ${transform_tool.formatTimeInSec(state.time.remaining)})`,
130
+ format_bytes: true,
131
+ color: "cyan"
132
+ }, true);
133
+ }
132
134
  )
133
135
  );
134
136
  }
@@ -14,6 +14,7 @@ async function select(content, data) {
14
14
  info("");
15
15
  // 支持数组以及普通对象
16
16
  let optionKeys = Object.keys(content);
17
+ const isContentArray = Array.isArray(content);
17
18
  // 过滤
18
19
  let keyFilterRegExp =
19
20
  data.key_filter_pattern && new RegExp(data.key_filter_pattern);
@@ -34,8 +35,10 @@ async function select(content, data) {
34
35
  const options = content;
35
36
  const viewOptions = optionKeys.map((optionKey, index) => {
36
37
  let optionValue = options[optionKey];
38
+ const showKey = isContentArray ? (+optionKey + 1) : optionKey;
37
39
  if (data.preview_handler) {
38
40
  return {
41
+ showKey,
39
42
  key: optionKey,
40
43
  value: eval_code(data.preview_handler)(
41
44
  optionValue,
@@ -45,16 +48,17 @@ async function select(content, data) {
45
48
  };
46
49
  }
47
50
  return {
51
+ showKey,
48
52
  key: optionKey,
49
53
  value: data.preview
50
54
  ? toArray(data.preview)
51
- .map((k, i) =>
52
- i == -1 ? `${k}:${optionValue[k]}` : optionValue[k]
53
- )
54
- .join(" | ")
55
+ .map((k, i) =>
56
+ i == -1 ? `${k}:${optionValue[k]}` : optionValue[k]
57
+ )
58
+ .join(" | ")
55
59
  : typeof optionValue === "object"
56
- ? JSON.stringify(optionValue)
57
- : optionValue,
60
+ ? JSON.stringify(optionValue)
61
+ : optionValue,
58
62
  };
59
63
  });
60
64
  let filteredViewOptions = viewOptions;
@@ -127,7 +131,7 @@ async function select(content, data) {
127
131
  warn(err);
128
132
  }
129
133
  }
130
- let numPerPage = OPTION_PAGE_SIZE;
134
+ let numPerPage = data.OPTION_PAGE_SIZE || OPTION_PAGE_SIZE;
131
135
  function restrictFocusedIndex() {
132
136
  if (focusedIndex < 0) {
133
137
  focusedIndex = 0;
@@ -231,7 +235,7 @@ async function select(content, data) {
231
235
  );
232
236
  focusedIndex = viewOptions.indexOf(
233
237
  filteredViewOptions[
234
- Math.min(filterIdx + 1, filteredViewOptions.length - 1)
238
+ Math.min(filterIdx + 1, filteredViewOptions.length - 1)
235
239
  ]
236
240
  );
237
241
  restrictFocusedIndex();
@@ -284,15 +288,15 @@ async function select(content, data) {
284
288
  filteredViewOptions = !inputParts
285
289
  ? viewOptions
286
290
  : viewOptions.filter((option, i) => {
287
- let valueStr = JSON.stringify(option.value);
288
- return inputParts.some((part) => {
289
- return (
290
- part == i ||
291
- part == option.key ||
292
- valueStr.indexOf(part) != -1
293
- );
294
- });
291
+ let valueStr = JSON.stringify(option.value);
292
+ return inputParts.some((part) => {
293
+ return (
294
+ part == i ||
295
+ part == option.key ||
296
+ valueStr.indexOf(part) != -1
297
+ );
295
298
  });
299
+ });
296
300
  if (filteredViewOptions.length) {
297
301
  focusedIndex = viewOptions.indexOf(filteredViewOptions[0]);
298
302
  }
@@ -316,6 +320,7 @@ async function multiSelect(content, data) {
316
320
  info("");
317
321
  // 支持数组以及普通对象
318
322
  let optionKeys = Object.keys(content);
323
+ const isContentArray = Array.isArray(content);
319
324
  // 过滤
320
325
  let keyFilterRegExp =
321
326
  data.key_filter_pattern && new RegExp(data.key_filter_pattern);
@@ -336,8 +341,10 @@ async function multiSelect(content, data) {
336
341
  const options = content;
337
342
  const viewOptions = optionKeys.map((optionKey, index) => {
338
343
  let optionValue = options[optionKey];
344
+ const showKey = isContentArray ? (1 + optionKey) : optionKey;
339
345
  if (data.preview_handler) {
340
346
  return {
347
+ showKey,
341
348
  key: optionKey,
342
349
  value: eval_code(data.preview_handler)(
343
350
  optionValue,
@@ -347,16 +354,17 @@ async function multiSelect(content, data) {
347
354
  };
348
355
  }
349
356
  return {
357
+ showKey,
350
358
  key: optionKey,
351
359
  value: data.preview
352
360
  ? toArray(data.preview)
353
- .map((k, i) =>
354
- i == -1 ? `${k}:${optionValue[k]}` : optionValue[k]
355
- )
356
- .join(" | ")
361
+ .map((k, i) =>
362
+ i == -1 ? `${k}:${optionValue[k]}` : optionValue[k]
363
+ )
364
+ .join(" | ")
357
365
  : typeof optionValue === "object"
358
- ? JSON.stringify(optionValue)
359
- : optionValue,
366
+ ? JSON.stringify(optionValue)
367
+ : optionValue,
360
368
  };
361
369
  });
362
370
  let filteredViewOptions = viewOptions;
@@ -365,7 +373,7 @@ async function multiSelect(content, data) {
365
373
  let focusedIndex = 0;
366
374
  let confirmEmpty = false;
367
375
  let selectedIndices = [];
368
- let numPerPage = OPTION_PAGE_SIZE;
376
+ let numPerPage = data.OPTION_PAGE_SIZE || OPTION_PAGE_SIZE;
369
377
  function restrictFocusedIndex() {
370
378
  if (focusedIndex < 0) {
371
379
  focusedIndex = 0;
@@ -476,7 +484,7 @@ async function multiSelect(content, data) {
476
484
  );
477
485
  focusedIndex = viewOptions.indexOf(
478
486
  filteredViewOptions[
479
- Math.min(filterIdx + 1, filteredViewOptions.length - 1)
487
+ Math.min(filterIdx + 1, filteredViewOptions.length - 1)
480
488
  ]
481
489
  );
482
490
  restrictFocusedIndex();
@@ -557,15 +565,15 @@ async function multiSelect(content, data) {
557
565
  filteredViewOptions = !inputParts
558
566
  ? viewOptions
559
567
  : viewOptions.filter((option, i) => {
560
- let valueStr = JSON.stringify(option.value);
561
- return inputParts.some((part) => {
562
- return (
563
- part == i ||
564
- part == option.key ||
565
- valueStr.indexOf(part) != -1
566
- );
567
- });
568
+ let valueStr = JSON.stringify(option.value);
569
+ return inputParts.some((part) => {
570
+ return (
571
+ part == i ||
572
+ part == option.key ||
573
+ valueStr.indexOf(part) != -1
574
+ );
568
575
  });
576
+ });
569
577
  if (inputStr && filteredViewOptions.length) {
570
578
  focusedIndex = viewOptions.indexOf(filteredViewOptions[0]);
571
579
  }
@@ -64,6 +64,7 @@ async function exec_shell(data) {
64
64
  let results = [];
65
65
  let errors = [];
66
66
  let encoding = data.encoding || "cp936";
67
+ let raw_output = encoding == "raw";
67
68
  !quiet && whisper(`cmd:[${cmd}] cwd:${data.cwd} inputs:${data.inputs}`);
68
69
  options.stdio = ["pipe", capture_stdout ? "pipe" : process.stdout, "pipe"];
69
70
  const child = child_process.spawn(cmd[0], cmd.slice(1), options);
@@ -71,7 +72,7 @@ async function exec_shell(data) {
71
72
  child.stdout.on("data", (chunk) => {
72
73
  results.push(chunk);
73
74
  if (instant_stdout) {
74
- warn(iconv.decode(chunk, encoding));
75
+ warn(!raw_output ? iconv.decode(chunk, encoding) : chunk.toString());
75
76
  }
76
77
  });
77
78
  }
@@ -98,7 +99,7 @@ async function exec_shell(data) {
98
99
  // child.on('close', code => {
99
100
  child.on('exit', code => {
100
101
  if (!data.ignore_code && code != 0) {
101
- let errMsg = iconv.decode(Buffer.concat(errors), encoding);
102
+ let errMsg = !raw_output ? iconv.decode(Buffer.concat(errors), encoding) : Buffer.concat(errors).toString();
102
103
  let isAcceptableErrors = errMsg && acceptableErrors.some(err => {
103
104
  return errMsg.indexOf(err) >= 0;
104
105
  });
@@ -107,7 +108,7 @@ async function exec_shell(data) {
107
108
  }
108
109
  }
109
110
  if (results.length) {
110
- let result = iconv.decode(Buffer.concat(results), encoding);
111
+ let result = !raw_output ? iconv.decode(Buffer.concat(results), encoding) : Buffer.concat(results);
111
112
  if (data.trim) {
112
113
  result = result.trim();
113
114
  }