Skip to content

Commit a40ff3e

Browse files
authored
feat(qobuz_importer): add artist and label page linking with MB (#755)
- had to add the query string param to the library file as the client caches them for unknown period of time and this is the only way I found to get the fresh version;
1 parent 14f73a5 commit a40ff3e

1 file changed

Lines changed: 148 additions & 11 deletions

File tree

qobuz_importer.user.js

Lines changed: 148 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// ==UserScript==
22
// @name Import Qobuz releases to MusicBrainz
33
// @description Add a button on Qobuz's album pages to open MusicBrainz release editor with pre-filled data for the selected release
4-
// @version 2025.10.07.1
4+
// @version 2025.12.21.1
55
// @namespace https://github.com/murdos/musicbrainz-userscripts
66
// @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/qobuz_importer.user.js
77
// @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/qobuz_importer.user.js
8-
// @include /^https?://www\.qobuz\.com/[^/]+/album/[^/]+/[^/]+$/
8+
// @include /^https?://www\.qobuz\.com/[^/]+/(album|interpreter|label)(/[^/?]+)+(\?.*)?$/
99
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
1010
// @require lib/mbimport.js
1111
// @require lib/logger.js
12-
// @require lib/mblinks.js
12+
// @require lib/mblinks.js?version=v2025.12.21.1
1313
// @require lib/mbimportstyle.js
1414
// @icon https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/assets/images/Musicbrainz_import_logo.png
1515
// @run-at document-start
@@ -419,11 +419,118 @@ function lookupLabelAndDisplayLinks({ release, mblinks }) {
419419
}
420420
}
421421

422-
$(document).ready(function () {
423-
MBImportStyle();
422+
/**
423+
* Check if the URL has a locale and return both the URL with and without the locale.
424+
*/
425+
function getEntityUrls(url, locale) {
426+
if (url.includes(`/${locale}/`)) {
427+
return [url, url.replace(`/${locale}/`, '/')];
428+
} else {
429+
return [url];
430+
}
431+
}
424432

425-
// Initialize MBLinks for checking already imported releases
426-
let mblinks = new MBLinks('QOBUZ_MBLINKS_CACHE');
433+
function processDiscographyPage({ mblinks, locale }) {
434+
const items = document.querySelectorAll('.product__item');
435+
const artist_urls_data = [];
436+
const label_urls_data = [];
437+
const album_urls_data = [];
438+
const artist_urls_map = new Map();
439+
const label_urls_map = new Map();
440+
const album_urls_map = new Map();
441+
442+
// Collect all artist links from the page
443+
for (const item of items) {
444+
const container = item.querySelector('.product__container');
445+
if (!container) {
446+
continue;
447+
}
448+
const artist_link = container.querySelector('a[href*="interpreter"]');
449+
if (artist_link && artist_link instanceof HTMLAnchorElement && artist_link.href) {
450+
const artist_url = artist_link.href.split('?')[0].split('#')[0];
451+
const artist_urls = getEntityUrls(artist_url, locale);
452+
artist_urls.forEach(url => {
453+
if (!artist_urls_map.has(url)) {
454+
artist_urls_map.set(url, []);
455+
}
456+
artist_urls_map.get(url).push(artist_link);
457+
});
458+
}
459+
460+
const label_link = container.querySelector('a[href*="label"]');
461+
if (label_link && label_link instanceof HTMLAnchorElement && label_link.href) {
462+
const label_url = label_link.href.split('?')[0].split('#')[0];
463+
const label_urls = getEntityUrls(label_url, locale);
464+
label_urls.forEach(url => {
465+
if (!label_urls_map.has(url)) {
466+
label_urls_map.set(url, []);
467+
}
468+
label_urls_map.get(url).push(label_link);
469+
});
470+
}
471+
472+
const album_link = container.querySelector('a[href*="album"]');
473+
if (album_link && album_link instanceof HTMLAnchorElement && album_link.href) {
474+
const album_url = album_link.href.split('?')[0].split('#')[0];
475+
const album_urls = getEntityUrls(album_url, locale);
476+
album_urls.forEach(url => {
477+
if (!album_urls_map.has(url)) {
478+
album_urls_map.set(url, []);
479+
}
480+
album_urls_map.get(url).push(album_link);
481+
});
482+
}
483+
}
484+
485+
// Build urls_data array for batch processing
486+
artist_urls_map.forEach((artist_link_elements, artist_url) => {
487+
artist_urls_data.push({
488+
url: artist_url,
489+
mb_type: 'artist',
490+
insert_func: function (link) {
491+
// Insert the MusicBrainz link before each artist link
492+
artist_link_elements.forEach(artist_link_element => {
493+
artist_link_element.insertAdjacentHTML('beforebegin', link);
494+
});
495+
},
496+
key: `artist:${artist_url}`,
497+
});
498+
});
499+
500+
label_urls_map.forEach((label_link_elements, label_url) => {
501+
label_urls_data.push({
502+
url: label_url,
503+
mb_type: 'label',
504+
insert_func: function (link) {
505+
label_link_elements.forEach(label_link_element => {
506+
label_link_element.insertAdjacentHTML('beforebegin', link);
507+
});
508+
},
509+
key: `label:${label_url}`,
510+
});
511+
});
512+
513+
album_urls_map.forEach((album_link_elements, album_url) => {
514+
album_urls_data.push({
515+
url: album_url,
516+
mb_type: 'release',
517+
insert_func: function (link) {
518+
album_link_elements.forEach(album_link_element => {
519+
album_link_element.insertAdjacentHTML('beforebegin', link);
520+
});
521+
},
522+
key: `release:${album_url}`,
523+
});
524+
});
525+
526+
// Batch retrieve and display links
527+
mblinks.searchAndDisplayMbLinks(artist_urls_data);
528+
mblinks.searchAndDisplayMbLinks(label_urls_data);
529+
mblinks.searchAndDisplayMbLinks(album_urls_data);
530+
}
531+
532+
function processReleasePage({ mblinks }) {
533+
MBImportStyle();
427534

428535
extractAlbumData()
429536
.then(raw_release_data => {
@@ -441,10 +548,40 @@ $(document).ready(function () {
441548
// Replace the image zoom link with the maximum size image link
442549
const ogImageMetaElement = document.querySelector('meta[property="og:image"]');
443550
if (ogImageMetaElement) {
444-
let maxImgURL = ogImageMetaElement.getAttribute('content').replace('_600', '_max');
445-
document.querySelectorAll('img.album-cover__image').forEach(imgElement => {
446-
imgElement.setAttribute('src', maxImgURL);
447-
});
551+
const content = ogImageMetaElement.getAttribute('content');
552+
if (content) {
553+
let maxImgURL = content.replace('_600', '_max');
554+
document.querySelectorAll('img.album-cover__image').forEach(imgElement => {
555+
imgElement.setAttribute('src', maxImgURL);
556+
});
557+
}
558+
}
559+
}
560+
561+
$(document).ready(function () {
562+
// Initialize MBLinks for checking already imported releases
563+
const mblinks = new MBLinks('QOBUZ_MBLINKS_CACHE');
564+
const pageTypeRegex = new RegExp(`^\\/([a-z]{2}-[a-z]{2})?(?:\\/)?(interpreter|album|label)\\/`);
565+
566+
const locale = window.location.pathname.match(pageTypeRegex)?.[1];
567+
const pageType = window.location.pathname.match(pageTypeRegex)?.[2];
568+
569+
if (!pageType) {
570+
return;
571+
} else {
572+
switch (pageType) {
573+
case 'interpreter':
574+
processDiscographyPage({ mblinks, locale });
575+
break;
576+
case 'album':
577+
processReleasePage({ mblinks });
578+
break;
579+
case 'label':
580+
processDiscographyPage({ mblinks, locale });
581+
break;
582+
default:
583+
return;
584+
}
448585
}
449586
});
450587

0 commit comments

Comments
 (0)