Files
jarri-spooty/README.md
T

371 lines
6.5 KiB
Markdown

# Spooty Hardened
Self-hosted Spotify playlist and track downloader built with NestJS + Angular.
Spooty does not download audio from Spotify itself.
It retrieves metadata from Spotify and locates matching audio on YouTube.
This hardened branch focuses on:
- Large playlist support (>100 tracks)
- Spotify OAuth login flow
- Better YouTube pacing and throttling resistance
- Improved Docker deployment
- Safer credential handling
- More resilient cover-art embedding
- Better queue stability
---
# Features
- Download Spotify playlists
- Download individual Spotify tracks
- Playlist auto-subscription support
- Automatic YouTube matching
- MP3 tagging and embedded cover art
- Docker deployment
- Queue-based download system
- Spotify OAuth integration
- Large playlist pagination support
- Download pacing controls
- YouTube cookie support
---
# Important Notice
Use this software responsibly.
Only download music you legally own or are permitted to access.
The maintainers are not responsible for misuse.
---
# Supported URLs
- Spotify playlists
- Spotify tracks
Example:
https://open.spotify.com/playlist/...
https://open.spotify.com/track/...
---
# Quick Start (Recommended)
## 1. Create Spotify Developer App
Go to:
https://developer.spotify.com/dashboard
Create an application.
Add this Redirect URI:
http://127.0.0.1:3000/api/spotify/callback
Copy:
- Client ID
- Client Secret
---
## 2. Store Credentials Outside Repository
Create a secure env file:
~~~bash
sudo mkdir -p /etc/tokens
sudo tee /etc/tokens/spotify.env > /dev/null <<'EOF'
SPOTIFY_CLIENT_ID=your_client_id
SPOTIFY_CLIENT_SECRET=your_client_secret
EOF
sudo chown root:$USER /etc/tokens/spotify.env
sudo chmod 640 /etc/tokens/spotify.env
~~~
Never commit this file.
---
# Docker Run
~~~bash
docker run --rm -p 3000:3000 \
--env-file /etc/tokens/spotify.env \
-e SPOTIFY_REDIRECT_URI='http://127.0.0.1:3000/api/spotify/callback' \
-e AUTH_ENABLED=true \
-e SPOOTY_AUTH_TOKEN=change_this_token \
-e YT_SEARCH_DELAY_MS=7000 \
-e YT_DOWNLOADS_PER_MINUTE=3 \
-v "$PWD/downloads:/spooty/backend/downloads" \
spootyfy-hardened:local
~~~
Open:
http://127.0.0.1:3000/?token=change_this_token
Then:
1. Click "Connect Spotify"
2. Login to Spotify
3. Approve access
4. Paste playlist URL
5. Download
---
# Docker Compose
~~~yaml
services:
spooty:
image: spootyfy-hardened:local
container_name: spooty
restart: unless-stopped
ports:
- "3000:3000"
env_file:
- /etc/tokens/spotify.env
environment:
SPOTIFY_REDIRECT_URI: "http://127.0.0.1:3000/api/spotify/callback"
AUTH_ENABLED: "true"
SPOOTY_AUTH_TOKEN: "change_this_token"
YT_SEARCH_DELAY_MS: "7000"
YT_DOWNLOADS_PER_MINUTE: "3"
volumes:
- ./downloads:/spooty/backend/downloads
~~~
---
# Build From Source
## Requirements
- Node.js 20.20.0
- Docker
- ffmpeg
- Python3
- Redis
---
## Build
~~~bash
npm install
npm run build
~~~
---
## Run
~~~bash
npm run start
~~~
---
# Environment Variables
| Variable | Default | Description |
|---|---|---|
| DB_PATH | `./config/db.sqlite` | SQLite database path |
| DOWNLOADS_PATH | `./downloads` | Download directory |
| FORMAT | `mp3` | Output format |
| REDIS_HOST | `localhost` | Redis host |
| REDIS_PORT | `6379` | Redis port |
| SPOTIFY_CLIENT_ID | unset | Spotify client ID |
| SPOTIFY_CLIENT_SECRET | unset | Spotify client secret |
| SPOTIFY_REDIRECT_URI | unset | OAuth callback URI |
| AUTH_ENABLED | `false` | Enable frontend token auth |
| SPOOTY_AUTH_TOKEN | unset | Frontend auth token |
| YT_SEARCH_DELAY_MS | `5000` | Delay between YouTube searches |
| YT_DOWNLOADS_PER_MINUTE | `3` | Download pacing |
| YT_COOKIES | unset | Browser cookie extraction |
| YT_COOKIES_FILE | unset | Netscape cookies.txt path |
---
# YouTube Cookies
YouTube may throttle or block requests without cookies.
Two supported methods exist.
---
## Browser Cookies (Native Install Only)
~~~bash
YT_COOKIES=firefox
~~~
Supported:
- firefox
- chrome
- chromium
- edge
- brave
- opera
This does NOT work reliably in Docker.
---
## Cookies File (Recommended)
Export a Netscape-format `cookies.txt`.
Mount into container:
~~~bash
-v /path/to/cookies.txt:/spooty/config/cookies.txt
~~~
Then:
~~~bash
-e YT_COOKIES_FILE=/spooty/config/cookies.txt
~~~
---
# Large Playlist Support
The hardened branch fixes several Spotify API limitations:
- Proper playlist pagination
- >100 track playlists
- OAuth-authenticated playlist access
- Queue stability improvements
Verified working with playlists containing 300+ tracks.
---
# Queue Pacing
Aggressive YouTube access can trigger:
- HTTP 302 loops
- CAPTCHA
- temporary throttling
- incomplete downloads
Recommended safe pacing:
~~~bash
-e YT_SEARCH_DELAY_MS=7000
-e YT_DOWNLOADS_PER_MINUTE=3
~~~
---
# Security Notes
Never commit:
- Spotify secrets
- OAuth tokens
- cookies.txt
- downloaded music
- local databases
Recommended `.gitignore` additions:
~~~gitignore
downloads/
config/
*.sqlite
cookies.txt
.env
.env.local
~~~
---
# Hardened Branch Changelog
## Unreleased Hardened Changes
### Spotify
- Added Spotify OAuth login flow
- Added persistent Spotify user token storage
- Added authenticated playlist retrieval
- Fixed large playlist pagination
- Fixed playlist truncation at 100 tracks
- Added playlist retrieval debugging
- Added OAuth status endpoint
### YouTube
- Added configurable search pacing
- Added configurable download pacing
- Reduced aggressive YouTube request bursts
- Improved queue throttling behavior
### Backend
- Added safer queue pacing logic
- Added explicit search processor throttling
- Improved Docker runtime stability
- Improved logging around Spotify retrieval
- Added auth bootstrap flow support
### Frontend
- Added Spotify login integration
- Added frontend auth token bootstrap
- Fixed playlist progress handling for large playlists
- Improved playlist rendering stability
### Security
- Moved secrets to external env files
- Improved Docker secret handling recommendations
- Added security documentation
- Prevented accidental secret inclusion in repository
---
# Development Notes
Recommended local test run:
~~~bash
docker run --rm -p 3000:3000 \
--env-file /etc/tokens/spotify.env \
-e SPOTIFY_REDIRECT_URI='http://127.0.0.1:3000/api/spotify/callback' \
-e AUTH_ENABLED=true \
-e SPOOTY_AUTH_TOKEN=test-token \
-e YT_SEARCH_DELAY_MS=7000 \
-e YT_DOWNLOADS_PER_MINUTE=3 \
-v "$PWD/downloads:/spooty/backend/downloads" \
spootyfy-hardened:local
~~~
---
# License
MIT