reelsort 0.1.2 → 0.2.0
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/dist/cli.js +203 -175
- package/dist/index.d.mts +16 -9
- package/dist/index.d.ts +16 -9
- package/dist/index.js +125 -104
- package/dist/index.mjs +119 -100
- package/package.json +2 -4
package/dist/cli.js
CHANGED
|
@@ -24,13 +24,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/program.ts
|
|
27
|
-
var
|
|
27
|
+
var import_termkit19 = require("termkit");
|
|
28
28
|
|
|
29
29
|
// src/actions/add.ts
|
|
30
|
-
var import_cosmetic = __toESM(require("cosmetic"));
|
|
31
30
|
var import_fs3 = require("fs");
|
|
32
31
|
var import_path3 = require("path");
|
|
33
|
-
var
|
|
32
|
+
var import_termkit2 = require("termkit");
|
|
34
33
|
|
|
35
34
|
// src/config.ts
|
|
36
35
|
var import_fs = require("fs");
|
|
@@ -277,28 +276,21 @@ var searchTv = async (title, apiKey) => {
|
|
|
277
276
|
};
|
|
278
277
|
|
|
279
278
|
// src/refs/spinner.ts
|
|
280
|
-
var
|
|
279
|
+
var import_termkit = require("termkit");
|
|
281
280
|
var Spinner = class {
|
|
282
281
|
spinner;
|
|
283
|
-
_isSpinning = false;
|
|
284
|
-
_text = "";
|
|
285
282
|
constructor() {
|
|
286
|
-
this.spinner = new
|
|
283
|
+
this.spinner = new import_termkit.Spinner();
|
|
287
284
|
}
|
|
288
285
|
get text() {
|
|
289
|
-
return this.
|
|
286
|
+
return this.spinner.text;
|
|
290
287
|
}
|
|
291
288
|
set text(t) {
|
|
292
|
-
this.
|
|
293
|
-
if (this._isSpinning) this.spinner.message(t);
|
|
294
|
-
}
|
|
295
|
-
get isSpinning() {
|
|
296
|
-
return this._isSpinning;
|
|
289
|
+
this.spinner.text = t;
|
|
297
290
|
}
|
|
298
291
|
start(s) {
|
|
299
|
-
if (s) this.
|
|
292
|
+
if (s) this.spinner.text = s;
|
|
300
293
|
this.spinner.start();
|
|
301
|
-
this._isSpinning = true;
|
|
302
294
|
return this;
|
|
303
295
|
}
|
|
304
296
|
info(s) {
|
|
@@ -319,8 +311,6 @@ var Spinner = class {
|
|
|
319
311
|
}
|
|
320
312
|
stop() {
|
|
321
313
|
this.spinner.stop();
|
|
322
|
-
this._isSpinning = false;
|
|
323
|
-
process.stdin.resume();
|
|
324
314
|
return this;
|
|
325
315
|
}
|
|
326
316
|
};
|
|
@@ -338,7 +328,7 @@ var add = async ({ name }) => {
|
|
|
338
328
|
if (results.length === 0) throw new Error(`no TMDb results for "${name}"`);
|
|
339
329
|
let picked = results.length === 1 ? results[0] : null;
|
|
340
330
|
if (!picked) {
|
|
341
|
-
const select = new
|
|
331
|
+
const select = new import_termkit2.Select();
|
|
342
332
|
const items = results.map((r) => ({
|
|
343
333
|
label: r.year ? `${r.title} (${r.year})` : r.title,
|
|
344
334
|
description: [r.overview?.slice(0, 60), hyperlink(r.url, "themoviedb.org")].filter(Boolean).join(" \xB7 "),
|
|
@@ -353,14 +343,14 @@ var add = async ({ name }) => {
|
|
|
353
343
|
(0, import_fs3.mkdirSync)(showPath, { recursive: true });
|
|
354
344
|
upsertShow(showPath, picked.id, picked.title);
|
|
355
345
|
spinner_default.start();
|
|
356
|
-
spinner_default.succeed(`added ${
|
|
346
|
+
spinner_default.succeed(`added ${import_termkit2.Color.cyan.encoder(folderName)}`);
|
|
357
347
|
spinner_default.stop();
|
|
358
348
|
};
|
|
359
349
|
var add_default = add;
|
|
360
350
|
|
|
361
351
|
// src/actions/clean.ts
|
|
362
|
-
var import_cosmetic2 = __toESM(require("cosmetic"));
|
|
363
352
|
var import_fs4 = require("fs");
|
|
353
|
+
var import_termkit3 = require("termkit");
|
|
364
354
|
var parseOlderThan = (s) => {
|
|
365
355
|
const match = s.match(/^(\d+)([dhm])$/);
|
|
366
356
|
if (!match) return null;
|
|
@@ -393,17 +383,17 @@ var clean = async ({ dryRun, olderThan }) => {
|
|
|
393
383
|
continue;
|
|
394
384
|
}
|
|
395
385
|
if (dryRun) {
|
|
396
|
-
spinner_default.succeed(`[dry] would remove ${
|
|
386
|
+
spinner_default.succeed(`[dry] would remove ${import_termkit3.Color.blue.encoder(imp.sourcePath)}`);
|
|
397
387
|
cleaned++;
|
|
398
388
|
continue;
|
|
399
389
|
}
|
|
400
390
|
try {
|
|
401
391
|
(0, import_fs4.rmSync)(imp.sourcePath, { recursive: true, force: true });
|
|
402
392
|
deleteImport(imp.id);
|
|
403
|
-
spinner_default.succeed(`removed ${
|
|
393
|
+
spinner_default.succeed(`removed ${import_termkit3.Color.blue.encoder(imp.sourcePath)}`);
|
|
404
394
|
cleaned++;
|
|
405
395
|
} catch {
|
|
406
|
-
spinner_default.warn(`locked or inaccessible, skipped: ${
|
|
396
|
+
spinner_default.warn(`locked or inaccessible, skipped: ${import_termkit3.Color.blue.encoder(imp.sourcePath)}`);
|
|
407
397
|
skipped++;
|
|
408
398
|
}
|
|
409
399
|
}
|
|
@@ -414,8 +404,8 @@ var clean = async ({ dryRun, olderThan }) => {
|
|
|
414
404
|
var clean_default = clean;
|
|
415
405
|
|
|
416
406
|
// src/actions/config.ts
|
|
417
|
-
var import_cosmetic3 = __toESM(require("cosmetic"));
|
|
418
407
|
var import_path4 = require("path");
|
|
408
|
+
var import_termkit4 = require("termkit");
|
|
419
409
|
|
|
420
410
|
// src/helpers/formatEpisode.ts
|
|
421
411
|
var DEFAULT_EPISODE_FORMAT = "{s}x{ee}";
|
|
@@ -435,37 +425,64 @@ var formatEpisode = (season, episode, format = DEFAULT_EPISODE_FORMAT, double =
|
|
|
435
425
|
|
|
436
426
|
// src/actions/config.ts
|
|
437
427
|
var DEST_TYPES = ["movie", "tv", "ps3"];
|
|
438
|
-
var
|
|
439
|
-
|
|
440
|
-
const dir = (0, import_path4.resolve)(value);
|
|
428
|
+
var sourceAdd = async ({ dir }) => {
|
|
429
|
+
const resolved = (0, import_path4.resolve)(dir);
|
|
441
430
|
const config = getConfig();
|
|
442
|
-
if (config.sources.includes(
|
|
431
|
+
if (config.sources.includes(resolved)) {
|
|
443
432
|
spinner_default.start();
|
|
444
|
-
spinner_default.info(`source already configured: ${
|
|
433
|
+
spinner_default.info(`source already configured: ${import_termkit4.Color.blue.encoder(resolved)}`);
|
|
445
434
|
spinner_default.stop();
|
|
446
435
|
return;
|
|
447
436
|
}
|
|
448
|
-
config.sources.push(
|
|
437
|
+
config.sources.push(resolved);
|
|
449
438
|
saveConfig(config);
|
|
450
439
|
spinner_default.start();
|
|
451
|
-
spinner_default.succeed(`added source: ${
|
|
440
|
+
spinner_default.succeed(`added source: ${import_termkit4.Color.blue.encoder(resolved)}`);
|
|
452
441
|
spinner_default.stop();
|
|
453
442
|
};
|
|
454
|
-
var
|
|
455
|
-
|
|
456
|
-
const dir = (0, import_path4.resolve)(value);
|
|
443
|
+
var sourceRemove = async ({ dir }) => {
|
|
444
|
+
const resolved = (0, import_path4.resolve)(dir);
|
|
457
445
|
const config = getConfig();
|
|
458
|
-
const index = config.sources.indexOf(
|
|
446
|
+
const index = config.sources.indexOf(resolved);
|
|
459
447
|
if (index === -1) {
|
|
460
448
|
spinner_default.start();
|
|
461
|
-
spinner_default.warn(`source not found: ${
|
|
449
|
+
spinner_default.warn(`source not found: ${import_termkit4.Color.blue.encoder(resolved)}`);
|
|
462
450
|
spinner_default.stop();
|
|
463
451
|
return;
|
|
464
452
|
}
|
|
465
453
|
config.sources.splice(index, 1);
|
|
466
454
|
saveConfig(config);
|
|
467
455
|
spinner_default.start();
|
|
468
|
-
spinner_default.succeed(`removed source: ${
|
|
456
|
+
spinner_default.succeed(`removed source: ${import_termkit4.Color.blue.encoder(resolved)}`);
|
|
457
|
+
spinner_default.stop();
|
|
458
|
+
};
|
|
459
|
+
var destAdd = async ({ type, dir }) => {
|
|
460
|
+
if (!DEST_TYPES.includes(type)) {
|
|
461
|
+
throw new Error(`unknown type '${type}', expected: ${DEST_TYPES.join(", ")}`);
|
|
462
|
+
}
|
|
463
|
+
const resolved = (0, import_path4.resolve)(dir);
|
|
464
|
+
const config = getConfig();
|
|
465
|
+
config.dest[type] = resolved;
|
|
466
|
+
saveConfig(config);
|
|
467
|
+
spinner_default.start();
|
|
468
|
+
spinner_default.succeed(`set ${type} destination: ${import_termkit4.Color.cyan.encoder(resolved)}`);
|
|
469
|
+
spinner_default.stop();
|
|
470
|
+
};
|
|
471
|
+
var destRemove = async ({ type }) => {
|
|
472
|
+
if (!DEST_TYPES.includes(type)) {
|
|
473
|
+
throw new Error(`unknown type '${type}', expected: ${DEST_TYPES.join(", ")}`);
|
|
474
|
+
}
|
|
475
|
+
const config = getConfig();
|
|
476
|
+
if (!config.dest[type]) {
|
|
477
|
+
spinner_default.start();
|
|
478
|
+
spinner_default.warn(`no ${type} destination configured`);
|
|
479
|
+
spinner_default.stop();
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
delete config.dest[type];
|
|
483
|
+
saveConfig(config);
|
|
484
|
+
spinner_default.start();
|
|
485
|
+
spinner_default.succeed(`removed ${type} destination`);
|
|
469
486
|
spinner_default.stop();
|
|
470
487
|
};
|
|
471
488
|
var configSet = async ({ key, subkey, value }) => {
|
|
@@ -474,7 +491,7 @@ var configSet = async ({ key, subkey, value }) => {
|
|
|
474
491
|
config.language = subkey;
|
|
475
492
|
saveConfig(config);
|
|
476
493
|
spinner_default.start();
|
|
477
|
-
spinner_default.succeed(`set subtitle language: ${
|
|
494
|
+
spinner_default.succeed(`set subtitle language: ${import_termkit4.Color.cyan.encoder(subkey)}`);
|
|
478
495
|
spinner_default.stop();
|
|
479
496
|
return;
|
|
480
497
|
}
|
|
@@ -504,21 +521,11 @@ var configSet = async ({ key, subkey, value }) => {
|
|
|
504
521
|
}
|
|
505
522
|
saveConfig(config);
|
|
506
523
|
spinner_default.start();
|
|
507
|
-
spinner_default.succeed(`set ${subkey} format: ${
|
|
524
|
+
spinner_default.succeed(`set ${subkey} format: ${import_termkit4.Color.cyan.encoder(value ?? subkey)}`);
|
|
508
525
|
spinner_default.stop();
|
|
509
526
|
return;
|
|
510
527
|
}
|
|
511
|
-
|
|
512
|
-
if (!DEST_TYPES.includes(subkey)) {
|
|
513
|
-
throw new Error(`unknown type '${subkey}', expected: ${DEST_TYPES.join(", ")}`);
|
|
514
|
-
}
|
|
515
|
-
if (!value) throw new Error(`missing path for dest ${subkey}`);
|
|
516
|
-
const dir = (0, import_path4.resolve)(value);
|
|
517
|
-
config.dest[subkey] = dir;
|
|
518
|
-
saveConfig(config);
|
|
519
|
-
spinner_default.start();
|
|
520
|
-
spinner_default.succeed(`set ${subkey} destination: ${import_cosmetic3.default.cyan.encoder(dir)}`);
|
|
521
|
-
spinner_default.stop();
|
|
528
|
+
throw new Error(`unknown key '${key}', expected: language, tmdb-key, format`);
|
|
522
529
|
};
|
|
523
530
|
var configShow = async () => {
|
|
524
531
|
const config = getConfig();
|
|
@@ -526,7 +533,7 @@ var configShow = async () => {
|
|
|
526
533
|
if (config.sources.length === 0) {
|
|
527
534
|
console.log(" (none)");
|
|
528
535
|
} else {
|
|
529
|
-
for (const s of config.sources) console.log(` ${
|
|
536
|
+
for (const s of config.sources) console.log(` ${import_termkit4.Color.blue.encoder(s)}`);
|
|
530
537
|
}
|
|
531
538
|
console.log("\nDestinations:");
|
|
532
539
|
const entries = DEST_TYPES.map((t) => ({ type: t, path: config.dest[t] })).filter((e) => e.path);
|
|
@@ -534,26 +541,26 @@ var configShow = async () => {
|
|
|
534
541
|
console.log(" (none)");
|
|
535
542
|
} else {
|
|
536
543
|
for (const { type, path } of entries) {
|
|
537
|
-
console.log(` ${type.padEnd(6)} ${
|
|
544
|
+
console.log(` ${type.padEnd(6)} ${import_termkit4.Color.cyan.encoder(path)}`);
|
|
538
545
|
}
|
|
539
546
|
}
|
|
540
547
|
console.log(`
|
|
541
|
-
Subtitle language: ${
|
|
542
|
-
console.log(`TMDb API key: ${config.tmdbApiKey ?
|
|
543
|
-
console.log(`Movie format: ${
|
|
544
|
-
console.log(`Episode format: ${
|
|
545
|
-
console.log(`Season folder: ${
|
|
548
|
+
Subtitle language: ${import_termkit4.Color.cyan.encoder(config.language ?? "eng (default)")}`);
|
|
549
|
+
console.log(`TMDb API key: ${config.tmdbApiKey ? import_termkit4.Color.green.encoder("configured") : import_termkit4.Color.red.encoder("not set")}`);
|
|
550
|
+
console.log(`Movie format: ${import_termkit4.Color.cyan.encoder(config.format?.movie ?? DEFAULT_MOVIE_FORMAT + " (default)")}`);
|
|
551
|
+
console.log(`Episode format: ${import_termkit4.Color.cyan.encoder(config.format?.episode ?? DEFAULT_EPISODE_FORMAT + " (default)")}`);
|
|
552
|
+
console.log(`Season folder: ${import_termkit4.Color.cyan.encoder(config.format?.season ?? DEFAULT_SEASON_FORMAT + " (default)")}`);
|
|
546
553
|
console.log();
|
|
547
554
|
};
|
|
548
555
|
|
|
549
556
|
// src/actions/differences.ts
|
|
550
|
-
var import_cosmetic4 = __toESM(require("cosmetic"));
|
|
551
557
|
var import_fs5 = require("fs");
|
|
552
558
|
var import_path5 = require("path");
|
|
559
|
+
var import_termkit5 = require("termkit");
|
|
553
560
|
var differences = async ({ dir1: rawDir1, dir2: rawDir2, only, ignore }) => {
|
|
554
561
|
let dir1 = rawDir1;
|
|
555
562
|
let dir2 = rawDir2;
|
|
556
|
-
spinner_default.text = `checking differences between ${
|
|
563
|
+
spinner_default.text = `checking differences between ${import_termkit5.Color.blue.encoder(dir1)} and ${import_termkit5.Color.blue.encoder(dir2)}`;
|
|
557
564
|
spinner_default.start();
|
|
558
565
|
dir1 = (0, import_path5.resolve)(dir1);
|
|
559
566
|
dir2 = (0, import_path5.resolve)(dir2);
|
|
@@ -589,18 +596,17 @@ var differences = async ({ dir1: rawDir1, dir2: rawDir2, only, ignore }) => {
|
|
|
589
596
|
removed.push(l);
|
|
590
597
|
}
|
|
591
598
|
}
|
|
592
|
-
spinner_default.succeed(`checked differences between ${
|
|
599
|
+
spinner_default.succeed(`checked differences between ${import_termkit5.Color.blue.encoder(dir1)} and ${import_termkit5.Color.blue.encoder(dir2)}`);
|
|
593
600
|
spinner_default.succeed(`found ${added.length} added files`);
|
|
594
601
|
spinner_default.succeed(`found ${removed.length} removed files`);
|
|
595
602
|
spinner_default.stop();
|
|
596
|
-
for (const i of added) console.log(`${
|
|
597
|
-
for (const i of removed) console.log(`${
|
|
603
|
+
for (const i of added) console.log(`${import_termkit5.Color.green.encoder("added")} ${i}`);
|
|
604
|
+
for (const i of removed) console.log(`${import_termkit5.Color.red.encoder("removed")} ${i}`);
|
|
598
605
|
};
|
|
599
606
|
var differences_default = differences;
|
|
600
607
|
|
|
601
608
|
// src/actions/ended.ts
|
|
602
|
-
var
|
|
603
|
-
var import_termpulse3 = require("termpulse");
|
|
609
|
+
var import_termkit6 = require("termkit");
|
|
604
610
|
var ended = async ({ remove }) => {
|
|
605
611
|
const shows2 = getShows();
|
|
606
612
|
const candidates = shows2.filter((s) => remove ? s.ended : !s.ended);
|
|
@@ -610,7 +616,7 @@ var ended = async ({ remove }) => {
|
|
|
610
616
|
spinner_default.stop();
|
|
611
617
|
return;
|
|
612
618
|
}
|
|
613
|
-
const select = new
|
|
619
|
+
const select = new import_termkit6.Select();
|
|
614
620
|
const items = candidates.map((s) => ({
|
|
615
621
|
label: s.path.split("/").pop() ?? s.path,
|
|
616
622
|
path: s.path
|
|
@@ -621,17 +627,17 @@ var ended = async ({ remove }) => {
|
|
|
621
627
|
setShowEnded(picked.path, !remove);
|
|
622
628
|
spinner_default.start();
|
|
623
629
|
if (remove) {
|
|
624
|
-
spinner_default.succeed(`marked as active: ${
|
|
630
|
+
spinner_default.succeed(`marked as active: ${import_termkit6.Color.cyan.encoder(picked.label)}`);
|
|
625
631
|
} else {
|
|
626
|
-
spinner_default.succeed(`marked as ended: ${
|
|
632
|
+
spinner_default.succeed(`marked as ended: ${import_termkit6.Color.cyan.encoder(picked.label)}`);
|
|
627
633
|
}
|
|
628
634
|
spinner_default.stop();
|
|
629
635
|
};
|
|
630
636
|
var ended_default = ended;
|
|
631
637
|
|
|
632
638
|
// src/actions/history.ts
|
|
633
|
-
var import_cosmetic6 = __toESM(require("cosmetic"));
|
|
634
639
|
var import_path6 = require("path");
|
|
640
|
+
var import_termkit7 = require("termkit");
|
|
635
641
|
var history = async ({ limit, imports }) => {
|
|
636
642
|
if (imports) {
|
|
637
643
|
const sessions = getImportHistory(limit ?? 10);
|
|
@@ -643,11 +649,11 @@ var history = async ({ limit, imports }) => {
|
|
|
643
649
|
const date = new Date(session.sessionId);
|
|
644
650
|
const label = isNaN(date.getTime()) ? session.sessionId : date.toLocaleString();
|
|
645
651
|
console.log(`
|
|
646
|
-
${
|
|
652
|
+
${import_termkit7.Color.yellow.encoder(label)} (${session.records.length} item${session.records.length !== 1 ? "s" : ""})`);
|
|
647
653
|
for (const r of session.records) {
|
|
648
654
|
const src = (0, import_path6.basename)(r.sourcePath);
|
|
649
|
-
const dest =
|
|
650
|
-
const mode = r.mode !== "move" ? ` ${
|
|
655
|
+
const dest = import_termkit7.Color.cyan.encoder(r.destinationPath);
|
|
656
|
+
const mode = r.mode !== "move" ? ` ${import_termkit7.Color.blue.encoder(`[${r.mode}]`)}` : "";
|
|
651
657
|
console.log(` ${src} \u2192 ${dest}${mode}`);
|
|
652
658
|
}
|
|
653
659
|
}
|
|
@@ -662,11 +668,11 @@ ${import_cosmetic6.default.yellow.encoder(label)} (${session.records.length} it
|
|
|
662
668
|
const label = isNaN(date.getTime()) ? session.sessionId : date.toLocaleString();
|
|
663
669
|
const folders = session.records.filter((r) => (0, import_path6.extname)(r.newPath) === "");
|
|
664
670
|
console.log(`
|
|
665
|
-
${
|
|
671
|
+
${import_termkit7.Color.yellow.encoder(label)} (${folders.length} item${folders.length !== 1 ? "s" : ""})`);
|
|
666
672
|
for (const r of folders) {
|
|
667
673
|
const oldName = (0, import_path6.basename)(r.oldPath);
|
|
668
674
|
const newName = (0, import_path6.basename)(r.newPath);
|
|
669
|
-
console.log(` ${
|
|
675
|
+
console.log(` ${import_termkit7.Color.blue.encoder(oldName)} \u2192 ${import_termkit7.Color.cyan.encoder(newName)}`);
|
|
670
676
|
}
|
|
671
677
|
}
|
|
672
678
|
}
|
|
@@ -675,10 +681,9 @@ ${import_cosmetic6.default.yellow.encoder(label)} (${folders.length} item${fold
|
|
|
675
681
|
var history_default = history;
|
|
676
682
|
|
|
677
683
|
// src/actions/link.ts
|
|
678
|
-
var import_cosmetic7 = __toESM(require("cosmetic"));
|
|
679
684
|
var import_fs6 = require("fs");
|
|
680
685
|
var import_path7 = require("path");
|
|
681
|
-
var
|
|
686
|
+
var import_termkit8 = require("termkit");
|
|
682
687
|
var parseShowTitle = (folderName) => {
|
|
683
688
|
const withoutYear = folderName.replace(/\s*\(\d{4}\)\s*$/, "").trim();
|
|
684
689
|
return withoutYear || folderName;
|
|
@@ -705,7 +710,7 @@ var link = async ({ force }) => {
|
|
|
705
710
|
skipped++;
|
|
706
711
|
continue;
|
|
707
712
|
}
|
|
708
|
-
spinner_default.start(`linking ${
|
|
713
|
+
spinner_default.start(`linking ${import_termkit8.Color.blue.encoder(show)}`);
|
|
709
714
|
const title = parseShowTitle(show);
|
|
710
715
|
const results = await searchTv(title, config.tmdbApiKey);
|
|
711
716
|
if (results.length === 0) {
|
|
@@ -715,12 +720,12 @@ var link = async ({ force }) => {
|
|
|
715
720
|
}
|
|
716
721
|
if (results.length === 1) {
|
|
717
722
|
upsertShow(showPath, results[0].id, results[0].title);
|
|
718
|
-
spinner_default.succeed(`${show} \u2192 ${
|
|
723
|
+
spinner_default.succeed(`${show} \u2192 ${import_termkit8.Color.cyan.encoder(results[0].title)} (${results[0].year})`);
|
|
719
724
|
linked++;
|
|
720
725
|
continue;
|
|
721
726
|
}
|
|
722
727
|
spinner_default.stop();
|
|
723
|
-
const select = new
|
|
728
|
+
const select = new import_termkit8.Select();
|
|
724
729
|
const items = results.map((r) => ({
|
|
725
730
|
label: r.year ? `${r.title} (${r.year})` : r.title,
|
|
726
731
|
description: [r.overview?.slice(0, 60), hyperlink(r.url, "themoviedb.org")].filter(Boolean).join(" \xB7 "),
|
|
@@ -730,7 +735,7 @@ var link = async ({ force }) => {
|
|
|
730
735
|
spinner_default.start();
|
|
731
736
|
if (picked) {
|
|
732
737
|
upsertShow(showPath, picked.id, picked.title);
|
|
733
|
-
spinner_default.succeed(`${show} \u2192 ${
|
|
738
|
+
spinner_default.succeed(`${show} \u2192 ${import_termkit8.Color.cyan.encoder(picked.title)} (${picked.year})`);
|
|
734
739
|
linked++;
|
|
735
740
|
} else {
|
|
736
741
|
spinner_default.info(`skipped: ${show}`);
|
|
@@ -745,9 +750,9 @@ var link = async ({ force }) => {
|
|
|
745
750
|
var link_default = link;
|
|
746
751
|
|
|
747
752
|
// src/actions/list.ts
|
|
748
|
-
var import_cosmetic8 = __toESM(require("cosmetic"));
|
|
749
753
|
var import_fs8 = require("fs");
|
|
750
754
|
var import_path9 = require("path");
|
|
755
|
+
var import_termkit9 = require("termkit");
|
|
751
756
|
|
|
752
757
|
// src/helpers/dirSize.ts
|
|
753
758
|
var import_fs7 = require("fs");
|
|
@@ -879,7 +884,6 @@ var parseLibraryFolder = (name) => {
|
|
|
879
884
|
if (match) return { title: match[1].trim(), year: parseInt(match[2]) };
|
|
880
885
|
return { title: name };
|
|
881
886
|
};
|
|
882
|
-
var col = (s, width) => s.padEnd(width).substring(0, width);
|
|
883
887
|
var list = async ({ type, missingSubs, codec: codecFilter, resolution: resFilter, sort }) => {
|
|
884
888
|
const config = getConfig();
|
|
885
889
|
const types = (type ? [type] : DEST_TYPES2).filter((t) => config.dest[t]);
|
|
@@ -888,7 +892,7 @@ var list = async ({ type, missingSubs, codec: codecFilter, resolution: resFilter
|
|
|
888
892
|
const destRoot = config.dest[t];
|
|
889
893
|
if (!(0, import_fs8.existsSync)(destRoot)) {
|
|
890
894
|
console.log(`
|
|
891
|
-
${t.toUpperCase()} ${
|
|
895
|
+
${t.toUpperCase()} ${import_termkit9.Color.blue.encoder(destRoot)} (not found)`);
|
|
892
896
|
continue;
|
|
893
897
|
}
|
|
894
898
|
const folders = (0, import_fs8.readdirSync)(destRoot).filter((f) => {
|
|
@@ -918,18 +922,29 @@ ${t.toUpperCase()} ${import_cosmetic8.default.blue.encoder(destRoot)} (not fou
|
|
|
918
922
|
const yearDiff = (b.year ?? 0) - (a.year ?? 0);
|
|
919
923
|
return yearDiff !== 0 ? yearDiff : a.title.localeCompare(b.title);
|
|
920
924
|
});
|
|
921
|
-
const titleW = Math.min(50, Math.max(10, ...filtered.map((e) => e.title.length)) + 2);
|
|
922
|
-
const divider = "\u2500".repeat(titleW + 44);
|
|
923
925
|
console.log(`
|
|
924
|
-
${
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
926
|
+
${import_termkit9.Color.yellow.encoder(t.toUpperCase())} ${import_termkit9.Color.blue.encoder(destRoot)}`);
|
|
927
|
+
new import_termkit9.Table(
|
|
928
|
+
filtered.map((e) => ({
|
|
929
|
+
title: e.title,
|
|
930
|
+
year: e.year,
|
|
931
|
+
resolution: e.resolution,
|
|
932
|
+
codec: e.codec,
|
|
933
|
+
size: e.size,
|
|
934
|
+
sub: e.hasSub
|
|
935
|
+
})),
|
|
936
|
+
{
|
|
937
|
+
separator: " ",
|
|
938
|
+
columns: [
|
|
939
|
+
{ key: "title", title: "Title" },
|
|
940
|
+
{ key: "year", title: "Year", align: "right", value: (v) => v != null ? String(v) : "\u2014" },
|
|
941
|
+
{ key: "resolution", title: "Res", value: (v) => v ?? "\u2014" },
|
|
942
|
+
{ key: "codec", title: "Codec", value: (v) => v ?? "\u2014" },
|
|
943
|
+
{ key: "size", title: "Size" },
|
|
944
|
+
{ key: "sub", title: "Sub", value: (v) => v ? import_termkit9.Color.green.encoder("\u2713") : import_termkit9.Color.red.encoder("\u2717") }
|
|
945
|
+
]
|
|
946
|
+
}
|
|
947
|
+
).print();
|
|
933
948
|
console.log(`${filtered.length} of ${entries.length} item${entries.length !== 1 ? "s" : ""}`);
|
|
934
949
|
}
|
|
935
950
|
console.log();
|
|
@@ -937,9 +952,9 @@ ${import_cosmetic8.default.yellow.encoder(t.toUpperCase())} ${import_cosmetic8.
|
|
|
937
952
|
var list_default = list;
|
|
938
953
|
|
|
939
954
|
// src/actions/missing.ts
|
|
940
|
-
var import_cosmetic9 = __toESM(require("cosmetic"));
|
|
941
955
|
var import_fs9 = require("fs");
|
|
942
956
|
var import_path10 = require("path");
|
|
957
|
+
var import_termkit10 = require("termkit");
|
|
943
958
|
var TODAY = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
944
959
|
var parseSeasonNumber = (folderName) => {
|
|
945
960
|
const match = folderName.match(/(?:season|s)\s*0*(\d+)/i);
|
|
@@ -1001,7 +1016,7 @@ var missing = async ({ show: showFilter }) => {
|
|
|
1001
1016
|
if (showMissing.length > 0) {
|
|
1002
1017
|
totalMissing += showMissing.length;
|
|
1003
1018
|
console.log(`
|
|
1004
|
-
${
|
|
1019
|
+
${import_termkit10.Color.yellow.encoder(show)}`);
|
|
1005
1020
|
for (const line of showMissing) console.log(line);
|
|
1006
1021
|
}
|
|
1007
1022
|
}
|
|
@@ -1020,9 +1035,9 @@ var missing_default = missing;
|
|
|
1020
1035
|
|
|
1021
1036
|
// src/actions/probe.ts
|
|
1022
1037
|
var import_child_process = require("child_process");
|
|
1023
|
-
var import_cosmetic10 = __toESM(require("cosmetic"));
|
|
1024
1038
|
var import_fs10 = require("fs");
|
|
1025
1039
|
var import_path11 = require("path");
|
|
1040
|
+
var import_termkit11 = require("termkit");
|
|
1026
1041
|
var DEST_TYPES3 = ["movie", "tv", "ps3"];
|
|
1027
1042
|
var CODEC_MAP2 = {
|
|
1028
1043
|
hevc: "x265",
|
|
@@ -1098,7 +1113,7 @@ var probe = async ({ type, force, verbose }) => {
|
|
|
1098
1113
|
for (const t of types) {
|
|
1099
1114
|
const destRoot = config.dest[t];
|
|
1100
1115
|
if (!(0, import_fs10.existsSync)(destRoot)) continue;
|
|
1101
|
-
spinner_default.text = `scanning ${
|
|
1116
|
+
spinner_default.text = `scanning ${import_termkit11.Color.blue.encoder(destRoot)}`;
|
|
1102
1117
|
const files = walkVideoFiles(destRoot);
|
|
1103
1118
|
for (const filePath of files) {
|
|
1104
1119
|
if (!force && getMediaInfo(filePath)) {
|
|
@@ -1106,7 +1121,7 @@ var probe = async ({ type, force, verbose }) => {
|
|
|
1106
1121
|
skipped++;
|
|
1107
1122
|
continue;
|
|
1108
1123
|
}
|
|
1109
|
-
spinner_default.text = `probing ${
|
|
1124
|
+
spinner_default.text = `probing ${import_termkit11.Color.blue.encoder(filePath)}`;
|
|
1110
1125
|
const result = runFfprobe(filePath);
|
|
1111
1126
|
if (!result) {
|
|
1112
1127
|
if (verbose) spinner_default.warn(`ffprobe failed: ${filePath}`);
|
|
@@ -1126,10 +1141,10 @@ var probe = async ({ type, force, verbose }) => {
|
|
|
1126
1141
|
var probe_default = probe;
|
|
1127
1142
|
|
|
1128
1143
|
// src/actions/rename.ts
|
|
1129
|
-
var import_cosmetic11 = __toESM(require("cosmetic"));
|
|
1130
1144
|
var import_fs11 = require("fs");
|
|
1131
1145
|
var import_path12 = require("path");
|
|
1132
1146
|
var import_rimraf = require("rimraf");
|
|
1147
|
+
var import_termkit12 = require("termkit");
|
|
1133
1148
|
|
|
1134
1149
|
// src/helpers/findSubtitle.ts
|
|
1135
1150
|
var LANGUAGE_ALIASES = {
|
|
@@ -1190,13 +1205,13 @@ var rename = async ({ dir: inputDir, type, verbose }) => {
|
|
|
1190
1205
|
const config = getConfig();
|
|
1191
1206
|
const language = config.language ?? "eng";
|
|
1192
1207
|
const movieFormat = config.format?.movie ?? DEFAULT_MOVIE_FORMAT;
|
|
1193
|
-
spinner_default.text = `renaming in ${
|
|
1208
|
+
spinner_default.text = `renaming in ${import_termkit12.Color.blue.encoder(dir)}`;
|
|
1194
1209
|
spinner_default.start();
|
|
1195
1210
|
if (!(0, import_fs11.existsSync)(dir)) throw new Error(`dir ${dir} does not exist`);
|
|
1196
1211
|
const list2 = (0, import_fs11.readdirSync)(dir);
|
|
1197
1212
|
let renamed = 0, removed = 0, skipped = 0;
|
|
1198
1213
|
for (const [index, entry] of list2.entries()) {
|
|
1199
|
-
spinner_default.text = `renaming in ${
|
|
1214
|
+
spinner_default.text = `renaming in ${import_termkit12.Color.blue.encoder(dir)} ${index + 1}/${list2.length}`;
|
|
1200
1215
|
if (!(0, import_fs11.lstatSync)((0, import_path12.resolve)(dir, entry)).isDirectory()) {
|
|
1201
1216
|
if (verbose) spinner_default.info(`skipped ${entry}`);
|
|
1202
1217
|
skipped++;
|
|
@@ -1281,18 +1296,18 @@ var rename = async ({ dir: inputDir, type, verbose }) => {
|
|
|
1281
1296
|
spinner_default.succeed(`renamed ${renamed} files`);
|
|
1282
1297
|
if (removed) spinner_default.info(`removed ${removed} files`);
|
|
1283
1298
|
spinner_default.info(`skipped ${skipped} files`);
|
|
1284
|
-
spinner_default.succeed(`done in ${
|
|
1299
|
+
spinner_default.succeed(`done in ${import_termkit12.Color.cyan.encoder(dir)}`);
|
|
1285
1300
|
spinner_default.stop();
|
|
1286
1301
|
};
|
|
1287
1302
|
var rename_default = rename;
|
|
1288
1303
|
|
|
1289
1304
|
// src/actions/reset.ts
|
|
1290
|
-
var import_cosmetic12 = __toESM(require("cosmetic"));
|
|
1291
1305
|
var import_fs12 = require("fs");
|
|
1292
1306
|
var import_path13 = require("path");
|
|
1307
|
+
var import_termkit13 = require("termkit");
|
|
1293
1308
|
var reset = async ({ dir: inputDir, double }) => {
|
|
1294
1309
|
let dir = inputDir;
|
|
1295
|
-
spinner_default.text = `resetting episodes in ${
|
|
1310
|
+
spinner_default.text = `resetting episodes in ${import_termkit13.Color.blue.encoder(dir)}`;
|
|
1296
1311
|
spinner_default.start();
|
|
1297
1312
|
dir = (0, import_path13.resolve)(dir);
|
|
1298
1313
|
if (!(0, import_fs12.existsSync)(dir)) throw new Error(`dir ${dir} does not exist`);
|
|
@@ -1321,7 +1336,7 @@ var reset = async ({ dir: inputDir, double }) => {
|
|
|
1321
1336
|
const episodeFormat = getConfig().format?.episode;
|
|
1322
1337
|
let renamed = 0, skipped = other.length;
|
|
1323
1338
|
for (const [index, i] of sublist.entries()) {
|
|
1324
|
-
spinner_default.text = `resetting episodes in ${
|
|
1339
|
+
spinner_default.text = `resetting episodes in ${import_termkit13.Color.blue.encoder(dir)} ${index}/${list2.length}`;
|
|
1325
1340
|
const ext = i.match(/([^.]+$)/)?.[0];
|
|
1326
1341
|
const episode = double ? index * 2 + 1 : index + 1;
|
|
1327
1342
|
const name = `${formatEpisode(seasonNum, episode, episodeFormat, double, showTitle)}.${ext}`;
|
|
@@ -1334,16 +1349,15 @@ var reset = async ({ dir: inputDir, double }) => {
|
|
|
1334
1349
|
}
|
|
1335
1350
|
spinner_default.succeed(`renamed ${renamed} files`);
|
|
1336
1351
|
spinner_default.info(`skipped ${skipped} files`);
|
|
1337
|
-
spinner_default.succeed(`done in ${
|
|
1352
|
+
spinner_default.succeed(`done in ${import_termkit13.Color.cyan.encoder(dir)}`);
|
|
1338
1353
|
spinner_default.stop();
|
|
1339
1354
|
};
|
|
1340
1355
|
var reset_default = reset;
|
|
1341
1356
|
|
|
1342
1357
|
// src/actions/scan.ts
|
|
1343
|
-
var import_cosmetic13 = __toESM(require("cosmetic"));
|
|
1344
1358
|
var import_fs13 = require("fs");
|
|
1345
1359
|
var import_path14 = require("path");
|
|
1346
|
-
var
|
|
1360
|
+
var import_termkit14 = require("termkit");
|
|
1347
1361
|
|
|
1348
1362
|
// src/helpers/detectEdition.ts
|
|
1349
1363
|
var EDITIONS = [
|
|
@@ -1450,10 +1464,10 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, verbose, auto }) => {
|
|
|
1450
1464
|
let imported = 0, skipped = 0;
|
|
1451
1465
|
for (const source of config.sources) {
|
|
1452
1466
|
if (!(0, import_fs13.existsSync)(source)) {
|
|
1453
|
-
spinner_default.warn(`source not found: ${
|
|
1467
|
+
spinner_default.warn(`source not found: ${import_termkit14.Color.blue.encoder(source)}`);
|
|
1454
1468
|
continue;
|
|
1455
1469
|
}
|
|
1456
|
-
spinner_default.text = `scanning ${
|
|
1470
|
+
spinner_default.text = `scanning ${import_termkit14.Color.blue.encoder(source)}`;
|
|
1457
1471
|
for (const entry of (0, import_fs13.readdirSync)(source)) {
|
|
1458
1472
|
const entryPath = (0, import_path14.resolve)(source, entry);
|
|
1459
1473
|
const isDir = (0, import_fs13.lstatSync)(entryPath).isDirectory();
|
|
@@ -1520,7 +1534,7 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, verbose, auto }) => {
|
|
|
1520
1534
|
resolvedYear = results[0].year ?? parsed.year;
|
|
1521
1535
|
} else if (results.length > 1) {
|
|
1522
1536
|
spinner_default.stop();
|
|
1523
|
-
const select = new
|
|
1537
|
+
const select = new import_termkit14.Select();
|
|
1524
1538
|
const items = results.map((r) => ({
|
|
1525
1539
|
label: r.year ? `${r.title} (${r.year})` : r.title,
|
|
1526
1540
|
description: [r.overview?.slice(0, 60), hyperlink(r.url, "themoviedb.org")].filter(Boolean).join(" \xB7 "),
|
|
@@ -1687,8 +1701,8 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, verbose, auto }) => {
|
|
|
1687
1701
|
var scan_default = scan;
|
|
1688
1702
|
|
|
1689
1703
|
// src/actions/shows.ts
|
|
1690
|
-
var import_cosmetic14 = __toESM(require("cosmetic"));
|
|
1691
1704
|
var import_fs14 = require("fs");
|
|
1705
|
+
var import_termkit15 = require("termkit");
|
|
1692
1706
|
var dim = (s) => `\x1B[2m${s}\x1B[0m`;
|
|
1693
1707
|
var shows = async () => {
|
|
1694
1708
|
const config = getConfig();
|
|
@@ -1699,30 +1713,36 @@ var shows = async () => {
|
|
|
1699
1713
|
console.log();
|
|
1700
1714
|
return;
|
|
1701
1715
|
}
|
|
1702
|
-
const names = allShows.map((s) => s.path.split("/").pop() ?? s.path);
|
|
1703
|
-
const titleW = Math.min(50, Math.max(10, ...names.map((n) => n.length)) + 2);
|
|
1704
|
-
const divider = "\u2500".repeat(titleW + 32);
|
|
1705
1716
|
console.log(`
|
|
1706
|
-
${
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1717
|
+
${import_termkit15.Color.yellow.encoder("SHOWS")}${destRoot ? ` ${import_termkit15.Color.blue.encoder(destRoot)}` : ""} (${allShows.length} registered)`);
|
|
1718
|
+
new import_termkit15.Table(
|
|
1719
|
+
allShows.map((show) => ({
|
|
1720
|
+
name: show.path.split("/").pop() ?? show.path,
|
|
1721
|
+
size: (0, import_fs14.existsSync)(show.path) ? formatSize(dirSize(show.path)) : "\u2014",
|
|
1722
|
+
tmdbId: show.tmdbId,
|
|
1723
|
+
ended: show.ended
|
|
1724
|
+
})),
|
|
1725
|
+
{
|
|
1726
|
+
separator: " ",
|
|
1727
|
+
columns: [
|
|
1728
|
+
{ key: "name", title: "Title" },
|
|
1729
|
+
{ key: "size", title: "Size" },
|
|
1730
|
+
{
|
|
1731
|
+
key: "tmdbId",
|
|
1732
|
+
title: "Linked",
|
|
1733
|
+
value: (v) => {
|
|
1734
|
+
if (v) {
|
|
1735
|
+
const url = `https://www.themoviedb.org/tv/${v}`;
|
|
1736
|
+
const text = process.stdout.isTTY ? hyperlink(url, "\u2713 tmdb") : "\u2713 tmdb";
|
|
1737
|
+
return import_termkit15.Color.green.encoder(text);
|
|
1738
|
+
}
|
|
1739
|
+
return import_termkit15.Color.red.encoder("\u2717");
|
|
1740
|
+
}
|
|
1741
|
+
},
|
|
1742
|
+
{ key: "ended", title: "Status", value: (v) => v ? dim("ended") : "active" }
|
|
1743
|
+
]
|
|
1721
1744
|
}
|
|
1722
|
-
|
|
1723
|
-
console.log(`${name.padEnd(titleW).substring(0, titleW)} ${size.padEnd(10)} ${linked2} ${status}`);
|
|
1724
|
-
}
|
|
1725
|
-
console.log(divider);
|
|
1745
|
+
).print();
|
|
1726
1746
|
const ended2 = allShows.filter((s) => s.ended).length;
|
|
1727
1747
|
const linked = allShows.filter((s) => s.tmdbId).length;
|
|
1728
1748
|
console.log(`${allShows.length} shows \xB7 ${linked} linked \xB7 ${ended2} ended`);
|
|
@@ -1731,9 +1751,9 @@ ${import_cosmetic14.default.yellow.encoder("SHOWS")}${destRoot ? ` ${import_cos
|
|
|
1731
1751
|
var shows_default = shows;
|
|
1732
1752
|
|
|
1733
1753
|
// src/actions/stats.ts
|
|
1734
|
-
var import_cosmetic15 = __toESM(require("cosmetic"));
|
|
1735
1754
|
var import_fs15 = require("fs");
|
|
1736
1755
|
var import_path15 = require("path");
|
|
1756
|
+
var import_termkit16 = require("termkit");
|
|
1737
1757
|
var countVideos = (dir) => {
|
|
1738
1758
|
let count = 0;
|
|
1739
1759
|
try {
|
|
@@ -1765,36 +1785,38 @@ var countDirs = (dir) => {
|
|
|
1765
1785
|
var stats = async () => {
|
|
1766
1786
|
const config = getConfig();
|
|
1767
1787
|
const shows2 = getShows();
|
|
1768
|
-
const
|
|
1769
|
-
const val = (n) => String(n);
|
|
1770
|
-
console.log("\nLIBRARY STATISTICS\n");
|
|
1788
|
+
const rows = [];
|
|
1771
1789
|
const movieDest = config.dest.movie;
|
|
1772
1790
|
if (movieDest && (0, import_fs15.existsSync)(movieDest)) {
|
|
1773
|
-
|
|
1774
|
-
const size = formatSize(dirSize(movieDest));
|
|
1775
|
-
console.log(`${label("Movies")}${val(count).padStart(6)} ${size}`);
|
|
1791
|
+
rows.push({ category: "Movies", count: countDirs(movieDest), size: formatSize(dirSize(movieDest)) });
|
|
1776
1792
|
}
|
|
1777
1793
|
const tvDest = config.dest.tv;
|
|
1778
1794
|
if (tvDest && (0, import_fs15.existsSync)(tvDest)) {
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
const size = formatSize(dirSize(tvDest));
|
|
1782
|
-
console.log(`${label("Shows")}${val(showCount).padStart(6)} ${size}`);
|
|
1783
|
-
console.log(`${label("Episodes")}${val(episodeCount).padStart(6)}`);
|
|
1795
|
+
rows.push({ category: "Shows", count: shows2.length, size: formatSize(dirSize(tvDest)) });
|
|
1796
|
+
rows.push({ category: "Episodes", count: countVideos(tvDest) });
|
|
1784
1797
|
}
|
|
1785
1798
|
const ps3Dest = config.dest.ps3;
|
|
1786
1799
|
if (ps3Dest && (0, import_fs15.existsSync)(ps3Dest)) {
|
|
1787
|
-
|
|
1788
|
-
const size = formatSize(dirSize(ps3Dest));
|
|
1789
|
-
console.log(`${label("PS3")}${val(count).padStart(6)} ${size}`);
|
|
1800
|
+
rows.push({ category: "PS3", count: countDirs(ps3Dest), size: formatSize(dirSize(ps3Dest)) });
|
|
1790
1801
|
}
|
|
1802
|
+
if (rows.length === 0) return;
|
|
1803
|
+
console.log();
|
|
1804
|
+
new import_termkit16.Table(rows, {
|
|
1805
|
+
title: "LIBRARY STATISTICS",
|
|
1806
|
+
separator: " ",
|
|
1807
|
+
columns: [
|
|
1808
|
+
{ key: "category", title: "Category" },
|
|
1809
|
+
{ key: "count", title: "Count", align: "right", value: (v) => v != null ? String(v) : "" },
|
|
1810
|
+
{ key: "size", title: "Size", value: (v) => v ?? "" }
|
|
1811
|
+
]
|
|
1812
|
+
}).print();
|
|
1791
1813
|
console.log();
|
|
1792
1814
|
};
|
|
1793
1815
|
var stats_default = stats;
|
|
1794
1816
|
|
|
1795
1817
|
// src/actions/undo.ts
|
|
1796
|
-
var import_cosmetic16 = __toESM(require("cosmetic"));
|
|
1797
1818
|
var import_fs16 = require("fs");
|
|
1819
|
+
var import_termkit17 = require("termkit");
|
|
1798
1820
|
var undo = async () => {
|
|
1799
1821
|
spinner_default.start();
|
|
1800
1822
|
const records = getLastSession();
|
|
@@ -1806,7 +1828,7 @@ var undo = async () => {
|
|
|
1806
1828
|
let undone = 0;
|
|
1807
1829
|
for (const record of records) {
|
|
1808
1830
|
(0, import_fs16.renameSync)(record.newPath, record.oldPath);
|
|
1809
|
-
spinner_default.succeed(`${
|
|
1831
|
+
spinner_default.succeed(`${import_termkit17.Color.cyan.encoder(record.newPath)} \u2192 ${import_termkit17.Color.blue.encoder(record.oldPath)}`);
|
|
1810
1832
|
undone++;
|
|
1811
1833
|
}
|
|
1812
1834
|
deleteSession(records[0].sessionId);
|
|
@@ -1817,9 +1839,9 @@ var undo_default = undo;
|
|
|
1817
1839
|
|
|
1818
1840
|
// src/actions/watch.ts
|
|
1819
1841
|
var import_chokidar = __toESM(require("chokidar"));
|
|
1820
|
-
var import_cosmetic17 = __toESM(require("cosmetic"));
|
|
1821
1842
|
var import_fs17 = require("fs");
|
|
1822
1843
|
var import_path16 = require("path");
|
|
1844
|
+
var import_termkit18 = require("termkit");
|
|
1823
1845
|
var sameDev2 = (a, b) => {
|
|
1824
1846
|
try {
|
|
1825
1847
|
let bExisting = b;
|
|
@@ -1890,7 +1912,7 @@ var processItem = async (entryPath, useHardlink, verbose, language, auto) => {
|
|
|
1890
1912
|
}
|
|
1891
1913
|
moveItem(entryPath, destPath);
|
|
1892
1914
|
recordImport(sessionId, entryPath, destPath, "move");
|
|
1893
|
-
spinner_default.succeed(`imported ${
|
|
1915
|
+
spinner_default.succeed(`imported ${import_termkit18.Color.cyan.encoder(destName)}`);
|
|
1894
1916
|
return;
|
|
1895
1917
|
}
|
|
1896
1918
|
const parsed = parseDownloadName(entry);
|
|
@@ -1963,7 +1985,7 @@ var processItem = async (entryPath, useHardlink, verbose, language, auto) => {
|
|
|
1963
1985
|
if (isDir) (0, import_fs17.rmSync)(entryPath, { recursive: true, force: true });
|
|
1964
1986
|
}
|
|
1965
1987
|
recordImport(sessionId, entryPath, seasonPath, mode);
|
|
1966
|
-
spinner_default.succeed(`imported ${
|
|
1988
|
+
spinner_default.succeed(`imported ${import_termkit18.Color.cyan.encoder(`${showFolderName} / ${seasonFolderName} / ${episodeName}`)}`);
|
|
1967
1989
|
return;
|
|
1968
1990
|
}
|
|
1969
1991
|
const edition = detectEdition(entry);
|
|
@@ -2020,7 +2042,7 @@ var processItem = async (entryPath, useHardlink, verbose, language, auto) => {
|
|
|
2020
2042
|
}
|
|
2021
2043
|
recordImport(sessionId, entryPath, destFolder, "move");
|
|
2022
2044
|
}
|
|
2023
|
-
spinner_default.succeed(`imported ${
|
|
2045
|
+
spinner_default.succeed(`imported ${import_termkit18.Color.cyan.encoder(folderName)}`);
|
|
2024
2046
|
};
|
|
2025
2047
|
var watch = async ({ hardlink = false, verbose = false, auto = false }) => {
|
|
2026
2048
|
const config = getConfig();
|
|
@@ -2051,35 +2073,41 @@ var watch = async ({ hardlink = false, verbose = false, auto = false }) => {
|
|
|
2051
2073
|
watcher.on("add", handle);
|
|
2052
2074
|
spinner_default.start();
|
|
2053
2075
|
spinner_default.succeed(`watching ${config.sources.length} source${config.sources.length !== 1 ? "s" : ""}`);
|
|
2054
|
-
for (const s of config.sources) spinner_default.info(` ${
|
|
2076
|
+
for (const s of config.sources) spinner_default.info(` ${import_termkit18.Color.blue.encoder(s)}`);
|
|
2055
2077
|
spinner_default.stop();
|
|
2056
2078
|
process.stdin.resume();
|
|
2057
2079
|
};
|
|
2058
2080
|
var watch_default = watch;
|
|
2059
2081
|
|
|
2060
2082
|
// package.json
|
|
2061
|
-
var version = "0.
|
|
2083
|
+
var version = "0.2.0";
|
|
2062
2084
|
|
|
2063
2085
|
// src/program.ts
|
|
2064
2086
|
var adapt = (fn) => (options) => fn(options);
|
|
2065
|
-
var
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
(
|
|
2074
|
-
(
|
|
2075
|
-
|
|
2076
|
-
(
|
|
2077
|
-
|
|
2078
|
-
(
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2087
|
+
var { command, option } = import_termkit19.Program;
|
|
2088
|
+
var program = import_termkit19.Program.command("reelsort").version(version).description("a cli to manage media").commands([
|
|
2089
|
+
command("config").description("manage configuration").commands([
|
|
2090
|
+
command("source").description("manage source directories").commands([command("add", "<dir>").description("add a source directory").action(adapt(sourceAdd)), command("remove", "<dir>").description("remove a source directory").action(adapt(sourceRemove))]),
|
|
2091
|
+
command("dest").description("manage destinations").commands([command("add", "<type> <dir>").description("set a destination (movie, tv, ps3)").action(adapt(destAdd)), command("remove", "<type>").description("remove a destination (movie, tv, ps3)").action(adapt(destRemove))]),
|
|
2092
|
+
command("set", "<key> <subkey> [value]").description("set a value (e.g. set language eng)").action(adapt(configSet)),
|
|
2093
|
+
command("show").description("show current configuration").action(adapt(configShow))
|
|
2094
|
+
]),
|
|
2095
|
+
command("rename", "<dir>").description("rename media files in directory").options([option("t", "type", "<type>", "media type: movie, tv, ps3"), option("v", "verbose", null, "additional output")]).action(adapt(rename_default)),
|
|
2096
|
+
command("reset", "<dir>").description("reset episode names (sxee)").options([option("d", "double", null, "episodes are doubles")]).action(adapt(reset_default)),
|
|
2097
|
+
command("probe").description("index library metadata using ffprobe").options([option("t", "type", "<type>", "media type: movie, tv, ps3"), option("f", "force", null, "re-probe files already indexed"), option("v", "verbose", null, "show each file as it is probed")]).action(adapt(probe_default)),
|
|
2098
|
+
command("list").description("list library contents").options([option("t", "type", "<type>", "media type: movie, tv, ps3"), option("m", "missing-subs", null, "only show items without subtitles"), option("c", "codec", "<codec>", "filter by codec (e.g. x265)"), option("r", "resolution", "<res>", "filter by resolution (e.g. 1080p, 4K)"), option("s", "sort", "<field>", "sort by: year (default), title")]).action(adapt(list_default)),
|
|
2099
|
+
command("watch").description("watch sources and auto-import new media").options([option("H", "hardlink", null, "hardlink instead of moving (falls back to copy across filesystems)"), option("v", "verbose", null, "additional output"), option("a", "auto", null, "auto-register unrecognised TV shows instead of skipping them")]).action(adapt(watch_default)),
|
|
2100
|
+
command("scan").description("import media from configured sources to destinations").options([option("t", "type", "<type>", "only process this media type: movie, tv, ps3"), option("H", "hardlink", null, "hardlink instead of moving (falls back to copy across filesystems)"), option("n", "dry-run", null, "show what would be imported without doing it"), option("v", "verbose", null, "additional output"), option("a", "auto", null, "auto-register unrecognised TV shows instead of skipping them")]).action(adapt(scan_default)),
|
|
2101
|
+
command("clean").description("remove source files that have already been imported").options([option("n", "dry-run", null, "show what would be removed without doing it"), option("o", "older-than", "<age>", "only clean imports older than age (e.g. 14d, 6h, 30m)")]).action(adapt(clean_default)),
|
|
2102
|
+
command("undo").description("undo the last rename session").action(adapt(undo_default)),
|
|
2103
|
+
command("history").description("show rename or import history").options([option("l", "limit", "<n>", "number of sessions to show (default 10)"), option("i", "imports", null, "show import history instead of rename history")]).action(adapt(history_default)),
|
|
2104
|
+
command("diff", "<dir1> <dir2>").description("compare differences between two directories").options([option("o", "only", "[ext...]", "check specified extensions"), option("i", "ignore", "[ext...]", "ignore specified extensions")]).action(adapt(differences_default)),
|
|
2105
|
+
command("missing").description("show missing episodes for TV shows (requires TMDb key)").options([option("s", "show", "<name>", "check a specific show instead of all")]).action(adapt(missing_default)),
|
|
2106
|
+
command("shows").description("list all registered TV shows with TMDb status and size").action(adapt(shows_default)),
|
|
2107
|
+
command("stats").description("show library statistics").action(adapt(stats_default)),
|
|
2108
|
+
command("link").description("link TV shows to TMDb (retroactively or after manual library setup)").options([option("f", "force", null, "re-link shows that are already linked")]).action(adapt(link_default)),
|
|
2109
|
+
command("ended").description("mark a show as ended (excluded from reelsort missing)").options([option("r", "remove", null, "restore an ended show to active")]).action(adapt(ended_default)),
|
|
2110
|
+
command("add", "<name>").description("add a TV show by name \u2014 searches TMDb and registers it for scanning").action(adapt(add_default))
|
|
2083
2111
|
]);
|
|
2084
2112
|
var program_default = program;
|
|
2085
2113
|
|