@lucaperret/tidal-cli 1.1.2 → 1.2.2
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/README.md +13 -1
- package/dist/album.d.ts +4 -0
- package/dist/album.js +69 -50
- package/dist/artist.d.ts +7 -0
- package/dist/artist.js +139 -91
- package/dist/history.d.ts +3 -2
- package/dist/history.js +27 -17
- package/dist/index.js +96 -1
- package/dist/library.d.ts +25 -2
- package/dist/library.js +97 -48
- package/dist/mix.d.ts +4 -0
- package/dist/mix.js +59 -0
- package/dist/playback.d.ts +4 -0
- package/dist/playback.js +62 -46
- package/dist/playlist.d.ts +43 -0
- package/dist/playlist.js +183 -104
- package/dist/recommend.d.ts +4 -1
- package/dist/recommend.js +71 -19
- package/dist/saved.d.ts +16 -0
- package/dist/saved.js +107 -0
- package/dist/search-history.d.ts +13 -0
- package/dist/search-history.js +94 -0
- package/dist/search.d.ts +4 -2
- package/dist/search.js +66 -45
- package/dist/session.js +17 -7
- package/dist/share.d.ts +5 -0
- package/dist/share.js +53 -0
- package/dist/track.d.ts +14 -0
- package/dist/track.js +128 -91
- package/dist/types.d.ts +158 -0
- package/dist/types.js +4 -0
- package/dist/user.d.ts +3 -0
- package/dist/user.js +27 -18
- package/package.json +8 -6
package/dist/playlist.d.ts
CHANGED
|
@@ -1,9 +1,52 @@
|
|
|
1
|
+
import type { PlaylistInfo } from './types';
|
|
2
|
+
export type { PlaylistInfo };
|
|
3
|
+
export declare function listPlaylistsData(client: any, countryCode: string): Promise<PlaylistInfo[]>;
|
|
1
4
|
export declare function listPlaylists(json: boolean): Promise<void>;
|
|
5
|
+
export declare function createPlaylistData(name: string, description: string, client: any): Promise<{
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}>;
|
|
2
10
|
export declare function createPlaylist(name: string, description: string, json: boolean): Promise<void>;
|
|
11
|
+
export declare function renamePlaylistData(playlistId: string, name: string, client: any): Promise<{
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
success: boolean;
|
|
15
|
+
}>;
|
|
3
16
|
export declare function renamePlaylist(playlistId: string, name: string, json: boolean): Promise<void>;
|
|
17
|
+
export declare function deletePlaylistData(playlistId: string, client: any): Promise<{
|
|
18
|
+
id: string;
|
|
19
|
+
deleted: boolean;
|
|
20
|
+
}>;
|
|
4
21
|
export declare function deletePlaylist(playlistId: string, json: boolean): Promise<void>;
|
|
22
|
+
export declare function addTrackToPlaylistData(playlistId: string, trackId: string, client: any): Promise<{
|
|
23
|
+
playlistId: string;
|
|
24
|
+
trackId: string;
|
|
25
|
+
added: boolean;
|
|
26
|
+
}>;
|
|
5
27
|
export declare function addTrackToPlaylist(playlistId: string, trackId: string, json: boolean): Promise<void>;
|
|
28
|
+
export declare function removeTrackFromPlaylistData(playlistId: string, trackId: string, client: any): Promise<{
|
|
29
|
+
playlistId: string;
|
|
30
|
+
trackId: string;
|
|
31
|
+
removed: boolean;
|
|
32
|
+
}>;
|
|
6
33
|
export declare function removeTrackFromPlaylist(playlistId: string, trackId: string, json: boolean): Promise<void>;
|
|
34
|
+
export declare function addAlbumToPlaylistData(playlistId: string, albumId: string, client: any, countryCode: string): Promise<{
|
|
35
|
+
playlistId: string;
|
|
36
|
+
albumId: string;
|
|
37
|
+
tracksAdded: number;
|
|
38
|
+
}>;
|
|
7
39
|
export declare function addAlbumToPlaylist(playlistId: string, albumId: string, json: boolean): Promise<void>;
|
|
40
|
+
export declare function moveTrackInPlaylistData(playlistId: string, trackId: string, positionBefore: string, client: any): Promise<{
|
|
41
|
+
playlistId: string;
|
|
42
|
+
trackId: string;
|
|
43
|
+
positionBefore: string;
|
|
44
|
+
moved: boolean;
|
|
45
|
+
}>;
|
|
8
46
|
export declare function moveTrackInPlaylist(playlistId: string, trackId: string, positionBefore: string, json: boolean): Promise<void>;
|
|
47
|
+
export declare function updatePlaylistDescriptionData(playlistId: string, description: string, client: any): Promise<{
|
|
48
|
+
id: string;
|
|
49
|
+
description: string;
|
|
50
|
+
success: boolean;
|
|
51
|
+
}>;
|
|
9
52
|
export declare function updatePlaylistDescription(playlistId: string, description: string, json: boolean): Promise<void>;
|
package/dist/playlist.js
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listPlaylistsData = listPlaylistsData;
|
|
3
4
|
exports.listPlaylists = listPlaylists;
|
|
5
|
+
exports.createPlaylistData = createPlaylistData;
|
|
4
6
|
exports.createPlaylist = createPlaylist;
|
|
7
|
+
exports.renamePlaylistData = renamePlaylistData;
|
|
5
8
|
exports.renamePlaylist = renamePlaylist;
|
|
9
|
+
exports.deletePlaylistData = deletePlaylistData;
|
|
6
10
|
exports.deletePlaylist = deletePlaylist;
|
|
11
|
+
exports.addTrackToPlaylistData = addTrackToPlaylistData;
|
|
7
12
|
exports.addTrackToPlaylist = addTrackToPlaylist;
|
|
13
|
+
exports.removeTrackFromPlaylistData = removeTrackFromPlaylistData;
|
|
8
14
|
exports.removeTrackFromPlaylist = removeTrackFromPlaylist;
|
|
15
|
+
exports.addAlbumToPlaylistData = addAlbumToPlaylistData;
|
|
9
16
|
exports.addAlbumToPlaylist = addAlbumToPlaylist;
|
|
17
|
+
exports.moveTrackInPlaylistData = moveTrackInPlaylistData;
|
|
10
18
|
exports.moveTrackInPlaylist = moveTrackInPlaylist;
|
|
19
|
+
exports.updatePlaylistDescriptionData = updatePlaylistDescriptionData;
|
|
11
20
|
exports.updatePlaylistDescription = updatePlaylistDescription;
|
|
12
21
|
const auth_1 = require("./auth");
|
|
13
|
-
async function
|
|
14
|
-
const client = await (0, auth_1.getApiClient)();
|
|
22
|
+
async function listPlaylistsData(client, countryCode) {
|
|
15
23
|
const { data, error } = await client.GET('/playlists', {
|
|
16
24
|
params: {
|
|
17
25
|
query: {
|
|
18
26
|
'filter[owners.id]': ['me'],
|
|
19
|
-
countryCode
|
|
27
|
+
countryCode,
|
|
20
28
|
},
|
|
21
29
|
},
|
|
22
30
|
});
|
|
23
31
|
if (error || !data) {
|
|
24
|
-
|
|
25
|
-
process.exit(1);
|
|
32
|
+
throw new Error(`Failed to list playlists — ${JSON.stringify(error)}`);
|
|
26
33
|
}
|
|
27
|
-
|
|
34
|
+
return (data.data ?? []).map((p) => ({
|
|
28
35
|
id: p.id,
|
|
29
36
|
name: p.attributes?.name ?? 'Untitled',
|
|
30
37
|
description: p.attributes?.description,
|
|
@@ -32,24 +39,34 @@ async function listPlaylists(json) {
|
|
|
32
39
|
createdAt: p.attributes?.createdAt,
|
|
33
40
|
lastModifiedAt: p.attributes?.lastModifiedAt,
|
|
34
41
|
}));
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
}
|
|
43
|
+
async function listPlaylists(json) {
|
|
44
|
+
const client = await (0, auth_1.getApiClient)();
|
|
45
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
46
|
+
try {
|
|
47
|
+
const playlists = await listPlaylistsData(client, countryCode);
|
|
48
|
+
if (json) {
|
|
49
|
+
console.log(JSON.stringify(playlists, null, 2));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (playlists.length === 0) {
|
|
53
|
+
console.log('No playlists found.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
console.log('\nYour playlists:\n');
|
|
57
|
+
for (const p of playlists) {
|
|
58
|
+
console.log(` [${p.id}] ${p.name} (${p.numberOfItems ?? 0} tracks)`);
|
|
59
|
+
if (p.description)
|
|
60
|
+
console.log(` ${p.description}`);
|
|
61
|
+
}
|
|
62
|
+
console.log();
|
|
42
63
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (p.description)
|
|
47
|
-
console.log(` ${p.description}`);
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.error(`Error: ${err.message}`);
|
|
66
|
+
process.exit(1);
|
|
48
67
|
}
|
|
49
|
-
console.log();
|
|
50
68
|
}
|
|
51
|
-
async function
|
|
52
|
-
const client = await (0, auth_1.getApiClient)();
|
|
69
|
+
async function createPlaylistData(name, description, client) {
|
|
53
70
|
const { data, error } = await client.POST('/playlists', {
|
|
54
71
|
body: {
|
|
55
72
|
data: {
|
|
@@ -63,23 +80,31 @@ async function createPlaylist(name, description, json) {
|
|
|
63
80
|
},
|
|
64
81
|
});
|
|
65
82
|
if (error || !data) {
|
|
66
|
-
|
|
67
|
-
process.exit(1);
|
|
83
|
+
throw new Error(`Failed to create playlist — ${JSON.stringify(error)}`);
|
|
68
84
|
}
|
|
69
85
|
const created = data.data;
|
|
70
|
-
|
|
86
|
+
return {
|
|
71
87
|
id: created.id,
|
|
72
88
|
name: created.attributes?.name ?? name,
|
|
73
89
|
description: created.attributes?.description ?? description,
|
|
74
90
|
};
|
|
75
|
-
if (json) {
|
|
76
|
-
console.log(JSON.stringify(result, null, 2));
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
console.log(`\nPlaylist created: [${result.id}] ${result.name}`);
|
|
80
91
|
}
|
|
81
|
-
async function
|
|
92
|
+
async function createPlaylist(name, description, json) {
|
|
82
93
|
const client = await (0, auth_1.getApiClient)();
|
|
94
|
+
try {
|
|
95
|
+
const result = await createPlaylistData(name, description, client);
|
|
96
|
+
if (json) {
|
|
97
|
+
console.log(JSON.stringify(result, null, 2));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
console.log(`\nPlaylist created: [${result.id}] ${result.name}`);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.error(`Error: ${err.message}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function renamePlaylistData(playlistId, name, client) {
|
|
83
108
|
const { error } = await client.PATCH('/playlists/{id}', {
|
|
84
109
|
params: { path: { id: playlistId } },
|
|
85
110
|
body: {
|
|
@@ -91,32 +116,50 @@ async function renamePlaylist(playlistId, name, json) {
|
|
|
91
116
|
},
|
|
92
117
|
});
|
|
93
118
|
if (error) {
|
|
94
|
-
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
if (json) {
|
|
98
|
-
console.log(JSON.stringify({ id: playlistId, name, success: true }, null, 2));
|
|
99
|
-
return;
|
|
119
|
+
throw new Error(`Failed to rename playlist — ${JSON.stringify(error)}`);
|
|
100
120
|
}
|
|
101
|
-
|
|
121
|
+
return { id: playlistId, name, success: true };
|
|
102
122
|
}
|
|
103
|
-
async function
|
|
123
|
+
async function renamePlaylist(playlistId, name, json) {
|
|
104
124
|
const client = await (0, auth_1.getApiClient)();
|
|
125
|
+
try {
|
|
126
|
+
const result = await renamePlaylistData(playlistId, name, client);
|
|
127
|
+
if (json) {
|
|
128
|
+
console.log(JSON.stringify(result, null, 2));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
console.log(`\nPlaylist ${playlistId} renamed to "${name}".`);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
console.error(`Error: ${err.message}`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function deletePlaylistData(playlistId, client) {
|
|
105
139
|
const { error } = await client.DELETE('/playlists/{id}', {
|
|
106
140
|
params: { path: { id: playlistId } },
|
|
107
141
|
});
|
|
108
142
|
if (error) {
|
|
109
|
-
|
|
110
|
-
process.exit(1);
|
|
111
|
-
}
|
|
112
|
-
if (json) {
|
|
113
|
-
console.log(JSON.stringify({ id: playlistId, deleted: true }, null, 2));
|
|
114
|
-
return;
|
|
143
|
+
throw new Error(`Failed to delete playlist — ${JSON.stringify(error)}`);
|
|
115
144
|
}
|
|
116
|
-
|
|
145
|
+
return { id: playlistId, deleted: true };
|
|
117
146
|
}
|
|
118
|
-
async function
|
|
147
|
+
async function deletePlaylist(playlistId, json) {
|
|
119
148
|
const client = await (0, auth_1.getApiClient)();
|
|
149
|
+
try {
|
|
150
|
+
const result = await deletePlaylistData(playlistId, client);
|
|
151
|
+
if (json) {
|
|
152
|
+
console.log(JSON.stringify(result, null, 2));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
console.log(`\nPlaylist ${playlistId} deleted.`);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
console.error(`Error: ${err.message}`);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async function addTrackToPlaylistData(playlistId, trackId, client) {
|
|
120
163
|
const { error } = await client.POST('/playlists/{id}/relationships/items', {
|
|
121
164
|
params: { path: { id: playlistId } },
|
|
122
165
|
body: {
|
|
@@ -124,30 +167,36 @@ async function addTrackToPlaylist(playlistId, trackId, json) {
|
|
|
124
167
|
},
|
|
125
168
|
});
|
|
126
169
|
if (error) {
|
|
127
|
-
|
|
128
|
-
process.exit(1);
|
|
170
|
+
throw new Error(`Failed to add track — ${JSON.stringify(error)}`);
|
|
129
171
|
}
|
|
130
|
-
|
|
131
|
-
console.log(JSON.stringify({ playlistId, trackId, added: true }, null, 2));
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
console.log(`\nTrack ${trackId} added to playlist ${playlistId}.`);
|
|
172
|
+
return { playlistId, trackId, added: true };
|
|
135
173
|
}
|
|
136
|
-
async function
|
|
174
|
+
async function addTrackToPlaylist(playlistId, trackId, json) {
|
|
137
175
|
const client = await (0, auth_1.getApiClient)();
|
|
138
|
-
|
|
176
|
+
try {
|
|
177
|
+
const result = await addTrackToPlaylistData(playlistId, trackId, client);
|
|
178
|
+
if (json) {
|
|
179
|
+
console.log(JSON.stringify(result, null, 2));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
console.log(`\nTrack ${trackId} added to playlist ${playlistId}.`);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
console.error(`Error: ${err.message}`);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function removeTrackFromPlaylistData(playlistId, trackId, client) {
|
|
139
190
|
const { data: itemsData, error: itemsError } = await client.GET('/playlists/{id}/relationships/items', {
|
|
140
191
|
params: { path: { id: playlistId } },
|
|
141
192
|
});
|
|
142
193
|
if (itemsError || !itemsData) {
|
|
143
|
-
|
|
144
|
-
process.exit(1);
|
|
194
|
+
throw new Error(`Failed to get playlist items — ${JSON.stringify(itemsError)}`);
|
|
145
195
|
}
|
|
146
196
|
const items = itemsData.data ?? [];
|
|
147
197
|
const item = items.find((i) => i.id === trackId);
|
|
148
198
|
if (!item) {
|
|
149
|
-
|
|
150
|
-
process.exit(1);
|
|
199
|
+
throw new Error(`Track ${trackId} not found in playlist ${playlistId}.`);
|
|
151
200
|
}
|
|
152
201
|
const { error } = await client.DELETE('/playlists/{id}/relationships/items', {
|
|
153
202
|
params: { path: { id: playlistId } },
|
|
@@ -156,71 +205,82 @@ async function removeTrackFromPlaylist(playlistId, trackId, json) {
|
|
|
156
205
|
},
|
|
157
206
|
});
|
|
158
207
|
if (error) {
|
|
159
|
-
|
|
160
|
-
process.exit(1);
|
|
208
|
+
throw new Error(`Failed to remove track — ${JSON.stringify(error)}`);
|
|
161
209
|
}
|
|
162
|
-
|
|
163
|
-
console.log(JSON.stringify({ playlistId, trackId, removed: true }, null, 2));
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
console.log(`\nTrack ${trackId} removed from playlist ${playlistId}.`);
|
|
210
|
+
return { playlistId, trackId, removed: true };
|
|
167
211
|
}
|
|
168
|
-
async function
|
|
212
|
+
async function removeTrackFromPlaylist(playlistId, trackId, json) {
|
|
169
213
|
const client = await (0, auth_1.getApiClient)();
|
|
170
|
-
|
|
214
|
+
try {
|
|
215
|
+
const result = await removeTrackFromPlaylistData(playlistId, trackId, client);
|
|
216
|
+
if (json) {
|
|
217
|
+
console.log(JSON.stringify(result, null, 2));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
console.log(`\nTrack ${trackId} removed from playlist ${playlistId}.`);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
console.error(`Error: ${err.message}`);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function addAlbumToPlaylistData(playlistId, albumId, client, countryCode) {
|
|
171
228
|
const { data: albumData, error: albumError } = await client.GET('/albums/{id}', {
|
|
172
229
|
params: {
|
|
173
230
|
path: { id: albumId },
|
|
174
|
-
query: { countryCode
|
|
231
|
+
query: { countryCode, include: ['items'] },
|
|
175
232
|
},
|
|
176
233
|
});
|
|
177
234
|
if (albumError || !albumData) {
|
|
178
|
-
|
|
179
|
-
process.exit(1);
|
|
235
|
+
throw new Error(`Failed to get album — ${JSON.stringify(albumError)}`);
|
|
180
236
|
}
|
|
181
|
-
// Extract track IDs from included items
|
|
182
237
|
const included = albumData.included ?? [];
|
|
183
238
|
const trackIds = included
|
|
184
239
|
.filter((item) => item.type === 'tracks')
|
|
185
240
|
.map((item) => ({ id: item.id, type: 'tracks' }));
|
|
186
241
|
if (trackIds.length === 0) {
|
|
187
|
-
|
|
188
|
-
process.exit(1);
|
|
242
|
+
throw new Error('No tracks found in album.');
|
|
189
243
|
}
|
|
190
244
|
const { error } = await client.POST('/playlists/{id}/relationships/items', {
|
|
191
245
|
params: { path: { id: playlistId } },
|
|
192
246
|
body: { data: trackIds },
|
|
193
247
|
});
|
|
194
248
|
if (error) {
|
|
195
|
-
|
|
196
|
-
process.exit(1);
|
|
249
|
+
throw new Error(`Failed to add album tracks — ${JSON.stringify(error)}`);
|
|
197
250
|
}
|
|
198
|
-
|
|
199
|
-
console.log(JSON.stringify({ playlistId, albumId, tracksAdded: trackIds.length }, null, 2));
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
console.log(`\n${trackIds.length} tracks from album ${albumId} added to playlist ${playlistId}.`);
|
|
251
|
+
return { playlistId, albumId, tracksAdded: trackIds.length };
|
|
203
252
|
}
|
|
204
|
-
async function
|
|
253
|
+
async function addAlbumToPlaylist(playlistId, albumId, json) {
|
|
205
254
|
const client = await (0, auth_1.getApiClient)();
|
|
206
|
-
|
|
255
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
256
|
+
try {
|
|
257
|
+
const result = await addAlbumToPlaylistData(playlistId, albumId, client, countryCode);
|
|
258
|
+
if (json) {
|
|
259
|
+
console.log(JSON.stringify(result, null, 2));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
console.log(`\n${result.tracksAdded} tracks from album ${albumId} added to playlist ${playlistId}.`);
|
|
263
|
+
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
console.error(`Error: ${err.message}`);
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function moveTrackInPlaylistData(playlistId, trackId, positionBefore, client) {
|
|
207
270
|
const { data: itemsData, error: itemsError } = await client.GET('/playlists/{id}/relationships/items', {
|
|
208
271
|
params: { path: { id: playlistId } },
|
|
209
272
|
});
|
|
210
273
|
if (itemsError || !itemsData) {
|
|
211
|
-
|
|
212
|
-
process.exit(1);
|
|
274
|
+
throw new Error(`Failed to get playlist items — ${JSON.stringify(itemsError)}`);
|
|
213
275
|
}
|
|
214
276
|
const items = itemsData.data ?? [];
|
|
215
277
|
const item = items.find((i) => i.id === trackId);
|
|
216
278
|
if (!item) {
|
|
217
|
-
|
|
218
|
-
process.exit(1);
|
|
279
|
+
throw new Error(`Track ${trackId} not found in playlist ${playlistId}.`);
|
|
219
280
|
}
|
|
220
281
|
const itemId = item.meta?.itemId;
|
|
221
282
|
if (!itemId) {
|
|
222
|
-
|
|
223
|
-
process.exit(1);
|
|
283
|
+
throw new Error(`Could not find itemId for track ${trackId}.`);
|
|
224
284
|
}
|
|
225
285
|
const meta = {};
|
|
226
286
|
if (positionBefore !== 'end') {
|
|
@@ -234,18 +294,27 @@ async function moveTrackInPlaylist(playlistId, trackId, positionBefore, json) {
|
|
|
234
294
|
},
|
|
235
295
|
});
|
|
236
296
|
if (error) {
|
|
237
|
-
|
|
238
|
-
process.exit(1);
|
|
239
|
-
}
|
|
240
|
-
if (json) {
|
|
241
|
-
console.log(JSON.stringify({ playlistId, trackId, positionBefore, moved: true }, null, 2));
|
|
242
|
-
return;
|
|
297
|
+
throw new Error(`Failed to move track — ${JSON.stringify(error)}`);
|
|
243
298
|
}
|
|
244
|
-
|
|
245
|
-
console.log(`\nTrack ${trackId} moved ${posDesc} in playlist ${playlistId}.`);
|
|
299
|
+
return { playlistId, trackId, positionBefore, moved: true };
|
|
246
300
|
}
|
|
247
|
-
async function
|
|
301
|
+
async function moveTrackInPlaylist(playlistId, trackId, positionBefore, json) {
|
|
248
302
|
const client = await (0, auth_1.getApiClient)();
|
|
303
|
+
try {
|
|
304
|
+
const result = await moveTrackInPlaylistData(playlistId, trackId, positionBefore, client);
|
|
305
|
+
if (json) {
|
|
306
|
+
console.log(JSON.stringify(result, null, 2));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const posDesc = positionBefore === 'end' ? 'to end of playlist' : `before item ${positionBefore}`;
|
|
310
|
+
console.log(`\nTrack ${trackId} moved ${posDesc} in playlist ${playlistId}.`);
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
console.error(`Error: ${err.message}`);
|
|
314
|
+
process.exit(1);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async function updatePlaylistDescriptionData(playlistId, description, client) {
|
|
249
318
|
const { error } = await client.PATCH('/playlists/{id}', {
|
|
250
319
|
params: { path: { id: playlistId } },
|
|
251
320
|
body: {
|
|
@@ -257,13 +326,23 @@ async function updatePlaylistDescription(playlistId, description, json) {
|
|
|
257
326
|
},
|
|
258
327
|
});
|
|
259
328
|
if (error) {
|
|
260
|
-
|
|
261
|
-
process.exit(1);
|
|
329
|
+
throw new Error(`Failed to update playlist description — ${JSON.stringify(error)}`);
|
|
262
330
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
331
|
+
return { id: playlistId, description, success: true };
|
|
332
|
+
}
|
|
333
|
+
async function updatePlaylistDescription(playlistId, description, json) {
|
|
334
|
+
const client = await (0, auth_1.getApiClient)();
|
|
335
|
+
try {
|
|
336
|
+
const result = await updatePlaylistDescriptionData(playlistId, description, client);
|
|
337
|
+
if (json) {
|
|
338
|
+
console.log(JSON.stringify(result, null, 2));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
console.log(`\nPlaylist ${playlistId} description updated.`);
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
console.error(`Error: ${err.message}`);
|
|
345
|
+
process.exit(1);
|
|
266
346
|
}
|
|
267
|
-
console.log(`\nPlaylist ${playlistId} description updated.`);
|
|
268
347
|
}
|
|
269
348
|
//# sourceMappingURL=playlist.js.map
|
package/dist/recommend.d.ts
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { MixCategory, RecommendationItem } from './types';
|
|
2
|
+
export type { MixCategory, RecommendationItem };
|
|
3
|
+
export declare function getRecommendationsData(client: any, countryCode: string, category?: MixCategory): Promise<RecommendationItem[]>;
|
|
4
|
+
export declare function getRecommendations(category: MixCategory | undefined, json: boolean): Promise<void>;
|
package/dist/recommend.js
CHANGED
|
@@ -1,36 +1,88 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRecommendationsData = getRecommendationsData;
|
|
3
4
|
exports.getRecommendations = getRecommendations;
|
|
4
5
|
const auth_1 = require("./auth");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const categoryEndpoints = {
|
|
7
|
+
daily: '/userDailyMixes/{id}',
|
|
8
|
+
discovery: '/userDiscoveryMixes/{id}',
|
|
9
|
+
'new-release': '/userNewReleaseMixes/{id}',
|
|
10
|
+
offline: '/userOfflineMixes/{id}',
|
|
11
|
+
};
|
|
12
|
+
async function getCategoryItems(category, client, countryCode) {
|
|
13
|
+
const { data, error } = await client.GET(categoryEndpoints[category], {
|
|
8
14
|
params: {
|
|
15
|
+
path: { id: 'me' },
|
|
9
16
|
query: {
|
|
10
|
-
countryCode
|
|
11
|
-
include: ['
|
|
17
|
+
countryCode,
|
|
18
|
+
include: ['items'],
|
|
12
19
|
},
|
|
13
20
|
},
|
|
14
21
|
});
|
|
15
22
|
if (error || !data) {
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
// Some categories (e.g. offline) may 404 for users without entitlement — treat as empty.
|
|
24
|
+
return [];
|
|
18
25
|
}
|
|
19
26
|
const included = data.included ?? [];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return
|
|
27
|
+
return included.map((item) => {
|
|
28
|
+
const attrs = item.attributes ?? {};
|
|
29
|
+
return {
|
|
30
|
+
id: item.id,
|
|
31
|
+
type: item.type,
|
|
32
|
+
name: attrs.title ?? attrs.name ?? 'Untitled',
|
|
33
|
+
category,
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async function getRecommendationsData(client, countryCode, category) {
|
|
38
|
+
if (category) {
|
|
39
|
+
return getCategoryItems(category, client, countryCode);
|
|
23
40
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
const categories = ['daily', 'discovery', 'new-release', 'offline'];
|
|
42
|
+
const results = await Promise.all(categories.map((c) => getCategoryItems(c, client, countryCode)));
|
|
43
|
+
return results.flat();
|
|
44
|
+
}
|
|
45
|
+
async function getRecommendations(category, json) {
|
|
46
|
+
const client = await (0, auth_1.getApiClient)();
|
|
47
|
+
const countryCode = await (0, auth_1.getCountryCode)();
|
|
48
|
+
try {
|
|
49
|
+
const items = await getRecommendationsData(client, countryCode, category);
|
|
50
|
+
if (json) {
|
|
51
|
+
console.log(JSON.stringify(items, null, 2));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (items.length === 0) {
|
|
55
|
+
console.log('No recommendations found.');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (category) {
|
|
59
|
+
console.log(`\nYour ${category} mixes:\n`);
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
console.log(` [${item.id}] (${item.type}) ${item.name}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log('\nYour recommendations:\n');
|
|
66
|
+
const grouped = items.reduce((acc, item) => {
|
|
67
|
+
const key = item.category ?? 'other';
|
|
68
|
+
(acc[key] ??= []).push(item);
|
|
69
|
+
return acc;
|
|
70
|
+
}, {});
|
|
71
|
+
for (const cat of ['daily', 'discovery', 'new-release', 'offline']) {
|
|
72
|
+
const list = grouped[cat];
|
|
73
|
+
if (!list?.length)
|
|
74
|
+
continue;
|
|
75
|
+
console.log(` ${cat}:`);
|
|
76
|
+
for (const item of list) {
|
|
77
|
+
console.log(` [${item.id}] (${item.type}) ${item.name}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
console.log();
|
|
27
82
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const name = attrs?.title ?? attrs?.name ?? 'Untitled';
|
|
32
|
-
console.log(` [${item.id}] (${item.type}) ${name}`);
|
|
83
|
+
catch (err) {
|
|
84
|
+
console.error(`Error: ${err.message}`);
|
|
85
|
+
process.exit(1);
|
|
33
86
|
}
|
|
34
|
-
console.log();
|
|
35
87
|
}
|
|
36
88
|
//# sourceMappingURL=recommend.js.map
|
package/dist/saved.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SavedItem, SavedItemType } from './types';
|
|
2
|
+
export type { SavedItem, SavedItemType };
|
|
3
|
+
export declare function listSavedItemsData(client: any): Promise<SavedItem[]>;
|
|
4
|
+
export declare function listSavedItems(json: boolean): Promise<void>;
|
|
5
|
+
export declare function addSavedItemData(itemType: SavedItemType, itemId: string, client: any): Promise<{
|
|
6
|
+
id: string;
|
|
7
|
+
type: SavedItemType;
|
|
8
|
+
added: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function addSavedItem(itemType: SavedItemType, itemId: string, json: boolean): Promise<void>;
|
|
11
|
+
export declare function removeSavedItemData(itemType: SavedItemType, itemId: string, client: any): Promise<{
|
|
12
|
+
id: string;
|
|
13
|
+
type: SavedItemType;
|
|
14
|
+
removed: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function removeSavedItem(itemType: SavedItemType, itemId: string, json: boolean): Promise<void>;
|