runit/spotify-tracker | ||
src | ||
.gitignore | ||
Cargo.toml | ||
deploy.sh | ||
example-config.toml | ||
NEXT_STEPS.md | ||
phantombot-example.js | ||
quick-start.sh | ||
README-deployment.md | ||
README.md |
Spotify Tracker
A rock-solid Rust implementation for retrieving the current playing song from Spotify. This replaces the unreliable custom API approach with a direct integration to the official Spotify Web API.
Features
🎵 Real-time Track Information
- Current playing track details (song, artist, album)
- Playback progress and duration
- Playing/paused status
- Album artwork URLs
🔄 Robust & Reliable
- Automatic token refresh
- Rate limiting handling with exponential backoff
- Comprehensive error handling
- Retry logic for failed requests
⚙️ Flexible Usage
- One-time track lookup
- Continuous monitoring mode
- Multiple output formats (JSON, plain text, formatted)
- Configurable polling intervals
🛠️ Easy Setup
- Simple CLI interface
- Automatic configuration management
- Secure token storage
🎮 PhantomBot Integration
- HTTP server mode for bot integration
- Multiple endpoints for different use cases
- Compatible with existing bot APIs
Prerequisites
- Spotify Developer Account: Create one at developer.spotify.com
- Spotify App: Create a new app in your Spotify Developer Dashboard
- Rust: Install from rustup.rs
Installation
git clone <repository-url>
cd spotify-tracker
cargo build --release
Quick Start
1. Set up Spotify App
- Go to Spotify Developer Dashboard
- Create a new app
- Note your Client ID and Client Secret
- Add
http://localhost:8888/callback
to your app's Redirect URIs
2. Authenticate
# Run the authentication setup
cargo run -- auth
# Or provide credentials directly
cargo run -- auth --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET
Follow the prompts to complete OAuth2 authentication.
3. Get Current Track
# Get current track once
cargo run -- current
# Monitor continuously (updates every second)
cargo run -- monitor
# Monitor with custom interval
cargo run -- monitor --interval 5
Usage
Commands
auth
Set up Spotify authentication
cargo run -- auth --client-id YOUR_ID --client-secret YOUR_SECRET
current
Get the currently playing track once
cargo run -- current
cargo run -- current --format json
monitor
Continuously monitor the current track
cargo run -- monitor --interval 2
config
Show current configuration
cargo run -- config
logout
Reset authentication (remove saved tokens)
cargo run -- logout
auth-url
Get the authorization URL for manual setup
cargo run -- auth-url
server
Start HTTP server for PhantomBot integration
cargo run -- server --port 8888
Output Formats
Formatted (Default)
▶️ Bohemian Rhapsody - Queen (A Night at the Opera)
2:34 / 5:55
JSON
{
"track_name": "Bohemian Rhapsody",
"artist_name": "Queen",
"album_name": "A Night at the Opera",
"is_playing": true,
"progress_ms": 154000,
"duration_ms": 355000,
"external_url": "https://open.spotify.com/track/...",
"image_url": "https://i.scdn.co/image/...",
"timestamp": "2024-01-15T10:30:00Z"
}
Plain
Bohemian Rhapsody - Queen - A Night at the Opera
CLI Options
-v, --verbose
: Enable verbose logging-i, --interval <SECONDS>
: Override polling interval-f, --format <FORMAT>
: Output format (json, plain, formatted)
Configuration
Configuration is automatically managed in:
- macOS:
~/Library/Application Support/spotify-tracker/
- Linux:
~/.config/spotify-tracker/
- Windows:
%APPDATA%\\spotify-tracker\\
Files:
config.toml
: Application configurationtoken.json
: OAuth2 tokens (automatically managed)
Example config.toml
[spotify]
client_id = "your_client_id"
client_secret = "your_client_secret"
redirect_uri = "http://localhost:8888/callback"
scopes = ["user-read-currently-playing", "user-read-playback-state"]
output_format = "formatted"
polling_interval = 1
max_retries = 3
Error Handling
The application handles various error scenarios:
- Token Expiration: Automatically refreshes using refresh token
- Rate Limiting: Implements exponential backoff
- Network Issues: Retry logic with configurable attempts
- API Errors: Comprehensive error reporting
- No Current Track: Graceful handling when nothing is playing
Development
Project Structure
src/
├── main.rs # CLI application entry point
├── lib.rs # Library exports
├── auth.rs # OAuth2 authentication
├── client.rs # Spotify API client
├── models.rs # Data structures
├── config.rs # Configuration management
└── error.rs # Error types
Running Tests
cargo test
Building Release Binary
cargo build --release
./target/release/spotify-tracker --help
Comparison with Previous Implementation
Feature | Old API | New Rust Implementation |
---|---|---|
Reliability | Unreliable custom API | Direct Spotify Web API |
Authentication | Manual code passing | Full OAuth2 flow with refresh |
Error Handling | Basic | Comprehensive with retries |
Rate Limiting | None | Exponential backoff |
Token Management | Manual | Automatic refresh |
Output Formats | Limited | JSON, Plain, Formatted |
Configuration | None | Persistent config management |
Monitoring | Single requests | Continuous monitoring mode |
PhantomBot Integration
Perfect for streamers using PhantomBot! The server mode provides HTTP endpoints that your bot can call.
Starting the Server
# Start server on default port (8888)
cargo run -- server
# Start on custom port
cargo run -- server --port 9000
Available Endpoints
/current
- JSON Response
{
"playing": true,
"track": "Bohemian Rhapsody",
"artist": "Queen",
"album": "A Night at the Opera",
"url": "https://open.spotify.com/track/...",
"image": "https://i.scdn.co/image/...",
"progress_ms": 154000,
"duration_ms": 355000,
"is_playing": true,
"timestamp": "2024-01-15T10:30:00Z"
}
/phantombot
- Plain Text Response
🎵 Bohemian Rhapsody - Queen (A Night at the Opera)
/health
- Health Check
{
"status": "healthy",
"service": "spotify-tracker",
"timestamp": "2024-01-15T10:30:00Z"
}
PhantomBot Usage
Replace your existing custom API call:
// Old unreliable API
// https://pizzabot.t1nc4n.tech/sptf-cur-track?code=...
// New rock-solid API
http://localhost:8888/phantombot
Example PhantomBot Commands
// In your PhantomBot command
$.customAPI.get("http://localhost:8888/phantombot").content
For JSON data:
var response = JSON.parse($.customAPI.get("http://localhost:8888/current").content);
if (response.playing) {
$.say("Now playing: " + response.track + " by " + response.artist);
} else {
$.say("No music currently playing");
}
Troubleshooting
Authentication Issues
# Clear saved tokens and re-authenticate
cargo run -- logout
cargo run -- auth
Rate Limiting
The application automatically handles rate limiting, but you can increase polling interval:
cargo run -- monitor --interval 5 # Poll every 5 seconds instead of 1
Verbose Logging
cargo run -- current --verbose
License
[Add your license here]
Contributing
[Add contribution guidelines here]