/* global $ helper relEditor sidebar */ 'use strict'; // ==UserScript== // @name MusicBrainz edit: Create entity or fill data from wikipedia / wikidata / VIAF / ISNI // @namespace mbz-loujine // @author loujine // @version 2023.3.11 // @downloadURL https://raw.githubusercontent.com/loujine/musicbrainz-scripts/master/mb-edit-create_from_wikidata.user.js // @updateURL https://raw.githubusercontent.com/loujine/musicbrainz-scripts/master/mb-edit-create_from_wikidata.user.js // @supportURL https://github.com/loujine/musicbrainz-scripts // @icon https://raw.githubusercontent.com/loujine/musicbrainz-scripts/master/icon.png // @description musicbrainz.org edit: Create entity or fill data from wikipedia / wikidata / VIAF / ISNI // @compatible firefox+tampermonkey // @license MIT // @require https://raw.githubusercontent.com/loujine/musicbrainz-scripts/master/mbz-loujine-common.js // @include http*://*musicbrainz.org/artist/create* // @include http*://*musicbrainz.org/artist/*/edit // @exclude http*://*musicbrainz.org/artist/*/alias/*/edit // @exclude http*://*musicbrainz.org/artist/*/credit/*/edit // @include http*://*musicbrainz.org/label/create* // @include http*://*musicbrainz.org/label/*/edit // @exclude http*://*musicbrainz.org/label/*/alias/*/edit // @include http*://*musicbrainz.org/place/create* // @include http*://*musicbrainz.org/place/*/edit // @exclude http*://*musicbrainz.org/place/*/alias/*/edit // @include http*://*musicbrainz.org/work/create* // @include http*://*musicbrainz.org/work/*/edit // @exclude http*://*musicbrainz.org/work/*/alias/*/edit // @grant GM_xmlhttpRequest // @connect wikipedia.org // @connect isni.org // @connect oclc.org // @run-at document-end // ==/UserScript== // https://www.wikidata.org/wiki/Wikidata:List_of_properties/Person class WikiDataHelpers { constructor() { this.language = 'en'; this.entities = { person: 5, stringQuartet: 207338, orchestra: 42998, band: 215380, rockBand: 5741069, male: 6581097, female: 6581072, }; this.fields = { type: 'P31', gender: 'P21', citizen: 'P27', coordinates: 'P625', country: 'P495', isni: 'P213', birthDate: 'P569', inceptionDate: 'P571', birthPlace: 'P19', formationLocation: 'P740', deathDate: 'P570', dissolutionDate: 'P576', deathPlace: 'P20', mbidArtist: 'P434', mbidArea: 'P982', mbidPlace: 'P1004', members: 'P527', student: 'P802', teacher: 'P1066', officialWebsite: 'P856', // authorities idVIAF: 'P214', idGND: 'P227', idLoC: 'P244', idWorldCat: 'P244', idBNF: 'P268', idTrove: 'P1315', // databases idIMDB: 'P345', idOL: 'P648', idIMSLP: 'P839', idIDBD: 'P1220', idAllMusic: 'P1728', idMetalArchivesBand: 'P1952', idDiscogs: 'P1953', idMetalArchivesArtist: 'P1989', idSecondHandSongs: 'P2909', idSNAC: 'P3430', idVGMDB: 'P3435', idOperabase: 'P4869', // social media idTwitter: 'P2002', idInstagram: 'P2003', idFacebook: 'P2013', idGenius: 'P2373', idGooglePlus: 'P2847', idMyspace: 'P3265', idWeibo: 'P3579', idPinterest: 'P3836', // other idSpotify: 'P1902', idYoutube: 'P2397', idDeezer: 'P2722', idiTunes: 'P2850', idDailymotion: 'P2942', idSoundCloud: 'P3040', idLastFM: 'P3192', idSongkick: 'P3478', idVimeo: 'P4015', idPatreon: 'P4175', // missing: Tumblr (P3943), Bandcamp (P3283) }; this.urls = { officialWebsite: '', // authorities idVIAF: 'https://viaf.org/viaf/', idGND: 'https://d-nb.info/gnd/', idLoC: 'https://id.loc.gov/authorities/names/', idWorldCat: 'https://www.worldcat.org/identities/lccn-', idBNF: 'http://catalogue.bnf.fr/ark:/12148/cb', idTrove: 'https://nla.gov.au/nla.party-', // databases idIMDB: 'https://www.imdb.com/name/', idOL: 'https://openlibrary.org/works/', idIMSLP: 'https://imslp.org/wiki/', idIDBD: 'https://ibdb.com/person.php?id=', idAllMusic: 'https://www.allmusic.com/artist/', idMetalArchivesBand: 'https://www.metal-archives.com/band.php?id=', idDiscogs: 'https://www.discogs.com/artist/', idMetalArchivesArtist: 'https://www.metal-archives.com/artist.php?id=', idGenius: 'https://genius.com/artists/', idSecondHandSongs: 'https://secondhandsongs.com/artist/', idVGMDB: 'https://vgmdb.net/artist/', idOperabase: 'http://operabase.com/artists/', idSNAC: 'http://snaccooperative.org/ark:/99166/', // social media idTwitter: 'https://twitter.com/', idInstagram: 'https://www.instagram.com/', idFacebook: 'https://www.facebook.com/', idGooglePlus: 'https://plus.google.com/u/0/', idMyspace: 'https://myspace.com/', idWeibo: 'https://weibo.com/', idPinterest: 'https://www.pinterest.com/', // other idSpotify: 'https://open.spotify.com/artist/', idYoutube: 'https://www.youtube.com/channel/', idDeezer: 'https://www.deezer.com/artist/', idiTunes: 'https://itunes.apple.com/artist/', idDailymotion: 'https://www.dailymotion.com/', idSoundCloud: 'https://soundcloud.com/', idLastFM: 'https://www.last.fm/music/', idSongkick: 'https://www.songkick.com/artists/', idVimeo: 'https://vimeo.com/', idPatreon: 'https://www.patreon.com/', }; } existField(entity, field) { return entity.claims[this.fields[field]] !== undefined; } fieldValue(entity, field) { if (entity.claims[this.fields[field]][0].mainsnak.snaktype === 'value') { return entity.claims[this.fields[field]][0].mainsnak.datavalue.value; } // snaktype='somevalue' seems to mean ill-defined/undefined, do not parse return ''; } /* * data: wikidata json for the area * place: wikidata code ('Q90', etc.) */ _fillArea(data, place, nodeId, lang) { const entityArea = data.entities[place]; const input = document.getElementById(`id-edit-artist.${nodeId}.name`); if (!entityArea || !input) { // no wikidata data return; } const area = entityArea.labels[lang].value; $('#newFields').append( $('
', {'text': 'You must set the sort name to ' + 'save the edit'}).css('color', 'red') ); } } } setValue(`id-edit-${entityType}.name`, value, callback); } function _fillEntityType(entity, entityType) { let value; const type = libWD.fieldValue(entity, 'type')['numeric-id']; switch (type) { case libWD.entities.person: value = 1; break; case libWD.entities.stringQuartet: case libWD.entities.orchestra: case libWD.entities.band: case libWD.entities.rockBand: value = 2; break; default: value = 0; break; } setValue(`id-edit-${entityType}.type_id`, value); } function _fillEntityGender(entity) { let value; const gender = libWD.fieldValue(entity, 'gender')['numeric-id']; switch (gender) { case libWD.entities.male: value = 1; break; case libWD.entities.female: value = 2; break; default: value = 3; break; } setValue('id-edit-artist.gender_id', value); } // eslint-disable-next-line complexity function _fillFormFromWikidata(entity, entityType) { let lang = libWD.language; let field; let input; if (!(lang in entity.labels)) { lang = Object.keys(entity.labels)[0]; } // name and sort name _fillEntityName(entity.labels[lang].value, entityType); // for places: Coordinates if (libWD.existField(entity, 'coordinates')) { input = document.getElementById('id-edit-place.coordinates'); const coord = libWD.fieldValue(entity, 'coordinates'); input.value = coord.latitude + ', ' + coord.longitude; } // Type and gender if (libWD.existField(entity, 'type')) { _fillEntityType(entity, entityType); } if (libWD.existField(entity, 'gender')) { _fillEntityGender(entity); } // Area // we need to fetch the wikidata entry of the different areas to // check if a musicbrainz MBID already exists if ( libWD.existField(entity, 'citizen') || libWD.existField(entity, 'country') ) { field = libWD.existField(entity, 'citizen') ? 'citizen' : 'country'; libWD.fillArea(entity, field, 'area', lang); } // ISNI if (entityType === 'artist' && libWD.existField(entity, 'isni')) { fillISNI(libWD.fieldValue(entity, 'isni')); } // Dates & places if ( libWD.existField(entity, 'birthDate') || libWD.existField(entity, 'inceptionDate') ) { field = libWD.existField(entity, 'birthDate') ? 'birthDate' : 'inceptionDate'; libWD.fillDate(entity, entityType, field, 'begin_date'); } if ( libWD.existField(entity, 'birthPlace') || libWD.existField(entity, 'formationLocation') ) { field = libWD.existField(entity, 'birthPlace') ? 'birthPlace' : 'formationLocation'; libWD.fillArea(entity, field, 'begin_area', lang); } if ( libWD.existField(entity, 'deathDate') || libWD.existField(entity, 'dissolutionDate') ) { field = libWD.existField(entity, 'deathDate') ? 'deathDate' : 'dissolutionDate'; libWD.fillDate(entity, entityType, field, 'end_date'); } if (libWD.existField(entity, 'deathPlace')) { libWD.fillArea(entity, 'deathPlace', 'end_area', lang); } const existingDomains = _existingDomains(); for (const [externalLink, url] of Object.entries(libWD.urls)) { const domain = url.split('/')[2]; if (!libWD.existField(entity, externalLink)) { continue; } const fullUrl = url + libWD.fieldValue(entity, externalLink); if ( (domain && !existingDomains.includes(domain)) || // official website (!domain && !existingDomains.includes(fullUrl.split('/')[2])) ) { _fillExternalLinks(fullUrl); } } for (const role of ['student', 'teacher']) { if (libWD.existField(entity, role)) { libWD.request(libWD.fieldValue(entity, role).id, data => { const name = data.labels[lang].value; $('#newFields').append( $('
',
{'text': 'The request to ISNI website timed out'}).css('color', 'red')
);
},
onload: resp => {
fillISNI(isniURL.split('/')[3]);
let rgx = new RegExp(`href="(.*?musicbrainz.org.*?)"`).exec(resp.responseText);
if (rgx.length) {
// eslint-disable-next-line no-alert
if (window.confirm(
'An entity already exists linked to this ISNI id, ' +
'click "ok" to redirect to their page')) {
window.location.href = rgx[1];
}
}
for (const site of [
'catalogue.bnf.fr', 'd-nb.info', 'wikidata.org', 'id.loc.gov', 'viaf.org'
]) {
rgx = new RegExp(`href="(.*?${site}.*?)"`).exec(resp.responseText);
if (rgx.length) {
fillExternalLinks(rgx[1]);
}
}
rgx = new RegExp(
/Name:.*? Add a wkipedia/wikidata/VIAF/ISNI link here
to retrieve automatically some information.Add external link
`);
document.getElementById('loujine-menu').style.marginLeft = '550px';
})();
$(document).ready(function () {
if (!helper.isUserLoggedIn()) {
return false;
}
const node = document.getElementById('linkParser');
node.addEventListener('input', () => {
node.value = node.value.trim();
if (!node.value) {
return;
}
const domain = node.value.split('/')[2];
node.style.backgroundColor = '#bbffbb';
if (domain === "www.wikidata.org") {
fillExternalLinks(node.value);
fillFormFromWikidata(node.value.match(/\/(Q\d+)\b/)[1]);
} else if (domain.includes("wikipedia.org")) {
GM_xmlhttpRequest({
method: "GET",
url: node.value,
timeout: 1000,
onload: function(resp) {
const parser = new DOMParser();
const doc = parser.parseFromString(resp.responseText, 'text/html');
const link = doc.querySelector('#p-tb a[href*="www.wikidata.org"]');
fillExternalLinks(link.href);
fillFormFromWikidata(link.href.match(/\/(Q\d+)\b/)[1]);
}
});
} else if (domain === "viaf.org") {
node.value = node.value.replace(/http:/g, 'https:');
if (!node.value.endsWith('/')) {
node.value += '/';
}
fillFormFromVIAF(node.value);
} else if (domain.includes("isni.org")) {
node.value = node.value.replace(/http:/g, 'https:');
node.value = node.value.replace(/isni\//g, '');
fillFormFromISNI(node.value);
} else {
node.style.backgroundColor = '#ffaaaa';
}
}, false);
return false;
});
// test data:
// https://www.wikidata.org/wiki/Q11331342
// https://www.wikidata.org/wiki/Special:EntityPage/Q5383 wikipedia link
// https://www.wikidata.org/wiki/Q1277689 invalid date with precision=10 (Y+M)
// https://www.wikidata.org/wiki/Q3290108 invalid date with precision=9 (year)
// https://www.wikidata.org/wiki/Q3193910 invalid date with precision=7
// https://www.wikidata.org/wiki/Q732552 unknown value date of birth
// import viaf
// https://viaf.org/viaf/44485204/
// https://viaf.org/viaf/80111787/
// https://viaf.org/viaf/176025900/ work
// bnf
// http://catalogue.bnf.fr/ark:/12148/cb13894801b.unimarc
// 103 .. $a 19161019 19851014
// test data for places:
// https://www.wikidata.org/wiki/Q2303621
// test data for works:
// https://www.wikidata.org/wiki/Q31745949
// isni
// http://www.isni.org/isni/0000000073684002 person
// http://www.isni.org/0000000120191498 orchestra