Raw Source
jesus2099 / mb. PREFERRED MBS

// ==UserScript==
// @name         mb. PREFERRED MBS
// @version      2026.5.6
// @description  Choose your favourite MusicBrainz server (MBS) (main/beta/test/eu) / Stay in current MBS
// @namespace    https://github.com/jesus2099/konami-command
// @supportURL   https://github.com/jesus2099/konami-command/labels/mb_PREFERRED-MBS
// @downloadURL  https://github.com/jesus2099/konami-command/raw/master/mb_PREFERRED-MBS.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        2016-01-12; inspiration by https://web.archive.org/web/20140712013355/userscripts-mirror.org/scripts/show/487275
// @icon         data:image/gif;base64,R0lGODlhEAAQAMIDAAAAAIAAAP8AAP///////////////////yH5BAEKAAQALAAAAAAQABAAAAMuSLrc/jA+QBUFM2iqA2ZAMAiCNpafFZAs64Fr66aqjGbtC4WkHoU+SUVCLBohCQA7
// @grant        none
// @include      /^https?:\/\//
// @run-at       document-start
// ==/UserScript==
"use strict";
/* ----------------------------------------------- */
/* preferred_mbs can be either (there is no more HTTP)
 * https://musicbrainz.org or https://beta.musicbrainz.org or https://test.musicbrainz.org or https://musicbrainz.eu
 * it is not intended to work with any other values */
var preferred_mbs = "https://musicbrainz.org";
/* ----------------------------------------------- */
/* Simple Discourse click tracker problem work-around ------------- */
var discourse_url = location.href.match(/^https?:\/\/community\.metabrainz\.org\/clicks\/track\?url=([^?&]+)/);
if (discourse_url) {
	location.replace(decodeURIComponent(discourse_url[1]));
}
/* ---------------------------------------------------------------- */
var is_mbs = location.host.match(/^(musicbrainz\.eu|((beta|test)\.)?musicbrainz\.org)$/i);
// MBS-13728 bug: Annotation, edit note, collection description and user biography pasted MB links: Should always stay in same MBS (eu/org, beta/main)
// https://tickets.metabrainz.org/browse/MBS-13728
var MBS_13728_bug = "/* many paths */ .edit-note-text, /* /collection/<mbid> */ .description, /* /user/.+ */ .profileinfo .biography";
preferred_mbs = leftTrim(preferred_mbs);
if (!is_mbs) {
	// Redirect importers to preferred MBS
	document.addEventListener("submit", function(event) {
		var element = event.target || event.srcElement;
		if (element && element.nodeType == Node.ELEMENT_NODE && element.tagName == "FORM") {
			var action = element.getAttribute("action");
			if (action && !action.match(/oauth/) && !element.querySelector("input[type='password']")) {
				var new_action = prefer(action);
				if (new_action) {
					var urlInput = element.querySelector("input[name='url']");
					if (urlInput) {
						var newUrl = prefer(urlInput.value);
						if (newUrl) {
							urlInput.value = newUrl;
						}
					}
					element.setAttribute("action", new_action);
					element.style.setProperty("background-color", "#cfc");
				}
			}
		}
	}, true);
}
// Redirect links to preferred MBS
// Non-MBS websites: All MBS links
// MBS websites: Edit note text links only https://tickets.metabrainz.org/browse/MBS-13728
document.addEventListener("mousedown", function(event) {
	var element = event.target || event.srcElement;
	if (element && element.nodeType == Node.ELEMENT_NODE) {
		if (element.tagName != "A") {
			element = element.closest("a");
		}
		if (
			element
			&& element.matches("a:not(.jesus2099-bypass-mb_PREFERRED-MBS)") // mb_SUPER-MIND-CONTROL-II-X-TURBO server switcher
			&& (
				!is_mbs
				|| element.closest(MBS_13728_bug)
			)
		) {
			process(element);
		}
	}
});
function process(anchor) {
	var href = anchor.getAttribute("href");
	if (href) {
		var new_href;
		if (anchor.closest(MBS_13728_bug)) {
			// Stay in current MBS when clicking edit note links (annotations are doing it natively OK)
			// Test at:
			// https://musicbrainz.org/edit/1736776
			// https://beta.musicbrainz.org/collection/ece5ad67-e46a-4936-b466-693031a719e0
			// https://beta.musicbrainz.org/user/jesus2099
			new_href = prefer(href, location.protocol + "//" + location.host);
		} else {
			new_href = prefer(href);
		}
		if (new_href) {
			anchor.setAttribute("href", new_href);
			anchor.style.setProperty("background-color", "#cfc");
			anchor.style.setProperty("color", "#606");
			anchor.style.setProperty("text-decoration", "line-through");
			var tooltip = anchor.getAttribute("title") || "";
			if (tooltip) {
				tooltip += "\n";
			}
			anchor.setAttribute("title", tooltip + "old: " + href + "\nnew: " + new_href);
		}
	}
}
function prefer(url, forced_mbs) {
	var new_url = forced_mbs ? forced_mbs : preferred_mbs;
	var matched_url = url.trim().match(/^(https?:)?(\/\/)?(((beta|test)\.)?musicbrainz\.(org|eu)(:\d+)?)(?<path>\/.*)?(?<query>\?.*)?(?<hash>#.*)?$/);
	if (matched_url) {
		if (matched_url.groups.path) {
			new_url += matched_url.groups.path;
		}
		if (matched_url.groups.query) {
			new_url += matched_url.groups.query;
		}
		if (matched_url.groups.hash) {
			new_url += matched_url.groups.hash;
		}
		if (new_url && new_url != (forced_mbs ? forced_mbs : preferred_mbs) && leftTrim(new_url) != leftTrim(url)) {
			return new_url;
		}
	}
}
function leftTrim(url) {
	var trimmed_url = url;
	if (trimmed_url.indexOf(location.protocol) === 0) {
		trimmed_url = trimmed_url.replace(/^https?:/, "");
	}
	if (trimmed_url.indexOf("//" + location.host) === 0) {
		trimmed_url = trimmed_url.replace(new RegExp("^//" + location.host), "");
	}
	return trimmed_url;
}