2026-03-04 18:25:09 +00:00

224 lines
8.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { createClient } from 'jsr:@supabase/supabase-js@2';
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
interface WeatherRequest {
lat: number;
lon: number;
start_date: string; // ISO date string
end_date: string; // ISO date string
units?: 'metric' | 'imperial' | 'standard';
lang?: string;
}
interface DailyForecast {
date: string;
temp_min: number;
temp_max: number;
temp_day: number;
feels_like_day: number;
humidity: number;
wind_speed: number;
weather_main: string;
weather_description: string;
weather_icon: string;
pop: number; // Probability of precipitation
sunrise: number;
sunset: number;
}
Deno.serve(async (req) => {
// Handle CORS preflight
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const { lat, lon, start_date, end_date, units = 'metric', lang = 'tr' }: WeatherRequest = await req.json();
// Validate input
if (!lat || !lon || !start_date || !end_date) {
return new Response(
JSON.stringify({ error: 'lat, lon, start_date ve end_date gereklidir' }),
{ status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Get API key from environment
const apiKey = Deno.env.get('INTEGRATIONS_API_KEY');
if (!apiKey) {
console.error('INTEGRATIONS_API_KEY bulunamadı');
return new Response(
JSON.stringify({ error: 'Hava durumu servisi yapılandırılmamış' }),
{ status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Call Weather API
const weatherUrl = `https://app-9w9pd00g5j41-api-wL1zlmgJGAlY.gateway.appmedo.com/data/3.0/onecall?lat=${lat}&lon=${lon}&units=${units}&lang=${lang}`;
console.log('Hava durumu API çağrısı yapılıyor:', { lat, lon, units, lang });
const weatherResponse = await fetch(weatherUrl, {
method: 'GET',
headers: {
'X-Gateway-Authorization': `Bearer ${apiKey}`,
'Accept': 'application/json',
},
});
if (!weatherResponse.ok) {
const errorText = await weatherResponse.text();
console.error('Hava durumu API hatası:', weatherResponse.status, errorText);
return new Response(
JSON.stringify({ error: 'Hava durumu verisi alınamadı', details: errorText }),
{ status: weatherResponse.status, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
const weatherData = await weatherResponse.json();
// Parse dates - use UTC to avoid timezone issues
const startDate = new Date(start_date + 'T00:00:00Z');
const endDate = new Date(end_date + 'T00:00:00Z');
// Get current date from the weather API response timezone or use UTC
const now = new Date();
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
// Calculate days difference
const daysFromToday = Math.floor((startDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
const tripDuration = Math.floor((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)) + 1;
console.log('Tarih bilgileri:', {
daysFromToday,
tripDuration,
start_date,
end_date,
today: today.toISOString().split('T')[0],
availableDailyForecasts: weatherData.daily?.length || 0
});
// Check if we have any daily forecast data
if (!weatherData.daily || weatherData.daily.length === 0) {
console.error('API yanıtında günlük tahmin verisi yok');
return new Response(
JSON.stringify({
error: 'Hava durumu tahmini mevcut değil',
message: 'Seçilen konum için hava durumu verisi alınamadı'
}),
{ status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Extract daily forecasts for trip dates
const forecasts: DailyForecast[] = [];
if (weatherData.daily && Array.isArray(weatherData.daily)) {
// The API returns forecasts starting from today (index 0)
// We need to map trip days to the correct forecast indices
for (let i = 0; i < tripDuration && i < weatherData.daily.length; i++) {
// Calculate which forecast index to use
const forecastIndex = Math.max(0, Math.min(daysFromToday + i, weatherData.daily.length - 1));
const dailyData = weatherData.daily[forecastIndex];
if (dailyData) {
const forecastDate = new Date(startDate);
forecastDate.setUTCDate(startDate.getUTCDate() + i);
forecasts.push({
date: forecastDate.toISOString().split('T')[0],
temp_min: dailyData.temp?.min || dailyData.temp,
temp_max: dailyData.temp?.max || dailyData.temp,
temp_day: dailyData.temp?.day || dailyData.temp,
feels_like_day: dailyData.feels_like?.day || dailyData.feels_like,
humidity: dailyData.humidity,
wind_speed: dailyData.wind_speed,
weather_main: dailyData.weather?.[0]?.main || 'Clear',
weather_description: dailyData.weather?.[0]?.description || 'açık',
weather_icon: dailyData.weather?.[0]?.icon || '01d',
pop: dailyData.pop || 0,
sunrise: dailyData.sunrise,
sunset: dailyData.sunset,
});
}
}
}
// If no daily data available, try to use hourly data for near-term forecasts
if (forecasts.length === 0 && weatherData.hourly && Array.isArray(weatherData.hourly)) {
console.log('Günlük veri yok, saatlik veriden tahmin oluşturuluyor');
// Group hourly data by day
const hourlyByDay: { [key: string]: any[] } = {};
for (let i = 0; i < Math.min(tripDuration, 2); i++) {
const forecastDate = new Date(startDate);
forecastDate.setUTCDate(startDate.getUTCDate() + i);
const dateKey = forecastDate.toISOString().split('T')[0];
hourlyByDay[dateKey] = [];
// Find hourly data for this day
const targetTimestamp = forecastDate.getTime() / 1000;
const dayStart = targetTimestamp;
const dayEnd = targetTimestamp + (24 * 60 * 60);
for (const hourData of weatherData.hourly) {
if (hourData.dt >= dayStart && hourData.dt < dayEnd) {
hourlyByDay[dateKey].push(hourData);
}
}
// Calculate daily summary from hourly data
if (hourlyByDay[dateKey].length > 0) {
const temps = hourlyByDay[dateKey].map(h => h.temp);
const midDayData = hourlyByDay[dateKey][Math.floor(hourlyByDay[dateKey].length / 2)];
forecasts.push({
date: dateKey,
temp_min: Math.min(...temps),
temp_max: Math.max(...temps),
temp_day: temps.reduce((a, b) => a + b, 0) / temps.length,
feels_like_day: midDayData.feels_like,
humidity: midDayData.humidity,
wind_speed: midDayData.wind_speed,
weather_main: midDayData.weather?.[0]?.main || 'Clear',
weather_description: midDayData.weather?.[0]?.description || 'açık',
weather_icon: midDayData.weather?.[0]?.icon || '01d',
pop: Math.max(...hourlyByDay[dateKey].map(h => h.pop || 0)),
sunrise: 0,
sunset: 0,
});
}
}
}
// Return whatever forecasts we have
console.log(`${forecasts.length} günlük tahmin döndürülüyor`);
return new Response(
JSON.stringify({
forecasts,
location: {
lat: weatherData.lat,
lon: weatherData.lon,
timezone: weatherData.timezone,
},
units,
}),
{ status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
} catch (error: any) {
console.error('Hava durumu fonksiyonu hatası:', error);
return new Response(
JSON.stringify({ error: error.message || 'Sunucu hatası' }),
{ status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
});