Skip to content

Commit 962189c

Browse files
authored
Merge pull request #10 from flightaware/BCK-7005_display_alerts
Display POSTed Alerts
2 parents 7707a0e + d0cd396 commit 962189c

File tree

1 file changed

+108
-45
lines changed

1 file changed

+108
-45
lines changed

alerts_backend/python/app.py

Lines changed: 108 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,24 @@
66
import json
77
import requests
88
from flask import Flask, jsonify, Response, request
9+
from flask.logging import create_logger
910
from flask_cors import CORS
1011

11-
from sqlalchemy import (exc, create_engine, MetaData, Table,
12-
Column, Integer, Boolean, Text, insert, Date, DateTime)
1312
from sqlalchemy.sql import func
13+
from sqlalchemy import (
14+
exc,
15+
create_engine,
16+
MetaData,
17+
Table,
18+
Column,
19+
Integer,
20+
Boolean,
21+
Text,
22+
insert,
23+
Date,
24+
select,
25+
DateTime,
26+
)
1427

1528
AEROAPI_BASE_URL = "https://aeroapi.flightaware.com/aeroapi"
1629
AEROAPI_KEY = os.environ["AEROAPI_KEY"]
@@ -19,6 +32,7 @@
1932

2033
# pylint: disable=invalid-name
2134
app = Flask(__name__)
35+
logger = create_logger(app)
2236
CORS(app)
2337

2438
# create the SQL engine using SQLite
@@ -34,41 +48,43 @@
3448
metadata_obj = MetaData()
3549
# Table for alert configurations
3650
aeroapi_alert_configurations = Table(
37-
"aeroapi_alert_configurations",
38-
metadata_obj,
39-
Column("fa_alert_id", Integer, primary_key=True),
40-
Column("ident", Text),
41-
Column("origin", Text),
42-
Column("destination", Text),
43-
Column("aircraft_type", Text),
44-
Column("start_date", Date),
45-
Column("end_date", Date),
46-
Column("max_weekly", Integer),
47-
Column("eta", Integer),
48-
Column("arrival", Boolean),
49-
Column("cancelled", Boolean),
50-
Column("departure", Boolean),
51-
Column("diverted", Boolean),
52-
Column("filed", Boolean),
53-
)
51+
"aeroapi_alert_configurations",
52+
metadata_obj,
53+
Column("fa_alert_id", Integer, primary_key=True),
54+
Column("ident", Text),
55+
Column("origin", Text),
56+
Column("destination", Text),
57+
Column("aircraft_type", Text),
58+
Column("start_date", Date),
59+
Column("end_date", Date),
60+
Column("max_weekly", Integer),
61+
Column("eta", Integer),
62+
Column("arrival", Boolean),
63+
Column("cancelled", Boolean),
64+
Column("departure", Boolean),
65+
Column("diverted", Boolean),
66+
Column("filed", Boolean),
67+
)
5468
# Table for POSTed alerts
5569
aeroapi_alerts = Table(
56-
"aeroapi_alerts",
57-
metadata_obj,
58-
Column("id", Integer, primary_key=True, autoincrement=True),
59-
Column("time_alert_received", DateTime(timezone=True), server_default=func.now()), # Store time in UTC that the alert was received
60-
Column("long_description", Text),
61-
Column("short_description", Text),
62-
Column("summary", Text),
63-
Column("event_code", Text),
64-
Column("alert_id", Integer),
65-
Column("fa_flight_id", Text),
66-
Column("ident", Text),
67-
Column("registration", Text),
68-
Column("aircraft_type", Text),
69-
Column("origin", Text),
70-
Column("destination", Text)
71-
)
70+
"aeroapi_alerts",
71+
metadata_obj,
72+
Column("id", Integer, primary_key=True, autoincrement=True),
73+
Column(
74+
"time_alert_received", DateTime(timezone=True), server_default=func.now()
75+
), # Store time in UTC that the alert was received
76+
Column("long_description", Text),
77+
Column("short_description", Text),
78+
Column("summary", Text),
79+
Column("event_code", Text),
80+
Column("alert_id", Integer),
81+
Column("fa_flight_id", Text),
82+
Column("ident", Text),
83+
Column("registration", Text),
84+
Column("aircraft_type", Text),
85+
Column("origin", Text),
86+
Column("destination", Text),
87+
)
7288

7389

7490
def create_tables():
@@ -79,10 +95,12 @@ def create_tables():
7995
try:
8096
# Create the table(s) if they don't exist
8197
metadata_obj.create_all(engine)
82-
app.logger.info("Table(s) successfully created (if not already created)")
98+
logger.info("Table(s) successfully created (if not already created)")
8399
except exc.SQLAlchemyError as e:
84100
# Since creation of table(s) is a critical error, raise exception
85-
app.logger.error(f"SQL error occurred during creation of table(s) (CRITICAL - THROWING ERROR): {e}")
101+
logger.error(
102+
f"SQL error occurred during creation of table(s) (CRITICAL - THROWING ERROR): {e}"
103+
)
86104
raise e
87105

88106

@@ -99,13 +117,47 @@ def insert_into_table(data_to_insert: Dict[str, Any], table: Table) -> int:
99117
stmt = insert(table)
100118
conn.execute(stmt, data_to_insert)
101119
conn.commit()
102-
app.logger.info(f"Data successfully inserted into table {table.name}")
120+
logger.info(f"Data successfully inserted into table {table.name}")
103121
except exc.SQLAlchemyError as e:
104-
app.logger.error(f"SQL error occurred during insertion into table {table.name}: {e}")
122+
logger.error(f"SQL error occurred during insertion into table {table.name}: {e}")
105123
return -1
106124
return 0
107125

108126

127+
@app.route("/posted_alerts")
128+
def get_posted_alerts() -> Response:
129+
"""
130+
Function to return all the triggered POSTed alerts via the SQL table.
131+
Returns a JSON payload of all the POSTed alerts.
132+
"""
133+
data: Dict[str, Any] = {"posted_alerts": []}
134+
with engine.connect() as conn:
135+
stmt = select(aeroapi_alerts)
136+
result = conn.execute(stmt)
137+
conn.commit()
138+
for row in result:
139+
data["posted_alerts"].append(dict(row))
140+
141+
return jsonify(data)
142+
143+
144+
@app.route("/alert_configs")
145+
def get_alert_configs() -> Response:
146+
"""
147+
Function to return all the alerts that are currently configured
148+
via the SQL table. Returns a JSON payload of all the configured alerts.
149+
"""
150+
data: Dict[str, Any] = {"alert_configurations": []}
151+
with engine.connect() as conn:
152+
stmt = select(aeroapi_alert_configurations)
153+
result = conn.execute(stmt)
154+
conn.commit()
155+
for row in result:
156+
data["alert_configurations"].append(dict(row))
157+
158+
return jsonify(data)
159+
160+
109161
@app.route("/post", methods=["POST"])
110162
def handle_alert() -> Tuple[Response, int]:
111163
"""
@@ -146,7 +198,9 @@ def handle_alert() -> Tuple[Response, int]:
146198
r_status = 200
147199
except KeyError as e:
148200
# If value doesn't exist, do not insert into table and produce error
149-
app.logger.error(f"Alert POST request did not have one or more keys with data. Will process but will return 400: {e}")
201+
logger.error(
202+
f"Alert POST request did not have one or more keys with data. Will process but will return 400: {e}"
203+
)
150204
r_title = "Missing info in request"
151205
r_detail = "At least one value to insert in the database is missing in the post request"
152206
r_status = 400
@@ -166,7 +220,7 @@ def create_alert() -> Response:
166220
# initialize response headers
167221
r_alert_id: int = -1
168222
r_success: bool = False
169-
r_description: str = ''
223+
r_description: str = ""
170224
# Process json
171225
content_type = request.headers.get("Content-Type")
172226
data: Dict[str, Any]
@@ -190,15 +244,21 @@ def create_alert() -> Response:
190244
if "max_weekly" not in data:
191245
data["max_weekly"] = 1000
192246

193-
app.logger.info(f"Making AeroAPI request to POST {api_resource}")
247+
logger.info(f"Making AeroAPI request to POST {api_resource}")
194248
result = AEROAPI.post(f"{AEROAPI_BASE_URL}{api_resource}", json=data)
195249
if result.status_code != 201:
196250
# return to front end the error, decode and clean the response
197251
try:
198252
processed_json = result.json()
199-
r_description = f"Error code {result.status_code} with the following description: {processed_json['detail']}"
253+
r_description = (
254+
f"Error code {result.status_code} with the following "
255+
f"description: {processed_json['detail']}"
256+
)
200257
except json.decoder.JSONDecodeError:
201-
r_description = f"Error code {result.status_code} could not be parsed into JSON. The following is the HTML response given: {result.text}"
258+
r_description = (
259+
f"Error code {result.status_code} could not be parsed into JSON. "
260+
f"The following is the HTML response given: {result.text}"
261+
)
202262
else:
203263
# Package created alert and put into database
204264
fa_alert_id = int(result.headers["Location"][8:])
@@ -228,7 +288,10 @@ def create_alert() -> Response:
228288
data["fa_alert_id"] = fa_alert_id
229289

230290
if insert_into_table(data, aeroapi_alert_configurations) == -1:
231-
r_description = f"Database insertion error, check your database configuration. Alert has still been configured with alert id {r_alert_id}"
291+
r_description = (
292+
f"Database insertion error, check your database configuration. "
293+
f"Alert has still been configured with alert id {r_alert_id}"
294+
)
232295
else:
233296
r_success = True
234297
r_description = f"Request sent successfully with alert id {r_alert_id}"

0 commit comments

Comments
 (0)