--- name: Apple Music Integration overview: Exploratory investigation of Apple Music API integration options for adding requests to a user's Apple Music queue/playlist and automatically detecting when songs are played, with assessment of feasibility, prerequisites, and architectural approaches. todos: - id: prereqs content: Set up Apple Developer Program account, create MusicKit identifier, generate private key status: pending - id: apple-music-module content: Create SongRequest/apple_music.py with JWT generation and REST API wrapper status: pending - id: musickit-js-embed content: Embed MusicKit JS v3 in the dashboard, add authorize flow and queue control status: pending - id: now-playing-detection content: Add playbackStateDidChange listener in dashboard JS + /api/now-playing endpoint in web.py status: pending - id: auto-played-matching content: Implement trackId matching logic in store/plugin to auto-mark requests as played status: pending - id: config-values content: Add config entries for Apple Developer key, team ID, key ID, playlist ID, and feature toggles status: pending - id: recently-played-poller content: (Optional) Add server-side polling of recently-played API as a fallback status: pending isProject: false --- # Apple Music Integration: Feasibility and Implementation Plan ## Prerequisites (Required for Both Features) Before any integration work, you need: - **Paid Apple Developer Program membership** ($99/year) -- required to generate MusicKit keys - **MusicKit identifier + private key** from Certificates, Identifiers & Profiles in the Apple Developer portal - **Developer Token (JWT)** -- an ES256-signed JWT with your Team ID and key ID, valid up to 6 months - **Music User Token** -- obtained via MusicKit JS authorization flow in the browser; required for any personal library/playlist operations. The dashboard operator must have an **active Apple Music subscription** The current plugin uses the **public iTunes Search API** (no auth needed). Both proposed features require authenticated access to a specific user's Apple Music account. --- ## Feature 1: Add Requests to Apple Music Playlist/Queue ### How It Would Work There are two viable approaches, each with different trade-offs: ### Approach A: Server-Side REST API (Add to Playlist) The Apple Music REST API supports adding tracks to a user's library playlist: ``` POST https://api.music.apple.com/v1/me/library/playlists/{playlist_id}/tracks Authorization: Bearer {developer_token} Music-User-Token: {user_token} { "data": [ { "id": "{catalog_song_id}", "type": "songs" } ] } ``` **Architecture:** ```mermaid sequenceDiagram participant IRC as IRC User participant Bot as Limnoria Bot participant iTunes as iTunes Search API participant Dashboard as Web Dashboard participant AM as Apple Music API IRC->>Bot: !request Artist - Title Bot->>iTunes: Search query iTunes-->>Bot: Track results (includes trackId) Bot->>Dashboard: WebSocket push (new card) Dashboard->>AM: POST /v1/me/.../tracks (on approve) AM-->>Dashboard: 200 OK (added to playlist) Dashboard->>Bot: WebSocket notify (added) ``` **Implementation steps:** - Add a new module `[SongRequest/apple_music.py](SongRequest/apple_music.py)` for JWT generation (using `PyJWT` + `cryptography`) and REST API calls - Add config values for Apple Developer key path, key ID, team ID, target playlist ID, and stored Music User Token - The web dashboard handles the MusicKit JS authorization flow once (popup login), stores the Music User Token, and sends it to the bot backend - When a request is approved (or auto-approved), the bot calls `POST /v1/me/library/playlists/{id}/tracks` with the iTunes `trackId` (which maps to Apple Music catalog IDs) - New config option: `appleMusicAutoAdd` (boolean) to toggle this behavior **Key concern:** The `trackId` from the iTunes Search API should map to Apple Music catalog song IDs, but this needs verification. The iTunes Search API returns `trackId` (numeric), while the Apple Music API expects string catalog IDs. These are typically the same value, just as a string. **Pros:** Fully server-side, works without the dashboard open, songs appear in a persistent playlist **Cons:** Adds to a playlist only (not the live playback queue), tracks go to the end of the playlist, no position control, Music User Token expires and needs periodic re-auth ### Approach B: MusicKit JS Web Player (Add to Queue + Play) Embed MusicKit JS in the web dashboard to directly control Apple Music playback: ```javascript const music = MusicKit.getInstance(); await music.authorize(); await music.setQueue({ songs: [catalogSongId] }); // Or append to existing queue await music.playNext({ songs: [catalogSongId] }); ``` **Architecture:** ```mermaid sequenceDiagram participant IRC as IRC User participant Bot as Limnoria Bot participant Dashboard as Web Dashboard + MusicKit JS participant AM as Apple Music (Playback) IRC->>Bot: !request Artist - Title Bot->>Dashboard: WebSocket push (new request) Note over Dashboard: Operator approves Dashboard->>AM: MusicKit.playNext(songId) AM-->>Dashboard: Song added to queue Note over Dashboard: Apple Music plays on this device ``` **Implementation steps:** - Add MusicKit JS SDK to `[SongRequest/templates/index.html](SongRequest/templates/index.html)` via `