Metadata-Version: 2.4
Name: beets-beatport4
Version: 1.1.1
Summary: Plugin for beets (http://beets.io) to replace stock beatport plugin which is not yet compatible with Beatport API v4.
Author-email: Szymon 'Samik' Tarasinski <st.samik@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/Samik081/beets-beatport4
Project-URL: Download, https://github.com/Samik081/beets-beatport4/releases/download/v1.1.1/beets-beatport4-1.1.1.tar.gz
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Multimedia :: Sound/Audio :: Players :: MP3
Classifier: Environment :: Console
Classifier: Environment :: Web Environment
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: beets>=2.7.0
Requires-Dist: requests
Requires-Dist: confuse
Provides-Extra: dev
Requires-Dist: mypy; extra == "dev"
Requires-Dist: types-requests; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-mock; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: responses; extra == "dev"
Dynamic: license-file

# beets-beatport4

**Beatport API v4 plugin for [beets](https://github.com/beetbox/beets)**

[![PyPI version](https://img.shields.io/pypi/v/beets-beatport4.svg)](https://pypi.python.org/pypi/beets-beatport4)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Test (latest beets release)](https://github.com/Samik081/beets-beatport4/actions/workflows/test-release.yml/badge.svg)](https://github.com/Samik081/beets-beatport4/actions/workflows/test-release.yml)
[![Test (beets master)](https://github.com/Samik081/beets-beatport4/actions/workflows/test-master.yml/badge.svg)](https://github.com/Samik081/beets-beatport4/actions/workflows/test-master.yml)
[![Test (Poetry build)](https://github.com/Samik081/beets-beatport4/actions/workflows/test-poetry.yml/badge.svg)](https://github.com/Samik081/beets-beatport4/actions/workflows/test-poetry.yml)

A drop-in replacement for the stock beets beatport plugin, updated for Beatport API v4.

As Beatport killed their API v3, the stock beatport plugin no longer works. It is also currently not possible to request API access the "normal" way (using your client credentials or an API token generated by Beatport), so this plugin uses a workaround: the public API client ID from the [Beatport docs frontend](https://api.beatport.com/v4/docs/).

For more info, see [this issue](https://github.com/beetbox/beets/issues/3862). A [pull request](https://github.com/beetbox/beets/pull/4477) has also been opened in the official beets repository — if it gets merged, this plugin may be retired.

---

## Table of Contents

- [Installation](#installation)
- [Authorization](#beatport-authorization)
  - [Method 1: Username and password](#method-1-username-and-password)
  - [Method 2: Copy token from the browser](#method-2-copy-token-from-the-browser)
- [Album Art](#fetching-and-embedding-album-art)
  - [Image size](#image-size)
- [Singleton Album Metadata](#singleton-album-metadata)
- [Configuration Reference](#configuration-reference)
- [Debug Logging & Sensitive Data](#debug-logging--sensitive-data)

---

## Installation

```bash
# if beets was installed with pip:
pip install beets-beatport4

# or, if beets was installed with pipx:
pipx inject beets beets-beatport4
```

Then add `beatport4` to the `plugins` list in your beets config file.

---

## Beatport Authorization

There are two ways to acquire a user access token for the Beatport v4 API.

### Method 1: Username and password

This method is fully automatic and relies on storing your Beatport username and password in your beets config file. It authorizes via the `authorization_code` grant type using the `client_id` provided by Beatport for their [swagger-ui frontend](https://api.beatport.com/v4/docs/). By default, the `client_id` is scraped automatically from that URL. Alternatively, you can set it manually via plugin configuration.

> [!WARNING]
> This method stores your Beatport credentials **unencrypted** in the config file. If that is a concern, use [Method 2](#method-2-copy-token-from-the-browser) instead.

**Steps:**

1. Add `beatport4` to your `beets/config.yaml` plugins list.
2. Add the following configuration and fill in your credentials:

```yaml
beatport4:
    username: <YOUR_BEATPORT_USERNAME>
    password: <YOUR_BEATPORT_PASSWORD>
```

### Method 2: Copy token from the browser

Use this method if you don't want to store credentials in the config file, or if something goes wrong during username/password authorization. This is also the fallback method when invalid credentials are provided.

**Steps:**

1. Add `beatport4` to your `beets/config.yaml` plugins list.
2. When the first import with the plugin enabled happens, you will be prompted to paste the access token JSON.
3. Visit <https://api.beatport.com/v4/docs/>.
4. Open the Network tab in your browser and start capturing traffic.
5. Log in with your Beatport account.
6. Search for the request to `https://api.beatport.com/v4/auth/o/token/`.
7. Copy the response (the whole JSON structure).
8. Paste it into the terminal (or save it to a `beatport_token.json` file next to your `beets/config.yaml` — check the path with `beet config --paths`).
9. If the token expires, you will be prompted again to repeat the above steps.

---

## Fetching and Embedding Album Art

This plugin has its own art fetching and embedding, independent of the [fetchart](https://beets.readthedocs.io/en/stable/plugins/fetchart.html) and [embedart](https://beets.readthedocs.io/en/stable/plugins/embedart.html) plugins. It uses the [beets.art module](https://github.com/beetbox/beets/blob/master/beets/art.py) shipped with the core library. It handles both albums and singletons, but only works when the chosen candidate source is Beatport.

Under the hood, it uses the image URL for the track's release exposed by the Beatport API.

Enable this feature via configuration (**disabled by default**):

```yaml
beatport4:
    art: yes
```

By default, existing art will **not** be overwritten. To force overwriting:

```yaml
beatport4:
    art: yes
    art_overwrite: yes
```

### Image size

Original Beatport images can be large, but thanks to Beatport's dynamic image URIs you can request a pre-resized image, saving bandwidth and local processing.

```yaml
beatport4:
    art: yes
    art_width: 250   # omit or set to 0 to disable
    art_height: 250  # omit or set to 0 to disable
```

> [!TIP]
> - If you specify only one dimension, the other is set to the same value (1:1 aspect ratio).
> - If you omit both dimensions, the original full-size art is downloaded.
> - If you specify both dimensions, they are used in the dynamic URI, but Beatport typically returns images in 1:1 aspect ratio using the smaller dimension.

---

## Singleton Album Metadata

When importing singletons (individual tracks), the original Beatport plugin does not populate album-level fields such as year, album name, label, catalog number, album artist, or track number. This plugin can optionally fetch the full release data from Beatport and fill these fields.

> [!NOTE]
> Enabling this triggers an **additional API call per matched singleton track** to retrieve release data. This may slow down singleton imports.

Enable the feature via configuration (**disabled by default**). Individual fields can be toggled off — all default to `yes` when the feature is enabled:

```yaml
beatport4:
    singletons_with_album_metadata:
        enabled: yes
        year: yes          # release date (year, month, day)
        album: yes         # album name
        label: yes         # record label
        catalognum: yes    # catalog number
        albumartist: yes   # album artist
        track_number: yes  # track number within the release
```

---

## Configuration Reference

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `art` | bool | `no` | Enable album art fetching and embedding |
| `art_overwrite` | bool | `no` | Overwrite existing art if already present |
| `art_width` | int | *(none)* | Target image width in pixels (0 or omit to disable resizing) |
| `art_height` | int | *(none)* | Target image height in pixels (0 or omit to disable resizing) |
| `singletons_with_album_metadata.enabled` | bool | `no` | Fetch release data for singleton imports |
| `singletons_with_album_metadata.year` | bool | `yes` | Populate release date fields |
| `singletons_with_album_metadata.album` | bool | `yes` | Populate album name |
| `singletons_with_album_metadata.label` | bool | `yes` | Populate record label |
| `singletons_with_album_metadata.catalognum` | bool | `yes` | Populate catalog number |
| `singletons_with_album_metadata.albumartist` | bool | `yes` | Populate album artist |
| `singletons_with_album_metadata.track_number` | bool | `yes` | Populate track number within the release |
| `username` | string | *(none)* | Your Beatport username (for auto-authorization) |
| `password` | string | *(none)* | Your Beatport password (for auto-authorization) |
| `client_id` | string | *(auto)* | Beatport API client ID (scraped automatically from docs) |

Full example with all defaults:

```yaml
beatport4:
    art: no
    art_overwrite: no
    art_width: 0
    art_height: 0
    singletons_with_album_metadata:
        enabled: no
        year: yes
        album: yes
        label: yes
        catalognum: yes
        albumartist: yes
        track_number: yes
    username:
    password:
    client_id:  # optional, scraped automatically from Beatport docs
```

---

## Debug Logging & Sensitive Data

When running beets with verbose logging (`beet -vv`), the plugin automatically redacts sensitive information — usernames, emails, authorization codes, and access tokens — replacing them with `<REDACTED>`. This makes it safe to paste `-vv` output into bug reports.

If you need the full unredacted output for local debugging, set the `BEATPORT4_DEBUG_DISABLE_REDACTION` environment variable:

**Linux / macOS:**

```bash
BEATPORT4_DEBUG_DISABLE_REDACTION=1 beet -vv import /path/to/music
```

**Windows (PowerShell):**

```powershell
$env:BEATPORT4_DEBUG_DISABLE_REDACTION = "1"
beet -vv import C:\path\to\music
```

**Windows (cmd):**

```batch
set BEATPORT4_DEBUG_DISABLE_REDACTION=1
beet -vv import C:\path\to\music
```

---

Apart from the above, the plugin works the same way as the stock one — refer to the [official documentation](https://beets.readthedocs.io/en/stable/plugins/beatport.html) for general usage.
