diff --git a/.github/workflows/README.md b/.github/workflows/README.md
deleted file mode 100644
index 33b01b656..000000000
--- a/.github/workflows/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Instructions for Github Actions setup
-
-## Idea
-We can schedule to run a script on the GitHub Actions servers.
-
-## Instructions
-1. Create GitHub Actions secrets below:
- - CREDENTIALS - See the README.md in the project root directory for more info about the contents.
- - RECEIVERS - Same as above.
- - FAIL_MAIL_USERNAME - Gmail alert address for the workflow fails alerts.
- - FAIL_MAIL_PASSWORD - Gmail password for the above. User is advised to check
- [Sign in with App Passwords](https://support.google.com/accounts/answer/185833?p=InvalidSecondFactor&visit_id=637593941018469305-643690772&rd=1)
-
-2. Manually run Github Action workflow. It is normal if the Download artifacts from the last workflow
-step fails because there is no workflows beforehand.
-
-3. Thats it. The Github Action workflow should run as scheduled and the Python script should be
-executed once per day.
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
deleted file mode 100644
index fb8381c1e..000000000
--- a/.github/workflows/unit_tests.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-name: Unit tests
-
-on:
- # Trigger the workflow on push or pull request,
- # but only for the master branch
- push:
- branches:
- - master
- pull_request:
- branches:
- - master
- # Also trigger on page_build, as well as release created events
- page_build:
- release:
- types: # This configuration does not affect the page_build event above
- - created
- workflow_dispatch:
-
-jobs:
- run:
- runs-on: ubuntu-20.04
-
- steps:
- - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
- # Fix Python version. Probably works with other versions.
- - uses: actions/setup-python@dc73133d4da04e56a135ae2246682783cc7c7cb6
- with:
- python-version: '3.8.5'
-
- - name: Install requirements
- run: make init
-
- - name: Run Unit tests
- run: make test
diff --git a/.github/workflows/weather_check.yml b/.github/workflows/weather_check.yml
index 3c913b61a..18323cdf9 100644
--- a/.github/workflows/weather_check.yml
+++ b/.github/workflows/weather_check.yml
@@ -2,58 +2,28 @@ name: Weather check
on:
schedule:
- # Run every 25th minute
- - cron: '*/25 * * * *'
+ # Run every day at 3:00 UTC (5:00 CEST)
+ - cron: '0 3 * * *'
workflow_dispatch:
jobs:
run:
runs-on: ubuntu-20.04
- # if there is no artifact to download
- continue-on-error: true
env:
ACTION_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
steps:
- uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
-
- # Fix Python version. Probably works with other versions.
- uses: actions/setup-python@dc73133d4da04e56a135ae2246682783cc7c7cb6
with:
python-version: '3.8.5'
- # This step is using CREDENTIALS and RECEIVERS Github Actions secrets.
- # View the README.md file for instructions about secrets contents.
- - name: Create Credentials and Receivers files
+ - name: Setup environment variables
env:
- CREDENTIALS: ${{ secrets.CREDENTIALS }}
+ SENDER_EMAIL: ${{ secrets.SENDER_EMAIL }}
+ SENDER_PASSWORD: ${{ secrets.SENDER_PASSWORD }}
RECEIVERS: ${{ secrets.RECEIVERS }}
- run: |
- echo "$CREDENTIALS" > credentials/credentials.yaml
- echo "$RECEIVERS" > credentials/receivers.txt
-
- - name: Install requirements
- run: make init
- # if Download exec timetable step failed still run the script
- name: Run main application
- run: make run
-
- # This step uses Github Actions secrets FAIL_MAIL_USERNAME and FAIL_MAIL_PASSWORD
- # which are Gmail username and password respectively.
- #- name: Send an email alert if there are any failed steps
- # if: failure()
- # uses: dawidd6/action-send-mail@db36373cbed0fba7d5e12c338b580277550bdba1
- # with:
- # server_address: smtp.gmail.com
- # server_port: 465
- # username: ${{ secrets.FAIL_MAIL_USERNAME }}
- # password: ${{ secrets.FAIL_MAIL_PASSWORD }}
- # subject: rain_alert app run ${{ github.run_number }} failed
- # # send to itself
- # to: ${{ secrets.FAIL_MAIL_USERNAME }}
- # from: https://github.com/IvanVnucec/rain_alert
- # body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
- # # TODO: Add the workflow logs to the attachments
- # #attachments:
+ run: python3 main.py
diff --git a/.gitignore b/.gitignore
index 6a89d363d..7b62f12d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,2 @@
-venv
__pycache__
-credentials/credentials.yaml
-credentials/receivers.txt
-logs/exec_timetable.json.aes
+.vscode
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index b74b6b081..000000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- // Use IntelliSense to learn about possible attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Python: Current File",
- "type": "python",
- "request": "launch",
- "program": "${workspaceFolder}/main.py",
- "console": "integratedTerminal"
- }
- ]
-}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 0cffe0616..000000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "python.formatting.provider": "autopep8",
- "python.formatting.autopep8Args": ["--max-line-length", "80"],
- "python.linting.pylintEnabled": true,
- "python.linting.enabled": true,
- "python.linting.lintOnSave": true,
- "python.pythonPath": "venv/bin/python3.8",
-}
\ No newline at end of file
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 6211ab843..000000000
--- a/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-run: init
- . venv/bin/activate; python main.py
-
-PHONY: init
-init: venv
-
-PHONY: test
-test: venv
- . venv/bin/activate; python -m unittest -v
-
-PHONY: clean
-clean:
- rm -rf venv
- find -iname "*.pyc" -delete
-
-.PHONY: list
-list:
- @echo "run - Run app,"
- @echo "init - Install all the dependancies with virtualenv,"
- @echo "test - Run unit tests,"
- @echo "clean - Clean virtualenv directory."
- @echo "list - List all the makefile commands."
-
-venv: venv/touchfile
-
-venv/touchfile: requirements.txt
- python3 -m pip install virtualenv
- test -d venv || python -m virtualenv venv
- . venv/bin/activate; pip install -Ur requirements.txt
- touch venv/touchfile
diff --git a/README.md b/README.md
index a68dbef42..4b3a2f26d 100644
--- a/README.md
+++ b/README.md
@@ -1,113 +1,22 @@
+# rain_alert
+
[![App running](https://github.com/IvanVnucec/rain_alert/actions/workflows/weather_check.yml/badge.svg?branch=master&event=schedule)](https://github.com/IvanVnucec/rain_alert/actions/workflows/weather_check.yml)
-# rain_alert
-You will not forget your umbrella anymore. :umbrella:
+You will not forget your :umbrella: anymore.
## About
-Check every morning at 5 AM local time if it will be raining that day, if yes
-send an email with forecast message like this:
-
-
-
- Hour [h] |
- Probability [%] |
-
-
- 6 |
- 0 |
-
-
- 7 |
- 0 |
-
-
- 8 |
- 0 |
-
-
- 9 |
- 0 |
-
-
- 10 |
- 10 |
-
-
- 11 |
- 22 |
-
-
- 12 |
- 35 |
-
-
- 13 |
- 60 |
-
-
- 14 |
- 86 |
-
-
- 15 |
- 100 |
-
-
- 16 |
- 100 |
-
-
- 17 |
- 100 |
-
-
- 18 |
- 100 |
-
-
- 19 |
- 72 |
-
-
- 20 |
- 36 |
-
-
- 21 |
- 5 |
-
-
- 22 |
- 0 |
-
-
- 23 |
- 0 |
-
-
-
+
+Check the weather at 5AM Zagreb time and send an email if it will rain today.
## Get started
-0. Create Gmail account and enable the Less secure app access and also create an OpenWeather API Key.
-1. Create `credentials/credentials.yaml` file and put Gmail and OpenWeather credentials from step 0.
-```
-senderEmail:
-senderPassword:
-openWeatherApiKey:
-```
-2. Create `credentials/receivers.txt` file put in email subscribers. For example:
-```
-example1@email.com, Zagreb
-example2@email.com, Berlin
-example3@email.com, Milwaukee
-example4@email.com, Mobile Alabama
-example5@email.com, Nashville Tennessee
-example6@email.com, Nashville Indiana
-```
-3. Run the app using Makefile as `make run`
-4. (Recommended) You can schedule the script to run on GitHub servers like we did in
-[our GitHub Actions CI workflow](https://github.com/IvanVnucec/rain_alert/blob/master/.github/workflows/weather_check.yml).
-See the [Instructions](./.github/workflows/README.md) for more info.
+
+1. Create Gmail account and enable the Less secure app access.
+2. Add the following environment variables to GitHub actions:
+ - `SENDER_EMAIL` - sender Gmail email
+ - `SENDER_PASSWORD` - Gmail email password
+ - `RECEIVERS` - list of email addresses to send the alert to
+3. Run the GitHub Action workflow manually to check if everything is working.
## License
+
[MIT](LICENSE.md)
diff --git a/credentials/.gitkeep b/credentials/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/exec_tracker.py b/exec_tracker.py
deleted file mode 100644
index 3797d8e75..000000000
--- a/exec_tracker.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""
-Because GitHub actions sometimes runs in irregular intervals
-caused by high server demand and not strictly once every hour,
-we will track and store latest execution times. If the script
-was not executed that morning at 5 AM local time, GitHub Actions
-would run it sometimes later that day.
-If the script is ran more than once per day, it would check every
-time if it was already executed. If yes then skip.
-Execution times are being saved in exec_timetable.json file.
-Before closing execution timetable file it is being encrypted
-with AES into exec_timetable.json.aes file with some password.
-Be sure that the password is kept as a secret.
-"""
-
-from datetime import datetime
-import json
-from os import path, remove, system
-from pyAesCrypt import encryptFile, decryptFile
-from utils import debug, get_github_actions_url
-
-DATE_FORMAT = '%m/%d/%Y, %H:%M:%S'
-TIMETABLE_PATH = path.abspath(path.join('logs', 'exec_timetable.json'))
-TIMETABLE_PATH_ENCRYPTED = TIMETABLE_PATH + '.aes'
-BUFFERSIZE = 64 * 1024
-
-
-class ExecTracker:
- def __init__(self, password):
- self.timetable_modified = False
- self.__password = password
-
- if path.exists(TIMETABLE_PATH_ENCRYPTED):
- debug('Found exec timetable file')
- decryptFile(TIMETABLE_PATH_ENCRYPTED, TIMETABLE_PATH, self.__password, BUFFERSIZE)
- else:
- debug('Did not found exec timetable file. Creating new.')
- self.timetable = open(TIMETABLE_PATH, 'w')
- self.timetable.write('{}')
- self.timetable.close()
-
- self.timetable = open(TIMETABLE_PATH, 'r')
- self.exec_times = json.load(self.timetable)
- debug(self.exec_times)
- self.timetable.close()
-
- def close(self):
- if self.timetable_modified:
- debug('Timetable is modified. Saving now.')
- self.timetable = open(TIMETABLE_PATH, 'r+')
- json.dump(self.exec_times, self.timetable, indent=4)
- self.timetable.close()
- else:
- debug('Timetable was not modified.')
-
- debug('Showing execution timetable before encryption.')
- debug(self.exec_times)
-
- debug('Encrypting file.')
- if path.exists(TIMETABLE_PATH_ENCRYPTED):
- remove(TIMETABLE_PATH_ENCRYPTED)
- encryptFile(TIMETABLE_PATH, TIMETABLE_PATH_ENCRYPTED, self.__password, BUFFERSIZE)
-
- debug('Deleting original file.')
- remove(TIMETABLE_PATH)
-
-
- def script_executed_today(self, location):
- if location.name in self.exec_times:
- local_time = location.get_local_time()
-
- for exec_time_str in self.exec_times[location.name]:
- exec_time = datetime.strptime(exec_time_str, DATE_FORMAT)
-
- if exec_time.date() == local_time.date():
- return True
-
- return False
-
- def mark_exec_time(self, location):
- self.timetable_modified = True
-
- location_name = location.name
- local_time_str = location.get_local_time().strftime(DATE_FORMAT)
-
- if location_name in self.exec_times:
- self.exec_times[location_name].append(local_time_str)
- else:
- self.exec_times[location_name] = [local_time_str]
-
- def is_timetable_modified(self):
- return self.timetable_modified
-
- def add_and_commit_timetable(self):
- system('git config --global user.email "you@example.com"')
- system('git config --global user.name "GitHub Actions"')
- debug('git add encrypted timetable')
- system(f'git add {TIMETABLE_PATH_ENCRYPTED}')
- debug('git commit encrypted timetable')
- system(f"git commit -m 'update timetable {get_github_actions_url()}'")
- system("git push")
diff --git a/forecast.py b/forecast.py
deleted file mode 100644
index 05633ca38..000000000
--- a/forecast.py
+++ /dev/null
@@ -1,140 +0,0 @@
-from open_weather import OpenWeather
-from utils import debug, get_github_actions_url
-
-DAY_START_HOUR = 6
-DAY_END_HOUR = 23
-RAIN_PROB_TRESHOLD = 0.5
-
-
-
-class Forecast:
- def __init__(self, location):
- self.location = location
- self.forecastToday = self.get_forecast_today()
-
- def get_forecast_today(self):
- forecastToday = []
-
- lat, lon = self.location.get_latitude_longitude()
-
- ow = OpenWeather()
- forecasts = ow.get_forecast(lat, lon)
- localDate = self.location.get_local_time().date()
-
- for forecast in forecasts:
- forecastDate = forecast['t'].date()
- forecastHour = forecast['t'].hour
- probability = forecast['p']
-
- sameDayForecast = localDate == forecastDate
- inTimeRange = forecastHour >= DAY_START_HOUR and forecastHour <= DAY_END_HOUR
- highRainProbability = probability >= RAIN_PROB_TRESHOLD
-
- if sameDayForecast and inTimeRange:
- forecastToday.append(
- {'b': highRainProbability, 'p': probability, 'h': forecastHour})
-
- return forecastToday
-
- def get_rain_start_hour(self):
- hour = None
-
- for forecast in self.forecastToday:
- if forecast['b']:
- hour = forecast['h']
- break
-
- return hour
-
- def __construct_plain_message(self, locationName):
- plain = f'{locationName} forecast\n\n'
- for forecast in self.forecastToday:
- hourStr = str(forecast['h'])
- probStr = str(round(forecast['p'] * 100))
- plain += f'{hourStr : <2}h {probStr : >3}%\n'
-
- action_url = get_github_actions_url()
- plain += action_url + '\n\n'
-
- return plain
-
- def __construct_html_message(self, locationName):
- html = """
-
-
-
-
-
- {locationName} forecast
-
-
- Hour [h] |
- Probability [%] |
-
"""
-
- # populate cells
- for id, forecast in enumerate(self.forecastToday):
- hourStr = str(forecast['h'])
- probStr = str(round(forecast['p'] * 100))
- html += f"""
-
- {hourStr} |
- {probStr} |
-
- """
-
- html += """
-
"""
- action_url = get_github_actions_url()
- html += f"""
- GitHub Action Run
-
-
-"""
- debug(html)
- return html
-
- def get_forecast_message(self):
- rainStartHour = self.get_rain_start_hour()
- locationName = self.location.get_location_name()
-
- subject = f'Rain in {locationName} from {rainStartHour}h'
-
- plain = self.__construct_plain_message(locationName)
- html = self.__construct_html_message(locationName)
-
- return (subject, plain, html)
-
- def rain_today(self):
- # for debug only
- debug(f"Hourly forecast in {self.location.get_location_name()}")
- for byhour_forecast in self.forecastToday:
- debug(str(byhour_forecast))
-
- return True in [forecast['b'] for forecast in self.forecastToday]
diff --git a/gmail.py b/gmail.py
deleted file mode 100644
index 56451b844..000000000
--- a/gmail.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import smtplib
-import ssl
-from email.mime.text import MIMEText
-from email.mime.multipart import MIMEMultipart
-from utils import error
-
-
-SSL_PORT = 465
-SMTP_GMAIL = 'smtp.gmail.com'
-
-
-class Gmail:
- def __init__(self, sender_email, password):
- self.sender = sender_email
-
- context = ssl.create_default_context()
- self.__server = smtplib.SMTP_SSL(SMTP_GMAIL, SSL_PORT, context=context)
-
- try:
- self.__server.login(self.sender, password)
- except smtplib.SMTPAuthenticationError:
- error('Wrong username or password.')
-
- def send(self, receiver, subject, content, contentHtml=None):
- message = MIMEMultipart("alternative")
-
- message['From'] = self.sender
- message['To'] = receiver
- message['Subject'] = subject
-
- message.attach(MIMEText(content, "plain"))
-
- if contentHtml:
- message.attach(MIMEText(contentHtml, "html"))
-
- self.__server.send_message(message, self.sender, receiver)
diff --git a/location.py b/location.py
deleted file mode 100644
index 16c07e3b8..000000000
--- a/location.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from timezonefinder import TimezoneFinder
-from datetime import datetime
-from geopy import geocoders
-import pytz
-from utils import error, debug
-
-GEOLOC_APP_NAME = 'Locator-request-app'
-
-
-class Location:
- def __init__(self, name):
- self.name = name
-
- # get latitude, longitude
- try:
- geolocator = geocoders.Nominatim(user_agent=GEOLOC_APP_NAME)
- self.point = geolocator.geocode(self.name)
- except Exception as e:
- error(str(e))
- else:
- if self.point == None:
- error(f"Could not find '{self.name}'.")
-
- # get timezone
- tf = TimezoneFinder()
- self.timezone = tf.timezone_at(
- lat=self.point.latitude, lng=self.point.longitude)
- debug(f'Timezone: {self.timezone}')
-
- def get_location_name(self):
- return self.name
-
- def get_local_time(self):
- tz = pytz.timezone(self.timezone)
- local_time = datetime.now(tz)
- debug(f'Local time: {local_time}')
- return local_time
-
- def get_local_time_utc(self):
- local_time = self.get_local_time()
- return local_time.astimezone(pytz.utc)
-
- def get_latitude_longitude(self):
- return self.point.latitude, self.point.longitude
diff --git a/logs/.gitkeep b/logs/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/logs/exec_timetable.json.aes b/logs/exec_timetable.json.aes
deleted file mode 100644
index 495e68aa4..000000000
Binary files a/logs/exec_timetable.json.aes and /dev/null differ
diff --git a/main.py b/main.py
index 023a2a79d..6d89ed10f 100644
--- a/main.py
+++ b/main.py
@@ -1,70 +1,94 @@
-from datetime import time
-from utils import error, get_email_credentials, get_github_actions_url, get_receivers, debug
-from gmail import Gmail
-from forecast import Forecast
-from location import Location
-from exec_tracker import ExecTracker
-
-SEND_EMAIL_HOUR = 5 # AM local time
-
-
-def send_forecast_message(gmail, receiver, message):
- subject, msgPlain, msgHtml = message
- gmail.send(receiver, subject, msgPlain, msgHtml)
-
-
-def main():
- debug(get_github_actions_url())
- sender, password = get_email_credentials()
- receivers = get_receivers()
- if len(receivers) == 0: error('No receivers imported.')
-
- gmail = Gmail(sender, password)
-
- # use password from email to encrypt exec tracker file
- track = ExecTracker(password)
-
- for locationName, emails in receivers.items():
- location = Location(locationName)
-
- executed_today = track.script_executed_today(location)
- time_to_send_email = location.get_local_time().hour >= SEND_EMAIL_HOUR
-
- if executed_today:
- debug('Script already executed today, no need to fetch forecast.')
- if not time_to_send_email:
- debug(f'Its not time to send an email. Waiting for {SEND_EMAIL_HOUR} A.M. local time.')
-
- if not executed_today and time_to_send_email:
- """ mark execution time only when time to send en email because
- we don't want to exceed the number of free OpenWeather API calls """
- debug("Script not executed today and its time to send en email.")
- debug('Mark executed time.')
- track.mark_exec_time(location)
-
- forecast = Forecast(location)
-
- if forecast.rain_today():
- debug('It will rain today.')
- message = forecast.get_forecast_message()
-
- for email in emails:
- debug('Sending email message.')
- send_forecast_message(gmail, email, message)
- else:
- debug('It will not rain today.')
-
- debug('Closing execution timetable.')
- track.close()
- debug('Checking if timetable is modified')
- if track.is_timetable_modified():
- debug('Timetable modified')
- track.add_and_commit_timetable()
- else:
- debug('Timetable not modified')
-
- debug("Application finished.")
-
-
-if __name__ == "__main__":
- main()
+import os
+
+# Get hourly precipitation probability for Zagreb
+import urllib.request
+import json
+ZAGREB_WEATHER_API = "https://api.open-meteo.com/v1/forecast?latitude=45.8144&longitude=15.978&hourly=precipitation_probability&timezone=Europe%2FBerlin&forecast_days=1"
+with urllib.request.urlopen(ZAGREB_WEATHER_API) as response:
+ assert response.status == 200
+ data = json.loads(response.read())
+
+from datetime import datetime
+data_hourly = data["hourly"]
+precipitation = [(datetime.fromisoformat(time), int(prob)) for time, prob in zip(data_hourly["time"], data_hourly["precipitation_probability"])]
+
+# If there is a high probability of rain, send an email
+if any(prob >= 0.5 for _, prob in precipitation):
+ import smtplib
+ import ssl
+ from email.mime.text import MIMEText
+ from email.mime.multipart import MIMEMultipart
+ SSL_PORT = 465
+ SMTP_GMAIL = 'smtp.gmail.com'
+ context = ssl.create_default_context()
+ server = smtplib.SMTP_SSL(SMTP_GMAIL, SSL_PORT, context=context)
+ sender_email, password = os.getenv('SENDER_EMAIL'), os.getenv('SENDER_PASSWORD')
+ assert sender_email is not None and password is not None
+ server.login(sender_email, password)
+
+ # get first high probability of rain
+ hour_start = [time for time, prob in precipitation if prob >= 0.5][0]
+ # Construct message subject and HTML content
+ subject = f"Padaline u Zagrebu od {hour_start.strftime('%H:%M')}h"
+ content = """
+
+
+
+
+
+ Zagreb forecast
+
+
+ Hour [h] |
+ Probability [%] |
+
"""
+ for id,forecast in enumerate(precipitation):
+ hourStr = str(forecast[0].hour)
+ probStr = str(forecast[1])
+ content += f"""
+
+ {hourStr} |
+ {probStr} |
+
+ """
+
+ content += """
"""
+ action_url = os.getenv('ACTION_URL') or "Unknown"
+ content += f"""
+ GitHub Action Run
+
+
+"""
+ print(content)
+ receivers = os.getenv('RECEIVERS')
+ assert receivers is not None
+ receivers = receivers.split('\n')
+ for receiver in receivers:
+ message = MIMEMultipart("alternative")
+ message['From'] = sender_email
+ message['To'] = receiver
+ message['Subject'] = subject
+ message.attach(MIMEText(content, "html"))
+ server.send_message(message, sender_email, receiver)
diff --git a/open_weather.py b/open_weather.py
deleted file mode 100644
index 924db7cde..000000000
--- a/open_weather.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import requests
-from datetime import datetime
-from utils import get_openWeather_api_key, error, debug
-
-
-class OpenWeather:
- # we want to get API key only once
- __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.__API_KEY}'
-
- try:
- response = requests.get(API_URL)
- except:
- error('OpenWeather API request failed.')
-
- return response.json()
-
- def get_forecast(self, latitude, longitude):
- forecastByHour = []
-
- data = self._get_data_from_api(latitude, longitude)
- debug(data)
-
- timezoneOffset = data['timezone_offset']
- byHours = data['hourly']
-
- for hour in byHours:
- unixTime = hour['dt'] + timezoneOffset
- localTime = datetime.utcfromtimestamp(unixTime)
-
- rainProbability = hour['pop']
-
- rainData = {'t': localTime, 'p': rainProbability}
- forecastByHour.append(rainData)
-
- return forecastByHour
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 957faf686..000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-astroid==2.5.2
-autopep8==1.5.6
-certifi==2020.12.5
-cffi==1.14.5
-chardet==4.0.0
-cryptography==3.4.7
-geographiclib==1.50
-geopy==2.1.0
-idna==2.10
-isort==5.8.0
-lazy-object-proxy==1.6.0
-mccabe==0.6.1
-numpy==1.20.2
-pyAesCrypt==6.0.0
-pycodestyle==2.7.0
-pycparser==2.20
-pylint==2.7.4
-pytz==2021.1
-PyYAML==5.4.1
-requests==2.25.1
-timezonefinder==5.2.0
-toml==0.10.2
-urllib3==1.26.4
-wrapt==1.12.1
diff --git a/tests/context.py b/tests/context.py
deleted file mode 100644
index d81038992..000000000
--- a/tests/context.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import os
-import sys
-sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
-
-import rain_alert.utils as utils
diff --git a/tests/test_utils.py b/tests/test_utils.py
deleted file mode 100644
index 1f23f333b..000000000
--- a/tests/test_utils.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from rain_alert.utils import RECEIVERS_FILE_PATH
-import unittest
-
-from .context import utils
-
-import os
-
-
-class TestGetReceivers(unittest.TestCase):
- def test_no_file(self):
- # set the path of the receivers to this folder because in tests folder
- # we dont have the receivers file
- utils.RECEIVERS_FILE_PATH = os.path.split(utils.RECEIVERS_FILE_PATH)[-1]
- self.assertTrue(True)
-
-"""
-class TestGetCredentials(unittest.TestCase):
- ...
-"""
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/utils.py b/utils.py
deleted file mode 100644
index 4ae13519b..000000000
--- a/utils.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import yaml
-from os import path, getenv
-
-DEBUG = True
-CREDENTIALS_FILE_PATH = path.abspath(
- path.join('credentials', 'credentials.yaml'))
-RECEIVERS_FILE_PATH = path.abspath(path.join('credentials', 'receivers.txt'))
-ACTION_URL_ENV = 'ACTION_URL' # defined in weather_check.yml
-
-
-def get_email_credentials():
- try:
- with open(CREDENTIALS_FILE_PATH, 'r') as file:
- credentials = yaml.load(file, Loader=yaml.FullLoader)
- except:
- error(
- f"Could not open {CREDENTIALS_FILE_PATH}. Check if the file exist with the correct name.")
-
- try:
- sender = credentials['senderEmail']
- password = credentials['senderPassword']
- except:
- error("Could not retrieve Email or Email password from the Credentials file.")
-
- 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:
- error(
- f"Could not open {CREDENTIALS_FILE_PATH}. Check if the file exist with the correct name.")
-
- try:
- key = credentials['openWeatherApiKey']
- except:
- error("Could not get the OpenWeather API key from Credentials file.")
-
- return key
-
-
-def get_receivers():
- try:
- with open(RECEIVERS_FILE_PATH, 'r') as file:
- lines = file.read().splitlines()
- except FileNotFoundError:
- error(f"Could not open {RECEIVERS_FILE_PATH}. Check if the file exist with the correct name.")
- else:
- locations = {}
-
- for line in lines:
- receiver, _, location = line.partition(',')
- receiver = receiver.strip()
- location = location.strip()
-
- if not location in locations:
- locations[location] = []
-
- locations[location].append(receiver)
-
- return locations
-
-
-def get_github_actions_url():
- action_url = getenv(ACTION_URL_ENV)
- if action_url is None:
- debug('Cannot get GitHub Actions link')
- action_url = ''
-
- return action_url
-
-
-def debug(msg):
- if DEBUG:
- if type(msg) is dict:
- print('DEBUG: ')
- print(msg)
- else:
- print('DEBUG: ' + msg)
-
-
-def error(msg):
- exit('ERROR: ' + msg)