Skip to content
This repository was archived by the owner on Jun 1, 2024. It is now read-only.

Commit 13d1249

Browse files
committed
refactor(API): clean code
1 parent a179431 commit 13d1249

File tree

1 file changed

+45
-56
lines changed

1 file changed

+45
-56
lines changed

src/API.ts

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import SpotifyInfo from "spotify-url-info";
22
import SpotifyWebApi from "spotify-web-api-node";
33
import { fetch } from "undici";
4+
import { DisTubeError, isTruthy } from "distube";
45
import { parse as parseSpotifyUri } from "spotify-uri";
5-
import { DisTubeError } from "distube";
66

77
const SUPPORTED_TYPES = ["album", "playlist", "track", "artist"] as const;
88

@@ -42,7 +42,7 @@ type Data = Track | TrackList;
4242
let firstWarning1 = true;
4343
let firstWarning2 = true;
4444

45-
const apiError = (e: any) =>
45+
export const apiError = (e: any) =>
4646
new DisTubeError(
4747
"SPOTIFY_API_ERROR",
4848
`The URL is private or unavailable.${e?.body?.error?.message ? `\nDetails: ${e.body.error.message}` : ""}${
@@ -125,26 +125,27 @@ export class API {
125125
getData(url: `${string}/artist/${string}`): Promise<Artist>;
126126
getData(url: string): Promise<Data>;
127127
async getData(url: string): Promise<Data> {
128-
const parsedUrl = this.parseUrl(url);
129-
const id = (<any>parsedUrl).id;
128+
const { type, id } = this.parseUrl(url);
129+
130130
if (!id) throw new DisTubeError("SPOTIFY_API_INVALID_URL", "Invalid URL");
131-
if (!this.isSupportedTypes(parsedUrl.type)) {
132-
throw new DisTubeError("SPOTIFY_API_UNSUPPORTED_TYPE", "Unsupported URL type");
133-
}
131+
if (!this.isSupportedTypes(type)) throw new DisTubeError("SPOTIFY_API_UNSUPPORTED_TYPE", "Unsupported URL type");
132+
134133
await this.refreshToken();
135-
if (parsedUrl.type === "track") {
136-
if (!this._tokenAvailable) return info.getData(url);
137-
return api
138-
.getTrack(id)
139-
.then(({ body }) => body)
140-
.catch(e => {
141-
throw apiError(e);
142-
});
134+
if (type === "track") {
135+
if (!this._tokenAvailable) {
136+
return info.getData(url);
137+
}
138+
try {
139+
const { body } = await api.getTrack(id);
140+
return body;
141+
} catch (e) {
142+
throw apiError(e);
143+
}
143144
}
144145
if (!this._tokenAvailable) {
145146
const data = (await info.getData(url)) as EmbedList;
146147
return {
147-
type: parsedUrl.type,
148+
type,
148149
name: data.title,
149150
thumbnail: data.coverArt?.sources?.[0]?.url,
150151
url,
@@ -155,51 +156,39 @@ export class API {
155156
})),
156157
};
157158
}
158-
let name: string, thumbnail: string, tracks: Track[];
159159
try {
160-
switch (parsedUrl.type) {
161-
case "album": {
162-
const { body } = await api.getAlbum(id);
163-
name = body.name;
164-
thumbnail = body.images?.[0]?.url;
165-
url = body.external_urls?.spotify;
166-
tracks = await this.#getFullItems(body);
167-
break;
168-
}
169-
case "playlist": {
170-
const { body } = await api.getPlaylist(id);
171-
name = body.name;
172-
thumbnail = body.images?.[0]?.url;
173-
url = body.external_urls?.spotify;
174-
tracks = (await this.#getFullItems(body)).map(i => i.track);
175-
break;
176-
}
177-
case "artist": {
178-
const { body } = await api.getArtist(id);
179-
name = body.name;
180-
thumbnail = body.images?.[0]?.url;
181-
url = body.external_urls?.spotify;
182-
tracks = (await api.getArtistTopTracks(id, this.topTracksCountry)).body.tracks;
183-
break;
184-
}
185-
default:
186-
throw new DisTubeError("SPOTIFY_API_UNSUPPORTED_TYPE", "Unsupported URL type");
187-
}
188-
} catch (e: any) {
160+
const { body } = await api[type === "album" ? "getAlbum" : type === "playlist" ? "getPlaylist" : "getArtist"](id);
161+
return {
162+
type,
163+
name: body.name,
164+
thumbnail: body.images?.[0]?.url,
165+
url: body.external_urls?.spotify,
166+
tracks: (await this.#getTracks(body)).filter(t => t?.type === "track"),
167+
};
168+
} catch (e) {
189169
throw apiError(e);
190170
}
191-
return {
192-
type: parsedUrl.type,
193-
name,
194-
thumbnail,
195-
url,
196-
tracks: tracks.filter(t => t?.type === "track"),
197-
};
198171
}
199172

200-
#getFullItems(data: SpotifyApi.SingleAlbumResponse): Promise<SpotifyApi.TrackObjectSimplified[]>;
201-
#getFullItems(data: SpotifyApi.SinglePlaylistResponse): Promise<SpotifyApi.PlaylistTrackObject[]>;
202-
async #getFullItems(data: SpotifyApi.SingleAlbumResponse | SpotifyApi.SinglePlaylistResponse) {
173+
async #getTracks(
174+
data: SpotifyApi.SingleAlbumResponse | SpotifyApi.SinglePlaylistResponse | SpotifyApi.SingleArtistResponse,
175+
): Promise<Track[]> {
176+
switch (data.type) {
177+
case "artist": {
178+
return (await api.getArtistTopTracks(data.id, this.topTracksCountry)).body.tracks;
179+
}
180+
case "album": {
181+
return await this.#getPaginatedItems(data);
182+
}
183+
case "playlist": {
184+
return (await this.#getPaginatedItems(data)).map(i => i.track).filter(isTruthy);
185+
}
186+
}
187+
}
188+
189+
#getPaginatedItems(data: SpotifyApi.SingleAlbumResponse): Promise<SpotifyApi.TrackObjectSimplified[]>;
190+
#getPaginatedItems(data: SpotifyApi.SinglePlaylistResponse): Promise<SpotifyApi.PlaylistTrackObject[]>;
191+
async #getPaginatedItems(data: SpotifyApi.SingleAlbumResponse | SpotifyApi.SinglePlaylistResponse) {
203192
const items: (SpotifyApi.TrackObjectSimplified | SpotifyApi.PlaylistTrackObject)[] = data.tracks.items;
204193
const isPlaylist = data.type === "playlist";
205194
const limit = isPlaylist ? 100 : 50;

0 commit comments

Comments
 (0)