Supraphon Online: Fetch album info to clipboard

Zkopíruje playlist do schránky tak aby jej bylo možno v hudebním přehrávači aplikovat na tagy

Verze ze dne 03. 08. 2019. Zobrazit nejnovější verzi.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         Supraphon Online: Fetch album info to clipboard
// @namespace    https://www.supraphonline.cz/
// @version      1.0
// @description  Zkopíruje playlist do schránky tak aby jej bylo možno v hudebním přehrávači aplikovat na tagy
// @author       Já, Osobně
// @match        https://www.supraphonline.cz/album/*
// @match        http://www.supraphonline.cz/album/*
// @run-at       document-idle
// @grant        RegExp
// @grant        GM_getValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// @grant        GM_deleteValue
// @grant        GM_xmlhttpRequest
// @grant        GM.xmlHttpRequest
// ==/UserScript==

// Výraz pro 'Automatically Fill Values" funkci ve foobaru2000:
//   %album artist%%album%%date%%releasedate%%genre%%label%%catalog%%discnumber%%totaldiscs%%tracknumber%%totaltracks%%artist%%title%%performer%%composer%%comment%%url%

'use strict';

var buttons = document.getElementsByName('buy');
if (buttons == null) return;
var child = document.createElement('button');
child.id = 'copy-info-to-clipboard';
child.textContent = 'Kopírovat do schránky';
child.type = 'button';
child.name = 'copy-info-to-clipboard';
child.setAttribute('class', 'btn btn-danger topframe_login');
child.addEventListener("click", fetchAlbum, false);
buttons[1].parentNode.insertBefore(child, buttons[1]);
child = document.createTextNode(' ');
buttons[1].parentNode.insertBefore(child, buttons[1]);

function fetchAlbum() {
  var matches, node, results, clipboard = '';
  var album_years, release_year;
  var track, tracks = [], totaldiscs = 1;
  var parser = new DOMParser();
  var req = new XMLHttpRequest();
  var button = document.getElementById('copy-info-to-clipboard');
  if (button != null) {
	button.disabled = true;
	var original_text = button.textContent;
	button.textContent = 'Pracuji...';
  }
  var album_artist = get_string('//h2[@class="album-artist"]/a/text()');
  var album = get_string('//h1[@itemprop="name"]/text()');
  var release_date = get_detail('Datum vydání');
  var genre = get_detail('Žánr');
  var label = get_detail('Vydavatel');
  var catalog = get_detail('Katalogové číslo');
  var desc = get_string('//div[@itemprop="description"]/p');
  var album_singers = get_album_artists('Stěžejní interpreti').sort((a, b) => a[1].localeCompare(b[1]));
  var album_groups = get_album_artists('Hudební tělesa').sort((a, b) => a.localeCompare(b));
  var album_composers = get_album_artists('Stěžejní autoři').sort((a, b) => a[1].localeCompare(b[1]));
  function get_album_artists(label) {
	var result = [];
	results = document.evaluate('//ul/li[h3[text() = "' + label + '"]]/following-sibling::li',
									document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
	if (results.resultType == XPathResult.FIRST_ORDERED_NODE_TYPE) {
	  results = results.singleNodeValue;
	  while (results) {
		if (results.childNodes[0].tagName == 'SPAN') {
		  result.push([
			results.childNodes[0].textContent.replace(/\s*:\s*$/, ''),
			results.childNodes[2].textContent,
		  ]);
		} else if (results.childNodes[1].tagName == 'A') {
		  result.push(results.childNodes[1].textContent);
		}
		results = results.nextSiblingElement;
	  }
	  return result;
	}
	return undefined;
  }
  if (desc) desc = desc.replace(/\r/g, '\\r').replace(/\n/g, '\\n');
  function get_string(xpath, html = document, root = html.body) {
	var node = html.evaluate(xpath, root, null, XPathResult.STRING_TYPE, null);
	return node.resultType == XPathResult.STRING_TYPE ? node.stringValue.trim() : undefined;
  }
  function get_detail(prop) {
	var base = '//ul[@class="summary"]/li[span[starts-with(text(), "' + prop + '")]]';
	return get_string(base + '/text()') || get_string(base + '/a/text()');
  }
  function get_node(xpath, html = document, root = html.body) {
	var node = html.evaluate(xpath, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
	return node.resultType == XPathResult.FIRST_ORDERED_NODE_TYPE ? node.singleNodeValue : null;
  }

  results = document.evaluate('//table[@class="table table-tracklist"]/tbody/tr[@itemprop="track"]',
	document.body, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
  while (node = results.iterateNext()) {
	let cdhdr = get_string('./preceding-sibling::tr[starts-with(@class, "cd-header")][1]/td/h3/text()', document, node);
	let discnumber = (matches = cdhdr.match(/^(?:CD|DVD)\s*(\d+)$/)) ? Number(matches[1]) : undefined;
	track = {
	  id: node.id,
	  discnumber: discnumber,
	  tracknumber: node.childNodes[1].textContent.trim(),
	  title: node.childNodes[5].textContent.trim(),
	  duration: node.childNodes[7].textContent.trim(),
	  performers: [],
	  composers: [],
	  directors: [],
	};
	if (matches = track.id.match(/^track-(\d+)$/)) track.id = matches[1];
	if (matches = track.tracknumber.match(/^(\d+)\.$/)) track.tracknumber = Number(matches[1]);
	req.open('GET', node.childNodes[5].childNodes[0].href, false);
	req.send();
	if (req.readyState == 4 && req.status == 200) {
	  let html = parser.parseFromString(req.responseText, "text/html");
	  var tr_det = get_node('//div[@data-swap="trackdetail-' + track.id + '"]/div/div[@class="row"]', html);
	  if (tr_det != null) {
		track.album_year = Number(get_detail('Rok prvního vydání'));
		function get_detail(prop) {
		  var base = './div/ul[@class="summary"]/li[span[starts-with(text(), "' + prop + '")]]';
		  return get_string(base + '/text()', html, tr_det) || get_string(base + '/a/text()', html, tr_det);
		}
		let node, results = html.evaluate('./div[h4]/ul/li[span]',
			tr_det, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
		while (node = results.iterateNext()) {
		  let prop = node.childNodes[1].textContent.trim().replace(/\s*:\s*$/, '');
		  let val = node.childNodes[3].textContent.trim();
		  if (['hudba', 'text', 'hudba+text', 'původní text', 'český text'].includes(prop)) {
			track.composers.push([prop, val]);
		  } else if (['řídí'].includes(prop)) {
			track.directors.push([prop, val]);
		  } else if (['produkce'].includes(prop)) {
		  } else {
			track.performers.push([prop, val]);
		  }
		  function push_unique(prop, val) { if (!track[prop].includes(val)) track[prop].push(val); }
		}
	  }
	}
	tracks.push(track);
	if (discnumber != undefined && discnumber > totaldiscs) totaldiscs = discnumber;
  }
  album_years = tracks.map(k => k.album_year);
  album_years = album_years.filter((item, pos) => album_years.indexOf(item) == pos);
  if (matches = release_date.match(/^(\d+)\.\s*(\d+)\.\s*(\d+)$/)) {
	release_year = Number(matches[3]);
	release_date = matches[3].padEnd(4, '0') + '-' + matches[2].padEnd(2, '0') + '-' + matches[1].padEnd(2, '0');
  }
  for (track of tracks.sort(function(a, b) {
	var k = a.discnumber - b.discnumber;
	return isNaN(k) || k == 0 ? a.tracknumber - b.tracknumber : k;
  })) {
	let track_artist = album_artist;
	let track_singers = track.performers.filter(k => k[0] == 'zpěv').sort((a, b) => a[1].localeCompare(b[1]));
	let track_groups = track.performers.filter(k => k[0] == 'hudební těleso').sort((a, b) => a[1].localeCompare(b[1])).map(k => k[1]);
	// test if track artists match album artist
	let same = true;
	if (album_groups.length > 0 && (album_groups.length != album_groups.length
		|| !track_groups.every((k, ndx) => k == album_groups[ndx]))) same = false;
	if (same && (track_singers.length != album_singers.length
		|| !track_singers.every((k, ndx) => k[1] == album_singers[ndx][1]))) same = false;
	if (!same) {
	  track_groups = album_groups.length > 0 ? track.performers.filter(k => k[0] == 'hudební těleso').map(k => k[1]).join(', ') : '';
	  track_singers = track.performers.filter(k => k[0] == 'zpěv').map(k => k[1]).join(', ');
	  track_artist = track_groups + (track_groups && track_singers ? ', ' : '') + track_singers;
	}
	clipboard += [
	  album_artist,
	  album,
	  album_years.length == 1 ? album_years[0] : release_year,
	  release_date,
	  genre,
	  label,
	  catalog,
	  totaldiscs > 1 ? track.discnumber : undefined,
	  totaldiscs > 1 ? totaldiscs : undefined,
	  track.tracknumber,
	  tracks.length,
	  track_artist,
	  track.title,
	  track.performers.map(k => k[1] + (['Artist', 'Umělec', 'hudební těleso'].includes(k[0]) ? '' : ' (' + k[0] + ')')).join(', '),
	  track.composers.map(k => k[1] + ' (' + k[0] + ')').join(', '),
	  desc,
	  document.URL.replace(/\?.*/, ''),
	].join('\x1E') + '\n';
  }
  GM_setClipboard(clipboard, 'text');
  if (button != null) {
	button.disabled = false;
	button.textContent = original_text;
  }
}