-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathweather.py
103 lines (85 loc) · 3.5 KB
/
weather.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python3.9
"""Tells whether to use a sunblock or umbrella."""
import argparse
import json
import os
import sys
from collections import namedtuple
from datetime import datetime
from typing import Set
from zoneinfo import ZoneInfo
import requests
DESC = """Gets weather info for your localisation and tells you whether to
wear a sunblock or take an umbrella.
Requires openweathermap API key in environment and relies on
ifconfig.co for geoip.
Also assumes your timezone is configured accordingly to your
region."""
API_KEY = None
UV_INDEX_THRESHOLD = 3
UVI_FLAG = 'shine'
PRECIP_PROB_THRESHOLD = 5
PRECIP_PROB_FLAG = 'rain'
Location = namedtuple('Location', ['longitude', 'latitude'])
WeatherConditions = namedtuple('WeatherConditions',
['uvi', 'precip_prob'])
def get_location() -> Location:
"""Get your location using geoip."""
try:
ip_lookup = requests.get('https://ifconfig.co/json').json()
return Location(ip_lookup['longitude'], ip_lookup['latitude'])
except json.decoder.JSONDecodeError as exc:
raise ValueError('GEOIP lookup returned invalid data.') from exc
def is_today(unix_ts: int) -> bool:
"""Do all the hard TZ work and tell me if a unix timestamp is today."""
utc_unix_ts = datetime.fromtimestamp(unix_ts, tz=ZoneInfo('UTC'))
unix_ts_localtime = utc_unix_ts.astimezone()
localtime = datetime.now(tz=None).astimezone()
return (localtime.day == unix_ts_localtime.day and
localtime.month == unix_ts_localtime.month and
localtime.year == unix_ts_localtime.year)
def get_uvi_precip_prob(loc: Location) -> WeatherConditions:
"""Given location, report UV index and rain chances."""
request_url = 'https://api.openweathermap.org/data/2.5/onecall?' \
'lat={lat}&lon={lon}&exclude={part}&appid={apikey}' \
.format(lat=loc.latitude, lon=loc.longitude,
part='current,minutely,hourly,alerts', apikey=API_KEY)
try:
weather_data = requests.get(request_url).json()
except json.decoder.JSONDecodeError as exc:
raise ValueError('Weather lookup returned malformed data.') from exc
try:
today = None
for day in weather_data['daily']:
if is_today(day['sunrise']):
today = day
break
if not today:
raise ValueError("Could not find today's forecast.")
return WeatherConditions(today['uvi'], today['pop'])
except KeyError as ex:
raise ValueError('Weather lookup did not return weather data.') from ex
def main(check_for: Set[str]) -> bool:
"""Entrypoint for the program after parsing arguments."""
weather_conditions = get_uvi_precip_prob(get_location())
result = False
if (weather_conditions.uvi >= UV_INDEX_THRESHOLD
and UVI_FLAG in check_for):
print(f'Expected UV index: {weather_conditions.uvi}')
result = True
if (weather_conditions.precip_prob >= PRECIP_PROB_THRESHOLD
and PRECIP_PROB_FLAG in check_for):
print('Expected precipitation probability'
f' {weather_conditions.precip_prob}')
result = True
return result
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=DESC)
parser.add_argument('--weather',
choices=[UVI_FLAG, PRECIP_PROB_FLAG],
required=True, action='append')
parsed = parser.parse_args()
API_KEY = os.environ['API_KEY']
if main(set(parsed.weather)):
sys.exit(0)
sys.exit(1)