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 +22 -0
- package/README.md +18 -2
- package/dist/package.json +2 -2
- package/dist/src/gerdur.js +10 -3
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.js +78 -67
- package/dist/src/lib/download-track.d.ts +7 -1
- package/dist/src/lib/download-track.js +20 -2
- package/package.json +2 -2
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`, `
|
|
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.
|
|
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.
|
|
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",
|
package/dist/src/gerdur.js
CHANGED
|
@@ -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
|
|
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
|
package/dist/src/index.d.ts
CHANGED
|
@@ -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.
|
|
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
|
|
97
|
-
Object.defineProperty(exports, "initDeezerApi", { enumerable: true, get: function () { return
|
|
98
|
-
Object.defineProperty(exports, "parseInfo", { enumerable: true, get: function () { return
|
|
99
|
-
Object.defineProperty(exports, "searchMusic", { enumerable: true, get: function () { return
|
|
100
|
-
Object.defineProperty(exports, "
|
|
101
|
-
Object.defineProperty(exports, "
|
|
102
|
-
Object.defineProperty(exports, "
|
|
103
|
-
Object.defineProperty(exports, "
|
|
104
|
-
Object.defineProperty(exports, "
|
|
105
|
-
Object.defineProperty(exports, "
|
|
106
|
-
Object.defineProperty(exports, "
|
|
107
|
-
Object.defineProperty(exports, "
|
|
108
|
-
Object.defineProperty(exports, "
|
|
109
|
-
Object.defineProperty(exports, "
|
|
110
|
-
Object.defineProperty(exports, "
|
|
111
|
-
Object.defineProperty(exports, "
|
|
112
|
-
Object.defineProperty(exports, "
|
|
113
|
-
Object.defineProperty(exports, "
|
|
114
|
-
Object.defineProperty(exports, "
|
|
115
|
-
Object.defineProperty(exports, "
|
|
116
|
-
Object.defineProperty(exports, "
|
|
117
|
-
Object.defineProperty(exports, "
|
|
118
|
-
Object.defineProperty(exports, "
|
|
119
|
-
Object.defineProperty(exports, "
|
|
120
|
-
Object.defineProperty(exports, "
|
|
121
|
-
Object.defineProperty(exports, "
|
|
122
|
-
Object.defineProperty(exports, "
|
|
123
|
-
Object.defineProperty(exports, "
|
|
124
|
-
Object.defineProperty(exports, "
|
|
125
|
-
Object.defineProperty(exports, "
|
|
126
|
-
Object.defineProperty(exports, "
|
|
127
|
-
Object.defineProperty(exports, "
|
|
128
|
-
Object.defineProperty(exports, "
|
|
129
|
-
Object.defineProperty(exports, "
|
|
130
|
-
Object.defineProperty(exports, "
|
|
131
|
-
Object.defineProperty(exports, "
|
|
132
|
-
Object.defineProperty(exports, "
|
|
133
|
-
Object.defineProperty(exports, "
|
|
134
|
-
Object.defineProperty(exports, "
|
|
135
|
-
Object.defineProperty(exports, "
|
|
136
|
-
Object.defineProperty(exports, "
|
|
137
|
-
Object.defineProperty(exports, "
|
|
138
|
-
Object.defineProperty(exports, "
|
|
139
|
-
Object.defineProperty(exports, "
|
|
140
|
-
Object.defineProperty(exports, "
|
|
141
|
-
Object.defineProperty(exports, "
|
|
142
|
-
Object.defineProperty(exports, "
|
|
143
|
-
Object.defineProperty(exports, "
|
|
144
|
-
Object.defineProperty(exports, "
|
|
145
|
-
Object.defineProperty(exports, "
|
|
146
|
-
Object.defineProperty(exports, "
|
|
147
|
-
Object.defineProperty(exports, "
|
|
148
|
-
Object.defineProperty(exports, "
|
|
149
|
-
Object.defineProperty(exports, "
|
|
150
|
-
Object.defineProperty(exports, "
|
|
151
|
-
Object.defineProperty(exports, "
|
|
152
|
-
Object.defineProperty(exports, "
|
|
153
|
-
Object.defineProperty(exports, "
|
|
154
|
-
Object.defineProperty(exports, "
|
|
155
|
-
Object.defineProperty(exports, "
|
|
156
|
-
Object.defineProperty(exports, "
|
|
157
|
-
Object.defineProperty(exports, "
|
|
158
|
-
Object.defineProperty(exports, "
|
|
159
|
-
Object.defineProperty(exports, "
|
|
160
|
-
Object.defineProperty(exports, "
|
|
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, {
|
|
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.
|
|
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.
|
|
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",
|