diff --git a/package.json b/package.json index c0679f4..f53737c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lucida", - "version": "2.0.0-28", + "version": "2.0.0-29", "description": "A modular music downloader tool", "main": "build/index.js", "type": "module", diff --git a/src/index.ts b/src/index.ts index 9c4b6fd..be82ae1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -91,6 +91,15 @@ class Lucida { }) ) } + async isrcLookup(isrc: string) { + const results = await Promise.all( + Object.values(this.modules).map(async (e) => { + if (e.isrcLookup) return await e.isrcLookup(isrc) + }) + ) + const moduleNames = Object.keys(this.modules) + return Object.fromEntries(results.map((e, i) => [moduleNames[i], e])) + } } export default Lucida diff --git a/src/streamers/deezer/main.ts b/src/streamers/deezer/main.ts index d0f7d8f..4d4974c 100644 --- a/src/streamers/deezer/main.ts +++ b/src/streamers/deezer/main.ts @@ -520,4 +520,14 @@ export default class Deezer implements StreamerWithLogin { explicit: userData.USER.EXPLICIT_CONTENT_LEVEL != 'explicit_hide' } } + + async isrcLookup(isrc: string): Promise { + const resp = <{ type?: 'track'; link?: string }>( + await (await fetch(`https://api.deezer.com/track/isrc:${isrc}`)).json() + ) + if (resp.type == 'track' && resp.link) { + const track = (await this.getByUrl(resp.link)).metadata + return track + } else throw new Error(`Not available on Deezer.`) + } } diff --git a/src/streamers/qobuz/main.ts b/src/streamers/qobuz/main.ts index a9fc7d9..54ea7e5 100644 --- a/src/streamers/qobuz/main.ts +++ b/src/streamers/qobuz/main.ts @@ -300,4 +300,12 @@ export default class Qobuz implements StreamerWithLogin { explicit: true } } + async isrcLookup(isrc: string): Promise { + const isrcUrl = (await this.search(isrc)).tracks?.[0]?.url + if (!isrcUrl) throw new Error(`Not available on Qobuz.`) + else { + const track = (await this.getByUrl(isrcUrl)).metadata + return track + } + } } diff --git a/src/streamers/spotify/main.ts b/src/streamers/spotify/main.ts index 7c5f517..96b4b76 100644 --- a/src/streamers/spotify/main.ts +++ b/src/streamers/spotify/main.ts @@ -5,7 +5,8 @@ import { ItemType, SearchResults, StreamerAccount, - StreamerWithLogin + StreamerWithLogin, + Track } from '../../types.js' class Spotify implements StreamerWithLogin { @@ -134,6 +135,11 @@ class Spotify implements StreamerWithLogin { tracks: results.tracks?.map((e) => parseTrack(e)) ?? [] } } + async isrcLookup(isrc: string): Promise { + const results = await this.search(`isrc:${isrc}`) + if (results?.tracks[0]) return (await this.getByUrl(results.tracks?.[0]?.url)).metadata + else throw new Error(`Not available on Spotify.`) + } async getAccountInfo(): Promise { const info = await this.client.get.me() diff --git a/src/streamers/tidal/main.ts b/src/streamers/tidal/main.ts index 085b1f4..6beec31 100644 --- a/src/streamers/tidal/main.ts +++ b/src/streamers/tidal/main.ts @@ -64,6 +64,24 @@ interface SubscriptionData { paymentOverdue: boolean } +interface RawSearchResults { + albums: { + items: RawAlbum[] + } + artists: { + items: RawArtist[] + } + tracks: { + items: RawTrack[] + } +} + +interface RawIsrcLookup { + limit: number + offset: number + items: RawTrack[] +} + export default class Tidal implements Streamer { tvToken: string tvSecret: string @@ -116,6 +134,11 @@ export default class Tidal implements Streamer { 'User-Agent': 'TIDAL_ANDROID/1039 okhttp/3.14.9' } } + async isrcLookup(isrc: string): Promise { + const isrcQuery = await this.#get('tracks', { isrc }) + if (isrcQuery?.items?.[0]) return (await this.getByUrl(isrcQuery.items[0].url)).metadata + else throw new Error(`Not available on Tidal.`) + } async #get( url: string, params: { [key: string]: string | number } = {}, @@ -257,17 +280,6 @@ export default class Tidal implements Streamer { return false } async search(query: string, limit = 20): Promise { - interface RawSearchResults { - albums: { - items: RawAlbum[] - } - artists: { - items: RawArtist[] - } - tracks: { - items: RawTrack[] - } - } const results = await this.#get('search/top-hits', { query: query, limit: limit, diff --git a/src/types.ts b/src/types.ts index 8ea2c9e..4df61b0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -149,6 +149,7 @@ export interface Streamer { hostnames: string[] testData?: StreamerTestData search(query: string, limit: number): Promise + isrcLookup?(isrc: string): Promise getTypeFromUrl(url: string): Promise getByUrl: | ((url: string) => Promise)