lulzScript

DA Conglomerator 1.5.4 [2019-05-19]

Feb 19th, 2015
695
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name           DA Conglomerator
  3. // @namespace      http://lulz.net/
  4. // @version        1.5.4
  5. // @description    Extracts all submissions from a DeviantArt gallery and displays them as a list of links in a new window. A button "Conglomerate" is inserted into the galery page which activates the script. Checkboxes allow to set specific options for conglomeration. See the tooltip info (move mouse cursor onto the checkboxes) for further explanation of the options. Install guide, updates, changelog and other scripts @ http://pastebin.com/u/lulzScript
  6. //
  7. // @include        http*://*.deviantart.com/*/gallery/*
  8. // @include        http*://*.deviantart.com/*/art/*
  9. //
  10. // @run-at         document-start
  11. // @grant          unsafeWindow
  12. // @grant          GM_xmlhttpRequest
  13. // ==/UserScript==
  14.  
  15. //Some constants
  16. //Default is up to 3 retries for a page to load.
  17. var congRetries = 3;
  18. //DA only shows 24 Images per page. This is a fixed value by DA for nonpaid accounts and cannot be changed as of now.
  19. //Other values will leave out images.
  20. var daImgsPerPage = 24;
  21.  
  22. //Size of the thumbnails in pixels;
  23. var thumbnailSize = 150;
  24.  
  25.  
  26. //When each request either loaded or gave an error, the rCount should be back at 0.
  27. //Pending downlaods lead to rCount > 0
  28. function checkIfDone(gsrc)
  29. {
  30.   if (rCount[gsrc] == 0)
  31.     lStatus[gsrc].innerHTML = '<b> Done!</b>';
  32. }
  33.  
  34. //Function called when the "GET" request was successful.
  35. //gsrc = index for gallery/scraps source
  36. //req = XMLHttpRequest object of the loaded page
  37. //sCount = submission number within the conglomerator window
  38. //lElement = reference to the link element in the conglomerator window.
  39. function onRetFlashURL (gsrc, req, sCount, lElement)
  40. {
  41.   var URLFound = false;
  42.   //Get the Flash URL from the response text and insert it into the conglomerator window
  43.   var embed = req.responseText.match(/<embed [^>]*?>/);
  44.   if (embed)
  45.   {
  46.     var fURL = embed[0].match(/src=\"([^\"]*?)\"/);
  47.     if (fURL)
  48.       URLFound = true;
  49.   }
  50.  
  51.   if ( URLFound )
  52.     congSetLineElement (lElement, fURL[1]);
  53.   else
  54.     lElement[1].innerHTML = '<b>[Error determining Flash URL]</b>';
  55.  
  56.   //Decrease request counter and check if rCount = 0.
  57.   rCount[gsrc]--;
  58.   checkIfDone(gsrc);
  59. }
  60.  
  61. //Function called when the "GET" request failed.
  62. //gsrc = index for gallery/scraps source
  63. //req = XMLHttpRequest object of the failed request
  64. //sCount = submission number within the conglomerator window
  65. //lElement = reference to the link element in the conglomerator window.
  66. function onRetFlashURLErr (gsrc, req, sCount, lElement)
  67. {
  68.   //If the "HEAD" request failed, show message in the conglomerator window
  69.   lElement[1].innerHTML = '<b>[Error determining Flash URL]</b>';
  70.  
  71.   //Decrease request counter and check if rCount = 0.
  72.   rCount[gsrc]--;
  73.   checkIfDone(gsrc);
  74.  
  75. }
  76.  
  77. //Send a "GET" request to get a page with the embed-code of the flash object from which the URL to the swf can be extracted
  78. //gsrc = index for gallery/scraps source
  79. //url = URL of a temporary DA link.
  80. //sCount = submission number within the conglomerator window
  81. //lElement = reference to the link element in the conglomerator window.
  82. //retry = counter that indicates the current number of retries.
  83. //After [congRetries] failed retries, the function fails.
  84.  
  85. function retFlashURL (gsrc, url, sCount, lElement, retry)
  86. {
  87.   var req = GM_xmlhttpRequest
  88.   (
  89.     {
  90.       url: url,
  91.       method: "GET",
  92.       onreadystatechange: function (req)
  93.       {
  94.         if (req.readyState == 4)
  95.         {
  96.           if ( (req.status >= 200) && (req.status < 400) )
  97.             //If response was sucessfully loaded
  98.             onRetFlashURL (gsrc, req, sCount, lElement);
  99.           else
  100.           {
  101.             //On error retry up to [congRetries] times. Otherwise call error handler.
  102.             if ( retry < congRetries )
  103.               retFlashURL (gsrc, url, sCount, lElement, retry+1);
  104.             else
  105.               onRetFlashURLErr (gsrc, req, sCount, lElement);
  106.           }
  107.         }
  108.       }
  109.     }
  110.   );
  111. }
  112.  
  113.  
  114. //Function called when the "HEAD" request was successfully.
  115. //gsrc = index for gallery/scraps source
  116. //req = XMLHttpRequest object of the loaded page
  117. //sCount = submission number within the conglomerator window
  118. //lElement = reference to the link element in the conglomerator window.
  119. function onRetFinalURL (gsrc, req, sCount, lElement)
  120. {
  121.   //Get the final URL from the "loaction" Header and insert it into the conglomerator window
  122.   var loc = req.finalUrl;
  123.  
  124.   congSetLineElement (lElement, loc);
  125.  
  126.   //Decrease request counter and check if rCount = 0.
  127.   rCount[gsrc]--;
  128.   checkIfDone(gsrc);
  129.  
  130. }
  131.  
  132. //Function called when the "HEAD" request failed.
  133. //gsrc = index for gallery/scraps source
  134. //req = XMLHttpRequest object of the failed request
  135. //sCount = submission number within the conglomerator window
  136. //lElement = reference to the link element in the conglomerator window.
  137. function onRetFinalURLErr (gsrc, req, sCount, lElement, ourl)
  138. {
  139.   //If the "HEAD" request failed, show message in the conglomerator window
  140.   lElement[1].innerHTML = '<b>[Error determining final URL]</b>';
  141.  
  142.   //Decrease request counter and check if rCount = 0.
  143.   rCount[gsrc]--;
  144.   checkIfDone(gsrc);
  145.  
  146. }
  147.  
  148. //Send a "HEAD" request to get a response with the actual location from the temporary link
  149. //gsrc = index for gallery/scraps source
  150. //url = URL of a temporary DA link.
  151. //sCount = submission number within the conglomerator window
  152. //lElement = reference to the link element in the conglomerator window.
  153. //retry = counter that indicates the current number of retries.
  154. //After [congRetries] failed retries, the function fails.
  155.  
  156. function retFinalURL (gsrc, url, sCount, lElement, retry)
  157. {
  158.   var req = GM_xmlhttpRequest
  159.   (
  160.     {
  161.       url: url,
  162.       method: "HEAD",
  163.       onreadystatechange: function (req)
  164.       {
  165.         if (req.readyState == 4)
  166.         {
  167.           if ( ((req.status >= 400) && (req.finalURL != url)) || (req.status >= 200) && (req.status < 400) )
  168.             onRetFinalURL (gsrc, req, sCount, lElement);
  169.           else
  170.           {
  171.             //On error retry up to [congRetries] times. Otherwise call error handler.
  172.             if ( retry < congRetries )
  173.               retFinalURL (gsrc, url, sCount, lElement, retry+1);
  174.             else
  175.               onRetFinalURLErr (gsrc, req, sCount, lElement, url);
  176.           }
  177.         }
  178.       }
  179.     }
  180.   );
  181. }
  182.  
  183. function checkForVideoContent (req)
  184. {
  185.   //Find DA movie player tag
  186.   var daFilmPlayer = req.responseText.match(/<div *class=\"da-film-player[^>]*?>/i);
  187.   if ( daFilmPlayer )
  188.   {
  189.     //Global match for all available movie qualities
  190.     var playerSources = daFilmPlayer[0].match(/&quot;src&quot;:&quot;[^]*?&quot;/ig);
  191.     if ( playerSources )
  192.     {
  193.       //Get last match (should be the best quality), remove backslashes and extract URL
  194.       var submURL = playerSources[playerSources.length-1].replace (/\\/g, '').match(/&quot;src&quot;:&quot;([^]*?)&quot;/i);
  195.       return([submURL[1]]);
  196.     }
  197.   }
  198.  
  199.   //If nothing was found, return null
  200.   return (null);
  201.  
  202. }
  203.  
  204. function checkForDownloadButton (req)
  205. {
  206.   var submURL = req.responseText.match(/<a *class=\"[^\"]*?dev-page-download[^\"]*?\"[^]*?href=\"([^\"]*?)\"/i);
  207.   if (submURL)
  208.     return ([submURL[1].replace(/&amp;/, '&')]);
  209.  
  210.   //If nothing was found, return null
  211.   return (null);
  212. }
  213.  
  214. function checkForImageViewer (req)
  215. {
  216.   var submURL1 = req.responseText.match(/<img [^>]*?class=\" *dev-content-full *\"[^>]*?>/i);
  217.  
  218.   if (!submURL1)
  219.     var submURL1 = req.responseText.match(/<img [^>]*?class=\" *dev-content-normal *\"[^>]*?>/i);
  220.  
  221.   if (submURL1)
  222.   {
  223.     var submURL2 = submURL1[0].match(/src=\"([^\"]*?)\"/i);
  224.     if (submURL2)
  225.       return ([submURL2[1]]);
  226.   }
  227.   //If nothing was found, return null
  228.   return (null);
  229. }
  230.  
  231.  
  232. function checkForFlashContent (req)
  233. {
  234.   //Find the sandbox-link of the flash content
  235.   var sbflashURL = req.responseText.match(/<iframe *class=\"flashtime\"[^]*?src=\"([^\"]*?)\"[^>]*?/i);
  236.   if ( sbflashURL )
  237.     return ([sbflashURL[1]]);
  238.  
  239.   //If nothing was found, return null
  240.   return (null);
  241. }
  242.  
  243.  
  244. function checkForEmbeddedImages (req)
  245. {
  246.   var submURLs_ = req.responseText.match(/class=\"[^\"]*?embedded-deviation[^\"]*?\"[^]*?data-fullview=\"[^\"]*?\"/ig);
  247.   if ( submURLs_ )
  248.   {
  249.     var submURLs = [];
  250.  
  251.     for (var i=0; i < submURLs_.length; i++)
  252.     {
  253.       var submURL = submURLs_[i].match(/data-fullview=\"([^\"]*)\"/);
  254.       if ( submURL )
  255.         submURLs.push(submURL[1]);
  256.     }
  257.  
  258.     if (submURLs.length > 0)
  259.       return (submURLs);
  260.   }
  261.  
  262.   //If nothing was found, return null
  263.   return (null);
  264.  
  265. }
  266.  
  267.  
  268. //Function called when a submission page was successfully loaded.
  269. //gsrc = index for gallery/scraps source
  270. //req = XMLHttpRequest object of the loaded page
  271. //sCount = submission number within the conglomerator window
  272. //lElement = reference to the link element in the conglomerator window.
  273. function onSubm (gsrc, req, sCount, lElement)
  274. {
  275.   var submURLStr = null;
  276.  
  277.   //Get the submission URL from the page source
  278.  
  279.  
  280.   //Check for movie first
  281.   //If submission is a movie, don't use download links, but extract URL(s) from DA movie viewer
  282.   submURLStr = checkForVideoContent (req);
  283.  
  284.   //If no movie try the download button
  285.   if ( !submURLStr )
  286.     submURLStr = checkForDownloadButton (req);
  287.  
  288.   //If no download button try image viewer
  289.   if ( !submURLStr )
  290.     submURLStr = checkForImageViewer (req);
  291.  
  292.   //If no image viewer try flash content
  293.   var flash = false;
  294.   if ( !submURLStr )
  295.   {
  296.     submURLStr = checkForFlashContent (req);
  297.     flash = true;
  298.   }
  299.  
  300.   //If no flash content try embedded images in literature
  301.   if ( !submURLStr )
  302.     submURLStr = checkForEmbeddedImages (req);
  303.  
  304.   //if content is found, insert link into conglomerator window
  305.   if ( submURLStr )
  306.   {
  307.     //If the content is Flash, the actual URL of the swf has to be extracted from the response text of another request.
  308.     if (flash)
  309.     {
  310.       //Increase request counter for additional request.
  311.       rCount[gsrc]++;
  312.       setTimeout (retFlashURL, 0, gsrc, submURLStr[0], sCount, lElement, 0);
  313.     }
  314.     else
  315.     {
  316.       //If option is set to retieve the final URLs from the temporary ones first, do so
  317.       if ( retrieveFinalURL )
  318.       {
  319.         //Increase request counter for each additional request.
  320.         rCount[gsrc]++;
  321.         setTimeout(retFinalURL, 0, gsrc, submURLStr[0], sCount, lElement, 0);
  322.       }
  323.       else
  324.       {
  325.         //Otherwise insert the temporary links (which will expire after a few mintes)
  326.         congSetLineElement(lElement, submURLStr[0]);
  327.       }
  328.     }
  329.     var prevLElement = lElement;
  330.  
  331.     for (var i=1; i < submURLStr.length; i++)
  332.     {
  333.       var tempLElement = congCreateNewLineElement(gsrc, '', prevLElement, lElement[3] + '.' + (i+1));
  334.       congSetLineElement(tempLElement, submURLStr[i]);
  335.  
  336.       //If the content is Flash, the actual URL of the swf has to be extracted from the response text of another request.
  337.       if (flash)
  338.       {
  339.         //Increase request counter for each additional request.
  340.         rCount[gsrc]++;
  341.         setTimeout (retFlashURL, 0, gsrc, submURLStr[0], sCount, lElement, 0);
  342.       }
  343.       else
  344.       {
  345.         //If option is set to retieve the final URLs from the temporary ones first, do so
  346.         if (retrieveFinalURL)
  347.         {
  348.           //Increase request counter for each additional request.
  349.           rCount[gsrc]++;
  350.           setTimeout(retFinalURL, 0, gsrc, submURLStr[i], sCount, tempLElement, 0);
  351.         }
  352.         else
  353.         {
  354.           //Otherwise insert the temporary links (which will expire after a few mintes)
  355.           congSetLineElement(tempLElement, submURLStr[i]);
  356.         }
  357.       }
  358.       prevLElement = tempLElement;
  359.  
  360.     }
  361.  
  362.     //Decrease request counter and check if rCount = 0.
  363.     rCount[gsrc]--;
  364.     checkIfDone(gsrc);
  365.  
  366.   }
  367.   else
  368.   {
  369.     //If theres is no content found, this is either probably mature content and the user
  370.     //is either not logged in or the account's age setting ("Date of Birth") does not
  371.     //allow mature content. Or it is unsupported/special content like stories/writing
  372.     //that cannot be downloaded.
  373.  
  374.     lElement[1].innerHTML = '<b>[No content link found in submission page - Not logged in? Mature content disabled? Unsupported/special content?]</b>';
  375.  
  376.     //Decrease request counter and check if rCount = 0.
  377.     rCount[gsrc]--;
  378.     checkIfDone(gsrc);
  379.   }
  380.  
  381. }
  382.  
  383. //Function called when a submission page failed to load.
  384. //gsrc = index for gallery/scraps source
  385. //req = XMLHttpRequest object of the failed page
  386. //sCount = submission number within the conglomerator window
  387. //lElement = reference to the link element in the conglomerator window.
  388. function onSubmErr (gsrc, req, sCount, lElement)
  389. {
  390.   //Page could not be loaded. Display Error message.
  391.   lElement[1].innerHTML = '<b>[Error loading submission]</b>';
  392.  
  393.   //Request finished with error. Decrease request counter and check if rCount = 0.
  394.   rCount[gsrc]--;
  395.   checkIfDone(gsrc);
  396. }
  397.  
  398. //Loads a submission page from the gallery/scraps collection asynchronously.
  399. //gsrc = index for gallery/scraps source
  400. //submPageURL = URL of submission page.
  401. //sCount = submission number within the conglomerator window
  402. //lElement = reference to the link element in the conglomerator window.
  403. //retry = counter that indicates the current number of retries.
  404. //After [congRetries] failed retries, the function fails.
  405. function getSubm (gsrc, submPageURL, sCount, lElement, retry)
  406. {
  407.   var req = new XMLHttpRequest();
  408.   //Prepare request with full URL, containing the desired page number
  409.   req.open('GET', submPageURL, true);
  410.   //Function to call when loading state of page changes
  411.   req.onreadystatechange = function (evt)
  412.   {
  413.     //Check if page was loaded (or not)
  414.     if (req.readyState == 4)
  415.     {
  416.       if ( (req.status >= 200) && (req.status < 400) )
  417.         //If page was sucessfully loaded
  418.         onSubm (gsrc, req, sCount, lElement);
  419.       else
  420.       {
  421.         //If page failed to load, retry up to [congRetries] times. Otherwise call error handler.
  422.         if ( retry < congRetries )
  423.           getSubm (gsrc, submPageURL, sCount, lElement, retry+1);
  424.         else
  425.           onSubmErr (gsrc, req, sCount, lElement);
  426.       }
  427.     }
  428.   };
  429.  
  430.   //Sends request and starts loading of the page.
  431.   req.send(null);
  432. }
  433.  
  434.  
  435. function congCreateNewLineElement(gsrc, thumbURL, insertAfter, lineNoTxt)
  436. {
  437.   var span1 = congLinkWin[gsrc].document.createElement('span');
  438.  
  439.   if ( lineNoTxt )
  440.     var lineNo = lineNoTxt;
  441.   else
  442.     var lineNo = sCount[gsrc].toString();
  443.  
  444.   span1.innerHTML = '<br><b>' + lineNo + ': </b>';
  445.  
  446.   var span2 = congLinkWin[gsrc].document.createElement('span');
  447.   var linkObj = congLinkWin[gsrc].document.createElement('a');
  448.   //This attribute will open a new page if the link is clicked in the conglomerator window.
  449.   linkObj.setAttribute('target', '_blank');
  450.  
  451.   if ( thumbURL )
  452.   {
  453.     var thumbnail = congLinkWin[gsrc].document.createElement('img');
  454.     thumbnail.setAttribute('src', thumbURL);
  455.     thumbnail.setAttribute('height', thumbnailSize + 'px');
  456.  
  457.     span1.insertBefore(thumbnail, null); //lElement[0] = span
  458.  
  459.     thumbnail.style.verticalAlign = "middle";
  460.     thumbnail.style.marginRight = '10px';
  461.   }
  462.  
  463.   span1.insertBefore(span2, null);
  464.  
  465.   var insertAt = null;
  466.   if ( insertAfter )
  467.     insertAt = insertAfter[0].nextSibling;
  468.  
  469.   //Add the newly created line element to the conglomerator window
  470.   congLinkWin[gsrc].document.body.insertBefore(span1, insertAt);
  471.  
  472.   return ( [span1, span2, linkObj, lineNo] );
  473.  
  474. }
  475.  
  476. function congSetLineElement(lElement, sURL)
  477. {
  478.   //Insert download link into link list
  479.   //Link displayed as text
  480.   lElement[2].innerHTML = sURL;
  481.   //Also set the href attribut, to make the link clickable
  482.   lElement[2].setAttribute('href', sURL);
  483.   lElement[1].innerHTML = '';
  484.   lElement[0].insertBefore(lElement[2], null);
  485. }
  486.  
  487. function fixProtocol (URL)
  488. {
  489.   return (daProtocol + URL.replace(/https/, '').replace(/http/, ''));
  490. }
  491.  
  492. //Function called when a submission list page was successfully loaded.
  493. //gsrc = index for gallery/scraps source
  494. //req = XMLHttpRequest object of the loaded page
  495. //no = number of loaded page
  496. function onSubmList (gsrc, req, no)
  497. {
  498.   //Extract all submission IDs
  499.  
  500.   var PDstart = req.responseText.search('data-sigil=\"gallery-torpedo\"');
  501.   var PDend = PDstart + req.responseText.substr(PDstart).search('id=\"gmi-CCommentMaster\"');
  502.   var newResponseText = req.responseText.substring(PDstart, PDend);
  503.  
  504.   //Find thumbnail elements with links to the full image
  505.   //var rawSubmLinks = newResponseText.match(/<a *class=[^>]*?title=[^>]*?(?:data-super-img=[^>]*?|)>/gi);
  506.   var rawSubmLinks = newResponseText.match(/<span[^>]+?class=\"thumb[^]*?<\/span>/gi);
  507.  
  508.   //Continue as long as there are thumbnail elememts found
  509.   if ( rawSubmLinks )
  510.   {
  511.     //Display page number
  512.     var span = congLinkWin[gsrc].document.createElement('span');
  513.     span.innerHTML = '<br></br><b>Page ' + no + '</b><br>';
  514.     congLinkWin[gsrc].document.body.insertBefore(span, null);
  515.  
  516.     //Iterate through all found thumbnails
  517.     for (var i=0; i < rawSubmLinks.length; i++)
  518.     {
  519.       //Create a new line element for the submission in the conglomerator window
  520.  
  521.       var thumbURLStr = null;
  522.  
  523.       //Optionally get thumbnail URL and insert thumbnail in conglomerator window
  524.       if (showThumbnails)
  525.       {
  526.         var thumbURL = rawSubmLinks[i].match(/<img[^]*?src=\"([^\"]*?)\"[^>]*?>/);
  527.         if ( thumbURL )
  528.           thumbURLStr = thumbURL[1];
  529.       }
  530.  
  531.       var lElement = congCreateNewLineElement(gsrc, thumbURLStr, null, null);
  532.  
  533.  
  534.       //If checkbox is checked, only get links fromn the submission page.
  535.       if ( submpOnly )
  536.         submURL = null;
  537.       else
  538.       {
  539.         //Try to extract the URL from "data-super-full-img"
  540.         var submURL = rawSubmLinks[i].match(/data-super-full-img=\"([^\"]*)\"/);
  541.  
  542.         //If there is no "data-super-full-img" alternatively extract the URL from "data-super-img"
  543.         if ( !submURL )
  544.           var submURL = rawSubmLinks[i].match(/data-super-img=\"([^\"]*)\"/);
  545.  
  546.       }
  547.  
  548.  
  549.       //If either "data-super-full-img" or "data-super-img" was found, create a link in the conglomerator window
  550.       if ( submURL )
  551.       {
  552.         //Insert download link into link list
  553.         congSetLineElement (lElement, submURL[1]);
  554.       }
  555.       //Otherwise it is either locked (mature) content, special content (or both) or the
  556.       //checkbox for conglomeration from the submission page only was checked.
  557.       //In this case try to extract the link from the submission page
  558.       else
  559.       {
  560.         var submPageURL = rawSubmLinks[i].match(/href=\"([^\"]*)\"/);
  561.         if ( submPageURL )
  562.         {
  563.  
  564.           //Increase request counter
  565.           rCount[gsrc]++;
  566.  
  567.           //Load submission page asynchronously.
  568.           //function fixProtocol will make sure that the correct protocol is used
  569.           getSubm (gsrc, fixProtocol(submPageURL[1]), sCount[gsrc], lElement, 0);
  570.           lElement[1].innerHTML = '<b>loading...</b>';
  571.  
  572.         }
  573.         //If there is no link display message in conglomerator window
  574.         else
  575.           lElement[1].innerHTML = '<b>[No submission page link found]</b>';
  576.  
  577.       }
  578.  
  579.  
  580.       //Increase submission counter
  581.       sCount[gsrc]++;
  582.  
  583.     }
  584.     //Increase request counter
  585.     rCount[gsrc]++;
  586.  
  587.     //Load next submission list page
  588.     getSubmList (gsrc, no+1, 0);
  589.   }
  590.   else
  591.   {
  592.     //There are no more pages. Display message.
  593.     var span = congLinkWin[gsrc].document.createElement('span');
  594.     span.innerHTML = '<br><br><b>No more pages!<b>';
  595.     congLinkWin[gsrc].document.body.insertBefore(span, null);
  596.   }
  597.  
  598.   //Request finished successfully. Decrease request counter and check if rCount = 0.
  599.   rCount[gsrc]--;
  600.   checkIfDone(gsrc);
  601.  
  602. }
  603.  
  604. //Function called when a submission list page failed to load.
  605. //gsrc = index for gallery/scraps source
  606. //req = XMLHttpRequest object of the failed page
  607. //no = number of loaded page
  608. function onSubmListErr (gsrc, req, no)
  609. {
  610.   //Page could not be loaded. Display Error message.
  611.   var span = congLinkWin[gsrc].document.createElement('span');
  612.   span.innerHTML = '<br><br><b>Error - cannot load page ' + no + '!<br/>Further conglomeration stoppped.</b>';
  613.   congLinkWin[gsrc].document.body.insertBefore(span, null);
  614.  
  615.   //Request finished with error. Decrease request counter and check if rCount = 0.
  616.   rCount[gsrc]--;
  617.   checkIfDone(gsrc);
  618. }
  619.  
  620. //Loads a submission list page from the gallery/scraps collection asynchronously.
  621. //gsrc = index for gallery/scraps source
  622. //no = Nummer of list page to load
  623. //retry = counter that indicates the current number of retries.
  624. //After [congRetries] failed retries, the function fails.
  625. function getSubmList (gsrc, no, retry)
  626. {
  627.   var req = new XMLHttpRequest();
  628.   //Prepare request with full URL, containing the desired page number
  629.   req.open('GET', submBaseURL[gsrc] + (no-1) * daImgsPerPage, true);
  630.   //Function to call when loading state of page changes
  631.   req.onreadystatechange = function (evt)
  632.   {
  633.     //Check if page was loaded (or not)
  634.     if (req.readyState == 4)
  635.     {
  636.  
  637.       if ( (req.status >= 200) && (req.status < 400) )
  638.         //If page was sucessfully loaded
  639.         onSubmList (gsrc, req, no);
  640.       else
  641.       {
  642.         //If page failed to load, retry up to [congRetries] times. Otherwise call error handler.
  643.         if ( retry < congRetries )
  644.           getSubmList (gsrc, no, retry+1);
  645.         else
  646.           onSubmListErr (gsrc, req, no);
  647.       }
  648.     }
  649.   };
  650.  
  651.   //Sends request and starts loading of the page.
  652.   req.send(null);
  653. }
  654.  
  655. //Global variables:
  656.  
  657. //Used in htmlUnescapeURL
  658. var dummyElement;
  659. //Base URL of DA, including protocol and subdomain
  660. var daBaseURL;
  661. //Used Protocol (http/https)
  662. var daProtocol;
  663. //Base URLs of gallery/scraps
  664. var submBaseURL = [,];
  665. var submBaseURL = [,];
  666.  
  667. //Reference to new link window
  668. var congLinkWin = [,];
  669. var congLinkWin = [,];
  670.  
  671. //Counter for submission index
  672. var sCount = [,];
  673. //Request counter. Used to determine when all submissions are loaded.
  674. var rCount = [,];
  675.  
  676.  
  677. //Name of DA user whose galery/scraps are being conglomerated
  678. var daUsername;
  679. //Reference to status message in link window
  680. var lStatus = [,];
  681. var lStatus = [,];
  682.  
  683. //State of the congCB checkbox
  684. var submpOnly;
  685. //State of the congCB2 checkbox
  686. var retrieveFinalURL;
  687. //State of the congCB3 checkbox
  688. var showThumbnails;
  689. //Selection of gallery and/or scraps to be conglomerated
  690. var doCong = [,];
  691.  
  692. var ACDummy;
  693.  
  694. //Main script function. Called when conglomerator button is clicked
  695. function congStart(e)
  696. {
  697.   ACDummy = new AudioContext();
  698.  
  699.   //Prevents the form's default action for a button
  700.   e.preventDefault();
  701.  
  702.   //Get state of congCB checkbox
  703.   submpOnly = congCB_fsp[0].checked;
  704.  
  705.   //Get state of congCB2 checkbox
  706.   retrieveFinalURL = congCB_fu[0].checked;
  707.  
  708.   //Get state of congCB3 checkbox
  709.   showThumbnails = congCB_st[0].checked;
  710.  
  711.   //Get state of gallery/scraps selection
  712.   doCong[0] = congCB_g[0].checked;
  713.   doCong[1] = congCB_s[0].checked;
  714.  
  715.  
  716.   //Create dummy element used in htmlUnescapeURL function
  717.   dummyElement = document.createElement('span');
  718.  
  719.   //Get DA base URL (including protocol and a possible subdomain)
  720.   var daBaseURL_ = document.location.href.match(/(([^\/]*):\/\/[^\.]*\.deviantart\.com\/([^\/]*)\/)gallery\//);
  721.   if ( daBaseURL_ )
  722.   {
  723.     daBaseURL = daBaseURL_[1];
  724.     daProtocol = daBaseURL_[2]; //Needed because DA uses mixed http/https content that has to be fixed when fetching the thumbnail page
  725.  
  726.     daUsername = daBaseURL_[3];
  727.  
  728.     submBaseURL[0] = daBaseURL + 'gallery/?catpath=%2F&offset=';
  729.     submBaseURL[1] = daBaseURL + 'gallery/?catpath=scraps%2F&offset=';
  730.  
  731.  
  732.  
  733.     //Open new window(s) for extracted submission links
  734.     for (var i=0; i < 2; i++)
  735.     {
  736.       if (doCong[i])
  737.       {
  738.         congLinkWin[i] = unsafeWindow.open();
  739.         if ( congLinkWin[i] )
  740.         {
  741.  
  742.           //Add title to link window
  743.           var span = congLinkWin[i].document.createElement('span');
  744.           switch (i)
  745.           {
  746.             case 0:
  747.               span.innerHTML = '<b>List of ' + daUsername + '\'s gallery:<b>';
  748.               //Set title of new window
  749.               congLinkWin[0].document.title = 'DA conglomerator - Gallery';
  750.             break;
  751.             case 1:
  752.               span.innerHTML = '<b>List of ' + daUsername + '\'s scraps:<b>';
  753.               //Set title of new window
  754.               congLinkWin[1].document.title = 'DA conglomerator - Scraps';
  755.             break;
  756.           }
  757.  
  758.           congLinkWin[i].document.body.insertBefore(span, null);
  759.  
  760.           //Add status message to link Window
  761.           lStatus[i] = congLinkWin[i].document.createElement('span');
  762.           lStatus[i].innerHTML = '<b> Loading...</b>';
  763.           congLinkWin[i].document.body.insertBefore(lStatus[i], null);
  764.  
  765.           //Reset submission and request counter
  766.           sCount[i] = 1;
  767.           rCount[i] = 1;
  768.  
  769.           //At this point daBaseURL and submBaseURL both matched correctly.
  770.           //Load first submission list page. Page counter begins at 1
  771.           getSubmList (i, 1, 0);
  772.         }
  773.       }
  774.     }
  775.   }
  776. }
  777.  
  778. function insertButton()
  779. {
  780.   //Find location of gallery controls
  781.   var gmi = document.getElementById('gmi-GalleryEditor');
  782.   if (gmi)
  783.   {
  784.     var lis = gmi.getElementsByTagName('li');
  785.     for (var i=0; i < lis.length; i++)
  786.     {
  787.       if ( lis[i].getAttribute('class').search(/browse/) == 0 )
  788.       {
  789.         var browsebar = lis[i].parentNode;
  790.         break;
  791.       }
  792.     }
  793.  
  794.     //If found, insert conglomerator button and checkbox/text
  795.     if ( browsebar )
  796.     {
  797.  
  798.       //Insert button element and a line break
  799.       browsebar.insertBefore(congButton, null);
  800.       browsebar.insertBefore(document.createElement('br'), null);
  801.  
  802.       //Insert checkbox elements and a line breaks
  803.       browsebar.insertBefore(congCB_g[1], null);
  804.       browsebar.insertBefore(document.createElement('br'), null);
  805.  
  806.       browsebar.insertBefore(congCB_s[1], null);
  807.       browsebar.insertBefore(document.createElement('br'), null);
  808.       browsebar.insertBefore(document.createElement('br'), null);
  809.  
  810.       browsebar.insertBefore(congCB_fsp[1], null);
  811.       browsebar.insertBefore(document.createElement('br'), null);
  812.  
  813.       browsebar.insertBefore(congCB_fu[1], null);
  814.       browsebar.insertBefore(document.createElement('br'), null);
  815.  
  816.       browsebar.insertBefore(congCB_st[1], null);
  817.       browsebar.insertBefore(document.createElement('br'), null);
  818.  
  819.       buttonInserted = true;
  820.     }
  821.   }
  822. }
  823.  
  824. function createCheckBox (checked, text, tooltip)
  825. {
  826.   var CB = [,];
  827.  
  828.   //Create checkbox for extracting links from submission page only
  829.   CB[0] = document.createElement('input');
  830.   //Set input type to checkbox
  831.   CB[0].setAttribute('type', 'checkbox');
  832.   //Set default state
  833.   CB[0].checked = checked;
  834.  
  835.   //Create checkbox text label
  836.   CB[1] = document.createElement('label');
  837.   //Reduce checkbox font size
  838.   CB[1].style.fontSize = '8pt';
  839.   //Set checkbox text
  840.   CB[1].innerHTML = text;
  841.   //Add tooltip info
  842.   CB[1].title = tooltip;
  843.  
  844.   //insert checkbox into label element
  845.   CB[1].insertBefore(CB[0], CB[1].firstChild);
  846.  
  847.   return(CB);
  848. }
  849.  
  850.  
  851. //Flag that is later set to true if button was inserted.
  852. var buttonInserted = false;
  853.  
  854. //Conglomerator button
  855. //=====================================================
  856.  
  857. //Create button for conglomerator script
  858. var congButton = document.createElement('button');
  859. //Set button text
  860. congButton.innerHTML = 'Conglomerate';
  861. //Set button style to DA style
  862. congButton.setAttribute('class', 'smbutton');
  863. //Set function to call on a click
  864. congButton.addEventListener ('click', congStart, false);
  865. //Add tooltip info
  866. congButton.title = 'Extract all submissions from this gallery and display them as a list of links in a new window.';
  867. //=====================================================
  868.  
  869.  
  870. //Conglomerator checkbox: "from subm. page"
  871. //=====================================================
  872.  
  873. var cToolTip =
  874. 'Conglomerate links from the actual submission page.\n' +
  875. 'This takes longer but will always get the links with the highest image quality (eg. from the "Download" button on submission page)\n' +
  876. 'Otherwise the links are extracted from the thumbnail page, which don\'t always point to the best image quality';
  877.  
  878. var congCB_fsp = createCheckBox (true, 'from subm. page', cToolTip);
  879.  
  880.  
  881. //Conglomerator checkbox: "final URL"
  882. //=====================================================
  883.  
  884. var cToolTip =
  885. 'Retrieve the final download server URLs.\n\n' +
  886. 'DA creates temporary links to images that will expire after a few minutes.\n' +
  887. 'If conglomeration takes too long, links may expire before they can be downloaded.\n' +
  888. 'This option will retrieve the final download server URLs which don\'t expire, but conglomeration is slower because an additinal requests to the server has to be sent for each link.\n\n' +
  889. 'This option is ignored if option "from subm. page" is not checked.\n\n' +
  890. 'NOTE:\n' +
  891. 'If you\'re blocking third-party cookies, add an exception for "deviantart.com" in the browser\'s cookie settings. Otherwise the final URL cannot be retrieved.';
  892.  
  893. var congCB_fu = createCheckBox (true, 'final URL', cToolTip);
  894.  
  895.  
  896. //Conglomerator checkbox: "Show thumbnails"
  897. //=====================================================
  898.  
  899. var cToolTip =
  900. 'Show thumbnails for each link in the conglomerator window';
  901.  
  902. var congCB_st = createCheckBox (false, 'Show thumbnails', cToolTip);
  903.  
  904.  
  905. //Conglomerator checkbox: "Gallery"
  906. //=====================================================
  907.  
  908. var cToolTip =
  909. 'Conglomerate gallery';
  910.  
  911. var congCB_g = createCheckBox (true, 'Gallery', cToolTip);
  912.  
  913.  
  914. //Conglomerator checkbox: "Scraps"
  915. //=====================================================
  916.  
  917. var cToolTip =
  918. 'Conglomerate scraps';
  919.  
  920. var congCB_s = createCheckBox (true, 'Scraps', cToolTip);
  921. //=====================================================
  922.  
  923.  
  924.  
  925. //Try to insert button into page if page is already available at this time
  926. insertButton();
  927.  
  928. //Function onDCL is called when DOM tree has completely been loaded.
  929. //This is the savest way to start a script.
  930. document.addEventListener ('DOMContentLoaded',
  931.   function onDCL(e)
  932.   {
  933.  
  934.     //If the button wasn't inserted before because the page wasn't
  935.     //available at that time, it will be inserted now.
  936.     if ( !buttonInserted )
  937.       insertButton();
  938.  
  939.   }, false
  940. );
  941.  
  942.  
  943. //Additional, faster way to insert and display the conglomerator button.
  944. //Inernal scripts on the page sometimes seem to block the DOMContentLoaded event until they have executed completely.
  945. //This code will insert the button as soon as (but before) an internal script is called
  946. document.addEventListener ('beforescriptexecute',
  947.   function onDCL(e)
  948.   {
  949.     //Try to insert button, if it hasn't been inserted yet.
  950.     if ( !buttonInserted )
  951.       insertButton();
  952.  
  953.     //Check if the button was inserted somehow (either by this function or by the DOMContentLoaded event listener above)
  954.     if (buttonInserted)
  955.     {
  956.       //Remove this event listener again if button was inserted successfully.
  957.       document.removeEventListener ('beforescriptexecute', onDCL, false);
  958.     }
  959.  
  960.   }, false
  961. );
Advertisement
Add Comment
Please, Sign In to add comment