Skip to content

Commit

Permalink
Merge pull request #28 from everettsouthwick/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
everettsouthwick authored Sep 10, 2023
2 parents 689b1be + c9420ca commit 900ae3f
Showing 1 changed file with 82 additions and 29 deletions.
111 changes: 82 additions & 29 deletions src/schedule_retriever.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

from .config import Config

GOES_URL_FORMAT = 'https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=500&locationId={0}&minimum=1'
GOES_URL_FORMAT = "https://ttp.cbp.dhs.gov/schedulerapi/slots?orderBy=soonest&limit=500&locationId={0}&minimum=1"


class ScheduleRetriever:
"""
Expand All @@ -22,7 +23,9 @@ def __init__(self, config: Config) -> None:
self.config = config
self.notification_handler = NotificationHandler(self)

def _evaluate_timestamp(self, schedule: List[Schedule], location_id: int, timestamp: str) -> List[Schedule]:
def _evaluate_timestamp(
self, schedule: List[Schedule], location_id: int, timestamp: str
) -> List[Schedule]:
"""
Evaluates the given timestamp against the provided schedule and location ID. If the timestamp is within the
acceptable range specified in the configuration, it is added to the schedule.
Expand All @@ -36,20 +39,22 @@ def _evaluate_timestamp(self, schedule: List[Schedule], location_id: int, timest
:return: The updated schedule.
:rtype: List[Schedule]
"""
parsed_date = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M')
parsed_date = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M")

for dates in schedule:
if dates.appointment_date.date() == parsed_date.date():
if self._is_acceptable_appointment(location_id, parsed_date):
dates.appointment_times.append(parsed_date)
return schedule

if self._is_acceptable_appointment(location_id, parsed_date):
schedule.append(Schedule(parsed_date, [parsed_date]))

return schedule

def _is_acceptable_appointment(self, location_id: int, parsed_date: datetime) -> bool:
return schedule

def _is_acceptable_appointment(
self, location_id: int, parsed_date: datetime
) -> bool:
"""
Determines if the given appointment time is acceptable based on the configuration settings and existing
appointments in the database.
Expand All @@ -61,37 +66,80 @@ def _is_acceptable_appointment(self, location_id: int, parsed_date: datetime) ->
:return: True if the appointment time is acceptable, False otherwise.
:rtype: bool
"""
if self.config.current_appointment_date is None or self.config.current_appointment_date > parsed_date:
if self.config.start_appointment_time is None or self.config.start_appointment_time.time() <= parsed_date.time():
if self.config.end_appointment_time is None or self.config.end_appointment_time.time() >= parsed_date.time():
conn = sqlite3.connect('ttp.db')
if (
self.config.current_appointment_date is None
or self.config.current_appointment_date > parsed_date
):
if (
self.config.start_appointment_time is None
or self.config.start_appointment_time.time() <= parsed_date.time()
):
if (
self.config.end_appointment_time is None
or self.config.end_appointment_time.time() >= parsed_date.time()
):
conn = sqlite3.connect("ttp.db")

cursor = conn.cursor()

# Check if there is an existing appointment with the same location ID and timestamp
cursor.execute('''SELECT COUNT(*) FROM appointments
WHERE location_id = ? AND start_time = ?''',
(location_id, parsed_date.isoformat()))
cursor.execute(
"""SELECT COUNT(*) FROM appointments
WHERE location_id = ? AND start_time = ?""",
(location_id, parsed_date.isoformat()),
)

count = cursor.fetchone()[0]

if count > 0:
conn.close()

return False
else:
cursor.execute('''INSERT INTO appointments (location_id, start_time)
VALUES (?, ?)''',
(location_id, parsed_date.isoformat()))

conn.commit()
cursor.execute(
"""INSERT INTO appointments (location_id, start_time)
VALUES (?, ?)""",
(location_id, parsed_date.isoformat()),
)

conn.close()
conn.commit()

conn.close()

return True
return True

return False

def _clear_database_of_claimed_appointments(
self, location_id: int, schedule: List[Schedule]
) -> None:
"""
Clears the database of any appointments that have been claimed.
:return: None
"""
active_appointment_times = []
for dates in schedule:
for appointment_time in dates.appointment_times:
active_appointment_times.append(appointment_time.isoformat())

if not active_appointment_times:
return

conn = sqlite3.connect("ttp.db")
cursor = conn.cursor()

cursor.execute(
f"""DELETE FROM appointments
WHERE location_id = ? AND start_time NOT IN ({",".join(['?'] * len(active_appointment_times))})""",
[location_id] + active_appointment_times,
)

print(f"Cleared {cursor.rowcount} appointments no longer available from the database")

conn.commit()
conn.close()

def _get_schedule(self, location_id: int) -> None:
"""
Retrieves the schedule for the given location ID and evaluates the available appointment times. If there are
Expand All @@ -103,24 +151,29 @@ def _get_schedule(self, location_id: int) -> None:
"""
try:
time.sleep(1)
appointments = requests.get(GOES_URL_FORMAT.format(location_id)).json()
appointments = requests.get(
GOES_URL_FORMAT.format(location_id), timeout=30
).json()

if not appointments:
return

schedule = []
for appointment in appointments:
if appointment['active']:
schedule = self._evaluate_timestamp(schedule, location_id, appointment['startTimestamp'])
if appointment["active"]:
schedule = self._evaluate_timestamp(
schedule, location_id, appointment["startTimestamp"]
)

if not schedule:
return

self.notification_handler.new_appointment(location_id, schedule)

self._clear_database_of_claimed_appointments(location_id, schedule)

except OSError:
return

def monitor_location(self, location_id: int) -> None:
"""
Monitors the given location ID for available appointment times. If the retrieval interval is set to 0, the
Expand All @@ -146,4 +199,4 @@ def monitor_location(self, location_id: int) -> None:
time_taken = (time_after - time_before).total_seconds()
time_to_sleep = self.config.retrieval_interval - time_taken
if time_to_sleep > 0:
time.sleep(time_to_sleep)
time.sleep(time_to_sleep)

0 comments on commit 900ae3f

Please sign in to comment.