Skip to content

Commit

Permalink
Merge pull request #6 from aitormagan/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
aitormagan authored Jun 28, 2021
2 parents 3267676 + aa23c46 commit 9cd86a2
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 13 deletions.
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
requests==2.25.1
boto3==1.17.93
aws_lambda_powertools==1.17.0
aws_lambda_powertools==1.17.0
func_timeout==4.3.5
4 changes: 4 additions & 0 deletions serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ custom:
min_date_param:
dev: "/autocita/madrid/dev/min-date-info"
pro: "/autocita/madrid/pro/min-date-info"
min_years_param:
dev: "/autocita/madrid/dev/min-years"
pro: "/autocita/madrid/pro/min-years"
table:
dev: "vaccine-notifications-dev"
pro: "vaccine-notifications-pro"
Expand Down Expand Up @@ -60,6 +63,7 @@ provider:
PARAM_MIN_DATE: ${self:custom.min_date_param.${opt:stage, self:provider.stage}}
BOT_TOKEN: ${env:BOT_TOKEN}
UPDATE_CENTRES_TIME: ${self:custom.update_centres_time.${opt:stage, self:provider.stage}}
PARAM_MIN_YEARS: ${self:custom.min_years_param.${opt:stage, self:provider.stage}}

functions:
message_handler:
Expand Down
26 changes: 21 additions & 5 deletions src/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from aws_lambda_powertools import Logger
from datetime import datetime
from src.telegram_helpers import send_text
from src.db import save_notification, get_non_notified_people
from src.db import save_notification, get_non_notified_people, get_min_years as db_get_min_years, save_min_years
from func_timeout import func_set_timeout
from func_timeout.exceptions import FunctionTimedOut

logger = Logger(service="vacunacovidmadridbot")

Expand All @@ -21,16 +23,30 @@ def mark_as_notified(user_info):


def get_min_years():
data = requests.get("https://autocitavacuna.sanidadmadrid.org/ohcitacovid/assets/config/app-config.json",
verify=False, timeout=5).json()
try:
years = _get_min_years()
except (FunctionTimedOut, requests.exceptions.RequestException):
years = db_get_min_years()

return years


@func_set_timeout(15)
def _get_min_years():
req = requests.get("https://autocitavacuna.sanidadmadrid.org/ohcitacovid/assets/config/app-config.json",
verify=False, timeout=5)

req.raise_for_status()
data = req.json()
max_birthday = datetime.strptime(data["dFin_Birthday"], "%d/%m/%Y")
curr_date = datetime.now()
return curr_date.year - max_birthday.year
max_years = curr_date.year - max_birthday.year
save_min_years(max_years)
return max_years


def main():
min_years = get_min_years()
min_years = _get_min_years()
non_notified = get_non_notified_people()

for person in non_notified:
Expand Down
19 changes: 19 additions & 0 deletions src/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import os
import json
from datetime import datetime
from src.exceptions import ImpossibleToDetermineMaxAge

TABLE_NAME = os.environ.get("NOTIFICATIONS_TABLE")
MIN_DATE_PARAMETER = os.environ.get("PARAM_MIN_DATE")
MIN_YEARS_PARAMETER = os.environ.get("PARAM_MIN_YEARS")
CLIENT = boto3.client('dynamodb')
CLIENT_SSM = boto3.client('ssm')

Expand Down Expand Up @@ -70,3 +72,20 @@ def get_min_date_info():
return centres_by_date, datetime.fromtimestamp(decoded_content[__UPDATED_AT])
except CLIENT_SSM.exceptions.ParameterNotFound:
return {}, None


def save_min_years(max_years):
try:
current_years = get_min_years()
except ImpossibleToDetermineMaxAge:
current_years = None

if current_years != max_years:
CLIENT_SSM.put_parameter(Name=MIN_YEARS_PARAMETER, Value=str(max_years), Type="String")


def get_min_years():
try:
return int(CLIENT_SSM.get_parameter(Name=MIN_YEARS_PARAMETER)["Parameter"]["Value"])
except CLIENT_SSM.exceptions.ParameterNotFound:
raise ImpossibleToDetermineMaxAge()
2 changes: 2 additions & 0 deletions src/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ImpossibleToDetermineMaxAge(BaseException):
pass
18 changes: 15 additions & 3 deletions src/message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from src import telegram_helpers
from src import db
from src.checker import get_min_years
from func_timeout import func_set_timeout
from func_timeout.exceptions import FunctionTimedOut


UPDATE_CENTRES_TIME = int(os.environ.get("UPDATE_CENTRES_TIME", 300))
Expand Down Expand Up @@ -178,16 +180,25 @@ def handle_min_date(_):
centres_by_date, last_update = db.get_min_date_info()

if last_update is None or (datetime.now() - last_update).seconds >= UPDATE_CENTRES_TIME:
centres_by_date, last_update = update_centres()
try:
centres_by_date, last_update = update_centres()
except (FunctionTimedOut, requests.exceptions.RequestException):
pass

if centres_by_date:
message = "¡Estupendo 😊! Aquí tienes las primeras fechas disponibles en el sistema de autocita:\n\n"
updated_ago_seconds = (datetime.now() - last_update).seconds
message = "¡Estupendo 😊! Aquí tienes las primeras fechas disponibles en el sistema de autocita:" \
if updated_ago_seconds < UPDATE_CENTRES_TIME else "Perdona 😔, pero me está costando un poquito contactar " \
"con el servicio de autocita de la Comunidad de " \
"Madrid. Aquí tienes la última información que puede " \
"extraer:"
message += "\n\n"
for date in sorted(centres_by_date.keys()):
date_str = date.strftime("%d/%m/%Y")
centres = "\n".join(map(lambda x: f"- {x}", centres_by_date[date]))
message += f"*{date_str}*:\n{centres}\n\n"

updated_ago = int((datetime.now() - last_update).seconds / 60)
updated_ago = int(round(updated_ago_seconds / 60))
updated_at_msg = f"Actualizado hace {updated_ago} minutos"
updated_at_msg = updated_at_msg[:-1] if updated_ago == 1 else updated_at_msg
message += updated_at_msg
Expand All @@ -197,6 +208,7 @@ def handle_min_date(_):
return message


@func_set_timeout(22)
def update_centres():
centres_by_date = defaultdict(lambda: list())
centres = requests.post("https://autocitavacuna.sanidadmadrid.org/ohcitacovid/autocita/obtenerCentros",
Expand Down
20 changes: 17 additions & 3 deletions tests/unit/test_checker.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from unittest.mock import patch, MagicMock, ANY, call
from freezegun import freeze_time
from func_timeout.exceptions import FunctionTimedOut
from src import checker


Expand Down Expand Up @@ -29,20 +30,33 @@ def test_when_mark_as_notified_then_db_updated(save_notification_mock):
save_notification_mock.assert_called_once_with(user_id, name, age, True)


@patch("src.checker._get_min_years", return_value=24)
def test_given_no_error_when_get_min_years_then_aux_result_returned(get_min_years_aux_mock):
assert checker.get_min_years() == 24


@patch("src.checker._get_min_years", side_effect=FunctionTimedOut)
@patch("src.checker.db_get_min_years", return_value=32)
def test_given_error_when_get_min_years_then_aux_result_returned(db_get_min_years_mock, get_min_years_aux_mock):
assert checker.get_min_years() == 32


@patch("src.checker.requests")
@patch("src.checker.save_min_years")
@freeze_time("2021-06-20")
def test_given_1990_as_year_when_get_min_years_then_31_returned(requests_mock):
def test_given_1990_as_year_when_get_min_years_aux_then_31_returned(save_min_years_mock, requests_mock):
requests_mock.get.return_value.json.return_value = {
"dFin_Birthday": "31/12/1990"
}

assert checker.get_min_years() == 31
assert checker._get_min_years() == 31
save_min_years_mock.assert_called_once_with(31)


@patch("src.checker.mark_as_notified")
@patch("src.checker.notify")
@patch("src.checker.get_non_notified_people")
@patch("src.checker.get_min_years", return_value=45)
@patch("src.checker._get_min_years", return_value=45)
def test_when_main_then_only_people_above_min_age_notified(get_min_years_mock, get_non_notified_people_mock,
notify_mock, mark_as_notified_mock):

Expand Down
48 changes: 48 additions & 0 deletions tests/unit/test_db.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from unittest.mock import patch, MagicMock
from datetime import datetime
import json
import pytest
from src import db
from src.exceptions import ImpossibleToDetermineMaxAge


TABLE_NAME = "test-table"
Expand Down Expand Up @@ -156,3 +158,49 @@ def test_given_parameter_when_save_min_date_info_then_info_stored_in_ssm(ssm_moc
datetime(2021, 5, 9): ["hosp3", "hosp4"]
}
assert received_last_update == datetime.fromtimestamp(int(last_update.timestamp()))


@patch("src.db.CLIENT_SSM")
@patch("src.db.get_min_years")
@patch("src.db.MIN_YEARS_PARAMETER", "param2_name")
def test_given_param_not_updated_when_save_min_years_then_put_parameter_called(get_min_years_mock, client_ssm_mock):
years = 20
get_min_years_mock.return_value = 21
db.save_min_years(years)
client_ssm_mock.put_parameter.assert_called_once_with(Name=db.MIN_YEARS_PARAMETER, Value=str(years),
Type="String")


@patch("src.db.CLIENT_SSM")
@patch("src.db.get_min_years")
@patch("src.db.MIN_YEARS_PARAMETER", "param2_name")
def test_given_param_not_updated_when_save_min_years_then_put_parameter_not_called(get_min_years_mock, client_ssm_mock):
years = 21
get_min_years_mock.return_value = 21
db.save_min_years(years)
client_ssm_mock.put_parameter.assert_not_called()


@patch("src.db.CLIENT_SSM")
@patch("src.db.MIN_YEARS_PARAMETER", "param2_name")
def test_given_param_exists_when_get_min_years_then_converted_param_returned(client_ssm_mock):
years = "20"
client_ssm_mock.exceptions.ParameterNotFound = ParameterNotFound
client_ssm_mock.get_parameter.return_value = {
"Parameter": {
"Value": years
}
}

assert db.get_min_years() == int(years)
client_ssm_mock.get_parameter.assert_called_once_with(Name=db.MIN_YEARS_PARAMETER)


@patch("src.db.CLIENT_SSM")
@patch("src.db.MIN_YEARS_PARAMETER", "param2_name")
def test_given_param_does_not_exists_when_get_min_years_then_custom_exception_raises(client_ssm_mock):
client_ssm_mock.exceptions.ParameterNotFound = ParameterNotFound
client_ssm_mock.get_parameter.side_effect = ParameterNotFound

with pytest.raises(ImpossibleToDetermineMaxAge):
db.get_min_years()
2 changes: 1 addition & 1 deletion tests/unit/test_message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ def test_given_info_updated_when_handle_min_date_then_update_centres_not_called(

assert "*06/03/2021*:\n- hosp1\n- hosp2" in answer
assert "*09/05/2021*:\n- hosp3\n- hosp4" in answer
assert "Actualizado hace 19 minutos" in answer
assert "Actualizado hace 20 minutos" in answer


@freeze_time("2021-06-22 10:01:02")
Expand Down

0 comments on commit 9cd86a2

Please sign in to comment.