gerdur 2.5.0 → 2.7.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 +31 -0
- package/README.md +19 -3
- package/dist/package.json +2 -2
- package/dist/src/gerdur.js +52 -14
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.js +71 -53
- package/dist/src/lib/session.d.ts +20 -1
- package/dist/src/lib/session.js +46 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.7.0 - 2026-08-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`gerdur-core@^2.9.0`** — re-exports `downloadTrackBuffer` (download + decrypt
|
|
8
|
+
to a `Buffer`) and the low-level session client as `createCoreSession` /
|
|
9
|
+
`CoreSession` / `defaultSession` (for talking to Deezer directly or from
|
|
10
|
+
multiple accounts — gerdur's own `Session` stays the download orchestrator).
|
|
11
|
+
- **CLI `chart` / `chart:<genreId>`** — pick tracks from this week's Deezer chart
|
|
12
|
+
(optionally a genre) and download them. Headless-friendly.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Gateway retries are bounded and downloads are session-aware (via
|
|
17
|
+
`gerdur-core@2.4`–`2.9`); `license_token` refreshes proactively.
|
|
18
|
+
|
|
19
|
+
## 2.6.0 - 2026-08-31
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **`gerdur-core@^2.6.0`** — re-exports the Flow / radios / library surface:
|
|
24
|
+
`getUserFlow`, `getUserFavoriteTracks` / `Albums` / `Artists`,
|
|
25
|
+
`getUserPlaylists`, `getUserRadios`, `getUserChartTracks`, `getRadios`,
|
|
26
|
+
`getRadioTracks`, `getRadioGenres` + their types.
|
|
27
|
+
- **`Session` methods**: `flow`, `favoriteTracks`, `favoriteAlbums`,
|
|
28
|
+
`favoriteArtists`, `playlists`, `userRadios`, `radios`, `radioTracks` — the
|
|
29
|
+
`userId` argument defaults to the logged-in user.
|
|
30
|
+
- **CLI `flow` / `flow:<userId>` / `radio:<id>`** — pick tracks from your (or
|
|
31
|
+
another user's) Flow, or a radio's current playlist, and download them.
|
|
32
|
+
Headless-friendly.
|
|
33
|
+
|
|
3
34
|
## 2.5.0 - 2026-08-31
|
|
4
35
|
|
|
5
36
|
### Changed
|
package/README.md
CHANGED
|
@@ -159,8 +159,12 @@ When `gerdur` asks for a URL, a search term, or a prefixed query:
|
|
|
159
159
|
| `search:artist:"daft punk" bpm_min:120` | advanced track search (see operators below) |
|
|
160
160
|
| `isrc:GBDUW0000059` | download the exact track for an ISRC |
|
|
161
161
|
| `upc:0724384960650` | download the album for a UPC / EAN barcode |
|
|
162
|
+
| `flow` | pick tracks from your Deezer **Flow** |
|
|
163
|
+
| `flow:2064440442` | pick tracks from another user's Flow |
|
|
164
|
+
| `radio:38305` | pick tracks from a radio's current playlist |
|
|
165
|
+
| `chart` / `chart:132` | pick tracks from this week's chart (optionally a genre) |
|
|
162
166
|
|
|
163
|
-
`isrc:`
|
|
167
|
+
`isrc:` / `upc:` / `flow` / `radio:` also work in `--headless` mode (`-u flow`, …).
|
|
164
168
|
|
|
165
169
|
### From flags (works headless)
|
|
166
170
|
|
|
@@ -258,6 +262,9 @@ Session methods:
|
|
|
258
262
|
- **browse** — `genres`, `chart`, `chartTracks`, `editorialSections`,
|
|
259
263
|
`artistTopTracks`, `relatedArtists`, `artistAlbums`, `artistRadio`,
|
|
260
264
|
`trackByISRC`, `albumByUPC`
|
|
265
|
+
- **flow / library** — `flow`, `favoriteTracks`, `favoriteAlbums`,
|
|
266
|
+
`favoriteArtists`, `playlists`, `userRadios`, `radios`, `radioTracks`
|
|
267
|
+
(the `userId` arg defaults to the logged-in user)
|
|
261
268
|
- **user / download** — `getUser`, `getTrackBuffer`, `streamTrack`,
|
|
262
269
|
`downloadTrack`, `downloadTracks`, `downloadUrl`, `trackPreview`, `downloadPreview`
|
|
263
270
|
|
|
@@ -319,10 +326,19 @@ or `createSession`):
|
|
|
319
326
|
`getEditorialCharts`, `getArtistTopTracks`, `getRelatedArtists`,
|
|
320
327
|
`getArtistAlbums`, `getArtistPlaylists`, `getArtistRadioTracks`,
|
|
321
328
|
`getTrackByISRC`, `getAlbumByUPC`
|
|
329
|
+
- **Flow / library** — `getUserFlow`, `getUserFavoriteTracks`,
|
|
330
|
+
`getUserFavoriteAlbums`, `getUserFavoriteArtists`, `getUserPlaylists`,
|
|
331
|
+
`getUserRadios`, `getUserChartTracks`, `getRadios`, `getRadioTracks`,
|
|
332
|
+
`getRadioGenres`
|
|
322
333
|
- **Download** — `getTrackDownloadUrl`, `resolveDownloadUrls`,
|
|
323
|
-
`streamTrackDownload`, `
|
|
324
|
-
`downloadPreview`, `formatName`, `toFormat`, `DEEZER_FORMATS`
|
|
334
|
+
`streamTrackDownload`, `downloadTrackBuffer`, `createDecryptStream`, `getStream`,
|
|
335
|
+
`getTrackPreview`, `downloadPreview`, `formatName`, `toFormat`, `DEEZER_FORMATS`
|
|
325
336
|
- **Errors** — `DeezerError` (`code` / `keys` / `retryable`), `GeoBlocked`
|
|
337
|
+
- **Low-level sessions** — `createCoreSession(arl)` / `CoreSession` /
|
|
338
|
+
`defaultSession` from `gerdur-core`: an isolated client (its own `arl`, cache,
|
|
339
|
+
`license_token`) with `getTrackInfo` / `searchMusic` / `getTrackBuffer` / … for
|
|
340
|
+
talking to Deezer directly or from multiple accounts. gerdur's own
|
|
341
|
+
`createSession` / `Session` (above) is the higher-level download orchestrator.
|
|
326
342
|
|
|
327
343
|
### Auth & config helpers
|
|
328
344
|
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gerdur",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.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.9.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
|
@@ -111,18 +111,14 @@ const stampVersion = (t) => {
|
|
|
111
111
|
* picks into download-ready gw tracks via `getTrackInfo`. Returns `null` when
|
|
112
112
|
* nothing was matched or selected.
|
|
113
113
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
console.log(signale_1.default.info(`Searching Deezer for: ${chalk_1.default.cyan(query)}`));
|
|
121
|
-
if (usedFallback) {
|
|
122
|
-
console.log(signale_1.default.note('No matches for the operators — retried as a plain-text search.'));
|
|
123
|
-
}
|
|
114
|
+
/**
|
|
115
|
+
* Given a list of public-API track objects (from search / flow / a radio), let
|
|
116
|
+
* the user pick (unless headless) and hydrate the picks into download-ready gw
|
|
117
|
+
* tracks via `getTrackInfo`.
|
|
118
|
+
*/
|
|
119
|
+
const pickAndHydrate = async (results, id) => {
|
|
124
120
|
if (!results.length) {
|
|
125
|
-
console.log(signale_1.default.warn('
|
|
121
|
+
console.log(signale_1.default.warn('Nothing to download.'));
|
|
126
122
|
return null;
|
|
127
123
|
}
|
|
128
124
|
let picks = results;
|
|
@@ -131,7 +127,7 @@ const resolveAdvancedSearch = async (filters) => {
|
|
|
131
127
|
{
|
|
132
128
|
type: 'multiselect',
|
|
133
129
|
name: 'items',
|
|
134
|
-
message: `Select tracks to download. ${results.length}
|
|
130
|
+
message: `Select tracks to download. ${results.length} available.`,
|
|
135
131
|
choices: results.map((r) => ({
|
|
136
132
|
title: `${r.title} — ${r.artist?.name ?? 'Unknown'}`,
|
|
137
133
|
value: r,
|
|
@@ -151,7 +147,19 @@ const resolveAdvancedSearch = async (filters) => {
|
|
|
151
147
|
console.log(signale_1.default.warn('None of the selected tracks could be resolved.'));
|
|
152
148
|
return null;
|
|
153
149
|
}
|
|
154
|
-
return { info: { type: 'track', id
|
|
150
|
+
return { info: { type: 'track', id }, linktype: 'track', linkinfo: {}, tracks };
|
|
151
|
+
};
|
|
152
|
+
const resolveAdvancedSearch = async (filters) => {
|
|
153
|
+
const limit = toFiniteNumber(options.searchLimit) ?? 50;
|
|
154
|
+
const { data: results, query, usedFallback } = await (0, search_1.searchAdvancedTracks)(filters, { limit });
|
|
155
|
+
if (!query) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
console.log(signale_1.default.info(`Searching Deezer for: ${chalk_1.default.cyan(query)}`));
|
|
159
|
+
if (usedFallback) {
|
|
160
|
+
console.log(signale_1.default.note('No matches for the operators — retried as a plain-text search.'));
|
|
161
|
+
}
|
|
162
|
+
return pickAndHydrate(results, query);
|
|
155
163
|
};
|
|
156
164
|
/**
|
|
157
165
|
* `--preview`: fetch the 30-second clip for each selected track and write it as
|
|
@@ -228,7 +236,7 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
|
|
|
228
236
|
{
|
|
229
237
|
type: 'text',
|
|
230
238
|
name: 'query',
|
|
231
|
-
message: 'Enter a URL, a search term, or
|
|
239
|
+
message: 'Enter a URL, a search term, or `search:` / `isrc:` / `upc:` / `flow` / `radio:<id>` / `chart[:<genre>]`:',
|
|
232
240
|
validate: (value) => (value ? true : false),
|
|
233
241
|
},
|
|
234
242
|
], { onCancel });
|
|
@@ -260,6 +268,36 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
|
|
|
260
268
|
console.log(signale_1.default.info(`UPC ${code} → ${found.title} (${found.nb_tracks} tracks)`));
|
|
261
269
|
url = `https://www.deezer.com/album/${found.id}`;
|
|
262
270
|
}
|
|
271
|
+
// `flow:` / `flow:<userId>` — download from Deezer Flow.
|
|
272
|
+
if (!searchData && url && (url === 'flow' || url.startsWith('flow:'))) {
|
|
273
|
+
const uid = url.includes(':') ? url.slice('flow:'.length).trim() : (await (0, gerdur_core_1.getUser)()).USER_ID;
|
|
274
|
+
console.log(signale_1.default.info(`Fetching Flow for user ${uid}…`));
|
|
275
|
+
const { data } = await (0, gerdur_core_1.getUserFlow)(uid);
|
|
276
|
+
searchData = await pickAndHydrate(data, `flow:${uid}`);
|
|
277
|
+
if (!searchData) {
|
|
278
|
+
throw new Error('Flow returned no tracks (is the profile public?).');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// `radio:<id>` — download a radio's current tracklist.
|
|
282
|
+
if (!searchData && url && url.startsWith('radio:')) {
|
|
283
|
+
const rid = url.slice('radio:'.length).trim();
|
|
284
|
+
console.log(signale_1.default.info(`Fetching radio ${rid}…`));
|
|
285
|
+
const { data } = await (0, gerdur_core_1.getRadioTracks)(rid);
|
|
286
|
+
searchData = await pickAndHydrate(data, `radio:${rid}`);
|
|
287
|
+
if (!searchData) {
|
|
288
|
+
throw new Error(`Radio ${rid} returned no tracks.`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// `chart` / `chart:<genreId>` — download from Deezer's weekly chart.
|
|
292
|
+
if (!searchData && url && (url === 'chart' || url.startsWith('chart:'))) {
|
|
293
|
+
const genreId = url.includes(':') ? url.slice('chart:'.length).trim() : 0;
|
|
294
|
+
console.log(signale_1.default.info(`Fetching chart${genreId ? ` for genre ${genreId}` : ''}…`));
|
|
295
|
+
const { data } = await (0, gerdur_core_1.getChartTracks)(genreId, toFiniteNumber(options.searchLimit) ?? 50);
|
|
296
|
+
searchData = await pickAndHydrate(data, `chart:${genreId}`);
|
|
297
|
+
if (!searchData) {
|
|
298
|
+
throw new Error('Chart returned no tracks.');
|
|
299
|
+
}
|
|
300
|
+
}
|
|
263
301
|
if (!searchData && !url.match(urlRegex)) {
|
|
264
302
|
if (options.headless) {
|
|
265
303
|
throw new Error('Please provide a valid URL. Unknown URL: ' + url);
|
package/dist/src/index.d.ts
CHANGED
|
@@ -56,10 +56,12 @@ export declare class LoginError extends Error {
|
|
|
56
56
|
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
|
+
export { createSession as createCoreSession, Session as CoreSession, defaultSession } from 'gerdur-core';
|
|
60
|
+
export type { SessionUserData } from 'gerdur-core';
|
|
59
61
|
export { getTrackBuffer, getTaggedTrack, downloadTrackToFile } from './lib/api-download';
|
|
60
62
|
export type { Quality, GetTrackBufferOptions, DownloadTrackOptions, DownloadResult } from './lib/api-download';
|
|
61
63
|
export { default as Config, globalConfigPath, resolveConfigFile } from './lib/config';
|
|
62
|
-
export { initDeezerApi, parseInfo, searchMusic, searchPublicApi, searchTracks, searchAlbums, searchArtists, searchPlaylists, buildAdvancedQuery, suggest, getGenres, getChart, getChartTracks, getGenreArtists, getEditorialList, getEditorialReleases, getEditorialSelection, getEditorialCharts, getArtistTopTracks, getRelatedArtists, getArtistAlbums, getArtistPlaylists, getArtistRadioTracks, getTrackByISRC, getAlbumByUPC, getTrackPreview, downloadPreview, formatName, toFormat, DEEZER_FORMATS, getUser, getTrackInfo, getAlbumInfo, getAlbumTracks, getPlaylistInfo, getPlaylistTracks, getArtistInfo, getDiscography, getLyrics, getTrackDownloadUrl, resolveDownloadUrls, streamTrackDownload, createDecryptStream, getStream, addTrackTags, getRichAlbum, normalizeContributors, toLrc, GeoBlocked, DeezerError, } from 'gerdur-core';
|
|
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, 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';
|
|
63
65
|
export type { AddTrackTagsOptions, TaggedTrack, TrackTagModel, RichAlbum, ResolvedUrl, NormalizedContributors, } from 'gerdur-core';
|
|
64
|
-
export type { advancedSearchFilters, searchOrder, searchEntity, publicApiSearchOptions, publicApiSearchResponse, searchResultTrack, searchResultAlbum, searchResultArtist, searchResultPlaylist, suggestResult, publicApiList, chartType, chartTrack, chartAlbum, chartArtist, chartPlaylist, chartPodcast, genreType, editorialType, artistAlbumResult, } from 'gerdur-core/types';
|
|
66
|
+
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';
|
|
65
67
|
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.streamTrackDownload = exports.resolveDownloadUrls = exports.getTrackDownloadUrl = void 0;
|
|
36
|
+
exports.getTrackPreview = exports.getAlbumByUPC = exports.getTrackByISRC = 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 = 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; } });
|
|
@@ -72,6 +72,13 @@ exports.getArl = getArl;
|
|
|
72
72
|
var session_1 = require("./lib/session");
|
|
73
73
|
Object.defineProperty(exports, "createSession", { enumerable: true, get: function () { return session_1.createSession; } });
|
|
74
74
|
Object.defineProperty(exports, "Session", { enumerable: true, get: function () { return session_1.Session; } });
|
|
75
|
+
// `gerdur-core`'s low-level session — an isolated client (its own `arl`, cache,
|
|
76
|
+
// `license_token`) for talking to Deezer directly / from multiple accounts.
|
|
77
|
+
// gerdur's `Session` above is the higher-level download-orchestration one.
|
|
78
|
+
var gerdur_core_1 = require("gerdur-core");
|
|
79
|
+
Object.defineProperty(exports, "createCoreSession", { enumerable: true, get: function () { return gerdur_core_1.createSession; } });
|
|
80
|
+
Object.defineProperty(exports, "CoreSession", { enumerable: true, get: function () { return gerdur_core_1.Session; } });
|
|
81
|
+
Object.defineProperty(exports, "defaultSession", { enumerable: true, get: function () { return gerdur_core_1.defaultSession; } });
|
|
75
82
|
// ─── Download primitives ─────────────────────────────────────────────────────
|
|
76
83
|
var api_download_1 = require("./lib/api-download");
|
|
77
84
|
Object.defineProperty(exports, "getTrackBuffer", { enumerable: true, get: function () { return api_download_1.getTrackBuffer; } });
|
|
@@ -86,54 +93,65 @@ Object.defineProperty(exports, "resolveConfigFile", { enumerable: true, get: fun
|
|
|
86
93
|
// ─── Re-exported core query functions ────────────────────────────────────────
|
|
87
94
|
// Convenience re-exports so consumers don't need `gerdur-core` directly.
|
|
88
95
|
// After `initDeezerApi(arl)` (or `createSession`) these are ready to use.
|
|
89
|
-
var
|
|
90
|
-
Object.defineProperty(exports, "initDeezerApi", { enumerable: true, get: function () { return
|
|
91
|
-
Object.defineProperty(exports, "parseInfo", { enumerable: true, get: function () { return
|
|
92
|
-
Object.defineProperty(exports, "searchMusic", { enumerable: true, get: function () { return
|
|
93
|
-
Object.defineProperty(exports, "searchPublicApi", { enumerable: true, get: function () { return
|
|
94
|
-
Object.defineProperty(exports, "searchTracks", { enumerable: true, get: function () { return
|
|
95
|
-
Object.defineProperty(exports, "searchAlbums", { enumerable: true, get: function () { return
|
|
96
|
-
Object.defineProperty(exports, "searchArtists", { enumerable: true, get: function () { return
|
|
97
|
-
Object.defineProperty(exports, "searchPlaylists", { enumerable: true, get: function () { return
|
|
98
|
-
Object.defineProperty(exports, "buildAdvancedQuery", { enumerable: true, get: function () { return
|
|
99
|
-
Object.defineProperty(exports, "suggest", { enumerable: true, get: function () { return
|
|
100
|
-
Object.defineProperty(exports, "getGenres", { enumerable: true, get: function () { return
|
|
101
|
-
Object.defineProperty(exports, "getChart", { enumerable: true, get: function () { return
|
|
102
|
-
Object.defineProperty(exports, "getChartTracks", { enumerable: true, get: function () { return
|
|
103
|
-
Object.defineProperty(exports, "getGenreArtists", { enumerable: true, get: function () { return
|
|
104
|
-
Object.defineProperty(exports, "getEditorialList", { enumerable: true, get: function () { return
|
|
105
|
-
Object.defineProperty(exports, "getEditorialReleases", { enumerable: true, get: function () { return
|
|
106
|
-
Object.defineProperty(exports, "getEditorialSelection", { enumerable: true, get: function () { return
|
|
107
|
-
Object.defineProperty(exports, "getEditorialCharts", { enumerable: true, get: function () { return
|
|
108
|
-
Object.defineProperty(exports, "getArtistTopTracks", { enumerable: true, get: function () { return
|
|
109
|
-
Object.defineProperty(exports, "getRelatedArtists", { enumerable: true, get: function () { return
|
|
110
|
-
Object.defineProperty(exports, "getArtistAlbums", { enumerable: true, get: function () { return
|
|
111
|
-
Object.defineProperty(exports, "getArtistPlaylists", { enumerable: true, get: function () { return
|
|
112
|
-
Object.defineProperty(exports, "getArtistRadioTracks", { enumerable: true, get: function () { return
|
|
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, "
|
|
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, "getTrackByISRC", { enumerable: true, get: function () { return gerdur_core_2.getTrackByISRC; } });
|
|
131
|
+
Object.defineProperty(exports, "getAlbumByUPC", { enumerable: true, get: function () { return gerdur_core_2.getAlbumByUPC; } });
|
|
132
|
+
Object.defineProperty(exports, "getTrackPreview", { enumerable: true, get: function () { return gerdur_core_2.getTrackPreview; } });
|
|
133
|
+
Object.defineProperty(exports, "downloadPreview", { enumerable: true, get: function () { return gerdur_core_2.downloadPreview; } });
|
|
134
|
+
Object.defineProperty(exports, "formatName", { enumerable: true, get: function () { return gerdur_core_2.formatName; } });
|
|
135
|
+
Object.defineProperty(exports, "toFormat", { enumerable: true, get: function () { return gerdur_core_2.toFormat; } });
|
|
136
|
+
Object.defineProperty(exports, "DEEZER_FORMATS", { enumerable: true, get: function () { return gerdur_core_2.DEEZER_FORMATS; } });
|
|
137
|
+
Object.defineProperty(exports, "getUser", { enumerable: true, get: function () { return gerdur_core_2.getUser; } });
|
|
138
|
+
Object.defineProperty(exports, "getTrackInfo", { enumerable: true, get: function () { return gerdur_core_2.getTrackInfo; } });
|
|
139
|
+
Object.defineProperty(exports, "getAlbumInfo", { enumerable: true, get: function () { return gerdur_core_2.getAlbumInfo; } });
|
|
140
|
+
Object.defineProperty(exports, "getAlbumTracks", { enumerable: true, get: function () { return gerdur_core_2.getAlbumTracks; } });
|
|
141
|
+
Object.defineProperty(exports, "getPlaylistInfo", { enumerable: true, get: function () { return gerdur_core_2.getPlaylistInfo; } });
|
|
142
|
+
Object.defineProperty(exports, "getPlaylistTracks", { enumerable: true, get: function () { return gerdur_core_2.getPlaylistTracks; } });
|
|
143
|
+
Object.defineProperty(exports, "getArtistInfo", { enumerable: true, get: function () { return gerdur_core_2.getArtistInfo; } });
|
|
144
|
+
Object.defineProperty(exports, "getDiscography", { enumerable: true, get: function () { return gerdur_core_2.getDiscography; } });
|
|
145
|
+
Object.defineProperty(exports, "getLyrics", { enumerable: true, get: function () { return gerdur_core_2.getLyrics; } });
|
|
146
|
+
Object.defineProperty(exports, "getTrackDownloadUrl", { enumerable: true, get: function () { return gerdur_core_2.getTrackDownloadUrl; } });
|
|
147
|
+
Object.defineProperty(exports, "resolveDownloadUrls", { enumerable: true, get: function () { return gerdur_core_2.resolveDownloadUrls; } });
|
|
148
|
+
Object.defineProperty(exports, "streamTrackDownload", { enumerable: true, get: function () { return gerdur_core_2.streamTrackDownload; } });
|
|
149
|
+
Object.defineProperty(exports, "downloadTrackBuffer", { enumerable: true, get: function () { return gerdur_core_2.downloadTrackBuffer; } });
|
|
150
|
+
Object.defineProperty(exports, "createDecryptStream", { enumerable: true, get: function () { return gerdur_core_2.createDecryptStream; } });
|
|
151
|
+
Object.defineProperty(exports, "getStream", { enumerable: true, get: function () { return gerdur_core_2.getStream; } });
|
|
152
|
+
Object.defineProperty(exports, "addTrackTags", { enumerable: true, get: function () { return gerdur_core_2.addTrackTags; } });
|
|
153
|
+
Object.defineProperty(exports, "getRichAlbum", { enumerable: true, get: function () { return gerdur_core_2.getRichAlbum; } });
|
|
154
|
+
Object.defineProperty(exports, "normalizeContributors", { enumerable: true, get: function () { return gerdur_core_2.normalizeContributors; } });
|
|
155
|
+
Object.defineProperty(exports, "toLrc", { enumerable: true, get: function () { return gerdur_core_2.toLrc; } });
|
|
156
|
+
Object.defineProperty(exports, "GeoBlocked", { enumerable: true, get: function () { return gerdur_core_2.GeoBlocked; } });
|
|
157
|
+
Object.defineProperty(exports, "DeezerError", { enumerable: true, get: function () { return gerdur_core_2.DeezerError; } });
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { parseInfo, searchMusic } from 'gerdur-core';
|
|
3
3
|
import type { AdvancedSearchOptions } from './search';
|
|
4
4
|
import type { Quality, DownloadTrackOptions, DownloadResult } from './api-download';
|
|
5
|
-
import type { trackType, userType, advancedSearchFilters, publicApiSearchResponse, searchResultTrack, suggestResult, chartType, genreType, editorialType, artistAlbumResult, searchResultArtist, publicApiList, trackTypePublicApi, albumTypePublicApi } from 'gerdur-core/types';
|
|
5
|
+
import type { trackType, userType, advancedSearchFilters, publicApiSearchResponse, searchResultTrack, suggestResult, chartType, genreType, editorialType, artistAlbumResult, searchResultArtist, publicApiList, trackTypePublicApi, albumTypePublicApi, userFavoriteTrack, userFavoriteAlbum, userFavoriteArtist, userPlaylistResult, radioResult } from 'gerdur-core/types';
|
|
6
6
|
import type { TrackPreview, StreamTrackOptions, TrackStream } from 'gerdur-core';
|
|
7
7
|
/** Search result categories accepted by {@link Session.search}. */
|
|
8
8
|
export type SearchType = 'ALBUM' | 'ARTIST' | 'TRACK' | 'PLAYLIST' | 'RADIO' | 'SHOW' | 'USER' | 'LIVESTREAM' | 'CHANNEL';
|
|
@@ -39,7 +39,10 @@ export declare class Session {
|
|
|
39
39
|
/** The arl in use for this session. */
|
|
40
40
|
readonly arl: string;
|
|
41
41
|
private concurrency;
|
|
42
|
+
private userId?;
|
|
42
43
|
private constructor();
|
|
44
|
+
/** The logged-in user's numeric id (cached). Used by the no-arg `flow` / `favorite*` methods. */
|
|
45
|
+
private resolveUserId;
|
|
43
46
|
/**
|
|
44
47
|
* Log in and return a ready-to-use session. Accepts either an `arl` or
|
|
45
48
|
* `email`+`password` (which are exchanged for an arl via Deezer's OAuth flow).
|
|
@@ -86,6 +89,22 @@ export declare class Session {
|
|
|
86
89
|
trackByISRC(isrc: string): Promise<trackTypePublicApi>;
|
|
87
90
|
/** Resolve a UPC/EAN barcode to the public-API album (with its `tracks`). */
|
|
88
91
|
albumByUPC(upc: string): Promise<albumTypePublicApi>;
|
|
92
|
+
/** Deezer **Flow** — the endless personalised mix, as tracks. */
|
|
93
|
+
flow(userId?: string | number, limit?: number): Promise<publicApiList<searchResultTrack>>;
|
|
94
|
+
/** A user's favourite (loved) tracks, newest first (each with `time_add`). */
|
|
95
|
+
favoriteTracks(userId?: string | number, limit?: number): Promise<publicApiList<userFavoriteTrack>>;
|
|
96
|
+
/** A user's favourite albums. */
|
|
97
|
+
favoriteAlbums(userId?: string | number, limit?: number): Promise<publicApiList<userFavoriteAlbum>>;
|
|
98
|
+
/** A user's favourite artists. */
|
|
99
|
+
favoriteArtists(userId?: string | number, limit?: number): Promise<publicApiList<userFavoriteArtist>>;
|
|
100
|
+
/** A user's own + followed playlists. */
|
|
101
|
+
playlists(userId?: string | number, limit?: number): Promise<publicApiList<userPlaylistResult>>;
|
|
102
|
+
/** The radios a user has favourited. */
|
|
103
|
+
userRadios(userId?: string | number): Promise<publicApiList<radioResult>>;
|
|
104
|
+
/** Deezer's curated radio list. */
|
|
105
|
+
radios(): Promise<publicApiList<radioResult>>;
|
|
106
|
+
/** A radio's current tracklist — a ready-to-play (public-API) source. */
|
|
107
|
+
radioTracks(radioId: string | number): Promise<publicApiList<searchResultTrack>>;
|
|
89
108
|
/** The 30-second preview clip URL for a track (plain MP3 — no licence, no decryption). */
|
|
90
109
|
trackPreview(track: trackType | string | number): Promise<TrackPreview | null>;
|
|
91
110
|
/** Fetch a track's 30-second preview clip as a `Buffer` (plain MP3). */
|
package/dist/src/lib/session.js
CHANGED
|
@@ -18,10 +18,21 @@ class Session {
|
|
|
18
18
|
/** The arl in use for this session. */
|
|
19
19
|
arl;
|
|
20
20
|
concurrency;
|
|
21
|
+
userId;
|
|
21
22
|
constructor(arl, concurrency) {
|
|
22
23
|
this.arl = arl;
|
|
23
24
|
this.concurrency = concurrency;
|
|
24
25
|
}
|
|
26
|
+
/** The logged-in user's numeric id (cached). Used by the no-arg `flow` / `favorite*` methods. */
|
|
27
|
+
async resolveUserId(explicit) {
|
|
28
|
+
if (explicit !== undefined) {
|
|
29
|
+
return String(explicit);
|
|
30
|
+
}
|
|
31
|
+
if (!this.userId) {
|
|
32
|
+
this.userId = (await (0, gerdur_core_1.getUser)()).USER_ID;
|
|
33
|
+
}
|
|
34
|
+
return this.userId;
|
|
35
|
+
}
|
|
25
36
|
/**
|
|
26
37
|
* Log in and return a ready-to-use session. Accepts either an `arl` or
|
|
27
38
|
* `email`+`password` (which are exchanged for an arl via Deezer's OAuth flow).
|
|
@@ -116,6 +127,41 @@ class Session {
|
|
|
116
127
|
albumByUPC(upc) {
|
|
117
128
|
return (0, gerdur_core_1.getAlbumByUPC)(upc);
|
|
118
129
|
}
|
|
130
|
+
// ─── Flow, radios & library (public REST) ──────────────────────────────────
|
|
131
|
+
// `userId` defaults to the logged-in user (via `getUser`); their profile must
|
|
132
|
+
// be public for these to see it.
|
|
133
|
+
/** Deezer **Flow** — the endless personalised mix, as tracks. */
|
|
134
|
+
async flow(userId, limit) {
|
|
135
|
+
return (0, gerdur_core_1.getUserFlow)(await this.resolveUserId(userId), limit);
|
|
136
|
+
}
|
|
137
|
+
/** A user's favourite (loved) tracks, newest first (each with `time_add`). */
|
|
138
|
+
async favoriteTracks(userId, limit) {
|
|
139
|
+
return (0, gerdur_core_1.getUserFavoriteTracks)(await this.resolveUserId(userId), limit);
|
|
140
|
+
}
|
|
141
|
+
/** A user's favourite albums. */
|
|
142
|
+
async favoriteAlbums(userId, limit) {
|
|
143
|
+
return (0, gerdur_core_1.getUserFavoriteAlbums)(await this.resolveUserId(userId), limit);
|
|
144
|
+
}
|
|
145
|
+
/** A user's favourite artists. */
|
|
146
|
+
async favoriteArtists(userId, limit) {
|
|
147
|
+
return (0, gerdur_core_1.getUserFavoriteArtists)(await this.resolveUserId(userId), limit);
|
|
148
|
+
}
|
|
149
|
+
/** A user's own + followed playlists. */
|
|
150
|
+
async playlists(userId, limit) {
|
|
151
|
+
return (0, gerdur_core_1.getUserPlaylists)(await this.resolveUserId(userId), limit);
|
|
152
|
+
}
|
|
153
|
+
/** The radios a user has favourited. */
|
|
154
|
+
async userRadios(userId) {
|
|
155
|
+
return (0, gerdur_core_1.getUserRadios)(await this.resolveUserId(userId));
|
|
156
|
+
}
|
|
157
|
+
/** Deezer's curated radio list. */
|
|
158
|
+
radios() {
|
|
159
|
+
return (0, gerdur_core_1.getRadios)();
|
|
160
|
+
}
|
|
161
|
+
/** A radio's current tracklist — a ready-to-play (public-API) source. */
|
|
162
|
+
radioTracks(radioId) {
|
|
163
|
+
return (0, gerdur_core_1.getRadioTracks)(radioId);
|
|
164
|
+
}
|
|
119
165
|
/** The 30-second preview clip URL for a track (plain MP3 — no licence, no decryption). */
|
|
120
166
|
trackPreview(track) {
|
|
121
167
|
return (0, gerdur_core_1.getTrackPreview)(track);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gerdur",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.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.9.0",
|
|
52
52
|
"dot-prop": "^6.0.1",
|
|
53
53
|
"got": "^11.8.6",
|
|
54
54
|
"gradient-string": "^2.0.2",
|