Compare commits

...

14 Commits

Author SHA1 Message Date
blallo fa0023d2d1
Bump to v0.3.3 2022-09-27 23:16:11 +02:00
blallo 4d1596c4a2
Make cc REALLY work 2022-09-27 23:15:50 +02:00
blallo 821335d719
Bump to v0.3.2 2022-09-27 23:06:12 +02:00
blallo 635780b353
Some mailserver require the Date header 2022-09-27 23:04:12 +02:00
blallo 51b4e6c112
Cc should not be empty 2022-09-27 23:03:42 +02:00
blallo 9750623929
Bump to v0.3.1 2022-09-20 22:30:18 +02:00
blallo f3ed2b0cc9
Optionally add Cc to the email 2022-09-20 22:29:59 +02:00
blallo 365105f4b4
Bump to v0.3.0 2022-09-18 23:30:42 +02:00
blallo 8860db44b4
Black'd 2022-09-18 23:29:49 +02:00
blallo 00baa4a2f2
Retrieve more data from fr24 2022-09-18 23:29:32 +02:00
blallo 55b6d565b0
Optionally save file to store path 2022-09-18 23:29:02 +02:00
blallo 8a07cbf2aa
Bump to v0.2.1 2022-09-09 11:09:33 +02:00
blallo e6825248dd
Fix: adjust timestamp for fr24 data retrieval 2022-09-09 11:09:03 +02:00
blallo 7e7d1fff1e
Add debug logging 2022-09-09 11:08:37 +02:00
8 changed files with 60 additions and 20 deletions

View File

@ -20,6 +20,8 @@ def get_section(obj: T.Dict[T.Text, T.Any], key: T.Text) -> T.Any:
class Config(object): class Config(object):
smtp: T.Dict[T.Text, T.Any] = {} smtp: T.Dict[T.Text, T.Any] = {}
to: T.List[T.Text] = [] to: T.List[T.Text] = []
cc: T.List[T.Text] = []
store: T.Optional[T.Text] = None
def __init__(self, path: T.Text) -> None: def __init__(self, path: T.Text) -> None:
self.from_file(path) self.from_file(path)
@ -34,6 +36,9 @@ class Config(object):
self.to = get_section(content, "to") self.to = get_section(content, "to")
if cc := content.get("cc"):
self.cc = cc
smtp = get_section(content, "smtp") smtp = get_section(content, "smtp")
for key in [ for key in [
"smtp_addr", "smtp_addr",
@ -46,5 +51,7 @@ class Config(object):
self.smtp["smtp_from"] = smtp.get("smtp_from") self.smtp["smtp_from"] = smtp.get("smtp_from")
self.store = content.get("store")
def __str__(self) -> T.Text: def __str__(self) -> T.Text:
return f"Config<smtp={self.smtp},to={self.to}>" return f"Config<smtp={self.smtp},to={self.to}>"

View File

@ -1,4 +1,5 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from datetime import datetime, timedelta
import functools import functools
import logging import logging
import sys import sys
@ -48,3 +49,10 @@ def retry_and_log(logger: logging.Logger, retries: int):
return inner return inner
return wrapper return wrapper
def get_date() -> T.Text:
"""
Get yesterday's date in %Y-%m-%d format.
"""
return (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")

View File

@ -32,10 +32,10 @@ def main(config: Config):
data.append(get_details(row, aux_data)) data.append(get_details(row, aux_data))
if not data: if not data:
out.send_no_data(config.to) out.send_no_data(config.to, config.cc)
excel = to_excel(data) excel = to_excel(data, config.store)
out.send_result(config.to, excel) out.send_result(config.to, config.cc, excel)
def cli(): def cli():

View File

@ -1,6 +1,6 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from contextlib import contextmanager from contextlib import contextmanager
from datetime import datetime, timedelta from datetime import datetime
from email import encoders from email import encoders
from email.mime.base import MIMEBase from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
@ -10,8 +10,7 @@ import smtplib
import ssl import ssl
import typing as T import typing as T
from latecomers.helpers import retry_and_log, get_date
from latecomers.helpers import retry_and_log
RETRIES = 3 RETRIES = 3
@ -57,13 +56,18 @@ class Notifier(object):
conn.sendmail(self._from, to, email) conn.sendmail(self._from, to, email)
@retry_and_log(logger, RETRIES) @retry_and_log(logger, RETRIES)
def send_result(self, to: T.List[T.Text], result: bytes) -> None: def send_result(
date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d") self, to: T.List[T.Text], cc: T.List[T.Text], result: bytes
) -> None:
date = get_date()
body = f"Resoconto dei voli dal sito di AdR per l'aereoporto di Ciampino in data {date}" # noqa: E501 body = f"Resoconto dei voli dal sito di AdR per l'aereoporto di Ciampino in data {date}" # noqa: E501
message = MIMEMultipart() message = MIMEMultipart()
message["Date"] = datetime.now().strftime("%a, %d %b %Y %H:%M:%S %z")
message["From"] = self._from message["From"] = self._from
message["To"] = ",".join(to) message["To"] = ",".join(to)
if cc:
message["Cc"] = ",".join(cc)
message["Subject"] = f"[{date}] Resoconto CIA da AdR" message["Subject"] = f"[{date}] Resoconto CIA da AdR"
message.attach(MIMEText(body, "plain")) message.attach(MIMEText(body, "plain"))
@ -80,11 +84,14 @@ class Notifier(object):
email = message.as_string() email = message.as_string()
self.send(to, email) rcpt = to
rcpt.extend(cc)
self.send(rcpt, email)
@retry_and_log(logger, RETRIES) @retry_and_log(logger, RETRIES)
def send_no_data(self, to: T.List[T.Text]) -> None: def send_no_data(self, to: T.List[T.Text], cc: T.List[T.Text]) -> None:
date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d") date = get_date()
body = f"""Attenzione body = f"""Attenzione
Nessun dato è stato trovato per i voli in data {date} dal sito di AdR per Nessun dato è stato trovato per i voli in data {date} dal sito di AdR per
@ -93,11 +100,17 @@ il vostro tecnico preferito.
""" """
message = MIMEMultipart() message = MIMEMultipart()
message["Date"] = datetime.now().strftime("%a, %d %b %Y %H:%M:%S %z")
message["From"] = self._from message["From"] = self._from
message["To"] = ",".join(to) message["To"] = ",".join(to)
if cc:
message["Cc"] = ",".join(cc)
message["Subject"] = f"ATTENZIONE: [{date}] Resoconto CIA da AdR" message["Subject"] = f"ATTENZIONE: [{date}] Resoconto CIA da AdR"
message.attach(MIMEText(body, "plain")) message.attach(MIMEText(body, "plain"))
email = message.as_string() email = message.as_string()
self.send(to, email) rcpt = to
rcpt.extend(cc)
self.send(rcpt, email)

View File

@ -197,6 +197,8 @@ def parse_fr24(
""" """
This function parses the given FlightRadar24 data into a pandas DataFrame. This function parses the given FlightRadar24 data into a pandas DataFrame.
""" """
logger.debug("fr24 raw data: %s", data)
if not data: if not data:
return None return None
@ -209,9 +211,9 @@ def parse_fr24(
]: # noqa: E501 ]: # noqa: E501
try: try:
id_num = flight["flight"]["identification"]["number"] id_num = flight["flight"]["identification"]["number"]
if (_code := id_num.get("default")): if _code := id_num.get("default"):
code = _code code = _code
elif (_code := id_num.get("alternative")): elif _code := id_num.get("alternative"):
code = _code code = _code
else: else:
# skip if no flight code found # skip if no flight code found
@ -219,6 +221,7 @@ def parse_fr24(
ts = flight["flight"]["time"]["real"]["arrival"] ts = flight["flight"]["time"]["real"]["arrival"]
real_arrival = datetime.fromtimestamp(ts).strftime("%H:%M") real_arrival = datetime.fromtimestamp(ts).strftime("%H:%M")
results[code] = real_arrival results[code] = real_arrival
logger.debug(f"{code} -> {real_arrival}")
except: # noqa: E722 except: # noqa: E722
continue continue

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,11 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
import logging import logging
import os.path
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
import typing as T import typing as T
from latecomers.parse import Details from latecomers.parse import Details
from latecomers.helpers import logit from latecomers.helpers import logit, get_date
import pandas as pd import pandas as pd
@ -13,7 +14,7 @@ logger = logging.getLogger(__name__)
@logit(logger) @logit(logger)
def to_excel(data: T.List[Details]) -> bytes: def to_excel(data: T.List[Details], dst: T.Optional[T.Text] = None) -> bytes:
""" """
This function takes the list of parsed rows as input and returns This function takes the list of parsed rows as input and returns
the bytes corresponding to the excel file derived from such lines. the bytes corresponding to the excel file derived from such lines.
@ -38,4 +39,12 @@ def to_excel(data: T.List[Details]) -> bytes:
tmp.seek(0) tmp.seek(0)
content = tmp.read() content = tmp.read()
if dst:
filepath = os.path.join(dst, f"{get_date()}.xlsx")
try:
with open(filepath, "wb") as out:
out.write(content)
except Exception as e:
logger.warning(f"Cannot save to path '{filepath}': {e}")
return content return content

View File

@ -1,6 +1,6 @@
[project] [project]
name = "latecomers" name = "latecomers"
version = "0.2.0" version = "0.3.3"
description = "Retrieve and save data from ADR Ciampino airport" description = "Retrieve and save data from ADR Ciampino airport"
authors = [{name="Leonardo Barcaroli", email="blallo@autistici.org"}] authors = [{name="Leonardo Barcaroli", email="blallo@autistici.org"}]
license = {text="Public Domain"} license = {text="Public Domain"}