""" Handle external requests and pre-process weather data Providers: * OpenWeather Free Access on OpenWeather allows for some API calls, see https://openweathermap.org/price """ import requests import pandas as pd import config def get_current_weather(city: str) -> dict: """https://openweathermap.org/current""" pos = _get_position(city) if not pos: return None url = f"http://api.openweathermap.org/data/2.5/weather?lat={pos['lat']}&lon={pos['lon']}&appid={config.OPENWEATHER_API_KEY}&units=metric" data = requests.get(url).json() data['summary'] = _format_current_weather(data) # On icon URL codes: https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2 data['icon_url'] = f"https://openweathermap.org/img/wn/{data['weather'][0]['icon']}@2x.png" return data def _format_current_weather(data: dict) -> str: """final formatting should occur in HTML/JS, not here""" ts = [data['dt'], data['sys']['sunrise'], data['sys']['sunset']] ts = [pd.to_datetime(x + data['timezone'], unit='s') for x in ts] s = f"""{data['name']}, {data['sys']['country']} ({ts[0]}) {data['weather'][0]['description']} {data['main']['temp']}°C (feels like {data['main']['feels_like']}°C), humidity: {data['main']['humidity']}%, pressure: {data['main']['grnd_level']} hPa visibility: {data['visibility']/1000:.1f}km wind: {data['wind']['speed']}m/s from {data['wind']['deg']}°N (with gusts of {data['wind'].get('gust', 0)} m/s) clouds: {data['clouds']['all']}% sunrise & sunset: {ts[1].strftime('%H:%M')}, {ts[2].strftime('%H:%M')}""" return s def get_forecast(city: str) -> dict: """https://openweathermap.org/forecast5""" # 5 days, 3 hours forecast data lat, lon = _get_position(city) url = f"http://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={config.OPENWEATHER_API_KEY}&units=metric" data = requests.get(url).json() return data def _get_position(name) -> dict: """direct geocoding name: City name, state code (only for the US) and country code divided by comma. Please use ISO 3166 country codes. https://openweathermap.org/api/geocoding-api#direct """ limit = 5 url = f"http://api.openweathermap.org/geo/1.0/direct?q={name}&limit={limit}&appid={config.OPENWEATHER_API_KEY}" data = requests.get(url).json() if not data: return None return data[0] def get_weathermap() -> dict: """https://openweathermap.org/api/weathermaps"""