export const dynamic = 'force-dynamic'; import { NextResponse } from "next/server"; // Convert WMO weather codes to wttr.in-compatible codes for emoji mapping function wmoToWttrCode(wmo: number): string { if (wmo === 0) return "113"; // Clear sunny if (wmo === 1) return "116"; // Mainly clear if (wmo === 2) return "116"; // Partly cloudy if (wmo === 3) return "122"; // Overcast if (wmo >= 45 && wmo <= 48) return "143"; // Fog if (wmo >= 51 && wmo <= 55) return "185"; // Drizzle if (wmo >= 56 && wmo <= 57) return "281"; // Freezing drizzle if (wmo >= 61 && wmo <= 65) return "305"; // Rain if (wmo >= 66 && wmo <= 67) return "281"; // Freezing rain if (wmo >= 71 && wmo <= 77) return "227"; // Snow if (wmo >= 80 && wmo <= 82) return "305"; // Rain showers if (wmo >= 85 && wmo <= 86) return "260"; // Snow showers if (wmo === 95) return "200"; // Thunderstorm if (wmo >= 96 && wmo <= 99) return "389"; // Thunderstorm with hail return "116"; } function wmoToDesc(wmo: number): string { if (wmo === 0) return "Ясно"; if (wmo === 1) return "Преим. ясно"; if (wmo === 2) return "Переменная облачность"; if (wmo === 3) return "Пасмурно"; if (wmo === 45 || wmo === 48) return "Туман"; if (wmo >= 51 && wmo <= 55) return "Морось"; if (wmo >= 61 && wmo <= 65) return "Дождь"; if (wmo >= 71 && wmo <= 77) return "Снег"; if (wmo >= 80 && wmo <= 82) return "Ливень"; if (wmo >= 85 && wmo <= 86) return "Снегопад"; if (wmo === 95) return "Гроза"; if (wmo >= 96 && wmo <= 99) return "Гроза с градом"; return "Облачно"; } export async function GET() { try { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 8000); const url = "https://api.open-meteo.com/v1/forecast?" + new URLSearchParams({ latitude: "59.9343", longitude: "30.3351", current: "temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m", daily: "weather_code,temperature_2m_max,temperature_2m_min", timezone: "Europe/Moscow", forecast_days: "3", }); const res = await fetch(url, { signal: controller.signal, cache: "no-store", headers: { "Accept": "application/json" }, }); clearTimeout(timeout); if (!res.ok) throw new Error(`Open-Meteo responded ${res.status}`); const data = await res.json(); const current = data.current; const daily = data.daily; const forecast = (daily.time || []).slice(0, 3).map((date: string, i: number) => ({ date, maxTemp: String(Math.round(daily.temperature_2m_max[i])), minTemp: String(Math.round(daily.temperature_2m_min[i])), desc: wmoToDesc(daily.weather_code[i]), weatherCode: wmoToWttrCode(daily.weather_code[i]), })); return NextResponse.json({ temp: String(Math.round(current.temperature_2m)), feelsLike: String(Math.round(current.apparent_temperature)), humidity: String(current.relative_humidity_2m), desc: wmoToDesc(current.weather_code), weatherCode: wmoToWttrCode(current.weather_code), windSpeed: String(Math.round(current.wind_speed_10m / 3.6)), forecast, }); } catch (e) { console.error("Weather fetch error:", e); return NextResponse.json( { temp: "—", feelsLike: "—", humidity: "—", desc: "Нет данных", weatherCode: "116", windSpeed: "—", forecast: [], error: String(e), }, { status: 200 } ); } }