music-helper

This script provides integration with online description generator YADG (http://yadg.cc)

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/444988/1268106/music-helper.js

  1. // ==UserScript==
  2. // @name music-helper
  3. // @contributor Slack06/SavageCore/tomorrow505
  4. // @description This script provides integration with online description generator YADG (http://yadg.cc)
  5. // @license https://github.com/SavageCore/yadg-pth-userscript/blob/master/LICENSE
  6. // @version v1.3
  7. // @namespace yadg
  8. // @grant GM_xmlhttpRequest
  9. // @require https://code.jquery.com/jquery-1.12.4.js
  10. // @include http*://*redacted.ch/upload.php*
  11. // @include http*://*redacted.ch/requests.php*
  12. // @include http*://*redacted.ch/torrents.php*
  13. // @include http*://*orpheus.network/upload.php*
  14. // @include http*://*orpheus.network/requests.php*
  15. // @include http*://*orpheus.network/torrents.php*
  16. // @include http*://*dicmusic.com/upload.php*
  17. // @include http*://*dicmusic.com/requests.php*
  18. // @include http*://*dicmusic.com/torrents.php*
  19. // @match https://*open.cd/plugin_upload.php*
  20. // @match https://*.open.cd/plugin_upload.php*
  21. // ==/UserScript==
  22.  
  23. let worker_ok = location.href.split('#seperator#')[0].match(/lemonhd|redacted|orpheus|notwhat|dicmusic|waffles|d3si/i) ? true: false;
  24.  
  25. var JSandbox = (function(self) {
  26. var undef_type = "undefined",
  27. doc = self.document,
  28. Worker = self.Worker;
  29. if (typeof Worker === undef_type) {
  30. return;
  31. }
  32. var $eval = "eval",
  33. $exec = "exec",
  34. $load = "load",
  35. $requests = "requests",
  36. $input = "input",
  37. $terminate = "terminate",
  38. $data = "data",
  39. $callback = "callback",
  40. $onerror = "onerror",
  41. $worker = "worker",
  42. $onresponse = "onresponse",
  43. $prototype = "prototype",
  44. $call = "call",
  45. str_type = "string",
  46. fun_type = "function",
  47. Sandbox = function() {
  48. var sandbox = this;
  49. if (! (sandbox instanceof Sandbox)) {
  50. return new Sandbox()
  51. }
  52. if (worker_ok) sandbox[$worker] = new Worker(Sandbox.url);
  53. sandbox[$requests] = {};
  54. if (worker_ok) {
  55. sandbox[$worker].onmessage = function(event) {
  56. var data = event[$data],
  57. request;
  58. if (typeof data !== "object") {
  59. return
  60. }
  61. request = sandbox[$requests][data.id];
  62. if (request) {
  63. if (data.error) {
  64. if (typeof sandbox[$onerror] === fun_type) {
  65. sandbox[$onerror](data, request)
  66. }
  67. if (typeof request[$onerror] === fun_type) {
  68. request[$onerror][$call](sandbox, data.error)
  69. }
  70. } else {
  71. if (typeof sandbox[$onresponse] === fun_type) {
  72. sandbox[$onresponse](data, request)
  73. }
  74. if (typeof request[$callback] === fun_type) {
  75. request[$callback][$call](sandbox, data.results)
  76. }
  77. }
  78. delete sandbox[$requests][data.id]
  79. }
  80. }
  81. }
  82. },
  83. proto = Sandbox[$prototype],
  84. createRequestMethod = function(method) {
  85. proto[method] = function(options, callback, input, onerror) {
  86. if (typeof options === str_type || Object[$prototype].toString[$call](options) === "[object Array]" || arguments.length > 1) {
  87. options = {
  88. data: options,
  89. input: input,
  90. callback: callback,
  91. onerror: onerror
  92. }
  93. }
  94. if (method === $load && typeof options[$data] === str_type) {
  95. options[$data] = [options[$data]]
  96. }
  97. var data = options[$data],
  98. id = this.createRequestID();
  99. input = options[$input];
  100. delete options[$data];
  101. delete options[$input];
  102. this[$requests][id] = options;
  103. if (worker_ok) {
  104. this[$worker].postMessage({
  105. id: id,
  106. method: method,
  107. data: data,
  108. input: input
  109. });
  110. }
  111. return id
  112. };
  113. Sandbox[method] = function() {
  114. var sandbox = new Sandbox();
  115. sandbox[$onresponse] = sandbox[$onerror] = function() {
  116. sandbox[$terminate]();
  117. sandbox = null
  118. };
  119. Sandbox[$prototype][method].apply(sandbox, Array[$prototype].slice[$call](arguments));
  120. return Sandbox
  121. }
  122. },
  123. methods = [$eval, $load, $exec],
  124. i = 3;
  125. while (i--) {
  126. createRequestMethod(methods[i])
  127. }
  128. proto[$terminate] = function() {
  129. this[$requests] = {};
  130. if (worker_ok) {
  131. this[$worker].onmessage = null;
  132. this[$worker][$terminate]()
  133. }
  134. };
  135. proto.abort = function(id) {
  136. delete this[$requests][id]
  137. };
  138. proto.createRequestID = function() {
  139. var id = Math.random().toString();
  140. if (id in this[$requests]) {
  141. return this.createRequestID()
  142. }
  143. return id
  144. };
  145. if (typeof doc !== undef_type) {
  146. var linkElems = doc.getElementsByTagName("link");
  147. i = linkElems.length;
  148. while (i--) {
  149. if (linkElems[i].getAttribute("rel") === "jsandbox") {
  150. Sandbox.url = linkElems[i].getAttribute("href");
  151. break
  152. }
  153. }
  154. }
  155. return Sandbox
  156. } (self)),
  157. Sandbox = JSandbox;
  158.  
  159. /* global window unsafeWindow document GM JSandbox formatName AddArtistField RemoveArtistField Blob alert Image */
  160. /* eslint max-depth: 'off', block-scoped-var: 'off', no-loop-func: 'off', no-alert: 'off', unicorn/prefer-module: 'off', no-bitwise: 'off' */
  161.  
  162. /*
  163. Here you can set site specific default templates.
  164. You can find a list of available templates at: https://yadg.cc/api/v2/templates/
  165. */
  166. const defaultPTHFormat = 5;
  167. const defaultWafflesFormat = 9;
  168. const defaultPTHTarget = 'other';
  169. const defaultPTHDescriptionTarget = 'album';
  170. let yadg; // eslint-disable-line prefer-const
  171. let factory; // eslint-disable-line prefer-const
  172. let yadgRenderer; // eslint-disable-line prefer-const
  173. let yadgTemplates; // eslint-disable-line prefer-const
  174. let autoRehost;
  175.  
  176. // --------- USER SETTINGS END ---------
  177.  
  178. function fetchImage(target, callback) {
  179. const input = document.querySelector('[name="cover"]');
  180. if (input === null) {
  181. return;
  182. }
  183. if (/imgur|ptpimg/g.test(input.value)) {
  184. return;
  185. }
  186.  
  187. const link = target === null ? $('#yadg_input').val() : target;
  188. switch (true) {
  189. case /discogs/.test(link):
  190. GM_xmlhttpRequest({
  191. method: 'GET',
  192. url: link,
  193. onload(response) {
  194. if (response.status === 200) {
  195. const container = document.implementation.createHTMLDocument()
  196. .documentElement;
  197. container.innerHTML = response.responseText;
  198. const script = container.querySelector('#release_schema');
  199. try {
  200. const data = JSON.parse(script.textContent);
  201. callback(data.image);
  202. } catch {
  203. callback(false);
  204. }
  205. }
  206. },
  207. });
  208. break;
  209. case /music.apple/.test(link): {
  210. const regex = /apple\.com\/(?:([a-z]{2,3})\/)?.*\/(?:(\d+)|id(\d*))/;
  211. const result = regex.exec(link);
  212. const id = result[2] | result[3];
  213. let country = 'us';
  214. if (result[1]) {
  215. [, country] = result;
  216. }
  217.  
  218. GM_xmlhttpRequest({
  219. method: 'GET',
  220. url: 'https://itunes.apple.com/lookup?id=' + id + '&country=' + country,
  221. onload(response) {
  222. if (response.status === 200) {
  223. const data = JSON.parse(response.responseText);
  224. const settingCover = factory.getCoverSize().value;
  225. const hires = settingCover === 'large' ? data.results[0].artworkUrl100.replace(
  226. '100x100bb',
  227. '100000x100000-999',
  228. ) : data.results[0].artworkUrl100.replace(
  229. '100x100bb',
  230. '700x700bb',
  231. );
  232.  
  233. if (typeof callback === 'function') {
  234. callback(hires);
  235. }
  236. }
  237. },
  238. });
  239. break;
  240. }
  241. case factory.getScraperSelect().value === 'bandcamp': {
  242. let img;
  243. GM_xmlhttpRequest({
  244. method: 'GET',
  245. url: link,
  246. onload(response) {
  247. if (response.status === 200) {
  248. const container = document.implementation.createHTMLDocument()
  249. .documentElement;
  250. container.innerHTML = response.responseText;
  251. const [imgElement_] = container.querySelectorAll(
  252. '#tralbumArt > a > img',
  253. );
  254. if (!imgElement_) {
  255. if (typeof callback === 'function') {
  256. callback(false);
  257. }
  258.  
  259. return false;
  260. }
  261.  
  262. const scaledImg = imgElement_.src;
  263. const settingCover = factory.getCoverSize().value;
  264. const originalImg = settingCover === 'large' ? scaledImg.replace(/_16/, '_0') : scaledImg.replace(/_16/, '_10');
  265.  
  266. const temporaryImg = new Image();
  267. temporaryImg.src = originalImg;
  268. temporaryImg.addEventListener('load', function () {
  269. img = this.width === this.height ? originalImg : scaledImg;
  270.  
  271. if (typeof callback === 'function') {
  272. callback(img);
  273. }
  274. });
  275. }
  276. },
  277. });
  278. break;
  279. }
  280. case /beatport/.test(link):
  281. GM_xmlhttpRequest({
  282. method: 'GET',
  283. url: link,
  284. onload(response) {
  285. if (response.status === 200) {
  286. const container = document.implementation.createHTMLDocument()
  287. .documentElement;
  288. container.innerHTML = response.responseText;
  289. if (typeof callback === 'function') {
  290. callback(
  291. container.querySelectorAll(
  292. 'div.interior-release-chart-artwork-parent > img',
  293. )[0].src,
  294. );
  295. }
  296. }
  297. },
  298. });
  299. break;
  300. case /musicbrainz/.test(link): {
  301. const regex = /release\/(.*)/;
  302. const {1: id} = regex.exec(link);
  303. GM_xmlhttpRequest({
  304. headers: {
  305. 'User-Agent': 'YADG/1.4.41 (yadg.cc)',
  306. },
  307. method: 'GET',
  308. url: 'http://coverartarchive.org/release/' + id + '/',
  309. onload(response) {
  310. if (response.status === 200) {
  311. const data = JSON.parse(response.responseText);
  312. if (typeof callback === 'function') {
  313. callback(data.images[0].image);
  314. }
  315. }
  316. },
  317. });
  318. break;
  319. }
  320. case /junodownload/.test(link):
  321. GM_xmlhttpRequest({
  322. method: 'GET',
  323. url: link,
  324. onload(response) {
  325. if (response.status === 200) {
  326. const container = document.implementation.createHTMLDocument()
  327. .documentElement;
  328. container.innerHTML = response.responseText;
  329. if (typeof callback === 'function') {
  330. callback(container.querySelector('.img-fluid-fill').src);
  331. }
  332. }
  333. },
  334. });
  335. break;
  336. case /metal-archives/.test(link):
  337. GM_xmlhttpRequest({
  338. method: 'GET',
  339. url: link,
  340. onload(response) {
  341. if (response.status === 200) {
  342. const container = document.implementation.createHTMLDocument()
  343. .documentElement;
  344. container.innerHTML = response.responseText;
  345.  
  346. const parser = document.createElement('a');
  347. parser.href = container.querySelectorAll('#cover > img')[0].src;
  348. const imgLink
  349. = parser.protocol + '//' + parser.hostname + parser.pathname;
  350. if (typeof callback === 'function') {
  351. callback(imgLink);
  352. }
  353. }
  354. },
  355. });
  356. break;
  357. case /allmusic/.test(link):
  358. GM_xmlhttpRequest({
  359. method: 'GET',
  360. url: link,
  361. onload(response) {
  362. if (response.status === 200) {
  363. const container = document.implementation.createHTMLDocument()
  364. .documentElement;
  365. container.innerHTML = response.responseText;
  366. const data = container.querySelector('[data-largeurl]');
  367. // No image available https://www.allmusic.com/album/release/beatles-mr0003843619
  368. if (data !== null) {
  369. const cover = data.getAttribute('data-largeurl');
  370. if (typeof callback === 'function') {
  371. callback(cover);
  372. }
  373. }
  374. }
  375. },
  376. });
  377. break;
  378. case /deezer/.test(link): {
  379. const regex = /\.com\/(\w+\/)?(album)\/(\d+)/g;
  380. const helper = regex.exec(link);
  381. const id = helper[3];
  382. GM_xmlhttpRequest({
  383. method: 'GET',
  384. url: 'https://api.deezer.com/album/' + id,
  385. onload(response) {
  386. if (response.status === 200) {
  387. const data = JSON.parse(response.responseText);
  388. const settingCover = factory.getCoverSize().value;
  389. const cover = settingCover === 'large' ? data.cover_xl.replace(
  390. '1000x1000-000000-80-0-0.jpg',
  391. '1400x1400-000000-100-0-0.jpg',
  392. ) : data.cover_xl;
  393.  
  394. if (typeof callback === 'function') {
  395. callback(cover);
  396. }
  397. }
  398. },
  399. });
  400. break;
  401. }
  402. }
  403. }
  404.  
  405. function pthImgIt() {
  406. const [pthImgIt] = document.querySelectorAll('.rehost_it_cover');
  407. let imgElement;
  408.  
  409. switch (window.location.href) {
  410. case (window.location.href.match(/\/upload\.php/) || {}).input: {
  411. imgElement = document.querySelector('#image').value;
  412. break;
  413. }
  414.  
  415. case (window.location.href.match(/torrents\.php\?action=editgroup/) || {})
  416. .input: {
  417. imgElement = document.querySelectorAll(
  418. '#content > div > div:nth-child(2) > form > div > input[type="text"]:nth-child(5)',
  419. )[0].value;
  420. break;
  421. }
  422.  
  423. default:
  424. break;
  425. }
  426. if (pthImgIt && imgElement) {
  427. pthImgIt.click();
  428. }
  429. }
  430.  
  431. function insertImage(img, callback) {
  432. switch (window.location.href) {
  433. case (window.location.href.match(/\/upload\.php/) || {}).input: {
  434. const input = document.querySelector('#image');
  435. input.value = img;
  436. if (input.getAttribute('autorehost') === 'true') {
  437. const evt = document.createEvent('HTMLEvents');
  438. evt.initEvent('keyup', false, true);
  439. input.dispatchEvent(evt);
  440. }
  441.  
  442. input.parentNode.parentNode.insertAdjacentHTML(
  443. 'beforebegin',
  444. '<tr id="yadg_image_preview_tr"><td class="label">Album Art Preview:</td><td><img id="yadg_image_preview" src="'
  445. + img
  446. + '" width="300px" /></tr></td>',
  447. );
  448. callback();
  449. break;
  450. }
  451.  
  452. case (window.location.href.match(/torrents\.php\?action=editgroup/) || {})
  453. .input: {
  454. const [imageInputElement] = document.querySelectorAll(
  455. '#content > div > div:nth-child(2) > form > div > input[type="text"]:nth-child(5)',
  456. );
  457. imageInputElement.value = img;
  458. imageInputElement.parentNode.insertAdjacentHTML(
  459. 'beforebegin',
  460. '<div id="yadg_image_preview_div"><img id="yadg_image_preview" src="'
  461. + img
  462. + '" width="300px" /></div>',
  463. );
  464. callback();
  465. break;
  466. }
  467.  
  468. case (window.location.href.match(/requests\.php\?/) || {}).input: {
  469. const [imageInputElement] = document.querySelectorAll(
  470. '#image_tr > td:nth-child(2) > input[type="text"]:nth-child(1)',
  471. );
  472. imageInputElement.value = img;
  473. imageInputElement.parentNode.parentNode.insertAdjacentHTML(
  474. 'beforebegin',
  475. '<tr id="yadg_image_preview_tr"><td class="label">Album Art Preview:</td><td><img id="yadg_image_preview" src="'
  476. + img
  477. + '" width="300px" /></tr></td>',
  478. );
  479. callback();
  480. break;
  481. }
  482.  
  483. default:
  484. break;
  485. }
  486. }
  487.  
  488. // --------- THIRD PARTY CODE AREA START ---------
  489.  
  490. // Creates an object which gives some helper methods to
  491. // Save/Load/Remove data to/from the localStorage
  492. // Source from: https://github.com/gergob/localstoragewrapper
  493.  
  494. function LocalStorageWrapper(appPrefix) {
  495. 'use strict';
  496.  
  497. if (appPrefix === undefined) {
  498. throw new Error('applicationPrefix parameter should be defined');
  499. }
  500.  
  501. const delimiter = '_';
  502.  
  503. // If the passed in value for prefix is not string, it should be converted
  504. const keyPrefix
  505. = typeof appPrefix === 'string'
  506. ? appPrefix
  507. : JSON.stringify(appPrefix);
  508.  
  509. const localStorage = window.localStorage || unsafeWindow.localStorage;
  510.  
  511. const isLocalStorageAvailable = function () {
  512. return typeof localStorage !== 'undefined';
  513. };
  514.  
  515. const getKeyPrefix = function () {
  516. return keyPrefix;
  517. };
  518.  
  519. //
  520. // validates if there is a prefix defined for the keys
  521. // and checks if the localStorage functionality is available or not
  522. //
  523. const makeChecks = function (key) {
  524. const prefix = getKeyPrefix();
  525. if (prefix === undefined) {
  526. throw new Error('No prefix was defined, data cannot be saved');
  527. }
  528.  
  529. if (!isLocalStorageAvailable()) {
  530. throw new Error(
  531. 'LocalStorage is not supported by your browser, data cannot be saved',
  532. );
  533. }
  534.  
  535. // Keys are always strings
  536. const checkedKey = typeof key === 'string' ? key : JSON.stringify(key);
  537.  
  538. return checkedKey;
  539. };
  540.  
  541. //
  542. // saves the value associated to the key into the localStorage
  543. //
  544. const addItem = function (key, value) {
  545. try {
  546. const checkedKey = makeChecks(key);
  547. const combinedKey = this.getKeyPrefix() + delimiter + checkedKey;
  548. localStorage.setItem(combinedKey, JSON.stringify(value));
  549. } catch (error) {
  550. console.log(error);
  551. throw error;
  552. }
  553. };
  554.  
  555. //
  556. // gets the value of the object saved to the key passed as parameter
  557. //
  558. const getItem = function (key) {
  559. let result;
  560. try {
  561. const checkedKey = makeChecks(key);
  562. const combinedKey = this.getKeyPrefix() + delimiter + checkedKey;
  563. const resultAsJSON = localStorage.getItem(combinedKey);
  564. result = JSON.parse(resultAsJSON);
  565. } catch (error) {
  566. console.log(error);
  567. throw error;
  568. }
  569.  
  570. return result;
  571. };
  572.  
  573. //
  574. // returns all the keys from the localStorage
  575. //
  576. const getAllKeys = function () {
  577. const prefix = getKeyPrefix();
  578. const results = [];
  579.  
  580. if (prefix === undefined) {
  581. throw new Error('No prefix was defined, data cannot be saved');
  582. }
  583.  
  584. if (!isLocalStorageAvailable()) {
  585. throw new Error(
  586. 'LocalStorage is not supported by your browser, data cannot be saved',
  587. );
  588. }
  589.  
  590. for (const key in localStorage) {
  591. if (key.indexOf(prefix) === 0) {
  592. const keyParts = key.split(delimiter);
  593. results.push(keyParts[1]);
  594. }
  595. }
  596.  
  597. return results;
  598. };
  599.  
  600. //
  601. // removes the value associated to the key from the localStorage
  602. //
  603. const removeItem = function (key) {
  604. let result = false;
  605. try {
  606. const checkedKey = makeChecks(key);
  607. const combinedKey = this.getKeyPrefix() + delimiter + checkedKey;
  608. localStorage.removeItem(combinedKey);
  609. result = true;
  610. } catch (error) {
  611. console.log(error);
  612. throw error;
  613. }
  614.  
  615. return result;
  616. };
  617.  
  618. //
  619. // removes all the values from the localStorage
  620. //
  621. const removeAll = function () {
  622. try {
  623. const allKeys = this.getAllKeys();
  624. for (const key of allKeys) {
  625. const checkedKey = makeChecks(key);
  626. const combinedKey = this.getKeyPrefix() + delimiter + checkedKey;
  627. localStorage.removeItem(combinedKey);
  628. }
  629. } catch (error) {
  630. console.log(error);
  631. throw error;
  632. }
  633. };
  634.  
  635. // Make some of the functionalities public
  636. return {
  637. isLocalStorageAvailable,
  638. getKeyPrefix,
  639. addItem,
  640. getItem,
  641. getAllKeys,
  642. removeItem,
  643. removeAll,
  644. };
  645. }
  646.  
  647. // --------- THIRD PARTY CODE AREA END ---------
  648.  
  649. const yadgUtil = {
  650. exec(fn) {
  651. const script = document.createElement('script');
  652. script.setAttribute('type', 'application/javascript');
  653. script.textContent = '(' + fn + ')();';
  654. document.body.append(script); // Run the script
  655. script.remove(); // Clean up
  656. },
  657.  
  658. // Handle for updating page css, taken from one of hateradio's scripts
  659. addCSS(style) {
  660. if (!this.style) {
  661. this.style = document.createElement('style');
  662. this.style.type = 'text/css';
  663. (document.head || document.querySelectorAll('head')[0]).append(
  664. this.style,
  665. );
  666. }
  667.  
  668. this.style.append(document.createTextNode(style + '\n'));
  669. },
  670.  
  671. setValueIfSet(value, input, cond) {
  672. input.value = cond ? value : '';
  673. },
  674.  
  675. // Negative count will remove, positive count will add given number of artist boxes
  676. addRemoveArtistBoxes(count) {
  677. if (count !== 0) {
  678. if (count < 0) {
  679. for (let i = 0; i < -count; i++) {
  680. yadgUtil.exec(() => {
  681. RemoveArtistField(); // eslint-disable-line new-cap
  682. });
  683. }
  684. } else {
  685. for (let i = 0; i < count; i++) {
  686. yadgUtil.exec(() => {
  687. AddArtistField(); // eslint-disable-line new-cap
  688. });
  689. }
  690. }
  691. }
  692. },
  693.  
  694. getOptionOffsets(select) {
  695. const optionOffsets = {};
  696. for (let j = 0; j < select.options.length; j++) {
  697. optionOffsets[select.options[j].value] = select.options[j].index;
  698. }
  699.  
  700. return optionOffsets;
  701. },
  702.  
  703. storage: new LocalStorageWrapper('yadg'),
  704.  
  705. settings: new LocalStorageWrapper('yadgSettings'),
  706. };
  707.  
  708. // Very simple wrapper for XmlHttpRequest
  709. // eslint-disable-next-line max-params
  710. function Requester(url, method, callback, data, errorCallback) {
  711. this.data = data;
  712. this.url = url;
  713. this.method = method;
  714. if (!errorCallback) {
  715. errorCallback = yadg.failedCallback;
  716. }
  717.  
  718. this.send = function () {
  719. const details = {
  720. url: this.url,
  721. method: this.method,
  722. onload(response) {
  723. if (response.status === 200) {
  724. callback(JSON.parse(response.responseText));
  725. } else if (response.status === 401) {
  726. yadg.failedAuthenticationCallback();
  727. } else {
  728. errorCallback();
  729. }
  730. },
  731. onerror: errorCallback,
  732. };
  733. if (method === 'POST') {
  734. details.data = JSON.stringify(this.data);
  735. }
  736.  
  737. const headers = {
  738. Accept: 'application/json',
  739. 'Content-Type': 'application/json',
  740. };
  741.  
  742. if (yadgUtil.settings.getItem(factory.KEY_API_TOKEN)) {
  743. headers.Authorization
  744. = 'Token ' + yadgUtil.settings.getItem(factory.KEY_API_TOKEN);
  745. }
  746.  
  747. details.headers = headers;
  748.  
  749. GM_xmlhttpRequest(details);
  750. };
  751. }
  752.  
  753. const yadgSandbox = {
  754. KEY_LAST_WARNING: 'templateLastWarning',
  755.  
  756. init(callback) {
  757. GM_xmlhttpRequest({
  758. method: 'GET',
  759. url: yadg.yadgHost + '/static/js/jsandbox-worker.js',
  760. onload(response) {
  761. let script;
  762. let dataURL = null;
  763. if (response.status === 200) {
  764. script = response.responseText;
  765. const blob = new Blob([script], {type: 'application/javascript'});
  766. const URL = window.URL || window.webkitURL;
  767. if (!URL || !URL.createObjectURL) {
  768. throw new Error(
  769. 'No no valid implementation of window.URL.createObjectURL found.',
  770. );
  771. }
  772.  
  773. dataURL = URL.createObjectURL(blob);
  774. yadgSandbox.initCallback(dataURL);
  775. yadgSandbox.loadSwig(callback);
  776. } else {
  777. yadgSandbox.initCallbackError();
  778. }
  779. },
  780. onerror() {
  781. yadgSandbox.initCallbackError();
  782. },
  783. });
  784. },
  785.  
  786. loadSwig(callback) {
  787. // ImportScripts for the web worker will not work in Firefox with cross-domain requests
  788. // see: https://bugzilla.mozilla.org/show_bug.cgi?id=756589
  789. // so download the Swig files manually with GM_xmlhttpRequest
  790. GM_xmlhttpRequest({
  791. method: 'GET',
  792. url: yadg.yadgHost + '/static/js/swig.min.js',
  793. onload(response) {
  794. if (response.status === 200) {
  795. yadgSandbox.swigScript = response.responseText;
  796.  
  797. GM_xmlhttpRequest({
  798. method: 'GET',
  799. url: yadg.yadgHost + '/static/js/swig.custom.js',
  800. onload(response) {
  801. if (response.status === 200) {
  802. yadgSandbox.swigCustomScript = response.responseText;
  803. callback();
  804. }
  805. },
  806. });
  807. }
  808. },
  809. });
  810. },
  811.  
  812. initializeSwig(dependencies) {
  813. if (!(this.swigScript && this.swigCustomScript)) {
  814. yadg.failedCallback();
  815. return;
  816. }
  817.  
  818. yadgSandbox.exec({data: this.swigScript, onerror: yadg.failedCallback});
  819. yadgSandbox.exec({
  820. data: this.swigCustomScript,
  821. onerror: yadg.failedCallback,
  822. });
  823. yadgSandbox.exec({
  824. data:
  825. 'var myswig = new swig.Swig({ loader: swig.loaders.memory(input.templates), autoescape: false }), i=0; yadg_filters.register_filters(myswig);',
  826. input: {templates: dependencies},
  827. });
  828. },
  829.  
  830. renderTemplate(template, data, callback, error) {
  831. const evalString
  832. = 'myswig.render(input.template, { locals: input.data, filename: \'scratchpad\' + (i++) })';
  833. this.eval({
  834. data: evalString,
  835. callback(out) {
  836. callback(out);
  837. },
  838. input: {template, data},
  839. onerror(error_) {
  840. error(error_);
  841. },
  842. });
  843. },
  844.  
  845. initCallback(dataUrl) {
  846. JSandbox.url = dataUrl;
  847. this.jsandbox = new JSandbox();
  848. this.initError = false;
  849. },
  850.  
  851. resetSandbox() {
  852. this.jsandbox.terminate();
  853. this.jsandbox = new JSandbox();
  854. },
  855.  
  856. load(options) {
  857. this.jsandbox.load(options);
  858. },
  859.  
  860. exec(options) {
  861. this.jsandbox.exec(options);
  862. },
  863.  
  864. eval(options) {
  865. this.jsandbox.eval(options);
  866. },
  867.  
  868. initCallbackError() {
  869. this.initError = true;
  870.  
  871. const lastWarning = yadgUtil.storage.getItem(this.KEY_LAST_WARNING);
  872. const now = new Date();
  873. if (
  874. lastWarning === null
  875. || now.getTime() - new Date(lastWarning).getTime() > factory.CACHE_TIMEOUT
  876. ) {
  877. console.log(
  878. '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.',
  879. );
  880. yadgUtil.storage.addItem(this.KEY_LAST_WARNING, now);
  881. }
  882. },
  883. };
  884.  
  885. factory = {
  886. // Storage keys for cache
  887. KEY_LAST_CHECKED: 'lastChecked',
  888. KEY_SCRAPER_LIST: 'scraperList',
  889. KEY_FORMAT_LIST: 'formatList',
  890.  
  891. // Storage keys for settings
  892. KEY_API_TOKEN: 'apiToken',
  893. KEY_DEFAULT_TEMPLATE: 'defaultTemplate',
  894. KEY_DEFAULT_TARGET: 'defaultTarget',
  895. KEY_DESCRIPTION_TARGET: 'descriptionTarget',
  896. KEY_DEFAULT_SCRAPER: 'defaultScraper',
  897. KEY_REPLACE_DESCRIPTION: 'replaceDescriptionOn',
  898. KEY_SETTINGS_INIT_VER: 'settingsInitializedVer',
  899. KEY_FETCH_IMAGE: 'fetchImage',
  900. KEY_AUTO_PREVIEW: 'autoPreview',
  901. KEY_AUTO_REHOST: 'autoRehost',
  902. KEY_AUTO_SELECT_SCRAPER: 'autoSelectScraper',
  903. KEY_COVER_SIZE: 'coverSize',
  904.  
  905. CACHE_TIMEOUT: 1000 * 60 * 60 * 24, // 24 hours
  906.  
  907. UPDATE_PROGRESS: 0,
  908. locations: [
  909. {
  910. name: 'pth_upload',
  911. regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/upload\.php.*/i,
  912. },
  913. {
  914. name: 'pth_edit',
  915. regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/torrents\.php\?action=editgroup&groupid=.*/i,
  916. },
  917. {
  918. name: 'pth_request',
  919. regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/requests\.php\?action=new/i,
  920. },
  921. {
  922. name: 'pth_request_edit',
  923. regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/requests\.php\?action=edit&id=.*/i,
  924. },
  925. {
  926. name: 'pth_torrent_overview',
  927. regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/torrents\.php\?id=.*/i,
  928. },
  929. {
  930. name: 'lemonhd_upload',
  931. regex: /https:\/\/lemonhd.org\/upload_music.php*/i,
  932. },
  933. {
  934. name: 'opencd_upload',
  935. regex: /https:\/\/.*open.cd\/plugin_upload.php*/i,
  936. },
  937. {
  938. name: 'ops_upload',
  939. regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/upload\.php.*/i,
  940. },
  941. {
  942. name: 'ops_edit',
  943. regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/torrents\.php\?action=editgroup&groupid=.*/i,
  944. },
  945. {
  946. name: 'ops_request',
  947. regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/requests\.php\?action=new/i,
  948. },
  949. {
  950. name: 'ops_request_edit',
  951. regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/requests\.php\?action=edit&id=.*/i,
  952. },
  953. {
  954. name: 'ops_torrent_overview',
  955. regex: /http(s)?:\/\/(.*\.)?orpheus\.network\/torrents\.php\?id=.*/i,
  956. },
  957. {
  958. name: 'dic_upload',
  959. regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/upload\.php.*/i,
  960. },
  961. {
  962. name: 'dic_edit',
  963. regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/torrents\.php\?action=editgroup&groupid=.*/i,
  964. },
  965. {
  966. name: 'dic_request',
  967. regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/requests\.php\?action=new/i,
  968. },
  969. {
  970. name: 'dic_request_edit',
  971. regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/requests\.php\?action=edit&id=.*/i,
  972. },
  973. {
  974. name: 'dic_torrent_overview',
  975. regex: /http(s)?:\/\/(.*\.)?dicmusic\.com\/torrents\.php\?id=.*/i,
  976. },
  977. ],
  978.  
  979. determineLocation(uri) {
  980. for (let i = 0; i < this.locations.length; i++) {
  981. if (this.locations[i].regex.test(uri)) {
  982. return this.locations[i].name;
  983. }
  984. }
  985.  
  986. return null;
  987. },
  988.  
  989. init() {
  990. this.currentLocation = this.determineLocation(document.URL);
  991. // Only continue with the initialization if we found a valid location
  992. if (this.currentLocation === null) {
  993. return false;
  994. }
  995.  
  996. if (this.currentLocation === 'pth_request') {
  997. this.inputsOff(document.URL);
  998. }
  999.  
  1000. this.insertIntoPage(this.getInputElements());
  1001.  
  1002. // Set the necessary styles
  1003. this.setStyles();
  1004.  
  1005. // Make sure we initialize the settings to the most recent version
  1006. this.initializeSettings();
  1007.  
  1008. // Populate settings inputs
  1009. this.populateSettings();
  1010.  
  1011. // Add the appropriate action for the input textbox
  1012. const input = document.querySelector('#yadg_input');
  1013. input.addEventListener('input', () => {
  1014. if (factory.getAutoSelectScraperCheckbox().checked) {
  1015. const inputValue = input.value;
  1016. const yadgScraper = document.querySelector('#yadg_scraper');
  1017. if (/discogs/.test(inputValue)) {
  1018. yadgScraper.value = 'discogs';
  1019. } else if (/music.apple/.test(inputValue)) {
  1020. yadgScraper.value = 'itunes';
  1021. } else if (/bandcamp/.test(inputValue)) {
  1022. yadgScraper.value = 'bandcamp';
  1023. } else if (/beatport/.test(inputValue)) {
  1024. yadgScraper.value = 'beatport';
  1025. } else if (/musicbrainz/.test(inputValue)) {
  1026. yadgScraper.value = 'musicbrainz';
  1027. } else if (/junodownload/.test(inputValue)) {
  1028. yadgScraper.value = 'junodownload';
  1029. } else if (/metal-archives/.test(inputValue)) {
  1030. yadgScraper.value = 'metalarchives';
  1031. } else if (/deezer/.test(inputValue)) {
  1032. yadgScraper.value = 'deezer';
  1033. } else if (/allmusic/.test(inputValue)) {
  1034. yadgScraper.value = 'allmusic';
  1035. }
  1036. }
  1037. });
  1038.  
  1039. // Add the appropriate action for the button
  1040. const button = document.querySelector('#yadg_submit');
  1041. button.addEventListener(
  1042. 'click',
  1043. event => {
  1044. event.preventDefault();
  1045. yadg.makeRequest();
  1046. if (factory.getFetchImageCheckbox().checked) {
  1047. fetchImage(null, data => {
  1048. if (data) {
  1049. insertImage(data, () => {
  1050. if (
  1051. factory.getAutoRehostCheckbox()
  1052. && factory.getAutoRehostCheckbox().checked
  1053. ) {
  1054. pthImgIt();
  1055. }
  1056. });
  1057. }
  1058. });
  1059. }
  1060. },
  1061. false,
  1062. );
  1063.  
  1064. // Add the action for the options toggle
  1065. const toggleLink = document.querySelector('#yadg_toggle_options');
  1066. if (toggleLink !== null) {
  1067. toggleLink.addEventListener('click', event => {
  1068. event.preventDefault();
  1069.  
  1070. const optionsDiv = document.querySelector('#yadg_options');
  1071. const {display} = optionsDiv.style;
  1072.  
  1073. optionsDiv.style.display = display === 'none' || display === '' ? 'block' : 'none';
  1074. });
  1075. }
  1076.  
  1077. // Add the action for the cover size select
  1078. const coverSizeSetting = document.querySelector('#yadg_options_image');
  1079. if (coverSizeSetting !== null) {
  1080. coverSizeSetting.addEventListener('click', () => {
  1081. const optionsCoverSize = document.querySelector(
  1082. '#yadg_options_coversize',
  1083. );
  1084. const {display} = optionsCoverSize.style;
  1085. optionsCoverSize.style.display = display === 'none' || display === '' ? 'block' : 'none';
  1086. });
  1087. }
  1088.  
  1089. // Add the action for the template select
  1090. const formatSelect = this.getFormatSelect();
  1091. if (formatSelect !== null) {
  1092. formatSelect.addEventListener('change', function () {
  1093. if (yadgRenderer.hasCached()) {
  1094. yadgRenderer.renderCached(
  1095. this.value,
  1096. factory.setDescriptionBoxValue,
  1097. factory.setDescriptionBoxValue,
  1098. );
  1099. }
  1100. });
  1101. }
  1102.  
  1103. // add the action to the save settings link
  1104. const saveSettingsLink = document.querySelector('#yadg_save_settings');
  1105. if (saveSettingsLink !== null) {
  1106. saveSettingsLink.addEventListener('click', event => {
  1107. event.preventDefault();
  1108.  
  1109. factory.saveSettings();
  1110.  
  1111. alert('Settings saved successfully.');
  1112. });
  1113. }
  1114.  
  1115. // Add the action to the clear cache link
  1116. const clearCacheLink = document.querySelector('#yadg_clear_cache');
  1117. if (clearCacheLink !== null) {
  1118. clearCacheLink.addEventListener('click', event => {
  1119. event.preventDefault();
  1120.  
  1121. yadgUtil.storage.removeAll();
  1122.  
  1123. alert('Cache cleared. Please reload the page for this to take effect.');
  1124. });
  1125. }
  1126.  
  1127. const lastChecked = yadgUtil.storage.getItem(factory.KEY_LAST_CHECKED);
  1128. if (
  1129. lastChecked === null
  1130. || Date.now() - new Date(lastChecked).getTime()
  1131. > factory.CACHE_TIMEOUT
  1132. ) {
  1133. // Update the scraper and formats list
  1134. factory.UPDATE_PROGRESS = 1;
  1135. yadg.getScraperList(factory.setScraperSelect);
  1136. yadg.getFormatsList(factory.setFormatSelect);
  1137. } else {
  1138. factory.setScraperSelect(
  1139. yadgUtil.storage.getItem(factory.KEY_SCRAPER_LIST),
  1140. );
  1141. factory.setFormatSelect(
  1142. yadgUtil.storage.getItem(factory.KEY_FORMAT_LIST),
  1143. );
  1144. }
  1145.  
  1146. return true;
  1147. },
  1148.  
  1149. getApiTokenInput() {
  1150. return document.querySelector('#yadg_api_token');
  1151. },
  1152.  
  1153. getReplaceDescriptionCheckbox() {
  1154. return document.querySelector('#yadg_options_replace');
  1155. },
  1156.  
  1157. getFetchImageCheckbox() {
  1158. return document.querySelector('#yadg_options_image');
  1159. },
  1160.  
  1161. getAutoRehostCheckbox() {
  1162. return document.querySelector('#yadg_options_rehost');
  1163. },
  1164.  
  1165. getAutoPreviewCheckbox() {
  1166. return document.querySelector('#yadg_options_preview');
  1167. },
  1168.  
  1169. getAutoSelectScraperCheckbox() {
  1170. return document.querySelector('#yadg_options_auto_select_scraper');
  1171. },
  1172.  
  1173. getReplaceDescriptionSettingKey() {
  1174. return this.makeReplaceDescriptionSettingsKey(this.currentLocation);
  1175. },
  1176.  
  1177. makeReplaceDescriptionSettingsKey(subKey) {
  1178. return this.KEY_REPLACE_DESCRIPTION + subKey.replace(/_/g, '');
  1179. },
  1180.  
  1181. // Disable fields when groupid set
  1182. inputsOff(url) {
  1183. if (/groupid=\d+/.test(url)) {
  1184. for (const i of [
  1185. 'artists[]',
  1186. 'importance[]',
  1187. 'title',
  1188. 'releasetype',
  1189. 'genre_tags',
  1190. 'tags',
  1191. ]) {
  1192. for (const element of document.getElementsByName(i)) {
  1193. element.readOnly = true;
  1194. }
  1195. }
  1196. }
  1197. },
  1198.  
  1199. initializeSettings() {
  1200. let settingsVer = yadgUtil.settings.getItem(factory.KEY_SETTINGS_INIT_VER);
  1201. const currentVer = 1;
  1202.  
  1203. if (!settingsVer) {
  1204. settingsVer = 0;
  1205. }
  1206.  
  1207. if (settingsVer < currentVer) {
  1208. // Replace descriptions on upload and new request pages
  1209. const locations = [
  1210. 'pth_upload',
  1211. 'lemonhd_upload',
  1212. 'opencd_upload',
  1213. 'pth_request',
  1214. 'ops_upload',
  1215. 'ops_request',
  1216. 'dic_upload',
  1217. 'dic_request',
  1218. ];
  1219. for (const loc of locations) {
  1220. const replaceDescSettingKey = factory.makeReplaceDescriptionSettingsKey(
  1221. loc,
  1222. );
  1223.  
  1224. yadgUtil.settings.addItem(replaceDescSettingKey, true);
  1225. }
  1226. }
  1227.  
  1228. yadgUtil.settings.addItem(factory.KEY_SETTINGS_INIT_VER, currentVer);
  1229. },
  1230.  
  1231. populateSettings() {
  1232. const apiToken = yadgUtil.settings.getItem(factory.KEY_API_TOKEN);
  1233. const replaceDesc = yadgUtil.settings.getItem(
  1234. factory.getReplaceDescriptionSettingKey(),
  1235. );
  1236. const fetchImage = yadgUtil.settings.getItem(factory.KEY_FETCH_IMAGE);
  1237. const autoPreview = yadgUtil.settings.getItem(factory.KEY_AUTO_PREVIEW);
  1238. autoRehost = yadgUtil.settings.getItem(factory.KEY_AUTO_REHOST);
  1239. const autoSelectScraper = yadgUtil.settings.getItem(
  1240. factory.KEY_AUTO_SELECT_SCRAPER,
  1241. );
  1242. const coverSize = yadgUtil.settings.getItem(factory.KEY_COVER_SIZE);
  1243.  
  1244. if (apiToken) {
  1245. const apiTokenInput = factory.getApiTokenInput();
  1246. apiTokenInput.value = apiToken;
  1247. }
  1248.  
  1249. if (replaceDesc) {
  1250. const replaceDescCheckbox = factory.getReplaceDescriptionCheckbox();
  1251. replaceDescCheckbox.checked = true;
  1252. }
  1253.  
  1254. if (fetchImage) {
  1255. const fetchImageCheckbox = factory.getFetchImageCheckbox();
  1256. fetchImageCheckbox.checked = true;
  1257. }
  1258.  
  1259. if (autoRehost) {
  1260. const autoRehostCheckbox = factory.getAutoRehostCheckbox();
  1261. if (autoRehostCheckbox) {
  1262. autoRehostCheckbox.checked = true;
  1263. }
  1264. }
  1265.  
  1266. if (autoPreview) {
  1267. const autoPreviewCheckbox = factory.getAutoPreviewCheckbox();
  1268. autoPreviewCheckbox.checked = true;
  1269. }
  1270.  
  1271. if (autoSelectScraper) {
  1272. const autoSelectScraperCheckbox = factory.getAutoSelectScraperCheckbox();
  1273. autoSelectScraperCheckbox.checked = true;
  1274. }
  1275.  
  1276. if (coverSize) {
  1277. const coverSizeOption = factory.getCoverSize();
  1278. coverSizeOption.value = coverSize;
  1279. if (factory.getFetchImageCheckbox().checked) {
  1280. const optionsCoverSize = document.querySelector(
  1281. '#yadg_options_coversize',
  1282. );
  1283. optionsCoverSize.style.display = 'block';
  1284. }
  1285. }
  1286. },
  1287.  
  1288. saveSettings() {
  1289. const scraperSelect = factory.getScraperSelect();
  1290. const templateSelect = factory.getFormatSelect();
  1291. const targetSelect = factory.getTargetSelect();
  1292. const descriptionTargetSelect = factory.getDescriptionTargetSelect();
  1293. const apiTokenInput = factory.getApiTokenInput();
  1294. const replaceDescCheckbox = factory.getReplaceDescriptionCheckbox();
  1295. const fetchImageCheckbox = factory.getFetchImageCheckbox();
  1296. const autoRehostCheckbox = factory.getAutoRehostCheckbox();
  1297. const autoPreviewCheckbox = factory.getAutoPreviewCheckbox();
  1298. const autoSelectScraperCheckbox = factory.getAutoSelectScraperCheckbox();
  1299. const coverSize = factory.getCoverSize();
  1300.  
  1301. let currentScraper = null;
  1302. let currentTemplate = null;
  1303. let currentTarget = null;
  1304. let currentDescriptionTarget = null;
  1305. let currentCoverSize = null;
  1306. const apiToken = apiTokenInput.value.trim();
  1307. const replaceDescription = replaceDescCheckbox.checked;
  1308. const fetchImage = fetchImageCheckbox.checked;
  1309. const autoSelectScraper = autoSelectScraperCheckbox.checked;
  1310. const autoPreview = autoPreviewCheckbox.checked;
  1311. if (autoRehostCheckbox) {
  1312. autoRehost = autoRehostCheckbox.checked;
  1313. }
  1314.  
  1315. if (scraperSelect.options.length > 0) {
  1316. currentScraper = scraperSelect.options[scraperSelect.selectedIndex].value;
  1317. }
  1318.  
  1319. if (templateSelect.options.length > 0) {
  1320. currentTemplate
  1321. = templateSelect.options[templateSelect.selectedIndex].value;
  1322. }
  1323.  
  1324. if (targetSelect.options.length > 0) {
  1325. currentTarget = targetSelect.options[targetSelect.selectedIndex].value;
  1326. }
  1327.  
  1328. if (descriptionTargetSelect.options.length > 0) {
  1329. currentDescriptionTarget
  1330. = descriptionTargetSelect.options[descriptionTargetSelect.selectedIndex]
  1331. .value;
  1332. }
  1333.  
  1334. if (coverSize.options.length > 0) {
  1335. currentCoverSize = coverSize.options[coverSize.selectedIndex].value;
  1336. }
  1337.  
  1338. if (currentScraper !== null) {
  1339. yadgUtil.settings.addItem(factory.KEY_DEFAULT_SCRAPER, currentScraper);
  1340. }
  1341.  
  1342. if (currentTemplate !== null) {
  1343. yadgUtil.settings.addItem(factory.KEY_DEFAULT_TEMPLATE, currentTemplate);
  1344. }
  1345.  
  1346. if (currentTarget !== null) {
  1347. yadgUtil.settings.addItem(factory.KEY_DEFAULT_TARGET, currentTarget);
  1348. }
  1349.  
  1350. if (currentDescriptionTarget !== null) {
  1351. yadgUtil.settings.addItem(
  1352. factory.KEY_DESCRIPTION_TARGET,
  1353. currentDescriptionTarget,
  1354. );
  1355. }
  1356.  
  1357. if (currentCoverSize !== null) {
  1358. yadgUtil.settings.addItem(factory.KEY_COVER_SIZE, currentCoverSize);
  1359. }
  1360.  
  1361. if (apiToken === '') {
  1362. yadgUtil.settings.removeItem(factory.KEY_API_TOKEN);
  1363. } else {
  1364. yadgUtil.settings.addItem(factory.KEY_API_TOKEN, apiToken);
  1365. }
  1366.  
  1367. const replaceDescSettingKey = factory.getReplaceDescriptionSettingKey();
  1368. if (replaceDescription) {
  1369. yadgUtil.settings.addItem(replaceDescSettingKey, true);
  1370. } else {
  1371. yadgUtil.settings.removeItem(replaceDescSettingKey);
  1372. }
  1373.  
  1374. if (fetchImage) {
  1375. yadgUtil.settings.addItem(factory.KEY_FETCH_IMAGE, true);
  1376. } else {
  1377. yadgUtil.settings.removeItem(factory.KEY_FETCH_IMAGE);
  1378. }
  1379.  
  1380. if (autoRehost) {
  1381. yadgUtil.settings.addItem(factory.KEY_AUTO_REHOST, true);
  1382. } else if (!autoRehost && autoRehostCheckbox) {
  1383. yadgUtil.settings.removeItem(factory.KEY_AUTO_REHOST);
  1384. }
  1385.  
  1386. if (autoPreview) {
  1387. yadgUtil.settings.addItem(factory.KEY_AUTO_PREVIEW, true);
  1388. } else {
  1389. yadgUtil.settings.removeItem(factory.KEY_AUTO_PREVIEW);
  1390. }
  1391.  
  1392. if (autoSelectScraper) {
  1393. yadgUtil.settings.addItem(factory.KEY_AUTO_SELECT_SCRAPER, true);
  1394. } else {
  1395. yadgUtil.settings.removeItem(factory.KEY_AUTO_SELECT_SCRAPER);
  1396. }
  1397. },
  1398.  
  1399. setDescriptionBoxValue(value) {
  1400. const descBox = factory.getDescriptionBox();
  1401. const replaceDesc = factory.getReplaceDescriptionCheckbox().checked;
  1402. const skipAutoPreview = ['pth_torrent_overview',
  1403. 'ops_torrent_overview',
  1404. 'dic_torrent_overview'].includes(factory.currentLocation);
  1405.  
  1406. const boxes = Array.isArray(descBox) ? descBox : [descBox];
  1407. for (const box of boxes) {
  1408. const disabled = box.getAttribute('disabled');
  1409. if (disabled === 'disabled') {
  1410. continue;
  1411. }
  1412.  
  1413. if (replaceDesc) {
  1414. box.value = value;
  1415. } else {
  1416. const blankline = /\S/.test(box.value) ? '\n\n' : '';
  1417. box.value += blankline + value;
  1418. }
  1419.  
  1420. if (skipAutoPreview) {
  1421. continue;
  1422. }
  1423.  
  1424. const div = box.parentNode.nextSibling.nextSibling;
  1425. const button = div.firstChild.nextSibling;
  1426. const autoPreviewChecked = factory.getAutoPreviewCheckbox().checked;
  1427. if (button && autoPreviewChecked) {
  1428. button.click();
  1429. }
  1430. }
  1431. },
  1432.  
  1433. getFormatSelect() {
  1434. return document.querySelector('#yadg_format');
  1435. },
  1436.  
  1437. setDefaultFormat() {
  1438. const formatSelect = factory.getFormatSelect();
  1439. const formatOffsets = yadgUtil.getOptionOffsets(formatSelect);
  1440.  
  1441. const defaultFormat = yadgUtil.settings.getItem(
  1442. factory.KEY_DEFAULT_TEMPLATE,
  1443. );
  1444. if (defaultFormat !== null && defaultFormat in formatOffsets) {
  1445. formatSelect.selectedIndex = formatOffsets[defaultFormat];
  1446. } else {
  1447. // We have no settings so fall back to the hard coded defaults
  1448. switch (this.currentLocation) {
  1449. default:
  1450. formatSelect.selectedIndex = formatOffsets[defaultPTHFormat];
  1451. break;
  1452. }
  1453. }
  1454. },
  1455.  
  1456. getCoverSize() {
  1457. return document.querySelector('#yadg_coversize');
  1458. },
  1459.  
  1460. getTargetSelect() {
  1461. return document.querySelector('#yadg_target');
  1462. },
  1463.  
  1464. getDescriptionTargetSelect() {
  1465. return document.querySelector('#yadg_description_target');
  1466. },
  1467.  
  1468. setDefaultTarget() {
  1469. const targetSelect = factory.getTargetSelect();
  1470. const targetOffsets = yadgUtil.getOptionOffsets(targetSelect);
  1471.  
  1472. const defaultTarget = yadgUtil.settings.getItem(factory.KEY_DEFAULT_TARGET);
  1473. targetSelect.selectedIndex = defaultTarget !== null && defaultTarget in targetOffsets ? targetOffsets[defaultTarget] : targetOffsets[defaultPTHTarget];
  1474. },
  1475.  
  1476. setDefaultDescriptionTarget() {
  1477. const targetDescriptionSelect = factory.getDescriptionTargetSelect();
  1478. const targetDescriptionOffsets = yadgUtil.getOptionOffsets(
  1479. targetDescriptionSelect,
  1480. );
  1481.  
  1482. const defaultDescriptionTarget = yadgUtil.settings.getItem(
  1483. factory.KEY_DESCRIPTION_TARGET,
  1484. );
  1485. if (
  1486. defaultDescriptionTarget !== null
  1487. && defaultDescriptionTarget in targetDescriptionOffsets
  1488. ) {
  1489. targetDescriptionSelect.selectedIndex
  1490. = targetDescriptionOffsets[defaultDescriptionTarget];
  1491. } else {
  1492. targetDescriptionSelect.selectedIndex
  1493. = targetDescriptionOffsets[defaultPTHDescriptionTarget];
  1494. }
  1495. },
  1496.  
  1497. getScraperSelect() {
  1498. return document.querySelector('#yadg_scraper');
  1499. },
  1500.  
  1501. setDefaultScraper() {
  1502. const defaultScraper = yadgUtil.settings.getItem(
  1503. factory.KEY_DEFAULT_SCRAPER,
  1504. );
  1505. if (defaultScraper !== null) {
  1506. const scraperSelect = factory.getScraperSelect();
  1507. const scraperOffsets = yadgUtil.getOptionOffsets(scraperSelect);
  1508.  
  1509. if (defaultScraper in scraperOffsets) {
  1510. scraperSelect.selectedIndex = scraperOffsets[defaultScraper];
  1511. }
  1512. }
  1513. },
  1514.  
  1515. setScraperSelect(scrapers) {
  1516. const scraperSelect = factory.getScraperSelect();
  1517.  
  1518. factory.setSelect(scraperSelect, scrapers);
  1519. factory.setDefaultScraper();
  1520.  
  1521. if (factory.UPDATE_PROGRESS > 0) {
  1522. yadgUtil.storage.addItem(factory.KEY_SCRAPER_LIST, scrapers);
  1523. factory.UPDATE_PROGRESS |= 1 << 1;
  1524.  
  1525. if (factory.UPDATE_PROGRESS === 7) {
  1526. yadgUtil.storage.addItem(factory.KEY_LAST_CHECKED, new Date());
  1527. }
  1528. }
  1529. },
  1530.  
  1531. setFormatSelect(templates) {
  1532. const formatSelect = factory.getFormatSelect();
  1533.  
  1534. const nonUtility = [];
  1535. const saveTemplates = [];
  1536. for (const element of templates) {
  1537. if (factory.UPDATE_PROGRESS > 0) {
  1538. if (element.name === 'What') {
  1539. element.name = 'RED';
  1540. element.nameFormatted = 'RED';
  1541. } else if (element.name === 'What (Tracks only)') {
  1542. element.name = 'RED (Tracks only)';
  1543. element.nameFormatted = 'RED (Tracks only)';
  1544. }
  1545.  
  1546. yadgTemplates.addTemplate(element);
  1547.  
  1548. saveTemplates.push({
  1549. id: element.id,
  1550. url: element.url,
  1551. name: element.name,
  1552. nameFormatted: element.nameFormatted,
  1553. owner: element.owner,
  1554. default: element.default,
  1555. isUtility: element.isUtility,
  1556. });
  1557. } else {
  1558. if (element.name === 'What') {
  1559. element.name = 'PTH';
  1560. element.nameFormatted = 'PTH';
  1561. } else if (element.name === 'What (Tracks only)') {
  1562. element.name = 'PTH (Tracks only)';
  1563. element.nameFormatted = 'PTH (Tracks only)';
  1564. }
  1565.  
  1566. yadgTemplates.addTemplateUrl(element.id, element.url);
  1567. }
  1568.  
  1569. if (!element.isUtility) {
  1570. nonUtility.push(element);
  1571. }
  1572. }
  1573.  
  1574. factory.setSelect(formatSelect, nonUtility);
  1575. factory.setDefaultFormat();
  1576. factory.setDefaultTarget();
  1577. factory.setDefaultDescriptionTarget();
  1578.  
  1579. if (factory.UPDATE_PROGRESS > 0) {
  1580. yadgUtil.storage.addItem(factory.KEY_FORMAT_LIST, saveTemplates);
  1581. factory.UPDATE_PROGRESS |= 1 << 2;
  1582.  
  1583. if (factory.UPDATE_PROGRESS === 7) {
  1584. yadgUtil.storage.addItem(factory.KEY_LAST_CHECKED, new Date());
  1585. }
  1586. }
  1587. },
  1588.  
  1589. setSelect(select, data) {
  1590. select.options.length = data.length;
  1591.  
  1592. for (const [i, element] of data.entries()) {
  1593. // We are not using the javascript constructor to create an Option instance because this will create an
  1594. // incompatibility with jQuery in Chrome which will make it impossible to add a new artist field on redacted.ch
  1595. const o = document.createElement('option');
  1596. o.text = 'nameFormatted' in element ? element.nameFormatted : element.name;
  1597.  
  1598. o.value = element.value || element.id;
  1599. o.selected = element.default;
  1600. select.options[i] = o;
  1601. if (element.default) {
  1602. select.selectedIndex = i;
  1603. }
  1604.  
  1605. if (element.url) {
  1606. o.dataset.url = element.url;
  1607. }
  1608. }
  1609. },
  1610.  
  1611. setStyles() {
  1612. // General styles
  1613. yadgUtil.addCSS(
  1614. '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 }',
  1615. );
  1616. },
  1617.  
  1618. // eslint-disable-next-line complexity
  1619. getInputElements() {
  1620. const buttonHTML = '<input type="submit" value="Fetch" id="yadg_submit"/>';
  1621. const scraperSelectHTML
  1622. = '<select name="yadg_scraper" id="yadg_scraper"></select>';
  1623. let optionsHTML
  1624. = '<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>';
  1625. optionsHTML
  1626. += '<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>';
  1627. if (document.querySelectorAll('.rehost_it_cover')[0]) {
  1628. optionsHTML
  1629. += '<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>';
  1630. }
  1631.  
  1632. 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>';
  1633. 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> ';
  1634. 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>';
  1635. const inputHTML = '<input type="text" name="yadg_input" id="yadg_input" size="60" />';
  1636. const responseDivHTML = '<div id="yadg_response"></div>';
  1637. const toggleOptionsLinkHTML
  1638. = '<a id="yadg_toggle_options" href="#">Toggle options</a>';
  1639. const scraperInfoLink
  1640. = '<a id="yadg_scraper_info" href="https://yadg.cc/available-scrapers" target="_blank" title="Get additional information on the available scrapers">[?]</a>';
  1641.  
  1642. switch (this.currentLocation) {
  1643. case 'ops_upload':
  1644. case 'dic_upload':
  1645. case 'pth_upload': {
  1646. const tr = document.createElement('tr');
  1647. tr.className = 'yadg_tr';
  1648. tr.innerHTML
  1649. = '<td class="label">YADG:</td><td>'
  1650. + inputHTML
  1651. + scraperSelectHTML
  1652. + scraperInfoLink
  1653. + buttonHTML
  1654. + toggleOptionsLinkHTML
  1655. + optionsHTML
  1656. + responseDivHTML
  1657. + '</td>';
  1658. return tr;
  1659. }
  1660.  
  1661. case 'lemonhd_upload': {
  1662. const tr = document.createElement('tr');
  1663. tr.className = 'yadg_tr';
  1664. tr.innerHTML
  1665. = '<td class="label rowhead nowrap" align="right">YADG:</td><td class="rowfollow">'
  1666. + inputHTML
  1667. + scraperSelectHTML
  1668. + scraperInfoLink
  1669. + buttonHTML
  1670. + toggleOptionsLinkHTML
  1671. + optionsHTML
  1672. + responseDivHTML
  1673. + '</td>';
  1674. return tr;
  1675. }
  1676.  
  1677. case 'opencd_upload': {
  1678. const tr = document.createElement('tr');
  1679. tr.className = 'yadg_tr';
  1680. tr.innerHTML
  1681. = '<td class="label" align="right"><b>YADG:</b></td><td colspan="5" class="embedded" style="margin-right:5px; margin-left:5px">'
  1682. + '<table style="width:99%; margin-left:0.5%"><tbody><tr><td class="embedded" align="left">'
  1683. + '<input type="text" name="yadg_input" id="yadg_input" size="60" /></td><td>'
  1684. + scraperSelectHTML + '</td><td>'
  1685. + scraperInfoLink + '</td><td>'
  1686. + buttonHTML + '</td><td>'
  1687. + toggleOptionsLinkHTML + '</td></tr><tr><td colspan="5">'
  1688. + optionsHTML
  1689. + responseDivHTML + '&nbsp;'
  1690. + '</td><tr></tbody></table>'
  1691. + '</td>';
  1692. return tr;
  1693. }
  1694.  
  1695. case 'ops_edit':
  1696. case 'dic_edit':
  1697. case 'pth_edit': {
  1698. const div = document.createElement('div');
  1699. div.className = 'yadg_div';
  1700. div.innerHTML
  1701. = '<h3 class="label">YADG:</h3>\n'
  1702. + inputHTML
  1703. + '\n'
  1704. + scraperSelectHTML
  1705. + '\n'
  1706. + scraperInfoLink
  1707. + '\n'
  1708. + buttonHTML
  1709. + '\n'
  1710. + toggleOptionsLinkHTML
  1711. + '\n'
  1712. + optionsHTML
  1713. + '\n'
  1714. + responseDivHTML;
  1715. return div;
  1716. }
  1717.  
  1718. case 'ops_torrent_overview':
  1719. case 'dic_torrent_overview':
  1720. case 'pth_torrent_overview': {
  1721. const div = document.createElement('div');
  1722. div.id = 'yadg_div';
  1723. div.className = 'box';
  1724. div.innerHTML
  1725. = '<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'
  1726. + scraperSelectHTML
  1727. + '\n'
  1728. + scraperInfoLink
  1729. + '\n'
  1730. + buttonHTML
  1731. + '\n'
  1732. + toggleOptionsLinkHTML
  1733. + '\n'
  1734. + optionsHTML
  1735. + '\n'
  1736. + responseDivHTML;
  1737. return div;
  1738. }
  1739.  
  1740. case 'ops_request':
  1741. case 'ops_request_edit':
  1742. case 'dic_request':
  1743. case 'dic_request_edit':
  1744. case 'pth_request':
  1745. case 'pth_request_edit': {
  1746. const tr = document.createElement('tr');
  1747. tr.className = 'yadg_tr';
  1748. tr.innerHTML
  1749. = '<td class="label">YADG:</td><td>'
  1750. + inputHTML
  1751. + scraperSelectHTML
  1752. + scraperInfoLink
  1753. + buttonHTML
  1754. + toggleOptionsLinkHTML
  1755. + optionsHTML
  1756. + responseDivHTML
  1757. + '</td>';
  1758. return tr;
  1759. }
  1760. default:
  1761. // This should actually never happen
  1762. return document.createElement('div');
  1763. }
  1764. },
  1765.  
  1766. // eslint-disable-next-line complexity
  1767. insertIntoPage(element) {
  1768. // alert(this.currentLocation)
  1769. switch (this.currentLocation) {
  1770. case 'ops_upload':
  1771. case 'dic_upload':
  1772. case 'pth_upload': {
  1773. const yearTr = document.querySelector('#year_tr');
  1774. yearTr.parentNode.insertBefore(element, yearTr);
  1775. break;
  1776. }
  1777. case 'lemonhd_upload':
  1778. const tr = document.querySelector("#compose > table > tbody > tr:nth-child(3)");
  1779. tr.parentNode.insertBefore(element, tr);
  1780. break;
  1781. case 'opencd_upload':
  1782. const trd = document.querySelector("#compose > table > tbody > tr:nth-child(5)");
  1783. trd.parentNode.insertBefore(element, trd);
  1784. break;
  1785. case 'ops_edit':
  1786. case 'dic_edit':
  1787. case 'pth_edit': {
  1788. const [summaryInput] = document.getElementsByName('summary');
  1789. summaryInput.parentNode.insertBefore(
  1790. element,
  1791. summaryInput.nextSibling.nextSibling,
  1792. );
  1793. break;
  1794. }
  1795.  
  1796. case 'ops_torrent_overview':
  1797. case 'dic_torrent_overview':
  1798. case 'pth_torrent_overview': {
  1799. const [addArtistsBox] = document.querySelectorAll('.box_addartists');
  1800. addArtistsBox.parentNode.insertBefore(
  1801. element,
  1802. addArtistsBox.nextSibling.nextSibling,
  1803. );
  1804. break;
  1805. }
  1806. case 'ops_request':
  1807. case 'ops_request_edit':
  1808. case 'dic_request':
  1809. case 'dic_request_edit':
  1810. case 'pth_request':
  1811. case 'pth_request_edit': {
  1812. const artistTr = document.querySelector('#artist_tr');
  1813. artistTr.parentNode.insertBefore(element, artistTr);
  1814. break;
  1815. }
  1816.  
  1817. default:
  1818. break;
  1819. }
  1820. },
  1821.  
  1822. // eslint-disable-next-line complexity
  1823. getDescriptionBox() {
  1824. switch (this.currentLocation) {
  1825. case 'ops_upload':
  1826. case 'dic_upload':
  1827. case 'pth_upload':
  1828. if (factory.getDescriptionTargetSelect().value === 'album') {
  1829. return document.querySelector('#album_desc');
  1830. }
  1831.  
  1832. if (factory.getDescriptionTargetSelect().value === 'release') {
  1833. return document.querySelector('#release_desc');
  1834. }
  1835.  
  1836. if (factory.getDescriptionTargetSelect().value === 'both') {
  1837. return [
  1838. document.querySelector('#album_desc'),
  1839. document.querySelector('#release_desc'),
  1840. ];
  1841. }
  1842. break;
  1843. case 'lemonhd_upload':
  1844. if (factory.getDescriptionTargetSelect().value === 'album') {
  1845. return document.querySelector('#descr');
  1846. }
  1847.  
  1848. if (factory.getDescriptionTargetSelect().value === 'release') {
  1849. return document.querySelector('#descr');
  1850. }
  1851.  
  1852. if (factory.getDescriptionTargetSelect().value === 'both') {
  1853. return [
  1854. document.querySelector('#descr'),
  1855. document.querySelector('#descr'),
  1856. ];
  1857. }
  1858. break;
  1859. case 'opencd_upload':
  1860. if (factory.getDescriptionTargetSelect().value === 'album') {
  1861. return document.querySelector('#descr');
  1862. }
  1863.  
  1864. if (factory.getDescriptionTargetSelect().value === 'release') {
  1865. return document.querySelector('#descr');
  1866. }
  1867.  
  1868. if (factory.getDescriptionTargetSelect().value === 'both') {
  1869. return [
  1870. document.querySelector('#descr'),
  1871. document.querySelector('#descr'),
  1872. ];
  1873. }
  1874. break;
  1875.  
  1876. case 'ops_edit':
  1877. case 'dic_edit':
  1878. case 'pth_edit':
  1879. return document.getElementsByName('body')[0];
  1880.  
  1881. case 'ops_torrent_overview':
  1882. case 'dic_torrent_overview':
  1883. case 'pth_torrent_overview':
  1884. if (!Object.prototype.hasOwnProperty.call(this, 'dummybox')) {
  1885. this.dummybox = document.createElement('div');
  1886. }
  1887.  
  1888. return this.dummybox;
  1889.  
  1890. case 'ops_request':
  1891. case 'ops_request_edit':
  1892. case 'dic_request':
  1893. case 'dic_request_edit':
  1894. case 'pth_request':
  1895. case 'pth_request_edit':
  1896. return document.getElementsByName('description')[0];
  1897. default:
  1898. // That should actually never happen
  1899. return document.createElement('div');
  1900. }
  1901. },
  1902.  
  1903. // eslint-disable-next-line complexity
  1904. getFormFillFunction() {
  1905. const currentTarget = factory.getTargetSelect().value;
  1906.  
  1907. var type_dict = {
  1908. "electronic": "电子(Electronic)",
  1909. "blues": "蓝调(Blues)",
  1910. "blues": "蓝调(Blues)", "rhythm.and.blues": "蓝调(Blues)",
  1911. "classical": "古典(Classical)",
  1912. "country": "乡村(Country)",
  1913. "folk": "民间(Folk)",
  1914. "drum.and.bass": "贝斯(Drum Bass)",
  1915. "jazz": "爵士(Jazz)",
  1916. "new.age": "新世纪(NewAge)",
  1917. "soul": "天籁(Soul)",
  1918. "modern.classical": "古典(Classical)",
  1919. "garage.house": "汽车(garage)", "garage.rock": "汽车(garage)",
  1920. "reggae": "雷鬼(Reggae)",
  1921. "hip.hop": "嘻哈(Hip Hop)",
  1922. "instrumental": "器乐(Instrumental)",
  1923. "indie": "独立(Indie)",
  1924. "japanese": "日韩", "korean": "日韩",
  1925. "chinese": "大陆", "thai": "其他地区",
  1926. "dance": "舞曲(Dance)","english": "欧美"
  1927. };
  1928.  
  1929. var info = {
  1930. "大陆": "1","欧美": "2","港台": "3","日韩": "4","其它地区": "5","流行(Pop)": "6",
  1931. "发烧(HiFi)": "7","汽车(garage)": "8","古典(Classical)": "9","民族(National)": "10",
  1932. "摇滚(rock)": "11","原声(OST)": "12","民间(Folk)": "13","乡村(Country)": "14",
  1933. "天籁(Soul)": "15","新世纪(NewAge)": "16","蓝调(Blues)": "17","爵士(Jazz)": "18",
  1934. "金属(Metal)": "19","朋克(Punk)": "20","电子(Electronic)": "21","儿童(Children's)": "22",
  1935. "宗教(Religion)": "23","雷鬼(Reggae)": "24","贝斯(Drum Bass)": "25","说唱(Rap)": "26","音乐剧(musical)": "27"
  1936. };
  1937.  
  1938. function getDescr(rawData) {
  1939. var descr = `[size=4][b]Album Info[/b][/size]\n`;
  1940. if (rawData.title) { descr += `[b]Music title[/b]: ${rawData.title}\n`; }
  1941. if (rawData.artists.length) { descr += `[b]Music artists[/b]: ${rawData.artists[0].name}\n`; }
  1942. if (rawData.format) { descr += `[b]Music format[/b]: ${rawData.format}\n`; }
  1943. if (rawData.styles.length) { descr += `[b]Music style[/b]: ${rawData.styles.join(', ')}\n`; }
  1944. if (rawData.genres.length) { descr += `[b]Music Genres[/b]: ${rawData.genres.join(' | ')}\n`; }
  1945. if (rawData.releaseEvents.length) { descr += `[b]Music release[/b]: ${rawData.releaseEvents[0].country}-${rawData.releaseEvents[0].date}\n`; }
  1946. if (rawData.labelIds.length) {
  1947. descr += '[b]Music labelIds[/b]: ';
  1948.  
  1949. rawData.labelIds.map((item, index)=>{
  1950. if (index == 0) {
  1951. descr += `${item.label}(${item.catalogueNrs[0]}); `;
  1952. } else {
  1953. descr += `${item.label}(${item.catalogueNrs[0]});`;
  1954. }
  1955. })
  1956. }
  1957. if (rawData.url) {
  1958. descr += '\n\n' + `More information: [url]${rawData.url}[/url]`;
  1959. }
  1960. return descr;
  1961. }
  1962.  
  1963. function getMinute(i) {
  1964. var hour = parseInt(i/3600);
  1965. if (hour > 0) {
  1966. i = i % 3600;
  1967. }
  1968. var minutes = parseInt(i/60);
  1969. var seconds = i % 60;
  1970. var timeStr = `(${minutes}:${seconds})`;
  1971. if (hour) {
  1972. timeStr = `(${hour}:${minutes}:${seconds})`;
  1973. }
  1974. return timeStr;
  1975. }
  1976. switch (this.currentLocation) {
  1977. case 'lemonhd_upload': {
  1978. const f = function (rawData) {
  1979. console.log(rawData)
  1980. let albumTitleInput;
  1981. let yearInput;
  1982. let labelInput;
  1983. let catalogInput;
  1984.  
  1985. albumTitleInput = document.querySelector('[name=title]');
  1986. yearInput = document.querySelector('[name=remaster_year]');
  1987. labelInput = document.querySelector('[name=remaster_record_label]');
  1988. catalogInput = document.querySelector('[name=remaster_catalogue_number]');
  1989.  
  1990. if (/music.apple/.test(rawData.url)) {
  1991. switch (true) {
  1992. case /.+ - Single$/.test(rawData.title):
  1993. rawData.title = rawData.title.replace(/ - Single$/, '');
  1994. $('select[name=music_category]').val(3);
  1995. break;
  1996. case /.+ - EP$/.test(rawData.title):
  1997. rawData.title = rawData.title.replace(/ - EP$/, '');
  1998. $('select[name=music_category]').val(4);
  1999. }
  2000. }
  2001.  
  2002. var descr = getDescr(rawData);
  2003. $('#descr').val(descr + $('#descr').val());
  2004.  
  2005. let artistInputs = document.getElementsByName('artists[]');
  2006.  
  2007. const releaseTypeInput = document.querySelector('[name=music_category]');
  2008. const data = yadg.prepareRawResponse(rawData);
  2009.  
  2010. console.log(data)
  2011.  
  2012. let nullArtistCount = 0;
  2013.  
  2014. if (artistInputs[0].getAttribute('disabled') !== 'disabled') {
  2015. if (data.artists === false) {
  2016. for (const element of artistInputs) {
  2017. element.value = '';
  2018. }
  2019. } else {
  2020. let inputIdx = 0;
  2021.  
  2022. yadgUtil.addRemoveArtistBoxes(
  2023. data.effective_artist_count - artistInputs.length,
  2024. );
  2025.  
  2026. artistInputs = document.getElementsByName('artists[]');
  2027.  
  2028. for (let i = 0; i < data.artist_keys.length; i++) {
  2029. const artistKey = data.artist_keys[i];
  2030. if (artistKey === 'null') {
  2031. nullArtistCount++;
  2032. continue;
  2033. }
  2034.  
  2035. const artistTypes = data.artists[artistKey];
  2036.  
  2037. for (const artistType of artistTypes) {
  2038. const artistInput = artistInputs[inputIdx];
  2039. let typeSelect = artistInput.nextSibling;
  2040.  
  2041. while (typeSelect.tagName !== 'SELECT') {
  2042. typeSelect = typeSelect.nextSibling;
  2043. }
  2044.  
  2045. artistInput.value = artistKey;
  2046.  
  2047. const optionOffsets = yadgUtil.getOptionOffsets(typeSelect);
  2048.  
  2049. switch (artistType) {
  2050. case 'main': {
  2051. typeSelect.selectedIndex = optionOffsets[1];
  2052.  
  2053. break;
  2054. }
  2055.  
  2056. case 'guest': {
  2057. typeSelect.selectedIndex = optionOffsets[2];
  2058.  
  2059. break;
  2060. }
  2061.  
  2062. case 'remixer': {
  2063. typeSelect.selectedIndex = optionOffsets[3];
  2064.  
  2065. break;
  2066. }
  2067.  
  2068. default: {
  2069. // We don't know this artist type, default to "main"
  2070. typeSelect.selectedIndex = optionOffsets[1];
  2071. }
  2072. }
  2073.  
  2074. // Next artist input
  2075. inputIdx += 1;
  2076. }
  2077. }
  2078.  
  2079. if (nullArtistCount > 0) {
  2080. yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1));
  2081. }
  2082. }
  2083. }
  2084.  
  2085. if (yearInput.getAttribute('disabled') !== 'disabled') {
  2086. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  2087. }
  2088.  
  2089. if (albumTitleInput.getAttribute('disabled') !== 'disabled') {
  2090. yadgUtil.setValueIfSet(
  2091. data.title,
  2092. albumTitleInput,
  2093. data.title !== false,
  2094. );
  2095. }
  2096.  
  2097. if (labelInput.getAttribute('disabled') !== 'disabled') {
  2098. yadgUtil.setValueIfSet(
  2099. data.label,
  2100. labelInput,
  2101. data.label !== false,
  2102. );
  2103. }
  2104.  
  2105. if (catalogInput.getAttribute('disabled') !== 'disabled') {
  2106. yadgUtil.setValueIfSet(
  2107. data.catalog,
  2108. catalogInput,
  2109. data.catalog !== false,
  2110. );
  2111. }
  2112.  
  2113. // tags
  2114. var music_type = [];
  2115. data.tags.map((item)=>{
  2116. item = item.toLowerCase();
  2117. if (item.match(/pop/) && music_type.indexOf("流行(Pop)") < 0) {
  2118. music_type.push("流行(Pop)");
  2119. }
  2120. if (item.match(/rock/) && music_type.indexOf("摇滚(rock)") < 0) {
  2121. music_type.push("摇滚(rock)");
  2122. }
  2123. if (item.match(/punk/) && music_type.indexOf("朋克(Punk)") < 0) {
  2124. music_type.push("朋克(Punk)");
  2125. }
  2126. if (item.match(/Metal/i) && music_type.indexOf("金属(Metal)") < 0) {
  2127. music_type.push("金属(Metal)");
  2128. }
  2129. if (type_dict.hasOwnProperty(item) && music_type.indexOf(type_dict[item]) < 0) {
  2130. music_type.push(type_dict[item]);
  2131. }
  2132. if (item.match(/alternative/) && music_type.indexOf("另类(Alternative)") < 0) {
  2133. music_type.push("另类(Alternative)");
  2134. }
  2135. if (item.match(/world.music/) && music_type.indexOf("世界音乐(World)") < 0) {
  2136. music_type.push("世界音乐(World)");
  2137. }
  2138. });
  2139. music_type.map((item)=>{
  2140. if (info.hasOwnProperty(item)) {
  2141. addTag(info[item]);
  2142. }
  2143. });
  2144.  
  2145. var releasetype_dict = {
  2146. 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
  2147. }
  2148. data.releaseType = releasetype_dict[data.releaseType];
  2149.  
  2150. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2151. yadgUtil.setValueIfSet(
  2152. data.releaseType,
  2153. releaseTypeInput,
  2154. data.releaseType !== false,
  2155. );
  2156. }
  2157. };
  2158. return f;
  2159. }
  2160.  
  2161. case 'opencd_upload': {
  2162. // eslint-disable-next-line complexity
  2163. const f = function (rawData) {
  2164. console.log(rawData)
  2165. let albumTitleInput;
  2166. let yearInput;
  2167.  
  2168. albumTitleInput = document.querySelector('[name=resource_name]');
  2169. yearInput = document.querySelector('[name=year]');
  2170.  
  2171. let artistInputs = document.getElementsByName('artist');
  2172. if (artistInputs[0].getAttribute('disabled') !== 'disabled') {
  2173. if (rawData.artists.length) {
  2174. artistInputs[0].value = rawData.artists[0].name;
  2175. }
  2176. }
  2177.  
  2178. console.log(rawData);
  2179. var descr = getDescr(rawData);
  2180. if ($('#yadg2descr').length == 1) {
  2181. $('#yadg2descr').remove();
  2182. $('#descr').parent().append(`<a style="text-decoration:none;" href="#" id="yadg2descr"><font color="red">从yadg导入</font></a>`);
  2183. } else {
  2184. $('#descr').parent().append(`<br><a style="text-decoration:none;" href="#" id="yadg2descr"><font color="red">从yadg导入</font></a>`);
  2185. }
  2186. $('#yadg2descr').click((e)=>{
  2187. e.preventDefault();
  2188. var originDescr = $('#descr').val();
  2189. $('#descr').val(descr + '\n\n' + originDescr);
  2190. });
  2191.  
  2192.  
  2193. const data = yadg.prepareRawResponse(rawData);
  2194. if (yearInput.getAttribute('disabled') !== 'disabled') {
  2195. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  2196. }
  2197. if (albumTitleInput.getAttribute('disabled') !== 'disabled') {
  2198. yadgUtil.setValueIfSet(
  2199. data.title,
  2200. albumTitleInput,
  2201. data.title !== false,
  2202. );
  2203. }
  2204.  
  2205. var tracklist = ``;
  2206. if (rawData.discs.length) {
  2207. rawData.discs.map(disc=>{
  2208. var total_time = 0;
  2209. disc.tracks.map(item=>{
  2210. console.log(item.length);
  2211. tracklist += `${item.number} ${item.title}${item['length'] ? getMinute(item['length']): ''}\n`;
  2212. total_time += item['length'] ? item['length'] : 0;
  2213. });
  2214. tracklist += total_time? `\n[b]Total length:[/b] ${getMinute(total_time)}\n\n` : '\n\n';
  2215. })
  2216. }
  2217.  
  2218. if ($('#yadg2dtracklit').length == 0) {
  2219. $('textarea[name=track_list]').parent().append(`<br><a style="text-decoration:none;" href="#" id="yadg2dtracklit"><font color="red">从yadg导入</font></a>`);
  2220. }
  2221. $('#yadg2dtracklit').click((e)=>{
  2222. e.preventDefault();
  2223. $('textarea[name=track_list]').val(tracklist);
  2224. });
  2225.  
  2226. // tags
  2227. var music_type = [];
  2228. if (data.tags) {
  2229. data.tags.map((item)=>{
  2230. item = item.toLowerCase();
  2231. if (item.match(/pop/) && music_type.indexOf("流行(Pop)") < 0) {
  2232. music_type.push("流行(Pop)");
  2233. }
  2234. if (item.match(/rock/) && music_type.indexOf("摇滚(rock)") < 0) {
  2235. music_type.push("摇滚(rock)");
  2236. }
  2237. if (item.match(/punk/) && music_type.indexOf("朋克(Punk)") < 0) {
  2238. music_type.push("朋克(Punk)");
  2239. }
  2240. if (item.match(/Metal/i) && music_type.indexOf("金属(Metal)") < 0) {
  2241. music_type.push("金属(Metal)");
  2242. }
  2243. if (type_dict.hasOwnProperty(item) && music_type.indexOf(type_dict[item]) < 0) {
  2244. music_type.push(type_dict[item]);
  2245. }
  2246. if (item.match(/alternative/) && music_type.indexOf("另类(Alternative)") < 0) {
  2247. music_type.push("另类(Alternative)");
  2248. }
  2249. if (item.match(/world.music/) && music_type.indexOf("世界音乐(World)") < 0) {
  2250. music_type.push("世界音乐(World)");
  2251. }
  2252. });
  2253. }
  2254.  
  2255. setTimeout(function(){
  2256. var source_selected = false;
  2257. music_type.map(item=>{
  2258. console.log(item)
  2259. var source = $(`a.tag:contains("${item}")`);
  2260. if (item == "贝斯(Drum Bass)") { source = $(`a.tag[value="25"]`); }
  2261. if (source.lenth) {
  2262. addTag(source);
  2263. }
  2264. if (!source_selected) {
  2265. if (item == '摇滚(rock)') {
  2266. item = '摇滚(Rock)';
  2267. }
  2268. if ($(`#source>option:contains(${item})`).length) {
  2269. $(`#source>option:contains(${item})`).attr('selected', true);
  2270. source_selected = true;
  2271. }
  2272. }
  2273. })
  2274. }, 500);
  2275.  
  2276. var evt = document.createEvent("HTMLEvents");
  2277. evt.initEvent("change", false, true);
  2278. document.getElementById('audio_mode').dispatchEvent(evt);
  2279.  
  2280. };
  2281. return f;
  2282. }
  2283.  
  2284. case 'pth_upload': {
  2285. // eslint-disable-next-line complexity
  2286. const f = function (rawData) {
  2287. let albumTitleInput;
  2288. let yearInput;
  2289. let labelInput;
  2290. let catalogInput;
  2291. if (currentTarget === 'other') {
  2292. albumTitleInput = document.querySelector('#title');
  2293. yearInput = document.querySelector('#remaster_year');
  2294. labelInput = document.querySelector('#remaster_record_label');
  2295. catalogInput = document.querySelector('#remaster_catalogue_number');
  2296. unsafeWindow.CheckYear(); // eslint-disable-line new-cap
  2297. } else {
  2298. albumTitleInput = document.querySelector('#title');
  2299. yearInput = document.querySelector('#year');
  2300. labelInput = document.querySelector('#remaster_record_label');
  2301. catalogInput = document.querySelector('#remaster_catalogue_number');
  2302. }
  2303.  
  2304. if (/music.apple/.test(rawData.url)) {
  2305. const releaseTypeInput = document.querySelector('#releasetype');
  2306. switch (true) {
  2307. case /.+ - Single$/.test(rawData.title):
  2308. rawData.title = rawData.title.replace(/ - Single$/, '');
  2309. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2310. releaseTypeInput.value = 9;
  2311. }
  2312.  
  2313. break;
  2314. case /.+ - EP$/.test(rawData.title):
  2315. rawData.title = rawData.title.replace(/ - EP$/, '');
  2316. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2317. releaseTypeInput.value = 5;
  2318. }
  2319.  
  2320. break;
  2321. default:
  2322. break;
  2323. }
  2324. }
  2325.  
  2326. let artistInputs = document.getElementsByName('artists[]');
  2327. const tagsInput = document.querySelector('#tags');
  2328. const mediaInput = document.querySelector('#media');
  2329. const releaseTypeInput = document.querySelector('#releasetype');
  2330. const data = yadg.prepareRawResponse(rawData);
  2331. let nullArtistCount = 0;
  2332.  
  2333. if (artistInputs[0].getAttribute('disabled') !== 'disabled') {
  2334. if (data.artists === false) {
  2335. for (const element of artistInputs) {
  2336. element.value = '';
  2337. }
  2338. } else {
  2339. let inputIdx = 0;
  2340.  
  2341. yadgUtil.addRemoveArtistBoxes(
  2342. data.effective_artist_count - artistInputs.length,
  2343. );
  2344.  
  2345. artistInputs = document.getElementsByName('artists[]');
  2346.  
  2347. for (let i = 0; i < data.artist_keys.length; i++) {
  2348. const artistKey = data.artist_keys[i];
  2349. if (artistKey === 'null') {
  2350. nullArtistCount++;
  2351. continue;
  2352. }
  2353.  
  2354. const artistTypes = data.artists[artistKey];
  2355.  
  2356. for (const artistType of artistTypes) {
  2357. const artistInput = artistInputs[inputIdx];
  2358. let typeSelect = artistInput.nextSibling;
  2359.  
  2360. while (typeSelect.tagName !== 'SELECT') {
  2361. typeSelect = typeSelect.nextSibling;
  2362. }
  2363.  
  2364. artistInput.value = artistKey;
  2365.  
  2366. const optionOffsets = yadgUtil.getOptionOffsets(typeSelect);
  2367.  
  2368. switch (artistType) {
  2369. case 'main': {
  2370. typeSelect.selectedIndex = optionOffsets[1];
  2371.  
  2372. break;
  2373. }
  2374.  
  2375. case 'guest': {
  2376. typeSelect.selectedIndex = optionOffsets[2];
  2377.  
  2378. break;
  2379. }
  2380.  
  2381. case 'remixer': {
  2382. typeSelect.selectedIndex = optionOffsets[3];
  2383.  
  2384. break;
  2385. }
  2386.  
  2387. default: {
  2388. // We don't know this artist type, default to "main"
  2389. typeSelect.selectedIndex = optionOffsets[1];
  2390. }
  2391. }
  2392.  
  2393. // Next artist input
  2394. inputIdx += 1;
  2395. }
  2396. }
  2397.  
  2398. if (nullArtistCount > 0) {
  2399. yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1));
  2400. }
  2401. }
  2402. }
  2403.  
  2404. if (tagsInput.getAttribute('disabled') !== 'disabled') {
  2405. if (data.tags === false) {
  2406. tagsInput.value = '';
  2407. } else {
  2408. const tagsArray = data.tag_string.split(', ');
  2409. const tagsUnique = tagsArray.filter((element, index, self) => index === self.indexOf(element));
  2410. tagsInput.value = tagsUnique.join(',').toLowerCase();
  2411. }
  2412. }
  2413.  
  2414. if (yearInput.getAttribute('disabled') !== 'disabled') {
  2415. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  2416. }
  2417.  
  2418. if (albumTitleInput.getAttribute('disabled') !== 'disabled') {
  2419. yadgUtil.setValueIfSet(
  2420. data.title,
  2421. albumTitleInput,
  2422. data.title !== false,
  2423. );
  2424. }
  2425.  
  2426. if (labelInput.getAttribute('disabled') !== 'disabled') {
  2427. yadgUtil.setValueIfSet(
  2428. data.label,
  2429. labelInput,
  2430. data.label !== false,
  2431. );
  2432. }
  2433.  
  2434. if (catalogInput.getAttribute('disabled') !== 'disabled') {
  2435. yadgUtil.setValueIfSet(
  2436. data.catalog,
  2437. catalogInput,
  2438. data.catalog !== false,
  2439. );
  2440. }
  2441.  
  2442. if (mediaInput.getAttribute('disabled') !== 'disabled') {
  2443. yadgUtil.setValueIfSet(
  2444. data.format,
  2445. mediaInput,
  2446. data.format !== false,
  2447. );
  2448. }
  2449.  
  2450. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2451. yadgUtil.setValueIfSet(
  2452. data.releaseType,
  2453. releaseTypeInput,
  2454. data.releaseType !== false,
  2455. );
  2456. }
  2457. };
  2458.  
  2459. return f;
  2460. }
  2461.  
  2462. case 'ops_upload': {
  2463. // eslint-disable-next-line complexity
  2464. const f = function (rawData) {
  2465. let albumTitleInput;
  2466. let yearInput;
  2467. let labelInput;
  2468. let catalogInput;
  2469. if (currentTarget === 'other') {
  2470. const remaster = document.querySelector('#remaster');
  2471. albumTitleInput = document.querySelector('#title');
  2472. yearInput = document.querySelector('#remaster_year');
  2473. labelInput = document.querySelector('#remaster_record_label');
  2474. catalogInput = document.querySelector('#remaster_catalogue_number');
  2475. remaster.checked = 'checked';
  2476. unsafeWindow.Remaster(); // eslint-disable-line new-cap
  2477. unsafeWindow.CheckYear(); // eslint-disable-line new-cap
  2478. } else {
  2479. albumTitleInput = document.querySelector('#title');
  2480. yearInput = document.querySelector('#year');
  2481. labelInput = document.querySelector('#record_label');
  2482. catalogInput = document.querySelector('#catalogue_number');
  2483. }
  2484.  
  2485. if (/itunes/.test(rawData.url)) {
  2486. const releaseTypeInput = document.querySelector('#releasetype');
  2487. switch (true) {
  2488. case /.+ - Single$/.test(rawData.title):
  2489. rawData.title = rawData.title.replace(/ - Single$/, '');
  2490. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2491. releaseTypeInput.value = 9;
  2492. }
  2493.  
  2494. break;
  2495. case /.+ - EP$/.test(rawData.title):
  2496. rawData.title = rawData.title.replace(/ - EP$/, '');
  2497. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2498. releaseTypeInput.value = 5;
  2499. }
  2500.  
  2501. break;
  2502. default:
  2503. break;
  2504. }
  2505. }
  2506.  
  2507. let artistInputs = document.getElementsByName('artists[]');
  2508. const tagsInput = document.querySelector('#tags');
  2509. const data = yadg.prepareRawResponse(rawData);
  2510. let nullArtistCount = 0;
  2511.  
  2512. if (artistInputs[0].getAttribute('disabled') !== 'disabled') {
  2513. if (data.artists === false) {
  2514. for (const element of artistInputs) {
  2515. element.value = '';
  2516. }
  2517. } else {
  2518. let inputIdx = 0;
  2519.  
  2520. yadgUtil.addRemoveArtistBoxes(
  2521. data.effective_artist_count - artistInputs.length,
  2522. );
  2523.  
  2524. artistInputs = document.getElementsByName('artists[]');
  2525.  
  2526. for (let i = 0; i < data.artist_keys.length; i++) {
  2527. const artistKey = data.artist_keys[i];
  2528. if (artistKey === 'null') {
  2529. nullArtistCount++;
  2530. continue;
  2531. }
  2532.  
  2533. const artistTypes = data.artists[artistKey];
  2534.  
  2535. for (const artistType of artistTypes) {
  2536. const artistInput = artistInputs[inputIdx];
  2537. let typeSelect = artistInput.nextSibling;
  2538.  
  2539. while (typeSelect.tagName !== 'SELECT') {
  2540. typeSelect = typeSelect.nextSibling;
  2541. }
  2542.  
  2543. artistInput.value = artistKey;
  2544.  
  2545. const optionOffsets = yadgUtil.getOptionOffsets(typeSelect);
  2546.  
  2547. switch (artistType) {
  2548. case 'main': {
  2549. typeSelect.selectedIndex = optionOffsets[1];
  2550.  
  2551. break;
  2552. }
  2553.  
  2554. case 'guest': {
  2555. typeSelect.selectedIndex = optionOffsets[2];
  2556.  
  2557. break;
  2558. }
  2559.  
  2560. case 'remixer': {
  2561. typeSelect.selectedIndex = optionOffsets[3];
  2562.  
  2563. break;
  2564. }
  2565.  
  2566. default: {
  2567. // We don't know this artist type, default to "main"
  2568. typeSelect.selectedIndex = optionOffsets[1];
  2569. }
  2570. }
  2571.  
  2572. // Next artist input
  2573. inputIdx += 1;
  2574. }
  2575. }
  2576.  
  2577. if (nullArtistCount > 0) {
  2578. yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1));
  2579. }
  2580. }
  2581. }
  2582.  
  2583. if (tagsInput.getAttribute('disabled') !== 'disabled') {
  2584. if (data.tags === false) {
  2585. tagsInput.value = '';
  2586. } else {
  2587. const tagsArray = data.tag_string.split(', ');
  2588. const tagsUnique = tagsArray.filter((element, index, self) => index === self.indexOf(element));
  2589. tagsInput.value = tagsUnique.join(',').toLowerCase();
  2590. }
  2591. }
  2592.  
  2593. if (yearInput.getAttribute('disabled') !== 'disabled') {
  2594. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  2595. }
  2596.  
  2597. if (albumTitleInput.getAttribute('disabled') !== 'disabled') {
  2598. yadgUtil.setValueIfSet(
  2599. data.title,
  2600. albumTitleInput,
  2601. data.title !== false,
  2602. );
  2603. }
  2604.  
  2605. if (labelInput.getAttribute('disabled') !== 'disabled') {
  2606. yadgUtil.setValueIfSet(
  2607. data.label,
  2608. labelInput,
  2609. data.label !== false,
  2610. );
  2611. }
  2612.  
  2613. if (catalogInput.getAttribute('disabled') !== 'disabled') {
  2614. yadgUtil.setValueIfSet(
  2615. data.catalog,
  2616. catalogInput,
  2617. data.catalog !== false,
  2618. );
  2619. }
  2620. };
  2621.  
  2622. return f;
  2623. }
  2624.  
  2625. case 'dic_upload': {
  2626. // eslint-disable-next-line complexity
  2627. const f = function (rawData) {
  2628. let albumTitleInput;
  2629. let yearInput;
  2630. let labelInput;
  2631. let catalogInput;
  2632. if (currentTarget === 'other') {
  2633. albumTitleInput = document.querySelector('#title');
  2634. yearInput = document.querySelector('#remaster_year');
  2635. labelInput = document.querySelector('#remaster_record_label');
  2636. catalogInput = document.querySelector('#remaster_catalogue_number');
  2637. unsafeWindow.CheckYear(); // eslint-disable-line new-cap
  2638. } else {
  2639. const unknownCheckbox = document.querySelector('#unknown');
  2640. albumTitleInput = document.querySelector('#title');
  2641. yearInput = document.querySelector('#year');
  2642. unknownCheckbox.checked = 'checked';
  2643. unsafeWindow.ToggleUnknown(); // eslint-disable-line new-cap
  2644. }
  2645.  
  2646. const releaseTypeInput = document.querySelector('#releasetype');
  2647. if (/itunes/.test(rawData.url)) {
  2648. switch (true) {
  2649. case /.+ - Single$/.test(rawData.title):
  2650. rawData.title = rawData.title.replace(/ - Single$/, '');
  2651. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2652. releaseTypeInput.value = 9;
  2653. }
  2654.  
  2655. break;
  2656. case /.+ - EP$/.test(rawData.title):
  2657. rawData.title = rawData.title.replace(/ - EP$/, '');
  2658. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2659. releaseTypeInput.value = 5;
  2660. }
  2661.  
  2662. break;
  2663. default:
  2664. break;
  2665. }
  2666. }
  2667.  
  2668. let artistInputs = document.getElementsByName('artists[]');
  2669. const tagsInput = document.querySelector('#tags');
  2670. const data = yadg.prepareRawResponse(rawData);
  2671. let nullArtistCount = 0;
  2672.  
  2673. if (artistInputs[0].getAttribute('disabled') !== 'disabled') {
  2674. if (data.artists === false) {
  2675. for (const element of artistInputs) {
  2676. element.value = '';
  2677. }
  2678. } else {
  2679. let inputIdx = 0;
  2680.  
  2681. yadgUtil.addRemoveArtistBoxes(
  2682. data.effective_artist_count - artistInputs.length,
  2683. );
  2684.  
  2685. artistInputs = document.getElementsByName('artists[]');
  2686.  
  2687. for (let i = 0; i < data.artist_keys.length; i++) {
  2688. const artistKey = data.artist_keys[i];
  2689. if (artistKey === 'null') {
  2690. nullArtistCount++;
  2691. continue;
  2692. }
  2693.  
  2694. const artistTypes = data.artists[artistKey];
  2695.  
  2696. for (const artistType of artistTypes) {
  2697. const artistInput = artistInputs[inputIdx];
  2698. let typeSelect = artistInput.nextSibling;
  2699.  
  2700. while (typeSelect.tagName !== 'SELECT') {
  2701. typeSelect = typeSelect.nextSibling;
  2702. }
  2703.  
  2704. artistInput.value = artistKey;
  2705.  
  2706. const optionOffsets = yadgUtil.getOptionOffsets(typeSelect);
  2707.  
  2708. switch (artistType) {
  2709. case 'main': {
  2710. typeSelect.selectedIndex = optionOffsets[1];
  2711.  
  2712. break;
  2713. }
  2714.  
  2715. case 'guest': {
  2716. typeSelect.selectedIndex = optionOffsets[2];
  2717.  
  2718. break;
  2719. }
  2720.  
  2721. case 'remixer': {
  2722. typeSelect.selectedIndex = optionOffsets[3];
  2723.  
  2724. break;
  2725. }
  2726.  
  2727. default: {
  2728. // We don't know this artist type, default to "main"
  2729. typeSelect.selectedIndex = optionOffsets[1];
  2730. }
  2731. }
  2732.  
  2733. // Next artist input
  2734. inputIdx += 1;
  2735. }
  2736. }
  2737.  
  2738. if (nullArtistCount > 0) {
  2739. yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1));
  2740. }
  2741. }
  2742. }
  2743.  
  2744. if (tagsInput.getAttribute('disabled') !== 'disabled') {
  2745. if (data.tags === false) {
  2746. tagsInput.value = '';
  2747. } else {
  2748. const tagsArray = data.tag_string.split(', ');
  2749. const tagsUnique = tagsArray.filter((element, index, self) => index === self.indexOf(element));
  2750. tagsInput.value = tagsUnique.join(',').toLowerCase();
  2751. }
  2752. }
  2753.  
  2754. if (yearInput.getAttribute('disabled') !== 'disabled') {
  2755. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  2756. }
  2757.  
  2758. if (albumTitleInput.getAttribute('disabled') !== 'disabled') {
  2759. yadgUtil.setValueIfSet(
  2760. data.title,
  2761. albumTitleInput,
  2762. data.title !== false,
  2763. );
  2764. }
  2765.  
  2766. if (labelInput && labelInput.getAttribute('disabled') !== 'disabled') {
  2767. yadgUtil.setValueIfSet(
  2768. data.label,
  2769. labelInput,
  2770. data.label !== false,
  2771. );
  2772. }
  2773.  
  2774. if (catalogInput && catalogInput.getAttribute('disabled') !== 'disabled') {
  2775. yadgUtil.setValueIfSet(
  2776. data.catalog,
  2777. catalogInput,
  2778. data.catalog !== false,
  2779. );
  2780. }
  2781. if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
  2782. yadgUtil.setValueIfSet(
  2783. data.releaseType,
  2784. releaseTypeInput,
  2785. data.releaseType !== false,
  2786. );
  2787. }
  2788. };
  2789.  
  2790. return f;
  2791. }
  2792.  
  2793. case 'ops_edit':
  2794. case 'dic_edit':
  2795. case 'pth_edit': {
  2796. const f = function (rawData) {
  2797. const [summaryInput] = document.getElementsByName('summary');
  2798. const [yearInput] = document.getElementsByName('year');
  2799. const [labelInput] = document.getElementsByName('record_label');
  2800. const [catalogInput] = document.getElementsByName('catalogue_number');
  2801. const data = yadg.prepareRawResponse(rawData);
  2802.  
  2803. summaryInput.value = 'YADG Update';
  2804. if (yearInput && yearInput.getAttribute('disabled') !== 'disabled') {
  2805. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  2806. }
  2807.  
  2808. if (
  2809. labelInput
  2810. && labelInput.getAttribute('disabled') !== 'disabled'
  2811. ) {
  2812. yadgUtil.setValueIfSet(
  2813. data.label,
  2814. labelInput,
  2815. data.label !== false,
  2816. );
  2817. }
  2818.  
  2819. if (
  2820. catalogInput
  2821. && catalogInput.getAttribute('disabled') !== 'disabled'
  2822. ) {
  2823. yadgUtil.setValueIfSet(
  2824. data.catalog,
  2825. catalogInput,
  2826. data.catalog !== false,
  2827. );
  2828. }
  2829. };
  2830.  
  2831. return f;
  2832. }
  2833.  
  2834. case 'ops_torrent_overview':
  2835. case 'dic_torrent_overview':
  2836. case 'pth_torrent_overview': {
  2837. const f = function (rawData) {
  2838. let artistInputs = document.getElementsByName('aliasname[]');
  2839. const data = yadg.prepareRawResponse(rawData);
  2840.  
  2841. if (data.artists === false) {
  2842. for (const element of artistInputs) {
  2843. element.value = '';
  2844. }
  2845. } else {
  2846. let inputIdx = 0;
  2847.  
  2848. yadgUtil.addRemoveArtistBoxes(
  2849. data.effective_artist_count - artistInputs.length,
  2850. );
  2851.  
  2852. artistInputs = document.getElementsByName('aliasname[]');
  2853.  
  2854. for (let i = 0; i < data.artist_keys.length; i++) {
  2855. const artistKey = data.artist_keys[i];
  2856. const artistTypes = data.artists[artistKey];
  2857.  
  2858. for (const artistType of artistTypes) {
  2859. const artistInput = artistInputs[inputIdx];
  2860. let typeSelect = artistInput.nextSibling;
  2861.  
  2862. while (typeSelect.tagName !== 'SELECT') {
  2863. typeSelect = typeSelect.nextSibling;
  2864. }
  2865.  
  2866. artistInput.value = artistKey;
  2867.  
  2868. const optionOffsets = yadgUtil.getOptionOffsets(typeSelect);
  2869.  
  2870. switch (artistType) {
  2871. case 'main': {
  2872. typeSelect.selectedIndex = optionOffsets[1];
  2873.  
  2874. break;
  2875. }
  2876.  
  2877. case 'guest': {
  2878. typeSelect.selectedIndex = optionOffsets[2];
  2879.  
  2880. break;
  2881. }
  2882.  
  2883. case 'remixer': {
  2884. typeSelect.selectedIndex = optionOffsets[3];
  2885.  
  2886. break;
  2887. }
  2888.  
  2889. default: {
  2890. // We don't know this artist type, default to "main"
  2891. typeSelect.selectedIndex = optionOffsets[1];
  2892. }
  2893. }
  2894.  
  2895. // Next artist input
  2896. inputIdx += 1;
  2897. }
  2898. }
  2899. }
  2900. };
  2901.  
  2902. return f;
  2903. }
  2904.  
  2905. case 'ops_request':
  2906. case 'ops_request_edit':
  2907. case 'dic_request':
  2908. case 'dic_request_edit':
  2909. case 'pth_request':
  2910. case 'pth_request_edit': {
  2911. const f = function (rawData) {
  2912. let artistInputs = document.getElementsByName('artists[]');
  2913. const [albumTitleInput] = document.getElementsByName('title');
  2914. const [yearInput] = document.getElementsByName('year');
  2915. const [labelInput] = document.getElementsByName('recordlabel');
  2916. const [catalogInput] = document.getElementsByName('cataloguenumber');
  2917. const tagsInput = document.querySelector('#tags');
  2918. const data = yadg.prepareRawResponse(rawData);
  2919. let nullArtistCount = 0;
  2920.  
  2921. if (!/groupid=\d+/.test(document.location.search)) {
  2922. if (data.artists === false) {
  2923. for (const element of artistInputs) {
  2924. element.value = '';
  2925. }
  2926. } else {
  2927. let inputIdx = 0;
  2928.  
  2929. yadgUtil.addRemoveArtistBoxes(
  2930. data.effective_artist_count - artistInputs.length,
  2931. );
  2932.  
  2933. artistInputs = document.getElementsByName('artists[]');
  2934.  
  2935. for (let i = 0; i < data.artist_keys.length; i++) {
  2936. const artistKey = data.artist_keys[i];
  2937. const artistTypes = data.artists[artistKey];
  2938. if (artistKey === 'null') {
  2939. nullArtistCount++;
  2940. continue;
  2941. }
  2942.  
  2943. for (const artistType of artistTypes) {
  2944. const artistInput = artistInputs[inputIdx];
  2945. let typeSelect = artistInput.nextSibling;
  2946.  
  2947. while (typeSelect.tagName !== 'SELECT') {
  2948. typeSelect = typeSelect.nextSibling;
  2949. }
  2950.  
  2951. artistInput.value = artistKey;
  2952.  
  2953. const optionOffsets = yadgUtil.getOptionOffsets(typeSelect);
  2954.  
  2955. switch (artistType) {
  2956. case 'main': {
  2957. typeSelect.selectedIndex = optionOffsets[1];
  2958.  
  2959. break;
  2960. }
  2961.  
  2962. case 'guest': {
  2963. typeSelect.selectedIndex = optionOffsets[2];
  2964.  
  2965. break;
  2966. }
  2967.  
  2968. case 'remixer': {
  2969. typeSelect.selectedIndex = optionOffsets[3];
  2970.  
  2971. break;
  2972. }
  2973.  
  2974. default: {
  2975. // We don't know this artist type, default to "main"
  2976. typeSelect.selectedIndex = optionOffsets[1];
  2977. }
  2978. }
  2979.  
  2980. // Next artist input
  2981. inputIdx += 1;
  2982. }
  2983. }
  2984.  
  2985. if (nullArtistCount > 0) {
  2986. yadgUtil.addRemoveArtistBoxes((nullArtistCount *= -1));
  2987. }
  2988. }
  2989.  
  2990. tagsInput.value = data.tags === false ? '' : data.tag_string.toLowerCase();
  2991.  
  2992. yadgUtil.setValueIfSet(
  2993. data.title,
  2994. albumTitleInput,
  2995. data.title !== false,
  2996. );
  2997. }
  2998.  
  2999. yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
  3000. yadgUtil.setValueIfSet(data.label, labelInput, data.label !== false);
  3001. yadgUtil.setValueIfSet(
  3002. data.catalog,
  3003. catalogInput,
  3004. data.catalog !== false,
  3005. );
  3006. };
  3007.  
  3008. return f;
  3009. }
  3010.  
  3011. default:
  3012. // That should actually never happen
  3013. return function () {};
  3014. }
  3015. },
  3016. };
  3017.  
  3018. yadgTemplates = {
  3019. _templates: {},
  3020. _templateUrls: {},
  3021.  
  3022. getTemplate(id, callback) {
  3023. if (id in this._templates) {
  3024. callback(this._templates[id]);
  3025. } else if (id in this._templateUrls) {
  3026. const request = new Requester(
  3027. this._templateUrls[id],
  3028. 'GET',
  3029. template => {
  3030. yadgTemplates.addTemplate(template);
  3031. callback(template);
  3032. },
  3033. null,
  3034. yadgTemplates.errorTemplate,
  3035. );
  3036. request.send();
  3037. } else {
  3038. this.errorTemplate();
  3039. }
  3040. },
  3041.  
  3042. addTemplate(template) {
  3043. this._templates[template.id] = template;
  3044. },
  3045.  
  3046. addTemplateUrl(id, url) {
  3047. this._templateUrls[id] = url;
  3048. },
  3049.  
  3050. errorTemplate() {
  3051. yadg.printError('Could not get template. Please choose another one.', true);
  3052. },
  3053. };
  3054.  
  3055. yadgRenderer = {
  3056. _lastData: null,
  3057. _lastTemplateId: null,
  3058.  
  3059. render(templateId, data, callback, errorCallback) {
  3060. this._lastData = data;
  3061. const newTemplate = this._lastTemplateId !== templateId;
  3062. this._lastTemplateId = templateId;
  3063.  
  3064. yadgTemplates.getTemplate(templateId, template => {
  3065. // The new template might have different dependencies, so initialize Swig with those
  3066. if (newTemplate) {
  3067. yadgSandbox.resetSandbox();
  3068. yadgSandbox.initializeSwig(template.dependencies);
  3069. }
  3070.  
  3071. template.code = template.code.replace(
  3072. 'https://what.cd',
  3073. 'https://' + window.location.hostname,
  3074. );
  3075. yadgSandbox.renderTemplate(template.code, data, callback, errorCallback);
  3076. });
  3077. },
  3078.  
  3079. renderCached(templateId, callback, errorCallback) {
  3080. if (this.hasCached()) {
  3081. this.render(templateId, this._lastData, callback, errorCallback);
  3082. }
  3083. },
  3084.  
  3085. hasCached() {
  3086. return this._lastData !== null;
  3087. },
  3088.  
  3089. clearCached() {
  3090. this._lastData = null;
  3091. },
  3092. };
  3093.  
  3094. yadg = {
  3095. yadgHost: 'https://yadg.cc',
  3096. baseURI: '/api/v2/',
  3097.  
  3098. standardError:
  3099. '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.',
  3100. authenticationError:
  3101. 'Your API token is invalid. Please provide a valid API token or remove the current one.',
  3102. lastStateError: false,
  3103.  
  3104. isBusy: false,
  3105.  
  3106. init() {
  3107. this.scraperSelect = document.querySelector('#yadg_scraper');
  3108. this.formatSelect = document.querySelector('#yadg_format');
  3109. this.input = document.querySelector('#yadg_input');
  3110. this.targetSelect = document.querySelector('#yadg_target');
  3111. this.targetDescriptionSelect = document.querySelector(
  3112. '#yadg_description_target',
  3113. );
  3114. this.responseDiv = document.querySelector('#yadg_response');
  3115. this.button = document.querySelector('#yadg_submit');
  3116. },
  3117.  
  3118. getBaseURL() {
  3119. return this.yadgHost + this.baseURI;
  3120. },
  3121.  
  3122. getScraperList(callback) {
  3123. const url = this.getBaseURL() + 'scrapers/';
  3124.  
  3125. const request = new Requester(url, 'GET', callback);
  3126.  
  3127. request.send();
  3128. },
  3129.  
  3130. getFormatsList(callback) {
  3131. const url = this.getBaseURL() + 'templates/';
  3132.  
  3133. this.getTemplates(url, [], callback);
  3134. },
  3135.  
  3136. getTemplates(url, templates, callback) {
  3137. const request = new Requester(url, 'GET', data => {
  3138. for (let i = 0; i < data.results.length; i++) {
  3139. templates.push(data.results[i]);
  3140. }
  3141.  
  3142. if (data.next === null) {
  3143. callback(templates);
  3144. } else {
  3145. yadg.getTemplates(data.next, templates, callback);
  3146. }
  3147. });
  3148.  
  3149. request.send();
  3150. },
  3151.  
  3152. makeRequest(parameters) {
  3153. if (this.isBusy) {
  3154. return;
  3155. }
  3156.  
  3157. let data;
  3158. if (parameters) {
  3159. data = parameters;
  3160. } else {
  3161. // If beta.musicbrainz.org link strip query params and remove beta
  3162. if (this.input.value.includes('beta.musicbrainz.org')) {
  3163. this.input.value = this.input.value.replace(/beta./, '');
  3164. this.input.value = this.input.value.replace(/\?.*$/, '');
  3165. }
  3166.  
  3167. data = {
  3168. scraper: this.scraperSelect.options[this.scraperSelect.selectedIndex]
  3169. .value,
  3170. input: this.input.value,
  3171. };
  3172. }
  3173.  
  3174. const url = this.getBaseURL() + 'query/';
  3175.  
  3176. if (data.input !== '') {
  3177. const request = new Requester(
  3178. url,
  3179. 'POST',
  3180. result => {
  3181. yadg.getResult(result.url);
  3182. },
  3183. data,
  3184. );
  3185. this.busyStart();
  3186. request.send();
  3187. }
  3188. },
  3189.  
  3190. getResult(resultUrl) {
  3191. const request = new Requester(resultUrl, 'GET', response => {
  3192. if (response.status === 'done') {
  3193. switch (response.data.type) {
  3194. case 'ReleaseResult': {
  3195. const templateId
  3196. = yadg.formatSelect.options[yadg.formatSelect.selectedIndex].value;
  3197. yadgRenderer.render(
  3198. templateId,
  3199. response,
  3200. factory.setDescriptionBoxValue,
  3201. factory.setDescriptionBoxValue,
  3202. );
  3203.  
  3204. if (yadg.lastStateError === true) {
  3205. yadg.responseDiv.innerHTML = '';
  3206. yadg.lastStateError = false;
  3207. }
  3208.  
  3209. const fillFunc = factory.getFormFillFunction();
  3210. fillFunc(response.data);
  3211. break;
  3212. }
  3213.  
  3214. case 'ListResult': {
  3215. const ul = document.createElement('ul');
  3216. ul.id = 'yadg_release_list';
  3217.  
  3218. const releaseList = response.data.items;
  3219. for (const element of releaseList) {
  3220. const {name, info, queryParams} = element;
  3221. const releaseUrl = element.url;
  3222.  
  3223. if (name.match(/ううううううう/)) {
  3224. continue;
  3225. }
  3226. const li = document.createElement('li');
  3227. const a = document.createElement('a');
  3228.  
  3229. a.textContent = name;
  3230. a.params = queryParams;
  3231. a.href = releaseUrl;
  3232.  
  3233. a.addEventListener(
  3234. 'click',
  3235. function (event) {
  3236. event.preventDefault();
  3237. yadg.makeRequest(this.params);
  3238. if (factory.getFetchImageCheckbox().checked) {
  3239. fetchImage(this.href, data => {
  3240. insertImage(data, () => {
  3241. if (
  3242. factory.getAutoRehostCheckbox()
  3243. && factory.getAutoRehostCheckbox().checked
  3244. ) {
  3245. pthImgIt();
  3246. }
  3247. });
  3248. });
  3249. }
  3250. },
  3251. false,
  3252. );
  3253.  
  3254. li.append(a);
  3255. li.append(document.createElement('br'));
  3256. if (info) {
  3257. li.append(document.createTextNode(info));
  3258. }
  3259.  
  3260. ul.append(li);
  3261. }
  3262.  
  3263. if (ul.childNodes.length === 0) {
  3264. yadg.printError('Sorry, there were no matches.');
  3265. } else {
  3266. yadg.responseDiv.innerHTML = '';
  3267. yadg.responseDiv.append(ul);
  3268. yadg.lastStateError = false;
  3269.  
  3270. // We got a ListResult so clear the last ReleaseResult from the render cache
  3271. yadgRenderer.clearCached();
  3272. }
  3273.  
  3274. break;
  3275. }
  3276.  
  3277. case 'NotFoundResult': {
  3278. yadg.printError(
  3279. 'I could not find the release with the given ID. You may want to try again with another one.',
  3280. );
  3281.  
  3282. break;
  3283. }
  3284.  
  3285. default: {
  3286. yadg.printError('Something weird happened. Please try again');
  3287. }
  3288. }
  3289.  
  3290. yadg.busyStop();
  3291. } else if (response.status === 'failed') {
  3292. yadg.failedCallback();
  3293. } else {
  3294. const delay = function () {
  3295. yadg.getResult(response.url);
  3296. };
  3297.  
  3298. window.setTimeout(delay, 1000);
  3299. }
  3300. });
  3301. request.send();
  3302. },
  3303.  
  3304. printError(message, templateError) {
  3305. this.responseDiv.innerHTML = message;
  3306. if (!templateError) {
  3307. this.lastStateError = true;
  3308.  
  3309. // There was a non template related error, so for consistencies sake clear the last ReleaseResult from the
  3310. // render cache
  3311. yadgRenderer.clearCached();
  3312. }
  3313. },
  3314.  
  3315. failedCallback() {
  3316. yadg.printError(yadg.standardError);
  3317. yadg.busyStop();
  3318. },
  3319.  
  3320. failedAuthenticationCallback() {
  3321. yadg.printError(yadg.authenticationError);
  3322. yadg.busyStop();
  3323. },
  3324.  
  3325. busyStart() {
  3326. this.isBusy = true;
  3327. this.button.setAttribute('disabled', true);
  3328. this.button.value = 'Please wait...';
  3329. this.input.setAttribute('disabled', true);
  3330. this.scraperSelect.setAttribute('disabled', true);
  3331. this.formatSelect.setAttribute('disabled', true);
  3332. this.targetSelect.setAttribute('disabled', true);
  3333. },
  3334.  
  3335. busyStop() {
  3336. this.button.removeAttribute('disabled');
  3337. this.button.value = 'Fetch';
  3338. this.input.removeAttribute('disabled');
  3339. this.scraperSelect.removeAttribute('disabled');
  3340. this.formatSelect.removeAttribute('disabled');
  3341. this.targetSelect.removeAttribute('disabled');
  3342. this.isBusy = false;
  3343. },
  3344.  
  3345. // eslint-disable-next-line complexity
  3346. prepareRawResponse(rawData) {
  3347. const result = {};
  3348.  
  3349. result.artists = false;
  3350. result.year = false;
  3351. result.title = false;
  3352. result.label = false;
  3353. result.catalog = false;
  3354. result.genre = false;
  3355. result.style = false;
  3356. result.tags = false;
  3357. result.is_various = false; // eslint-disable-line camelcase
  3358. result.flat_artistString = false; // eslint-disable-line camelcase
  3359. result.format = false;
  3360. result.releaseType = false;
  3361.  
  3362. if (rawData.artists.length > 0) {
  3363. result.artists = {};
  3364.  
  3365. for (let i = 0; i < rawData.artists.length; i++) {
  3366. const artist = rawData.artists[i];
  3367. if (artist.isVarious) {
  3368. result.is_various = true; // eslint-disable-line camelcase
  3369. } else {
  3370. result.artists[artist.name] = artist.types;
  3371. }
  3372. }
  3373. }
  3374.  
  3375. if (rawData.discs.length > 0) {
  3376. for (let k = 0; k < rawData.discs.length; k++) {
  3377. const disc = rawData.discs[k];
  3378. for (let l = 0; l < disc.tracks.length; l++) {
  3379. const track = disc.tracks[l];
  3380. for (let m = 0; m < track.artists.length; m++) {
  3381. const {name} = track.artists[m];
  3382. const type = track.artists[m].types;
  3383.  
  3384. let newTypes = null;
  3385. if (name in result.artists) {
  3386. newTypes = result.artists[name].concat(type);
  3387. // Deduplicate new types array
  3388. for (let i = 0; i < newTypes.length; ++i) {
  3389. for (let j = i + 1; j < newTypes.length; ++j) {
  3390. if (newTypes[i] === newTypes[j]) {
  3391. newTypes.splice(j--, 1);
  3392. }
  3393. }
  3394. }
  3395. } else {
  3396. newTypes = type;
  3397. }
  3398.  
  3399. result.artists[name] = newTypes;
  3400. }
  3401. }
  3402. }
  3403. }
  3404.  
  3405. for (let i = 0; i < rawData.releaseEvents.length; i++) {
  3406. const event = rawData.releaseEvents[i];
  3407. if (event.date) {
  3408. [result.year] = event.date.match(/\d{4}/);
  3409. if (result.year.length === 4) {
  3410. break;
  3411. } else {
  3412. result.year = false;
  3413. }
  3414. }
  3415. }
  3416.  
  3417. if (rawData.title) {
  3418. result.title = rawData.title;
  3419. }
  3420.  
  3421. if (rawData.labelIds.length > 0) {
  3422. const [labelId] = rawData.labelIds;
  3423. if (labelId.label) {
  3424. result.label = labelId.label;
  3425. }
  3426.  
  3427. if (labelId.catalogueNrs.length > 0) {
  3428. [result.catalog] = labelId.catalogueNrs;
  3429. }
  3430. }
  3431.  
  3432. if (rawData.genres.length > 0) {
  3433. result.genre = rawData.genres;
  3434. }
  3435.  
  3436. if (rawData.styles.length > 0) {
  3437. result.style = rawData.styles;
  3438. }
  3439.  
  3440. if (result.genre !== false && result.style !== false) {
  3441. result.tags = rawData.genres.concat(rawData.styles);
  3442. } else if (result.genre !== false) {
  3443. result.tags = rawData.genres;
  3444. } else if (result.style !== false) {
  3445. result.tags = rawData.styles;
  3446. }
  3447.  
  3448. if (result.tags !== false) {
  3449. result.tag_string = ''; // eslint-disable-line camelcase
  3450. result.tag_string_nodots = ''; // eslint-disable-line camelcase
  3451.  
  3452. for (let i = 0; i < result.tags.length; i++) {
  3453. switch (result.tags[i]) {
  3454. case 'Techno (Peak Time / Driving)':
  3455. result.tags[i] = 'Techno';
  3456. break;
  3457. case 'Techno (Raw / Deep / Hypnotic)':
  3458. result.tags[i] = 'Dub Techno';
  3459. break;
  3460. case 'Minimal / Deep Tech':
  3461. result.tags[i] = 'Tech House';
  3462. break;
  3463.  
  3464. default:
  3465. break;
  3466. }
  3467.  
  3468. result.tag_string += result.tags[i].replace(/\s+/g, '.').replace(/\bn\b|&/, 'and'); // eslint-disable-line camelcase
  3469. result.tag_string_nodots += result.tags[i].replace(/\s+/g, ' '); // eslint-disable-line camelcase
  3470. if (i !== result.tags.length - 1) {
  3471. result.tag_string += ', '; // eslint-disable-line camelcase
  3472. result.tag_string_nodots += ', '; // eslint-disable-line camelcase
  3473. }
  3474. }
  3475. }
  3476.  
  3477. if (result.artists !== false) {
  3478. // Count the artists
  3479. result.artists_length = 0; // eslint-disable-line camelcase
  3480. result.artist_keys = []; // eslint-disable-line camelcase
  3481. result.effective_artist_count = 0; // eslint-disable-line camelcase
  3482.  
  3483. for (const i in result.artists) {
  3484. if (Object.prototype.hasOwnProperty.call(result.artists, i)) {
  3485. result.artists_length++;
  3486. result.artist_keys.push(i);
  3487. result.effective_artist_count += result.artists[i].length; // eslint-disable-line camelcase
  3488. }
  3489. }
  3490. }
  3491.  
  3492. if (result.artists_length === 0) {
  3493. result.artists = false;
  3494. } else {
  3495. // Create a flat string of all the main artists
  3496. let artistString = '';
  3497.  
  3498. for (let i = 0; i < result.artists_length; i++) {
  3499. if (result.artists[result.artist_keys[i]].includes('main')) {
  3500. if (artistString !== '' && i < result.artists_length - 2) {
  3501. artistString += ', ';
  3502. } else if (artistString !== '' && i < result.artists_length - 1) {
  3503. artistString += ' & ';
  3504. }
  3505.  
  3506. artistString += result.artist_keys[i];
  3507. }
  3508. }
  3509.  
  3510. result.flat_artistString = artistString; // eslint-disable-line camelcase
  3511. }
  3512.  
  3513. if (rawData.format) {
  3514. const format = rawData.format.toLowerCase();
  3515. if (format.includes('vinyl')) {
  3516. result.format = 'Vinyl';
  3517. } else if (format.includes('cd')) {
  3518. result.format = 'CD';
  3519. } else if (format.includes('dvd') || format.includes('dvd-video')) {
  3520. result.format = 'DVD';
  3521. } else if (format.includes('sacd')) {
  3522. result.format = 'SACD';
  3523. } else if (format.includes('cassettes')) {
  3524. result.format = 'Cassette';
  3525. } else if (format.includes('Blu-ray')) {
  3526. result.format = 'Blu-Ray';
  3527. } else if (format.includes('file')) {
  3528. result.format = 'WEB';
  3529. }
  3530. }
  3531.  
  3532. if (rawData.format) {
  3533. const format = rawData.format.toLowerCase();
  3534. if (format.includes('album') || rawData.styles.includes('Album')) {
  3535. result.releaseType = 1;
  3536. } else if (format.includes('soundtrack') || rawData.styles.includes('Soundtrack')) {
  3537. result.releaseType = 3;
  3538. } else if (format.includes('ep') || rawData.styles.includes('EP')) {
  3539. result.releaseType = 5;
  3540. } else if (format.includes('anthology') || rawData.styles.includes('Anthology')) {
  3541. result.releaseType = 6;
  3542. } else if (format.includes('compilation') || rawData.styles.includes('Compilation')) {
  3543. result.releaseType = 7;
  3544. } else if (format.includes('single') || rawData.styles.includes('Single')) {
  3545. result.releaseType = 9;
  3546. }
  3547. }
  3548.  
  3549. return result;
  3550. },
  3551. };
  3552.  
  3553. yadgSandbox.init(() => {
  3554. if (factory.init()) {
  3555. // Returns true if we run on a valid location
  3556. yadg.init();
  3557. }
  3558. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址