Skip to content

Commit 209c4b1

Browse files
authored
feat(bandcamp,qobuz): add support to display ended release links in grayscale (#830)
1 parent 53a39b0 commit 209c4b1

File tree

3 files changed

+38
-18
lines changed

3 files changed

+38
-18
lines changed

bandcamp_importer.user.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ==UserScript==
22
// @name Import Bandcamp releases to MusicBrainz
33
// @description Add a button on Bandcamp's album pages to open MusicBrainz release editor with pre-filled data for the selected release
4-
// @version 2026.03.05.3
4+
// @version 2026.03.05.4
55
// @namespace http://userscripts.org/users/22504
66
// @downloadURL https://raw.github.com/murdos/musicbrainz-userscripts/master/bandcamp_importer.user.js
77
// @updateURL https://raw.github.com/murdos/musicbrainz-userscripts/master/bandcamp_importer.user.js
@@ -11,7 +11,7 @@
1111
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
1212
// @require lib/mbimport.js
1313
// @require lib/logger.js
14-
// @require lib/mblinks.js?version=v2026.03.05.2
14+
// @require lib/mblinks.js?version=v2026.03.05.4
1515
// @require lib/mbimportstyle.js
1616
// @icon https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/assets/images/Musicbrainz_import_logo.png
1717
// @grant unsafeWindow

lib/mblinks.js

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,27 @@ const MBLinks = function (user_cache_key, version, expiration) {
4545

4646
if (!relations) return;
4747

48-
const insertedMbUrls = {};
48+
// Build map of mb_url -> ended (true if any relation has ended). Only relevant for release.
49+
const urlData = {};
4950
relations.forEach(relation => {
5051
if (_type in relation) {
5152
const mb_url = `${mblinks.mb_server}/${reference.mb_type}/${relation[_type].id}`;
52-
if (insertedMbUrls[mb_url]) return;
53-
insertedMbUrls[mb_url] = true;
54-
if ($.inArray(mb_url, mblinks.cache[key].urls) === -1) {
55-
mblinks.cache[key].urls.push(mb_url);
56-
}
57-
const link = mblinks.createMusicBrainzLink(mb_url, _type);
58-
matching_urls_data.forEach(m => m.insert_func(link));
53+
if (!(mb_url in urlData)) urlData[mb_url] = { ended: false };
54+
if (relation.ended) urlData[mb_url].ended = true;
5955
}
6056
});
57+
58+
const cacheUrls = mblinks.cache[key].urls;
59+
const getUrl = entry => (typeof entry === 'string' ? entry : entry.url);
60+
Object.keys(urlData).forEach(mb_url => {
61+
const ended = urlData[mb_url].ended;
62+
const alreadyCached = cacheUrls.some(e => getUrl(e) === mb_url);
63+
if (!alreadyCached) {
64+
cacheUrls.push({ url: mb_url, ended: _type === 'release' ? ended : false });
65+
}
66+
const link = mblinks.createMusicBrainzLink(mb_url, _type, _type === 'release' ? { ended } : {});
67+
matching_urls_data.forEach(m => m.insert_func(link));
68+
});
6169
}
6270

6371
this.supports_local_storage = (function () {
@@ -103,7 +111,7 @@ const MBLinks = function (user_cache_key, version, expiration) {
103111
};
104112
this.cache = {};
105113
this.expirationMinutes = typeof expiration != 'undefined' && expiration !== false ? parseInt(expiration, 10) : 90 * 24 * 60; // default to 90 days
106-
let cache_version = 2;
114+
let cache_version = 3;
107115
this.user_cache_key = user_cache_key;
108116
this.cache_key = `${this.user_cache_key}-v${cache_version}${typeof version != 'undefined' ? `.${version}` : ''}`;
109117
this.mb_server = 'https://musicbrainz.org';
@@ -227,17 +235,21 @@ const MBLinks = function (user_cache_key, version, expiration) {
227235
// If the url is not known by the cache, no attempt will be made to request the MusicBrainz webservice, in order to keep this method synchronous.
228236
this.resolveMBID = function (key) {
229237
if (this.is_cached(key) && this.cache[key].urls.length == 1) {
230-
return this.cache[key].urls[0].slice(-36);
238+
const entry = this.cache[key].urls[0];
239+
const mb_url = typeof entry === 'string' ? entry : entry.url;
240+
return mb_url.slice(-36);
231241
}
232242
};
233243

234244
/**
235245
* Create an HTML element for a MusicBrainz link with the given type and URL.
236246
* @param {string} mb_url - The URL of the MusicBrainz entity.
237247
* @param {string} _type - The type of the MusicBrainz entity.
248+
* @param {Object} [options] - Optional options.
249+
* @param {boolean} [options.ended] - When true and type is release, applies grayscale to the icon.
238250
* @returns {string} The HTML for the MusicBrainz link.
239251
*/
240-
this.createMusicBrainzLink = function (mb_url, _type) {
252+
this.createMusicBrainzLink = function (mb_url, _type, options) {
241253
let title = `See this ${_type} on MusicBrainz`;
242254
let img_url = `${this.mb_server}/static/images/entity/${_type}.svg`;
243255
let img_src = `<img src="${img_url}" height=16 width=16 />`;
@@ -248,6 +260,9 @@ const MBLinks = function (user_cache_key, version, expiration) {
248260
if (ti.img_url) img_url = ti.img_url;
249261
if (ti.img_src) img_src = ti.img_src;
250262
}
263+
if (_type === 'release' && options && options.ended) {
264+
img_src = img_src.replace('/>', ' style="filter: grayscale(1)" />');
265+
}
251266
return `<a href="${mb_url}" title="${title}">${img_src}</a> `;
252267
};
253268

@@ -265,7 +280,8 @@ const MBLinks = function (user_cache_key, version, expiration) {
265280

266281
if (!key) key = url;
267282
if (this.is_cached(key)) {
268-
$.each(mblinks.cache[key].urls, function (idx, mb_url) {
283+
$.each(mblinks.cache[key].urls, function (idx, cacheEntry) {
284+
const mb_url = typeof cacheEntry === 'string' ? cacheEntry : cacheEntry.url;
269285
insert_func(mblinks.createMusicBrainzLink(mb_url, _type));
270286
});
271287
if (typeof onComplete === 'function') {
@@ -353,8 +369,12 @@ const MBLinks = function (user_cache_key, version, expiration) {
353369
const key = data.key || data.url;
354370
if (this.is_cached(key)) {
355371
// Handle cached results immediately
356-
$.each(mblinks.cache[key].urls, function (idx, mb_url) {
357-
data.insert_func(mblinks.createMusicBrainzLink(mb_url, data.mb_type.replace('-', '_')));
372+
const data_type = data.mb_type.replace('-', '_');
373+
$.each(mblinks.cache[key].urls, function (idx, cacheEntry) {
374+
const mb_url = typeof cacheEntry === 'string' ? cacheEntry : cacheEntry.url;
375+
const ended = typeof cacheEntry === 'string' ? false : cacheEntry.ended;
376+
const options = data_type === 'release' ? { ended } : {};
377+
data.insert_func(mblinks.createMusicBrainzLink(mb_url, data_type, options));
358378
});
359379
} else {
360380
uncached_urls.push(data);

qobuz_importer.user.js

Lines changed: 2 additions & 2 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 2026.03.05.2
4+
// @version 2026.03.05.3
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
88
// @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?version=v2026.03.05.2
12+
// @require lib/mblinks.js?version=v2026.03.05.3
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

0 commit comments

Comments
 (0)