2012-03-28 22:49:43 +00:00
// ==UserScript==
2015-06-10 12:59:12 +00:00
// @name Import Bandcamp releases to MusicBrainz
2015-05-28 08:26:38 +00:00
// @description Add a button on Bandcamp's album pages to open MusicBrainz release editor with pre-filled data for the selected release
2019-12-21 10:19:17 +00:00
// @version 2019.12.21.1
2012-03-28 22:49:43 +00:00
// @namespace http://userscripts.org/users/22504
2014-02-22 09:33:26 +00:00
// @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/bandcamp_importer.user.js
// @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/bandcamp_importer.user.js
2015-06-16 19:33:26 +00:00
// @include /^https?://[^/]+/(?:album|track)/[^/]+$/
2015-06-05 08:39:00 +00:00
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
2015-06-17 22:29:08 +00:00
// @require lib/mbimport.js
2015-06-05 09:13:42 +00:00
// @require lib/logger.js
// @require lib/mblinks.js
2015-06-15 07:52:59 +00:00
// @require lib/mbimportstyle.js
2015-07-10 12:27:31 +00:00
// @icon https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/assets/images/Musicbrainz_import_logo.png
2019-01-05 14:48:14 +00:00
// @grant unsafeWindow
2012-03-28 22:49:43 +00:00
// ==/UserScript==
2015-06-05 08:39:00 +00:00
// prevent JQuery conflicts, see http://wiki.greasespot.net/@grant
this . $ = this . jQuery = jQuery . noConflict ( true ) ;
2015-05-25 16:13:40 +00:00
if ( ! unsafeWindow ) unsafeWindow = window ;
2015-05-16 12:41:23 +00:00
2018-11-20 22:18:49 +00:00
String . prototype . fix _bandcamp _url = function ( ) {
Bandcamp Importer: Use only https URLs
- Bandcamp now redirects all http URLs to https
- They didn't change URLs in DOM data yet, most are still http
- MB changed Bandcamp URLs normalization to use https
- MB didn't change old Bandcamp http URLs in the database yet
Basically this breaks some features of the importer, like detection of existing artists, labels, and releases (small icons)
Since the importer has no way to know if the url is stored as http or https, the result is quite random.
One solution would be to query for both, doubling the number of requests to the web service.
Another, much better, is to convert all old Bandcamp http URLs in MB database to https (all new URLs are normalized to https).
This patch only fix http URLs still appearing in pages, and look up for https URLS on the web service.
So, at the moment, the fix is incomplete.
2018-06-01 21:22:19 +00:00
return this . replace ( 'http://' , 'https://' ) ;
} ;
2015-05-25 16:13:40 +00:00
var BandcampImport = {
2018-11-20 22:18:49 +00:00
// Analyze Bandcamp data and return a release object
retrieveReleaseInfo : function ( ) {
let bandcampAlbumData = unsafeWindow . TralbumData ;
let bandcampEmbedData = unsafeWindow . EmbedData ;
let release = {
discs : [ ] ,
artist _credit : [ ] ,
2019-12-07 15:52:07 +00:00
barcode : bandcampAlbumData . current . upc ,
2018-11-20 22:18:49 +00:00
title : '' ,
year : 0 ,
month : 0 ,
day : 0 ,
parent _album _url : '' ,
labels : [ ] ,
format : 'Digital Media' ,
country : 'XW' ,
type : '' ,
status : 'official' ,
packaging : 'None' ,
language : 'eng' ,
script : 'Latn' ,
urls : [ ] ,
url : bandcampAlbumData . url . fix _bandcamp _url ( )
} ;
2012-03-28 22:49:43 +00:00
2018-11-20 22:18:49 +00:00
// Grab release title
release . title = bandcampAlbumData . current . title ;
// Grab release event information
let date = this . convdate ( bandcampAlbumData . current . release _date ) ;
if ( date ) {
if ( ! ( date . year > 2008 || ( date . year == 2008 && date . month >= 9 ) ) ) {
// use publish date if release date is before Bandcamp launch (2008-09)
let pdate = this . convdate ( bandcampAlbumData . current . publish _date ) ;
if ( pdate ) {
date = pdate ;
}
}
release . year = date . year ;
release . month = date . month ;
release . day = date . day ;
2014-10-08 21:24:41 +00:00
}
2015-06-18 09:52:59 +00:00
2018-11-20 22:18:49 +00:00
// FIXME: implement a mapping between bandcamp release types and MB ones
if ( bandcampAlbumData . current . type == 'track' ) {
// map Bandcamp single tracks to singles
release . type = 'single' ;
// if track belongs to an album, get its url.
if ( bandcampEmbedData . album _embed _data ) {
release . parent _album _url = bandcampEmbedData . album _embed _data . linkback . fix _bandcamp _url ( ) ;
release . type = 'track' ; // <-- no import
}
2015-06-18 09:52:59 +00:00
}
2015-05-29 08:58:14 +00:00
2018-11-20 22:18:49 +00:00
// Tracks
let disc = {
tracks : [ ] ,
format : release . format
2015-05-29 08:58:14 +00:00
} ;
2018-11-20 22:18:49 +00:00
release . discs . push ( disc ) ;
// attempt to detect multiple artists tracks
// bandcamp formats them as 'artist - tracktitle'
// only set to true if ALL tracks are formatted like this
// and if string doesn't start with a number (ie. 02 - title)
let various _artists = true ;
for ( var i = 0 ; i < bandcampAlbumData . trackinfo . length ; i ++ ) {
if ( ! bandcampAlbumData . trackinfo [ i ] . title . match ( / - / ) || bandcampAlbumData . trackinfo [ i ] . title . match ( /^\d+ - / ) ) {
various _artists = false ;
break ;
}
}
2015-05-29 08:58:14 +00:00
2018-11-20 22:18:49 +00:00
// Release artist credit
if ( bandcampAlbumData . artist . match ( /^various(?: artists)?$/i ) && various _artists ) {
release . artist _credit = [ MBImport . specialArtist ( 'various_artists' ) ] ;
} else {
release . artist _credit = MBImport . makeArtistCredits ( [ bandcampAlbumData . artist ] ) ;
}
let tracks _streamable = 0 ;
$ . each ( bandcampAlbumData . trackinfo , function ( index , bctrack ) {
let title = bctrack . title ;
let artist = [ ] ;
if ( various _artists ) {
let m = bctrack . title . match ( /^(.+) - (.+)$/ ) ;
if ( m ) {
title = m [ 2 ] ;
artist = [ m [ 1 ] ] ;
}
}
if ( bctrack . file ) tracks _streamable ++ ;
let track = {
title : title ,
duration : Math . round ( bctrack . duration * 1000 ) ,
artist _credit : MBImport . makeArtistCredits ( artist )
} ;
disc . tracks . push ( track ) ;
2015-05-25 16:13:40 +00:00
} ) ;
2015-06-12 21:54:01 +00:00
2018-11-20 22:18:49 +00:00
// Check for hidden tracks (more tracks in the download than shown for streaming ie.)
let showntracks = bandcampAlbumData . trackinfo . length ;
let numtracks = - 1 ;
let nostream = false ;
// album description indicates number of tracks in the download
let match = /^\d+ track album$/ . exec ( $ ( "meta[property='og:description']" ) . attr ( 'content' ) ) ;
if ( match ) {
numtracks = parseInt ( match , 10 ) ;
}
if ( numtracks > 0 && numtracks > showntracks ) {
// display a warning if tracks in download differs from tracks shown
$ ( 'h2.trackTitle' ) . append (
` ${ '<p style="font-size:70%; font-style: italic; margin: 0.1em 0;">' + 'Warning: ' } ${ numtracks } vs ${ showntracks } tracks ` +
` </p> `
) ;
// append unknown tracks to the release
for ( var i = 0 ; i < numtracks - showntracks ; i ++ ) {
let track = {
title : '[unknown]' ,
duration : null ,
artist _credit : [ ]
} ;
disc . tracks . push ( track ) ;
}
// disable stream link as only part of the album can be streamed
nostream = true ;
}
2012-03-28 22:49:43 +00:00
2018-11-20 22:18:49 +00:00
// URLs
let link _type = MBImport . URL _TYPES ;
// Download for free vs. for purchase
if ( bandcampAlbumData . current . download _pref !== null ) {
if (
bandcampAlbumData . freeDownloadPage !== null ||
bandcampAlbumData . current . download _pref === 1 ||
( bandcampAlbumData . current . download _pref === 2 && bandcampAlbumData . current . minimum _price === 0 )
) {
release . urls . push ( {
url : release . url ,
link _type : link _type . download _for _free
} ) ;
}
if ( bandcampAlbumData . current . download _pref === 2 ) {
release . urls . push ( {
url : release . url ,
link _type : link _type . purchase _for _download
} ) ;
}
}
// Check if the release is streamable
if ( bandcampAlbumData . hasAudio && ! nostream && disc . tracks . length > 0 && disc . tracks . length == tracks _streamable ) {
release . urls . push ( {
url : release . url ,
link _type : link _type . stream _for _free
} ) ;
}
// Check if release is Creative Commons licensed
if ( $ ( 'div#license a.cc-icons' ) . length > 0 ) {
release . urls . push ( {
url : $ ( 'div#license a.cc-icons' ) . attr ( 'href' ) ,
link _type : link _type . license
} ) ;
}
// Check if album has a back link to a label
2019-12-16 22:19:00 +00:00
let label = $ ( 'a.back-to-label-link span.back-link-text' )
. contents ( )
. get ( 2 ) . textContent ;
2018-11-20 22:18:49 +00:00
if ( label ) {
release . labels . push ( {
name : label ,
mbid : '' ,
catno : 'none'
} ) ;
}
2015-06-16 13:34:02 +00:00
2018-11-20 22:18:49 +00:00
return release ;
} ,
2015-05-25 16:13:40 +00:00
2018-11-20 22:18:49 +00:00
// Insert links in page
insertLink : function ( release ) {
if ( release . type == 'track' ) {
// only import album or single, tracks belong to an album
return false ;
}
// Form parameters
let edit _note = MBImport . makeEditNote ( release . url , 'Bandcamp' ) ;
let parameters = MBImport . buildFormParameters ( release , edit _note ) ;
// Build form
let mbUI = $ ( ` <div id="mb_buttons"> ${ MBImport . buildFormHTML ( parameters ) } ${ MBImport . buildSearchButton ( release ) } </div> ` ) . hide ( ) ;
// Append MB import link
$ ( '#name-section' ) . append ( mbUI ) ;
$ ( '#mb_buttons' ) . css ( { 'margin-top' : '6px' } ) ;
$ ( 'form.musicbrainz_import' ) . css ( { display : 'inline-block' } ) ;
mbUI . slideDown ( ) ;
} ,
// helper to convert bandcamp date to MB date
convdate : function ( date ) {
if ( typeof date != 'undefined' && date !== '' ) {
let d = new Date ( date ) ;
return {
year : d . getUTCFullYear ( ) ,
month : d . getUTCMonth ( ) + 1 ,
day : d . getUTCDate ( )
} ;
}
return false ;
2015-05-25 16:13:40 +00:00
}
} ;
2018-11-20 22:18:49 +00:00
$ ( document ) . ready ( function ( ) {
/ * k e e p t h e f o l l o w i n g l i n e a s f i r s t , i t i s r e q u i r e d t o s k i p
* pages which aren ' t actually a bandcamp page , since we support
* bandcamp pages under third - party domains .
* see @ include
* /
if ( ! unsafeWindow . TralbumData ) return ;
/***/
2015-06-16 19:33:26 +00:00
2018-11-20 22:18:49 +00:00
MBImportStyle ( ) ;
2015-05-25 16:13:40 +00:00
2018-11-20 22:18:49 +00:00
let mblinks = new MBLinks ( 'BCI_MBLINKS_CACHE' ) ;
2015-06-05 08:39:00 +00:00
2018-11-20 22:18:49 +00:00
let release = BandcampImport . retrieveReleaseInfo ( ) ;
2015-06-06 23:20:23 +00:00
2018-11-20 22:18:49 +00:00
// add MB artist link
let root _url = release . url . match ( /^(https?:\/\/[^\/]+)/ ) [ 1 ] . split ( '?' ) [ 0 ] ;
let label _url = '' ;
mblinks . searchAndDisplayMbLink ( root _url , 'artist' , function ( link ) {
$ ( 'div#name-section span[itemprop="byArtist"]' ) . before ( link ) ;
} ) ;
mblinks . searchAndDisplayMbLink (
root _url ,
'label' ,
function ( link ) {
$ ( 'p#band-name-location span.title' ) . append ( link ) ;
} ,
` label: ${ root _url } `
) ;
let labelback = $ ( 'a.back-to-label-link' ) ;
if ( labelback ) {
let labelbacklink = labelback . attr ( 'href' ) ;
if ( labelbacklink ) {
label _url = labelbacklink
. match ( /^(https?:\/\/[^\/]+)/ ) [ 1 ]
. split ( '?' ) [ 0 ]
. fix _bandcamp _url ( ) ;
mblinks . searchAndDisplayMbLink (
label _url ,
'label' ,
function ( link ) {
$ ( 'a.back-to-label-link span.back-link-text' ) . append ( link ) ;
} ,
` label: ${ label _url } `
) ;
}
2017-09-05 08:34:13 +00:00
}
2015-06-05 08:39:00 +00:00
2018-11-20 22:18:49 +00:00
if ( release . artist _credit . length == 1 ) {
// try to get artist's mbid from cache
let artist _mbid = mblinks . resolveMBID ( root _url ) ;
if ( artist _mbid ) {
release . artist _credit [ 0 ] . mbid = artist _mbid ;
}
2015-06-16 19:24:01 +00:00
}
2015-07-10 08:14:01 +00:00
2018-11-20 22:18:49 +00:00
// try to get label mbid from cache
let label _mbid = '' ;
let label _name = '' ;
if ( label _url ) {
label _mbid = mblinks . resolveMBID ( ` label: ${ label _url } ` ) ;
label _name = $ ( 'a.back-to-label-link span.back-link-text ' )
. contents ( )
. get ( 2 ) . textContent ;
} else {
label _mbid = mblinks . resolveMBID ( ` label: ${ root _url } ` ) ;
if ( label _mbid )
label _name = $ ( 'p#band-name-location span.title' )
. text ( )
. trim ( ) ;
}
if ( label _mbid || label _name ) {
if ( release . labels . length == 0 ) {
release . labels . push ( {
name : '' ,
mbid : '' ,
catno : 'none'
} ) ;
}
release . labels [ 0 ] . name = label _name ;
release . labels [ 0 ] . mbid = label _mbid ;
2015-07-10 08:14:01 +00:00
}
2015-06-16 19:24:01 +00:00
2018-11-20 22:18:49 +00:00
BandcampImport . insertLink ( release ) ;
LOGGER . info ( 'Parsed release: ' , release ) ;
2015-06-05 08:39:00 +00:00
2018-11-20 22:18:49 +00:00
if ( release . type == 'track' ) {
// add MB links to parent album
mblinks . searchAndDisplayMbLink ( release . parent _album _url , 'release' , function ( link ) {
$ ( 'div#name-section span[itemprop="inAlbum"] a:first' ) . before ( link ) ;
} ) ;
} else {
// add MB release links to album or single
mblinks . searchAndDisplayMbLink ( release . url , 'release' , function ( link ) {
$ ( 'div#name-section span[itemprop="byArtist"]' ) . after ( link ) ;
} ) ;
}
2012-03-28 22:49:43 +00:00
2018-11-20 22:18:49 +00:00
// append a comma after each tag to ease cut'n'paste to MB
$ ( 'div.tralbum-tags a:not(:last-child).tag' ) . after ( ', ' ) ;
2015-06-01 10:01:08 +00:00
2018-11-20 22:18:49 +00:00
// append a link to the full size image
let fullsizeimageurl = $ ( 'div#tralbumArt a' )
. attr ( 'href' )
. replace ( '_10' , '_0' ) ;
$ ( 'div#tralbumArt' ) . after (
` <div id='bci_link'><a class='custom-color' href=' ${ fullsizeimageurl } ' title='Open original image in a new tab (Bandcamp importer)' target='_blank'>Original image</a></div> `
) ;
2015-05-25 16:13:40 +00:00
2018-11-20 22:18:49 +00:00
$ ( 'div#bci_link' ) . css ( { 'padding-top' : '0.5em' , 'text-align' : 'right' } ) ;
$ ( 'div#bci_link a' ) . css ( { 'font-weight' : 'bold' } ) ;
2015-05-25 16:13:40 +00:00
} ) ;