// ==UserScript== // @name Import Discogs releases to MusicBrainz // @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) // @version 2016.12.17.0 // @namespace http://userscripts.org/users/22504 // @downloadURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/discogs_importer.user.js // @updateURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/discogs_importer.user.js // @include http*://www.discogs.com/* // @include http*://*.discogs.com/*release/* // @exclude http*://*.discogs.com/*release/*?f=xml* // @exclude http*://www.discogs.com/release/add // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js // @require lib/mbimport.js // @require lib/logger.js // @require lib/mblinks.js // @require lib/mbimportstyle.js // @icon https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/assets/images/Musicbrainz_import_logo.png // ==/UserScript== // prevent JQuery conflicts, see http://wiki.greasespot.net/@grant this.$ = this.jQuery = jQuery.noConflict(true); if (!unsafeWindow) unsafeWindow = window; var DEBUG = false; //DEBUG = true; if (DEBUG) { LOGGER.setLevel('debug'); } //////////////////////////////////////////////////////////////////////////////////////////////////////// /* * Test cases: * - http://www.discogs.com/release/1566223 : Artist credit of tracks contains an ending ',' join phrase */ var mblinks = new MBLinks('DISCOGS_MBLINKS_CACHE', '1'); $(document).ready(function(){ MBImportStyle(); MBSearchItStyle(); var current_page_key = getDiscogsLinkKey(window.location.href.replace(/\?.*$/, '').replace(/#.*$/, '').replace('/master/view/', '/master/')); if (!current_page_key) return; // 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'); // Display links of equivalent MusicBrainz entities insertMBLinks(current_page_key); // 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') { // Discogs Webservice URL var discogsWsUrl = 'https://api.discogs.com/releases/' + current_page_info.id; $.ajax({ url: discogsWsUrl, dataType: 'json', crossDomain: true, success: function (data, textStatus, jqXHR) { LOGGER.debug("Discogs JSON Data from API:", data); try { var release = parseDiscogsRelease(data); insertMBSection(release, current_page_key); } catch (e) { $('div.musicbrainz').remove(); var mbUI = $('
' + e + '
Please report this error, along the current page URL.
Warning: this release has perhaps a buggy tracklist, please check twice the data you import.
'; mbContentBlock.append(innerHTML); insertMbUI(mbUI); $('#mb_buttons').css({ display: 'inline-block', width: '100%' }); $('form.musicbrainz_import').css({width: '49%', display:'inline-block'}); $('form.musicbrainz_import_search').css({'float': 'right'}) $('form.musicbrainz_import > button').css({width: '100%', 'box-sizing': 'border-box'}); mbUI.slideDown(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Parsing of Discogs data // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function cleanup_discogs_artist_credit(obj) { // Fix some odd Discogs release (e.g. http://api.discogs.com/releases/1566223) that have a ',' join phrase after the last artist // Discogs set a join phrase even there's only one artist or when extraartists is set (ie. remix) var last = obj.artist_credit.length-1; if (last == 0 || obj.artist_credit[last].joinphrase == ", ") { obj.artist_credit[last].joinphrase = ""; } } // Returns the name without the numerical suffic Discogs adds as disambiguation // ie. "ABC (123)" -> "ABC" function artistNoNum(artist_name) { return artist_name.replace(/ \(\d+\)$/, ""); } // Parse a US date string and set object properties year, month, day function parse_YYYY_MM_DD(date, obj) { if (!date) return; var m = date.split(/\D+/, 3).map(function (e) { return parseInt(e, 10); }); if (m[0] !== undefined) { obj.year = m[0]; if (m[1] !== undefined) { obj.month = m[1]; if (m[2] !== undefined) { obj.day = m[2]; } } } } // Analyze Discogs data and return a release object function parseDiscogsRelease(data) { var discogsRelease = data; var release = {}; release.discs = []; //buggy tracklist indicator, used to warn user release.maybe_buggy = false; // Release artist credit release.artist_credit = []; $.each(discogsRelease.artists, function(index, artist) { var ac = { 'artist_name': artistNoNum(artist.name), 'credited_name': (artist.anv != "" ? artist.anv : artistNoNum(artist.name)), 'joinphrase': decodeDiscogsJoinphrase(artist.join), 'mbid': MBIDfromUrl(artist.resource_url, 'artist') }; if (artist.id == 194) { // discogs place holder for various ac = MBImport.specialArtist('various_artists', ac); } release.artist_credit.push(ac); }); cleanup_discogs_artist_credit(release); // ReleaseGroup if (discogsRelease.master_url) { release.release_group_mbid = MBIDfromUrl(discogsRelease.master_url, 'master'); } // Release title release.title = discogsRelease.title; // Release date if (discogsRelease.released) { parse_YYYY_MM_DD(discogsRelease.released, release); } // Release country if (discogsRelease.country) { release.country = Countries[discogsRelease.country]; } // Release labels release.labels = []; if (discogsRelease.labels) { $.each(discogsRelease.labels, function(index, label) { var labelinfo = { name: label.name, catno: (label.catno == "none" ? "[none]" : label.catno), mbid: MBIDfromUrl(label.resource_url, 'label') }; release.labels.push(labelinfo); }); } // Release URL release.urls = [ { url: getCleanUrl(discogsRelease.uri, 'release'), link_type: MBImport.URL_TYPES.discogs } ]; // Release format var release_formats = []; release.secondary_types = []; if (discogsRelease.formats.length > 0) { for (var i = 0; i < discogsRelease.formats.length; i++) { // Release format var discogs_format = discogsRelease.formats[i].name; var mb_format = undefined; if (discogs_format in MediaTypes) { mb_format = MediaTypes[discogs_format]; } if (discogsRelease.formats[i].descriptions) { $.each(discogsRelease.formats[i].descriptions, function(index, desc) { if (!(discogs_format in ['Box Set'])) { // Release format: special handling of Vinyl and Shellac 7", 10" and 12" if (desc.match(/7"|10"|12"/) && (discogs_format.concat(desc) in MediaTypes)) mb_format = MediaTypes[discogs_format.concat(desc)]; // Release format: special handling of specific CD/DVD formats if (desc.match(/^VCD|SVCD|CD\+G|HDCD|DVD-Audio|DVD-Video/) && (desc in MediaTypes)) mb_format = MediaTypes[desc]; } // Release format: special handling of Vinyl, LP == 12" (http://www.discogs.com/help/submission-guidelines-release-format.html#LP) if (discogs_format == "Vinyl" && desc == "LP") mb_format = '12" Vinyl'; // Release format: special handling of CD, Mini == 8cm CD if (discogs_format == "CD" && desc == "Mini") mb_format = '8cm CD'; // Release status if (desc.match(/Promo|Smplr/)) release.status = "promotion"; if (desc.match(/Unofficial Release/)) release.status = "bootleg"; // Release type if (desc.match(/Compilation/)) release.secondary_types.push("compilation"); if (desc.match(/^Album/)) release.type = "album"; if (desc.match(/Single(?! Sided)/)) release.type = "single"; if (desc.match(/EP|Mini-Album/)) release.type = "ep"; }); } if (mb_format) { for (var j = 0; j < discogsRelease.formats[i].qty; j++) { release_formats.push(mb_format); } } // Release packaging if (discogsRelease.formats[i].text) { var freetext = discogsRelease.formats[i].text.toLowerCase().replace(/[\s-]/g, ''); if (freetext.match(/cardboard|paper/)) release.packaging = "cardboard/paper sleeve"; else if (freetext.match(/digipak/)) release.packaging = "digipak"; else if (freetext.match(/keepcase/)) release.packaging = "keep case"; else if (freetext.match(/jewel/)) { release.packaging = freetext.match(/slim/) ? "slim jewel case" : "jewel case"; } else if (freetext.match(/gatefold|digisleeve/)) release.packaging = "gatefold cover"; } } } // 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 = []; var heading = ""; var releaseNumber = 1; var lastPosition = 0; $.each(discogsRelease.tracklist, function(index, discogsTrack) { if (discogsTrack.type_ == 'heading') { heading = discogsTrack.title; return; } if (discogsTrack.type_ != 'track' && discogsTrack.type_ != 'index') { return; } var track = new Object(); track.title = discogsTrack.title; track.duration = MBImport.hmsToMilliSeconds(discogsTrack.duration); // MB in milliseconds // Track artist credit track.artist_credit = []; if (discogsTrack.artists) { $.each(discogsTrack.artists, function(index, artist) { var ac = { 'artist_name': artistNoNum(artist.name), 'credited_name': (artist.anv != "" ? artist.anv : artistNoNum(artist.name)), 'joinphrase': decodeDiscogsJoinphrase(artist.join), 'mbid': MBIDfromUrl(artist.resource_url, 'artist') }; track.artist_credit.push(ac); }); cleanup_discogs_artist_credit(track); } // Track position and release number var trackPosition = discogsTrack.position; // Handle sub-tracks if (trackPosition == "" && discogsTrack.sub_tracks) { trackPosition = discogsTrack.sub_tracks[0].position; // Append titles of sub-tracks to main track title var subtrack_titles = []; var subtrack_total_duration = 0; $.each(discogsTrack.sub_tracks, function(subtrack_index, subtrack) { if (subtrack.type_ != 'track') { return; } if (subtrack.duration) { subtrack_total_duration += MBImport.hmsToMilliSeconds(subtrack.duration); } 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(' / '); } if (isNaN(track.duration) && !isNaN(subtrack_total_duration)) { track.duration = subtrack_total_duration; } } // Skip special tracks if (trackPosition.match(/^(?:video|mp3)/i)) { trackPosition = ""; } // Possible track position: // A1 or A => Vinyl or Cassette : guess releaseNumber from vinyl side // 1-1 or 1.1 => releaseNumber.trackNumber // 1 => trackNumber var tmp = trackPosition.match(/(\d+|[A-Z])(?:[\.-]+(\d+))?/i); if (tmp) { tmp[1] = parseInt(tmp[1], 10); var buggyTrackNumber = false; var prevReleaseNumber = releaseNumber; if (Number.isInteger(tmp[1])) { if (tmp[2]) { // 1-1, 1-2, 2-1, ... - we can get release number and track number from this releaseNumber = tmp[1]; lastPosition = parseInt(tmp[2], 10); } else if (tmp[1] <= lastPosition) { // 1, 2, 3, ... - We've moved onto a new medium releaseNumber++; lastPosition = tmp[1]; } else { lastPosition = tmp[1]; } } else { if (trackPosition.match(/^[A-Z]\d*$/i)) { // Vinyl or cassette, handle it specially // A,B -> 1; C,D -> 2; E,F -> 3, etc... releaseNumber = ((32|trackPosition.charCodeAt(0))-97>>1)+1; lastPosition++; } else if (trackPosition.match(/^[A-Z]+\d*$/i)) { // Vinyl or cassette, handle it specially // something like AA1, exemple : http://www.discogs.com/release/73531 // TODO: find a better fix buggyTrackNumber = true; } } if (releaseNumber > release_formats.length) { // something went wrong in track position parsing buggyTrackNumber = true; releaseNumber = prevReleaseNumber; } if (buggyTrackNumber) { // well, it went wrong so ... lastPosition++; } } // Create release if needed var discindex = releaseNumber-1; if (!release.discs[discindex]) { var newdisc = { tracks: [], format: release_formats[discindex], }; if (heading) { newdisc.title = heading; heading = ""; } release.discs.push(newdisc); } // Track number (only for Vinyl and Cassette) if (buggyTrackNumber || (release.discs[discindex].format.match(/(Vinyl|Cassette)/) && discogsTrack.position.match(/^[A-Z]+[\.-]?\d*/i))) { track.number = discogsTrack.position; } // Trackposition is empty e.g. for release title if (trackPosition != "" && trackPosition != null) { release.discs[discindex].tracks.push(track); } if (buggyTrackNumber && !release.maybe_buggy) { release.maybe_buggy = true; } }); if (release.discs.length == 1 && release.discs[0].title) { // remove title if there is only one disc // https://github.com/murdos/musicbrainz-userscripts/issues/69 release.discs[0].title = ''; } LOGGER.info("Parsed release: ", release); 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; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Discogs -> MusicBrainz mapping // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var MediaTypes = { "8-Track Cartridge": "Cartridge", "Acetate": "Vinyl", "Betamax": "Betamax", "Blu-ray": "Blu-ray", "Blu-ray-R": "Blu-ray", "Cassette": "Cassette", "CD": "CD", "CDr": "CD-R", "CDV": "CDV", "CD+G": "CD+G", "Cylinder": "Wax Cylinder", "DAT": "DAT", "Datassette": "Other", "DCC": "DCC", "DVD": "DVD", "DVDr": "DVD", "DVD-Audio": "DVD-Audio", "DVD-Video": "DVD-Video", "Edison Disc": "Vinyl", "File": "Digital Media", "Flexi-disc": "Vinyl", "Floppy Disk": "Other", "HDCD": "HDCD", "HD DVD": "HD-DVD", "HD DVD-R": "HD-DVD", "Hybrid": "Other", "Laserdisc": "LaserDisc", "Memory Stick": "Other", "Microcassette": "Other", "Minidisc": "MiniDisc", "MVD": "Other", "Reel-To-Reel": "Reel-to-reel", "SelectaVision": "Other", "Shellac": "Shellac", 'Shellac7"': '7" Shellac', 'Shellac10"': '10" Shellac', 'Shellac12"': '12" Shellac', "SVCD": "SVCD", "UMD": "UMD", "VCD": "VCD", "VHS": "VHS", "Video 2000": "Other", "Vinyl": "Vinyl", 'Vinyl7"': '7" Vinyl', 'Vinyl10"': '10" Vinyl', 'Vinyl12"': '12" Vinyl' }; var Countries = { "Afghanistan": "AF", "Albania": "AL", "Algeria": "DZ", "American Samoa": "AS", "Andorra": "AD", "Angola": "AO", "Anguilla": "AI", "Antarctica": "AQ", "Antigua and Barbuda": "AG", "Argentina": "AR", "Armenia": "AM", "Aruba": "AW", "Australia": "AU", "Austria": "AT", "Azerbaijan": "AZ", "Bahamas": "BS", "Bahrain": "BH", "Bangladesh": "BD", "Barbados": "BB", "Belarus": "BY", "Belgium": "BE", "Belize": "BZ", "Benin": "BJ", "Bermuda": "BM", "Bhutan": "BT", "Bolivia": "BO", "Croatia": "HR", "Botswana": "BW", "Bouvet Island": "BV", "Brazil": "BR", "British Indian Ocean Territory": "IO", "Brunei Darussalam": "BN", "Bulgaria": "BG", "Burkina Faso": "BF", "Burundi": "BI", "Cambodia": "KH", "Cameroon": "CM", "Canada": "CA", "Cape Verde": "CV", "Cayman Islands": "KY", "Central African Republic": "CF", "Chad": "TD", "Chile": "CL", "China": "CN", "Christmas Island": "CX", "Cocos (Keeling) Islands": "CC", "Colombia": "CO", "Comoros": "KM", "Congo": "CG", "Cook Islands": "CK", "Costa Rica": "CR", "Virgin Islands, British": "VG", "Cuba": "CU", "Cyprus": "CY", "Czech Republic": "CZ", "Denmark": "DK", "Djibouti": "DJ", "Dominica": "DM", "Dominican Republic": "DO", "Ecuador": "EC", "Egypt": "EG", "El Salvador": "SV", "Equatorial Guinea": "GQ", "Eritrea": "ER", "Estonia": "EE", "Ethiopia": "ET", "Falkland Islands (Malvinas)": "FK", "Faroe Islands": "FO", "Fiji": "FJ", "Finland": "FI", "France": "FR", "French Guiana": "GF", "French Polynesia": "PF", "French Southern Territories": "TF", "Gabon": "GA", "Gambia": "GM", "Georgia": "GE", "Germany": "DE", "Ghana": "GH", "Gibraltar": "GI", "Greece": "GR", "Greenland": "GL", "Grenada": "GD", "Guadeloupe": "GP", "Guam": "GU", "Guatemala": "GT", "Guinea": "GN", "Guinea-Bissau": "GW", "Guyana": "GY", "Haiti": "HT", "Virgin Islands, U.S.": "VI", "Honduras": "HN", "Hong Kong": "HK", "Hungary": "HU", "Iceland": "IS", "India": "IN", "Indonesia": "ID", "Wallis and Futuna": "WF", "Iraq": "IQ", "Ireland": "IE", "Israel": "IL", "Italy": "IT", "Jamaica": "JM", "Japan": "JP", "Jordan": "JO", "Kazakhstan": "KZ", "Kenya": "KE", "Kiribati": "KI", "Kuwait": "KW", "Kyrgyzstan": "KG", "Lao People's Democratic Republic": "LA", "Latvia": "LV", "Lebanon": "LB", "Lesotho": "LS", "Liberia": "LR", "Libyan Arab Jamahiriya": "LY", "Liechtenstein": "LI", "Lithuania": "LT", "Luxembourg": "LU", "Montserrat": "MS", "Macedonia, The Former Yugoslav Republic of": "MK", "Madagascar": "MG", "Malawi": "MW", "Malaysia": "MY", "Maldives": "MV", "Mali": "ML", "Malta": "MT", "Marshall Islands": "MH", "Martinique": "MQ", "Mauritania": "MR", "Mauritius": "MU", "Mayotte": "YT", "Mexico": "MX", "Micronesia, Federated States of": "FM", "Morocco": "MA", "Monaco": "MC", "Mongolia": "MN", "Mozambique": "MZ", "Myanmar": "MM", "Namibia": "NA", "Nauru": "NR", "Nepal": "NP", "Netherlands": "NL", "Netherlands Antilles": "AN", "New Caledonia": "NC", "New Zealand": "NZ", "Nicaragua": "NI", "Niger": "NE", "Nigeria": "NG", "Niue": "NU", "Norfolk Island": "NF", "Northern Mariana Islands": "MP", "Norway": "NO", "Oman": "OM", "Pakistan": "PK", "Palau": "PW", "Panama": "PA", "Papua New Guinea": "PG", "Paraguay": "PY", "Peru": "PE", "Philippines": "PH", "Pitcairn": "PN", "Poland": "PL", "Portugal": "PT", "Puerto Rico": "PR", "Qatar": "QA", "Reunion": "RE", "Romania": "RO", "Russian Federation": "RU", "Russia": "RU", "Rwanda": "RW", "Saint Kitts and Nevis": "KN", "Saint Lucia": "LC", "Saint Vincent and The Grenadines": "VC", "Samoa": "WS", "San Marino": "SM", "Sao Tome and Principe": "ST", "Saudi Arabia": "SA", "Senegal": "SN", "Seychelles": "SC", "Sierra Leone": "SL", "Singapore": "SG", "Slovenia": "SI", "Solomon Islands": "SB", "Somalia": "SO", "South Africa": "ZA", "Spain": "ES", "Sri Lanka": "LK", "Sudan": "SD", "Suriname": "SR", "Swaziland": "SZ", "Sweden": "SE", "Switzerland": "CH", "Syrian Arab Republic": "SY", "Tajikistan": "TJ", "Tanzania, United Republic of": "TZ", "Thailand": "TH", "Togo": "TG", "Tokelau": "TK", "Tonga": "TO", "Trinidad and Tobago": "TT", "Tunisia": "TN", "Turkey": "TR", "Turkmenistan": "TM", "Turks and Caicos Islands": "TC", "Tuvalu": "TV", "Uganda": "UG", "Ukraine": "UA", "United Arab Emirates": "AE", "UK": "GB", "US": "US", "United States Minor Outlying Islands": "UM", "Uruguay": "UY", "Uzbekistan": "UZ", "Vanuatu": "VU", "Vatican City State (Holy See)": "VA", "Venezuela": "VE", "Viet Nam": "VN", "Western Sahara": "EH", "Yemen": "YE", "Zambia": "ZM", "Zimbabwe": "ZW", "Taiwan": "TW", "[Worldwide]": "XW", "Europe": "XE", "Soviet Union (historical, 1922-1991)": "SU", "East Germany (historical, 1949-1990)": "XG", "Czechoslovakia (historical, 1918-1992)": "XC", "Congo, The Democratic Republic of the": "CD", "Slovakia": "SK", "Bosnia and Herzegovina": "BA", "Korea (North), Democratic People's Republic of": "KP", "North Korea": "KP", "Korea (South), Republic of": "KR", "South Korea": "KR", "Montenegro": "ME", "South Georgia and the South Sandwich Islands": "GS", "Palestinian Territory": "PS", "Macao": "MO", "Timor-Leste": "TL", "<85>land Islands": "AX", "Guernsey": "GG", "Isle of Man": "IM", "Jersey": "JE", "Serbia": "RS", "Saint Barthélemy": "BL", "Saint Martin": "MF", "Moldova": "MD", "Yugoslavia (historical, 1918-2003)": "YU", "Serbia and Montenegro (historical, 2003-2006)": "CS", "Côte d'Ivoire": "CI", "Heard Island and McDonald Islands": "HM", "Iran, Islamic Republic of": "IR", "Saint Pierre and Miquelon": "PM", "Saint Helena": "SH", "Svalbard and Jan Mayen": "SJ" };