import { Hono } from "hono"; import { PARK_MAP } from "../../../lib/parks"; import { QUEUE_TIMES_IDS } from "../../../lib/queue-times-map"; import { getCoasterSet } from "../../../lib/coaster-data"; import { getTodayLocal, isWithinOperatingWindow } from "../../../lib/env"; import { fetchLiveRides } from "../../../lib/scrapers/queuetimes"; import { scrapeRidesForDay } from "../../../lib/scrapers/sixflags"; import { getDayData } from "../db/queries"; import { TtlCache } from "../services/cache"; import type { LiveRidesResult } from "../../../lib/scrapers/queuetimes"; const liveRidesCache = new TtlCache(5 * 60 * 1000); const app = new Hono(); app.get("/:id/rides", async (c) => { const id = c.req.param("id"); const park = PARK_MAP.get(id); if (!park) return c.json({ error: "Park not found" }, 404); const today = getTodayLocal(); const todayData = getDayData(id, today); const withinWindow = todayData?.hoursLabel ? isWithinOperatingWindow(todayData.hoursLabel, park.timezone) : false; const queueTimesId = QUEUE_TIMES_IDS[id]; let liveRides: LiveRidesResult | null = null; if (queueTimesId) { liveRides = liveRidesCache.get(id); if (liveRides === null) { const coasterSet = getCoasterSet(id); liveRides = await fetchLiveRides(queueTimesId, coasterSet).catch(() => null); if (liveRides) liveRidesCache.set(id, liveRides); } if (liveRides && !withinWindow) { liveRides = { ...liveRides, rides: liveRides.rides.map((r) => ({ ...r, isOpen: false, waitMinutes: 0 })), }; } } const isWeatherDelay = withinWindow && liveRides !== null && liveRides.rides.length > 0 && liveRides.rides.every((r) => !r.isOpen); let scheduleFallback = null; if (!liveRides) { scheduleFallback = await scrapeRidesForDay(park.apiId, today).catch(() => null); } c.header("Cache-Control", "public, max-age=60, stale-while-revalidate=120"); return c.json({ parkId: id, today, parkOpenToday: !!(todayData?.isOpen && todayData?.hoursLabel), withinWindow, isWeatherDelay, liveRides, scheduleFallback, }); }); export default app;