tele_bot / weather.py
PRC142004's picture
Upload 21 files
945d0f8 verified
import datetime, logging, os, requests, warnings
from typing import Optional, List, Dict
from dotenv import load_dotenv
from fastapi import FastAPI, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from geopy.geocoders import Photon
warnings.filterwarnings("ignore")
load_dotenv()
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
logger = logging.getLogger("WeatherAPI")
app = FastAPI(title="Farmer Weather API")
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
PHOTON = Photon(user_agent="FarmerWeatherApp", timeout=10)
NV_KEY = os.getenv("NVIDIA_API_KEY")
OWM_KEY = os.getenv("OPENWEATHERMAP_API_KEY")
ICONS = {0: "β˜€οΈ", 1: "β›…", 2: "β›…", 3: "β›…", 45: "🌫️", 51: "🌦️", 61: "🌧️", 71: "❄️", 80: "🌦️", 95: "β›ˆοΈ"}
DESC = {0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast", 45: "Fog", 51: "Drizzle", 61: "Rain", 71: "Snow", 80: "Showers", 95: "Thunderstorm"}
class WeatherResponse(BaseModel):
location: str
current: dict
highlights: dict
forecast: List[dict]
alerts: List[dict]
critical_days: List[str]
warning_days: List[str]
ai_recommendations: Optional[str]
def get_addr(lat, lon):
try: return PHOTON.reverse((lat, lon), exactly_one=True).address
except: return f"Lat: {lat}, Lon: {lon}"
def build_alerts(forecast):
alerts, crit, warn = [], [], []
for d in forecast:
conds, sev = [], "INFO"
tmx, tmn = d['temp_max'], d['temp_min']
if tmx > 40: (conds.append("🌑️ Extreme heat"), sev := "CRITICAL")
elif tmx > 35: (conds.append("🌑️ High temp"), sev := "WARNING")
if tmn < 5: (conds.append("❄️ Frost risk"), sev := "CRITICAL")
if "storm" in d['description'].lower(): (conds.append("β›ˆοΈ Severe storm"), sev := "CRITICAL")
if conds:
(crit.append(d['day_name']) if sev=="CRITICAL" else warn.append(d['day_name']))
alerts.append({"day": d['day_name'], "severity": sev, "conditions": conds})
return alerts, crit, warn
@app.get("/weather", response_model=WeatherResponse)
def get_weather(lat: float = 18.52, lon: float = 73.85):
addr = get_addr(lat, lon)
params = {"latitude": lat, "longitude": lon, "current_weather": True, "forecast_days": 10, "timezone": "auto",
"hourly": "temperature_2m,relative_humidity_2m,precipitation,windspeed_10m",
"daily": "weathercode,temperature_2m_max,temperature_2m_min,sunrise,sunset"}
data = requests.get("https://api.open-meteo.com/v1/forecast", params=params).json()
cw, daily, hourly = data['current_weather'], data['daily'], data['hourly']
cur = {"temp": cw['temperature'], "icon": ICONS.get(cw['weathercode'], "❓"), "desc": DESC.get(cw['weathercode'], "Unknown"), "wind": cw['windspeed']}
if OWM_KEY:
try:
ow = requests.get(f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={OWM_KEY}&units=metric").json()
cur.update({"temp": ow['main']['temp'], "desc": ow['weather'][0]['description'].capitalize()})
except: pass
forecast = []
for i, t in enumerate(daily['time']):
dt = datetime.datetime.fromisoformat(t)
forecast.append({"day_name": dt.strftime("%A"), "date": dt.strftime("%b %d"), "icon": ICONS.get(daily['weathercode'][i], "❓"),
"description": DESC.get(daily['weathercode'][i], "Unknown"), "temp_max": daily['temperature_2m_max'][i], "temp_min": daily['temperature_2m_min'][i]})
alerts, crit, warn = build_alerts(forecast)
ai_rec = None
if alerts and NV_KEY:
try:
from openai import OpenAI
nv = OpenAI(base_url="https://integrate.api.nvidia.com/v1", api_key=NV_KEY)
res = nv.chat.completions.create(model="meta/llama-3.1-70b-instruct",
messages=[{"role": "user", "content": f"Brief farming advice for {addr.split(',')[-1]} with {crit+warn} weather."}], max_tokens=100)
ai_rec = res.choices[0].message.content
except: ai_rec = f"Weather alert in {addr}. Monitor crops."
return {"location": addr, "current": cur, "highlights": {}, "forecast": forecast, "alerts": alerts, "critical_days": crit, "warning_days": warn, "ai_recommendations": ai_rec}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)