2015-01-18 01:01:36 +00:00
// ==UserScript==
2012-06-08 23:58:47 +00:00
// @name Import Discogs releases to MusicBrainz
2015-06-10 13:00:03 +00:00
// @description Add a button to import Discogs releases to MusicBrainz and add links to matching MusicBrainz entities for various Discogs entities (artist,release,master,label)
2015-06-15 07:54:21 +00:00
// @version 2015.06.15.0
2012-06-08 23:58:47 +00:00
// @namespace http://userscripts.org/users/22504
// @icon http://www.discogs.com/images/discogs130.png
2012-12-08 21:30:19 +00:00
// @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/discogs_importer.user.js
// @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/discogs_importer.user.js
2012-06-08 23:58:47 +00:00
// @include http://www.discogs.com/*
// @include http://*.discogs.com/*release/*
// @exclude http://*.discogs.com/*release/*?f=xml*
// @exclude http://www.discogs.com/release/add
2015-06-06 11:12:47 +00:00
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
2015-06-05 18:49:23 +00:00
// @require lib/import_functions.js
// @require lib/logger.js
2015-06-05 20:17:24 +00:00
// @require lib/mblinks.js
2015-06-15 07:52:59 +00:00
// @require lib/mbimportstyle.js
2012-06-08 23:58:47 +00:00
// ==/UserScript==
2015-06-06 11:12:47 +00:00
// prevent JQuery conflicts, see http://wiki.greasespot.net/@grant
this . $ = this . jQuery = jQuery . noConflict ( true ) ;
if ( ! unsafeWindow ) unsafeWindow = window ;
2015-06-11 09:57:52 +00:00
var DEBUG = false ;
//DEBUG = true;
if ( DEBUG ) {
LOGGER . setLevel ( 'debug' ) ;
}
2015-06-06 11:12:47 +00:00
2012-06-08 23:58:47 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////
2015-01-18 01:01:36 +00:00
/ *
* Test cases :
* - http : //www.discogs.com/release/1566223 : Artist credit of tracks contains an ending ',' join phrase
* /
2012-06-08 23:58:47 +00:00
2015-06-16 07:15:13 +00:00
var mblinks = new MBLinks ( 'DISCOGS_MBLINKS_CACHE' , '1' ) ;
2012-06-08 23:58:47 +00:00
2015-06-05 20:17:24 +00:00
$ ( document ) . ready ( function ( ) {
2012-06-08 23:58:47 +00:00
2015-06-15 07:52:59 +00:00
MBImportStyle ( ) ;
2015-06-14 12:08:55 +00:00
var current _page _key = getDiscogsLinkKey ( window . location . href . replace ( /\?.*$/ , '' ) . replace ( /#.*$/ , '' ) . replace ( '/master/view/' , '/master/' ) ) ;
2015-06-12 13:55:00 +00:00
if ( ! current _page _key ) return ;
2015-06-12 13:07:21 +00:00
// disable evil pjax (used for artist page navigation)
// it causes various annoying issues with our code;
// it should be possible to react to pjax events
$ ( "div#pjax_container" ) . attr ( 'id' , 'pjax_disabled' ) ;
2012-06-08 23:58:47 +00:00
2015-06-12 13:15:07 +00:00
// Display links of equivalent MusicBrainz entities for masters and releases
2013-12-31 18:21:47 +00:00
insertMBLinks ( ) ;
2012-06-08 23:58:47 +00:00
2015-06-12 13:55:00 +00:00
// Add an import button in a new section in sidebar, if we're on a release page?
var current _page _info = link _infos [ current _page _key ] ;
if ( current _page _info . type == 'release' ) {
2013-12-31 18:21:47 +00:00
// Discogs Webservice URL
2015-06-12 13:55:00 +00:00
var discogsWsUrl = 'http://api.discogs.com/releases/' + current _page _info . id ;
2013-12-31 18:21:47 +00:00
$ . ajax ( {
2014-02-21 18:25:49 +00:00
url : discogsWsUrl ,
2014-12-30 16:35:11 +00:00
dataType : 'json' ,
2014-02-21 18:25:49 +00:00
crossDomain : true ,
success : function ( data , textStatus , jqXHR ) {
2015-01-18 13:00:58 +00:00
LOGGER . debug ( "Discogs JSON Data from API:" , data ) ;
2014-02-21 18:25:49 +00:00
var release = parseDiscogsRelease ( data ) ;
2015-06-12 13:55:00 +00:00
insertLink ( release , current _page _key ) ;
2014-02-21 18:25:49 +00:00
} ,
error : function ( jqXHR , textStatus , errorThrown ) {
2015-01-18 13:00:58 +00:00
LOGGER . error ( "AJAX Status: " , textStatus ) ;
LOGGER . error ( "AJAX error thrown: " , errorThrown ) ;
2014-02-21 18:25:49 +00:00
}
2013-08-04 08:33:02 +00:00
} ) ;
2012-06-08 23:58:47 +00:00
}
} ) ;
2013-12-31 18:21:47 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Display links of equivalent MusicBrainz entities for masters and releases //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2013-08-04 08:33:02 +00:00
2013-12-31 18:21:47 +00:00
// Insert MusicBrainz links in a section of the page
2013-12-04 07:36:53 +00:00
function insertMBLinks ( $root ) {
2015-06-12 09:21:43 +00:00
function searchAndDisplayMbLinkInSection ( $tr , discogs _type , mb _type ) {
if ( ! mb _type ) mb _type = defaultMBtype ( discogs _type ) ;
2015-06-11 09:22:23 +00:00
$tr . find ( 'a[mlink^="' + discogs _type + '/"]' ) . each ( function ( ) {
2013-08-04 08:33:02 +00:00
var $link = $ ( this ) ;
2015-06-12 09:27:19 +00:00
if ( $link . attr ( 'mlink_stop' ) ) return ; // for places
2015-06-11 09:22:23 +00:00
var mlink = $link . attr ( 'mlink' ) ;
2015-06-06 08:42:28 +00:00
// ensure we do it only once per link
2015-06-11 13:33:11 +00:00
var done = ( $link . attr ( 'mlink_done' ) || "" ) . split ( "," ) ;
for ( var i = 0 ; i < done . length ; i ++ ) {
if ( mb _type == done [ i ] ) return ;
}
done . push ( mb _type ) ;
$link . attr ( 'mlink_done' , done . filter ( function ( e ) { return ( e != "" ) ; } ) . join ( ',' ) ) ;
2015-06-11 09:22:23 +00:00
if ( link _infos [ mlink ] && link _infos [ mlink ] . type == discogs _type ) {
var discogs _url = link _infos [ mlink ] . clean _url ;
2015-06-12 09:27:19 +00:00
var cachekey = getCacheKeyFromInfo ( mlink , mb _type ) ;
var insert _func = function ( link ) { $link . before ( link ) ; }
if ( mb _type == 'place' ) {
// if a place link was added we stop, we don't want further queries for this 'label'
insert _func = function ( link ) { $link . before ( link ) ; $link . attr ( 'mlink_stop' , true ) ; }
}
mblinks . searchAndDisplayMbLink ( discogs _url , mb _type , insert _func , cachekey ) ;
2015-06-11 09:22:23 +00:00
}
2013-08-04 08:33:02 +00:00
} ) ;
}
if ( ! $root ) {
$root = $ ( 'body' ) ;
}
2015-06-12 13:08:12 +00:00
function debug _color ( what , n , id ) {
2015-06-11 09:57:52 +00:00
var colors = [
'#B3C6FF' ,
'#C6B3FF' ,
'#ECB3FF' ,
'#FFB3EC' ,
'#FFB3C6' ,
'#FFC6B3' ,
'#FFECB3' ,
'#ECFFB3' ,
'#C6FFB3' ,
'#B3FFC6' ,
'#B3FFEC' ,
'#B3ECFF' ,
'#7598FF' ,
] ;
if ( DEBUG ) {
$ ( what ) . css ( 'border' , '2px dotted ' + colors [ n % colors . length ] ) ;
var debug _attr = $ ( what ) . attr ( 'debug_discogs' ) ;
2015-06-12 13:08:12 +00:00
if ( ! id ) id = '' ;
2015-06-11 09:57:52 +00:00
if ( debug _attr ) {
2015-06-12 13:08:12 +00:00
$ ( what ) . attr ( 'debug_discogs' , debug _attr + ' || ' + id + '(' + n + ')' ) ;
2015-06-11 09:57:52 +00:00
} else {
2015-06-12 13:08:12 +00:00
$ ( what ) . attr ( 'debug_discogs' , id + '(' + n + ')' ) ;
2015-06-11 09:57:52 +00:00
}
}
}
2015-06-05 21:28:45 +00:00
2015-06-12 13:12:09 +00:00
var add _mblinks _counter = 0 ;
function add _mblinks ( _root , selector , types ) {
// types can be:
// 'discogs type 1'
// ['discogs_type 1', 'discogs_type 2']
// [['discogs_type 1', 'mb type 1'], 'discogs_type 2']
// etc.
if ( ! $ . isArray ( types ) ) {
// just one string
types = [ types ] ;
}
$ . each ( types ,
function ( idx , val ) {
if ( ! $ . isArray ( val ) ) {
types [ idx ] = [ val , undefined ] ;
}
}
) ;
LOGGER . debug ( 'add_mblinks: ' + selector + ' / ' + JSON . stringify ( types ) ) ;
_root . find ( selector ) . each ( function ( ) {
var node = $ ( this ) . get ( 0 ) ;
magnifyLinks ( node ) ;
debug _color ( this , ++ add _mblinks _counter , selector ) ;
var that = this ;
$ . each ( types , function ( idx , val ) {
var discogs _type = val [ 0 ] ;
var mb _type = val [ 1 ] ;
searchAndDisplayMbLinkInSection ( $ ( that ) , discogs _type , mb _type ) ;
} ) ;
} ) ;
}
2013-08-04 08:33:02 +00:00
2015-06-12 13:15:07 +00:00
add _mblinks ( $root , 'div.profile' , [ 'artist' , 'label' ] ) ;
add _mblinks ( $root , 'tr[data-object-type="release"] td.artist,td.title' , 'artist' ) ;
add _mblinks ( $root , 'tr[data-object-type="release"] td.title' , 'release' ) ;
add _mblinks ( $root , 'tr[data-object-type="release"]' , 'label' ) ;
add _mblinks ( $root , 'tr[data-object-type~="master"]' , [ 'master' , 'artist' , 'label' ] ) ;
add _mblinks ( $root , 'div#tracklist' , 'artist' ) ;
add _mblinks ( $root , 'div#companies' , [ [ 'label' , 'place' ] , 'label' ] ) ;
add _mblinks ( $root , 'div#credits' , [ 'label' , 'artist' ] ) ;
add _mblinks ( $root , 'div#page_aside div.section_content:first' , 'master' ) ;
2013-08-04 08:33:02 +00:00
}
2013-12-04 07:36:53 +00:00
2013-12-31 18:21:47 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Normalize Discogs URLs in a DOM tree //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2015-06-12 13:09:53 +00:00
var mlink _processed = 0 ;
2013-12-31 18:21:47 +00:00
// Normalize Discogs URLs in a DOM tree
2015-06-12 13:09:53 +00:00
function magnifyLinks ( rootNode ) {
2013-08-04 08:33:02 +00:00
if ( ! rootNode ) {
rootNode = document . body ;
}
2012-06-08 23:58:47 +00:00
// Check if we already added links for this content
2015-06-12 13:09:53 +00:00
if ( rootNode . hasAttribute ( 'mlink_processed' ) )
2012-06-08 23:58:47 +00:00
return ;
2015-06-12 13:09:53 +00:00
rootNode . setAttribute ( 'mlink_processed' , ++ mlink _processed ) ;
2012-06-08 23:58:47 +00:00
2013-08-04 08:33:02 +00:00
var elems = rootNode . getElementsByTagName ( 'a' ) ;
2012-06-08 23:58:47 +00:00
for ( var i = 0 ; i < elems . length ; i ++ ) {
var elem = elems [ i ] ;
// Ignore empty links
2013-12-31 18:21:47 +00:00
if ( ! elem . href || $ . trim ( elem . textContent ) == '' || elem . textContent . substring ( 4 , 0 ) == 'http' )
2012-06-08 23:58:47 +00:00
continue ;
2015-06-11 09:22:23 +00:00
if ( ! elem . hasAttribute ( 'mlink' ) ) {
elem . setAttribute ( 'mlink' , getDiscogsLinkKey ( elem . href ) ) ;
}
2013-12-31 18:21:47 +00:00
}
}
2015-06-11 09:22:23 +00:00
// contains infos for each link key
var link _infos = { } ;
// Parse discogs url to extract info, returns a key and set link_infos for this key
// the key is in the form discogs_type/discogs_id
function getDiscogsLinkKey ( url ) {
2015-06-12 14:00:04 +00:00
var re = /^http:\/\/(?:www|api)\.discogs\.com\/(?:(?:(?!sell).+|sell.+)\/)?(master|release|artist|label)s?\/(\d+)(?:[^\?#]*)(?:\?noanv=1|\?anv=[^=]+)?$/i ;
2013-12-31 18:21:47 +00:00
if ( m = re . exec ( url ) ) {
2015-06-11 09:22:23 +00:00
var key = m [ 1 ] + '/' + m [ 2 ] ;
if ( ! link _infos [ key ] ) {
link _infos [ key ] = {
type : m [ 1 ] ,
id : m [ 2 ] ,
clean _url : 'http://www.discogs.com/' + m [ 1 ] + '/' + m [ 2 ]
}
LOGGER . debug ( 'getDiscogsLinkKey:' + url + ' --> ' + key ) ;
} else {
LOGGER . debug ( 'getDiscogsLinkKey:' + url + ' --> ' + key + ' (key exists)' ) ;
}
return key ;
2012-06-08 23:58:47 +00:00
}
2015-06-11 09:22:23 +00:00
LOGGER . debug ( 'getDiscogsLinkKey:' + url + ' ?' ) ;
return false ;
2012-06-08 23:58:47 +00:00
}
2015-06-11 09:22:23 +00:00
function getCleanUrl ( url , discogs _type ) {
try {
var key = getDiscogsLinkKey ( url ) ;
if ( key ) {
if ( ! discogs _type || link _infos [ key ] . type == discogs _type ) {
LOGGER . debug ( 'getCleanUrl: ' + key + ', ' + url + ' --> ' + link _infos [ key ] . clean _url ) ;
return link _infos [ key ] . clean _url ;
} else {
LOGGER . debug ( 'getCleanUrl: ' + key + ', ' + url + ' --> unmatched type: ' + discogs _type ) ;
}
}
}
catch ( err ) {
LOGGER . error ( err ) ;
}
LOGGER . debug ( 'getCleanUrl: ' + url + ' (' + discogs _type + ') failed' ) ;
return false ;
}
2015-06-12 09:21:43 +00:00
function defaultMBtype ( discogs _type ) {
if ( discogs _type == 'master' ) return 'release-group' ;
return discogs _type ;
}
2015-06-12 09:23:38 +00:00
function getCacheKeyFromInfo ( info _key , mb _type ) {
var inf = link _infos [ info _key ] ;
if ( inf ) {
if ( ! mb _type ) mb _type = defaultMBtype ( inf . type ) ;
return inf . type + '/' + inf . id + '/' + mb _type ;
}
return '' ;
}
function getCacheKeyFromUrl ( url , discogs _type , mb _type ) {
try {
var key = getDiscogsLinkKey ( url ) ;
if ( key ) {
if ( ! discogs _type || link _infos [ key ] . type == discogs _type ) {
var cachekey = getCacheKeyFromInfo ( key , mb _type ) ;
LOGGER . debug ( 'getCacheKeyFromUrl: ' + key + ', ' + url + ' --> ' + cachekey ) ;
return cachekey ;
} else {
LOGGER . debug ( 'getCacheKeyFromUrl: ' + key + ', ' + url + ' --> unmatched type: ' + discogs _type ) ;
}
}
}
catch ( err ) {
LOGGER . error ( err ) ;
}
LOGGER . debug ( 'getCacheKeyFromUrl: ' + url + ' (' + discogs _type + ') failed' ) ;
return false ;
}
2015-06-12 09:24:55 +00:00
function MBIDfromUrl ( url , discogs _type , mb _type ) {
var cachekey = getCacheKeyFromUrl ( url , discogs _type , mb _type ) ;
if ( ! cachekey ) return '' ;
return mblinks . resolveMBID ( cachekey ) ;
2015-06-11 09:22:23 +00:00
}
2013-12-31 18:21:47 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Insert MusicBrainz section into Discogs page //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Insert links in Discogs page
2015-06-12 13:55:00 +00:00
function insertLink ( release , current _page _key ) {
var current _page _info = link _infos [ current _page _key ] ;
2013-12-31 18:21:47 +00:00
2015-06-14 12:17:49 +00:00
var mbUI = $ ( '<div class="section musicbrainz"><h3>MusicBrainz</h3></div>' ) . hide ( ) ;
2013-12-31 18:21:47 +00:00
2015-06-14 12:25:10 +00:00
if ( DEBUG ) mbUI . css ( { 'border' : '1px dotted red' } ) ;
2013-12-31 18:21:47 +00:00
var mbContentBlock = $ ( '<div class="section_content"></div>' ) ;
mbUI . append ( mbContentBlock ) ;
2015-06-14 12:21:18 +00:00
var mbLinked = $ ( '<p><small>MusicBrainz release(s) linked to this page: </small></p>' ) . hide ( ) ;
mbContentBlock . prepend ( mbLinked ) ;
2013-12-31 18:21:47 +00:00
// Form parameters
2015-06-12 13:55:00 +00:00
var edit _note = 'Imported from ' + current _page _info . clean _url ;
2013-12-31 18:21:47 +00:00
var parameters = MBReleaseImportHelper . buildFormParameters ( release , edit _note ) ;
// Build form
2015-06-14 12:21:18 +00:00
var innerHTML = MBReleaseImportHelper . buildFormHTML ( parameters ) ;
2013-12-31 18:21:47 +00:00
// Append search link
innerHTML += ' <small>(' + MBReleaseImportHelper . buildSearchLink ( release ) + ')</small>' ;
2015-06-14 12:21:18 +00:00
mbContentBlock . append ( innerHTML ) ;
2013-12-31 18:21:47 +00:00
var prevNode = $ ( "div.section.social" ) ;
prevNode . before ( mbUI ) ;
// Find MB release(s) linked to this Discogs release
2015-06-14 12:21:18 +00:00
var mbLinkInsert = function ( link ) {
var sel = "div.section.musicbrainz div.section_content p" ;
$ ( sel ) . append ( link ) ;
$ ( sel ) . find ( 'img' ) . css ( { 'vertical-align' : 'text-top' } ) ;
mbLinked . show ( ) ;
}
2015-06-12 13:55:00 +00:00
var cachekey = getCacheKeyFromInfo ( current _page _key , 'release' ) ;
mblinks . searchAndDisplayMbLink ( current _page _info . clean _url , 'release' , mbLinkInsert , cachekey ) ;
2015-06-14 12:17:49 +00:00
mbUI . slideDown ( ) ;
2012-06-08 23:58:47 +00:00
}
2013-12-31 18:21:47 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Parsing of Discogs data //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2015-06-04 08:08:03 +00:00
2012-06-08 23:58:47 +00:00
// Analyze Discogs data and return a release object
function parseDiscogsRelease ( data ) {
2014-12-30 16:35:11 +00:00
var discogsRelease = data ;
2012-06-08 23:58:47 +00:00
var release = new Object ( ) ;
release . discs = [ ] ;
// Release artist credit
release . artist _credit = new Array ( ) ;
$ . each ( discogsRelease . artists , function ( index , artist ) {
var ac = {
'artist_name' : artist . name . replace ( / \(\d+\)$/ , "" ) ,
'credited_name' : ( artist . anv != "" ? artist . anv : artist . name . replace ( / \(\d+\)$/ , "" ) ) ,
2015-06-07 19:49:51 +00:00
'joinphrase' : decodeDiscogsJoinphrase ( artist . join ) ,
2015-06-11 09:22:23 +00:00
'mbid' : MBIDfromUrl ( artist . resource _url , 'artist' )
2012-06-08 23:58:47 +00:00
} ;
release . artist _credit . push ( ac ) ;
} ) ;
2015-06-07 19:49:51 +00:00
// ReleaseGroup
2015-06-11 13:57:15 +00:00
if ( discogsRelease . master _url ) {
release . release _group _mbid = MBIDfromUrl ( discogsRelease . master _url , 'master' ) ;
}
2015-06-07 19:49:51 +00:00
2012-06-08 23:58:47 +00:00
// Release title
release . title = discogsRelease . title ;
// Release date
if ( discogsRelease . released ) {
var releasedate = discogsRelease . released ;
if ( typeof releasedate != "undefined" && releasedate != "" ) {
var tmp = releasedate . split ( '-' ) ; if ( tmp [ 0 ] != "undefined" && tmp [ 0 ] != "" ) {
release . year = parseInt ( tmp [ 0 ] , 10 ) ;
if ( tmp [ 1 ] != "undefined" && tmp [ 1 ] != "" ) {
release . month = parseInt ( tmp [ 1 ] , 10 ) ;
if ( tmp [ 2 ] != "undefined" && tmp [ 2 ] != "" ) {
release . day = parseInt ( tmp [ 2 ] , 10 ) ;
}
}
}
}
}
// Release country
if ( discogsRelease . country ) {
release . country = Countries [ discogsRelease . country ] ;
}
// Release labels
release . labels = new Array ( ) ;
if ( discogsRelease . labels ) {
$ . each ( discogsRelease . labels , function ( index , label ) {
2015-06-11 09:22:23 +00:00
var labelinfo = {
name : label . name ,
catno : ( label . catno == "none" ? "[none]" : label . catno ) ,
mbid : MBIDfromUrl ( label . resource _url , 'label' )
} ;
release . labels . push ( labelinfo ) ;
2012-06-08 23:58:47 +00:00
} ) ;
}
2014-02-21 19:05:25 +00:00
// Release URL
release . urls = new Array ( ) ;
2015-06-12 13:55:00 +00:00
var release _url = getCleanUrl ( discogsRelease . uri , 'release' ) ;
2015-06-12 22:23:45 +00:00
release . urls . push ( { url : release _url , link _type : MBReleaseImportHelper . URL _TYPES . discogs } ) ;
2014-02-21 19:05:25 +00:00
2012-06-08 23:58:47 +00:00
// Release format
2012-12-08 21:23:04 +00:00
var release _formats = new Array ( ) ;
2014-08-14 23:55:30 +00:00
release . secondary _types = new Array ( ) ;
2012-06-08 23:58:47 +00:00
if ( discogsRelease . formats . length > 0 ) {
2012-12-08 21:23:04 +00:00
for ( var i = 0 ; i < discogsRelease . formats . length ; i ++ )
{
for ( var j = 0 ; j < discogsRelease . formats [ i ] . qty ; j ++ )
release _formats . push ( MediaTypes [ discogsRelease . formats [ i ] . name ] ) ;
if ( discogsRelease . formats [ i ] . descriptions ) {
$ . each ( discogsRelease . formats [ i ] . descriptions , function ( index , desc ) {
2014-08-15 00:23:51 +00:00
// Release format: special handling of vinyl 7", 10" and 12" and other more specific CD/DVD formats
if ( desc . match ( /7"|10"|12"|^VCD|SVCD|CD\+G|HDCD|DVD-Audio|DVD-Video/ ) ) release _formats [ release _formats . length - 1 ] = MediaTypes [ desc ] ;
2012-12-08 21:23:04 +00:00
// Release format: special handling of Vinyl, LP == 12" (http://www.discogs.com/help/submission-guidelines-release-format.html#LP)
if ( discogsRelease . formats [ i ] . name == "Vinyl" && desc == "LP" ) release _formats [ release _formats . length - 1 ] = '12" Vinyl' ;
2014-08-15 00:23:51 +00:00
// Release format: special handling of CD, Mini == 8cm CD
if ( discogsRelease . formats [ i ] . name == "CD" && desc == "Mini" ) release _formats [ release _formats . length - 1 ] = '8cm CD' ;
2012-12-08 21:23:04 +00:00
// Release status
if ( desc . match ( /Promo|Smplr/ ) ) release . status = "promotion" ;
2014-08-14 22:51:44 +00:00
if ( desc . match ( /Unofficial Release/ ) ) release . status = "bootleg" ;
2012-12-08 21:23:04 +00:00
// Release type
2014-08-14 23:55:30 +00:00
if ( desc . match ( /Compilation/ ) ) release . secondary _types . push ( "compilation" ) ;
if ( desc . match ( /^Album/ ) ) release . type = "album" ;
2012-12-08 21:23:04 +00:00
if ( desc . match ( /Single/ ) ) release . type = "single" ;
2014-08-14 23:55:30 +00:00
if ( desc . match ( /EP|Mini-Album/ ) ) release . type = "ep" ;
2012-12-08 21:23:04 +00:00
} ) ;
}
2012-06-08 23:58:47 +00:00
2012-12-08 21:23:04 +00:00
// Release packaging
2012-12-08 21:30:19 +00:00
if ( discogsRelease . formats [ i ] . text ) {
var freetext = discogsRelease . formats [ i ] . text . toLowerCase ( ) . replace ( /-/g , '' ) . replace ( / /g , '' ) ;
if ( freetext . match ( /cardboard|paper/ ) ) release . packaging = "cardboard/paper sleeve" ;
if ( freetext . match ( /digipak/ ) ) release . packaging = "digipak" ;
if ( freetext . match ( /keepcase/ ) ) release . packaging = "keep case" ;
if ( freetext . match ( /jewel/ ) ) {
release . packaging = freetext . match ( /slim/ ) ? "slim jewel case" : "jewel case" ;
}
}
2012-06-08 23:58:47 +00:00
}
}
// Barcode
if ( discogsRelease . identifiers ) {
$ . each ( discogsRelease . identifiers , function ( index , identifier ) {
if ( identifier . type == "Barcode" ) {
release . barcode = identifier . value . replace ( / /g , '' ) ;
return false ;
}
} ) ;
}
// Inspect tracks
var tracks = [ ] ;
2015-06-03 15:09:38 +00:00
var heading = "" ;
2012-12-08 21:23:04 +00:00
var releaseNumber = 1 ;
var lastPosition = 0 ;
2012-06-08 23:58:47 +00:00
$ . each ( discogsRelease . tracklist , function ( index , discogsTrack ) {
2015-06-03 15:09:38 +00:00
if ( discogsTrack . type _ == 'heading' ) {
heading = discogsTrack . title ;
return ;
2015-06-03 22:37:15 +00:00
} else if ( discogsTrack . type _ != 'track' && discogsTrack . type _ != 'index' ) {
2015-06-03 15:09:38 +00:00
return ;
}
2012-06-08 23:58:47 +00:00
var track = new Object ( ) ;
track . title = discogsTrack . title ;
2015-06-13 02:25:31 +00:00
track . duration = MBReleaseImportHelper . hmsToMilliSeconds ( discogsTrack . duration ) ; // MB in milliseconds
2012-06-08 23:58:47 +00:00
// Track artist credit
track . artist _credit = new Array ( ) ;
if ( discogsTrack . artists ) {
$ . each ( discogsTrack . artists , function ( index , artist ) {
var ac = {
'artist_name' : artist . name . replace ( / \(\d+\)$/ , "" ) ,
'credited_name' : ( artist . anv != "" ? artist . anv : artist . name . replace ( / \(\d+\)$/ , "" ) ) ,
2015-06-07 19:49:51 +00:00
'joinphrase' : decodeDiscogsJoinphrase ( artist . join ) ,
2015-06-11 09:22:23 +00:00
'mbid' : MBIDfromUrl ( artist . resource _url , 'artist' )
2012-06-08 23:58:47 +00:00
} ;
track . artist _credit . push ( ac ) ;
} ) ;
2015-01-18 01:01:36 +00:00
// Fix some odd Discogs release (e.g. http://api.discogs.com/releases/1566223) that have a ',' join phrase after the last artist
if ( track . artist _credit [ track . artist _credit . length - 1 ] . joinphrase == ", " ) {
track . artist _credit [ track . artist _credit . length - 1 ] . joinphrase = "" ;
}
2012-06-08 23:58:47 +00:00
}
// Track position and release number
var trackPosition = discogsTrack . position ;
2015-06-03 22:37:15 +00:00
// Handle sub-tracks
2015-01-16 12:56:36 +00:00
if ( trackPosition == "" && discogsTrack . sub _tracks ) {
trackPosition = discogsTrack . sub _tracks [ 0 ] . position ;
2015-06-03 22:37:15 +00:00
// Append titles of sub-tracks to main track title
var subtrack _titles = [ ] ;
2015-06-04 08:08:03 +00:00
var subtrack _total _duration = 0 ;
2015-06-03 22:37:15 +00:00
$ . each ( discogsTrack . sub _tracks , function ( subtrack _index , subtrack ) {
if ( subtrack . type _ != 'track' ) {
return ;
}
2015-06-04 08:08:03 +00:00
if ( subtrack . duration ) {
2015-06-13 02:25:31 +00:00
subtrack _total _duration += MBReleaseImportHelper . hmsToMilliSeconds ( subtrack . duration ) ;
2015-06-04 08:08:03 +00:00
}
2015-06-03 22:37:15 +00:00
if ( subtrack . title ) {
subtrack _titles . push ( subtrack . title ) ;
} else {
subtrack _titles . push ( '[unknown]' ) ;
}
} ) ;
if ( subtrack _titles . length ) {
if ( track . title ) {
track . title += ': ' ;
}
track . title += subtrack _titles . join ( ' / ' ) ;
}
2015-06-13 02:25:31 +00:00
if ( isNaN ( track . duration ) && ! isNaN ( subtrack _total _duration ) ) {
2015-06-12 22:24:41 +00:00
track . duration = subtrack _total _duration ;
2015-06-04 08:08:03 +00:00
}
2015-01-16 12:56:36 +00:00
}
2012-06-08 23:58:47 +00:00
// Skip special tracks
if ( trackPosition . toLowerCase ( ) . match ( "^(video|mp3)" ) ) {
trackPosition = "" ;
}
2012-12-08 21:23:04 +00:00
var tmp = trackPosition . match ( /(\d+)(?:[\.-](\d+))?/ ) ;
if ( tmp )
{
tmp [ 1 ] = parseInt ( tmp [ 1 ] , 10 ) ;
var trackNumber = 1 ;
if ( tmp [ 2 ] ) // 1-1, 1-2, 2-1, ... - we can get release number and track number from this
{
releaseNumber = tmp [ 1 ] ;
trackNumber = parseInt ( tmp [ 2 ] , 10 ) ;
}
else if ( trackPosition . match ( /^[A-Za-z]\d*$/ ) ) // Vinyl or cassette, handle it specially
{
var code = trackPosition . charCodeAt ( 0 ) ;
2012-06-08 23:58:47 +00:00
// A-Z
if ( 65 <= code && code <= 90 ) {
code = code - 65 ;
} else if ( 97 <= code && code <= 122 ) {
// a-z
code = code - ( 65 + 32 ) ;
}
releaseNumber = ( code - code % 2 ) / 2 + 1 ;
}
2012-12-08 21:23:04 +00:00
else if ( tmp [ 1 ] <= lastPosition ) // 1, 2, 3, ... - We've moved onto a new medium
{
releaseNumber ++ ;
trackNumber = tmp [ 1 ] ;
}
else
{
trackNumber = tmp [ 1 ] ;
}
lastPosition = trackNumber ;
2012-06-08 23:58:47 +00:00
}
// Create release if needed
if ( ! release . discs [ releaseNumber - 1 ] ) {
release . discs . push ( new Object ( ) ) ;
release . discs [ releaseNumber - 1 ] . tracks = [ ] ;
2012-12-08 21:23:04 +00:00
release . discs [ releaseNumber - 1 ] . format = release _formats [ releaseNumber - 1 ] ;
2015-06-03 15:09:38 +00:00
if ( heading ) {
release . discs [ releaseNumber - 1 ] . title = heading ;
heading = "" ;
}
2012-06-08 23:58:47 +00:00
}
// Track number (only for Vinyl and Cassette)
2014-09-26 14:21:01 +00:00
if ( release . discs [ releaseNumber - 1 ] . format . match ( /(Vinyl|Cassette)/ )
2012-06-08 23:58:47 +00:00
&& discogsTrack . position . match ( /^[A-Z]+[\.-]?\d*/ ) ) {
track . number = discogsTrack . position ;
}
// Trackposition is empty e.g. for release title
2015-06-12 22:24:41 +00:00
if ( trackPosition != "" && trackPosition != null ) {
2012-06-08 23:58:47 +00:00
release . discs [ releaseNumber - 1 ] . tracks . push ( track ) ;
2015-06-12 22:24:41 +00:00
}
2012-06-08 23:58:47 +00:00
} ) ;
2015-01-18 13:00:58 +00:00
LOGGER . info ( "Parsed release: " , release ) ;
2012-06-08 23:58:47 +00:00
return release ;
}
function decodeDiscogsJoinphrase ( join ) {
var joinphrase = "" ;
var trimedjoin = join . replace ( /^\s*/ , "" ) . replace ( /\s*$/ , "" ) ;
if ( trimedjoin == "" ) return trimedjoin ;
if ( trimedjoin != "," ) joinphrase += " " ;
joinphrase += trimedjoin ;
joinphrase += " " ;
return joinphrase ;
}
2013-12-31 18:21:47 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Discogs -> MusicBrainz mapping //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2012-06-08 23:58:47 +00:00
var MediaTypes = new Array ( ) ;
MediaTypes [ "8-Track Cartridge" ] = "Cartridge" ;
MediaTypes [ "Acetate" ] = "Vinyl" ;
MediaTypes [ "Betamax" ] = "Betamax" ;
MediaTypes [ "Blu-ray" ] = "Blu-ray" ;
MediaTypes [ "Blu-ray-R" ] = "Blu-ray" ;
MediaTypes [ "Cassette" ] = "Cassette" ;
MediaTypes [ "CD" ] = "CD" ;
MediaTypes [ "CDr" ] = "CD-R" ;
2014-08-15 00:25:58 +00:00
MediaTypes [ "CDV" ] = "CDV" ;
2014-08-15 00:23:51 +00:00
MediaTypes [ "CD+G" ] = "CD+G" ;
2012-06-08 23:58:47 +00:00
MediaTypes [ "Cylinder" ] = "Wax Cylinder" ;
MediaTypes [ "DAT" ] = "DAT" ;
MediaTypes [ "Datassette" ] = "Other" ;
MediaTypes [ "DCC" ] = "DCC" ;
MediaTypes [ "DVD" ] = "DVD" ;
MediaTypes [ "DVDr" ] = "DVD" ;
2014-08-15 00:23:51 +00:00
MediaTypes [ "DVD-Audio" ] = "DVD-Audio" ;
MediaTypes [ "DVD-Video" ] = "DVD-Video" ;
2012-06-08 23:58:47 +00:00
MediaTypes [ "Edison Disc" ] = "Vinyl" ;
MediaTypes [ "File" ] = "Digital Media" ;
MediaTypes [ "Flexi-disc" ] = "Vinyl" ;
2014-08-15 00:25:58 +00:00
MediaTypes [ "Floppy Disk" ] = "Other" ;
2014-08-15 00:23:51 +00:00
MediaTypes [ "HDCD" ] = "HDCD" ;
2012-06-08 23:58:47 +00:00
MediaTypes [ "HD DVD" ] = "HD-DVD" ;
MediaTypes [ "HD DVD-R" ] = "HD-DVD" ;
MediaTypes [ "Hybrid" ] = "Other" ;
MediaTypes [ "Laserdisc" ] = "LaserDisc" ;
2014-08-15 04:04:41 +00:00
MediaTypes [ "Memory Stick" ] = "Other" ;
2012-06-08 23:58:47 +00:00
MediaTypes [ "Microcassette" ] = "Other" ;
MediaTypes [ "Minidisc" ] = "MiniDisc" ;
MediaTypes [ "MVD" ] = "Other" ;
MediaTypes [ "Reel-To-Reel" ] = "Reel-to-reel" ;
MediaTypes [ "SelectaVision" ] = "Other" ;
MediaTypes [ "Shellac" ] = "Vinyl" ;
2014-08-15 00:23:51 +00:00
MediaTypes [ "SVCD" ] = "SVCD" ;
2012-06-08 23:58:47 +00:00
MediaTypes [ "UMD" ] = "UMD" ;
2014-08-15 00:23:51 +00:00
MediaTypes [ "VCD" ] = "VCD" ;
2012-06-08 23:58:47 +00:00
MediaTypes [ "VHS" ] = "VHS" ;
MediaTypes [ "Video 2000" ] = "Other" ;
MediaTypes [ "Vinyl" ] = "Vinyl" ;
MediaTypes [ '7"' ] = '7" Vinyl' ;
MediaTypes [ '10"' ] = '10" Vinyl' ;
MediaTypes [ '12"' ] = '12" Vinyl' ;
var Countries = new Array ( ) ;
Countries [ "Afghanistan" ] = "AF" ;
Countries [ "Albania" ] = "AL" ;
Countries [ "Algeria" ] = "DZ" ;
Countries [ "American Samoa" ] = "AS" ;
Countries [ "Andorra" ] = "AD" ;
Countries [ "Angola" ] = "AO" ;
Countries [ "Anguilla" ] = "AI" ;
Countries [ "Antarctica" ] = "AQ" ;
Countries [ "Antigua and Barbuda" ] = "AG" ;
Countries [ "Argentina" ] = "AR" ;
Countries [ "Armenia" ] = "AM" ;
Countries [ "Aruba" ] = "AW" ;
Countries [ "Australia" ] = "AU" ;
Countries [ "Austria" ] = "AT" ;
Countries [ "Azerbaijan" ] = "AZ" ;
Countries [ "Bahamas" ] = "BS" ;
Countries [ "Bahrain" ] = "BH" ;
Countries [ "Bangladesh" ] = "BD" ;
Countries [ "Barbados" ] = "BB" ;
Countries [ "Belarus" ] = "BY" ;
Countries [ "Belgium" ] = "BE" ;
Countries [ "Belize" ] = "BZ" ;
Countries [ "Benin" ] = "BJ" ;
Countries [ "Bermuda" ] = "BM" ;
Countries [ "Bhutan" ] = "BT" ;
Countries [ "Bolivia" ] = "BO" ;
Countries [ "Croatia" ] = "HR" ;
Countries [ "Botswana" ] = "BW" ;
Countries [ "Bouvet Island" ] = "BV" ;
Countries [ "Brazil" ] = "BR" ;
Countries [ "British Indian Ocean Territory" ] = "IO" ;
Countries [ "Brunei Darussalam" ] = "BN" ;
Countries [ "Bulgaria" ] = "BG" ;
Countries [ "Burkina Faso" ] = "BF" ;
Countries [ "Burundi" ] = "BI" ;
Countries [ "Cambodia" ] = "KH" ;
Countries [ "Cameroon" ] = "CM" ;
Countries [ "Canada" ] = "CA" ;
Countries [ "Cape Verde" ] = "CV" ;
Countries [ "Cayman Islands" ] = "KY" ;
Countries [ "Central African Republic" ] = "CF" ;
Countries [ "Chad" ] = "TD" ;
Countries [ "Chile" ] = "CL" ;
Countries [ "China" ] = "CN" ;
Countries [ "Christmas Island" ] = "CX" ;
Countries [ "Cocos (Keeling) Islands" ] = "CC" ;
Countries [ "Colombia" ] = "CO" ;
Countries [ "Comoros" ] = "KM" ;
Countries [ "Congo" ] = "CG" ;
Countries [ "Cook Islands" ] = "CK" ;
Countries [ "Costa Rica" ] = "CR" ;
Countries [ "Virgin Islands, British" ] = "VG" ;
Countries [ "Cuba" ] = "CU" ;
Countries [ "Cyprus" ] = "CY" ;
Countries [ "Czech Republic" ] = "CZ" ;
Countries [ "Denmark" ] = "DK" ;
Countries [ "Djibouti" ] = "DJ" ;
Countries [ "Dominica" ] = "DM" ;
Countries [ "Dominican Republic" ] = "DO" ;
Countries [ "Ecuador" ] = "EC" ;
Countries [ "Egypt" ] = "EG" ;
Countries [ "El Salvador" ] = "SV" ;
Countries [ "Equatorial Guinea" ] = "GQ" ;
Countries [ "Eritrea" ] = "ER" ;
Countries [ "Estonia" ] = "EE" ;
Countries [ "Ethiopia" ] = "ET" ;
Countries [ "Falkland Islands (Malvinas)" ] = "FK" ;
Countries [ "Faroe Islands" ] = "FO" ;
Countries [ "Fiji" ] = "FJ" ;
Countries [ "Finland" ] = "FI" ;
Countries [ "France" ] = "FR" ;
Countries [ "French Guiana" ] = "GF" ;
Countries [ "French Polynesia" ] = "PF" ;
Countries [ "French Southern Territories" ] = "TF" ;
Countries [ "Gabon" ] = "GA" ;
Countries [ "Gambia" ] = "GM" ;
Countries [ "Georgia" ] = "GE" ;
Countries [ "Germany" ] = "DE" ;
Countries [ "Ghana" ] = "GH" ;
Countries [ "Gibraltar" ] = "GI" ;
Countries [ "Greece" ] = "GR" ;
Countries [ "Greenland" ] = "GL" ;
Countries [ "Grenada" ] = "GD" ;
Countries [ "Guadeloupe" ] = "GP" ;
Countries [ "Guam" ] = "GU" ;
Countries [ "Guatemala" ] = "GT" ;
Countries [ "Guinea" ] = "GN" ;
Countries [ "Guinea-Bissau" ] = "GW" ;
Countries [ "Guyana" ] = "GY" ;
Countries [ "Haiti" ] = "HT" ;
Countries [ "Virgin Islands, U.S." ] = "VI" ;
Countries [ "Honduras" ] = "HN" ;
Countries [ "Hong Kong" ] = "HK" ;
Countries [ "Hungary" ] = "HU" ;
Countries [ "Iceland" ] = "IS" ;
Countries [ "India" ] = "IN" ;
Countries [ "Indonesia" ] = "ID" ;
Countries [ "Wallis and Futuna" ] = "WF" ;
Countries [ "Iraq" ] = "IQ" ;
Countries [ "Ireland" ] = "IE" ;
Countries [ "Israel" ] = "IL" ;
Countries [ "Italy" ] = "IT" ;
Countries [ "Jamaica" ] = "JM" ;
Countries [ "Japan" ] = "JP" ;
Countries [ "Jordan" ] = "JO" ;
Countries [ "Kazakhstan" ] = "KZ" ;
Countries [ "Kenya" ] = "KE" ;
Countries [ "Kiribati" ] = "KI" ;
Countries [ "Kuwait" ] = "KW" ;
Countries [ "Kyrgyzstan" ] = "KG" ;
Countries [ "Lao People's Democratic Republic" ] = "LA" ;
Countries [ "Latvia" ] = "LV" ;
Countries [ "Lebanon" ] = "LB" ;
Countries [ "Lesotho" ] = "LS" ;
Countries [ "Liberia" ] = "LR" ;
Countries [ "Libyan Arab Jamahiriya" ] = "LY" ;
Countries [ "Liechtenstein" ] = "LI" ;
Countries [ "Lithuania" ] = "LT" ;
Countries [ "Luxembourg" ] = "LU" ;
Countries [ "Montserrat" ] = "MS" ;
Countries [ "Macedonia, The Former Yugoslav Republic of" ] = "MK" ;
Countries [ "Madagascar" ] = "MG" ;
Countries [ "Malawi" ] = "MW" ;
Countries [ "Malaysia" ] = "MY" ;
Countries [ "Maldives" ] = "MV" ;
Countries [ "Mali" ] = "ML" ;
Countries [ "Malta" ] = "MT" ;
Countries [ "Marshall Islands" ] = "MH" ;
Countries [ "Martinique" ] = "MQ" ;
Countries [ "Mauritania" ] = "MR" ;
Countries [ "Mauritius" ] = "MU" ;
Countries [ "Mayotte" ] = "YT" ;
Countries [ "Mexico" ] = "MX" ;
Countries [ "Micronesia, Federated States of" ] = "FM" ;
Countries [ "Morocco" ] = "MA" ;
Countries [ "Monaco" ] = "MC" ;
Countries [ "Mongolia" ] = "MN" ;
Countries [ "Mozambique" ] = "MZ" ;
Countries [ "Myanmar" ] = "MM" ;
Countries [ "Namibia" ] = "NA" ;
Countries [ "Nauru" ] = "NR" ;
Countries [ "Nepal" ] = "NP" ;
Countries [ "Netherlands" ] = "NL" ;
Countries [ "Netherlands Antilles" ] = "AN" ;
Countries [ "New Caledonia" ] = "NC" ;
Countries [ "New Zealand" ] = "NZ" ;
Countries [ "Nicaragua" ] = "NI" ;
Countries [ "Niger" ] = "NE" ;
Countries [ "Nigeria" ] = "NG" ;
Countries [ "Niue" ] = "NU" ;
Countries [ "Norfolk Island" ] = "NF" ;
Countries [ "Northern Mariana Islands" ] = "MP" ;
Countries [ "Norway" ] = "NO" ;
Countries [ "Oman" ] = "OM" ;
Countries [ "Pakistan" ] = "PK" ;
Countries [ "Palau" ] = "PW" ;
Countries [ "Panama" ] = "PA" ;
Countries [ "Papua New Guinea" ] = "PG" ;
Countries [ "Paraguay" ] = "PY" ;
Countries [ "Peru" ] = "PE" ;
Countries [ "Philippines" ] = "PH" ;
Countries [ "Pitcairn" ] = "PN" ;
Countries [ "Poland" ] = "PL" ;
Countries [ "Portugal" ] = "PT" ;
Countries [ "Puerto Rico" ] = "PR" ;
Countries [ "Qatar" ] = "QA" ;
Countries [ "Reunion" ] = "RE" ;
Countries [ "Romania" ] = "RO" ;
Countries [ "Russian Federation" ] = "RU" ;
Countries [ "Russia" ] = "RU" ;
Countries [ "Rwanda" ] = "RW" ;
Countries [ "Saint Kitts and Nevis" ] = "KN" ;
Countries [ "Saint Lucia" ] = "LC" ;
Countries [ "Saint Vincent and The Grenadines" ] = "VC" ;
Countries [ "Samoa" ] = "WS" ;
Countries [ "San Marino" ] = "SM" ;
Countries [ "Sao Tome and Principe" ] = "ST" ;
Countries [ "Saudi Arabia" ] = "SA" ;
Countries [ "Senegal" ] = "SN" ;
Countries [ "Seychelles" ] = "SC" ;
Countries [ "Sierra Leone" ] = "SL" ;
Countries [ "Singapore" ] = "SG" ;
Countries [ "Slovenia" ] = "SI" ;
Countries [ "Solomon Islands" ] = "SB" ;
Countries [ "Somalia" ] = "SO" ;
Countries [ "South Africa" ] = "ZA" ;
Countries [ "Spain" ] = "ES" ;
Countries [ "Sri Lanka" ] = "LK" ;
Countries [ "Sudan" ] = "SD" ;
Countries [ "Suriname" ] = "SR" ;
Countries [ "Swaziland" ] = "SZ" ;
Countries [ "Sweden" ] = "SE" ;
Countries [ "Switzerland" ] = "CH" ;
Countries [ "Syrian Arab Republic" ] = "SY" ;
Countries [ "Tajikistan" ] = "TJ" ;
Countries [ "Tanzania, United Republic of" ] = "TZ" ;
Countries [ "Thailand" ] = "TH" ;
Countries [ "Togo" ] = "TG" ;
Countries [ "Tokelau" ] = "TK" ;
Countries [ "Tonga" ] = "TO" ;
Countries [ "Trinidad and Tobago" ] = "TT" ;
Countries [ "Tunisia" ] = "TN" ;
Countries [ "Turkey" ] = "TR" ;
Countries [ "Turkmenistan" ] = "TM" ;
Countries [ "Turks and Caicos Islands" ] = "TC" ;
Countries [ "Tuvalu" ] = "TV" ;
Countries [ "Uganda" ] = "UG" ;
Countries [ "Ukraine" ] = "UA" ;
Countries [ "United Arab Emirates" ] = "AE" ;
Countries [ "UK" ] = "GB" ;
Countries [ "US" ] = "US" ;
Countries [ "United States Minor Outlying Islands" ] = "UM" ;
Countries [ "Uruguay" ] = "UY" ;
Countries [ "Uzbekistan" ] = "UZ" ;
Countries [ "Vanuatu" ] = "VU" ;
Countries [ "Vatican City State (Holy See)" ] = "VA" ;
Countries [ "Venezuela" ] = "VE" ;
Countries [ "Viet Nam" ] = "VN" ;
Countries [ "Western Sahara" ] = "EH" ;
Countries [ "Yemen" ] = "YE" ;
Countries [ "Zambia" ] = "ZM" ;
Countries [ "Zimbabwe" ] = "ZW" ;
Countries [ "Taiwan" ] = "TW" ;
Countries [ "[Worldwide]" ] = "XW" ;
Countries [ "Europe" ] = "XE" ;
Countries [ "Soviet Union (historical, 1922-1991)" ] = "SU" ;
Countries [ "East Germany (historical, 1949-1990)" ] = "XG" ;
Countries [ "Czechoslovakia (historical, 1918-1992)" ] = "XC" ;
Countries [ "Congo, The Democratic Republic of the" ] = "CD" ;
Countries [ "Slovakia" ] = "SK" ;
Countries [ "Bosnia and Herzegovina" ] = "BA" ;
Countries [ "Korea (North), Democratic People's Republic of" ] = "KP" ;
Countries [ "North Korea" ] = "KP" ;
Countries [ "Korea (South), Republic of" ] = "KR" ;
Countries [ "South Korea" ] = "KR" ;
Countries [ "Montenegro" ] = "ME" ;
Countries [ "South Georgia and the South Sandwich Islands" ] = "GS" ;
Countries [ "Palestinian Territory" ] = "PS" ;
Countries [ "Macao" ] = "MO" ;
Countries [ "Timor-Leste" ] = "TL" ;
Countries [ "<85>land Islands" ] = "AX" ;
Countries [ "Guernsey" ] = "GG" ;
Countries [ "Isle of Man" ] = "IM" ;
Countries [ "Jersey" ] = "JE" ;
Countries [ "Serbia" ] = "RS" ;
Countries [ "Saint Barthélemy" ] = "BL" ;
Countries [ "Saint Martin" ] = "MF" ;
Countries [ "Moldova" ] = "MD" ;
Countries [ "Yugoslavia (historical, 1918-2003)" ] = "YU" ;
Countries [ "Serbia and Montenegro (historical, 2003-2006)" ] = "CS" ;
Countries [ "Côte d'Ivoire" ] = "CI" ;
Countries [ "Heard Island and McDonald Islands" ] = "HM" ;
Countries [ "Iran, Islamic Republic of" ] = "IR" ;
Countries [ "Saint Pierre and Miquelon" ] = "PM" ;
Countries [ "Saint Helena" ] = "SH" ;
Countries [ "Svalbard and Jan Mayen" ] = "SJ" ;