q-fi-core 2.3.1

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.
Files changed (79) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/LICENSE +1 -0
  3. package/README.md +186 -0
  4. package/dist/api/api.d.ts +78 -0
  5. package/dist/api/api.js +182 -0
  6. package/dist/api/cache.d.ts +3 -0
  7. package/dist/api/cache.js +12 -0
  8. package/dist/api/index.d.ts +2 -0
  9. package/dist/api/index.js +18 -0
  10. package/dist/api/request.d.ts +23 -0
  11. package/dist/api/request.js +88 -0
  12. package/dist/converter/deezer.d.ts +3 -0
  13. package/dist/converter/deezer.js +45 -0
  14. package/dist/converter/index.d.ts +5 -0
  15. package/dist/converter/index.js +34 -0
  16. package/dist/converter/parse.d.ts +18 -0
  17. package/dist/converter/parse.js +176 -0
  18. package/dist/converter/spotify.d.ts +40 -0
  19. package/dist/converter/spotify.js +154 -0
  20. package/dist/converter/tidal.d.ts +146 -0
  21. package/dist/converter/tidal.js +199 -0
  22. package/dist/converter/youtube.d.ts +6 -0
  23. package/dist/converter/youtube.js +102 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.js +24 -0
  26. package/dist/lib/decrypt.d.ts +9 -0
  27. package/dist/lib/decrypt.js +63 -0
  28. package/dist/lib/fast-lru.d.ts +63 -0
  29. package/dist/lib/fast-lru.js +121 -0
  30. package/dist/lib/get-url.d.ts +16 -0
  31. package/dist/lib/get-url.js +154 -0
  32. package/dist/lib/http.d.ts +66 -0
  33. package/dist/lib/http.js +235 -0
  34. package/dist/lib/metaflac-js.d.ts +124 -0
  35. package/dist/lib/metaflac-js.js +343 -0
  36. package/dist/lib/request.d.ts +18 -0
  37. package/dist/lib/request.js +86 -0
  38. package/dist/metadata-writer/abumCover.d.ts +10 -0
  39. package/dist/metadata-writer/abumCover.js +37 -0
  40. package/dist/metadata-writer/flacmetata.d.ts +3 -0
  41. package/dist/metadata-writer/flacmetata.js +80 -0
  42. package/dist/metadata-writer/getTrackLyrics.d.ts +2 -0
  43. package/dist/metadata-writer/getTrackLyrics.js +26 -0
  44. package/dist/metadata-writer/id3.d.ts +3 -0
  45. package/dist/metadata-writer/id3.js +119 -0
  46. package/dist/metadata-writer/index.d.ts +9 -0
  47. package/dist/metadata-writer/index.js +44 -0
  48. package/dist/metadata-writer/musixmatchLyrics.d.ts +1 -0
  49. package/dist/metadata-writer/musixmatchLyrics.js +39 -0
  50. package/dist/metadata-writer/useragents.d.ts +1 -0
  51. package/dist/metadata-writer/useragents.js +86 -0
  52. package/dist/types/album.d.ts +123 -0
  53. package/dist/types/album.js +2 -0
  54. package/dist/types/artist.d.ts +36 -0
  55. package/dist/types/artist.js +2 -0
  56. package/dist/types/channel.d.ts +33 -0
  57. package/dist/types/channel.js +2 -0
  58. package/dist/types/index.d.ts +10 -0
  59. package/dist/types/index.js +26 -0
  60. package/dist/types/playlist-channel.d.ts +81 -0
  61. package/dist/types/playlist-channel.js +2 -0
  62. package/dist/types/playlist.d.ts +49 -0
  63. package/dist/types/playlist.js +2 -0
  64. package/dist/types/profile.d.ts +29 -0
  65. package/dist/types/profile.js +2 -0
  66. package/dist/types/radio.d.ts +7 -0
  67. package/dist/types/radio.js +2 -0
  68. package/dist/types/search.d.ts +79 -0
  69. package/dist/types/search.js +2 -0
  70. package/dist/types/show.d.ts +61 -0
  71. package/dist/types/show.js +2 -0
  72. package/dist/types/tracks.d.ts +144 -0
  73. package/dist/types/tracks.js +2 -0
  74. package/dist/types/user.d.ts +16 -0
  75. package/dist/types/user.js +2 -0
  76. package/package.json +69 -0
  77. package/types/index.d.ts +1 -0
  78. package/types/index.js +3 -0
  79. package/types/package.json +4 -0
@@ -0,0 +1,124 @@
1
+ /// <reference types="node" />
2
+ declare class Metaflac {
3
+ buffer: Buffer;
4
+ marker: string;
5
+ streamInfo: any;
6
+ blocks: any[];
7
+ padding: any;
8
+ vorbisComment: any;
9
+ vendorString: string;
10
+ tags: any;
11
+ pictures: Buffer[];
12
+ picturesSpecs: object[];
13
+ picturesDatas: string[];
14
+ framesOffset: number;
15
+ constructor(flac: Buffer);
16
+ init(): void;
17
+ parseVorbisComment(): void;
18
+ parsePictureBlock(): void;
19
+ getPicturesSpecs(): object[];
20
+ /**
21
+ * Get the MD5 signature from the STREAMINFO block.
22
+ */
23
+ getMd5sum(): any;
24
+ /**
25
+ * Get the minimum block size from the STREAMINFO block.
26
+ */
27
+ getMinBlocksize(): any;
28
+ /**
29
+ * Get the maximum block size from the STREAMINFO block.
30
+ */
31
+ getMaxBlocksize(): any;
32
+ /**
33
+ * Get the minimum frame size from the STREAMINFO block.
34
+ */
35
+ getMinFramesize(): any;
36
+ /**
37
+ * Get the maximum frame size from the STREAMINFO block.
38
+ */
39
+ getMaxFramesize(): any;
40
+ /**
41
+ * Get the sample rate from the STREAMINFO block.
42
+ */
43
+ getSampleRate(): number;
44
+ /**
45
+ * Get the number of channels from the STREAMINFO block.
46
+ */
47
+ getChannels(): number;
48
+ /**
49
+ * Get the # of bits per sample from the STREAMINFO block.
50
+ */
51
+ getBps(): number;
52
+ /**
53
+ * Get the total # of samples from the STREAMINFO block.
54
+ */
55
+ getTotalSamples(): number;
56
+ /**
57
+ * Show the vendor string from the VORBIS_COMMENT block.
58
+ */
59
+ getVendorTag(): string;
60
+ /**
61
+ * Get all tags where the the field name matches NAME.
62
+ *
63
+ * @param {string} name
64
+ */
65
+ getTag(name: string): any;
66
+ /**
67
+ * Remove all tags whose field name is NAME.
68
+ *
69
+ * @param {string} name
70
+ */
71
+ removeTag(name: string): void;
72
+ /**
73
+ * Remove first tag whose field name is NAME.
74
+ *
75
+ * @param {string} name
76
+ */
77
+ removeFirstTag(name: string): void;
78
+ /**
79
+ * Remove all tags, leaving only the vendor string.
80
+ */
81
+ removeAllTags(): void;
82
+ /**
83
+ * Add a tag.
84
+ * The FIELD must comply with the Vorbis comment spec, of the form NAME=VALUE. If there is currently no tag block, one will be created.
85
+ *
86
+ * @param {string} field
87
+ */
88
+ setTag(field: string): void;
89
+ /**
90
+ * Import a picture and store it in a PICTURE metadata block.
91
+ *
92
+ * @param {string} filename
93
+ */
94
+ importPicture(picture: Buffer, dimension: number, mime: 'image/jpeg' | 'image/png'): void;
95
+ /**
96
+ * Return all tags.
97
+ */
98
+ getAllTags(): any;
99
+ buildSpecification(spec?: {}): {
100
+ type: number;
101
+ mime: string;
102
+ description: string;
103
+ width: number;
104
+ height: number;
105
+ depth: number;
106
+ colors: number;
107
+ };
108
+ /**
109
+ * Build a picture block.
110
+ *
111
+ * @param {Buffer} picture
112
+ * @param {Object} specification
113
+ * @returns {Buffer}
114
+ */
115
+ buildPictureBlock(picture: Buffer, specification?: any): Buffer;
116
+ buildMetadataBlock(type: number, block: Buffer, isLast?: boolean): Buffer;
117
+ buildMetadata(): Buffer[];
118
+ buildStream(): Buffer[];
119
+ /**
120
+ * Save changes to buffer and return changed buffer
121
+ */
122
+ getBuffer(): Buffer;
123
+ }
124
+ export default Metaflac;
@@ -0,0 +1,343 @@
1
+ "use strict";
2
+ // const BLOCK_TYPE = {
3
+ // 0: 'STREAMINFO',
4
+ // 1: 'PADDING',
5
+ // 2: 'APPLICATION',
6
+ // 3: 'SEEKTABLE',
7
+ // 4: 'VORBIS_COMMENT', // There may be only one VORBIS_COMMENT block in a stream.
8
+ // 5: 'CUESHEET',
9
+ // 6: 'PICTURE',
10
+ // };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const STREAMINFO = 0;
13
+ const PADDING = 1;
14
+ const APPLICATION = 2;
15
+ const SEEKTABLE = 3;
16
+ const VORBIS_COMMENT = 4;
17
+ const CUESHEET = 5;
18
+ const PICTURE = 6;
19
+ const formatVorbisComment = (vendorString, commentList) => {
20
+ const bufferArray = [];
21
+ const vendorStringBuffer = Buffer.from(vendorString, 'utf8');
22
+ const vendorLengthBuffer = Buffer.alloc(4);
23
+ vendorLengthBuffer.writeUInt32LE(vendorStringBuffer.length);
24
+ const userCommentListLengthBuffer = Buffer.alloc(4);
25
+ userCommentListLengthBuffer.writeUInt32LE(commentList.length);
26
+ bufferArray.push(vendorLengthBuffer, vendorStringBuffer, userCommentListLengthBuffer);
27
+ for (let i = 0; i < commentList.length; i++) {
28
+ const comment = commentList[i];
29
+ const commentBuffer = Buffer.from(comment, 'utf8');
30
+ const lengthBuffer = Buffer.alloc(4);
31
+ lengthBuffer.writeUInt32LE(commentBuffer.length);
32
+ bufferArray.push(lengthBuffer, commentBuffer);
33
+ }
34
+ return Buffer.concat(bufferArray);
35
+ };
36
+ class Metaflac {
37
+ constructor(flac) {
38
+ this.buffer = flac;
39
+ this.marker = '';
40
+ this.streamInfo = null;
41
+ this.blocks = [];
42
+ this.padding = null;
43
+ this.vorbisComment = null;
44
+ this.vendorString = '';
45
+ this.tags = [];
46
+ this.pictures = [];
47
+ this.picturesSpecs = [];
48
+ this.picturesDatas = [];
49
+ this.framesOffset = 0;
50
+ this.init();
51
+ }
52
+ init() {
53
+ let offset = 4;
54
+ let blockType = 0;
55
+ let isLastBlock = false;
56
+ while (!isLastBlock) {
57
+ blockType = this.buffer.readUInt8(offset++);
58
+ isLastBlock = blockType >= 128;
59
+ blockType = blockType % 128;
60
+ const blockLength = this.buffer.readUIntBE(offset, 3);
61
+ offset += 3;
62
+ if (blockType === STREAMINFO) {
63
+ this.streamInfo = this.buffer.slice(offset, offset + blockLength);
64
+ }
65
+ if (blockType === VORBIS_COMMENT) {
66
+ this.vorbisComment = this.buffer.slice(offset, offset + blockLength);
67
+ this.parseVorbisComment();
68
+ }
69
+ if ([APPLICATION, SEEKTABLE, CUESHEET].includes(blockType)) {
70
+ this.blocks.push([blockType, this.buffer.slice(offset, offset + blockLength)]);
71
+ }
72
+ offset += blockLength;
73
+ }
74
+ this.framesOffset = offset;
75
+ }
76
+ parseVorbisComment() {
77
+ const vendorLength = this.vorbisComment.readUInt32LE(0);
78
+ this.vendorString = this.vorbisComment.slice(4, vendorLength + 4).toString('utf8');
79
+ }
80
+ parsePictureBlock() {
81
+ this.pictures.forEach((picture) => {
82
+ let offset = 0;
83
+ const type = picture.readUInt32BE(offset);
84
+ offset += 4;
85
+ const mimeTypeLength = picture.readUInt32BE(offset);
86
+ offset += 4;
87
+ const mime = picture.slice(offset, offset + mimeTypeLength).toString('ascii');
88
+ offset += mimeTypeLength;
89
+ const descriptionLength = picture.readUInt32BE(offset);
90
+ offset += 4;
91
+ const description = picture.slice(offset, (offset += descriptionLength)).toString('utf8');
92
+ const width = picture.readUInt32BE(offset);
93
+ offset += 4;
94
+ const height = picture.readUInt32BE(offset);
95
+ offset += 4;
96
+ const depth = picture.readUInt32BE(offset);
97
+ offset += 4;
98
+ const colors = picture.readUInt32BE(offset);
99
+ offset += 4;
100
+ const pictureDataLength = picture.readUInt32BE(offset);
101
+ offset += 4;
102
+ this.picturesDatas.push(picture.slice(offset, offset + pictureDataLength));
103
+ this.picturesSpecs.push(this.buildSpecification({
104
+ type,
105
+ mime,
106
+ description,
107
+ width,
108
+ height,
109
+ depth,
110
+ colors,
111
+ }));
112
+ });
113
+ }
114
+ getPicturesSpecs() {
115
+ return this.picturesSpecs;
116
+ }
117
+ /**
118
+ * Get the MD5 signature from the STREAMINFO block.
119
+ */
120
+ getMd5sum() {
121
+ return this.streamInfo.slice(18, 34).toString('hex');
122
+ }
123
+ /**
124
+ * Get the minimum block size from the STREAMINFO block.
125
+ */
126
+ getMinBlocksize() {
127
+ return this.streamInfo.readUInt16BE(0);
128
+ }
129
+ /**
130
+ * Get the maximum block size from the STREAMINFO block.
131
+ */
132
+ getMaxBlocksize() {
133
+ return this.streamInfo.readUInt16BE(2);
134
+ }
135
+ /**
136
+ * Get the minimum frame size from the STREAMINFO block.
137
+ */
138
+ getMinFramesize() {
139
+ return this.streamInfo.readUIntBE(4, 3);
140
+ }
141
+ /**
142
+ * Get the maximum frame size from the STREAMINFO block.
143
+ */
144
+ getMaxFramesize() {
145
+ return this.streamInfo.readUIntBE(7, 3);
146
+ }
147
+ /**
148
+ * Get the sample rate from the STREAMINFO block.
149
+ */
150
+ getSampleRate() {
151
+ // 20 bits number
152
+ return this.streamInfo.readUIntBE(10, 3) >> 4;
153
+ }
154
+ /**
155
+ * Get the number of channels from the STREAMINFO block.
156
+ */
157
+ getChannels() {
158
+ // 3 bits
159
+ return this.streamInfo.readUIntBE(10, 3) & (0x00000f >> 1);
160
+ }
161
+ /**
162
+ * Get the # of bits per sample from the STREAMINFO block.
163
+ */
164
+ getBps() {
165
+ return this.streamInfo.readUIntBE(12, 2) & (0x01f0 >> 4);
166
+ }
167
+ /**
168
+ * Get the total # of samples from the STREAMINFO block.
169
+ */
170
+ getTotalSamples() {
171
+ return this.streamInfo.readUIntBE(13, 5) & 0x0fffffffff;
172
+ }
173
+ /**
174
+ * Show the vendor string from the VORBIS_COMMENT block.
175
+ */
176
+ getVendorTag() {
177
+ return this.vendorString;
178
+ }
179
+ /**
180
+ * Get all tags where the the field name matches NAME.
181
+ *
182
+ * @param {string} name
183
+ */
184
+ getTag(name) {
185
+ return this.tags
186
+ .filter((item) => {
187
+ const itemName = item.split('=')[0];
188
+ return itemName === name;
189
+ })
190
+ .join('\n');
191
+ }
192
+ /**
193
+ * Remove all tags whose field name is NAME.
194
+ *
195
+ * @param {string} name
196
+ */
197
+ removeTag(name) {
198
+ this.tags = this.tags.filter((item) => {
199
+ const itemName = item.split('=')[0];
200
+ return itemName !== name;
201
+ });
202
+ }
203
+ /**
204
+ * Remove first tag whose field name is NAME.
205
+ *
206
+ * @param {string} name
207
+ */
208
+ removeFirstTag(name) {
209
+ const found = this.tags.findIndex((item) => {
210
+ return item.split('=')[0] === name;
211
+ });
212
+ if (found !== -1) {
213
+ this.tags.splice(found, 1);
214
+ }
215
+ }
216
+ /**
217
+ * Remove all tags, leaving only the vendor string.
218
+ */
219
+ removeAllTags() {
220
+ this.tags = [];
221
+ }
222
+ /**
223
+ * Add a tag.
224
+ * The FIELD must comply with the Vorbis comment spec, of the form NAME=VALUE. If there is currently no tag block, one will be created.
225
+ *
226
+ * @param {string} field
227
+ */
228
+ setTag(field) {
229
+ if (field.indexOf('=') === -1) {
230
+ throw new Error(`malformed vorbis comment field "${field}", field contains no '=' character`);
231
+ }
232
+ this.tags.push(field);
233
+ }
234
+ /**
235
+ * Import a picture and store it in a PICTURE metadata block.
236
+ *
237
+ * @param {string} filename
238
+ */
239
+ importPicture(picture, dimension, mime) {
240
+ const spec = this.buildSpecification({
241
+ mime,
242
+ width: dimension,
243
+ height: dimension,
244
+ });
245
+ this.pictures.push(this.buildPictureBlock(picture, spec));
246
+ this.picturesSpecs.push(spec);
247
+ }
248
+ /**
249
+ * Return all tags.
250
+ */
251
+ getAllTags() {
252
+ return this.tags;
253
+ }
254
+ buildSpecification(spec = {}) {
255
+ const defaults = {
256
+ type: 3,
257
+ mime: 'image/jpeg',
258
+ description: '',
259
+ width: 0,
260
+ height: 0,
261
+ depth: 24,
262
+ colors: 0,
263
+ };
264
+ return Object.assign(defaults, spec);
265
+ }
266
+ /**
267
+ * Build a picture block.
268
+ *
269
+ * @param {Buffer} picture
270
+ * @param {Object} specification
271
+ * @returns {Buffer}
272
+ */
273
+ buildPictureBlock(picture, specification = {}) {
274
+ const pictureType = Buffer.alloc(4);
275
+ const mimeLength = Buffer.alloc(4);
276
+ const mime = Buffer.from(specification.mime, 'ascii');
277
+ const descriptionLength = Buffer.alloc(4);
278
+ const description = Buffer.from(specification.description, 'utf8');
279
+ const width = Buffer.alloc(4);
280
+ const height = Buffer.alloc(4);
281
+ const depth = Buffer.alloc(4);
282
+ const colors = Buffer.alloc(4);
283
+ const pictureLength = Buffer.alloc(4);
284
+ pictureType.writeUInt32BE(specification.type);
285
+ mimeLength.writeUInt32BE(specification.mime.length);
286
+ descriptionLength.writeUInt32BE(specification.description.length);
287
+ width.writeUInt32BE(specification.width);
288
+ height.writeUInt32BE(specification.height);
289
+ depth.writeUInt32BE(specification.depth);
290
+ colors.writeUInt32BE(specification.colors);
291
+ pictureLength.writeUInt32BE(picture.length);
292
+ return Buffer.concat([
293
+ pictureType,
294
+ mimeLength,
295
+ mime,
296
+ descriptionLength,
297
+ description,
298
+ width,
299
+ height,
300
+ depth,
301
+ colors,
302
+ pictureLength,
303
+ picture,
304
+ ]);
305
+ }
306
+ buildMetadataBlock(type, block, isLast = false) {
307
+ const header = Buffer.alloc(4);
308
+ if (isLast) {
309
+ type += 128;
310
+ }
311
+ header.writeUIntBE(type, 0, 1);
312
+ header.writeUIntBE(block.length, 1, 3);
313
+ return Buffer.concat([header, block]);
314
+ }
315
+ buildMetadata() {
316
+ const bufferArray = [];
317
+ bufferArray.push(this.buildMetadataBlock(STREAMINFO, this.streamInfo));
318
+ this.blocks.forEach((block) => {
319
+ // @ts-ignore
320
+ bufferArray.push(this.buildMetadataBlock(...block));
321
+ });
322
+ bufferArray.push(this.buildMetadataBlock(VORBIS_COMMENT, formatVorbisComment(this.vendorString, this.tags)));
323
+ this.pictures.forEach((block) => {
324
+ bufferArray.push(this.buildMetadataBlock(PICTURE, block));
325
+ });
326
+ if (this.padding == null) {
327
+ this.padding = Buffer.alloc(16384);
328
+ }
329
+ bufferArray.push(this.buildMetadataBlock(PADDING, this.padding, true));
330
+ return bufferArray;
331
+ }
332
+ buildStream() {
333
+ const metadata = this.buildMetadata();
334
+ return [this.buffer.slice(0, 4), ...metadata, this.buffer.slice(this.framesOffset)];
335
+ }
336
+ /**
337
+ * Save changes to buffer and return changed buffer
338
+ */
339
+ getBuffer() {
340
+ return Buffer.concat(this.buildStream());
341
+ }
342
+ }
343
+ exports.default = Metaflac;
@@ -0,0 +1,18 @@
1
+ import type { HttpQuery, HttpResponse } from './http';
2
+ type DeezerRequestConfig = {
3
+ headers?: Record<string, string>;
4
+ params?: HttpQuery;
5
+ };
6
+ export declare const initDeezerApi: (arl: string) => Promise<string>;
7
+ declare const _default: {
8
+ defaults: {
9
+ baseURL?: string | undefined;
10
+ headers: import("./http").HttpHeaders;
11
+ maxRedirects: number;
12
+ params: HttpQuery;
13
+ timeout: number;
14
+ };
15
+ get: <T>(url: string, config?: DeezerRequestConfig) => Promise<HttpResponse<T>>;
16
+ post: <T_1>(url: string, body?: unknown, config?: DeezerRequestConfig) => Promise<HttpResponse<T_1>>;
17
+ };
18
+ export default _default;
@@ -0,0 +1,86 @@
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.initDeezerApi = void 0;
7
+ const delay_1 = __importDefault(require("delay"));
8
+ const http_1 = require("./http");
9
+ let user_arl = 'c973964816688562722418b5200c1515dffaad15a42643ebf87cc72824a54612ec51c2ad42d566743f9e424c774e98ccae7737770acff59251328e6cd598c7bcac38ca269adf78bfb88ec5bbad6cd800db3c0b88b2af645bb22b99e71de26416';
10
+ const instance = new http_1.HttpClient({
11
+ baseURL: 'https://api.deezer.com/1.0',
12
+ timeout: 15000,
13
+ headers: {
14
+ Accept: '*/*',
15
+ 'Accept-Encoding': 'gzip, deflate',
16
+ 'Accept-Language': 'en-US',
17
+ 'Cache-Control': 'no-cache',
18
+ 'Content-Type': 'application/json; charset=UTF-8',
19
+ 'User-Agent': 'Deezer/8.32.0.2 (iOS; 14.4; Mobile; en; iPhone10_5)',
20
+ },
21
+ params: {
22
+ version: '8.32.0',
23
+ api_key: 'ZAIVAHCEISOHWAICUQUEXAEPICENGUAFAEZAIPHAELEEVAHPHUCUFONGUAPASUAY',
24
+ output: 3,
25
+ input: 3,
26
+ buildId: 'ios12_universal',
27
+ screenHeight: '480',
28
+ screenWidth: '320',
29
+ lang: 'en',
30
+ },
31
+ });
32
+ const getApiToken = async () => {
33
+ const { data } = await instance.get('https://www.deezer.com/ajax/gw-light.php', {
34
+ params: {
35
+ method: 'deezer.getUserData',
36
+ api_version: '1.0',
37
+ api_token: 'null',
38
+ },
39
+ });
40
+ instance.defaults.params.sid = data.results.SESSION_ID;
41
+ instance.defaults.params.api_token = data.results.checkForm;
42
+ return data.results.checkForm;
43
+ };
44
+ const initDeezerApi = async (arl) => {
45
+ if (arl.length !== 192) {
46
+ throw new Error(`Invalid arl. Length should be 192 characters. You have provided ${arl.length} characters.`);
47
+ }
48
+ user_arl = arl;
49
+ const { data } = await instance.get('https://www.deezer.com/ajax/gw-light.php', {
50
+ params: { method: 'deezer.ping', api_version: '1.0', api_token: '' },
51
+ headers: { cookie: 'arl=' + arl },
52
+ });
53
+ instance.defaults.params.sid = data.results.SESSION;
54
+ return data.results.SESSION;
55
+ };
56
+ exports.initDeezerApi = initDeezerApi;
57
+ let token_retry = 0;
58
+ const requestWithRetry = async (method, url, body, config = {}) => {
59
+ var _a;
60
+ const response = method === 'POST' ? await instance.post(url, body, config) : await instance.get(url, config);
61
+ const error = (_a = response.data) === null || _a === void 0 ? void 0 : _a.error;
62
+ if (!error || Object.keys(error).length === 0) {
63
+ token_retry = 0;
64
+ return response;
65
+ }
66
+ if (error.NEED_API_AUTH_REQUIRED) {
67
+ await (0, exports.initDeezerApi)(user_arl);
68
+ return await requestWithRetry(method, url, body, config);
69
+ }
70
+ if (error.code === 4) {
71
+ await delay_1.default.range(1000, 1500);
72
+ return await requestWithRetry(method, url, body, config);
73
+ }
74
+ if (error.GATEWAY_ERROR || (error.VALID_TOKEN_REQUIRED && token_retry < 15)) {
75
+ token_retry += 1;
76
+ await getApiToken();
77
+ return await requestWithRetry(method, url, body, config);
78
+ }
79
+ token_retry = 0;
80
+ return response;
81
+ };
82
+ exports.default = {
83
+ defaults: instance.defaults,
84
+ get: async (url, config = {}) => await requestWithRetry('GET', url, undefined, config),
85
+ post: async (url, body, config = {}) => await requestWithRetry('POST', url, body, config),
86
+ };
@@ -0,0 +1,10 @@
1
+ /// <reference types="node" />
2
+ import type { trackType } from '../types';
3
+ type coverSize = 56 | 250 | 500 | 1000 | 1500 | 1800 | number;
4
+ /**
5
+ *
6
+ * @param {Object} track track info json from deezer api
7
+ * @param {Number} albumCoverSize in pixel, between 56-1800
8
+ */
9
+ export declare const downloadAlbumCover: (track: trackType, albumCoverSize: coverSize) => Promise<Buffer | null>;
10
+ export {};
@@ -0,0 +1,37 @@
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.downloadAlbumCover = void 0;
7
+ const fast_lru_1 = __importDefault(require("../lib/fast-lru"));
8
+ const http_1 = require("../lib/http");
9
+ // expire cache in 30 minutes
10
+ const lru = new fast_lru_1.default({
11
+ maxSize: 50,
12
+ ttl: 30 * 60000,
13
+ });
14
+ /**
15
+ *
16
+ * @param {Object} track track info json from deezer api
17
+ * @param {Number} albumCoverSize in pixel, between 56-1800
18
+ */
19
+ const downloadAlbumCover = async (track, albumCoverSize) => {
20
+ if (!track.ALB_PICTURE) {
21
+ return null;
22
+ }
23
+ const cache = lru.get(track.ALB_PICTURE + albumCoverSize);
24
+ if (cache) {
25
+ return cache;
26
+ }
27
+ try {
28
+ const url = `https://e-cdns-images.dzcdn.net/images/cover/${track.ALB_PICTURE}/${albumCoverSize}x${albumCoverSize}-000000-80-0-0.jpg`;
29
+ const data = await (0, http_1.getBuffer)(url);
30
+ lru.set(track.ALB_PICTURE + albumCoverSize, data);
31
+ return data;
32
+ }
33
+ catch (err) {
34
+ return null;
35
+ }
36
+ };
37
+ exports.downloadAlbumCover = downloadAlbumCover;
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" />
2
+ import type { albumTypePublicApi, trackType } from '../types';
3
+ export declare const writeMetadataFlac: (buffer: Buffer, track: trackType, album: albumTypePublicApi | null, dimension: number, cover?: Buffer | null) => Buffer;