NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name mb. ALL LINKS
// @version 2026.4.6
// @description Hidden links include fanpage, social network, etc. (NO duplicates) Generated autolinks (configurable) includes plain web search, auto last.fm, Discogs and lyrics searches, etc. Shows begin/end dates on URL and provides edit link. Expands Wikidata links to wikipedia articles.
// @namespace https://github.com/jesus2099/konami-command
// @supportURL https://github.com/jesus2099/konami-command/labels/mb_ALL-LINKS
// @downloadURL https://github.com/jesus2099/konami-command/raw/master/mb_ALL-LINKS.user.js
// @author jesus2099
// @licence CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/
// @licence GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
// @since 2011-08-02; https://web.archive.org/web/20131103162328/userscripts.org/scripts/show/108889 / https://web.archive.org/web/20141011084020/userscripts-mirror.org/scripts/show/108889
// @icon data:image/gif;base64,R0lGODlhEAAQAMIDAAAAAIAAAP8AAP///////////////////yH5BAEKAAQALAAAAAAQABAAAAMuSLrc/jA+QBUFM2iqA2ZAMAiCNpafFZAs64Fr66aqjGbtC4WkHoU+SUVCLBohCQA7
// @require https://github.com/jesus2099/konami-command/raw/de88f870c0e6c633e02f32695e32c4f50329fc3e/lib/SUPER.js?version=2022.3.24.224
// @grant none
// @match *://*.musicbrainz.org/area/*
// @match *://*.musicbrainz.org/artist/*
// @match *://*.musicbrainz.org/event/*
// @match *://*.musicbrainz.org/genre/*
// @match *://*.musicbrainz.org/instrument/*
// @match *://*.musicbrainz.org/label/*
// @match *://*.musicbrainz.org/place/*
// @match *://*.musicbrainz.org/recording/*
// @match *://*.musicbrainz.org/release/*
// @match *://*.musicbrainz.org/release-group/*
// @match *://*.musicbrainz.org/series/*
// @match *://*.musicbrainz.org/url/*
// @match *://*.musicbrainz.org/work/*
// @match *://musicbrainz.eu/area/*
// @match *://musicbrainz.eu/artist/*
// @match *://musicbrainz.eu/event/*
// @match *://musicbrainz.eu/genre/*
// @match *://musicbrainz.eu/instrument/*
// @match *://musicbrainz.eu/label/*
// @match *://musicbrainz.eu/place/*
// @match *://musicbrainz.eu/recording/*
// @match *://musicbrainz.eu/release/*
// @match *://musicbrainz.eu/release-group/*
// @match *://musicbrainz.eu/series/*
// @match *://musicbrainz.eu/url/*
// @match *://musicbrainz.eu/work/*
// @exclude */*/*/*annotat*
// @exclude */*/*/*create*
// @exclude */*/*/*delete*
// @exclude */*/*/*edit*
// @exclude */*/*/*merge*
// @exclude */*/*/*remove*
// @exclude */*/*/*split*
// @exclude */*/*/add-alias*
// @exclude */*/*annotat*
// @exclude */*/*create*
// @exclude */*/*delete*
// @exclude */*/*edit*
// @exclude */*/*merge*
// @exclude */*/*remove*
// @exclude */*/*split*
// @exclude */release/add
// @exclude */release/add?*
// @run-at document-end
// ==/UserScript==
"use strict";
/* hint for Opera 12 users allow opera:config#UserPrefs|Allowscripttolowerwindow and opera:config#UserPrefs|Allowscripttoraisewindow */
const userjs = "jesus2099_all-links";
const nonLatinName = /[\u0384-\u1cf2\u1f00-\uffff]/; // U+2FA1D is currently out of js range
var rawLanguages = JSON.parse(localStorage.getItem(userjs + "_languages")) || ["navigator", "musicbrainz"];
const path_ID_separator = "::::";
// Available tokens:
// - for all entity pages: %entity-type% %entity-mbid% %entity-name%
// - for "that" type entity pages: %that-mbid% %that-name% where "that" is an entity type in the above @include list
// - for artist entity pages: %artist-sort-name% %artist-family-name-first% %artist-latin-script-name%
// - for release entity pages: %release-barcode%
// - for url entity pages: %url-target% (while %entity-name% and %url-name% are deliberately ignored)
const hiddenLinks = {
de: "Versteckte Links",
en: "Hidden links",
fr: "Liens cachés"
};
var webSearchLinks = {
title: {
en: "Search the web",
de: "Web durchsuchen",
fr: "Chercher sur le Web",
nl: "Zoeken op het Web"
},
items: {
webPageSearch: {
title: {en: "Web pages", de: "Webseiten", fr: "Pages Web", nl: "Webpagina’s"},
target: [
"//duckduckgo.com/?q=%22%release-group-artist-credit%%22+%22%release-group-name%%22",
"//duckduckgo.com/?q=%22%release-artist-credit%%22+%22%release-name%%22",
"//duckduckgo.com/?q=%22%entity-name%%22"
]
},
imageSearch: {
title: {en: "Images", de: "Bilder", fr: "Images", nl: "Afbeeldingen"},
target: [
"//duckduckgo.com/?q=%22%release-group-artist-credit%%22+%22%release-group-name%%22+!i",
"//duckduckgo.com/?q=%22%release-artist-credit%%22+%22%release-name%%22+!i",
"//duckduckgo.com/?q=%22%entity-name%%22+!i"
]
},
videoSearch: {
title: {en: "Videos", de: "Videos", fr: "Vidéos", nl: "Video’s"},
target: [
"//duckduckgo.com/?q=%22%release-group-artist-credit%%22+%22%release-group-name%%22+!v",
"//duckduckgo.com/?q=%22%release-artist-credit%%22+%22%release-name%%22+!v",
"//duckduckgo.com/?q=%22%entity-name%%22+!v"
]
},
waybackMachineHistory: {
title: {en: "Archive history", de: "Archivierte Versionen", fr: "Versions archivées", nl: "Archiefgeschiedenis"},
target: "//web.archive.org/web/*/%url-target%"
},
"Lyrics": [
"//duckduckgo.com/?q=intitle%3A%22%recording-name%%22%20%22lyrics%22",
"//duckduckgo.com/?q=intitle%3A%22%work-name%%22%20%22lyrics%22",
],
"Paroles": [
"//duckduckgo.com/?q=intitle%3A%22%recording-name%%22%20%22paroles%22",
"//duckduckgo.com/?q=intitle%3A%22%work-name%%22%20%22paroles%22",
],
"歌詞": [
"//duckduckgo.com/?q=intitle%3A%22%recording-name%%22%20%22歌詞%22",
"//duckduckgo.com/?q=intitle%3A%22%work-name%%22%20%22歌詞%22",
],
}
};
var whitelistSearchLinks = {
title: {
de: "Whitelist durchsuchen",
en: "Search in the whitelist",
fr: "Sites autorisés",
nl: "Zoeken in de witte lijst"
},
items: {
genreDBs: {
title: {
de: "Nach Genre",
en: "By genre",
fr: "Par genre",
nl: "Per Genre"
},
items: {
classical: {
title: {
de: "Klassik",
en: "Classical",
fr: "Classique",
nl: "Klassiek"
},
items: {
// Skipped "Brahms" which has a search dropdown but no search page
// Skipped "Classical Archives" which have an internal JSON search API only
"DRAM": [
"https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%release-group-name%&dram-search[t]=album",
"https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%release-name%&dram-search[t]=album",
"https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%work-name%&dram-search[t]=work",
"https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%recording-name%&dram-search[t]=track",
],
"DRAM (composers)": "https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%artist-name%&dram-search[t]=composer",
"DRAM (performers)": "https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%artist-name%&dram-search[t]=performer",
"DRAM (ensembles)": "https://jesus2099.gitlab.io/forward-request.html?_action=https://www.dramonline.org/search&_method=post&dram-search[q]=%artist-name%&dram-search[t]=ensemble",
"Operabase (composers)": {
"bg cs da de el en es eu fi fr ga hu is it lt lv ja ko mt nl no pl ro ru sk sl sv zh": "https://www.operabase.com/composers/search/%language%?query=%artist-name%"
},
"Operabase (other artists)": {
"bg cs da de el en es eu fi fr ga hu is it lt lv ja ko mt nl no pl ro ru sk sl sv zh": "https://www.operabase.com/artists/search/%language%?query=%artist-name%"
},
"Operabase (festivals)": {
"bg cs da de el en es eu fi fr ga hu is it lt lv ja ko mt nl no pl ro ru sk sl sv zh": "https://www.operabase.com/festivals/search/%language%?query=%event-name%"
},
"Operabase (venues)": {
"bg cs da de el en es eu fi fr ga hu is it lt lv ja ko mt nl no pl ro ru sk sl sv zh": "https://www.operabase.com/venues/search/%language%?query=%place-name%"
},
// Skipped "Operadis" which has no search engine online
// Skipped "Overture/Doremus" which have a currently broken search engine
}
},
electronic: {
title: {
de: "Elektronik",
en: "Eletronic",
fr: "Électronique",
nl: "Elektronisch"
},
items: {
"PsyDB": [
"https://www.psydb.net/search?q=%artist-name%",
"https://www.psydb.net/search?q=%label-name%",
"https://www.psydb.net/search?q=%release-group-name%",
"https://www.psydb.net/search?q=%release-name%"
],
// Skipped "Resident Advisor" which has a search dropdown but no search page
// Skipped "RollDaBeats" which is down since December 2022
}
},
folk: {
title: {
"en de": "Traditional",
fr: "Traditionnelle",
nl: "Traditionele"
},
items: {
"Cape Breton Fiddle Recordings": [
"https://www.cbfiddle.com/rx/tunesearch.cgi?search=%recording-name%",
"https://www.cbfiddle.com/rx/tunesearch.cgi?search=%work-name%"
],
// Skipped "DanceDB" which has no free text search
"Irish Traditional Music Tunes": [
"https://www.irishtune.info/album-search.php?value=%release-group-name%&form=title",
"https://www.irishtune.info/album-search.php?value=%release-name%&form=title",
"https://www.irishtune.info/search.php?lookfor=string&term=%recording-name%&type=any",
"https://www.irishtune.info/search.php?lookfor=string&term=%work-name%&type=any"
],
"Mainly Norfolk": [
"https://jesus2099.gitlab.io/forward-request.html?_action=https://mainlynorfolk.info/folk/records/search.php&_method=post&album=%release-group-name%",
"https://jesus2099.gitlab.io/forward-request.html?_action=https://mainlynorfolk.info/folk/records/search.php&_method=post&album=%release-name%",
"https://jesus2099.gitlab.io/forward-request.html?_action=https://mainlynorfolk.info/folk/songs/search.php&_method=post&song=%recording-name%",
"https://jesus2099.gitlab.io/forward-request.html?_action=https://mainlynorfolk.info/folk/songs/search.php&_method=post&song=%work-name%"
],
// Skipped "The Dance Gypsy" which is down since February 2022
"The Session": [
"https://thesession.org/recordings/search?q=%release-group-name%",
"https://thesession.org/recordings/search?q=%release-name%",
"https://thesession.org/tunes/search?q=%recording-name%",
"https://thesession.org/tunes/search?q=%work-name%"
],
"The Traditional Tune Archive": [
"https://tunearch.org/wiki/Special:Search?search=%artist-name%&fulltext=Dig+deeper&ns844=1&ns3002=1",
"https://tunearch.org/wiki/Special:Search?search=%recording-name%&fulltext=Dig+deeper",
"https://tunearch.org/wiki/Special:Search?search=%work-name%&fulltext=Dig+deeper"
]
}
},
// Skipped "Jazz Music Archives" which have a search dropdown but no search page
metal: {
title: {
"de en nl": "Metal",
fr: "Métal"
},
items: {
"Metal-Archives": [
"https://www.metal-archives.com/search?searchString=%label-name%&type=label_name",
"https://www.metal-archives.com/search?searchString=%release-group-name%&type=album_title",
"https://www.metal-archives.com/search?searchString=%release-name%&type=album_title"
],
"Metal-Archives (aliases)": "https://www.metal-archives.com/search?searchString=%artist-name%&type=artist_alias",
"Metal-Archives (bands)": "https://www.metal-archives.com/search?searchString=%artist-name%&type=band_name",
"Spirit of Metal": [
{
"cn de en es fr pl pt ru": "https://www.spirit-of-metal.com/labels.php?l=%language%&search=%label-name%"
},
{
"cn de en es fr pl pt ru": "https://www.spirit-of-metal.com/places.php?l=%language%&search=%place-name%"
},
{
"cn de en es fr pl pt ru": "https://www.spirit-of-metal.com/albums.php?l=%language%&search=%release-group-name%"
},
{
"cn de en es fr pl pt ru": "https://www.spirit-of-metal.com/albums.php?l=%language%&search=%release-name%"
},
],
"Spirit of Metal (bands)": "https://www.spirit-of-metal.com/liste_groupe.php?recherche_groupe=%artist-name%",
"Spirit of Metal (other artists)": {
"cn de en es fr pl pt ru": "https://www.spirit-of-metal.com/artists.php?l=%language%&search=%artist-name%"
}
}
},
rock: {
title: "Rock",
items: {
"Prog Archives": [
"http://www.progarchives.com/google-search-results.asp?cx=artists&q=%artist-name%",
"http://www.progarchives.com/google-search-results.asp?cx=artists&q=%release-group-name%"
],
"Prog Archives (by barcode)": "http://www.progarchives.com/google-search-results.asp?cx=artists&q=%release-barcode%",
"Prog Archives (by name)": "http://www.progarchives.com/google-search-results.asp?cx=artists&q=%release-name%",
"Spirit of Rock": [
{
"cn de en es fr pl pt ru": "https://www.spirit-of-rock.com/labels.php?l=%language%&search=%label-name%"
},
{
"cn de en es fr pl pt ru": "https://www.spirit-of-rock.com/places.php?l=%language%&search=%place-name%"
},
{
"cn de en es fr pl pt ru": "https://www.spirit-of-rock.com/albums.php?l=%language%&search=%release-group-name%"
},
{
"cn de en es fr pl pt ru": "https://www.spirit-of-rock.com/albums.php?l=%language%&search=%release-name%"
},
],
"Spirit of Rock (bands)": "https://www.spirit-of-rock.com/liste_groupe.php?recherche_groupe=%artist-name%",
"Spirit of Rock (other artists)": {
"cn de en es fr pl pt ru": "https://www.spirit-of-rock.com/artists.php?l=%language%&search=%artist-name%"
}
}
},
soundtrack: {
title: {
"de en": "Soundtrack",
fr: "Bande son",
nl: "Geluidsspoor"
},
items: {
"OverClock ReMix": [
"https://ocremix.org/site-search/?q=%artist-name%",
"https://ocremix.org/site-search/?q=%label-name%",
"https://ocremix.org/site-search/?q=%recording-name%",
"https://ocremix.org/site-search/?q=%release-group-name%",
"https://ocremix.org/site-search/?q=%release-name%",
"https://ocremix.org/site-search/?q=%work-name%"
],
"SoundtrackCollector": [
"https://www.soundtrackcollector.com/catalog/search.php?searchon=composer&searchtext=%artist-name%",
"https://www.soundtrackcollector.com/catalog/search.php?searchon=track&searchtext=%recording-name%",
"https://www.soundtrackcollector.com/catalog/search.php?searchon=title&searchtext=%release-group-name%",
"https://www.soundtrackcollector.com/catalog/search.php?searchon=soundtrack&searchtext=%work-name%",
],
"SoundtrackCollector (by barcode)": "https://www.soundtrackcollector.com/catalog/search.php?searchon=labelnr&searchtext=%release-barcode%",
"SoundtrackCollector (by name)": "https://www.soundtrackcollector.com/catalog/search.php?searchon=title&searchtext=%release-name%"
}
// Skipped "Videogam.in" which is down since 2016/2017
},
theatre: {
title: {
de: "Theater",
en: "Theatre",
fr: "Théâtre",
nl: "Theater"
},
items: {
"CastAlbums.org": [
"https://castalbums.org/search/?search=%artist-name%&type=People",
"https://castalbums.org/search/?search=%release-group-name%&type=Recordings",
"https://castalbums.org/search/?search=%release-name%&type=Recordings"
],
"CastAlbums.org (songs)": [
"https://castalbums.org/search/?search=%recording-name%&type=Songs",
"https://castalbums.org/search/?search=%work-name%&type=Songs"
],
"CastAlbums.org (shows)": "https://castalbums.org/search/?search=%work-name%&type=Shows",
// Skipped "IBDb" which search has a hidden request verification token input
"IOBDb": [
"http://www.iobdb.com/Search?searchText=%artist-name%&searchDomain=CreditableEntity",
"http://www.iobdb.com/Search?searchText=%label-name%&searchDomain=CreditableEntity",
"http://www.iobdb.com/Search?searchText=%place-name%&searchDomain=Theatre",
"http://www.iobdb.com/Search?searchText=%recording-name%&searchDomain=Any",
"http://www.iobdb.com/Search?searchText=%work-name%&searchDomain=Any"
],
"Theatricalia": [
"https://theatricalia.com/search?q=%artist-name%",
"https://theatricalia.com/search?q=%label-name%",
"https://theatricalia.com/search?q=%place-name%",
"https://theatricalia.com/search?q=%recording-name%",
"https://theatricalia.com/search?q=%work-name%"
]
}
},
literature: {
title: {
de: "Literatur",
en: "Literature",
fr: "Littérature",
ja: "文学",
},
items: {
BookBrainz: [
"//bookbrainz.org/search?type=author&q=%artist-name%",
"//bookbrainz.org/search?type=edition&q=%release-name%",
"//bookbrainz.org/search?type=edition_group&q=%release-group-name%",
"//bookbrainz.org/search?type=publisher&q=%label-name%",
"//bookbrainz.org/search?type=series&q=%series-name%",
"//bookbrainz.org/search?type=work&q=%work-name%"
],
"BookBrainz (all entities)": "//bookbrainz.org/search?type=all_entities&q=%entity-name%",
"Open Library": [
"//openlibrary.org/search/authors?q=%artist-name%",
"//openlibrary.org/search?mode=everything&q=%work-name%",
"//openlibrary.org/search?mode=everything&q=%release-name%"
],
LibraryThing: [
"//www.librarything.com/search.php?searchtype=authorname&search=%artist-name%",
"//www.librarything.com/search.php?searchtype=newwork_titles&search=%work-name%",
"//www.librarything.com/search.php?searchtype=nseries&search=%series-name%"
],
Goodreads: [
"//www.goodreads.com/search?utf8=%E2%9C%93&search_type=books&search%5Bfield%5D=author&q=%artist-name%",
"//www.goodreads.com/search?utf8=%E2%9C%93&search_type=books&search%5Bfield%5D=title&q=%release-name%",
"//www.goodreads.com/search?utf8=%E2%9C%93&search_type=books&search%5Bfield%5D=title&q=%work-name%",
"//www.goodreads.com/search?q=%series-name%"
],
// TODO?: Search on first name + last name:
// ORCID: "//orcid.org/orcid-search/search?firstName=%artist-first-name%&lastName=%artist-last-name%&otherFields=true",
ORCID: "https://orcid.org/orcid-search/search?searchQuery=%artist-name%",
"LibriVox (author)": "https://librivox.org/search?search_form=advanced&author=%artist-name%",
"LibriVox (reader)": "https://librivox.org/search?search_form=advanced&reader=%artist-name%",
LibriVox: "https://librivox.org/search?search_form=advanced&title=%release-name%"
}
}
}
},
lyricsDBs: {
title: {
de: "Liedtext",
en: "Lyrics",
fr: "Paroles",
nl: "Liedtekst"
},
items: {
Genius: [
"//genius.com/search?q=%artist-latin-script-name%",
"//genius.com/search?q=%recording-name%",
"//genius.com/search?q=%work-name%"
],
"J-Lyric(歌手名)": "//j-lyric.net/index.php?ka=%artist-name%",
"J-Lyric(曲名)": [
"//j-lyric.net/index.php?kt=%recording-name%",
"//j-lyric.net/index.php?kt=%work-name%"
]
}
},
scoreDBs: {
title: {
de: "Partitur",
en: "Score",
fr: "Partitions",
nl: "Bladmuziek"
},
items: {
"IMSLP/Petrucci Music Library": "//duckduckgo.com/?q=site:imslp.org+%22%work-name%%22"
}
},
regionalDBs: {
title: {
de: "Nach Gebiet",
en: "By area",
fr: "Par région",
nl: "Per Gebied"
},
items: {
JP: {
title: {
fr: "Japon",
en: "Japan"
},
items: {
"Amazon JP (cat)": "//amazon.jp/s/?url=search-alias%3Dpopular&field-keywords=%release-catalogue-number%",
"Amazon JP (bars)": "//amazon.jp/s/?url=search-alias%3Dpopular&field-keywords=%release-barcode%",
VGMdb: [
"//vgmdb.net/search?type=artist&q=%artist-name%",
"//vgmdb.net/search?type=album&q=%release-group-name%",
"//vgmdb.net/search?type=album&q=%release-name%",
"//vgmdb.net/search?type=org&q=%label-name%",
],
VKDB: "//duckduckgo.com/?q=site:vkdb.jp+%22%artist-name%%22"
}
},
KR: {
title: {
fr: "Corée",
en: "Korea"
},
items: {
maniadb: "http://www.maniadb.com/search/%artist-name%/?sr=P"
}
},
DE: {
title: {
de: "Deutschland",
en: "Germany",
fr: "Allemagne",
nl: "Duitsland"
},
items: {
"Musik-Sammler.de": [
"https://www.musik-sammler.de/search/%artist-name%/?q=artist",
"https://www.musik-sammler.de/search/%release-name%/?q=medium",
"https://www.musik-sammler.de/search/%release-group-name%/?q=album"
],
"DNB - Deutsches Musikarchiv": {de: "https://portal.dnb.de/opac.htm?query=%28mat%3DMusic+OR+cod%3Dmt%29+AND+%release-name%&method=simpleSearch&cqlMode=true"}
}
},
FR: {
title: {
de: "Frankreich",
en: "France",
fr: "France",
nl: "Frankrijk"
},
items: {
"Encyclopédisque": [
"//jesus2099.gitlab.io/forward-request.html?_accept-charset=ISO-8859-15&_action=//www.encyclopedisque.fr/recherche.html%23resultat&ra=%artist-latin-script-name%&sp=1",
"//jesus2099.gitlab.io/forward-request.html?_accept-charset=ISO-8859-15&_action=//www.encyclopedisque.fr/recherche.html%23resultat&rd=%release-name%&sp=1"
]
}
},
"CA-QC": {
title: "Québec",
items: {
"Québec Info Musique": [
// TODO: make it work with "=" in title: https://musicbrainz.org/release-group/22d4bc68-c5f3-4e53-ab07-07d5920bbee1
"http://jesus2099.gitlab.io/forward-request.html?_action=http://quebecinfomusique.com/artistes/artiste.asp&_accept-charset=ISO-8859-1&search=%artist-name%",
"http://jesus2099.gitlab.io/forward-request.html?_action=http://quebecinfomusique.com/albums/albums.asp&_accept-charset=ISO-8859-1&search=%release-name%",
"http://jesus2099.gitlab.io/forward-request.html?_action=http://quebecinfomusique.com/albums/albums.asp&_accept-charset=ISO-8859-1&search=%release-group-name%",
]
}
},
NL: {
title: {
de: "Niederlande",
en: "Netherlands",
fr: "Pays-Bas",
ja: "オランダ",
nl: "Nederland"
},
items: {
"Muziekweb": [
"https://www.muziekweb.nl/en/Muziekweb/Cat/SingleSearch/Search?q=%artist-name%",
"https://www.muziekweb.nl/en/Muziekweb/Cat/SingleSearch/Search?q=%label-name%",
"https://www.muziekweb.nl/en/Muziekweb/Cat/SingleSearch/Search?q=%release-name%",
"https://www.muziekweb.nl/en/Muziekweb/Cat/SingleSearch/Search?q=%recording-name%",
"https://www.muziekweb.nl/en/Muziekweb/Cat/SingleSearch/Search?q=%work-name%"
]
}
},
SE: {
title: {
de: "Schweden",
en: "Sweden",
fr: "Suède",
ja: "スウェーデン",
nl: "Zweden",
sv: "Sverige"
},
items: {
"Svensk Mediedatabas (SMDB)": [
"//smdb.kb.se/catalog/search?q=namn%3A%28%artist-family-name-first%%29",
"//smdb.kb.se/catalog/search?q=%release-name%",
],
"Svensk Mediedatabas (cat. no.)": "//smdb.kb.se/catalog/search?q=%release-catalogue-number%",
}
},
VN: {
title: "Việt Nam",
items: {
"Wikipedia (vi)": "//vi.wikipedia.org/w?search=%entity-name%"
}
}
}
},
shops: {
title: {
fr: "Boutiques en ligne",
en: "Online shops",
},
items: {
"Amazon (barcode)": "https://www.amazon.com/s?k=%release-barcode%",
Bandcamp: "https://bandcamp.com/search?q=%artist-name%",
Deezer: "https://www.deezer.com/search/%artist-name%",
SoundCloud: "https://soundcloud.com/search/people?q=%artist-name%",
Spotify: "https://open.spotify.com/search/%artist-name%",
"Spotify (barcode)": "//open.spotify.com/search/upc:%release-barcode%",
},
},
socialNetworks: {
title: {
de: "Soziale Netzwerke",
fr: "Réseaux sociaux",
en: "Social networks"
},
items: {
Facebook: "https://www.facebook.com/search/pages/?q=%artist-name%",
Twitter: "https://twitter.com/search?f=users&q=%artist-name%",
YouTube: "https://www.youtube.com/results?search_query=%artist-name%&sp=EgIQAg%253D%253D"
},
},
otherDBs: {
title: {
de: "Andere Datenbanken",
en: "Other databases",
fr: "Autres bases de données",
nl: "Andere databases"
},
items: {
AllMusic: {
target: [
"//www.allmusic.com/search/artists/%artist-name%",
"//www.allmusic.com/search/labels/%label-name%",
"//www.allmusic.com/search/songs/%recording-name%",
"//www.allmusic.com/search/all/%release-name%",
"//www.allmusic.com/search/albums/%release-group-name%",
"//www.allmusic.com/search/compositions/%work-name%"
]
},
Discogs: [
"//www.discogs.com/%language%/search?q=%artist-name%&type=artist",
"//www.discogs.com/%language%/search?title=%release-name%&type=release",
"//www.discogs.com/%language%/search?title=%release-group-name%&type=release",
"//www.discogs.com/%language%/search?q=%label-name%&type=label"
],
"Discogs (artist credit)": [
"//www.discogs.com/%language%/search?title=%release-name%&artist=%release-artist-credit%&type=release",
"//www.discogs.com/%language%/search?title=%release-group-name%&artist=%release-group-artist-credit%&type=release"
],
"Discogs (barcode)": "//www.discogs.com/%language%/search/?q=%release-barcode%&type=release",
MusicMoz: "//musicmoz.org/search/search.cgi?search=%entity-name%",
"Dynamic Range DB": "//dr.loudness-war.info/?artist=%release-artist-credit%&album=%release-name%",
GeoNames: [
"http://www.geonames.org/search.html?q=%area-name%",
"http://www.geonames.org/advanced-search.html?q=%place-name%&featureClass=S"
],
IMDb: "//www.imdb.com/find?q=%artist-name%&s=nm",
TMDB: "//www.themoviedb.org/search/person?query=%artist-name%",
IMVDb: [
"//imvdb.com/search?search_term=%artist-name%",
"//imvdb.com/search?search_term=%label-name%",
"//imvdb.com/search?search_term=%recording-name%",
// TODO: implement %recording-artist-credit% like %release-artist-credit% for better search below
// "//imvdb.com/search?search_term=%recording-name% %recording-artist-credit%",
"//imvdb.com/search?search_term=%work-name%"
],
ISNI: "//isni.oclc.org/xslt/CMD?ACT=SRCHA&IKT=8006&TRM=%artist-name%",
VIAF: "//viaf.org/viaf/search?query=local.names+all+%22%artist-name%%22",
"Last.fm (MBID)": {
"en": "//last.fm/mbid/%artist-mbid%",
"de es fr it ja pl pt ru sv tr zh": "//last.fm/%language%/mbid/%artist-mbid%"
},
lastfmName: {
title: {en: "Last.fm (name)", de: "Last.fm (Name)", es: "Last.fm (nombre)", fr: "Last.fm (nom)", it: "Last.fm (Nome)", ja: "Last.fm (名)", pl: "Last.fm (Nazwa)", pt: "Last.fm (nome)", ru: "Last.fm (имя)", sv: "Last.fm (namn)", tr: "Last.fm (ad)", zh: "Last.fm (名)"},
target: {
"en": "//last.fm/search?q=%artist-name%",
"de es fr it ja pl pt ru sv tr zh": "//last.fm/%language%/search?q=%artist-name%"
}
},
"Rate Your Music": [
"//rateyourmusic.com/search?searchtype=a&searchterm=%artist-name%",
"//rateyourmusic.com/search?searchtype=b&searchterm=%label-name%",
"//rateyourmusic.com/search?searchtype=l&searchterm=%release-name%",
"//rateyourmusic.com/search?searchtype=r&searchterm=%work-name%"
],
SecondHandSongs: [
"//secondhandsongs.com/search/artist?op_commonName=contains&commonName=%artist-name%&op_type=equals&display=commonName.type&sort=simplifiedCommonName",
"//secondhandsongs.com/search/label?op_name=contains&name=%label-name%&display=name&sort=simplifiedName",
"//secondhandsongs.com/search/performance?op_title=contains&title=%recording-name%&op_performer=contains&display=title.performer&sort=simplifiedTitle",
"//secondhandsongs.com/search/release?op_title=contains&title=%release-name%&op_performer=contains&display=title.performer&sort=simplifiedTitle",
"//secondhandsongs.com/search/work?op_title=contains&title=%work-name%&op_credits=contains&display=title.credits&sort=simplifiedTitle"
],
"setlist.fm": "//www.setlist.fm/search?query=%artist-name%",
WhoSampled: [
"//www.whosampled.com/search/artists/?q=%artist-name%",
"//www.whosampled.com/search/tracks/?q=%recording-name%",
"//www.whosampled.com/search/tracks/?q=%work-name%"
],
Wikidata: "//www.wikidata.org/w?search=%entity-name%",
Wikipedia: "//duckduckgo.com/?q=site:wikipedia.org+intitle%3A%22%entity-name%%22",
LocalWikipedia: {
title: "Wikipedia (%language%)",
target: "//%language%.wikipedia.org/w?search=%entity-name%"
}
}
}
}
};
var additionalSearchLinks = {
title: {
de: "Weiter suchen",
en: "Search further",
fr: "Chercher plus loin",
nl: "Zoeken verder naar"
},
items: {
regionalDBs: {
title: {
de: "Nach Gebiet",
en: "By area",
fr: "Par région",
nl: "Per Gebied"
},
items: {
FR: {
title: {
de: "Frankreich",
en: "France",
fr: "France",
nl: "Frankrijk"
},
items: {
SACEM: [
{
fr: "//repertoire.sacem.fr/resultats?filters=titles&query=%work-name%#searchBtn",
"de en nl": "//repertoire.sacem.fr/en/results?filters=titles&query=%work-name%#searchBtn"
},
{
fr: "//repertoire.sacem.fr/resultats?filters=titles&query=%recording-name%#searchBtn",
"de en nl": "//repertoire.sacem.fr/en/results?filters=titles&query=%recording-name%#searchBtn"
},
{
fr: "//repertoire.sacem.fr/resultats?filters=parties&query=%artist-latin-script-name%#searchBtn",
"de en nl": "//repertoire.sacem.fr/en/results?filters=parties&query=%artist-latin-script-name%#searchBtn"
},
{
fr: "//repertoire.sacem.fr/resultats?filters=parties&query=%label-name%#searchBtn",
"de en nl": "//repertoire.sacem.fr/en/results?filters=parties&query=%label-name%#searchBtn"
}
]
}
},
JP: {
title: {
en: "Japan",
fr: "Japon",
ja: "日本"
},
items: {
CDJournal: [
"//www.cdjournal.com/search/do/?k=%artist-name%&target=a",
"//www.cdjournal.com/search/do/?k=%release-group-name%&target=cd",
"//www.cdjournal.com/search/do/?k=%release-name%&target=cd",
],
JASRAC: "//jesus2099.gitlab.io/forward-request.html?_accept-charset=Shift_JIS&_method=post&_action=//www2.jasrac.or.jp/eJwid/main%3FtrxID%3DA00401-3%23result&IN_DEFAULT_WORKS_KOUHO_MAX=100&IN_DEFAULT_WORKS_KOUHO_SEQ=1&IN_WORKS_TITLE_NAME1=%recording-name%&IN_WORKS_TITLE_CONDITION=1&IN_DEFAULT_SEARCH_WORKS_NAIGAI=0&RESULT_CURRENT_PAGE=1",
"MINC(アーティスト名・作家名)": "//www.minc.or.jp/artist/list/?nm=%artist-name%",
"MINC(CD商品タイトル)": [
"//www.minc.or.jp/product/list/?tl=%release-group-name%&ta=%release-group-artist-credit%&type=search-form-title&match=2",
"//www.minc.or.jp/product/list/?tl=%release-name%&ta=%release-artist-credit%&type=search-form-title&match=2",
],
// TODO: Add token replacement in link labels before using all catalogue numbers (here only the first catalogue number is used)
"MINC(品番/POS)": "//www.minc.or.jp/product/list/?dn=%release-catalogue-number%&type=search-form-diskno",
"mercari (CD)": [
"//jp.mercari.com/search?keyword=%release-artist-credit%+%release-name%&t1_category_id=5&category_id=75",
"//jp.mercari.com/search?keyword=%release-group-artist-credit%+%release-group-name%&t1_category_id=5&category_id=75",
],
"Joshin web (cat)": "//joshinweb.jp/cdshops/Dps?KEY=RECODE&FM=0&KEYWORD=%release-catalogue-number%",
"Joshin web (barcode)": "//joshinweb.jp/dp/%release-barcode%.html",
"ヨドバシカメラ (cat)": "//www.yodobashi.com/category/91139/?word=%release-catalogue-number%",
}
},
USA: {
items: {
BMI: [
"//repertoire.bmi.com/Search/Search?SearchForm.Main_Search=Title&SearchForm.Main_Search_Text=%recording-name%",
"//repertoire.bmi.com/Search/Search?SearchForm.Main_Search=Title&SearchForm.Main_Search_Text=%work-name%",
"//repertoire.bmi.com/Search/Search?SearchForm.Main_Search=Publisher&SearchForm.Main_Search_Text=%label-name%"
],
"BMI (performer)": "//repertoire.bmi.com/Search/Search?SearchForm.Main_Search=Performer&SearchForm.Main_Search_Text=%artist-name%",
"BMI (writer)": "//repertoire.bmi.com/Search/Search?SearchForm.Main_Search=Writer%2FComposer&SearchForm.Main_Search_Text=%artist-name%"
}
}
}
},
isrcDBs: {
title: "ISRC",
items: {
IFPI: "https://isrcsearch.ifpi.org/#!/search?upcCode=%release-barcode%&tab=lookup&showReleases&start=0&number=100",
}
},
otherDBs: {
title: {
de: "Andere Datenbanken",
en: "Other databases",
fr: "Autres bases de données",
nl: "Andere databases"
},
items: {
GnuDb: [
"//gnudb.org/search/artist/%22%artist-name%%22",
"//gnudb.org/search/%22%release-artist-credit%%22%20%22%release-name%%22",
"//gnudb.org/search/%22%release-group-artist-credit%%22%20%22%release-group-name%%22",
"//gnudb.org/search/song/%22%recording-name%%22",
"//gnudb.org/search/song/%22%work-name%%22",
],
"GnuDb (just title)": [
"//gnudb.org/search/album/%22%release-name%%22",
"//gnudb.org/search/album/%22%release-group-name%%22",
],
"GnuDb (abc)": [
"//gnudb.org/search/artist/%22%artist-latin-script-name%%22",
],
}
}
}
};
var searchLinks = {items: {
additional: additionalSearchLinks,
whitelist: whitelistSearchLinks,
web: webSearchLinks
}};
var disabledSearchLinks = {};
var FAVICON_CLASSES = { // from https://github.com/metabrainz/musicbrainz-server/blob/62d70e6e702d2f083bbdfe9f6a6056703a64ed30/root/static/scripts/common/constants.js#L53-L229
"45cat.com": "fortyfivecat",
"45worlds.com": "fortyfiveworlds",
"abc.net.au/triplejunearthed": "triplejunearthed",
"adp.library.ucsb.edu": "dahr",
"allmusic.com": "allmusic",
"animenewsnetwork.com": "animenewsnetwork",
"anison.info": "anisongeneration",
"archive.org": "archive",
"audiomack.com": "audiomack",
"baidu.com": "baidu",
"bandcamp.com": "bandcamp",
"bandsintown.com": "bandsintown",
"bbc.co.uk": "bbc",
"beatport.com": "beatport",
"bibliotekapiosenki.pl": "piosenki",
"bigcartel.com": "bigcartel",
"bookbrainz.org": "bookbrainz",
"books.apple.com": "applebooks",
"boomplay.com": "boomplay",
"cancioneros.si": "cancioneros",
"castalbums.org": "castalbums",
"catalogue.bnf.fr": "bnfcatalogue",
"cbfiddle.com/rx/": "cbfiddlerx",
"ccmixter.org": "ccmixter",
"cdjapan.co.jp": "cdjapan",
"changetip.com": "changetip",
"ci.nii.ac.jp": "cinii",
"classicalarchives.com": "classicalarchives",
"cpdl.org": "cpdl",
"d-nb.info": "dnb",
"dailymotion.com": "dailymotion",
"deezer.com": "deezer",
"dhhu.dk": "dhhu",
"discogs.com": "discogs",
"dogmazic.net": "dogmazic",
"dramonline.org": "dram",
"encyclopedisque.fr": "encyclopedisque",
"ester.ee": "ester",
"facebook.com": "facebook",
"finna.fi": "finna",
"finnmusic.net": "finnmusic",
"flattr.com": "flattr",
"fono.fi": "fonofi",
"generasia.com/wiki": "generasia",
"genius.com": "genius",
"geonames.org": "geonames",
"gutenberg.org": "gutenberg",
"hoick.jp": "hoick",
"ibdb.com": "ibdb",
"idref.fr": "idref",
"imdb.com": "imdb",
"imslp.org": "imslp",
"imvdb.com": "imvdb",
"indiegogo.com": "indiegogo",
"instagram.com": "instagram",
"ircam.fr": "ircam",
"irishtune.info": "irishtune",
"iss.ndl.go.jp": "ndl",
"itunes.apple.com": "itunes",
"j-lyric.net": "jlyric",
"jazzmusicarchives.com": "jazzmusicarchives",
"joysound.com": "joysound",
"junodownload.com": "junodownload",
"kashinavi.com": "kashinavi",
"kget.jp": "kget",
"kickstarter.com": "kickstarter",
"ko-fi.com": "kofi",
"laboiteauxparoles.com": "laboiteauxparoles",
"lantis.jp": "lantis",
"last.fm": "lastfm",
"lieder.net": "lieder",
"linkedin.com": "linkedin",
"livefans.jp": "livefans",
"loc.gov": "loc",
"loudr.fm": "loudr",
"lyric.evesta.jp": "evestalyric",
"mainlynorfolk.info": "mainlynorfolk",
"melon.com": "melon",
"metal-archives.com": "metalarchives",
"mixcloud.com": "mixcloud",
"mora.jp": "mora",
"music.amazon": "amazonmusic",
"music.apple.com": "applemusic",
"music.bugs.co.kr": "bugs",
"music.migu.cn": "migumusic",
"music.youtube.com": "youtubemusic",
"musicapopular.cl": "musicapopularcl",
"musik-sammler.de": "musiksammler",
"musixmatch.com": "musixmatch",
"musopen.org": "musopen",
"muziekweb.nl": "muziekweb",
"muzikum.eu": "muzikum",
"myspace.com": "myspace",
"napster.com": "napster",
"nicovideo.jp": "niconicovideo",
"nla.gov.au": "trove",
"ocremix.org": "ocremix",
"offiziellecharts.de": "offiziellecharts",
"online-bijbel.nl": "onlinebijbel",
"opac.kbr.be": "kbr",
"openlibrary.org": "openlibrary",
"operabase.com": "operabase",
"overture.doremus.org": "overture",
"patreon.com": "patreon",
"paypal.me": "paypal",
"petitlyrics.com": "petitlyrics",
"pinterest.com": "pinterest",
"progarchives.com": "progarchives",
"psydb.net": "psydb",
"qim.com": "quebecinfomusique",
"qobuz.com": "qobuz",
"ra.co": "residentadvisor",
"rateyourmusic.com": "rateyourmusic",
"recochoku.jp": "recochoku",
"reverbnation.com": "reverbnation",
"rock.com.ar": "rockcomar",
"rockensdanmarkskort.dk": "rockensdanmarkskort",
"rockinchina.com": "ric",
"rockipedia.no": "rockipedia",
"rolldabeats.com": "rolldabeats",
"runeberg.org": "runeberg",
"saisaibatake.ame-zaiku.com/gakki": "gakki",
"saisaibatake.ame-zaiku.com/musical": "gakki",
"saisaibatake.ame-zaiku.com/musical_instrument": "gakki",
"secondhandsongs.com": "secondhandsongs",
"setlist.fm": "setlistfm",
"smdb.kb.se": "smdb",
"snaccooperative.org": "snac",
"songfacts.com": "songfacts",
"songkick.com": "songkick",
"soundcloud.com": "soundcloud",
"spirit-of-metal.com": "spiritofmetal",
"spirit-of-rock.com": "spiritofrock",
"spotify.com": "spotify",
"stage48.net": "stage48",
"target.com": "target",
"tedcrane.com/DanceDB": "dancedb",
"theatricalia.com": "theatricalia",
"thedancegypsy.com": "thedancegypsy",
"thesession.org": "thesession",
"tidal.com": "tidal",
"tiktok.com": "tiktok",
"tipeee.com": "tipeee",
"tobarandualchais.co.uk": "tobar",
"touhoudb.com": "touhoudb",
"tower.jp": "tower",
"traxsource.com": "traxsource",
"triplejunearthed.com": "triplejunearthed",
"tunearch.org": "tunearch",
"twitch.tv": "twitch",
"twitter.com": "twitter",
"uta-net.com": "utanet",
"utaitedb.net": "utaitedb",
"utamap.com": "utamap",
"utaten.com": "utaten",
"vgmdb.net": "vgmdb",
"viaf.org": "viaf",
"videogam.in": "videogamin",
"vimeo.com/ondemand": "vimeoondemand",
"vimeo.com": "vimeo",
"vk.com": "vk",
"vkdb.jp": "vkdb",
"vocadb.net": "vocadb",
"weibo.com": "weibo",
"whosampled.com": "whosampled",
"wikidata.org": "wikidata",
"wikipedia.org": "wikipedia",
"wikisource.org": "wikisource",
"worldcat.org": "worldcat",
"www.amazon": "amazon",
"www.youtube.com": "youtube",
"www5.atwiki.jp/hmiku/": "hmikuwiki",
"yesasia.com": "yesasia",
};
var favicons = {
"deezer.com": "https://e-cdns-files.dzcdn.net/cache/images/common/favicon/favicon-16x16.526cde4edf20647be4ee32cdf35c1c13.png",
"lastfm.": "//musicbrainz.org/static/images/favicons/lastfm-16.png",
"rakuten.co.jp": "//plaza.rakuten.co.jp/favicon.ico",
};
var favicontry = [];
var guessOtherFavicons = true;
var sidebar = document.getElementById("sidebar");
var tokenValues = {};
var entityUrlRelsWS = self.location.protocol + "//" + self.location.host + "/ws/2/%entity-type%/%entity-mbid%?inc=url-rels";
var extlinks;
var j2css = document.createElement("style");
j2css.setAttribute("type", "text/css");
document.head.appendChild(j2css);
j2css = j2css.sheet;
j2css.insertRule("ul.external_links > li.defaultAutolink > input[type='checkbox'] { display: none; }", 0);
j2css.insertRule("ul.external_links > li.defaultAutolink.disabled { text-decoration: line-through; display: none; }", 0);
j2css.insertRule("ul.external_links.configure > li.defaultAutolink.disabled { display: list-item; }", 0);
j2css.insertRule("ul.external_links.configure > li.defaultAutolink > input[type='checkbox'] { display: inline; }", 0);
j2css.insertRule("div#sidebar [class^='" + userjs + "'], div#sidebar [class^='" + userjs + "'] + ul, div#sidebar [class*='" + userjs + "_wd-'] ul { background-color: #FF9; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks.emptySection { display: none; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks li.emptySection { display: none; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks input[type='checkbox'] { display: none; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks.disabled { text-decoration: line-through; display: none; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks .disabled { text-decoration: line-through; display: none; }", 0);
j2css.insertRule("div#sidebar > .configure." + userjs + "_searchLinks.emptySection { display: block; }", 0);
j2css.insertRule("div#sidebar > .configure." + userjs + "_searchLinks li.emptySection { display: list-item; }", 0);
j2css.insertRule("div#sidebar > .configure." + userjs + "_searchLinks input[type='checkbox'] { display: inline; }", 0);
j2css.insertRule("div#sidebar > .configure." + userjs + "_searchLinks.disabled { display: block; }", 0);
j2css.insertRule("div#sidebar > ul.configure." + userjs + "_searchLinks.disabled { display: none; }", 0);
j2css.insertRule("div#sidebar > .configure." + userjs + "_searchLinks li.disabled { display: list-item; }", 0);
j2css.insertRule("div#sidebar > .configure." + userjs + "_searchLinks ul.disabled { display: none; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks h3 { margin: 0; }", 0);
j2css.insertRule("div#sidebar > ." + userjs + "_searchLinks h4 { margin: 0; }", 0);
j2css.insertRule("div#sidebar > ul." + userjs + "_userLinks > li.subsectionHeader { font-weight: 'bold'; padding: '0px'; float: 'right'; }", 0);
main();
function main() {
if (sidebar) {
var entityMatch = self.location.href.match(/\/([a-z-]*)\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}).*/i);
var entityType = tokenValues["%entity-type%"] = entityMatch[1];
var entityMBID = tokenValues["%entity-mbid%"] = entityMatch[2];
tokenValues["%" + entityType + "-mbid%"] = entityMBID;
/* Hidden links and autolinks */
if (entityType && entityMBID) {
// Tokens for autolinks
var entityHeaderClass = (entityType === "release-group" ? "rg" : entityType) + "header";
var entityNameNode = document.querySelector("div#content > div." + entityHeaderClass + " > h1 a, div#content > div." + entityHeaderClass + " > h1 span[href]"); /* for compatibilly with https://gist.github.com/jesus2099/4111760 */
if (entityNameNode) {
var entityName = tokenValues["%entity-name%"] = entityNameNode.textContent.trim();
tokenValues["%" + entityType + "-name%"] = entityName;
if (entityType == "artist") {
var artistname = entityName;
var artistsortname = sidebar.querySelector("dd.sort-name");
var artistsortnameSwapped = "";
artistsortname = tokenValues["%artist-sort-name%"] = artistsortname ? artistsortname.textContent : artistname;
if (!artistname.match(nonLatinName)) {
tokenValues["%artist-family-name-first%"] = artistsortname;
tokenValues["%artist-latin-script-name%"] = artistname;
} else {
var tmpsn = artistsortname.split(",");
for (var isn = tmpsn.length - 1; isn >= 0; isn--) {
artistsortnameSwapped += tmpsn[isn].trim();
if (isn != 0) {
artistsortnameSwapped += " ";
}
}
tokenValues["%artist-family-name-first%"] = artistname;
tokenValues["%artist-latin-script-name%"] = artistsortnameSwapped;
}
} else if (entityType === "release") {
let barcodeNode = document.querySelector("#sidebar .barcode");
if (barcodeNode && barcodeNode.textContent.match(/^\d+$/)) {
tokenValues["%release-barcode%"] = barcodeNode.textContent;
}
let catnoNode = document.querySelector("#sidebar .catalog-number");
if (catnoNode) {
tokenValues["%release-catalogue-number%"] = catnoNode.textContent;
}
} else if (entityType == "url") {
delete tokenValues["%entity-name%"];
delete tokenValues["%url-name%"];
tokenValues["%url-target%"] = entityName;
}
if (entityType.match(/^release(-group)?/)) {
var artistCredit = document.querySelector("div#content > div." + entityHeaderClass + " > p.subheader");
if (artistCredit) {
tokenValues["%" + entityType + "-artist-credit%"] = parseArtistCredit(artistCredit);
}
}
}
extlinks = sidebar.querySelector("h2.external-links + ul.external_links");
if (!extlinks) {
var previous = sidebar.querySelector("div.sidebar-tags") || sidebar.querySelector("p.lastupdate");
extlinks = addAfter(createTag("ul", {a: {class: "external_links"}}, createTag("li", {}, "No white‐listed links yet.")), previous);
addAfter(createTag("h2", {a: {class: "external-links"}}, "External links"), previous);
}
var editingBlock = sidebar.querySelector("h2.editing + ul.links");
if (editingBlock) {
// We want to move external links (including release group ones) after editing block
editingBlock = sidebar.insertBefore(sidebar.removeChild(editingBlock), sidebar.querySelector("h2.external-links"));
sidebar.insertBefore(sidebar.removeChild(sidebar.querySelector("h2.editing")), editingBlock);
}
// Hidden links
entityUrlRelsWS = entityUrlRelsWS.replace(/%entity-type%/, entityType).replace(/%entity-mbid%/, entityMBID);
addHiddenLinks();
// Search links
loadDisabledSearchLinks();
for (var sectionKey in searchLinks.items) if (Object.prototype.hasOwnProperty.call(searchLinks.items, sectionKey)) {
addSearchLinksSection([sectionKey], sidebar);
}
// User links
addUserLinks(sidebar);
}
/* Wikidata to Wikipedia */
if (rawLanguages && Array.isArray(rawLanguages) && rawLanguages.length > 0) {
var languages = parseLanguages(rawLanguages);
var wikidatas = sidebar.querySelectorAll("ul.external_links > li a[href*='wikidata.org/wiki/Q']");
for (var wd = 0; wd < wikidatas.length; wd++) {
var wikidataID = wikidatas[wd].getAttribute("href").match(/Q\d+$/);
if (wikidataID) {
if (!wikidatas[wd].parentNode.querySelector("a.edit-languages")) {
addAfter(createTag("div", {a: {class: "icon img"}, s: {backgroundImage: "url(/static/images/icons/cog.png)", opacity: ".5"}}, createTag("a", {a: {class: "edit-languages", title: "choose languages"}, s: {color: "transparent"}, e: {click: configureModule}}, "choose languages")), wikidatas[wd]);
addAfter(document.createTextNode(" "), wikidatas[wd]);
}
var xhr = new XMLHttpRequest();
xhr.id = wikidataID[0];
wikidatas[wd].closest("li").classList.add(userjs + "_wd-" + xhr.id);
wikidatas[wd].parentNode.appendChild(createTag("img", {a: {alt: "checking available wikipedia languages…", src: "/static/images/icons/loading.gif"}}));
xhr.addEventListener("load", function(event) {
var wikidataListItem = sidebar.querySelector("ul.external_links > li." + userjs + "_wd-" + this.id);
removeNode(wikidataListItem.querySelector("img[src$='loading.gif']"));
var wikidata = JSON.parse(this.responseText);
if (wikidata && wikidata.entities && (wikidata = wikidata.entities[this.id])) {
for (var languageCode = 0; languageCode < languages.length; languageCode++) {
var wikiEntry = wikidata.sitelinks[languages[languageCode] + "wiki"];
if (wikiEntry) {
var href = wikiEntry.url.replace(/^https?:/, "");
var ul;
if (!sidebar.querySelector("ul.external_links > li a[href$='" + href + "']")) {
if (!ul) {
ul = wikidataListItem.appendChild(createTag("ul", {s: {listStyle: "none"}}));
}
ul.appendChild(createTag("li", {a: {class: "wikipedia-favicon"}, s: {marginLeft: "-22px"}}, [languages[languageCode], ": ", createTag("a", {a: {href: href}}, wikiEntry.title)]));
}
}
}
}
});
xhr.open("get", "https://www.wikidata.org/wiki/Special:EntityData/" + xhr.id + ".json", true);
xhr.send(null);
}
}
}
}
}
function addExternalLink(parameters/* text, target, begin, end, sntarget, mbid, enabledDefaultAutolink */) {
var newLink = true;
let li;
if (parameters.target) {
// This is a link
if (typeof parameters.target === "string") {
console.debug(GM_info.script.name + " ### Strange it now does not run for everything?\ntarget: " + parameters.target);
var escapedTarget = parameters.target.replace(/'/g, "\\'");
var existingLink =
sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "']")
// MBS adds a trailing code to ASIN URL https://github.com/metabrainz/musicbrainz-server/blob/7b16dfae25fef7ef570bbc96e2d7cb71f123139e/lib/DBDefs/Default.pm#L318-L328
|| parameters.target.match(/\bamazon\.ca\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=music0b72-20']")
|| parameters.target.match(/\bamazon\.co\.jp\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=musicbrainzjp-22']")
|| parameters.target.match(/\bamazon\.co\.uk\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=music080d-21']")
|| parameters.target.match(/\bamazon\.com\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=musicbrainz0d-20']")
|| parameters.target.match(/\bamazon\.de\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=music059-21']")
|| parameters.target.match(/\bamazon\.fr\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=music083d-21']")
|| parameters.target.match(/\bamazon\.it\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=music084d-21']")
|| parameters.target.match(/\bamazon\.es\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "?tag=music02e-21']")
// MBS adds a trailing slash to viaf URL https://github.com/jesus2099/konami-command/issues/293#issuecomment-376875307
|| parameters.target.match(/\bviaf\b/) && sidebar.querySelector("ul.external_links > li a[href$='" + escapedTarget.replace(/^https?:/, "") + "/']");
if (existingLink) {
newLink = false;
li = existingLink.closest("li");
} else {
li = createTag("li", {a: {ref: parameters.text}});
if (parameters.end) {
li.appendChild(createTag("span", {a: {class: "deleted", title: parameters.target}}, parameters.text));
} else {
li.appendChild(createTag("a", {a: {href: parameters.target}}, parameters.text));
}
}
if (parameters.sntarget && newLink) {
li.appendChild(document.createTextNode(" ("));
li.appendChild(createTag("a", {a: {href: parameters.sntarget, title: "search with latin name"}}, "lat."));
li.appendChild(document.createTextNode(")"));
}
if (parameters.begin || parameters.end) {
var ardates = createTag("span", {s: {whiteSpace: "nowrap"}}, " (");
if (!parameters.begin && parameters.end == "????") {
ardates.appendChild(archivedDate(parameters.end, parameters.target));
} else {
if (parameters.begin) { ardates.appendChild(archivedDate(parameters.begin, parameters.target)); }
if (parameters.begin != parameters.end) { ardates.appendChild(document.createTextNode("—")); }
if (parameters.end && parameters.begin != parameters.end) { ardates.appendChild(archivedDate(parameters.end, parameters.target)); }
}
ardates.appendChild(document.createTextNode(")"));
ardates.normalize();
li.appendChild(ardates);
}
if (parameters.mbid) {
addAfter(createTag("div", {a: {class: "icon img edit-item"}, s: {opacity: ".5"}}, createTag("a", {a: {title: "edit this URL relationship", href: "/url/" + parameters.mbid + "/edit"}, s: {color: "transparent"}}, "edit")), li.querySelector("a"));
addAfter(document.createTextNode(" "), li.querySelector("a"));
}
}
setFavicon(li, (typeof parameters.target == "string") ? parameters.target : parameters.target.action);
} else {
// This is a Hidden links header
li = createTag("li", {s: {fontWeight: "bold"}, a: {class: userjs + "_hidden-links " + "separator"}}, parameters.text);
if (parameters.text.indexOf(" ") === 0) {
// Level 1 header
li.style.setProperty("padding-top", "0px");
extlinks.insertBefore(li, extlinks.lastChild);
} else {
// Level 2 header
li.style.setProperty("padding", "0px");
li.style.setProperty("float", "right");
extlinks.appendChild(li);
}
}
if (newLink) {
if (parameters.target) { extlinks.appendChild(li); }
}
return newLink;
}
function addHiddenLinks() {
loading(true);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(event) {
if (this.readyState == 4) {
if (this.status == 200) {
loading(false);
var res = this.responseXML;
var url, urls = res.evaluate("//mb:relation-list[@target-type='url']/mb:relation", res, nsr, XPathResult.ANY_TYPE, null);
var haslinks = false;
while ((url = urls.iterateNext())) {
var target = res.evaluate("./mb:target", url, nsr, XPathResult.ANY_TYPE, null);
target = target.iterateNext();
var begin, end;
if ((begin = res.evaluate("./mb:begin", url, nsr, XPathResult.ANY_TYPE, null).iterateNext())) {
begin = begin.textContent;
}
if ((end = res.evaluate("./mb:end", url, nsr, XPathResult.ANY_TYPE, null).iterateNext())) {
end = end.textContent;
} else if (res.evaluate("./mb:ended", url, nsr, XPathResult.ANY_TYPE, null).iterateNext()) {
end = "????";
}
if (target) {
if (addExternalLink({text: url.getAttribute("type"), target: target.textContent, mbid: target.getAttribute("id"), begin: begin, end: end})) {
if (!haslinks) {
haslinks = true;
addExternalLink({text: " " + getLocalisedText(hiddenLinks)});
}
}
}
}
} else if (this.status >= 400 || this.status == 0) {
var txt = this.responseText.match(/<error><text>(.+)<\/text><text>/);
txt = txt ? txt[1] : "";
error(this.status, txt);
}
}
};
xhr.open("GET", entityUrlRelsWS, true);
xhr.send(null);
}
function addSearchLinksSection(sectionPath, parentNode) {
var level = sectionPath.length;
var section = pathToItem(sectionPath);
var sectionID = pathToID(sectionPath);
var sectionTitleNode = createTag("h" + (1 + level), {a: {ref: sectionID}}, section.title ? getLocalisedText(section.title) : sectionPath[sectionPath.length - 1]);
if (level === 1) {
sectionTitleNode.classList.add(userjs + "_searchLinks");
if (parentNode == extlinks.parentNode) {
addAfter(sectionTitleNode, extlinks);
} else {
parentNode.appendChild(sectionTitleNode);
}
if (section === webSearchLinks) {
sectionTitleNode.appendChild(document.createTextNode(" "));
sectionTitleNode.appendChild(
createTag("a", {a: {title: "filter search links"}, s: {padding: "1px 3px"}, e: {click: configureModule}},
createTag("img", {a: {src: "/static/images/icons/filter.png", alt: "filter search links", title: "filter search links"}})
)
);
}
} else {
parentNode.appendChild(sectionTitleNode);
}
var sectionListNode = addAfter(createTag("ul", {a: {class: "external_links"}}), sectionTitleNode);
if (level === 1) {
sectionListNode.classList.add(userjs + "_searchLinks");
}
if (section !== webSearchLinks) {
var sectionCBox = sectionTitleNode.appendChild(
createTag("input", {a: {type: "checkbox"}, s: {float: "right", margin: "1px"}, e: {click: function(event) {
toggleStorage(this.parentNode.getAttribute("ref"));
this.parentNode.nextElementSibling.classList.toggle("disabled", !this.checked);
if (this.parentNode.parentNode.id !== "sidebar") {
this.parentNode.parentNode.classList.toggle("disabled", !this.checked);
toggleEmpty(this.parentNode.parentNode, !this.checked);
} else {
this.parentNode.classList.toggle("disabled", !this.checked);
}
}}})
);
sectionCBox.checked = !disabledSearchLinks[sectionID];
if (disabledSearchLinks[sectionID]) {
sectionListNode.classList.add("disabled");
if (level === 1) {
sectionTitleNode.classList.add("disabled");
} else {
parentNode.classList.add("disabled");
}
}
}
var hasNothing = true;
var hasVisibleContent = false;
for (let itemKey in section.items) if (Object.prototype.hasOwnProperty.call(section.items, itemKey)) {
var item = section.items[itemKey];
var itemPath = sectionPath.concat([itemKey]);
var itemID = pathToID(itemPath);
var itemNode = createTag("li", {a: {ref: itemID}});
if (typeof item === "object" && item.items) {
hasNothing = false;
sectionListNode.appendChild(itemNode);
var subIsVisible = addSearchLinksSection(itemPath, itemNode);
if (subIsVisible) {
hasVisibleContent = true;
} else {
itemNode.classList.add("emptySection");
}
} else {
// "key": <target> → "key": {"target": <target>}
if (typeof item !== "object" || !item.target) {
item = {target: item};
// section.items[itemKey] = item; // not sure I need this
}
var itemTarget = false;
if (!Array.isArray(item.target)) {
item.target = [item.target];
}
for (var t = 0; t < item.target.length; t++) {
itemTarget = replaceAllTokens(getLocalisedText(item.target[t]), true);
if (itemTarget) {
break;
}
}
if (itemTarget) {
hasNothing = false;
sectionListNode.appendChild(itemNode);
itemNode.appendChild(createTag("a", {a: {href: itemTarget}}, item.title ? getLocalisedText(item.title) : itemKey));
setFavicon(itemNode, itemTarget);
var itemCBox = itemNode.appendChild(
createTag("input", {a: {type: "checkbox"}, s: {float: "right", margin: "1px"}, e: {click: function(event) {
this.parentNode.classList.toggle("disabled", !this.checked);
toggleStorage(this.parentNode.getAttribute("ref"));
toggleEmpty(this.parentNode, !this.checked);
}}})
);
itemCBox.checked = !disabledSearchLinks[itemID];
if (disabledSearchLinks[itemID]) {
itemNode.classList.add("disabled");
} else {
hasVisibleContent = true;
}
}
}
}
if (!hasVisibleContent) {
if (level === 1 && section !== webSearchLinks) {
sectionTitleNode.classList.add("emptySection");
sectionListNode.classList.add("emptySection");
}
if (hasNothing) {
var noItemNote = {
de: "nichts für diesen Entitätstyp",
en: "nothing for this entity type",
fr: "rien pour ce type d’entité",
nl: "niets voor dit soort entiteit"
};
sectionListNode.appendChild(createTag("li", {s: {fontStyle: "italic", opacity: "0.5"}}, getLocalisedText(noItemNote)));
}
}
return hasVisibleContent && !disabledSearchLinks[sectionID];
}
function addUserLinks(parentNode) {
var loadedUserLinks = JSON.parse(localStorage.getItem(userjs + "_user-autolinks")) || {};
var filteredUserLinks = {};
var currentSection = "";
var currentSectionIsEmpty = true;
for (let title in loadedUserLinks) if (Object.prototype.hasOwnProperty.call(loadedUserLinks, title)) {
let target = loadedUserLinks[title];
if (!target || target === "") {
if (currentSectionIsEmpty) {
delete filteredUserLinks[currentSection];
}
currentSection = title;
currentSectionIsEmpty = true;
filteredUserLinks[title] = null;
}
if (typeof target === "string") {
target = replaceAllTokens(target, true);
if (target) {
currentSectionIsEmpty = false;
filteredUserLinks[title] = target;
}
}
}
if (currentSectionIsEmpty) {
delete filteredUserLinks[currentSection];
}
if (!Object.getOwnPropertyNames(filteredUserLinks).length) {
return;
}
var userLinksTitle = {
de: "Meine Links",
en: "My links",
fr: "Mes liens",
nl: "Mijn links"
};
var userLinksTitleNode = createTag("h2", {}, getLocalisedText(userLinksTitle));
userLinksTitleNode.appendChild(document.createTextNode(" "));
userLinksTitleNode.appendChild(
createTag("a", {a: {title: "configure user autolinks"}, s: {padding: "0px"}, e: {click: configureModule}},
createTag("img", {a: {src: "/static/images/icons/cog.png", alt: "configure user autolinks", title: "configure user autolinks"}})
)
);
if (parentNode == extlinks.parentNode) {
addAfter(userLinksTitleNode, extlinks);
} else {
parentNode.appendChild(userLinksTitleNode);
}
var userLinksListNode = createTag("ul", {a: {class: userjs + "_userLinks external_links"}});
addAfter(userLinksListNode, userLinksTitleNode);
for (let title in filteredUserLinks) if (Object.prototype.hasOwnProperty.call(filteredUserLinks, title)) {
let target = filteredUserLinks[title];
let itemNode = createTag("li", {});
if (target === null) {
itemNode.classList.add("subsectionHeader", "separator");
itemNode.appendChild(document.createTextNode(title));
} else {
itemNode.appendChild(createTag("a", {a: {href: target}}, title));
setFavicon(itemNode, target);
}
userLinksListNode.appendChild(itemNode);
}
}
function getLocalisedText(textSet) {
if (typeof textSet === "string") {
if (textSet.match(/%language%/)) {
return textSet.replace(/%language%/g, parseLanguages(["musicbrainz", "navigator"])[0]);
} else {
return textSet;
}
}
// Manages both "fr" and multinligual "fr vi ja en" formats
var expanded = {};
for (var key in textSet) if (Object.prototype.hasOwnProperty.call(textSet, key)) {
var allKeys = key.split(" ");
for (var ak = 0; ak < allKeys.length; ak++)
expanded[allKeys[ak]] = textSet[key].replace(/%language%/g, allKeys[ak]);
}
textSet = expanded;
var languages = parseLanguages(["musicbrainz", "navigator"]);
for (var l = 0; l < languages.length; l++) {
if (Object.prototype.hasOwnProperty.call(textSet, languages[l])) {
return textSet[languages[l]];
}
}
return textSet[Object.getOwnPropertyNames(textSet)[0]];
}
function idToPath(id) {
return id.replace(userjs + "_searchLinks" + path_ID_separator, "").split(path_ID_separator);
}
function loadDisabledSearchLinks() {
var loadedSettings = JSON.parse(localStorage.getItem(userjs + "_disabled-search-links")) || {};
for (var itemID in loadedSettings) if (Object.prototype.hasOwnProperty.call(loadedSettings, itemID)) {
var itemPath = idToPath(itemID);
if (itemPath && pathToItem(itemPath)) {
disabledSearchLinks[itemID] = true;
}
}
delete disabledSearchLinks[pathToID(["web"])];
localStorage.setItem(userjs + "_disabled-search-links", JSON.stringify(disabledSearchLinks));
}
function pathToItem(path) {
var item = searchLinks;
for (var i = 0; i < path.length; i++) {
item = item.items[path[i]];
if (!item) {
return false;
}
}
return item;
}
function pathToID(path) {
var id = userjs + "_searchLinks";
for (var i = 0; i < path.length; i++)
id = id + path_ID_separator + path[i];
return id;
}
function replaceAllTokens(string, encode) {
var stringTokens = string.match(/%[a-z]+(?:-[a-z]+)+%/g);
if (stringTokens) for (var t = 0; t < stringTokens.length; t++) {
var token = stringTokens[t];
if (!Object.prototype.hasOwnProperty.call(tokenValues, token)) {
return false;
}
string = string.replace(token, encode && token != "%url-target%" ? encodeURIComponent(tokenValues[token]).replace(/[()]/g, "") : tokenValues[token]);
}
return string;
}
function setFavicon(li, url) {
var favclass = "no";
// MusicBrainz cached favicon CSS classes
var searchdomain = url.match(/site:([^+]*)\+/);
var urldomain = searchdomain ? searchdomain[1] : url.split("/")[2];
for (var classdomain in FAVICON_CLASSES) if (Object.prototype.hasOwnProperty.call(FAVICON_CLASSES, classdomain)) {
if (urldomain.match(classdomain)) {
favclass = FAVICON_CLASSES[classdomain];
break;
}
}
if (favclass != "no") {
li.classList.add(favclass + "-favicon");
} else {
// Static favicon URL dictionary
var favurlfound = false;
for (var part in favicons) if (Object.prototype.hasOwnProperty.call(favicons, part)) {
if (url.indexOf(part) != -1) {
favurlfound = favicons[part];
break;
}
}
if (!guessOtherFavicons && !favurlfound) {
li.classList.add("no-favicon");
} else {
// arbitrary /favicon.ico load try out
if (guessOtherFavicons && !favurlfound) {
favurlfound = url.match(/^(?:https?:)?(\/\/[^/]+)\/(?:.+_action=https?:(\/\/[^/]+)\/)?/);
if (favurlfound) {
favurlfound = (favurlfound[1] != "//jesus2099.gitlab.io" ? favurlfound[1] : favurlfound[2]) + "/favicon.ico";
}
}
var ifit = favicontry.length;
favicontry[ifit] = new Image();
favicontry[ifit].addEventListener("error", function (event) {
this.li.classList.add("no-favicon");
});
favicontry[ifit].addEventListener("load", function (event) {
clearTimeout(this.to);
this.li.style.setProperty("background-image", "url(" + this.src + ")");
this.li.style.setProperty("background-size", "16px 16px");
});
favicontry[ifit].li = li;
favicontry[ifit].src = favurlfound;
favicontry[ifit].to = setTimeout(function() {
// don’t wait for more than 5 seconds
favicontry[ifit].src = "";
favicontry[ifit].li.classList.add("no-favicon");
}, 5000);
}
}
}
function toggleEmpty(itemNode, hide) {
if (!hide) {
if (itemNode.parentNode.parentNode.id === "sidebar") {
itemNode.parentNode.classList.remove("emptySection");
itemNode.parentNode.previousElementSibling.classList.remove("emptySection");
} else {
itemNode.parentNode.parentNode.classList.remove("emptySection");
toggleEmpty(itemNode.parentNode.parentNode, hide);
}
} else if (!itemNode.parentNode.classList.contains(pathToID(["web"]))) {
var allDisabled = true;
var siblings = itemNode.parentNode.children;
for (var n = 0; n < siblings.length; n++) {
if ((!siblings[n].classList.contains("disabled")) && (!siblings[n].classList.contains("emptySection"))) {
allDisabled = false;
break;
}
}
if (allDisabled) {
if (itemNode.parentNode.parentNode.id === "sidebar") {
itemNode.parentNode.classList.add("emptySection");
itemNode.parentNode.previousElementSibling.classList.add("emptySection");
} else {
itemNode.parentNode.parentNode.classList.add("emptySection");
toggleEmpty(itemNode.parentNode.parentNode, hide);
}
}
}
}
function toggleStorage(itemID) {
var toggledSettings = JSON.parse(localStorage.getItem(userjs + "_disabled-search-links")) || {};
if (toggledSettings[itemID]) {
delete toggledSettings[itemID];
} else {
toggledSettings[itemID] = true;
}
localStorage.setItem(userjs + "_disabled-search-links", JSON.stringify(toggledSettings));
}
/* function weirdobg() {
var weirdo = userjs + " _" + (new Date().getTime());
try { open("", weirdo).blur(); } catch (error) {}
self.focus();
return weirdo;
} */
function error(code, text) {
var ldng = document.getElementById(userjs + "_loading");
if (ldng) {
ldng.setAttribute("id", userjs + "_error");
ldng.style.setProperty("background", "pink");
ldng.replaceChild(document.createTextNode("Error " + code), ldng.firstChild);
ldng.appendChild(createTag("a", {a: {href: entityUrlRelsWS}}, "*"));
ldng.appendChild(document.createTextNode(" in "));
ldng.appendChild(createTag("a", {a: {href: "http://userscripts-mirror.org/scripts/show/108889"}}, "all links"));
ldng.appendChild(document.createTextNode(" ("));
ldng.appendChild(createTag("a", {e: {click: function(event) {
var err = document.getElementById(userjs + "_error");
if (err) { err.parentNode.removeChild(err); }
addHiddenLinks();
}}}, "retry"));
ldng.appendChild(document.createTextNode(")"));
ldng.appendChild(document.createElement("br"));
ldng.appendChild(createTag("i", {}, text));
} else {
loading(true);
error(code, text);
}
}
function loading(on) {
var ldng = document.getElementById(userjs + "_loading");
if (on && !ldng) {
extlinks.appendChild(createTag("li", {a: {id: userjs + "_loading"}}, createTag("img", {a: {alt: "loading all links…", src: "/static/images/icons/loading.gif"}})));
var li = extlinks.querySelector("ul.external_links > li.all-relationships");
if (li) {
li.style.setProperty("display", "none");
}
} else if (ldng && !on) {
ldng.parentNode.removeChild(ldng);
}
}
function archivedDate(date, url) {
var text = date == "????" ? "ended" : date.replace(/-/g, "‐");
if (!url.match(/\.archive\.org\//)) {
var archiveStamp = "*";
if (date != "????") {
archiveStamp = date.replace(/\D/g, "");
while (archiveStamp.length < 14) archiveStamp += "0";
}
return createTag("a", {a: {href: "//wayback.archive.org/web/" + archiveStamp + "/" + url.replace(/https?:\/\//, ""), title: "Internet Archive Wayback Machine capture"}}, text);
} else {
return document.createTextNode(text);
}
}
function nsr(prefix) {
switch (prefix) {
case "mb":
return "http://musicbrainz.org/ns/mmd-2.0#";
default:
return null;
}
}
function guessNavigatorLanguages() {
if (Array.isArray(navigator.languages)) {
return navigator.languages;
} else {
var language = navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage;
if (language) {
return [language];
} else {
return [];
}
}
}
function parseLanguages(inputLanguages) {
var detectedLanguages = [];
for (let il = 0; il < inputLanguages.length; il++) {
let nextLanguage = inputLanguages[il];
switch (nextLanguage) {
case "navigator":
detectedLanguages = detectedLanguages.concat(guessNavigatorLanguages());
break;
case "musicbrainz":
detectedLanguages.push(document.documentElement.getAttribute("lang") || "en");
break;
default:
detectedLanguages.push(nextLanguage);
}
}
var outputLanguages = [];
for (let dl = 0; dl < detectedLanguages.length; dl++) {
let nextLanguage = detectedLanguages[dl];
if (outputLanguages.indexOf(nextLanguage) < 0) {
outputLanguages.push(nextLanguage);
if (nextLanguage.match("-")) {
var splitLanguage = nextLanguage.split("-")[0];
if (outputLanguages.indexOf(splitLanguage) < 0) {
outputLanguages.push(splitLanguage);
}
}
}
}
return outputLanguages;
}
function parseArtistCredit(subheader) {
var artistCredit = "";
for (var i = 0, acStarted = false; i < subheader.childNodes.length && !(subheader.childNodes[i].nodeType === Node.ELEMENT_NODE && subheader.childNodes[i].tagName === "SPAN" && subheader.childNodes[i].classList.contains("small")); i++) {
if (!acStarted && subheader.childNodes[i].nodeType === Node.ELEMENT_NODE && (subheader.childNodes[i].matches("a[href^='/artist/']") || subheader.childNodes[i].querySelector("a[href^='/artist/']"))) {
acStarted = true;
}
if (acStarted) {
artistCredit += subheader.childNodes[i].textContent;
}
}
return artistCredit.trim();
}
function configureModule(event) {
switch (event.target.getAttribute("title")) {
case "configure user autolinks":
// TODO: provide a real editor
var loadedUserAutolinks = localStorage.getItem(userjs + "_user-autolinks") || {};
var newUserAutolinks = prompt("Edit your user autolinks\nCopy/paste in a real editor\nSorry for such an awful prompt\n\nAvailable variables:\n- for all entity pages: %entity-type%, %entity-mbid% and %entity-name%\n- for \"foobar\" entity pages: %foobar-mbid% and %foobar-name% where \"foobar\" is an entity type.\n- for artist entity pages: %artist-sort-name%, %artist-family-name-first% and %artist-latin-script-name%\n- for url entity pages: %url-target% (while %entity-name% and %url-name% are deliberately ignored)\n\nExample: {\"Search for reviews\": \"//duckduckgo.com/?q=%22%entity-name%%22+reviews\",\n\"Search for fans\": \"//duckduckgo.com/?q=%22%artist-name%%22+fans\",\n\"Works\": \"/ws/2/artist/%artist-mbid%?inc=works\",\n\"La FNAC\": \"http://recherche.fnac.com/SearchResult/ResultList.aspx?SCat=3%211&Search=%release-name%&sft=1&sa=0\"}", loadedUserAutolinks);
if (newUserAutolinks && newUserAutolinks != loadedUserAutolinks && JSON.stringify(newUserAutolinks)) {
localStorage.setItem(userjs + "_user-autolinks", newUserAutolinks);
}
break;
case "filter search links":
/* var topSectionNodes = */ sidebar.children;
for (var n = 0; n < sidebar.children.length; n++) {
if (sidebar.children[n].classList.contains(userjs + "_searchLinks")) {
sidebar.children[n].classList.toggle("configure");
}
}
break;
case "choose languages":
var defaultLanguages = parseLanguages(["navigator", "musicbrainz"]);
var navigatorLanguages = guessNavigatorLanguages();
var musicbrainzLanguage = document.documentElement.getAttribute("lang") || "en";
var loadedLanguages = (localStorage.getItem(userjs + "_languages") || JSON.stringify(rawLanguages)).replace(/,/g, "$& ").replace(/\s+/g, " ");
var newLanguages = prompt("Choose your favourite language(s)\n\nType a language array: [\"favourite language\", \"second favourite\", …, \"least favourite\"]\n\nTwo meta languages can be used:\n- \"navigator\" for navigator settings, currently " + (navigatorLanguages.length > 0 ? "detected as " + JSON.stringify(navigatorLanguages).replace(/,/g, "$& ").replace(/\s+/g, " ") : "undetected") + "\n- \"musicbrainz\" for selected MusicBrainz UI language, currently " + (musicbrainzLanguage ? "detected as [" + JSON.stringify(musicbrainzLanguage) + "]" : "undetected") + "\n\nDefault:\n- [\"navigator\", \"musicbrainz\"], currently expands to " + JSON.stringify(defaultLanguages).replace(/,/g, "$& ").replace(/\s+/g, " ") + "\n\nSome examples:\n- [\"musicbrainz\", \"fr-FR\", \"en-GB\", \"vi\", \"ja\", \"navigator\"]\n- [\"fr\", \"en\", \"vi\", \"ja\"]\n- [\"en-GB\"]\n- [\"fr-FR\", \"navigator\", \"en-GB\", \"musicbrainz\"]\n- []" + "\n\nCurrent setting expands to " + JSON.stringify(parseLanguages(JSON.parse(loadedLanguages))).replace(/,/g, "$& ").replace(/\s+/g, " "), loadedLanguages);
if (
newLanguages
&& (newLanguages = newLanguages.match(/\[(\s*["'](navigator|musicbrainz|\w{2}(-\w{2,}(-\w{2,})?)?)['"]\s*,?\s*)*]/))
&& (newLanguages = newLanguages[0])
&& newLanguages != loadedLanguages
&& JSON.parse(newLanguages)
) {
localStorage.setItem(userjs + "_languages", newLanguages);
rawLanguages = JSON.parse(newLanguages);
}
break;
}
}