refactor(hifi): add getArtistBiography
This commit is contained in:
parent
e154215fc5
commit
a282b37d88
3 changed files with 43 additions and 13 deletions
43
js/HiFi.ts
43
js/HiFi.ts
|
|
@ -57,6 +57,7 @@ class HiFiClient {
|
||||||
readonly #albumTracksMax = 20;
|
readonly #albumTracksMax = 20;
|
||||||
readonly #albumTracksQueue: Array<() => void> = [];
|
readonly #albumTracksQueue: Array<() => void> = [];
|
||||||
readonly #countryCode: string;
|
readonly #countryCode: string;
|
||||||
|
readonly #locale: string;
|
||||||
readonly #clientId: string;
|
readonly #clientId: string;
|
||||||
readonly #clientSecret: string;
|
readonly #clientSecret: string;
|
||||||
readonly #emitter = new EventEmitter();
|
readonly #emitter = new EventEmitter();
|
||||||
|
|
@ -216,16 +217,27 @@ class HiFiClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
static #getOptions({
|
static #getOptions({
|
||||||
|
locale = 'en_US',
|
||||||
countryCode = 'US',
|
countryCode = 'US',
|
||||||
baseUrl = null,
|
baseUrl = null,
|
||||||
clientId = HiFiClient.BROWSER_CLIENT_ID,
|
clientId = HiFiClient.BROWSER_CLIENT_ID,
|
||||||
clientSecret = HiFiClient.BROWSER_CLIENT_SECRET,
|
clientSecret = HiFiClient.BROWSER_CLIENT_SECRET,
|
||||||
token,
|
token,
|
||||||
tokenExpiry,
|
tokenExpiry,
|
||||||
refreshToken: tokenRefresh,
|
refreshToken,
|
||||||
storage = [],
|
storage = [],
|
||||||
}: HiFiClient.ConstructorOptions = {}) {
|
}: HiFiClient.ConstructorOptions = {}): WithRequiredKeys<HiFiClient.ConstructorOptions> {
|
||||||
return { countryCode, baseUrl, clientId, clientSecret, token, tokenExpiry, tokenRefresh, storage };
|
return {
|
||||||
|
locale,
|
||||||
|
countryCode,
|
||||||
|
baseUrl,
|
||||||
|
clientId,
|
||||||
|
clientSecret,
|
||||||
|
token,
|
||||||
|
tokenExpiry,
|
||||||
|
refreshToken,
|
||||||
|
storage,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchToken(force: boolean = false, signal: AbortSignal | undefined = undefined) {
|
async fetchToken(force: boolean = false, signal: AbortSignal | undefined = undefined) {
|
||||||
|
|
@ -289,15 +301,16 @@ class HiFiClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(options: HiFiClient.ConstructorOptions = {}) {
|
constructor(options: HiFiClient.ConstructorOptions = {}) {
|
||||||
const { countryCode, baseUrl, clientId, clientSecret, token, tokenExpiry, tokenRefresh, storage } =
|
const { locale, countryCode, baseUrl, clientId, clientSecret, token, tokenExpiry, refreshToken, storage } =
|
||||||
HiFiClient.#getOptions(options);
|
HiFiClient.#getOptions(options);
|
||||||
|
this.#locale = locale;
|
||||||
this.#countryCode = countryCode;
|
this.#countryCode = countryCode;
|
||||||
this.#baseUrl = baseUrl;
|
this.#baseUrl = baseUrl;
|
||||||
this.#clientId = clientId;
|
this.#clientId = clientId;
|
||||||
this.#clientSecret = clientSecret;
|
this.#clientSecret = clientSecret;
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.appTokenExpiry = tokenExpiry;
|
this.appTokenExpiry = tokenExpiry;
|
||||||
this.refreshToken = tokenRefresh;
|
this.refreshToken = refreshToken;
|
||||||
|
|
||||||
for (const store of !Array.isArray(storage) ? [storage] : storage) {
|
for (const store of !Array.isArray(storage) ? [storage] : storage) {
|
||||||
this.#useStorage(store);
|
this.#useStorage(store);
|
||||||
|
|
@ -633,6 +646,17 @@ class HiFiClient {
|
||||||
return HiFiClient.#jsonResponse({ version: HiFiClient.API_VERSION, albums: page_data, tracks });
|
return HiFiClient.#jsonResponse({ version: HiFiClient.API_VERSION, albums: page_data, tracks });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getArtistBiography(artistId: number, signal?: AbortSignal) {
|
||||||
|
const url = `https://api.tidal.com/v1/artists/${artistId}/bio`;
|
||||||
|
const params = {
|
||||||
|
locale: this.#locale,
|
||||||
|
countryCode: this.#countryCode,
|
||||||
|
};
|
||||||
|
const data = await this.#fetchJson(url, params, signal);
|
||||||
|
|
||||||
|
return HiFiClient.#jsonResponse({ version: API_VERSION, data: data });
|
||||||
|
}
|
||||||
|
|
||||||
#buildCoverEntry(cover_slug: string, name?: string | null, track_id?: number | null) {
|
#buildCoverEntry(cover_slug: string, name?: string | null, track_id?: number | null) {
|
||||||
const slug = cover_slug.replace(/-/g, '/');
|
const slug = cover_slug.replace(/-/g, '/');
|
||||||
return {
|
return {
|
||||||
|
|
@ -922,6 +946,8 @@ class HiFiClient {
|
||||||
return new TidalResponse(
|
return new TidalResponse(
|
||||||
await this.getSimilarAlbums(Number(qp.id), qp.cursor ?? undefined, signal)
|
await this.getSimilarAlbums(Number(qp.id), qp.cursor ?? undefined, signal)
|
||||||
);
|
);
|
||||||
|
case '/artist/bio':
|
||||||
|
return new TidalResponse(await this.getArtistBiography(Number(qp.id), signal));
|
||||||
case '/artist':
|
case '/artist':
|
||||||
return new TidalResponse(
|
return new TidalResponse(
|
||||||
await this.getArtist(
|
await this.getArtist(
|
||||||
|
|
@ -1027,8 +1053,13 @@ namespace HiFiClient {
|
||||||
clientSecret?: string;
|
clientSecret?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConstructorOptions extends ClientOptions, TokenOptions, RefreshTokenOptions {
|
export interface LocaleOptions {
|
||||||
|
locale?: string;
|
||||||
countryCode?: string;
|
countryCode?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConstructorOptions
|
||||||
|
extends LocaleOptions, RefreshTokenOptions, ClientOptions, TokenOptions, RefreshTokenOptions {
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
storage?: Pick<Storage, 'setItem' | 'removeItem'>[] | Pick<Storage, 'setItem' | 'removeItem'>;
|
storage?: Pick<Storage, 'setItem' | 'removeItem'>[] | Pick<Storage, 'setItem' | 'removeItem'>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1240,15 +1240,10 @@ export class LosslessAPI {
|
||||||
if (cached) return cached;
|
if (cached) return cached;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = `https://api.tidal.com/v1/artists/${artistId}/bio?locale=en_US&countryCode=GB`;
|
const response = await HiFiClient.instance.query(`/artist/bio/?id=${artistId}`);
|
||||||
const response = await fetch(url, {
|
|
||||||
headers: {
|
|
||||||
'X-Tidal-Token': TIDAL_V2_TOKEN,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const { data } = await response.json();
|
||||||
if (data && data.text) {
|
if (data && data.text) {
|
||||||
const bio = {
|
const bio = {
|
||||||
text: data.text,
|
text: data.text,
|
||||||
|
|
|
||||||
4
js/global.d.ts
vendored
4
js/global.d.ts
vendored
|
|
@ -27,3 +27,7 @@ declare module 'https://cdn.jsdelivr.net/npm/client-zip@2.4.5/+esm' {
|
||||||
/** Creates a ZIP stream from an async iterable of file entries. */
|
/** Creates a ZIP stream from an async iterable of file entries. */
|
||||||
export function downloadZip(files: AsyncIterable<object>): Response;
|
export function downloadZip(files: AsyncIterable<object>): Response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WithRequiredKeys<T> = {
|
||||||
|
[K in keyof T]-?: T[K] | undefined;
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue