2012-03-28 22:16:10 +00:00
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// MusicBrainz Import helper functions
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/*
|
2015-01-18 12:34:10 +00:00
|
|
|
|
* How to use this module?
|
|
|
|
|
*
|
|
|
|
|
* - First build a release object (see expected format below) that you'll fill in from source of data
|
|
|
|
|
* - Call as follows, e.g.:
|
|
|
|
|
* var parameters = MBReleaseImportHelper.buildFormParameters(parsedRelease, optionalEditNote);
|
|
|
|
|
* - Then build the HTML that you'll inject into source site page:
|
|
|
|
|
* var formHtml = MBReleaseImportHelper.buildFormHTML(parameters);
|
|
|
|
|
* - Addinionally, you can inject a search link to verify that the release is not already known by MusicBrainz:
|
|
|
|
|
* var linkHtml = MBReleaseImportHelper.buildSearchLink(parsedRelease);
|
|
|
|
|
*
|
|
|
|
|
* Expected format of release object:
|
|
|
|
|
*
|
|
|
|
|
* release = {
|
|
|
|
|
* title,
|
|
|
|
|
* artist_credit,
|
|
|
|
|
* type,
|
|
|
|
|
* status,
|
|
|
|
|
* language,
|
|
|
|
|
* script,
|
|
|
|
|
* packaging,
|
|
|
|
|
* country,
|
|
|
|
|
* year,
|
|
|
|
|
* month,
|
|
|
|
|
* day,
|
|
|
|
|
* labels = [ { name, mbid, catno }, ... ],
|
|
|
|
|
* barcode,
|
|
|
|
|
* urls = [ {url, link_type }, ... ],
|
|
|
|
|
* discs = [
|
|
|
|
|
* {
|
|
|
|
|
* title,
|
|
|
|
|
* format,
|
|
|
|
|
* tracks = [
|
|
|
|
|
* { number, title, duration, artist_credit },
|
|
|
|
|
* ...
|
|
|
|
|
* ]
|
|
|
|
|
* },
|
|
|
|
|
* ...
|
|
|
|
|
* ],
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* where 'artist_credit' has the following format:
|
|
|
|
|
*
|
|
|
|
|
* artist_credit = [
|
|
|
|
|
* {
|
|
|
|
|
* credited_name,
|
|
|
|
|
* artist_name,
|
|
|
|
|
* artist_mbid,
|
|
|
|
|
* joinphrase
|
|
|
|
|
* },
|
|
|
|
|
* ...
|
|
|
|
|
* ]
|
|
|
|
|
*
|
|
|
|
|
*/
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
|
|
|
|
var MBReleaseImportHelper = (function() {
|
|
|
|
|
|
|
|
|
|
// --------------------------------------- publics ----------------------------------------- //
|
|
|
|
|
|
2015-06-12 19:28:24 +00:00
|
|
|
|
var url_types = {
|
|
|
|
|
purchase_for_download: 74,
|
|
|
|
|
download_for_free: 75,
|
2015-06-12 22:15:20 +00:00
|
|
|
|
discogs: 76,
|
|
|
|
|
purchase_for_mail_order: 79,
|
2015-06-12 22:30:38 +00:00
|
|
|
|
other_databases: 82,
|
2015-06-12 19:28:24 +00:00
|
|
|
|
stream_for_free: 85,
|
2015-06-12 22:15:20 +00:00
|
|
|
|
license: 301
|
2015-06-12 19:28:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-28 22:16:10 +00:00
|
|
|
|
// compute HTML of search link
|
2014-02-21 17:42:25 +00:00
|
|
|
|
function fnBuildSearchLink(release) {
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
var totaltracks = 0;
|
|
|
|
|
for (var i=0; i < release.discs.length; i++) {
|
|
|
|
|
totaltracks += release.discs[i].tracks.length;
|
|
|
|
|
}
|
2012-03-28 22:16:10 +00:00
|
|
|
|
var release_artist = "";
|
|
|
|
|
for (var i=0; i < release.artist_credit.length; i++) {
|
|
|
|
|
var ac = release.artist_credit[i];
|
|
|
|
|
release_artist += ac.artist_name;
|
|
|
|
|
if (typeof ac.joinphrase != 'undefined' && ac.joinphrase != "") {
|
2012-03-28 22:20:52 +00:00
|
|
|
|
release_artist += ac.joinphrase;
|
2012-03-28 22:16:10 +00:00
|
|
|
|
} else {
|
2014-02-21 17:46:29 +00:00
|
|
|
|
if (i != release.artist_credit.length-1) release_artist += ", ";
|
|
|
|
|
}
|
2012-03-28 22:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
var innerHTML = '<a href="http://musicbrainz.org/search?query=artist%3A(' + luceneEscape(release_artist) + ')%20release%3A(' + luceneEscape(release.title) + ')%20tracks%3A(' + totaltracks + ')';
|
2012-03-28 22:16:10 +00:00
|
|
|
|
if(release.country) innerHTML += '%20country:'+release.country;
|
|
|
|
|
innerHTML += '&type=release&advanced=1">Search in MusicBrainz</a>';
|
|
|
|
|
|
|
|
|
|
return innerHTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// compute HTML of import form
|
2014-02-21 17:42:25 +00:00
|
|
|
|
function fnBuildFormHTML(parameters) {
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Build form
|
2015-06-14 12:13:00 +00:00
|
|
|
|
var innerHTML = '<form class="musicbrainz_import" action="//musicbrainz.org/release/add" method="post" target="_blank" accept-charset="UTF-8" charset="' + document.characterSet + '">';
|
2014-02-21 17:46:29 +00:00
|
|
|
|
parameters.forEach(function(parameter) {
|
2012-03-28 22:16:10 +00:00
|
|
|
|
var value = parameter.value + "";
|
2014-02-21 17:46:29 +00:00
|
|
|
|
innerHTML += "<input type='hidden' value='" + value.replace(/'/g,"'") + "' name='" + parameter.name + "'/>";
|
|
|
|
|
});
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2015-06-14 12:11:39 +00:00
|
|
|
|
innerHTML += '<button type="submit">Import into MB</button>';
|
2014-02-21 17:46:29 +00:00
|
|
|
|
innerHTML += '</form>';
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
|
|
|
|
return innerHTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// build form POST parameters that MB is waiting
|
2014-02-21 17:42:25 +00:00
|
|
|
|
function fnBuildFormParameters(release, edit_note) {
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Form parameters
|
|
|
|
|
var parameters = new Array();
|
|
|
|
|
appendParameter(parameters, 'name', release.title);
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Release Artist credits
|
|
|
|
|
buildArtistCreditsFormParameters(parameters, "", release.artist_credit);
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2014-08-14 23:55:30 +00:00
|
|
|
|
if (release["secondary_types"]) {
|
|
|
|
|
for (var i=0; i < release.secondary_types.length; i++) {
|
|
|
|
|
appendParameter(parameters, 'type', release.secondary_types[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-02-21 17:46:29 +00:00
|
|
|
|
appendParameter(parameters, 'status', release.status);
|
|
|
|
|
appendParameter(parameters, 'language', release.language);
|
|
|
|
|
appendParameter(parameters, 'script', release.script);
|
|
|
|
|
appendParameter(parameters, 'packaging', release.packaging);
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2015-06-07 19:48:00 +00:00
|
|
|
|
// ReleaseGroup
|
|
|
|
|
appendParameter(parameters, 'release_group', release.release_group_mbid);
|
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Date + country
|
|
|
|
|
appendParameter(parameters, 'country', release.country);
|
|
|
|
|
if (!isNaN(release.year) && release.year != 0) { appendParameter(parameters, 'date.year', release.year); };
|
|
|
|
|
if (!isNaN(release.month) && release.month != 0) { appendParameter(parameters, 'date.month', release.month); };
|
|
|
|
|
if (!isNaN(release.day) && release.day != 0) { appendParameter(parameters, 'date.day', release.day); };
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
|
|
|
|
// Barcode
|
2014-02-21 18:21:53 +00:00
|
|
|
|
appendParameter(parameters, 'barcode', release.barcode);
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Label + catnos
|
2012-03-28 22:16:10 +00:00
|
|
|
|
for (var i=0; i < release.labels.length; i++) {
|
|
|
|
|
var label = release.labels[i];
|
|
|
|
|
appendParameter(parameters, 'labels.'+i+'.name', label.name);
|
|
|
|
|
appendParameter(parameters, 'labels.'+i+'.mbid', label.mbid);
|
2014-02-21 17:46:29 +00:00
|
|
|
|
if (label.catno != "none") {
|
2012-03-28 22:16:10 +00:00
|
|
|
|
appendParameter(parameters, 'labels.'+i+'.catalog_number', label.catno);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-02-21 17:42:25 +00:00
|
|
|
|
|
2014-02-21 19:04:38 +00:00
|
|
|
|
// URLs
|
|
|
|
|
for (var i=0; i < release.urls.length; i++) {
|
|
|
|
|
var url = release.urls[i];
|
|
|
|
|
appendParameter(parameters, 'urls.'+i+'.url', url.url);
|
|
|
|
|
appendParameter(parameters, 'urls.'+i+'.link_type', url.link_type);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Mediums
|
2015-06-13 02:25:31 +00:00
|
|
|
|
var total_tracks = 0;
|
|
|
|
|
var total_tracks_with_duration = 0;
|
|
|
|
|
var total_duration = 0;
|
2014-02-21 17:46:29 +00:00
|
|
|
|
for (var i=0; i < release.discs.length; i++) {
|
|
|
|
|
var disc = release.discs[i];
|
|
|
|
|
appendParameter(parameters, 'mediums.'+i+'.format', disc.format);
|
|
|
|
|
appendParameter(parameters, 'mediums.'+i+'.name', disc.title);
|
|
|
|
|
|
|
|
|
|
// Tracks
|
|
|
|
|
for (var j=0; j < disc.tracks.length; j++) {
|
|
|
|
|
var track = disc.tracks[j];
|
2015-06-13 02:25:31 +00:00
|
|
|
|
total_tracks++;
|
2014-02-21 17:46:29 +00:00
|
|
|
|
appendParameter(parameters, 'mediums.'+i+'.track.'+j+'.number', track.number);
|
|
|
|
|
appendParameter(parameters, 'mediums.'+i+'.track.'+j+'.name', track.title);
|
2015-06-13 02:25:31 +00:00
|
|
|
|
var tracklength = "?:??";
|
|
|
|
|
var duration_ms = hmsToMilliSeconds(track.duration);
|
|
|
|
|
if (!isNaN(duration_ms)) {
|
|
|
|
|
tracklength = duration_ms;
|
|
|
|
|
total_tracks_with_duration++;
|
|
|
|
|
total_duration += duration_ms;
|
|
|
|
|
}
|
2014-02-21 17:46:29 +00:00
|
|
|
|
appendParameter(parameters, 'mediums.'+i+'.track.'+j+'.length', tracklength);
|
|
|
|
|
|
|
|
|
|
buildArtistCreditsFormParameters(parameters, 'mediums.'+i+'.track.'+j+'.', track.artist_credit);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-03-28 22:16:10 +00:00
|
|
|
|
|
2015-06-13 02:25:31 +00:00
|
|
|
|
// Guess release type if not given
|
|
|
|
|
if (!release.type && release.title && total_tracks == total_tracks_with_duration) {
|
|
|
|
|
release.type = fnGuessReleaseType(release.title, total_tracks, total_duration);
|
|
|
|
|
}
|
|
|
|
|
appendParameter(parameters, 'type', release.type);
|
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
// Add Edit note parameter
|
|
|
|
|
appendParameter(parameters, 'edit_note', edit_note);
|
2014-02-21 17:42:25 +00:00
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
return parameters;
|
2012-03-28 22:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-12 20:01:06 +00:00
|
|
|
|
// Convert a list of artists to a list of artist credits with joinphrases
|
|
|
|
|
function fnArtistCredits(artists_list) {
|
|
|
|
|
var artists = artists_list.map(function(item) { return {artist_name: item}; });
|
|
|
|
|
if (artists.length > 2) {
|
|
|
|
|
var last = artists.pop();
|
|
|
|
|
last.joinphrase = '';
|
|
|
|
|
var prev = artists.pop();
|
|
|
|
|
prev.joinphrase = ' & ';
|
|
|
|
|
for (var i = 0; i < artists.length; i++) {
|
|
|
|
|
artists[i].joinphrase = ', ';
|
|
|
|
|
}
|
|
|
|
|
artists.push(prev);
|
|
|
|
|
artists.push(last);
|
|
|
|
|
} else if (artists.length == 2) {
|
|
|
|
|
artists[0].joinphrase = ' & ';
|
|
|
|
|
}
|
2015-06-13 13:18:04 +00:00
|
|
|
|
var credits = [];
|
|
|
|
|
// re-split artists if featuring or vs
|
|
|
|
|
artists.map(function (item) {
|
|
|
|
|
var c = item.artist_name.replace(/\s*(?:feat\.?|ft\.?|featuring)\s+/gi, ' feat. ');
|
|
|
|
|
c = c.replace(/\s*\(( feat. )([^\)]+)\)/g, '$1$2');
|
|
|
|
|
c = c.replace(/\s+(?:versus|vs\.?)\s+/gi, ' vs. ');
|
|
|
|
|
c = c.replace(/\s+/g, ' ');
|
|
|
|
|
var splitted = c.split(/( feat\. | vs\. )/);
|
|
|
|
|
if (splitted.length == 1) {
|
|
|
|
|
credits.push(item); // nothing to split
|
|
|
|
|
} else {
|
|
|
|
|
var new_items = [];
|
|
|
|
|
var n = 0;
|
|
|
|
|
for (var i = 0; i < splitted.length; i++) {
|
|
|
|
|
if (n && (splitted[i] == ' feat. ' || splitted[i] == ' vs. ')) {
|
|
|
|
|
new_items[n-1].joinphrase = splitted[i];
|
|
|
|
|
} else {
|
|
|
|
|
new_items[n++] = {
|
|
|
|
|
artist_name: splitted[i].trim(),
|
|
|
|
|
joinphrase: ''
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
new_items[n-1].joinphrase = item.joinphrase;
|
|
|
|
|
new_items.map(function (newit) {
|
|
|
|
|
credits.push(newit)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return credits;
|
2015-06-12 20:01:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-13 02:25:31 +00:00
|
|
|
|
// Try to guess release type using number of tracks, title and total duration (in millisecs)
|
|
|
|
|
function fnGuessReleaseType(title, num_tracks, duration_ms) {
|
|
|
|
|
if (num_tracks < 1) return '';
|
2015-06-12 20:40:40 +00:00
|
|
|
|
var has_single = !!title.match(/\bsingle\b/i);
|
|
|
|
|
var has_EP = !!title.match(/\bEP\b/i);
|
|
|
|
|
if (has_single && has_EP) {
|
|
|
|
|
has_single = false;
|
|
|
|
|
has_EP = false;
|
|
|
|
|
}
|
2015-06-13 02:25:31 +00:00
|
|
|
|
var perhaps_single = ((has_single && num_tracks <= 4) || num_tracks <= 2);
|
|
|
|
|
var perhaps_EP = has_EP || (num_tracks > 2 && num_tracks <= 6);
|
|
|
|
|
var perhaps_album = (num_tracks > 8);
|
|
|
|
|
if (isNaN(duration_ms)) {
|
|
|
|
|
// no duration, try to guess with title and number of tracks
|
|
|
|
|
if (perhaps_single && !perhaps_EP && !perhaps_album) return 'single';
|
|
|
|
|
if (!perhaps_single && perhaps_EP && !perhaps_album) return 'EP';
|
|
|
|
|
if (!perhaps_single && !perhaps_EP && perhaps_album) return 'album';
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
var duration_mn = duration_ms / (60*1000);
|
|
|
|
|
if (perhaps_single && duration_mn >= 1 && duration_mn < 7) return 'single';
|
|
|
|
|
if (perhaps_EP && duration_mn > 7 && duration_mn <= 30) return 'EP';
|
|
|
|
|
if (perhaps_album && duration_mn > 30) return 'album';
|
2015-06-12 20:40:40 +00:00
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-13 02:25:31 +00:00
|
|
|
|
// convert HH:MM:SS or MM:SS to milliseconds
|
|
|
|
|
function hmsToMilliSeconds(str) {
|
|
|
|
|
if (typeof str == 'number') return str;
|
|
|
|
|
var t = str.split(':');
|
|
|
|
|
var s = 0;
|
|
|
|
|
var m = 1;
|
|
|
|
|
while (t.length > 0) {
|
|
|
|
|
s += m * parseInt(t.pop(), 10);
|
|
|
|
|
m *= 60;
|
|
|
|
|
}
|
|
|
|
|
return s*1000;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-28 22:16:10 +00:00
|
|
|
|
// --------------------------------------- privates ----------------------------------------- //
|
|
|
|
|
|
|
|
|
|
function appendParameter(parameters, paramName, paramValue) {
|
|
|
|
|
if(!paramValue) return;
|
2014-02-21 17:46:29 +00:00
|
|
|
|
parameters.push( { name: paramName, value: paramValue } );
|
2012-03-28 22:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function luceneEscape(text) {
|
2014-02-21 17:46:29 +00:00
|
|
|
|
var newtext = text.replace(/[-[\]{}()*+?~:\\^!"]/g, "\\$&");
|
|
|
|
|
return newtext.replace("&&", "\&&").replace("||", "\||");
|
2012-03-28 22:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildArtistCreditsFormParameters(parameters, paramPrefix, artist_credit) {
|
|
|
|
|
if(!artist_credit) return;
|
|
|
|
|
for (var i=0; i < artist_credit.length; i++) {
|
|
|
|
|
var ac = artist_credit[i];
|
2014-02-21 17:46:29 +00:00
|
|
|
|
appendParameter(parameters, paramPrefix+'artist_credit.names.'+i+'.name', ac.credited_name);
|
2012-03-28 22:16:10 +00:00
|
|
|
|
appendParameter(parameters, paramPrefix+'artist_credit.names.'+i+'.artist.name', ac.artist_name);
|
2015-06-07 19:48:00 +00:00
|
|
|
|
appendParameter(parameters, paramPrefix+'artist_credit.names.'+i+'.mbid', ac.mbid);
|
2014-02-21 17:46:29 +00:00
|
|
|
|
if (typeof ac.joinphrase != 'undefined' && ac.joinphrase != "") {
|
|
|
|
|
appendParameter(parameters, paramPrefix+'artist_credit.names.'+i+'.join_phrase', ac.joinphrase);
|
2012-03-28 22:16:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------- expose publics here ------------------------------------ //
|
|
|
|
|
|
2014-02-21 17:46:29 +00:00
|
|
|
|
return {
|
2015-06-12 19:28:24 +00:00
|
|
|
|
buildSearchLink: fnBuildSearchLink,
|
|
|
|
|
buildFormHTML: fnBuildFormHTML,
|
|
|
|
|
buildFormParameters: fnBuildFormParameters,
|
2015-06-12 20:01:06 +00:00
|
|
|
|
makeArtistCredits: fnArtistCredits,
|
2015-06-12 20:40:40 +00:00
|
|
|
|
guessReleaseType: fnGuessReleaseType,
|
2015-06-13 02:25:31 +00:00
|
|
|
|
hmsToMilliSeconds: hmsToMilliSeconds,
|
2015-06-12 19:28:24 +00:00
|
|
|
|
URL_TYPES: url_types
|
|
|
|
|
};
|
2012-03-28 22:16:10 +00:00
|
|
|
|
})();
|