Harmony: Re-Lookup MusicBrainz Release

Adds a link to re-lookup a release from the Harmony release actions page.

// ==UserScript==
// @name        Harmony: Re-Lookup MusicBrainz Release
// @namespace   https://musicbrainz.org/user/chaban
// @version     2.1
// @description Adds a link to re-lookup a release from the Harmony release actions page.
// @tag         ai-created
// @author      chaban
// @license     MIT
// @match       *://harmony.pulsewidth.org.uk/release/actions
// @icon        https://harmony.pulsewidth.org.uk/harmony-logo.svg
// @grant       none
// ==/UserScript==

(function() {
    'use strict';

    /**
     * Extracts a URL parameter by name.
     * @param {string} name - The name of the URL parameter.
     * @param {URLSearchParams} params - The URLSearchParams object.
     * @returns {string|null} The value of the parameter, or null if not found.
     */
    function getUrlParameter(name, params) {
        return params.get(name);
    }

    /**
     * Finds an H2 element containing specific text.
     * @param {string} text - The text to search for within the H2 element.
     * @returns {HTMLHeadingElement|null} The found H2 element, or null if not found.
     */
    function findH2ByText(text) {
        return Array.from(document.querySelectorAll('h2')).find(h2 => h2.textContent.includes(text));
    }

    const url = new URL(window.location.href);
    const params = url.searchParams;

    if (params.has('release_mbid')) {
        const mbidFromUrl = getUrlParameter('release_mbid', params);

        if (mbidFromUrl) {
            const providerIds = {
                musicbrainz: mbidFromUrl
            };

            const providerListItems = document.querySelectorAll('.provider-list li');

            providerListItems.forEach(item => {
                const providerName = item.getAttribute('data-provider');
                const providerIdElement = item.querySelector('.provider-id');

                if (providerName && providerIdElement) {
                    const paramName = providerName.toLowerCase();
                    const id = providerIdElement.textContent.trim();

                    providerIds[paramName] = id;
                }
            });

            const harmonyParams = new URLSearchParams();
            harmonyParams.set('gtin', '');
            harmonyParams.set('region', 'us');
            harmonyParams.set('category', 'preferred');

            for (const provider in providerIds) {
                if (Object.prototype.hasOwnProperty.call(providerIds, provider) && providerIds[provider]) {
                    harmonyParams.set(provider, providerIds[provider]);
                }
            }
            const harmonyLookupUrl = `https://harmony.pulsewidth.org.uk/release?${harmonyParams.toString()}`;

            const releaseActionsH2 = findH2ByText('Release Actions');

            if (releaseActionsH2) {
                const newDiv = document.createElement('div');
                newDiv.classList.add('message');

                const svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
                svgIcon.classList.add('icon');
                svgIcon.setAttribute('width', '24');
                svgIcon.setAttribute('height', '24');
                svgIcon.setAttribute('stroke-width', '2');

                const useElement = document.createElementNS('http://www.w3.org/2000/svg', 'use');
                useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '/icon-sprite.svg#brand-metabrainz');
                svgIcon.appendChild(useElement);

                const linkParagraph = document.createElement('p');
                const link = document.createElement('a');
                link.href = harmonyLookupUrl;
                link.textContent = 'Re-Lookup with Harmony';
                linkParagraph.appendChild(link);

                newDiv.appendChild(svgIcon);
                newDiv.appendChild(linkParagraph);

                releaseActionsH2.parentNode.insertBefore(newDiv, releaseActionsH2.nextSibling);
            }
        }
    }
})();