2017-11-11 01:28:11 +00:00
// ==UserScript==
2015-07-18 20:59:15 +00:00
// @name Display shortcut for relationships on MusicBrainz
// @description Display icon shortcut for relationships of release-group, release, recording and work: e.g. Amazon, Discogs, Wikipedia, ... links. This allows to access some relationships without opening the entity page.
2021-08-05 16:25:01 +00:00
// @version 2021.8.5.1
2015-07-18 20:59:15 +00:00
// @author Aurelien Mino <aurelien.mino@gmail.com>
// @licence GPL (http://www.gnu.org/copyleft/gpl.html)
// @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/mb_relationship_shortcuts.user.js
// @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/mb_relationship_shortcuts.user.js
// @include http*://*musicbrainz.org/artist/*
// @include http*://*musicbrainz.org/release-group/*
// @include http*://*musicbrainz.org/label/*
2017-11-11 01:28:11 +00:00
// @require https://code.jquery.com/jquery-3.2.1.min.js
2015-07-18 20:59:15 +00:00
// ==/UserScript==
// Definitions: relations-type and corresponding icons we are going to treat
2021-08-05 15:50:04 +00:00
const relationsIconsURLs = {
2018-11-20 22:18:49 +00:00
url : {
'creative commons licensed download' : 'http://creativecommons.org/favicon.ico' ,
'cover art link' : 'http://www.cdcovers.cc/favicon.ico' ,
2021-08-05 16:25:01 +00:00
// 'http://www.nomy.nu/img/lyrics-icon.gif'
lyrics : ` data:image/gif;base64,R0lGODlhEQARALMAAAAAAP////z8/Onp6dzc3KmpqaGhoZGRkYyMjHx8fP///wAAAAAAAAAAAAAAAAAAACH5BAEAAAoALAAAAAARABEAAARNUBCUqr0JEVnI+GA4EJ0WnGiKTskQGEcsy0YwVK6q2/g7/7Vba6cTumA/Gm9ITBl9yViw10Q9kdEps7o8RqU8EzcwIXlEIrOEgsFoBBEAOw== ` ,
2015-07-18 20:59:15 +00:00
} ,
'release-group' : {
2021-08-05 16:25:01 +00:00
// http://www.amaesingtools.com/images/left_arrow_icon.gif
'single from' : ` data:image/gif;base64,R0lGODlhDwALAJEAAP2ZAZmZmf///wAAACH5BAAAAAAALAAAAAAPAAsAAAIflI+pq2ABY0DAiYmwqOyaCoaHxjHaZp0e9UhQB8dCAQA7 ` ,
2015-07-18 20:59:15 +00:00
} ,
2018-11-20 22:18:49 +00:00
release : {
'part of set' : 'http://web.archive.org/web/20060709091901/http://wiki.musicbrainz.org/-/musicbrainz/img/moin-inter.png' ,
2020-04-05 14:01:21 +00:00
remaster : 'http://web.archive.org/web/20060708200714/http://wiki.musicbrainz.org/-/musicbrainz/img/moin-www.png' ,
} ,
2015-07-18 20:59:15 +00:00
} ;
2021-11-13 22:59:37 +00:00
const urlRelationsIconClasses = {
allmusic : 'allmusic' ,
'amazon asin' : 'amazon' ,
discogs : 'discogs' ,
imdb : 'imdb' ,
secondhandsongs : 'secondhandsongs' ,
vgmdb : 'vgmdb' ,
wikidata : 'wikidata' ,
2017-11-12 02:01:52 +00:00
} ;
2021-11-13 22:59:37 +00:00
const otherDatabasesIconClasses = {
'd-nb.info' : 'dnb' ,
'www.musik-sammler.de' : 'musiksammler' ,
'rateyourmusic.com' : 'rateyourmusic' ,
'www.worldcat.org' : 'worldcat' ,
2021-11-12 12:30:00 +00:00
} ;
2021-11-13 22:59:37 +00:00
const streamingIconClasses = {
'music.amazon.' : 'amazonmusic' ,
'music.apple.com' : 'applemusic' ,
'bandcamp.com' : 'bandcamp' ,
'www.deezer.com' : 'deezer' ,
'itunes.apple.com' : 'itunes' ,
'qobuz.com' : 'qobuz' ,
'soundcloud.com' : 'soundcloud' ,
'open.spotify.com' : 'spotify' ,
'tidal.com' : 'tidal' ,
} ;
function injectShortcutIcon ( mbid , targetUrl , iconClass ) {
if ( ! iconClass ) return ;
$ ( ` # ${ mbid } td.relationships ` ) . append (
` <a href=' ${ targetUrl . replace ( /'/g , ''' ) } '><span class='favicon ${ iconClass } -favicon' /></a> `
) ;
}
function findIconClassOfUrl ( url , iconClassMap ) {
for ( let partialUrl in iconClassMap ) {
if ( url . indexOf ( partialUrl ) != - 1 ) {
return iconClassMap [ partialUrl ] ;
}
}
}
2021-08-05 15:50:04 +00:00
const incOptions = {
2018-11-20 22:18:49 +00:00
'release-group' : [ 'release-group-rels' , 'url-rels' ] ,
release : [ 'release-rels' , 'url-rels' , 'discids' ] ,
recording : [ 'work-rels' ] ,
2020-04-05 14:01:21 +00:00
work : [ 'url-rels' ] ,
2015-07-18 20:59:15 +00:00
} ;
2021-11-13 22:59:37 +00:00
const userscriptCSS = `
td . relationships span . favicon {
display : inline - block ;
width : 16 px ;
height : 16 px ;
vertical - align : middle ;
margin - right : 4 px ;
} ` ;
2015-07-18 20:59:15 +00:00
// prevent JQuery conflicts, see http://wiki.greasespot.net/@grant
this . $ = this . jQuery = jQuery . noConflict ( true ) ;
if ( ! unsafeWindow ) unsafeWindow = window ;
2020-04-05 14:01:21 +00:00
$ ( document ) . ready ( function ( ) {
2015-07-18 20:59:15 +00:00
// Get pageType (label or artist)
2018-11-20 22:18:49 +00:00
let parent = { } ;
let child = { } ;
2021-08-05 15:50:04 +00:00
let m ;
2018-11-20 22:18:49 +00:00
if ( ( m = window . location . href . match ( '/artist/(.{36})[^/]*$' ) ) ) {
2015-07-18 20:59:15 +00:00
parent . type = 'artist' ;
parent . mbid = m [ 1 ] ;
child . type = 'release-group' ;
2018-11-20 22:18:49 +00:00
} else if ( ( m = window . location . href . match ( '/(release-group|label)/(.{36})[^/]*$' ) ) ) {
2015-07-18 20:59:15 +00:00
parent . type = m [ 1 ] ;
parent . mbid = m [ 2 ] ;
child . type = 'release' ;
2018-11-20 22:18:49 +00:00
} else if ( ( m = window . location . href . match ( '/artist/(.{36})/(releases|recordings|works)' ) ) ) {
2015-07-18 20:59:15 +00:00
parent . type = 'artist' ;
parent . mbid = m [ 1 ] ;
child . type = m [ 2 ] . replace ( /s$/ , '' ) ;
} else {
// Not supported
return ;
}
2021-11-13 22:59:37 +00:00
$ ( ` <style id='relationship-shortcuts-userscript-css'> ${ userscriptCSS } </style> ` ) . appendTo ( 'head' ) ;
2018-11-20 22:18:49 +00:00
let mbidRE = /(release|release-group|work)\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/ ;
2015-07-18 20:59:15 +00:00
// Determine target column
2018-11-20 22:18:49 +00:00
let columnindex = 0 ;
2020-04-05 14:01:21 +00:00
$ ( "table.tbl tbody tr[class!='subh']" ) . each ( function ( ) {
2018-11-20 22:18:49 +00:00
$ ( this )
. children ( 'td' )
2020-04-05 14:01:21 +00:00
. each ( function ( ) {
if ( $ ( this ) . find ( 'a' ) . attr ( 'href' ) !== undefined && $ ( this ) . find ( 'a' ) . attr ( 'href' ) . match ( mbidRE ) ) {
2018-11-20 22:18:49 +00:00
return false ;
}
columnindex ++ ;
} ) ;
2015-07-18 20:59:15 +00:00
return false ;
} ) ;
// Set MBID to row in tables to get easiest fastest access
2020-04-05 14:01:21 +00:00
$ ( "table.tbl tr[class!='subh']" ) . each ( function ( ) {
2018-11-20 22:18:49 +00:00
let $tr = $ ( this ) ;
$tr . children ( ` th:eq( ${ columnindex } ) ` ) . after ( "<th style='width: 150px;'>Relationships</th>" ) ;
$tr . children ( ` td:eq( ${ columnindex } ) ` ) . after ( "<td class='relationships'></td>" ) ;
$ ( this )
. find ( 'a' )
2020-04-05 14:01:21 +00:00
. each ( function ( ) {
2018-11-20 22:18:49 +00:00
let href = $ ( this ) . attr ( 'href' ) ;
if ( ( m = href . match ( mbidRE ) ) ) {
$tr . attr ( 'id' , m [ 2 ] ) ;
return false ;
}
} ) ;
2015-07-18 20:59:15 +00:00
} ) ;
2020-03-31 09:56:56 +00:00
// Adapt width of subheader rows by incrementing the colspan of a cell
2020-04-05 19:56:29 +00:00
$ ( 'table.tbl tr.subh' ) . each ( function ( ) {
2020-03-31 10:28:52 +00:00
$ ( this )
. children ( 'th[colspan]' )
2020-04-05 19:56:29 +00:00
. attr ( 'colspan' , function ( index , oldValue ) {
2020-03-31 10:28:52 +00:00
if ( index === 0 ) {
return Number ( oldValue ) + 1 ;
} else {
return oldValue ;
}
} ) ;
2020-03-31 09:56:56 +00:00
} ) ;
2017-04-16 20:07:25 +00:00
// Calculate offset for multi-page lists
2018-11-20 22:18:49 +00:00
let page = 1 ;
if ( ( m = window . location . href . match ( '[?&]page=([0-9]*)' ) ) ) {
2017-11-11 01:28:11 +00:00
page = m [ 1 ] ;
2017-04-16 20:07:25 +00:00
}
2018-11-20 22:18:49 +00:00
let offset = ( page - 1 ) * 100 ;
2017-11-11 01:28:11 +00:00
2015-07-18 20:59:15 +00:00
// Call the MB webservice
2018-11-20 22:18:49 +00:00
let url = ` /ws/2/ ${ child . type } ? ${ parent . type } = ${ parent . mbid } &inc= ${ incOptions [ child . type ] . join ( '+' ) } &limit=100&offset= ${ offset } ` ;
2017-11-11 01:28:11 +00:00
//console.log("MB WS url: " + url);
2015-07-18 20:59:15 +00:00
2020-04-05 14:01:21 +00:00
$ . get ( url , function ( data , textStatus , jqXHR ) {
2015-07-18 20:59:15 +00:00
// Parse each child
2018-11-20 22:18:49 +00:00
$ ( data )
. find ( child . type )
2020-04-05 14:01:21 +00:00
. each ( function ( ) {
2018-11-20 22:18:49 +00:00
let mbid = $ ( this ) . attr ( 'id' ) ;
// URL relationships
$ ( this )
. find ( "relation-list[target-type='url'] relation" )
2020-04-05 14:01:21 +00:00
. each ( function ( ) {
2021-11-13 22:59:37 +00:00
let relType = $ ( this ) . attr ( 'type' ) ;
let targetUrl = $ ( this ) . children ( 'target' ) . text ( ) ;
if ( relType in urlRelationsIconClasses ) {
injectShortcutIcon ( mbid , targetUrl , urlRelationsIconClasses [ relType ] ) ;
} else if ( Object . prototype . hasOwnProperty . call ( relationsIconsURLs . url , relType ) ) {
// Use (data) URLs for custom icons which are not included in MBS (as classes)
2018-11-20 22:18:49 +00:00
$ ( ` # ${ mbid } td.relationships ` ) . append (
2021-11-13 22:59:37 +00:00
` <a href=' ${ targetUrl . replace ( /'/g , ''' ) } '> ` +
` <img style='max-height: 16px;' src=' ${ relationsIconsURLs . url [ relType ] } ' /> ` +
2018-11-20 22:18:49 +00:00
` </a> `
) ;
2021-11-13 22:59:37 +00:00
} else if ( [ 'free streaming' , 'streaming' , 'purchase for download' ] . includes ( relType ) ) {
injectShortcutIcon ( mbid , targetUrl , findIconClassOfUrl ( targetUrl , streamingIconClasses ) ) ;
} else {
// Other database?
injectShortcutIcon ( mbid , targetUrl , findIconClassOfUrl ( targetUrl , otherDatabasesIconClasses ) ) ;
2018-11-20 22:18:49 +00:00
}
} ) ;
// Other relationships
$ ( this )
. find ( "relation-list[target-type!='url']" )
2020-04-05 14:01:21 +00:00
. each ( function ( ) {
let targettype = $ ( this ) . attr ( 'target-type' ) . replace ( 'release_group' , 'release-group' ) ;
2018-11-20 22:18:49 +00:00
let relations = { } ;
if ( relationsIconsURLs [ targettype ] === undefined ) {
return ;
}
$ ( this )
. children ( 'relation' )
2020-04-05 14:01:21 +00:00
. each ( function ( ) {
2018-11-20 22:18:49 +00:00
let reltype = $ ( this ) . attr ( 'type' ) ;
2020-04-05 14:01:21 +00:00
let target = $ ( this ) . children ( 'target' ) . text ( ) ;
2018-11-20 22:18:49 +00:00
let url = targettype == 'url' ? target : ` / ${ targettype } / ${ target } ` ;
2020-03-14 00:43:40 +00:00
if ( Object . prototype . hasOwnProperty . call ( relationsIconsURLs [ targettype ] , reltype ) ) {
if ( ! Object . prototype . hasOwnProperty . call ( relations , reltype ) ) relations [ reltype ] = [ url ] ;
2018-11-20 22:18:49 +00:00
else relations [ reltype ] . push ( url ) ;
}
} ) ;
2020-04-05 14:01:21 +00:00
$ . each ( relations , function ( reltype , urls ) {
2018-11-20 22:18:49 +00:00
let html = '' ;
if ( urls . length < - 1 ) {
html += ` <img src=' ${ relationsIconsURLs [ targettype ] [ reltype ] } ' />( ${ urls . length } ) ` ;
} else {
2020-04-05 14:01:21 +00:00
$ . each ( urls , function ( index , url ) {
2018-11-20 22:18:49 +00:00
html += ` <a href=' ${ url } '><img src=' ${ relationsIconsURLs [ targettype ] [ reltype ] } ' /></a> ` ;
} ) ;
}
$ ( ` # ${ mbid } td.relationships ` ) . append ( html ) ;
2015-07-18 20:59:15 +00:00
} ) ;
2018-11-20 22:18:49 +00:00
} ) ;
2015-07-18 20:59:15 +00:00
} ) ;
} ) ;
} ) ;