tidal: chunk playlist adding, fix next-paging handling
This commit is contained in:
@ -121,8 +121,13 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
try {
|
try {
|
||||||
let albumUrl: URL;
|
let albumUrl: URL;
|
||||||
if (nextLink) {
|
if (nextLink) {
|
||||||
|
this.logger.debug('getAlbumItems nextPage', nextLink);
|
||||||
albumUrl = new URL(nextLink);
|
albumUrl = new URL(nextLink);
|
||||||
} else {
|
} else {
|
||||||
|
this.logger.debug(
|
||||||
|
'getAlbumItems albumUrl',
|
||||||
|
`${this.apiBase}/albums/${albumId}/relationships/items`
|
||||||
|
);
|
||||||
albumUrl = new URL(`${this.apiBase}/albums/${albumId}/relationships/items`);
|
albumUrl = new URL(`${this.apiBase}/albums/${albumId}/relationships/items`);
|
||||||
albumUrl.searchParams.append('countryCode', 'DE');
|
albumUrl.searchParams.append('countryCode', 'DE');
|
||||||
}
|
}
|
||||||
@ -144,7 +149,12 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
return { id: x.id, type: x.type };
|
return { id: x.id, type: x.type };
|
||||||
});
|
});
|
||||||
if (respData.links?.next) {
|
if (respData.links?.next) {
|
||||||
const nextPage = await this.getAlbumItems(albumId, remaning, respData.links.next);
|
this.logger.debug('getAlbumItems requesting next page', respData.links.next);
|
||||||
|
const nextPage = await this.getAlbumItems(
|
||||||
|
albumId,
|
||||||
|
remaning,
|
||||||
|
this.apiBase + respData.links.next
|
||||||
|
);
|
||||||
tracks = tracks.concat(nextPage);
|
tracks = tracks.concat(nextPage);
|
||||||
}
|
}
|
||||||
return tracks;
|
return tracks;
|
||||||
@ -243,8 +253,23 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
this.logger.error('Could not check for tidal dupes', dbe);
|
this.logger.error('Could not check for tidal dupes', dbe);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This would be API v2, but that's still in beta and only allows adding an item *before* another one
|
// Tidal can only handle max. 20 items to be added at once
|
||||||
const options: RequestInit = {
|
// This isn't documented, but the API helpfully provides a useful error message
|
||||||
|
let chunkSize = 20;
|
||||||
|
const chunkedTracks: { id: string; type: string }[][] = [];
|
||||||
|
let chunkIndex = 0;
|
||||||
|
while (chunkIndex < tracks.length) {
|
||||||
|
chunkedTracks.push(tracks.slice(chunkIndex, chunkIndex + chunkSize));
|
||||||
|
chunkIndex += chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiUrl = new URL(`${this.apiBase}/playlists/${TIDAL_PLAYLIST_ID}/relationships/items`);
|
||||||
|
let options: RequestInit;
|
||||||
|
let request: Request;
|
||||||
|
let resp: Response | null = null;
|
||||||
|
let respTxt: string | null = null;
|
||||||
|
for (let chunk of chunkedTracks) {
|
||||||
|
options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `${token.token_type} ${token.access_token}`,
|
Authorization: `${token.token_type} ${token.access_token}`,
|
||||||
@ -252,17 +277,14 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
Accept: 'application/vnd.api+json'
|
Accept: 'application/vnd.api+json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
data: tracks,
|
data: chunk,
|
||||||
meta: {
|
meta: {
|
||||||
positionBefore: 'ffb6286e-237a-4dfc-bbf1-2fb0eb004ed5' // Hardcoded last element of list
|
positionBefore: 'ffb6286e-237a-4dfc-bbf1-2fb0eb004ed5' // Hardcoded last element of list
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
const apiUrl = new URL(`${this.apiBase}/playlists/${TIDAL_PLAYLIST_ID}/relationships/items`);
|
|
||||||
const request = new Request(apiUrl, options);
|
|
||||||
|
|
||||||
let resp: Response | null = null;
|
request = new Request(apiUrl, options);
|
||||||
let respTxt: string | null = null;
|
|
||||||
try {
|
try {
|
||||||
resp = await fetch(request);
|
resp = await fetch(request);
|
||||||
this.processTidalHeaders(resp.headers);
|
this.processTidalHeaders(resp.headers);
|
||||||
@ -281,7 +303,7 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
if (token == null) {
|
if (token == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.addToPlaylistRetry(song, remaning--);
|
await this.addToPlaylistRetry(song, remaning--);
|
||||||
}
|
}
|
||||||
} else if (respObj === null) {
|
} else if (respObj === null) {
|
||||||
switch (resp.status) {
|
switch (resp.status) {
|
||||||
@ -314,9 +336,8 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
'sec'
|
'sec'
|
||||||
);
|
);
|
||||||
// Try again secondsToWait sec later, just to be safe one additional second
|
// Try again secondsToWait sec later, just to be safe one additional second
|
||||||
setTimeout(() => {
|
await sleep(secondsToWait * 1000);
|
||||||
this.addToPlaylistRetry(song, remaning--);
|
await this.addToPlaylistRetry(song, remaning--);
|
||||||
}, secondsToWait * 1000);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -335,6 +356,7 @@ export class TidalPlaylistAdder extends OauthPlaylistAdder implements PlaylistAd
|
|||||||
this.logger.error('Add to playlist request failed', resp?.status, e);
|
this.logger.error('Add to playlist request failed', resp?.status, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public async addToPlaylist(song: SongInfo) {
|
public async addToPlaylist(song: SongInfo) {
|
||||||
await this.addToPlaylistRetry(song);
|
await this.addToPlaylistRetry(song);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user