diff --git a/src/routes/integrations.js b/src/routes/integrations.js index 94251d9..70cbb6a 100644 --- a/src/routes/integrations.js +++ b/src/routes/integrations.js @@ -171,26 +171,40 @@ export async function integrationRoutes(app) { const { rows: [loc] } = await pool.query(`SELECT config FROM integrations WHERE slug = 'hotel_location'`) const lat = loc?.config?.latitude || '51.5072' const lon = loc?.config?.longitude || '-0.1276' - // Two separate subscriptions, two separate keys — test each against the - // endpoint weather actually uses it for (Spot -> daily, Forecast -> - // hourly). forecast_api_key is optional, only tested if set. - const errors = [] - const dailyRes = await fetch( - `https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/daily?latitude=${lat}&longitude=${lon}`, - { headers: { apikey: creds.api_key }, signal: AbortSignal.timeout(8000) } - ) - if (dailyRes.status === 401 || dailyRes.status === 403) errors.push('Spot key: invalid or not subscribed to the daily endpoint') - else if (!dailyRes.ok) errors.push(`Spot key: daily endpoint returned ${dailyRes.status}`) + // Which of Spot vs Forecast actually covers which timestep isn't + // documented anywhere we could find, and a first guess (Forecast -> + // hourly) turned out wrong live — so this tests every configured key + // against every endpoint and reports the full matrix, rather than + // assuming, so the actual working combination is on screen instead of + // guessed at again. + const keys = [['Spot', creds.api_key]] + if (creds.forecast_api_key) keys.push(['Forecast', creds.forecast_api_key]) + const endpoints = ['daily', 'hourly', 'three-hourly'] - if (creds.forecast_api_key) { - const hourlyRes = await fetch( - `https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/hourly?latitude=${lat}&longitude=${lon}`, - { headers: { apikey: creds.forecast_api_key }, signal: AbortSignal.timeout(8000) } - ) - if (hourlyRes.status === 401 || hourlyRes.status === 403) errors.push('Forecast key: invalid or not subscribed to the hourly endpoint') - else if (!hourlyRes.ok) errors.push(`Forecast key: hourly endpoint returned ${hourlyRes.status}`) + const results = [] + for (const [keyName, key] of keys) { + for (const endpoint of endpoints) { + let outcome + try { + const res = await fetch( + `https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/${endpoint}?latitude=${lat}&longitude=${lon}`, + { headers: { apikey: key }, signal: AbortSignal.timeout(8000) } + ) + if (res.status === 401 || res.status === 403) outcome = 'not subscribed' + else if (!res.ok) outcome = `HTTP ${res.status}` + else outcome = 'OK' + } catch (e) { + outcome = `error: ${e.message}` + } + results.push(`${keyName}/${endpoint}: ${outcome}`) + } } - if (errors.length) throw new Error(errors.join(' | ')) + + // Frontend renders `message` when ok, `error` when not — set both to the + // same diagnostic text so the full matrix shows up either way. + const summary = results.join(' | ') + const ok = results.some(r => r.endsWith('OK')) + return { ok, message: summary, error: summary } } else if (req.params.slug === 'sambapos') { const errors = []