Advertisement
Guest User

Untitled

a guest
Dec 10th, 2016
1,820
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @id             apollo-yadg
  3. // @name           apollo.rip - YADG
  4. // @description    This script provides integration with online description generator YADG (http://yadg.cc)
  5. // @license        https://github.com/Slack06/yadg-userscript/blob/master/LICENSE
  6. // @version        1.3.7
  7. // @namespace      yadg
  8. // @grant          GM_xmlhttpRequest
  9. // @require        https://yadg.cc/static/js/jsandbox.min.js
  10. // @include        http*://*apollo.rip/upload.php*
  11. // @include        http*://*apollo.rip/requests.php*
  12. // @include        http*://*apollo.rip/torrents.php*
  13. // @include        http*://*waffles.ch/upload.php*
  14. // @include        http*://*waffles.ch/requests.php*
  15. // ==/UserScript==
  16.  
  17. // --------- USER SETTINGS START ---------
  18.  
  19. /*
  20.  Here you can set site specific default templates.
  21.  You can find a list of available templates at: https://yadg.cc/api/v2/templates/
  22. */
  23. var defaultapolloFormat = 5,
  24.     defaultWafflesFormat = 9,
  25.     apolloLinoHazeBetterCss = false; // Will improve css on torrent pages for LinoHaze theme, put "true" to activate it
  26.  
  27. // --------- USER SETTINGS END ---------
  28.  
  29.  
  30.  
  31. // --------- THIRD PARTY CODE AREA START ---------
  32.  
  33. //
  34. // Creates an object which gives some helper methods to
  35. // Save/Load/Remove data to/from the localStorage
  36. //
  37. // Source from: https://github.com/gergob/localstoragewrapper
  38. //
  39. function LocalStorageWrapper (applicationPrefix) {
  40.     "use strict";
  41.  
  42.     if(applicationPrefix == undefined) {
  43.         throw new Error('applicationPrefix parameter should be defined');
  44.     }
  45.  
  46.     var delimiter = '_';
  47.  
  48.     //if the passed in value for prefix is not string, it should be converted
  49.     var keyPrefix = typeof(applicationPrefix) === 'string' ? applicationPrefix : JSON.stringify(applicationPrefix);
  50.  
  51.     var localStorage = window.localStorage||unsafeWindow.localStorage;
  52.  
  53.     var isLocalStorageAvailable = function() {
  54.         return typeof(localStorage) != undefined
  55.     };
  56.  
  57.     var getKeyPrefix = function() {
  58.         return keyPrefix;
  59.     };
  60.  
  61.     //
  62.     // validates if there is a prefix defined for the keys
  63.     // and checks if the localStorage functionality is available or not
  64.     //
  65.     var makeChecks = function(key) {
  66.         var prefix = getKeyPrefix();
  67.         if(prefix == undefined) {
  68.             throw new Error('No prefix was defined, data cannot be saved');
  69.         }
  70.  
  71.         if(!isLocalStorageAvailable()) {
  72.             throw new Error('LocalStorage is not supported by your browser, data cannot be saved');
  73.         }
  74.  
  75.         //keys are always strings
  76.         var checkedKey = typeof(key) === 'string' ? key : JSON.stringify(key);
  77.  
  78.         return checkedKey;
  79.     };
  80.  
  81.     //
  82.     // saves the value associated to the key into the localStorage
  83.     //
  84.     var addItem = function(key, value) {
  85.         var that = this;
  86.         try{
  87.             var checkedKey = makeChecks(key);
  88.             var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
  89.             localStorage.setItem(combinedKey, JSON.stringify(value));
  90.         }
  91.         catch(error) {
  92.             console.log(error);
  93.             throw error;
  94.         }
  95.     };
  96.  
  97.     //
  98.     // gets the value of the object saved to the key passed as parameter
  99.     //
  100.     var getItem = function(key) {
  101.         var that = this;
  102.         var result = undefined;
  103.         try{
  104.             var checkedKey = makeChecks(key);
  105.             var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
  106.             var resultAsJSON = localStorage.getItem(combinedKey);
  107.             result = JSON.parse(resultAsJSON);
  108.         }
  109.         catch(error) {
  110.             console.log(error);
  111.             throw error;
  112.         }
  113.         return result;
  114.     };
  115.  
  116.     //
  117.     // returns all the keys from the localStorage
  118.     //
  119.     var getAllKeys = function() {
  120.         var prefix = getKeyPrefix();
  121.         var results = [];
  122.  
  123.         if(prefix == undefined) {
  124.             throw new Error('No prefix was defined, data cannot be saved');
  125.         }
  126.  
  127.         if(!isLocalStorageAvailable()) {
  128.             throw new Error('LocalStorage is not supported by your browser, data cannot be saved');
  129.         }
  130.  
  131.         for(var key in localStorage) {
  132.             if(key.indexOf(prefix) == 0) {
  133.                 var keyParts = key.split(delimiter);
  134.                 results.push(keyParts[1]);
  135.             }
  136.         }
  137.  
  138.         return results;
  139.     };
  140.  
  141.     //
  142.     // removes the value associated to the key from the localStorage
  143.     //
  144.     var removeItem = function(key) {
  145.         var that = this;
  146.         var result = false;
  147.         try{
  148.             var checkedKey = makeChecks(key);
  149.             var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
  150.             localStorage.removeItem(combinedKey);
  151.             result = true;
  152.         }
  153.         catch(error) {
  154.             console.log(error);
  155.             throw error;
  156.         }
  157.         return result;
  158.     };
  159.  
  160.     //
  161.     // removes all the values from the localStorage
  162.     //
  163.     var removeAll = function() {
  164.         var that = this;
  165.  
  166.         try{
  167.             var allKeys = that.getAllKeys();
  168.             for(var i=0; i < allKeys.length; ++i) {
  169.                 var checkedKey = makeChecks(allKeys[i]);
  170.                 var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
  171.                 localStorage.removeItem(combinedKey);
  172.             }
  173.         }
  174.         catch(error) {
  175.             console.log(error);
  176.             throw error;
  177.         }
  178.     };
  179.  
  180.     // make some of the functionalities public
  181.     return {
  182.         isLocalStorageAvailable : isLocalStorageAvailable,
  183.         getKeyPrefix : getKeyPrefix,
  184.         addItem : addItem,
  185.         getItem : getItem,
  186.         getAllKeys : getAllKeys,
  187.         removeItem : removeItem,
  188.         removeAll : removeAll
  189.     }
  190. }
  191.  
  192. // --------- THIRD PARTY CODE AREA END ---------
  193.  
  194. var yadg_util = {
  195.     exec : function exec(fn) {
  196.         var script = document.createElement('script');
  197.         script.setAttribute("type", "application/javascript");
  198.         script.textContent = '(' + fn + ')();';
  199.         document.body.appendChild(script); // run the script
  200.         document.body.removeChild(script); // clean up
  201.     },
  202.  
  203.     // handle for updating page css, taken from one of hateradio's scripts
  204.     addCSS : function(style) {
  205.         if(!this.style) {
  206.             this.style = document.createElement('style');
  207.             this.style.type = 'text/css';
  208.             (document.head || document.getElementsByTagName('head')[0]).appendChild(this.style);
  209.         }
  210.         this.style.appendChild(document.createTextNode(style+'\n'));
  211.     },
  212.  
  213.     setValueIfSet: function(value,input,cond) {
  214.         if (cond) {
  215.             input.value = value;
  216.         } else {
  217.             input.value = '';
  218.         }
  219.     },
  220.  
  221.     // negative count will remove, positive count will add given number of artist boxes
  222.     addRemoveArtistBoxes : function(count) {
  223.         if (count != 0) {
  224.             if (count < 0) {
  225.                 for (var i = 0; i < -count; i++) {
  226.                     yadg_util.exec(function() {RemoveArtistField()});
  227.                 }
  228.             } else {
  229.                 for (var i = 0; i < count; i++) {
  230.                     yadg_util.exec(function() {AddArtistField()});
  231.                 }
  232.             }
  233.         }
  234.     },
  235.  
  236.     getOptionOffsets : function(select) {
  237.         var option_offsets = {};
  238.         for (var j = 0; j < select.options.length; j++) {
  239.             option_offsets[select.options[j].value] = select.options[j].index;
  240.         }
  241.         return option_offsets;
  242.     },
  243.  
  244.     storage : new LocalStorageWrapper("yadg"),
  245.  
  246.     settings : new LocalStorageWrapper("yadgSettings")
  247. };
  248.  
  249. // very simple wrapper for XmlHttpRequest
  250. function requester(url, method, callback, data, error_callback) {
  251.     this.data = data;
  252.     this.url = url;
  253.     this.method = method;
  254.     if (!error_callback) {
  255.         error_callback = yadg.failed_callback;
  256.     }
  257.  
  258.     this.send = function() {
  259.         var details = {
  260.             url : this.url,
  261.             method : this.method,
  262.             onload : function(response) {
  263.                 if (response.status === 200) {
  264.                     callback(JSON.parse(response.responseText));
  265.                 } else if (response.status === 401) {
  266.                     yadg.failed_authentication_callback();
  267.                 } else {
  268.                     error_callback();
  269.                 }
  270.             },
  271.             onerror : error_callback
  272.         };
  273.         if (method == "POST") {
  274.             details.data = JSON.stringify(this.data);
  275.         }
  276.  
  277.         var headers = {
  278.             "Accept" : "application/json",
  279.             "Content-Type" : "application/json"
  280.         };
  281.  
  282.         if (yadg_util.settings.getItem(factory.KEY_API_TOKEN)) {
  283.             headers.Authorization = "Token " + yadg_util.settings.getItem(factory.KEY_API_TOKEN);
  284.         }
  285.  
  286.         details.headers = headers;
  287.  
  288.         GM_xmlhttpRequest(details);
  289.     };
  290. }
  291.  
  292. var yadg_sandbox = {
  293.  
  294.     KEY_LAST_WARNING : "templateLastWarning",
  295.  
  296.     init : function(callback) {
  297.         GM_xmlhttpRequest({
  298.             method: 'GET',
  299.             url: yadg.yadgHost + '/static/js/jsandbox-worker.js',
  300.             onload: function(response) {
  301.                 var script, dataURL = null;
  302.                 if (response.status === 200) {
  303.                     script = response.responseText;
  304.                     var blob = new Blob([script], {type: 'application/javascript'});
  305.                     var URL = window.URL || window.webkitURL;
  306.                     if (!URL || !URL.createObjectURL) {
  307.                         throw new Error('No no valid implementation of window.URL.createObjectURL found.');
  308.                     }
  309.                     dataURL = URL.createObjectURL(blob);
  310.                     yadg_sandbox.initCallback(dataURL);
  311.                     yadg_sandbox.loadSwig(callback);
  312.                 } else {
  313.                     yadg_sandbox.initCallbackError();
  314.                 }
  315.             },
  316.             onerror: function() {
  317.                 yadg_sandbox.initCallbackError();
  318.             }
  319.         });
  320.  
  321.     },
  322.  
  323.     loadSwig : function(callback) {
  324.         // importScripts for the web worker will not work in Firefox with cross-domain requests
  325.         // see: https://bugzilla.mozilla.org/show_bug.cgi?id=756589
  326.         // so download the Swig files manually with GM_xmlhttpRequest
  327.         GM_xmlhttpRequest({
  328.             method: 'GET',
  329.             url: yadg.yadgHost + "/static/js/swig.min.js",
  330.             onload: function(response) {
  331.                 if (response.status === 200) {
  332.                     yadg_sandbox.swig_script = response.responseText;
  333.  
  334.                     GM_xmlhttpRequest({
  335.                         method: 'GET',
  336.                         url: yadg.yadgHost + "/static/js/swig.custom.js",
  337.                         onload: function(response) {
  338.                             if (response.status === 200) {
  339.                                 yadg_sandbox.swig_custom_script = response.responseText;
  340.                                 callback();
  341.                             }
  342.                         }
  343.                     });
  344.                 }
  345.             }
  346.         });
  347.     },
  348.  
  349.     initializeSwig : function(dependencies) {
  350.         if (!(this.swig_script && this.swig_custom_script)) {
  351.             yadg.failed_callback();
  352.             return
  353.         }
  354.  
  355.         yadg_sandbox.exec({data: this.swig_script, onerror: yadg.failed_callback});
  356.         yadg_sandbox.exec({data: this.swig_custom_script, onerror: yadg.failed_callback});
  357.         yadg_sandbox.exec({data: "var myswig = new swig.Swig({ loader: swig.loaders.memory(input.templates), autoescape: false }), i=0; yadg_filters.register_filters(myswig);", input: {templates: dependencies}});
  358.     },
  359.  
  360.     renderTemplate : function(template, data, callback, error) {
  361.         var eval_string = "myswig.render(input.template, { locals: input.data, filename: 'scratchpad' + (i++) })";
  362.         this.eval({data: eval_string, callback: function(out) {callback(out);}, input: {template: template, data: data}, onerror: function(err){error(err);}});
  363.     },
  364.  
  365.     initCallback : function(dataUrl) {
  366.         JSandbox.url = dataUrl;
  367.         this.jsandbox = new JSandbox();
  368.         this.initError = false;
  369.     },
  370.  
  371.     resetSandbox : function() {
  372.         this.jsandbox.terminate();
  373.         this.jsandbox = new JSandbox();
  374.     },
  375.  
  376.     load : function(options) {
  377.         this.jsandbox.load(options);
  378.     },
  379.  
  380.     exec : function(options) {
  381.         this.jsandbox.exec(options);
  382.     },
  383.  
  384.     eval : function(options) {
  385.         this.jsandbox.eval(options);
  386.     },
  387.  
  388.     initCallbackError : function() {
  389.         this.initError = true;
  390.  
  391.         var last_warning = yadg_util.storage.getItem(this.KEY_LAST_WARNING),
  392.             now = new Date();
  393.         if (last_warning === null || now.getTime() - (new Date(last_warning)).getTime() > factory.CACHE_TIMEOUT) {
  394.             alert("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.");
  395.             yadg_util.storage.addItem(this.KEY_LAST_WARNING, now);
  396.         }
  397.     }
  398. };
  399.  
  400. var factory = {
  401.     // storage keys for cache
  402.     KEY_LAST_CHECKED : "lastChecked",
  403.     KEY_SCRAPER_LIST : "scraperList",
  404.     KEY_FORMAT_LIST : "formatList",
  405.  
  406.     // storage keys for settings
  407.     KEY_API_TOKEN : "apiToken",
  408.     KEY_DEFAULT_TEMPLATE : "defaultTemplate",
  409.     KEY_DEFAULT_SCRAPER : "defaultScraper",
  410.     KEY_REPLACE_DESCRIPTION : "replaceDescriptionOn",
  411.     KEY_SETTINGS_INIT_VER : "settingsInitializedVer",
  412.  
  413.     CACHE_TIMEOUT : 1000*60*60*24, // 24 hours
  414.  
  415.     UPDATE_PROGRESS : 0,
  416.  
  417.     locations : new Array(
  418.         {
  419.             name : 'apollorip_upload',
  420.             regex : /http(s)?\:\/\/(.*\.)?apollo\.rip\/upload\.php.*/i
  421.         },
  422.         {
  423.             name : 'apollorip_edit',
  424.             regex : /http(s)?\:\/\/(.*\.)?apollo\.rip\/torrents\.php\?action=editgroup&groupid=.*/i
  425.         },
  426.         {
  427.             name : 'apollorip_request',
  428.             regex : /http(s)?\:\/\/(.*\.)?apollo\.rip\/requests\.php\?action=new/i
  429.         },
  430.         {
  431.             name : 'apollorip_request_edit',
  432.             regex : /http(s)?\:\/\/(.*\.)?apollo\.rip\/requests\.php\?action=edit&id=.*/i
  433.         },
  434.         {
  435.             name : 'apollorip_torrent_overview',
  436.             regex : /http(s)?\:\/\/(.*\.)?apollo\.rip\/torrents\.php\?id=.*/i
  437.         },
  438.         {
  439.             name : 'waffles_upload',
  440. //            regex : /http(s)?\:\/\/(.*\.)?waffles\.ch\/upload\.php\?legacy=1.*/i
  441. //        },
  442. //        {
  443. //            TODO: reenable support for the new Waffles upload page once it is reactivated
  444. //            name : 'waffles_upload_new',
  445.             regex : /http(s)?\:\/\/(.*\.)?waffles\.ch\/upload\.php.*/i
  446.         },
  447.         {
  448.             name : 'waffles_request',
  449.             regex : /http(s)?\:\/\/(.*\.)?waffles\.ch\/requests\.php\?do=add/i
  450.         }
  451.     ),
  452.  
  453.     determineLocation : function(uri) {
  454.         for (var i = 0; i < this.locations.length; i++) {
  455.             if (this.locations[i].regex.test(uri)) {
  456.                 return this.locations[i].name;
  457.             }
  458.         }
  459.         return null;
  460.     },
  461.  
  462.     init : function() {
  463.         this.currentLocation = this.determineLocation(document.URL);
  464.         // only continue with the initialization if we found a valid location
  465.         if (this.currentLocation !== null) {
  466.             this.insertIntoPage(this.getInputElements());
  467.  
  468.             // set the necessary styles
  469.             this.setStyles();
  470.  
  471.             // make sure we initialize the settings to the most recent version
  472.             this.initializeSettings();
  473.  
  474.             // populate settings inputs
  475.             this.populateSettings();
  476.  
  477.             // add the appropriate action for the button
  478.             var button = document.getElementById('yadg_submit');
  479.             button.addEventListener('click', function (e) {
  480.                 e.preventDefault();
  481.                 yadg.makeRequest();
  482.             }, false);
  483.  
  484.             // add the action for the options toggle
  485.             var toggleLink = document.getElementById('yadg_toggle_options');
  486.             if (toggleLink !== null) {
  487.                 toggleLink.addEventListener('click', function (e) {
  488.                     e.preventDefault();
  489.  
  490.                     var optionsDiv = document.getElementById('yadg_options'),
  491.                         display = optionsDiv.style.display;
  492.  
  493.                     if (display == 'none' || display == '') {
  494.                         optionsDiv.style.display = 'block';
  495.                     } else {
  496.                         optionsDiv.style.display = 'none';
  497.                     }
  498.                 });
  499.             }
  500.  
  501.             // add the action for the template select
  502.             var formatSelect = this.getFormatSelect();
  503.             if (formatSelect !== null) {
  504.                 formatSelect.addEventListener('change', function (e) {
  505.                     if (yadg_renderer.hasCached()) {
  506.                         yadg_renderer.renderCached(this.value, factory.setDescriptionBoxValue, factory.setDescriptionBoxValue);
  507.                     }
  508.                 });
  509.             }
  510.  
  511.             // add the action to the save settings link
  512.             var saveSettingsLink = document.getElementById('yadg_save_settings');
  513.             if (saveSettingsLink !== null) {
  514.                 saveSettingsLink.addEventListener('click', function (e) {
  515.                     e.preventDefault();
  516.  
  517.                     factory.saveSettings();
  518.  
  519.                     alert("Settings saved successfully.");
  520.                 });
  521.             }
  522.  
  523.             // add the action to the clear cache link
  524.             var clearCacheLink = document.getElementById('yadg_clear_cache');
  525.             if (clearCacheLink !== null) {
  526.                 clearCacheLink.addEventListener('click', function (e) {
  527.                     e.preventDefault();
  528.  
  529.                     yadg_util.storage.removeAll();
  530.  
  531.                     alert("Cache cleared. Please reload the page for this to take effect.");
  532.                 });
  533.             }
  534.  
  535.             var last_checked = yadg_util.storage.getItem(factory.KEY_LAST_CHECKED);
  536.             if (last_checked === null || (new Date()).getTime() - (new Date(last_checked)).getTime() > factory.CACHE_TIMEOUT) {
  537.                 // update the scraper and formats list
  538.                 factory.UPDATE_PROGRESS = 1;
  539.                 yadg.getScraperList(factory.setScraperSelect);
  540.                 yadg.getFormatsList(factory.setFormatSelect);
  541.             } else {
  542.                 factory.setScraperSelect(yadg_util.storage.getItem(factory.KEY_SCRAPER_LIST));
  543.                 factory.setFormatSelect(yadg_util.storage.getItem(factory.KEY_FORMAT_LIST));
  544.             }
  545.  
  546.             return true;
  547.         } else {
  548.             return false;
  549.         }
  550.     },
  551.  
  552.     getApiTokenInput : function() {
  553.         return document.getElementById('yadg_api_token');
  554.     },
  555.  
  556.     getReplaceDescriptionCheckbox : function() {
  557.         return document.getElementById('yadg_options_replace');
  558.     },
  559.  
  560.     getReplaceDescriptionSettingKey : function() {
  561.         return this.makeReplaceDescriptionSettingsKey(this.currentLocation);
  562.     },
  563.  
  564.     makeReplaceDescriptionSettingsKey : function(subKey) {
  565.         return this.KEY_REPLACE_DESCRIPTION + subKey.replace(/_/g, "");
  566.     },
  567.  
  568.     initializeSettings : function() {
  569.         var settings_ver = yadg_util.settings.getItem(factory.KEY_SETTINGS_INIT_VER),
  570.             current_ver = 1;
  571.  
  572.         if (!settings_ver) {
  573.             settings_ver = 0;
  574.         }
  575.  
  576.         if (settings_ver < current_ver) {
  577.             // replace descriptions on upload and new request pages
  578.             var locations = [
  579.                 'apollorip_upload',
  580.                 'apollorip_request',
  581.                 'waffles_upload',
  582.                 'waffles_upload_new',
  583.                 'waffles_request'
  584.             ];
  585.             for (var i = 0; i < locations.length; i++) {
  586.                 var loc = locations[i],
  587.                     replace_desc_setting_key = factory.makeReplaceDescriptionSettingsKey(loc);
  588.  
  589.                 yadg_util.settings.addItem(replace_desc_setting_key, true);
  590.             }
  591.         }
  592.  
  593.         yadg_util.settings.addItem(factory.KEY_SETTINGS_INIT_VER, current_ver);
  594.     },
  595.  
  596.     populateSettings : function() {
  597.         var api_token = yadg_util.settings.getItem(factory.KEY_API_TOKEN),
  598.             replace_desc = yadg_util.settings.getItem(factory.getReplaceDescriptionSettingKey());
  599.  
  600.         if (api_token) {
  601.             var api_token_input = factory.getApiTokenInput();
  602.             api_token_input.value = api_token;
  603.         }
  604.  
  605.         if (replace_desc) {
  606.             var replace_desc_checkbox = factory.getReplaceDescriptionCheckbox();
  607.             replace_desc_checkbox.checked = true;
  608.         }
  609.     },
  610.  
  611.     saveSettings : function() {
  612.         var scraper_select = factory.getScraperSelect(),
  613.             template_select = factory.getFormatSelect(),
  614.             api_token_input = factory.getApiTokenInput(),
  615.             replace_desc_checkbox = factory.getReplaceDescriptionCheckbox();
  616.  
  617.         var current_scraper = null,
  618.             current_template = null,
  619.             api_token = api_token_input.value.trim(),
  620.             replace_description = replace_desc_checkbox.checked;
  621.  
  622.         if (scraper_select.options.length > 0) {
  623.             current_scraper = scraper_select.options[scraper_select.selectedIndex].value;
  624.         }
  625.  
  626.         if (template_select.options.length > 0) {
  627.             current_template = template_select.options[template_select.selectedIndex].value;
  628.         }
  629.  
  630.         if (current_scraper !== null) {
  631.             yadg_util.settings.addItem(factory.KEY_DEFAULT_SCRAPER, current_scraper);
  632.         }
  633.  
  634.         if (current_template !== null) {
  635.             yadg_util.settings.addItem(factory.KEY_DEFAULT_TEMPLATE, current_template);
  636.         }
  637.  
  638.         if (api_token !== "") {
  639.             yadg_util.settings.addItem(factory.KEY_API_TOKEN, api_token);
  640.         } else {
  641.             yadg_util.settings.removeItem(factory.KEY_API_TOKEN);
  642.         }
  643.  
  644.         var replace_desc_setting_key = factory.getReplaceDescriptionSettingKey();
  645.         if (replace_description) {
  646.             yadg_util.settings.addItem(replace_desc_setting_key, true);
  647.         } else {
  648.             yadg_util.settings.removeItem(replace_desc_setting_key);
  649.         }
  650.     },
  651.  
  652.     setDescriptionBoxValue : function(value) {
  653.         var desc_box = factory.getDescriptionBox(),
  654.             replace_desc_checkbox = factory.getReplaceDescriptionCheckbox(),
  655.             replace_desc = false;
  656.  
  657.         if (replace_desc_checkbox !== null) {
  658.             replace_desc = replace_desc_checkbox.checked;
  659.         }
  660.  
  661.         if (desc_box !== null) {
  662.             if (!replace_desc && /\S/.test(desc_box.value)) { // check if the current description contains more than whitespace
  663.                 desc_box.value += "\n\n" + value;
  664.             } else {
  665.                 desc_box.value = value;
  666.             }
  667.         }
  668.     },
  669.  
  670.     getFormatSelect : function() {
  671.         return document.getElementById('yadg_format');
  672.     },
  673.  
  674.     setDefaultFormat : function() {
  675.         var format_select = factory.getFormatSelect();
  676.         var format_offsets = yadg_util.getOptionOffsets(format_select);
  677.  
  678.         var default_format = yadg_util.settings.getItem(factory.KEY_DEFAULT_TEMPLATE);
  679.         if (default_format !== null && default_format in format_offsets) {
  680.             format_select.selectedIndex = format_offsets[default_format];
  681.         } else {
  682.             // we have no settings so fall back to the hard coded defaults
  683.             switch (this.currentLocation) {
  684.                 case "waffles_upload":
  685.                 case "waffles_upload_new":
  686.                 case "waffles_request":
  687.                     format_select.selectedIndex = format_offsets[defaultWafflesFormat];
  688.                     break;
  689.  
  690.                 default:
  691.                     format_select.selectedIndex = format_offsets[defaultapolloFormat];
  692.                     break;
  693.             }
  694.         }
  695.     },
  696.  
  697.     getScraperSelect : function() {
  698.         return document.getElementById("yadg_scraper");
  699.     },
  700.  
  701.     setDefaultScraper : function() {
  702.         var default_scraper = yadg_util.settings.getItem(factory.KEY_DEFAULT_SCRAPER);
  703.         if (default_scraper !== null) {
  704.             var scraper_select = factory.getScraperSelect();
  705.             var scraper_offsets = yadg_util.getOptionOffsets(scraper_select);
  706.  
  707.             if (default_scraper in scraper_offsets) {
  708.                 scraper_select.selectedIndex = scraper_offsets[default_scraper];
  709.             }
  710.         }
  711.     },
  712.  
  713.     setScraperSelect : function(scrapers) {
  714.         var scraper_select = factory.getScraperSelect();
  715.  
  716.         factory.setSelect(scraper_select, scrapers);
  717.         factory.setDefaultScraper();
  718.  
  719.         if (factory.UPDATE_PROGRESS > 0) {
  720.             yadg_util.storage.addItem(factory.KEY_SCRAPER_LIST, scrapers);
  721.             factory.UPDATE_PROGRESS |= 1<<1;
  722.  
  723.             if (factory.UPDATE_PROGRESS === 7) {
  724.                 yadg_util.storage.addItem(factory.KEY_LAST_CHECKED, new Date());
  725.             }
  726.         }
  727.     },
  728.  
  729.     setFormatSelect : function(templates) {
  730.         var format_select = factory.getFormatSelect();
  731.  
  732.         var non_utility = [];
  733.         var save_templates = [];
  734.         for (var i = 0; i < templates.length; i++) {
  735.             if (factory.UPDATE_PROGRESS > 0) {
  736.                 if(templates[i].name === 'What'){
  737.                     templates[i].name = 'Apollo';
  738.                     templates[i].nameFormatted = 'Apollo';
  739.                 } else if(templates[i].name === 'What (Tracks only)'){
  740.                     templates[i].name = 'Apollo (Tracks only)';
  741.                     templates[i].nameFormatted = 'Apollo (Tracks only)';
  742.                 }
  743.  
  744.                 yadg_templates.addTemplate(templates[i]);
  745.  
  746.                 save_templates.push({
  747.                     id : templates[i]['id'],
  748.                     url : templates[i]['url'],
  749.                     name : templates[i]['name'],
  750.                     nameFormatted : templates[i]['nameFormatted'],
  751.                     owner : templates[i]['owner'],
  752.                     default : templates[i]['default'],
  753.                     isUtility : templates[i]['isUtility']
  754.                 });
  755.             } else {
  756.                 if(templates[i].name === 'What'){
  757.                     templates[i].name = 'Apollo';
  758.                     templates[i].nameFormatted = 'Apollo';
  759.                 } else if(templates[i].name === 'What (Tracks only)'){
  760.                     templates[i].name = 'Apollo (Tracks only)';
  761.                     templates[i].nameFormatted = 'Apollo (Tracks only)';
  762.                 }
  763.  
  764.                 yadg_templates.addTemplateUrl(templates[i]['id'], templates[i]['url']);
  765.             }
  766.  
  767.             if (!templates[i]['isUtility']) {
  768.                 non_utility.push(templates[i]);
  769.             }
  770.         }
  771.  
  772.         factory.setSelect(format_select, non_utility);
  773.         factory.setDefaultFormat();
  774.  
  775.         if (factory.UPDATE_PROGRESS > 0) {
  776.             yadg_util.storage.addItem(factory.KEY_FORMAT_LIST, save_templates);
  777.             factory.UPDATE_PROGRESS |= 1<<2;
  778.  
  779.             if (factory.UPDATE_PROGRESS === 7) {
  780.                 yadg_util.storage.addItem(factory.KEY_LAST_CHECKED, new Date());
  781.             }
  782.         }
  783.     },
  784.  
  785.     setSelect : function(select, data) {
  786.         select.options.length = data.length;
  787.  
  788.         for (var i = 0; i < data.length; i++) {
  789.             // we are not using the javascript constructor to create an Option instance because this will create an
  790.             // incompatibility with jQuery in Chrome which will make it impossible to add a new artist field on apollo.rip
  791.             var o = document.createElement("option");
  792.             if ('nameFormatted' in data[i]) {
  793.                 o.text = data[i]['nameFormatted'];
  794.             } else {
  795.                 o.text = data[i]['name'];
  796.             }
  797.             o.value = data[i]['value'] || data[i]['id'];
  798.             o.selected = data[i]['default'];
  799.             select.options[i] = o;
  800.             if (data[i]['default']) {
  801.                 select.selectedIndex = i;
  802.             }
  803.             if (data[i]['url']) {
  804.                 o.setAttribute('data-url', data[i]['url']);
  805.             }
  806.         }
  807.     },
  808.  
  809.     setStyles : function() {
  810.         // general styles
  811.         yadg_util.addCSS('div#yadg_options{ display:none; margin-top:3px; } input#yadg_input,input#yadg_submit,label#yadg_format_label,a#yadg_scraper_info { margin-right: 5px } div#yadg_response { margin-top:3px; } select#yadg_scraper { margin-right: 2px } #yadg_options_template,#yadg_options_api_token,#yadg_options_replace_div { margin-bottom: 3px; }');
  812.  
  813.         // location specific styles will go here
  814.         switch(this.currentLocation) {
  815.             case "waffles_upload":
  816.                 yadg_util.addCSS('div#yadg_response ul { margin-left: 0 !important; padding-left: 0 !important; }');
  817.                 break;
  818.  
  819.             case "waffles_request":
  820.                 yadg_util.addCSS('div#yadg_response ul { margin-left: 0 !important; padding-left: 0 !important; }');
  821.                 break;
  822.  
  823.             default:
  824.  
  825.                 break;
  826.         }
  827.     },
  828.  
  829.     getInputElements : function() {
  830.         var buttonHTML = '<input type="submit" value="Fetch" id="yadg_submit"/>',
  831.             scraperSelectHTML = '<select name="yadg_scraper" id="yadg_scraper"></select>',
  832.             optionsHTML = '<div id="yadg_options"><div id="yadg_options_template"><label for="yadg_format" id="yadg_format_label">Template:</label><select name="yadg_format" id="yadg_format"></select></div><div id="yadg_options_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_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>',
  833.             inputHTML = '<input type="text" name="yadg_input" id="yadg_input" size="60" />',
  834.             responseDivHTML = '<div id="yadg_response"></div>',
  835.             toggleOptionsLinkHTML = '<a id="yadg_toggle_options" href="#">Toggle options</a>',
  836.             scraperInfoLink = '<a id="yadg_scraper_info" href="https://yadg.cc/available-scrapers" target="_blank" title="Get additional information on the available scrapers">[?]</a>';
  837.  
  838.  
  839.         switch (this.currentLocation) {
  840.             case "apollorip_upload":
  841.                 var tr = document.createElement('tr');
  842.                 tr.className = "yadg_tr";
  843.                 if(apolloLinoHazeBetterCss === true){
  844.                     tr.innerHTML = '<td class="label" style="padding-bottom: 15px;">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
  845.                 } else {
  846.                     tr.innerHTML = '<td class="label">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
  847.                 }
  848.                 return tr;
  849.  
  850.             case "apollorip_edit":
  851.                 var div = document.createElement('div');
  852.                 div.className = "yadg_div";
  853.                 div.innerHTML = '<h3 class="label">YADG</h3>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML;
  854.                 return div;
  855.  
  856.             case "apollorip_torrent_overview":
  857.                 var div = document.createElement('div');
  858.                 if(apolloLinoHazeBetterCss === true){
  859.                     var scraperSelectHTML_to = '<select name="yadg_scraper" id="yadg_scraper" style="width: 90%;"></select>';
  860.                     var scraperInfoLink_to = '<a id="yadg_scraper_info" href="https://yadg.cc/available-scrapers" target="_blank" title="Get additional information on the available scrapers" style="width: 10%; margin: 0; display: inline-block; text-align: right;">[?]</a>';
  861.                     var buttonHTML_to = '<input type="submit" value="Fetch" id="yadg_submit" style="width: 100%;"/>';
  862.                     div.className = "yadg_div body add_form";
  863.                     div.setAttribute("name","artists");
  864.                     div.style.width = '100%';
  865.                     div.style.paddingTop = '0';
  866.                     div.innerHTML = '<h3 class="label">YADG</h3>' + '<input type="text" name="yadg_input" id="yadg_input" style="width: 100%;" />' + scraperSelectHTML_to + scraperInfoLink_to + buttonHTML_to + optionsHTML + responseDivHTML;
  867.                 } else {
  868.                     div.className = "yadg_div";
  869.                     div.innerHTML = '<h3 class="label">YADG</h3>' + '<input type="text" name="yadg_input" id="yadg_input" />' + scraperSelectHTML + scraperInfoLink + buttonHTML + optionsHTML + responseDivHTML;
  870.                 }
  871.                 return div;
  872.  
  873.             case "apollorip_request":
  874.             case "apollorip_request_edit":
  875.                 var tr = document.createElement('tr');
  876.                 tr.className = "yadg_tr";
  877.                 tr.innerHTML = '<td class="label">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
  878.                 return tr;
  879.  
  880.             case "waffles_upload":
  881.                 var tr = document.createElement('tr');
  882.                 tr.className = "yadg_tr";
  883.                 tr.innerHTML = '<td class="heading" valign="top" align="right"><label for="yadg_input">YADG:</label></td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
  884.                 return tr;
  885.  
  886.             case "waffles_upload_new":
  887.                 var p = document.createElement('p');
  888.                 p.className = "yadg_p";
  889.                 p.innerHTML = '<label for="yadg_input">YADG:</label>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML;
  890.                 return p;
  891.  
  892.             case "waffles_request":
  893.                 var tr = document.createElement('tr');
  894.                 tr.className = "yadg_tr";
  895.                 tr.innerHTML = '<td style="text-align:left;width:100px;">YADG:</td><td style="text-align:left;">' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
  896.                 return tr;
  897.  
  898.             default:
  899.                 // that should actually never happen
  900.                 return document.createElement('div');
  901.         }
  902.     },
  903.  
  904.     insertIntoPage : function(element) {
  905.         switch (this.currentLocation) {
  906.             case "apollorip_upload":
  907.                 var year_tr = document.getElementById('year_tr');
  908.                 year_tr.parentNode.insertBefore(element,year_tr);
  909.                 break;
  910.  
  911.             case "apollorip_edit":
  912.                 var summary_input = document.getElementsByName('summary')[0];
  913.                 summary_input.parentNode.insertBefore(element,summary_input.nextSibling.nextSibling);
  914.                 break;
  915.  
  916.             case "apollorip_torrent_overview":
  917.                 var add_artists_box = document.getElementsByClassName("box_addartists")[0];
  918.                 add_artists_box.appendChild(element);
  919.                 break;
  920.  
  921.             case "apollorip_request":
  922.             case "apollorip_request_edit":
  923.                 var artist_tr = document.getElementById('artist_tr');
  924.                 artist_tr.parentNode.insertBefore(element,artist_tr);
  925.                 break;
  926.  
  927.             case "waffles_upload":
  928.                 var submit_button = document.getElementsByName('submit')[0];
  929.                 submit_button.parentNode.parentNode.parentNode.insertBefore(element,submit_button.parentNode.parentNode);
  930.                 break;
  931.  
  932.             case "waffles_upload_new":
  933.                 var h4s = document.getElementsByTagName('h4');
  934.                 var div;
  935.                 for (var i=0; i < h4s.length; i++) {
  936.                     if (h4s[i].innerHTML.indexOf('read the rules') !== -1) {
  937.                         div = h4s[i].parentNode;
  938.                         break;
  939.                     }
  940.                 }
  941.                 div.appendChild(element);
  942.                 break;
  943.  
  944.             case "waffles_request":
  945.                 var category_select = document.getElementsByName('category')[0];
  946.                 category_select.parentNode.parentNode.parentNode.insertBefore(element,category_select.parentNode.parentNode);
  947.                 break;
  948.  
  949.             default:
  950.                 break;
  951.         }
  952.     },
  953.  
  954.     getDescriptionBox : function() {
  955.         switch (this.currentLocation) {
  956.             case "apollorip_upload":
  957.                 return document.getElementById('album_desc');
  958.  
  959.             case "apollorip_edit":
  960.                 return document.getElementsByName('body')[0];
  961.  
  962.             case "apollorip_torrent_overview":
  963.                 if (!this.hasOwnProperty("dummybox")) {
  964.                     this.dummybox = document.createElement('div');
  965.                 }
  966.                 return this.dummybox;
  967.  
  968.             case "apollorip_request":
  969.             case "apollorip_request_edit":
  970.                 return document.getElementsByName('description')[0];
  971.  
  972.             case "waffles_upload":
  973.                 return document.getElementById('descr');
  974.  
  975.             case "waffles_upload_new":
  976.                 return document.getElementById('id_descr');
  977.  
  978.             case "waffles_request":
  979.                 return document.getElementsByName('information')[0];
  980.  
  981.             default:
  982.                 // that should actually never happen
  983.                 return document.createElement('div');
  984.         }
  985.     },
  986.  
  987.     getFormFillFunction : function() {
  988.         switch (this.currentLocation) {
  989.             case "apollorip_upload":
  990.                 var f = function(rawData) {
  991.                     var artist_inputs = document.getElementsByName("artists[]"),
  992.                         album_title_input = document.getElementById("title"),
  993.                         year_input = document.getElementById("year"),
  994.                         label_input = document.getElementById("record_label"),
  995.                         catalog_input = document.getElementById("catalogue_number"),
  996.                         tags_input = document.getElementById("tags"),
  997.                         data = yadg.prepareRawResponse(rawData);
  998.  
  999.                     if (data.artists != false) {
  1000.                         var input_idx = 0;
  1001.  
  1002.                         yadg_util.addRemoveArtistBoxes(data.effective_artist_count - artist_inputs.length);
  1003.  
  1004.                         artist_inputs = document.getElementsByName("artists[]");
  1005.  
  1006.                         for (var i = 0; i < data.artist_keys.length; i++) {
  1007.                             var artist_key = data.artist_keys[i],
  1008.                                 artist_types = data.artists[artist_key];
  1009.  
  1010.                             for (var j = 0; j < artist_types.length; j++) {
  1011.                                 var artist_type = artist_types[j],
  1012.                                     artist_input = artist_inputs[input_idx],
  1013.                                     type_select = artist_input.nextSibling;
  1014.  
  1015.                                 while (type_select.tagName != 'SELECT') {
  1016.                                     type_select = type_select.nextSibling;
  1017.                                 }
  1018.  
  1019.                                 artist_input.value = artist_key;
  1020.  
  1021.                                 var option_offsets = yadg_util.getOptionOffsets(type_select);
  1022.  
  1023.                                 if (artist_type === "main") {
  1024.                                     type_select.selectedIndex = option_offsets[1];
  1025.                                 } else if (artist_type === "guest") {
  1026.                                     type_select.selectedIndex = option_offsets[2];
  1027.                                 } else if (artist_type === "remixer") {
  1028.                                     type_select.selectedIndex = option_offsets[3];
  1029.                                 } else {
  1030.                                     // we don't know this artist type, default to "main"
  1031.                                     type_select.selectedIndex = option_offsets[1];
  1032.                                 }
  1033.  
  1034.                                 // next artist input
  1035.                                 input_idx += 1;
  1036.                             }
  1037.                         }
  1038.                     } else {
  1039.                         for (var i = 0; i < artist_inputs.length; i++) {
  1040.                             artist_inputs[i].value = '';
  1041.                         }
  1042.                     }
  1043.  
  1044.                     if (data.tags != false) {
  1045.                         tags_input.value = data.tag_string.toLowerCase();
  1046.                     } else {
  1047.                         tags_input.value = '';
  1048.                     }
  1049.  
  1050.                     yadg_util.setValueIfSet(data.year,year_input,data.year != false);
  1051.                     yadg_util.setValueIfSet(data.title,album_title_input,data.title != false);
  1052.                     yadg_util.setValueIfSet(data.label,label_input,data.label != false);
  1053.                     yadg_util.setValueIfSet(data.catalog,catalog_input,data.catalog != false);
  1054.                 };
  1055.                 return f;
  1056.  
  1057.             case "apollorip_edit":
  1058.                 f = function(rawData) {
  1059.                     var year_input = document.getElementsByName("year")[0],
  1060.                         label_input = document.getElementsByName("record_label")[0],
  1061.                         catalog_input = document.getElementsByName("catalogue_number")[0],
  1062.                         data = yadg.prepareRawResponse(rawData);
  1063.  
  1064.                     yadg_util.setValueIfSet(data.year,year_input,data.year != false);
  1065.                     yadg_util.setValueIfSet(data.label,label_input,data.label != false);
  1066.                     yadg_util.setValueIfSet(data.catalog,catalog_input,data.catalog != false);
  1067.                 };
  1068.                 return f;
  1069.  
  1070.             case "apollorip_torrent_overview":
  1071.                 f = function(rawData) {
  1072.                     var artist_inputs = document.getElementsByName("aliasname[]"),
  1073.                         data = yadg.prepareRawResponse(rawData);
  1074.  
  1075.                     if (data.artists != false) {
  1076.                         var input_idx = 0;
  1077.  
  1078.                         yadg_util.addRemoveArtistBoxes(data.effective_artist_count - artist_inputs.length);
  1079.  
  1080.                         artist_inputs = document.getElementsByName("aliasname[]");
  1081.  
  1082.                         for (var i = 0; i < data.artist_keys.length; i++) {
  1083.                             var artist_key = data.artist_keys[i],
  1084.                                 artist_types = data.artists[artist_key];
  1085.  
  1086.                             for (var j = 0; j < artist_types.length; j++) {
  1087.                                 var artist_type = artist_types[j],
  1088.                                     artist_input = artist_inputs[input_idx],
  1089.                                     type_select = artist_input.nextSibling;
  1090.  
  1091.                                 while (type_select.tagName != 'SELECT') {
  1092.                                     type_select = type_select.nextSibling;
  1093.                                 }
  1094.  
  1095.                                 artist_input.value = artist_key;
  1096.  
  1097.                                 var option_offsets = yadg_util.getOptionOffsets(type_select);
  1098.  
  1099.                                 if (artist_type === "main") {
  1100.                                     type_select.selectedIndex = option_offsets[1];
  1101.                                 } else if (artist_type === "guest") {
  1102.                                     type_select.selectedIndex = option_offsets[2];
  1103.                                 } else if (artist_type === "remixer") {
  1104.                                     type_select.selectedIndex = option_offsets[3];
  1105.                                 } else {
  1106.                                     // we don't know this artist type, default to "main"
  1107.                                     type_select.selectedIndex = option_offsets[1];
  1108.                                 }
  1109.  
  1110.                                 // next artist input
  1111.                                 input_idx += 1;
  1112.                             }
  1113.                         }
  1114.                     } else {
  1115.                         for (var i = 0; i < artist_inputs.length; i++) {
  1116.                             artist_inputs[i].value = '';
  1117.                         }
  1118.                     }
  1119.                 };
  1120.                 return f;
  1121.  
  1122.             case "apollorip_request":
  1123.             case "apollorip_request_edit":
  1124.                 var f = function(rawData) {
  1125.                     var artist_inputs = document.getElementsByName("artists[]"),
  1126.                         album_title_input = document.getElementsByName("title")[0],
  1127.                         year_input = document.getElementsByName("year")[0],
  1128.                         label_input = document.getElementsByName("recordlabel")[0],
  1129.                         catalog_input = document.getElementsByName("cataloguenumber")[0],
  1130.                         tags_input = document.getElementById("tags"),
  1131.                         data = yadg.prepareRawResponse(rawData);
  1132.  
  1133.                     if (data.artists != false) {
  1134.                         var input_idx = 0;
  1135.  
  1136.                         yadg_util.addRemoveArtistBoxes(data.effective_artist_count - artist_inputs.length);
  1137.  
  1138.                         artist_inputs = document.getElementsByName("artists[]");
  1139.  
  1140.                         for (var i = 0; i < data.artist_keys.length; i++) {
  1141.                             var artist_key = data.artist_keys[i],
  1142.                                 artist_types = data.artists[artist_key];
  1143.  
  1144.                             for (var j = 0; j < artist_types.length; j++) {
  1145.                                 var artist_type = artist_types[j],
  1146.                                     artist_input = artist_inputs[input_idx],
  1147.                                     type_select = artist_input.nextSibling;
  1148.  
  1149.                                 while (type_select.tagName != 'SELECT') {
  1150.                                     type_select = type_select.nextSibling;
  1151.                                 }
  1152.  
  1153.                                 artist_input.value = artist_key;
  1154.  
  1155.                                 var option_offsets = yadg_util.getOptionOffsets(type_select);
  1156.  
  1157.                                 if (artist_type === "main") {
  1158.                                     type_select.selectedIndex = option_offsets[1];
  1159.                                 } else if (artist_type === "guest") {
  1160.                                     type_select.selectedIndex = option_offsets[2];
  1161.                                 } else if (artist_type === "remixer") {
  1162.                                     type_select.selectedIndex = option_offsets[3];
  1163.                                 } else {
  1164.                                     // we don't know this artist type, default to "main"
  1165.                                     type_select.selectedIndex = option_offsets[1];
  1166.                                 }
  1167.  
  1168.                                 // next artist input
  1169.                                 input_idx += 1;
  1170.                             }
  1171.                         }
  1172.                     } else {
  1173.                         for (var i = 0; i < artist_inputs.length; i++) {
  1174.                             artist_inputs[i].value = '';
  1175.                         }
  1176.                     }
  1177.  
  1178.                     if (data.tags != false) {
  1179.                         tags_input.value = data.tag_string.toLowerCase();
  1180.                     } else {
  1181.                         tags_input.value = '';
  1182.                     }
  1183.  
  1184.                     yadg_util.setValueIfSet(data.year,year_input,data.year != false);
  1185.                     yadg_util.setValueIfSet(data.title,album_title_input,data.title != false);
  1186.                     yadg_util.setValueIfSet(data.label,label_input,data.label != false);
  1187.                     yadg_util.setValueIfSet(data.catalog,catalog_input,data.catalog != false);
  1188.                 };
  1189.                 return f;
  1190.  
  1191.             case "waffles_upload":
  1192.                 var f = function(rawData) {
  1193.                     var artist_input = document.getElementsByName("artist")[0],
  1194.                         album_title_input = document.getElementsByName("album")[0],
  1195.                         year_input = document.getElementsByName("year")[0],
  1196.                         va_checkbox = document.getElementById("va"),
  1197.                         tags_input = document.getElementById("tags"),
  1198.                         data = yadg.prepareRawResponse(rawData);
  1199.  
  1200.                     if (data.artists != false) {
  1201.                         if (data.is_various) {
  1202.                             artist_input.value = "";
  1203.                             va_checkbox.checked = true;
  1204.                         } else {
  1205.                             artist_input.value = data.flat_artist_string;
  1206.                             va_checkbox.checked = false;
  1207.                         }
  1208.                     } else {
  1209.                         va_checkbox.checked = false;
  1210.                         artist_input.value = "";
  1211.                     }
  1212.  
  1213.                     yadg_util.setValueIfSet(data.year,year_input,data.year != false);
  1214.                     yadg_util.setValueIfSet(data.title,album_title_input,data.title != false);
  1215.  
  1216.                     if (data.tags != false) {
  1217.                         tags_input.value = data.tag_string_nodots.toLowerCase();
  1218.                     } else {
  1219.                         tags_input.value = '';
  1220.                     }
  1221.  
  1222.                     yadg_util.exec(function() {formatName()});
  1223.                 };
  1224.                 return f;
  1225.  
  1226.             case "waffles_upload_new":
  1227.                 var f = function(rawData) {
  1228.                     var artist_input = document.getElementById("id_artist"),
  1229.                         album_title_input = document.getElementById("id_album"),
  1230.                         year_input = document.getElementById("id_year"),
  1231.                         va_checkbox = document.getElementById("id_va"),
  1232.                         tags_input = document.getElementById("id_tags"),
  1233.                         data = yadg.prepareRawResponse(rawData);
  1234.  
  1235.                     if (data.artists != false) {
  1236.                         if (data.is_various) {
  1237.                             if (!va_checkbox.checked) {
  1238.                                 va_checkbox.click();
  1239.                             }
  1240.                         } else {
  1241.                             if (va_checkbox.checked) {
  1242.                                 va_checkbox.click();
  1243.                             }
  1244.                             artist_input.value = data.flat_artist_string;
  1245.                         }
  1246.                     } else {
  1247.                         if (va_checkbox.checked) {
  1248.                             va_checkbox.click();
  1249.                         }
  1250.                         artist_input.value = "";
  1251.                     }
  1252.  
  1253.                     yadg_util.setValueIfSet(data.year,year_input,data.year != false);
  1254.                     yadg_util.setValueIfSet(data.title,album_title_input,data.title != false);
  1255.  
  1256.                     if (data.tags != false) {
  1257.                         tags_input.value = data.tag_string_nodots.toLowerCase();
  1258.                     } else {
  1259.                         tags_input.value = '';
  1260.                     }
  1261.                 };
  1262.                 return f;
  1263.  
  1264.             case "waffles_request":
  1265.                 var f = function(rawData) {
  1266.                     var artist_input = document.getElementsByName("artist")[0],
  1267.                         album_title_input = document.getElementsByName("title")[0],
  1268.                         year_input = document.getElementsByName("year")[0],
  1269.                         data = yadg.prepareRawResponse(rawData);
  1270.  
  1271.                     if (data.artists != false) {
  1272.                         if (data.is_various) {
  1273.                             artist_input.value = "Various Artists";
  1274.                         } else {
  1275.                             artist_input.value = data.flat_artist_string;
  1276.                         }
  1277.                     } else {
  1278.                         artist_input.value = "";
  1279.                     }
  1280.  
  1281.                     yadg_util.setValueIfSet(data.year,year_input,data.year != false);
  1282.                     yadg_util.setValueIfSet(data.title,album_title_input,data.title != false);
  1283.                 };
  1284.                 return f;
  1285.  
  1286.             default:
  1287.                 // that should actually never happen
  1288.                 return function(data) {};
  1289.         }
  1290.     }
  1291. };
  1292.  
  1293. var yadg_templates = {
  1294.     _templates : {},
  1295.     _template_urls : {},
  1296.  
  1297.     getTemplate : function(id, callback) {
  1298.         if (id in this._templates) {
  1299.             callback(this._templates[id]);
  1300.         } else if (id in this._template_urls) {
  1301.             var request = new requester(this._template_urls[id], 'GET', function(template) {
  1302.                 yadg_templates.addTemplate(template);
  1303.                 callback(template);
  1304.             }, null, yadg_templates.errorTemplate);
  1305.             request.send();
  1306.         } else {
  1307.             this.errorTemplate();
  1308.         }
  1309.     },
  1310.  
  1311.     addTemplate : function(template) {
  1312.         this._templates[template.id] = template;
  1313.     },
  1314.  
  1315.     addTemplateUrl : function(id, url) {
  1316.         this._template_urls[id] = url;
  1317.     },
  1318.  
  1319.     errorTemplate : function() {
  1320.         yadg.printError("Could not get template. Please choose another one.", true);
  1321.     }
  1322. };
  1323.  
  1324. var yadg_renderer = {
  1325.     _last_data : null,
  1326.     _last_template_id : null,
  1327.  
  1328.     render : function(template_id, data, callback, error_callback) {
  1329.         this._last_data = data;
  1330.         var new_template = this._last_template_id !== template_id;
  1331.         this._last_template_id = template_id;
  1332.  
  1333.         yadg_templates.getTemplate(template_id, function(template) {
  1334.             // the new template might have different dependencies, so initialize Swig with those
  1335.             if (new_template) {
  1336.                 yadg_sandbox.resetSandbox();
  1337.                 yadg_sandbox.initializeSwig(template.dependencies);
  1338.             }
  1339.             template.code = template.code.replace('https://what.cd','https://apollo.rip');
  1340.             yadg_sandbox.renderTemplate(template.code, data, callback, error_callback);
  1341.         });
  1342.     },
  1343.  
  1344.     renderCached : function(template_id, callback, error_callback) {
  1345.         if (this.hasCached()) {
  1346.             this.render(template_id, this._last_data, callback, error_callback);
  1347.         }
  1348.     },
  1349.  
  1350.     hasCached : function() {
  1351.         return this._last_data !== null;
  1352.     },
  1353.  
  1354.     clearCached : function() {
  1355.         this._last_data = null;
  1356.     }
  1357. };
  1358.  
  1359. var yadg = {
  1360.     yadgHost : "https://yadg.cc",
  1361.     baseURI : "/api/v2/",
  1362.  
  1363.     standardError : "Sorry, an error occured. Please try again. If this error persists the user script might need updating.",
  1364.     authenticationError : "Your API token is invalid. Please provide a valid API token or remove the current one.",
  1365.     lastStateError : false,
  1366.  
  1367.     isBusy : false,
  1368.  
  1369.     init : function() {
  1370.         this.scraperSelect = document.getElementById('yadg_scraper');
  1371.         this.formatSelect = document.getElementById('yadg_format');
  1372.         this.input = document.getElementById('yadg_input');
  1373.         this.responseDiv = document.getElementById('yadg_response');
  1374.         this.button = document.getElementById('yadg_submit');
  1375.     },
  1376.  
  1377.     getBaseURL : function() {
  1378.         return this.yadgHost + this.baseURI;
  1379.     },
  1380.  
  1381.     getScraperList : function(callback) {
  1382.         var url = this.getBaseURL() + "scrapers/";
  1383.  
  1384.         var request = new requester(url, 'GET', callback);
  1385.  
  1386.         request.send();
  1387.     },
  1388.  
  1389.     getFormatsList : function(callback) {
  1390.         var url = this.getBaseURL() + "templates/";
  1391.  
  1392.         this.getTemplates(url, [], callback);
  1393.     },
  1394.  
  1395.     getTemplates : function(url, templates, callback) {
  1396.         var request = new requester(url, 'GET', function(data) {
  1397.             for (var i = 0; i < data.results.length; i++) {
  1398.                 templates.push(data.results[i]);
  1399.             }
  1400.             if (data.next !== null) {
  1401.                 yadg.getTemplates(data.next, templates, callback);
  1402.             } else {
  1403.                 callback(templates);
  1404.             }
  1405.         });
  1406.  
  1407.         request.send();
  1408.     },
  1409.  
  1410.     makeRequest : function(params) {
  1411.         if (this.isBusy) return;
  1412.  
  1413.         var data;
  1414.         if (params) {
  1415.             data = params;
  1416.         } else {
  1417.             data = {
  1418.                 scraper: this.scraperSelect.options[this.scraperSelect.selectedIndex].value,
  1419.                 input: this.input.value
  1420.             };
  1421.         }
  1422.             var url = this.getBaseURL() + 'query/';
  1423.  
  1424.         if (data.input !== '') {
  1425.             var request = new requester(url, 'POST', function(result) {
  1426.                 yadg.getResult(result.url);
  1427.             }, data);
  1428.             this.busyStart();
  1429.             request.send();
  1430.         }
  1431.     },
  1432.  
  1433.     getResult : function(result_url) {
  1434.         var request = new requester(result_url, 'GET', function(response) {
  1435.             if (response.status == "done") {
  1436.                 if (response.data.type == 'ReleaseResult') {
  1437.                     var template_id = yadg.formatSelect.options[yadg.formatSelect.selectedIndex].value;
  1438.                     yadg_renderer.render(template_id, response, factory.setDescriptionBoxValue, factory.setDescriptionBoxValue);
  1439.  
  1440.                     if (yadg.lastStateError == true) {
  1441.                         yadg.responseDiv.innerHTML = "";
  1442.                         yadg.lastStateError = false;
  1443.                     }
  1444.  
  1445.                     var fillFunc = factory.getFormFillFunction();
  1446.                     fillFunc(response.data);
  1447.                 } else if (response.data.type == 'ListResult') {
  1448.                     var ul = document.createElement('ul');
  1449.                     ul.id = "yadg_release_list";
  1450.  
  1451.                     var release_list = response.data.items;
  1452.                     for (var i = 0; i < release_list.length;i++) {
  1453.                         var name = release_list[i]['name'],
  1454.                             info = release_list[i]['info'],
  1455.                             query_params = release_list[i]['queryParams'],
  1456.                             release_url = release_list[i]['url'];
  1457.  
  1458.                         var li = document.createElement('li'),
  1459.                             a = document.createElement('a');
  1460.  
  1461.                         a.textContent = name;
  1462.                         a.params = query_params;
  1463.                         a.href = release_url;
  1464.  
  1465.                         a.addEventListener('click',function(e) { e.preventDefault(); yadg.makeRequest(this.params);},false);
  1466.  
  1467.                         li.appendChild(a);
  1468.                         li.appendChild(document.createElement('br'));
  1469.                         li.appendChild(document.createTextNode(info));
  1470.  
  1471.                         ul.appendChild(li);
  1472.                     }
  1473.  
  1474.                     if (ul.childNodes.length != 0) {
  1475.                         yadg.responseDiv.innerHTML = "";
  1476.                         yadg.responseDiv.appendChild(ul);
  1477.                         yadg.lastStateError = false;
  1478.  
  1479.                         // we got a ListResult so clear the last ReleaseResult from the render cache
  1480.                         yadg_renderer.clearCached();
  1481.                     } else {
  1482.                         yadg.printError('Sorry, there were no matches.');
  1483.                     }
  1484.                 } else if (response.data.type == 'NotFoundResult') {
  1485.                     yadg.printError('I could not find the release with the given ID. You may want to try again with another one.');
  1486.                 } else {
  1487.                     yadg.printError('Something weird happened. Please try again');
  1488.                 }
  1489.                 yadg.busyStop();
  1490.             } else if (response.status == 'failed') {
  1491.                 yadg.failed_callback();
  1492.             } else  {
  1493.                 var delay = function() { yadg.getResult(response.url); };
  1494.                 window.setTimeout(delay, 1000);
  1495.             }
  1496.         });
  1497.         request.send();
  1498.     },
  1499.  
  1500.     printError : function(message, template_error) {
  1501.         this.responseDiv.innerHTML = "";
  1502.         this.responseDiv.appendChild(document.createTextNode(message));
  1503.         if (!template_error) {
  1504.             this.lastStateError = true;
  1505.  
  1506.             // there was a non template related error, so for consistencies sake clear the last ReleaseResult from the
  1507.             // render cache
  1508.             yadg_renderer.clearCached();
  1509.         }
  1510.     },
  1511.  
  1512.     failed_callback : function() {
  1513.         yadg.printError(yadg.standardError);
  1514.         yadg.busyStop();
  1515.     },
  1516.  
  1517.     failed_authentication_callback : function() {
  1518.         yadg.printError(yadg.authenticationError);
  1519.         yadg.busyStop();
  1520.     },
  1521.  
  1522.     busyStart : function() {
  1523.         this.isBusy = true;
  1524.         this.button.setAttribute('disabled',true);
  1525.         this.button.value = "Please wait...";
  1526.         this.input.setAttribute('disabled',true);
  1527.         this.scraperSelect.setAttribute('disabled',true);
  1528.         this.formatSelect.setAttribute('disabled',true);
  1529.     },
  1530.  
  1531.     busyStop : function() {
  1532.         this.button.removeAttribute('disabled');
  1533.         this.button.value = "Fetch";
  1534.         this.input.removeAttribute('disabled');
  1535.         this.scraperSelect.removeAttribute('disabled');
  1536.         this.formatSelect.removeAttribute('disabled');
  1537.         this.isBusy = false;
  1538.     },
  1539.  
  1540.     prepareRawResponse : function(rawData) {
  1541.         var result = {};
  1542.  
  1543.         result.artists = false;
  1544.         result.year = false;
  1545.         result.title = false;
  1546.         result.label = false;
  1547.         result.catalog = false;
  1548.         result.genre = false;
  1549.         result.style = false;
  1550.         result.tags = false;
  1551.         result.is_various = false;
  1552.         result.flat_artist_string = false;
  1553.  
  1554.         if (rawData.artists.length > 0) {
  1555.             result.artists = {};
  1556.  
  1557.             for (var i = 0; i < rawData.artists.length; i++) {
  1558.                 var artist = rawData.artists[i];
  1559.                 if (!artist["isVarious"]) {
  1560.                     result.artists[artist["name"]] = artist["types"];
  1561.                 } else {
  1562.                     result.is_various = true;
  1563.                 }
  1564.             }
  1565.         }
  1566.         if (rawData.discs.length > 0) {
  1567.             for (var k = 0; k < rawData.discs.length; k++) {
  1568.                 var disc = rawData.discs[k];
  1569.                 for (var l = 0; l < disc["tracks"].length; l++) {
  1570.                     var track = disc["tracks"][l];
  1571.                     for (var m = 0; m < track["artists"].length; m++) {
  1572.                         var name = track["artists"][m]["name"],
  1573.                             type = track["artists"][m]["types"];
  1574.  
  1575.                         var newTypes = null;
  1576.                         if (name in result.artists) {
  1577.                             newTypes = result.artists[name].concat(type);
  1578.                             // deduplicate new types array
  1579.                             for(var i = 0; i < newTypes.length; ++i) {
  1580.                                 for(var j = i+1; j < newTypes.length; ++j) {
  1581.                                     if(newTypes[i] === newTypes[j])
  1582.                                         newTypes.splice(j--, 1);
  1583.                                 }
  1584.                             }
  1585.                         } else {
  1586.                             newTypes = type;
  1587.                         }
  1588.  
  1589.                         result.artists[name] = newTypes;
  1590.                     }
  1591.                 }
  1592.             }
  1593.         }
  1594.         for (var i = 0; i < rawData['releaseEvents'].length; i++) {
  1595.             var event = rawData['releaseEvents'][i];
  1596.             if (event.date) {
  1597.                 result.year = event.date.match(/\d{4}/)[0];
  1598.                 if (result.year.length != 4) {
  1599.                     result.year = false;
  1600.                 } else {
  1601.                     break;
  1602.                 }
  1603.             }
  1604.         }
  1605.         if (rawData.title) {
  1606.             result.title = rawData.title;
  1607.         }
  1608.         if (rawData.labelIds.length > 0) {
  1609.             var labelId = rawData['labelIds'][0];
  1610.             if (labelId.label) {
  1611.                 result.label = labelId.label;
  1612.             }
  1613.             if (labelId.catalogueNrs.length > 0) {
  1614.                 result.catalog = labelId.catalogueNrs[0];
  1615.             }
  1616.         }
  1617.         if (rawData.genres.length > 0) {
  1618.             result.genre = rawData.genres;
  1619.         }
  1620.         if (rawData.styles.length > 0) {
  1621.             result.style = rawData.styles;
  1622.         }
  1623.         if (result.genre != false && result.style != false) {
  1624.             result.tags = rawData.genres.concat(rawData.styles);
  1625.         } else if (result.genre != false) {
  1626.             result.tags = rawData.genres;
  1627.         } else if (result.style != false) {
  1628.             result.tags = rawData.styles;
  1629.         }
  1630.  
  1631.         if (result.tags != false) {
  1632.             result.tag_string = "";
  1633.             result.tag_string_nodots = "";
  1634.  
  1635.             for (var i = 0; i < result.tags.length; i++) {
  1636.                 result.tag_string = result.tag_string + result.tags[i].replace(/\s+/g,'.');
  1637.                 result.tag_string_nodots = result.tag_string_nodots + result.tags[i].replace(/\s+/g,' ');
  1638.                 if (i != result.tags.length-1) {
  1639.                     result.tag_string = result.tag_string + ', ';
  1640.                     result.tag_string_nodots = result.tag_string_nodots + ', ';
  1641.                 }
  1642.             }
  1643.         }
  1644.  
  1645.         if (result.artists != false) {
  1646.             // count the artists
  1647.             result.artists_length = 0;
  1648.             result.artist_keys = [];
  1649.             result.effective_artist_count = 0;
  1650.  
  1651.             for (var i in result.artists) {
  1652.                 if (result.artists.hasOwnProperty(i)) {
  1653.                     result.artists_length++;
  1654.                     result.artist_keys.push(i);
  1655.                     result.effective_artist_count += result.artists[i].length;
  1656.                 }
  1657.             }
  1658.         }
  1659.  
  1660.         if (result.artists_length == 0) {
  1661.             result.artists = false;
  1662.         } else {
  1663.             // create a flat string of all the main artists
  1664.             var artist_string = "";
  1665.  
  1666.             for (var i = 0; i < result.artists_length; i++) {
  1667.                 if (result.artists[result.artist_keys[i]].indexOf("main") != -1) {
  1668.                     if (artist_string != "" && i < result.artists_length - 2) {
  1669.                         artist_string = artist_string + ", ";
  1670.                     } else if (artist_string != "" && i < result.artists_length - 1) {
  1671.                         artist_string = artist_string + " & ";
  1672.                     }
  1673.                     artist_string = artist_string + result.artist_keys[i];
  1674.                 }
  1675.             }
  1676.  
  1677.             result.flat_artist_string = artist_string;
  1678.         }
  1679.  
  1680.         return result;
  1681.     }
  1682. };
  1683.  
  1684. yadg_sandbox.init(function() {
  1685.     if (factory.init()) { // returns true if we run on a valid location
  1686.         yadg.init();
  1687.     }
  1688. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement