// ==UserScript== // @name MusicBrainz: Batch-add "performance of" relationships // @version 2011-09-16~1 // @author bitmap + some code from nikki // @include http://musicbrainz.org/artist/*/recordings* // @include http://test.musicbrainz.org/artist/*/recordings* // ==/UserScript== //**************************************************************************// var content = document.getElementById("content"), forms = document.getElementsByTagName("form"), form = forms[forms.length-1], trs = [], rows = [], checked = iid = null, current = 0, button1 = createButton("Query relationships of checked recordings"), button2 = createButton("Go"), button3 = createButton("Go"), input1 = document.createElement("input"), input2 = document.createElement("input"), mbid_patt=/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/; function get_rows() { rows = []; trs = document.getElementsByTagName("tr"); for (var i = 0; i < trs.length; i++) { var tr = trs[i], attr = tr.getAttribute("xmlns:rec"); if (!attr) continue; var mbid = attr.match(mbid_patt); var tds = tr.getElementsByTagName("td"), inp = tds[0].getElementsByTagName("input")[0]; rows.push([mbid, inp, tds[1]]); } } get_rows(); var table = document.createElement("table"); table.innerHTML = '\ \  '; var trs = table.getElementsByTagName("tr"); trs[0].getElementsByTagName("td")[0].appendChild(button1); var removeinput = trs[0].getElementsByTagName("td")[1].getElementsByTagName("input")[0]; trs[1].getElementsByTagName("td")[0].textContent = "Relate checked recordings to new work with this title:"; trs[1].getElementsByTagName("td")[1].appendChild(input1); trs[1].getElementsByTagName("td")[1].appendChild(button2); trs[2].getElementsByTagName("td")[0].textContent = "Relate checked recordings to existing work (URL/MBID):"; trs[2].getElementsByTagName("td")[1].appendChild(input2); trs[2].getElementsByTagName("td")[1].appendChild(button3); var foo = trs[3].getElementsByTagName("input"), coverinput = foo[0], liveinput = foo[1]; content.insertBefore(table, form); function createButton(text) { var button = document.createElement("button"); button.textContent = text; styleButton(button); return button; } function styleButton(button) { button.style.color = "#565656"; button.style.backgroundColor = "#F0F0F0"; button.style.border = "1px solid #D0D0D0"; button.style.borderTop = "1px solid #EAEAEA"; button.style.borderLeft = "1px solid #EAEAEA"; } button1.addEventListener("click", start_queries, false); button2.addEventListener("click", function() { if (!input1.value) { alert("Please enter a title."); return; } add_work(); }, false); button3.addEventListener("click", function() { var m = input2.value.match(mbid_patt); if (!m) { alert("Please enter a valid MBID."); return; } relate_to_work(m[0]); }, false); function start_queries() { checked = get_checked(); if (checked.length == 0) return; current = 0; iid = window.setInterval(loop, 1000); button1.removeEventListener("click", start_queries, false); button1.addEventListener("click", cancel_queries, false); button1.textContent = "Cancel queries"; }; function cancel_queries() { window.clearInterval(iid); button1.removeEventListener("click", cancel_queries, false); button1.addEventListener("click", start_queries, false); button1.textContent = "Query relationships of checked recordings"; get_rows(); }; function get_checked() { var elems = []; for (var i = 0; i < rows.length; i++) if (rows[i][1].checked) elems.push(rows[i]); return elems; } function loop() { var tr = checked[current]; query_recording(tr); current++; if (current == checked.length) cancel_queries(); } function query_recording(row) { wsurl = "http://musicbrainz.org/ws/2/recording/"+row[0]+"?inc=work-rels", a = row[2].getElementsByTagName("a")[0]; get_(wsurl, row[2]); a.style.color = "purple"; } function add_work() { var data = 'edit-work.name=' + input1.value; var w_url = 'http://musicbrainz.org/work/create'; post(w_url, data, function (doc) { var m = doc.match(/\/work\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/); w_mbid = m[1]; relate_to_work(w_mbid); }); } function relate_to_work(w_mbid) { var checked = get_checked(); for (var i = 0; i < checked.length; i++) { var row = checked[i]; rel_url = 'http://musicbrainz.org/edit/relationship/create?type1=work&entity1='+w_mbid+'&type0=recording&entity0='+row[0], data = 'ar.as_auto_editor=1&ar.link_type_id=278&type1=work&entity1='+w_mbid+'&type0=recording&entity0='+row[0]; console.log(liveinput.checked); if (coverinput.checked) data += "ar.attrs.cover=1"; if (liveinput.checked) data += "&ar.attrs.live=1"; post(rel_url, data, function(r) { return function() {query_recording(r);}; }(row)); } } function success1(doc, td) { var rels = doc.getElementsByTagName("relation"), children = td.childNodes; for (var i = 0; i < children.length; i++) { var child = children[i]; if (child.nodeName == "span" && child.className != "comment") td.removeChild(child); } for (var i = 0; i < rels.length; i++) { var rel = rels[i]; if (!rel.attributes[0].value.match(/performance/)) continue; var nodes = rel.childNodes, wmbid = wtitle = cover = live = ""; for (var j = 0; j < nodes.length; j++) { var node = nodes[j]; if (node.nodeName == "target") wmbid = node.childNodes[0].nodeValue; if (node.nodeName == "work") wtitle=node.getElementsByTagName("title")[0].childNodes[0].nodeValue; if (node.nodeName == "attribute-list") { for (var k = 0; k < node.childNodes.length; k++) { var child = node.childNodes[k], value = child.childNodes[0].nodeValue; if (value == "cover") cover = "cover "; if (value == "live") live = "live "; } } } var wurl = "/work/" + wmbid, txt = "• "+live+cover+"performance of "+wtitle+"", span = document.createElement("span"); span.innerHTML = txt; td.innerHTML += "
"; td.appendChild(span); } } function success2(doc, td) { var rels = doc.getElementsByTagName("relation"); for (var i = 0; i < rels.length; i++) { var rel = rels[i]; if (rel.attributes[0].value.match(/performance/)) { td.parentNode.parentNode.removeChild(td.parentNode); } } } function get_(url, td) { var req = new XMLHttpRequest(); req.open("GET", url, true); req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) if (!removeinput.checked) success1(req.responseXML, td); else success2(req.responseXML, td); } req.send(null); } function post(url, data, success) { var req = new XMLHttpRequest(); req.open("POST", url, true); req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) success(req.responseText); } req.send(data); }