380 lines
13 KiB
Python
Executable File
380 lines
13 KiB
Python
Executable File
#!/usr/bin/env nix-shell
|
||
#! nix-shell -i python3 --pure
|
||
#! nix-shell -p python3 python3Packages.requests
|
||
|
||
import json
|
||
from datetime import datetime
|
||
|
||
import requests
|
||
|
||
WWO_CODE = {
|
||
"113": "Sunny",
|
||
"116": "PartlyCloudy",
|
||
"119": "Cloudy",
|
||
"122": "VeryCloudy",
|
||
"143": "Fog",
|
||
"176": "LightShowers",
|
||
"179": "LightSleetShowers",
|
||
"182": "LightSleet",
|
||
"185": "LightSleet",
|
||
"200": "ThunderyShowers",
|
||
"227": "LightSnow",
|
||
"230": "HeavySnow",
|
||
"248": "Fog",
|
||
"260": "Fog",
|
||
"263": "LightShowers",
|
||
"266": "LightRain",
|
||
"281": "LightSleet",
|
||
"284": "LightSleet",
|
||
"293": "LightRain",
|
||
"296": "LightRain",
|
||
"299": "HeavyShowers",
|
||
"302": "HeavyRain",
|
||
"305": "HeavyShowers",
|
||
"308": "HeavyRain",
|
||
"311": "LightSleet",
|
||
"314": "LightSleet",
|
||
"317": "LightSleet",
|
||
"320": "LightSnow",
|
||
"323": "LightSnowShowers",
|
||
"326": "LightSnowShowers",
|
||
"329": "HeavySnow",
|
||
"332": "HeavySnow",
|
||
"335": "HeavySnowShowers",
|
||
"338": "HeavySnow",
|
||
"350": "LightSleet",
|
||
"353": "LightShowers",
|
||
"356": "HeavyShowers",
|
||
"359": "HeavyRain",
|
||
"362": "LightSleetShowers",
|
||
"365": "LightSleetShowers",
|
||
"368": "LightSnowShowers",
|
||
"371": "HeavySnowShowers",
|
||
"374": "LightSleetShowers",
|
||
"377": "LightSleet",
|
||
"386": "ThunderyShowers",
|
||
"389": "ThunderyHeavyRain",
|
||
"392": "ThunderySnowShowers",
|
||
"395": "HeavySnowShowers",
|
||
}
|
||
|
||
WEATHER_SYMBOL_EMOJI = {
|
||
"Unknown": "✨",
|
||
"Cloudy": "☁️",
|
||
"Fog": "🌫",
|
||
"HeavyRain": "🌧",
|
||
"HeavyShowers": "🌧",
|
||
"HeavySnow": "❄️",
|
||
"HeavySnowShowers": "❄️",
|
||
"LightRain": "🌦",
|
||
"LightShowers": "🌦",
|
||
"LightSleet": "🌧",
|
||
"LightSleetShowers": "🌧",
|
||
"LightSnow": "🌨",
|
||
"LightSnowShowers": "🌨",
|
||
"PartlyCloudy": "⛅️",
|
||
"Sunny": "☀️",
|
||
"ThunderyHeavyRain": "🌩",
|
||
"ThunderyShowers": "⛈",
|
||
"ThunderySnowShowers": "⛈",
|
||
"VeryCloudy": "☁️",
|
||
}
|
||
|
||
WEATHER_SYMBOL = {
|
||
"Unknown": "✨",
|
||
"Cloudy": "☁️",
|
||
"Fog": "🌫",
|
||
"HeavyRain": "🌧",
|
||
"HeavyShowers": "🌧",
|
||
"HeavySnow": "❄️",
|
||
"HeavySnowShowers": "❄️",
|
||
"LightRain": "🌦",
|
||
"LightShowers": "🌦",
|
||
"LightSleet": "🌧",
|
||
"LightSleetShowers": "🌧",
|
||
"LightSnow": "🌨",
|
||
"LightSnowShowers": "🌨",
|
||
"PartlyCloudy": "⛅️",
|
||
"Sunny": "☀️",
|
||
"ThunderyHeavyRain": "🌩",
|
||
"ThunderyShowers": "⛈",
|
||
"ThunderySnowShowers": "⛈",
|
||
"VeryCloudy": "☁️",
|
||
}
|
||
|
||
WEATHER_CODES = {key: WEATHER_SYMBOL[value] for key, value in WWO_CODE.items()}
|
||
|
||
WIND_DIRECTION = [
|
||
"↓", "↙", "←", "↖", "↑", "↗", "→", "↘",
|
||
]
|
||
|
||
MOON_PHASES = (
|
||
"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"
|
||
)
|
||
|
||
WEATHER_SYMBOL_WI_DAY = {
|
||
"Unknown": "",
|
||
"Cloudy": "",
|
||
"Fog": "",
|
||
"HeavyRain": "",
|
||
"HeavyShowers": "",
|
||
"HeavySnow": "",
|
||
"HeavySnowShowers": "",
|
||
"LightRain": "",
|
||
"LightShowers": "",
|
||
"LightSleet": "",
|
||
"LightSleetShowers": "",
|
||
"LightSnow": "",
|
||
"LightSnowShowers": "",
|
||
"PartlyCloudy": "",
|
||
"Sunny": "",
|
||
"ThunderyHeavyRain": "",
|
||
"ThunderyShowers": "",
|
||
"ThunderySnowShowers": "",
|
||
"VeryCloudy": "",
|
||
}
|
||
|
||
WEATHER_CODES_WI_DAY = {key: WEATHER_SYMBOL_WI_DAY[value] for key, value in WWO_CODE.items()}
|
||
|
||
WEATHER_SYMBOL_WI_NIGHT = {
|
||
"Unknown": "",
|
||
"Cloudy": "",
|
||
"Fog": "",
|
||
"HeavyRain": "",
|
||
"HeavyShowers": "",
|
||
"HeavySnow": "",
|
||
"HeavySnowShowers": "",
|
||
"LightRain": "",
|
||
"LightShowers": "",
|
||
"LightSleet": "",
|
||
"LightSleetShowers": "",
|
||
"LightSnow": "",
|
||
"LightSnowShowers": "",
|
||
"PartlyCloudy": "",
|
||
"Sunny": "",
|
||
"ThunderyHeavyRain": "",
|
||
"ThunderyShowers": "",
|
||
"ThunderySnowShowers": "",
|
||
"VeryCloudy": "",
|
||
}
|
||
|
||
WEATHER_CODES_WI_NIGHT = {key: WEATHER_SYMBOL_WI_NIGHT[value] for key, value in WWO_CODE.items()}
|
||
|
||
WIND_DIRECTION_WI = [
|
||
"", "", "", "", "", "", "", "",
|
||
]
|
||
|
||
WIND_SCALE_WI = [
|
||
"", "", "", "", "", "", "", "", "", "", "", "", "",
|
||
]
|
||
|
||
MOON_PHASES_WI = (
|
||
"", "", "", "", "", "", "",
|
||
"", "", "", "", "", "", "",
|
||
"", "", "", "", "", "", "",
|
||
"", "", "", "", "", "", "",
|
||
)
|
||
|
||
WEATHER_SYMBOL_WEGO = {
|
||
"Unknown": [
|
||
" .-. ",
|
||
" __) ",
|
||
" ( ",
|
||
" `-’ ",
|
||
" • "],
|
||
"Sunny": [
|
||
"\033[38;5;226m \\ / \033[0m",
|
||
"\033[38;5;226m .-. \033[0m",
|
||
"\033[38;5;226m ― ( ) ― \033[0m",
|
||
"\033[38;5;226m `-’ \033[0m",
|
||
"\033[38;5;226m / \\ \033[0m"],
|
||
"PartlyCloudy": [
|
||
"\033[38;5;226m \\ /\033[0m ",
|
||
"\033[38;5;226m _ /\"\"\033[38;5;250m.-. \033[0m",
|
||
"\033[38;5;226m \\_\033[38;5;250m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;250m(___(__) \033[0m",
|
||
" "],
|
||
"Cloudy": [
|
||
" ",
|
||
"\033[38;5;250m .--. \033[0m",
|
||
"\033[38;5;250m .-( ). \033[0m",
|
||
"\033[38;5;250m (___.__)__) \033[0m",
|
||
" "],
|
||
"VeryCloudy": [
|
||
" ",
|
||
"\033[38;5;240;1m .--. \033[0m",
|
||
"\033[38;5;240;1m .-( ). \033[0m",
|
||
"\033[38;5;240;1m (___.__)__) \033[0m",
|
||
" "],
|
||
"LightShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;250m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;250m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;250m(___(__) \033[0m",
|
||
"\033[38;5;111m ‘ ‘ ‘ ‘ \033[0m",
|
||
"\033[38;5;111m ‘ ‘ ‘ ‘ \033[0m"],
|
||
"HeavyShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;240;1m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;240;1m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;240;1m(___(__) \033[0m",
|
||
"\033[38;5;21;1m ‚‘‚‘‚‘‚‘ \033[0m",
|
||
"\033[38;5;21;1m ‚’‚’‚’‚’ \033[0m"],
|
||
"LightSnowShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;250m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;250m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;250m(___(__) \033[0m",
|
||
"\033[38;5;255m * * * \033[0m",
|
||
"\033[38;5;255m * * * \033[0m"],
|
||
"HeavySnowShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;240;1m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;240;1m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;240;1m(___(__) \033[0m",
|
||
"\033[38;5;255;1m * * * * \033[0m",
|
||
"\033[38;5;255;1m * * * * \033[0m"],
|
||
"LightSleetShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;250m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;250m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;250m(___(__) \033[0m",
|
||
"\033[38;5;111m ‘ \033[38;5;255m*\033[38;5;111m ‘ \033[38;5;255m* \033[0m",
|
||
"\033[38;5;255m *\033[38;5;111m ‘ \033[38;5;255m*\033[38;5;111m ‘ \033[0m"],
|
||
"ThunderyShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;250m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;250m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;250m(___(__) \033[0m",
|
||
"\033[38;5;228;5m ⚡\033[38;5;111;25m‘ ‘\033[38;5;228;5m⚡\033[38;5;111;25m‘ ‘ \033[0m",
|
||
"\033[38;5;111m ‘ ‘ ‘ ‘ \033[0m"],
|
||
"ThunderyHeavyRain": [
|
||
"\033[38;5;240;1m .-. \033[0m",
|
||
"\033[38;5;240;1m ( ). \033[0m",
|
||
"\033[38;5;240;1m (___(__) \033[0m",
|
||
"\033[38;5;21;1m ‚‘\033[38;5;228;5m⚡\033[38;5;21;25m‘‚\033[38;5;228;5m⚡\033[38;5;21;25m‚‘ \033[0m",
|
||
"\033[38;5;21;1m ‚’‚’\033[38;5;228;5m⚡\033[38;5;21;25m’‚’ \033[0m"],
|
||
"ThunderySnowShowers": [
|
||
"\033[38;5;226m _`/\"\"\033[38;5;250m.-. \033[0m",
|
||
"\033[38;5;226m ,\\_\033[38;5;250m( ). \033[0m",
|
||
"\033[38;5;226m /\033[38;5;250m(___(__) \033[0m",
|
||
"\033[38;5;255m *\033[38;5;228;5m⚡\033[38;5;255;25m*\033[38;5;228;5m⚡\033[38;5;255;25m* \033[0m",
|
||
"\033[38;5;255m * * * \033[0m"],
|
||
"LightRain": [
|
||
"\033[38;5;250m .-. \033[0m",
|
||
"\033[38;5;250m ( ). \033[0m",
|
||
"\033[38;5;250m (___(__) \033[0m",
|
||
"\033[38;5;111m ‘ ‘ ‘ ‘ \033[0m",
|
||
"\033[38;5;111m ‘ ‘ ‘ ‘ \033[0m"],
|
||
"HeavyRain": [
|
||
"\033[38;5;240;1m .-. \033[0m",
|
||
"\033[38;5;240;1m ( ). \033[0m",
|
||
"\033[38;5;240;1m (___(__) \033[0m",
|
||
"\033[38;5;21;1m ‚‘‚‘‚‘‚‘ \033[0m",
|
||
"\033[38;5;21;1m ‚’‚’‚’‚’ \033[0m"],
|
||
"LightSnow": [
|
||
"\033[38;5;250m .-. \033[0m",
|
||
"\033[38;5;250m ( ). \033[0m",
|
||
"\033[38;5;250m (___(__) \033[0m",
|
||
"\033[38;5;255m * * * \033[0m",
|
||
"\033[38;5;255m * * * \033[0m"],
|
||
"HeavySnow": [
|
||
"\033[38;5;240;1m .-. \033[0m",
|
||
"\033[38;5;240;1m ( ). \033[0m",
|
||
"\033[38;5;240;1m (___(__) \033[0m",
|
||
"\033[38;5;255;1m * * * * \033[0m",
|
||
"\033[38;5;255;1m * * * * \033[0m"],
|
||
"LightSleet": [
|
||
"\033[38;5;250m .-. \033[0m",
|
||
"\033[38;5;250m ( ). \033[0m",
|
||
"\033[38;5;250m (___(__) \033[0m",
|
||
"\033[38;5;111m ‘ \033[38;5;255m*\033[38;5;111m ‘ \033[38;5;255m* \033[0m",
|
||
"\033[38;5;255m *\033[38;5;111m ‘ \033[38;5;255m*\033[38;5;111m ‘ \033[0m"],
|
||
"Fog": [
|
||
" ",
|
||
"\033[38;5;251m _ - _ - _ - \033[0m",
|
||
"\033[38;5;251m _ - _ - _ \033[0m",
|
||
"\033[38;5;251m _ - _ - _ - \033[0m",
|
||
" "],
|
||
}
|
||
|
||
data = {}
|
||
|
||
|
||
weather = requests.get("https://wttr.in/?u&format=j1").json()
|
||
moon = requests.get("https://wttr.in/?format=%m").text
|
||
|
||
|
||
def format_time(time):
|
||
return datetime.strptime(format_24_time(time), "%H").strftime("%I %p")
|
||
|
||
def format_24_time(time):
|
||
return time.replace("00", "").zfill(2)
|
||
|
||
|
||
def format_temp(temp):
|
||
return (hour["FeelsLikeF"] + "°").ljust(3)
|
||
|
||
|
||
def format_chances(hour):
|
||
chances = {
|
||
"chanceoffog": "Fog",
|
||
"chanceoffrost": "Frost",
|
||
"chanceofovercast": "Overcast",
|
||
"chanceofrain": "Rain",
|
||
"chanceofsnow": "Snow",
|
||
"chanceofsunshine": "Sunshine",
|
||
"chanceofthunder": "Thunder",
|
||
"chanceofwindy": "Wind",
|
||
}
|
||
|
||
conditions = []
|
||
for event in chances.keys():
|
||
if int(hour[event]) > 0:
|
||
conditions.append(chances[event] + " " + hour[event] + "%")
|
||
return ", ".join(conditions)
|
||
|
||
|
||
tempint = int(weather["current_condition"][0]["FeelsLikeF"])
|
||
extrachar = ""
|
||
if tempint > 0 and tempint < 10:
|
||
extrachar = "+"
|
||
|
||
|
||
data["text"] = (
|
||
" "
|
||
+ WEATHER_CODES[weather["current_condition"][0]["weatherCode"]]
|
||
+ " "
|
||
+ extrachar
|
||
+ weather["current_condition"][0]["FeelsLikeF"]
|
||
+ "°F"
|
||
)
|
||
|
||
data["tooltip"] = (
|
||
f"<b>{weather['current_condition'][0]['weatherDesc'][0]['value']} {weather['current_condition'][0]['temp_F']}°</b>\n"
|
||
)
|
||
data["tooltip"] += f"Feels like: {weather['current_condition'][0]['FeelsLikeF']}°\n"
|
||
data["tooltip"] += f"Wind: {weather['current_condition'][0]['windspeedMiles']}mph\n"
|
||
data["tooltip"] += f"Humidity: {weather['current_condition'][0]['humidity']}%\n"
|
||
data["tooltip"] += f"Moon phase: {weather["weather"][0]['astronomy'][0]['moon_phase']} " + moon + "\n"
|
||
for i, day in enumerate(weather["weather"]):
|
||
data["tooltip"] += f"\n<b>"
|
||
if i == 0:
|
||
data["tooltip"] += "Today, "
|
||
if i == 1:
|
||
data["tooltip"] += "Tomorrow, "
|
||
date = datetime.strptime(day['date'], "%Y-%m-%d").strftime("%a %b %d %Y")
|
||
data["tooltip"] += f"{date}</b>\n"
|
||
data["tooltip"] += f" {day['maxtempF']}°F {day['mintempF']}°F"
|
||
data[
|
||
"tooltip"
|
||
] += f" {day['astronomy'][0]['sunrise']} {day['astronomy'][0]['sunset']}\n"
|
||
for hour in day["hourly"]:
|
||
if i == 0:
|
||
if int(format_24_time(hour["time"])) < datetime.now().hour - 2:
|
||
continue
|
||
if int(format_24_time(hour["time"])) > datetime.strptime(day['astronomy'][0]['sunset'], "%I:%M %p").hour or int(format_24_time(hour["time"])) < datetime.strptime(day['astronomy'][0]['sunrise'], "%I:%M %p").hour:
|
||
codes = WEATHER_CODES_WI_NIGHT
|
||
else:
|
||
codes = WEATHER_CODES_WI_DAY
|
||
data[
|
||
"tooltip"
|
||
] += f"{format_time(hour['time'])} {codes[hour['weatherCode']]} {format_temp(hour['FeelsLikeF'])} {hour['weatherDesc'][0]['value']}, {format_chances(hour)}\n"
|
||
|
||
|
||
print(json.dumps(data))
|