Greasy Fork is available in English.
This script provides integration with online description generator YADG (http://yadg.cc)
此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.org/scripts/444988/1268106/music-helper.js
// ==UserScript== // @name music-helper // @contributor Slack06/SavageCore/tomorrow505 // @description This script provides integration with online description generator YADG (http://yadg.cc) // @license https://github.com/SavageCore/yadg-pth-userscript/blob/master/LICENSE // @version v1.3 // @namespace yadg // @grant GM_xmlhttpRequest // @require https://code.jquery.com/jquery-1.12.4.js // @include http*://*redacted.ch/upload.php* // @include http*://*redacted.ch/requests.php* // @include http*://*redacted.ch/torrents.php* // @include http*://*orpheus.network/upload.php* // @include http*://*orpheus.network/requests.php* // @include http*://*orpheus.network/torrents.php* // @include http*://*dicmusic.com/upload.php* // @include http*://*dicmusic.com/requests.php* // @include http*://*dicmusic.com/torrents.php* // @match https://*open.cd/plugin_upload.php* // @match https://*.open.cd/plugin_upload.php* // ==/UserScript== let worker_ok = location.href.split('#seperator#')[0].match(/lemonhd|redacted|orpheus|notwhat|dicmusic|waffles|d3si/i) ? true: false; var JSandbox = (function(self) { var undef_type = "undefined", doc = self.document, Worker = self.Worker; if (typeof Worker === undef_type) { return; } var $eval = "eval", $exec = "exec", $load = "load", $requests = "requests", $input = "input", $terminate = "terminate", $data = "data", $callback = "callback", $onerror = "onerror", $worker = "worker", $onresponse = "onresponse", $prototype = "prototype", $call = "call", str_type = "string", fun_type = "function", Sandbox = function() { var sandbox = this; if (! (sandbox instanceof Sandbox)) { return new Sandbox() } if (worker_ok) sandbox[$worker] = new Worker(Sandbox.url); sandbox[$requests] = {}; if (worker_ok) { sandbox[$worker].onmessage = function(event) { var data = event[$data], request; if (typeof data !== "object") { return } request = sandbox[$requests][data.id]; if (request) { if (data.error) { if (typeof sandbox[$onerror] === fun_type) { sandbox[$onerror](data, request) } if (typeof request[$onerror] === fun_type) { request[$onerror][$call](sandbox, data.error) } } else { if (typeof sandbox[$onresponse] === fun_type) { sandbox[$onresponse](data, request) } if (typeof request[$callback] === fun_type) { request[$callback][$call](sandbox, data.results) } } delete sandbox[$requests][data.id] } } } }, proto = Sandbox[$prototype], createRequestMethod = function(method) { proto[method] = function(options, callback, input, onerror) { if (typeof options === str_type || Object[$prototype].toString[$call](options) === "[object Array]" || arguments.length > 1) { options = { data: options, input: input, callback: callback, onerror: onerror } } if (method === $load && typeof options[$data] === str_type) { options[$data] = [options[$data]] } var data = options[$data], id = this.createRequestID(); input = options[$input]; delete options[$data]; delete options[$input]; this[$requests][id] = options; if (worker_ok) { this[$worker].postMessage({ id: id, method: method, data: data, input: input }); } return id }; Sandbox[method] = function() { var sandbox = new Sandbox(); sandbox[$onresponse] = sandbox[$onerror] = function() { sandbox[$terminate](); sandbox = null }; Sandbox[$prototype][method].apply(sandbox, Array[$prototype].slice[$call](arguments)); return Sandbox } }, methods = [$eval, $load, $exec], i = 3; while (i--) { createRequestMethod(methods[i]) } proto[$terminate] = function() { this[$requests] = {}; if (worker_ok) { this[$worker].onmessage = null; this[$worker][$terminate]() } }; proto.abort = function(id) { delete this[$requests][id] }; proto.createRequestID = function() { var id = Math.random().toString(); if (id in this[$requests]) { return this.createRequestID() } return id }; if (typeof doc !== undef_type) { var linkElems = doc.getElementsByTagName("link"); i = linkElems.length; while (i--) { if (linkElems[i].getAttribute("rel") === "jsandbox") { Sandbox.url = linkElems[i].getAttribute("href"); break } } } return Sandbox } (self)), Sandbox = JSandbox; /* global window unsafeWindow document GM JSandbox formatName AddArtistField RemoveArtistField Blob alert Image */ /* eslint max-depth: 'off', block-scoped-var: 'off', no-loop-func: 'off', no-alert: 'off', unicorn/prefer-module: 'off', no-bitwise: 'off' */ /* Here you can set site specific default templates. You can find a list of available templates at: https://yadg.cc/api/v2/templates/ */ const defaultPTHFormat = 5; const defaultWafflesFormat = 9; const defaultPTHTarget = 'other'; const defaultPTHDescriptionTarget = 'album'; let yadg; // eslint-disable-line prefer-const let factory; // eslint-disable-line prefer-const let yadgRenderer; // eslint-disable-line prefer-const let yadgTemplates; // eslint-disable-line prefer-const let autoRehost; // --------- USER SETTINGS END --------- function fetchImage(target, callback) { const input = document.querySelector('[name="cover"]'); if (input === null) { return; } if (/imgur|ptpimg/g.test(input.value)) { return; } const link = target === null ? $('#yadg_input').val() : target; switch (true) { case /discogs/.test(link): GM_xmlhttpRequest({ method: 'GET', url: link, onload(response) { if (response.status === 200) { const container = document.implementation.createHTMLDocument() .documentElement; container.innerHTML = response.responseText; const script = container.querySelector('#release_schema'); try { const data = JSON.parse(script.textContent); callback(data.image); } catch { callback(false); } } }, }); break; case /music.apple/.test(link): { const regex = /apple\.com\/(?:([a-z]{2,3})\/)?.*\/(?:(\d+)|id(\d*))/; const result = regex.exec(link); const id = result[2] | result[3]; let country = 'us'; if (result[1]) { [, country] = result; } GM_xmlhttpRequest({ method: 'GET', url: 'https://itunes.apple.com/lookup?id=' + id + '&country=' + country, onload(response) { if (response.status === 200) { const data = JSON.parse(response.responseText); const settingCover = factory.getCoverSize().value; const hires = settingCover === 'large' ? data.results[0].artworkUrl100.replace( '100x100bb', '100000x100000-999', ) : data.results[0].artworkUrl100.replace( '100x100bb', '700x700bb', ); if (typeof callback === 'function') { callback(hires); } } }, }); break; } case factory.getScraperSelect().value === 'bandcamp': { let img; GM_xmlhttpRequest({ method: 'GET', url: link, onload(response) { if (response.status === 200) { const container = document.implementation.createHTMLDocument() .documentElement; container.innerHTML = response.responseText; const [imgElement_] = container.querySelectorAll( '#tralbumArt > a > img', ); if (!imgElement_) { if (typeof callback === 'function') { callback(false); } return false; } const scaledImg = imgElement_.src; const settingCover = factory.getCoverSize().value; const originalImg = settingCover === 'large' ? scaledImg.replace(/_16/, '_0') : scaledImg.replace(/_16/, '_10'); const temporaryImg = new Image(); temporaryImg.src = originalImg; temporaryImg.addEventListener('load', function () { img = this.width === this.height ? originalImg : scaledImg; if (typeof callback === 'function') { callback(img); } }); } }, }); break; } case /beatport/.test(link): GM_xmlhttpRequest({ method: 'GET', url: link, onload(response) { if (response.status === 200) { const container = document.implementation.createHTMLDocument() .documentElement; container.innerHTML = response.responseText; if (typeof callback === 'function') { callback( container.querySelectorAll( 'div.interior-release-chart-artwork-parent > img', )[0].src, ); } } }, }); break; case /musicbrainz/.test(link): { const regex = /release\/(.*)/; const {1: id} = regex.exec(link); GM_xmlhttpRequest({ headers: { 'User-Agent': 'YADG/1.4.41 (yadg.cc)', }, method: 'GET', url: 'http://coverartarchive.org/release/' + id + '/', onload(response) { if (response.status === 200) { const data = JSON.parse(response.responseText); if (typeof callback === 'function') { callback(data.images[0].image); } } }, }); break; } case /junodownload/.test(link): GM_xmlhttpRequest({ method: 'GET', url: link, onload(response) { if (response.status === 200) { const container = document.implementation.createHTMLDocument() .documentElement; container.innerHTML = response.responseText; if (typeof callback === 'function') { callback(container.querySelector('.img-fluid-fill').src); } } }, }); break; case /metal-archives/.test(link): GM_xmlhttpRequest({ method: 'GET', url: link, onload(response) { if (response.status === 200) { const container = document.implementation.createHTMLDocument() .documentElement; container.innerHTML = response.responseText; const parser = document.createElement('a'); parser.href = container.querySelectorAll('#cover > img')[0].src; const imgLink = parser.protocol + '//' + parser.hostname + parser.pathname; if (typeof callback === 'function') { callback(imgLink); } } }, }); break; case /allmusic/.test(link): GM_xmlhttpRequest({ method: 'GET', url: link, onload(response) { if (response.status === 200) { const container = document.implementation.createHTMLDocument() .documentElement; container.innerHTML = response.responseText; const data = container.querySelector('[data-largeurl]'); // No image available https://www.allmusic.com/album/release/beatles-mr0003843619 if (data !== null) { const cover = data.getAttribute('data-largeurl'); if (typeof callback === 'function') { callback(cover); } } } }, }); break; case /deezer/.test(link): { const regex = /\.com\/(\w+\/)?(album)\/(\d+)/g; const helper = regex.exec(link); const id = helper[3]; GM_xmlhttpRequest({ method: 'GET', url: 'https://api.deezer.com/album/' + id, onload(response) { if (response.status === 200) { const data = JSON.parse(response.responseText); const settingCover = factory.getCoverSize().value; const cover = settingCover === 'large' ? data.cover_xl.replace( '1000x1000-000000-80-0-0.jpg', '1400x1400-000000-100-0-0.jpg', ) : data.cover_xl; if (typeof callback === 'function') { callback(cover); } } }, }); break; } } } function pthImgIt() { const [pthImgIt] = document.querySelectorAll('.rehost_it_cover'); let imgElement; switch (window.location.href) { case (window.location.href.match(/\/upload\.php/) || {}).input: { imgElement = document.querySelector('#image').value; break; } case (window.location.href.match(/torrents\.php\?action=editgroup/) || {}) .input: { imgElement = document.querySelectorAll( '#content > div > div:nth-child(2) > form > div > input[type="text"]:nth-child(5)', )[0].value; break; } default: break; } if (pthImgIt && imgElement) { pthImgIt.click(); } } function insertImage(img, callback) { switch (window.location.href) { case (window.location.href.match(/\/upload\.php/) || {}).input: { const input = document.querySelector('#image'); input.value = img; if (input.getAttribute('autorehost') === 'true') { const evt = document.createEvent('HTMLEvents'); evt.initEvent('keyup', false, true); input.dispatchEvent(evt); } input.parentNode.parentNode.insertAdjacentHTML( 'beforebegin', '<tr id="yadg_image_preview_tr"><td class="label">Album Art Preview:</td><td><img id="yadg_image_preview" src="' + img + '" width="300px" /></tr></td>', ); callback(); break; } case (window.location.href.match(/torrents\.php\?action=editgroup/) || {}) .input: { const [imageInputElement] = document.querySelectorAll( '#content > div > div:nth-child(2) > form > div > input[type="text"]:nth-child(5)', ); imageInputElement.value = img; imageInputElement.parentNode.insertAdjacentHTML( 'beforebegin', '<div id="yadg_image_preview_div"><img id="yadg_image_preview" src="' + img + '" width="300px" /></div>', ); callback(); break; } case (window.location.href.match(/requests\.php\?/) || {}).input: { const [imageInputElement] = document.querySelectorAll( '#image_tr > td:nth-child(2) > input[type="text"]:nth-child(1)', ); imageInputElement.value = img; imageInputElement.parentNode.parentNode.insertAdjacentHTML( 'beforebegin', '<tr id="yadg_image_preview_tr"><td class="label">Album Art Preview:</td><td><img id="yadg_image_preview" src="' + img + '" width="300px" /></tr></td>', ); callback(); break; } default: break; } } // --------- THIRD PARTY CODE AREA START --------- // Creates an object which gives some helper methods to // Save/Load/Remove data to/from the localStorage // Source from: https://github.com/gergob/localstoragewrapper function LocalStorageWrapper(appPrefix) { 'use strict'; if (appPrefix === undefined) { throw new Error('applicationPrefix parameter should be defined'); } const delimiter = '_'; // If the passed in value for prefix is not string, it should be converted const keyPrefix = typeof appPrefix === 'string' ? appPrefix : JSON.stringify(appPrefix); const localStorage = window.localStorage || unsafeWindow.localStorage; const isLocalStorageAvailable = function () { return typeof localStorage !== 'undefined'; }; const getKeyPrefix = function () { return keyPrefix; }; // // validates if there is a prefix defined for the keys // and checks if the localStorage functionality is available or not // const makeChecks = function (key) { const prefix = getKeyPrefix(); if (prefix === undefined) { throw new Error('No prefix was defined, data cannot be saved'); } if (!isLocalStorageAvailable()) { throw new Error( 'LocalStorage is not supported by your browser, data cannot be saved', ); } // Keys are always strings const checkedKey = typeof key === 'string' ? key : JSON.stringify(key); return checkedKey; }; // // saves the value associated to the key into the localStorage // const addItem = function (key, value) { try { const checkedKey = makeChecks(key); const combinedKey = this.getKeyPrefix() + delimiter + checkedKey; localStorage.setItem(combinedKey, JSON.stringify(value)); } catch (error) { console.log(error); throw error; } }; // // gets the value of the object saved to the key passed as parameter // const getItem = function (key) { let result; try { const checkedKey = makeChecks(key); const combinedKey = this.getKeyPrefix() + delimiter + checkedKey; const resultAsJSON = localStorage.getItem(combinedKey); result = JSON.parse(resultAsJSON); } catch (error) { console.log(error); throw error; } return result; }; // // returns all the keys from the localStorage // const getAllKeys = function () { const prefix = getKeyPrefix(); const results = []; if (prefix === undefined) { throw new Error('No prefix was defined, data cannot be saved'); } if (!isLocalStorageAvailable()) { throw new Error( 'LocalStorage is not supported by your browser, data cannot be saved', ); } for (const key in localStorage) { if (key.indexOf(prefix) === 0) { const keyParts = key.split(delimiter); results.push(keyParts[1]); } } return results; }; // // removes the value associated to the key from the localStorage // const removeItem = function (key) { let result = false; try { const checkedKey = makeChecks(key); const combinedKey = this.getKeyPrefix() + delimiter + checkedKey; localStorage.removeItem(combinedKey); result = true; } catch (error) { console.log(error); throw error; } return result; }; // // removes all the values from the localStorage // const removeAll = function () { try { const allKeys = this.getAllKeys(); for (const key of allKeys) { const checkedKey = makeChecks(key); const combinedKey = this.getKeyPrefix() + delimiter + checkedKey; localStorage.removeItem(combinedKey); } } catch (error) { console.log(error); throw error; } }; // Make some of the functionalities public return { isLocalStorageAvailable, getKeyPrefix, addItem, getItem, getAllKeys, removeItem, removeAll, }; } // --------- THIRD PARTY CODE AREA END --------- const yadgUtil = { exec(fn) { const script = document.createElement('script'); script.setAttribute('type', 'application/javascript'); script.textContent = '(' + fn + ')();'; document.body.append(script); // Run the script script.remove(); // Clean up }, // Handle for updating page css, taken from one of hateradio's scripts addCSS(style) { if (!this.style) { this.style = document.createElement('style'); this.style.type = 'text/css'; (document.head || document.querySelectorAll('head')[0]).append( this.style, ); } this.style.append(document.createTextNode(style + '\n')); }, setValueIfSet(value, input, cond) { input.value = cond ? value : ''; }, // Negative count will remove, positive count will add given number of artist boxes addRemoveArtistBoxes(count) { if (count !== 0) { if (count < 0) { for (let i = 0; i < -count; i++) { yadgUtil.exec(() => { RemoveArtistField(); // eslint-disable-line new-cap }); } } else { for (let i = 0; i < count; i++) { yadgUtil.exec(() => { AddArtistField(); // eslint-disable-line new-cap }); } } } }, getOptionOffsets(select) { const optionOffsets = {}; for (let j = 0; j < select.options.length; j++) { optionOffsets[select.options[j].value] = select.options[j].index; } return optionOffsets; }, storage: new LocalStorageWrapper('yadg'), settings: new LocalStorageWrapper('yadgSettings'), }; // Very simple wrapper for XmlHttpRequest // eslint-disable-next-line max-params function Requester(url, method, callback, data, errorCallback) { this.data = data; this.url = url; this.method = method; if (!errorCallback) { errorCallback = yadg.failedCallback; } this.send = function () { const details = { url: this.url, method: this.method, onload(response) { if (response.status === 200) { callback(JSON.parse(response.responseText)); } else if (response.status === 401) { yadg.failedAuthenticationCallback(); } else { errorCallback(); } }, onerror: errorCallback, }; if (method === 'POST') { details.data = JSON.stringify(this.data); } const headers = { Accept: 'application/json', 'Content-Type': 'application/json', }; if (yadgUtil.settings.getItem(factory.KEY_API_TOKEN)) { headers.Authorization = 'Token ' + yadgUtil.settings.getItem(factory.KEY_API_TOKEN); } details.headers = headers; GM_xmlhttpRequest(details); }; } const yadgSandbox = { KEY_LAST_WARNING: 'templateLastWarning', init(callback) { GM_xmlhttpRequest({ method: 'GET', url: yadg.yadgHost + '/static/js/jsandbox-worker.js', onload(response) { let script; let dataURL = null; if (response.status === 200) { script = response.responseText; const blob = new Blob([script], {type: 'application/javascript'}); const URL = window.URL || window.webkitURL; if (!URL || !URL.createObjectURL) { throw new Error( 'No no valid implementation of window.URL.createObjectURL found.', ); } dataURL = URL.createObjectURL(blob); yadgSandbox.initCallback(dataURL); yadgSandbox.loadSwig(callback); } else { yadgSandbox.initCallbackError(); } }, onerror() { yadgSandbox.initCallbackError(); }, }); }, loadSwig(callback) { // ImportScripts for the web worker will not work in Firefox with cross-domain requests // see: https://bugzilla.mozilla.org/show_bug.cgi?id=756589 // so download the Swig files manually with GM_xmlhttpRequest GM_xmlhttpRequest({ method: 'GET', url: yadg.yadgHost + '/static/js/swig.min.js', onload(response) { if (response.status === 200) { yadgSandbox.swigScript = response.responseText; GM_xmlhttpRequest({ method: 'GET', url: yadg.yadgHost + '/static/js/swig.custom.js', onload(response) { if (response.status === 200) { yadgSandbox.swigCustomScript = response.responseText; callback(); } }, }); } }, }); }, initializeSwig(dependencies) { if (!(this.swigScript && this.swigCustomScript)) { yadg.failedCallback(); return; } yadgSandbox.exec({data: this.swigScript, onerror: yadg.failedCallback}); yadgSandbox.exec({ data: this.swigCustomScript, onerror: yadg.failedCallback, }); yadgSandbox.exec({ data: 'var myswig = new swig.Swig({ loader: swig.loaders.memory(input.templates), autoescape: false }), i=0; yadg_filters.register_filters(myswig);', input: {templates: dependencies}, }); }, renderTemplate(template, data, callback, error) { const evalString = 'myswig.render(input.template, { locals: input.data, filename: \'scratchpad\' + (i++) })'; this.eval({ data: evalString, callback(out) { callback(out); }, input: {template, data}, onerror(error_) { error(error_); }, }); }, initCallback(dataUrl) { JSandbox.url = dataUrl; this.jsandbox = new JSandbox(); this.initError = false; }, resetSandbox() { this.jsandbox.terminate(); this.jsandbox = new JSandbox(); }, load(options) { this.jsandbox.load(options); }, exec(options) { this.jsandbox.exec(options); }, eval(options) { this.jsandbox.eval(options); }, initCallbackError() { this.initError = true; const lastWarning = yadgUtil.storage.getItem(this.KEY_LAST_WARNING); const now = new Date(); if ( lastWarning === null || now.getTime() - new Date(lastWarning).getTime() > factory.CACHE_TIMEOUT ) { console.log( 'Could not load the necessary script files for executing YADG. If this error persists you might need to update the user script. You will only get this message once a day.', ); yadgUtil.storage.addItem(this.KEY_LAST_WARNING, now); } }, }; factory = { // Storage keys for cache KEY_LAST_CHECKED: 'lastChecked', KEY_SCRAPER_LIST: 'scraperList', KEY_FORMAT_LIST: 'formatList', // Storage keys for settings KEY_API_TOKEN: 'apiToken', KEY_DEFAULT_TEMPLATE: 'defaultTemplate', KEY_DEFAULT_TARGET: 'defaultTarget', KEY_DESCRIPTION_TARGET: 'descriptionTarget', KEY_DEFAULT_SCRAPER: 'defaultScraper', KEY_REPLACE_DESCRIPTION: 'replaceDescriptionOn', KEY_SETTINGS_INIT_VER: 'settingsInitializedVer', KEY_FETCH_IMAGE: 'fetchImage', KEY_AUTO_PREVIEW: 'autoPreview', KEY_AUTO_REHOST: 'autoRehost', KEY_AUTO_SELECT_SCRAPER: 'autoSelectScraper', KEY_COVER_SIZE: 'coverSize', CACHE_TIMEOUT: 1000 * 60 * 60 * 24, // 24 hours UPDATE_PROGRESS: 0, locations: [ { name: 'pth_upload', regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/upload\.php.*/i, }, { name: 'pth_edit', regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/torrents\.php\?action=editgroup&groupid=.*/i, }, { name: 'pth_request', regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/requests\.php\?action=new/i, }, { name: 'pth_request_edit', regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/requests\.php\?action=edit&id=.*/i, }, { name: 'pth_torrent_overview', regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/torrents\.php\?id=.*/i, }, { name: 'lemonhd_upload', regex: /https:\/\/lemonhd.org\/upload_music.php*/i, }, { name: 'opencd_upload', regex: /https:\/\/.*open.cd\/plugin_upload.php*/i, }, { name: 'ops_upload', regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/upload\.php.*/i, }, { name: 'ops_edit', regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/torrents\.php\?action=editgroup&groupid=.*/i, }, { name: 'ops_request', regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/requests\.php\?action=new/i, }, { name: 'ops_request_edit', regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/requests\.php\?action=edit&id=.*/i, }, { name: 'ops_torrent_overview', regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/torrents\.php\?id=.*/i, }, { name: 'dic_upload', regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/upload\.php.*/i, }, { name: 'dic_edit', regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/torrents\.php\?action=editgroup&groupid=.*/i, }, { name: 'dic_request', regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/requests\.php\?action=new/i, }, { name: 'dic_request_edit', regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/requests\.php\?action=edit&id=.*/i, }, { name: 'dic_torrent_overview', regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/torrents\.php\?id=.*/i, }, ], determineLocation(uri) { for (let i = 0; i < this.locations.length; i++) { if (this.locations[i].regex.test(uri)) { return this.locations[i].name; } } return null; }, init() { this.currentLocation = this.determineLocation(document.URL); // Only continue with the initialization if we found a valid location if (this.currentLocation === null) { return false; } if (this.currentLocation === 'pth_request') { this.inputsOff(document.URL); } this.insertIntoPage(this.getInputElements()); // Set the necessary styles this.setStyles(); // Make sure we initialize the settings to the most recent version this.initializeSettings(); // Populate settings inputs this.populateSettings(); // Add the appropriate action for the input textbox const input = document.querySelector('#yadg_input'); input.addEventListener('input', () => { if (factory.getAutoSelectScraperCheckbox().checked) { const inputValue = input.value; const yadgScraper = document.querySelector('#yadg_scraper'); if (/discogs/.test(inputValue)) { yadgScraper.value = 'discogs'; } else if (/music.apple/.test(inputValue)) { yadgScraper.value = 'itunes'; } else if (/bandcamp/.test(inputValue)) { yadgScraper.value = 'bandcamp'; } else if (/beatport/.test(inputValue)) { yadgScraper.value = 'beatport'; } else if (/musicbrainz/.test(inputValue)) { yadgScraper.value = 'musicbrainz'; } else if (/junodownload/.test(inputValue)) { yadgScraper.value = 'junodownload'; } else if (/metal-archives/.test(inputValue)) { yadgScraper.value = 'metalarchives'; } else if (/deezer/.test(inputValue)) { yadgScraper.value = 'deezer'; } else if (/allmusic/.test(inputValue)) { yadgScraper.value = 'allmusic'; } } }); // Add the appropriate action for the button const button = document.querySelector('#yadg_submit'); button.addEventListener( 'click', event => { event.preventDefault(); yadg.makeRequest(); if (factory.getFetchImageCheckbox().checked) { fetchImage(null, data => { if (data) { insertImage(data, () => { if ( factory.getAutoRehostCheckbox() && factory.getAutoRehostCheckbox().checked ) { pthImgIt(); } }); } }); } }, false, ); // Add the action for the options toggle const toggleLink = document.querySelector('#yadg_toggle_options'); if (toggleLink !== null) { toggleLink.addEventListener('click', event => { event.preventDefault(); const optionsDiv = document.querySelector('#yadg_options'); const {display} = optionsDiv.style; optionsDiv.style.display = display === 'none' || display === '' ? 'block' : 'none'; }); } // Add the action for the cover size select const coverSizeSetting = document.querySelector('#yadg_options_image'); if (coverSizeSetting !== null) { coverSizeSetting.addEventListener('click', () => { const optionsCoverSize = document.querySelector( '#yadg_options_coversize', ); const {display} = optionsCoverSize.style; optionsCoverSize.style.display = display === 'none' || display === '' ? 'block' : 'none'; }); } // Add the action for the template select const formatSelect = this.getFormatSelect(); if (formatSelect !== null) { formatSelect.addEventListener('change', function () { if (yadgRenderer.hasCached()) { yadgRenderer.renderCached( this.value, factory.setDescriptionBoxValue, factory.setDescriptionBoxValue, ); } }); } // add the action to the save settings link const saveSettingsLink = document.querySelector('#yadg_save_settings'); if (saveSettingsLink !== null) { saveSettingsLink.addEventListener('click', event => { event.preventDefault(); factory.saveSettings(); alert('Settings saved successfully.'); }); } // Add the action to the clear cache link const clearCacheLink = document.querySelector('#yadg_clear_cache'); if (clearCacheLink !== null) { clearCacheLink.addEventListener('click', event => { event.preventDefault(); yadgUtil.storage.removeAll(); alert('Cache cleared. Please reload the page for this to take effect.'); }); } const lastChecked = yadgUtil.storage.getItem(factory.KEY_LAST_CHECKED); if ( lastChecked === null || Date.now() - new Date(lastChecked).getTime() > factory.CACHE_TIMEOUT ) { // Update the scraper and formats list factory.UPDATE_PROGRESS = 1; yadg.getScraperList(factory.setScraperSelect); yadg.getFormatsList(factory.setFormatSelect); } else { factory.setScraperSelect( yadgUtil.storage.getItem(factory.KEY_SCRAPER_LIST), ); factory.setFormatSelect( yadgUtil.storage.getItem(factory.KEY_FORMAT_LIST), ); } return true; }, getApiTokenInput() { return document.querySelector('#yadg_api_token'); }, getReplaceDescriptionCheckbox() { return document.querySelector('#yadg_options_replace'); }, getFetchImageCheckbox() { return document.querySelector('#yadg_options_image'); }, getAutoRehostCheckbox() { return document.querySelector('#yadg_options_rehost'); }, getAutoPreviewCheckbox() { return document.querySelector('#yadg_options_preview'); }, getAutoSelectScraperCheckbox() { return document.querySelector('#yadg_options_auto_select_scraper'); }, getReplaceDescriptionSettingKey() { return this.makeReplaceDescriptionSettingsKey(this.currentLocation); }, makeReplaceDescriptionSettingsKey(subKey) { return this.KEY_REPLACE_DESCRIPTION + subKey.replace(/_/g, ''); }, // Disable fields when groupid set inputsOff(url) { if (/groupid=\d+/.test(url)) { for (const i of [ 'artists[]', 'importance[]', 'title', 'releasetype', 'genre_tags', 'tags', ]) { for (const element of document.getElementsByName(i)) { element.readOnly = true; } } } }, initializeSettings() { let settingsVer = yadgUtil.settings.getItem(factory.KEY_SETTINGS_INIT_VER); const currentVer = 1; if (!settingsVer) { settingsVer = 0; } if (settingsVer < currentVer) { // Replace descriptions on upload and new request pages const locations = [ 'pth_upload', 'lemonhd_upload', 'opencd_upload', 'pth_request', 'ops_upload', 'ops_request', 'dic_upload', 'dic_request', ]; for (const loc of locations) { const replaceDescSettingKey = factory.makeReplaceDescriptionSettingsKey( loc, ); yadgUtil.settings.addItem(replaceDescSettingKey, true); } } yadgUtil.settings.addItem(factory.KEY_SETTINGS_INIT_VER, currentVer); }, populateSettings() { const apiToken = yadgUtil.settings.getItem(factory.KEY_API_TOKEN); const replaceDesc = yadgUtil.settings.getItem( factory.getReplaceDescriptionSettingKey(), ); const fetchImage = yadgUtil.settings.getItem(factory.KEY_FETCH_IMAGE); const autoPreview = yadgUtil.settings.getItem(factory.KEY_AUTO_PREVIEW); autoRehost = yadgUtil.settings.getItem(factory.KEY_AUTO_REHOST); const autoSelectScraper = yadgUtil.settings.getItem( factory.KEY_AUTO_SELECT_SCRAPER, ); const coverSize = yadgUtil.settings.getItem(factory.KEY_COVER_SIZE); if (apiToken) { const apiTokenInput = factory.getApiTokenInput(); apiTokenInput.value = apiToken; } if (replaceDesc) { const replaceDescCheckbox = factory.getReplaceDescriptionCheckbox(); replaceDescCheckbox.checked = true; } if (fetchImage) { const fetchImageCheckbox = factory.getFetchImageCheckbox(); fetchImageCheckbox.checked = true; } if (autoRehost) { const autoRehostCheckbox = factory.getAutoRehostCheckbox(); if (autoRehostCheckbox) { autoRehostCheckbox.checked = true; } } if (autoPreview) { const autoPreviewCheckbox = factory.getAutoPreviewCheckbox(); autoPreviewCheckbox.checked = true; } if (autoSelectScraper) { const autoSelectScraperCheckbox = factory.getAutoSelectScraperCheckbox(); autoSelectScraperCheckbox.checked = true; } if (coverSize) { const coverSizeOption = factory.getCoverSize(); coverSizeOption.value = coverSize; if (factory.getFetchImageCheckbox().checked) { const optionsCoverSize = document.querySelector( '#yadg_options_coversize', ); optionsCoverSize.style.display = 'block'; } } }, saveSettings() { const scraperSelect = factory.getScraperSelect(); const templateSelect = factory.getFormatSelect(); const targetSelect = factory.getTargetSelect(); const descriptionTargetSelect = factory.getDescriptionTargetSelect(); const apiTokenInput = factory.getApiTokenInput(); const replaceDescCheckbox = factory.getReplaceDescriptionCheckbox(); const fetchImageCheckbox = factory.getFetchImageCheckbox(); const autoRehostCheckbox = factory.getAutoRehostCheckbox(); const autoPreviewCheckbox = factory.getAutoPreviewCheckbox(); const autoSelectScraperCheckbox = factory.getAutoSelectScraperCheckbox(); const coverSize = factory.getCoverSize(); let currentScraper = null; let currentTemplate = null; let currentTarget = null; let currentDescriptionTarget = null; let currentCoverSize = null; const apiToken = apiTokenInput.value.trim(); const replaceDescription = replaceDescCheckbox.checked; const fetchImage = fetchImageCheckbox.checked; const autoSelectScraper = autoSelectScraperCheckbox.checked; const autoPreview = autoPreviewCheckbox.checked; if (autoRehostCheckbox) { autoRehost = autoRehostCheckbox.checked; } if (scraperSelect.options.length > 0) { currentScraper = scraperSelect.options[scraperSelect.selectedIndex].value; } if (templateSelect.options.length > 0) { currentTemplate = templateSelect.options[templateSelect.selectedIndex].value; } if (targetSelect.options.length > 0) { currentTarget = targetSelect.options[targetSelect.selectedIndex].value; } if (descriptionTargetSelect.options.length > 0) { currentDescriptionTarget = descriptionTargetSelect.options[descriptionTargetSelect.selectedIndex] .value; } if (coverSize.options.length > 0) { currentCoverSize = coverSize.options[coverSize.selectedIndex].value; } if (currentScraper !== null) { yadgUtil.settings.addItem(factory.KEY_DEFAULT_SCRAPER, currentScraper); } if (currentTemplate !== null) { yadgUtil.settings.addItem(factory.KEY_DEFAULT_TEMPLATE, currentTemplate); } if (currentTarget !== null) { yadgUtil.settings.addItem(factory.KEY_DEFAULT_TARGET, currentTarget); } if (currentDescriptionTarget !== null) { yadgUtil.settings.addItem( factory.KEY_DESCRIPTION_TARGET, currentDescriptionTarget, ); } if (currentCoverSize !== null) { yadgUtil.settings.addItem(factory.KEY_COVER_SIZE, currentCoverSize); } if (apiToken === '') { yadgUtil.settings.removeItem(factory.KEY_API_TOKEN); } else { yadgUtil.settings.addItem(factory.KEY_API_TOKEN, apiToken); } const replaceDescSettingKey = factory.getReplaceDescriptionSettingKey(); if (replaceDescription) { yadgUtil.settings.addItem(replaceDescSettingKey, true); } else { yadgUtil.settings.removeItem(replaceDescSettingKey); } if (fetchImage) { yadgUtil.settings.addItem(factory.KEY_FETCH_IMAGE, true); } else { yadgUtil.settings.removeItem(factory.KEY_FETCH_IMAGE); } if (autoRehost) { yadgUtil.settings.addItem(factory.KEY_AUTO_REHOST, true); } else if (!autoRehost && autoRehostCheckbox) { yadgUtil.settings.removeItem(factory.KEY_AUTO_REHOST); } if (autoPreview) { yadgUtil.settings.addItem(factory.KEY_AUTO_PREVIEW, true); } else { yadgUtil.settings.removeItem(factory.KEY_AUTO_PREVIEW); } if (autoSelectScraper) { yadgUtil.settings.addItem(factory.KEY_AUTO_SELECT_SCRAPER, true); } else { yadgUtil.settings.removeItem(factory.KEY_AUTO_SELECT_SCRAPER); } }, setDescriptionBoxValue(value) { const descBox = factory.getDescriptionBox(); const replaceDesc = factory.getReplaceDescriptionCheckbox().checked; const skipAutoPreview = ['pth_torrent_overview', 'ops_torrent_overview', 'dic_torrent_overview'].includes(factory.currentLocation); const boxes = Array.isArray(descBox) ? descBox : [descBox]; for (const box of boxes) { const disabled = box.getAttribute('disabled'); if (disabled === 'disabled') { continue; } if (replaceDesc) { box.value = value; } else { const blankline = /\S/.test(box.value) ? '\n\n' : ''; box.value += blankline + value; } if (skipAutoPreview) { continue; } const div = box.parentNode.nextSibling.nextSibling; const button = div.firstChild.nextSibling; const autoPreviewChecked = factory.getAutoPreviewCheckbox().checked; if (button && autoPreviewChecked) { button.click(); } } }, getFormatSelect() { return document.querySelector('#yadg_format'); }, setDefaultFormat() { const formatSelect = factory.getFormatSelect(); const formatOffsets = yadgUtil.getOptionOffsets(formatSelect); const defaultFormat = yadgUtil.settings.getItem( factory.KEY_DEFAULT_TEMPLATE, ); if (defaultFormat !== null && defaultFormat in formatOffsets) { formatSelect.selectedIndex = formatOffsets[defaultFormat]; } else { // We have no settings so fall back to the hard coded defaults switch (this.currentLocation) { default: formatSelect.selectedIndex = formatOffsets[defaultPTHFormat]; break; } } }, getCoverSize() { return document.querySelector('#yadg_coversize'); }, getTargetSelect() { return document.querySelector('#yadg_target'); }, getDescriptionTargetSelect() { return document.querySelector('#yadg_description_target'); }, setDefaultTarget() { const targetSelect = factory.getTargetSelect(); const targetOffsets = yadgUtil.getOptionOffsets(targetSelect); const defaultTarget = yadgUtil.settings.getItem(factory.KEY_DEFAULT_TARGET); targetSelect.selectedIndex = defaultTarget !== null && defaultTarget in targetOffsets ? targetOffsets[defaultTarget] : targetOffsets[defaultPTHTarget]; }, setDefaultDescriptionTarget() { const targetDescriptionSelect = factory.getDescriptionTargetSelect(); const targetDescriptionOffsets = yadgUtil.getOptionOffsets( targetDescriptionSelect, ); const defaultDescriptionTarget = yadgUtil.settings.getItem( factory.KEY_DESCRIPTION_TARGET, ); if ( defaultDescriptionTarget !== null && defaultDescriptionTarget in targetDescriptionOffsets ) { targetDescriptionSelect.selectedIndex = targetDescriptionOffsets[defaultDescriptionTarget]; } else { targetDescriptionSelect.selectedIndex = targetDescriptionOffsets[defaultPTHDescriptionTarget]; } }, getScraperSelect() { return document.querySelector('#yadg_scraper'); }, setDefaultScraper() { const defaultScraper = yadgUtil.settings.getItem( factory.KEY_DEFAULT_SCRAPER, ); if (defaultScraper !== null) { const scraperSelect = factory.getScraperSelect(); const scraperOffsets = yadgUtil.getOptionOffsets(scraperSelect); if (defaultScraper in scraperOffsets) { scraperSelect.selectedIndex = scraperOffsets[defaultScraper]; } } }, setScraperSelect(scrapers) { const scraperSelect = factory.getScraperSelect(); factory.setSelect(scraperSelect, scrapers); factory.setDefaultScraper(); if (factory.UPDATE_PROGRESS > 0) { yadgUtil.storage.addItem(factory.KEY_SCRAPER_LIST, scrapers); factory.UPDATE_PROGRESS |= 1 << 1; if (factory.UPDATE_PROGRESS === 7) { yadgUtil.storage.addItem(factory.KEY_LAST_CHECKED, new Date()); } } }, setFormatSelect(templates) { const formatSelect = factory.getFormatSelect(); const nonUtility = []; const saveTemplates = []; for (const element of templates) { if (factory.UPDATE_PROGRESS > 0) { if (element.name === 'What') { element.name = 'RED'; element.nameFormatted = 'RED'; } else if (element.name === 'What (Tracks only)') { element.name = 'RED (Tracks only)'; element.nameFormatted = 'RED (Tracks only)'; } yadgTemplates.addTemplate(element); saveTemplates.push({ id: element.id, url: element.url, name: element.name, nameFormatted: element.nameFormatted, owner: element.owner, default: element.default, isUtility: element.isUtility, }); } else { if (element.name === 'What') { element.name = 'PTH'; element.nameFormatted = 'PTH'; } else if (element.name === 'What (Tracks only)') { element.name = 'PTH (Tracks only)'; element.nameFormatted = 'PTH (Tracks only)'; } yadgTemplates.addTemplateUrl(element.id, element.url); } if (!element.isUtility) { nonUtility.push(element); } } factory.setSelect(formatSelect, nonUtility); factory.setDefaultFormat(); factory.setDefaultTarget(); factory.setDefaultDescriptionTarget(); if (factory.UPDATE_PROGRESS > 0) { yadgUtil.storage.addItem(factory.KEY_FORMAT_LIST, saveTemplates); factory.UPDATE_PROGRESS |= 1 << 2; if (factory.UPDATE_PROGRESS === 7) { yadgUtil.storage.addItem(factory.KEY_LAST_CHECKED, new Date()); } } }, setSelect(select, data) { select.options.length = data.length; for (const [i, element] of data.entries()) { // We are not using the javascript constructor to create an Option instance because this will create an // incompatibility with jQuery in Chrome which will make it impossible to add a new artist field on redacted.ch const o = document.createElement('option'); o.text = 'nameFormatted' in element ? element.nameFormatted : element.name; o.value = element.value || element.id; o.selected = element.default; select.options[i] = o; if (element.default) { select.selectedIndex = i; } if (element.url) { o.dataset.url = element.url; } } }, setStyles() { // General styles yadgUtil.addCSS( 'div#yadg_options{ display:none; margin-top:3px; } input#yadg_input,input#yadg_submit,label#yadg_format_label,a#yadg_scraper_info { margin-right: 5px } div#yadg_response { margin-top:3px; } select#yadg_scraper { margin-right: 2px } #yadg_options_template,#yadg_options_api_token,#yadg_options_replace_div { margin-bottom: 3px; } .add_form[name="yadg"] input,.add_form[name="yadg"] select { width: 90%; margin: 2px 0 !important; } input#yadg_submit { position: inherit !important} div#yadg_options_coversize { display:none; padding-left: 16px }', ); }, // eslint-disable-next-line complexity getInputElements() { const buttonHTML = '<input type="submit" value="Fetch" id="yadg_submit"/>'; const scraperSelectHTML = '<select name="yadg_scraper" id="yadg_scraper"></select>'; let optionsHTML = '<div id="yadg_options"><div id="yadg_options_template"><label for="yadg_format" id="yadg_format_label">Template:</label><select name="yadg_format" id="yadg_format"></select></div><div id="yadg_options_target"><label for="yadg_target" id="yadg_target_label">Edition:</label><select name="yadg_target" id="yadg_target"><option value="original">Original</option><option value="other">Other</option></select></div><div id="yadg_options_description_target"><label for="yadg_description_target" id="yadg_description_target_label">Description:</label><select name="yadg_description_target" id="yadg_description_target"><option value="album">Album</option><option value="release">Release</option><option value="both">Both</option></select></div><div id="yadg_options_api_token"><label for="yadg_api_token" id="yadg_api_token_label">API token (<a href="https://yadg.cc/api/token" target="_blank">Get one here</a>):</label> <input type="text" name="yadg_api_token" id="yadg_api_token" size="50" /></div><div id="yadg_options_replace_div"><input type="checkbox" name="yadg_options_replace" id="yadg_options_replace" /> <label for="yadg_options_replace" id="yadg_options_replace_label">Replace descriptions on this page</label></div><div id="yadg_options_image_div"><input type="checkbox" name="yadg_options_image" id="yadg_options_image" /> <label for="yadg_options_image" id="yadg_options_image_label">Auto fetch Album Art (Allmusic, Bandcamp, Beatport, Deezer, Discogs, iTunes, Junodownload, Metal-Archives, MusicBrainz)</label></div>'; optionsHTML += '<div id="yadg_options_coversize"><label for="yadg_coversize" id="yadg_coversize_label">Cover size: </label><select name="yadg_coversize" id="yadg_coversize"><option value="large">Large</option><option value="medium">Medium</option></select></div>'; if (document.querySelectorAll('.rehost_it_cover')[0]) { optionsHTML += '<div id="yadg_options_rehost_div"><input type="checkbox" name="yadg_options_rehost" id="yadg_options_rehost" /> <label for="yadg_options_rehost" id="yadg_options_rehost_label">Auto rehost with <a href="https://redacted.ch/forums.php?action=viewthread&threadid=1992">[User Script] PTPIMG URL uploader</a></label></div>'; } optionsHTML += '<div id="yadg_options_preview_div"><input type="checkbox" name="yadg_options_preview" id="yadg_options_preview" /> <label for="yadg_options_preview" id="yadg_options_preview_label">Auto preview description</label></div>'; optionsHTML += '<div id="yadg_options_auto_select_scraper_div"><input type="checkbox" name="yadg_options_auto_select_scraper" id="yadg_options_auto_select_scraper"/><label for="yadg_options_auto_select_scraper" id="yadg_options_auto_select_scraper_label">Auto select the correct scraper when pasting the URL</label></div> '; optionsHTML += '<div id="yadg_options_links"><a id="yadg_save_settings" href="#" title="Save the currently selected scraper and template as default for this site and save the given API token.">Save settings</a> <span class="yadg_separator">|</span> <a id="yadg_clear_cache" href="#">Clear cache</a></div></div>'; const inputHTML = '<input type="text" name="yadg_input" id="yadg_input" size="60" />'; const responseDivHTML = '<div id="yadg_response"></div>'; const toggleOptionsLinkHTML = '<a id="yadg_toggle_options" href="#">Toggle options</a>'; const scraperInfoLink = '<a id="yadg_scraper_info" href="https://yadg.cc/available-scrapers" target="_blank" title="Get additional information on the available scrapers">[?]</a>'; switch (this.currentLocation) { case 'ops_upload': case 'dic_upload': case 'pth_upload': { const tr = document.createElement('tr'); tr.className = 'yadg_tr'; tr.innerHTML = '<td class="label">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>'; return tr; } case 'lemonhd_upload': { const tr = document.createElement('tr'); tr.className = 'yadg_tr'; tr.innerHTML = '<td class="label rowhead nowrap" align="right">YADG:</td><td class="rowfollow">' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>'; return tr; } case 'opencd_upload': { const tr = document.createElement('tr'); tr.className = 'yadg_tr'; tr.innerHTML = '<td class="label" align="right"><b>YADG:</b></td><td colspan="5" class="embedded" style="margin-right:5px; margin-left:5px">' + '<table style="width:99%; margin-left:0.5%"><tbody><tr><td class="embedded" align="left">' + '<input type="text" name="yadg_input" id="yadg_input" size="60" /></td><td>' + scraperSelectHTML + '</td><td>' + scraperInfoLink + '</td><td>' + buttonHTML + '</td><td>' + toggleOptionsLinkHTML + '</td></tr><tr><td colspan="5">' + optionsHTML + responseDivHTML + ' ' + '</td><tr></tbody></table>' + '</td>'; return tr; } case 'ops_edit': case 'dic_edit': case 'pth_edit': { const div = document.createElement('div'); div.className = 'yadg_div'; div.innerHTML = '<h3 class="label">YADG:</h3>\n' + inputHTML + '\n' + scraperSelectHTML + '\n' + scraperInfoLink + '\n' + buttonHTML + '\n' + toggleOptionsLinkHTML + '\n' + optionsHTML + '\n' + responseDivHTML; return div; } case 'ops_torrent_overview': case 'dic_torrent_overview': case 'pth_torrent_overview': { const div = document.createElement('div'); div.id = 'yadg_div'; div.className = 'box'; div.innerHTML = '<div class="head"><strong>YADG</strong></div>\n<div class="body">\n<form class="add_form" name="yadg" method="post">\n<input type="text" name="yadg_input" id="yadg_input" />\n' + scraperSelectHTML + '\n' + scraperInfoLink + '\n' + buttonHTML + '\n' + toggleOptionsLinkHTML + '\n' + optionsHTML + '\n' + responseDivHTML; return div; } case 'ops_request': case 'ops_request_edit': case 'dic_request': case 'dic_request_edit': case 'pth_request': case 'pth_request_edit': { const tr = document.createElement('tr'); tr.className = 'yadg_tr'; tr.innerHTML = '<td class="label">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>'; return tr; } default: // This should actually never happen return document.createElement('div'); } }, // eslint-disable-next-line complexity insertIntoPage(element) { // alert(this.currentLocation) switch (this.currentLocation) { case 'ops_upload': case 'dic_upload': case 'pth_upload': { const yearTr = document.querySelector('#year_tr'); yearTr.parentNode.insertBefore(element, yearTr); break; } case 'lemonhd_upload': const tr = document.querySelector("#compose > table > tbody > tr:nth-child(3)"); tr.parentNode.insertBefore(element, tr); break; case 'opencd_upload': const trd = document.querySelector("#compose > table > tbody > tr:nth-child(5)"); trd.parentNode.insertBefore(element, trd); break; case 'ops_edit': case 'dic_edit': case 'pth_edit': { const [summaryInput] = document.getElementsByName('summary'); summaryInput.parentNode.insertBefore( element, summaryInput.nextSibling.nextSibling, ); break; } case 'ops_torrent_overview': case 'dic_torrent_overview': case 'pth_torrent_overview': { const [addArtistsBox] = document.querySelectorAll('.box_addartists'); addArtistsBox.parentNode.insertBefore( element, addArtistsBox.nextSibling.nextSibling, ); break; } case 'ops_request': case 'ops_request_edit': case 'dic_request': case 'dic_request_edit': case 'pth_request': case 'pth_request_edit': { const artistTr = document.querySelector('#artist_tr'); artistTr.parentNode.insertBefore(element, artistTr); break; } default: break; } }, // eslint-disable-next-line complexity getDescriptionBox() { switch (this.currentLocation) { case 'ops_upload': case 'dic_upload': case 'pth_upload': if (factory.getDescriptionTargetSelect().value === 'album') { return document.querySelector('#album_desc'); } if (factory.getDescriptionTargetSelect().value === 'release') { return document.querySelector('#release_desc'); } if (factory.getDescriptionTargetSelect().value === 'both') { return [ document.querySelector('#album_desc'), document.querySelector('#release_desc'), ]; } break; case 'lemonhd_upload': if (factory.getDescriptionTargetSelect().value === 'album') { return document.querySelector('#descr'); } if (factory.getDescriptionTargetSelect().value === 'release') { return document.querySelector('#descr'); } if (factory.getDescriptionTargetSelect().value === 'both') { return [ document.querySelector('#descr'), document.querySelector('#descr'), ]; } break; case 'opencd_upload': if (factory.getDescriptionTargetSelect().value === 'album') { return document.querySelector('#descr'); } if (factory.getDescriptionTargetSelect().value === 'release') { return document.querySelector('#descr'); } if (factory.getDescriptionTargetSelect().value === 'both') { return [ document.querySelector('#descr'), document.querySelector('#descr'), ]; } break; case 'ops_edit': case 'dic_edit': case 'pth_edit': return document.getElementsByName('body')[0]; case 'ops_torrent_overview': case 'dic_torrent_overview': case 'pth_torrent_overview': if (!Object.prototype.hasOwnProperty.call(this, 'dummybox')) { this.dummybox = document.createElement('div'); } return this.dummybox; case 'ops_request': case 'ops_request_edit': case 'dic_request': case 'dic_request_edit': case 'pth_request': case 'pth_request_edit': return document.getElementsByName('description')[0]; default: // That should actually never happen return document.createElement('div'); } }, // eslint-disable-next-line complexity getFormFillFunction() { const currentTarget = factory.getTargetSelect().value; var type_dict = { "electronic": "电子(Electronic)", "blues": "蓝调(Blues)", "blues": "蓝调(Blues)", "rhythm.and.blues": "蓝调(Blues)", "classical": "古典(Classical)", "country": "乡村(Country)", "folk": "民间(Folk)", "drum.and.bass": "贝斯(Drum Bass)", "jazz": "爵士(Jazz)", "new.age": "新世纪(NewAge)", "soul": "天籁(Soul)", "modern.classical": "古典(Classical)", "garage.house": "汽车(garage)", "garage.rock": "汽车(garage)", "reggae": "雷鬼(Reggae)", "hip.hop": "嘻哈(Hip Hop)", "instrumental": "器乐(Instrumental)", "indie": "独立(Indie)", "japanese": "日韩", "korean": "日韩", "chinese": "大陆", "thai": "其他地区", "dance": "舞曲(Dance)","english": "欧美" }; var info = { "大陆": "1","欧美": "2","港台": "3","日韩": "4","其它地区": "5","流行(Pop)": "6", "发烧(HiFi)": "7","汽车(garage)": "8","古典(Classical)": "9","民族(National)": "10", "摇滚(rock)": "11","原声(OST)": "12","民间(Folk)": "13","乡村(Country)": "14", "天籁(Soul)": "15","新世纪(NewAge)": "16","蓝调(Blues)": "17","爵士(Jazz)": "18", "金属(Metal)": "19","朋克(Punk)": "20","电子(Electronic)": "21","儿童(Children's)": "22", "宗教(Religion)": "23","雷鬼(Reggae)": "24","贝斯(Drum Bass)": "25","说唱(Rap)": "26","音乐剧(musical)": "27" }; function getDescr(rawData) { var descr = `[size=4][b]Album Info[/b][/size]\n`; if (rawData.title) { descr += `[b]Music title[/b]: ${rawData.title}\n`; } if (rawData.artists.length) { descr += `[b]Music artists[/b]: ${rawData.artists[0].name}\n`; } if (rawData.format) { descr += `[b]Music format[/b]: ${rawData.format}\n`; } if (rawData.styles.length) { descr += `[b]Music style[/b]: ${rawData.styles.join(', ')}\n`; } if (rawData.genres.length) { descr += `[b]Music Genres[/b]: ${rawData.genres.join(' | ')}\n`; } if (rawData.releaseEvents.length) { descr += `[b]Music release[/b]: ${rawData.releaseEvents[0].country}-${rawData.releaseEvents[0].date}\n`; } if (rawData.labelIds.length) { descr += '[b]Music labelIds[/b]: '; rawData.labelIds.map((item, index)=>{ if (index == 0) { descr += `${item.label}(${item.catalogueNrs[0]}); `; } else { descr += `${item.label}(${item.catalogueNrs[0]});`; } }) } if (rawData.url) { descr += '\n\n' + `More information: [url]${rawData.url}[/url]`; } return descr; } function getMinute(i) { var hour = parseInt(i/3600); if (hour > 0) { i = i % 3600; } var minutes = parseInt(i/60); var seconds = i % 60; var timeStr = `(${minutes}:${seconds})`; if (hour) { timeStr = `(${hour}:${minutes}:${seconds})`; } return timeStr; } switch (this.currentLocation) { case 'lemonhd_upload': { const f = function (rawData) { console.log(rawData) let albumTitleInput; let yearInput; let labelInput; let catalogInput; albumTitleInput = document.querySelector('[name=title]'); yearInput = document.querySelector('[name=remaster_year]'); labelInput = document.querySelector('[name=remaster_record_label]'); catalogInput = document.querySelector('[name=remaster_catalogue_number]'); if (/music.apple/.test(rawData.url)) { switch (true) { case /.+ - Single$/.test(rawData.title): rawData.title = rawData.title.replace(/ - Single$/, ''); $('select[name=music_category]').val(3); break; case /.+ - EP$/.test(rawData.title): rawData.title = rawData.title.replace(/ - EP$/, ''); $('select[name=music_category]').val(4); } } var descr = getDescr(rawData); $('#descr').val(descr + $('#descr').val()); let artistInputs = document.getElementsByName('artists[]'); const releaseTypeInput = document.querySelector('[name=music_category]'); const data = yadg.prepareRawResponse(rawData); console.log(data) let nullArtistCount = 0; if (artistInputs[0].getAttribute('disabled') !== 'disabled') { if (data.artists === false) { for (const element of artistInputs) { element.value = ''; } } else { let inputIdx = 0; yadgUtil.addRemoveArtistBoxes( data.effective_artist_count - artistInputs.length, ); artistInputs = document.getElementsByName('artists[]'); for (let i = 0; i < data.artist_keys.length; i++) { const artistKey = data.artist_keys[i]; if (artistKey === 'null') { nullArtistCount++; continue; } const artistTypes = data.artists[artistKey]; for (const artistType of artistTypes) { const artistInput = artistInputs[inputIdx]; let typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') { typeSelect = typeSelect.nextSibling; } artistInput.value = artistKey; const optionOffsets = yadgUtil.getOptionOffsets(typeSelect); switch (artistType) { case 'main': { typeSelect.selectedIndex = optionOffsets[1]; break; } case 'guest': { typeSelect.selectedIndex = optionOffsets[2]; break; } case 'remixer': { typeSelect.selectedIndex = optionOffsets[3]; break; } default: { // We don't know this artist type, default to "main" typeSelect.selectedIndex = optionOffsets[1]; } } // Next artist input inputIdx += 1; } } if (nullArtistCount > 0) { yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1)); } } } if (yearInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); } if (albumTitleInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.title, albumTitleInput, data.title !== false, ); } if (labelInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.label, labelInput, data.label !== false, ); } if (catalogInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.catalog, catalogInput, data.catalog !== false, ); } // tags var music_type = []; data.tags.map((item)=>{ item = item.toLowerCase(); if (item.match(/pop/) && music_type.indexOf("流行(Pop)") < 0) { music_type.push("流行(Pop)"); } if (item.match(/rock/) && music_type.indexOf("摇滚(rock)") < 0) { music_type.push("摇滚(rock)"); } if (item.match(/punk/) && music_type.indexOf("朋克(Punk)") < 0) { music_type.push("朋克(Punk)"); } if (item.match(/Metal/i) && music_type.indexOf("金属(Metal)") < 0) { music_type.push("金属(Metal)"); } if (type_dict.hasOwnProperty(item) && music_type.indexOf(type_dict[item]) < 0) { music_type.push(type_dict[item]); } if (item.match(/alternative/) && music_type.indexOf("另类(Alternative)") < 0) { music_type.push("另类(Alternative)"); } if (item.match(/world.music/) && music_type.indexOf("世界音乐(World)") < 0) { music_type.push("世界音乐(World)"); } }); music_type.map((item)=>{ if (info.hasOwnProperty(item)) { addTag(info[item]); } }); var releasetype_dict = { 1:1, 3:9, 5:4, 6:6, 7:5, 9:3, 11:2, 13: 13, 14: 14, 15: 15, 16:16, 17: 17, 18:18, 19:19, 21:21 } data.releaseType = releasetype_dict[data.releaseType]; if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.releaseType, releaseTypeInput, data.releaseType !== false, ); } }; return f; } case 'opencd_upload': { // eslint-disable-next-line complexity const f = function (rawData) { console.log(rawData) let albumTitleInput; let yearInput; albumTitleInput = document.querySelector('[name=resource_name]'); yearInput = document.querySelector('[name=year]'); let artistInputs = document.getElementsByName('artist'); if (artistInputs[0].getAttribute('disabled') !== 'disabled') { if (rawData.artists.length) { artistInputs[0].value = rawData.artists[0].name; } } console.log(rawData); var descr = getDescr(rawData); if ($('#yadg2descr').length == 1) { $('#yadg2descr').remove(); $('#descr').parent().append(`<a style="text-decoration:none;" href="#" id="yadg2descr"><font color="red">从yadg导入</font></a>`); } else { $('#descr').parent().append(`<br><a style="text-decoration:none;" href="#" id="yadg2descr"><font color="red">从yadg导入</font></a>`); } $('#yadg2descr').click((e)=>{ e.preventDefault(); var originDescr = $('#descr').val(); $('#descr').val(descr + '\n\n' + originDescr); }); const data = yadg.prepareRawResponse(rawData); if (yearInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); } if (albumTitleInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.title, albumTitleInput, data.title !== false, ); } var tracklist = ``; if (rawData.discs.length) { rawData.discs.map(disc=>{ var total_time = 0; disc.tracks.map(item=>{ console.log(item.length); tracklist += `${item.number} – ${item.title}${item['length'] ? getMinute(item['length']): ''}\n`; total_time += item['length'] ? item['length'] : 0; }); tracklist += total_time? `\n[b]Total length:[/b] ${getMinute(total_time)}\n\n` : '\n\n'; }) } if ($('#yadg2dtracklit').length == 0) { $('textarea[name=track_list]').parent().append(`<br><a style="text-decoration:none;" href="#" id="yadg2dtracklit"><font color="red">从yadg导入</font></a>`); } $('#yadg2dtracklit').click((e)=>{ e.preventDefault(); $('textarea[name=track_list]').val(tracklist); }); // tags var music_type = []; if (data.tags) { data.tags.map((item)=>{ item = item.toLowerCase(); if (item.match(/pop/) && music_type.indexOf("流行(Pop)") < 0) { music_type.push("流行(Pop)"); } if (item.match(/rock/) && music_type.indexOf("摇滚(rock)") < 0) { music_type.push("摇滚(rock)"); } if (item.match(/punk/) && music_type.indexOf("朋克(Punk)") < 0) { music_type.push("朋克(Punk)"); } if (item.match(/Metal/i) && music_type.indexOf("金属(Metal)") < 0) { music_type.push("金属(Metal)"); } if (type_dict.hasOwnProperty(item) && music_type.indexOf(type_dict[item]) < 0) { music_type.push(type_dict[item]); } if (item.match(/alternative/) && music_type.indexOf("另类(Alternative)") < 0) { music_type.push("另类(Alternative)"); } if (item.match(/world.music/) && music_type.indexOf("世界音乐(World)") < 0) { music_type.push("世界音乐(World)"); } }); } setTimeout(function(){ var source_selected = false; music_type.map(item=>{ console.log(item) var source = $(`a.tag:contains("${item}")`); if (item == "贝斯(Drum Bass)") { source = $(`a.tag[value="25"]`); } if (source.lenth) { addTag(source); } if (!source_selected) { if (item == '摇滚(rock)') { item = '摇滚(Rock)'; } if ($(`#source>option:contains(${item})`).length) { $(`#source>option:contains(${item})`).attr('selected', true); source_selected = true; } } }) }, 500); var evt = document.createEvent("HTMLEvents"); evt.initEvent("change", false, true); document.getElementById('audio_mode').dispatchEvent(evt); }; return f; } case 'pth_upload': { // eslint-disable-next-line complexity const f = function (rawData) { let albumTitleInput; let yearInput; let labelInput; let catalogInput; if (currentTarget === 'other') { albumTitleInput = document.querySelector('#title'); yearInput = document.querySelector('#remaster_year'); labelInput = document.querySelector('#remaster_record_label'); catalogInput = document.querySelector('#remaster_catalogue_number'); unsafeWindow.CheckYear(); // eslint-disable-line new-cap } else { albumTitleInput = document.querySelector('#title'); yearInput = document.querySelector('#year'); labelInput = document.querySelector('#remaster_record_label'); catalogInput = document.querySelector('#remaster_catalogue_number'); } if (/music.apple/.test(rawData.url)) { const releaseTypeInput = document.querySelector('#releasetype'); switch (true) { case /.+ - Single$/.test(rawData.title): rawData.title = rawData.title.replace(/ - Single$/, ''); if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { releaseTypeInput.value = 9; } break; case /.+ - EP$/.test(rawData.title): rawData.title = rawData.title.replace(/ - EP$/, ''); if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { releaseTypeInput.value = 5; } break; default: break; } } let artistInputs = document.getElementsByName('artists[]'); const tagsInput = document.querySelector('#tags'); const mediaInput = document.querySelector('#media'); const releaseTypeInput = document.querySelector('#releasetype'); const data = yadg.prepareRawResponse(rawData); let nullArtistCount = 0; if (artistInputs[0].getAttribute('disabled') !== 'disabled') { if (data.artists === false) { for (const element of artistInputs) { element.value = ''; } } else { let inputIdx = 0; yadgUtil.addRemoveArtistBoxes( data.effective_artist_count - artistInputs.length, ); artistInputs = document.getElementsByName('artists[]'); for (let i = 0; i < data.artist_keys.length; i++) { const artistKey = data.artist_keys[i]; if (artistKey === 'null') { nullArtistCount++; continue; } const artistTypes = data.artists[artistKey]; for (const artistType of artistTypes) { const artistInput = artistInputs[inputIdx]; let typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') { typeSelect = typeSelect.nextSibling; } artistInput.value = artistKey; const optionOffsets = yadgUtil.getOptionOffsets(typeSelect); switch (artistType) { case 'main': { typeSelect.selectedIndex = optionOffsets[1]; break; } case 'guest': { typeSelect.selectedIndex = optionOffsets[2]; break; } case 'remixer': { typeSelect.selectedIndex = optionOffsets[3]; break; } default: { // We don't know this artist type, default to "main" typeSelect.selectedIndex = optionOffsets[1]; } } // Next artist input inputIdx += 1; } } if (nullArtistCount > 0) { yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1)); } } } if (tagsInput.getAttribute('disabled') !== 'disabled') { if (data.tags === false) { tagsInput.value = ''; } else { const tagsArray = data.tag_string.split(', '); const tagsUnique = tagsArray.filter((element, index, self) => index === self.indexOf(element)); tagsInput.value = tagsUnique.join(',').toLowerCase(); } } if (yearInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); } if (albumTitleInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.title, albumTitleInput, data.title !== false, ); } if (labelInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.label, labelInput, data.label !== false, ); } if (catalogInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.catalog, catalogInput, data.catalog !== false, ); } if (mediaInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.format, mediaInput, data.format !== false, ); } if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.releaseType, releaseTypeInput, data.releaseType !== false, ); } }; return f; } case 'ops_upload': { // eslint-disable-next-line complexity const f = function (rawData) { let albumTitleInput; let yearInput; let labelInput; let catalogInput; if (currentTarget === 'other') { const remaster = document.querySelector('#remaster'); albumTitleInput = document.querySelector('#title'); yearInput = document.querySelector('#remaster_year'); labelInput = document.querySelector('#remaster_record_label'); catalogInput = document.querySelector('#remaster_catalogue_number'); remaster.checked = 'checked'; unsafeWindow.Remaster(); // eslint-disable-line new-cap unsafeWindow.CheckYear(); // eslint-disable-line new-cap } else { albumTitleInput = document.querySelector('#title'); yearInput = document.querySelector('#year'); labelInput = document.querySelector('#record_label'); catalogInput = document.querySelector('#catalogue_number'); } if (/itunes/.test(rawData.url)) { const releaseTypeInput = document.querySelector('#releasetype'); switch (true) { case /.+ - Single$/.test(rawData.title): rawData.title = rawData.title.replace(/ - Single$/, ''); if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { releaseTypeInput.value = 9; } break; case /.+ - EP$/.test(rawData.title): rawData.title = rawData.title.replace(/ - EP$/, ''); if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { releaseTypeInput.value = 5; } break; default: break; } } let artistInputs = document.getElementsByName('artists[]'); const tagsInput = document.querySelector('#tags'); const data = yadg.prepareRawResponse(rawData); let nullArtistCount = 0; if (artistInputs[0].getAttribute('disabled') !== 'disabled') { if (data.artists === false) { for (const element of artistInputs) { element.value = ''; } } else { let inputIdx = 0; yadgUtil.addRemoveArtistBoxes( data.effective_artist_count - artistInputs.length, ); artistInputs = document.getElementsByName('artists[]'); for (let i = 0; i < data.artist_keys.length; i++) { const artistKey = data.artist_keys[i]; if (artistKey === 'null') { nullArtistCount++; continue; } const artistTypes = data.artists[artistKey]; for (const artistType of artistTypes) { const artistInput = artistInputs[inputIdx]; let typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') { typeSelect = typeSelect.nextSibling; } artistInput.value = artistKey; const optionOffsets = yadgUtil.getOptionOffsets(typeSelect); switch (artistType) { case 'main': { typeSelect.selectedIndex = optionOffsets[1]; break; } case 'guest': { typeSelect.selectedIndex = optionOffsets[2]; break; } case 'remixer': { typeSelect.selectedIndex = optionOffsets[3]; break; } default: { // We don't know this artist type, default to "main" typeSelect.selectedIndex = optionOffsets[1]; } } // Next artist input inputIdx += 1; } } if (nullArtistCount > 0) { yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1)); } } } if (tagsInput.getAttribute('disabled') !== 'disabled') { if (data.tags === false) { tagsInput.value = ''; } else { const tagsArray = data.tag_string.split(', '); const tagsUnique = tagsArray.filter((element, index, self) => index === self.indexOf(element)); tagsInput.value = tagsUnique.join(',').toLowerCase(); } } if (yearInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); } if (albumTitleInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.title, albumTitleInput, data.title !== false, ); } if (labelInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.label, labelInput, data.label !== false, ); } if (catalogInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.catalog, catalogInput, data.catalog !== false, ); } }; return f; } case 'dic_upload': { // eslint-disable-next-line complexity const f = function (rawData) { let albumTitleInput; let yearInput; let labelInput; let catalogInput; if (currentTarget === 'other') { albumTitleInput = document.querySelector('#title'); yearInput = document.querySelector('#remaster_year'); labelInput = document.querySelector('#remaster_record_label'); catalogInput = document.querySelector('#remaster_catalogue_number'); unsafeWindow.CheckYear(); // eslint-disable-line new-cap } else { const unknownCheckbox = document.querySelector('#unknown'); albumTitleInput = document.querySelector('#title'); yearInput = document.querySelector('#year'); unknownCheckbox.checked = 'checked'; unsafeWindow.ToggleUnknown(); // eslint-disable-line new-cap } const releaseTypeInput = document.querySelector('#releasetype'); if (/itunes/.test(rawData.url)) { switch (true) { case /.+ - Single$/.test(rawData.title): rawData.title = rawData.title.replace(/ - Single$/, ''); if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { releaseTypeInput.value = 9; } break; case /.+ - EP$/.test(rawData.title): rawData.title = rawData.title.replace(/ - EP$/, ''); if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { releaseTypeInput.value = 5; } break; default: break; } } let artistInputs = document.getElementsByName('artists[]'); const tagsInput = document.querySelector('#tags'); const data = yadg.prepareRawResponse(rawData); let nullArtistCount = 0; if (artistInputs[0].getAttribute('disabled') !== 'disabled') { if (data.artists === false) { for (const element of artistInputs) { element.value = ''; } } else { let inputIdx = 0; yadgUtil.addRemoveArtistBoxes( data.effective_artist_count - artistInputs.length, ); artistInputs = document.getElementsByName('artists[]'); for (let i = 0; i < data.artist_keys.length; i++) { const artistKey = data.artist_keys[i]; if (artistKey === 'null') { nullArtistCount++; continue; } const artistTypes = data.artists[artistKey]; for (const artistType of artistTypes) { const artistInput = artistInputs[inputIdx]; let typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') { typeSelect = typeSelect.nextSibling; } artistInput.value = artistKey; const optionOffsets = yadgUtil.getOptionOffsets(typeSelect); switch (artistType) { case 'main': { typeSelect.selectedIndex = optionOffsets[1]; break; } case 'guest': { typeSelect.selectedIndex = optionOffsets[2]; break; } case 'remixer': { typeSelect.selectedIndex = optionOffsets[3]; break; } default: { // We don't know this artist type, default to "main" typeSelect.selectedIndex = optionOffsets[1]; } } // Next artist input inputIdx += 1; } } if (nullArtistCount > 0) { yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1)); } } } if (tagsInput.getAttribute('disabled') !== 'disabled') { if (data.tags === false) { tagsInput.value = ''; } else { const tagsArray = data.tag_string.split(', '); const tagsUnique = tagsArray.filter((element, index, self) => index === self.indexOf(element)); tagsInput.value = tagsUnique.join(',').toLowerCase(); } } if (yearInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); } if (albumTitleInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.title, albumTitleInput, data.title !== false, ); } if (labelInput && labelInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.label, labelInput, data.label !== false, ); } if (catalogInput && catalogInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.catalog, catalogInput, data.catalog !== false, ); } if (releaseTypeInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet( data.releaseType, releaseTypeInput, data.releaseType !== false, ); } }; return f; } case 'ops_edit': case 'dic_edit': case 'pth_edit': { const f = function (rawData) { const [summaryInput] = document.getElementsByName('summary'); const [yearInput] = document.getElementsByName('year'); const [labelInput] = document.getElementsByName('record_label'); const [catalogInput] = document.getElementsByName('catalogue_number'); const data = yadg.prepareRawResponse(rawData); summaryInput.value = 'YADG Update'; if (yearInput && yearInput.getAttribute('disabled') !== 'disabled') { yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); } if ( labelInput && labelInput.getAttribute('disabled') !== 'disabled' ) { yadgUtil.setValueIfSet( data.label, labelInput, data.label !== false, ); } if ( catalogInput && catalogInput.getAttribute('disabled') !== 'disabled' ) { yadgUtil.setValueIfSet( data.catalog, catalogInput, data.catalog !== false, ); } }; return f; } case 'ops_torrent_overview': case 'dic_torrent_overview': case 'pth_torrent_overview': { const f = function (rawData) { let artistInputs = document.getElementsByName('aliasname[]'); const data = yadg.prepareRawResponse(rawData); if (data.artists === false) { for (const element of artistInputs) { element.value = ''; } } else { let inputIdx = 0; yadgUtil.addRemoveArtistBoxes( data.effective_artist_count - artistInputs.length, ); artistInputs = document.getElementsByName('aliasname[]'); for (let i = 0; i < data.artist_keys.length; i++) { const artistKey = data.artist_keys[i]; const artistTypes = data.artists[artistKey]; for (const artistType of artistTypes) { const artistInput = artistInputs[inputIdx]; let typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') { typeSelect = typeSelect.nextSibling; } artistInput.value = artistKey; const optionOffsets = yadgUtil.getOptionOffsets(typeSelect); switch (artistType) { case 'main': { typeSelect.selectedIndex = optionOffsets[1]; break; } case 'guest': { typeSelect.selectedIndex = optionOffsets[2]; break; } case 'remixer': { typeSelect.selectedIndex = optionOffsets[3]; break; } default: { // We don't know this artist type, default to "main" typeSelect.selectedIndex = optionOffsets[1]; } } // Next artist input inputIdx += 1; } } } }; return f; } case 'ops_request': case 'ops_request_edit': case 'dic_request': case 'dic_request_edit': case 'pth_request': case 'pth_request_edit': { const f = function (rawData) { let artistInputs = document.getElementsByName('artists[]'); const [albumTitleInput] = document.getElementsByName('title'); const [yearInput] = document.getElementsByName('year'); const [labelInput] = document.getElementsByName('recordlabel'); const [catalogInput] = document.getElementsByName('cataloguenumber'); const tagsInput = document.querySelector('#tags'); const data = yadg.prepareRawResponse(rawData); let nullArtistCount = 0; if (!/groupid=\d+/.test(document.location.search)) { if (data.artists === false) { for (const element of artistInputs) { element.value = ''; } } else { let inputIdx = 0; yadgUtil.addRemoveArtistBoxes( data.effective_artist_count - artistInputs.length, ); artistInputs = document.getElementsByName('artists[]'); for (let i = 0; i < data.artist_keys.length; i++) { const artistKey = data.artist_keys[i]; const artistTypes = data.artists[artistKey]; if (artistKey === 'null') { nullArtistCount++; continue; } for (const artistType of artistTypes) { const artistInput = artistInputs[inputIdx]; let typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') { typeSelect = typeSelect.nextSibling; } artistInput.value = artistKey; const optionOffsets = yadgUtil.getOptionOffsets(typeSelect); switch (artistType) { case 'main': { typeSelect.selectedIndex = optionOffsets[1]; break; } case 'guest': { typeSelect.selectedIndex = optionOffsets[2]; break; } case 'remixer': { typeSelect.selectedIndex = optionOffsets[3]; break; } default: { // We don't know this artist type, default to "main" typeSelect.selectedIndex = optionOffsets[1]; } } // Next artist input inputIdx += 1; } } if (nullArtistCount > 0) { yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1)); } } tagsInput.value = data.tags === false ? '' : data.tag_string.toLowerCase(); yadgUtil.setValueIfSet( data.title, albumTitleInput, data.title !== false, ); } yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false); yadgUtil.setValueIfSet(data.label, labelInput, data.label !== false); yadgUtil.setValueIfSet( data.catalog, catalogInput, data.catalog !== false, ); }; return f; } default: // That should actually never happen return function () {}; } }, }; yadgTemplates = { _templates: {}, _templateUrls: {}, getTemplate(id, callback) { if (id in this._templates) { callback(this._templates[id]); } else if (id in this._templateUrls) { const request = new Requester( this._templateUrls[id], 'GET', template => { yadgTemplates.addTemplate(template); callback(template); }, null, yadgTemplates.errorTemplate, ); request.send(); } else { this.errorTemplate(); } }, addTemplate(template) { this._templates[template.id] = template; }, addTemplateUrl(id, url) { this._templateUrls[id] = url; }, errorTemplate() { yadg.printError('Could not get template. Please choose another one.', true); }, }; yadgRenderer = { _lastData: null, _lastTemplateId: null, render(templateId, data, callback, errorCallback) { this._lastData = data; const newTemplate = this._lastTemplateId !== templateId; this._lastTemplateId = templateId; yadgTemplates.getTemplate(templateId, template => { // The new template might have different dependencies, so initialize Swig with those if (newTemplate) { yadgSandbox.resetSandbox(); yadgSandbox.initializeSwig(template.dependencies); } template.code = template.code.replace( 'https://what.cd', 'https://' + window.location.hostname, ); yadgSandbox.renderTemplate(template.code, data, callback, errorCallback); }); }, renderCached(templateId, callback, errorCallback) { if (this.hasCached()) { this.render(templateId, this._lastData, callback, errorCallback); } }, hasCached() { return this._lastData !== null; }, clearCached() { this._lastData = null; }, }; yadg = { yadgHost: 'https://yadg.cc', baseURI: '/api/v2/', standardError: 'Sorry, an error occured. Please try again. If this error persists check on <a href="https://yadg.cc">yadg.cc</a> before reporting an error with the userscript.', authenticationError: 'Your API token is invalid. Please provide a valid API token or remove the current one.', lastStateError: false, isBusy: false, init() { this.scraperSelect = document.querySelector('#yadg_scraper'); this.formatSelect = document.querySelector('#yadg_format'); this.input = document.querySelector('#yadg_input'); this.targetSelect = document.querySelector('#yadg_target'); this.targetDescriptionSelect = document.querySelector( '#yadg_description_target', ); this.responseDiv = document.querySelector('#yadg_response'); this.button = document.querySelector('#yadg_submit'); }, getBaseURL() { return this.yadgHost + this.baseURI; }, getScraperList(callback) { const url = this.getBaseURL() + 'scrapers/'; const request = new Requester(url, 'GET', callback); request.send(); }, getFormatsList(callback) { const url = this.getBaseURL() + 'templates/'; this.getTemplates(url, [], callback); }, getTemplates(url, templates, callback) { const request = new Requester(url, 'GET', data => { for (let i = 0; i < data.results.length; i++) { templates.push(data.results[i]); } if (data.next === null) { callback(templates); } else { yadg.getTemplates(data.next, templates, callback); } }); request.send(); }, makeRequest(parameters) { if (this.isBusy) { return; } let data; if (parameters) { data = parameters; } else { // If beta.musicbrainz.org link strip query params and remove beta if (this.input.value.includes('beta.musicbrainz.org')) { this.input.value = this.input.value.replace(/beta./, ''); this.input.value = this.input.value.replace(/\?.*$/, ''); } data = { scraper: this.scraperSelect.options[this.scraperSelect.selectedIndex] .value, input: this.input.value, }; } const url = this.getBaseURL() + 'query/'; if (data.input !== '') { const request = new Requester( url, 'POST', result => { yadg.getResult(result.url); }, data, ); this.busyStart(); request.send(); } }, getResult(resultUrl) { const request = new Requester(resultUrl, 'GET', response => { if (response.status === 'done') { switch (response.data.type) { case 'ReleaseResult': { const templateId = yadg.formatSelect.options[yadg.formatSelect.selectedIndex].value; yadgRenderer.render( templateId, response, factory.setDescriptionBoxValue, factory.setDescriptionBoxValue, ); if (yadg.lastStateError === true) { yadg.responseDiv.innerHTML = ''; yadg.lastStateError = false; } const fillFunc = factory.getFormFillFunction(); fillFunc(response.data); break; } case 'ListResult': { const ul = document.createElement('ul'); ul.id = 'yadg_release_list'; const releaseList = response.data.items; for (const element of releaseList) { const {name, info, queryParams} = element; const releaseUrl = element.url; if (name.match(/ううううううう/)) { continue; } const li = document.createElement('li'); const a = document.createElement('a'); a.textContent = name; a.params = queryParams; a.href = releaseUrl; a.addEventListener( 'click', function (event) { event.preventDefault(); yadg.makeRequest(this.params); if (factory.getFetchImageCheckbox().checked) { fetchImage(this.href, data => { insertImage(data, () => { if ( factory.getAutoRehostCheckbox() && factory.getAutoRehostCheckbox().checked ) { pthImgIt(); } }); }); } }, false, ); li.append(a); li.append(document.createElement('br')); if (info) { li.append(document.createTextNode(info)); } ul.append(li); } if (ul.childNodes.length === 0) { yadg.printError('Sorry, there were no matches.'); } else { yadg.responseDiv.innerHTML = ''; yadg.responseDiv.append(ul); yadg.lastStateError = false; // We got a ListResult so clear the last ReleaseResult from the render cache yadgRenderer.clearCached(); } break; } case 'NotFoundResult': { yadg.printError( 'I could not find the release with the given ID. You may want to try again with another one.', ); break; } default: { yadg.printError('Something weird happened. Please try again'); } } yadg.busyStop(); } else if (response.status === 'failed') { yadg.failedCallback(); } else { const delay = function () { yadg.getResult(response.url); }; window.setTimeout(delay, 1000); } }); request.send(); }, printError(message, templateError) { this.responseDiv.innerHTML = message; if (!templateError) { this.lastStateError = true; // There was a non template related error, so for consistencies sake clear the last ReleaseResult from the // render cache yadgRenderer.clearCached(); } }, failedCallback() { yadg.printError(yadg.standardError); yadg.busyStop(); }, failedAuthenticationCallback() { yadg.printError(yadg.authenticationError); yadg.busyStop(); }, busyStart() { this.isBusy = true; this.button.setAttribute('disabled', true); this.button.value = 'Please wait...'; this.input.setAttribute('disabled', true); this.scraperSelect.setAttribute('disabled', true); this.formatSelect.setAttribute('disabled', true); this.targetSelect.setAttribute('disabled', true); }, busyStop() { this.button.removeAttribute('disabled'); this.button.value = 'Fetch'; this.input.removeAttribute('disabled'); this.scraperSelect.removeAttribute('disabled'); this.formatSelect.removeAttribute('disabled'); this.targetSelect.removeAttribute('disabled'); this.isBusy = false; }, // eslint-disable-next-line complexity prepareRawResponse(rawData) { const result = {}; result.artists = false; result.year = false; result.title = false; result.label = false; result.catalog = false; result.genre = false; result.style = false; result.tags = false; result.is_various = false; // eslint-disable-line camelcase result.flat_artistString = false; // eslint-disable-line camelcase result.format = false; result.releaseType = false; if (rawData.artists.length > 0) { result.artists = {}; for (let i = 0; i < rawData.artists.length; i++) { const artist = rawData.artists[i]; if (artist.isVarious) { result.is_various = true; // eslint-disable-line camelcase } else { result.artists[artist.name] = artist.types; } } } if (rawData.discs.length > 0) { for (let k = 0; k < rawData.discs.length; k++) { const disc = rawData.discs[k]; for (let l = 0; l < disc.tracks.length; l++) { const track = disc.tracks[l]; for (let m = 0; m < track.artists.length; m++) { const {name} = track.artists[m]; const type = track.artists[m].types; let newTypes = null; if (name in result.artists) { newTypes = result.artists[name].concat(type); // Deduplicate new types array for (let i = 0; i < newTypes.length; ++i) { for (let j = i + 1; j < newTypes.length; ++j) { if (newTypes[i] === newTypes[j]) { newTypes.splice(j--, 1); } } } } else { newTypes = type; } result.artists[name] = newTypes; } } } } for (let i = 0; i < rawData.releaseEvents.length; i++) { const event = rawData.releaseEvents[i]; if (event.date) { [result.year] = event.date.match(/\d{4}/); if (result.year.length === 4) { break; } else { result.year = false; } } } if (rawData.title) { result.title = rawData.title; } if (rawData.labelIds.length > 0) { const [labelId] = rawData.labelIds; if (labelId.label) { result.label = labelId.label; } if (labelId.catalogueNrs.length > 0) { [result.catalog] = labelId.catalogueNrs; } } if (rawData.genres.length > 0) { result.genre = rawData.genres; } if (rawData.styles.length > 0) { result.style = rawData.styles; } if (result.genre !== false && result.style !== false) { result.tags = rawData.genres.concat(rawData.styles); } else if (result.genre !== false) { result.tags = rawData.genres; } else if (result.style !== false) { result.tags = rawData.styles; } if (result.tags !== false) { result.tag_string = ''; // eslint-disable-line camelcase result.tag_string_nodots = ''; // eslint-disable-line camelcase for (let i = 0; i < result.tags.length; i++) { switch (result.tags[i]) { case 'Techno (Peak Time / Driving)': result.tags[i] = 'Techno'; break; case 'Techno (Raw / Deep / Hypnotic)': result.tags[i] = 'Dub Techno'; break; case 'Minimal / Deep Tech': result.tags[i] = 'Tech House'; break; default: break; } result.tag_string += result.tags[i].replace(/\s+/g, '.').replace(/\bn\b|&/, 'and'); // eslint-disable-line camelcase result.tag_string_nodots += result.tags[i].replace(/\s+/g, ' '); // eslint-disable-line camelcase if (i !== result.tags.length - 1) { result.tag_string += ', '; // eslint-disable-line camelcase result.tag_string_nodots += ', '; // eslint-disable-line camelcase } } } if (result.artists !== false) { // Count the artists result.artists_length = 0; // eslint-disable-line camelcase result.artist_keys = []; // eslint-disable-line camelcase result.effective_artist_count = 0; // eslint-disable-line camelcase for (const i in result.artists) { if (Object.prototype.hasOwnProperty.call(result.artists, i)) { result.artists_length++; result.artist_keys.push(i); result.effective_artist_count += result.artists[i].length; // eslint-disable-line camelcase } } } if (result.artists_length === 0) { result.artists = false; } else { // Create a flat string of all the main artists let artistString = ''; for (let i = 0; i < result.artists_length; i++) { if (result.artists[result.artist_keys[i]].includes('main')) { if (artistString !== '' && i < result.artists_length - 2) { artistString += ', '; } else if (artistString !== '' && i < result.artists_length - 1) { artistString += ' & '; } artistString += result.artist_keys[i]; } } result.flat_artistString = artistString; // eslint-disable-line camelcase } if (rawData.format) { const format = rawData.format.toLowerCase(); if (format.includes('vinyl')) { result.format = 'Vinyl'; } else if (format.includes('cd')) { result.format = 'CD'; } else if (format.includes('dvd') || format.includes('dvd-video')) { result.format = 'DVD'; } else if (format.includes('sacd')) { result.format = 'SACD'; } else if (format.includes('cassettes')) { result.format = 'Cassette'; } else if (format.includes('Blu-ray')) { result.format = 'Blu-Ray'; } else if (format.includes('file')) { result.format = 'WEB'; } } if (rawData.format) { const format = rawData.format.toLowerCase(); if (format.includes('album') || rawData.styles.includes('Album')) { result.releaseType = 1; } else if (format.includes('soundtrack') || rawData.styles.includes('Soundtrack')) { result.releaseType = 3; } else if (format.includes('ep') || rawData.styles.includes('EP')) { result.releaseType = 5; } else if (format.includes('anthology') || rawData.styles.includes('Anthology')) { result.releaseType = 6; } else if (format.includes('compilation') || rawData.styles.includes('Compilation')) { result.releaseType = 7; } else if (format.includes('single') || rawData.styles.includes('Single')) { result.releaseType = 9; } } return result; }, }; yadgSandbox.init(() => { if (factory.init()) { // Returns true if we run on a valid location yadg.init(); } });