# Plex Library — Folder-Based Location Management via SQLite

When Plex groups compilation/VA folders together as "Various Artists" or cross-contaminates album metadata, the fix is to add each subfolder as an **individual library location** instead of a single parent folder.

## The Problem

Plex treats a library's root folder as one namespace. If you have:
```
/Music/English/
  ├── Best of HipHop (2000-2026)/    ← compilation
  ├── Drake/                          ← proper album
  ├── Green Day/                      ← proper album
  └── Today's Top Hits/              ← compilation
```

With `respectTags=false`, Plex uses folder names as album titles — compilation folders are fine but tagged albums get wrong metadata.

With `respectTags=true`, Plex uses embedded tags — tagged albums are correct, but compilation folders (which often have tracks with different "Album" tags from different sources) get grouped as "Various Artists" and cross-contaminated.

## The Fix: Individual Locations

Add each subfolder as a separate library location. This makes Plex treat each folder as its own namespace — no cross-contamination.

### Step 1: Check Current Locations

```bash
curl -s "http://192.168.50.98:32400/library/sections?X-Plex-Token=<TOKEN>" | grep -o '<Location[^>]*>'
```

Or via Python:
```python
import urllib.request, xml.etree.ElementTree as ET

tree = ET.parse('/path/to/Preferences.xml')
token = tree.getroot().get('PlexOnlineToken')

url = f"http://localhost:32400/library/sections?X-Plex-Token={token}"
with urllib.request.urlopen(url) as resp:
    print(resp.read().decode())
```

**Pitfall:** Bash mangles tokens with special characters. Use Python for all Plex API calls.

### Step 2: List Subfolders

```bash
ls -1 /mnt/seagate8tb/Music/English/
```

### Step 3: Add Each Subfolder as Location

Plex API for adding music library locations is unreliable (404s, auth issues). Use direct SQLite:

```python
import sqlite3

db = "/home/ray/docker/plex/config/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db"
conn = sqlite3.connect(db)

base = "/mnt/seagate8tb/Music/English"
folders = ["Best of HipHop (2000-2026)", "Drake", "Green Day", ...]

for folder in folders:
    path = f"{base}/{folder}"
    conn.execute(
        "INSERT INTO section_locations (library_section_id, root_path) VALUES (?, ?)",
        (1, path)  # 1 = library section ID
    )
conn.commit()
conn.close()
```

### Step 4: Remove Parent Location

```python
conn.execute("DELETE FROM section_locations WHERE id=<parent_location_id>")
conn.commit()
```

### Step 5: Restart and Scan

```bash
docker compose restart plex
```

Then trigger a scan (Python, not bash):
```python
url = f"http://localhost:32400/library/sections/1/refresh?X-Plex-Token={token}"
urllib.request.urlopen(url)
```

### Step 6: Verify

```bash
# Check if scan is running
grep -i "scan\|refresh" '/path/to/Plex Media Server.log' | tail -5

# Check scanner processes
ps aux | grep "Plex Media Scanner" | grep -v grep
```

## DB Schema Reference

```sql
-- section_locations table
CREATE TABLE section_locations (
    id INTEGER PRIMARY KEY,
    library_section_id INTEGER,
    root_path VARCHAR(255),
    available BOOLEAN DEFAULT 't',
    scanned_at INTEGER,
    created_at INTEGER,
    updated_at INTEGER
);
```

## Tags vs Folder Names Tradeoff

- `respectTags=true` — proper albums show correctly; compilations need the individual-location fix
- `respectTags=false` — compilations show correctly as folder names; tagged albums get wrong metadata

With the individual-location fix, `respectTags=true` works for both cases.
