您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Tries to recognize and add featured artists from selected text in description
当前为
- // ==UserScript==
- // @name Gazelle extract featured artists from description
- // @namespace https://greasyfork.org/cs/users/321857-anakunda
- // @version 1.1
- // @description Tries to recognize and add featured artists from selected text in description
- // @author Anakunda
- // @match https://redacted.ch/torrents.php?*id=*
- // @match https://orpheus.network/torrents.php?*id=*
- // @match https://notwhat.cd/torrents.php?*id=*
- // @grant RegExp
- // @grant GM_xmlhttpRequest
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_deleteValue
- // @grant GM_log
- // @require https://greasyfork.org/scripts/388280-xpathlib/code/XPathLib.js
- // ==/UserScript==
- var artist_index;
- var modal = null, btnAdd = null, btnCustom = null, customCtrls = [], sel = null;
- var prefs = {
- set: function(prop, def) { this[prop] = GM_getValue(prop, def) }
- };
- (function() {
- 'use strict';
- const styleSheet = `
- .modal {
- position: fixed;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.5);
- opacity: 0;
- visibility: hidden;
- transform: scale(1.1);
- transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
- }
- .modal-content {
- position: absolute;
- top: 50%;
- left: 50%;
- font-size: 17px;
- transform: translate(-50%, -50%);
- background-color: FloralWhite;
- color: black;
- width: 31rem;
- border-radius: 0.5rem;
- padding: 2rem 2rem 2rem 2rem;
- font-family: monospace;
- }
- .show-modal {
- opacity: 1;
- visibility: visible;
- transform: scale(1.0);
- transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
- }
- input[type="text"] { cursor: text; }
- input[type="radio"] { cursor: pointer; }
- .lbl { cursor: pointer; }
- .tooltip {
- position: relative;
- }
- .tooltip .tooltiptext {
- visibility: hidden;
- width: 120px;
- background-color: #555;
- color: #fff;
- text-align: center;
- border-radius: 6px;
- padding: 5px 0;
- position: absolute;
- z-index: 1;
- bottom: 125%;
- left: 50%;
- margin-left: -60px;
- opacity: 0;
- transition: opacity 0.3s;
- }
- .tooltip .tooltiptext::after {
- content: "";
- position: absolute;
- top: 100%;
- left: 50%;
- margin-left: -5px;
- border-width: 5px;
- border-style: solid;
- border-color: #555 transparent transparent transparent;
- }
- .tooltip:hover .tooltiptext {
- visibility: visible;
- opacity: 1;
- }
- `;
- var addBox = document.querySelector('form.add_form[name="artists"]');
- if (addBox == null) return;
- btnAdd = document.createElement('input');
- btnAdd.id = 'add-artists-from-selection';
- btnAdd.value = 'Extract from selection';
- btnAdd.onclick = add_from_selection;
- btnAdd.type = 'button';
- btnAdd.style.marginLeft = '5px';
- btnAdd.style.visibility = 'hidden';
- addBox.appendChild(btnAdd);
- var style = document.createElement('style');
- document.head.appendChild(style);
- style.id = 'artist-parser-form';
- style.type = 'text/css';
- style.innerHTML = styleSheet;
- var el, elem = [];
- elem.push(document.createElement('div'));
- elem[elem.length - 1].className = 'modal';
- elem[elem.length - 1].id = 'add-from-selection-form';
- modal = elem[0];
- elem.push(document.createElement('div'));
- elem[elem.length - 1].className = 'modal-content';
- elem.push(document.createElement('input'));
- elem[elem.length - 1].id = 'btnFill';
- elem[elem.length - 1].type = 'submit';
- elem[elem.length - 1].value = 'Capture';
- elem[elem.length - 1].style = "position: fixed; right: 30px; width: 80px; top: 30px;";
- elem[elem.length - 1].onclick = do_parse;
- elem.push(document.createElement('input'));
- elem[elem.length - 1].id = 'btnCancel';
- elem[elem.length - 1].type = 'button';
- elem[elem.length - 1].value = 'Cancel';
- elem[elem.length - 1].style = "position: fixed; right: 30px; width: 80px; top: 65px;";
- elem[elem.length - 1].onclick = closeModal;
- var presetIndex = 0;
- function addPreset(val, label = 'Custom', rx = null, order = [1, 2]) {
- elem.push(document.createElement('div'));
- el = document.createElement('input');
- elem[elem.length - 1].style.paddingBottom = '10px';
- el.id = 'parse-preset-' + val;
- el.name = 'parse-preset';
- el.value = val;
- if (val == 1) el.checked = true;
- el.type = 'radio';
- el.onchange = update_custom_ctrls;
- if (rx) {
- el.rx = rx;
- el.order = order;
- }
- if (val == 999) btnCustom = el;
- elem[elem.length - 1].appendChild(el);
- el = document.createElement('label');
- el.style.marginLeft = '10px';
- el.style.marginRight = '10px';
- el.htmlFor = 'parse-preset-' + val;
- el.className = 'lbl';
- el.innerHTML = label;
- elem[elem.length - 1].appendChild(el);
- if (val != 999) return;
- el = document.createElement('input');
- el.type = 'text';
- el.id = 'custom-pattern';
- el.style.width = '20rem';
- el.style.fontFamily = 'monospace';
- el.autoComplete = "on";
- addTooltip(el, 'RegExp to parse lines, first two captured groups are used');
- customCtrls.push(elem[elem.length - 1].appendChild(el));
- el = document.createElement('input');
- el.type = 'radio';
- el.name = 'parse-order';
- el.id = 'parse-order-1';
- el.value = 1;
- el.checked = true;
- el.style.marginLeft = '1rem';
- addTooltip(el, 'Captured regex groups assigned in order $1: artist(s), $2: assignment');
- customCtrls.push(elem[elem.length - 1].appendChild(el));
- el = document.createElement('label');
- el.htmlFor = 'parse-order-1';
- el.textContent = '→';
- el.style.marginLeft = '5px';
- elem[elem.length - 1].appendChild(el);
- el = document.createElement('input');
- el.type = 'radio';
- el.name = 'parse-order';
- el.id = 'parse-order-2';
- el.value = 2;
- el.style.marginLeft = '10px';
- addTooltip(el, 'Captured regex groups assigned in order $1: assignment, $2: artist(s)');
- customCtrls.push(elem[elem.length - 1].appendChild(el));
- el = document.createElement('label');
- el.htmlFor = 'parse-order-2';
- el.textContent = '←';
- el.style.marginLeft = '5px';
- elem[elem.length - 1].appendChild(el);
- }
- addPreset(++presetIndex, escapeHTML('<artist(s)> - <assignment>]'), /^\s*(.*?)(?:\s*[\-\−\—\~\–]+\s*(.*?))?\s*$/);
- addPreset(++presetIndex, escapeHTML('<artist>[, <assignment>]') +
- '<span style="font-family: initial;"> <i>(HRA style)</i></span>',
- /^\s*(.*?)(?:\s*,\s*(.*?))?\s*$/);
- addPreset(++presetIndex, escapeHTML('<artist(s)>[: <assignment>]'), /^\s*(.*?)(?:\s*:+\s*(.*?))?\s*$/);
- addPreset(++presetIndex, escapeHTML('[<assignment> - ]<artist(s)>'), /^\s*(?:(.*?)\s*[\-\−\—\~\–]+\s*)?(.*?)\s*$/, [2, 1]);
- addPreset(++presetIndex, escapeHTML('[<assignment>: ]<artist(s)>'), /^\s*(?:(.*?)\s*:+\s*)?(.*?)\s*$/, [2, 1]);
- addPreset(++presetIndex, escapeHTML('<artist>[ / <assignment>]'), /^\s*(.*?)(?:\s*\/+\s*(.*?))?\s*$/);
- addPreset(++presetIndex, escapeHTML('<artist>[; <assignment>]'), /^\s*(.*?)(?:\s*;\s*(.*?))?\s*$/);
- addPreset(++presetIndex, escapeHTML('[<assignment> / ]<artist(s)>'), /^\s*(?:(.*?)\s*\/+\s*)?(.*?)\s*$/, [2, 1]);
- addPreset(999);
- elem.slice(2).forEach(k => { elem[1].appendChild(k) });
- elem[0].appendChild(elem[1]);
- document.body.appendChild(elem[0]);
- window.addEventListener("click", windowOnClick);
- document.addEventListener('selectionchange', () => {
- var cs = window.getComputedStyle(modal);
- if (!btnAdd || window.getComputedStyle(modal).visibility != 'hidden') return;
- var sel = document.getSelection();
- ShowHideAddbutton();
- });
- })();
- function add_from_selection() {
- sel = document.getSelection();
- if (sel.isCollapsed || modal == null) return;
- prefs.set('preset', 1);
- prefs.set('custom_pattern', '^\\s*(.*?)(?:\\s*:+\\s*(.*?))?\\s*$');
- prefs.set('custom_pattern_order', 1);
- setRadiosValue('parse-preset', prefs.preset);
- customCtrls[0].value = prefs.custom_pattern;
- setRadiosValue('parse-order', prefs.custom_pattern_order);
- sel = sel.toString();
- update_custom_ctrls();
- modal.classList.add("show-modal");
- }
- function do_parse(expr, flags = '') {
- closeModal();
- if (!sel) return;
- var preset = getSelectedRadio('parse-preset');
- if (preset == null) return;
- prefs.preset = preset.value;
- var order = preset.order;
- var custom_parse_order = getSelectedRadio('parse-order');
- var rx = preset.rx;
- if (!rx && preset.value == 999 && custom_parse_order != null) {
- rx = new RegExp(customCtrls[0].value);
- if (custom_parse_order != null) {
- order = custom_parse_order.value == 1 ? [1, 2] : custom_parse_order.value == 2 ? [2, 1] : null;
- } else {
- order = [1, 2];
- }
- }
- const artistSplit = /\s*[\,\;\/\|]\s*/;
- function extr_artists(kind) { return document.querySelectorAll('ul#artist_list > li.artist_' + kind + ' > a') }
- var artists = [
- extr_artists('main'),
- extr_artists('guest'),
- extr_artists('remixer'),
- extr_artists('composer'),
- extr_artists('conductor'),
- extr_artists('compiler'),
- extr_artists('producer'),
- ];
- cleanupArtistsForm();
- var addedartists = new Array(7);
- addedartists.fill([]);
- artist_index = 0;
- for (var line of sel.split(/[\r\n]+/)) {
- if (!line || !line.trim()) continue;
- if (line.search(/^\s*(?:Recorded\b)/i) >= 0) continue;
- var matches = line.match(/^\s*Produced by (.+?)\s*$/);
- if (matches) {
- add_artist(matches[1], 7);
- } else if (matches = rx.exec(line)) {
- if (matches[order[0]]) {
- matches[order[0]].split(artistSplit).forEach(k => { add_artist(k, deduce_artist(matches[order[1]])) });
- } else {
- matches[order[1]].split(artistSplit).forEach(k => { add_artist(k) });
- }
- }
- }
- prefs.custom_pattern = customCtrls[0].value;
- prefs.custom_pattern_order = custom_parse_order != null ? custom_parse_order.value : 1;
- for (var i in prefs) { if (typeof prefs[i] != 'function') GM_setValue(i, prefs[i]) }
- return;
- function deduce_artist(str) {
- var result = 2; // guest by default
- if (str) {
- if (str.search(/\b(?:remix)/i) >= 0) result = 3; // remixer
- if (str.search(/\b(?:composer\b|libretto\b|lyric)/i) >= 0) result = 4; // composer
- if (str.search(/\b(?:conduct|rirector\b)/i) >= 0) result = 5; // conductor
- if (str.search(/\b(?:compiler\b)/i) >= 0) result = 5; // conductor
- if (str.search(/\b(?:producer\b|produced by\b)/i) >= 0) result = 7; // producer
- }
- return result;
- }
- function add_artist(name, type = 1) {
- if (!name || !type) return false;
- // avoid dupes
- for (var i of artists[0]) { if (name == i.textContent) return false }
- if (type >= 2) for (i of artists[type - 1]) { if (name == i.textContent) return false }
- for (i of addedartists[0]) { if (name == i) return false }
- if (type >= 2) for (i of addedartists[type - 1]) { if (name == i) return false }
- var id = get_artist_field(artist_index);
- if (id == null) {
- add_artist_field();
- id = get_artist_field(artist_index);
- if (id == null) return false;
- }
- id.value = name;
- id.nextElementSibling.value = type;
- addedartists[type - 1].push(name);
- ++artist_index;
- return true;
- }
- }
- function add_artist_field() { exec(function() { AddArtistField() }) }
- function exec(fn) {
- let script = document.createElement('script');
- script.type = 'application/javascript';
- script.textContent = '(' + fn + ')();';
- document.body.appendChild(script); // run the script
- document.body.removeChild(script); // clean up
- }
- function get_artist_field(index) {
- var id = document.getElementById('artist');
- if (index <= 0) return id;
- for (var i = 0; i < index; ++i) {
- do { id = id.nextElementSibling } while (id != null && (id.localName != 'input' || id.name != 'aliasname[]'));
- if (id == null) break;
- }
- return id;
- }
- function closeModal() {
- if (modal == null) return;
- ShowHideAddbutton();
- modal.classList.remove("show-modal");
- }
- function windowOnClick(event) {
- if (modal != null && event.target === modal) closeModal();
- }
- function update_custom_ctrls() {
- function en(elem) {
- if (elem == null || btnCustom == null) return;
- elem.disabled = !btnCustom.checked;
- elem.style.opacity = btnCustom.checked ? 1 : 0.5;
- }
- customCtrls.forEach(k => { en(k) });
- }
- function getSelectedRadio(name) {
- for (var i of document.getElementsByName(name)) { if (i.checked) return i }
- return null;
- }
- function setRadiosValue(name, val) {
- for (var i of document.getElementsByName(name)) { if (i.value == val) i.checked = true }
- }
- function ShowHideAddbutton() {
- //btnAdd.style.visibility = document.getSelection().type == 'Range' ? 'visible' : 'hidden';
- btnAdd.style.visibility = document.getSelection().isCollapsed ? 'hidden' : 'visible';
- }
- function escapeHTML(string) {
- var pre = document.createElement('pre');
- var text = document.createTextNode(string);
- pre.appendChild(text);
- return pre.innerHTML;
- }
- function cleanupArtistsForm() {
- var id = get_artist_field(0);
- do {
- id.value = null;
- id = id.nextElementSibling;
- if (id == null) break;
- id.value = 1;
- do { id = id.nextElementSibling } while (id != null && (id.localName != 'input' || id.name != 'aliasname[]'));
- } while (id != null);
- }
- function addTooltip(elem, text) {
- if (elem == null) return;
- elem.classList.add('tooltip');
- var tt = document.createElement('span');
- tt.className = 'tooltiptext';
- tt.textContent = text;
- elem.appendChild(tt);
- }