Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ def execute_query(self, query: str) -> None:
commands.simple_scroll(direction)
else:
print("Scroll command not recognized")
elif "weather" in query:
cities = re.findall(
r"\b(?:of|in|at)\s+(\w+)", query
) # Extract the city name just after the word 'of'
commands.weather_reporter(self.__voice_interface, cities[0])

else:
self.__voice_interface.speak("could not interpret the query")
Expand Down
57 changes: 57 additions & 0 deletions src/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import googlesearch
import pyautogui as pag
import pygetwindow
import requests
import wikipedia
from PIL import ImageGrab

Expand Down Expand Up @@ -293,3 +294,59 @@ def simple_scroll(direction: str) -> None:
pag.press(keys=direction, presses=25)
else:
print("Invalid direction")


def weather_reporter(vi: VoiceInterface, city_name: str) -> None:
"""
Fetches and reports the weather conditions for a given city.

This function retrieves the latitude and longitude of the specified city using the API Ninjas City API.
It then fetches the current weather data from the Open-Meteo API and reports the temperature, humidity,
apparent temperature, rain probability, cloud cover, and wind speed using the VoiceInterface instance.

Args:
vi (VoiceInterface): The VoiceInterface instance used to speak the weather report.
city_name (str): The name of the city for which to fetch weather data.

Raises:
requests.exceptions.RequestException: If there is an issue with the API request.
IndexError: If the city name is not found in the API response.
KeyError: If expected weather data fields are missing from the response.
"""
# Fetch latitude and longitude for the given city to be used by open-metro api
params = {
"name": city_name,
}
geo_codes = requests.get(
"https://api.api-ninjas.com/v1/city",
params=params,
headers={"origin": "https://www.api-ninjas.com"},
).json()

# Fetch weather data from Open-Meteo using the obtained coordinates
weather_data_response = requests.get(
f'https://api.open-meteo.com/v1/forecast?latitude={geo_codes[0].get("latitude")}&longitude={geo_codes[0].get("longitude")}&current=temperature_2m,relative_humidity_2m,apparent_temperature,rain,showers,cloud_cover,wind_speed_10m&forecast_days=1'
).json()

weather_data = weather_data_response.get("current")
weather_units = weather_data_response.get("current_units")

vi.speak(
f"The current temperature in {city_name} is {weather_data.get('temperature_2m')}{weather_units.get('temperature_2m')}. "
f"However, due to a relative humidity of {weather_data.get('relative_humidity_2m')}{weather_units.get('relative_humidity_2m')}, "
f"it feels like {weather_data.get('apparent_temperature')}{weather_units.get('apparent_temperature')}."
)

if weather_data.get("rain") == 0:
vi.speak("The skies will be clear, with no chance of rain.")
else:
cloud_cover = weather_data.get("cloud_cover")
vi.speak(
f"The sky will be {cloud_cover}{weather_units.get('cloud_cover')} cloudy, "
f"and there's a predicted rainfall of {weather_data.get('rain')}{weather_units.get('rain')}."
)

vi.speak(
f"The wind speed is expected to be {weather_data.get('wind_speed_10m')}{weather_units.get('wind_speed_10m')}, "
"so plan accordingly."
)