From 6fbcb100cf6856aaee087e6b119efe5d5c8cda5a Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Sun, 31 Oct 2021 18:19:39 +0100 Subject: [PATCH] Add Deezer advanced track search --- docs/Deezer/README.md | 26 ++++++++++++++ play-dl/Deezer/index.ts | 77 ++++++++++++++++++++++++++++++++++++++--- play-dl/index.ts | 2 +- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/docs/Deezer/README.md b/docs/Deezer/README.md index 75c582f..6f03caf 100644 --- a/docs/Deezer/README.md +++ b/docs/Deezer/README.md @@ -52,6 +52,32 @@ const results = await dz_search(query, { }); // Returns an array with one track, using exact matching ``` +### dz_advanced_track_search(options: `DeezerAdvancedSearchOptions`) + +_Searches Deezer for tracks using the specified metadata._ + +**Returns :** `DeezerTrack[]` an array of tracks + +#### `DeezerAdvancedSearchOptions` + +- **limit?** `number` The maximum number of results to return, maximum `100`, defaults to `10`. +- **artist?** `string` The name of the artist +- **album?** `string` The title of the album +- **title?** `string` The title of the track +- **label?** `string` The label that released the track +- **minDurationInSec?** `number` The minimum duration in seconds +- **maxDurationInSec?** `number` The maximum duration in seconds +- **minBpm?** `number` The minimum BPM +- **maxBpm?** `number` The minimum BPM + +```js +const results = await dz_advanced_track_search({ + limit: 1, + artist: 'Rick Astley', + title: 'Never Gonna Give You Up' +}); // Returns an array with one track +``` + ## Classes [ Returned by `deezer(url)` function ] ### DeezerTrack diff --git a/play-dl/Deezer/index.ts b/play-dl/Deezer/index.ts index fe4b427..39dccdc 100644 --- a/play-dl/Deezer/index.ts +++ b/play-dl/Deezer/index.ts @@ -14,6 +14,18 @@ interface DeezerSearchOptions { fuzzy?: boolean; } +interface DeezerAdvancedSearchOptions { + limit?: number; + artist?: string; + album?: string; + title?: string; + label?: string; + minDurationInSec?: number; + maxDurationInSec?: number; + minBPM?: number; + maxBPM?: number; +} + async function internalValidate(url: string): Promise { let urlObj; try { @@ -140,11 +152,9 @@ export async function dz_validate(url: string): Promise<'track' | 'playlist' | ' * @param query The search query * @param options Extra options to configure the search: * - * type?: The type to search for `'track'`, `'playlist'` or `'album'`. Defaults to `'track'`. - * - * limit?: The maximum number of results to return, maximum `100`, defaults to `10`. - * - * fuzzy?: Whether the search should be fuzzy or only return exact matches. Defaults to `true`. + * * type?: The type to search for `'track'`, `'playlist'` or `'album'`. Defaults to `'track'`. + * * limit?: The maximum number of results to return, maximum `100`, defaults to `10`. + * * fuzzy?: Whether the search should be fuzzy or only return exact matches. Defaults to `true`. * @returns An array of tracks, playlists or albums */ export async function dz_search(query: string, options: DeezerSearchOptions): Promise { @@ -188,3 +198,60 @@ export async function dz_search(query: string, options: DeezerSearchOptions): Pr return results; } + +/** + * Searches Deezer for tracks using the specified metadata. + * @param options The metadata and limit for the search + * + * * limit?: The maximum number of results to return, maximum `100`, defaults to `10`. + * * artist?: The name of the artist + * * album?: The title of the album + * * title?: The title of the track + * * label?: The label that released the track + * * minDurationInSec?: The minimum duration in seconds + * * maxDurationInSec?: The maximum duration in seconds + * * minBpm?: The minimum BPM + * * maxBpm?: The minimum BPM + * @returns An array of tracks matching the metadata + */ +export async function dz_advanced_track_search(options: DeezerAdvancedSearchOptions): Promise { + const limit = options.limit ?? 10; + + if (limit > 100) throw new Error('The maximum search limit for Deezer is 100'); + if (limit < 1) throw new Error('The minimum search limit for Deezer is 1'); + + const metadata: string[] = []; + if (options.artist) metadata.push(`artist:"${encodeURIComponent(options.artist)}"`); + + if (options.album) metadata.push(`album:"${encodeURIComponent(options.album)}"`); + + if (options.title) metadata.push(`track:"${encodeURIComponent(options.title)}"`); + + if (options.label) metadata.push(`label:"${encodeURIComponent(options.label)}"`); + + if (Number(options.minDurationInSec) !== NaN) metadata.push(`dur_min:${options.minDurationInSec}`); + + if (Number(options.maxDurationInSec) !== NaN) metadata.push(`dur_max:${options.maxDurationInSec}`); + + if (Number(options.minBPM) !== NaN) metadata.push(`bpm_min:${options.minBPM}`); + + if (Number(options.maxBPM) !== NaN) metadata.push(`bpm_max:${options.maxBPM}`); + + if (metadata.length === 0) throw new Error('At least one type of metadata is required.'); + + const response = await request(`https://api.deezer.com/search/track/?q=${metadata.join(' ')}&limit=${limit}`).catch( + (err: Error) => err + ); + + if (response instanceof Error) throw response; + + const jsonData = JSON.parse(response); + + if (jsonData.error) { + throw new Error(`Deezer API Error: ${jsonData.error.type}: ${jsonData.error.message}`); + } + + const results = jsonData.data.map((track: any) => new DeezerTrack(track, true)); + + return results; +} diff --git a/play-dl/index.ts b/play-dl/index.ts index 262920f..4083760 100644 --- a/play-dl/index.ts +++ b/play-dl/index.ts @@ -10,7 +10,7 @@ export { } from './YouTube'; export { spotify, sp_validate, refreshToken, is_expired, Spotify } from './Spotify'; export { soundcloud, so_validate, SoundCloud, SoundCloudStream, getFreeClientID } from './SoundCloud'; -export { deezer, dz_validate, dz_search, Deezer } from './Deezer'; +export { deezer, dz_validate, dz_search, dz_advanced_track_search, Deezer } from './Deezer'; export { setToken } from './token'; enum AudioPlayerStatus {