Spotify Downloader with Lucida

Automates Spotify link submission to Lucida downloader and auto-scrolls the Lucida page undetected.

  1. // ==UserScript==
  2. // @name Spotify Downloader with Lucida
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3
  5. // @description Automates Spotify link submission to Lucida downloader and auto-scrolls the Lucida page undetected.
  6. // @author UniverseDev
  7. // @license GPL-3.0-or-later
  8. // @match *://open.spotify.com/*
  9. // @match https://lucida.to/*
  10. // @icon https://www.google.com/s2/favicons?sz=64&domain=spotify.com
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. if (window.location.href.includes('open.spotify.com')) {
  18. const style = document.createElement('style');
  19.  
  20. style.innerText = `
  21. [role='grid'] {
  22. margin-left: 50px;
  23. }
  24.  
  25. [data-testid='tracklist-row'] {
  26. position: relative;
  27. }
  28.  
  29. .btn {
  30. width: 40px;
  31. height: 40px;
  32. border-radius: 50%;
  33. border: 0;
  34. background-color: #1fdf64;
  35. background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><path d="M17 12v5H3v-5H1v5a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5z"/><path d="M10 15l5-6h-4V1H9v8H5l5 6z"/></svg>');
  36. background-position: center;
  37. background-repeat: no-repeat;
  38. cursor: pointer;
  39. }
  40.  
  41. .btn:hover {
  42. transform: scale(1.1);
  43. }
  44.  
  45. [data-testid='tracklist-row'] .btn {
  46. position: absolute;
  47. top: 50%;
  48. right: 100%;
  49. margin-top: -20px;
  50. margin-right: 10px;
  51. }
  52. `;
  53.  
  54. document.body.appendChild(style);
  55.  
  56. function getTrackURI(trackElement) {
  57. const link = trackElement.querySelector('a[href*="/track/"]');
  58. return link ? link.getAttribute('href').split('/track/')[1] : null;
  59. }
  60.  
  61. function addButton(track) {
  62. const button = document.createElement('button');
  63. button.className = 'btn';
  64. button.onclick = () => {
  65. const trackURI = getTrackURI(track);
  66. if (trackURI) {
  67. const spotifyLink = `https://open.spotify.com/track/${trackURI}`;
  68. window.open(`https://lucida.to?url=${encodeURIComponent(spotifyLink)}`, '_blank');
  69. } else {
  70. console.error("Failed to retrieve track URI.");
  71. }
  72. };
  73. track.appendChild(button);
  74. track.dataset.hasButton = 'true';
  75. }
  76.  
  77. function animate() {
  78. const tracks = document.querySelectorAll('[data-testid="tracklist-row"]');
  79. tracks.forEach(track => {
  80. if (!track.dataset.hasButton) {
  81. addButton(track);
  82. }
  83. });
  84. }
  85.  
  86. setInterval(animate, 1000);
  87. }
  88.  
  89. if (window.location.href.includes('lucida.to')) {
  90. window.addEventListener('load', () => {
  91. const urlParams = new URLSearchParams(window.location.search);
  92. const spotifyLink = urlParams.get('url');
  93.  
  94. if (spotifyLink) {
  95. const inputField = document.querySelector('input#download');
  96. const goButton = document.querySelector('button#go');
  97.  
  98. if (inputField && goButton) {
  99. inputField.value = spotifyLink;
  100. goButton.click();
  101. }
  102. }
  103.  
  104. const scrollInterval = setInterval(() => {
  105. window.scrollBy(0, 100);
  106. if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
  107. clearInterval(scrollInterval);
  108. }
  109. }, 100);
  110. });
  111. }
  112. })();