mirror of
https://gitlab.com/RemixDev/deemix-js.git
synced 2024-12-28 02:16:08 +00:00
First commit
This commit is contained in:
commit
f19f744153
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
node_modules
|
81
deemix/index.js
Normal file
81
deemix/index.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
const got = require('got')
|
||||
const {
|
||||
generateTrackItem,
|
||||
generateAlbumItem,
|
||||
generatePlaylistItem,
|
||||
generateArtistItem,
|
||||
generateArtistDiscographyItem,
|
||||
generateArtistTopItem
|
||||
} = require('./itemgen.js')
|
||||
|
||||
async function parseLink(link){
|
||||
if (link.indexOf('deezer.page.link') != -1) link = await got.get(link).url // Resolve URL shortner
|
||||
// Remove extra stuff
|
||||
if (link.indexOf('?') != -1) link = link.substring(0, link.indexOf('?'))
|
||||
if (link.indexOf('&') != -1) link = link.substring(0, link.indexOf('&'))
|
||||
if (link.endsWith('/')) link = link.substring(0, link.length-1) // Remove last slash if present
|
||||
|
||||
let type, id
|
||||
|
||||
if (link.indexOf('deezer') == -1) return [link, type, id] // return if not a deezer link
|
||||
|
||||
if (link.search(/\/track\/(.+)/g) != -1){
|
||||
type = 'track'
|
||||
id = link.match(/\/track\/(.+)/g)[1]
|
||||
}else if (link.search(/\/playlist\/(\d+)/g) != -1){
|
||||
type = 'playlist'
|
||||
id = link.match(/\/playlist\/(\d+)/g)[1]
|
||||
}else if (link.search(/\/album\/(.+)/g) != -1){
|
||||
type = 'album'
|
||||
id = link.match(/\/album\/(.+)/g)[1]
|
||||
}else if (link.search(/\/artist\/(\d+)\/top_track/g) != -1){
|
||||
type = 'artist_top'
|
||||
id = link.match(/\/artist\/(\d+)\/top_track/g)[1]
|
||||
}else if (link.search(/\/artist\/(\d+)\/discography/g) != -1){
|
||||
type = 'artist_discography'
|
||||
id = link.match(/\/artist\/(\d+)\/discography/g)[1]
|
||||
}else if (link.search(/\/artist\/(\d+)/g) != -1){
|
||||
type = 'artist'
|
||||
id = link.match(/\/artist\/(\d+)/g)[1]
|
||||
}
|
||||
|
||||
return [link, type, id]
|
||||
}
|
||||
|
||||
async function generateDownloadObject(dz, link, bitrate){
|
||||
let [link, type, id] = await parseLink(link)
|
||||
|
||||
if (type == null || id == null) return null
|
||||
|
||||
switch (type) {
|
||||
case 'track':
|
||||
return generateTrackItem(dz, id, bitrate)
|
||||
case 'album':
|
||||
return generateAlbumItem(dz, id, bitrate)
|
||||
case 'playlist':
|
||||
return generatePlaylistItem(dz, id, bitrate)
|
||||
case 'artist':
|
||||
return generateArtistItem(dz, id, bitrate)
|
||||
case 'artist_discography':
|
||||
return generateArtistDiscographyItem(dz, id, bitrate)
|
||||
case 'artist_top':
|
||||
return generateArtistTopItem(dz, id, bitrate)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseLink,
|
||||
generateDownloadObject,
|
||||
VARIOUS_ARTISTS,
|
||||
types: {
|
||||
...require('./types/index.js'),
|
||||
...require('./types/Album.js'),
|
||||
...require('./types/Artist.js'),
|
||||
...require('./types/Date.js'),
|
||||
...require('./types/Lyrics.js'),
|
||||
...require('./types/Picture.js'),
|
||||
...require('./types/Playlist.js'),
|
||||
...require('./types/Track.js'),
|
||||
}
|
||||
}
|
246
deemix/itemgen.js
Normal file
246
deemix/itemgen.js
Normal file
|
@ -0,0 +1,246 @@
|
|||
async function generateTrackItem(dz, id, bitrate, trackAPI, albumAPI){
|
||||
// Check if is an isrc: url
|
||||
if (str(id).startsWith("isrc")){
|
||||
try {
|
||||
trackAPI = await dz.api.get_track(id)
|
||||
} catch {
|
||||
throw Exception("WrongURL")
|
||||
}
|
||||
|
||||
if (trackAPI.id && trackAPI.title){
|
||||
id = trackAPI.id
|
||||
} else {
|
||||
throw Exception("ISRCnotOnDeezer")
|
||||
}
|
||||
}
|
||||
|
||||
// Get essential track info
|
||||
try {
|
||||
trackAPI_gw = await dz.gw.get_track_with_fallback(id)
|
||||
} catch {
|
||||
throw Exception("WrongURL")
|
||||
}
|
||||
|
||||
let title = trackAPI_gw.SNG_TITLE.trim()
|
||||
if (trackAPI_gw.VERSION && title.indexOf(trackAPI_gw.VERSION.trim()) == -1){
|
||||
title += ` ${trackAPI_gw.VERSION.trim()}`
|
||||
}
|
||||
const explicit = bool(int(trackAPI_gw.EXPLICIT_LYRICS || "0"))
|
||||
|
||||
return Single({
|
||||
type: 'track',
|
||||
id: id,
|
||||
bitrate: bitrate,
|
||||
title: title,
|
||||
artist: trackAPI_gw.ART_NAME,
|
||||
cover: `https://e-cdns-images.dzcdn.net/images/cover/${trackAPI_gw.ALB_PICTURE}/75x75-000000-80-0-0.jpg`,
|
||||
explicit: explicit,
|
||||
single: {
|
||||
trackAPI_gw: trackAPI_gw,
|
||||
trackAPI: trackAPI,
|
||||
albumAPI: albumAPI
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function generateAlbumItem(dz, id, bitrate, rootArtist){
|
||||
// Get essential album info
|
||||
let albumAPI
|
||||
try{
|
||||
albumAPI = dz.api.get_album(id)
|
||||
} catch {
|
||||
throw Exception("WrongURL")
|
||||
}
|
||||
|
||||
if str(id).startswith('upc') { id = albumAPI['id'] }
|
||||
|
||||
// Get extra info about album
|
||||
// This saves extra api calls when downloading
|
||||
let albumAPI_gw = dz.gw.get_album(id)
|
||||
albumAPI.nb_disk = albumAPI_gw.NUMBER_DISK
|
||||
albumAPI.copyright = albumAPI_gw.COPYRIGHT
|
||||
albumAPI.root_artist = rootArtist
|
||||
|
||||
// If the album is a single download as a track
|
||||
if (albumAPI.nb_tracks == 1){
|
||||
return generateTrackItem(dz, albumAPI.tracks.data[0].id, bitrate, null, albumAPI)
|
||||
}
|
||||
|
||||
tracksArray = dz.gw.get_album_tracks(id)
|
||||
|
||||
if (albumAPI.cover_small){
|
||||
const cover = albumAPI.cover_small.substring(0, albumAPI.cover_small.length-24) + '/75x75-000000-80-0-0.jpg'
|
||||
}else{
|
||||
const cover = `https://e-cdns-images.dzcdn.net/images/cover/${albumAPI_gw.ALB_PICTURE}/75x75-000000-80-0-0.jpg`
|
||||
}
|
||||
|
||||
const totalSize = tracksArray.length
|
||||
albumAPI.nb_tracks = totalSize
|
||||
let collection = []
|
||||
tracksArray.forEach((trackAPI, pos) => {
|
||||
trackAPI.POSITION = pos+1
|
||||
trackAPI.SIZE = totalSize
|
||||
collection.push(trackAPI)
|
||||
})
|
||||
|
||||
explicit = albumAPI_gw.get('EXPLICIT_ALBUM_CONTENT', {}).get('EXPLICIT_LYRICS_STATUS', LyricsStatus.UNKNOWN) in [LyricsStatus.EXPLICIT, LyricsStatus.PARTIALLY_EXPLICIT]
|
||||
|
||||
return Collection({
|
||||
type: 'album',
|
||||
id: id,
|
||||
bitrate: bitrate,
|
||||
title: albumAPI.title,
|
||||
artist: albumAPI.artist.name,
|
||||
cover: cover,
|
||||
explicit: explicit,
|
||||
size: totalSize,
|
||||
collection: {
|
||||
tracks_gw: collection,
|
||||
albumAPI: albumAPI
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function generatePlaylistItem(dz, id, bitrate, playlistAPI, playlistTracksAPI){
|
||||
if (!playlistAPI){
|
||||
// Get essential playlist info
|
||||
try{
|
||||
playlistAPI = dz.api.get_playlist(id)
|
||||
}catch{
|
||||
playlistAPI = null
|
||||
}
|
||||
// Fallback to gw api if the playlist is private
|
||||
if (!playlistAPI){
|
||||
try{
|
||||
let userPlaylist = dz.gw.get_playlist_page(id)
|
||||
playlistAPI = map_user_playlist(userPlaylist['DATA'])
|
||||
}catch{
|
||||
throw Exception("WrongURL")
|
||||
}
|
||||
}
|
||||
// Check if private playlist and owner
|
||||
if (!playlsitAPI.public && playlistAPI.creator.id != dz.current_user.id){
|
||||
throw Exception("notYourPrivatePlaylist")
|
||||
}
|
||||
}
|
||||
|
||||
if (!playlistTracksAPI){
|
||||
playlistTracksAPI = dz.gw.get_playlist_tracks(id)
|
||||
}
|
||||
playlistAPI.various_artist = dz.api.get_artist(5080) // Useful for save as compilation
|
||||
|
||||
const totalSize = playlistTracksAPI.length
|
||||
playlistAPI.nb_tracks = totalSize
|
||||
let collection = []
|
||||
playlistTracksAPI.forEach((trackAPI, pos) => {
|
||||
//TODO: Add explicit check
|
||||
trackAPI.POSITION = pos+1
|
||||
trackAPI.SIZE = totalSize
|
||||
collection.push(trackAPI)
|
||||
});
|
||||
|
||||
if (!playlistAPI.explicit) playlistAPI.explicit = false
|
||||
|
||||
return Collection({
|
||||
type: 'playlist',
|
||||
id: id,
|
||||
bitrate: bitrate,
|
||||
title: playlistAPI.title,
|
||||
artist: playlistAPI.creator.name,
|
||||
cover: playlistAPI.cover_small.substring(0, playlistAPI.cover_small.length-24) + '/75x75-000000-80-0-0.jpg',
|
||||
explicit: playlistAPI.explicit,
|
||||
size: totalSize,
|
||||
collection: {
|
||||
tracks_gw: collection,
|
||||
playlistAPI: playlistAPI
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function generateArtistItem(dz, id, bitrate, interface=None):
|
||||
// Get essential artist info
|
||||
try:
|
||||
artistAPI = dz.api.get_artist(id)
|
||||
except APIError as e:
|
||||
e = str(e)
|
||||
raise GenerationError("https://deezer.com/artist/"+str(id), f"Wrong URL: {e}")
|
||||
|
||||
if interface: interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
|
||||
rootArtist = {
|
||||
'id': artistAPI['id'],
|
||||
'name': artistAPI['name']
|
||||
}
|
||||
|
||||
artistDiscographyAPI = dz.gw.get_artist_discography_tabs(id, 100)
|
||||
allReleases = artistDiscographyAPI.pop('all', [])
|
||||
albumList = []
|
||||
for album in allReleases:
|
||||
albumList.append(generateAlbumItem(dz, album['id'], bitrate, rootArtist=rootArtist))
|
||||
|
||||
if interface: interface.send("finishAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
|
||||
return albumList
|
||||
|
||||
async function generateArtistDiscographyItem(dz, id, bitrate, interface=None):
|
||||
// Get essential artist info
|
||||
try:
|
||||
artistAPI = dz.api.get_artist(id)
|
||||
except APIError as e:
|
||||
e = str(e)
|
||||
raise GenerationError("https://deezer.com/artist/"+str(id)+"/discography", f"Wrong URL: {e}")
|
||||
|
||||
if interface: interface.send("startAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
|
||||
rootArtist = {
|
||||
'id': artistAPI['id'],
|
||||
'name': artistAPI['name']
|
||||
}
|
||||
|
||||
artistDiscographyAPI = dz.gw.get_artist_discography_tabs(id, 100)
|
||||
artistDiscographyAPI.pop('all', None) // all contains albums and singles, so its all duplicates. This removes them
|
||||
albumList = []
|
||||
for type in artistDiscographyAPI:
|
||||
for album in artistDiscographyAPI[type]:
|
||||
albumList.append(generateAlbumItem(dz, album['id'], bitrate, rootArtist=rootArtist))
|
||||
|
||||
if interface: interface.send("finishAddingArtist", {'name': artistAPI['name'], 'id': artistAPI['id']})
|
||||
return albumList
|
||||
|
||||
async function generateArtistTopItem(dz, id, bitrate, interface=None):
|
||||
// Get essential artist info
|
||||
try:
|
||||
artistAPI = dz.api.get_artist(id)
|
||||
except APIError as e:
|
||||
e = str(e)
|
||||
raise GenerationError("https://deezer.com/artist/"+str(id)+"/top_track", f"Wrong URL: {e}")
|
||||
|
||||
// Emulate the creation of a playlist
|
||||
// Can't use generatePlaylistItem directly as this is not a real playlist
|
||||
playlistAPI = {
|
||||
'id': str(artistAPI['id'])+"_top_track",
|
||||
'title': artistAPI['name']+" - Top Tracks",
|
||||
'description': "Top Tracks for "+artistAPI['name'],
|
||||
'duration': 0,
|
||||
'public': True,
|
||||
'is_loved_track': False,
|
||||
'collaborative': False,
|
||||
'nb_tracks': 0,
|
||||
'fans': artistAPI['nb_fan'],
|
||||
'link': "https://www.deezer.com/artist/"+str(artistAPI['id'])+"/top_track",
|
||||
'share': None,
|
||||
'picture': artistAPI['picture'],
|
||||
'picture_small': artistAPI['picture_small'],
|
||||
'picture_medium': artistAPI['picture_medium'],
|
||||
'picture_big': artistAPI['picture_big'],
|
||||
'picture_xl': artistAPI['picture_xl'],
|
||||
'checksum': None,
|
||||
'tracklist': "https://api.deezer.com/artist/"+str(artistAPI['id'])+"/top",
|
||||
'creation_date': "XXXX-00-00",
|
||||
'creator': {
|
||||
'id': "art_"+str(artistAPI['id']),
|
||||
'name': artistAPI['name'],
|
||||
'type': "user"
|
||||
},
|
||||
'type': "playlist"
|
||||
}
|
||||
|
||||
artistTopTracksAPI_gw = dz.gw.get_artist_toptracks(id)
|
||||
return generatePlaylistItem(dz, playlistAPI['id'], bitrate, playlistAPI=playlistAPI, playlistTracksAPI=artistTopTracksAPI_gw)
|
164
deemix/types/Album.js
Normal file
164
deemix/types/Album.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
const { LyricsStatus } = require('deezer-js').gw
|
||||
|
||||
const { removeDuplicateArtists, removeFeatures } = require('../utils/index.js')
|
||||
const { Artist } = require('./Artist.js')
|
||||
const { Date } = require('./Date.js')
|
||||
const { Picture } = require('./Picture.js')
|
||||
const { VARIOUS_ARTISTS } = require('./index.js')
|
||||
|
||||
class Album {
|
||||
constructor(id = 0, title = "", pic_md5 = ""){
|
||||
this.id = id
|
||||
this.title = title
|
||||
this.pic = Picture(md5=pic_md5, type="cover")
|
||||
this.artist = {"Main": []}
|
||||
this.artists = []
|
||||
self.mainArtist = null
|
||||
this.date = Date()
|
||||
this.dateString = ""
|
||||
this.trackTotal = "0"
|
||||
this.discTotal = "0"
|
||||
this.embeddedCoverPath = ""
|
||||
this.embeddedCoverURL = ""
|
||||
this.explicit = false
|
||||
this.genre = []
|
||||
this.barcode = "Unknown"
|
||||
this.label = "Unknown"
|
||||
this.recordType = "album"
|
||||
this.bitrate = 0
|
||||
self.rootArtist = null
|
||||
self.variousArtists = null
|
||||
}
|
||||
|
||||
parseAlbum(albumAPI){
|
||||
this.title = albumAPI.title
|
||||
|
||||
// Getting artist image ID
|
||||
// ex: https://e-cdns-images.dzcdn.net/images/artist/f2bc007e9133c946ac3c3907ddc5d2ea/56x56-000000-80-0-0.jpg
|
||||
let art_pic = albumAPI.artist.picture_small
|
||||
art_pic = art_pic.substring( art_pic.indexOf('artist/')+7, art_pic.length-24 )
|
||||
this.mainArtist = Artist(
|
||||
albumAPI.artist.id,
|
||||
albumAPI.artist.name,
|
||||
pic_md5 = art_pic
|
||||
)
|
||||
if (albumAPI.root_artist){
|
||||
let art_pic = albumAPI.root_artist.picture_small
|
||||
art_pic = art_pic.substring( art_pic.indexOf('artist/')+7, art_pic.length-24 )
|
||||
this.rootArtist = Artist(
|
||||
albumAPI.root_artist.id,
|
||||
albumAPI.root_artist.name,
|
||||
pic_md5 = art_pic
|
||||
)
|
||||
}
|
||||
|
||||
albumAPI.contributors.forEach(artist => {
|
||||
let isVariousArtists = str(artist.id) == VARIOUS_ARTISTS
|
||||
let isMainArtist = artist.role == "Main"
|
||||
|
||||
if (isVariousArtists){
|
||||
this.variousArtists = Artist(
|
||||
artist.id,
|
||||
artist.name,
|
||||
artist.role
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (this.artists.includes(artist.name)){
|
||||
this.artists.push(artist.name)
|
||||
}
|
||||
|
||||
if (isMainArtist || !this.artist['Main'].includes(artist.name) && !isMainArtist){
|
||||
if (!this.artist[artist.role]) this.artist[artist.role] = []
|
||||
this.artist[artist.role].push(artist.name)
|
||||
}
|
||||
});
|
||||
|
||||
this.trackTotal = albumAPI.nb_tracks
|
||||
this.recordType = albumAPI.record_type
|
||||
|
||||
this.barcode = albumAPI.upc || this.barcode
|
||||
this.label = albumAPI.label || this.label
|
||||
this.explicit = bool(albumAPI.explicit_lyrics || false)
|
||||
if (albumAPI.release_date){
|
||||
this.date.year = albumAPI.release_date.substring(0,4)
|
||||
this.date.month = albumAPI.release_date.substring(5,7)
|
||||
this.date.day = albumAPI.release_date.substring(8,10)
|
||||
this.date.fixDayMonth()
|
||||
}
|
||||
|
||||
this.discTotal = albumAPI.nb_disk || "1"
|
||||
this.copyright = albumAPI.copyright
|
||||
|
||||
if (this.pic.md5 == ""){
|
||||
// Getting album cover MD5
|
||||
// ex: https://e-cdns-images.dzcdn.net/images/cover/2e018122cb56986277102d2041a592c8/56x56-000000-80-0-0.jpg
|
||||
let alb_pic = albumAPI.cover_small
|
||||
this.pic.md5 = alb_pic.substring( alb_pic.indexOf('cover/')+6, alb_pic.length-24 )
|
||||
}
|
||||
|
||||
if (albumAPI.genres && albumAPI.genres.data && albumAPI.genres.data.length > 0) {
|
||||
albumAPI.genres.data.forEach(genre => {
|
||||
this.genre.push(genre.name)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
parseAlbumGW(albumAPI_gw){
|
||||
this.title = albumAPI_gw.ALB_TITLE
|
||||
this.mainArtist = Aritst(
|
||||
albumAPI_gw.ART_ID,
|
||||
albumAPI_gw.ART_NAME
|
||||
)
|
||||
|
||||
this.artists = [albumAPI_gw.ART_NAME]
|
||||
this.trackTotal = albumAPI_gw.NUMBER_TRACK
|
||||
this.discTotal = albumAPI_gw.NUMBER_DISK
|
||||
this.label = albumAPI_gw.LABEL_NAME || this.label
|
||||
|
||||
let explicitLyricsStatus = albumAPI_gw.EXPLICIT_ALBUM_CONTENT.EXPLICIT_LYRICS_STATUS
|
||||
|
||||
if (this.pic.md5 == ""){
|
||||
this.pic.md5 = albumAPI_gw.ALB_PICTURE
|
||||
}
|
||||
if (albumAPI_gw.PHYSICAL_RELEASE_DATE){
|
||||
this.date.year = albumAPI_gw.PHYSICAL_RELEASE_DATE.substring(0,4)
|
||||
this.date.month = albumAPI_gw.PHYSICAL_RELEASE_DATE.substring(5,7)
|
||||
this.date.day = albumAPI_gw.PHYSICAL_RELEASE_DATE.substring(8,10)
|
||||
this.date.fixDayMonth()
|
||||
}
|
||||
}
|
||||
|
||||
makePlaylistCompilation(playlist){
|
||||
this.variousArtists = playlist.variousArtists
|
||||
this.mainArtist = playlist.mainArtist
|
||||
this.title = playlist.title
|
||||
this.rootArtist = playlist.rootArtist
|
||||
this.artist = playlist.artist
|
||||
this.artists = playlist.artists
|
||||
this.trackTotal = playlist.trackTotal
|
||||
this.recordType = playlist.recordType
|
||||
this.barcode = playlist.barcode
|
||||
this.label = playlist.label
|
||||
this.explicit = playlist.explicit
|
||||
this.date = playlist.date
|
||||
this.discTotal = playlist.discTotal
|
||||
this.playlistId = playlist.playlistId
|
||||
this.owner = playlist.owner
|
||||
this.pic = playlist.pic
|
||||
}
|
||||
|
||||
removeDuplicateArtists(){
|
||||
[self.artist, self.artists] = removeDuplicateArtists(self.artist, self.artists)
|
||||
}
|
||||
|
||||
getCleanTitle(){
|
||||
return removeFeatures(self.title)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Album
|
||||
}
|
20
deemix/types/Artist.js
Normal file
20
deemix/types/Artist.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
const { Picture } = require('./Picture.js')
|
||||
const { VARIOUS_ARTISTS } = require('../index.js')
|
||||
|
||||
class Artist {
|
||||
constructor(id="0", name="", role = "", pic_md5 = ""){
|
||||
this.id = str(id)
|
||||
this.name = name
|
||||
this.pic = Picture(md5 = pic_md5, type="artist")
|
||||
this.role = role
|
||||
this.save = True
|
||||
}
|
||||
|
||||
ifVariousArtist(){
|
||||
return this.id == VARIOUS_ARTISTS
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Artist
|
||||
}
|
27
deemix/types/Date.js
Normal file
27
deemix/types/Date.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
class Date {
|
||||
constructor(day = "00", month = "00", year = "XXXX"){
|
||||
this.day = day
|
||||
this.month = month
|
||||
this.year = year
|
||||
this.fixDayMonth()
|
||||
}
|
||||
|
||||
fixDayMonth(){
|
||||
if (int(this.month) > 12){
|
||||
let temp = this.month
|
||||
this.month = this.day
|
||||
this.day = temp
|
||||
}
|
||||
}
|
||||
|
||||
format(template){
|
||||
template = template.replaceAll(/D+/g, this.day)
|
||||
template = template.replaceAll(/M+/g, this.month)
|
||||
template = template.replaceAll(/Y+/g, this.year)
|
||||
return template
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Date
|
||||
}
|
142
deemix/types/DownloadObjects.js
Normal file
142
deemix/types/DownloadObjects.js
Normal file
|
@ -0,0 +1,142 @@
|
|||
class IDownloadObject{
|
||||
constructor(obj){
|
||||
this.type = obj.type
|
||||
this.id = obj.id
|
||||
this.bitrate = obj.bitrate
|
||||
this.title = obj.title
|
||||
this.artist = obj.artist
|
||||
this.cover = obj.cover
|
||||
this.explicit = obj.explicit || false
|
||||
this.size = obj.size
|
||||
this.downloaded = obj.downloaded || 0
|
||||
this.failed = obj.failed || 0
|
||||
this.progress = obj.progress || 0
|
||||
this.errors = obj.errors || []
|
||||
this.files = obj.files || []
|
||||
this.progressNext = 0
|
||||
this.uuid = `${this.type}_${this.id}_${this.bitrate}`
|
||||
this.ack = null
|
||||
this.__type__ = null
|
||||
}
|
||||
|
||||
toDict(){
|
||||
return {
|
||||
type: this.type,
|
||||
id: this.id,
|
||||
bitrate: this.bitrate,
|
||||
uuid: this.uuid,
|
||||
title: this.title,
|
||||
artist: this.artist,
|
||||
cover: this.cover,
|
||||
explicit: this.explicit,
|
||||
size: this.size,
|
||||
downloaded: this.downloaded,
|
||||
failed: this.failed,
|
||||
progress: this.progress,
|
||||
errors: this.errors,
|
||||
files: this.files,
|
||||
ack: this.ack,
|
||||
__type__: this.__type__
|
||||
}
|
||||
}
|
||||
|
||||
getResettedDict(){
|
||||
item = this.toDict()
|
||||
item.downloaded = 0
|
||||
item.failed = 0
|
||||
item.progress = 0
|
||||
item.errors = []
|
||||
item.files = []
|
||||
return item
|
||||
}
|
||||
|
||||
getSlimmedDict(){
|
||||
light = this.toDict()
|
||||
propertiesToDelete = ['single', 'collection', 'convertable']
|
||||
propertiesToDelete.forEach((property) => {
|
||||
if (Object.keys(light).includes(property)){
|
||||
delete light[property]
|
||||
}
|
||||
})
|
||||
return light
|
||||
}
|
||||
|
||||
updateProgress(interface){
|
||||
if (Math.round(this.progressNext) != this.progress && Math.round(this.progressNext) % 2 == 0){
|
||||
this.progress = Math.round(this.progressNext)
|
||||
if (interface) interface.emit('updateQueue', {uuid: this.uuid, progress: this.progress})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Single(IDownloadObject){
|
||||
constructor(obj){
|
||||
super(obj)
|
||||
this.size = 1
|
||||
this.single = obj.single
|
||||
this.__type__ = "Single"
|
||||
}
|
||||
|
||||
toDict(){
|
||||
item = super().toDict()
|
||||
item.single = this.single
|
||||
return item
|
||||
}
|
||||
|
||||
completeTrackProgress(interface){
|
||||
this.progressNext = 100
|
||||
this.updateProgress(interface)
|
||||
}
|
||||
|
||||
removeTrackProgress(interface){
|
||||
this.progressNext = 0
|
||||
this.updateProgress(interface)
|
||||
}
|
||||
}
|
||||
|
||||
class Collection(IDownloadObject){
|
||||
constructor(obj){
|
||||
super(obj)
|
||||
this.collection = obj.collection
|
||||
this.__type__ = "Collection"
|
||||
}
|
||||
|
||||
toDict(){
|
||||
item = super().toDict()
|
||||
item.collection = this.collection
|
||||
return item
|
||||
}
|
||||
|
||||
completeTrackProgress(interface){
|
||||
this.progressNext += (1 / this.size) * 100
|
||||
this.updateProgress(interface)
|
||||
}
|
||||
|
||||
removeTrackProgress(interface){
|
||||
this.progressNext -= (1 / this.size) * 100
|
||||
this.updateProgress(interface)
|
||||
}
|
||||
}
|
||||
|
||||
class Convertable(Collection){
|
||||
constructor(obj){
|
||||
super(obj)
|
||||
this.plugin = obj.plugin
|
||||
this.conversion_data = obj.conversion_data
|
||||
this.__type__ = "Convertable"
|
||||
}
|
||||
|
||||
toDict(){
|
||||
item = super().toDict()
|
||||
item.plugin = this.plugin
|
||||
item.conversion_data = this.conversion_data
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
IDownloadObject,
|
||||
Single,
|
||||
Collection,
|
||||
Convertable
|
||||
}
|
33
deemix/types/Lyrics.js
Normal file
33
deemix/types/Lyrics.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
class Lyrics {
|
||||
constructor(id = "0") {
|
||||
this.id = id
|
||||
this.sync = ""
|
||||
this.unsync = ""
|
||||
this.syncID3 = []
|
||||
}
|
||||
|
||||
parseLyrics(lyricsAPI) {
|
||||
this.unsync = lyricsAPI.LYRICS_TEXT || ""
|
||||
if (lyricsAPI.LYRICS_SYNC_JSON) {
|
||||
let syncLyricsJson = lyricsAPI.LYRICS_SYNC_JSON
|
||||
let timestamp = ""
|
||||
let milliseconds = 0
|
||||
for (let line = 0; line < syncLyricsJson.length; line++) {
|
||||
if (syncLyricsJson[line].line != ""){
|
||||
timestamp = syncLyricsJson[line].lrc_timestamp
|
||||
milliseconds = int(syncLyricsJson[line].milliseconds)
|
||||
this.syncID3.push([syncLyricsJson[line].line, milliseconds])
|
||||
}else{
|
||||
let notEmptyLine = line + 1
|
||||
while (syncLyricsJson[notEmptyLine].line == "") notEmptyLine = line + 1
|
||||
timestamp = syncLyricsJson[notEmptyLine].lrc_timestamp
|
||||
}
|
||||
this.sync += timestamp + syncLyricsJson[line].line + "\r\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Lyrics
|
||||
}
|
30
deemix/types/Picture.js
Normal file
30
deemix/types/Picture.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
class Picture {
|
||||
constructor(md5 = "", type = "", url) {
|
||||
this.md5 = md5
|
||||
this.type = type
|
||||
this.staticUrl = url
|
||||
}
|
||||
|
||||
getURL(size, format) {
|
||||
if (this.staticUrl) return this.staticUrl
|
||||
|
||||
let url: string = `https://e-cdns-images.dzcdn.net/images/${this.type}/${this.md5}/${str(size)}x${str(size)}`
|
||||
|
||||
if (format.startsWith('jpg')){
|
||||
let quality: number = 80
|
||||
if (format.indexOf('-') != -1) quality = int(format.substr(4))
|
||||
format = 'jpg'
|
||||
return url+`-000000-${str(quality)}-0-0.jpg`
|
||||
}
|
||||
if (format == 'png'){
|
||||
return url+`-none-100-0-0.png`
|
||||
}
|
||||
|
||||
return url+'.jpg'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Picture
|
||||
}
|
53
deemix/types/Playlist.js
Normal file
53
deemix/types/Playlist.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
const { Artist } = require('./Artist.js')
|
||||
const { Date } = require('./Date.js')
|
||||
const { Picture } = require('./Picture.js')
|
||||
|
||||
class Playlist {
|
||||
constructor(playlistAPI) {
|
||||
this.id = `pl_${str(playlistAPI.id)}`
|
||||
this.title = playlistAPI.title
|
||||
this.artist = {"Main": []}
|
||||
this.artists = []
|
||||
this.trackTotal = playlistAPI.nb_tracks
|
||||
this.recordType = "compile"
|
||||
this.barcode = ""
|
||||
this.label = ""
|
||||
this.explicit = playlistAPI.explicit
|
||||
this.genre = ["Compilation", ]
|
||||
|
||||
let year = playlistAPI.creation_date.substring(0,4)
|
||||
let month = playlistAPI.creation_date.substring(5,7)
|
||||
let day = playlistAPI.creation_date.substring(8,10)
|
||||
this.date = Date(day, month, year)
|
||||
|
||||
this.discTotal = "1"
|
||||
this.playlistID = playlistAPI.id
|
||||
this.owner = playlistAPI.creator
|
||||
|
||||
if (playlistAPI.picture_small.indexOf("dzcdn.net") != -1) {
|
||||
url = playlistAPI.picture_small
|
||||
let picType = url.substring(url.indexOf('images/')+7)
|
||||
picType = picType.substring(0, picType.indexOf('/'))
|
||||
let md5 = url.substring( url.indexOf(picType+'/') + picType.length+1, url.length-24 )
|
||||
this.pic = Picture(md5 = md5, type = picType)
|
||||
} else {
|
||||
this.pic = Picture(url = playlistAPI.picture_xl)
|
||||
}
|
||||
|
||||
if (playlistAPI.various_artist) {
|
||||
let pic_md5 = playlistAPI.various_artist.picture_small
|
||||
pic_md5 = pic_md5.substring( pic_md5.indexOf('artist/')+7, pic_md5.length-24 )
|
||||
this.variousArtists = Artist(
|
||||
id = playlistAPI.various_artist.id,
|
||||
name = playlistAPI.various_artist.name,
|
||||
role = playlistAPI.various_artist.role,
|
||||
pic_md5 = pic_md5
|
||||
)
|
||||
this.mainArtist = this.variousArtists
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Playlist
|
||||
}
|
270
deemix/types/Track.js
Normal file
270
deemix/types/Track.js
Normal file
|
@ -0,0 +1,270 @@
|
|||
const got = require('got')
|
||||
|
||||
class Track(){
|
||||
constructor(){
|
||||
this.id = "0",
|
||||
this.title = "",
|
||||
this.MD5 = ""
|
||||
this.mediaVersion = ""
|
||||
this.duration = 0
|
||||
this.fallbackID = "0"
|
||||
this.filesizes = {}
|
||||
this.localTrack = false
|
||||
this.mainArtist = null
|
||||
this.artist = {"Main": []}
|
||||
this.artists = []
|
||||
this.album = null
|
||||
this.trackNumber = "0"
|
||||
this.discNumber = "0"
|
||||
this.date = null
|
||||
this.lyrics = null
|
||||
this.bpm = 0
|
||||
this.contributors = {}
|
||||
this.copyright = ""
|
||||
this.explicit = false
|
||||
this.ISRC = ""
|
||||
this.replayGain = ""
|
||||
this.playlist = null
|
||||
this.position = null
|
||||
this.searched = false
|
||||
this.selectedFormat = 0
|
||||
this.singleDownload = false
|
||||
this.dateString = ""
|
||||
this.artistsString = ""
|
||||
this.mainArtistsString = ""
|
||||
this.featArtistsString = ""
|
||||
}
|
||||
|
||||
parseEssentialData(trackAPI_gw, trackAPI){
|
||||
this.id = str(trackAPI_gw.SNG_ID)
|
||||
this.duration = trackAPI_gw.DURATION
|
||||
this.MD5 = trackAPI_gw.MD5_ORIGIN
|
||||
if (!this.MD5){
|
||||
if (trackAPI && trackAPI.md5_origin){
|
||||
this.MD5 = trackAPI.md5_origin
|
||||
}else{
|
||||
throw MD5NotFound
|
||||
}
|
||||
}
|
||||
this.mediaVersion = trackAPI_gw.MEDIA_VERSION
|
||||
this.fallbackID = "0"
|
||||
if (trackAPI_gw.FALLBACK){
|
||||
this.fallbackID = trackAPI_gw.FALLBACK.SNG_ID
|
||||
}
|
||||
this.localTrack = int(this.id) < 0
|
||||
}
|
||||
|
||||
async retriveFilesizes(dz){
|
||||
const guest_sid = await dz.cookie_jar.getCookies('deezer.com').sid
|
||||
try{
|
||||
const result_json = await got.post("https://api.deezer.com/1.0/gateway.php",{
|
||||
searchParams:{
|
||||
api_key: "4VCYIJUCDLOUELGD1V8WBVYBNVDYOXEWSLLZDONGBBDFVXTZJRXPR29JRLQFO6ZE",
|
||||
sid: guest_sid,
|
||||
input: '3',
|
||||
output: '3',
|
||||
method: 'song_getData'
|
||||
},
|
||||
json: {sng_id: this.id},
|
||||
headers: dz.headers,
|
||||
timeout: 30000
|
||||
}).json()
|
||||
}catch{
|
||||
console.log(e)
|
||||
await new Promise(r => setTimeout(r, 2000)) // sleep(2000ms)
|
||||
return this.retriveFilesizes(dz)
|
||||
}
|
||||
if (result_json.error.length){ throw APIError }
|
||||
const response = result_json.results
|
||||
let filesizes = {}
|
||||
Object.entries(response).forEach((value, key) => {
|
||||
if (key.startsWith("FILESIZE_")){
|
||||
filesizes[key] = value
|
||||
filesizes[key+"_TESTED"] = false
|
||||
}
|
||||
})
|
||||
this.filesizes = filesizes
|
||||
}
|
||||
|
||||
async parseData(dz, id, trackAPI_gw, trackAPI, albumAPI_gw, albumAPI, playlistAPI){
|
||||
if (id && !trackAPI_gw) { trackAPI_gw = await dz.gw.get_track_with_fallback(id) }
|
||||
else if (!trackAPI_gw) { throw NoDataToParse }
|
||||
|
||||
if (!trackAPI) {
|
||||
try { trackAPI = await dz.api.get_track(trackAPI_gw.SNG_ID) }
|
||||
catch { trackAPI = null }
|
||||
}
|
||||
|
||||
this.parseEssentialData(trackAPI_gw, trackAPI)
|
||||
|
||||
if (this.localTrack){
|
||||
this.parseLocalTrackData(trackAPI_gw)
|
||||
}else{
|
||||
await this.retriveFilesizes(dz)
|
||||
this.parseTrackGW(trackAPI_gw)
|
||||
|
||||
// Get Lyrics Data
|
||||
if (!trackAPI_gw.LYRICS and this.lyrics.id != "0"){
|
||||
try { trackAPI_gw.LYRICS = await dz.gw.get_track_lyrics(this.id) }
|
||||
catch { this.lyrics.id = "0" }
|
||||
}
|
||||
if (this.lyrics.id != "0"){ this.lyrics.parseLyrics(trackAPI_gw.LYRICS) }
|
||||
|
||||
// Parse Album Data
|
||||
this.album = Album(trackAPI_gw.ALB_ID, trackAPI_gw.ALB_TITLE, trackAPI_gw.ALB_PICTURE || "")
|
||||
|
||||
// Get album Data
|
||||
if (!albumAPI){
|
||||
try { albumAPI = await dz.api.get_album(this.album.id) }
|
||||
catch { albumAPI = None }
|
||||
}
|
||||
|
||||
// Get album_gw Data
|
||||
if (!albumAPI_gw){
|
||||
try { albumAPI_gw = await dz.gw.get_album(this.album.id) }
|
||||
catch { albumAPI_gw = None }
|
||||
}
|
||||
|
||||
if (albumAPI){
|
||||
this.album.parseAlbum(albumAPI)
|
||||
}else if (albumAPI_gw){
|
||||
this.album.parseAlbumGW(albumAPI_gw)
|
||||
// albumAPI_gw doesn't contain the artist cover
|
||||
// Getting artist image ID
|
||||
// ex: https://e-cdns-images.dzcdn.net/images/artist/f2bc007e9133c946ac3c3907ddc5d2ea/56x56-000000-80-0-0.jpg
|
||||
const artistAPI = await dz.api.get_artist(self.album.mainArtist.id)
|
||||
self.album.mainArtist.pic.md5 = artistAPI.picture_small.substring( artistAPI.picture_small.search('artist/')+7, artistAPI.picture_small.length-24 )
|
||||
}else{
|
||||
throw AlbumDoesntExists
|
||||
}
|
||||
|
||||
// Fill missing data
|
||||
if (this.album.date && !this.date) this.date = this.album.date
|
||||
if (!this.album.discTotal) this.album.discTotal = albumAPI_gw.NUMBER_DISK || "1"
|
||||
if (!this.copyright) this.copyright = albumAPI_gw.COPYRIGHT
|
||||
this.parseTrack(trackAPI)
|
||||
}
|
||||
|
||||
// Remove unwanted charaters in track name
|
||||
// Example: track/127793
|
||||
this.title = this.title.replace(/\s\s+/g, ' ')
|
||||
|
||||
// Make sure there is at least one artist
|
||||
if (!this.artist.Main.length){
|
||||
this.artist.Main = [this.mainArtist.name]
|
||||
}
|
||||
|
||||
this.position = trackAPI_gw.POSITION
|
||||
|
||||
if (playlistAPI) { this.playlist = Playlist(playlistAPI) }
|
||||
|
||||
this.generateMainFeatStrings()
|
||||
return this
|
||||
}
|
||||
|
||||
parseLocalTrackData(trackAPI_gw){
|
||||
// Local tracks has only the trackAPI_gw page and
|
||||
// contains only the tags provided by the file
|
||||
this.title = trackAPI_gw.SNG_TITLE
|
||||
this.album = Album(trackAPI_gw.ALB_TITLE)
|
||||
this.album.pic = Picture(
|
||||
trackAPI_gw.ALB_PICTURE || "",
|
||||
"cover"
|
||||
)
|
||||
this.mainArtist = Artist(trackAPI_gw.ART_NAME)
|
||||
this.artists = [trackAPI_gw.ART_NAME]
|
||||
this.artist = {
|
||||
'Main': [trackAPI_gw.ART_NAME]
|
||||
}
|
||||
this.date = Date()
|
||||
this.album.artist = this.artist
|
||||
this.album.artists = this.artists
|
||||
this.album.date = this.date
|
||||
this.album.mainArtist = this.mainArtist
|
||||
}
|
||||
|
||||
parseTrackGW(trackAPI_gw){
|
||||
this.title = trackAPI_gw.SNG_TITLE.trim()
|
||||
if (trackAPI_gw.VERSION && this.title.indexOf(trackAPI_gw.VERSION.trim()) == -1){
|
||||
this.title += ` ${trackAPI_gw.VERSION.trim()}`
|
||||
}
|
||||
|
||||
this.discNumber = trackAPI_gw.DISK_NUMBER
|
||||
this.explicit = bool(int(trackAPI_gw.EXPLICIT_LYRICS || "0"))
|
||||
this.copyright = trackAPI_gw.COPYRIGHT
|
||||
if (trackAPI_gw.GAIN) this.replayGain = generateReplayGainString(trackAPI_gw.GAIN)
|
||||
this.ISRC = trackAPI_gw.ISRC
|
||||
this.trackNumber = trackAPI_gw.TRACK_NUMBER
|
||||
this.contributors = trackAPI_gw.SNG_CONTRIBUTORS
|
||||
|
||||
this.lyrics = Lyrics(trackAPI_gw.LYRICS_ID || "0")
|
||||
|
||||
this.mainArtist = Artist(
|
||||
trackAPI_gw.ART_ID,
|
||||
trackAPI_gw.ART_NAME,
|
||||
trackAPI_gw.ART_PICTRUE
|
||||
)
|
||||
|
||||
if (trackAPI_gw.PHYSICAL_RELEASE_DATE){
|
||||
const day = trackAPI_gw.PHYSICAL_RELEASE_DATE.substring(8,10)
|
||||
const month = trackAPI_gw.PHYSICAL_RELEASE_DATE.substring(5,7)
|
||||
const year = trackAPI_gw.PHYSICAL_RELEASE_DATE.substring(0,4)
|
||||
this.date = Date(day, month, year)
|
||||
}
|
||||
}
|
||||
|
||||
parseTrack(trackAPI){
|
||||
this.bpm = trackAPI.bpm
|
||||
|
||||
if (!this.replayGain && trackAPI.gain) this.replayGain = generateReplayGainString(trackAPI.gain)
|
||||
if (!this.explicit) this.explicit = trackAPI.explicit_lyrics
|
||||
if (!this.discNumber) this.discNumber = trackAPI.disk_number
|
||||
|
||||
trackAPI.contributors.forEach(artist => {
|
||||
const isVariousArtists = str(artist.id) == VARIOUS_ARTISTS
|
||||
const isMainArtist = artist.role == "Main"
|
||||
|
||||
if (trackAPI.contributors.length > 1 && isVariousArtists) return
|
||||
|
||||
if (!this.artsits.contains(artist.name))
|
||||
this.artsits.push(artist.name)
|
||||
|
||||
if (isMainArtist || !this.artsit.Main.contains(artist.name) && !isMainArtist){
|
||||
if (!this.artist[aritst.role])
|
||||
this.artist[artist.role] = []
|
||||
this.artist[artist.role].push(artist.name)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
removeDuplicateArtists(){
|
||||
[this.artist, this.artsits] = removeDuplicateArtists(this.artist, this.artists)
|
||||
}
|
||||
|
||||
getCleanTitle(){
|
||||
return removeFeatures(this.title)
|
||||
}
|
||||
|
||||
getFeatTitle(){
|
||||
if (this.featArtistsString && this.title.toLowerCase().indexOf("feat.") == -1){
|
||||
return `${this.title} (${this.featArtistsString})`
|
||||
}
|
||||
return this.title
|
||||
}
|
||||
|
||||
generateMainFeatStrings(){
|
||||
this.mainArtistsString = andCommaConcat(this.artist.Main)
|
||||
this.featArtistsString = ""
|
||||
if (this.artist.Featured){
|
||||
this.featArtistsString = `feat. ${andCommaConcat(this.artist.Featured)}`
|
||||
}
|
||||
}
|
||||
|
||||
applySettings(settings, TEMPDIR, embeddedImageFormat){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Track
|
||||
}
|
1
deemix/types/index.js
Normal file
1
deemix/types/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
const VARIOUS_ARTISTS = "5080"
|
59
deemix/utils/index.js
Normal file
59
deemix/utils/index.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
function generateReplayGainString(trackGain){
|
||||
return `${Math.round((float(trackGain) + 18.4)*-100)/100} dB`
|
||||
}
|
||||
|
||||
function removeFeatures(title){
|
||||
let clean = title
|
||||
if (clean.search(/\(feat\./gi) != -1){
|
||||
const pos = clean.search(/\(feat\./gi)
|
||||
let tempTrack = clean.substring(0, pos)
|
||||
if (clean.indexOf(')') != -1)
|
||||
tempTrack += clean.substring(clean.indexOf(')', pos+1)+1)
|
||||
clean = tempTrack.trim()
|
||||
clean = clean.replace(/\s\s+/g, ' ') // remove extra spaces
|
||||
}
|
||||
return clean
|
||||
}
|
||||
|
||||
function andCommaConcat(lst){
|
||||
const tot = lst.length
|
||||
let result = ""
|
||||
lst.forEach((art, i) => {
|
||||
result += art
|
||||
if (tot != i+1){
|
||||
if (tot - 1 == i+1){
|
||||
result += " & "
|
||||
} else {
|
||||
result += ", "
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
function uniqueArray(arr){
|
||||
arr.forEach((namePrinc, iPrinc) => {
|
||||
arr.forEach((nameRest, iRest) => {
|
||||
if (iPrinc != iRest && nameRest.toLowerCase().indexOf(namePrinc.toLowerCase()) != -1){
|
||||
arr.splice(iRest, 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
return arr
|
||||
}
|
||||
|
||||
function removeDuplicateArtists(artist, artists){
|
||||
artists = uniqueArray(artists)
|
||||
Object.keys(artist).forEach((role) => {
|
||||
artist[role] = uniqueArray(artist[role])
|
||||
})
|
||||
return [artist, artists]
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateReplayGainString,
|
||||
removeFeatures,
|
||||
andCommaConcat,
|
||||
uniqueArray,
|
||||
removeDuplicateArtists
|
||||
}
|
593
package-lock.json
generated
Normal file
593
package-lock.json
generated
Normal file
|
@ -0,0 +1,593 @@
|
|||
{
|
||||
"name": "deemix",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "deemix",
|
||||
"version": "0.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"deezer-js": "^0.0.2",
|
||||
"got": "^11.8.2"
|
||||
}
|
||||
},
|
||||
"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.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.34.tgz",
|
||||
"integrity": "sha512-dBPaxocOK6UVyvhbnpFIj2W+S+1cBTkHQbFQfeeJhoKFbzYcVUGHvddeWPSucKATb3F0+pgDq0i6ghEaZjsugA=="
|
||||
},
|
||||
"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/deezer-js": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/deezer-js/-/deezer-js-0.0.2.tgz",
|
||||
"integrity": "sha512-v78DXcqeeui6wWEKd+6vVDITT76ck3pp8p+fSUZrvX3P8N6fQXGFzHqjgHaGm2rJpEnG5Ad8a8KTesDKZ56A6Q==",
|
||||
"dependencies": {
|
||||
"got": "^11.8.2",
|
||||
"tough-cookie": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"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.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.34.tgz",
|
||||
"integrity": "sha512-dBPaxocOK6UVyvhbnpFIj2W+S+1cBTkHQbFQfeeJhoKFbzYcVUGHvddeWPSucKATb3F0+pgDq0i6ghEaZjsugA=="
|
||||
},
|
||||
"@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=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"deezer-js": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/deezer-js/-/deezer-js-0.0.2.tgz",
|
||||
"integrity": "sha512-v78DXcqeeui6wWEKd+6vVDITT76ck3pp8p+fSUZrvX3P8N6fQXGFzHqjgHaGm2rJpEnG5Ad8a8KTesDKZ56A6Q==",
|
||||
"requires": {
|
||||
"got": "^11.8.2",
|
||||
"tough-cookie": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"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="
|
||||
}
|
||||
}
|
||||
}
|
15
package.json
Normal file
15
package.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "deemix",
|
||||
"version": "0.0.0",
|
||||
"description": "a barebones deezer downloader library",
|
||||
"main": "deemix/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "RemixDev",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"deezer-js": "^0.0.2",
|
||||
"got": "^11.8.2"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue