Metadata-Version: 2.4
Name: imsg2spot
Version: 0.1.0
Summary: turn spotify links from an imessage group into a spotify playlist
Project-URL: Homepage, https://github.com/finnjclancy/imessage-spotify-playlist
Author: Finn Clancy
License: MIT
Requires-Python: >=3.9
Requires-Dist: requests>=2.32.0
Requires-Dist: rich>=13.7.0
Description-Content-Type: text/markdown

## cli quickstart

run this from your mac to turn spotify links in an imessage group into a playlist.

- install (once it’s on pypi):
```bash
pipx install imsg2spot  # or: pip install imsg2spot
```

- make a playlist (one command):
```bash
imsg2spot make-playlist --chat-name "F is F" --name "FEDs" --public
```
that opens spotify in your browser, you click authorize, and the playlist appears (oldest → newest, no duplicates).

- if you prefer ids:
```bash
imsg2spot list-chats --limit 50
imsg2spot make-playlist --chat-id <id> --name "FEDs" --public
```

- if you’re running from the repo (no pypi):
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python cli.py make-playlist --chat-name "F is F" --name "FEDs" --public
```

## library (optional)

want to script it? you can import a couple of helpers directly.

```python
from cli import open_db, extract_spotify_links, dedupe_keep_first_by_track

conn = open_db("db/chat.db")
found = extract_spotify_links(conn, chat_id=27, expand_short_links=True)
tracks = dedupe_keep_first_by_track(found)
for t in tracks:
    print(t.timestamp, t.sender, t.track_id)
```

## what this does

- reads your local imessage database (mac only)
- finds spotify links in a specific chat, including rich links
- keeps only real song links (`/track/<22-char-id>`), no podcasts/shows/albums/playlists
- de-dupes (keeps the first time a song was shared)
- orders oldest → newest
- creates/updates a public playlist on your spotify

## requirements

- macos with the messages app history on this machine
- python 3.9+
- grant your terminal full disk access (system settings → privacy & security → full disk access)

## prep the messages database (safe copy)

quit the messages app first if possible, then:
```bash
mkdir -p db
sqlite3 ~/Library/Messages/chat.db ".backup 'db/chat.db'"
```

## find your chat

- list and eyeball participants:
```bash
imsg2spot list-chats --limit 50
# filter by participants if needed
imsg2spot list-chats --limit 200 --filter-participant "+353863205817" --filter-participant "+12677096964"
```
- or just use the name:
```bash
imsg2spot dry-run --chat-name "F is F"
```

## privacy

- everything runs locally; we only read your `db/chat.db` file
- don’t commit personal data; `.gitignore` excludes `db/chat.db*` and `config.py`

## troubleshooting

- nothing prints on dry-run: your chat likely uses rich links only — the tool handles those; make sure you picked the right chat
- messages locked: quit messages and use the sqlite `.backup` command above
- oauth redirect: we use loopback `http://127.0.0.1:8000/callback` with pkce (no secret). it’s normal and secure for local apps
- port 8000 busy: set env `SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888/callback` and re-run

## how other people can use this with zero setup

- this tool uses a shared spotify app client id + pkce
- once the app is set to “production” in spotify’s dashboard, anyone can authorize without creating their own app
- users just clone and run the one command shown at the top

## getting older messages (e.g., a parent from 2019)

1) they run it on their own mac (same steps), or
2) they send you a safe copy of their db:
```bash
sqlite3 ~/Library/Messages/chat.db ".backup '/tmp/chat.db'"
```
put that file at `db/dad_chat.db` and add `--db db/dad_chat.db` to commands.

## install from source (dev)

```bash
pipx install --editable .
# or
pip install -e .
```
run:
```bash
imsg2spot dry-run --chat-name "F is F"
imsg2spot make-playlist --chat-name "F is F" --name "FEDs" --public
```

## publish to pypi (maintainer)

```bash
python -m pip install --upgrade build twine
python -m build
python -m twine upload dist/*
```

## license

mit. do what you want, be kind.
