gerdur-core 2.16.0 → 2.18.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,71 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.18.0 - 2026-08-31
4
+
5
+ Write operations — the first part of this package that changes an account.
6
+
7
+ ### Added
8
+
9
+ - **`src/api/favorites.ts`** — mutating library operations, in their own module
10
+ and wired into no download path, so they only run when called deliberately:
11
+ - `addFavoriteTracks(ids)` / `removeFavoriteTracks(ids)` (`song.addFavorites` /
12
+ `song.removeFavorites` — note the plural)
13
+ - `addFavoriteAlbum` / `removeFavoriteAlbum`, `addFavoriteArtist` /
14
+ `removeFavoriteArtist`
15
+ - `followPlaylist` / `unfollowPlaylist` (the gateway wants
16
+ `parent_playlist_id` to follow but `playlist_id` to unfollow)
17
+ - `addFavoriteShow`, `createPlaylist`, `addTracksToPlaylist`,
18
+ `removeTracksFromPlaylist`
19
+
20
+ The surface was mapped by calling each candidate with **incomplete
21
+ parameters** — an existing method answers `MISSING_PARAMETER_*`, an absent one
22
+ `GATEWAY_ERROR` — so method names and their parameter names were established
23
+ without creating or changing anything.
24
+
25
+ ### Verification status
26
+
27
+ - Method existence and parameter names: **confirmed by probe**.
28
+ - End-to-end execution: **not run.** `__tests__/favorites.ts` contains
29
+ snapshot → mutate → assert → revert → assert-restored round trips, gated
30
+ behind `GERDUR_ALLOW_WRITE_TESTS=1` so they never fire by accident.
31
+
32
+ ### Known gaps
33
+
34
+ - **Deezer's gateway has no playlist delete.** `playlist.delete`, `.remove`,
35
+ `.destroy`, `.deletePlaylist` and eight other spellings all answer
36
+ `GATEWAY_ERROR`, so `createPlaylist` is one-way — remove what it makes from a
37
+ Deezer client. Everything else here has a confirmed inverse.
38
+ - No `show.deleteFavorite` was found, so `addFavoriteShow` is one-way too.
39
+ - **`log.listen` (scrobbling) is not implemented.** It never answered the probe,
40
+ so its shape is unknown, and it writes to listening history that cannot be
41
+ undone — not something to ship on a guess.
42
+
43
+ ## 2.17.0 - 2026-08-31
44
+
45
+ The account's own library, over the authenticated gateway.
46
+
47
+ ### Added
48
+
49
+ - **`src/api/library.ts`** — the logged-in account's *private* library. Distinct
50
+ from the public-REST surface in `api/user.ts`, which needs a public profile and
51
+ only shows what that profile exposes. Found by probing the gateway: seven
52
+ methods answer here that the public API cannot reach.
53
+ - `getMyPlaylists(userId?, nb?, start?)` — **including private playlists**
54
+ - `getMyFavoriteTracks` / `getMyFavoriteAlbums` / `getMyFavoriteArtists`
55
+ - `getMyFavoritePlaylists` / `getMyFavoriteRadios` / `getMyFavoriteShows`
56
+ - `getMyFavoriteTrackIds()` — every loved track id in one small request, for
57
+ diffing a local library against the account
58
+ - `userId` defaults to the logged-in account. Responses are gateway shapes, so
59
+ tracks arrive with a `TRACK_TOKEN` and are directly downloadable; being
60
+ account-scoped they stay in the per-session cache and are never shared.
61
+ - **`getTrackMix(sngId, nb?, start?)`** (`song.getSearchTrackMix`) — a "more like
62
+ this" mix seeded from one track. Unlike the public radio endpoints it returns
63
+ full gateway tracks **with tokens already attached**: verified that
64
+ `resolveDownloadUrls` resolves them 3/3 with no `getTrackInfo` round trip.
65
+
66
+ Verified against a live account: `getMyPlaylists` 1/1, `getMyFavoriteArtists`
67
+ 7/7 with real names, `getTrackMix` 5/5 all carrying tokens.
68
+
3
69
  ## 2.16.0 - 2026-08-31
4
70
 
5
71
  ### Added
package/README.md CHANGED
@@ -46,6 +46,8 @@ the CLI and the file-writing layer on top.
46
46
  - [Search](#search)
47
47
  - [Browse and discover](#browse-and-discover)
48
48
  - [Flow, radios and a user's library](#flow-radios-and-a-users-library)
49
+ - [Your own library](#your-own-library)
50
+ - [Changing the account (write operations)](#changing-the-account-write-operations)
49
51
  - [Podcasts](#podcasts)
50
52
  - [Preview clips](#preview-clips)
51
53
  - [Resolve a download URL](#resolve-a-download-url)
@@ -381,6 +383,70 @@ const {data: loved} = await getUserFavoriteTracks(me.USER_ID);
381
383
  const {data: eighties} = await getRadioTracks(38305); // "The '80s"
382
384
  ```
383
385
 
386
+ ### Your own library
387
+
388
+ `api/user.ts` above reads a **public** profile. These read what the *account*
389
+ can see — private playlists included — over the authenticated gateway, and
390
+ return gateway shapes, so tracks come with a `TRACK_TOKEN` and are immediately
391
+ downloadable.
392
+
393
+ | Function | Returns |
394
+ | :--- | :--- |
395
+ | `getMyPlaylists(userId?, nb?, start?)` | the account's own playlists, **including private ones** |
396
+ | `getMyFavoriteTracks(userId?, nb?, start?)` | loved tracks, as downloadable gw tracks |
397
+ | `getMyFavoriteTrackIds()` | every loved track id in one request — for diffing a local library |
398
+ | `getMyFavoriteAlbums` / `getMyFavoriteArtists` | favourited albums / artists |
399
+ | `getMyFavoritePlaylists` / `getMyFavoriteRadios` / `getMyFavoriteShows` | followed playlists / radios / shows |
400
+ | `getTrackMix(sngId, nb?, start?)` | a "more like this" mix seeded from a track — **tokens already attached** |
401
+
402
+ ```ts
403
+ import {getMyPlaylists, getTrackMix, resolveDownloadUrls} from 'gerdur-core';
404
+
405
+ const {data: playlists} = await getMyPlaylists(); // yours, private included
406
+ const {data: mix} = await getTrackMix('3135556', 20); // 20 tracks like this one
407
+ const urls = await resolveDownloadUrls(mix, [9, 3, 1]); // straight to download — no per-track lookup
408
+ ```
409
+
410
+ `userId` defaults to the logged-in account. These are account-scoped, so they
411
+ never enter the shared cross-session cache.
412
+
413
+ ### Changing the account (write operations)
414
+
415
+ Everything above reads. These change the logged-in account's library for real —
416
+ they are in their own module, wired into no download path, and only run when you
417
+ call them.
418
+
419
+ | Function | Inverse |
420
+ | :--- | :--- |
421
+ | `addFavoriteTracks(ids)` | `removeFavoriteTracks(ids)` |
422
+ | `addFavoriteAlbum(id)` | `removeFavoriteAlbum(id)` |
423
+ | `addFavoriteArtist(id)` | `removeFavoriteArtist(id)` |
424
+ | `followPlaylist(id)` | `unfollowPlaylist(id)` |
425
+ | `addFavoriteShow(id)` | — none found |
426
+ | `createPlaylist(title, opts?)` | **— none exists, see below** |
427
+ | `addTracksToPlaylist(id, sngIds)` | `removeTracksFromPlaylist(id, sngIds)` |
428
+
429
+ ```ts
430
+ import {addFavoriteTracks, removeFavoriteTracks} from 'gerdur-core';
431
+
432
+ await addFavoriteTracks(['3135556']); // love it
433
+ await removeFavoriteTracks(['3135556']); // and back
434
+ ```
435
+
436
+ > **`createPlaylist` is a one-way door.** Deezer's gateway exposes no delete —
437
+ > a dozen spellings of `playlist.delete` all answer `GATEWAY_ERROR` — so a
438
+ > playlist made here has to be removed from a Deezer client. It is also the one
439
+ > function in this module that has not been exercised against a live account,
440
+ > for exactly that reason.
441
+ >
442
+ > Method names and parameters were established by probing with incomplete
443
+ > arguments (an existing method answers `MISSING_PARAMETER_*`), so the surface is
444
+ > real; the round trips live in `__tests__/favorites.ts` behind
445
+ > `GERDUR_ALLOW_WRITE_TESTS=1`.
446
+
447
+ Scrobbling (`log.listen`) is deliberately absent: it never answered the probe and
448
+ it writes history that cannot be undone.
449
+
384
450
  ### Podcasts
385
451
 
386
452
  ```ts
@@ -787,7 +853,14 @@ import type {
787
853
 
788
854
  `getUserFlow` · `getUserFavoriteTracks` · `getUserFavoriteAlbums` ·
789
855
  `getUserFavoriteArtists` · `getUserPlaylists` · `getUserRadios` ·
790
- `getUserChartTracks` · `getRadios` · `getRadioTracks` · `getRadioGenres`
856
+ `getUserChartTracks` · `getRadios` · `getRadioTracks` · `getRadioGenres` ·
857
+ `getMyPlaylists` · `getMyFavoriteTracks` · `getMyFavoriteTrackIds` ·
858
+ `getMyFavoriteAlbums` · `getMyFavoriteArtists` · `getMyFavoritePlaylists` ·
859
+ `getMyFavoriteRadios` · `getMyFavoriteShows` · `getTrackMix` ·
860
+ `addFavoriteTracks` · `removeFavoriteTracks` · `addFavoriteAlbum` ·
861
+ `removeFavoriteAlbum` · `addFavoriteArtist` · `removeFavoriteArtist` ·
862
+ `followPlaylist` · `unfollowPlaylist` · `addFavoriteShow` · `createPlaylist` ·
863
+ `addTracksToPlaylist` · `removeTracksFromPlaylist`
791
864
  </details>
792
865
 
793
866
  <details>
@@ -0,0 +1,59 @@
1
+ /** What the gateway returns for a mutation — usually `true`, or the new id. */
2
+ export type WriteResult = boolean | string | number | Record<string, any>;
3
+ /**
4
+ * Love one or more tracks (`song.addFavorites`). Reversible with
5
+ * {@link removeFavoriteTracks}.
6
+ *
7
+ * @param sngIds `SNG_ID`s
8
+ */
9
+ export declare const addFavoriteTracks: (sngIds: (string | number)[]) => Promise<WriteResult>;
10
+ /** Un-love one or more tracks (`song.removeFavorites`). */
11
+ export declare const removeFavoriteTracks: (sngIds: (string | number)[]) => Promise<WriteResult>;
12
+ /** Add an album to favourites (`album.addFavorite`). */
13
+ export declare const addFavoriteAlbum: (albId: string | number) => Promise<WriteResult>;
14
+ /** Remove an album from favourites (`album.deleteFavorite`). */
15
+ export declare const removeFavoriteAlbum: (albId: string | number) => Promise<WriteResult>;
16
+ /** Follow an artist (`artist.addFavorite`). */
17
+ export declare const addFavoriteArtist: (artId: string | number) => Promise<WriteResult>;
18
+ /** Unfollow an artist (`artist.deleteFavorite`). */
19
+ export declare const removeFavoriteArtist: (artId: string | number) => Promise<WriteResult>;
20
+ /**
21
+ * Follow someone else's playlist (`playlist.addFavorite`). Note the gateway
22
+ * wants `parent_playlist_id` here but plain `playlist_id` to unfollow.
23
+ */
24
+ export declare const followPlaylist: (playlistId: string | number) => Promise<WriteResult>;
25
+ /** Unfollow a playlist (`playlist.deleteFavorite`). */
26
+ export declare const unfollowPlaylist: (playlistId: string | number) => Promise<WriteResult>;
27
+ /**
28
+ * Follow a podcast show (`show.addFavorite`).
29
+ *
30
+ * No `show.deleteFavorite` answered the probe, so treat this as one-way until
31
+ * the inverse is found.
32
+ */
33
+ export declare const addFavoriteShow: (showId: string | number) => Promise<WriteResult>;
34
+ /**
35
+ * Create a playlist (`playlist.create`). Resolves to the new `PLAYLIST_ID`.
36
+ *
37
+ * **One-way.** The gateway has no delete counterpart (see the module note), so
38
+ * anything created here has to be removed from a Deezer client. For the same
39
+ * reason this is the one function on this page that has not been exercised
40
+ * against a live account.
41
+ *
42
+ * @param title playlist title
43
+ * @param options `description`, `status` (0 public / 1 private / 2 collaborative),
44
+ * and `songs` to seed it with `SNG_ID`s
45
+ */
46
+ export declare const createPlaylist: (title: string, options?: {
47
+ description?: string;
48
+ status?: 0 | 1 | 2;
49
+ songs?: (string | number)[];
50
+ }) => Promise<WriteResult>;
51
+ /**
52
+ * Append tracks to a playlist (`playlist.addSongs`). Reversible with
53
+ * {@link removeTracksFromPlaylist}.
54
+ *
55
+ * The gateway takes `songs` as `[[sngId, offset], …]`; this wraps that for you.
56
+ */
57
+ export declare const addTracksToPlaylist: (playlistId: string | number, sngIds: (string | number)[]) => Promise<WriteResult>;
58
+ /** Remove tracks from a playlist (`playlist.deleteSongs`). */
59
+ export declare const removeTracksFromPlaylist: (playlistId: string | number, sngIds: (string | number)[]) => Promise<WriteResult>;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeTracksFromPlaylist = exports.addTracksToPlaylist = exports.createPlaylist = exports.addFavoriteShow = exports.unfollowPlaylist = exports.followPlaylist = exports.removeFavoriteArtist = exports.addFavoriteArtist = exports.removeFavoriteAlbum = exports.addFavoriteAlbum = exports.removeFavoriteTracks = exports.addFavoriteTracks = void 0;
4
+ /**
5
+ * **Mutating** operations on the logged-in account's library.
6
+ *
7
+ * Everything else in this package reads. These change the account, so they are
8
+ * kept in their own module and none of them are wired into any download path —
9
+ * you have to call them deliberately.
10
+ *
11
+ * The method names here were established by probing the gateway with incomplete
12
+ * parameters, which makes an existing method answer `MISSING_PARAMETER_*` while
13
+ * an absent one answers `GATEWAY_ERROR` — so the surface was mapped without
14
+ * creating or changing anything.
15
+ *
16
+ * **Deezer's gateway exposes no way to delete a playlist.** `playlist.delete`,
17
+ * `.remove`, `.destroy` and nine other spellings all answer `GATEWAY_ERROR`.
18
+ * {@link createPlaylist} is therefore a one-way door: whatever it makes, you
19
+ * remove from a Deezer client, not from here. Everything else on this page has a
20
+ * confirmed inverse and is safe to undo.
21
+ */
22
+ const request_1 = require("./request");
23
+ // ─── Loved tracks ────────────────────────────────────────────────────────────
24
+ /**
25
+ * Love one or more tracks (`song.addFavorites`). Reversible with
26
+ * {@link removeFavoriteTracks}.
27
+ *
28
+ * @param sngIds `SNG_ID`s
29
+ */
30
+ const addFavoriteTracks = (sngIds) => (0, request_1.request)({ ids: sngIds.map(String) }, 'song.addFavorites');
31
+ exports.addFavoriteTracks = addFavoriteTracks;
32
+ /** Un-love one or more tracks (`song.removeFavorites`). */
33
+ const removeFavoriteTracks = (sngIds) => (0, request_1.request)({ ids: sngIds.map(String) }, 'song.removeFavorites');
34
+ exports.removeFavoriteTracks = removeFavoriteTracks;
35
+ // ─── Albums / artists ────────────────────────────────────────────────────────
36
+ /** Add an album to favourites (`album.addFavorite`). */
37
+ const addFavoriteAlbum = (albId) => (0, request_1.request)({ alb_id: String(albId) }, 'album.addFavorite');
38
+ exports.addFavoriteAlbum = addFavoriteAlbum;
39
+ /** Remove an album from favourites (`album.deleteFavorite`). */
40
+ const removeFavoriteAlbum = (albId) => (0, request_1.request)({ alb_id: String(albId) }, 'album.deleteFavorite');
41
+ exports.removeFavoriteAlbum = removeFavoriteAlbum;
42
+ /** Follow an artist (`artist.addFavorite`). */
43
+ const addFavoriteArtist = (artId) => (0, request_1.request)({ art_id: String(artId) }, 'artist.addFavorite');
44
+ exports.addFavoriteArtist = addFavoriteArtist;
45
+ /** Unfollow an artist (`artist.deleteFavorite`). */
46
+ const removeFavoriteArtist = (artId) => (0, request_1.request)({ art_id: String(artId) }, 'artist.deleteFavorite');
47
+ exports.removeFavoriteArtist = removeFavoriteArtist;
48
+ // ─── Playlists & shows ───────────────────────────────────────────────────────
49
+ /**
50
+ * Follow someone else's playlist (`playlist.addFavorite`). Note the gateway
51
+ * wants `parent_playlist_id` here but plain `playlist_id` to unfollow.
52
+ */
53
+ const followPlaylist = (playlistId) => (0, request_1.request)({ parent_playlist_id: String(playlistId) }, 'playlist.addFavorite');
54
+ exports.followPlaylist = followPlaylist;
55
+ /** Unfollow a playlist (`playlist.deleteFavorite`). */
56
+ const unfollowPlaylist = (playlistId) => (0, request_1.request)({ playlist_id: String(playlistId) }, 'playlist.deleteFavorite');
57
+ exports.unfollowPlaylist = unfollowPlaylist;
58
+ /**
59
+ * Follow a podcast show (`show.addFavorite`).
60
+ *
61
+ * No `show.deleteFavorite` answered the probe, so treat this as one-way until
62
+ * the inverse is found.
63
+ */
64
+ const addFavoriteShow = (showId) => (0, request_1.request)({ show_id: String(showId) }, 'show.addFavorite');
65
+ exports.addFavoriteShow = addFavoriteShow;
66
+ // ─── Playlist contents ───────────────────────────────────────────────────────
67
+ /**
68
+ * Create a playlist (`playlist.create`). Resolves to the new `PLAYLIST_ID`.
69
+ *
70
+ * **One-way.** The gateway has no delete counterpart (see the module note), so
71
+ * anything created here has to be removed from a Deezer client. For the same
72
+ * reason this is the one function on this page that has not been exercised
73
+ * against a live account.
74
+ *
75
+ * @param title playlist title
76
+ * @param options `description`, `status` (0 public / 1 private / 2 collaborative),
77
+ * and `songs` to seed it with `SNG_ID`s
78
+ */
79
+ const createPlaylist = (title, options = {}) => {
80
+ var _a, _b, _c;
81
+ return (0, request_1.request)({
82
+ title,
83
+ description: (_a = options.description) !== null && _a !== void 0 ? _a : '',
84
+ status: (_b = options.status) !== null && _b !== void 0 ? _b : 1,
85
+ songs: ((_c = options.songs) !== null && _c !== void 0 ? _c : []).map((id) => [String(id), 0]),
86
+ }, 'playlist.create');
87
+ };
88
+ exports.createPlaylist = createPlaylist;
89
+ /**
90
+ * Append tracks to a playlist (`playlist.addSongs`). Reversible with
91
+ * {@link removeTracksFromPlaylist}.
92
+ *
93
+ * The gateway takes `songs` as `[[sngId, offset], …]`; this wraps that for you.
94
+ */
95
+ const addTracksToPlaylist = (playlistId, sngIds) => (0, request_1.request)({ playlist_id: String(playlistId), songs: sngIds.map((id) => [String(id), 0]) }, 'playlist.addSongs');
96
+ exports.addTracksToPlaylist = addTracksToPlaylist;
97
+ /** Remove tracks from a playlist (`playlist.deleteSongs`). */
98
+ const removeTracksFromPlaylist = (playlistId, sngIds) => (0, request_1.request)({ playlist_id: String(playlistId), songs: sngIds.map((id) => [String(id), 0]) }, 'playlist.deleteSongs');
99
+ exports.removeTracksFromPlaylist = removeTracksFromPlaylist;
@@ -5,3 +5,5 @@ export * from './browse';
5
5
  export * from './preview';
6
6
  export * from './user';
7
7
  export * from './podcast';
8
+ export * from './library';
9
+ export * from './favorites';
package/dist/api/index.js CHANGED
@@ -21,3 +21,5 @@ __exportStar(require("./browse"), exports);
21
21
  __exportStar(require("./preview"), exports);
22
22
  __exportStar(require("./user"), exports);
23
23
  __exportStar(require("./podcast"), exports);
24
+ __exportStar(require("./library"), exports);
25
+ __exportStar(require("./favorites"), exports);
@@ -0,0 +1,72 @@
1
+ import type { playlistInfoMinimal, trackType } from '../types';
2
+ /** Envelope the gateway wraps these listings in. */
3
+ export interface GwList<T> {
4
+ data: T[];
5
+ count: number;
6
+ total: number;
7
+ filtered_count?: number;
8
+ checksum?: string;
9
+ }
10
+ /** A favourited artist, as the library returns it. */
11
+ export interface FavoriteArtist {
12
+ ART_ID: string;
13
+ ART_NAME: string;
14
+ ART_PICTURE: string;
15
+ /** when it was favourited — `YYYY-MM-DD HH:MM:SS` */
16
+ DATE_ADD?: string;
17
+ NB_ALBUM?: number;
18
+ NB_FAN?: number;
19
+ ARTIST_IS_DUMMY?: boolean;
20
+ __TYPE__?: string;
21
+ }
22
+ /** A favourited album, as the library returns it. */
23
+ export interface FavoriteAlbum {
24
+ ALB_ID: string;
25
+ ALB_TITLE: string;
26
+ ALB_PICTURE: string;
27
+ ART_ID?: string;
28
+ ART_NAME?: string;
29
+ DATE_ADD?: string;
30
+ NUMBER_TRACK?: number;
31
+ PHYSICAL_RELEASE_DATE?: string;
32
+ __TYPE__?: string;
33
+ }
34
+ /**
35
+ * The account's own playlists (`playlist.getList`) — **including private ones**,
36
+ * which the public `/user/{id}/playlists` endpoint will not show you.
37
+ *
38
+ * @param userId defaults to the logged-in account
39
+ */
40
+ export declare const getMyPlaylists: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<playlistInfoMinimal>>;
41
+ /**
42
+ * Loved tracks (`song.getFavorites`). Gateway track objects, so each carries a
43
+ * `TRACK_TOKEN` and can go straight to `resolveDownloadUrls`.
44
+ */
45
+ export declare const getMyFavoriteTracks: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<trackType>>;
46
+ /**
47
+ * Just the ids of every loved track (`song.getFavoriteIds`) — one small request
48
+ * for the whole set, for diffing a local library against the account.
49
+ */
50
+ export declare const getMyFavoriteTrackIds: () => Promise<GwList<{
51
+ SNG_ID: string;
52
+ }>>;
53
+ /** Favourited albums (`album.getFavorites`). */
54
+ export declare const getMyFavoriteAlbums: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<FavoriteAlbum>>;
55
+ /** Favourited artists (`artist.getFavorites`). */
56
+ export declare const getMyFavoriteArtists: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<FavoriteArtist>>;
57
+ /** Playlists the account follows (`playlist.getFavorites`). */
58
+ export declare const getMyFavoritePlaylists: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<playlistInfoMinimal>>;
59
+ /** Favourited radios (`radio.getFavorites`). */
60
+ export declare const getMyFavoriteRadios: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<Record<string, any>>>;
61
+ /** Favourited podcast shows (`show.getFavorites`). */
62
+ export declare const getMyFavoriteShows: (userId?: string | number, nb?: number, start?: number) => Promise<GwList<Record<string, any>>>;
63
+ /**
64
+ * A "more like this" mix seeded from one track (`song.getSearchTrackMix`).
65
+ *
66
+ * Returns full gateway tracks **with `TRACK_TOKEN`s**, so unlike the public
67
+ * radio endpoints the results are immediately downloadable — no `getTrackInfo`
68
+ * round trip per hit.
69
+ *
70
+ * @param sngId the seed track's `SNG_ID`
71
+ */
72
+ export declare const getTrackMix: (sngId: string, nb?: number, start?: number) => Promise<GwList<trackType>>;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTrackMix = exports.getMyFavoriteShows = exports.getMyFavoriteRadios = exports.getMyFavoritePlaylists = exports.getMyFavoriteArtists = exports.getMyFavoriteAlbums = exports.getMyFavoriteTrackIds = exports.getMyFavoriteTracks = exports.getMyPlaylists = void 0;
4
+ /**
5
+ * The **logged-in account's own library**, over the authenticated gateway.
6
+ *
7
+ * This is not the same surface as `src/api/user.ts`. Those functions read the
8
+ * *public* REST profile (`/user/{id}/tracks` …), which needs the profile to be
9
+ * public and shows only what that profile exposes. These read what the account
10
+ * itself can see — including a private library — and return gateway shapes, so
11
+ * tracks arrive with a `TRACK_TOKEN` and are directly downloadable.
12
+ *
13
+ * Every response here is account-scoped, so it lives in the per-session cache
14
+ * and is never shared between sessions.
15
+ */
16
+ const request_1 = require("./request");
17
+ const api_1 = require("./api");
18
+ /** Resolve the caller's own user id when one wasn't supplied. */
19
+ const ownUserId = async (userId) => userId !== undefined ? String(userId) : String((await (0, api_1.getUser)()).USER_ID);
20
+ /**
21
+ * The account's own playlists (`playlist.getList`) — **including private ones**,
22
+ * which the public `/user/{id}/playlists` endpoint will not show you.
23
+ *
24
+ * @param userId defaults to the logged-in account
25
+ */
26
+ const getMyPlaylists = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start, tab: 'all' }, 'playlist.getList');
27
+ exports.getMyPlaylists = getMyPlaylists;
28
+ /**
29
+ * Loved tracks (`song.getFavorites`). Gateway track objects, so each carries a
30
+ * `TRACK_TOKEN` and can go straight to `resolveDownloadUrls`.
31
+ */
32
+ const getMyFavoriteTracks = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start }, 'song.getFavorites');
33
+ exports.getMyFavoriteTracks = getMyFavoriteTracks;
34
+ /**
35
+ * Just the ids of every loved track (`song.getFavoriteIds`) — one small request
36
+ * for the whole set, for diffing a local library against the account.
37
+ */
38
+ const getMyFavoriteTrackIds = () => (0, request_1.request)({}, 'song.getFavoriteIds');
39
+ exports.getMyFavoriteTrackIds = getMyFavoriteTrackIds;
40
+ /** Favourited albums (`album.getFavorites`). */
41
+ const getMyFavoriteAlbums = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start }, 'album.getFavorites');
42
+ exports.getMyFavoriteAlbums = getMyFavoriteAlbums;
43
+ /** Favourited artists (`artist.getFavorites`). */
44
+ const getMyFavoriteArtists = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start }, 'artist.getFavorites');
45
+ exports.getMyFavoriteArtists = getMyFavoriteArtists;
46
+ /** Playlists the account follows (`playlist.getFavorites`). */
47
+ const getMyFavoritePlaylists = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start }, 'playlist.getFavorites');
48
+ exports.getMyFavoritePlaylists = getMyFavoritePlaylists;
49
+ /** Favourited radios (`radio.getFavorites`). */
50
+ const getMyFavoriteRadios = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start }, 'radio.getFavorites');
51
+ exports.getMyFavoriteRadios = getMyFavoriteRadios;
52
+ /** Favourited podcast shows (`show.getFavorites`). */
53
+ const getMyFavoriteShows = async (userId, nb = 50, start = 0) => (0, request_1.request)({ user_id: await ownUserId(userId), nb, start }, 'show.getFavorites');
54
+ exports.getMyFavoriteShows = getMyFavoriteShows;
55
+ /**
56
+ * A "more like this" mix seeded from one track (`song.getSearchTrackMix`).
57
+ *
58
+ * Returns full gateway tracks **with `TRACK_TOKEN`s**, so unlike the public
59
+ * radio endpoints the results are immediately downloadable — no `getTrackInfo`
60
+ * round trip per hit.
61
+ *
62
+ * @param sngId the seed track's `SNG_ID`
63
+ */
64
+ const getTrackMix = (sngId, nb = 40, start = 0) => (0, request_1.request)({ sng_id: sngId, start, nb }, 'song.getSearchTrackMix');
65
+ exports.getTrackMix = getTrackMix;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur-core",
3
- "version": "2.16.0",
3
+ "version": "2.18.0",
4
4
  "description": "Deezer API client, cross-service URL resolution, Blowfish track decryption and MP3/FLAC metadata tagging — the engine behind the gerdur CLI.",
5
5
  "keywords": [
6
6
  "deezer",