Warning: This code was mostly written by AI. I do not provide any guarantees about it being even slightly functional.
Find a file
kalle de8205cbed
All checks were successful
Publish Docker image / Push Docker image to local registry (push) Successful in 28s
Merge pull request 'Update python Docker tag to v3.14' (#2) from renovate/python-3.x into main
Reviewed-on: #2
2026-01-19 17:42:32 +01:00
.forgejo/workflows Add Forgejo Actions workflow for publishing Docker image 2026-01-19 17:22:38 +01:00
.github MVP 2026-01-19 14:47:28 +01:00
src Add MusicBrainz caching support and Docker setup 2026-01-19 17:16:27 +01:00
.env.example Add MusicBrainz caching support and Docker setup 2026-01-19 17:16:27 +01:00
.envrc MVP 2026-01-19 14:47:28 +01:00
.gitignore MVP 2026-01-19 14:47:28 +01:00
Dockerfile Update python Docker tag to v3.14 2026-01-19 16:41:56 +00:00
flake.lock MVP 2026-01-19 14:47:28 +01:00
flake.nix MVP 2026-01-19 14:47:28 +01:00
README.md Add MusicBrainz caching support and Docker setup 2026-01-19 17:16:27 +01:00
renovate.json Add renovate.json 2026-01-19 16:30:07 +00:00
requirements.txt MVP 2026-01-19 14:47:28 +01:00

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

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-DD and [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.