Fix: weather uses open-meteo directly (wttr.in hangs)
This commit is contained in:
@@ -1,67 +1,36 @@
|
||||
export const dynamic = "force-dynamic";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Попробовать несколько источников
|
||||
const sources = [
|
||||
"https://wttr.in/Saint+Petersburg?format=j1",
|
||||
"https://wttr.in/Saint%20Petersburg?format=j1",
|
||||
"http://wttr.in/Saint+Petersburg?format=j1",
|
||||
];
|
||||
|
||||
let lastError: Error | null = null;
|
||||
|
||||
for (const url of sources) {
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
"User-Agent": "curl/7.74.0",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
return NextResponse.json(data);
|
||||
}
|
||||
} catch (e) {
|
||||
lastError = e as Error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: open-meteo (не через Cloudflare)
|
||||
const geoRes = await fetch("https://geocoding-api.open-meteo.com/v1/search?name=Saint+Petersburg&country=Russia&count=1", {
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
const geoData = await geoRes.json();
|
||||
const loc = geoData.results?.[0];
|
||||
|
||||
if (!loc) throw new Error("Geocoding failed");
|
||||
|
||||
const meteoRes = await fetch(
|
||||
`https://api.open-meteo.com/v1/forecast?latitude=${loc.latitude}&longitude=${loc.longitude}¤t=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,weather_code&wind_speed_unit=kmh`,
|
||||
{ signal: AbortSignal.timeout(5000) }
|
||||
);
|
||||
const meteoData = await meteoRes.json();
|
||||
|
||||
// Нормализовать в формат wttr.in
|
||||
const wmoDescriptions: Record<number, string> = {
|
||||
0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast",
|
||||
45: "Foggy", 48: "Icy fog", 51: "Light drizzle", 53: "Drizzle", 55: "Heavy drizzle",
|
||||
61: "Light rain", 63: "Rain", 65: "Heavy rain", 71: "Light snow", 73: "Snow", 75: "Heavy snow",
|
||||
80: "Light showers", 81: "Showers", 82: "Heavy showers", 95: "Thunderstorm",
|
||||
const WMO_DESCRIPTIONS: Record<number, string> = {
|
||||
0: "Ясно", 1: "Преимущественно ясно", 2: "Переменная облачность", 3: "Пасмурно",
|
||||
45: "Туман", 48: "Ледяной туман", 51: "Лёгкая морось", 53: "Морось", 55: "Сильная морось",
|
||||
61: "Лёгкий дождь", 63: "Дождь", 65: "Сильный дождь",
|
||||
71: "Лёгкий снег", 73: "Снег", 75: "Сильный снег",
|
||||
80: "Небольшой ливень", 81: "Ливень", 82: "Сильный ливень", 95: "Гроза",
|
||||
};
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Open-Meteo: координаты Санкт-Петербурга
|
||||
const lat = 59.9343;
|
||||
const lon = 30.3351;
|
||||
|
||||
const meteoRes = await fetch(
|
||||
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,weather_code&wind_speed_unit=kmh`,
|
||||
{ signal: AbortSignal.timeout(6000) }
|
||||
);
|
||||
|
||||
if (!meteoRes.ok) throw new Error("Open-Meteo error");
|
||||
const meteoData = await meteoRes.json();
|
||||
const c = meteoData.current;
|
||||
|
||||
const normalized = {
|
||||
current_condition: [{
|
||||
temp_C: Math.round(c.temperature_2m).toString(),
|
||||
FeelsLikeC: Math.round(c.apparent_temperature).toString(),
|
||||
humidity: Math.round(c.relative_humidity_2m).toString(),
|
||||
windspeedKmph: Math.round(c.wind_speed_10m).toString(),
|
||||
weatherDesc: [{ value: wmoDescriptions[c.weather_code] || "Unknown" }],
|
||||
weatherDesc: [{ value: WMO_DESCRIPTIONS[c.weather_code] ?? "Неизвестно" }],
|
||||
}],
|
||||
source: "open-meteo",
|
||||
};
|
||||
|
||||
31
weather-proxy.py
Normal file
31
weather-proxy.py
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
import subprocess, json
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def log_message(self, *a): pass
|
||||
def do_GET(self):
|
||||
try:
|
||||
cmd = ["curl", "-s", "--max-time", "5", "https://wttr.in/Saint+Petersburg?format=j1"]
|
||||
result = subprocess.run(cmd, timeout=8, capture_output=True, text=True)
|
||||
if result.stdout and len(result.stdout) > 10:
|
||||
body = result.stdout.encode()
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Content-Length", len(body))
|
||||
self.end_headers()
|
||||
self.wfile.write(body)
|
||||
else:
|
||||
raise Exception("No data rc=" + str(result.returncode))
|
||||
except Exception as e:
|
||||
err = json.dumps({"error": str(e)}).encode()
|
||||
self.send_response(502)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Content-Length", len(err))
|
||||
self.end_headers()
|
||||
self.wfile.write(err)
|
||||
|
||||
if __name__ == "__main__":
|
||||
server = HTTPServer(("0.0.0.0", 8765), Handler)
|
||||
print("Weather proxy on :8765", flush=True)
|
||||
server.serve_forever()
|
||||
Reference in New Issue
Block a user