2025-03-16 12:06:12 +05:00
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
from os import environ
|
|
|
|
|
import json
|
|
|
|
|
|
2026-03-16 12:16:29 +01:00
|
|
|
import requests
|
|
|
|
|
|
|
|
|
|
URL = "https://api.weatherapi.com/v1"
|
|
|
|
|
REQUEST_TIMEOUT_SECONDS = 10
|
2025-03-16 12:06:12 +05:00
|
|
|
|
|
|
|
|
|
2025-03-16 17:03:55 +05:00
|
|
|
def time_now() -> str:
|
|
|
|
|
return str(datetime.now(timezone.utc))
|
2025-03-16 12:06:12 +05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_current_weather(location: str) -> str:
|
|
|
|
|
weather = Weather(location=location)
|
|
|
|
|
return json.dumps(weather.realtime())
|
|
|
|
|
|
|
|
|
|
|
2026-03-16 12:16:29 +01:00
|
|
|
def get_weather_forecast(location: str, days: int = 0) -> str:
|
|
|
|
|
if days is None:
|
|
|
|
|
days = 0
|
|
|
|
|
|
|
|
|
|
days = int(days) + 1
|
2025-06-17 10:57:19 +05:00
|
|
|
days = max(1, days)
|
|
|
|
|
days = min(14, days)
|
2026-03-16 12:16:29 +01:00
|
|
|
|
2025-03-16 12:06:12 +05:00
|
|
|
weather = Weather(location=location)
|
2025-06-17 10:57:19 +05:00
|
|
|
return json.dumps(weather.forecast(days=days))
|
2025-03-16 12:06:12 +05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class Weather:
|
|
|
|
|
def __init__(self, location: str):
|
|
|
|
|
self.__location = location
|
2026-03-16 12:16:29 +01:00
|
|
|
self.api_key = environ.get("WEATHER_API_KEY")
|
2025-03-16 13:22:48 +01:00
|
|
|
|
2025-03-16 12:06:12 +05:00
|
|
|
@property
|
|
|
|
|
def location(self) -> str:
|
|
|
|
|
return self.__location
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def make_request(method: str, params: dict) -> dict:
|
2026-03-16 12:16:29 +01:00
|
|
|
try:
|
|
|
|
|
response = requests.get(
|
|
|
|
|
url=f"{URL}{method}",
|
|
|
|
|
params=params,
|
|
|
|
|
timeout=REQUEST_TIMEOUT_SECONDS,
|
|
|
|
|
)
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
payload = response.json()
|
|
|
|
|
except requests.RequestException as error:
|
|
|
|
|
return {"error": f"Weather API request failed: {error}"}
|
|
|
|
|
except ValueError as error:
|
|
|
|
|
return {"error": f"Weather API returned invalid JSON: {error}"}
|
|
|
|
|
|
|
|
|
|
if isinstance(payload, dict) and "error" in payload:
|
|
|
|
|
api_error = payload["error"]
|
|
|
|
|
if isinstance(api_error, dict):
|
|
|
|
|
message = api_error.get("message", "Unknown weather API error")
|
|
|
|
|
else:
|
|
|
|
|
message = str(api_error)
|
|
|
|
|
return {"error": message}
|
|
|
|
|
|
|
|
|
|
return payload
|
2025-03-16 12:06:12 +05:00
|
|
|
|
|
|
|
|
def realtime(self):
|
2026-03-16 12:16:29 +01:00
|
|
|
method = "/current.json"
|
2025-03-16 12:06:12 +05:00
|
|
|
params = {
|
2026-03-16 12:16:29 +01:00
|
|
|
"key": self.api_key,
|
|
|
|
|
"q": self.location,
|
2025-03-16 12:06:12 +05:00
|
|
|
}
|
|
|
|
|
return self.make_request(method=method, params=params)
|
|
|
|
|
|
2025-06-17 10:57:19 +05:00
|
|
|
def forecast(self, days: int = 14):
|
2026-03-16 12:16:29 +01:00
|
|
|
method = "/forecast.json"
|
2025-03-16 12:06:12 +05:00
|
|
|
params = {
|
2026-03-16 12:16:29 +01:00
|
|
|
"key": self.api_key,
|
|
|
|
|
"q": self.location,
|
|
|
|
|
"days": days,
|
2025-03-16 12:06:12 +05:00
|
|
|
}
|
|
|
|
|
return self.make_request(method=method, params=params)
|
|
|
|
|
|
|
|
|
|
|
2026-03-16 12:16:29 +01:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
test_weather = Weather("Aqtobe")
|
2025-06-17 10:57:19 +05:00
|
|
|
result = json.dumps(test_weather.forecast(days=13), indent=2)
|
2025-03-16 12:06:12 +05:00
|
|
|
print(result)
|