mirror of
https://gitlab.com/RemixDev/deezer-js.git
synced 2025-01-15 11:05:18 +00:00
First commit
This commit is contained in:
commit
f2ac5665e6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
node_modules
|
423
deezer/api.js
Normal file
423
deezer/api.js
Normal file
|
@ -0,0 +1,423 @@
|
|||
const got = require('got')
|
||||
|
||||
// Possible values for order parameter in search
|
||||
export const SearchOrder = {
|
||||
RANKING : "RANKING"
|
||||
TRACK_ASC : "TRACK_ASC"
|
||||
TRACK_DESC : "TRACK_DESC"
|
||||
ARTIST_ASC : "ARTIST_ASC"
|
||||
ARTIST_DESC : "ARTIST_DESC"
|
||||
ALBUM_ASC : "ALBUM_ASC"
|
||||
ALBUM_DESC : "ALBUM_DESC"
|
||||
RATING_ASC : "RATING_ASC"
|
||||
RATING_DESC : "RATING_DESC"
|
||||
DURATION_ASC : "DURATION_ASC"
|
||||
DURATION_DESC : "DURATION_DESC"
|
||||
}
|
||||
|
||||
export class API{
|
||||
constructor(cookie_jar, headers){
|
||||
this.http_headers = headers
|
||||
this.cookie_jar = cookie_jar
|
||||
this.access_token = null
|
||||
}
|
||||
|
||||
async api_call(method, args){
|
||||
if (typeof args == "undefined") args = {}
|
||||
if this.access_token: args.access_token = this.access_token
|
||||
try {
|
||||
const result_json = await got.get("https://api.deezer.com/" + method, {
|
||||
searchParams: args,
|
||||
cookieJar: this.cookie_jar,
|
||||
headers: this.http_headers,
|
||||
timeout: 30000
|
||||
}).json()
|
||||
} catch (error) {
|
||||
await new Promise(r => setTimeout(r, 2000)) // sleep(2000ms)
|
||||
return await this.api_call(method, args)
|
||||
}
|
||||
if (result_json.error){
|
||||
if (result_json.error.code){
|
||||
if ([4, 700].indexOf(result_json.error.code) != -1) {
|
||||
await new Promise(r => setTimeout(r, 5000)) // sleep(5000ms)
|
||||
return await this.api_call(method, args)
|
||||
}
|
||||
if (result_json.error.code == 100) throw new ItemsLimitExceededException(`ItemsLimitExceededException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 200) throw new PermissionException(`PermissionException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 300) throw new InvalidTokenException(`InvalidTokenException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 500) throw new WrongParameterException(`ParameterException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 501) throw new MissingParameterException(`MissingParameterException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 600) throw new InvalidQueryException(`InvalidQueryException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 800) throw new DataException(`DataException: ${method} ${result_json.error.message || ""}`)
|
||||
if (result_json.error.code == 901) throw new IndividualAccountChangedNotAllowedException(`IndividualAccountChangedNotAllowedException: ${method} ${result_json.error.message || ""}`)
|
||||
}
|
||||
throw APIError(result_json.error))
|
||||
}
|
||||
return result_json
|
||||
}
|
||||
|
||||
async get_album(album_id){
|
||||
return await this.api_call(`album/${album_id}`)
|
||||
}
|
||||
|
||||
async get_album_by_UPC(upc){
|
||||
return await this.get_album(`upc:${upc}`)
|
||||
}
|
||||
|
||||
async get_album_comments(album_id, index=0, limit=10){
|
||||
return await this.api_call(`album/${album_id}/comments`, {index, limit})
|
||||
}
|
||||
|
||||
async get_album_fans(album_id, index=0, limit=100){
|
||||
return await this.api_call(`album/${album_id}/fans`, {index, limit})
|
||||
}
|
||||
|
||||
async get_album_tracks(album_id, index=0, limit=-1){
|
||||
return await this.api_call(`album/${album_id}/tracks`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist(artist_id){
|
||||
return await this.api_call(`artist/${artist_id}`)
|
||||
}
|
||||
|
||||
async get_artist_top(artist_id, index=0, limit=10){
|
||||
return await this.api_call(`artist/${artist_id}/top`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist_albums(artist_id, index=0, limit=-1){
|
||||
return await this.api_call(`artist/${artist_id}/albums`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist_comments(artist_id, index=0, limit=10){
|
||||
return await this.api_call(`artist/${artist_id}/comments`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist_fans(artist_id, index=0, limit=100){
|
||||
return await this.api_call(`artist/${artist_id}/fans`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist_related(artist_id, index=0, limit=20){
|
||||
return await this.api_call(`artist/${artist_id}/related`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist_radio(artist_id, index=0, limit=25){
|
||||
return await this.api_call(`artist/${artist_id}/radio`, {index, limit})
|
||||
}
|
||||
|
||||
async get_artist_playlists(artist_id, index=0, limit=-1){
|
||||
return await this.api_call(`artist/${artist_id}/playlists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_chart(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`chart/${genre_id}`, {index, limit})
|
||||
}
|
||||
|
||||
async get_chart_tracks(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`chart/${genre_id}/tracks`, {index, limit})
|
||||
}
|
||||
|
||||
async get_chart_albums(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`chart/${genre_id}/albums`, {index, limit})
|
||||
}
|
||||
|
||||
async get_chart_artists(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`chart/${genre_id}/artists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_chart_playlists(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`chart/${genre_id}/playlists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_chart_podcasts(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`chart/${genre_id}/podcasts`, {index, limit})
|
||||
}
|
||||
|
||||
async get_comment(comment_id){
|
||||
return await this.api_call(`comment/${comment_id}`)
|
||||
}
|
||||
|
||||
async get_editorials(index=0, limit=10){
|
||||
return await this.api_call('editorial', {index, limit})
|
||||
}
|
||||
|
||||
async get_editorial(genre_id=0){
|
||||
return await this.api_call(`editorial/${genre_id}`)
|
||||
}
|
||||
|
||||
async get_editorial_selection(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`editorial/${genre_id}/selection`, {index, limit})
|
||||
}
|
||||
|
||||
async get_editorial_charts(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`editorial/${genre_id}/charts`, {index, limit})
|
||||
}
|
||||
|
||||
async get_editorial_releases(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`editorial/${genre_id}/releases`, {index, limit})
|
||||
}
|
||||
|
||||
async get_genres(index=0, limit=10){
|
||||
return await this.api_call('genre', {index, limit})
|
||||
}
|
||||
|
||||
async get_genre(genre_id=0){
|
||||
return await this.api_call(`genre/${genre_id}`)
|
||||
}
|
||||
|
||||
async get_genre_artists(genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`genre/${genre_id}/artists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_genre_radios( genre_id=0, index=0, limit=10){
|
||||
return await this.api_call(`genre/${genre_id}/radios`, {index, limit})
|
||||
}
|
||||
|
||||
async get_infos(){
|
||||
return await this.api_call('infos')
|
||||
}
|
||||
|
||||
async get_options(){
|
||||
return await this.api_call('options')
|
||||
}
|
||||
|
||||
async get_playlist(playlist_id){
|
||||
return await this.api_call(`playlist/${playlist_id}`)
|
||||
}
|
||||
|
||||
async get_playlist_comments(album_id, index=0, limit=10){
|
||||
return await this.api_call(`playlist/${album_id}/comments`, {index, limit})
|
||||
}
|
||||
|
||||
async get_playlist_fans(album_id, index=0, limit=100){
|
||||
return await this.api_call(`playlist/${album_id}/fans`, {index, limit})
|
||||
}
|
||||
|
||||
async get_playlist_tracks(album_id, index=0, limit=-1){
|
||||
return await this.api_call(`playlist/${album_id}/tracks`, {index, limit})
|
||||
}
|
||||
|
||||
async get_playlist_radio(album_id, index=0, limit=100){
|
||||
return await this.api_call(`playlist/${album_id}/radio`, {index, limit})
|
||||
}
|
||||
|
||||
async get_radios(index=0, limit=10){
|
||||
return await this.api_call('radio', {index, limit})
|
||||
}
|
||||
|
||||
async get_radios_genres(index=0, limit=25){
|
||||
return await this.api_call('radio/genres', {index, limit})
|
||||
}
|
||||
|
||||
async get_radios_top(index=0, limit=50){
|
||||
return await this.api_call('radio/top', {index, limit})
|
||||
}
|
||||
|
||||
async get_radios_lists(index=0, limit=25){
|
||||
return await this.api_call('radio/lists', {index, limit})
|
||||
}
|
||||
|
||||
async get_radio(radio_id){
|
||||
return await this.api_call(`radio/${radio_id}`)
|
||||
}
|
||||
|
||||
async get_radio_tracks(radio_id, index=0, limit=40){
|
||||
return await this.api_call(`radio/${radio_id}/tracks`, {index, limit})
|
||||
}
|
||||
|
||||
_generate_search_advanced_query(artist="", album="", track="", label="", dur_min=0, dur_max=0, bpm_min=0, bpm_max=0){
|
||||
let query = ""
|
||||
if (artist != "") query += `artist:"${artist}" `
|
||||
if (album != "") query += `album:"${album}" `
|
||||
if (track != "") query += `track:"${track}" `
|
||||
if (label != "") query += `label:"${label}" `
|
||||
if (dur_min != 0) query += `dur_min:"${dur_min}" `
|
||||
if (dur_max != 0) query += `dur_max:"${dur_max}" `
|
||||
if (bpm_min != 0) query += `bpm_min:"${bpm_min}" `
|
||||
if (bpm_max != 0) query += `bpm_max:"${bpm_max}" `
|
||||
return query.trim()
|
||||
}
|
||||
|
||||
_generate_search_args(query, strict=false, order, index=0, limit=25){
|
||||
let args = {q: query, index, limit}
|
||||
if (strict) args.strict = 'on'
|
||||
if (order) args.order = order
|
||||
return args
|
||||
}
|
||||
|
||||
async search(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search', args)
|
||||
}
|
||||
|
||||
async advanced_search(artist="", album="", track="", label="", dur_min=0, dur_max=0, bpm_min=0, bpm_max=0, strict=false, order, index=0, limit=25){
|
||||
const query = this._generate_search_advanced_query(artist, album, track, label, dur_min, dur_max, bpm_min, bpm_max)
|
||||
return await this.search(query, strict, order, index, limit)
|
||||
}
|
||||
|
||||
async search_album(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search/album', args)
|
||||
}
|
||||
|
||||
async search_artist(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search/artist', args)
|
||||
}
|
||||
|
||||
async search_playlist(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search/playlist', args)
|
||||
}
|
||||
|
||||
async search_radio(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search/radio', args)
|
||||
}
|
||||
|
||||
async search_track(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search/track', args)
|
||||
}
|
||||
|
||||
async search_user(query, strict=false, order, index=0, limit=25){
|
||||
const args = this._generate_search_args(query, strict, order, index, limit)
|
||||
return await this.api_call('search/user', args)
|
||||
}
|
||||
|
||||
async get_track(song_id){
|
||||
return await this.api_call(`track/${song_id}`)
|
||||
}
|
||||
|
||||
async get_track_by_ISRC(isrc){
|
||||
return await this.get_track(`isrc:${isrc}`)
|
||||
}
|
||||
|
||||
async get_user(user_id){
|
||||
return await this.api_call(`user/${user_id}`)
|
||||
}
|
||||
|
||||
async get_user_albums(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/albums`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_artists(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/artists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_artists(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/artists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_flow(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/flow`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_following(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/followings`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_followers(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/followers`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_playlists(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/playlists`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_radios(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/radios`, {index, limit})
|
||||
}
|
||||
|
||||
async get_user_tracks(user_id, index=0, limit=25){
|
||||
return await this.api_call(`user/${user_id}/tracks`, {index, limit})
|
||||
}
|
||||
|
||||
// Extra calls
|
||||
|
||||
async get_countries_charts(){
|
||||
let temp = await this.get_user_playlists('637006841', limit=-1)['data']
|
||||
result = temp.sort((a, b) => a.title.localeCompare(b.title)) // Sort all playlists
|
||||
if (!result[0].title.startsWith('Top')) result.shift() // Remove loved tracks playlist
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
async get_track_id_from_metadata(artist, track, album){
|
||||
artist = artist.replace("–", "-").replace("’", "'")
|
||||
track = track.replace("–", "-").replace("’", "'")
|
||||
album = album.replace("–", "-").replace("’", "'")
|
||||
|
||||
let resp = await this.advanced_search(artist=artist, track=track, album=album, limit=1)
|
||||
if (resp.data.length > 0) return resp.data[0].id
|
||||
|
||||
resp = await this.advanced_search(artist=artist, track=track, limit=1)
|
||||
if (resp.data.length > 0) return resp.data[0].id
|
||||
|
||||
// Try removing version
|
||||
if ( track.indexOf("(") != -1 && track.indexOf(")") != -1 && track.indexOf("(") < track.indexOf(")") ){
|
||||
resp = await this.advanced_search(artist=artist, track=track.split("(")[0], limit=1)
|
||||
if (resp.data.length > 0) return resp.data[0].id
|
||||
} else if ( track.indexOf(" - ") != -1) {
|
||||
resp = await this.advanced_search(artist=artist, track=track.split(" - ")[0], limit=1)
|
||||
if (resp.data.length > 0) return resp.data[0].id
|
||||
}
|
||||
|
||||
return "0"
|
||||
}
|
||||
}
|
||||
|
||||
// Base class for Deezer exceptions
|
||||
export class APIError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "APIError";
|
||||
}
|
||||
}
|
||||
export class ItemsLimitExceededException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "ItemsLimitExceededException";
|
||||
}
|
||||
}
|
||||
export class PermissionException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "PermissionException";
|
||||
}
|
||||
}
|
||||
export class InvalidTokenException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "InvalidTokenException";
|
||||
}
|
||||
}
|
||||
export class WrongParameterException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "WrongParameterException";
|
||||
}
|
||||
}
|
||||
export class MissingParameterException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "MissingParameterException";
|
||||
}
|
||||
}
|
||||
export class InvalidQueryException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "InvalidQueryException";
|
||||
}
|
||||
}
|
||||
export class DataException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "DataException";
|
||||
}
|
||||
}
|
||||
export class IndividualAccountChangedNotAllowedException extends APIError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "IndividualAccountChangedNotAllowedException";
|
||||
}
|
||||
}
|
429
deezer/gw.js
Normal file
429
deezer/gw.js
Normal file
|
@ -0,0 +1,429 @@
|
|||
const got = require('got')
|
||||
const {map_artist_album, map_user_track, map_user_artist, map_user_album, map_user_playlist} = require('./utils.js')
|
||||
|
||||
// Explicit Content Lyrics
|
||||
export const LyricsStatus = {
|
||||
NOT_EXPLICIT: 0 // Not Explicit
|
||||
EXPLICIT: 1 // Explicit
|
||||
UNKNOWN: 2 // Unknown
|
||||
EDITED: 3 // Edited
|
||||
PARTIALLY_EXPLICIT: 4 // Partially Explicit (Album "lyrics" only)
|
||||
PARTIALLY_UNKNOWN: 5 // Partially Unknown (Album "lyrics" only)
|
||||
NO_ADVICE: 6 // No Advice Available
|
||||
PARTIALLY_NO_ADVICE: 7 // Partially No Advice Available (Album "lyrics" only)
|
||||
}
|
||||
|
||||
export const PlaylistStatus = {
|
||||
PUBLIC: 0
|
||||
PRIVATE: 1
|
||||
COLLABORATIVE: 2
|
||||
}
|
||||
|
||||
|
||||
export const EMPTY_TRACK_OBJ = {
|
||||
SNG_ID: 0,
|
||||
SNG_TITLE: '',
|
||||
DURATION: 0,
|
||||
MD5_ORIGIN: 0,
|
||||
MEDIA_VERSION: 0,
|
||||
FILESIZE: 0,
|
||||
ALB_TITLE: "",
|
||||
ALB_PICTURE: "",
|
||||
ART_ID: 0,
|
||||
ART_NAME: ""
|
||||
}
|
||||
|
||||
export class GW{
|
||||
constructor(cookie_jar, headers){
|
||||
this.http_headers = headers
|
||||
this.cookie_jar = cookie_jar
|
||||
}
|
||||
|
||||
async api_call(method, args, params){
|
||||
if (typeof args == "unasyncined") args = {}
|
||||
if (typeof params == "unasyncined") params = {}
|
||||
p = {
|
||||
api_version: "1.0",
|
||||
api_token: method == 'deezer.getUserData' ? 'null' : this._get_token(),
|
||||
input: '3',
|
||||
method: method,
|
||||
..params
|
||||
}
|
||||
try{
|
||||
const result_json = await got.get("http://www.deezer.com/ajax/gw-light.php", {
|
||||
searchParams: p,
|
||||
json: args,
|
||||
cookieJar: this.cookie_jar,
|
||||
headers: this.http_headers,
|
||||
timeout: 30000
|
||||
}).json()
|
||||
}catch{
|
||||
await new Promise(r => setTimeout(r, 2000)) // sleep(2000ms)
|
||||
return await this.api_call(method, args, params)
|
||||
}
|
||||
if (result_json.error.length):
|
||||
throw new GWAPIError(result_json.error)
|
||||
return result_json.results
|
||||
}
|
||||
|
||||
async _get_token(){
|
||||
let token_data = await this.get_user_data()
|
||||
return token_data.checkForm
|
||||
}
|
||||
|
||||
async get_user_data(){
|
||||
return await this.api_call('deezer.getUserData')
|
||||
}
|
||||
|
||||
async get_user_profile_page(user_id, tab, limit=10){
|
||||
return await this.api_call('deezer.pageProfile', {user_id, tab, nb: limit})
|
||||
}
|
||||
|
||||
async get_child_accounts(){
|
||||
return await this.api_call('deezer.getChildAccounts')
|
||||
}
|
||||
|
||||
async get_track(sng_id){
|
||||
return await this.api_call('song.getData', {sng_id})
|
||||
}
|
||||
|
||||
async get_track_page(sng_id){
|
||||
return await this.api_call('deezer.pageTrack', {sng_id})
|
||||
}
|
||||
|
||||
async get_track_lyrics(sng_id){
|
||||
return await this.api_call('song.getLyrics', {sng_id})
|
||||
}
|
||||
|
||||
async get_tracks_gw(sng_ids){
|
||||
let tracks_array = []
|
||||
let body = await this.api_call('song.getListData', {sng_ids})
|
||||
let errors = 0
|
||||
for (let i = 0; i < sng_ids.length; i++){
|
||||
if (sng_ids[0] != 0){
|
||||
tracks_array.push(body.data[i - errors])
|
||||
} else {
|
||||
errors++
|
||||
tracks_array.push(EMPTY_TRACK_OBJ)
|
||||
}
|
||||
}
|
||||
return tracks_array
|
||||
}
|
||||
|
||||
async get_album(alb_id){
|
||||
return await this.api_call('album.getData', {alb_id})
|
||||
}
|
||||
|
||||
async get_album_page(alb_id){
|
||||
return await this.api_call('deezer.pageAlbum', {
|
||||
alb_id,
|
||||
lang: 'en',
|
||||
header: True,
|
||||
tab: 0
|
||||
})
|
||||
}
|
||||
|
||||
async get_album_tracks(alb_id){
|
||||
let tracks_array = []
|
||||
let body = await this.api_call('song.getListByAlbum', {alb_id, nb: -1})
|
||||
body.data.forEach(track => {
|
||||
let _track = track
|
||||
_track.POSITION = body.data.indexOf(track)
|
||||
tracks_array.push(_track)
|
||||
})
|
||||
return tracks_array
|
||||
}
|
||||
|
||||
async get_artist(art_id){
|
||||
return await this.api_call('artist.getData', {art_id})
|
||||
}
|
||||
|
||||
async get_artist_page(art_id){
|
||||
return this.api_call('deezer.pageArtist', {
|
||||
art_id,
|
||||
lang: 'en',
|
||||
header: True,
|
||||
tab: 0
|
||||
})
|
||||
}
|
||||
|
||||
async get_artist_top_tracks(art_id, limit=100){
|
||||
let tracks_array = []
|
||||
let body = await this.api_call('artist.getTopTrack', {art_id, nb: limit})
|
||||
body.data.forEach(track => {
|
||||
track.POSITION = body.data.indexOf(track)
|
||||
tracks_array.push(_track)
|
||||
})
|
||||
return tracks_array
|
||||
}
|
||||
|
||||
async get_artist_discography(art_id, index=0, limit=25){
|
||||
return await this.api_call('album.getDiscography', {
|
||||
art_id,
|
||||
discography_mode:"all",
|
||||
nb: limit,
|
||||
nb_songs: 0,
|
||||
start: index
|
||||
})
|
||||
}
|
||||
|
||||
async get_playlist(playlist_id){
|
||||
return await this.api_call('playlist.getData', {playlist_id})
|
||||
}
|
||||
|
||||
async get_playlist_page(playlist_id){
|
||||
return await this.api_call('deezer.pagePlaylist', {
|
||||
playlist_id,
|
||||
lang: 'en',
|
||||
header: True,
|
||||
tab: 0
|
||||
})
|
||||
}
|
||||
|
||||
async get_playlist_tracks(playlist_id){
|
||||
let tracks_array = []
|
||||
let body = await this.api_call('playlist.getSongs', {playlist_id, nb: -1})
|
||||
body.data.forEach(track => {
|
||||
track.POSITION = body.data.indexOf(track)
|
||||
tracks_array.push(_track)
|
||||
})
|
||||
return tracks_array
|
||||
}
|
||||
|
||||
async create_playlist(title, status=PlaylistStatus.PUBLIC, description, songs=[]){
|
||||
newSongs = []
|
||||
songs.forEach(song => {
|
||||
newSongs.push([song, 0])
|
||||
});
|
||||
return await this.api_call('playlist.create', {
|
||||
title,
|
||||
status,
|
||||
description,
|
||||
songs: newSongs
|
||||
})
|
||||
}
|
||||
|
||||
async edit_playlist(playlist_id, title, status, description, songs=[]){
|
||||
newSongs = []
|
||||
songs.forEach(song => {
|
||||
newSongs.push([song, 0])
|
||||
});
|
||||
return await this.api_call('playlist.update', {
|
||||
playlist_id,
|
||||
title,
|
||||
status,
|
||||
description,
|
||||
songs: newSongs
|
||||
})
|
||||
}
|
||||
|
||||
async add_songs_to_playlist(playlist_id, songs, offset=-1){
|
||||
newSongs = []
|
||||
songs.forEach(song => {
|
||||
newSongs.push([song, 0])
|
||||
});
|
||||
return await this.api_call('playlist.addSongs', {
|
||||
playlist_id,
|
||||
songs: newSongs,
|
||||
offset
|
||||
})
|
||||
}
|
||||
|
||||
async add_song_to_playlist(playlist_id, sng_id, offset=-1){
|
||||
return await this.add_songs_to_playlist(playlist_id, [sng_id], offset)
|
||||
}
|
||||
|
||||
async remove_songs_from_playlist(playlist_id, songs){
|
||||
newSongs = []
|
||||
songs.forEach(song => {
|
||||
newSongs.push([song, 0])
|
||||
});
|
||||
return await this.api_call('playlist.deleteSongs', {
|
||||
playlist_id,
|
||||
songs: newSongs
|
||||
})
|
||||
}
|
||||
|
||||
async remove_song_from_playlist(playlist_id, sng_id){
|
||||
return await this.remove_songs_from_playlist(playlist_id, [sng_id])
|
||||
}
|
||||
|
||||
async delete_playlist(playlist_id){
|
||||
return await this.api_call('playlist.delete', {playlist_id})
|
||||
}
|
||||
|
||||
async add_song_to_favorites(sng_id){
|
||||
return await this.gw_api_call('favorite_song.add', {sng_id})
|
||||
}
|
||||
|
||||
async remove_song_from_favorites(sng_id){
|
||||
return await this.gw_api_call('favorite_song.remove', {sng_id})
|
||||
}
|
||||
|
||||
async add_album_to_favorites(alb_id){
|
||||
return await this.gw_api_call('album.addFavorite', {alb_id})
|
||||
}
|
||||
|
||||
async remove_album_from_favorites(alb_id){
|
||||
return await this.gw_api_call('album.deleteFavorite', {alb_id})
|
||||
}
|
||||
|
||||
async add_artist_to_favorites(art_id){
|
||||
return await this.gw_api_call('artist.addFavorite', {art_id})
|
||||
}
|
||||
|
||||
async remove_artist_from_favorites(art_id){
|
||||
return await this.gw_api_call('artist.deleteFavorite', {art_id})
|
||||
}
|
||||
|
||||
async add_playlist_to_favorites(playlist_id){
|
||||
return await this.gw_api_call('playlist.addFavorite', {PARENT_PLAYLIST_ID: playlist_id})
|
||||
}
|
||||
|
||||
async remove_playlist_from_favorites(playlist_id){
|
||||
return await this.gw_api_call('playlist.deleteFavorite', {PLAYLIST_ID: playlist_id})
|
||||
}
|
||||
|
||||
async get_page(page){
|
||||
let params = {
|
||||
gateway_input: JSON.stringify({
|
||||
PAGE: page,
|
||||
VERSION: '2.3',
|
||||
SUPPORT: {
|
||||
grid: [
|
||||
'channel',
|
||||
'album'
|
||||
],
|
||||
horizontal-grid: [
|
||||
'album'
|
||||
],
|
||||
},
|
||||
LANG: 'en'
|
||||
})
|
||||
}
|
||||
return await this.api_call('page.get', params=params)
|
||||
}
|
||||
|
||||
async search(query, index=0, limit=10, suggest=true, artist_suggest=true, top_tracks=true){
|
||||
return await this.api_call('deezer.pageSearch', {
|
||||
query,
|
||||
start: index,
|
||||
nb: limit,
|
||||
suggest,
|
||||
artist_suggest,
|
||||
top_tracks
|
||||
})
|
||||
}
|
||||
|
||||
async search_music(query, type, index=0, limit=10){
|
||||
return await this.api_call('search.music', {
|
||||
query,
|
||||
filter: "ALL",
|
||||
output: type,
|
||||
start: index,
|
||||
nb: limit
|
||||
})
|
||||
}
|
||||
|
||||
// Extra calls
|
||||
|
||||
async get_artist_discography_tabs(art_id, limit=100){
|
||||
let index = 0
|
||||
let releases = []
|
||||
let result = {all: []}
|
||||
let ids = []
|
||||
|
||||
// Get all releases
|
||||
do {
|
||||
response = await this.get_artist_discography(art_id, index=index, limit=limit)
|
||||
releases.concat(response.data)
|
||||
index += limit
|
||||
} while (index < response.total)
|
||||
|
||||
releases.forEach(release => {
|
||||
if (ids.indexOf(release.ALB_ID) == -1){
|
||||
ids.push(release.ALB_ID)
|
||||
obj = map_artist_album(release)
|
||||
if ((release.ART_ID == art_id || release.ART_ID != art_id && release.ROLE_ID == 0) && release.ARTISTS_ALBUMS_IS_OFFICIAL){
|
||||
// Handle all base record types
|
||||
if (!result[obj.record_type]) result[obj.record_type] = []
|
||||
result[obj.record_type].push(obj)
|
||||
result.all.push(obj)
|
||||
}
|
||||
} else {
|
||||
if (release.ROLE_ID == 5) { // Handle albums where the artist is featured
|
||||
if (!result.featured) result.featured = []
|
||||
result.featured.push(obj)
|
||||
} else if release.ROLE_ID == 0 { // Handle "more" albums
|
||||
if (!result.more) result.more = []
|
||||
result.more.push(obj)
|
||||
result.all.push(obj)
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
async get_track_with_fallback(sng_id){
|
||||
let body
|
||||
if (int(sng_id) > 0){
|
||||
try{ body = await this.get_track_page(sng_id) }
|
||||
catch (e) {}
|
||||
}
|
||||
|
||||
if (body){
|
||||
if (body.LYRICS) body.DATA.LYRICS = body.LYRICS
|
||||
body = body.DATA
|
||||
} else {
|
||||
body = await this.get_track(sng_id)
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
async get_user_playlists(user_id, limit=25){
|
||||
let user_profile_page = await this.get_user_profile_page(user_id, 'playlists', limit=limit)
|
||||
let blog_name = user_profile_page.DATA.USER.BLOG_NAME || "Unknown"
|
||||
let data = user_profile_page.TAB.playlists.data
|
||||
let result = []
|
||||
data.forEach(playlist => {
|
||||
result.push(map_user_playlist(playlist, blog_name))
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
async get_user_albums(user_id, limit=25){
|
||||
let data = await this.get_user_profile_page(user_id, 'albums', limit=limit).TAB.albums.data
|
||||
let result = []
|
||||
data.forEach(album => {
|
||||
result.push(map_user_album(album))
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
async get_user_artists(user_id, limit=25){
|
||||
let data = this.get_user_profile_page(user_id, 'artists', limit=limit).TAB.artists.data
|
||||
let result = []
|
||||
data.forEach(artist => {
|
||||
result.push(map_user_artist(artist))
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
async get_user_tracks(user_id, limit=25){
|
||||
let data = this.get_user_profile_page(user_id, 'loved', limit=limit).TAB.loved.data
|
||||
let result = []
|
||||
data.forEach(track => {
|
||||
result.push(map_user_track(track))
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Base class for Deezer exceptions
|
||||
export class GWAPIError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "APIError";
|
||||
}
|
||||
}
|
127
deezer/index.js
Normal file
127
deezer/index.js
Normal file
|
@ -0,0 +1,127 @@
|
|||
const got = require('got')
|
||||
const {CookieJar, Cookie} = require('tough-cookie')
|
||||
const { API } = require('./api.js')
|
||||
const { GW } = require('./gw.js')
|
||||
|
||||
// Number associtation for formats
|
||||
export const TrackFormats = {
|
||||
FLAC : 9
|
||||
MP3_320 : 3
|
||||
MP3_128 : 1
|
||||
MP4_RA3 : 15
|
||||
MP4_RA2 : 14
|
||||
MP4_RA1 : 13
|
||||
DEFAULT : 8
|
||||
LOCAL : 0
|
||||
}
|
||||
|
||||
export class Deezer{
|
||||
constructor(accept_language=""){
|
||||
this.http_headers = {
|
||||
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36",
|
||||
"Accept-Language": accept_language
|
||||
}
|
||||
this.cookie_jar = new CookieJar()
|
||||
|
||||
this.logged_in = false
|
||||
this.current_user = {}
|
||||
this.childs = []
|
||||
this.selected_account = 0
|
||||
|
||||
this.api = new API(this.cookie_jar, this.http_headers)
|
||||
this.gw = new GW(this.cookie_jar, this.http_headers)
|
||||
}
|
||||
|
||||
get_accept_language(){
|
||||
return this.http_headers['Accept-Language']
|
||||
}
|
||||
|
||||
set_accept_language(lang){
|
||||
this.http_headers['Accept-Language'] = lang
|
||||
}
|
||||
|
||||
async login(email, password, re_captcha_token, child=0){
|
||||
// Check if user already logged in
|
||||
let user_data = await this.gw.get_user_data()
|
||||
if (user_data.USER.USER_ID == 0){
|
||||
this.logged_in = false
|
||||
return false
|
||||
}
|
||||
// Get the checkFormLogin
|
||||
let check_form_login = user_data.checkFormLogin
|
||||
let login = await got.post("https://www.deezer.com/ajax/action.php", {
|
||||
headers: this.http_headers,
|
||||
cookieJar: this.cookie_jar,
|
||||
form:{
|
||||
type: 'login',
|
||||
mail: email,
|
||||
password: password,
|
||||
checkFormLogin: check_form_login,
|
||||
reCaptchaToken: re_captcha_token
|
||||
}
|
||||
}).text()
|
||||
// Check if user logged in
|
||||
if (login.text.indexOf('success') == -1){
|
||||
this.logged_in = false
|
||||
return false
|
||||
}
|
||||
user_data = await this.gw.get_user_data()
|
||||
await this._post_login(user_data)
|
||||
this.change_account(child)
|
||||
this.logged_in = true
|
||||
return true
|
||||
}
|
||||
|
||||
async login_via_arl(arl, child=0){
|
||||
arl = arl.trim()
|
||||
// TODO: Check how to do this
|
||||
let cookie_obj = Cookie({
|
||||
key: 'arl',
|
||||
value: arl,
|
||||
path: "/",
|
||||
httpOnly: true
|
||||
})
|
||||
this.cookie_jar.setCookie(cookie_obj, '.deezer.com')
|
||||
|
||||
let user_data = await this.gw.get_user_data()
|
||||
// Check if user logged in
|
||||
if (user_data.USER.USER_ID == 0){
|
||||
this.logged_in = false
|
||||
return false
|
||||
}
|
||||
await this._post_login(user_data)
|
||||
this.change_account(child)
|
||||
this.logged_in = true
|
||||
return true
|
||||
}
|
||||
|
||||
async _post_login(user_data){
|
||||
this.childs = []
|
||||
let family = user_data.USER.MULTI_ACCOUNT.ENABLED
|
||||
if (family){
|
||||
let childs = await this.gw.get_child_accounts()
|
||||
childs.forEach(child => {
|
||||
this.childs.push({
|
||||
'id': child.USER_ID,
|
||||
'name': child.BLOG_NAME,
|
||||
'picture': child.USER_PICTURE || ""
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.childs.append({
|
||||
'id': user_data.USER.USER_ID,
|
||||
'name': user_data.USER.BLOG_NAME,
|
||||
'picture': user_data.USER.USER_PICTURE || ""
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
change_account(child_n){
|
||||
if (this.childs.length-1 < child_n) child_n = 0
|
||||
this.current_user = this.childs[child_n]
|
||||
this.selected_account = child_n
|
||||
|
||||
return [this.current_user, this.selected_account]
|
||||
}
|
||||
|
||||
}
|
212
deezer/utils.js
Normal file
212
deezer/utils.js
Normal file
|
@ -0,0 +1,212 @@
|
|||
const RELEASE_TYPE = ["single", "album", "compile", "ep", "bundle"]
|
||||
|
||||
// maps gw-light api user/tracks to standard api
|
||||
export function map_user_track(track){
|
||||
return {
|
||||
id: track.SNG_ID,
|
||||
title: track.SNG_TITLE,
|
||||
link: 'https://www.deezer.com/track/'+track.SNG_ID,
|
||||
duration: track.DURATION,
|
||||
rank: track.RANK_SNG,
|
||||
explicit_lyrics: int(track.EXPLICIT_LYRICS) > 0,
|
||||
explicit_content_lyrics: track.EXPLICIT_TRACK_CONTENT.EXPLICIT_COVER_STATUS,
|
||||
explicit_content_cover: track.EXPLICIT_TRACK_CONTENT.EXPLICIT_LYRICS_STATUS,
|
||||
time_add: track.DATE_ADD,
|
||||
album: {
|
||||
id: track.ALB_ID,
|
||||
title: track.ALB_TITLE,
|
||||
cover: 'https://api.deezer.com/album/'+track.ALB_ID+'/image',
|
||||
cover_small: 'https://e-cdns-images.dzcdn.net/images/cover/'+track.ALB_PICTURE+'/56x56-000000-80-0-0.jpg',
|
||||
cover_medium: 'https://e-cdns-images.dzcdn.net/images/cover/'+track.ALB_PICTURE+'/250x250-000000-80-0-0.jpg',
|
||||
cover_big: 'https://e-cdns-images.dzcdn.net/images/cover/'+track.ALB_PICTURE+'/500x500-000000-80-0-0.jpg',
|
||||
cover_xl: 'https://e-cdns-images.dzcdn.net/images/cover/'+track.ALB_PICTURE+'/1000x1000-000000-80-0-0.jpg',
|
||||
tracklist: 'https://api.deezer.com/album/'+track.ALB_ID+'/tracks',
|
||||
type: 'album'
|
||||
},
|
||||
artist: {
|
||||
id: track.ART_ID,
|
||||
name: track.ART_NAME,
|
||||
picture: 'https://api.deezer.com/artist/'+track.ART_ID+'/image',
|
||||
picture_small: 'https://e-cdns-images.dzcdn.net/images/artist/'+track.ART_PICTURE+'/56x56-000000-80-0-0.jpg',
|
||||
picture_medium: 'https://e-cdns-images.dzcdn.net/images/artist/'+track.ART_PICTURE+'/250x250-000000-80-0-0.jpg',
|
||||
picture_big: 'https://e-cdns-images.dzcdn.net/images/artist/'+track.ART_PICTURE+'/500x500-000000-80-0-0.jpg',
|
||||
picture_xl: 'https://e-cdns-images.dzcdn.net/images/artist/'+track.ART_PICTURE+'/1000x1000-000000-80-0-0.jpg',
|
||||
tracklist: 'https://api.deezer.com/artist/'+track.ART_ID+'/top?limit=50',
|
||||
type: 'artist'
|
||||
},
|
||||
type: 'track'
|
||||
}
|
||||
}
|
||||
|
||||
// maps gw-light api user/artists to standard api
|
||||
export function map_user_artist(artist){
|
||||
return {
|
||||
id: artist.ART_ID,
|
||||
name: artist.ART_NAME,
|
||||
link: 'https://www.deezer.com/artist/'+artist.ART_ID,
|
||||
picture: 'https://api.deezer.com/artist/'+artist.ART_ID+'/image',
|
||||
picture_small: 'https://e-cdns-images.dzcdn.net/images/artist/'+artist.ART_PICTURE+'/56x56-000000-80-0-0.jpg',
|
||||
picture_medium: 'https://e-cdns-images.dzcdn.net/images/artist/'+artist.ART_PICTURE+'/250x250-000000-80-0-0.jpg',
|
||||
picture_big: 'https://e-cdns-images.dzcdn.net/images/artist/'+artist.ART_PICTURE+'/500x500-000000-80-0-0.jpg',
|
||||
picture_xl: 'https://e-cdns-images.dzcdn.net/images/artist/'+artist.ART_PICTURE+'/1000x1000-000000-80-0-0.jpg',
|
||||
nb_fan: artist.NB_FAN,
|
||||
tracklist: 'https://api.deezer.com/artist/'+artist.ART_ID+'/top?limit=50',
|
||||
type: 'artist'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// maps gw-light api user/albums to standard api
|
||||
export function map_user_album(album){
|
||||
return {
|
||||
id: album.ALB_ID,
|
||||
title: album.ALB_TITLE,
|
||||
link: 'https://www.deezer.com/album/'+album.ALB_ID,
|
||||
cover: 'https://api.deezer.com/album/'+album.ALB_ID+'/image',
|
||||
cover_small: 'https://e-cdns-images.dzcdn.net/images/cover/'+album.ALB_PICTURE+'/56x56-000000-80-0-0.jpg',
|
||||
cover_medium: 'https://e-cdns-images.dzcdn.net/images/cover/'+album.ALB_PICTURE+'/250x250-000000-80-0-0.jpg',
|
||||
cover_big: 'https://e-cdns-images.dzcdn.net/images/cover/'+album.ALB_PICTURE+'/500x500-000000-80-0-0.jpg',
|
||||
cover_xl: 'https://e-cdns-images.dzcdn.net/images/cover/'+album.ALB_PICTURE+'/1000x1000-000000-80-0-0.jpg',
|
||||
tracklist: 'https://api.deezer.com/album/'+album.ALB_ID+'/tracks',
|
||||
explicit_lyrics: album.EXPLICIT_ALBUM_CONTENT.EXPLICIT_LYRICS_STATUS > 0,
|
||||
artist: {
|
||||
id: album.ART_ID,
|
||||
name: album.ART_NAME,
|
||||
picture: 'https://api.deezer.com/artist/'+album.ART_ID+'image',
|
||||
tracklist: 'https://api.deezer.com/artist/'+album.ART_ID+'/top?limit=50'
|
||||
},
|
||||
type: 'album'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// maps gw-light api user/playlists to standard api
|
||||
export function map_user_playlist(playlist, default_user_name=""){
|
||||
return {
|
||||
id: playlist.PLAYLIST_ID,
|
||||
title: playlist.TITLE,
|
||||
description: playlist.DESCRIPTION || "",
|
||||
nb_tracks: playlist.NB_SONG,
|
||||
link: 'https://www.deezer.com/playlist/'+playlist.PLAYLIST_ID,
|
||||
picture: 'https://api.deezer.com/playlist/'+playlist.PLAYLIST_ID+'/image',
|
||||
picture_small: 'https://e-cdns-images.dzcdn.net/images/'+playlist.PICTURE_TYPE+'/'+playlist.PLAYLIST_PICTURE+'/56x56-000000-80-0-0.jpg',
|
||||
picture_medium: 'https://e-cdns-images.dzcdn.net/images/'+playlist.PICTURE_TYPE+'/'+playlist.PLAYLIST_PICTURE+'/250x250-000000-80-0-0.jpg',
|
||||
picture_big: 'https://e-cdns-images.dzcdn.net/images/'+playlist.PICTURE_TYPE+'/'+playlist.PLAYLIST_PICTURE+'/500x500-000000-80-0-0.jpg',
|
||||
picture_xl: 'https://e-cdns-images.dzcdn.net/images/'+playlist.PICTURE_TYPE+'/'+playlist.PLAYLIST_PICTURE+'/1000x1000-000000-80-0-0.jpg',
|
||||
tracklist: 'https://api.deezer.com/playlist/'+playlist.PLAYLIST_ID+'/tracks',
|
||||
creation_date: playlist.DATE_ADD,
|
||||
creator: {
|
||||
id: playlist.PARENT_USER_ID,
|
||||
name: playlist.PARENT_USERNAME || default_user_name
|
||||
},
|
||||
type: 'playlist'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// maps gw-light api albums to standard api
|
||||
export function map_album(album){
|
||||
return {
|
||||
id: album.ALB_ID,
|
||||
title: album.ALB_TITLE,
|
||||
upc: "", // TODO: Needs to be checked
|
||||
link: `https://www.deezer.com/album/${album.ALB_ID}`,
|
||||
share: "", // TODO: Needs to be checked
|
||||
cover: `https://api.deezer.com/album/${album.ALB_ID}/image`,
|
||||
cover_small: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/56x56-000000-80-0-0.jpg`,
|
||||
cover_medium: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/250x250-000000-80-0-0.jpg`,
|
||||
cover_big: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/500x500-000000-80-0-0.jpg`,
|
||||
cover_xl: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/1000x1000-000000-80-0-0.jpg`,
|
||||
md5_image: album.ALB_PICTURE,
|
||||
genre_id: album.GENRE_ID,
|
||||
genres: [], // TODO: Needs to be checked
|
||||
label: "", // TODO: Needs to be checked
|
||||
nb_tracks: album.NUMBER_TRACK,
|
||||
duration: 0, // TODO: Needs to be checked
|
||||
fans: album.RANK,
|
||||
rating: 0, // TODO: Needs to be checked
|
||||
release_date: album.PHYSICAL_RELEASE_DATE,
|
||||
record_type: RELEASE_TYPE[int(album.TYPE)] || "unknown",
|
||||
available: true, // TODO: Needs to be checked
|
||||
alternative: null, // TODO: Needs to be checked
|
||||
tracklist: `https://api.deezer.com/album/${album.ALB_ID}/tracks`,
|
||||
explicit_lyrics: int(album.EXPLICIT_LYRICS) > 0,
|
||||
explicit_content_lyrics: 2, // TODO: Needs to be checked
|
||||
explicit_content_cover: 2, // TODO: Needs to be checked
|
||||
contributors: [], // TODO: Needs to be checked
|
||||
artist: null, // TODO: Needs to be checked
|
||||
tracks: [], // TODO: Needs to be checked
|
||||
type: album.__TYPE__,
|
||||
// Extras
|
||||
nb_disk: album.NUMBER_DISK
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// maps gw-light api artist/albums to standard api
|
||||
export function map_artist_album(album){
|
||||
return {
|
||||
id: album.ALB_ID,
|
||||
title: album.ALB_TITLE,
|
||||
link: `https://www.deezer.com/album/${album.ALB_ID}`,
|
||||
cover: `https://api.deezer.com/album/${album.ALB_ID}/image`,
|
||||
cover_small: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/56x56-000000-80-0-0.jpg`,
|
||||
cover_medium: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/250x250-000000-80-0-0.jpg`,
|
||||
cover_big: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/500x500-000000-80-0-0.jpg`,
|
||||
cover_xl: `https://cdns-images.dzcdn.net/images/cover/${album.ALB_PICTURE}/1000x1000-000000-80-0-0.jpg`,
|
||||
genre_id: album.GENRE_ID,
|
||||
fans: album.RANK,
|
||||
release_date: album.PHYSICAL_RELEASE_DATE,
|
||||
record_type: RELEASE_TYPE[int(album.TYPE)] || "unknown",
|
||||
tracklist: `https://api.deezer.com/album/${album.ALB_ID}/tracks`,
|
||||
explicit_lyrics: int(album.EXPLICIT_LYRICS) > 0,
|
||||
type: album.__TYPE__,
|
||||
// Extras
|
||||
nb_tracks: album.NUMBER_TRACK,
|
||||
nb_disk: album.NUMBER_DISK
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// maps gw-light api playlists to standard api
|
||||
export function map_playlist(playlist){
|
||||
return {
|
||||
id: playlist.PLAYLIST_ID,
|
||||
title: playlist.TITLE,
|
||||
description: playlist.DESCRIPTION,
|
||||
duration: playlist.DURATION,
|
||||
public: playlist.STATUS == 1,
|
||||
is_loved_track: playlist.TYPE == 4,
|
||||
collaborative: playlist.STATUS == 2,
|
||||
nb_tracks: playlist.NB_SONG,
|
||||
fans: playlist.NB_FAN,
|
||||
link: "https://www.deezer.com/playlist/"+playlist.PLAYLIST_ID,
|
||||
share: "https://www.deezer.com/playlist/"+playlist.PLAYLIST_ID,
|
||||
picture: "https://api.deezer.com/playlist/"+playlist.PLAYLIST_ID+"/image",
|
||||
picture_small: "https://cdns-images.dzcdn.net/images/"+playlist.PICTURE_TYPE+"/"+playlist.PLAYLIST_PICTURE+"/56x56-000000-80-0-0.jpg",
|
||||
picture_medium: "https://cdns-images.dzcdn.net/images/"+playlist.PICTURE_TYPE+"/"+playlist.PLAYLIST_PICTURE+"/250x250-000000-80-0-0.jpg",
|
||||
picture_big: "https://cdns-images.dzcdn.net/images/"+playlist.PICTURE_TYPE+"/"+playlist.PLAYLIST_PICTURE+"/500x500-000000-80-0-0.jpg",
|
||||
picture_xl: "https://cdns-images.dzcdn.net/images/"+playlist.PICTURE_TYPE+"/"+playlist.PLAYLIST_PICTURE+"/1000x1000-000000-80-0-0.jpg",
|
||||
checksum: playlist.CHECKSUM,
|
||||
tracklist: "https://api.deezer.com/playlist/"+playlist.PLAYLIST_ID+"/tracks",
|
||||
creation_date: playlist.DATE_ADD,
|
||||
creator: {
|
||||
id: playlist.PARENT_USER_ID,
|
||||
name: playlist.PARENT_USERNAME,
|
||||
tracklist: "https://api.deezer.com/user/"+playlist.PARENT_USER_ID+"/flow",
|
||||
type: "user"
|
||||
},
|
||||
type: "playlist"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Cleanup terms that can hurt search results
|
||||
export function clean_search_query(term){
|
||||
term = term.replaceAll(/ feat[\.]? /g, " ")
|
||||
term = term.replaceAll(/ ft[\.]? /g, " ")
|
||||
term = term.replaceAll(/\(feat[\.]? /g, " ")
|
||||
term = term.replaceAll(/\(ft[\.]? /g, " ")
|
||||
term = term.replace(' & ', " ").replace('–', "-").replace('—', "-")
|
||||
return term
|
||||
}
|
574
package-lock.json
generated
Normal file
574
package-lock.json
generated
Normal file
|
@ -0,0 +1,574 @@
|
|||
{
|
||||
"name": "deezer-js",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"got": "^11.8.2",
|
||||
"tough-cookie": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz",
|
||||
"integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz",
|
||||
"integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==",
|
||||
"dependencies": {
|
||||
"defer-to-connect": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cacheable-request": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz",
|
||||
"integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==",
|
||||
"dependencies": {
|
||||
"@types/http-cache-semantics": "*",
|
||||
"@types/keyv": "*",
|
||||
"@types/node": "*",
|
||||
"@types/responselike": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/http-cache-semantics": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz",
|
||||
"integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A=="
|
||||
},
|
||||
"node_modules/@types/keyv": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz",
|
||||
"integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "14.14.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.33.tgz",
|
||||
"integrity": "sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g=="
|
||||
},
|
||||
"node_modules/@types/responselike": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
|
||||
"integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-lookup": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
|
||||
"engines": {
|
||||
"node": ">=10.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-request": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz",
|
||||
"integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==",
|
||||
"dependencies": {
|
||||
"clone-response": "^1.0.2",
|
||||
"get-stream": "^5.1.0",
|
||||
"http-cache-semantics": "^4.0.0",
|
||||
"keyv": "^4.0.0",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"normalize-url": "^4.1.0",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-response": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
|
||||
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
|
||||
"dependencies": {
|
||||
"mimic-response": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response/node_modules/mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/defer-to-connect": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/got": {
|
||||
"version": "11.8.2",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz",
|
||||
"integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.0.0",
|
||||
"@szmarczak/http-timer": "^4.0.5",
|
||||
"@types/cacheable-request": "^6.0.1",
|
||||
"@types/responselike": "^1.0.0",
|
||||
"cacheable-lookup": "^5.0.3",
|
||||
"cacheable-request": "^7.0.1",
|
||||
"decompress-response": "^6.0.0",
|
||||
"http2-wrapper": "^1.0.0-beta.5.2",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
|
||||
},
|
||||
"node_modules/http2-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
|
||||
"dependencies": {
|
||||
"quick-lru": "^5.1.1",
|
||||
"resolve-alpn": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz",
|
||||
"integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
|
||||
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/p-cancelable": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz",
|
||||
"integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/quick-lru": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
|
||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-alpn": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz",
|
||||
"integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA=="
|
||||
},
|
||||
"node_modules/responselike": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
|
||||
"integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
|
||||
"dependencies": {
|
||||
"lowercase-keys": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
|
||||
"dependencies": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz",
|
||||
"integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ=="
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz",
|
||||
"integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==",
|
||||
"requires": {
|
||||
"defer-to-connect": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@types/cacheable-request": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz",
|
||||
"integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==",
|
||||
"requires": {
|
||||
"@types/http-cache-semantics": "*",
|
||||
"@types/keyv": "*",
|
||||
"@types/node": "*",
|
||||
"@types/responselike": "*"
|
||||
}
|
||||
},
|
||||
"@types/http-cache-semantics": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz",
|
||||
"integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A=="
|
||||
},
|
||||
"@types/keyv": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz",
|
||||
"integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.14.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.33.tgz",
|
||||
"integrity": "sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g=="
|
||||
},
|
||||
"@types/responselike": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
|
||||
"integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"cacheable-lookup": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="
|
||||
},
|
||||
"cacheable-request": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz",
|
||||
"integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==",
|
||||
"requires": {
|
||||
"clone-response": "^1.0.2",
|
||||
"get-stream": "^5.1.0",
|
||||
"http-cache-semantics": "^4.0.0",
|
||||
"keyv": "^4.0.0",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"normalize-url": "^4.1.0",
|
||||
"responselike": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"clone-response": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
|
||||
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
|
||||
"requires": {
|
||||
"mimic-response": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"requires": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"defer-to-connect": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"got": {
|
||||
"version": "11.8.2",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz",
|
||||
"integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==",
|
||||
"requires": {
|
||||
"@sindresorhus/is": "^4.0.0",
|
||||
"@szmarczak/http-timer": "^4.0.5",
|
||||
"@types/cacheable-request": "^6.0.1",
|
||||
"@types/responselike": "^1.0.0",
|
||||
"cacheable-lookup": "^5.0.3",
|
||||
"cacheable-request": "^7.0.1",
|
||||
"decompress-response": "^6.0.0",
|
||||
"http2-wrapper": "^1.0.0-beta.5.2",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"responselike": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"http-cache-semantics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
|
||||
},
|
||||
"http2-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
|
||||
"requires": {
|
||||
"quick-lru": "^5.1.1",
|
||||
"resolve-alpn": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
|
||||
},
|
||||
"keyv": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz",
|
||||
"integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==",
|
||||
"requires": {
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
|
||||
},
|
||||
"mimic-response": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
|
||||
},
|
||||
"normalize-url": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
|
||||
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"p-cancelable": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz",
|
||||
"integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"quick-lru": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
|
||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="
|
||||
},
|
||||
"resolve-alpn": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz",
|
||||
"integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA=="
|
||||
},
|
||||
"responselike": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
|
||||
"integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
|
||||
"requires": {
|
||||
"lowercase-keys": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
|
||||
"requires": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
}
|
19
package.json
Normal file
19
package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "deezer-js",
|
||||
"version": "0.0.1",
|
||||
"description": "A wrapper for all Deezer's APIs",
|
||||
"main": "deezer/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.rip/RemixDev/deezer-js"
|
||||
},
|
||||
"author": "RemixDev",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"got": "^11.8.2",
|
||||
"tough-cookie": "^4.0.0"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue