2016-10-27 23:43:39 +00:00
|
|
|
/* global $ MBImport */
|
|
|
|
'use strict';
|
|
|
|
var meta = function() {
|
2018-11-20 22:18:49 +00:00
|
|
|
// ==UserScript==
|
|
|
|
// @name Import DG/Decca releases to MusicBrainz
|
|
|
|
// @namespace https://github.com/murdos/musicbrainz-userscripts
|
|
|
|
// @author loujine
|
|
|
|
// @version 2018.2.18.1
|
|
|
|
// @downloadURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/dgdecca_importer.user.js
|
|
|
|
// @updateURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/dgdecca_importer.user.js
|
|
|
|
// @icon https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/assets/images/Musicbrainz_import_logo.png
|
|
|
|
// @description Add a button to import DG/Decca releases to MusicBrainz
|
|
|
|
// @compatible firefox+greasemonkey
|
|
|
|
// @licence CC BY-NC-SA 3.0 (https://creativecommons.org/licenses/by-nc-sa/3.0/)
|
|
|
|
// @include http*://*deutschegrammophon.com/*/cat/*
|
|
|
|
// @include http*://*deccaclassics.com/*/cat/*
|
|
|
|
// @require lib/mbimport.js
|
|
|
|
// @require lib/mbimportstyle.js
|
|
|
|
// @grant none
|
|
|
|
// @run-at document-end
|
|
|
|
// ==/UserScript==
|
2016-10-27 23:43:39 +00:00
|
|
|
};
|
|
|
|
if (meta && meta.toString && (meta = meta.toString())) {
|
2018-11-20 22:18:49 +00:00
|
|
|
var meta = { name: meta.match(/@name\s+(.+)/)[1], version: meta.match(/@version\s+(.+)/)[1] };
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var siteURL = document.URL.split('/')[2].replace('www.', '');
|
|
|
|
|
|
|
|
var months = {
|
2018-11-20 22:18:49 +00:00
|
|
|
'Jan.': 1,
|
|
|
|
'Feb.': 2,
|
|
|
|
'Mar.': 3,
|
|
|
|
'Apr.': 4,
|
|
|
|
May: 5,
|
|
|
|
'Jun.': 6,
|
|
|
|
'Jul.': 7,
|
|
|
|
'Aug.': 8,
|
|
|
|
'Sep.': 9,
|
|
|
|
'Oct.': 10,
|
|
|
|
'Nov.': 11,
|
|
|
|
'Dec.': 12
|
2016-10-27 23:43:39 +00:00
|
|
|
};
|
|
|
|
var labels = {
|
|
|
|
'deutschegrammophon.com': {
|
2018-11-20 22:18:49 +00:00
|
|
|
name: 'Deutsche Grammophon',
|
|
|
|
mbid: '5a584032-dcef-41bb-9f8b-19540116fb1c',
|
|
|
|
catno: document.URL.split('/')[5]
|
2016-10-27 23:43:39 +00:00
|
|
|
},
|
|
|
|
'deccaclassics.com': {
|
2018-11-20 22:18:49 +00:00
|
|
|
name: 'Decca Classics',
|
|
|
|
mbid: '89a9993d-1dad-4445-a3d7-1d8df04f7e7b',
|
|
|
|
catno: document.URL.split('/')[5]
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
2018-11-20 22:18:49 +00:00
|
|
|
};
|
2016-10-27 23:43:39 +00:00
|
|
|
|
2018-11-20 22:45:38 +00:00
|
|
|
var editNote = `Imported from ${document.URL}\n —\nGM script: "${meta.name}" (${meta.version})\n\n`;
|
2016-10-27 23:43:39 +00:00
|
|
|
|
|
|
|
function _clean(s) {
|
|
|
|
return s
|
|
|
|
.replace(' In ', ' in ')
|
|
|
|
.replace('Minor', 'minor')
|
|
|
|
.replace('Major', 'major')
|
|
|
|
.replace('Op.', 'op. ')
|
|
|
|
.replace('No.', 'no. ')
|
|
|
|
.replace(' Flat', '-flat')
|
|
|
|
.replace(' flat', '-flat')
|
|
|
|
.replace(' Sharp', '-sharp')
|
|
|
|
.replace(' sharp', '-sharp')
|
|
|
|
.replace('1. ', 'I. ')
|
|
|
|
.replace('2. ', 'II. ')
|
|
|
|
.replace('3. ', 'III. ')
|
|
|
|
.replace('4. ', 'IV. ')
|
|
|
|
.replace('5. ', 'V. ')
|
|
|
|
.replace('6. ', 'VI. ')
|
|
|
|
.replace('7. ', 'VII. ')
|
|
|
|
.replace('8. ', 'VIII. ')
|
|
|
|
.replace('9. ', 'IX. ')
|
|
|
|
.replace('10. ', 'X. ')
|
|
|
|
.replace(' - ', ': ')
|
|
|
|
.replace(' | ', ': ')
|
|
|
|
.replace('K.', 'K. ') // Mozart
|
2018-11-20 22:18:49 +00:00
|
|
|
.replace('S.', 'S. '); // Liszt
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function extract_release_data() {
|
|
|
|
console.log('extract_release_data');
|
|
|
|
|
|
|
|
function _setTitle() {
|
2018-11-20 22:18:49 +00:00
|
|
|
let title = $('h4')[0].textContent;
|
2016-10-27 23:43:39 +00:00
|
|
|
if ($('div.works').length) {
|
2018-11-20 22:18:49 +00:00
|
|
|
title += ` ${$('div.works')[0]
|
|
|
|
.innerHTML.replace(/<br><br>/g, ' / ')
|
|
|
|
.replace(/<br>/g, ' ')}`;
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
return title;
|
|
|
|
}
|
|
|
|
function _setReleasePerformers() {
|
2018-11-20 22:18:49 +00:00
|
|
|
let list = $('div.artists')[0]
|
|
|
|
.innerHTML.split('<br>')
|
|
|
|
.map(function(artist) {
|
|
|
|
return {
|
|
|
|
credited_name: artist,
|
|
|
|
artist_name: artist,
|
|
|
|
artist_mbid: '',
|
|
|
|
joinphrase: ', '
|
|
|
|
};
|
|
|
|
});
|
2016-10-27 23:43:39 +00:00
|
|
|
list[list.length - 1]['joinphrase'] = '';
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _setReleaseArtists() {
|
2018-11-20 22:18:49 +00:00
|
|
|
let composer = document.getElementsByTagName('h4')[0].textContent;
|
|
|
|
let list = [
|
|
|
|
{
|
|
|
|
credited_name: composer,
|
|
|
|
artist_name: composer,
|
|
|
|
artist_mbid: '',
|
|
|
|
joinphrase: '; '
|
|
|
|
}
|
|
|
|
];
|
2016-10-27 23:43:39 +00:00
|
|
|
return list.concat(_setReleasePerformers());
|
|
|
|
}
|
|
|
|
|
|
|
|
function _indices(array, element) {
|
2018-11-20 22:18:49 +00:00
|
|
|
let indices = [];
|
|
|
|
let idx = array.indexOf(element);
|
2016-10-27 23:43:39 +00:00
|
|
|
while (idx != -1) {
|
|
|
|
indices.push(idx);
|
|
|
|
idx = array.indexOf(element, idx + 1);
|
|
|
|
}
|
|
|
|
return indices;
|
|
|
|
}
|
|
|
|
|
2018-11-20 22:18:49 +00:00
|
|
|
let date = document.getElementsByClassName('date')[0].textContent;
|
2016-10-27 23:43:39 +00:00
|
|
|
date = date.replace('Int. Release ', '').split(' ');
|
2018-11-20 22:18:49 +00:00
|
|
|
let nodes = [];
|
|
|
|
let tracklist_node = document.getElementById('tracklist');
|
2016-10-27 23:43:39 +00:00
|
|
|
|
2018-11-20 22:18:49 +00:00
|
|
|
$('.item,.hier0,.hier1,.hier2,.hier3').each(function(idx, node) {
|
2016-10-27 23:43:39 +00:00
|
|
|
var idx;
|
2018-11-20 22:18:49 +00:00
|
|
|
let d = {};
|
2016-10-27 23:43:39 +00:00
|
|
|
if (node.classList.contains('hier0')) {
|
|
|
|
d['level'] = 0;
|
|
|
|
} else if (node.classList.contains('hier1')) {
|
|
|
|
d['level'] = 1;
|
|
|
|
} else if (node.classList.contains('hier2')) {
|
|
|
|
d['level'] = 2;
|
2016-11-13 04:55:15 +00:00
|
|
|
} else if (node.classList.contains('hier3')) {
|
|
|
|
d['level'] = 3;
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
if (node.parentElement.classList.contains('track-container')) {
|
|
|
|
d['type'] = 'track';
|
|
|
|
} else if (node.parentElement.classList.contains('work-container')) {
|
|
|
|
d['type'] = 'work';
|
|
|
|
} else if (node.parentElement.classList.contains('artists-container')) {
|
|
|
|
d['type'] = 'artist';
|
|
|
|
} else {
|
|
|
|
d['type'] = 'medium';
|
|
|
|
}
|
|
|
|
d['title'] = node.textContent;
|
|
|
|
d['node'] = node.parentElement;
|
|
|
|
nodes.push(d);
|
|
|
|
});
|
|
|
|
console.log(nodes, tracklist_node);
|
|
|
|
|
|
|
|
// complete track titles
|
2018-11-20 22:18:49 +00:00
|
|
|
let header0, header1, header2, idx;
|
|
|
|
nodes.forEach(function(node, idx) {
|
|
|
|
let level = node['level'],
|
2016-10-27 23:43:39 +00:00
|
|
|
type = node['type'],
|
|
|
|
content = node['title'];
|
|
|
|
if (type === 'work') {
|
|
|
|
if (level === 0) {
|
|
|
|
header0 = content;
|
|
|
|
} else if (level === 1) {
|
|
|
|
header1 = content;
|
2016-11-13 04:55:15 +00:00
|
|
|
} else if (level === 2) {
|
|
|
|
header2 = content;
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
} else if (type === 'track') {
|
|
|
|
if (level === 0) {
|
|
|
|
nodes[idx]['title'] = content;
|
|
|
|
} else if (level === 1) {
|
2018-11-20 22:18:49 +00:00
|
|
|
nodes[idx]['title'] = `${header0}: ${content}`;
|
2016-10-27 23:43:39 +00:00
|
|
|
} else if (level === 2) {
|
2018-11-20 22:18:49 +00:00
|
|
|
nodes[idx]['title'] = `${header0}, ${header1}: ${content}`;
|
2016-11-13 04:55:15 +00:00
|
|
|
} else if (level === 3) {
|
2018-11-20 22:18:49 +00:00
|
|
|
nodes[idx]['title'] = `${header0}, ${header1}, ${header2}: ${content}`;
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-11-20 22:18:49 +00:00
|
|
|
let discs = [],
|
2016-10-27 23:43:39 +00:00
|
|
|
tracks = [],
|
|
|
|
medium_title = '';
|
2018-11-20 22:18:49 +00:00
|
|
|
nodes.forEach(function(item, idx) {
|
2016-10-27 23:43:39 +00:00
|
|
|
if (item.type === 'track') {
|
2018-11-20 22:18:49 +00:00
|
|
|
let track = extract_track_data(item.node);
|
2016-10-27 23:43:39 +00:00
|
|
|
track.title = _clean(item.title);
|
|
|
|
tracks.push(track);
|
|
|
|
}
|
|
|
|
if (item.type === 'medium') {
|
|
|
|
if (idx > 0) {
|
|
|
|
discs.push({
|
2018-11-20 22:18:49 +00:00
|
|
|
title: '', // medium_title,
|
|
|
|
format: 'CD',
|
|
|
|
tracks: tracks
|
2016-10-27 23:43:39 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
medium_title = item.title;
|
|
|
|
tracks = [];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// push last medium
|
|
|
|
discs.push({
|
2018-11-20 22:18:49 +00:00
|
|
|
title: '', // nodes[0].title,
|
|
|
|
format: 'CD',
|
|
|
|
tracks: tracks
|
2016-10-27 23:43:39 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
return {
|
2018-11-20 22:18:49 +00:00
|
|
|
title: _setTitle(),
|
|
|
|
artist_credit: _setReleaseArtists(),
|
|
|
|
type: 'Album',
|
|
|
|
status: 'Official',
|
|
|
|
language: 'eng', // 'English',
|
|
|
|
script: 'Latn', // 'Latin',
|
|
|
|
packaging: '',
|
|
|
|
country: '',
|
|
|
|
year: date[2],
|
|
|
|
month: months[date[1]],
|
|
|
|
day: date[0],
|
|
|
|
labels: [labels[siteURL]],
|
|
|
|
barcode: document.getElementById('upc').value.replace('00', ''), // too many 0s
|
|
|
|
urls: [
|
|
|
|
{
|
|
|
|
link_type: 288, // 'discography'
|
|
|
|
url: document.URL
|
|
|
|
}
|
|
|
|
],
|
|
|
|
discs: discs
|
2016-10-27 23:43:39 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function extract_track_data(node) {
|
|
|
|
function _setTrackArtists(artistString) {
|
|
|
|
console.log('artistString', artistString);
|
2018-11-20 22:18:49 +00:00
|
|
|
let artists;
|
2016-10-27 23:43:39 +00:00
|
|
|
if (artistString.includes(' | ')) {
|
2018-11-20 22:18:49 +00:00
|
|
|
artists = artistString.split(' | ').map(function(artist) {
|
2016-10-27 23:43:39 +00:00
|
|
|
return {
|
2018-11-20 22:18:49 +00:00
|
|
|
credited_name: artist.split(',')[0],
|
|
|
|
artist_name: artist.split(',')[0],
|
|
|
|
artist_mbid: '',
|
|
|
|
joinphrase: ', '
|
2016-10-27 23:43:39 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
} else {
|
2018-11-20 22:18:49 +00:00
|
|
|
artists = artistString.split(', ').map(function(artist, idx) {
|
|
|
|
let mbid = '';
|
|
|
|
let url = `/ws/js/artist/?q=${artist}&fmt=json&limit=1`;
|
2016-10-27 23:43:39 +00:00
|
|
|
return {
|
2018-11-20 22:18:49 +00:00
|
|
|
credited_name: artist,
|
|
|
|
artist_name: artist,
|
|
|
|
artist_mbid: mbid,
|
|
|
|
joinphrase: ', '
|
2016-10-27 23:43:39 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
artists[artists.length - 1]['joinphrase'] = '';
|
2018-11-20 22:18:49 +00:00
|
|
|
return artists;
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
|
2018-11-20 22:18:49 +00:00
|
|
|
let schema = {};
|
2016-10-27 23:43:39 +00:00
|
|
|
if (node.querySelectorAll('meta').length) {
|
|
|
|
// https://schema.org/MusicRecording info available
|
2018-11-20 22:18:49 +00:00
|
|
|
for (let item of node.querySelectorAll('meta')) {
|
|
|
|
let attrs = item.attributes;
|
2016-10-27 23:43:39 +00:00
|
|
|
schema[attrs.itemprop.value] = attrs.content.value;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log('no meta data on ', node);
|
|
|
|
schema.name = node.querySelectorAll('div.track-text > a.fancy')[0].textContent;
|
2018-11-20 22:18:49 +00:00
|
|
|
schema.byArtist = $(node)
|
|
|
|
.parent()
|
|
|
|
.nextAll('div.container-container')
|
|
|
|
.children('.artists-container')[0].textContent;
|
|
|
|
let previousComposers = $(node)
|
|
|
|
.parent()
|
|
|
|
.prevAll('div.container-container')
|
|
|
|
.children('.first-composer-container');
|
|
|
|
schema.creator = previousComposers[previousComposers.length - 1].textContent;
|
2016-10-27 23:43:39 +00:00
|
|
|
}
|
|
|
|
console.info('schema', schema);
|
|
|
|
return {
|
2018-11-20 22:18:49 +00:00
|
|
|
number: parseInt(node.querySelectorAll('div.track-no')[0].textContent),
|
|
|
|
title: _clean(schema.name),
|
|
|
|
duration: node.querySelectorAll('div.track-time')[0].textContent,
|
|
|
|
artist_credit: _setTrackArtists(schema.byArtist), // CSG
|
|
|
|
performer: schema.byArtist,
|
|
|
|
composer: schema.creator,
|
|
|
|
url: node.querySelectorAll('div.track-text > a.fancy')[0].href
|
2016-10-27 23:43:39 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert links in page
|
|
|
|
function insertMBSection(release) {
|
2018-11-20 22:18:49 +00:00
|
|
|
let mbUI = $('<div class="section musicbrainz"><h3>MusicBrainz</h3></div>');
|
|
|
|
let mbContentBlock = $('<div class="section_content"></div>');
|
2016-10-27 23:43:39 +00:00
|
|
|
mbUI.append(mbContentBlock);
|
|
|
|
|
|
|
|
// Form parameters
|
2018-11-20 22:18:49 +00:00
|
|
|
let parameters = MBImport.buildFormParameters(release, editNote);
|
2016-10-27 23:43:39 +00:00
|
|
|
|
|
|
|
// Build form + search button
|
2018-11-20 22:18:49 +00:00
|
|
|
let innerHTML = `<div id="mb_buttons">${MBImport.buildFormHTML(parameters)}${MBImport.buildSearchButton(release)}</div>`;
|
2016-10-27 23:43:39 +00:00
|
|
|
mbContentBlock.append(innerHTML);
|
|
|
|
|
|
|
|
$('div#product-text').append(mbUI[0]);
|
|
|
|
|
|
|
|
$('#mb_buttons').css({
|
2018-11-20 22:18:49 +00:00
|
|
|
display: 'inline-block',
|
|
|
|
width: '100%'
|
2016-10-27 23:43:39 +00:00
|
|
|
});
|
2018-11-20 22:18:49 +00:00
|
|
|
$('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' });
|
2016-10-27 23:43:39 +00:00
|
|
|
|
|
|
|
mbUI.slideDown();
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
var release = extract_release_data();
|
|
|
|
insertMBSection(release);
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
throw e;
|
|
|
|
}
|