From cb53203a1fd533519de997b4280a0254b6ffc31c Mon Sep 17 00:00:00 2001 From: Raman Sinclair Date: Sun, 19 Jul 2026 08:54:59 +0200 Subject: [PATCH] fix(qobuz_importer): duplicate Qobuz discography MB icons Qobuz discography pages look up multiple URL aliases for the same entity, including localized www.qobuz.com URLs and open.qobuz.com URLs. When more than one alias resolves to the same MusicBrainz entity, the callback inserted the same MB icon multiple times before the same Qobuz link. Deduplicate inserted MB links by their target href before adding them to the discography item. This preserves multiple distinct MB matches while suppressing duplicate icons from equivalent Qobuz URL variants. Also avoid re-inserting search placeholders when an MB/search indicator already exists before the Qobuz link. Search placeholders are still removed when a real MB link is inserted, since the resolved icon replaces the fallback search link. --- qobuz_importer.user.js | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/qobuz_importer.user.js b/qobuz_importer.user.js index 48a4420..8ebea04 100644 --- a/qobuz_importer.user.js +++ b/qobuz_importer.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name Import Qobuz releases to MusicBrainz // @description Add a button on Qobuz's album pages to open MusicBrainz release editor with pre-filled data for the selected release -// @version 2026.06.09.1 +// @version 2026.07.19.1 // @namespace https://github.com/murdos/musicbrainz-userscripts // @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/qobuz_importer.user.js // @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/qobuz_importer.user.js @@ -515,13 +515,48 @@ function removeMbSearchLinksBefore(element) { } } +/* + * Search placeholders are only useful before an unresolved Qobuz link. If a placeholder or resolved MB icon is already there, leave the DOM as-is. + */ +function hasMbIndicatorBeforeElement(element) { + const sibling = element.previousElementSibling; + return Boolean(sibling?.classList.contains('mb_searchit') || sibling?.matches('a[href^="https://musicbrainz.org/"]')); +} + function insertMbSearchLinkBeforeElement(element, mb_type, entityName) { - removeMbSearchLinksBefore(element); + if (hasMbIndicatorBeforeElement(element)) { + return; + } element.insertAdjacentHTML('beforebegin', createMbSearchLink(mb_type, entityName)); } +/* + * Extract the MB href from the generated link HTML so alias lookups can be deduped by target entity, not by the Qobuz URL variant that found it. + */ +function getLinkHref(link) { + const template = document.createElement('template'); + template.innerHTML = link.trim(); + const anchor = template.content.querySelector('a[href]'); + return anchor?.href; +} + +/* + * Discography pages query several URL forms for the same Qobuz entity. When two aliases resolve to the same MB URL, avoid inserting the same icon twice. + */ +function hasMbLinkBeforeElement(element, href) { + let sibling = element.previousElementSibling; + while (sibling?.classList.contains('mb_searchit') || sibling?.matches('a[href^="https://musicbrainz.org/"]')) { + if (sibling instanceof HTMLAnchorElement && sibling.href === href) { + return true; + } + sibling = sibling.previousElementSibling; + } + return false; +} + function insertMbLinkBeforeElements(elements, link) { const styledLink = link.replace('