nichts/nyx/homes/notashelf/services/wayland/waybar/scripts/waybar-wttr.py
2024-04-09 23:11:33 +02:00

168 lines
5.2 KiB
Python
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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"<b>{current_condition['weatherDesc'][0]['value']} {current_condition['temp_C']}°</b>\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<b>"
if i == 0:
formatted_data["tooltip"] += "Today, "
if i == 1:
formatted_data["tooltip"] += "Tomorrow, "
formatted_data["tooltip"] += f"{day['date']}</b>\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()