/** * Departures route handler * Handles fetching and returning transit departure data */ const https = require('https'); /** * Fetch departures for a specific site from SL Transport API * @param {string} siteId - The site ID to fetch departures for * @param {Object} options - Query options * @param {number} options.forecast - Time window in minutes (default: 60) * @param {string} options.transport - Transport mode filter (e.g. 'BUS', 'METRO') * @returns {Promise} - Departure data */ function fetchDeparturesForSite(siteId, options = {}) { return new Promise((resolve, reject) => { const params = new URLSearchParams(); params.set('forecast', options.forecast || 60); if (options.transport) { params.set('transport', options.transport); } const apiUrl = `https://transport.integration.sl.se/v1/sites/${siteId}/departures?${params}`; console.log(`Fetching data from: ${apiUrl}`); https.get(apiUrl, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const parsedData = JSON.parse(data); resolve(parsedData); } catch (error) { console.error('Error parsing departures API response:', error); resolve({ departures: [], error: 'Failed to parse API response: ' + error.message }); } }); }).on('error', (error) => { console.error('Error fetching departures:', error); reject(error); }); }); } /** * Fetch departures for all enabled sites * @param {Array} enabledSites - Array of enabled site configurations * @returns {Promise} - Object with sites array containing departure data */ async function fetchAllDepartures(enabledSites, globalOptions = {}) { if (enabledSites.length === 0) { return { sites: [], error: 'No enabled sites configured' }; } try { const sitesPromises = enabledSites.map(async (site) => { try { const siteOptions = { forecast: site.forecast || globalOptions.forecast || 60, transport: site.transport || globalOptions.transport || '' }; const departureData = await fetchDeparturesForSite(site.id, siteOptions); return { siteId: site.id, siteName: site.name, data: departureData }; } catch (error) { console.error(`Error fetching departures for site ${site.id}:`, error); return { siteId: site.id, siteName: site.name, error: error.message }; } }); const results = await Promise.all(sitesPromises); return { sites: results }; } catch (error) { console.error('Error fetching all departures:', error); return { sites: [], error: error.message }; } } /** * Handle departures API endpoint * @param {http.IncomingMessage} req - HTTP request object * @param {http.ServerResponse} res - HTTP response object * @param {Object} config - Application configuration */ async function handleDepartures(req, res, config) { try { const enabledSites = config.sites.filter(site => site.enabled); const globalOptions = { forecast: config.forecast || 60, transport: config.transport || '' }; const data = await fetchAllDepartures(enabledSites, globalOptions); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); } catch (error) { console.error('Error handling departures request:', error); res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: error.message })); } } module.exports = { handleDepartures, fetchDeparturesForSite, fetchAllDepartures };