/** * Background script - handles cookie operations and API calls */ // Initialize API on startup browser.runtime.onInstalled.addListener(async () => { console.log('GallerySubscriber extension installed'); await api.init(); }); browser.runtime.onStartup.addListener(async () => { await api.init(); }); // Handle messages from popup and options pages browser.runtime.onMessage.addListener((message, sender, sendResponse) => { handleMessage(message) .then(sendResponse) .catch(error => { console.error('Message handler error:', error); sendResponse({ error: error.message }); }); return true; // Keep channel open for async response }); /** * Route messages to appropriate handlers * @param {object} message - Message object with type property * @returns {Promise} - Response data */ async function handleMessage(message) { switch (message.type) { case 'EXPORT_COOKIES': return await exportCookies(message.platform); case 'EXPORT_ALL_COOKIES': return await exportAllCookies(); case 'GET_PLATFORM_STATUS': return await getPlatformStatus(); case 'TEST_CONNECTION': return await testConnection(); case 'GET_CONFIG': return await getConfig(); case 'SAVE_CONFIG': return await saveConfig(message.config); default: throw new Error(`Unknown message type: ${message.type}`); } } /** * Export cookies for a single platform to the backend * @param {string} platformKey - Platform identifier * @returns {Promise} - Result object */ async function exportCookies(platformKey) { await api.init(); const platform = PLATFORMS[platformKey]; if (!platform) { throw new Error(`Unknown platform: ${platformKey}`); } let credentialData; let credentialType; if (platform.authType === 'token') { // Discord and other token-based platforms require manual entry throw new Error(`${platform.name} requires manual token entry in the web UI. Token extraction is not supported for security reasons.`); } // Cookie-based auth const cookies = await extractCookiesForPlatform(platformKey); if (cookies.length === 0) { throw new Error(`No cookies found for ${platform.name}. Please ensure you are logged in.`); } credentialData = toNetscapeFormat(cookies); credentialType = 'cookies'; // Send to backend const result = await api.uploadCredentials(platformKey, credentialType, credentialData); return { success: true, platform: platformKey, cookieCount: cookies.length, message: result.message || 'Credentials exported successfully' }; } /** * Export cookies for all cookie-based platforms * @returns {Promise} - Results for each platform */ async function exportAllCookies() { await api.init(); const results = {}; const platforms = Object.keys(PLATFORMS); for (const platformKey of platforms) { const platform = PLATFORMS[platformKey]; // Skip token-based platforms if (platform.authType === 'token') { results[platformKey] = { success: false, platform: platformKey, skipped: true, message: 'Token-based auth requires manual entry' }; continue; } try { results[platformKey] = await exportCookies(platformKey); } catch (error) { results[platformKey] = { success: false, platform: platformKey, error: error.message }; } } return results; } /** * Get status information for all platforms * @returns {Promise} - Status for each platform */ async function getPlatformStatus() { const status = {}; for (const [key, platform] of Object.entries(PLATFORMS)) { try { if (platform.authType === 'token') { // Token-based platforms status[key] = { name: platform.name, authType: 'token', hasCookies: false, cookieCount: 0, note: platform.note || 'Requires manual token entry' }; } else { // Cookie-based platforms const cookies = await extractCookiesForPlatform(key); status[key] = { name: platform.name, authType: 'cookies', hasCookies: cookies.length > 0, cookieCount: cookies.length }; } } catch (error) { status[key] = { name: platform.name, authType: platform.authType, hasCookies: false, cookieCount: 0, error: error.message }; } } return status; } /** * Test connection to the backend * @returns {Promise} - Connection status */ async function testConnection() { await api.init(); if (!api.isConfigured()) { return { connected: false, error: 'Not configured' }; } try { await api.testConnection(); return { connected: true }; } catch (error) { return { connected: false, error: error.message }; } } /** * Get current configuration * @returns {Promise} - Config object */ async function getConfig() { const config = await browser.storage.local.get(['apiUrl', 'apiKey']); return config; } /** * Save configuration * @param {object} config - Config object with apiUrl and apiKey * @returns {Promise} - Success status */ async function saveConfig(config) { await browser.storage.local.set(config); await api.init(); return { success: true }; }