@vbarbarosh/node-helpers 3.36.0 → 3.37.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.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "Vladimir Barbarosh <vladimir.barbarosh@gmail.com>",
3
3
  "license": "MIT",
4
4
  "name": "@vbarbarosh/node-helpers",
5
- "version": "3.36.0",
5
+ "version": "3.37.1",
6
6
  "description": "A set of helpers for JavaScript/Node.js",
7
7
  "files": [
8
8
  "src"
@@ -1,17 +1,17 @@
1
1
  function format_bytes(bytes)
2
2
  {
3
3
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
4
- if (Number.isNaN(bytes*1)) {
4
+ if (typeof bytes !== 'number' || Number.isNaN(bytes)) {
5
5
  return 'n/a';
6
6
  }
7
- if (bytes == 0) {
7
+ if (!bytes) {
8
8
  return '0KB';
9
9
  }
10
10
  if (bytes < 1024) {
11
11
  return '1KB';
12
12
  }
13
13
  const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
14
- return `${(bytes / (1024 ** i)).toFixed(bytes > 1024*1024 ? 1 : 0)}${sizes[i]}`;
14
+ return `${(bytes / (1024 ** i)).toFixed(bytes > 1024*1024 ? 2 : 0)}${sizes[i]}`.replace(/\.00/, '.0');
15
15
  }
16
16
 
17
17
  module.exports = format_bytes;
@@ -0,0 +1,22 @@
1
+ const assert = require('assert');
2
+ const format_bytes = require('./format_bytes');
3
+
4
+ const items = [
5
+ ['', 'n/a'],
6
+ [null, 'n/a'],
7
+ [undefined, 'n/a'],
8
+ [0, '0KB'],
9
+ [1, '1KB'],
10
+ [1023, '1KB'],
11
+ [2048, '2KB'],
12
+ [35.45*1024*1024, '35.45MB'],
13
+ [3.92*1024*1024*1024, '3.92GB'],
14
+ ];
15
+
16
+ describe('format_bytes', function () {
17
+ items.forEach(function ([input, expected]) {
18
+ it(`${input} → ${expected}`, function () {
19
+ assert.strictEqual(expected, format_bytes(input));
20
+ });
21
+ });
22
+ });
@@ -0,0 +1,14 @@
1
+ function parse_bytes(bytes)
2
+ {
3
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
4
+ if (typeof bytes !== 'string') {
5
+ return Number.NaN;
6
+ }
7
+ const m = bytes.toUpperCase().match(/(\d+([.]?\d+)?)(([KMGTP]I?)?B)/);
8
+ if (!m) {
9
+ return Number.NaN;
10
+ }
11
+ return Math.floor(m[1]*Math.pow(1024, sizes.indexOf(m[3].replace('I', ''))));
12
+ }
13
+
14
+ module.exports = parse_bytes;
@@ -0,0 +1,21 @@
1
+ const assert = require('assert');
2
+ const parse_bytes = require('./parse_bytes');
3
+
4
+ const items = [
5
+ ['', Number.NaN],
6
+ [null, Number.NaN],
7
+ [undefined, Number.NaN],
8
+ ['0KB', 0],
9
+ ['1KB', 1024],
10
+ ['2KB', 2048],
11
+ ['35.45MB', Math.floor(35.45*1024*1024)],
12
+ ['3.92GB', Math.floor(3.92*1024*1024*1024)],
13
+ ];
14
+
15
+ describe('parse_bytes', function () {
16
+ items.forEach(function ([input, expected]) {
17
+ it(`${input} → ${expected}`, function () {
18
+ assert.strictEqual(expected, parse_bytes(input));
19
+ });
20
+ });
21
+ });
@@ -1,11 +1,13 @@
1
1
  const child_process = require('child_process');
2
+ const format_seconds = require('./format_seconds');
2
3
  const stream = require('stream');
3
4
  const stream_each = require('./stream_each');
4
5
  const stream_ytdlp_progress = require('./stream_ytdlp_progress');
5
6
 
6
- async function shell_ytdlp_progress(args, {progress_fn, ...options})
7
+ async function shell_ytdlp_progress(args, {user_friendly_status, ...options})
7
8
  {
8
9
  const proc = child_process.spawn('yt-dlp', ['--progress', ...args], {...options, stdio: 'pipe'});
10
+ const time0 = Date.now();
9
11
 
10
12
  const promises = [];
11
13
  promises.push(new Promise(function (resolve, reject) {
@@ -16,6 +18,16 @@ async function shell_ytdlp_progress(args, {progress_fn, ...options})
16
18
  promises.push(stream.promises.pipeline(proc.stderr, stream_each(v => console.log(`[stderr] ${v}`))));
17
19
 
18
20
  await Promise.all(promises);
21
+
22
+ function progress_fn(v) {
23
+ const duration = format_seconds((Date.now() - time0)/1000);
24
+ if (v.merging) {
25
+ user_friendly_status(`Merging... duration=${duration}`);
26
+ }
27
+ else {
28
+ user_friendly_status(`${v.perc} | [${v.current_part}/${v.total_parts}] ${v.done} of ${v.total} at ${v.speed} ETA ${v.eta} duration=${duration}`);
29
+ }
30
+ }
19
31
  }
20
32
 
21
33
  module.exports = shell_ytdlp_progress;
@@ -1,16 +1,81 @@
1
+ const format_bytes = require('./format_bytes');
2
+ const format_percents = require('./format_percents');
3
+ const parse_bytes = require('./parse_bytes');
1
4
  const stream = require('stream');
2
5
  const stream_filter = require('./stream_filter');
3
6
  const stream_lines = require('./stream_lines');
4
7
  const stream_map = require('./stream_map');
5
8
 
9
+ // [download] 0.0% of 15.71MiB at Unknown B/s ETA Unknown
10
+ // [download] 0.0% of 15.71MiB at Unknown B/s ETA Unknown
11
+ // [download] 0.0% of 15.71MiB at Unknown B/s ETA Unknown
12
+ // [download] 0.1% of 15.71MiB at Unknown B/s ETA Unknown
13
+ // [download] 0.2% of 15.71MiB at 21.76MiB/s ETA 00:00
14
+ // [download] 0.4% of 15.71MiB at 16.48MiB/s ETA 00:00
15
+ // [download] 0.8% of 15.71MiB at 25.54MiB/s ETA 00:00
16
+ // [download] 1.6% of 15.71MiB at 30.65MiB/s ETA 00:00
17
+ // [download] 3.2% of 15.71MiB at 42.99MiB/s ETA 00:00
18
+ // [download] 6.4% of 15.71MiB at 66.25MiB/s ETA 00:00
19
+ // [download] 12.7% of 15.71MiB at 81.24MiB/s ETA 00:00
20
+ // [download] 25.5% of 15.71MiB at 55.11MiB/s ETA 00:00
21
+ // [download] 50.9% of 15.71MiB at 33.83MiB/s ETA 00:00
22
+ // [download] 61.7% of 15.71MiB at 33.98MiB/s ETA 00:00
23
+ // [download] 61.7% of 15.71MiB at Unknown B/s ETA Unknown
24
+ // [download] 61.7% of 15.71MiB at Unknown B/s ETA Unknown
25
+ // [download] 61.7% of 15.71MiB at Unknown B/s ETA Unknown
26
+ // [download] 61.8% of 15.71MiB at Unknown B/s ETA Unknown
27
+ // [download] 61.9% of 15.71MiB at 12.32MiB/s ETA 00:00
28
+ // [download] 62.1% of 15.71MiB at 14.26MiB/s ETA 00:00
29
+ // [download] 62.5% of 15.71MiB at 25.10MiB/s ETA 00:00
30
+ // [download] 63.3% of 15.71MiB at 34.18MiB/s ETA 00:00
31
+ // [download] 64.9% of 15.71MiB at 8.95MiB/s ETA 00:00
32
+ // [download] 68.1% of 15.71MiB at 16.75MiB/s ETA 00:00
33
+ // [download] 74.4% of 15.71MiB at 29.10MiB/s ETA 00:00
34
+ // [download] 87.2% of 15.71MiB at 40.45MiB/s ETA 00:00
35
+ // [download] 100.0% of 15.71MiB at 47.64MiB/s ETA 00:00
36
+ // [download] 100% of 15.71MiB in 00:00:00 at 29.07MiB/s
37
+ // [Merger] Merging formats into "xxxxxxxxxxxxxxx.webm"
38
+ // Deleting original file xxxxxxxxxxxxxxx.f251.webm (pass -k to keep)
39
+ // Deleting original file xxxxxxxxxxxxxxx.f248.webm (pass -k to keep)
40
+
6
41
  function stream_ytdlp_progress()
7
42
  {
8
- const re = /^\[download] (.*) of (.*) at (.*) ETA (.*)$/;
43
+ let last = {};
44
+ let current_part = 1;
45
+ const downloading_formats = [];
9
46
  return stream.compose(
10
47
  stream_lines(),
11
- stream_map(function (v) {
12
- const m = re.exec(v);
13
- return !m ? false : {done: m[1].trim(), of: m[2].trim(), speed: m[3].trim(), eta: m[4].trim()};
48
+ stream_map(function (line) {
49
+ let m;
50
+ if (m = line.match(/^\[info] \S+: Downloading \d+ format\(s\): (.+)$/)) {
51
+ downloading_formats.push(...m[1].split('+'));
52
+ return false;
53
+ }
54
+ if (m = line.match(/^\[download] Destination: .*f(\d+)\.[^.]+/)) {
55
+ current_part = downloading_formats.indexOf(m[1]) + 1;
56
+ return false;
57
+ }
58
+ if (m = line.match(/^\[Merger]/i)) {
59
+ last.merging = true;
60
+ return last;
61
+ }
62
+ if (m = line.match(/^\[download] (.*) of (.*) at (.*) ETA (.*)$/)) {
63
+ const percentage = parseFloat(m[1].trim())/100;
64
+ const total = parse_bytes(m[2].trim());
65
+ const speed = m[3].trim().replace('i', '');
66
+ const eta = m[4].trim();
67
+ return last = {
68
+ current_part,
69
+ total_parts: downloading_formats.length,
70
+ perc: format_percents(percentage),
71
+ done: format_bytes(percentage*total),
72
+ total: format_bytes(total),
73
+ speed: speed.toLowerCase().includes('unknown') ? '~' : speed,
74
+ eta: eta.toLowerCase().includes('unknown') ? '~' : eta,
75
+ merging: false,
76
+ };
77
+ }
78
+ return false;
14
79
  }),
15
80
  stream_filter(v => v),
16
81
  );