Metadata-Version: 2.4
Name: spotiseek
Version: 0.1.0
Summary: Export a Spotify playlist and auto-download the songs from Soulseek via a self-managed slskd container.
Author: SpotiSeek
License: MIT
Project-URL: Homepage, https://github.com/andrewbazley/spotiseek
Project-URL: Issues, https://github.com/andrewbazley/spotiseek/issues
Keywords: spotify,soulseek,slskd,music,playlist,download
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: spotipy>=2.23.0
Requires-Dist: requests>=2.28.0
Requires-Dist: rapidfuzz>=3.0.0
Requires-Dist: PyYAML>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# 🎧 SpotiSeek

**Turn a Spotify playlist into downloaded music.** SpotiSeek reads a Spotify playlist
(or your Liked Songs), searches the **Soulseek** peer-to-peer network for each track, and
downloads the best match into a folder on your Desktop — all from one command.

It sets up and runs everything for you: you install a couple of apps, paste in two Spotify
keys once, and then it's `spotiseek run …`.

> **New to the command line?** That's fine — this guide assumes no prior experience with
> Python, Conda, or Docker. Follow the steps in order and copy‑paste the commands.

---

## What you'll end up typing

```bash
spotiseek setup                       # one time — sets everything up
spotiseek run me:liked --download     # download your Liked Songs
```

Downloaded songs appear in `~/Desktop/<playlist name>/`.

---

## ⚠️ Before you start — two honest limitations

1. **Spotify only lets this read your Liked Songs and playlists *you own*.** Because of a
   Spotify policy (Development Mode), the API often **won't hand over the track list of any
   playlist**, even ones you made. Your **Liked Songs** (`me:liked`) always work. If a
   playlist fails, that's Spotify's restriction, not a bug — see [Troubleshooting](#-troubleshooting).
2. **Soulseek is a real P2P network.** Results depend on other users being online and on
   your network letting Soulseek connect. If searches come back empty, run
   `spotiseek doctor` — it's almost always a network/port issue, not SpotiSeek.

SpotiSeek is an independent tool, **not affiliated with Spotify, Soulseek, or slskd**.
Use it for content you're allowed to download, and follow those services' terms.

---

## 🧰 Requirements

- A **Mac** (macOS). *(Windows isn't supported yet.)*
- **Anaconda** (gives you Python) — installed below.
- **Docker Desktop** (runs the Soulseek engine) — installed below.
- A free **Soulseek account** (username + password).
- A free **Spotify Developer app** (gives you two keys) — created below.

You do **not** need to download or clone anything from GitHub. `pip install spotiseek`
plus Docker is everything.

---

## 🚀 Setup (step by step)

### Step 1 — Install Anaconda (this gives you Python)

Anaconda is the easiest way to get Python and keep it tidy.

1. Go to **<https://www.anaconda.com/download>** and download the macOS installer.
2. Open the downloaded `.pkg` file and click through the installer.
3. Open the **Terminal** app (press `Cmd‑Space`, type "Terminal", hit Enter).
4. Confirm it worked — paste this and press Enter:
   ```bash
   conda --version
   ```
   You should see something like `conda 24.x.x`.

### Step 2 — Create a workspace for SpotiSeek

This makes an isolated Python "environment" so SpotiSeek can't clash with anything else.

```bash
conda create -n spotiseek python=3.12
conda activate spotiseek
```

After `activate`, your Terminal line starts with `(spotiseek)`. **Any time you open a new
Terminal to use SpotiSeek, run `conda activate spotiseek` first.**

### Step 3 — Install Docker Desktop (runs the Soulseek engine)

SpotiSeek uses a small background program called **slskd** to talk to Soulseek. Docker runs
it for you automatically — you just need Docker installed and open.

1. Download **Docker Desktop for Mac** from
   **<https://docs.docker.com/desktop/setup/install/mac-install/>**
   (pick the **Apple Silicon** build for M1/M2/M3 Macs, or **Intel** for older Macs).
2. Open the downloaded `.dmg` and drag **Docker** into Applications.
3. Launch **Docker** from Applications. Accept the prompts, and **sign in** when asked
   (Google sign‑in works fine).
4. Wait until the Docker whale icon in your menu bar stops animating — that means it's
   running. **Leave Docker Desktop running whenever you use SpotiSeek.**

### Step 4 — Get a free Soulseek account

SpotiSeek needs a Soulseek login to reach the network. If you don't have one, download the
Soulseek client from **<https://www.slsknet.org/news/>**, open it, and pick a username and
password (that's your account — no email needed). You **don't** have to share files to
download. You can then quit that app; SpotiSeek uses its own connection.

> Soulseek allows only **one login per username at a time**, so don't run the Soulseek
> desktop app and SpotiSeek at the same time with the same account.

### Step 5 — Create a Spotify app (two keys, one time)

1. Go to **<https://developer.spotify.com/dashboard>** and log in with your normal Spotify
   account.
2. Click **Create app**. Give it any name/description.
3. In **Redirect URIs**, add exactly this and save:
   ```
   http://127.0.0.1:8888/callback
   ```
4. Open the app's **Settings**. Copy the **Client ID** and (click "View client secret") the
   **Client Secret** — you'll paste these into `spotiseek setup` next.

### Step 6 — Install SpotiSeek

With `(spotiseek)` showing in your Terminal:

```bash
pip install spotiseek
```

### Step 7 — Run the one‑time setup

```bash
spotiseek setup
```

It will:
- check Docker is running,
- ask for your **Soulseek** username/password,
- ask for your **Spotify** Client ID/Secret,
- download and start the Soulseek engine automatically,
- open your browser once so you can approve Spotify access.

When it says **"All set"**, you're ready.

### Step 8 — Download some music 🎉

```bash
spotiseek run me:liked --download
```

Watch it search each track; finished songs land in **`~/Desktop/Liked Songs/`**.

---

## 🎵 Everyday use

Open Terminal and start with:

```bash
conda activate spotiseek
```

Then:

```bash
# Your Liked Songs (always works)
spotiseek run me:liked --download

# A playlist you OWN (paste its share link)
spotiseek run "https://open.spotify.com/playlist/XXXXXXXX" --download

# Preview matches without downloading (safe to try)
spotiseek run me:liked --dry-run --limit 10
```

**Getting a playlist link:** in Spotify, click the ••• next to a playlist →
**Share → Copy link to playlist**. Keep the quotes around the URL.

### Useful options

| Option | What it does | Default |
|---|---|---|
| `--download` | Actually download matches | (off = preview) |
| `--dry-run` | Search and report only, no downloads | |
| `--limit N` | Only process the first N tracks | all |
| `--formats mp3,flac,wav,m4a` | Allowed audio formats (and preference order) | `mp3,wav,m4a` |
| `--min-bitrate 256` | Minimum quality for MP3/M4A (kbps, `≥`) | `320` |
| `--min-confidence 70` | How closely the filename must match (0–100) | `80` |
| `--max-attempts 3` | Download tries per song (each a different user) | `2` |
| `--out results.csv` | Where to save the run report | `spotiseek_results.csv` |

### Commands

| Command | Purpose |
|---|---|
| `spotiseek setup` | One‑time (or repeat) setup: keys, engine, Spotify login |
| `spotiseek run <playlist> --download` | Search + download |
| `spotiseek doctor` | Diagnose the Soulseek connection with a test search |
| `spotiseek status` | Is the engine running and connected? |
| `spotiseek up` / `down` | Start / stop the Soulseek engine |
| `spotiseek logs` | Recent engine logs |
| `spotiseek config --blocked <user>` | Never download from a Soulseek user (advanced) |

---

## 📂 Where your files and data go

- **Downloaded music:** `~/Desktop/<playlist name>/`
- **Settings, keys, and the engine's data:** `~/.spotiseek/` (kept private on your Mac —
  it holds your Spotify/Soulseek credentials, so don't share that folder).

You can safely delete `~/.spotiseek/` to start over; just run `spotiseek setup` again.

---

## 🩺 Troubleshooting

**Run this first — it tells you what's wrong:**
```bash
spotiseek doctor
```

- **"0 files" / nothing downloads.** The Soulseek *connection* is the issue, not SpotiSeek
  (confirmed if `doctor`'s test search is also empty). Common fixes:
  - Make sure **no other Soulseek app** is logged in with the same account (that "kicks"
    SpotiSeek offline).
  - Your network may block Soulseek. Try a **home Wi‑Fi**, or forward **TCP port 50300** on
    your router to your Mac and allow it through the macOS firewall.
  - Cross‑check in the engine's own web page at **<http://localhost:5030>** (log in with
    `slskd` / `slskd`) and search there. If that's empty too, it's 100% the network.
- **A playlist says "no readable tracks" but Liked Songs work.** That's Spotify's
  Development‑Mode restriction on reading playlist tracks. Use `me:liked`, or apply for
  **Extended Quota** access on your Spotify app's dashboard.
- **"Found some files, but all filtered out."** Loosen the filters:
  `--min-bitrate 256 --formats mp3,flac,wav,m4a --min-confidence 70`.
- **"Docker isn't running."** Open **Docker Desktop** and wait for the whale icon to settle.
- **New Terminal doesn't know `spotiseek`.** Run `conda activate spotiseek` first.

---

## 🔍 How it works (for the curious)

```
Spotify playlist ──► SpotiSeek (Python) ──► slskd engine (Docker) ──► Soulseek network
     Spotipy            match & rank            REST API                search + download
```

- Reads Spotify via the official Web API (using **Spotipy**).
- Runs **slskd** (a self‑hosted Soulseek client) from its official Docker image — SpotiSeek
  writes its config, starts it, and talks to its REST API for you. **Nothing to clone or
  build.**
- Cleans each search to plain words (`Todd Terje – Strandbar (Extended)` →
  `Todd Terje Strandbar`), ranks results by format/bitrate/duration/closeness, downloads the
  best, and — if one peer stalls — tries a different user for that song.

---

## 🛠 For developers

```bash
git clone <this repo>   # optional, only if you want the source
pip install -e ".[dev]"
pytest spotiseek/tests -q
```

The test suite is fully offline (no Docker, no network) and covers matching, filters, the
download/fallback pipeline, file moving, Spotify error handling, and the Docker orchestration.

## 📜 License

MIT (see `LICENSE`). SpotiSeek does not include or redistribute slskd or Spotify; it
orchestrates slskd's public Docker image and calls the Spotify Web API under their
respective terms.
