met_office: add forecast_api_key, a second Met Office DataHub key
Met Office DataHub sells 'Global Spot' and 'Forecast' as separate subscriptions with separate keys. api_key (existing) is Spot, used for the daily endpoint (confirmed live via hvac). forecast_api_key is new and optional -- weather's hourly/three-hourly endpoints try it first, falling back to api_key, then Open-Meteo, per tier. Test route now checks each key against the endpoint it's actually used for (Spot -> daily, Forecast -> hourly) rather than only ever testing api_key against daily. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
5f84a44d1f
commit
210649d7ad
2 changed files with 24 additions and 4 deletions
|
|
@ -60,7 +60,13 @@ export const INTEGRATIONS = {
|
||||||
met_office: {
|
met_office: {
|
||||||
name: 'Met Office DataHub',
|
name: 'Met Office DataHub',
|
||||||
configFields: [],
|
configFields: [],
|
||||||
secretFields: ['api_key'],
|
// Met Office DataHub sells the "Global Spot" and "Forecast" site-specific
|
||||||
|
// products as separate subscriptions, each with its own API key — api_key is
|
||||||
|
// Spot (used for the daily endpoint, confirmed live via hvac); forecast_api_key
|
||||||
|
// is optional and, if set, is what weather's hourly/three-hourly endpoints try
|
||||||
|
// first (falling back to api_key, then to Open-Meteo, per tier — see weather's
|
||||||
|
// lib/weather-fetch.js). Leave it blank if you only have a Spot subscription.
|
||||||
|
secretFields: ['api_key', 'forecast_api_key'],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,12 +171,26 @@ export async function integrationRoutes(app) {
|
||||||
const { rows: [loc] } = await pool.query(`SELECT config FROM integrations WHERE slug = 'hotel_location'`)
|
const { rows: [loc] } = await pool.query(`SELECT config FROM integrations WHERE slug = 'hotel_location'`)
|
||||||
const lat = loc?.config?.latitude || '51.5072'
|
const lat = loc?.config?.latitude || '51.5072'
|
||||||
const lon = loc?.config?.longitude || '-0.1276'
|
const lon = loc?.config?.longitude || '-0.1276'
|
||||||
const res = await fetch(
|
// 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}`,
|
`https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/daily?latitude=${lat}&longitude=${lon}`,
|
||||||
{ headers: { apikey: creds.api_key }, signal: AbortSignal.timeout(8000) }
|
{ headers: { apikey: creds.api_key }, signal: AbortSignal.timeout(8000) }
|
||||||
)
|
)
|
||||||
if (res.status === 401 || res.status === 403) throw new Error('Invalid Met Office API key')
|
if (dailyRes.status === 401 || dailyRes.status === 403) errors.push('Spot key: invalid or not subscribed to the daily endpoint')
|
||||||
if (!res.ok) throw new Error(`Met Office DataHub returned ${res.status}`)
|
else if (!dailyRes.ok) errors.push(`Spot key: daily endpoint returned ${dailyRes.status}`)
|
||||||
|
|
||||||
|
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}`)
|
||||||
|
}
|
||||||
|
if (errors.length) throw new Error(errors.join(' | '))
|
||||||
}
|
}
|
||||||
else if (req.params.slug === 'sambapos') {
|
else if (req.params.slug === 'sambapos') {
|
||||||
const errors = []
|
const errors = []
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue