Greasy Fork

Greasy Fork is available in English.

MB Auto Track Lengths

Auto sets track lengths for media by unique attached disc id.

当前为 2024-05-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         MB Auto Track Lengths
// @version      1.01
// @match        https://musicbrainz.org/release/*/discids
// @match        https://beta.musicbrainz.org/release/*/discids
// @match        https://musicbrainz.org/cdtoc/*
// @match        https://beta.musicbrainz.org/cdtoc/*
// @run-at       document-end
// @author       Anakunda
// @namespace    http://greasyfork.icu/users/321857
// @copyright    2024, Anakunda (http://greasyfork.icu/users/321857)
// @license      GPL-3.0-or-later
// @description  Auto sets track lengths for media by unique attached disc id.
// @require      https://openuserjs.org/src/libs/Anakunda/xhrLib.min.js
// ==/UserScript==

'use strict';

const manualMode = false;
const isDiscIdRow = tr => ['odd', 'even'].some(cls => tr.classList.contains(cls));
const getTrackLengths = tr => Array.prototype.find.call(tr.querySelectorAll('td a'), function(a) {
	//if (a.textContent.trim() == 'Set track lengths') return true;
	if (!a.pathname.startsWith('/cdtoc/') || !a.pathname.endsWith('/set-durations')) return false;
	const query = new URLSearchParams(a.search);
	return parseInt(query.get('medium')) > 0;
}) || null;
const sections = document.location.pathname.startsWith('/release/') ? Array.from(document.body.querySelectorAll('table.tbl > tbody > tr.subh'), function(subh) {
	const discIds = [ ];
	for (let tr = subh.nextElementSibling; tr != null && isDiscIdRow(tr); tr = tr.nextElementSibling)
		discIds.push(getTrackLengths(tr));
	return discIds;
}) : document.location.pathname.startsWith('/cdtoc/') ?
	[Array.prototype.filter.call(document.body.querySelectorAll('table.tbl > tbody > tr'), isDiscIdRow)
		.map(getTrackLengths)] : null;
if (sections != null) sections.forEach(function(section) {
	function setTrackLengths(link, autoRun, makeVotable = false) {
		console.assert(link instanceof HTMLAnchorElement);
		if (!(link instanceof HTMLAnchorElement)) throw 'Invalid argument';
		if (link.disabled) return; else link.disabled = true;
		const animation = link.animate([
			{ offset: 0.0, opacity: 1 },
			{ offset: 0.4, opacity: 1 },
			{ offset: 0.5, opacity: 0.1 },
			{ offset: 0.9, opacity: 0.1 },
		], { duration: 600, iterations: Infinity });
		localXHR(link.href).then(function(document) {
			const diffs = Array.from(document.body.querySelectorAll('div#page > table.wrap-block.details'), function(track) {
				const times = ['old', 'new'].map(function(cls) {
					if ((cls = track.querySelector('td.' + cls)) != null) cls = cls.textContent.trim(); else return NaN;
					return cls.split(':').reverse().reduce((total, time, index) =>
						total + parseInt(time) * Math.pow(60, index), 0);
				});
				return Math.abs(times[1] - times[0]);
			});
			return Promise[diffs.some(diff => diff > 5) ? 'reject' : 'resolve'](diffs);
		}).then(function(diffs) {
			const postData = new URLSearchParams({ 'confirm.edit_note': '' });
			if (makeVotable) postData.set('confirm.make_votable', 1);
			localXHR(link.href, { responseType: null }, postData).then(statusCode => ({
				textContent: 'Track lengths successfully set',
				style: 'color: green;',
				title: 'Status code: ' + statusCode,
			}), reason => ({
				textContent: 'Error setting track lengths',
				style: 'color: red;',
				title: reason,
			})).then(attributes => { link.replaceWith(Object.assign(document.createElement('span'), attributes)) });
		}, function(diffs) {
			animation.cancel();
			if (!autoRun) return document.location.assign(link.href);
			link.style.color = 'red';
			link.disabled = false;
			link.title = '[ ' + diffs.join(', ') + ' ]';
		});
	}

	if (section.length > 1 || manualMode) return section.filter(Boolean).forEach(function(link) {
		link.onclick = function(evt) {
			setTrackLengths(evt.currentTarget, false);
			return false;
		};
	});
	if (section.length > 0) section = section.filter(Boolean); else return;
	if (section.length == 1) setTrackLengths(section[0], true);
});