gerdur-core 0.0.0-probe → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/LICENSE +1 -0
- package/README.md +188 -1
- package/dist/api/api.d.ts +78 -0
- package/dist/api/api.js +182 -0
- package/dist/api/cache.d.ts +3 -0
- package/dist/api/cache.js +12 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +18 -0
- package/dist/api/request.d.ts +23 -0
- package/dist/api/request.js +88 -0
- package/dist/converter/deezer.d.ts +3 -0
- package/dist/converter/deezer.js +45 -0
- package/dist/converter/index.d.ts +5 -0
- package/dist/converter/index.js +34 -0
- package/dist/converter/parse.d.ts +18 -0
- package/dist/converter/parse.js +176 -0
- package/dist/converter/spotify.d.ts +40 -0
- package/dist/converter/spotify.js +154 -0
- package/dist/converter/tidal.d.ts +146 -0
- package/dist/converter/tidal.js +199 -0
- package/dist/converter/youtube.d.ts +6 -0
- package/dist/converter/youtube.js +102 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +24 -0
- package/dist/lib/decrypt.d.ts +9 -0
- package/dist/lib/decrypt.js +63 -0
- package/dist/lib/fast-lru.d.ts +63 -0
- package/dist/lib/fast-lru.js +121 -0
- package/dist/lib/get-url.d.ts +16 -0
- package/dist/lib/get-url.js +154 -0
- package/dist/lib/http.d.ts +66 -0
- package/dist/lib/http.js +235 -0
- package/dist/lib/metaflac-js.d.ts +124 -0
- package/dist/lib/metaflac-js.js +343 -0
- package/dist/lib/request.d.ts +18 -0
- package/dist/lib/request.js +86 -0
- package/dist/metadata-writer/abumCover.d.ts +10 -0
- package/dist/metadata-writer/abumCover.js +37 -0
- package/dist/metadata-writer/flacmetata.d.ts +3 -0
- package/dist/metadata-writer/flacmetata.js +80 -0
- package/dist/metadata-writer/getTrackLyrics.d.ts +2 -0
- package/dist/metadata-writer/getTrackLyrics.js +26 -0
- package/dist/metadata-writer/id3.d.ts +3 -0
- package/dist/metadata-writer/id3.js +119 -0
- package/dist/metadata-writer/index.d.ts +9 -0
- package/dist/metadata-writer/index.js +44 -0
- package/dist/metadata-writer/musixmatchLyrics.d.ts +1 -0
- package/dist/metadata-writer/musixmatchLyrics.js +39 -0
- package/dist/metadata-writer/useragents.d.ts +1 -0
- package/dist/metadata-writer/useragents.js +86 -0
- package/dist/types/album.d.ts +123 -0
- package/dist/types/album.js +2 -0
- package/dist/types/artist.d.ts +36 -0
- package/dist/types/artist.js +2 -0
- package/dist/types/channel.d.ts +33 -0
- package/dist/types/channel.js +2 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.js +26 -0
- package/dist/types/playlist-channel.d.ts +81 -0
- package/dist/types/playlist-channel.js +2 -0
- package/dist/types/playlist.d.ts +49 -0
- package/dist/types/playlist.js +2 -0
- package/dist/types/profile.d.ts +29 -0
- package/dist/types/profile.js +2 -0
- package/dist/types/radio.d.ts +7 -0
- package/dist/types/radio.js +2 -0
- package/dist/types/search.d.ts +79 -0
- package/dist/types/search.js +2 -0
- package/dist/types/show.d.ts +61 -0
- package/dist/types/show.js +2 -0
- package/dist/types/tracks.d.ts +144 -0
- package/dist/types/tracks.js +2 -0
- package/dist/types/user.d.ts +16 -0
- package/dist/types/user.js +2 -0
- package/package.json +67 -5
- package/types/index.d.ts +1 -0
- package/types/index.js +3 -0
- package/types/package.json +4 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
|
+
if (mod && mod.__esModule) return mod;
|
|
23
|
+
var result = {};
|
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
25
|
+
__setModuleDefault(result, mod);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.youtube = exports.spotify = exports.tidal = void 0;
|
|
30
|
+
__exportStar(require("./parse"), exports);
|
|
31
|
+
__exportStar(require("./deezer"), exports);
|
|
32
|
+
exports.tidal = __importStar(require("./tidal"));
|
|
33
|
+
exports.spotify = __importStar(require("./spotify"));
|
|
34
|
+
exports.youtube = __importStar(require("./youtube"));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { albumType, artistInfoType, playlistInfo, trackType } from '../types';
|
|
2
|
+
type linkType = 'track' | 'album' | 'artist' | 'playlist';
|
|
3
|
+
export type urlPartsType = {
|
|
4
|
+
id: string;
|
|
5
|
+
type: 'track' | 'album' | 'audiobook' | 'artist' | 'playlist' | 'spotify-track' | 'spotify-album' | 'spotify-playlist' | 'spotify-artist' | 'tidal-track' | 'tidal-album' | 'tidal-playlist' | 'tidal-artist' | 'youtube-track';
|
|
6
|
+
};
|
|
7
|
+
export declare const getUrlParts: (url: string, setToken?: boolean) => Promise<urlPartsType>;
|
|
8
|
+
/**
|
|
9
|
+
* Deezer, Spotify or Tidal links only
|
|
10
|
+
* @param {String} url
|
|
11
|
+
*/
|
|
12
|
+
export declare const parseInfo: (url: string) => Promise<{
|
|
13
|
+
info: urlPartsType;
|
|
14
|
+
linktype: linkType;
|
|
15
|
+
linkinfo: Record<string, any> | artistInfoType | albumType | playlistInfo;
|
|
16
|
+
tracks: trackType[];
|
|
17
|
+
}>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.parseInfo = exports.getUrlParts = void 0;
|
|
30
|
+
const __1 = require("../");
|
|
31
|
+
const spotify_uri_1 = __importDefault(require("spotify-uri"));
|
|
32
|
+
const spotify = __importStar(require("./spotify"));
|
|
33
|
+
const tidal = __importStar(require("./tidal"));
|
|
34
|
+
const youtube = __importStar(require("./youtube"));
|
|
35
|
+
const p_queue_1 = __importDefault(require("p-queue"));
|
|
36
|
+
const http_1 = require("../lib/http");
|
|
37
|
+
const queue = new p_queue_1.default({ concurrency: 10 });
|
|
38
|
+
const getUrlParts = async (url, setToken = false) => {
|
|
39
|
+
if (url.startsWith('spotify:')) {
|
|
40
|
+
const spotify = url.split(':');
|
|
41
|
+
url = 'https://open.spotify.com/' + spotify[1] + '/' + spotify[2];
|
|
42
|
+
}
|
|
43
|
+
const site = url.match(/deezer|spotify|tidal|youtu\.?be/);
|
|
44
|
+
if (!site) {
|
|
45
|
+
throw new Error('Unknown URL: ' + url);
|
|
46
|
+
}
|
|
47
|
+
switch (site[0]) {
|
|
48
|
+
case 'deezer':
|
|
49
|
+
if (url.includes('page.link')) {
|
|
50
|
+
const { request } = await (0, http_1.headRequest)(url);
|
|
51
|
+
url = request.res.responseUrl;
|
|
52
|
+
}
|
|
53
|
+
const deezerUrlParts = url.split(/\/(\w+)\/(\d+)/);
|
|
54
|
+
return { type: deezerUrlParts[1], id: deezerUrlParts[2] };
|
|
55
|
+
case 'spotify':
|
|
56
|
+
const spotifyUrlParts = spotify_uri_1.default.parse(url);
|
|
57
|
+
if (setToken) {
|
|
58
|
+
await spotify.setSpotifyAnonymousToken();
|
|
59
|
+
}
|
|
60
|
+
return { type: ('spotify-' + spotifyUrlParts.type), id: spotifyUrlParts.id };
|
|
61
|
+
case 'tidal':
|
|
62
|
+
const tidalUrlParts = url.split(/\/(\w+)\/(\d+|\w+-\w+-\w+-\w+-\w+)/);
|
|
63
|
+
return { type: ('tidal-' + tidalUrlParts[1]), id: tidalUrlParts[2] };
|
|
64
|
+
case 'youtube':
|
|
65
|
+
let yotubeId = url.split('v=')[1];
|
|
66
|
+
if (yotubeId.includes('&')) {
|
|
67
|
+
yotubeId = yotubeId.split('&')[0];
|
|
68
|
+
}
|
|
69
|
+
return { type: 'youtube-track', id: yotubeId };
|
|
70
|
+
case 'youtu.be':
|
|
71
|
+
return { type: 'youtube-track', id: url.split('/').pop() };
|
|
72
|
+
default:
|
|
73
|
+
throw new Error('Unable to parse URL: ' + url);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
exports.getUrlParts = getUrlParts;
|
|
77
|
+
/**
|
|
78
|
+
* Deezer, Spotify or Tidal links only
|
|
79
|
+
* @param {String} url
|
|
80
|
+
*/
|
|
81
|
+
const parseInfo = async (url) => {
|
|
82
|
+
const info = await (0, exports.getUrlParts)(url, true);
|
|
83
|
+
if (!info.id) {
|
|
84
|
+
throw new Error('Unable to parse id');
|
|
85
|
+
}
|
|
86
|
+
let linktype = 'track';
|
|
87
|
+
let linkinfo = {};
|
|
88
|
+
let tracks = [];
|
|
89
|
+
switch (info.type) {
|
|
90
|
+
case 'track': {
|
|
91
|
+
tracks.push(await (0, __1.getTrackInfo)(info.id));
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case 'album':
|
|
95
|
+
case 'audiobook':
|
|
96
|
+
linkinfo = await (0, __1.getAlbumInfo)(info.id);
|
|
97
|
+
linktype = 'album';
|
|
98
|
+
const albumTracks = await (0, __1.getAlbumTracks)(info.id);
|
|
99
|
+
tracks = albumTracks.data;
|
|
100
|
+
break;
|
|
101
|
+
case 'playlist':
|
|
102
|
+
linkinfo = await (0, __1.getPlaylistInfo)(info.id);
|
|
103
|
+
linktype = 'playlist';
|
|
104
|
+
const playlistTracks = await (0, __1.getPlaylistTracks)(info.id);
|
|
105
|
+
tracks = playlistTracks.data;
|
|
106
|
+
break;
|
|
107
|
+
case 'artist':
|
|
108
|
+
linkinfo = await (0, __1.getArtistInfo)(info.id);
|
|
109
|
+
linktype = 'artist';
|
|
110
|
+
const artistAlbums = await (0, __1.getDiscography)(info.id);
|
|
111
|
+
await queue.addAll(artistAlbums.data.map((album) => {
|
|
112
|
+
return async () => {
|
|
113
|
+
if (album.ARTISTS.find((a) => a.ART_ID === info.id)) {
|
|
114
|
+
const albumTracks = await (0, __1.getAlbumTracks)(album.ALB_ID);
|
|
115
|
+
tracks = [...tracks, ...albumTracks.data.filter((t) => t.ART_ID === info.id)];
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}));
|
|
119
|
+
break;
|
|
120
|
+
case 'spotify-track':
|
|
121
|
+
tracks.push(await spotify.track2deezer(info.id));
|
|
122
|
+
break;
|
|
123
|
+
case 'spotify-album':
|
|
124
|
+
const [spotifyAlbumInfo, spotifyTracks] = await spotify.album2deezer(info.id);
|
|
125
|
+
tracks = spotifyTracks;
|
|
126
|
+
linkinfo = spotifyAlbumInfo;
|
|
127
|
+
linktype = 'album';
|
|
128
|
+
break;
|
|
129
|
+
case 'spotify-playlist':
|
|
130
|
+
const [spotifyPlaylistInfo, spotifyPlaylistTracks] = await spotify.playlist2Deezer(info.id);
|
|
131
|
+
tracks = spotifyPlaylistTracks;
|
|
132
|
+
linkinfo = spotifyPlaylistInfo;
|
|
133
|
+
linktype = 'playlist';
|
|
134
|
+
break;
|
|
135
|
+
case 'spotify-artist':
|
|
136
|
+
tracks = await spotify.artist2Deezer(info.id);
|
|
137
|
+
linktype = 'artist';
|
|
138
|
+
break;
|
|
139
|
+
case 'tidal-track':
|
|
140
|
+
tracks.push(await tidal.track2deezer(info.id));
|
|
141
|
+
break;
|
|
142
|
+
case 'tidal-album':
|
|
143
|
+
const [tidalAlbumInfo, tidalAlbumTracks] = await tidal.album2deezer(info.id);
|
|
144
|
+
tracks = tidalAlbumTracks;
|
|
145
|
+
linkinfo = tidalAlbumInfo;
|
|
146
|
+
linktype = 'album';
|
|
147
|
+
break;
|
|
148
|
+
case 'tidal-playlist':
|
|
149
|
+
const [tidalPlaylistInfo, tidalPlaylistTracks] = await tidal.playlist2Deezer(info.id);
|
|
150
|
+
tracks = tidalPlaylistTracks;
|
|
151
|
+
linkinfo = tidalPlaylistInfo;
|
|
152
|
+
linktype = 'playlist';
|
|
153
|
+
break;
|
|
154
|
+
case 'tidal-artist':
|
|
155
|
+
tracks = await tidal.artist2Deezer(info.id);
|
|
156
|
+
linktype = 'artist';
|
|
157
|
+
break;
|
|
158
|
+
case 'youtube-track':
|
|
159
|
+
tracks.push(await youtube.track2deezer(info.id));
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
throw new Error('Unknown type: ' + info.type);
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
info,
|
|
166
|
+
linktype,
|
|
167
|
+
linkinfo,
|
|
168
|
+
tracks: tracks.map((t) => {
|
|
169
|
+
if (t.VERSION && !t.SNG_TITLE.includes(t.VERSION)) {
|
|
170
|
+
t.SNG_TITLE += ' ' + t.VERSION;
|
|
171
|
+
}
|
|
172
|
+
return t;
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
exports.parseInfo = parseInfo;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/// <reference types="spotify-api" />
|
|
2
|
+
import SpotifyWebApi from 'spotify-web-api-node';
|
|
3
|
+
import type { playlistInfo, trackType } from '../types';
|
|
4
|
+
type tokensType = {
|
|
5
|
+
clientId: string;
|
|
6
|
+
accessToken: string;
|
|
7
|
+
accessTokenExpirationTimestampMs: number;
|
|
8
|
+
isAnonymous: true;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Export core spotify module
|
|
12
|
+
*/
|
|
13
|
+
export declare const spotifyApi: SpotifyWebApi;
|
|
14
|
+
/**
|
|
15
|
+
* Set spotify tokens anonymously. This is required to bypass api limits.
|
|
16
|
+
* @returns {tokensType}
|
|
17
|
+
*/
|
|
18
|
+
export declare const setSpotifyAnonymousToken: () => Promise<tokensType>;
|
|
19
|
+
/**
|
|
20
|
+
* Convert spotify songs to deezer
|
|
21
|
+
* @param {String} id Spotify track id
|
|
22
|
+
* @returns {trackType}
|
|
23
|
+
*/
|
|
24
|
+
export declare const track2deezer: (id: string) => Promise<trackType>;
|
|
25
|
+
/**
|
|
26
|
+
* Convert spotify albums to deezer
|
|
27
|
+
* @param {String} id Spotify track id
|
|
28
|
+
*/
|
|
29
|
+
export declare const album2deezer: (id: string) => Promise<[import("../types").albumType, trackType[]]>;
|
|
30
|
+
/**
|
|
31
|
+
* Convert playlist to deezer
|
|
32
|
+
* @param {String} id Spotify track id
|
|
33
|
+
*/
|
|
34
|
+
export declare const playlist2Deezer: (id: string, onError?: ((item: SpotifyApi.PlaylistTrackObject, index: number, err: Error) => void) | undefined) => Promise<[playlistInfo, trackType[]]>;
|
|
35
|
+
/**
|
|
36
|
+
* Convert artist songs to deezer. Maxium of 10 tracks.
|
|
37
|
+
* @param {String} id Spotify track id
|
|
38
|
+
*/
|
|
39
|
+
export declare const artist2Deezer: (id: string, onError?: ((item: SpotifyApi.TrackObjectFull, index: number, err: Error) => void) | undefined) => Promise<trackType[]>;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.artist2Deezer = exports.playlist2Deezer = exports.album2deezer = exports.track2deezer = exports.setSpotifyAnonymousToken = exports.spotifyApi = void 0;
|
|
7
|
+
const spotify_web_api_node_1 = __importDefault(require("spotify-web-api-node"));
|
|
8
|
+
const p_queue_1 = __importDefault(require("p-queue"));
|
|
9
|
+
const deezer_1 = require("./deezer");
|
|
10
|
+
const http_1 = require("../lib/http");
|
|
11
|
+
let anonymousToken = null;
|
|
12
|
+
let anonymousTokenPromise = null;
|
|
13
|
+
const hasValidAnonymousToken = () => Boolean(anonymousToken && anonymousToken.accessTokenExpirationTimestampMs - 60000 > Date.now());
|
|
14
|
+
/**
|
|
15
|
+
* Parse offset number
|
|
16
|
+
* @param {String} next next page url
|
|
17
|
+
* @returns {Number}
|
|
18
|
+
*/
|
|
19
|
+
const getOffset = (next) => {
|
|
20
|
+
if (next) {
|
|
21
|
+
const o = next.split('&').find((p) => p.includes('offset='));
|
|
22
|
+
return o ? Number(o.split('=')[1]) : 0;
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Limit process concurrency
|
|
28
|
+
*/
|
|
29
|
+
const queue = new p_queue_1.default({ concurrency: 25 });
|
|
30
|
+
/**
|
|
31
|
+
* Export core spotify module
|
|
32
|
+
*/
|
|
33
|
+
exports.spotifyApi = new spotify_web_api_node_1.default();
|
|
34
|
+
/**
|
|
35
|
+
* Set spotify tokens anonymously. This is required to bypass api limits.
|
|
36
|
+
* @returns {tokensType}
|
|
37
|
+
*/
|
|
38
|
+
const setSpotifyAnonymousToken = async () => {
|
|
39
|
+
if (hasValidAnonymousToken() && anonymousToken) {
|
|
40
|
+
exports.spotifyApi.setAccessToken(anonymousToken.accessToken);
|
|
41
|
+
return anonymousToken;
|
|
42
|
+
}
|
|
43
|
+
if (!anonymousTokenPromise) {
|
|
44
|
+
anonymousTokenPromise = (0, http_1.getJson)('https://open.spotify.com/get_access_token?reason=transport&productType=embed')
|
|
45
|
+
.then((data) => {
|
|
46
|
+
anonymousToken = data;
|
|
47
|
+
exports.spotifyApi.setAccessToken(data.accessToken);
|
|
48
|
+
return data;
|
|
49
|
+
})
|
|
50
|
+
.finally(() => {
|
|
51
|
+
anonymousTokenPromise = null;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return await anonymousTokenPromise;
|
|
55
|
+
};
|
|
56
|
+
exports.setSpotifyAnonymousToken = setSpotifyAnonymousToken;
|
|
57
|
+
/**
|
|
58
|
+
* Convert spotify songs to deezer
|
|
59
|
+
* @param {String} id Spotify track id
|
|
60
|
+
* @returns {trackType}
|
|
61
|
+
*/
|
|
62
|
+
const track2deezer = async (id) => {
|
|
63
|
+
const { body } = await exports.spotifyApi.getTrack(id);
|
|
64
|
+
return await (0, deezer_1.isrc2deezer)(body.name, body.external_ids.isrc);
|
|
65
|
+
};
|
|
66
|
+
exports.track2deezer = track2deezer;
|
|
67
|
+
/**
|
|
68
|
+
* Convert spotify albums to deezer
|
|
69
|
+
* @param {String} id Spotify track id
|
|
70
|
+
*/
|
|
71
|
+
const album2deezer = async (id) => {
|
|
72
|
+
const { body } = await exports.spotifyApi.getAlbum(id);
|
|
73
|
+
return await (0, deezer_1.upc2deezer)(body.name, body.external_ids.upc);
|
|
74
|
+
};
|
|
75
|
+
exports.album2deezer = album2deezer;
|
|
76
|
+
/**
|
|
77
|
+
* Convert playlist to deezer
|
|
78
|
+
* @param {String} id Spotify track id
|
|
79
|
+
*/
|
|
80
|
+
const playlist2Deezer = async (id, onError) => {
|
|
81
|
+
const { body } = await exports.spotifyApi.getPlaylist(id);
|
|
82
|
+
const tracks = [];
|
|
83
|
+
let items = body.tracks.items;
|
|
84
|
+
let offset = getOffset(body.tracks.next);
|
|
85
|
+
while (offset !== 0) {
|
|
86
|
+
const { body } = await exports.spotifyApi.getPlaylistTracks(id, { limit: 100, offset: offset ? offset : 0 });
|
|
87
|
+
offset = getOffset(body.next);
|
|
88
|
+
items = [...items, ...body.items];
|
|
89
|
+
}
|
|
90
|
+
await queue.addAll(items.map((item, index) => {
|
|
91
|
+
return async () => {
|
|
92
|
+
try {
|
|
93
|
+
if (item.track) {
|
|
94
|
+
const track = await (0, deezer_1.isrc2deezer)(item.track.name, item.track.external_ids.isrc);
|
|
95
|
+
track.TRACK_POSITION = index + 1;
|
|
96
|
+
tracks.push(track);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (onError) {
|
|
101
|
+
onError(item, index, err);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}));
|
|
106
|
+
const dateCreated = new Date().toISOString();
|
|
107
|
+
const playlistInfoData = {
|
|
108
|
+
PLAYLIST_ID: body.id,
|
|
109
|
+
PARENT_USERNAME: body.owner.id,
|
|
110
|
+
PARENT_USER_ID: body.owner.id,
|
|
111
|
+
PICTURE_TYPE: 'cover',
|
|
112
|
+
PLAYLIST_PICTURE: body.images[0].url,
|
|
113
|
+
TITLE: body.name,
|
|
114
|
+
TYPE: '0',
|
|
115
|
+
STATUS: '0',
|
|
116
|
+
USER_ID: body.owner.id,
|
|
117
|
+
DATE_ADD: dateCreated,
|
|
118
|
+
DATE_MOD: dateCreated,
|
|
119
|
+
DATE_CREATE: dateCreated,
|
|
120
|
+
NB_SONG: body.tracks.total,
|
|
121
|
+
NB_FAN: 0,
|
|
122
|
+
CHECKSUM: body.id,
|
|
123
|
+
HAS_ARTIST_LINKED: false,
|
|
124
|
+
IS_SPONSORED: false,
|
|
125
|
+
IS_EDITO: false,
|
|
126
|
+
__TYPE__: 'playlist',
|
|
127
|
+
};
|
|
128
|
+
return [playlistInfoData, tracks];
|
|
129
|
+
};
|
|
130
|
+
exports.playlist2Deezer = playlist2Deezer;
|
|
131
|
+
/**
|
|
132
|
+
* Convert artist songs to deezer. Maxium of 10 tracks.
|
|
133
|
+
* @param {String} id Spotify track id
|
|
134
|
+
*/
|
|
135
|
+
const artist2Deezer = async (id, onError) => {
|
|
136
|
+
// Artist tracks are limited to 10 items
|
|
137
|
+
const { body } = await exports.spotifyApi.getArtistTopTracks(id, 'GB');
|
|
138
|
+
const tracks = [];
|
|
139
|
+
await queue.addAll(body.tracks.map((item, index) => {
|
|
140
|
+
return async () => {
|
|
141
|
+
try {
|
|
142
|
+
const track = await (0, deezer_1.isrc2deezer)(item.name, item.external_ids.isrc);
|
|
143
|
+
tracks.push(track);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (onError) {
|
|
147
|
+
onError(item, index, err);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}));
|
|
152
|
+
return tracks;
|
|
153
|
+
};
|
|
154
|
+
exports.artist2Deezer = artist2Deezer;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { playlistInfo, trackType } from '../types';
|
|
2
|
+
interface commonType {
|
|
3
|
+
id: number;
|
|
4
|
+
title: string;
|
|
5
|
+
duration: number;
|
|
6
|
+
premiumStreamingOnly: boolean;
|
|
7
|
+
trackNumber: number;
|
|
8
|
+
copyright: string;
|
|
9
|
+
url: string;
|
|
10
|
+
explicit: boolean;
|
|
11
|
+
audioQuality: string;
|
|
12
|
+
artist: {
|
|
13
|
+
id: number;
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
};
|
|
17
|
+
album: {
|
|
18
|
+
id: number;
|
|
19
|
+
title: string;
|
|
20
|
+
cover: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
interface tidalTrackType extends commonType {
|
|
24
|
+
isrc: string;
|
|
25
|
+
editable: boolean;
|
|
26
|
+
audioQuality: string;
|
|
27
|
+
album: {
|
|
28
|
+
id: number;
|
|
29
|
+
title: string;
|
|
30
|
+
cover: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
interface tidalAlbumType extends commonType {
|
|
34
|
+
cover: string;
|
|
35
|
+
videoCover: null | string;
|
|
36
|
+
upc: string;
|
|
37
|
+
audioQuality: string;
|
|
38
|
+
}
|
|
39
|
+
interface tidalPlaylistType {
|
|
40
|
+
uuid: string;
|
|
41
|
+
title: string;
|
|
42
|
+
numberOfTracks: number;
|
|
43
|
+
numberOfVideos: number;
|
|
44
|
+
creator: {
|
|
45
|
+
id: number;
|
|
46
|
+
};
|
|
47
|
+
description: string;
|
|
48
|
+
duration: number;
|
|
49
|
+
lastUpdated: string;
|
|
50
|
+
created: string;
|
|
51
|
+
type: string;
|
|
52
|
+
publicPlaylist: boolean;
|
|
53
|
+
url: string;
|
|
54
|
+
image: string;
|
|
55
|
+
}
|
|
56
|
+
interface listType {
|
|
57
|
+
limit: number;
|
|
58
|
+
offset: number;
|
|
59
|
+
totalNumberOfItems: number;
|
|
60
|
+
}
|
|
61
|
+
interface tidalArtistTopTracksType extends listType {
|
|
62
|
+
items: tidalTrackType[];
|
|
63
|
+
}
|
|
64
|
+
interface tidalAlbumsTracksType extends listType {
|
|
65
|
+
items: tidalAlbumType[];
|
|
66
|
+
}
|
|
67
|
+
interface tidalPlaylistTracksType extends listType {
|
|
68
|
+
items: tidalTrackType[];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get a track by its id
|
|
72
|
+
* @param string} id - track id
|
|
73
|
+
* @example tidal.getTrack('64975224')
|
|
74
|
+
*/
|
|
75
|
+
export declare const getTrack: (id: string) => Promise<tidalTrackType>;
|
|
76
|
+
/**
|
|
77
|
+
* Convert a tidal track to deezer
|
|
78
|
+
* @param {string} id - track id
|
|
79
|
+
*/
|
|
80
|
+
export declare const track2deezer: (id: string) => Promise<trackType>;
|
|
81
|
+
/**
|
|
82
|
+
* Get an album by its id
|
|
83
|
+
* @param {string} id - album id
|
|
84
|
+
* @example tidal.getAlbum('80216363')
|
|
85
|
+
*/
|
|
86
|
+
export declare const getAlbum: (id: string) => Promise<tidalAlbumType>;
|
|
87
|
+
/**
|
|
88
|
+
* Convert a tidal albums to deezer
|
|
89
|
+
* @param {string} id - album id
|
|
90
|
+
*/
|
|
91
|
+
export declare const album2deezer: (id: string) => Promise<[import("../types").albumType, trackType[]]>;
|
|
92
|
+
/**
|
|
93
|
+
* Get album tracks by album id
|
|
94
|
+
* @param {string} id - album id
|
|
95
|
+
* @example tidal.getAlbumTracks('80216363')
|
|
96
|
+
*/
|
|
97
|
+
export declare const getAlbumTracks: (id: string) => Promise<tidalAlbumsTracksType>;
|
|
98
|
+
/**
|
|
99
|
+
* Get artist albums by artist id
|
|
100
|
+
* @param {string} id - artist id
|
|
101
|
+
* @example tidal.getArtistAlbums('3575680')
|
|
102
|
+
*/
|
|
103
|
+
export declare const getArtistAlbums: (id: string) => Promise<tidalAlbumsTracksType>;
|
|
104
|
+
/**
|
|
105
|
+
* Get top tracks by artist
|
|
106
|
+
* @param {string} id - artist id
|
|
107
|
+
* @example tidal.getArtistTopTracks('3575680')
|
|
108
|
+
*/
|
|
109
|
+
export declare const getArtistTopTracks: (id: string) => Promise<tidalArtistTopTracksType>;
|
|
110
|
+
/**
|
|
111
|
+
* Get a playlist by its uuid
|
|
112
|
+
* @param {string} uuid - playlist uuid
|
|
113
|
+
* @example tidal.getPlaylist('1c5d01ed-4f05-40c4-bd28-0f73099e9648')
|
|
114
|
+
*/
|
|
115
|
+
export declare const getPlaylist: (uuid: string) => Promise<tidalPlaylistType>;
|
|
116
|
+
/**
|
|
117
|
+
* Get playlist tracks by playlist uuid
|
|
118
|
+
* @param {string} uuid - playlist uuid
|
|
119
|
+
* @example tidal.getPlaylistTracks('1c5d01ed-4f05-40c4-bd28-0f73099e9648')
|
|
120
|
+
*/
|
|
121
|
+
export declare const getPlaylistTracks: (uuid: string) => Promise<tidalPlaylistTracksType>;
|
|
122
|
+
/**
|
|
123
|
+
* Get valid urls to album art
|
|
124
|
+
* @param {string} uuid - album art uuid (can be found as cover property in album object)
|
|
125
|
+
* @example tidal.albumArtToUrl('9a56f482-e9cf-46c3-bb21-82710e7854d4')
|
|
126
|
+
* @returns {Object}
|
|
127
|
+
*/
|
|
128
|
+
export declare const albumArtToUrl: (uuid: string) => {
|
|
129
|
+
sm: string;
|
|
130
|
+
md: string;
|
|
131
|
+
lg: string;
|
|
132
|
+
xl: string;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Find tidal artists tracks on deezer
|
|
136
|
+
* @param {string} id - artist id
|
|
137
|
+
* @example tidal.artist2Deezer('3575680')
|
|
138
|
+
*/
|
|
139
|
+
export declare const artist2Deezer: (id: string, onError?: ((item: tidalTrackType, index: number, err: Error) => void) | undefined) => Promise<trackType[]>;
|
|
140
|
+
/**
|
|
141
|
+
* Find same set of playlist tracks on deezer
|
|
142
|
+
* @param {string} uuid - playlist uuid
|
|
143
|
+
* @example tidal.playlist2Deezer('1c5d01ed-4f05-40c4-bd28-0f73099e9648')
|
|
144
|
+
*/
|
|
145
|
+
export declare const playlist2Deezer: (uuid: string, onError?: ((item: tidalTrackType, index: number, err: Error) => void) | undefined) => Promise<[playlistInfo, trackType[]]>;
|
|
146
|
+
export {};
|