reelsort 0.2.4 → 0.2.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/dist/cli.js +289 -197
- package/dist/index.d.mts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +281 -185
- package/dist/index.mjs +184 -90
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -98,6 +98,10 @@ var db = () => {
|
|
|
98
98
|
_db.exec("ALTER TABLE shows ADD COLUMN title TEXT");
|
|
99
99
|
} catch {
|
|
100
100
|
}
|
|
101
|
+
try {
|
|
102
|
+
_db.exec("ALTER TABLE imports ADD COLUMN type TEXT");
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
101
105
|
return _db;
|
|
102
106
|
};
|
|
103
107
|
var recordRename = (sessionId, oldPath, newPath) => {
|
|
@@ -111,8 +115,16 @@ var getLastSession = () => {
|
|
|
111
115
|
var deleteSession = (sessionId) => {
|
|
112
116
|
db().prepare("DELETE FROM renameHistory WHERE sessionId = ?").run(sessionId);
|
|
113
117
|
};
|
|
114
|
-
var
|
|
115
|
-
db().prepare("
|
|
118
|
+
var getLastImportSession = () => {
|
|
119
|
+
const last = db().prepare("SELECT sessionId FROM imports ORDER BY id DESC LIMIT 1").get();
|
|
120
|
+
if (!last) return [];
|
|
121
|
+
return db().prepare("SELECT * FROM imports WHERE sessionId = ? ORDER BY id DESC").all(last.sessionId);
|
|
122
|
+
};
|
|
123
|
+
var deleteImportSession = (sessionId) => {
|
|
124
|
+
db().prepare("DELETE FROM imports WHERE sessionId = ?").run(sessionId);
|
|
125
|
+
};
|
|
126
|
+
var recordImport = (sessionId, sourcePath, destPath, mode, tmdbId, type) => {
|
|
127
|
+
db().prepare("INSERT INTO imports (sessionId, sourcePath, destinationPath, mode, tmdbId, type) VALUES (?, ?, ?, ?, ?, ?)").run(sessionId, sourcePath, destPath, mode, tmdbId ?? null, type ?? null);
|
|
116
128
|
};
|
|
117
129
|
var getMediaInfo = (filePath) => {
|
|
118
130
|
return db().prepare("SELECT * FROM mediaInfo WHERE filePath = ?").get(filePath);
|
|
@@ -408,10 +420,10 @@ var import_path4 = require("path");
|
|
|
408
420
|
var import_termkit4 = require("termkit");
|
|
409
421
|
|
|
410
422
|
// src/helpers/formatEpisode.ts
|
|
411
|
-
var DEFAULT_EPISODE_FORMAT = "{s}x{ee}";
|
|
423
|
+
var DEFAULT_EPISODE_FORMAT = "{s}x{ee} - {title}";
|
|
412
424
|
var DEFAULT_SEASON_FORMAT = "Season {s}";
|
|
413
425
|
var renderEpisode = (format, season, episode, title, name) => {
|
|
414
|
-
return format.replace(/\{sss\}/g, season.toString().padStart(3, "0")).replace(/\{ss\}/g, season.toString().padStart(2, "0")).replace(/\{s\}/g, season.toString()).replace(/\{eee\}/g, episode.toString().padStart(3, "0")).replace(/\{ee\}/g, episode.toString().padStart(2, "0")).replace(/\{e\}/g, episode.toString()).replace(/\{
|
|
426
|
+
return format.replace(/\{sss\}/g, season.toString().padStart(3, "0")).replace(/\{ss\}/g, season.toString().padStart(2, "0")).replace(/\{s\}/g, season.toString()).replace(/\{eee\}/g, episode.toString().padStart(3, "0")).replace(/\{ee\}/g, episode.toString().padStart(2, "0")).replace(/\{e\}/g, episode.toString()).replace(/\{show\}/g, title ?? "").replace(/\{title\}/g, name ?? "").replace(/(\s*-\s*)+$/, "").replace(/^(\s*-\s*)+/, "").replace(/\s+/g, " ").trim();
|
|
415
427
|
};
|
|
416
428
|
var formatSeasonFolder = (format, season) => format.replace(/\{sss\}/g, season.toString().padStart(3, "0")).replace(/\{ss\}/g, season.toString().padStart(2, "0")).replace(/\{s\}/g, season.toString()).trim();
|
|
417
429
|
var formatEpisode = (season, episode, format = DEFAULT_EPISODE_FORMAT, double = false, title, name) => {
|
|
@@ -1484,8 +1496,8 @@ var reset = async ({ dir: inputDir, double }) => {
|
|
|
1484
1496
|
var reset_default = reset;
|
|
1485
1497
|
|
|
1486
1498
|
// src/actions/scan.ts
|
|
1487
|
-
var
|
|
1488
|
-
var
|
|
1499
|
+
var import_fs15 = require("fs");
|
|
1500
|
+
var import_path15 = require("path");
|
|
1489
1501
|
var import_termkit14 = require("termkit");
|
|
1490
1502
|
|
|
1491
1503
|
// src/helpers/detectEdition.ts
|
|
@@ -1506,10 +1518,49 @@ var detectEdition = (filename) => {
|
|
|
1506
1518
|
return null;
|
|
1507
1519
|
};
|
|
1508
1520
|
|
|
1521
|
+
// src/helpers/trash.ts
|
|
1522
|
+
var import_child_process2 = require("child_process");
|
|
1523
|
+
var import_fs14 = require("fs");
|
|
1524
|
+
var import_os3 = require("os");
|
|
1525
|
+
var import_path14 = require("path");
|
|
1526
|
+
var trashDir = () => {
|
|
1527
|
+
if (process.platform === "linux") return (0, import_path14.join)((0, import_os3.homedir)(), ".local", "share", "Trash", "files");
|
|
1528
|
+
return (0, import_path14.join)((0, import_os3.homedir)(), ".Trash");
|
|
1529
|
+
};
|
|
1530
|
+
var trashPath = (filePath, opts) => {
|
|
1531
|
+
if (process.platform === "darwin" || process.platform === "linux") {
|
|
1532
|
+
try {
|
|
1533
|
+
const dir = trashDir();
|
|
1534
|
+
if (!(0, import_fs14.existsSync)(dir)) (0, import_fs14.mkdirSync)(dir, { recursive: true });
|
|
1535
|
+
const name = (0, import_path14.basename)(filePath);
|
|
1536
|
+
let dest = (0, import_path14.join)(dir, name);
|
|
1537
|
+
let i = 1;
|
|
1538
|
+
while ((0, import_fs14.existsSync)(dest)) dest = (0, import_path14.join)(dir, `${name} ${i++}`);
|
|
1539
|
+
(0, import_fs14.renameSync)(filePath, dest);
|
|
1540
|
+
return;
|
|
1541
|
+
} catch {
|
|
1542
|
+
}
|
|
1543
|
+
} else if (process.platform === "win32") {
|
|
1544
|
+
try {
|
|
1545
|
+
const escaped = filePath.replace(/'/g, "''");
|
|
1546
|
+
const isDir = opts?.recursive ?? false;
|
|
1547
|
+
const method = isDir ? "DeleteDirectory" : "DeleteFile";
|
|
1548
|
+
(0, import_child_process2.execSync)(
|
|
1549
|
+
`powershell -NoProfile -NonInteractive -Command "Add-Type -AssemblyName Microsoft.VisualBasic; [Microsoft.VisualBasic.FileIO.FileSystem]::${method}('${escaped}', 'OnlyErrorDialogs', 'SendToRecycleBin')"`,
|
|
1550
|
+
{ stdio: "ignore" }
|
|
1551
|
+
);
|
|
1552
|
+
return;
|
|
1553
|
+
} catch {
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
(0, import_fs14.rmSync)(filePath, { recursive: opts?.recursive ?? false, force: true });
|
|
1557
|
+
};
|
|
1558
|
+
|
|
1509
1559
|
// src/helpers/parseDownloadName.ts
|
|
1510
1560
|
var QUALITY_TOKENS = /* @__PURE__ */ new Set(["480p", "576p", "720p", "1080p", "2160p", "4k", "8k", "bluray", "bdrip", "bdremux", "brrip", "webrip", "web-dl", "webdl", "web", "hdtv", "dvdrip", "dvdscr", "cam", "ts", "scr", "x264", "x265", "hevc", "avc", "h264", "h265", "xvid", "divx", "dts", "ac3", "aac", "mp3", "truehd", "atmos", "dd5", "hdr", "hdr10", "hlg", "dv", "dolby", "remux", "proper", "repack", "extended", "theatrical", "unrated", "multi", "dubbed", "subbed", "internal"]);
|
|
1511
1561
|
var TV_PATTERN = /^(.*?)[.\s_-]*(?:S(\d{2,3})E(\d{2,3})|(\d{1,2})x(\d{2,3})|Season[\s.](\d+))/i;
|
|
1512
|
-
var parseDownloadName = (
|
|
1562
|
+
var parseDownloadName = (rawName) => {
|
|
1563
|
+
const name = rawName.replace(/^[\w.-]+\.\w{2,6}\s+-+\s+/i, "");
|
|
1513
1564
|
const base = name.replace(/\.[a-z0-9]{2,4}$/i, "");
|
|
1514
1565
|
const tvMatch = TV_PATTERN.exec(base);
|
|
1515
1566
|
if (tvMatch) {
|
|
@@ -1553,31 +1604,31 @@ var bookExtensions_default = ["epub", "mobi", "azw3", "azw"];
|
|
|
1553
1604
|
var sameDev = (a, b) => {
|
|
1554
1605
|
try {
|
|
1555
1606
|
let bExisting = b;
|
|
1556
|
-
while (!(0,
|
|
1557
|
-
return (0,
|
|
1607
|
+
while (!(0, import_fs15.existsSync)(bExisting)) bExisting = (0, import_path15.dirname)(bExisting);
|
|
1608
|
+
return (0, import_fs15.statSync)(a).dev === (0, import_fs15.statSync)(bExisting).dev;
|
|
1558
1609
|
} catch {
|
|
1559
1610
|
return false;
|
|
1560
1611
|
}
|
|
1561
1612
|
};
|
|
1562
1613
|
var moveFolder = (src, dest) => {
|
|
1563
1614
|
if (sameDev(src, dest)) {
|
|
1564
|
-
(0,
|
|
1615
|
+
(0, import_fs15.renameSync)(src, dest);
|
|
1565
1616
|
} else {
|
|
1566
|
-
(0,
|
|
1567
|
-
(
|
|
1617
|
+
(0, import_fs15.cpSync)(src, dest, { recursive: true });
|
|
1618
|
+
trashPath(src, { recursive: true });
|
|
1568
1619
|
}
|
|
1569
1620
|
};
|
|
1570
|
-
var findVideo = (dir) => (0,
|
|
1621
|
+
var findVideo = (dir) => (0, import_fs15.readdirSync)(dir).find((f) => {
|
|
1571
1622
|
const ext = f.match(/([^.]+$)/)?.[0];
|
|
1572
1623
|
return ext && videoExtensions_default.includes(ext);
|
|
1573
1624
|
}) ?? null;
|
|
1574
|
-
var containsBook = (dir, depth = 2) => (0,
|
|
1625
|
+
var containsBook = (dir, depth = 2) => (0, import_fs15.readdirSync)(dir).some((f) => {
|
|
1575
1626
|
const ext = f.match(/([^.]+$)/)?.[0];
|
|
1576
1627
|
if (ext && bookExtensions_default.includes(ext)) return true;
|
|
1577
1628
|
if (depth > 1) {
|
|
1578
1629
|
try {
|
|
1579
|
-
const sub = (0,
|
|
1580
|
-
if ((0,
|
|
1630
|
+
const sub = (0, import_path15.resolve)(dir, f);
|
|
1631
|
+
if ((0, import_fs15.lstatSync)(sub).isDirectory()) return containsBook(sub, depth - 1);
|
|
1581
1632
|
} catch {
|
|
1582
1633
|
}
|
|
1583
1634
|
}
|
|
@@ -1587,11 +1638,11 @@ var isTvEpisodeName = (name) => /S\d{2,3}E\d{2,3}/i.test(name) || /\d+x\d{2,3}/i
|
|
|
1587
1638
|
var isSeasonDirName = (name) => !isTvEpisodeName(name) && /(?:^|[.\s_-])(?:season|s)\s*0*\d+(?:[.\s_-]|$)/i.test(name);
|
|
1588
1639
|
var gatherEntries = (source) => {
|
|
1589
1640
|
const result = [];
|
|
1590
|
-
for (const name of (0,
|
|
1591
|
-
const fullPath = (0,
|
|
1641
|
+
for (const name of (0, import_fs15.readdirSync)(source)) {
|
|
1642
|
+
const fullPath = (0, import_path15.resolve)(source, name);
|
|
1592
1643
|
let isDir;
|
|
1593
1644
|
try {
|
|
1594
|
-
isDir = (0,
|
|
1645
|
+
isDir = (0, import_fs15.lstatSync)(fullPath).isDirectory();
|
|
1595
1646
|
} catch {
|
|
1596
1647
|
continue;
|
|
1597
1648
|
}
|
|
@@ -1609,17 +1660,17 @@ var gatherEntries = (source) => {
|
|
|
1609
1660
|
}
|
|
1610
1661
|
let children;
|
|
1611
1662
|
try {
|
|
1612
|
-
children = (0,
|
|
1663
|
+
children = (0, import_fs15.readdirSync)(fullPath);
|
|
1613
1664
|
} catch {
|
|
1614
1665
|
result.push({ entry: name, entryPath: fullPath, isDir: true });
|
|
1615
1666
|
continue;
|
|
1616
1667
|
}
|
|
1617
1668
|
if (children.some((c) => isTvEpisodeName(c))) {
|
|
1618
1669
|
for (const child of children) {
|
|
1619
|
-
const childPath = (0,
|
|
1670
|
+
const childPath = (0, import_path15.resolve)(fullPath, child);
|
|
1620
1671
|
let childIsDir;
|
|
1621
1672
|
try {
|
|
1622
|
-
childIsDir = (0,
|
|
1673
|
+
childIsDir = (0, import_fs15.lstatSync)(childPath).isDirectory();
|
|
1623
1674
|
} catch {
|
|
1624
1675
|
continue;
|
|
1625
1676
|
}
|
|
@@ -1631,25 +1682,25 @@ var gatherEntries = (source) => {
|
|
|
1631
1682
|
}
|
|
1632
1683
|
const seasonDirs = children.filter((c) => {
|
|
1633
1684
|
try {
|
|
1634
|
-
return isSeasonDirName(c) && (0,
|
|
1685
|
+
return isSeasonDirName(c) && (0, import_fs15.lstatSync)((0, import_path15.resolve)(fullPath, c)).isDirectory();
|
|
1635
1686
|
} catch {
|
|
1636
1687
|
return false;
|
|
1637
1688
|
}
|
|
1638
1689
|
});
|
|
1639
1690
|
if (seasonDirs.length > 0) {
|
|
1640
1691
|
for (const seasonDir of seasonDirs) {
|
|
1641
|
-
const seasonPath = (0,
|
|
1692
|
+
const seasonPath = (0, import_path15.resolve)(fullPath, seasonDir);
|
|
1642
1693
|
let seasonChildren;
|
|
1643
1694
|
try {
|
|
1644
|
-
seasonChildren = (0,
|
|
1695
|
+
seasonChildren = (0, import_fs15.readdirSync)(seasonPath);
|
|
1645
1696
|
} catch {
|
|
1646
1697
|
continue;
|
|
1647
1698
|
}
|
|
1648
1699
|
for (const child of seasonChildren) {
|
|
1649
|
-
const childPath = (0,
|
|
1700
|
+
const childPath = (0, import_path15.resolve)(seasonPath, child);
|
|
1650
1701
|
let childIsDir;
|
|
1651
1702
|
try {
|
|
1652
|
-
childIsDir = (0,
|
|
1703
|
+
childIsDir = (0, import_fs15.lstatSync)(childPath).isDirectory();
|
|
1653
1704
|
} catch {
|
|
1654
1705
|
continue;
|
|
1655
1706
|
}
|
|
@@ -1665,19 +1716,19 @@ var gatherEntries = (source) => {
|
|
|
1665
1716
|
return result;
|
|
1666
1717
|
};
|
|
1667
1718
|
var findShowFolder = (destRoot, title) => {
|
|
1668
|
-
if (!(0,
|
|
1719
|
+
if (!(0, import_fs15.existsSync)(destRoot)) return null;
|
|
1669
1720
|
const normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1670
1721
|
const target = normalize(title);
|
|
1671
|
-
return (0,
|
|
1722
|
+
return (0, import_fs15.readdirSync)(destRoot).filter((f) => {
|
|
1672
1723
|
try {
|
|
1673
|
-
return (0,
|
|
1724
|
+
return (0, import_fs15.lstatSync)((0, import_path15.resolve)(destRoot, f)).isDirectory();
|
|
1674
1725
|
} catch {
|
|
1675
1726
|
return false;
|
|
1676
1727
|
}
|
|
1677
1728
|
}).find((f) => normalize(f) === target) ?? null;
|
|
1678
1729
|
};
|
|
1679
1730
|
var findShowFolderByContent = (destRoot, title) => {
|
|
1680
|
-
if (!(0,
|
|
1731
|
+
if (!(0, import_fs15.existsSync)(destRoot)) return null;
|
|
1681
1732
|
const normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1682
1733
|
const target = normalize(title);
|
|
1683
1734
|
const matchesTitle = (name) => {
|
|
@@ -1685,18 +1736,18 @@ var findShowFolderByContent = (destRoot, title) => {
|
|
|
1685
1736
|
const p = parseDownloadName(name);
|
|
1686
1737
|
return !!p && normalize(p.title) === target;
|
|
1687
1738
|
};
|
|
1688
|
-
for (const folder of (0,
|
|
1739
|
+
for (const folder of (0, import_fs15.readdirSync)(destRoot)) {
|
|
1689
1740
|
try {
|
|
1690
|
-
const folderPath = (0,
|
|
1691
|
-
if (!(0,
|
|
1692
|
-
const children = (0,
|
|
1741
|
+
const folderPath = (0, import_path15.resolve)(destRoot, folder);
|
|
1742
|
+
if (!(0, import_fs15.lstatSync)(folderPath).isDirectory()) continue;
|
|
1743
|
+
const children = (0, import_fs15.readdirSync)(folderPath);
|
|
1693
1744
|
if (children.some(matchesTitle)) return folder;
|
|
1694
1745
|
for (const child of children) {
|
|
1695
1746
|
if (!isSeasonDirName(child)) continue;
|
|
1696
1747
|
try {
|
|
1697
|
-
const seasonPath = (0,
|
|
1698
|
-
if (!(0,
|
|
1699
|
-
if ((0,
|
|
1748
|
+
const seasonPath = (0, import_path15.resolve)(folderPath, child);
|
|
1749
|
+
if (!(0, import_fs15.lstatSync)(seasonPath).isDirectory()) continue;
|
|
1750
|
+
if ((0, import_fs15.readdirSync)(seasonPath).some(matchesTitle)) return folder;
|
|
1700
1751
|
} catch {
|
|
1701
1752
|
}
|
|
1702
1753
|
}
|
|
@@ -1705,15 +1756,19 @@ var findShowFolderByContent = (destRoot, title) => {
|
|
|
1705
1756
|
}
|
|
1706
1757
|
return null;
|
|
1707
1758
|
};
|
|
1708
|
-
var findSeasonFolder = (showPath, season) => {
|
|
1709
|
-
if (!(0,
|
|
1710
|
-
const folders = (0,
|
|
1759
|
+
var findSeasonFolder = (showPath, season, specialsFolder) => {
|
|
1760
|
+
if (!(0, import_fs15.existsSync)(showPath)) return null;
|
|
1761
|
+
const folders = (0, import_fs15.readdirSync)(showPath).filter((f) => {
|
|
1711
1762
|
try {
|
|
1712
|
-
return (0,
|
|
1763
|
+
return (0, import_fs15.lstatSync)((0, import_path15.resolve)(showPath, f)).isDirectory();
|
|
1713
1764
|
} catch {
|
|
1714
1765
|
return false;
|
|
1715
1766
|
}
|
|
1716
1767
|
});
|
|
1768
|
+
if (season === 0 && specialsFolder) {
|
|
1769
|
+
const existing = folders.find((f) => f.toLowerCase() === specialsFolder.toLowerCase());
|
|
1770
|
+
if (existing) return existing;
|
|
1771
|
+
}
|
|
1717
1772
|
return folders.find((f) => {
|
|
1718
1773
|
const match = f.match(/(?:season|s)\s*0*(\d+)/i);
|
|
1719
1774
|
return match && parseInt(match[1]) === season;
|
|
@@ -1729,12 +1784,12 @@ var classifyMovieConfidence = (entry) => {
|
|
|
1729
1784
|
return "ambiguous";
|
|
1730
1785
|
};
|
|
1731
1786
|
var typeColor = {
|
|
1732
|
-
movie: import_termkit14.Color.
|
|
1733
|
-
tv: import_termkit14.Color.
|
|
1734
|
-
book: import_termkit14.Color.
|
|
1735
|
-
ps3: import_termkit14.Color.
|
|
1787
|
+
movie: (s) => import_termkit14.Color.cyan.encoder(s),
|
|
1788
|
+
tv: (s) => import_termkit14.Color.green.encoder(s),
|
|
1789
|
+
book: (s) => import_termkit14.Color.yellow.encoder(s),
|
|
1790
|
+
ps3: (s) => import_termkit14.Color.magenta.encoder(s)
|
|
1736
1791
|
};
|
|
1737
|
-
var typeGlyph = (t) => typeColor[t]
|
|
1792
|
+
var typeGlyph = (t) => typeColor[t]("\u25CF");
|
|
1738
1793
|
var typeTag = (t) => isVerbose() ? import_termkit14.Color.white.faint.encoder(` (${t})`) : "";
|
|
1739
1794
|
var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactive }) => {
|
|
1740
1795
|
const config = getConfig();
|
|
@@ -1742,11 +1797,13 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1742
1797
|
const language = config.language ?? "eng";
|
|
1743
1798
|
const movieFormat = config.format?.movie ?? DEFAULT_MOVIE_FORMAT;
|
|
1744
1799
|
const seasonFormat = config.format?.season ?? DEFAULT_SEASON_FORMAT;
|
|
1800
|
+
const specialsFolder = config.specialsFolder ?? "Specials";
|
|
1745
1801
|
const lookupMovie = async (parsed) => {
|
|
1746
1802
|
let tmdbId;
|
|
1747
1803
|
let resolvedTitle = parsed.title;
|
|
1748
1804
|
let resolvedYear = parsed.year;
|
|
1749
1805
|
if (config.tmdbApiKey) {
|
|
1806
|
+
spinner_default.text = `TMDb: ${parsed.title}`;
|
|
1750
1807
|
const results = await searchMovie(parsed.title, parsed.year, config.tmdbApiKey);
|
|
1751
1808
|
if (results.length === 1) {
|
|
1752
1809
|
tmdbId = results[0].id;
|
|
@@ -1774,8 +1831,8 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1774
1831
|
const importMovie = async (entry, entryPath, isDir, resolvedTitle, resolvedYear, tmdbId, destRoot) => {
|
|
1775
1832
|
const edition = detectEdition(entry);
|
|
1776
1833
|
const folderName = formatMovieName(movieFormat, resolvedTitle, resolvedYear, edition);
|
|
1777
|
-
const destFolder = (0,
|
|
1778
|
-
if ((0,
|
|
1834
|
+
const destFolder = (0, import_path15.resolve)(destRoot, folderName);
|
|
1835
|
+
if ((0, import_fs15.existsSync)(destFolder)) {
|
|
1779
1836
|
spinner_default.warn(`already exists: ${folderName}`);
|
|
1780
1837
|
return false;
|
|
1781
1838
|
}
|
|
@@ -1786,49 +1843,49 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1786
1843
|
}
|
|
1787
1844
|
const videoExt = videoFile.match(/([^.]+$)/)?.[0];
|
|
1788
1845
|
const destVideoName = `${folderName}.${videoExt}`;
|
|
1789
|
-
const videoSourcePath = isDir ? (0,
|
|
1790
|
-
const dirFiles = isDir ? (0,
|
|
1846
|
+
const videoSourcePath = isDir ? (0, import_path15.resolve)(entryPath, videoFile) : entryPath;
|
|
1847
|
+
const dirFiles = isDir ? (0, import_fs15.readdirSync)(entryPath) : [];
|
|
1791
1848
|
const subtitle = isDir ? findSubtitle(dirFiles, language) : null;
|
|
1792
1849
|
const subtitleExt = subtitle?.match(/([^.]+$)/)?.[0];
|
|
1793
|
-
const subtitleSourcePath = subtitle ? (0,
|
|
1850
|
+
const subtitleSourcePath = subtitle ? (0, import_path15.resolve)(entryPath, subtitle) : null;
|
|
1794
1851
|
const destSubtitleName = subtitle && subtitleExt ? `${folderName}.${subtitleExt}` : null;
|
|
1795
1852
|
if (!dryRun) {
|
|
1796
1853
|
if (useHardlink) {
|
|
1797
|
-
(0,
|
|
1798
|
-
const destVideoPath = (0,
|
|
1854
|
+
(0, import_fs15.mkdirSync)(destFolder, { recursive: true });
|
|
1855
|
+
const destVideoPath = (0, import_path15.resolve)(destFolder, destVideoName);
|
|
1799
1856
|
let mode;
|
|
1800
1857
|
try {
|
|
1801
1858
|
if (!sameDev(videoSourcePath, destRoot)) throw new Error("cross-filesystem");
|
|
1802
|
-
(0,
|
|
1859
|
+
(0, import_fs15.linkSync)(videoSourcePath, destVideoPath);
|
|
1803
1860
|
mode = "hardlink";
|
|
1804
1861
|
} catch {
|
|
1805
1862
|
spinner_default.warn(`hardlink unavailable \u2014 copying instead: ${folderName}`);
|
|
1806
|
-
(0,
|
|
1863
|
+
(0, import_fs15.cpSync)(videoSourcePath, destVideoPath);
|
|
1807
1864
|
mode = "copy";
|
|
1808
1865
|
}
|
|
1809
|
-
if (subtitleSourcePath && destSubtitleName) (0,
|
|
1810
|
-
recordImport(sessionId, entryPath, destFolder, mode, tmdbId);
|
|
1866
|
+
if (subtitleSourcePath && destSubtitleName) (0, import_fs15.cpSync)(subtitleSourcePath, (0, import_path15.resolve)(destFolder, destSubtitleName));
|
|
1867
|
+
recordImport(sessionId, entryPath, destFolder, mode, tmdbId, "movie");
|
|
1811
1868
|
} else {
|
|
1812
1869
|
if (isDir) {
|
|
1813
1870
|
const keep = new Set([videoFile, subtitle].filter(Boolean));
|
|
1814
|
-
for (const f of dirFiles.filter((f2) => !keep.has(f2))) (
|
|
1815
|
-
(0,
|
|
1816
|
-
if (subtitleSourcePath && destSubtitleName) (0,
|
|
1871
|
+
for (const f of dirFiles.filter((f2) => !keep.has(f2))) trashPath((0, import_path15.resolve)(entryPath, f), { recursive: true });
|
|
1872
|
+
(0, import_fs15.renameSync)(videoSourcePath, (0, import_path15.resolve)(entryPath, destVideoName));
|
|
1873
|
+
if (subtitleSourcePath && destSubtitleName) (0, import_fs15.renameSync)(subtitleSourcePath, (0, import_path15.resolve)(entryPath, destSubtitleName));
|
|
1817
1874
|
moveFolder(entryPath, destFolder);
|
|
1818
1875
|
} else {
|
|
1819
|
-
(0,
|
|
1820
|
-
const destVideoPath = (0,
|
|
1876
|
+
(0, import_fs15.mkdirSync)(destFolder, { recursive: true });
|
|
1877
|
+
const destVideoPath = (0, import_path15.resolve)(destFolder, destVideoName);
|
|
1821
1878
|
if (sameDev(videoSourcePath, destRoot)) {
|
|
1822
|
-
(0,
|
|
1879
|
+
(0, import_fs15.renameSync)(videoSourcePath, destVideoPath);
|
|
1823
1880
|
} else {
|
|
1824
|
-
(0,
|
|
1825
|
-
(
|
|
1881
|
+
(0, import_fs15.cpSync)(videoSourcePath, destVideoPath);
|
|
1882
|
+
trashPath(videoSourcePath);
|
|
1826
1883
|
}
|
|
1827
1884
|
}
|
|
1828
|
-
recordImport(sessionId, entryPath, destFolder, "move", tmdbId);
|
|
1885
|
+
recordImport(sessionId, entryPath, destFolder, "move", tmdbId, "movie");
|
|
1829
1886
|
}
|
|
1830
1887
|
}
|
|
1831
|
-
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("movie")} ${typeColor.movie
|
|
1888
|
+
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("movie")} ${typeColor.movie(folderName)}${typeTag("movie")}`);
|
|
1832
1889
|
return true;
|
|
1833
1890
|
};
|
|
1834
1891
|
spinner_default.start();
|
|
@@ -1839,12 +1896,13 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1839
1896
|
const ignoreSet = new Set(config.ignore ?? []);
|
|
1840
1897
|
const seenIgnored = /* @__PURE__ */ new Set();
|
|
1841
1898
|
for (const source of config.sources) {
|
|
1842
|
-
if (!(0,
|
|
1899
|
+
if (!(0, import_fs15.existsSync)(source)) {
|
|
1843
1900
|
spinner_default.warn(`source not found: ${import_termkit14.Color.white.encoder(source)}`);
|
|
1844
1901
|
continue;
|
|
1845
1902
|
}
|
|
1846
1903
|
spinner_default.text = `scanning ${import_termkit14.Color.white.encoder(source)}`;
|
|
1847
1904
|
for (const { entry, entryPath, isDir } of gatherEntries(source)) {
|
|
1905
|
+
spinner_default.text = `scanning: ${entry}`;
|
|
1848
1906
|
if (ignoreSet.has(entry)) {
|
|
1849
1907
|
seenIgnored.add(entry);
|
|
1850
1908
|
if (isVerbose()) spinner_default.info(`ignored: ${entry}`);
|
|
@@ -1879,23 +1937,23 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1879
1937
|
continue;
|
|
1880
1938
|
}
|
|
1881
1939
|
const destName = `${nameMatch[0]} [${id}]`;
|
|
1882
|
-
const destPath = (0,
|
|
1883
|
-
if ((0,
|
|
1940
|
+
const destPath = (0, import_path15.resolve)(destRoot, destName);
|
|
1941
|
+
if ((0, import_fs15.existsSync)(destPath)) {
|
|
1884
1942
|
spinner_default.warn(`already exists: ${destName}`);
|
|
1885
1943
|
skipped++;
|
|
1886
1944
|
continue;
|
|
1887
1945
|
}
|
|
1888
1946
|
if (!dryRun) {
|
|
1889
1947
|
moveFolder(entryPath, destPath);
|
|
1890
|
-
recordImport(sessionId, entryPath, destPath, "move");
|
|
1948
|
+
recordImport(sessionId, entryPath, destPath, "move", void 0, "ps3");
|
|
1891
1949
|
}
|
|
1892
|
-
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("ps3")} ${typeColor.ps3
|
|
1950
|
+
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("ps3")} ${typeColor.ps3(destName)}${typeTag("ps3")}`);
|
|
1893
1951
|
imported++;
|
|
1894
1952
|
continue;
|
|
1895
1953
|
}
|
|
1896
1954
|
if (detectedType === "book") {
|
|
1897
|
-
const destPath = (0,
|
|
1898
|
-
if ((0,
|
|
1955
|
+
const destPath = (0, import_path15.resolve)(destRoot, entry);
|
|
1956
|
+
if ((0, import_fs15.existsSync)(destPath)) {
|
|
1899
1957
|
spinner_default.warn(`already exists: ${entry}`);
|
|
1900
1958
|
skipped++;
|
|
1901
1959
|
continue;
|
|
@@ -1904,17 +1962,17 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1904
1962
|
if (isDir || isBookDir) {
|
|
1905
1963
|
moveFolder(entryPath, destPath);
|
|
1906
1964
|
} else {
|
|
1907
|
-
(0,
|
|
1965
|
+
(0, import_fs15.mkdirSync)(destRoot, { recursive: true });
|
|
1908
1966
|
if (sameDev(entryPath, destRoot)) {
|
|
1909
|
-
(0,
|
|
1967
|
+
(0, import_fs15.renameSync)(entryPath, destPath);
|
|
1910
1968
|
} else {
|
|
1911
|
-
(0,
|
|
1912
|
-
(0,
|
|
1969
|
+
(0, import_fs15.cpSync)(entryPath, destPath);
|
|
1970
|
+
(0, import_fs15.rmSync)(entryPath);
|
|
1913
1971
|
}
|
|
1914
1972
|
}
|
|
1915
|
-
recordImport(sessionId, entryPath, destPath, "move");
|
|
1973
|
+
recordImport(sessionId, entryPath, destPath, "move", void 0, "book");
|
|
1916
1974
|
}
|
|
1917
|
-
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("book")} ${typeColor.book
|
|
1975
|
+
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("book")} ${typeColor.book(entry)}${typeTag("book")}`);
|
|
1918
1976
|
imported++;
|
|
1919
1977
|
continue;
|
|
1920
1978
|
}
|
|
@@ -1941,6 +1999,7 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1941
1999
|
let resolvedYear = parsed.year;
|
|
1942
2000
|
if (config.tmdbApiKey) {
|
|
1943
2001
|
if (detectedType === "tv") {
|
|
2002
|
+
spinner_default.text = `TMDb: ${parsed.title}`;
|
|
1944
2003
|
const results = await searchTv(parsed.title, config.tmdbApiKey);
|
|
1945
2004
|
if (results.length === 1) {
|
|
1946
2005
|
tmdbId = results[0].id;
|
|
@@ -1985,18 +2044,18 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
1985
2044
|
const existingFolder = findShowFolder(destRoot, resolvedTitle) ?? findShowFolderByContent(destRoot, resolvedTitle);
|
|
1986
2045
|
if (existingFolder) {
|
|
1987
2046
|
showFolderName = existingFolder;
|
|
1988
|
-
showPath = (0,
|
|
2047
|
+
showPath = (0, import_path15.resolve)(destRoot, existingFolder);
|
|
1989
2048
|
} else if (auto) {
|
|
1990
2049
|
showFolderName = formatMovieName(movieFormat, resolvedTitle, resolvedYear);
|
|
1991
|
-
showPath = (0,
|
|
2050
|
+
showPath = (0, import_path15.resolve)(destRoot, showFolderName);
|
|
1992
2051
|
if (!dryRun) upsertShow(showPath, tmdbId ?? null, resolvedTitle);
|
|
1993
2052
|
} else {
|
|
1994
2053
|
pendingTv.push({ entry, entryPath, isDir, parsed, resolvedTitle, destRoot });
|
|
1995
2054
|
continue;
|
|
1996
2055
|
}
|
|
1997
2056
|
}
|
|
1998
|
-
const seasonFolderName = findSeasonFolder(showPath, parsed.season) ?? formatSeasonFolder(seasonFormat, parsed.season);
|
|
1999
|
-
const seasonPath = (0,
|
|
2057
|
+
const seasonFolderName = parsed.season === 0 ? findSeasonFolder(showPath, 0, specialsFolder) ?? specialsFolder : findSeasonFolder(showPath, parsed.season) ?? formatSeasonFolder(seasonFormat, parsed.season);
|
|
2058
|
+
const seasonPath = (0, import_path15.resolve)(showPath, seasonFolderName);
|
|
2000
2059
|
const videoFile = isDir ? findVideo(entryPath) : entry;
|
|
2001
2060
|
if (!videoFile) {
|
|
2002
2061
|
if (isVerbose()) spinner_default.info(`no video found in: ${entry}`);
|
|
@@ -2004,13 +2063,15 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
2004
2063
|
continue;
|
|
2005
2064
|
}
|
|
2006
2065
|
const videoExt = videoFile.match(/([^.]+$)/)?.[0];
|
|
2066
|
+
if (tmdbId && config.tmdbApiKey) spinner_default.text = `TMDb: episode name for ${resolvedTitle}`;
|
|
2007
2067
|
const tmdbEpisodeName = tmdbId && config.tmdbApiKey ? await getEpisodeName(tmdbId, parsed.season, parsed.episode ?? 1, config.tmdbApiKey) : null;
|
|
2008
2068
|
const episodeName = formatEpisode(parsed.season, parsed.episode ?? 1, config.format?.episode, false, resolvedTitle, tmdbEpisodeName ?? void 0);
|
|
2009
2069
|
const destVideoName = `${episodeName}.${videoExt}`;
|
|
2010
|
-
const destVideoPath = (0,
|
|
2011
|
-
const videoSourcePath = isDir ? (0,
|
|
2012
|
-
if ((0,
|
|
2013
|
-
|
|
2070
|
+
const destVideoPath = (0, import_path15.resolve)(seasonPath, destVideoName);
|
|
2071
|
+
const videoSourcePath = isDir ? (0, import_path15.resolve)(entryPath, videoFile) : entryPath;
|
|
2072
|
+
if ((0, import_fs15.existsSync)(destVideoPath)) {
|
|
2073
|
+
const isRepack = /\brepack\d*\b|\bproper\b/i.test(entry);
|
|
2074
|
+
let shouldReplace = force || isRepack;
|
|
2014
2075
|
if (!shouldReplace && interactive) {
|
|
2015
2076
|
spinner_default.stop();
|
|
2016
2077
|
const select = new import_termkit14.Select();
|
|
@@ -2027,43 +2088,43 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
2027
2088
|
continue;
|
|
2028
2089
|
}
|
|
2029
2090
|
if (!dryRun) {
|
|
2030
|
-
for (const f of (0,
|
|
2031
|
-
if (f.startsWith(`${episodeName}.`)) (
|
|
2091
|
+
for (const f of (0, import_fs15.readdirSync)(seasonPath)) {
|
|
2092
|
+
if (f.startsWith(`${episodeName}.`)) trashPath((0, import_path15.resolve)(seasonPath, f));
|
|
2032
2093
|
}
|
|
2033
2094
|
}
|
|
2034
2095
|
}
|
|
2035
|
-
const dirFiles = isDir ? (0,
|
|
2096
|
+
const dirFiles = isDir ? (0, import_fs15.readdirSync)(entryPath) : [];
|
|
2036
2097
|
const subtitle = isDir ? findSubtitle(dirFiles, language) : null;
|
|
2037
2098
|
const subtitleExt = subtitle?.match(/([^.]+$)/)?.[0];
|
|
2038
|
-
const subtitleSourcePath = subtitle ? (0,
|
|
2099
|
+
const subtitleSourcePath = subtitle ? (0, import_path15.resolve)(entryPath, subtitle) : null;
|
|
2039
2100
|
const destSubtitleName = subtitle && subtitleExt ? `${episodeName}.${subtitleExt}` : null;
|
|
2040
2101
|
if (!dryRun) {
|
|
2041
|
-
(0,
|
|
2102
|
+
(0, import_fs15.mkdirSync)(seasonPath, { recursive: true });
|
|
2042
2103
|
let mode = "move";
|
|
2043
2104
|
if (useHardlink) {
|
|
2044
2105
|
try {
|
|
2045
2106
|
if (!sameDev(videoSourcePath, seasonPath)) throw new Error("cross-filesystem");
|
|
2046
|
-
(0,
|
|
2107
|
+
(0, import_fs15.linkSync)(videoSourcePath, destVideoPath);
|
|
2047
2108
|
mode = "hardlink";
|
|
2048
2109
|
} catch {
|
|
2049
2110
|
spinner_default.warn(`hardlink unavailable \u2014 copying instead: ${episodeName}`);
|
|
2050
|
-
(0,
|
|
2111
|
+
(0, import_fs15.cpSync)(videoSourcePath, destVideoPath);
|
|
2051
2112
|
mode = "copy";
|
|
2052
2113
|
}
|
|
2053
|
-
if (subtitleSourcePath && destSubtitleName) (0,
|
|
2114
|
+
if (subtitleSourcePath && destSubtitleName) (0, import_fs15.cpSync)(subtitleSourcePath, (0, import_path15.resolve)(seasonPath, destSubtitleName));
|
|
2054
2115
|
} else {
|
|
2055
2116
|
if (sameDev(videoSourcePath, seasonPath)) {
|
|
2056
|
-
(0,
|
|
2117
|
+
(0, import_fs15.renameSync)(videoSourcePath, destVideoPath);
|
|
2057
2118
|
} else {
|
|
2058
|
-
(0,
|
|
2059
|
-
(
|
|
2119
|
+
(0, import_fs15.cpSync)(videoSourcePath, destVideoPath);
|
|
2120
|
+
trashPath(videoSourcePath);
|
|
2060
2121
|
}
|
|
2061
|
-
if (subtitleSourcePath && destSubtitleName) (0,
|
|
2062
|
-
if (isDir) (
|
|
2122
|
+
if (subtitleSourcePath && destSubtitleName) (0, import_fs15.renameSync)(subtitleSourcePath, (0, import_path15.resolve)(seasonPath, destSubtitleName));
|
|
2123
|
+
if (isDir) trashPath(entryPath, { recursive: true });
|
|
2063
2124
|
}
|
|
2064
|
-
recordImport(sessionId, entryPath, seasonPath, mode, tmdbId);
|
|
2125
|
+
recordImport(sessionId, entryPath, seasonPath, mode, tmdbId, "tv");
|
|
2065
2126
|
}
|
|
2066
|
-
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("tv")} ${typeColor.tv
|
|
2127
|
+
spinner_default.succeed(`${dryRun ? "[dry] " : ""}${typeGlyph("tv")} ${typeColor.tv(`${showFolderName} / ${seasonFolderName} / ${episodeName}`)}${typeTag("tv")}`);
|
|
2067
2128
|
imported++;
|
|
2068
2129
|
continue;
|
|
2069
2130
|
}
|
|
@@ -2124,7 +2185,7 @@ var scan = async ({ type, hardlink: useHardlink, dryRun, auto, force, interactiv
|
|
|
2124
2185
|
var scan_default = scan;
|
|
2125
2186
|
|
|
2126
2187
|
// src/actions/shows.ts
|
|
2127
|
-
var
|
|
2188
|
+
var import_fs16 = require("fs");
|
|
2128
2189
|
var import_termkit15 = require("termkit");
|
|
2129
2190
|
var dim = (s) => `\x1B[2m${s}\x1B[0m`;
|
|
2130
2191
|
var shows = async () => {
|
|
@@ -2141,7 +2202,7 @@ ${import_termkit15.Color.yellow.encoder("SHOWS")}${destRoot ? ` ${import_termki
|
|
|
2141
2202
|
new import_termkit15.Table(
|
|
2142
2203
|
allShows.map((show) => ({
|
|
2143
2204
|
name: show.path.split("/").pop() ?? show.path,
|
|
2144
|
-
size: (0,
|
|
2205
|
+
size: (0, import_fs16.existsSync)(show.path) ? formatSize(dirSize(show.path)) : "\u2014",
|
|
2145
2206
|
tmdbId: show.tmdbId,
|
|
2146
2207
|
ended: show.ended
|
|
2147
2208
|
})),
|
|
@@ -2174,15 +2235,15 @@ ${import_termkit15.Color.yellow.encoder("SHOWS")}${destRoot ? ` ${import_termki
|
|
|
2174
2235
|
var shows_default = shows;
|
|
2175
2236
|
|
|
2176
2237
|
// src/actions/stats.ts
|
|
2177
|
-
var
|
|
2178
|
-
var
|
|
2238
|
+
var import_fs17 = require("fs");
|
|
2239
|
+
var import_path16 = require("path");
|
|
2179
2240
|
var import_termkit16 = require("termkit");
|
|
2180
2241
|
var countVideos = (dir) => {
|
|
2181
2242
|
let count = 0;
|
|
2182
2243
|
try {
|
|
2183
|
-
for (const entry of (0,
|
|
2244
|
+
for (const entry of (0, import_fs17.readdirSync)(dir, { withFileTypes: true })) {
|
|
2184
2245
|
if (entry.isDirectory()) {
|
|
2185
|
-
count += countVideos((0,
|
|
2246
|
+
count += countVideos((0, import_path16.resolve)(dir, entry.name));
|
|
2186
2247
|
} else {
|
|
2187
2248
|
const ext = entry.name.match(/([^.]+$)/)?.[0]?.toLowerCase();
|
|
2188
2249
|
if (ext && videoExtensions_default.includes(ext)) count++;
|
|
@@ -2194,9 +2255,9 @@ var countVideos = (dir) => {
|
|
|
2194
2255
|
};
|
|
2195
2256
|
var countDirs = (dir) => {
|
|
2196
2257
|
try {
|
|
2197
|
-
return (0,
|
|
2258
|
+
return (0, import_fs17.readdirSync)(dir).filter((f) => {
|
|
2198
2259
|
try {
|
|
2199
|
-
return (0,
|
|
2260
|
+
return (0, import_fs17.lstatSync)((0, import_path16.resolve)(dir, f)).isDirectory();
|
|
2200
2261
|
} catch {
|
|
2201
2262
|
return false;
|
|
2202
2263
|
}
|
|
@@ -2210,16 +2271,16 @@ var stats = async () => {
|
|
|
2210
2271
|
const shows2 = getShows();
|
|
2211
2272
|
const rows = [];
|
|
2212
2273
|
const movieDest = config.dest.movie;
|
|
2213
|
-
if (movieDest && (0,
|
|
2274
|
+
if (movieDest && (0, import_fs17.existsSync)(movieDest)) {
|
|
2214
2275
|
rows.push({ category: "Movies", count: countDirs(movieDest), size: formatSize(dirSize(movieDest)) });
|
|
2215
2276
|
}
|
|
2216
2277
|
const tvDest = config.dest.tv;
|
|
2217
|
-
if (tvDest && (0,
|
|
2278
|
+
if (tvDest && (0, import_fs17.existsSync)(tvDest)) {
|
|
2218
2279
|
rows.push({ category: "Shows", count: shows2.length, size: formatSize(dirSize(tvDest)) });
|
|
2219
2280
|
rows.push({ category: "Episodes", count: countVideos(tvDest) });
|
|
2220
2281
|
}
|
|
2221
2282
|
const ps3Dest = config.dest.ps3;
|
|
2222
|
-
if (ps3Dest && (0,
|
|
2283
|
+
if (ps3Dest && (0, import_fs17.existsSync)(ps3Dest)) {
|
|
2223
2284
|
rows.push({ category: "PS3", count: countDirs(ps3Dest), size: formatSize(dirSize(ps3Dest)) });
|
|
2224
2285
|
}
|
|
2225
2286
|
if (rows.length === 0) return;
|
|
@@ -2238,61 +2299,92 @@ var stats = async () => {
|
|
|
2238
2299
|
var stats_default = stats;
|
|
2239
2300
|
|
|
2240
2301
|
// src/actions/undo.ts
|
|
2241
|
-
var
|
|
2302
|
+
var import_fs18 = require("fs");
|
|
2242
2303
|
var import_termkit17 = require("termkit");
|
|
2243
2304
|
var undo = async () => {
|
|
2244
2305
|
spinner_default.start();
|
|
2245
|
-
const
|
|
2246
|
-
|
|
2306
|
+
const renameRecords = getLastSession();
|
|
2307
|
+
const importRecords = getLastImportSession();
|
|
2308
|
+
if (renameRecords.length === 0 && importRecords.length === 0) {
|
|
2247
2309
|
spinner_default.info("nothing to undo");
|
|
2248
2310
|
spinner_default.stop();
|
|
2249
2311
|
return;
|
|
2250
2312
|
}
|
|
2313
|
+
const useImports = importRecords.length > 0 && (renameRecords.length === 0 || importRecords[0].sessionId > renameRecords[0].sessionId);
|
|
2314
|
+
if (!useImports) {
|
|
2315
|
+
let undone2 = 0;
|
|
2316
|
+
for (const record of renameRecords) {
|
|
2317
|
+
(0, import_fs18.renameSync)(record.newPath, record.oldPath);
|
|
2318
|
+
spinner_default.succeed(`${import_termkit17.Color.green.encoder(record.newPath)} \u2192 ${import_termkit17.Color.white.encoder(record.oldPath)}`);
|
|
2319
|
+
undone2++;
|
|
2320
|
+
}
|
|
2321
|
+
deleteSession(renameRecords[0].sessionId);
|
|
2322
|
+
spinner_default.succeed(`undid ${undone2} renames`);
|
|
2323
|
+
spinner_default.stop();
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2251
2326
|
let undone = 0;
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2327
|
+
let skipped = 0;
|
|
2328
|
+
for (const record of importRecords) {
|
|
2329
|
+
if (record.mode !== "move") {
|
|
2330
|
+
spinner_default.info(`skipped ${record.destinationPath} (${record.mode} \u2014 source file unchanged)`);
|
|
2331
|
+
skipped++;
|
|
2332
|
+
continue;
|
|
2333
|
+
}
|
|
2334
|
+
if (record.type === "tv") {
|
|
2335
|
+
spinner_default.info(`skipped TV import \u2014 season folder cannot be cleanly reversed: ${record.destinationPath}`);
|
|
2336
|
+
skipped++;
|
|
2337
|
+
continue;
|
|
2338
|
+
}
|
|
2339
|
+
if (!(0, import_fs18.existsSync)(record.destinationPath)) {
|
|
2340
|
+
spinner_default.info(`skipped \u2014 destination no longer exists: ${record.destinationPath}`);
|
|
2341
|
+
skipped++;
|
|
2342
|
+
continue;
|
|
2343
|
+
}
|
|
2344
|
+
(0, import_fs18.renameSync)(record.destinationPath, record.sourcePath);
|
|
2345
|
+
spinner_default.succeed(`${import_termkit17.Color.green.encoder(record.destinationPath)} \u2192 ${import_termkit17.Color.white.encoder(record.sourcePath)}`);
|
|
2255
2346
|
undone++;
|
|
2256
2347
|
}
|
|
2257
|
-
|
|
2258
|
-
spinner_default.succeed(`undid ${undone}
|
|
2348
|
+
deleteImportSession(importRecords[0].sessionId);
|
|
2349
|
+
if (undone > 0) spinner_default.succeed(`undid ${undone} import${undone !== 1 ? "s" : ""}`);
|
|
2350
|
+
if (skipped > 0) spinner_default.info(`skipped ${skipped} item${skipped !== 1 ? "s" : ""} (TV or non-move mode)`);
|
|
2259
2351
|
spinner_default.stop();
|
|
2260
2352
|
};
|
|
2261
2353
|
var undo_default = undo;
|
|
2262
2354
|
|
|
2263
2355
|
// src/actions/watch.ts
|
|
2264
2356
|
var import_chokidar = __toESM(require("chokidar"));
|
|
2265
|
-
var
|
|
2266
|
-
var
|
|
2357
|
+
var import_fs19 = require("fs");
|
|
2358
|
+
var import_path17 = require("path");
|
|
2267
2359
|
var import_termkit18 = require("termkit");
|
|
2268
2360
|
var sameDev2 = (a, b) => {
|
|
2269
2361
|
try {
|
|
2270
2362
|
let bExisting = b;
|
|
2271
|
-
while (!(0,
|
|
2272
|
-
return (0,
|
|
2363
|
+
while (!(0, import_fs19.existsSync)(bExisting)) bExisting = (0, import_path17.dirname)(bExisting);
|
|
2364
|
+
return (0, import_fs19.statSync)(a).dev === (0, import_fs19.statSync)(bExisting).dev;
|
|
2273
2365
|
} catch {
|
|
2274
2366
|
return false;
|
|
2275
2367
|
}
|
|
2276
2368
|
};
|
|
2277
2369
|
var moveItem = (src, dest) => {
|
|
2278
2370
|
if (sameDev2(src, dest)) {
|
|
2279
|
-
(0,
|
|
2371
|
+
(0, import_fs19.renameSync)(src, dest);
|
|
2280
2372
|
} else {
|
|
2281
|
-
(0,
|
|
2282
|
-
(0,
|
|
2373
|
+
(0, import_fs19.cpSync)(src, dest, { recursive: true });
|
|
2374
|
+
(0, import_fs19.rmSync)(src, { recursive: true, force: true });
|
|
2283
2375
|
}
|
|
2284
2376
|
};
|
|
2285
|
-
var findVideo2 = (dir) => (0,
|
|
2377
|
+
var findVideo2 = (dir) => (0, import_fs19.readdirSync)(dir).find((f) => {
|
|
2286
2378
|
const ext = f.match(/([^.]+$)/)?.[0];
|
|
2287
2379
|
return ext && videoExtensions_default.includes(ext);
|
|
2288
2380
|
}) ?? null;
|
|
2289
|
-
var containsBook2 = (dir, depth = 2) => (0,
|
|
2381
|
+
var containsBook2 = (dir, depth = 2) => (0, import_fs19.readdirSync)(dir).some((f) => {
|
|
2290
2382
|
const ext = f.match(/([^.]+$)/)?.[0];
|
|
2291
2383
|
if (ext && bookExtensions_default.includes(ext)) return true;
|
|
2292
2384
|
if (depth > 1) {
|
|
2293
2385
|
try {
|
|
2294
|
-
const sub = (0,
|
|
2295
|
-
if ((0,
|
|
2386
|
+
const sub = (0, import_path17.resolve)(dir, f);
|
|
2387
|
+
if ((0, import_fs19.lstatSync)(sub).isDirectory()) return containsBook2(sub, depth - 1);
|
|
2296
2388
|
} catch {
|
|
2297
2389
|
}
|
|
2298
2390
|
}
|
|
@@ -2303,26 +2395,26 @@ var isSeasonDirName2 = (name) => !isTvEpisodeName2(name) && /(?:^|[.\s_-])(?:sea
|
|
|
2303
2395
|
var expandWatchPath = (p) => {
|
|
2304
2396
|
let isDir;
|
|
2305
2397
|
try {
|
|
2306
|
-
isDir = (0,
|
|
2398
|
+
isDir = (0, import_fs19.lstatSync)(p).isDirectory();
|
|
2307
2399
|
} catch {
|
|
2308
2400
|
return [p];
|
|
2309
2401
|
}
|
|
2310
2402
|
if (!isDir) return [p];
|
|
2311
|
-
const name = (0,
|
|
2403
|
+
const name = (0, import_path17.basename)(p);
|
|
2312
2404
|
if (isTvEpisodeName2(name) || /(?<=\[).+?(?=\])/.test(name) || /^[A-Z]{4}\d{5}/i.test(name)) return [p];
|
|
2313
2405
|
let children;
|
|
2314
2406
|
try {
|
|
2315
|
-
children = (0,
|
|
2407
|
+
children = (0, import_fs19.readdirSync)(p);
|
|
2316
2408
|
} catch {
|
|
2317
2409
|
return [p];
|
|
2318
2410
|
}
|
|
2319
2411
|
if (children.some((c) => isTvEpisodeName2(c))) {
|
|
2320
2412
|
const entries = [];
|
|
2321
2413
|
for (const child of children) {
|
|
2322
|
-
const cp = (0,
|
|
2414
|
+
const cp = (0, import_path17.resolve)(p, child);
|
|
2323
2415
|
let cd;
|
|
2324
2416
|
try {
|
|
2325
|
-
cd = (0,
|
|
2417
|
+
cd = (0, import_fs19.lstatSync)(cp).isDirectory();
|
|
2326
2418
|
} catch {
|
|
2327
2419
|
continue;
|
|
2328
2420
|
}
|
|
@@ -2334,7 +2426,7 @@ var expandWatchPath = (p) => {
|
|
|
2334
2426
|
}
|
|
2335
2427
|
const seasonDirs = children.filter((c) => {
|
|
2336
2428
|
try {
|
|
2337
|
-
return isSeasonDirName2(c) && (0,
|
|
2429
|
+
return isSeasonDirName2(c) && (0, import_fs19.lstatSync)((0, import_path17.resolve)(p, c)).isDirectory();
|
|
2338
2430
|
} catch {
|
|
2339
2431
|
return false;
|
|
2340
2432
|
}
|
|
@@ -2342,18 +2434,18 @@ var expandWatchPath = (p) => {
|
|
|
2342
2434
|
if (seasonDirs.length > 0) {
|
|
2343
2435
|
const entries = [];
|
|
2344
2436
|
for (const sd of seasonDirs) {
|
|
2345
|
-
const sp = (0,
|
|
2437
|
+
const sp = (0, import_path17.resolve)(p, sd);
|
|
2346
2438
|
let sc;
|
|
2347
2439
|
try {
|
|
2348
|
-
sc = (0,
|
|
2440
|
+
sc = (0, import_fs19.readdirSync)(sp);
|
|
2349
2441
|
} catch {
|
|
2350
2442
|
continue;
|
|
2351
2443
|
}
|
|
2352
2444
|
for (const child of sc) {
|
|
2353
|
-
const cp = (0,
|
|
2445
|
+
const cp = (0, import_path17.resolve)(sp, child);
|
|
2354
2446
|
let cd;
|
|
2355
2447
|
try {
|
|
2356
|
-
cd = (0,
|
|
2448
|
+
cd = (0, import_fs19.lstatSync)(cp).isDirectory();
|
|
2357
2449
|
} catch {
|
|
2358
2450
|
continue;
|
|
2359
2451
|
}
|
|
@@ -2367,10 +2459,10 @@ var expandWatchPath = (p) => {
|
|
|
2367
2459
|
return [p];
|
|
2368
2460
|
};
|
|
2369
2461
|
var findSeasonFolder2 = (showPath, season) => {
|
|
2370
|
-
if (!(0,
|
|
2371
|
-
const folders = (0,
|
|
2462
|
+
if (!(0, import_fs19.existsSync)(showPath)) return null;
|
|
2463
|
+
const folders = (0, import_fs19.readdirSync)(showPath).filter((f) => {
|
|
2372
2464
|
try {
|
|
2373
|
-
return (0,
|
|
2465
|
+
return (0, import_fs19.lstatSync)((0, import_path17.resolve)(showPath, f)).isDirectory();
|
|
2374
2466
|
} catch {
|
|
2375
2467
|
return false;
|
|
2376
2468
|
}
|
|
@@ -2383,10 +2475,10 @@ var findSeasonFolder2 = (showPath, season) => {
|
|
|
2383
2475
|
var processItem = async (entryPath, useHardlink, language, auto) => {
|
|
2384
2476
|
const config = getConfig();
|
|
2385
2477
|
const sessionId = (/* @__PURE__ */ new Date()).toISOString();
|
|
2386
|
-
const entry = (0,
|
|
2478
|
+
const entry = (0, import_path17.basename)(entryPath);
|
|
2387
2479
|
const movieFormat = config.format?.movie ?? DEFAULT_MOVIE_FORMAT;
|
|
2388
2480
|
const seasonFormat = config.format?.season ?? DEFAULT_SEASON_FORMAT;
|
|
2389
|
-
const isDir = (0,
|
|
2481
|
+
const isDir = (0, import_fs19.lstatSync)(entryPath).isDirectory();
|
|
2390
2482
|
const ext = entry.match(/([^.]+$)/)?.[0];
|
|
2391
2483
|
const isVideo = !isDir && ext && videoExtensions_default.includes(ext);
|
|
2392
2484
|
const isBook = !isDir && ext && bookExtensions_default.includes(ext);
|
|
@@ -2412,34 +2504,34 @@ var processItem = async (entryPath, useHardlink, language, auto) => {
|
|
|
2412
2504
|
const id = entry.split("-")[0];
|
|
2413
2505
|
if (!nameMatch || !id) return;
|
|
2414
2506
|
const destName = `${nameMatch[0]} [${id}]`;
|
|
2415
|
-
const destPath = (0,
|
|
2416
|
-
if ((0,
|
|
2507
|
+
const destPath = (0, import_path17.resolve)(destRoot, destName);
|
|
2508
|
+
if ((0, import_fs19.existsSync)(destPath)) {
|
|
2417
2509
|
spinner_default.warn(`already exists: ${destName}`);
|
|
2418
2510
|
return;
|
|
2419
2511
|
}
|
|
2420
2512
|
moveItem(entryPath, destPath);
|
|
2421
|
-
recordImport(sessionId, entryPath, destPath, "move");
|
|
2513
|
+
recordImport(sessionId, entryPath, destPath, "move", void 0, "ps3");
|
|
2422
2514
|
spinner_default.succeed(`imported ${import_termkit18.Color.green.encoder(destName)}`);
|
|
2423
2515
|
return;
|
|
2424
2516
|
}
|
|
2425
2517
|
if (detectedType === "book") {
|
|
2426
|
-
const destPath = (0,
|
|
2427
|
-
if ((0,
|
|
2518
|
+
const destPath = (0, import_path17.resolve)(destRoot, entry);
|
|
2519
|
+
if ((0, import_fs19.existsSync)(destPath)) {
|
|
2428
2520
|
spinner_default.warn(`already exists: ${entry}`);
|
|
2429
2521
|
return;
|
|
2430
2522
|
}
|
|
2431
2523
|
if (isDir || isBookDir) {
|
|
2432
2524
|
moveItem(entryPath, destPath);
|
|
2433
2525
|
} else {
|
|
2434
|
-
(0,
|
|
2526
|
+
(0, import_fs19.mkdirSync)(destRoot, { recursive: true });
|
|
2435
2527
|
if (sameDev2(entryPath, destRoot)) {
|
|
2436
|
-
(0,
|
|
2528
|
+
(0, import_fs19.renameSync)(entryPath, destPath);
|
|
2437
2529
|
} else {
|
|
2438
|
-
(0,
|
|
2439
|
-
(0,
|
|
2530
|
+
(0, import_fs19.cpSync)(entryPath, destPath);
|
|
2531
|
+
(0, import_fs19.rmSync)(entryPath);
|
|
2440
2532
|
}
|
|
2441
2533
|
}
|
|
2442
|
-
recordImport(sessionId, entryPath, destPath, "move");
|
|
2534
|
+
recordImport(sessionId, entryPath, destPath, "move", void 0, "book");
|
|
2443
2535
|
spinner_default.succeed(`imported ${import_termkit18.Color.green.encoder(entry)}`);
|
|
2444
2536
|
return;
|
|
2445
2537
|
}
|
|
@@ -2461,14 +2553,14 @@ var processItem = async (entryPath, useHardlink, language, auto) => {
|
|
|
2461
2553
|
showFolderName = showPath.split("/").pop() ?? registeredShow.path;
|
|
2462
2554
|
} else if (auto) {
|
|
2463
2555
|
showFolderName = formatMovieName(movieFormat, parsed.title, parsed.year);
|
|
2464
|
-
showPath = (0,
|
|
2556
|
+
showPath = (0, import_path17.resolve)(destRoot, showFolderName);
|
|
2465
2557
|
upsertShow(showPath, null, parsed.title);
|
|
2466
2558
|
} else {
|
|
2467
2559
|
if (isVerbose()) spinner_default.info(`not registered, skipped: ${parsed.title} \u2014 run: reelsort add "${parsed.title}"`);
|
|
2468
2560
|
return;
|
|
2469
2561
|
}
|
|
2470
2562
|
const seasonFolderName = findSeasonFolder2(showPath, parsed.season) ?? formatSeasonFolder(seasonFormat, parsed.season);
|
|
2471
|
-
const seasonPath = (0,
|
|
2563
|
+
const seasonPath = (0, import_path17.resolve)(showPath, seasonFolderName);
|
|
2472
2564
|
const videoFile2 = isDir ? findVideo2(entryPath) : entry;
|
|
2473
2565
|
if (!videoFile2) {
|
|
2474
2566
|
if (isVerbose()) spinner_default.info(`no video found in: ${entry}`);
|
|
@@ -2478,48 +2570,48 @@ var processItem = async (entryPath, useHardlink, language, auto) => {
|
|
|
2478
2570
|
const tmdbEpisodeName = registeredShow?.tmdbId && config.tmdbApiKey ? await getEpisodeName(registeredShow.tmdbId, parsed.season, parsed.episode ?? 1, config.tmdbApiKey) : null;
|
|
2479
2571
|
const episodeName = formatEpisode(parsed.season, parsed.episode ?? 1, config.format?.episode, false, parsed.title, tmdbEpisodeName ?? void 0);
|
|
2480
2572
|
const destVideoName2 = `${episodeName}.${videoExt2}`;
|
|
2481
|
-
const destVideoPath = (0,
|
|
2482
|
-
const videoSourcePath2 = isDir ? (0,
|
|
2483
|
-
if ((0,
|
|
2573
|
+
const destVideoPath = (0, import_path17.resolve)(seasonPath, destVideoName2);
|
|
2574
|
+
const videoSourcePath2 = isDir ? (0, import_path17.resolve)(entryPath, videoFile2) : entryPath;
|
|
2575
|
+
if ((0, import_fs19.existsSync)(destVideoPath)) {
|
|
2484
2576
|
spinner_default.warn(`already exists: ${episodeName}`);
|
|
2485
2577
|
return;
|
|
2486
2578
|
}
|
|
2487
|
-
const dirFiles2 = isDir ? (0,
|
|
2579
|
+
const dirFiles2 = isDir ? (0, import_fs19.readdirSync)(entryPath) : [];
|
|
2488
2580
|
const subtitle2 = isDir ? findSubtitle(dirFiles2, language) : null;
|
|
2489
2581
|
const subtitleExt2 = subtitle2?.match(/([^.]+$)/)?.[0];
|
|
2490
|
-
const subtitleSourcePath2 = subtitle2 ? (0,
|
|
2582
|
+
const subtitleSourcePath2 = subtitle2 ? (0, import_path17.resolve)(entryPath, subtitle2) : null;
|
|
2491
2583
|
const destSubtitleName2 = subtitle2 && subtitleExt2 ? `${episodeName}.${subtitleExt2}` : null;
|
|
2492
|
-
(0,
|
|
2584
|
+
(0, import_fs19.mkdirSync)(seasonPath, { recursive: true });
|
|
2493
2585
|
let mode = "move";
|
|
2494
2586
|
if (useHardlink) {
|
|
2495
2587
|
try {
|
|
2496
2588
|
if (!sameDev2(videoSourcePath2, seasonPath)) throw new Error("cross-filesystem");
|
|
2497
|
-
(0,
|
|
2589
|
+
(0, import_fs19.linkSync)(videoSourcePath2, destVideoPath);
|
|
2498
2590
|
mode = "hardlink";
|
|
2499
2591
|
} catch {
|
|
2500
2592
|
spinner_default.warn(`hardlink unavailable \u2014 copying instead: ${episodeName}`);
|
|
2501
|
-
(0,
|
|
2593
|
+
(0, import_fs19.cpSync)(videoSourcePath2, destVideoPath);
|
|
2502
2594
|
mode = "copy";
|
|
2503
2595
|
}
|
|
2504
|
-
if (subtitleSourcePath2 && destSubtitleName2) (0,
|
|
2596
|
+
if (subtitleSourcePath2 && destSubtitleName2) (0, import_fs19.cpSync)(subtitleSourcePath2, (0, import_path17.resolve)(seasonPath, destSubtitleName2));
|
|
2505
2597
|
} else {
|
|
2506
2598
|
if (sameDev2(videoSourcePath2, seasonPath)) {
|
|
2507
|
-
(0,
|
|
2599
|
+
(0, import_fs19.renameSync)(videoSourcePath2, destVideoPath);
|
|
2508
2600
|
} else {
|
|
2509
|
-
(0,
|
|
2510
|
-
(0,
|
|
2601
|
+
(0, import_fs19.cpSync)(videoSourcePath2, destVideoPath);
|
|
2602
|
+
(0, import_fs19.rmSync)(videoSourcePath2);
|
|
2511
2603
|
}
|
|
2512
|
-
if (subtitleSourcePath2 && destSubtitleName2) (0,
|
|
2513
|
-
if (isDir) (0,
|
|
2604
|
+
if (subtitleSourcePath2 && destSubtitleName2) (0, import_fs19.renameSync)(subtitleSourcePath2, (0, import_path17.resolve)(seasonPath, destSubtitleName2));
|
|
2605
|
+
if (isDir) (0, import_fs19.rmSync)(entryPath, { recursive: true, force: true });
|
|
2514
2606
|
}
|
|
2515
|
-
recordImport(sessionId, entryPath, seasonPath, mode);
|
|
2607
|
+
recordImport(sessionId, entryPath, seasonPath, mode, void 0, "tv");
|
|
2516
2608
|
spinner_default.succeed(`imported ${import_termkit18.Color.green.encoder(`${showFolderName} / ${seasonFolderName} / ${episodeName}`)}`);
|
|
2517
2609
|
return;
|
|
2518
2610
|
}
|
|
2519
2611
|
const edition = detectEdition(entry);
|
|
2520
2612
|
const folderName = formatMovieName(movieFormat, parsed.title, parsed.year, edition);
|
|
2521
|
-
const destFolder = (0,
|
|
2522
|
-
if ((0,
|
|
2613
|
+
const destFolder = (0, import_path17.resolve)(destRoot, folderName);
|
|
2614
|
+
if ((0, import_fs19.existsSync)(destFolder)) {
|
|
2523
2615
|
spinner_default.warn(`already exists: ${folderName}`);
|
|
2524
2616
|
return;
|
|
2525
2617
|
}
|
|
@@ -2530,45 +2622,45 @@ var processItem = async (entryPath, useHardlink, language, auto) => {
|
|
|
2530
2622
|
}
|
|
2531
2623
|
const videoExt = videoFile.match(/([^.]+$)/)?.[0];
|
|
2532
2624
|
const destVideoName = `${folderName}.${videoExt}`;
|
|
2533
|
-
const videoSourcePath = isDir ? (0,
|
|
2534
|
-
const dirFiles = isDir ? (0,
|
|
2625
|
+
const videoSourcePath = isDir ? (0, import_path17.resolve)(entryPath, videoFile) : entryPath;
|
|
2626
|
+
const dirFiles = isDir ? (0, import_fs19.readdirSync)(entryPath) : [];
|
|
2535
2627
|
const subtitle = isDir ? findSubtitle(dirFiles, language) : null;
|
|
2536
2628
|
const subtitleExt = subtitle?.match(/([^.]+$)/)?.[0];
|
|
2537
|
-
const subtitleSourcePath = subtitle ? (0,
|
|
2629
|
+
const subtitleSourcePath = subtitle ? (0, import_path17.resolve)(entryPath, subtitle) : null;
|
|
2538
2630
|
const destSubtitleName = subtitle && subtitleExt ? `${folderName}.${subtitleExt}` : null;
|
|
2539
2631
|
if (useHardlink) {
|
|
2540
|
-
(0,
|
|
2541
|
-
const destVideoPath = (0,
|
|
2632
|
+
(0, import_fs19.mkdirSync)(destFolder, { recursive: true });
|
|
2633
|
+
const destVideoPath = (0, import_path17.resolve)(destFolder, destVideoName);
|
|
2542
2634
|
let mode;
|
|
2543
2635
|
try {
|
|
2544
2636
|
if (!sameDev2(videoSourcePath, destRoot)) throw new Error("cross-filesystem");
|
|
2545
|
-
(0,
|
|
2637
|
+
(0, import_fs19.linkSync)(videoSourcePath, destVideoPath);
|
|
2546
2638
|
mode = "hardlink";
|
|
2547
2639
|
} catch {
|
|
2548
2640
|
spinner_default.warn(`hardlink unavailable \u2014 copying instead: ${folderName}`);
|
|
2549
|
-
(0,
|
|
2641
|
+
(0, import_fs19.cpSync)(videoSourcePath, destVideoPath);
|
|
2550
2642
|
mode = "copy";
|
|
2551
2643
|
}
|
|
2552
|
-
if (subtitleSourcePath && destSubtitleName) (0,
|
|
2553
|
-
recordImport(sessionId, entryPath, destFolder, mode);
|
|
2644
|
+
if (subtitleSourcePath && destSubtitleName) (0, import_fs19.cpSync)(subtitleSourcePath, (0, import_path17.resolve)(destFolder, destSubtitleName));
|
|
2645
|
+
recordImport(sessionId, entryPath, destFolder, mode, void 0, "movie");
|
|
2554
2646
|
} else {
|
|
2555
2647
|
if (isDir) {
|
|
2556
2648
|
const keep = new Set([videoFile, subtitle].filter(Boolean));
|
|
2557
|
-
for (const f of dirFiles.filter((f2) => !keep.has(f2))) (0,
|
|
2558
|
-
(0,
|
|
2559
|
-
if (subtitleSourcePath && destSubtitleName) (0,
|
|
2649
|
+
for (const f of dirFiles.filter((f2) => !keep.has(f2))) (0, import_fs19.rmSync)((0, import_path17.resolve)(entryPath, f), { recursive: true, force: true });
|
|
2650
|
+
(0, import_fs19.renameSync)(videoSourcePath, (0, import_path17.resolve)(entryPath, destVideoName));
|
|
2651
|
+
if (subtitleSourcePath && destSubtitleName) (0, import_fs19.renameSync)(subtitleSourcePath, (0, import_path17.resolve)(entryPath, destSubtitleName));
|
|
2560
2652
|
moveItem(entryPath, destFolder);
|
|
2561
2653
|
} else {
|
|
2562
|
-
(0,
|
|
2563
|
-
const destVideoPath = (0,
|
|
2654
|
+
(0, import_fs19.mkdirSync)(destFolder, { recursive: true });
|
|
2655
|
+
const destVideoPath = (0, import_path17.resolve)(destFolder, destVideoName);
|
|
2564
2656
|
if (sameDev2(videoSourcePath, destRoot)) {
|
|
2565
|
-
(0,
|
|
2657
|
+
(0, import_fs19.renameSync)(videoSourcePath, destVideoPath);
|
|
2566
2658
|
} else {
|
|
2567
|
-
(0,
|
|
2568
|
-
(0,
|
|
2659
|
+
(0, import_fs19.cpSync)(videoSourcePath, destVideoPath);
|
|
2660
|
+
(0, import_fs19.rmSync)(videoSourcePath);
|
|
2569
2661
|
}
|
|
2570
2662
|
}
|
|
2571
|
-
recordImport(sessionId, entryPath, destFolder, "move");
|
|
2663
|
+
recordImport(sessionId, entryPath, destFolder, "move", void 0, "movie");
|
|
2572
2664
|
}
|
|
2573
2665
|
spinner_default.succeed(`imported ${import_termkit18.Color.green.encoder(folderName)}`);
|
|
2574
2666
|
};
|
|
@@ -2610,7 +2702,7 @@ var watch = async ({ hardlink = false, auto = false }) => {
|
|
|
2610
2702
|
var watch_default = watch;
|
|
2611
2703
|
|
|
2612
2704
|
// package.json
|
|
2613
|
-
var version = "0.2.
|
|
2705
|
+
var version = "0.2.6";
|
|
2614
2706
|
|
|
2615
2707
|
// src/program.ts
|
|
2616
2708
|
var toCamel = (s) => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|