add musicbrainz

master
Steve Ayerhart 2020-12-17 22:12:23 -05:00
parent ea4f32d57f
commit 5bafa0257b
No known key found for this signature in database
GPG Key ID: 5C815FDF3A00B8BA
8 changed files with 404 additions and 0 deletions

1
musicbrainz/authors.txt Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1,131 @@
USING: strings calendar sequences kernel math ;
IN: musicbrainz.entities
SINGLETONS:
person group orchestra choir character other
album single ep broadcast
compilation soundtrack spokenword interview audiobook audio-drama live remix dj-mix mixtape/street
male female
country subdivision county municipality city district island
search-hint artist-name
official promotional bootleg pseudo-release
normal high low
;
UNION: primary-release-group-type
album single ep broadcast other ;
UNION: secondary-release-group-type
compilation soundtrack spokenword interview audiobook audio-drama live remix dj-mix mixtape/street ;
UNION: artist-type
person group orchestra choir character other ;
UNION: area-type
country subdivision county municipality city district island ;
UNION: alias-type search-hint artist-name ;
UNION: artist-gender
male female ;
UNION: release-status
official promotional bootleg pseudo-release ;
UNION: release-quality
normal high low ;
TUPLE: entity
{ mbid string } ;
TUPLE: alias
{ name string }
{ sort-name string }
{ type maybe{ alias-type } }
{ locale maybe{ string } } ;
TUPLE: life-span
{ begin timestamp }
{ end maybe{ timestamp } }
{ ended? maybe{ boolean } } ;
TUPLE: area < entity
{ name string }
{ type maybe{ area-type } }
{ sort-name maybe{ string } }
{ iso-codes maybe{ sequence } }
{ begin-date maybe{ timestamp } } ;
TUPLE: artist < entity
{ name string }
{ sort-name string }
{ disambiguation maybe{ string } }
{ life-span maybe{ life-span } }
{ country maybe{ string } }
{ isnis maybe{ sequence } }
{ type maybe{ artist-type } }
{ gender maybe{ artist-gender } }
{ area maybe{ area } }
{ aliases maybe{ sequence } }
{ begin-area maybe{ area } } ;
TUPLE: text-representation
{ language string }
{ script string } ;
TUPLE: cover-art-archive
{ artwork? boolean }
{ count number }
{ front? boolean }
{ back? boolean } ;
TUPLE: release-event
{ date timestamp }
{ area maybe{ area } } ;
TUPLE: release < entity
{ title string }
{ status maybe{ release-status } }
{ quality maybe{ release-quality } }
{ disambiguation maybe{ string } }
{ date maybe{ timestamp } }
{ country maybe{ string } }
{ text-representation maybe{ text-representation } }
{ barcode maybe{ string } }
{ asin maybe{ string } }
{ release-events maybe{ sequence } }
{ packaging maybe{ string } }
{ mediums maybe{ sequence } }
{ artist maybe{ artist } }
{ label-info maybe{ sequence } }
{ cover-art-archive maybe{ cover-art-archive } } ;
TUPLE: collection < entity
{ name string }
{ editor string }
{ releases maybe{ sequence } } ;
TUPLE: recording < entity
{ title string }
{ length integer }
{ artist artist } ;
TUPLE: track < entity
{ position integer }
{ number integer }
{ length integer }
{ recording recording } ;
TUPLE: medium
{ position integer }
{ number integer }
{ format string }
{ dics sequence }
{ tracks sequence } ;
TUPLE: label < entity
{ type string }
{ name string }
{ sort-name maybe{ string } }
{ disambiguation maybe{ string } }
{ aliases maybe{ sequence } } ;

View File

@ -0,0 +1,10 @@
! Copyright (C) 2020 .
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax ;
IN: musicbrainz
ARTICLE: "musicbrainz" "musicbrainz"
{ $vocab-link "musicbrainz" }
;
ABOUT: "musicbrainz"

View File

@ -0,0 +1,4 @@
! Copyright (C) 2020 .
! See http://factorcode.org/license.txt for BSD license.
USING: tools.test musicbrainz ;
IN: musicbrainz.tests

View File

@ -0,0 +1,61 @@
! Copyright (C) 2020 .
! See http://factorcode.org/license.txt for BSD license.
USING: kernel io.sockets.secure http http.client urls strings alien.syntax accessors arrays sequences xml.syntax xml.traversal assocs slots calendar words calendar.parser combinators io.streams.string furnace.utilities splitting qw hashtables ;
USING: io prettyprint ;
USING: musicbrainz.entities musicbrainz.parser ;
IN: musicbrainz
CONSTANT: mb-base-url URL" https://musicbrainz.org/ws/2/"
CONSTANT: user-agent-header { "factor-musicbrainz/0.1.0 (steve@ayerh.art)" "user-agent" }
CONSTANT: accept-header { "application/xml" "accept" }
CONSTANT: collection-links qw{ releases }
: mb-entity>string ( entity -- str )
word>string ":" split last ;
: <mb-entity-url> ( mbid entity inc -- url )
[
word>string ":" split last swap 2array "/" join
mb-base-url clone swap >url derive-url
] dip "+" join "inc" set-query-param ;
: <mb-release-url> ( mbid -- url )
release qw{ artist-credits recordings labels aliases } <mb-entity-url> ;
: <mb-artist-url> ( mbid -- url )
artist qw{ aliases } <mb-entity-url> ;
: <mb-collection-url> ( mbid -- url )
"/releases" append collection qw{ artist-credits releases } <mb-entity-url> ;
: <mb-get-request> ( url -- request )
<get-request>
user-agent-header first2 set-header
accept-header first2 set-header
http-request nip parse-mb-response ;
: add-mb-headers ( url -- url )
user-agent-header first2 set-header
accept-header first2 set-header ;
: <mb-release-lookup> ( mbid -- release )
<mb-release-url> <mb-get-request> ;
: <mb-artist-lookup> ( mbid -- artist )
<mb-artist-url> <mb-get-request> ;
: <mb-collection-lookup> ( mbid -- collection )
<mb-collection-url> <mb-get-request> ;
: <mb-collection-release-url> ( mbid -- url )
[ mb-base-url clone "release" >url derive-url ] dip
"collection" set-query-param
"100" "limit" set-query-param ;
: <mb-collection-release-request> ( mbid -- releases )
<mb-collection-release-url> <mb-get-request> ;
: <mb-collections-lookup> ( user -- collections )
[ mb-base-url clone "collection" >url derive-url ] dip
"editor" set-query-param
<get-request> add-mb-headers http-request nip parse-mb-response ;

View File

@ -0,0 +1,195 @@
USING: kernel xml.syntax xml.traversal accessors words sequences calendar calendar.parser combinators io.streams.string assocs xml unicode arrays splitting html.components math.parser ;
USING: musicbrainz.entities ;
USING: prettyprint ;
IN: musicbrainz.parser
XML-NS: mb http://musicbrainz.org/ns/mmd-2.0#
ERROR: invalid-timestamp ;
: string>word ( str -- word )
"musicbrainz.entities" lookup-word ;
: string>timestamp ( str -- timestamp )
[ length ] keep
[
{
{ 4 [ read-0000 1 1 <date-gmt> ] }
{ 7 [ read-0000 "-" expect read-00 1 <date-gmt> ] }
{ 10 [ read-ymd <date-gmt> ] }
[ drop invalid-timestamp ]
} case
] with-string-reader ;
TAGS: mb-entity ( tag -- entity )
TAGS: entity-property ( entity tag -- entity )
TAG: name entity-property
children>string >>name ;
TAG: sort-name entity-property
children>string >>sort-name ;
TAG: disambiguation entity-property
children>string >>disambiguation ;
TAG: country entity-property
children>string >>country ;
TAG: packaging entity-property
children>string >>packaging ;
TAG: gender entity-property
children>string >lower string>word >>gender ;
TAG: iso-3166-2-code-list entity-property
children-tags [ children>string ] map >array >>iso-codes ;
TAG: iso-3166-1-code-list entity-property
children-tags [ children>string ] map >array >>iso-codes ;
TAG: isni-list entity-property
children-tags [ children>string ] map >array >>isnis ;
TAG: begin entity-property
children>string string>timestamp >>begin ;
TAG: end entity-property
children>string string>timestamp >>end ;
TAG: title entity-property
children>string >>title ;
TAG: language entity-property
children>string >>language ;
TAG: script entity-property
children>string >>script ;
TAG: status entity-property
children>string string>word >>status ;
TAG: quality entity-property
children>string string>word >>quality ;
TAG: text-representation entity-property
children-tags text-representation new [ entity-property ] reduce
>>text-representation ;
TAG: barcode entity-property
children>string >>barcode ;
TAG: artwork entity-property
children>string string>boolean >>artwork? ;
TAG: count entity-property
children>string string>number >>count ;
TAG: front entity-property
children>string string>boolean >>front? ;
TAG: back entity-property
children>string string>boolean >>back? ;
TAG: cover-art-archive entity-property
children-tags cover-art-archive new [ entity-property ] reduce
>>cover-art-archive ;
TAG: release-event-list entity-property
children-tags [ mb-entity ] map >array >>release-events ;
TAG: date entity-property
children>string string>timestamp >>date ;
TAG: life-span entity-property
children-tags life-span new [ entity-property ] reduce
>>life-span ;
TAG: ended entity-property
children>string string>boolean >>ended? ;
TAG: position entity-property
children>string string>number >>position ;
TAG: length entity-property
children>string string>number >>length ;
TAG: number entity-property
children>string string>number >>number ;
TAG: format entity-property
children>string >>format ;
TAG: editor entity-property
children>string >>editor ;
TAG: track mb-entity
[ children-tags track new [ entity-property ] reduce ]
[ attrs>> "id" of ] bi
>>mbid ;
! TODO: turn this into an mb-entity
TAG: alias-list entity-property
children-tags
[
[ children>string ]
[
attrs>>
[ "sort-name" of ]
[ "type" of >lower " " split "-" join string>word ]
[ "locale" of ] tri
] bi
alias boa
] map >array >>aliases ;
TAG: area entity-property
[ children-tags area new [ entity-property ] reduce ]
[ attrs>> [ "id" of ] [ "type" of string>word ] bi ] bi
[ >>mbid ] dip >>type >>area ;
TAG: begin-area entity-property
[ children-tags area new [ entity-property ] reduce ]
[ attrs>> [ "id" of ] [ "type" of string>word ] bi ] bi
[ >>mbid ] dip >>type >>begin-area ;
TAG: release-list mb-entity
children-tags [ mb-entity ] map >array ;
TAG: release-list entity-property
children-tags [ mb-entity ] map >array >>releases ;
TAG: asin entity-property
children>string >>asin ;
TAG: artist mb-entity
[ children-tags artist new [ entity-property ] reduce ]
[ attrs>> [ "id" of ] [ "type" of string>word ] bi ] bi
[ >>mbid ] dip >>type ;
TAG: release-event mb-entity
children-tags release-event new [ entity-property ] reduce ;
TAG: release mb-entity
[ children-tags release new [ entity-property ] reduce ]
[ attrs>> "id" of ] bi >>mbid ;
TAG: collection mb-entity
[ children-tags collection new [ entity-property ] reduce ]
[ attrs>> "id" of ] bi >>mbid ;
TAG: collection-list mb-entity
children-tags [ mb-entity ] map >array ;
TAG: medium-list entity-property
children-tags [ mb-entity ] map >array >>mediums ;
TAG: track-list entity-property
children-tags [ mb-entity ] map >array >>tracks ;
TAG: medium mb-entity
children-tags medium new [ entity-property ] reduce ;
TAG: artist-credit entity-property
"artist" deep-tag-named mb-entity >>artist ;
TAG: label-info-list entity-property
children-tags [ mb-entity ] map >array >>label-info ;
TAG: label-info mb-entity
first-child-tag
[ children-tags label new [ entity-property ] reduce ]
[ attrs>> [ "id" of ] [ "type" of ] bi ] bi
[ >>mbid ] dip >>type ;
TAG: recording entity-property
[ children-tags recording new [ entity-property ] reduce ]
[ attrs>> "id" of ] bi >>mbid >>recording ;
: parse-mb-response ( str -- entity )
string>xml first-child-tag mb-entity ;

1
musicbrainz/summary.txt Normal file
View File

@ -0,0 +1 @@
musicbrainz api

1
musicbrainz/tags.txt Normal file
View File

@ -0,0 +1 @@
musicbrainz music metadata