gerdur 2.8.0 → 2.10.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/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.10.0 - 2026-08-31
4
+
5
+ ### Added
6
+
7
+ - **`gerdur-core@^2.12.0`** — re-exports the optional read-only enrichment layer:
8
+ `lookupRecordingByISRC`, `getMusicBrainzRecording` / `getMusicBrainzRelease`,
9
+ `getCoverArt` / `getBestCoverArtUrl`, `configureMusicBrainz`, `PoliteJsonClient`.
10
+ - **`--enrich`** — during a download, look the track's ISRC up on MusicBrainz and
11
+ embed a higher-resolution front cover from the Cover Art Archive instead of
12
+ Deezer's (which caps at 1800 px). Falls back silently to Deezer's cover when
13
+ there's no match or the services are unavailable.
14
+
15
+ ## 2.9.0 - 2026-08-31
16
+
17
+ ### Added
18
+
19
+ - **`gerdur-core@^2.11.0`** — re-exports `searchFacets` (per-type hit counts +
20
+ Deezer's relevance `ORDER` from a `searchMusic` result).
21
+ - Plain-text search in the interactive prompt now shows a hint — *"also N albums
22
+ · M artists · P playlists (prefix with `album:` / `artist:` / `playlist:` …)"* —
23
+ so you know the other result types are there.
24
+
3
25
  ## 2.8.0 - 2026-08-31
4
26
 
5
27
  ### Added
package/README.md CHANGED
@@ -143,6 +143,7 @@ All options are optional. You can suppress prompts via providing `quality` and `
143
143
  | `--dur-min` / `--dur-max` | *None* | number (seconds) | Search filter — track duration range |
144
144
  | `--search-limit` | *None* | number (default 50) | How many search results to fetch |
145
145
  | `--preview` | *None* | *Nothing* | Download the 30-second preview clips (`.preview.mp3`) instead of full tracks — no `--quality` needed |
146
+ | `--enrich` | *None* | *Nothing* | Embed a higher-res front cover from the Cover Art Archive (looked up by ISRC via MusicBrainz); falls back to Deezer's cover |
146
147
 
147
148
  ## Search
148
149
 
@@ -217,6 +218,21 @@ gerdur --preview -u https://deezer.com/album/302127 # 14 clips
217
218
  gerdur -d --preview --artist "Justice" --search-limit 10 # audition a search
218
219
  ```
219
220
 
221
+ ## Better cover art (`--enrich`)
222
+
223
+ `--enrich` looks each track's ISRC up on MusicBrainz, finds its release-group,
224
+ and embeds the front cover from the [Cover Art Archive](https://coverartarchive.org)
225
+ instead of Deezer's (which is capped at 1800 px). No match, or the services are
226
+ down? It silently keeps Deezer's cover.
227
+
228
+ ```bash
229
+ gerdur --enrich -q flac -u https://deezer.com/album/302127
230
+ ```
231
+
232
+ The enrichment functions (`lookupRecordingByISRC`, `getBestCoverArtUrl`, …) are
233
+ also re-exported for programmatic use. Read-only, off by default, and
234
+ `gerdur-core` never wires them into tagging on its own.
235
+
220
236
  ## Programmatic API
221
237
 
222
238
  When installed as a dependency, `gerdur` exposes a side-effect-free API
@@ -321,8 +337,8 @@ or `createSession`):
321
337
  - **Query** — `parseInfo`, `getUser`, `getTrackInfo`, `getAlbumInfo`,
322
338
  `getAlbumTracks`, `getPlaylistInfo`, `getPlaylistTracks`, `getArtistInfo`,
323
339
  `getDiscography`, `getLyrics`
324
- - **Search** — `searchMusic`, `searchPublicApi`, `searchTracks`, `searchAlbums`,
325
- `searchArtists`, `searchPlaylists`, `buildAdvancedQuery`, `suggest`
340
+ - **Search** — `searchMusic`, `searchFacets`, `searchPublicApi`, `searchTracks`,
341
+ `searchAlbums`, `searchArtists`, `searchPlaylists`, `buildAdvancedQuery`, `suggest`
326
342
  - **Browse** — `getGenres`, `getChart`, `getChartTracks`, `getGenreArtists`,
327
343
  `getEditorialList`, `getEditorialReleases`, `getEditorialSelection`,
328
344
  `getEditorialCharts`, `getArtistTopTracks`, `getRelatedArtists`,
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "description": "The crucial streaming module for dabox systems.",
5
5
  "author": "Christian",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -48,7 +48,7 @@
48
48
  "adm-zip": "^0.5.16",
49
49
  "chalk": "^4.1.2",
50
50
  "commander": "^9.5.0",
51
- "gerdur-core": "^2.10.0",
51
+ "gerdur-core": "^2.12.0",
52
52
  "dot-prop": "^6.0.1",
53
53
  "got": "^11.8.6",
54
54
  "gradient-string": "^2.0.2",
@@ -59,7 +59,8 @@ const cmd = new commander_1.Command()
59
59
  .option('--dur-min <seconds>', 'Search filter: minimum duration')
60
60
  .option('--dur-max <seconds>', 'Search filter: maximum duration')
61
61
  .option('--search-limit <n>', 'Max search results to fetch', '50')
62
- .option('--preview', 'Download the 30-second preview clips instead of full tracks', false);
62
+ .option('--preview', 'Download the 30-second preview clips instead of full tracks', false)
63
+ .option('--enrich', 'Embed a higher-res cover from the Cover Art Archive (looked up by ISRC)', false);
63
64
  if (process.pkg) {
64
65
  cmd.option('-U, --update', 'Update this program to latest version');
65
66
  }
@@ -377,12 +378,17 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
377
378
  url = `https://deezer.com/us/playlist/${choice.items.PLAYLIST_ID}`;
378
379
  }
379
380
  else {
380
- const { TRACK } = await (0, gerdur_core_1.searchMusic)(url, ['TRACK']);
381
+ const result = await (0, gerdur_core_1.searchMusic)(url, ['TRACK', 'ALBUM', 'ARTIST', 'PLAYLIST']);
382
+ const facets = (0, gerdur_core_1.searchFacets)(result);
383
+ if (facets.album || facets.artist || facets.playlist) {
384
+ console.log(signale_1.default.note(`also ${facets.album} albums · ${facets.artist} artists · ${facets.playlist} playlists ` +
385
+ `(prefix with album: / artist: / playlist: to pick those)`));
386
+ }
381
387
  searchData = {
382
388
  info: { type: 'track', id: url },
383
389
  linktype: 'track',
384
390
  linkinfo: {},
385
- tracks: TRACK.data.map(stampVersion),
391
+ tracks: result.TRACK.data.map(stampVersion),
386
392
  };
387
393
  }
388
394
  }
@@ -479,6 +485,7 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
479
485
  overwrite,
480
486
  message: `(${index}/${data.tracks.length})`,
481
487
  lrc,
488
+ enrich: Boolean(options.enrich),
482
489
  prefetched: prefetchedUrls.get(track.SNG_ID) ?? null,
483
490
  });
484
491
  // Add to saved list
@@ -57,11 +57,13 @@ export declare const getArl: (email: string, password: string) => Promise<string
57
57
  export { createSession, Session } from './lib/session';
58
58
  export type { SessionOptions, DownloadTracksOptions, SearchType } from './lib/session';
59
59
  export { createSession as createCoreSession, Session as CoreSession, defaultSession } from 'gerdur-core';
60
- export type { SessionUserData } from 'gerdur-core';
60
+ export type { SessionUserData, SearchFacets } from 'gerdur-core';
61
+ export { configureMusicBrainz, lookupRecordingByISRC, getMusicBrainzRecording, getMusicBrainzRelease, getCoverArt, getBestCoverArtUrl, PoliteJsonClient, } from 'gerdur-core';
62
+ export type { MBRecording, MBRelease, MBArtistCredit, CoverArt, CoverArtImage } from 'gerdur-core';
61
63
  export { getTrackBuffer, getTaggedTrack, downloadTrackToFile } from './lib/api-download';
62
64
  export type { Quality, GetTrackBufferOptions, DownloadTrackOptions, DownloadResult } from './lib/api-download';
63
65
  export { default as Config, globalConfigPath, resolveConfigFile } from './lib/config';
64
- export { initDeezerApi, parseInfo, searchMusic, searchPublicApi, searchTracks, searchAlbums, searchArtists, searchPlaylists, buildAdvancedQuery, suggest, getGenres, getChart, getChartTracks, getGenreArtists, getEditorialList, getEditorialReleases, getEditorialSelection, getEditorialCharts, getArtistTopTracks, getRelatedArtists, getArtistAlbums, getArtistPlaylists, getArtistRadioTracks, getUserFlow, getUserFavoriteTracks, getUserFavoriteAlbums, getUserFavoriteArtists, getUserPlaylists, getUserRadios, getUserChartTracks, getRadios, getRadioTracks, getRadioGenres, getEpisode, getShowEpisodes, refreshTrackTokens, getTrackByISRC, getAlbumByUPC, getTrackPreview, downloadPreview, formatName, toFormat, DEEZER_FORMATS, getUser, getTrackInfo, getAlbumInfo, getAlbumTracks, getPlaylistInfo, getPlaylistTracks, getArtistInfo, getDiscography, getLyrics, getTrackDownloadUrl, resolveDownloadUrls, streamTrackDownload, downloadTrackBuffer, createDecryptStream, getStream, addTrackTags, getRichAlbum, normalizeContributors, toLrc, GeoBlocked, DeezerError, } from 'gerdur-core';
66
+ export { initDeezerApi, parseInfo, searchMusic, searchFacets, searchPublicApi, searchTracks, searchAlbums, searchArtists, searchPlaylists, buildAdvancedQuery, suggest, getGenres, getChart, getChartTracks, getGenreArtists, getEditorialList, getEditorialReleases, getEditorialSelection, getEditorialCharts, getArtistTopTracks, getRelatedArtists, getArtistAlbums, getArtistPlaylists, getArtistRadioTracks, getUserFlow, getUserFavoriteTracks, getUserFavoriteAlbums, getUserFavoriteArtists, getUserPlaylists, getUserRadios, getUserChartTracks, getRadios, getRadioTracks, getRadioGenres, getEpisode, getShowEpisodes, refreshTrackTokens, getTrackByISRC, getAlbumByUPC, getTrackPreview, downloadPreview, formatName, toFormat, DEEZER_FORMATS, getUser, getTrackInfo, getAlbumInfo, getAlbumTracks, getPlaylistInfo, getPlaylistTracks, getArtistInfo, getDiscography, getLyrics, getTrackDownloadUrl, resolveDownloadUrls, streamTrackDownload, downloadTrackBuffer, createDecryptStream, getStream, addTrackTags, getRichAlbum, normalizeContributors, toLrc, GeoBlocked, DeezerError, } from 'gerdur-core';
65
67
  export type { AddTrackTagsOptions, TaggedTrack, TrackTagModel, RichAlbum, ResolvedUrl, NormalizedContributors, } from 'gerdur-core';
66
68
  export type { advancedSearchFilters, searchOrder, searchEntity, publicApiSearchOptions, publicApiSearchResponse, searchResultTrack, searchResultAlbum, searchResultArtist, searchResultPlaylist, suggestResult, publicApiList, chartType, chartTrack, chartAlbum, chartArtist, chartPlaylist, chartPodcast, genreType, editorialType, artistAlbumResult, userFavoriteTrack, userFavoriteAlbum, userFavoriteArtist, userPlaylistResult, radioResult, radioGenre, } from 'gerdur-core/types';
67
69
  export type { Quality as MediaFormat, DeezerFormat, TrackPreview, StreamTrackOptions, TrackStream, StreamResponse, DeezerErrorPayload, } from 'gerdur-core';
package/dist/src/index.js CHANGED
@@ -33,8 +33,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.refreshTrackTokens = exports.getShowEpisodes = exports.getEpisode = exports.getRadioGenres = exports.getRadioTracks = exports.getRadios = exports.getUserChartTracks = exports.getUserRadios = exports.getUserPlaylists = exports.getUserFavoriteArtists = exports.getUserFavoriteAlbums = exports.getUserFavoriteTracks = exports.getUserFlow = exports.getArtistRadioTracks = exports.getArtistPlaylists = exports.getArtistAlbums = exports.getRelatedArtists = exports.getArtistTopTracks = exports.getEditorialCharts = exports.getEditorialSelection = exports.getEditorialReleases = exports.getEditorialList = exports.getGenreArtists = exports.getChartTracks = exports.getChart = exports.getGenres = exports.suggest = exports.buildAdvancedQuery = exports.searchPlaylists = exports.searchArtists = exports.searchAlbums = exports.searchTracks = exports.searchPublicApi = exports.searchMusic = exports.parseInfo = exports.initDeezerApi = exports.resolveConfigFile = exports.globalConfigPath = exports.Config = exports.downloadTrackToFile = exports.getTaggedTrack = exports.getTrackBuffer = exports.defaultSession = exports.CoreSession = exports.createCoreSession = exports.Session = exports.createSession = exports.getArl = exports.LoginError = exports.loginWithEmail = void 0;
37
- exports.DeezerError = exports.GeoBlocked = exports.toLrc = exports.normalizeContributors = exports.getRichAlbum = exports.addTrackTags = exports.getStream = exports.createDecryptStream = exports.downloadTrackBuffer = exports.streamTrackDownload = exports.resolveDownloadUrls = exports.getTrackDownloadUrl = exports.getLyrics = exports.getDiscography = exports.getArtistInfo = exports.getPlaylistTracks = exports.getPlaylistInfo = exports.getAlbumTracks = exports.getAlbumInfo = exports.getTrackInfo = exports.getUser = exports.DEEZER_FORMATS = exports.toFormat = exports.formatName = exports.downloadPreview = exports.getTrackPreview = exports.getAlbumByUPC = exports.getTrackByISRC = void 0;
36
+ exports.getUserPlaylists = exports.getUserFavoriteArtists = exports.getUserFavoriteAlbums = exports.getUserFavoriteTracks = exports.getUserFlow = exports.getArtistRadioTracks = exports.getArtistPlaylists = exports.getArtistAlbums = exports.getRelatedArtists = exports.getArtistTopTracks = exports.getEditorialCharts = exports.getEditorialSelection = exports.getEditorialReleases = exports.getEditorialList = exports.getGenreArtists = exports.getChartTracks = exports.getChart = exports.getGenres = exports.suggest = exports.buildAdvancedQuery = exports.searchPlaylists = exports.searchArtists = exports.searchAlbums = exports.searchTracks = exports.searchPublicApi = exports.searchFacets = exports.searchMusic = exports.parseInfo = exports.initDeezerApi = exports.resolveConfigFile = exports.globalConfigPath = exports.Config = exports.downloadTrackToFile = exports.getTaggedTrack = exports.getTrackBuffer = exports.PoliteJsonClient = exports.getBestCoverArtUrl = exports.getCoverArt = exports.getMusicBrainzRelease = exports.getMusicBrainzRecording = exports.lookupRecordingByISRC = exports.configureMusicBrainz = exports.defaultSession = exports.CoreSession = exports.createCoreSession = exports.Session = exports.createSession = exports.getArl = exports.LoginError = exports.loginWithEmail = void 0;
37
+ exports.DeezerError = exports.GeoBlocked = exports.toLrc = exports.normalizeContributors = exports.getRichAlbum = exports.addTrackTags = exports.getStream = exports.createDecryptStream = exports.downloadTrackBuffer = exports.streamTrackDownload = exports.resolveDownloadUrls = exports.getTrackDownloadUrl = exports.getLyrics = exports.getDiscography = exports.getArtistInfo = exports.getPlaylistTracks = exports.getPlaylistInfo = exports.getAlbumTracks = exports.getAlbumInfo = exports.getTrackInfo = exports.getUser = exports.DEEZER_FORMATS = exports.toFormat = exports.formatName = exports.downloadPreview = exports.getTrackPreview = exports.getAlbumByUPC = exports.getTrackByISRC = exports.refreshTrackTokens = exports.getShowEpisodes = exports.getEpisode = exports.getRadioGenres = exports.getRadioTracks = exports.getRadios = exports.getUserChartTracks = exports.getUserRadios = void 0;
38
38
  // ─── Authentication ────────────────────────────────────────────────────────
39
39
  const email_login_1 = require("./lib/email-login");
40
40
  Object.defineProperty(exports, "loginWithEmail", { enumerable: true, get: function () { return email_login_1.loginWithEmail; } });
@@ -79,6 +79,16 @@ var gerdur_core_1 = require("gerdur-core");
79
79
  Object.defineProperty(exports, "createCoreSession", { enumerable: true, get: function () { return gerdur_core_1.createSession; } });
80
80
  Object.defineProperty(exports, "CoreSession", { enumerable: true, get: function () { return gerdur_core_1.Session; } });
81
81
  Object.defineProperty(exports, "defaultSession", { enumerable: true, get: function () { return gerdur_core_1.defaultSession; } });
82
+ // Optional, read-only enrichment against open databases (MusicBrainz, Cover Art
83
+ // Archive). Off by default; `--enrich` on the CLI uses it for hi-res covers.
84
+ var gerdur_core_2 = require("gerdur-core");
85
+ Object.defineProperty(exports, "configureMusicBrainz", { enumerable: true, get: function () { return gerdur_core_2.configureMusicBrainz; } });
86
+ Object.defineProperty(exports, "lookupRecordingByISRC", { enumerable: true, get: function () { return gerdur_core_2.lookupRecordingByISRC; } });
87
+ Object.defineProperty(exports, "getMusicBrainzRecording", { enumerable: true, get: function () { return gerdur_core_2.getMusicBrainzRecording; } });
88
+ Object.defineProperty(exports, "getMusicBrainzRelease", { enumerable: true, get: function () { return gerdur_core_2.getMusicBrainzRelease; } });
89
+ Object.defineProperty(exports, "getCoverArt", { enumerable: true, get: function () { return gerdur_core_2.getCoverArt; } });
90
+ Object.defineProperty(exports, "getBestCoverArtUrl", { enumerable: true, get: function () { return gerdur_core_2.getBestCoverArtUrl; } });
91
+ Object.defineProperty(exports, "PoliteJsonClient", { enumerable: true, get: function () { return gerdur_core_2.PoliteJsonClient; } });
82
92
  // ─── Download primitives ─────────────────────────────────────────────────────
83
93
  var api_download_1 = require("./lib/api-download");
84
94
  Object.defineProperty(exports, "getTrackBuffer", { enumerable: true, get: function () { return api_download_1.getTrackBuffer; } });
@@ -93,68 +103,69 @@ Object.defineProperty(exports, "resolveConfigFile", { enumerable: true, get: fun
93
103
  // ─── Re-exported core query functions ────────────────────────────────────────
94
104
  // Convenience re-exports so consumers don't need `gerdur-core` directly.
95
105
  // After `initDeezerApi(arl)` (or `createSession`) these are ready to use.
96
- var gerdur_core_2 = require("gerdur-core");
97
- Object.defineProperty(exports, "initDeezerApi", { enumerable: true, get: function () { return gerdur_core_2.initDeezerApi; } });
98
- Object.defineProperty(exports, "parseInfo", { enumerable: true, get: function () { return gerdur_core_2.parseInfo; } });
99
- Object.defineProperty(exports, "searchMusic", { enumerable: true, get: function () { return gerdur_core_2.searchMusic; } });
100
- Object.defineProperty(exports, "searchPublicApi", { enumerable: true, get: function () { return gerdur_core_2.searchPublicApi; } });
101
- Object.defineProperty(exports, "searchTracks", { enumerable: true, get: function () { return gerdur_core_2.searchTracks; } });
102
- Object.defineProperty(exports, "searchAlbums", { enumerable: true, get: function () { return gerdur_core_2.searchAlbums; } });
103
- Object.defineProperty(exports, "searchArtists", { enumerable: true, get: function () { return gerdur_core_2.searchArtists; } });
104
- Object.defineProperty(exports, "searchPlaylists", { enumerable: true, get: function () { return gerdur_core_2.searchPlaylists; } });
105
- Object.defineProperty(exports, "buildAdvancedQuery", { enumerable: true, get: function () { return gerdur_core_2.buildAdvancedQuery; } });
106
- Object.defineProperty(exports, "suggest", { enumerable: true, get: function () { return gerdur_core_2.suggest; } });
107
- Object.defineProperty(exports, "getGenres", { enumerable: true, get: function () { return gerdur_core_2.getGenres; } });
108
- Object.defineProperty(exports, "getChart", { enumerable: true, get: function () { return gerdur_core_2.getChart; } });
109
- Object.defineProperty(exports, "getChartTracks", { enumerable: true, get: function () { return gerdur_core_2.getChartTracks; } });
110
- Object.defineProperty(exports, "getGenreArtists", { enumerable: true, get: function () { return gerdur_core_2.getGenreArtists; } });
111
- Object.defineProperty(exports, "getEditorialList", { enumerable: true, get: function () { return gerdur_core_2.getEditorialList; } });
112
- Object.defineProperty(exports, "getEditorialReleases", { enumerable: true, get: function () { return gerdur_core_2.getEditorialReleases; } });
113
- Object.defineProperty(exports, "getEditorialSelection", { enumerable: true, get: function () { return gerdur_core_2.getEditorialSelection; } });
114
- Object.defineProperty(exports, "getEditorialCharts", { enumerable: true, get: function () { return gerdur_core_2.getEditorialCharts; } });
115
- Object.defineProperty(exports, "getArtistTopTracks", { enumerable: true, get: function () { return gerdur_core_2.getArtistTopTracks; } });
116
- Object.defineProperty(exports, "getRelatedArtists", { enumerable: true, get: function () { return gerdur_core_2.getRelatedArtists; } });
117
- Object.defineProperty(exports, "getArtistAlbums", { enumerable: true, get: function () { return gerdur_core_2.getArtistAlbums; } });
118
- Object.defineProperty(exports, "getArtistPlaylists", { enumerable: true, get: function () { return gerdur_core_2.getArtistPlaylists; } });
119
- Object.defineProperty(exports, "getArtistRadioTracks", { enumerable: true, get: function () { return gerdur_core_2.getArtistRadioTracks; } });
120
- Object.defineProperty(exports, "getUserFlow", { enumerable: true, get: function () { return gerdur_core_2.getUserFlow; } });
121
- Object.defineProperty(exports, "getUserFavoriteTracks", { enumerable: true, get: function () { return gerdur_core_2.getUserFavoriteTracks; } });
122
- Object.defineProperty(exports, "getUserFavoriteAlbums", { enumerable: true, get: function () { return gerdur_core_2.getUserFavoriteAlbums; } });
123
- Object.defineProperty(exports, "getUserFavoriteArtists", { enumerable: true, get: function () { return gerdur_core_2.getUserFavoriteArtists; } });
124
- Object.defineProperty(exports, "getUserPlaylists", { enumerable: true, get: function () { return gerdur_core_2.getUserPlaylists; } });
125
- Object.defineProperty(exports, "getUserRadios", { enumerable: true, get: function () { return gerdur_core_2.getUserRadios; } });
126
- Object.defineProperty(exports, "getUserChartTracks", { enumerable: true, get: function () { return gerdur_core_2.getUserChartTracks; } });
127
- Object.defineProperty(exports, "getRadios", { enumerable: true, get: function () { return gerdur_core_2.getRadios; } });
128
- Object.defineProperty(exports, "getRadioTracks", { enumerable: true, get: function () { return gerdur_core_2.getRadioTracks; } });
129
- Object.defineProperty(exports, "getRadioGenres", { enumerable: true, get: function () { return gerdur_core_2.getRadioGenres; } });
130
- Object.defineProperty(exports, "getEpisode", { enumerable: true, get: function () { return gerdur_core_2.getEpisode; } });
131
- Object.defineProperty(exports, "getShowEpisodes", { enumerable: true, get: function () { return gerdur_core_2.getShowEpisodes; } });
132
- Object.defineProperty(exports, "refreshTrackTokens", { enumerable: true, get: function () { return gerdur_core_2.refreshTrackTokens; } });
133
- Object.defineProperty(exports, "getTrackByISRC", { enumerable: true, get: function () { return gerdur_core_2.getTrackByISRC; } });
134
- Object.defineProperty(exports, "getAlbumByUPC", { enumerable: true, get: function () { return gerdur_core_2.getAlbumByUPC; } });
135
- Object.defineProperty(exports, "getTrackPreview", { enumerable: true, get: function () { return gerdur_core_2.getTrackPreview; } });
136
- Object.defineProperty(exports, "downloadPreview", { enumerable: true, get: function () { return gerdur_core_2.downloadPreview; } });
137
- Object.defineProperty(exports, "formatName", { enumerable: true, get: function () { return gerdur_core_2.formatName; } });
138
- Object.defineProperty(exports, "toFormat", { enumerable: true, get: function () { return gerdur_core_2.toFormat; } });
139
- Object.defineProperty(exports, "DEEZER_FORMATS", { enumerable: true, get: function () { return gerdur_core_2.DEEZER_FORMATS; } });
140
- Object.defineProperty(exports, "getUser", { enumerable: true, get: function () { return gerdur_core_2.getUser; } });
141
- Object.defineProperty(exports, "getTrackInfo", { enumerable: true, get: function () { return gerdur_core_2.getTrackInfo; } });
142
- Object.defineProperty(exports, "getAlbumInfo", { enumerable: true, get: function () { return gerdur_core_2.getAlbumInfo; } });
143
- Object.defineProperty(exports, "getAlbumTracks", { enumerable: true, get: function () { return gerdur_core_2.getAlbumTracks; } });
144
- Object.defineProperty(exports, "getPlaylistInfo", { enumerable: true, get: function () { return gerdur_core_2.getPlaylistInfo; } });
145
- Object.defineProperty(exports, "getPlaylistTracks", { enumerable: true, get: function () { return gerdur_core_2.getPlaylistTracks; } });
146
- Object.defineProperty(exports, "getArtistInfo", { enumerable: true, get: function () { return gerdur_core_2.getArtistInfo; } });
147
- Object.defineProperty(exports, "getDiscography", { enumerable: true, get: function () { return gerdur_core_2.getDiscography; } });
148
- Object.defineProperty(exports, "getLyrics", { enumerable: true, get: function () { return gerdur_core_2.getLyrics; } });
149
- Object.defineProperty(exports, "getTrackDownloadUrl", { enumerable: true, get: function () { return gerdur_core_2.getTrackDownloadUrl; } });
150
- Object.defineProperty(exports, "resolveDownloadUrls", { enumerable: true, get: function () { return gerdur_core_2.resolveDownloadUrls; } });
151
- Object.defineProperty(exports, "streamTrackDownload", { enumerable: true, get: function () { return gerdur_core_2.streamTrackDownload; } });
152
- Object.defineProperty(exports, "downloadTrackBuffer", { enumerable: true, get: function () { return gerdur_core_2.downloadTrackBuffer; } });
153
- Object.defineProperty(exports, "createDecryptStream", { enumerable: true, get: function () { return gerdur_core_2.createDecryptStream; } });
154
- Object.defineProperty(exports, "getStream", { enumerable: true, get: function () { return gerdur_core_2.getStream; } });
155
- Object.defineProperty(exports, "addTrackTags", { enumerable: true, get: function () { return gerdur_core_2.addTrackTags; } });
156
- Object.defineProperty(exports, "getRichAlbum", { enumerable: true, get: function () { return gerdur_core_2.getRichAlbum; } });
157
- Object.defineProperty(exports, "normalizeContributors", { enumerable: true, get: function () { return gerdur_core_2.normalizeContributors; } });
158
- Object.defineProperty(exports, "toLrc", { enumerable: true, get: function () { return gerdur_core_2.toLrc; } });
159
- Object.defineProperty(exports, "GeoBlocked", { enumerable: true, get: function () { return gerdur_core_2.GeoBlocked; } });
160
- Object.defineProperty(exports, "DeezerError", { enumerable: true, get: function () { return gerdur_core_2.DeezerError; } });
106
+ var gerdur_core_3 = require("gerdur-core");
107
+ Object.defineProperty(exports, "initDeezerApi", { enumerable: true, get: function () { return gerdur_core_3.initDeezerApi; } });
108
+ Object.defineProperty(exports, "parseInfo", { enumerable: true, get: function () { return gerdur_core_3.parseInfo; } });
109
+ Object.defineProperty(exports, "searchMusic", { enumerable: true, get: function () { return gerdur_core_3.searchMusic; } });
110
+ Object.defineProperty(exports, "searchFacets", { enumerable: true, get: function () { return gerdur_core_3.searchFacets; } });
111
+ Object.defineProperty(exports, "searchPublicApi", { enumerable: true, get: function () { return gerdur_core_3.searchPublicApi; } });
112
+ Object.defineProperty(exports, "searchTracks", { enumerable: true, get: function () { return gerdur_core_3.searchTracks; } });
113
+ Object.defineProperty(exports, "searchAlbums", { enumerable: true, get: function () { return gerdur_core_3.searchAlbums; } });
114
+ Object.defineProperty(exports, "searchArtists", { enumerable: true, get: function () { return gerdur_core_3.searchArtists; } });
115
+ Object.defineProperty(exports, "searchPlaylists", { enumerable: true, get: function () { return gerdur_core_3.searchPlaylists; } });
116
+ Object.defineProperty(exports, "buildAdvancedQuery", { enumerable: true, get: function () { return gerdur_core_3.buildAdvancedQuery; } });
117
+ Object.defineProperty(exports, "suggest", { enumerable: true, get: function () { return gerdur_core_3.suggest; } });
118
+ Object.defineProperty(exports, "getGenres", { enumerable: true, get: function () { return gerdur_core_3.getGenres; } });
119
+ Object.defineProperty(exports, "getChart", { enumerable: true, get: function () { return gerdur_core_3.getChart; } });
120
+ Object.defineProperty(exports, "getChartTracks", { enumerable: true, get: function () { return gerdur_core_3.getChartTracks; } });
121
+ Object.defineProperty(exports, "getGenreArtists", { enumerable: true, get: function () { return gerdur_core_3.getGenreArtists; } });
122
+ Object.defineProperty(exports, "getEditorialList", { enumerable: true, get: function () { return gerdur_core_3.getEditorialList; } });
123
+ Object.defineProperty(exports, "getEditorialReleases", { enumerable: true, get: function () { return gerdur_core_3.getEditorialReleases; } });
124
+ Object.defineProperty(exports, "getEditorialSelection", { enumerable: true, get: function () { return gerdur_core_3.getEditorialSelection; } });
125
+ Object.defineProperty(exports, "getEditorialCharts", { enumerable: true, get: function () { return gerdur_core_3.getEditorialCharts; } });
126
+ Object.defineProperty(exports, "getArtistTopTracks", { enumerable: true, get: function () { return gerdur_core_3.getArtistTopTracks; } });
127
+ Object.defineProperty(exports, "getRelatedArtists", { enumerable: true, get: function () { return gerdur_core_3.getRelatedArtists; } });
128
+ Object.defineProperty(exports, "getArtistAlbums", { enumerable: true, get: function () { return gerdur_core_3.getArtistAlbums; } });
129
+ Object.defineProperty(exports, "getArtistPlaylists", { enumerable: true, get: function () { return gerdur_core_3.getArtistPlaylists; } });
130
+ Object.defineProperty(exports, "getArtistRadioTracks", { enumerable: true, get: function () { return gerdur_core_3.getArtistRadioTracks; } });
131
+ Object.defineProperty(exports, "getUserFlow", { enumerable: true, get: function () { return gerdur_core_3.getUserFlow; } });
132
+ Object.defineProperty(exports, "getUserFavoriteTracks", { enumerable: true, get: function () { return gerdur_core_3.getUserFavoriteTracks; } });
133
+ Object.defineProperty(exports, "getUserFavoriteAlbums", { enumerable: true, get: function () { return gerdur_core_3.getUserFavoriteAlbums; } });
134
+ Object.defineProperty(exports, "getUserFavoriteArtists", { enumerable: true, get: function () { return gerdur_core_3.getUserFavoriteArtists; } });
135
+ Object.defineProperty(exports, "getUserPlaylists", { enumerable: true, get: function () { return gerdur_core_3.getUserPlaylists; } });
136
+ Object.defineProperty(exports, "getUserRadios", { enumerable: true, get: function () { return gerdur_core_3.getUserRadios; } });
137
+ Object.defineProperty(exports, "getUserChartTracks", { enumerable: true, get: function () { return gerdur_core_3.getUserChartTracks; } });
138
+ Object.defineProperty(exports, "getRadios", { enumerable: true, get: function () { return gerdur_core_3.getRadios; } });
139
+ Object.defineProperty(exports, "getRadioTracks", { enumerable: true, get: function () { return gerdur_core_3.getRadioTracks; } });
140
+ Object.defineProperty(exports, "getRadioGenres", { enumerable: true, get: function () { return gerdur_core_3.getRadioGenres; } });
141
+ Object.defineProperty(exports, "getEpisode", { enumerable: true, get: function () { return gerdur_core_3.getEpisode; } });
142
+ Object.defineProperty(exports, "getShowEpisodes", { enumerable: true, get: function () { return gerdur_core_3.getShowEpisodes; } });
143
+ Object.defineProperty(exports, "refreshTrackTokens", { enumerable: true, get: function () { return gerdur_core_3.refreshTrackTokens; } });
144
+ Object.defineProperty(exports, "getTrackByISRC", { enumerable: true, get: function () { return gerdur_core_3.getTrackByISRC; } });
145
+ Object.defineProperty(exports, "getAlbumByUPC", { enumerable: true, get: function () { return gerdur_core_3.getAlbumByUPC; } });
146
+ Object.defineProperty(exports, "getTrackPreview", { enumerable: true, get: function () { return gerdur_core_3.getTrackPreview; } });
147
+ Object.defineProperty(exports, "downloadPreview", { enumerable: true, get: function () { return gerdur_core_3.downloadPreview; } });
148
+ Object.defineProperty(exports, "formatName", { enumerable: true, get: function () { return gerdur_core_3.formatName; } });
149
+ Object.defineProperty(exports, "toFormat", { enumerable: true, get: function () { return gerdur_core_3.toFormat; } });
150
+ Object.defineProperty(exports, "DEEZER_FORMATS", { enumerable: true, get: function () { return gerdur_core_3.DEEZER_FORMATS; } });
151
+ Object.defineProperty(exports, "getUser", { enumerable: true, get: function () { return gerdur_core_3.getUser; } });
152
+ Object.defineProperty(exports, "getTrackInfo", { enumerable: true, get: function () { return gerdur_core_3.getTrackInfo; } });
153
+ Object.defineProperty(exports, "getAlbumInfo", { enumerable: true, get: function () { return gerdur_core_3.getAlbumInfo; } });
154
+ Object.defineProperty(exports, "getAlbumTracks", { enumerable: true, get: function () { return gerdur_core_3.getAlbumTracks; } });
155
+ Object.defineProperty(exports, "getPlaylistInfo", { enumerable: true, get: function () { return gerdur_core_3.getPlaylistInfo; } });
156
+ Object.defineProperty(exports, "getPlaylistTracks", { enumerable: true, get: function () { return gerdur_core_3.getPlaylistTracks; } });
157
+ Object.defineProperty(exports, "getArtistInfo", { enumerable: true, get: function () { return gerdur_core_3.getArtistInfo; } });
158
+ Object.defineProperty(exports, "getDiscography", { enumerable: true, get: function () { return gerdur_core_3.getDiscography; } });
159
+ Object.defineProperty(exports, "getLyrics", { enumerable: true, get: function () { return gerdur_core_3.getLyrics; } });
160
+ Object.defineProperty(exports, "getTrackDownloadUrl", { enumerable: true, get: function () { return gerdur_core_3.getTrackDownloadUrl; } });
161
+ Object.defineProperty(exports, "resolveDownloadUrls", { enumerable: true, get: function () { return gerdur_core_3.resolveDownloadUrls; } });
162
+ Object.defineProperty(exports, "streamTrackDownload", { enumerable: true, get: function () { return gerdur_core_3.streamTrackDownload; } });
163
+ Object.defineProperty(exports, "downloadTrackBuffer", { enumerable: true, get: function () { return gerdur_core_3.downloadTrackBuffer; } });
164
+ Object.defineProperty(exports, "createDecryptStream", { enumerable: true, get: function () { return gerdur_core_3.createDecryptStream; } });
165
+ Object.defineProperty(exports, "getStream", { enumerable: true, get: function () { return gerdur_core_3.getStream; } });
166
+ Object.defineProperty(exports, "addTrackTags", { enumerable: true, get: function () { return gerdur_core_3.addTrackTags; } });
167
+ Object.defineProperty(exports, "getRichAlbum", { enumerable: true, get: function () { return gerdur_core_3.getRichAlbum; } });
168
+ Object.defineProperty(exports, "normalizeContributors", { enumerable: true, get: function () { return gerdur_core_3.normalizeContributors; } });
169
+ Object.defineProperty(exports, "toLrc", { enumerable: true, get: function () { return gerdur_core_3.toLrc; } });
170
+ Object.defineProperty(exports, "GeoBlocked", { enumerable: true, get: function () { return gerdur_core_3.GeoBlocked; } });
171
+ Object.defineProperty(exports, "DeezerError", { enumerable: true, get: function () { return gerdur_core_3.DeezerError; } });
@@ -21,6 +21,12 @@ interface downloadTrackProps {
21
21
  message?: string;
22
22
  /** Write a `.lrc` sidecar for tracks with time-synced lyrics. Default true. */
23
23
  lrc?: boolean;
24
+ /**
25
+ * Replace Deezer's cover art with a higher-resolution one from the Cover Art
26
+ * Archive (looked up via the track's ISRC on MusicBrainz). Falls back silently
27
+ * to Deezer's cover if there's no match. Off by default.
28
+ */
29
+ enrich?: boolean;
24
30
  /**
25
31
  * A download URL already resolved for this track by a batch `resolveDownloadUrls`
26
32
  * pass. When set, the per-track `get_url` request and quality-fallback round-trips
@@ -34,5 +40,5 @@ interface downloadTrackProps {
34
40
  format: string;
35
41
  } | null;
36
42
  }
37
- declare const downloadTrack: ({ track, quality, info, coverSizes, path, totalTracks, trackNumber, fallbackTrack, fallbackQuality, isFallback, isQualityFallback, overwrite, message, lrc, prefetched, }: downloadTrackProps) => Promise<string | undefined>;
43
+ declare const downloadTrack: ({ track, quality, info, coverSizes, path, totalTracks, trackNumber, fallbackTrack, fallbackQuality, isFallback, isQualityFallback, overwrite, message, lrc, enrich, prefetched, }: downloadTrackProps) => Promise<string | undefined>;
38
44
  export default downloadTrack;
@@ -18,7 +18,7 @@ const pipeline = (0, util_1.promisify)(stream_1.default.pipeline);
18
18
  const simulate = process.env.SIMULATE;
19
19
  /** media-API format string -> gerdur's numeric quality */
20
20
  const FORMAT_TO_QUALITY = { FLAC: 9, MP3_320: 3, MP3_256: 3, MP3_128: 1, MP3_64: 1 };
21
- const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTracks, trackNumber = true, fallbackTrack = true, fallbackQuality = true, isFallback = false, isQualityFallback = false, overwrite = false, message = '', lrc = true, prefetched = null, }) => {
21
+ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTracks, trackNumber = true, fallbackTrack = true, fallbackQuality = true, isFallback = false, isQualityFallback = false, overwrite = false, message = '', lrc = true, enrich = false, prefetched = null, }) => {
22
22
  (0, log_update_1.default)(signale_1.default.pending(track.SNG_TITLE + ' by ' + track.ART_NAME + ' from ' + track.ALB_TITLE));
23
23
  try {
24
24
  let ext = '.mp3', fileSize = 0, downloaded = 0, coverSize = 500;
@@ -153,8 +153,26 @@ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTrac
153
153
  else {
154
154
  outFile = (0, fs_1.readFileSync)(tmpfile);
155
155
  }
156
+ let enrichedCover;
157
+ if (enrich && track.ISRC && !simulate) {
158
+ try {
159
+ const rec = await (0, gerdur_core_1.lookupRecordingByISRC)(track.ISRC);
160
+ const rgid = rec?.releases.find((r) => r.releaseGroupMbid)?.releaseGroupMbid;
161
+ const coverUrl = rgid ? await (0, gerdur_core_1.getBestCoverArtUrl)(rgid, { minSize: 1200 }) : null;
162
+ if (coverUrl) {
163
+ enrichedCover = await (0, gerdur_core_1.getBuffer)(coverUrl);
164
+ (0, log_update_1.default)(signale_1.default.note(`Using a higher-res cover from the Cover Art Archive for ${track.SNG_TITLE}`));
165
+ }
166
+ }
167
+ catch {
168
+ // MusicBrainz / CAA unavailable or no match — keep Deezer's cover
169
+ }
170
+ }
156
171
  (0, log_update_1.default)(signale_1.default.pending('Tagging ' + track.SNG_TITLE + ' by ' + track.ART_NAME));
157
- const { buffer: trackWithMetadata, model } = await (0, gerdur_core_1.addTrackTags)(outFile, track, { coverSize });
172
+ const { buffer: trackWithMetadata, model } = await (0, gerdur_core_1.addTrackTags)(outFile, track, {
173
+ coverSize,
174
+ ...(enrichedCover ? { cover: enrichedCover } : {}),
175
+ });
158
176
  // Delete temporary file now
159
177
  (0, fs_1.unlinkSync)(tmpfile);
160
178
  (0, log_update_1.default)(signale_1.default.pending('Saving ' + track.SNG_TITLE + ' by ' + track.ART_NAME));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "description": "The crucial streaming module for dabox systems.",
5
5
  "author": "Christian",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -48,7 +48,7 @@
48
48
  "adm-zip": "^0.5.16",
49
49
  "chalk": "^4.1.2",
50
50
  "commander": "^9.5.0",
51
- "gerdur-core": "^2.10.0",
51
+ "gerdur-core": "^2.12.0",
52
52
  "dot-prop": "^6.0.1",
53
53
  "got": "^11.8.6",
54
54
  "gradient-string": "^2.0.2",