BeatStars Downloader

Used for automatically downloading BeatStars content

  1. // ==UserScript==
  2. // @name BeatStars Downloader
  3. // @namespace BeatStarsDL
  4. // @match *://www.beatstars.com/*/tracks
  5. // @match *://beatstars.com/*/tracks
  6. // @grant none
  7. // @version 1.0
  8. // @author OliverP
  9. // @description Used for automatically downloading BeatStars content
  10. // @inject-into auto
  11. // ==/UserScript==
  12.  
  13. /*
  14. -----------------------How to use-----------------------
  15. 1. Go into the tracks page of the user you want to download the tracks from
  16. 2. Click on "Load tracks" to load all available tracks of the user (the script is scrolling down automatically to do that)
  17. 3. Click on Download and wait until it completes
  18. 4. A modal will pop-up and allow you to copy the track names and the URLs (in a 2 line per track txt format)
  19. 5, Copy it into your downloader of choice or into the provided Python script
  20. --------------------------------------------------------
  21. */
  22.  
  23. var my_css = '.modal{display:none;position:fixed;z-index:100000;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,0.4)}.modal-content{position:fixed;bottom:0;background-color:#fefefe;width:100%;-webkit-animation-name:slideIn;-webkit-animation-duration:.4s;animation-name:slideIn;animation-duration:.4s}.close{color:#fff;float:right;font-size:28px;font-weight:700}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer}.modal-header{padding:2px 16px;background-color:#5cb85c;color:#fff}.modal-body{padding:2px 16px}';
  24. var new_sty = document.createElement("style");
  25. new_sty.setAttribute("type", "text/css");
  26. new_sty.appendChild(document.createTextNode(my_css));
  27. document.body.appendChild(new_sty);
  28. document.body.innerHTML += '<div id="myModal" class="modal"><div class="modal-content"><div class="modal-header"><span class="close">&times;</span><h2>Download complete</h2></div><div class="modal-body"><p>Links:</p><textarea id="urllinks_dl" style="font-size: 9px;"></textarea><button id="copydl">Copy</button><span id="copyreport" style="color: green;"></span></div></div></div>';
  29.  
  30. const checkElement = async selector => {
  31. while ( document.querySelector(selector) === null) {
  32. await new Promise( resolve => requestAnimationFrame(resolve) )
  33. }
  34. return document.querySelector(selector);
  35. };
  36.  
  37. function sleepFor(sleepDuration){
  38. var now = new Date().getTime();
  39. while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
  40. }
  41.  
  42. function copyText(){ //For the URL copying
  43. var copyText = document.getElementById("urllinks_dl");
  44. var copyReport = document.getElementById("copyreport");
  45.  
  46. copyText.select();
  47. copyText.setSelectionRange(0, 99999);
  48.  
  49. navigator.clipboard.writeText(copyText.value);
  50.  
  51. copyReport.innerHTML = "Successfully copied";
  52. }
  53.  
  54. function download(fileName, fileType, text) {
  55. var blob = new Blob([text], { type: fileType });
  56.  
  57. var a = document.createElement('a');
  58. a.download = fileName;
  59. a.href = URL.createObjectURL(blob);
  60. a.dataset.downloadurl = [fileType, a.download, a.href].join(':');
  61. a.style.display = "none";
  62. document.body.appendChild(a);
  63. a.click();
  64. document.body.removeChild(a);
  65. setTimeout(function() { URL.revokeObjectURL(a.href); }, 1500);
  66. }
  67.  
  68. function preload(){ //Preloads tracks by scrolling until no more load
  69. (function scroll() {
  70. if(window.scrollY != window.scrollMaxY){
  71. window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
  72. setTimeout(scroll, 1000);
  73. }else{
  74. document.body.scrollTop = document.documentElement.scrollTop = 0;
  75. }
  76. })();
  77. }
  78.  
  79. function dlCheck(){ //Starts download
  80. checkElement('.btn-download').then((selector) => {
  81. var dlbtn_el = document.getElementsByClassName('btn-download');
  82. timer = 0;
  83. (function next() {
  84. if(dlbtn_el.length-1>timer) { //Until there are downloadable tracks
  85. console.log((timer+1)+"/"+(dlbtn_el.length-1))
  86. var musiccnt = document.getElementsByClassName("number ng-star-inserted"); var count = musiccnt.length; for(var i = 0; i < count; i++){ if(musiccnt[i].innerHTML.includes(timer)){ music = musiccnt[i]; } }
  87. list += "\n"+music.parentNode.parentNode.childNodes[2].children[0].children[0].innerHTML;
  88. do_download(dlbtn_el[timer], (timer+1), (dlbtn_el.length-1));
  89. list += "\n";
  90. timer += 1;
  91. setTimeout(next, 1000);
  92. }else{
  93. if(dlbtn_el.length-1 == timer){ //When the download is finished
  94. console.log(list);
  95. document.getElementById("urllinks_dl").innerHTML = list.trim();
  96. var modal = document.getElementById("myModal");
  97. modal.style.display = "block";
  98. }
  99. }
  100. })();
  101. });
  102. }
  103.  
  104. async function do_download(item, timer, full_length){
  105. return new Promise((resolve,reject)=>{
  106. item.click();
  107. download(timer, full_length)
  108. resolve();
  109. });
  110.  
  111. }
  112.  
  113. list="" //This list will contain the download links
  114. async function download(timer, full_length){
  115. window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
  116. await new Promise(r => setTimeout(r, 1000));
  117. var downloadbtn = document.getElementsByClassName("mat-button-wrapper"); var count = downloadbtn.length; for(var i = 0; i < count; i++){ if(downloadbtn[i].innerHTML.includes("Download")){ btn = downloadbtn[i]; } }
  118. list+=btn.closest('a').href; //Add download link to the list
  119. var closebtn = document.getElementsByClassName("mat-dialog-title"); var count = closebtn.length; for(var i = 0; i < count; i++){ if(closebtn[i].innerHTML.includes("Free Download")){ closebtn[i].innerHTML += " "+timer+"/"+full_length; btn1 = closebtn[i]; } }
  120. btn1.parentNode.childNodes[1].click();
  121. await new Promise(r => setTimeout(r, 3000));
  122.  
  123. }
  124.  
  125. window.addEventListener("DOMContentLoaded", function(event) { //Adds the buttons to the site
  126. checkElement('.title').then((selector) => {
  127. selector.innerHTML += "<button id='prlbtn'>Load tracks</button><button id='dlbtn'>Download</button>";
  128. var dlbtn = document.getElementById("dlbtn");
  129. dlbtn.onclick = function() {
  130. dlCheck();
  131. }
  132. var prlbtn = document.getElementById("prlbtn");
  133. prlbtn.onclick = function() {
  134. preload();
  135. }
  136. var copydl = document.getElementById("copydl");
  137. copydl.onclick = function() {
  138. copyText();
  139. }
  140. });
  141. });
  142.  
  143. var modal = document.getElementById("myModal");
  144. var span = document.getElementsByClassName("close")[0];
  145.  
  146. // When the user clicks on the close button, close the modal
  147. span.onclick = function() {
  148. modal.style.display = "none";
  149. }
  150.  
  151. // When the user clicks anywhere outside of the modal, close it
  152. window.onclick = function(event) {
  153. if (event.target == modal) {
  154. modal.style.display = "none";
  155. }
  156. }