您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Integrate a download button for tracks on Spotify Web to download audio at 320kbps
// ==UserScript== // @name Spotify Enhancer (Track Downloader) - Cross-Version // @description Integrate a download button for tracks on Spotify Web to download audio at 320kbps // @version 1.4 // @match https://open.spotify.com/* // Adicionando a diretiva @match // @namespace https://greasyfork.org/users/1388220 // ==/UserScript== const API_HEADERS = { 'Host': 'api.spotifydown.com', 'Referer': 'https://spotifydown.com/', 'Origin': 'https://spotifydown.com', }; const BACKOFF_CONFIG = { initialDelay: 1000, maxDelay: 5000, factor: 2 }; const style = document.createElement('style'); style.id = 'spotify-enhancer-320-styles'; document.body.appendChild(style); function applyStyles() { const otherDownloader = document.querySelector('.btn'); style.innerHTML = ` [role='grid'] { margin-left: ${otherDownloader ? '90px' : '50px'}; } [data-testid='tracklist-row'] { position: relative; } .btn-320 { /* button styles */ width: 40px; /* etc */ }`; } function addDownloadButton(element, trackInfo, spotifyId) { if (element.querySelector('.btn-320')) return; const button = document.createElement('button'); button.className = 'btn-320'; button.onclick = function() { initiateDownload(spotifyId, trackInfo, this); }; element.appendChild(button); } function initiateDownload(spotifyId, trackInfo, button) { button.classList.add('loading'); let delay = BACKOFF_CONFIG.initialDelay; const downloadAttempt = function() { downloadTrack(spotifyId).then(response => { const link = document.createElement('a'); link.href = response.link; link.download = `${trackInfo.title} - ${trackInfo.artist}.mp3`; document.body.appendChild(link); link.click(); document.body.removeChild(link); button.classList.remove('loading'); }).catch(() => { setTimeout(() => { delay = Math.min(delay * BACKOFF_CONFIG.factor, BACKOFF_CONFIG.maxDelay); downloadAttempt(); // Retry download attempt }, delay); }); }; downloadAttempt(); // Start the first download attempt } function downloadTrack(spotifyId) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: `https://api.spotifydown.com/download/${spotifyId}`, headers: API_HEADERS, onload: function(response) { try { const result = JSON.parse(response.responseText); if (result.success) { resolve(result); } else { reject(new Error('Download failed')); } } catch (error) { reject(new Error('Failed to parse response')); } }, onerror: reject }); }); } function extractTrackInfo(trackElement) { const title = trackElement.querySelector('[data-encore-id="text"][dir="auto"]').textContent.trim(); const artist = Array.from(trackElement.querySelectorAll('a[href^="/artist"]')).map(a => a.textContent.trim()).join(', '); return { title, artist }; } function attachButtons() { const tracks = document.querySelectorAll('[data-testid="tracklist-row"]'); tracks.forEach(track => { const spotifyId = track.querySelector('[href^="/track"]').href.split('/').pop(); const trackInfo = extractTrackInfo(track); addDownloadButton(track, trackInfo, spotifyId); }); } new MutationObserver(function() { applyStyles(); attachButtons(); }).observe(document.body, { childList: true, subtree: true });