mirror of
https://github.com/BradNut/graphbrainz
synced 2025-09-08 17:40:32 +00:00
Media tracks (#87)
* Add support for getting tracks on release objects * Fix track number type, update docs * Stop snapshotting tracks query because it blows up AVA * Fix lint issue
This commit is contained in:
parent
a6693ed5a4
commit
cb2d2a1a3f
15 changed files with 1239 additions and 1298 deletions
|
|
@ -21,6 +21,7 @@ npm install graphbrainz --save
|
|||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
|
||||
- [Usage](#usage)
|
||||
- [As a standalone server](#as-a-standalone-server)
|
||||
- [As middleware](#as-middleware)
|
||||
|
|
|
|||
|
|
@ -1261,6 +1261,9 @@ type Medium {
|
|||
|
||||
"""A list of physical discs and their disc IDs for this medium."""
|
||||
discs: [Disc]
|
||||
|
||||
"""The list of tracks on the given media."""
|
||||
tracks: [Track]
|
||||
}
|
||||
|
||||
"""An object with an ID"""
|
||||
|
|
@ -2542,6 +2545,37 @@ type TagEdge {
|
|||
"""A time of day, in 24-hour hh:mm notation."""
|
||||
scalar Time
|
||||
|
||||
"""
|
||||
A track is the way a recording is represented on a particular
|
||||
release (or, more exactly, on a particular medium). Every track has a title
|
||||
(see the guidelines for titles) and is credited to one or more artists.
|
||||
"""
|
||||
type Track implements Entity {
|
||||
"""The MBID of the entity."""
|
||||
mbid: MBID!
|
||||
|
||||
"""The official title of the entity."""
|
||||
title: String
|
||||
|
||||
"""
|
||||
The track’s position on the overall release (including all
|
||||
tracks from all discs).
|
||||
"""
|
||||
position: Int
|
||||
|
||||
"""
|
||||
The track number, which may include information about the
|
||||
disc or side it appears on, e.g. “A1” or “B3”.
|
||||
"""
|
||||
number: String
|
||||
|
||||
"""The length of the track."""
|
||||
length: Duration
|
||||
|
||||
"""The recording that appears on the track."""
|
||||
recording: Recording
|
||||
}
|
||||
|
||||
"""
|
||||
A [URL](https://musicbrainz.org/doc/URL) pointing to a resource
|
||||
external to MusicBrainz, i.e. an official homepage, a site where music can be
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ or the schemas provided by the [built-in extensions](extensions).
|
|||
* [Tag](#tag)
|
||||
* [TagConnection](#tagconnection)
|
||||
* [TagEdge](#tagedge)
|
||||
* [Track](#track)
|
||||
* [URL](#url)
|
||||
* [Work](#work)
|
||||
* [WorkConnection](#workconnection)
|
||||
|
|
@ -3544,6 +3545,15 @@ The number of audio tracks on this medium.
|
|||
|
||||
A list of physical discs and their disc IDs for this medium.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>tracks</strong></td>
|
||||
<td valign="top">[<a href="#track">Track</a>]</td>
|
||||
<td>
|
||||
|
||||
The list of tracks on the given media.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
@ -6719,6 +6729,81 @@ these results were found through a search.
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
### Track
|
||||
|
||||
A track is the way a recording is represented on a particular
|
||||
release (or, more exactly, on a particular medium). Every track has a title
|
||||
(see the guidelines for titles) and is credited to one or more artists.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>mbid</strong></td>
|
||||
<td valign="top"><a href="#mbid">MBID</a>!</td>
|
||||
<td>
|
||||
|
||||
The MBID of the entity.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>title</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The official title of the entity.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>position</strong></td>
|
||||
<td valign="top"><a href="#int">Int</a></td>
|
||||
<td>
|
||||
|
||||
The track’s position on the overall release (including all
|
||||
tracks from all discs).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>number</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The track number, which may include information about the
|
||||
disc or side it appears on, e.g. “A1” or “B3”.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>length</strong></td>
|
||||
<td valign="top"><a href="#duration">Duration</a></td>
|
||||
<td>
|
||||
|
||||
The length of the track.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>recording</strong></td>
|
||||
<td valign="top"><a href="#recording">Recording</a></td>
|
||||
<td>
|
||||
|
||||
The recording that appears on the track.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### URL
|
||||
|
||||
A [URL](https://musicbrainz.org/doc/URL) pointing to a resource
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@
|
|||
"format": "npm run lint:fix",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"postinstall": "postinstall-build lib --script build:lib",
|
||||
"prepublish": "npm run clean:lib && npm run build:lib",
|
||||
"prepare": "npm run clean:lib && npm run build:lib",
|
||||
"preversion": "npm run update-schema && npm run build:docs && git add schema.json docs",
|
||||
"print-schema": "babel-node scripts/print-schema.js",
|
||||
"print-schema:json": "npm run print-schema -- --json",
|
||||
|
|
@ -84,7 +83,6 @@
|
|||
"graphql-tools": "^3.1.1",
|
||||
"lru-cache": "^4.1.3",
|
||||
"pascalcase": "^0.1.1",
|
||||
"postinstall-build": "^5.0.1",
|
||||
"qs": "^6.5.2",
|
||||
"request": "^2.87.0",
|
||||
"retry": "^0.12.0"
|
||||
|
|
|
|||
114
schema.json
114
schema.json
|
|
@ -1068,6 +1068,11 @@
|
|||
"name": "Release",
|
||||
"ofType": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Track",
|
||||
"ofType": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Label",
|
||||
|
|
@ -3432,6 +3437,22 @@
|
|||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "tracks",
|
||||
"description": "The list of tracks on the given media.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Track",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
|
|
@ -3579,6 +3600,99 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Track",
|
||||
"description": "A track is the way a recording is represented on a particular\n release (or, more exactly, on a particular medium). Every track has a title\n (see the guidelines for titles) and is credited to one or more artists.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mbid",
|
||||
"description": "The MBID of the entity.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "MBID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"description": "The official title of the entity.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "position",
|
||||
"description": "The track’s position on the overall release (including all\ntracks from all discs).",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "number",
|
||||
"description": "The track number, which may include information about the\ndisc or side it appears on, e.g. “A1” or “B3”.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "length",
|
||||
"description": "The length of the track.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Duration",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "recording",
|
||||
"description": "The recording that appears on the track.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Recording",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "Entity",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "LabelConnection",
|
||||
|
|
|
|||
|
|
@ -42,14 +42,17 @@ export function includeSubqueries(params, info, fragments = info.fragments) {
|
|||
artistCredit: ['artist-credits'],
|
||||
artistCredits: ['artist-credits'],
|
||||
isrcs: ['isrcs'],
|
||||
media: ['media', 'discids'],
|
||||
media: ['media'],
|
||||
'media.discs': ['discids'],
|
||||
'media.tracks': ['recordings'],
|
||||
rating: ['ratings'],
|
||||
tags: ['tags']
|
||||
}
|
||||
let fields = getFields(info, fragments)
|
||||
let fields = getFields(info, fragments, 1)
|
||||
const include = []
|
||||
for (const key in subqueryIncludes) {
|
||||
if (fields[key]) {
|
||||
const field = fields[key]
|
||||
if (field) {
|
||||
const value = subqueryIncludes[key]
|
||||
include.push(...value)
|
||||
}
|
||||
|
|
@ -58,11 +61,8 @@ export function includeSubqueries(params, info, fragments = info.fragments) {
|
|||
...params,
|
||||
inc: extendIncludes(params.inc, include)
|
||||
}
|
||||
if (fields.edges) {
|
||||
fields = getFields(fields.edges, fragments)
|
||||
if (fields.node) {
|
||||
params = includeSubqueries(params, fields.node, fragments)
|
||||
}
|
||||
if (fields['edges.node']) {
|
||||
params = includeSubqueries(params, fields['edges.node'], fragments)
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ import {
|
|||
GraphQLInt
|
||||
} from 'graphql/type'
|
||||
import Disc from './disc'
|
||||
import Track from './track'
|
||||
import { resolveHyphenated, fieldWithID } from './helpers'
|
||||
import { createSubqueryResolver } from '../resolvers'
|
||||
|
||||
export default new GraphQLObjectType({
|
||||
name: 'Medium',
|
||||
|
|
@ -37,6 +39,14 @@ multi-disc release).`
|
|||
type: new GraphQLList(Disc),
|
||||
description:
|
||||
'A list of physical discs and their disc IDs for this medium.'
|
||||
},
|
||||
tracks: {
|
||||
type: new GraphQLList(Track),
|
||||
description: 'The list of tracks on the given media.',
|
||||
resolve: createSubqueryResolver({
|
||||
inc: 'recordings',
|
||||
key: 'tracks'
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
42
src/types/track.js
Normal file
42
src/types/track.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { GraphQLObjectType, GraphQLInt, GraphQLString } from 'graphql/type'
|
||||
import Entity from './entity'
|
||||
import { Duration } from './scalars'
|
||||
import Recording from './recording'
|
||||
import { mbid, title } from './helpers'
|
||||
|
||||
export default new GraphQLObjectType({
|
||||
name: 'Track',
|
||||
description: `A track is the way a recording is represented on a particular
|
||||
release (or, more exactly, on a particular medium). Every track has a title
|
||||
(see the guidelines for titles) and is credited to one or more artists.`,
|
||||
interfaces: () => [Entity],
|
||||
fields: () => ({
|
||||
mbid,
|
||||
title,
|
||||
position: {
|
||||
type: GraphQLInt,
|
||||
description: `The track’s position on the overall release (including all
|
||||
tracks from all discs).`
|
||||
},
|
||||
number: {
|
||||
type: GraphQLString,
|
||||
description: `The track number, which may include information about the
|
||||
disc or side it appears on, e.g. “A1” or “B3”.`
|
||||
},
|
||||
length: {
|
||||
type: Duration,
|
||||
description: 'The length of the track.'
|
||||
},
|
||||
recording: {
|
||||
type: Recording,
|
||||
description: 'The recording that appears on the track.',
|
||||
resolve: source => {
|
||||
const { recording } = source
|
||||
if (recording) {
|
||||
recording._type = 'recording'
|
||||
}
|
||||
return recording
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
19
src/util.js
19
src/util.js
|
|
@ -2,7 +2,12 @@ import util from 'util'
|
|||
|
||||
export const ONE_DAY = 24 * 60 * 60 * 1000
|
||||
|
||||
export function getFields(info, fragments = info.fragments) {
|
||||
export function getFields(
|
||||
info,
|
||||
fragments = info.fragments,
|
||||
depth = 0,
|
||||
prefix = ''
|
||||
) {
|
||||
if (info.kind !== 'Field') {
|
||||
info = info.fieldNodes[0]
|
||||
}
|
||||
|
|
@ -18,7 +23,17 @@ export function getFields(info, fragments = info.fragments) {
|
|||
} else if (selection.kind === 'InlineFragment') {
|
||||
selection.selectionSet.selections.reduce(reducer, fields)
|
||||
} else {
|
||||
fields[selection.name.value] = selection
|
||||
const prefixedName = prefix + selection.name.value
|
||||
fields[prefixedName] = selection
|
||||
if (depth > 0 && selection.selectionSet) {
|
||||
const subFields = getFields(
|
||||
selection,
|
||||
fragments,
|
||||
depth - 1,
|
||||
`${prefixedName}.`
|
||||
)
|
||||
Object.assign(fields, subFields)
|
||||
}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1408,3 +1408,40 @@ test(
|
|||
t.true(artists[0].tags.edges.some(edge => edge.node.count > 0))
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'releases can include tracks',
|
||||
testData,
|
||||
`
|
||||
{
|
||||
lookup {
|
||||
release(mbid: "fba5f8fe-c6c8-4511-8562-c9febf482674") {
|
||||
media {
|
||||
trackCount
|
||||
position
|
||||
formatID
|
||||
format
|
||||
tracks {
|
||||
mbid
|
||||
title
|
||||
position
|
||||
number
|
||||
length
|
||||
recording {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
(t, data) => {
|
||||
t.true(data.lookup.release.media.every(media => media.tracks.length > 0))
|
||||
t.true(
|
||||
data.lookup.release.media.every(media =>
|
||||
media.tracks.every(track => track.recording)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
1
test/fixtures/7cf49c05d1e153f9622597f1e0e15281
vendored
Normal file
1
test/fixtures/7cf49c05d1e153f9622597f1e0e15281
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"packaging":"Cassette Case","title":"OK Computer","status":"Official","text-representation":{"script":"Latn","language":"eng"},"country":"GB","date":"1997-06-16","barcode":"724385522949","asin":"B000002UJR","media":[{"format-id":"f5e6e254-8f39-331c-936b-9c69d686dc47","format":"Cassette","track-offset":0,"title":"","position":1,"track-count":12,"tracks":[{"recording":{"title":"Airbag","video":false,"disambiguation":"","id":"4a7fea2e-545b-4c63-bc9a-9943cc3a29d7","length":284400},"position":1,"length":284400,"id":"a31f27a1-dfd8-38cc-958a-07f3af52fc25","number":"A1","title":"Airbag"},{"number":"A2","title":"Paranoid Android","recording":{"id":"9f9cf187-d6f9-437f-9d98-d59cdbd52757","length":383493,"title":"Paranoid Android","video":false,"disambiguation":""},"length":383493,"position":2,"id":"26ca3f84-46d8-3627-b894-b1eb8599a110"},{"id":"66ee1e73-a67c-3988-9ab5-e74721be5258","length":267706,"recording":{"length":267706,"id":"bd82738d-163c-4b1a-bfaf-7acffe30e68a","video":false,"title":"Subterranean Homesick Alien","disambiguation":""},"position":3,"title":"Subterranean Homesick Alien","number":"A3"},{"id":"db7b6f2d-18b8-39b2-826d-eb9e82f35f3a","position":4,"recording":{"disambiguation":"","video":false,"title":"Exit Music (for a Film)","length":264800,"id":"23c3c36b-9449-4484-9040-6ef2125999aa"},"length":264800,"title":"Exit Music (for a Film)","number":"A4"},{"title":"Let Down","number":"A5","id":"5fe3d1b0-2f09-327e-b7e7-9fcff3158a8a","recording":{"length":299266,"id":"47b02a82-c3bf-4647-b894-dd1c8f608e7f","disambiguation":"","video":false,"title":"Let Down"},"length":299266,"position":5},{"number":"A6","title":"Karma Police","length":261626,"recording":{"length":262000,"id":"9e2ad5bc-c6f9-40d2-a36f-3122ee2072a3","disambiguation":"","title":"Karma Police","video":false},"position":6,"id":"944a6d7d-a244-3295-ad6c-1440a52998e8"},{"title":"Fitter Happier","number":"B1","id":"7feb7034-4809-39c0-8576-2ea7a83d118e","position":7,"recording":{"video":false,"title":"Fitter Happier","disambiguation":"","id":"5838f978-0822-4e28-874f-e1511324ec3a","length":117333},"length":117333},{"recording":{"video":false,"title":"Electioneering","disambiguation":"","id":"ba0a796c-bd1f-4d4b-85a8-918f217a204a","length":230640},"position":8,"length":230640,"id":"0481f01e-b351-3c42-b851-748fa741ca74","number":"B2","title":"Electioneering"},{"id":"52ac1a5e-a231-37b4-a82d-7dbc0c74bd72","length":285200,"recording":{"disambiguation":"","video":false,"title":"Climbing Up the Walls","id":"c7225576-001e-423c-adc1-58f0985dcb27","length":285200},"position":9,"title":"Climbing Up the Walls","number":"B3"},{"title":"No Surprises","number":"B4","id":"94cede1d-3eb0-3978-8235-3747bb616cc0","position":10,"recording":{"length":228533,"id":"980a426e-623e-4ea5-98c7-008d037a0508","video":false,"title":"No Surprises","disambiguation":""},"length":228533},{"number":"B5","title":"Lucky","recording":{"disambiguation":"","title":"Lucky","video":false,"id":"79047824-f821-4b1a-9893-e0cea1c947dd","length":259626},"length":259626,"position":11,"id":"34a59962-7e37-3fd9-8a74-f80528ffa1a0"},{"number":"B6","title":"The Tourist","recording":{"length":324533,"id":"610c0012-6eb4-42a0-b759-3a2532ce0f15","title":"The Tourist","video":false,"disambiguation":""},"length":324533,"position":12,"id":"9f537c38-29dc-3114-9ce3-8c99d37e743f"}]}],"status-id":"4e304316-386d-3409-af2e-78857eec5cfe","disambiguation":"","packaging-id":"c70b737a-0114-39a9-88f7-82843e54f906","cover-art-archive":{"count":1,"artwork":true,"darkened":false,"back":false,"front":true},"release-events":[{"area":{"iso-3166-1-codes":["GB"],"disambiguation":"","sort-name":"United Kingdom","name":"United Kingdom","id":"8a754a16-0027-3a29-b6d7-2b40ea0481ed"},"date":"1997-06-16"}],"quality":"normal","id":"fba5f8fe-c6c8-4511-8562-c9febf482674"}
|
||||
28
test/fixtures/7cf49c05d1e153f9622597f1e0e15281.headers
vendored
Normal file
28
test/fixtures/7cf49c05d1e153f9622597f1e0e15281.headers
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"statusCode": 200,
|
||||
"headers": {
|
||||
"date": "Mon, 17 Sep 2018 04:12:07 GMT",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"transfer-encoding": "chunked",
|
||||
"connection": "keep-alive",
|
||||
"keep-alive": "timeout=15",
|
||||
"vary": "Accept-Encoding",
|
||||
"x-ratelimit-limit": "1200",
|
||||
"x-ratelimit-remaining": "909",
|
||||
"x-ratelimit-reset": "1537157527",
|
||||
"server": "Plack::Handler::Starlet",
|
||||
"etag": "W/\"cb65dbe98571f1f412e000ada8a9c1e9\"",
|
||||
"access-control-allow-origin": "*"
|
||||
},
|
||||
"url": "http://musicbrainz.org:80/ws/2/release/fba5f8fe-c6c8-4511-8562-c9febf482674?inc=media%2Brecordings&fmt=json",
|
||||
"time": 469,
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"User-Agent": "graphbrainz/8.0.4 ( https://github.com/exogen/graphbrainz )",
|
||||
"host": "musicbrainz.org",
|
||||
"accept-encoding": "gzip, deflate",
|
||||
"accept": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
1
test/fixtures/f70e148191e1ebbc95eb12ddc2d85be2
vendored
Normal file
1
test/fixtures/f70e148191e1ebbc95eb12ddc2d85be2
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"disambiguation":"","barcode":"606949047320","media":[{"track-count":12,"format":"CD","position":1,"title":"Left","format-id":"9712d52a-4509-3d4b-a1a2-67c88c643e31"},{"format-id":"9712d52a-4509-3d4b-a1a2-67c88c643e31","title":"Right","track-count":11,"position":2,"format":"CD"}],"country":"US","release-events":[{"area":{"name":"United States","sort-name":"United States","disambiguation":"","id":"489ce91b-6658-3307-9877-795b68554c98","iso-3166-1-codes":["US"]},"date":"1999-09-21"}],"status":"Official","date":"1999-09-21","packaging":"Digipak","asin":"B00001P4TH","status-id":"4e304316-386d-3409-af2e-78857eec5cfe","id":"a4864e94-6d75-4ade-bc93-0dabf3521453","cover-art-archive":{"front":true,"artwork":true,"count":2,"darkened":false,"back":true},"title":"The Fragile","text-representation":{"script":"Latn","language":"eng"},"packaging-id":"8f931351-d2e2-310f-afc6-37b89ddba246","quality":"normal"}
|
||||
28
test/fixtures/f70e148191e1ebbc95eb12ddc2d85be2.headers
vendored
Normal file
28
test/fixtures/f70e148191e1ebbc95eb12ddc2d85be2.headers
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"statusCode": 200,
|
||||
"headers": {
|
||||
"date": "Mon, 17 Sep 2018 04:11:56 GMT",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"transfer-encoding": "chunked",
|
||||
"connection": "keep-alive",
|
||||
"keep-alive": "timeout=15",
|
||||
"vary": "Accept-Encoding",
|
||||
"x-ratelimit-limit": "1200",
|
||||
"x-ratelimit-remaining": "1151",
|
||||
"x-ratelimit-reset": "1537157517",
|
||||
"server": "Plack::Handler::Starlet",
|
||||
"etag": "W/\"dc6ae505140f505a493e772ea6af4426\"",
|
||||
"access-control-allow-origin": "*"
|
||||
},
|
||||
"url": "http://musicbrainz.org:80/ws/2/release/a4864e94-6d75-4ade-bc93-0dabf3521453?inc=media&fmt=json",
|
||||
"time": 408,
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"User-Agent": "graphbrainz/8.0.4 ( https://github.com/exogen/graphbrainz )",
|
||||
"host": "musicbrainz.org",
|
||||
"accept-encoding": "gzip, deflate",
|
||||
"accept": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue