From 7d474f9857ee7f4a56cc7d00b6d6dee0cd696f55 Mon Sep 17 00:00:00 2001 From: Paul <203217+uniquePWD@users.noreply.github.com> Date: Tue, 3 Feb 2026 08:10:43 +0000 Subject: [PATCH] Update deezer_importer.user.js Fixes broken Deezer import script --- deezer_importer.user.js | 264 ++++++++++++++++++++-------------------- 1 file changed, 135 insertions(+), 129 deletions(-) diff --git a/deezer_importer.user.js b/deezer_importer.user.js index 6e52286..1438a60 100644 --- a/deezer_importer.user.js +++ b/deezer_importer.user.js @@ -1,159 +1,165 @@ // ==UserScript== -// @name Import Deezer releases into MusicBrainz +// @name Import Deezer releases into MusicBrainz (API & UI Fix) // @namespace https://github.com/murdos/musicbrainz-userscripts/ -// @description One-click importing of releases from deezer.com into MusicBrainz -// @version 2025.9.28 +// @description One-click importing of releases from deezer.com into MusicBrainz using the Deezer API +// @version 2026.02.03.2 // @downloadURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/deezer_importer.user.js // @updateURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/deezer_importer.user.js -// @match https://www.deezer.com/*/album/* +// @match https://www.deezer.com/* // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js -// @require lib/mbimport.js -// @require lib/logger.js -// @require lib/mbimportstyle.js +// @require https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/lib/mbimport.js +// @require https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/lib/logger.js +// @require https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/lib/mbimportstyle.js // @icon https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/assets/images/Musicbrainz_import_logo.png // @grant GM_xmlhttpRequest -// @grant GM.xmlHttpRequest // ==/UserScript== -// prevent JQuery conflicts, see http://wiki.greasespot.net/@grant this.$ = this.jQuery = jQuery.noConflict(true); -$(document).ready(function () { - let gmXHR; +(function () { + 'use strict'; - if (typeof GM_xmlhttpRequest != 'undefined') { - gmXHR = GM_xmlhttpRequest; - } else if (GM.xmlHttpRequest != 'undefined') { - gmXHR = GM.xmlHttpRequest; - } else { - LOGGER.error('Userscript requires GM_xmlHttpRequest or GM.xmlHttpRequest'); - return; + // --- Helpers --- + function getAlbumId() { + const match = window.location.pathname.match(/\/album\/(\d+)/); + return match ? match[1] : null; } - // allow 1 second for Deezer SPA to initialize - window.setTimeout(function () { - MBImportStyle(); - let releaseUrl = window.location.href.replace(/\?.*$/, '').replace(/#.*$/, ''); - let releaseId = releaseUrl.replace(/^https?:\/\/www\.deezer\.com\/[^/]+\/album\//i, ''); - let deezerApiUrl = `https://api.deezer.com/album/${releaseId}`; - - gmXHR({ - method: 'GET', - url: deezerApiUrl, - onload: function (resp) { - try { - let release = parseDeezerRelease(releaseUrl, JSON.parse(resp.responseText)); - insertLink(release, releaseUrl); - } catch (e) { - LOGGER.error('Failed to parse release: ', e); + function parseDuration(duration) { + return duration * 1000; + } + + // --- Main Logic --- + async function fetchAndImport(albumId) { + const apiUrl = `https://api.deezer.com/album/${albumId}`; + + GM_xmlhttpRequest({ + method: "GET", + url: apiUrl, + onload: function (response) { + if (response.status === 200) { + const data = JSON.parse(response.responseText); + if (data.error) return; + renderButton(data); } - }, - onerror: function (resp) { - LOGGER.error('AJAX status:', resp.status); - LOGGER.error('AJAX response:', resp.responseText); - }, + } }); - }, 1000); -}); - -function parseDeezerRelease(releaseUrl, data) { - let releaseDate = data.release_date.split('-'); - - let release = { - artist_credit: [], - title: data.title, - year: releaseDate[0], - month: releaseDate[1], - day: releaseDate[2], - packaging: 'None', - country: 'XW', - status: 'official', - language: 'eng', - script: 'Latn', - type: '', - urls: [], - labels: [], - discs: [], - }; - - $.each(data.contributors, function (index, artist) { - if (artist.role != 'Main') return true; - - let ac = { - artist_name: artist.name, - joinphrase: index == data.contributors.length - 1 ? '' : ', ', + } + + function renderButton(data) { + const release = { + title: data.title, + artist_credit: MBImport.makeArtistCredits([data.artist.name]), + type: data.record_type === 'single' ? 'single' : 'album', + status: 'official', + language: 'eng', + script: 'Latn', + barcode: data.upc, + labels: data.label ? [{ name: data.label, catno: '' }] : [], + urls: [{ url: data.link, link_type: MBImport.URL_TYPES.stream_for_free }], + discs: [] }; - if (artist.name == 'Various Artists') { - ac = MBImport.specialArtist('various_artists', ac); + if (data.release_date) { + const dateParts = data.release_date.split('-'); + release.year = dateParts[0]; + release.month = dateParts[1]; + release.day = dateParts[2]; } - release.artist_credit.push(ac); - }); + const tracks = data.tracks.data; + const discs = {}; - let disc = { - format: 'Digital Media', - title: '', - tracks: [], - }; - - $.each(data.tracks.data, function (index, track) { - let t = { - number: index + 1, - title: track.title_short, - duration: track.duration * 1000, - artist_credit: [], - }; + tracks.forEach(track => { + const discNum = track.disk_number || 1; + if (!discs[discNum]) { + discs[discNum] = { tracks: [], format: 'Digital Media' }; + } - // ignore pointless "(Original Mix)" in title version - if (track.title_version && !track.title_version.match(/^\s*\(Original Mix\)\s*$/i)) { - t.title += ` ${track.title_version}`; - } + const trackObj = { + title: track.title, + duration: parseDuration(track.duration), + artist_credit: [] + }; - t.artist_credit.push({ artist_name: track.artist.name }); + if (track.artist.name !== data.artist.name && data.artist.name === "Various Artists") { + trackObj.artist_credit = MBImport.makeArtistCredits([track.artist.name]); + } - disc.tracks.push(t); - }); + if (trackObj.title.match(/\(Original Mix\)/i)) { + trackObj.title = trackObj.title.replace(/\s*\(Original Mix\)\s*/i, ""); + } + + discs[discNum].tracks.push(trackObj); + }); - release.discs.push(disc); + Object.keys(discs).sort().forEach(k => { + release.discs.push(discs[k]); + }); - release.urls.push({ - link_type: MBImport.URL_TYPES.stream_for_free, - url: releaseUrl, - }); - release.labels.push({ name: data.label }); - release.type = data.record_type; - release.barcode = data.upc; - - return release; -} - -function waitForEl(selector, callback) { - if (jQuery(selector).length) { - callback(); - } else { - setTimeout(function () { - waitForEl(selector, callback); - }, 100); + insertLink(release, data.link); } -} - -function insertLink(release, release_url) { - let editNote = MBImport.makeEditNote(release_url, 'Deezer'); - let parameters = MBImport.buildFormParameters(release, editNote); - - let mbUI = $( - `
`, - ).hide(); - waitForEl('[data-testid="toolbar"]', function () { - $('[data-testid="toolbar"]').css({ + + function insertLink(release, releaseUrl) { + $('#mb_import_container').remove(); + + const editNote = MBImport.makeEditNote(releaseUrl, 'Deezer'); + const parameters = MBImport.buildFormParameters(release, editNote); + + const mbUI = $(` +