@emgeebee/music_downcoder 1.1.8 → 1.1.9

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.
@@ -1 +1 @@
1
- {"version":3,"file":"cleanEmptyFolders.d.ts","sourceRoot":"","sources":["../src/cleanEmptyFolders.ts"],"names":[],"mappings":";AAuEA,eAAO,MAAM,yBAAyB,GAAI,aAAa,MAAM,KAAG,MA0B/D,CAAC"}
1
+ {"version":3,"file":"cleanEmptyFolders.d.ts","sourceRoot":"","sources":["../src/cleanEmptyFolders.ts"],"names":[],"mappings":";AAyFA,eAAO,MAAM,yBAAyB,GAAI,aAAa,MAAM,KAAG,MAgC/D,CAAC"}
@@ -16,6 +16,10 @@ const MEDIA_EXTENSIONS = new Set([
16
16
  ".aif",
17
17
  ]);
18
18
  const isMediaFile = (filename) => MEDIA_EXTENSIONS.has(path.extname(filename).toLowerCase());
19
+ const formatError = (error) => error instanceof Error ? error.message : String(error);
20
+ const logAccessError = (action, dirPath, error) => {
21
+ console.warn(`Could not ${action} ${dirPath}: ${formatError(error)}`);
22
+ };
19
23
  const directoryHasMedia = (dirPath) => {
20
24
  let entries;
21
25
  try {
@@ -43,7 +47,14 @@ const cleanEmptyDirectories = (dirPath) => {
43
47
  return 0;
44
48
  }
45
49
  let removed = 0;
46
- const entries = fs.readdirSync(dirPath, { withFileTypes: true });
50
+ let entries;
51
+ try {
52
+ entries = fs.readdirSync(dirPath, { withFileTypes: true });
53
+ }
54
+ catch (error) {
55
+ logAccessError("read", dirPath, error);
56
+ return 0;
57
+ }
47
58
  for (const entry of entries) {
48
59
  if (!entry.isDirectory()) {
49
60
  continue;
@@ -51,9 +62,15 @@ const cleanEmptyDirectories = (dirPath) => {
51
62
  removed += cleanEmptyDirectories(path.join(dirPath, entry.name));
52
63
  }
53
64
  if (!directoryHasMedia(dirPath)) {
54
- fs.rmSync(dirPath, { recursive: true, force: true });
55
- console.log(`Removed ${dirPath}`);
56
- return removed + 1;
65
+ try {
66
+ fs.rmSync(dirPath, { recursive: true, force: true });
67
+ console.log(`Removed ${dirPath}`);
68
+ return removed + 1;
69
+ }
70
+ catch (error) {
71
+ logAccessError("remove", dirPath, error);
72
+ return removed;
73
+ }
57
74
  }
58
75
  return removed;
59
76
  };
@@ -70,7 +87,14 @@ export const cleanEncoderOutputFolders = (configPath) => {
70
87
  continue;
71
88
  }
72
89
  console.log(`Cleaning ${outputRoot}...`);
73
- const entries = fs.readdirSync(outputRoot, { withFileTypes: true });
90
+ let entries;
91
+ try {
92
+ entries = fs.readdirSync(outputRoot, { withFileTypes: true });
93
+ }
94
+ catch (error) {
95
+ logAccessError("read", outputRoot, error);
96
+ continue;
97
+ }
74
98
  for (const entry of entries) {
75
99
  if (!entry.isDirectory()) {
76
100
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"cleanEmptyFolders.js","sourceRoot":"","sources":["../src/cleanEmptyFolders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cleanEmptyFolders.js","sourceRoot":"","sources":["../src/cleanEmptyFolders.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAW,EAAE,CAChD,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAE7D,MAAM,WAAW,GAAG,CAAC,KAAc,EAAU,EAAE,CAC7C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAEzD,MAAM,cAAc,GAAG,CAAC,MAAc,EAAE,OAAe,EAAE,KAAc,EAAQ,EAAE;IAC/E,OAAO,CAAC,IAAI,CAAC,aAAa,MAAM,IAAI,OAAO,KAAK,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAW,EAAE;IACrD,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,OAAe,EAAU,EAAE;IACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACvC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QACD,OAAO,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;YAClC,OAAO,OAAO,GAAG,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YACzC,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,UAAmB,EAAU,EAAE;IACvE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,WAAW,GAAG;QAClB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;KACxE,CAAC;IAEF,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAC;YACtD,SAAS;QACX,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,YAAY,UAAU,KAAK,CAAC,CAAC;QACzC,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;YAC1C,SAAS;QACX,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,OAAO,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAClD,MAAM,UAAU,GACd,cAAc,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAErE,MAAM,OAAO,GAAG,yBAAyB,CAAC,UAAU,CAAC,CAAC;AACtD,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,mBAAmB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAYA,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAgBA,OAAO,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,12 @@ if (command === "serve") {
6
6
  else if (command === "clean-empty") {
7
7
  await import("./cleanEmptyFolders.js");
8
8
  }
9
+ else if (command === "sync-meta") {
10
+ await import("./syncMetaFromLocal.js");
11
+ }
12
+ else if (command === "repair-meta-years") {
13
+ await import("./repairMetaYears.js");
14
+ }
9
15
  else {
10
16
  await import("./cli.js");
11
17
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAExC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;KAAM,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;IACrC,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;AACzC,CAAC;KAAM,CAAC;IACN,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAExC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;KAAM,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;IACrC,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;AACzC,CAAC;KAAM,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;IACnC,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;AACzC,CAAC;KAAM,IAAI,OAAO,KAAK,mBAAmB,EAAE,CAAC;IAC3C,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;AACvC,CAAC;KAAM,CAAC;IACN,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare const sanitiseMeta: (meta: string) => string;
2
+ export declare const sanitisePathSegment: (segment: string) => string;
3
+ export declare const buildArtistDirName: (fullArtist: string) => string;
4
+ export declare const buildArtistOutputDir: (outputRoot: string, genre: string, fullArtist: string) => string;
5
+ export interface AlbumFolderMatch {
6
+ folderName: string;
7
+ year: string;
8
+ }
9
+ export declare const findAlbumFolderOnDisk: (artistDir: string, albumName: string) => AlbumFolderMatch | null;
10
+ //# sourceMappingURL=outputPaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outputPaths.d.ts","sourceRoot":"","sources":["../src/outputPaths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MACC,CAAC;AAE9C,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,KAAG,MACxB,CAAC;AAE/B,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,KAAG,MAGnB,CAAC;AAEtC,eAAO,MAAM,oBAAoB,GAC/B,YAAY,MAAM,EAClB,OAAO,MAAM,EACb,YAAY,MAAM,KACjB,MAKA,CAAC;AAKJ,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,qBAAqB,GAChC,WAAW,MAAM,EACjB,WAAW,MAAM,KAChB,gBAAgB,GAAG,IAgCrB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ export const sanitiseMeta = (meta) => meta.replace(/\//g, "_").replace(/:/g, "_");
4
+ export const sanitisePathSegment = (segment) => sanitiseMeta(segment).trim();
5
+ export const buildArtistDirName = (fullArtist) => fullArtist === "Various Artists"
6
+ ? "Compilations"
7
+ : sanitisePathSegment(fullArtist);
8
+ export const buildArtistOutputDir = (outputRoot, genre, fullArtist) => path.join(outputRoot, sanitisePathSegment(genre), buildArtistDirName(fullArtist));
9
+ const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10
+ export const findAlbumFolderOnDisk = (artistDir, albumName) => {
11
+ if (!fs.existsSync(artistDir)) {
12
+ return null;
13
+ }
14
+ const sanitisedAlbum = sanitisePathSegment(albumName);
15
+ const escapedAlbum = escapeRegex(sanitisedAlbum);
16
+ const yearPrefixPattern = new RegExp(`^\\((\\d{4})\\)\\s+${escapedAlbum}$`, "i");
17
+ const plainPattern = new RegExp(`^${escapedAlbum}$`, "i");
18
+ let plainMatch = null;
19
+ for (const entry of fs.readdirSync(artistDir, { withFileTypes: true })) {
20
+ if (!entry.isDirectory()) {
21
+ continue;
22
+ }
23
+ const yearMatch = entry.name.match(yearPrefixPattern);
24
+ if (yearMatch) {
25
+ return { folderName: entry.name, year: yearMatch[1] };
26
+ }
27
+ if (plainPattern.test(entry.name)) {
28
+ plainMatch = entry.name;
29
+ }
30
+ }
31
+ if (plainMatch) {
32
+ return { folderName: plainMatch, year: "" };
33
+ }
34
+ return null;
35
+ };
36
+ //# sourceMappingURL=outputPaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outputPaths.js","sourceRoot":"","sources":["../src/outputPaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAU,EAAE,CACnD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAe,EAAU,EAAE,CAC7D,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAE/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAkB,EAAU,EAAE,CAC/D,UAAU,KAAK,iBAAiB;IAC9B,CAAC,CAAC,cAAc;IAChB,CAAC,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,UAAkB,EAClB,KAAa,EACb,UAAkB,EACV,EAAE,CACV,IAAI,CAAC,IAAI,CACP,UAAU,EACV,mBAAmB,CAAC,KAAK,CAAC,EAC1B,kBAAkB,CAAC,UAAU,CAAC,CAC/B,CAAC;AAEJ,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE,CAC5C,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAO/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,SAAiB,EACjB,SAAiB,EACQ,EAAE;IAC3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,cAAc,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IACjD,MAAM,iBAAiB,GAAG,IAAI,MAAM,CAAC,sBAAsB,YAAY,GAAG,EAAE,GAAG,CAAC,CAAC;IACjF,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,EAAE,GAAG,CAAC,CAAC;IAE1D,IAAI,UAAU,GAAkB,IAAI,CAAC;IAErC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QAED,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACtD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAC9C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ export declare const repairMetaYearsFromAlac: (configPath?: string) => Promise<{
3
+ checked: number;
4
+ updated: number;
5
+ missing: number;
6
+ matched: number;
7
+ }>;
8
+ //# sourceMappingURL=repairMetaYears.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repairMetaYears.d.ts","sourceRoot":"","sources":["../src/repairMetaYears.ts"],"names":[],"mappings":";AAkCA,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,KAClB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA8DhF,CAAC"}
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { getConfig, loadConfig } from "./config.js";
5
+ import { buildArtistOutputDir, findAlbumFolderOnDisk, } from "./outputPaths.js";
6
+ import { createCliPrompts } from "./prompts.js";
7
+ const normalizeYear = (year) => year?.trim() ?? "";
8
+ const loadMetaCache = (metaFile) => {
9
+ try {
10
+ return JSON.parse(fs.readFileSync(metaFile, "utf-8"));
11
+ }
12
+ catch {
13
+ return {};
14
+ }
15
+ };
16
+ const writeLocalBackup = (sourcePath, meta) => {
17
+ const backupFile = path.join(sourcePath, "meta.json");
18
+ if (!fs.existsSync(sourcePath)) {
19
+ return;
20
+ }
21
+ fs.writeFileSync(backupFile, JSON.stringify(meta));
22
+ };
23
+ export const repairMetaYearsFromAlac = async (configPath) => {
24
+ loadConfig(configPath ? path.resolve(configPath) : undefined);
25
+ const config = getConfig();
26
+ const prompts = createCliPrompts();
27
+ const alacEncoder = config.encoders.find((encoder) => encoder.id === "alac");
28
+ if (!alacEncoder) {
29
+ throw new Error("No alac encoder found in config");
30
+ }
31
+ const metaData = loadMetaCache(config.metaFile);
32
+ const entries = Object.entries(metaData);
33
+ let checked = 0;
34
+ let updated = 0;
35
+ let missing = 0;
36
+ let matched = 0;
37
+ for (const [sourcePath, meta] of entries) {
38
+ checked++;
39
+ const artistDir = buildArtistOutputDir(alacEncoder.out, meta.genre, meta.fullArtist);
40
+ const folderMatch = findAlbumFolderOnDisk(artistDir, meta.fullAlbum);
41
+ if (!folderMatch) {
42
+ missing++;
43
+ continue;
44
+ }
45
+ matched++;
46
+ const metaYear = normalizeYear(meta.year);
47
+ const diskYear = normalizeYear(folderMatch.year);
48
+ if (metaYear === diskYear) {
49
+ continue;
50
+ }
51
+ const accept = await prompts.confirm(`Update ${meta.fullArtist} / ${meta.fullAlbum}\n` +
52
+ ` folder: ${folderMatch.folderName}\n` +
53
+ ` meta year: ${metaYear || "(none)"} -> ${diskYear || "(none)"}?`, true);
54
+ if (!accept) {
55
+ continue;
56
+ }
57
+ meta.year = diskYear;
58
+ metaData[sourcePath] = meta;
59
+ writeLocalBackup(sourcePath, meta);
60
+ updated++;
61
+ }
62
+ if (updated > 0) {
63
+ fs.writeFileSync(config.metaFile, JSON.stringify(metaData, undefined, 2));
64
+ }
65
+ return { checked, updated, missing, matched };
66
+ };
67
+ const configArgIndex = process.argv.indexOf("-c");
68
+ const configPath = configArgIndex >= 0 ? process.argv[configArgIndex + 1] : undefined;
69
+ const result = await repairMetaYearsFromAlac(configPath);
70
+ console.log(`Checked ${result.checked} meta entries.`);
71
+ console.log(` matched on disk: ${result.matched}`);
72
+ console.log(` no album folder: ${result.missing}`);
73
+ console.log(` updated: ${result.updated}`);
74
+ //# sourceMappingURL=repairMetaYears.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repairMetaYears.js","sourceRoot":"","sources":["../src/repairMetaYears.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ interface SyncMetaResult {
3
+ updated: number;
4
+ unchanged: number;
5
+ missingLocal: number;
6
+ added: number;
7
+ total: number;
8
+ }
9
+ export declare const syncMetaFromLocal: (configPath?: string) => SyncMetaResult;
10
+ export {};
11
+ //# sourceMappingURL=syncMetaFromLocal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncMetaFromLocal.d.ts","sourceRoot":"","sources":["../src/syncMetaFromLocal.ts"],"names":[],"mappings":";AAQA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAuED,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,cAkDvD,CAAC"}
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { getConfig, loadConfig } from "./config.js";
5
+ import { normalizeDir } from "./paths.js";
6
+ const shouldSkipDir = (name) => name.startsWith("@") || name === "#recycle";
7
+ const isValidMetadata = (value) => {
8
+ if (!value || typeof value !== "object") {
9
+ return false;
10
+ }
11
+ const meta = value;
12
+ return (typeof meta.fullArtist === "string" &&
13
+ typeof meta.fullAlbum === "string" &&
14
+ typeof meta.genre === "string" &&
15
+ meta.year !== undefined);
16
+ };
17
+ const readLocalMeta = (dirPath) => {
18
+ const backupFile = path.join(dirPath, "meta.json");
19
+ try {
20
+ const parsed = JSON.parse(fs.readFileSync(backupFile, "utf-8"));
21
+ if (isValidMetadata(parsed)) {
22
+ return parsed;
23
+ }
24
+ }
25
+ catch {
26
+ // no local meta.json or invalid contents
27
+ }
28
+ return null;
29
+ };
30
+ const walkLocalMeta = (start, found = new Map()) => {
31
+ const dirPath = normalizeDir(start);
32
+ let entries;
33
+ try {
34
+ entries = fs.readdirSync(dirPath, { withFileTypes: true });
35
+ }
36
+ catch {
37
+ return found;
38
+ }
39
+ const localMeta = readLocalMeta(dirPath);
40
+ if (localMeta) {
41
+ found.set(dirPath, localMeta);
42
+ }
43
+ for (const entry of entries) {
44
+ if (!entry.isDirectory() || shouldSkipDir(entry.name)) {
45
+ continue;
46
+ }
47
+ walkLocalMeta(path.join(dirPath, entry.name), found);
48
+ }
49
+ return found;
50
+ };
51
+ const loadCentralMeta = (metaFile) => {
52
+ try {
53
+ const parsed = JSON.parse(fs.readFileSync(metaFile, "utf-8"));
54
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
55
+ return {};
56
+ }
57
+ return parsed;
58
+ }
59
+ catch {
60
+ return {};
61
+ }
62
+ };
63
+ export const syncMetaFromLocal = (configPath) => {
64
+ loadConfig(configPath ? path.resolve(configPath) : undefined);
65
+ const config = getConfig();
66
+ const central = loadCentralMeta(config.metaFile);
67
+ const localByPath = new Map();
68
+ for (const folder of config.startFolders) {
69
+ walkLocalMeta(folder.path, localByPath);
70
+ }
71
+ let updated = 0;
72
+ let unchanged = 0;
73
+ let missingLocal = 0;
74
+ for (const dirPath of Object.keys(central)) {
75
+ const localMeta = readLocalMeta(dirPath) ?? localByPath.get(normalizeDir(dirPath));
76
+ if (!localMeta) {
77
+ missingLocal++;
78
+ continue;
79
+ }
80
+ if (JSON.stringify(central[dirPath]) === JSON.stringify(localMeta)) {
81
+ unchanged++;
82
+ continue;
83
+ }
84
+ central[dirPath] = localMeta;
85
+ updated++;
86
+ }
87
+ let added = 0;
88
+ for (const [dirPath, localMeta] of localByPath) {
89
+ if (central[dirPath]) {
90
+ continue;
91
+ }
92
+ central[dirPath] = localMeta;
93
+ added++;
94
+ }
95
+ fs.writeFileSync(config.metaFile, JSON.stringify(central, undefined, 2));
96
+ return {
97
+ updated,
98
+ unchanged,
99
+ missingLocal,
100
+ added,
101
+ total: Object.keys(central).length,
102
+ };
103
+ };
104
+ const configArgIndex = process.argv.indexOf("-c");
105
+ const configPath = configArgIndex >= 0 ? process.argv[configArgIndex + 1] : undefined;
106
+ const result = syncMetaFromLocal(configPath);
107
+ console.log(`Synced ${getConfig().metaFile} from local album meta.json files.`);
108
+ console.log(` updated: ${result.updated}`);
109
+ console.log(` unchanged: ${result.unchanged}`);
110
+ console.log(` no local meta: ${result.missingLocal}`);
111
+ console.log(` added: ${result.added}`);
112
+ console.log(` total entries: ${result.total}`);
113
+ //# sourceMappingURL=syncMetaFromLocal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncMetaFromLocal.js","sourceRoot":"","sources":["../src/syncMetaFromLocal.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emgeebee/music_downcoder",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "Scan music libraries and generate ffmpeg conversion scripts with a CLI or web UI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,6 +19,8 @@
19
19
  "list": "find ./cmd/**/*.sh -type f 2>/dev/null | sort -nr",
20
20
  "convert": "./batch.sh",
21
21
  "clean-empty": "tsx src/cleanEmptyFolders.ts -c docker/conf.local.json",
22
+ "sync-meta": "tsx src/syncMetaFromLocal.ts -c docker/conf.local.json",
23
+ "repair-meta-years": "tsx src/repairMetaYears.ts -c docker/conf.local.json",
22
24
  "type-check": "tsc --noEmit"
23
25
  },
24
26
  "dependencies": {