document.addEventListener('DOMContentLoaded', async () => { const extractBtn = document.getElementById('extract-btn'); const configBtn = document.getElementById('config-btn'); const status = document.getElementById('status'); const warning = document.getElementById('warning'); const notYoutube = document.getElementById('not-youtube'); const videoSection = document.getElementById('video-section'); const videoTitle = document.getElementById('video-title'); const videoUrl = document.getElementById('video-url'); // Config button click handler (needs to work regardless of page) configBtn.addEventListener('click', () => { chrome.tabs.create({ url: chrome.runtime.getURL('options.html') }); }); // Check if we're on YouTube const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tab.url || !tab.url.includes('youtube.com/watch')) { notYoutube.classList.remove('hidden'); return; } // Check API token configuration const result = await chrome.storage.sync.get(['apiToken', 'apiBaseUrl']); const apiToken = result.apiToken; const apiBaseUrl = result.apiBaseUrl || 'http://192-168-100-199.sslip.io'; if (!apiToken) { warning.classList.remove('hidden'); extractBtn.disabled = true; } else { videoSection.classList.remove('hidden'); } // Get video information from content script let currentVideoInfo = null; try { const response = await chrome.tabs.sendMessage(tab.id, { action: 'getVideoInfo' }); if (response && response.title && response.url) { currentVideoInfo = response; videoTitle.textContent = response.title; videoUrl.textContent = response.url; } else { videoTitle.textContent = 'Video information not available'; videoUrl.textContent = tab.url; } } catch (error) { console.error('Error getting video info:', error); videoTitle.textContent = 'Video information not available'; videoUrl.textContent = tab.url; } // Function to clean YouTube URL function getCleanVideoUrl(url) { const match = url.match(/[?&]v=([^&]+)/); if (match) { return `https://www.youtube.com/watch?v=${match[1]}`; } return url; // Return original if we can't extract video ID } // Extract button click handler extractBtn.addEventListener('click', async () => { if (!apiToken) { showStatus('Please configure your API token first', 'error'); return; } extractBtn.disabled = true; extractBtn.textContent = 'Extracting...'; showStatus('Starting audio extraction...', 'loading'); try { // Use clean URL for the API request const cleanUrl = getCleanVideoUrl(tab.url); console.log('Making extraction request:', { apiBaseUrl, cleanUrl, title: currentVideoInfo?.title, hasToken: !!apiToken }); const response = await fetch(`${apiBaseUrl}/api/v1/extractions/?url=${encodeURIComponent(cleanUrl)}`, { method: 'POST', headers: { 'API-TOKEN': apiToken } }); console.log('Response status:', response.status, response.statusText); if (!response.ok) { let errorMessage = `HTTP ${response.status}`; try { const errorData = await response.json(); if (errorData.detail) { errorMessage = errorData.detail; } else if (errorData.message) { errorMessage = errorData.message; } else if (typeof errorData === 'string') { errorMessage = errorData; } } catch (e) { // If we can't parse JSON, use the status text errorMessage = response.statusText || errorMessage; } throw new Error(errorMessage); } await response.json(); const successMessage = currentVideoInfo?.title ? `Audio extraction started for "${currentVideoInfo.title}"! Check your soundboard for the result.` : 'Audio extraction started successfully! Check your soundboard for the result.'; showStatus(successMessage, 'success'); // Close popup after successful extraction setTimeout(() => { window.close(); }, 2000); } catch (error) { console.error('Extraction error:', error); let errorMessage = 'Unknown error occurred'; if (error.message) { errorMessage = error.message; } else if (error.name === 'TypeError' && error.message.includes('fetch')) { errorMessage = 'Cannot connect to API server. Check your API base URL and network connection.'; } else if (typeof error === 'string') { errorMessage = error; } showStatus(`Failed to extract audio: ${errorMessage}`, 'error'); } finally { extractBtn.disabled = false; extractBtn.textContent = 'Extract Audio'; } }); function showStatus(message, type) { status.textContent = message; status.className = `status ${type}`; status.classList.remove('hidden'); } });