musicbrainz-api 0.12.0 → 0.14.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/README.md +33 -139
- package/lib/coverartarchive-api.js +3 -7
- package/lib/digest-auth.js +4 -8
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -18
- package/lib/musicbrainz-api.d.ts +54 -170
- package/lib/musicbrainz-api.js +81 -312
- package/lib/musicbrainz.types.d.ts +14 -6
- package/lib/musicbrainz.types.js +2 -5
- package/lib/xml/xml-isrc-list.d.ts +1 -1
- package/lib/xml/xml-isrc-list.js +3 -7
- package/lib/xml/xml-isrc.js +1 -5
- package/lib/xml/xml-metadata.d.ts +1 -1
- package/lib/xml/xml-metadata.js +4 -8
- package/lib/xml/xml-recording.d.ts +1 -1
- package/lib/xml/xml-recording.js +3 -7
- package/package.json +20 -19
- package/lib/rate-limiter.d.ts +0 -8
- package/lib/rate-limiter.js +0 -34
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://npmjs.org/package/musicbrainz-api)
|
|
3
3
|
[](https://npmcharts.com/compare/musicbrainz-api?interval=30&start=365)
|
|
4
4
|
[](https://coveralls.io/github/Borewit/musicbrainz-api?branch=master)
|
|
5
|
-
[](https://
|
|
5
|
+
[](https://app.codacy.com/gh/Borewit/musicbrainz-api/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
6
6
|
[](https://github.com/Borewit/musicbrainz-api/actions/workflows/codeql.yml)
|
|
7
7
|
[](https://snyk.io/test/github/Borewit/musicbrainz-api?targetFile=package.json)
|
|
8
8
|
[](https://deepscan.io/dashboard#view=project&tid=5165&pid=6991&bid=63373)
|
|
@@ -34,32 +34,20 @@ If you plan to use this module for submitting metadata, please ensure you comply
|
|
|
34
34
|
|
|
35
35
|
## Example
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
JavaScript example, how to import 'musicbrainz-api:
|
|
39
|
-
```js
|
|
40
|
-
const MusicBrainzApi = require('musicbrainz-api').MusicBrainzApi;
|
|
41
|
-
|
|
42
|
-
const mbApi = new MusicBrainzApi({
|
|
43
|
-
appName: 'my-app',
|
|
44
|
-
appVersion: '0.1.0',
|
|
45
|
-
appContactInfo: 'user@mail.org'
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
In TypeScript it would look like this:
|
|
37
|
+
Example, how to import 'musicbrainz-api:
|
|
50
38
|
```js
|
|
51
39
|
import {MusicBrainzApi} from 'musicbrainz-api';
|
|
52
40
|
|
|
53
41
|
const mbApi = new MusicBrainzApi({
|
|
54
42
|
appName: 'my-app',
|
|
55
43
|
appVersion: '0.1.0',
|
|
56
|
-
appContactInfo: 'user@mail.org'
|
|
44
|
+
appContactInfo: 'user@mail.org'
|
|
57
45
|
});
|
|
58
46
|
```
|
|
59
47
|
|
|
60
48
|
The following configuration settings can be passed
|
|
61
49
|
```js
|
|
62
|
-
import {MusicBrainzApi} from '
|
|
50
|
+
import {MusicBrainzApi} from 'musicbrainz-api';
|
|
63
51
|
|
|
64
52
|
const config = {
|
|
65
53
|
// MusicBrainz bot account username & password (optional)
|
|
@@ -94,106 +82,14 @@ MusicBrainz API documentation: [XML Web Service/Version 2 Lookups](https://wiki.
|
|
|
94
82
|
### Generic lookup function
|
|
95
83
|
|
|
96
84
|
Arguments:
|
|
97
|
-
* entity: `'artist'` | `'label'` | `'
|
|
85
|
+
* entity: `'area'` | `'artist'` | `'collection'` | `'instrument'` | `'label'` | `'place'` | `'release'` | `'release-group'` | `'recording'` | `'series'` | `'work'` | `'url'` | `'event'`
|
|
98
86
|
* MBID [(MusicBrainz identifier)](https://wiki.musicbrainz.org/MusicBrainz_Identifier)
|
|
87
|
+
* query
|
|
99
88
|
|
|
100
89
|
```js
|
|
101
|
-
const artist = await mbApi.
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Lookup area
|
|
105
|
-
|
|
106
|
-
```js
|
|
107
|
-
const area = await mbApi.lookupArea('ab2528d9-719f-4261-8098-21849222a0f2');
|
|
90
|
+
const artist = await mbApi.lookup('artist', 'ab2528d9-719f-4261-8098-21849222a0f2');
|
|
108
91
|
```
|
|
109
92
|
|
|
110
|
-
### Lookup artist
|
|
111
|
-
|
|
112
|
-
Lookup an `artist` and include their `releases`, `release-groups` and `aliases`
|
|
113
|
-
|
|
114
|
-
```js
|
|
115
|
-
const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2');
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Lookup collection
|
|
119
|
-
|
|
120
|
-
Lookup an instrument
|
|
121
|
-
|
|
122
|
-
```js
|
|
123
|
-
const collection = await mbApi.lookupCollection('de4fdfc4-53aa-458a-b463-8761cc7f5af8');
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
Lookup an event
|
|
127
|
-
|
|
128
|
-
```js
|
|
129
|
-
const event = await mbApi.lookupEvent('6d32c658-151e-45ec-88c4-fb8787524d61');
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Lookup instrument
|
|
133
|
-
|
|
134
|
-
Lookup an instrument
|
|
135
|
-
|
|
136
|
-
```js
|
|
137
|
-
const instrument = await mbApi.lookupInstrument('b3eac5f9-7859-4416-ac39-7154e2e8d348');
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Lookup label
|
|
141
|
-
|
|
142
|
-
Lookup a label
|
|
143
|
-
|
|
144
|
-
```js
|
|
145
|
-
const label = await mbApi.lookupLabel('25dda9f9-f069-4898-82f0-59330a106c7f');
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Lookup place
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
const place = await mbApi.lookupPlace('e6cfb74d-d69b-44c3-b890-1b3f509816e4');
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
```js
|
|
155
|
-
const place = await mbApi.lookupSeries('1ae6c9bc-2931-4d75-bee4-3dc53dfd246a');
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries), which will return more (nested) information:
|
|
159
|
-
```js
|
|
160
|
-
const artist = await mbApi.lookupArtist('ab2528d9-719f-4261-8098-21849222a0f2', ['releases', 'recordings', 'url-rels']);
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Lookup recording
|
|
164
|
-
|
|
165
|
-
The second argument can be used to pass [subqueries](https://wiki.musicbrainz.org/Development/XML_Web_Service/Version_2#Subqueries):
|
|
166
|
-
```js
|
|
167
|
-
const recording = await mbApi.lookupRecording('16afa384-174e-435e-bfa3-5591accda31c', ['artists', 'url-rels']);
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Lookup release
|
|
171
|
-
```js
|
|
172
|
-
const release = await mbApi.lookupRelease('976e0677-a480-4a5e-a177-6a86c1900bbf', ['artists', 'url-rels']);
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Lookup release-group
|
|
176
|
-
```js
|
|
177
|
-
const releaseGroup = await mbApi.lookupReleaseGroup('19099ea5-3600-4154-b482-2ec68815883e');
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Lookup work
|
|
181
|
-
```js
|
|
182
|
-
const work = await mbApi.lookupWork('b2aa02f4-6c95-43be-a426-aedb9f9a3805');
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Lookup URL
|
|
186
|
-
```js
|
|
187
|
-
const url = await mbApi.lookupUrl('c69556a6-7ded-4c54-809c-afb45a1abe7d');
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
## Browse entities
|
|
191
|
-
|
|
192
|
-
### Browse area
|
|
193
|
-
|
|
194
|
-
```js
|
|
195
|
-
const area = await browseAreas(query);
|
|
196
|
-
````
|
|
197
93
|
|
|
198
94
|
| Query argument | Query value |
|
|
199
95
|
|-----------------------|-----------------|
|
|
@@ -202,7 +98,7 @@ const area = await browseAreas(query);
|
|
|
202
98
|
### Browse artist
|
|
203
99
|
|
|
204
100
|
```js
|
|
205
|
-
const
|
|
101
|
+
const artists = await browse('artist', query);
|
|
206
102
|
````
|
|
207
103
|
|
|
208
104
|
| Query argument | Query value |
|
|
@@ -216,7 +112,7 @@ const artist = await browseArtist(query);
|
|
|
216
112
|
|
|
217
113
|
### Browse collection
|
|
218
114
|
```js
|
|
219
|
-
const
|
|
115
|
+
const collections = await browse('collection', query);
|
|
220
116
|
````
|
|
221
117
|
|
|
222
118
|
| Query argument | Query value |
|
|
@@ -234,7 +130,7 @@ const artist = await browseCollection(query);
|
|
|
234
130
|
|
|
235
131
|
### Browse events
|
|
236
132
|
```js
|
|
237
|
-
const events = await
|
|
133
|
+
const events = await browse('event', query);
|
|
238
134
|
````
|
|
239
135
|
|
|
240
136
|
| Query argument | Query value |
|
|
@@ -246,7 +142,7 @@ const events = await browseEvents(query);
|
|
|
246
142
|
|
|
247
143
|
### Browse instruments
|
|
248
144
|
```js
|
|
249
|
-
const instruments = await
|
|
145
|
+
const instruments = await browse('event', query);
|
|
250
146
|
````
|
|
251
147
|
|
|
252
148
|
| Query argument | Query value |
|
|
@@ -255,7 +151,7 @@ const instruments = await browseEvents(query);
|
|
|
255
151
|
|
|
256
152
|
### Browse labels
|
|
257
153
|
```js
|
|
258
|
-
const labels = await
|
|
154
|
+
const labels = await browse('label', query);
|
|
259
155
|
````
|
|
260
156
|
|
|
261
157
|
| Query argument | Query value |
|
|
@@ -266,7 +162,7 @@ const labels = await browseLabels(query);
|
|
|
266
162
|
|
|
267
163
|
### Browse places
|
|
268
164
|
```js
|
|
269
|
-
const places = await
|
|
165
|
+
const places = await browse('place', query);
|
|
270
166
|
````
|
|
271
167
|
|
|
272
168
|
| Query argument | Query value |
|
|
@@ -276,7 +172,7 @@ const places = await browsePlaces(query);
|
|
|
276
172
|
|
|
277
173
|
### Browse recordings
|
|
278
174
|
```js
|
|
279
|
-
const recordings = await
|
|
175
|
+
const recordings = await browse('recording', query);
|
|
280
176
|
````
|
|
281
177
|
|
|
282
178
|
| Query argument | Query value |
|
|
@@ -288,7 +184,7 @@ const recordings = await browseRecordings(query);
|
|
|
288
184
|
|
|
289
185
|
### Browse releases
|
|
290
186
|
```js
|
|
291
|
-
const
|
|
187
|
+
const releases = await browse('release', query);
|
|
292
188
|
````
|
|
293
189
|
|
|
294
190
|
| Query argument | Query value |
|
|
@@ -306,7 +202,7 @@ const places = await browseReleases(query);
|
|
|
306
202
|
|
|
307
203
|
### Browse release-groups
|
|
308
204
|
```js
|
|
309
|
-
const
|
|
205
|
+
const releaseGroups = await browse('release-group',query);
|
|
310
206
|
```
|
|
311
207
|
|
|
312
208
|
| Query argument | Query value |
|
|
@@ -317,7 +213,7 @@ const places = await browseReleaseGroups(query);
|
|
|
317
213
|
|
|
318
214
|
### Browse series
|
|
319
215
|
```js
|
|
320
|
-
const
|
|
216
|
+
const series = await browse('series');
|
|
321
217
|
````
|
|
322
218
|
|
|
323
219
|
| Query argument | Query value |
|
|
@@ -335,7 +231,7 @@ const places = await browseSeries();
|
|
|
335
231
|
|
|
336
232
|
### Browse works
|
|
337
233
|
```js
|
|
338
|
-
const
|
|
234
|
+
const works = await browse('work');
|
|
339
235
|
````
|
|
340
236
|
|
|
341
237
|
| Query argument | Query value |
|
|
@@ -345,7 +241,7 @@ const places = await browseWorks();
|
|
|
345
241
|
|
|
346
242
|
### Browse urls
|
|
347
243
|
```js
|
|
348
|
-
const urls = await
|
|
244
|
+
const urls = await browse('url');
|
|
349
245
|
````
|
|
350
246
|
|
|
351
247
|
| Query argument | Query value |
|
|
@@ -359,9 +255,9 @@ Implements [XML Web Service/Version 2/Search](https://wiki.musicbrainz.org/Devel
|
|
|
359
255
|
|
|
360
256
|
There are different search fields depending on the entity.
|
|
361
257
|
|
|
362
|
-
###
|
|
258
|
+
### Search function
|
|
363
259
|
|
|
364
|
-
Searches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number)
|
|
260
|
+
Searches can be performed using the generic search function: `query(entity: mb.EntityType, query: string | IFormData, offset?: number, limit?: number): Promise<entity>`
|
|
365
261
|
|
|
366
262
|
Arguments:
|
|
367
263
|
* Entity type, which can be one of:
|
|
@@ -404,27 +300,25 @@ Same as previous example, but automatically serialize parameters to search query
|
|
|
404
300
|
mbApi.search('release', 'barcode: 602537479870');
|
|
405
301
|
````
|
|
406
302
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
The following entity specific search functions are available:
|
|
410
|
-
```TypeScript
|
|
411
|
-
searchArtist(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IArtistList>
|
|
412
|
-
searchReleaseGroup(query: string | IFormData, offset?: number, limit?: number): Promise<mb.IReleaseGroupList>`
|
|
413
|
-
```
|
|
303
|
+
##### Example: search artist by artist name
|
|
414
304
|
|
|
415
305
|
Search artist:
|
|
416
306
|
```js
|
|
417
|
-
const result = await mbApi.
|
|
307
|
+
const result = await mbApi.search('artist', {query: 'Stromae'});
|
|
418
308
|
```
|
|
419
309
|
|
|
310
|
+
##### Example: search release-group by artist name
|
|
311
|
+
|
|
420
312
|
Search release-group:
|
|
421
313
|
```js
|
|
422
|
-
const result = await mbApi.
|
|
314
|
+
const result = await mbApi.search('release-group', {query: 'Racine carrée'});
|
|
423
315
|
```
|
|
424
316
|
|
|
317
|
+
##### Example: search release-group by release-group and an artist
|
|
318
|
+
|
|
425
319
|
Search a combination of a release-group and an artist.
|
|
426
320
|
```js
|
|
427
|
-
const result = await mbApi.
|
|
321
|
+
const result = await mbApi.search('release-group', {artist: 'Racine carrée', releasegroup: 'Stromae'});
|
|
428
322
|
```
|
|
429
323
|
|
|
430
324
|
# Submitting data via XML POST
|
|
@@ -451,7 +345,7 @@ For all of the following function you need to use a dedicated bot account.
|
|
|
451
345
|
|
|
452
346
|
## Submitting ISRC via post user form-data
|
|
453
347
|
|
|
454
|
-
<img width="150" src="http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg"/>
|
|
348
|
+
<img width="150" src="http://www.clker.com/cliparts/i/w/L/q/u/1/work-in-progress.svg" alt="Work in progress"/>
|
|
455
349
|
Use with caution, and only on a test server, it may clear existing metadata as side effect.
|
|
456
350
|
|
|
457
351
|
```js
|
|
@@ -460,7 +354,7 @@ const mbid_Formidable = '16afa384-174e-435e-bfa3-5591accda31c';
|
|
|
460
354
|
const isrc_Formidable = 'BET671300161';
|
|
461
355
|
|
|
462
356
|
|
|
463
|
-
const recording = await mbApi.
|
|
357
|
+
const recording = await mbApi.lookup('recording', mbid_Formidable);
|
|
464
358
|
|
|
465
359
|
// Authentication the http-session against MusicBrainz (as defined in config.baseUrl)
|
|
466
360
|
const succeed = await mbApi.login();
|
|
@@ -473,7 +367,7 @@ await mbApi.addIsrc(recording, isrc_Formidable);
|
|
|
473
367
|
### Submit recording URL
|
|
474
368
|
|
|
475
369
|
```js
|
|
476
|
-
const recording = await mbApi.
|
|
370
|
+
const recording = await mbApi.lookup('recording', '16afa384-174e-435e-bfa3-5591accda31c');
|
|
477
371
|
|
|
478
372
|
const succeed = await mbApi.login();
|
|
479
373
|
assert.isTrue(succeed, 'Login successful');
|
|
@@ -486,7 +380,7 @@ await mbApi.addUrlToRecording(recording, {
|
|
|
486
380
|
|
|
487
381
|
Actually a Spotify-track-ID can be submitted easier:
|
|
488
382
|
```js
|
|
489
|
-
const recording = await mbApi.
|
|
383
|
+
const recording = await mbApi.lookup('recording', '16afa384-174e-435e-bfa3-5591accda31c');
|
|
490
384
|
|
|
491
385
|
const succeed = await mbApi.login();
|
|
492
386
|
assert.isTrue(succeed, 'Login successful');
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CoverArtArchiveApi = void 0;
|
|
4
1
|
/* eslint-disable-next-line */
|
|
5
|
-
|
|
6
|
-
class CoverArtArchiveApi {
|
|
2
|
+
import got from 'got';
|
|
3
|
+
export class CoverArtArchiveApi {
|
|
7
4
|
constructor() {
|
|
8
5
|
this.host = 'coverartarchive.org';
|
|
9
6
|
}
|
|
10
7
|
async getJson(path) {
|
|
11
|
-
const response = await
|
|
8
|
+
const response = await got.get('https://' + this.host + path, {
|
|
12
9
|
headers: {
|
|
13
10
|
Accept: `application/json`
|
|
14
11
|
},
|
|
@@ -33,5 +30,4 @@ class CoverArtArchiveApi {
|
|
|
33
30
|
return info;
|
|
34
31
|
}
|
|
35
32
|
}
|
|
36
|
-
exports.CoverArtArchiveApi = CoverArtArchiveApi;
|
|
37
33
|
//# sourceMappingURL=coverartarchive-api.js.map
|
package/lib/digest-auth.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.DigestAuth = void 0;
|
|
4
|
-
const uuid_1 = require("uuid");
|
|
5
|
-
const crypto = require("crypto");
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import * as crypto from 'crypto';
|
|
6
3
|
function md5(str) {
|
|
7
4
|
return crypto.createHash('md5').update(str).digest('hex'); // lgtm [js/insufficient-password-hash]
|
|
8
5
|
}
|
|
9
|
-
class DigestAuth {
|
|
6
|
+
export class DigestAuth {
|
|
10
7
|
/**
|
|
11
8
|
* RFC 2617: handle both MD5 and MD5-sess algorithms.
|
|
12
9
|
*
|
|
@@ -45,7 +42,7 @@ class DigestAuth {
|
|
|
45
42
|
}
|
|
46
43
|
const qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth';
|
|
47
44
|
const nc = qop && '00000001';
|
|
48
|
-
const cnonce = qop && (
|
|
45
|
+
const cnonce = qop && uuidv4().replace(/-/g, '');
|
|
49
46
|
const ha1 = DigestAuth.ha1Compute(challenge.algorithm, this.credentials.username, challenge.realm, this.credentials.password, challenge.nonce, cnonce);
|
|
50
47
|
const ha2 = md5(method + ':' + path); // lgtm [js/insufficient-password-hash]
|
|
51
48
|
const digestResponse = qop
|
|
@@ -79,5 +76,4 @@ class DigestAuth {
|
|
|
79
76
|
return authHeader;
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
|
-
exports.DigestAuth = DigestAuth;
|
|
83
79
|
//# sourceMappingURL=digest-auth.js.map
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './coverartarchive-api';
|
|
2
|
-
export * from './musicbrainz-api';
|
|
1
|
+
export * from './coverartarchive-api.js';
|
|
2
|
+
export * from './musicbrainz-api.js';
|
package/lib/index.js
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./coverartarchive-api"), exports);
|
|
18
|
-
__exportStar(require("./musicbrainz-api"), exports);
|
|
1
|
+
export * from './coverartarchive-api.js';
|
|
2
|
+
export * from './musicbrainz-api.js';
|
|
19
3
|
//# sourceMappingURL=index.js.map
|