From 92c8263559d225a29ce5a0fb1ed549f8645d95ef Mon Sep 17 00:00:00 2001 From: Namkhai B Date: Mon, 11 Apr 2022 11:29:39 -0500 Subject: [PATCH] fix(api/searchMusic): Use Deezer's light gateway Improves search results by about 100% --- __tests__/api.ts | 2 +- src/api/api.ts | 4 ++-- src/api/request.ts | 26 ++++++++++++++++++++++++++ src/lib/request.ts | 16 ++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/__tests__/api.ts b/__tests__/api.ts index 28056b4..71f2d8f 100644 --- a/__tests__/api.ts +++ b/__tests__/api.ts @@ -137,7 +137,7 @@ test('SEARCH TRACK, ALBUM & ARTIST', async (t) => { const QUERY = 'Eminem'; const response = await api.searchMusic(QUERY, ['TRACK', 'ALBUM', 'ARTIST'], 1); - t.is(response.QUERY, QUERY.toLowerCase()); + t.is(response.QUERY, QUERY); t.truthy(response.TRACK.count > 0); t.truthy(response.ALBUM.count > 0); t.truthy(response.ARTIST.count > 0); diff --git a/src/api/api.ts b/src/api/api.ts index 70be46f..32e6039 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -1,4 +1,4 @@ -import {request, requestGet, requestPublicApi} from './request'; +import {request, requestLight, requestGet, requestPublicApi} from './request'; import type { albumType, trackType, @@ -113,7 +113,7 @@ type searchTypesProp = 'ALBUM' | 'ARTIST' | 'TRACK' | 'PLAYLIST' | 'RADIO' | 'SH * @param {Number} nb number of items to fetch */ export const searchMusic = (query: string, types: searchTypesProp[] = ['TRACK'], nb = 15): Promise => - request({query, nb, types}, 'mobile_suggest'); + requestLight({query, start: 0, nb, suggest: true, artist_suggest: true, top_tracks: true}, 'deezer.pageSearch'); /** * Get details about current user diff --git a/src/api/request.ts b/src/api/request.ts index 3edc39f..25ee43b 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -26,6 +26,32 @@ export const request = async (body: object, method: string) => { throw new Error(errorMessage); }; +/** + * Make POST requests to deezer api + * @param {Object} body post body + * @param {String} method request method + */ +export const requestLight = async (body: object, method: string) => { + const cacheKey = method + ':' + Object.entries(body).join(':'); + const cache = lru.get(cacheKey); + if (cache) { + return cache; + } + + const { + data: {error, results}, + } = await axios.post('https://www.deezer.com/ajax/gw-light.php', body, { + params: {method, api_version: '1.0'}, + }); + if (Object.keys(results).length > 0) { + lru.set(cacheKey, results); + return results; + } + + const errorMessage = Object.entries(error).join(', '); + throw new Error(errorMessage); +}; + /** * Make GET requests to deezer public api * @param {String} method request method diff --git a/src/lib/request.ts b/src/lib/request.ts index bdcad0b..f03285c 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -28,6 +28,19 @@ const instance = axios.create({ }, }); +const getApiToken = async (): Promise => { + const {data} = await instance.get('https://www.deezer.com/ajax/gw-light.php', { + params: { + method: 'deezer.getUserData', + api_version: '1.0', + api_token: 'null', + }, + }); + instance.defaults.params.sid = data.results.SESSION_ID; + instance.defaults.params.api_token = data.results.checkForm; + return data.results.checkForm; +}; + export const initDeezerApi = async (arl: string): Promise => { if (arl.length !== 192) { throw new Error(`Invalid arl. Length should be 192 characters. You have provided ${arl.length} characters.`); @@ -50,6 +63,9 @@ instance.interceptors.response.use(async (response: Record) => { } else if (response.data.error.code === 4) { await delay.range(1000, 1500); return await instance(response.config); + } else if (response.data.error.GATEWAY_ERROR) { + getApiToken(); + return await instance(response.config); } }