node-automator 1.4.9 → 1.4.11

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,7 @@ 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');
121
122
 
122
123
  const globalData = {
123
124
  "executed_cfg": [], // 执行过的配置文件
@@ -479,6 +480,7 @@ function init() {
479
480
  register("ali_oss", AliOssCommand, false);
480
481
  register("backup", BackupCommand, false);
481
482
  register("compress", CompressCommand, false);
483
+ register("word2txt", Word2txtCommand, false);
482
484
  }
483
485
 
484
486
  module.exports = {
@@ -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/index.js CHANGED
@@ -70,11 +70,18 @@ async function getCfgs() {
70
70
  async function MainProcess() {
71
71
  const enableTimer = argv.ENABLE_TIMER;
72
72
  const timerInterval = argv.TIMER_INTERVAL;
73
+ const estimateTime = +argv.ESTIMATE_TIME;
73
74
  let beginTime = Date.now();
74
75
  let timer;
75
76
  if (enableTimer && timerInterval) {
76
77
  timer = setInterval(() => {
77
- info(`\r[${formatTimestampMillisec(Date.now())}] 任务已运行 ${formatTimeInMillisec((Date.now() - beginTime), "hh:mm:ss")} ${clear_line_end}`, "");
78
+ const elapsedTime = Date.now() - beginTime;
79
+ if (!estimateTime) {
80
+ info(`\r[${formatTimestampMillisec(Date.now())}] 任务已运行 ${formatTimeInMillisec(elapsedTime, "hh:mm:ss")} ${clear_line_end}`, "");
81
+ } else {
82
+ const estimateLeft = Math.max(0, estimateTime - elapsedTime);
83
+ info(`\r[${formatTimestampMillisec(Date.now())}] 任务已运行 ${formatTimeInMillisec(elapsedTime, "hh:mm:ss")}, 预计剩余 ${formatTimeInMillisec(estimateLeft, "hh:mm:ss")} ${clear_line_end}`, "");
84
+ }
78
85
  }, timerInterval);
79
86
  }
80
87
  let lastError = null;
@@ -98,7 +105,17 @@ async function MainProcess() {
98
105
  if (enableTimer) {
99
106
  clearInterval(timer);
100
107
  info("")
101
- info(`>>> 任务总耗时 ${formatTimeInMillisec((Date.now() - beginTime))} <<<`, undefined, undefined, true);
108
+ const costTime = Date.now() - beginTime;
109
+ let timeLog = `任务总耗时 ${formatTimeInMillisec(costTime, "hh:mm:ss")}`;
110
+ if (estimateTime) {
111
+ const offsetTime = costTime - estimateTime;
112
+ if (offsetTime > 0) {
113
+ timeLog += `, 比预期慢了 ${formatTimeInMillisec(offsetTime, "hh:mm:ss")}`;
114
+ } else {
115
+ timeLog += `, 比预期快了 ${formatTimeInMillisec(-offsetTime, "hh:mm:ss")}`;
116
+ }
117
+ }
118
+ success(`>>> ${timeLog} <<<`, undefined, undefined, true);
102
119
  }
103
120
 
104
121
  let code = lastError ? (getLastErrorCode() || 1) : 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-automator",
3
- "version": "1.4.9",
3
+ "version": "1.4.11",
4
4
  "description": "Execute automation with yaml configuration(compatible with json)",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -41,6 +41,7 @@
41
41
  "log4js": "^6.3.0",
42
42
  "luaparse": "^0.3.1",
43
43
  "mail-watcher": "^0.6.1",
44
+ "mammoth": "^1.8.0",
44
45
  "markdown-table": "^2.0.0",
45
46
  "mysql": "^2.18.1",
46
47
  "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
  }