// ==UserScript==
// @name Import Loot releases to MusicBrainz
// @description Add a button to import Loot.co.za releases to MusicBrainz
// @version 2019.1.5.1
// @namespace https://github.com/murdos/musicbrainz-userscripts
// @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/loot_importer.user.js
// @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/loot_importer.user.js
// @include http*://www.loot.co.za/product/*
// @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);
var DEBUG = false;
//DEBUG = true;
if (DEBUG) {
LOGGER.setLevel('debug');
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* Test cases:
* - http://www.loot.co.za/product/jakkie-en-daai-band-louw-klein-karoo-cowboy/mgyv-565-g540
* - http://www.loot.co.za/product/various-artists-30-30-goue-sokkie-treffers-volume-17/hbhf-3088-g440
* - http://www.loot.co.za/product/jacques-de-coning-veels-geluk/lzmg-572-g610
* - http://www.loot.co.za/product/various-artists-vat-5-volume-5/dfnc-3405-g1a0
* - http://www.loot.co.za/product/bette-midler-a-gift-of-love/mhgm-3483-g060 *** NOT WORKING *** extra tab
*/
$(document).ready(function () {
LOGGER.info('Document Ready & Loot Userscript executing');
let LootRelease = ParseLootPage();
insertMBSection(LootRelease);
});
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Insert MusicBrainz section into Loot page //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function insertMbUI(mbUI) {
LOGGER.debug('insertMbUI Firing');
let e;
if ((e = $('#thumbs')) && e.length) {
e.after(mbUI);
} else if ((e = $('#productContent')) && e.length) {
e.before(mbUI);
} else if ((e = $('div.buyNow')) && e.length) {
e.before(mbUI);
}
}
// Insert links to high res image in Loot page
function insertIMGlinks() {
let imghref = $('#imagePreview0 a.fancybox').attr('href');
imghref = `http://static.loot.co.za/${imghref}`;
LOGGER.debug('insertIMGlink Firing', imghref);
$('#imagePreview0').append(`
MB High Res Image
`);
}
// Insert links in Loot page
function insertMBSection(release) {
LOGGER.debug('insertMBsection Firing');
let mbUI = $('MusicBrainz
').hide();
if (DEBUG)
mbUI.css({
border: '1px dotted red',
});
let mbContentBlock = $('');
mbUI.append(mbContentBlock);
if (release.maybe_buggy) {
let warning_buggy = $(
'Warning: this release has perhaps a buggy title, please check twice the data you import.
${MBImport.buildFormHTML(parameters)}${MBImport.buildSearchButton(release)}`;
mbContentBlock.append(innerHTML);
insertMbUI(mbUI);
insertIMGlinks();
$('#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();
}
function parseReleaseDate(rdate) {
let months = {
January: 1,
February: 2,
March: 3,
April: 4,
May: 5,
June: 6,
July: 7,
August: 8,
September: 9,
October: 10,
November: 11,
December: 12,
};
let m = rdate.match(/([a-zA-Z]+) (\d{4})/i);
if (m) {
return {
year: m[2],
month: months[m[1]],
};
}
return false;
}
// Analyze Loot data and return a release object
function ParseLootPage() {
LOGGER.debug('ParseLootPage function firing');
let releasebarcode = '';
let releasecountry = '';
let releasedaterel = '';
let releaselanguage = '';
let releasetitle = '';
let releaseartist = '';
let prodlabels = [];
let release_artist_array = [];
let release_format = '';
let release_maybe_buggy = false;
// div#productContent table tbody tr.productOverview td.productInfo h1
let AlbumName = document.querySelectorAll('div#productContent > table > tbody > tr.productOverview > td.productInfo > *');
releaseartist = AlbumName[1].innerText;
if (releaseartist == 'Various Artists') {
// Everything is: title(format)
releaseartisttitle_regex = /(.*?)\((.*)\)/; //match external parenthesis
if (AlbumName[0].innerText.match(releaseartisttitle_regex)) {
releaseartisttitle = AlbumName[0].innerText.match(releaseartisttitle_regex);
releasetitle = releaseartisttitle[1].trim();
release_format = releaseartisttitle[2];
} else {
LOGGER.debug(
'Release Title for Various Artist album does not match the name convention. Hint: Change releaseartisttitle regex for Compilations'
);
release_maybe_buggy = true;
releasetitle = '';
release_format = '';
}
} else {
// artist - title(format)
releaseartisttitle_regex = /(.*) (-|–) (.*?)\((.*)\)/;
if (AlbumName[0].innerText.match(releaseartisttitle_regex)) {
releaseartisttitle = AlbumName[0].innerText.match(releaseartisttitle_regex);
releasetitle = releaseartisttitle[3].trim();
releaseartist = releaseartisttitle[1];
release_format = releaseartisttitle[4];
} else {
LOGGER.debug(
'Release Title for Various Artist album does not match the name convention. Hint: Change releaseartisttitle regex for non Compilations'
);
release_maybe_buggy = true;
releasetitle = '';
releaseartist = '';
release_format = '';
}
}
LOGGER.debug('Release Title:', releasetitle, ' Release Artist:', releaseartist, ' Release Format:', release_format);
// extract all tr from table with class productDetails
$('table.productDetails tr').each(function () {
// get text from first td, trim and convert it to lowercase
let prodinfolabellowcase = $(this).children('td').eq(0).text().trim().toLowerCase();
prodinfolabellowcase = prodinfolabellowcase.replace(/\s+/g, ''); //removing white spaces as switch isnt matching spaces for some reason
// get test from second td, which is the corresponding value
let value = $(this).children('td').eq(1).text().trim();
// now compare and process
switch (prodinfolabellowcase) {
case 'label:': // use these cases to select the spesific text values
prodlabels.push({
name: value,
});
break;
case 'releasedate:':
releasedaterel = value;
LOGGER.debug(' ** release date: **', releasedaterel);
break;
case 'countryoforigin:':
releasecountry = value;
LOGGER.debug(' ** country of origin: **', releasecountry);
break;
case 'performers:':
LOGGER.debug(' ** performers: **', value);
release_artist_array.push({
name: value,
});
break;
case 'format:':
LOGGER.debug(' ** format: **');
break;
case 'categories:':
//LOGGER.debug(" ** categories: **", value);
if ($('table.productDetails tr td a:contains("Afrikaans")').length) {
LOGGER.debug('Language Afrikaans exists');
releaselanguage = 'Afrikaans';
}
if ($('table.productDetails tr td a:contains("South Africa")').length) {
LOGGER.debug('Country South Africa exists in catagories');
releasecountry = 'South Africa';
}
break;
}
});
// Select all data in the "Tracks" div id = tab-2
let allinfolist = document.querySelectorAll('div#tab-2 > table.productDetails > tbody');
LOGGER.debug('Track Info: (allinfolist)', allinfolist);
// Select the Disc names
let disccount = document.querySelectorAll('div#tab-2 > h3');
LOGGER.debug('Amount of discs: ', disccount.length);
let descriptionarray = [];
for (let disciterate = 0; disciterate < disccount.length; disciterate++) {
LOGGER.debug(disciterate);
let tracklisting = allinfolist[disciterate].getElementsByTagName('tr');
LOGGER.debug(' The Table: (tracklisting)', tracklisting);
for (let trackiterate = 0; trackiterate < tracklisting.length; trackiterate++) {
descriptiontrack = new Object();
let currenttrack = tracklisting[trackiterate].querySelectorAll('td');
// var artisttitle_regex = /(.*) - (.*)/; // regex: artist - title
var artisttitle_regex = /(.*) (-|–) (.*)/; // regex: artist - title char 45 or 8211
// need to check if this can be replaced with single regex for now check artist-title if
// not matching check just title
if (currenttrack[1].innerText.match(artisttitle_regex)) {
var artisttitle = currenttrack[1].innerText.match(artisttitle_regex);
descriptiontrack.title = artisttitle[3];
descriptiontrack.artist = artisttitle[1];
} else {
var artisttitle_regex = /(.*)/; // regex: title
var artisttitle = currenttrack[1].innerText.match(artisttitle_regex);
descriptiontrack.title = artisttitle[1];
descriptiontrack.artist = releaseartist;
}
descriptiontrack.disc = disciterate + 1;
descriptiontrack.track = parseInt(currenttrack[0].innerText);
descriptionarray.push(descriptiontrack);
}
}
// Discs
let disclistarray = new Array(); // create the tracklist array to use later
for (let desc_discs = 0; desc_discs < disccount.length; desc_discs++) {
let tracklistarray = new Array();
for (let desc__track = 0; desc__track < descriptionarray.length; desc__track++) {
let desc_currentdiscnumber = descriptionarray[desc__track].disc;
if (desc_currentdiscnumber == desc_discs + 1) {
let track = new Object();
let track_artist_credit = new Array();
track.number = descriptionarray[desc__track].track;
track.title = descriptionarray[desc__track].title;
let track_artist_credit_object = new Object();
track_artist_credit_object.artist_name = descriptionarray[desc__track].artist;
track_artist_credit.push(track_artist_credit_object);
track.artist_credit = track_artist_credit;
tracklistarray.push(track);
}
}
disclistarray.push(tracklistarray);
}
//LOGGER.debug(disclistarray);
release = new Object();
// Check if anything is untoward and highlight to importer
release.maybe_buggy = release_maybe_buggy;
// Release artist credit
release.artist_credit = new Array();
let artist_name = releaseartist;
let various_artists = releaseartist == 'Various Artists';
if (various_artists) {
release.artist_credit = [MBImport.specialArtist('various_artists')];
} else {
release.artist_credit = MBImport.makeArtistCredits([artist_name]);
}
// Release title
release.title = releasetitle;
// Release Barcode
release.barcode = releasebarcode;
// Default status is official
release.status = 'official';
// Other hard-coded info
release.script = 'Latn';
release.country = Countries[releasecountry];
release.language = Languages[releaselanguage];
release.discs = new Array();
for (let l = 0; l < disccount.length; l++) {
let disc = {
position: l + 1,
format: release_format,
tracks: disclistarray[l],
};
release.discs.push(disc);
}
release.labels = prodlabels;
// Release URL
release.urls = new Array();
release.urls.push({
url: window.location.href,
link_type: MBImport.URL_TYPES.purchase_for_mail_order,
});
// TODO check format then change purchase medium
// Release date
let parsed_releaseDate = parseReleaseDate(releasedaterel);
if (parsed_releaseDate) {
release.year = parsed_releaseDate.year;
release.month = parsed_releaseDate.month;
release.day = parsed_releaseDate.day;
}
LOGGER.info('Release:', release);
return release;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Loot -> MusicBrainz mapping //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var Languages = new Array();
Languages['Afrikaans'] = 'afr';
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';