feat: add cheerio nps scraping and nws weather alerts
This commit is contained in:
parent
f7b311802f
commit
0d88c2d5cb
|
|
@ -5,6 +5,7 @@
|
|||
"main": "server.js",
|
||||
"scripts": { "start": "node server.js" },
|
||||
"dependencies": {
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"express": "^4.18.2",
|
||||
"node-cron": "^3.0.3"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const fs = require('fs');
|
|||
const http = require('http');
|
||||
const https = require('https');
|
||||
const path = require('path');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json({ limit: '1mb' }));
|
||||
|
|
@ -62,16 +63,36 @@ async function getWeather(location) {
|
|||
}
|
||||
}
|
||||
|
||||
async function getNpsAlerts(parkCode) {
|
||||
async function scrapeNpsConditions(parkCode) {
|
||||
if (!parkCode) return null;
|
||||
const url = `https://www.nps.gov/${parkCode}/planyourvisit/conditions.htm`;
|
||||
try {
|
||||
const data = await fetchJson(`https://developer.nps.gov/api/v1/alerts?parkCode=${parkCode}&api_key=DEMO_KEY`);
|
||||
if (data.data && data.data.length > 0) {
|
||||
return data.data.map(a => `⚠️ ${a.title}`).slice(0, 3).join('\n');
|
||||
const html = await fetchText(url);
|
||||
const $ = cheerio.load(html);
|
||||
const alerts = [];
|
||||
$('.Alert-title').each((i, el) => {
|
||||
alerts.push(`⚠️ ${$(el).text().trim()}`);
|
||||
});
|
||||
if (alerts.length > 0) {
|
||||
return alerts.slice(0, 5).join('\n');
|
||||
}
|
||||
return 'No active NPS alerts.';
|
||||
return 'No active NPS conditions listed.';
|
||||
} catch (e) {
|
||||
return 'NPS alerts unavailable';
|
||||
console.error('[TripService] NPS scrape error:', e.message);
|
||||
return 'NPS conditions unavailable';
|
||||
}
|
||||
}
|
||||
|
||||
async function getWeatherAlerts(stateCode) {
|
||||
try {
|
||||
const data = await fetchJson(`https://api.weather.gov/alerts/active?area=${stateCode}`);
|
||||
if (data.features && data.features.length > 0) {
|
||||
return data.features.map(f => `🌩️ ${f.properties.event || f.properties.headline}`).slice(0, 3).join('\n');
|
||||
}
|
||||
return 'No active weather alerts.';
|
||||
} catch (e) {
|
||||
console.error('[TripService] Weather alerts error:', e.message);
|
||||
return 'Weather alerts unavailable';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,15 +310,17 @@ function sendWhatsApp(to, message) {
|
|||
// ── Briefing Generation ──────────────────────────────────────────────────────
|
||||
async function generateAndSendBriefing(trip, dayPlan) {
|
||||
const weather = await getWeather(dayPlan.location || 'Pigeon Forge, TN');
|
||||
const nps = await getNpsAlerts(trip.npsParkCode);
|
||||
const weatherAlerts = await getWeatherAlerts('TN');
|
||||
const nps = await scrapeNpsConditions(trip.npsParkCode);
|
||||
const traffic = await getTdotTraffic();
|
||||
const insight = await getAiInsight(dayPlan.activities, dayPlan.location || 'Smoky Mountains', trip);
|
||||
|
||||
const message = `*🏕️ ${trip.name} - ${dayPlan.date} Briefing*\n\n` +
|
||||
`*🌤️ Weather (${dayPlan.location || 'Pigeon Forge'}):* ${weather}\n\n` +
|
||||
`*🌩️ Weather Alerts (TN):*\n${weatherAlerts}\n\n` +
|
||||
`*📋 Today's Plan:*\n${dayPlan.activities}\n\n` +
|
||||
`*🍴 Meals:*\n${dayPlan.meals}\n\n` +
|
||||
(nps ? `*🌲 Park Alerts:*\n${nps}\n\n` : '') +
|
||||
(nps ? `*🌲 Park Conditions:*\n${nps}\n\n` : '') +
|
||||
`*🚗 Traffic Info:*\n${traffic}\n\n` +
|
||||
`*🤖 AI Insight:*\n${insight}`;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
"briefingTime": "07:00",
|
||||
"sendToGroup": true,
|
||||
"groupUrls": [
|
||||
"https://chat.whatsapp.com/YOUR_GROUP_INVITE_LINK_1",
|
||||
"https://chat.whatsapp.com/YOUR_GROUP_INVITE_LINK_2"
|
||||
"https://chat.whatsapp.com/FXO0SCLA8DpJwClNNWdhhx"
|
||||
],
|
||||
"npsParkCode": "grsm",
|
||||
"days": [
|
||||
|
|
|
|||
Loading…
Reference in New Issue