musicbrainz-api 0.10.1 → 0.10.3
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/.idea/checkstyle-idea.xml +16 -0
- package/.idea/inspectionProfiles/Project_Default.xml +7 -0
- package/.idea/misc.xml +5 -11
- package/.idea/modules.xml +7 -7
- package/.idea/vcs.xml +5 -5
- package/README.md +481 -477
- package/lib/digest-auth.ts +101 -0
- package/lib/musicbrainz-api.ts +794 -0
- package/lib/musicbrainz.types.d.ts +6 -1
- package/lib/musicbrainz.types.ts +689 -0
- package/lib/rate-limiter.ts +34 -0
- package/lib/xml/xml-isrc-list.ts +20 -0
- package/lib/xml/xml-isrc.ts +15 -0
- package/lib/xml/xml-metadata.ts +30 -0
- package/lib/xml/xml-recording.ts +19 -0
- package/package.json +103 -104
- package/.idea/$CACHE_FILE$ +0 -6
- package/.idea/$PRODUCT_WORKSPACE_FILE$ +0 -19
- package/.idea/jpa-buddy.xml +0 -6
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as Debug from 'debug';
|
|
2
|
+
|
|
3
|
+
const debug = Debug('musicbrainz-api:rate-limiter');
|
|
4
|
+
|
|
5
|
+
export class RateLimiter {
|
|
6
|
+
|
|
7
|
+
public static sleep(ms): Promise<void> {
|
|
8
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public queue: number[] = [];
|
|
12
|
+
private readonly period: number;
|
|
13
|
+
|
|
14
|
+
public constructor(period: number, private maxCalls: number) {
|
|
15
|
+
this.period = 1000 * period;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public async limit(): Promise<void> {
|
|
19
|
+
let now = new Date().getTime();
|
|
20
|
+
const t0 = now - (this.period);
|
|
21
|
+
while (this.queue.length > 0 && this.queue[0] < t0) {
|
|
22
|
+
this.queue.shift();
|
|
23
|
+
}
|
|
24
|
+
if (this.queue.length >= this.maxCalls) {
|
|
25
|
+
const delay = this.queue[0] + this.period - now;
|
|
26
|
+
debug(`Client side rate limiter activated: cool down for ${delay / 1000} s...`);
|
|
27
|
+
return RateLimiter.sleep(delay);
|
|
28
|
+
}
|
|
29
|
+
now = new Date().getTime();
|
|
30
|
+
this.queue.push(now);
|
|
31
|
+
// const ratePerSec = 1000 * this.queue.length / (now - this.queue[0]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { XmlIsrc } from './xml-isrc';
|
|
2
|
+
|
|
3
|
+
export class XmlIsrcList {
|
|
4
|
+
|
|
5
|
+
public items: XmlIsrc[] = [];
|
|
6
|
+
|
|
7
|
+
public pushIsrc(isrc: string) {
|
|
8
|
+
this.items.push(new XmlIsrc(isrc));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public toXml() {
|
|
12
|
+
return this.items.length === 0 ? null : {
|
|
13
|
+
name: 'isrc-list',
|
|
14
|
+
attrs: {
|
|
15
|
+
count: this.items.length
|
|
16
|
+
},
|
|
17
|
+
children: this.items.map(isrc => isrc.toXml())
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2#ISRC_submission
|
|
2
|
+
|
|
3
|
+
import * as jsontoxml from 'jsontoxml';
|
|
4
|
+
import { XmlRecording } from './xml-recording';
|
|
5
|
+
|
|
6
|
+
const ns_metadata = 'http://musicbrainz.org/ns/mmd-2.0#';
|
|
7
|
+
|
|
8
|
+
export class XmlMetadata {
|
|
9
|
+
|
|
10
|
+
public recordings: XmlRecording[] = [];
|
|
11
|
+
|
|
12
|
+
public pushRecording(id: string): XmlRecording {
|
|
13
|
+
const rec = new XmlRecording(id);
|
|
14
|
+
this.recordings.push(rec);
|
|
15
|
+
return rec;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public toXml(): string {
|
|
19
|
+
|
|
20
|
+
return jsontoxml([{
|
|
21
|
+
name: 'metadata',
|
|
22
|
+
attrs: {
|
|
23
|
+
xmlns: ns_metadata
|
|
24
|
+
},
|
|
25
|
+
children: [{
|
|
26
|
+
'recording-list': this.recordings.map(rec => rec.toXml())
|
|
27
|
+
}]
|
|
28
|
+
}], {prettyPrint: false, escape: true, xmlHeader: true});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { XmlIsrcList } from './xml-isrc-list';
|
|
2
|
+
|
|
3
|
+
export class XmlRecording {
|
|
4
|
+
|
|
5
|
+
public isrcList: XmlIsrcList = new XmlIsrcList();
|
|
6
|
+
|
|
7
|
+
public constructor(public id: string) {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public toXml() {
|
|
11
|
+
return {
|
|
12
|
+
name: 'recording',
|
|
13
|
+
attrs: {
|
|
14
|
+
id: this.id
|
|
15
|
+
},
|
|
16
|
+
children: [this.isrcList.toXml()]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,104 +1,103 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "musicbrainz-api",
|
|
3
|
-
"version": "0.10.
|
|
4
|
-
"description": "MusicBrainz API client for reading and submitting metadata",
|
|
5
|
-
"main": "lib/musicbrainz-api",
|
|
6
|
-
"types": "lib/musicbrainz-api",
|
|
7
|
-
"author": {
|
|
8
|
-
"name": "Borewit",
|
|
9
|
-
"url": "https://github.com/Borewit"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [
|
|
12
|
-
"MusicBrainz",
|
|
13
|
-
"metadata",
|
|
14
|
-
"meta",
|
|
15
|
-
"tag",
|
|
16
|
-
"tags",
|
|
17
|
-
"Picard",
|
|
18
|
-
"json",
|
|
19
|
-
"xml",
|
|
20
|
-
"web",
|
|
21
|
-
"service",
|
|
22
|
-
"submit",
|
|
23
|
-
"metabrainz"
|
|
24
|
-
],
|
|
25
|
-
"license": "MIT",
|
|
26
|
-
"private": false,
|
|
27
|
-
"engines": {
|
|
28
|
-
"node": "*"
|
|
29
|
-
},
|
|
30
|
-
"repository": {
|
|
31
|
-
"type": "git",
|
|
32
|
-
"url": "https://github.com/Borewit/musicbrainz-api.git"
|
|
33
|
-
},
|
|
34
|
-
"bugs": {
|
|
35
|
-
"url": "https://github.com/Borewit/musicbrainz-api/issues"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"@types/caseless": "^0.12.1",
|
|
39
|
-
"@types/request-promise-native": "^1.0.17",
|
|
40
|
-
"@types/uuid": "^
|
|
41
|
-
"caseless": "^0.12.0",
|
|
42
|
-
"debug": "^4.1.1",
|
|
43
|
-
"got": "^11.8.5",
|
|
44
|
-
"http-status-codes": "^2.1.4",
|
|
45
|
-
"json-stringify-safe": "^5.0.1",
|
|
46
|
-
"jsontoxml": "^1.0.1",
|
|
47
|
-
"source-map-support": "^0.5.16",
|
|
48
|
-
"tough-cookie": "^4.0.0",
|
|
49
|
-
"uuid": "^9.0.0"
|
|
50
|
-
},
|
|
51
|
-
"devDependencies": {
|
|
52
|
-
"@types/chai": "^4.3.0",
|
|
53
|
-
"@types/mocha": "^9.0.0",
|
|
54
|
-
"@types/node": "^18.6.1",
|
|
55
|
-
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
|
56
|
-
"@typescript-eslint/parser": "^5.13.0",
|
|
57
|
-
"chai": "^4.2.0",
|
|
58
|
-
"del-cli": "^5.0.0",
|
|
59
|
-
"eslint": "^8.10.0",
|
|
60
|
-
"eslint-config-prettier": "^8.4.0",
|
|
61
|
-
"eslint-import-resolver-typescript": "^3.3.0",
|
|
62
|
-
"eslint-plugin-import": "^2.25.4",
|
|
63
|
-
"eslint-plugin-jsdoc": "^
|
|
64
|
-
"eslint-plugin-node": "^11.1.0",
|
|
65
|
-
"eslint-plugin-unicorn": "^
|
|
66
|
-
"mocha": "^9.0.1",
|
|
67
|
-
"nyc": "^15.0.0",
|
|
68
|
-
"remark-cli": "^11.0.0",
|
|
69
|
-
"remark-preset-lint-recommended": "^6.1.2",
|
|
70
|
-
"ts-node": "^10.0.0",
|
|
71
|
-
"tslint": "^6.1.1",
|
|
72
|
-
"typescript": "^
|
|
73
|
-
},
|
|
74
|
-
"scripts": {
|
|
75
|
-
"clean": "del-cli
|
|
76
|
-
"compile-
|
|
77
|
-
"compile-test": "tsc -p test",
|
|
78
|
-
"compile": "npm run compile-
|
|
79
|
-
"eslint": "eslint
|
|
80
|
-
"lint-md": "remark -u preset-lint-recommended .",
|
|
81
|
-
"lint": "npm run lint-md && npm run eslint",
|
|
82
|
-
"test": "mocha --require ts-node/register --require source-map-support/register --full-trace test/test-*.ts",
|
|
83
|
-
"build": "npm run clean && npm run compile",
|
|
84
|
-
"start": "npm-run-all compile lint cover-test",
|
|
85
|
-
"test-coverage": "nyc npm run test",
|
|
86
|
-
"send-codacy": "nyc report --reporter=text-lcov | codacy-coverage"
|
|
87
|
-
},
|
|
88
|
-
"nyc": {
|
|
89
|
-
"exclude": [
|
|
90
|
-
"test/**/*.ts"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
"
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "musicbrainz-api",
|
|
3
|
+
"version": "0.10.3",
|
|
4
|
+
"description": "MusicBrainz API client for reading and submitting metadata",
|
|
5
|
+
"main": "lib/musicbrainz-api",
|
|
6
|
+
"types": "lib/musicbrainz-api",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Borewit",
|
|
9
|
+
"url": "https://github.com/Borewit"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"MusicBrainz",
|
|
13
|
+
"metadata",
|
|
14
|
+
"meta",
|
|
15
|
+
"tag",
|
|
16
|
+
"tags",
|
|
17
|
+
"Picard",
|
|
18
|
+
"json",
|
|
19
|
+
"xml",
|
|
20
|
+
"web",
|
|
21
|
+
"service",
|
|
22
|
+
"submit",
|
|
23
|
+
"metabrainz"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"private": false,
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": "*"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/Borewit/musicbrainz-api.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/Borewit/musicbrainz-api/issues"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@types/caseless": "^0.12.1",
|
|
39
|
+
"@types/request-promise-native": "^1.0.17",
|
|
40
|
+
"@types/uuid": "^9.0.0",
|
|
41
|
+
"caseless": "^0.12.0",
|
|
42
|
+
"debug": "^4.1.1",
|
|
43
|
+
"got": "^11.8.5",
|
|
44
|
+
"http-status-codes": "^2.1.4",
|
|
45
|
+
"json-stringify-safe": "^5.0.1",
|
|
46
|
+
"jsontoxml": "^1.0.1",
|
|
47
|
+
"source-map-support": "^0.5.16",
|
|
48
|
+
"tough-cookie": "^4.0.0",
|
|
49
|
+
"uuid": "^9.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/chai": "^4.3.0",
|
|
53
|
+
"@types/mocha": "^9.0.0",
|
|
54
|
+
"@types/node": "^18.6.1",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
|
56
|
+
"@typescript-eslint/parser": "^5.13.0",
|
|
57
|
+
"chai": "^4.2.0",
|
|
58
|
+
"del-cli": "^5.0.0",
|
|
59
|
+
"eslint": "^8.10.0",
|
|
60
|
+
"eslint-config-prettier": "^8.4.0",
|
|
61
|
+
"eslint-import-resolver-typescript": "^3.3.0",
|
|
62
|
+
"eslint-plugin-import": "^2.25.4",
|
|
63
|
+
"eslint-plugin-jsdoc": "^40.1.0",
|
|
64
|
+
"eslint-plugin-node": "^11.1.0",
|
|
65
|
+
"eslint-plugin-unicorn": "^46.0.0",
|
|
66
|
+
"mocha": "^9.0.1",
|
|
67
|
+
"nyc": "^15.0.0",
|
|
68
|
+
"remark-cli": "^11.0.0",
|
|
69
|
+
"remark-preset-lint-recommended": "^6.1.2",
|
|
70
|
+
"ts-node": "^10.0.0",
|
|
71
|
+
"tslint": "^6.1.1",
|
|
72
|
+
"typescript": "^5.0.2"
|
|
73
|
+
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"clean": "del-cli lib/**/*.js lib/**/*.js.map lib/**/*.d.ts test/**/*.js test/**/*.js.map",
|
|
76
|
+
"compile-lib": "tsc -p lib",
|
|
77
|
+
"compile-test": "tsc -p test",
|
|
78
|
+
"compile": "npm run compile-lib && npm run compile-test",
|
|
79
|
+
"eslint": "eslint lib/**/*.ts --ignore-pattern lib/**/*.d.ts test/**/*.ts",
|
|
80
|
+
"lint-md": "remark -u preset-lint-recommended .",
|
|
81
|
+
"lint": "npm run lint-md && npm run eslint",
|
|
82
|
+
"test": "mocha --require ts-node/register --require source-map-support/register --full-trace test/test-*.ts",
|
|
83
|
+
"build": "npm run clean && npm run compile",
|
|
84
|
+
"start": "npm-run-all compile lint cover-test",
|
|
85
|
+
"test-coverage": "nyc npm run test",
|
|
86
|
+
"send-codacy": "nyc report --reporter=text-lcov | codacy-coverage"
|
|
87
|
+
},
|
|
88
|
+
"nyc": {
|
|
89
|
+
"exclude": [
|
|
90
|
+
"test/**/*.ts"
|
|
91
|
+
],
|
|
92
|
+
"extension": [
|
|
93
|
+
".ts"
|
|
94
|
+
],
|
|
95
|
+
"sourceMap": true,
|
|
96
|
+
"instrument": true,
|
|
97
|
+
"reporter": [
|
|
98
|
+
"lcov",
|
|
99
|
+
"text"
|
|
100
|
+
],
|
|
101
|
+
"report-dir": "coverage"
|
|
102
|
+
}
|
|
103
|
+
}
|
package/.idea/$CACHE_FILE$
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="masterDetails">
|
|
4
|
-
<states>
|
|
5
|
-
<state key="ProjectJDKs.UI">
|
|
6
|
-
<settings>
|
|
7
|
-
<last-edited>1.8</last-edited>
|
|
8
|
-
<splitter-proportions>
|
|
9
|
-
<option name="proportions">
|
|
10
|
-
<list>
|
|
11
|
-
<option value="0.2" />
|
|
12
|
-
</list>
|
|
13
|
-
</option>
|
|
14
|
-
</splitter-proportions>
|
|
15
|
-
</settings>
|
|
16
|
-
</state>
|
|
17
|
-
</states>
|
|
18
|
-
</component>
|
|
19
|
-
</project>
|