/** * Spotify WebView Injection Scripts * * Two-phase extraction approach: * Phase 1 (SPOTIFY_TOKEN_INTERCEPTOR_SCRIPT): Injected before page load via * injectedJavaScriptBeforeContentLoaded. Monkey-patches window.fetch to capture * the bearer token from Spotify API requests as they happen. * Phase 2 (SPOTIFY_EXPORT_SCRIPT): Injected after user consents. Uses the captured * token to call Spotify APIs and extract listening data. * * Token Discovery: * The Spotify web player obtains its bearer token via: * GET https://open.spotify.com/get_access_token?reason=transport&productType=web_player * This returns JSON with { clientId, accessToken, accessTokenExpirationTimestampMs }. * The token is also present in the Authorization header of all subsequent API calls. * * API Endpoints (verified via network analysis): * GraphQL: POST https://api-partner.spotify.com/pathfinder/v2/query * Primary export target: fetchLibraryTracks (liked songs) * Legacy fallbacks retained below for recently-played debugging */ /** * Phase 1: Token Interceptor * Must be injected via injectedJavaScriptBeforeContentLoaded so it patches * fetch BEFORE the Spotify web player code runs. */ export declare const SPOTIFY_TOKEN_INTERCEPTOR_SCRIPT: string; /** * Consent Popup Script * Shows user consent UI before exporting data. * Note: Uses static string concatenation for the consent UI. This popup only * contains hardcoded Onairos-controlled content with no external input. */ export declare const SPOTIFY_CONSENT_POPUP_SCRIPT = "\n(function() {\n try {\n var existing = document.getElementById('onairos-consent-overlay');\n if (existing) existing.remove();\n\n var overlay = document.createElement('div');\n overlay.id = 'onairos-consent-overlay';\n overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.85);z-index:999999;display:flex;align-items:center;justify-content:center;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;';\n\n var popup = document.createElement('div');\n popup.style.cssText = 'background:#121212;border-radius:16px;padding:32px;max-width:400px;width:90%;box-shadow:0 20px 60px rgba(0,0,0,0.5);border:1px solid #282828;';\n\n var icon = document.createElement('div');\n icon.style.cssText = 'text-align:center;font-size:48px;margin-bottom:16px;';\n icon.textContent = '\\u{1F3B5}';\n\n var title = document.createElement('h2');\n title.style.cssText = 'margin:0 0 12px 0;font-size:24px;color:#FFFFFF;text-align:center;';\n title.textContent = 'Export Spotify Data?';\n\n var desc = document.createElement('p');\n desc.style.cssText = 'margin:0 0 24px 0;color:#B3B3B3;font-size:16px;line-height:1.5;text-align:center;';\n desc.textContent = 'Allow Onairos to export your Spotify liked songs and profile data for analysis?';\n\n var btnRow = document.createElement('div');\n btnRow.style.cssText = 'display:flex;gap:12px;justify-content:center;';\n\n var denyBtn = document.createElement('button');\n denyBtn.id = 'onairos-deny';\n denyBtn.textContent = 'Deny';\n denyBtn.style.cssText = 'flex:1;padding:14px 24px;border:2px solid #404040;background:transparent;color:#B3B3B3;border-radius:8px;font-size:16px;font-weight:600;cursor:pointer;';\n\n var allowBtn = document.createElement('button');\n allowBtn.id = 'onairos-allow';\n allowBtn.textContent = 'Allow';\n allowBtn.style.cssText = 'flex:1;padding:14px 24px;border:none;background:linear-gradient(135deg,#1DB954 0%,#1AA34A 100%);color:white;border-radius:8px;font-size:16px;font-weight:600;cursor:pointer;';\n\n btnRow.appendChild(denyBtn);\n btnRow.appendChild(allowBtn);\n popup.appendChild(icon);\n popup.appendChild(title);\n popup.appendChild(desc);\n popup.appendChild(btnRow);\n overlay.appendChild(popup);\n document.body.appendChild(overlay);\n\n denyBtn.onclick = function() {\n overlay.remove();\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'SPOTIFY_CONSENT',\n status: 'denied'\n }));\n };\n\n allowBtn.onclick = function() {\n allowBtn.textContent = 'Starting...';\n allowBtn.disabled = true;\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'SPOTIFY_CONSENT',\n status: 'allowed'\n }));\n setTimeout(function() { overlay.remove(); }, 500);\n };\n } catch (error) {\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'SPOTIFY_CONSENT',\n status: 'error',\n message: error.message\n }));\n }\n})();\ntrue;\n"; /** * Phase 2: Export Script * Uses the token captured by the interceptor to fetch all user data. * Strategy: * 1. Read token from window.__onairos_spotify__ (set by interceptor) * 2. Resolve profile via Spotify's first-party pathfinder GraphQL * 3. Paginate fetchLibraryTracks to export liked songs * 4. Send complete dataset back to React Native */ export declare const SPOTIFY_EXPORT_SCRIPT: string; export declare const SPOTIFY_SUCCESS_SCRIPT = "\n(function() {\n})();\ntrue;\n"; export declare const SPOTIFY_ERROR_SCRIPT = "\n(function() {\n})();\ntrue;\n"; //# sourceMappingURL=spotify.d.ts.map