// ==UserScript== // @name Redacted :: Import JSON to Upload Form // @namespace https://greasyfork.org/en/scripts/393534-redacted-import-json-to-upload-form // @version 2.0.0 // @description Adds buttons to attach and parse a .json file from NWCD, OPS, or Crossfade to fill in the upload form. // @author newstarshipsmell & rewritten by anon28410 for Crossfade // @include /https://redacted\.sh/upload\.php/ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAOTSURBVFhH7ZdbSJNhHMY/TTfCusjMtCiaMjFdXmQwL2wX4YgowguDEsGEKIjCSJC8yc4SeeguKI2oC7uolZrK1kkJs1Ir0dKmlkWGh06C0Zmn//9l73pbn+sru3TwY9vzPv/nfeb3bh9qADSDjxgil6gk7hOvCR5mxog24gSRTURNTED7E2JvAwVSCBchNzPKZcKut7HESIGThAg0m81YsyYLpaWVaGpqx8DAKMbHv+P9+2/o7x/B9et3UVJyAk5npvDKOaKKfJoewQrMJvgTICwsDNnZ2/HkySu8ffvFEH19w9iypUAt0kjMoTVNJViBWgIxMbGoqWnG6OhHQXt7HwoKDiM9fS1iYxeIciaTGfPmRSM1dSW2bSvEjRsdfr/Hcw+LFi2RJTxEOOmaZLICfMhog4Vobe3B0NAEentHkJOzQ2zIa3/C4cgUZXmWny2WOLl2ljRNolfASSA83ASXqxmDg+NoaelFQsJSGWCYqKhof4bH04GIiAi5tok0jdEr4CawdWsRvN431P4ZrNZkOfjXREbOxbVrD0VWYWGZ1G/Se40JLLCaoOs5nzZ+ju7uEWRkbJRD/8yyZXZ0dQ2js3MIixf7L0UO5f9WoJpAbu4edNwfQmVlA0JCQuTAlDh4sEpk7io4JrU6ev9LgRm8EBoaStftHh2+F0hLWyfNUyYpKVVkut3d9K0xSX2mWiCVRavVhqbmp6ipe2j4xBvlzNkmkW2zOaS2Wi2Qz6LTuRnuq17k51dI038jL2+fyM7K2i21Q2oBcf237yxHXX0PHKtypEkXE1FC9BMDvtes6XklK1asF9mFRSel1qAW6GSx5KgLFy91ISFxuTTpcoR4E8BeQs8rsViSRHZFRb3UvGoBcWu12zeQMVEaJoU/eWAB1vS8Kpydlu7/an9QC3zziYb41wKBqAWEYLEko/jAedQ3PEZb20u6zb7D2Ngn/4BE7xIUE4E+uueLec5pvfMCpRWXEB9v86+rBT6yULz/AqrPP0CjuzdoAXkI+QAGO4RqgbuUx7nl5Q1y/dNvf4FTVXcMFTCKXgHOl+vTBaYLTBeYLqAW6GPB6C+hUfQKKL+Eg2qB0yzGxSVj775q1F55NFkBB3GMaCGGic8++DVrvMYe4VcLtNweRFmZC/HWFJl1Ti1gJjp8C5Nxi71GYK8ypwf/dz1LeAMGjxPtxFdCHeBAm+oNBnt9M2oGZ3L28Z9eaD8A1I4FiHzaEHoAAAAASUVORK5CYII= // @grant none // ==/UserScript== (function () { 'use strict'; var sourceWebsites = ['NWCD', 'OPS', 'Crossfade']; var sourceWebsiteDomains = ['notwhat.cd', 'orpheus.network', 'crossfade.local']; var sourceWebsite, sourceWebsiteIndex; var JSONReleaseTypes = { 'NWCD': { '1': 'Album', '3': 'Soundtrack', '5': 'EP', '6': 'Anthology', '7': 'Compilation', '9': 'Single', '11': 'Live album', '13': 'Remix', '14': 'Bootleg', '15': 'Interview', '16': 'Mixtape', '17': 'Sampler', '21': 'Unknown', '22': 'Demo', '23': 'DJ Mix', '24': 'Concert Recording' }, 'OPS': { '1': 'Album', '3': 'Soundtrack', '5': 'EP', '6': 'Anthology', '7': 'Compilation', '9': 'Single', '11': 'Live album', '13': 'Remix', '14': 'Bootleg', '15': 'Interview', '16': 'Mixtape', '17': 'DJ Mix', '18': 'Concert recording', '21': 'Unknown' }, 'Crossfade': { '1': 'Album', '3': 'Soundtrack', '5': 'EP', '6': 'Anthology', '7': 'Compilation', '9': 'Single', '11': 'Live album', '13': 'Remix', '14': 'Bootleg', '15': 'Interview', '16': 'Mixtape', '17': 'DJ Mix', '18': 'Concert recording', '21': 'Unknown' } }; var addFormat = /(\?|&)groupid=/.test(location.href) ? true : false; var uploadRequest = /(\?|&)requestid=/.test(location.href) ? true : false; var ChooseTypeDropdown = document.getElementById('categories'); var ChooseJSONTR = document.createElement('tr'); var ChooseJSONTD = document.createElement('td'); ChooseJSONTD.classList.add('label'); ChooseJSONTD.textContent = 'JSON file:'; var ChooseJSONBtnTD = document.createElement('td'); var ChooseJSONBtn = document.createElement('input'); ChooseJSONBtn.id = 'json'; ChooseJSONBtn.type = 'file'; ChooseJSONBtn.name = 'json_input'; ChooseJSONBtn.accept = '.application/json,.json'; var ChooseJSONPasteBtn = document.createElement('button'); ChooseJSONPasteBtn.textContent = 'Paste JSON'; ChooseJSONPasteBtn.type = 'button'; ChooseJSONPasteBtn.style.marginLeft = '10px'; ChooseJSONPasteBtn.style.padding = '2px 8px'; ChooseJSONPasteBtn.style.cursor = 'pointer'; ChooseJSONTR.appendChild(ChooseJSONTD); ChooseJSONTR.appendChild(ChooseJSONBtnTD); ChooseJSONBtnTD.appendChild(ChooseJSONBtn); ChooseJSONBtnTD.appendChild(ChooseJSONPasteBtn); ChooseTypeDropdown.parentNode.parentNode.parentNode.insertBefore(ChooseJSONTR, ChooseTypeDropdown.parentNode.parentNode); function processJSON(releaseJSON, filename) { // Determine source if (releaseJSON.response && releaseJSON.response.source === 'Crossfade') { sourceWebsite = 'Crossfade'; sourceWebsiteIndex = 2; } else { sourceWebsiteIndex = /NWCD .+\.json/.test(filename) ? 0 : (/.+(\.opsnet| \[orpheus\.network\])\.json/.test(filename) ? 1 : -1); sourceWebsite = sourceWebsiteIndex > -1 && sourceWebsiteIndex < sourceWebsites.length ? sourceWebsites[sourceWebsiteIndex] : "N/A"; } if (sourceWebsite == 'N/A') { alert('The userscript failed to parse a supported website from the json filename or content! Aborting...') return; } var categories = ['Music', 'Applications', 'E-Books', 'Audiobooks', 'E-Learning Videos', 'Comedy', 'Comics']; var category = document.getElementById('categories'); var categoryJSON = parseInt(releaseJSON.response.group.categoryId); var categoryNameJSON = releaseJSON.response.group.categoryName; var categoryIndex = categories.indexOf(categoryNameJSON); if (categoryIndex > -1) { if (categoryIndex != 0) { alert('Currently only Music category torrents are supported. Aborting...'); return; } else { category.selectedIndex = categories.indexOf(categoryNameJSON); // Trigger change event to load fields var event = new Event('change'); category.dispatchEvent(event); } } else { alert('The category name indicated in the JSON (' + categoryNameJSON + ') is not one of the available category types! Aborting...'); return; } // Wait a bit for fields to load if category changed setTimeout(function () { switch (categoryIndex) { case 0: if (!addFormat) { if (!uploadRequest) { var artists = []; var artistRoles = [ { 'name': 'artists', 'index': 0 }, { 'name': 'with', 'index': 1 }, { 'name': 'composers', 'index': 2 }, { 'name': 'conductor', 'index': 3 }, { 'name': 'dj', 'index': 4 }, { 'name': 'remixedBy', 'index': 5 }, { 'name': 'producer', 'index': 6 }, ]; var artistsJSON = releaseJSON.response.group.musicInfo; for (var i = 0, len = artistRoles.length; i < len; i++) { if (!artistsJSON[artistRoles[i].name] || artistsJSON[artistRoles[i].name].length == 0) continue; for (var j = 0, lenj = artistsJSON[artistRoles[i].name].length; j < lenj; j++) { artists.push({ 'name': artistsJSON[artistRoles[i].name][j].name, 'index': artistRoles[i].index }); } } if (artists.length > 0) { var artistInputs = []; artistInputs.length = artists.length; for (i = 0, len = artists.length; i < len; i++) { if (i > 0) { // Check if AddArtistField exists (it should on upload page) if (typeof window.AddArtistField === 'function') { window.AddArtistField(); } else { // Fallback for some versions of the site var addLink = document.querySelector('a[onclick="AddArtistField()"]'); if (addLink) addLink.click(); } } artistInputs[i] = document.getElementById('artist' + (i > 0 ? '_' + i : '')); if (artistInputs[i]) { artistInputs[i].value = artists[i].name; var roles = document.querySelectorAll('select#importance'); // Changed selector to match typical RED form if (roles[i]) roles[i].selectedIndex = artists[i].index; } } } else { // alert('No artists are included in the JSON!'); } } var albumTitle = document.getElementById('title'); var albumTitleJSON = releaseJSON.response.group.name; if (albumTitleJSON != '') { albumTitle.value = albumTitleJSON; } else { alert('No album title is included in the JSON!'); } var initialYear = document.getElementById('year'); var initialYearJSON = releaseJSON.response.group.year; if (initialYearJSON != '') { initialYear.value = initialYearJSON; } else { alert('No initial year is included in the JSON!'); } var releaseType = document.getElementById('releasetype'); var releaseTypes = []; for (i = 0, len = releaseType.options.length; i < len; i++) { releaseTypes.push(releaseType.options[i].textContent.toLowerCase()); } var releaseTypeIndexJSON = parseInt(releaseJSON.response.group.releaseType || 1); // Default to Album if missing var releaseTypeNameJSON = JSONReleaseTypes[sourceWebsite][releaseTypeIndexJSON] || 'Album'; var releaseTypeIndex = releaseTypes.indexOf(releaseTypeNameJSON.toLowerCase()); if (releaseTypeIndex > -1) { releaseType.selectedIndex = releaseTypeIndex; } } var editionYear = document.getElementById('remaster_year'); var editionTitle = document.getElementById('remaster_title'); var editionLabel = document.getElementById('remaster_record_label'); var editionCatNo = document.getElementById('remaster_catalogue_number'); var edition = releaseJSON.response.torrent.remastered; if (edition) { var editionYearJSON = releaseJSON.response.torrent.remasterYear; var editionTitleJSON = releaseJSON.response.torrent.remasterTitle; var editionLabelJSON = releaseJSON.response.torrent.remasterRecordLabel; var editionCatNoJSON = releaseJSON.response.torrent.remasterCatalogueNumber; } else { editionYearJSON = initialYearJSON ? initialYearJSON : releaseJSON.response.group.year; editionTitleJSON = ''; editionLabelJSON = releaseJSON.response.group.recordLabel; editionCatNoJSON = releaseJSON.response.group.catalogueNumber; } if (editionYear) editionYear.value = editionYearJSON || ''; if (editionTitle) editionTitle.value = editionTitleJSON || ''; if (editionLabel) editionLabel.value = editionLabelJSON || ''; if (editionCatNo) editionCatNo.value = editionCatNoJSON || ''; var scene = document.getElementById('scene'); var sceneJSON = releaseJSON.response.torrent.scene; if (sceneJSON && scene) scene.checked = true; var format = document.getElementById('format'); var formats = []; for (i = 0, len = format.options.length; i < len; i++) { formats.push(format.options[i].textContent.toLowerCase()); } var formatJSON = releaseJSON.response.torrent.format; var formatIndex = formats.indexOf(formatJSON.toLowerCase()); if (formatIndex > -1) { format.selectedIndex = formatIndex; } var bitrate = document.getElementById('bitrate'); var bitrates = []; for (i = 0, len = bitrate.options.length; i < len; i++) { bitrates.push(bitrate.options[i].textContent.toLowerCase()); } var otherBitrate = document.getElementById('other_bitrate'); var otherBitrateVBR = document.getElementById('vbr'); var bitrateJSON = releaseJSON.response.torrent.encoding; var bitrateIndex = bitrates.indexOf(bitrateJSON.toLowerCase()); if (bitrateIndex > -1) { bitrate.selectedIndex = bitrateIndex; } else { var otherIndex = bitrates.indexOf('other'); if (otherIndex > -1) { bitrate.selectedIndex = otherIndex; var span = document.getElementById('other_bitrate_span'); if (span) span.classList.remove('hidden'); if (otherBitrate) otherBitrate.value = bitrateJSON.replace(/ \(VBR\)$/i, ''); if (otherBitrateVBR) otherBitrateVBR.checked = /.+ \(VBR\)$/i.test(bitrateJSON); } } var media = document.getElementById('media'); var medias = []; for (i = 0, len = media.options.length; i < len; i++) { medias.push(media.options[i].textContent.toLowerCase()); } var mediaJSON = releaseJSON.response.torrent.media; var mediaIndex = medias.indexOf(mediaJSON.toLowerCase()); if (mediaIndex > -1) { media.selectedIndex = mediaIndex; } if (!addFormat) { var tags = document.getElementById('tags'); var tagsJSON = releaseJSON.response.group.tags; var tagList = ''; if (tagsJSON && tagsJSON.length > 0) { for (i = 0, len = tagsJSON.length; i < len; i++) { tagList += (i > 0 ? ', ' : '') + tagsJSON[i]; } } if (tags) tags.value = tagList; var image = document.getElementById('image'); var imageJSON = releaseJSON.response.group.wikiImage; if (image && imageJSON) image.value = imageJSON; var albumDesc = document.getElementById('album_desc'); var albumDescJSON = releaseJSON.response.group.wikiBBcode ? releaseJSON.response.group.wikiBBcode : releaseJSON.response.group.wikiBody; if (albumDescJSON != '') { if (!releaseJSON.response.group.wikiBBcode) { // Basic cleanup if needed, but Crossfade provides clean tracklist } if (albumDesc) { albumDesc.value = albumDescJSON; // Trigger preview if possible // document.querySelector('input.button_preview_0').click(); } } } var relDesc = document.getElementById('release_desc'); var relDescJSON = releaseJSON.response.torrent.description; if (sourceWebsite !== 'Crossfade') { var groupIDJSON = releaseJSON.response.group.id; var torrentIDJSON = releaseJSON.response.torrent.id; relDescJSON += (relDescJSON ? '\n\n' : '') + 'Cross-posted from ' + sourceWebsite + ': https://'; relDescJSON += sourceWebsiteDomains[sourceWebsiteIndex] + '/torrents.php?id=' + groupIDJSON + '&torrentid=' + torrentIDJSON; } if (relDesc) relDesc.value = relDescJSON; // Show success message ChooseJSONTR.innerHTML = ''; var successTD = document.createElement('td'); successTD.colSpan = 2; successTD.style.fontWeight = 'bold'; successTD.style.color = 'green'; successTD.style.textAlign = 'center'; successTD.textContent = 'Data imported successfully!'; ChooseJSONTR.appendChild(successTD); break; } }, 500); // Delay to allow category change to propagate } ChooseJSONBtn.addEventListener('change', function (evt) { var file = document.getElementById('json').files[0]; if (file) { var reader = new FileReader(); reader.readAsText(file, "UTF-8"); reader.onload = function (evt) { var releaseJSON = JSON.parse(evt.target.result); processJSON(releaseJSON, file.name); } reader.onerror = function (evt) { alert('There was an error reading the file.'); } } else { alert('No JSON file has been chosen!'); } }); ChooseJSONPasteBtn.addEventListener('click', async function () { try { const text = await navigator.clipboard.readText(); if (!text) { alert('Clipboard is empty!'); return; } try { const releaseJSON = JSON.parse(text); processJSON(releaseJSON, 'clipboard.json'); } catch (e) { alert('Failed to parse JSON from clipboard. Make sure you copied the correct content.'); } } catch (err) { alert('Failed to read clipboard: ' + err); } }); })();