#!/usr/bin/env python import os import json import requests import logging from datetime import datetime, timedelta logging.basicConfig(level=logging.ERROR) logger = logging.getLogger(__name__) CACHE_EXPIRATION = 60 XDG_CACHE_HOME = os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache")) CACHE_DIR = os.path.join(XDG_CACHE_HOME, "waybar-wttr") FALLBACK_CACHE_DIR = "/tmp" CACHE_FILE = os.path.join(CACHE_DIR, "weather_cache.json") SUNNY = "☀️" CLOUDY = "☁️" RAIN = "🌧️" SNOW = "❄️" THUNDERSTORM = "⛈️" PARTLY_CLOUDY = "⛅️" CLEAR = "☀️" HOURS_AGO_THRESHOLD = 2 TEMP_THRESHOLD_COLD = 10 TEMP_THRESHOLD_HOT = 0 def ensure_cache_directory(): try: if not os.path.exists(CACHE_DIR): os.makedirs(CACHE_DIR, exist_ok=True) except Exception as e: logger.error(f"Error creating cache directory: {e}") def get_weather_data(): ensure_cache_directory() try: response = requests.get("https://wttr.in/?format=j1") response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: logger.error(f"Error fetching weather data: {e}") return None def get_cached_weather_data(): try: if os.path.exists(CACHE_FILE): with open(CACHE_FILE, "r") as cache_file: cached_data = json.load(cache_file) cache_time = datetime.strptime( cached_data["timestamp"], "%Y-%m-%d %H:%M:%S" ) if datetime.now() - cache_time < timedelta(minutes=CACHE_EXPIRATION): return cached_data["data"] except Exception as e: logger.error(f"Error loading cached data: {e}") return None def cache_weather_data(data): try: with open(CACHE_FILE, "w") as cache_file: cached_data = { "data": data, "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), } json.dump(cached_data, cache_file) except Exception as e: logger.error(f"Error caching data: {e}") def format_time(time): return time.replace("00", "").zfill(2) def format_temp(temp): return f"{temp}°".ljust(4) def get_emoji_for_condition(condition): emoji_map = { "Sunny": SUNNY, "Cloudy": CLOUDY, "Rain": RAIN, "Snow": SNOW, "Thunder": THUNDERSTORM, "Partly Cloudy": PARTLY_CLOUDY, "Clear": CLEAR, } return emoji_map.get(condition, "") def format_conditions(hour): condition_probabilities = { "chanceoffog": "Fog", "chanceoffrost": "Frost", "chanceofovercast": "Overcast", "chanceofrain": "Rain", "chanceofsnow": "Snow", "chanceofsunshine": "Sunshine", "chanceofthunder": "Thunder", "chanceofwindy": "Wind", } if "chanceofpartlycloudy" in hour: condition_probabilities["chanceofpartlycloudy"] = "Partly Cloudy" conditions = [] for event, description in condition_probabilities.items(): if event in hour: probability = int(hour[event]) if probability > 0: emoji = get_emoji_for_condition(description) conditions.append(f"{emoji} {description} {probability}%") return ", ".join(conditions) def format_weather_data(weather_data): current_condition = weather_data["current_condition"][0] temp = int(current_condition["FeelsLikeC"]) temp_sign = "+" if TEMP_THRESHOLD_HOT > temp > TEMP_THRESHOLD_COLD else "" formatted_data = { "text": f" {SUNNY} \n {temp_sign}{temp}°", "tooltip": f"{current_condition['weatherDesc'][0]['value']} {current_condition['temp_C']}°\n" f"Feels like: {current_condition['FeelsLikeC']}°\n" f"Wind: {current_condition['windspeedKmph']}Km/h\n" f"Humidity: {current_condition['humidity']}%\n", } for i, day in enumerate(weather_data["weather"]): formatted_data["tooltip"] += f"\n" if i == 0: formatted_data["tooltip"] += "Today, " if i == 1: formatted_data["tooltip"] += "Tomorrow, " formatted_data["tooltip"] += f"{day['date']}\n" formatted_data["tooltip"] += f"⬆️ {day['maxtempC']}° ⬇️ {day['mintempC']}° " formatted_data[ "tooltip" ] += f"🌅 {day['astronomy'][0]['sunrise']} 🌇 {day['astronomy'][0]['sunset']}\n" now = datetime.now() for hour in day["hourly"]: hour_time = format_time(hour["time"]) if i == 0 and int(hour_time) < now.hour - HOURS_AGO_THRESHOLD: continue formatted_data[ "tooltip" ] += f"{hour_time} {get_emoji_for_condition(hour['weatherDesc'][0]['value'])} {format_temp(hour['FeelsLikeC'])} {hour['weatherDesc'][0]['value']}, {format_conditions(hour)}\n" return formatted_data def main(): ensure_cache_directory() cached_data = get_cached_weather_data() if cached_data: print(json.dumps(cached_data)) return weather_data = get_weather_data() if weather_data: formatted_data = format_weather_data(weather_data) cache_weather_data(formatted_data) print(json.dumps(formatted_data)) if __name__ == "__main__": main()