163 lines
5.8 KiB
Python
163 lines
5.8 KiB
Python
"""
|
|
This plugin provides a command to get weather information for a location.
|
|
"""
|
|
|
|
import logging
|
|
import requests
|
|
import os
|
|
import simplematrixbotlib as botlib
|
|
from dotenv import load_dotenv
|
|
|
|
# Load environment variables from .env file in the parent directory
|
|
# Get the directory where this plugin file is located
|
|
plugin_dir = os.path.dirname(os.path.abspath(__file__))
|
|
# Get the parent directory (main bot directory)
|
|
parent_dir = os.path.dirname(plugin_dir)
|
|
# Load .env from parent directory
|
|
dotenv_path = os.path.join(parent_dir, '.env')
|
|
load_dotenv(dotenv_path)
|
|
|
|
# OpenWeatherMap API configuration
|
|
# Get your free API key from: https://openweathermap.org/api
|
|
WEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY", "")
|
|
WEATHER_API_URL = "https://api.openweathermap.org/data/2.5/weather"
|
|
|
|
async def handle_command(room, message, bot, prefix, config):
|
|
"""
|
|
Function to handle the !weather command.
|
|
|
|
Args:
|
|
room (Room): The Matrix room where the command was invoked.
|
|
message (RoomMessage): The message object containing the command.
|
|
bot (Bot): The bot object.
|
|
prefix (str): The command prefix.
|
|
config (dict): Configuration parameters.
|
|
|
|
Returns:
|
|
None
|
|
"""
|
|
match = botlib.MessageMatch(room, message, bot, prefix)
|
|
if match.is_not_from_this_bot() and match.prefix() and match.command("weather"):
|
|
logging.info("Received !weather command")
|
|
|
|
# Check if API key is configured
|
|
if not WEATHER_API_KEY:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
"Weather API key not configured. Please set OPENWEATHER_API_KEY environment variable."
|
|
)
|
|
return
|
|
|
|
args = match.args()
|
|
|
|
# Check if location was provided
|
|
if len(args) < 1:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
"Usage: !weather <location>\nExample: !weather London or !weather New York,US"
|
|
)
|
|
logging.info("Sent usage message for !weather")
|
|
return
|
|
|
|
location = ' '.join(args)
|
|
|
|
try:
|
|
# Make API request to OpenWeatherMap
|
|
params = {
|
|
'q': location,
|
|
'appid': WEATHER_API_KEY,
|
|
'units': 'metric' # Use metric units (Celsius)
|
|
}
|
|
|
|
response = requests.get(WEATHER_API_URL, params=params, timeout=10)
|
|
response.raise_for_status()
|
|
|
|
weather_data = response.json()
|
|
|
|
# Extract relevant weather information
|
|
city_name = weather_data['name']
|
|
country = weather_data['sys']['country']
|
|
temp = weather_data['main']['temp']
|
|
feels_like = weather_data['main']['feels_like']
|
|
humidity = weather_data['main']['humidity']
|
|
description = weather_data['weather'][0]['description'].capitalize()
|
|
wind_speed = weather_data['wind'].get('speed', 0)
|
|
|
|
# Convert temperature to Fahrenheit for display
|
|
temp_f = (temp * 9/5) + 32
|
|
feels_like_f = (feels_like * 9/5) + 32
|
|
|
|
# Get weather emoji based on condition
|
|
weather_emoji = get_weather_emoji(weather_data['weather'][0]['main'])
|
|
|
|
# Format the weather message
|
|
weather_message = f"""
|
|
<strong>[{weather_emoji} Weather for {city_name}, {country}]</strong>: <strong>Condition:</strong> {description} | <strong>Temperature:</strong> {temp:.1f}°C ({temp_f:.1f}°F) | <strong>Feels like:</strong> {feels_like:.1f}°C ({feels_like_f:.1f}°F) | <strong>Humidity:</strong> {humidity}% | <strong>Wind Speed:</strong> {wind_speed} m/s
|
|
""".strip()
|
|
|
|
await bot.api.send_markdown_message(room.room_id, weather_message)
|
|
logging.info(f"Sent weather information for {city_name}")
|
|
|
|
except requests.exceptions.HTTPError as e:
|
|
if e.response.status_code == 404:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
f"Location '{location}' not found. Please check the spelling and try again."
|
|
)
|
|
elif e.response.status_code == 401:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
"Weather API authentication failed. Please check the API key configuration."
|
|
)
|
|
else:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
f"Error fetching weather data: HTTP {e.response.status_code}"
|
|
)
|
|
logging.error(f"HTTP error fetching weather for '{location}': {e}")
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
f"Error connecting to weather service: {e}"
|
|
)
|
|
logging.error(f"Request error fetching weather for '{location}': {e}")
|
|
|
|
except (KeyError, ValueError) as e:
|
|
await bot.api.send_text_message(
|
|
room.room_id,
|
|
"Error parsing weather data. Please try again later."
|
|
)
|
|
logging.error(f"Error parsing weather data for '{location}': {e}")
|
|
|
|
|
|
def get_weather_emoji(condition):
|
|
"""
|
|
Get an emoji based on weather condition.
|
|
|
|
Args:
|
|
condition (str): Weather condition from API.
|
|
|
|
Returns:
|
|
str: Weather emoji.
|
|
"""
|
|
weather_emojis = {
|
|
'Clear': '☀️',
|
|
'Clouds': '☁️',
|
|
'Rain': '🌧️',
|
|
'Drizzle': '🌦️',
|
|
'Thunderstorm': '⛈️',
|
|
'Snow': '❄️',
|
|
'Mist': '🌫️',
|
|
'Fog': '🌫️',
|
|
'Haze': '🌫️',
|
|
'Smoke': '🌫️',
|
|
'Dust': '🌫️',
|
|
'Sand': '🌫️',
|
|
'Ash': '🌫️',
|
|
'Squall': '💨',
|
|
'Tornado': '🌪️'
|
|
}
|
|
|
|
return weather_emojis.get(condition, '🌡️')
|