Implement per-admin authentication with IRC-managed accounts (addSongAdmin/removeSongAdmin/listSongAdmins), session-based login, and admin presence tracking via WebSocket. Legacy webAuthToken retained as fallback. Add rename, clear, and delete actions for archived sessions with themed modal confirmations (admin-only UI). Made-with: Cursor
11 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | |||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Apple Music Integration | 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. |
|
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:
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 (usingPyJWT+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}/trackswith the iTunestrackId(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:
const music = MusicKit.getInstance();
await music.authorize();
await music.setQueue({ songs: [catalogSongId] });
// Or append to existing queue
await music.playNext({ songs: [catalogSongId] });
Architecture:
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<script src="https://js-cdn.music.apple.com/musickit/v3/musickit.js"> - Add a "Connect Apple Music" button in the dashboard that calls
music.authorize() - On approve/auto-approve, call
music.playNext({ songs: [trackId] })to queue the song - Optionally, add a mini player widget to the dashboard showing the current queue
Pros: Actually controls the live playback queue, songs play in order, real-time control from the dashboard Cons: Requires the dashboard to be open in a browser on the machine doing playback, browser tab must stay active, only controls playback on that specific device/session
Recommendation
Approach B (MusicKit JS) is better suited to the DJ/streamer use case -- it puts songs directly into the playback queue rather than just appending to a playlist. Approach A is useful as a secondary feature (e.g., building a "requested songs" playlist for later). Both can coexist.
Feature 2: Track When Requests Get Played Automatically
The Problem
Apple Music has no server-side webhook or push notification for "now playing" events. There is no way for the bot to passively learn that a song started playing without active client-side monitoring.
Viable Approaches
Approach A: MusicKit JS Event Monitoring (Best Fit)
If MusicKit JS is already embedded (from Feature 1, Approach B), the dashboard can listen for playback events:
const music = MusicKit.getInstance();
music.addEventListener('playbackStateDidChange', (event) => {
if (event.state === MusicKit.PlaybackStates.playing) {
const item = music.nowPlayingItem;
// Send track ID to bot backend via WebSocket/fetch
fetch('/api/now-playing', {
method: 'POST',
body: JSON.stringify({ trackId: item.id, title: item.title })
});
}
});
Architecture:
sequenceDiagram
participant AM as Apple Music (Playback)
participant Dashboard as Web Dashboard + MusicKit JS
participant Bot as Limnoria Bot
participant IRC as IRC Channel
AM->>Dashboard: playbackStateDidChange (playing)
Dashboard->>Dashboard: Check nowPlayingItem.id
Dashboard->>Bot: POST /api/now-playing {trackId}
Bot->>Bot: Match trackId against approved requests
Bot->>Bot: Update status to "played"
Bot->>IRC: [NOW PLAYING] Song - Artist (requested by nick)
Bot->>Dashboard: WebSocket push (card updated)
Implementation steps:
- Add
playbackStateDidChangeandnowPlayingItemDidChangeevent listeners in the dashboard JS - When a new song starts playing, the dashboard POSTs the track info to a new
/api/now-playingendpoint - The bot matches the
trackIdagainst approved requests in the database - If matched, auto-updates the request status to "played" and announces in IRC
- Add a
played_attimestamp column to the requests table for precise tracking
Pros: Automatic, real-time, no manual "Mark Played" clicking needed Cons: Requires the dashboard + MusicKit JS to be running, only detects playback from the MusicKit JS session (not from the Apple Music app directly)
Approach B: Recently Played Polling (Server-Side Fallback)
Poll the Apple Music REST API's recently-played endpoint:
GET https://api.music.apple.com/v1/me/recent/played/tracks
Authorization: Bearer {developer_token}
Music-User-Token: {user_token}
Implementation steps:
- Add a background polling loop (every 30-60 seconds) that fetches recently played tracks
- Compare against approved requests by
trackId - Auto-mark matched requests as "played"
Pros: Works without the dashboard being open, detects plays from any device/app Cons: Not real-time (30-60s delay), the recently-played API has undocumented limitations (unclear update frequency, unclear history depth, may miss short plays), Music User Token must be stored server-side and refreshed
Approach C: Hybrid
Use MusicKit JS events (Approach A) when the dashboard is open, and fall back to recently-played polling (Approach B) when it's not. The bot prefers the real-time signal but has the poller as a safety net.
Recommendation
Approach A (MusicKit JS events) is the most reliable and real-time option, especially since the dashboard is already the operator's control panel. Approach B could supplement it but has reliability concerns due to the poorly-documented recently-played API.
Summary of Feasibility
| Aspect | Feasibility | Notes |
|---|---|---|
| Add to playlist (REST) | High | Well-documented API, straightforward |
| Add to queue (MusicKit JS) | High | Requires dashboard open during playback |
| Auto-detect played (MusicKit JS) | High | Real-time, but scoped to dashboard session |
| Auto-detect played (server-side) | Medium | Recently-played API is poorly documented |
| Server-side webhook/push | Not possible | Apple provides no such mechanism |
Key Files to Modify
[SongRequest/templates/index.html](SongRequest/templates/index.html)-- embed MusicKit JS, add authorize flow, add event listeners[SongRequest/web.py](SongRequest/web.py)-- new/api/now-playingendpoint, MusicKit config endpoint[SongRequest/plugin.py](SongRequest/plugin.py)-- auto-play detection callback, IRC announcements[SongRequest/config.py](SongRequest/config.py)-- new config values for Apple Developer credentials- New:
[SongRequest/apple_music.py](SongRequest/apple_music.py)-- JWT generation, REST API wrapper (for Approach A playlist add and/or recently-played polling) [SongRequest/store.py](SongRequest/store.py)-- optionalplayed_atcolumn, query for matching trackId against approved requests
New Dependencies
PyJWT+cryptography-- for generating Apple Developer JWT tokens (server-side)- No new JS dependencies -- MusicKit JS is loaded from Apple's CDN