Skip to content

Commit

Permalink
add option to provide custom places
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanVnucec committed Apr 5, 2021
1 parent c0677f9 commit a0164c9
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 48 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ openWeatherApiKey: <OpenWeather API key>
```
2. Create `RECEIVERS.txt` and put email subscribers as:
```
example@gmail.com
example2@yahoo.com
example3@hotmail.com
example1@gmail.com, "<location name>"
example2@gmail.com, "Berlin"
example3@gmail.com, "Milwaukee"
example4@gmail.com, "Mobile, Alabama"
example5@gmail.com, "Nashville, Tennessee"
example6@gmail.com, "Nashville, Indiana"
```
3. Activate virtualenv.
4. Install dependencies from `requirements.txt`.
Expand Down
34 changes: 17 additions & 17 deletions forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
RAIN_PROB_TRESHOLD = 0.5


class Forecast(OpenWeather):
def __init__(self, apiKey):
super().__init__(apiKey)
self.rainToday = False
self.rainStartHour = None
class Forecast:
def __init__(self, location):
self.location = location
self.forecastToday = self.get_forecast_today()

def get_forecast_today(self, location):
def get_forecast_today(self):
forecastToday = []

lat, lon = location.get_latitude_longitude()
lat, lon = self.location.get_latitude_longitude()

forecasts = self.get_forecast(lat, lon)
localDate = location.get_local_time().date()
ow = OpenWeather()
forecasts = ow.get_forecast(lat, lon)
localDate = self.location.get_local_time().date()

for forecast in forecasts:
forecastDate = forecast['t'].date()
Expand All @@ -36,25 +36,25 @@ def get_forecast_today(self, location):

return forecastToday

def get_rain_start_hour(self, forecastToday):
def get_rain_start_hour(self):
hour = None

for forecast in forecastToday:
for forecast in self.forecastToday:
if forecast['b']:
hour = forecast['h']
break

return hour

def construct_forecast_message(self, forecastToday, location):
rainStartHour = self.get_rain_start_hour(forecastToday)
locationName = location.get_location_name()
def construct_forecast_message(self):
rainStartHour = self.get_rain_start_hour()
locationName = self.location.get_location_name()

subject = f'Rain in {locationName} from {rainStartHour}h'

html = '<html><body>'
plain = ''
for forecast in forecastToday:
for forecast in self.forecastToday:
hourStr = str(forecast['h'])
probStr = str(round(forecast['p'] * 100))

Expand All @@ -74,5 +74,5 @@ def construct_forecast_message(self, forecastToday, location):

return subject, plain, html

def rain_today(self, forecastToday):
return True in [forecast['b'] for forecast in forecastToday]
def rain_today(self):
return True in [forecast['b'] for forecast in self.forecastToday]
3 changes: 3 additions & 0 deletions location.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def __init__(self, name):
geolocator = geocoders.Nominatim(user_agent=GEOLOC_APP_NAME)
self.point = geolocator.geocode(self.name)

if self.point == None:
exit(f'ERROR: Can not find place by name.')

# get timezone
tf = TimezoneFinder()
self.timezone = tf.timezone_at(
Expand Down
33 changes: 18 additions & 15 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
import utils
from open_weather import OpenWeather
from utils import get_email_credentials, get_emails_and_locations
from gmail import Gmail
from forecast import Forecast
from location import Location

SEND_EMAIL_HOUR = 5 # AM local time
CREDENTIALS_FILE_PATH = 'CREDENTIALS.yaml'
RECEIVERS_FILE_PATH = 'RECEIVERS.txt'

if __name__ == "__main__":
sender, password, openWeatherApiKey = utils.get_credentials(
CREDENTIALS_FILE_PATH)
receivers = utils.get_emails_and_locations(RECEIVERS_FILE_PATH)
sender, password = get_email_credentials()
receivers = get_emails_and_locations()

numOfReceivers = len(receivers)
print(f'INFO: found {numOfReceivers} receive emails.')

gmail = Gmail(sender, password)
forecast = Forecast(openWeatherApiKey)

for receiver in receivers:
for num, receiver in enumerate(receivers, start=1):
print(f'INFO: {num}/{numOfReceivers}', end =' ')
location = Location(receiver['location'])

# is it time to send an email
if location.get_local_time().hour == SEND_EMAIL_HOUR:
forecastToday = forecast.get_forecast_today(location)
forecast = Forecast(location)

if forecast.rain_today(forecastToday):
subject, content, contentHtml = forecast.construct_forecast_message(
forecastToday, location)
print('INFO: Sending emails.')
if forecast.rain_today():
subject, content, contentHtml = forecast.construct_forecast_message()
print('Sending email.')
gmail.send(receiver['email'], subject, content, contentHtml)

else:
print('No rain today.')
else:
print("It's not time.")

print('INFO: Done.')
11 changes: 6 additions & 5 deletions open_weather.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import requests
import json
from datetime import datetime
import pytz
from utils import get_openWeather_api_key


class OpenWeather:
def __init__(self, apiKey) -> None:
self.__apiKey = apiKey
__API_KEY = get_openWeather_api_key()

def __init__(self):
pass

def _get_data_from_api(self, latitude, longitude):

API_URL = 'http://api.openweathermap.org/data/2.5/onecall?'\
f'&lat={latitude}'\
f'&lon={longitude}'\
'&exclude=current,minutely,daily,alerts&units=metric'\
f'&appid={self.__apiKey}'
f'&appid={self.__API_KEY}'

try:
response = requests.get(API_URL)
Expand Down
30 changes: 22 additions & 8 deletions utils.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import yaml

CREDENTIALS_FILE_PATH = 'CREDENTIALS.yaml'
RECEIVERS_FILE_PATH = 'RECEIVERS.txt'

def get_credentials(filePath):

def get_email_credentials():
try:
with open(filePath, 'r') as file:
with open(CREDENTIALS_FILE_PATH, 'r') as file:
credentials = yaml.load(file, Loader=yaml.FullLoader)

except FileNotFoundError:
exit('ERROR: credentials file not found.')

sender = credentials['senderEmail']
password = credentials['senderPassword']
openWeatherApiKey = credentials['openWeatherApiKey']

return sender, password, openWeatherApiKey
return sender, password


def get_openWeather_api_key():
try:
with open(CREDENTIALS_FILE_PATH, 'r') as file:
credentials = yaml.load(file, Loader=yaml.FullLoader)

except FileNotFoundError:
exit('ERROR: credentials file not found.')

return credentials['openWeatherApiKey']


def get_emails_and_locations(filePath):
def get_emails_and_locations():
try:
with open(filePath, 'r') as file:
with open(RECEIVERS_FILE_PATH, 'r') as file:
receivers = file.read().splitlines()

except FileNotFoundError:
Expand All @@ -29,8 +42,9 @@ def get_emails_and_locations(filePath):

for receiver in receivers:
email_and_location = {}
email_and_location['email'] = receiver.split(',')[0].strip()
email_and_location['location'] = receiver.split(',')[1].strip()
string = receiver.partition(',')
email_and_location['email'] = string[0].strip()
email_and_location['location'] = string[2].replace('"', '').strip()
emails_and_locations.append(email_and_location)

return emails_and_locations
Expand Down

0 comments on commit a0164c9

Please sign in to comment.