You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 line
15 KiB

  1. // ==UserScript==
  2. // @name SM :: Import JSON to Upload Form
  3. // @version 0.0.1
  4. // @description Adds buttons to attach and parse a .json file from RED or OPS to fill in the upload form.
  5. // @author herbert (original: newstarshipsmell)
  6. // @include /https://sugoimusic\.me/upload\.php/
  7. // @grant none
  8. // ==/UserScript==
  9. (function() {
  10. 'use strict';
  11. var sourceWebsites = ['RED', 'OPS'];
  12. var sourceWebsiteDomains = ['redacted.ch', 'orpheus.network'];
  13. var sourceWebsite, sourceWebsiteIndex;
  14. var JSONReleaseTypes = {
  15. 'RED': {
  16. '1': 'Album',
  17. '3': 'Soundtrack',
  18. '5': 'EP',
  19. '6': 'Anthology',
  20. '7': 'Compilation',
  21. '9': 'Single',
  22. '11': 'Live album',
  23. '13': 'Remix',
  24. '14': 'Bootleg',
  25. '15': 'Interview',
  26. '16': 'Mixtape',
  27. '17': 'Demo',
  28. '18': 'Concert Recording',
  29. '19': 'DJ Mix',
  30. '21': 'Unknown'
  31. },
  32. 'OPS': {
  33. '1': 'Album',
  34. '3': 'Soundtrack',
  35. '5': 'EP',
  36. '6': 'Anthology',
  37. '7': 'Compilation',
  38. '9': 'Single',
  39. '11': 'Live album',
  40. '13': 'Remix',
  41. '14': 'Bootleg',
  42. '15': 'Interview',
  43. '16': 'Mixtape',
  44. '17': 'DJ Mix',
  45. '18': 'Concert recording',
  46. '21': 'Unknown'
  47. }
  48. };
  49. var ChooseTypeDropdown = document.getElementById('categories');
  50. var ChooseJSONTR = document.createElement('tr');
  51. var ChooseJSONTD = document.createElement('td');
  52. ChooseJSONTD.classList.add('label');
  53. ChooseJSONTD.textContent = 'JSON file:';
  54. var ChooseJSONBtnTD = document.createElement('td');
  55. var ChooseJSONBtn = document.createElement('input');
  56. ChooseJSONBtn.id = 'json';
  57. ChooseJSONBtn.type = 'file';
  58. ChooseJSONBtn.name = 'json_input';
  59. ChooseJSONBtn.accept = '.application/json,.json';
  60. var ChooseJSONParseBtn = document.createElement('input');
  61. ChooseJSONParseBtn.id = 'json_parse';
  62. ChooseJSONParseBtn.type = 'button';
  63. ChooseJSONParseBtn.name = 'json_parse';
  64. ChooseJSONParseBtn.value = 'Parse JSON';
  65. ChooseJSONTR.appendChild(ChooseJSONTD);
  66. ChooseJSONTR.appendChild(ChooseJSONBtnTD);
  67. ChooseJSONBtnTD.appendChild(ChooseJSONBtn);
  68. ChooseJSONBtnTD.appendChild(document.createTextNode(' | '));
  69. ChooseJSONBtnTD.appendChild(ChooseJSONParseBtn);
  70. ChooseTypeDropdown.parentNode.parentNode.parentNode.insertBefore(ChooseJSONTR, ChooseTypeDropdown.parentNode.parentNode);
  71. ChooseJSONParseBtn.addEventListener('click', function (evt) {
  72. var file = document.getElementById('json').files[0];
  73. if (file) {
  74. sourceWebsiteIndex = /.+ \[redacted\.ch\]\.json/.test(file.name) ? 0 : (/.+ \[orpheus\.network\]\.json/.test(file.name) ? 1 : -1);
  75. sourceWebsite = sourceWebsiteIndex > -1 && sourceWebsiteIndex < sourceWebsites.length ? sourceWebsites[sourceWebsiteIndex] : "N/A";
  76. if (sourceWebsite == 'N/A') {
  77. alert('The userscript failed to parse a supported website from the json filename! Aborting...')
  78. return;
  79. } else {
  80. var reader = new FileReader();
  81. reader.readAsText(file, "UTF-8");
  82. reader.onload = function (evt) {
  83. var releaseJSON = JSON.parse(evt.target.result);
  84. var categories = ['Music', 'Applications', 'E-Books', 'Audiobooks', 'E-Learning Videos', 'Comedy', 'Comics'];
  85. var category = document.getElementById('categories');
  86. var categoryJSON = parseInt(releaseJSON.response.group.categoryId);
  87. var categoryNameJSON = releaseJSON.response.group.categoryName;
  88. var categoryIndex = categories.indexOf(categoryNameJSON);
  89. if (categoryIndex > -1) {
  90. if (categoryIndex != 0) {
  91. alert('Currently only Music category torrents are supported. Aborting...');
  92. return;
  93. } else {
  94. category.selectedIndex = categories.indexOf(categoryNameJSON);
  95. }
  96. } else {
  97. alert('The category name indicated in the JSON (' + categoryNameJSON + ') is not one of the available category types! Aborting...');
  98. return;
  99. }
  100. switch(categoryIndex) {
  101. case 0:
  102. var artists = [];
  103. var artistRoles = [
  104. {'name': 'artists', 'index': 0},
  105. {'name': 'with', 'index': 1},
  106. {'name': 'composers', 'index': 2},
  107. {'name': 'conductor', 'index': 3},
  108. {'name': 'dj', 'index': 4},
  109. {'name': 'remixedBy', 'index': 5},
  110. {'name': 'producer', 'index': 6},
  111. ];
  112. var artistsJSON = releaseJSON.response.group.musicInfo;
  113. for (var i = 0, len = artistRoles.length; i < len; i++) {
  114. if (artistsJSON[artistRoles[i].name].length == 0) continue;
  115. for (var j = 0, lenj = artistsJSON[artistRoles[i].name].length; j < lenj; j++) {
  116. artists.push({'name': artistsJSON[artistRoles[i].name][j].name, 'index': artistRoles[i].index});
  117. }
  118. }
  119. if (artists.length > 0) {
  120. var artistInputs = [];
  121. artistInputs.length = artists.length;
  122. for (i = 0, len = artists.length; i < len; i++) {
  123. if (i > 0) window.eval('AddArtistField();');
  124. artistInputs[i] = document.getElementById('idols_' + i );
  125. artistInputs[i].value = artists[i].name;
  126. // SM does not support roles
  127. //var roles = document.querySelectorAll('td#artistfields > #importance');
  128. //roles[i].selectedIndex = artists[i].index;
  129. }
  130. } else {
  131. alert('No artists are included in the JSON!');
  132. }
  133. var albumTitle = document.getElementById('title');
  134. var albumTitleJSON = releaseJSON.response.group.name;
  135. if (albumTitleJSON != '') {
  136. albumTitle.value = albumTitleJSON;
  137. } else {
  138. alert('No album title is included in the JSON!');
  139. }
  140. var initialYear = document.getElementById('year');
  141. var initialYearJSON = releaseJSON.response.group.year;
  142. if (initialYearJSON != '') {
  143. initialYear.value = initialYearJSON;
  144. } else {
  145. alert('No initial year is included in the JSON!');
  146. }
  147. var releaseType = document.getElementById('categories'); //On SM 'categories' == 'releaseType'
  148. var releaseTypes = [];
  149. for (i = 0, len = releaseType.options.length; i < len; i++) {
  150. releaseTypes.push(releaseType.options[i].textContent.toLowerCase());
  151. }
  152. var releaseTypeIndexJSON = parseInt(releaseJSON.response.group.releaseType);
  153. var releaseTypeNameJSON = JSONReleaseTypes[sourceWebsite][releaseTypeIndexJSON];
  154. var releaseTypeIndex = releaseTypes.indexOf(releaseTypeNameJSON.toLowerCase());
  155. if (releaseTypeIndex > -1) {
  156. releaseType.selectedIndex = releaseTypeIndex;
  157. } else {
  158. alert('The release type indicated in the JSON (' + releaseTypeNameJSON + ' [' + releaseTypeIndexJSON + ']) ' +
  159. 'is not one of the available release types!\n\nManually select the appropriate release type.');
  160. }
  161. var editionYear = document.getElementById('remasteryear');
  162. var editionTitle = document.getElementById('remastertitle');
  163. //var editionLabel = document.getElementById('remaster_record_label');
  164. //var editionCatNo = document.getElementById('remaster_catalogue_number');
  165. var edition = releaseJSON.response.torrent.remastered;
  166. if (edition) {
  167. var editionYearJSON = releaseJSON.response.torrent.remasterYear;
  168. var editionTitleJSON = releaseJSON.response.torrent.remasterTitle;
  169. //var editionLabelJSON = releaseJSON.response.torrent.remasterRecordLabel;
  170. //var editionCatNoJSON = releaseJSON.response.torrent.remasterCatalogueNumber;
  171. document.getElementById('remaster').click();
  172. } else {
  173. editionYearJSON = initialYearJSON
  174. editionTitleJSON = '';
  175. //editionLabelJSON = releaseJSON.response.group.recordLabel;
  176. //editionCatNoJSON = releaseJSON.response.group.catalogueNumber;
  177. }
  178. if (editionYearJSON == '') {
  179. alert('No edition year is included in the JSON!');
  180. }
  181. editionYear.value = editionYearJSON;
  182. editionTitle.value = editionTitleJSON;
  183. //editionLabel.value = editionLabelJSON;
  184. //editionCatNo.value = editionCatNoJSON;
  185. //Scene does not exist on SM
  186. //var scene = document.getElementById('scene');
  187. //var sceneJSON = releaseJSON.response.torrent.scene;
  188. //if (sceneJSON) scene.checked = true;
  189. var format = document.getElementsByName('audioformat')[0];
  190. var formats = [];
  191. for (i = 0, len = format.options.length; i < len; i++) {
  192. formats.push(format.options[i].textContent.toLowerCase());
  193. }
  194. var formatJSON = releaseJSON.response.torrent.format;
  195. var formatIndex = formats.indexOf(formatJSON.toLowerCase());
  196. if (formatIndex > -1) {
  197. format.selectedIndex = formatIndex;
  198. } else {
  199. alert('The format indicated in the JSON (' + formatJSON + ') ' +
  200. 'is not one of the available formats!\n\nManually select the appropriate formats.');
  201. }
  202. var bitrate = document.getElementsByName('bitrate')[0];
  203. var bitrates = [];
  204. for (i = 0, len = bitrate.options.length; i < len; i++) {
  205. bitrates.push(bitrate.options[i].textContent.toLowerCase());
  206. }
  207. var otherBitrate = document.getElementById('other_bitrate');
  208. var otherBitrateVBR = document.getElementById('vbr');
  209. var bitrateJSON = releaseJSON.response.torrent.encoding;
  210. var bitrateIndex = bitrates.indexOf(bitrateJSON.toLowerCase());
  211. if (bitrateIndex > -1) {
  212. bitrate.selectedIndex = bitrateIndex;
  213. } else {
  214. bitrate.selectedIndex = bitrates.indexOf('other');
  215. document.getElementById('other_bitrate_span').classList.remove('hidden');
  216. otherBitrate.value = bitrateJSON.replace(/ \(VBR\)$/i, '');
  217. otherBitrateVBR.checked = /.+ \(VBR\)$/i.test(bitrateJSON);
  218. }
  219. var media = document.getElementsByName('media')[0];
  220. var medias = [];
  221. for (i = 0, len = media.options.length; i < len; i++) {
  222. medias.push(media.options[i].textContent.toLowerCase());
  223. }
  224. var mediaJSON = releaseJSON.response.torrent.media;
  225. var mediaIndex = medias.indexOf(mediaJSON.toLowerCase());
  226. if (mediaIndex > -1) {
  227. media.selectedIndex = mediaIndex;
  228. } else {
  229. alert('The media indicated in the JSON (' + mediaJSON + ') ' +
  230. 'is not one of the available media!\n\nManually select the appropriate media.');
  231. }
  232. /* SM does not support logs yet
  233. if (formats[formatIndex] == 'flac' && bitrates[bitrateIndex] == 'lossless' && medias[mediaIndex] == 'cd') {
  234. var hasLogJSON = releaseJSON.response.torrent.hasLog;
  235. var logs = document.getElementById('upload_logs');
  236. if (hasLogJSON) logs.classList.remove('hidden');
  237. }*/
  238. var tags = document.getElementById('tags');
  239. var tagsJSON = releaseJSON.response.group.tags;
  240. var tagList = '';
  241. if (tagsJSON.length > 0) {
  242. for (i = 0, len = tagsJSON.length; i < len; i++) {
  243. tagList += (i > 0 ? ', ' : '') + tagsJSON[i];
  244. }
  245. }
  246. tags.value = tagList;
  247. var image = document.getElementById('image');
  248. var imageJSON = releaseJSON.response.group.wikiImage;
  249. image.value = imageJSON;
  250. var albumDesc = document.getElementById('album_desc');
  251. var albumDescJSON = releaseJSON.response.group.wikiBody;
  252. if (albumDescJSON != '') {
  253. albumDescJSON = albumDescJSON.replace(/<br \/>/g, '');
  254. albumDescJSON = albumDescJSON.replace(/&amp;/g, '&');
  255. albumDescJSON = albumDescJSON.replace(/&lt;/g, '<');
  256. albumDescJSON = albumDescJSON.replace(/&gt;/g, '>');
  257. albumDescJSON = albumDescJSON.replace(/&quot;/g, '"');
  258. albumDescJSON = albumDescJSON.replace(/&apos;/g, '\'');
  259. albumDescJSON = albumDescJSON.replace(/&#39;/g, '\'');
  260. albumDescJSON = albumDescJSON.replace(/<a href="artist\.php\?artistname=.+?">(.+?)<\/a>/g, '[artist]$1[/artist]');
  261. albumDescJSON = albumDescJSON.replace(/<a href="user\.php\?action=search&amp;search=.+?">(.+?)<\/a>/g, '[user]$1[/user]');
  262. albumDescJSON = albumDescJSON.replace(/<a .+?>(https?:\/\/.+?)<\/a>/g, '$1');
  263. albumDescJSON = albumDescJSON.replace(/<a .*?href="(https?:\/\/.+?)".*?>(.+?)<\/a>/g, '[url=$1]$2[/url]');
  264. albumDescJSON = albumDescJSON.replace(/<span class="size(\d+)">(.+?)<\/span>/g, '[size=$1]$2[/size]');
  265. albumDescJSON = albumDescJSON.replace(/<span style="font-style: italic;">(.+?)<\/span>/g, '[i]$1[/i]');
  266. albumDescJSON = albumDescJSON.replace(/<span style="text-decoration: underline;">(.+?)<\/span>/g, '[u]$1[/u]');
  267. albumDescJSON = albumDescJSON.replace(/<span style="text-decoration: line-through;">(.+?)<\/span>/g, '[s]$1[/s]');
  268. albumDescJSON = albumDescJSON.replace(/<span style="color: (.+?);">(.+?)<\/span>/g, '[color=$1]$2[/color]');
  269. albumDescJSON = albumDescJSON.replace(/<div style="text-align: (.+?);">(.+?)<\/div>/g, '[align=$1]$2[/align]');
  270. albumDescJSON = albumDescJSON.replace(
  271. /<img class="scale_image" onclick="lightbox.init\(this, \$\(this\)\.width\(\)\);" alt="(.+?)" src=".+?">/g,
  272. '[img]$1[/img]');
  273. albumDescJSON = albumDescJSON.replace(
  274. /<a href="#" onclick="QuoteJump\(event, '(\d+)'\); return false;"><strong class="quoteheader">(.+?)<\/strong> wrote: <\/a><blockquote>(.+?)<\/blockquote>/g,
  275. '[quote=$2|$1]$3[/quote]');
  276. albumDescJSON = albumDescJSON.replace(/<strong class="quoteheader">(.+?)<\/strong> wrote: <blockquote>(.+?)<\/blockquote>/g,
  277. '[quote=$1]$2[/quote]');
  278. albumDescJSON = albumDescJSON.replace(/<blockquote>(.+?)<\/blockquote>/g, '[quote]$1[/quote]');
  279. albumDescJSON = albumDescJSON.replace(/<strong>(.+?)<\/strong>: <a href="javascript:void\(0\);" onclick="BBCode\.spoiler\(this\);">Show<\/a><blockquote class="hidden spoiler">(.+?)<\/blockquote>/g,
  280. '[hide=$1]$2[/hide]');
  281. albumDescJSON = albumDescJSON.replace(/<strong>Hidden text<\/strong>: <a href="javascript:void\(0\);" onclick="BBCode\.spoiler\(this\);">Show<\/a><blockquote class="hidden spoiler">(.+?)<\/blockquote>/g,
  282. '[hide]$1[/hide]');
  283. albumDescJSON = albumDescJSON.replace(/<strong class="important_text">(.+?)<\/strong>/g, '[important]$1[/important]');
  284. albumDescJSON = albumDescJSON.replace(/<(pre|code)>(.+?)<\/\1>/g, '[$1]$2[/$1]');
  285. albumDescJSON = albumDescJSON.replace(/<(\/)?strong>/g, '[$1b]');
  286. albumDesc.value = albumDescJSON;
  287. document.querySelector('input.button_preview_0').click();
  288. } else {
  289. alert('No album description is included in the JSON!');
  290. }
  291. var relDesc = document.getElementById('release_desc');
  292. var relDescJSON = releaseJSON.response.torrent.description;
  293. var groupIDJSON = releaseJSON.response.group.id;
  294. var torrentIDJSON = releaseJSON.response.torrent.id;
  295. relDescJSON += (relDescJSON ? '\n\n' : '') + 'Cross-posted from ' + sourceWebsite + ': https://';
  296. relDescJSON += sourceWebsiteDomains[sourceWebsiteIndex] + '/torrents.php?id=' + groupIDJSON + '&torrentid=' + torrentIDJSON;
  297. sourceWebsiteDomains = ['redacted.ch', 'orpheus.network'];
  298. relDesc.value = relDescJSON;
  299. document.querySelector('input.button_preview_1').click();
  300. break;
  301. case 1:
  302. break;
  303. case 2:
  304. break;
  305. case 3:
  306. break;
  307. case 4:
  308. break;
  309. case 5:
  310. break;
  311. case 6:
  312. break;
  313. default:
  314. }
  315. }
  316. reader.onerror = function (evt) {
  317. alert('There was an error reading the file.');
  318. }
  319. }
  320. } else {
  321. alert('No JSON file has been chosen!');
  322. }
  323. });
  324. })();