-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbandcamp-tag-importer.user.js
122 lines (115 loc) · 5.36 KB
/
bandcamp-tag-importer.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// ==UserScript==
// @name MusicBrainz Bandcamp Tag Importer
// @version 2024.7.22
// @namespace https://github.com/zabe40
// @author zabe
// @description Easily submit tags on Bandcamp pages to Musicbrainz
// @homepageURL https://github.com/zabe40/musicbrainz-userscripts#musicbrainz-bandcamp-tag-importer
// @downloadURL https://raw.github.com/zabe40/musicbrainz-userscripts/main/dist/bandcamp-tag-importer.user.js
// @updateURL https://raw.github.com/zabe40/musicbrainz-userscripts/main/dist/bandcamp-tag-importer.user.js
// @supportURL https://github.com/zabe40/musicbrainz-userscripts/issues
// @grant GM_xmlhttpRequest
// @connect bandcamp.com
// @match *://*.musicbrainz.org/release/*
// @match *://*.musicbrainz.eu/release/*
// ==/UserScript==
(function () {
'use strict';
function fetchURL(url, options){
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: url,
onload: function(response){
if(400 <= response.status){
reject(new Error(`HTTP error! Status: ${response.status}`,
{ cause: response}));
}else {
resolve(response);
}
},
onabort: function(error){
reject(new Error("The request was aborted.",
{ cause: error}));
},
onerror: function(error){
reject(new Error("There was an error with the request. See the console for more details.",
{ cause: error}));
},
ontimeout: function(error){
reject(new Error("The request timed out.",
{ cause: error}));
},
...options,
});
});
}
function displayError(button, error){
let errorMessage = button.parentElement.querySelector("p.bandcamp-tag-importer-error");
if(!errorMessage){
errorMessage = document.createElement("p");
errorMessage.style.wordBreak = "break-word";
errorMessage.className = "error bandcamp-tag-importer-error";
button.insertAdjacentElement("afterend", errorMessage);
}
errorMessage.textContent = error.message;
}
function clearError(button){
let p = button.parentElement.querySelector("p.bandcamp-tag-importer-error");
if(p){
p.remove();
}
}
function importTags(url, button){
button.disabled = true;
clearError(button);
fetchURL(url)
.then(function(response){
const html = response.responseText;
const parser = new DOMParser();
let doc = parser.parseFromString(html, "text/html");
const input = document.querySelector(".tag-input");
const hasLocation = doc.querySelector(".location").textContent != "";
doc.querySelectorAll("a.tag")
.forEach((currentAnchor, currentIndex, listObj) => {
// on Bandcamp the last tag on an album is a tag
// of the location in the artist's profile (if the
// artist has included this in their profile).
// this information is often innaccurate (in the
// case of labels with Bandcamp pages) or
// outdated, and regardless the information is
// better represented via a relationship of some
// sort
if(!hasLocation || (currentIndex != listObj.length - 1)){
if(currentAnchor.innerText.includes(",")){
// Bandcamp tags can have commas, MusicBrainz tags cannot
// see https://bandcamp.com/discover/,
alert("The tag ${currentAnchor.innerText} includes a comma, which cannot be part of a tag.\nFor more information, see https://musicbrainz.org/doc/Folksonomy_Tagging.");
}
if(input.value != ""){
input.value += ",";
}
input.value += currentAnchor.innerText;
}
});
button.disabled = false;
input.focus();
})
.catch(function(error){
console.warn(error);
displayError(button, error);
})
.finally(function(){
button.disabled = false;
});
}
function addImportTagsButton(currentAnchor, _currentIndex, _listObj){
let importButton = document.createElement('button');
importButton.addEventListener("click", (function(){importTags(currentAnchor.href, importButton);}));
importButton.type = 'button';
importButton.innerHTML = "Tag";
importButton.className = 'styled-button';
importButton.style.float = 'right';
currentAnchor.parentElement.appendChild(importButton);
}
document.querySelectorAll(".bandcamp-favicon > a").forEach(addImportTagsButton);
})();