feat: geo-device-service, Weather по геопозиции, Discover вкладка GooSeek
Geo Device Service: - Новый сервис определения геопозиции, устройства, браузера - geoip-lite, ua-parser-js, CORS - GET/POST /api/context Frontend: - /api/geo-context — прокси к geo-device, fallback при недоступности - geoDevice.ts — fetchContextWithClient, fetchContextWithGeolocation - Weather: геопозиция через geo-device + GeoJS + ipwhois fallback - Weather API: поддержка city (геокодинг Open-Meteo) - Discover: вкладка GooSeek по умолчанию Документация: - MICROSERVICES.md — секция 3.9 Geo Device Service Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,22 +1,50 @@
|
||||
const geocodeCity = async (city: string): Promise<{ lat: number; lng: number; name: string } | null> => {
|
||||
const res = await fetch(
|
||||
`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1`,
|
||||
);
|
||||
const data = await res.json();
|
||||
const result = data.results?.[0];
|
||||
if (!result?.latitude || !result?.longitude) return null;
|
||||
return {
|
||||
lat: result.latitude,
|
||||
lng: result.longitude,
|
||||
name: result.name ?? city,
|
||||
};
|
||||
};
|
||||
|
||||
export const POST = async (req: Request) => {
|
||||
try {
|
||||
const body: {
|
||||
lat: number;
|
||||
lng: number;
|
||||
lat?: number;
|
||||
lng?: number;
|
||||
city?: string;
|
||||
measureUnit: 'Imperial' | 'Metric';
|
||||
} = await req.json();
|
||||
|
||||
if (!body.lat || !body.lng) {
|
||||
let lat: number;
|
||||
let lng: number;
|
||||
let cityName: string | undefined = body.city;
|
||||
|
||||
if (body.lat != null && body.lng != null) {
|
||||
lat = body.lat;
|
||||
lng = body.lng;
|
||||
} else if (body.city?.trim()) {
|
||||
const geo = await geocodeCity(body.city.trim());
|
||||
if (!geo) {
|
||||
return Response.json({ message: 'City not found.' }, { status: 404 });
|
||||
}
|
||||
lat = geo.lat;
|
||||
lng = geo.lng;
|
||||
cityName = geo.name;
|
||||
} else {
|
||||
return Response.json(
|
||||
{
|
||||
message: 'Invalid request.',
|
||||
},
|
||||
{ message: 'Invalid request. Provide lat/lng or city.' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const res = await fetch(
|
||||
`https://api.open-meteo.com/v1/forecast?latitude=${body.lat}&longitude=${body.lng}¤t=weather_code,temperature_2m,is_day,relative_humidity_2m,wind_speed_10m&timezone=auto${
|
||||
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lng}¤t=weather_code,temperature_2m,is_day,relative_humidity_2m,wind_speed_10m&timezone=auto${
|
||||
body.measureUnit === 'Metric' ? '' : '&temperature_unit=fahrenheit'
|
||||
}${body.measureUnit === 'Metric' ? '' : '&wind_speed_unit=mph'}`,
|
||||
);
|
||||
@@ -159,7 +187,7 @@ export const POST = async (req: Request) => {
|
||||
break;
|
||||
}
|
||||
|
||||
return Response.json(weather);
|
||||
return Response.json({ ...weather, city: cityName });
|
||||
} catch (err) {
|
||||
console.error('An error occurred while getting home widgets', err);
|
||||
return Response.json(
|
||||
|
||||
Reference in New Issue
Block a user