From 5e21128689f909309064025ace4526a330f0e58d Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Wed, 27 Sep 2023 18:30:05 +0300 Subject: Specialize EmailAlerter to use SendGrid API --- Aggrofile | 13 +++++------- aggro.py | 11 +++++----- app/AggroConfig.py | 7 +++---- app/EmailAlerter.py | 46 ----------------------------------------- app/PluginManager.py | 14 +++++++------ app/SendGridAlerter.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 70 deletions(-) delete mode 100644 app/EmailAlerter.py create mode 100644 app/SendGridAlerter.py diff --git a/Aggrofile b/Aggrofile index afd6bb7..e463b31 100644 --- a/Aggrofile +++ b/Aggrofile @@ -4,15 +4,12 @@ "host": "0.0.0.0", "port": 8080 }, - "email_alerter": { - "api_url": "${AGGRO_EMAIL_ALERT_API_URL}", - "api_headers": { - "Authorization": "${AGGRO_EMAIL_ALERT_API_AUTH}", - "Content-Type": "application/json" - }, - "email_from": "${AGGRO_EMAIL_ALERT_FROM}", + "sendgrid_alerter": { + "api_url": "${AGGRO_SENDGRID_API_URL}", + "api_token": "${AGGRO_SENDGRID_API_TOKEN}", + "email_from": "${AGGRO_SENDGRID_FROM}", "email_to": [ - "${AGGRO_EMAIL_ALERT_TO}" + "${AGGRO_SENDGRID_TO}" ] }, "plugins": { diff --git a/aggro.py b/aggro.py index 4f315e4..0ba40f8 100644 --- a/aggro.py +++ b/aggro.py @@ -7,7 +7,7 @@ import time from typing import Any from tinydb import Query -from app.AggroConfig import AggroConfig, AggroConfigServer, AggroConfigEmailAlerter +from app.AggroConfig import AggroConfig, AggroConfigServer, AggroConfigSendGridAlerter from app.MemoryState import memory_state from app.PluginManager import PluginManager from app.DatabaseManager import database_manager @@ -44,11 +44,10 @@ if __name__ == "__main__": port=get_config_or_default(aggrofile_server, "port", 8080), ) - aggrofile_email_alerter = get_config_or_default(aggrofile, "email_alerter", None) + aggrofile_email_alerter = get_config_or_default(aggrofile, "sendgrid_alerter", None) if aggrofile_email_alerter: - email_alerter_config = AggroConfigEmailAlerter( - api_url=get_config(aggrofile_email_alerter, "api_url"), - api_headers=get_config(aggrofile_email_alerter, "api_headers"), + email_alerter_config = AggroConfigSendGridAlerter( + api_token=get_config(aggrofile_email_alerter, "api_token"), email_from=get_config(aggrofile_email_alerter, "email_from"), email_to=get_config(aggrofile_email_alerter, "email_to"), ) @@ -57,7 +56,7 @@ if __name__ == "__main__": aggro_config = AggroConfig( server=server_config, - email_alerter=email_alerter_config, + sendgrid_alerter=email_alerter_config, db_path=get_config_or_default(aggrofile, "db_path", "db.json"), plugins=get_config(aggrofile, "plugins"), graph=get_config(aggrofile, "graph"), diff --git a/app/AggroConfig.py b/app/AggroConfig.py index 6dfbb94..3a9142d 100644 --- a/app/AggroConfig.py +++ b/app/AggroConfig.py @@ -10,9 +10,8 @@ class AggroConfigServer: @dataclass -class AggroConfigEmailAlerter: - api_url: str - api_headers: dict[str, str] +class AggroConfigSendGridAlerter: + api_token: str email_from: str email_to: list[str] @@ -20,7 +19,7 @@ class AggroConfigEmailAlerter: @dataclass class AggroConfig: server: AggroConfigServer - email_alerter: AggroConfigEmailAlerter | None + sendgrid_alerter: AggroConfigSendGridAlerter | None db_path: str plugins: dict[str, Params] graph: dict[str, list[str]] diff --git a/app/EmailAlerter.py b/app/EmailAlerter.py deleted file mode 100644 index d4406fc..0000000 --- a/app/EmailAlerter.py +++ /dev/null @@ -1,46 +0,0 @@ -import requests -import traceback -from datetime import datetime -from app.AggroConfig import AggroConfigEmailAlerter -from dataclasses import asdict - - -class EmailAlerter: - @staticmethod - def from_config(config: AggroConfigEmailAlerter) -> "EmailAlerter": - return EmailAlerter(**asdict(config)) - - def __init__( - self, - api_url: str, - api_headers: dict[str, str], - email_from: str, - email_to: list[str], - ): - self.api_url = api_url - self.email_from = email_from - self.email_to = email_to - self.api_headers = api_headers - - def send_alert(self, text: str): - try: - now = datetime.now() - now_text = now.strftime("%a, %d %b %Y %H:%M:%S +0000") - data = { - "from": self.email_from, - "to": self.email_to, - "subject": f"Aggro alert on {now_text}", - "text": text, - } - r = requests.post( - self.api_url, - data=data, - headers=self.api_headers, - ) - if r.status_code >= 400: - raise Exception( - f"[EmailAlerter] sending alert email via HTTP returned code {r.status_code} and body:\n{r.text}" - ) - - except: - traceback.print_exc() diff --git a/app/PluginManager.py b/app/PluginManager.py index fdc81a9..b19d038 100644 --- a/app/PluginManager.py +++ b/app/PluginManager.py @@ -7,10 +7,10 @@ from types import ModuleType from typing import Any from app.Item import Item from app.PluginInterface import Params, PluginInterface -from app.AggroConfig import AggroConfig, AggroConfigEmailAlerter +from app.AggroConfig import AggroConfig, AggroConfigSendGridAlerter from app.utils import get_config from app.MemoryState import memory_state -from app.EmailAlerter import EmailAlerter +from app.SendGridAlerter import SendGridAlerter class PluginManager: @@ -19,8 +19,10 @@ class PluginManager: self.plugin_instances: dict[str, PluginInterface] = {} self.config = config self.scheduled_plugin_ids: list[str] = [] - if self.config.email_alerter: - self.email_alerter = EmailAlerter.from_config(self.config.email_alerter) + if self.config.sendgrid_alerter: + self.sendgrid_alerter = SendGridAlerter.from_config( + self.config.sendgrid_alerter + ) def load_plugin(self, plugin_name: str) -> None: module: ModuleType = importlib.import_module(f"plugins.{plugin_name}") @@ -53,8 +55,8 @@ class PluginManager: except: exc = traceback.format_exc() print(exc, file=sys.stderr) - if self.email_alerter: - self.email_alerter.send_alert(exc) + if self.sendgrid_alerter: + self.sendgrid_alerter.send_alert(exc) def build_plugin_instances(self): for id in self.config.plugins: diff --git a/app/SendGridAlerter.py b/app/SendGridAlerter.py new file mode 100644 index 0000000..0509a57 --- /dev/null +++ b/app/SendGridAlerter.py @@ -0,0 +1,56 @@ +from typing import Any +import requests +import traceback +from datetime import datetime +from app.AggroConfig import AggroConfigSendGridAlerter +from dataclasses import asdict + + +class SendGridAlerter: + @staticmethod + def from_config(config: AggroConfigSendGridAlerter) -> "SendGridAlerter": + return SendGridAlerter(**asdict(config)) + + def __init__( + self, + api_token: str, + email_from: str, + email_to: list[str], + ): + self.email_from = email_from + self.email_to = email_to + self.api_token = api_token + + def send_alert(self, text: str): + try: + now = datetime.now() + now_text = now.strftime("%a, %d %b %Y %H:%M:%S +0000") + to_lst = [{"email": email} for email in self.email_to] + subject = f"Aggro alert on {now_text}" + API_URL = "https://api.sendgrid.com/v3/mail/send" + data = { + "personalizations": [{"to": to_lst}], + "from": {"email": self.email_from}, + "subject": subject, + "content": [ + { + "type": "text/plain", + "value": text, + } + ], + } + r = requests.post( + API_URL, + data=data, + headers={ + "Authorization": f"Bearer {self.api_token}", + "Content-Type": "application/json", + }, + ) + if r.status_code >= 400: + raise Exception( + f"[SendGridAlerter] sending alert email via HTTP returned code {r.status_code} and body:\n{r.text}" + ) + + except: + traceback.print_exc() -- cgit v1.3