|
All checks were successful
Publish Docker image / Push Docker image to local registry (push) Successful in 28s
Reviewed-on: #2 |
||
|---|---|---|
| .forgejo/workflows | ||
| .github | ||
| src | ||
| .env.example | ||
| .envrc | ||
| .gitignore | ||
| Dockerfile | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| renovate.json | ||
| requirements.txt | ||
ListenBrainz Sync
Fetch the ListenBrainz weekly jams and weekly exploration playlists for a user, ensure all albums are present and monitored in Lidarr, and sync tracks to Jellyfin playlists.
Project Structure
listenbrainz-sync/
├── requirements.txt # Python dependencies
├── flake.nix # Nix development environment
└── src/ # Source code
├── __init__.py # Package initialization
├── main.py # Main entry point
├── config.py # Configuration management
├── sync.py # Main synchronization logic
└── clients/ # API clients
├── __init__.py # Clients package initialization
├── listenbrainz.py # ListenBrainz API client and playlist extraction
├── lidarr.py # Lidarr API client
├── jellyfin.py # Jellyfin API client for playlist management
└── musicbrainz.py # MusicBrainz API client with caching
Configuration
Configuration is provided via environment variables:
ListenBrainz
LISTENBRAINZ_USER(required)LISTENBRAINZ_TOKEN(required)LISTENBRAINZ_BASE_URL(default: https://api.listenbrainz.org/1)
Lidarr
LIDARR_URL(required, e.g. http://lidarr:8686)LIDARR_API_KEY(required)LIDARR_ROOT_FOLDER(required, e.g. /music)LIDARR_QUALITY_PROFILE_ID(required, int)LIDARR_METADATA_PROFILE_ID(required, int)LIDARR_MONITORED(default: true)LIDARR_SEARCH_MISSING(default: false)
Jellyfin
JELLYFIN_BASE_URL(required, e.g. http://jellyfin:8096)JELLYFIN_API_KEY(required)JELLYFIN_USER_ID(optional Jellyfin GUID to own the playlists)
MusicBrainz Cache
MUSICBRAINZ_CACHE_DIR(optional, default: ~/.cache/listenbrainz-sync/musicbrainz)
Runtime
LOG_LEVEL(default: INFO)
Usage
# Install dependencies
pip install -r requirements.txt
# Run the sync
python -m src.main
Or use the Nix development environment:
nix develop
python -m src.main
Features
Lidarr Integration
- Automatically adds artists from weekly playlists to Lidarr
- Enables monitoring for albums matching the weekly playlists
- Uses MusicBrainz IDs for accurate artist/album matching
- Respects Lidarr quality and metadata profile settings
Jellyfin Integration
- Creates playlists named
[AUTO] Weekly jam of YYYY-MM-DDand[AUTO] Weekly exploration of YYYY-MM-DD - Performs best-effort track matching against Jellyfin library
- Automatically updates playlists on subsequent runs
- Gracefully handles missing tracks (doesn't fail if some tracks aren't in Jellyfin)
Development
The codebase is organized into logical modules:
- src/config.py: Configuration dataclasses and environment variable loading
- src/main.py: Main entry point with synchronization orchestration
- src/clients/: API client implementations
- src/clients/listenbrainz.py: ListenBrainz API client and playlist parsing
- src/clients/lidarr.py: Lidarr API client with artist/album management
- src/clients/jellyfin.py: Jellyfin API client for playlist creation and management
- src/clients/musicbrainz.py: MusicBrainz API client with file-based caching (24-hour validity)
- src/sync.py: Synchronization workflow logic
MusicBrainz Caching
To respect MusicBrainz's rate limits and reduce unnecessary API calls, the application caches all MusicBrainz API responses for 24 hours. By default, the cache is stored in ~/.cache/listenbrainz-sync/musicbrainz/. You can override this location using the MUSICBRAINZ_CACHE_DIR environment variable.
You can clear the cache if needed:
from src.clients import musicbrainz
# View cache statistics
stats = musicbrainz.get_cache_stats()
print(stats)
# Clear all cached data
musicbrainz.clear_cache()
Docker Setup
This project includes a Docker setup to run the synchronization script in a containerized environment.
Building the Docker Image
To build the Docker image, run the following command in the project root directory:
docker build -t listenbrainz-sync .
Running the Docker Container
To run the Docker container, you can specify the timer interval in minutes using the TIMER_INTERVAL environment variable. For example, to run the script every 5 minutes:
docker run -e TIMER_INTERVAL=5 listenbrainz-sync
How It Works
The container runs the main.py script on a timer. The script will execute every TIMER_INTERVAL minutes, as specified by the environment variable. The sleep command in the Dockerfile converts the interval from minutes to seconds to control the timing of the script execution.