implement basic caching mechanism

This commit is contained in:
Lea 2024-09-10 21:02:23 +02:00
parent 955bb572a3
commit 17d203575c
3 changed files with 62 additions and 29 deletions

3
.gitignore vendored
View File

@ -4,4 +4,5 @@
__pycache__
app-2.2.0.js
package-lock.json
node_modules
node_modules
_therapydb.cache

3
app.py
View File

@ -60,8 +60,7 @@ def search_for_doctors_with_params():
# Calculate the required base64 value why so ever
base64_value = api_handler.calculate_req_value_base64(float(location_match["lat"]), float(location_match["lon"]))
# Get the general list of doctors
api_handler.get_list_of_doctors(float(location_match["lat"]), float(location_match["lon"]), base64_value,
therapy_types, therapy_age_range, therapy_setting)
api_handler.get_list_of_doctors(float(location_match["lat"]), float(location_match["lon"]), base64_value, therapy_types, therapy_age_range, therapy_setting, amount_of_weeks)
# Get their information
api_handler.get_general_doctor_information()
# Filter for the distance

View File

@ -3,6 +3,7 @@ from typing import List
import requests
from requests import JSONDecodeError
import base64
import shelve
from datetime import datetime, timedelta
from arztapi.ArztPraxisDatas import ArztPraxisDatas
from arztapi.DoctorInformation import DoctorInformation, PhoneTime
@ -17,10 +18,12 @@ class APIHandler:
def __init__(self):
# Base URL as given by the base website
self.base_api_url = "https://arztsuche.116117.de/api/"
self.json_data = {}
# Containers for phone times, general doctor information and processed phone times of doctors
self.phone_times = []
self.general_information = []
self.processed_doctor_phone_times = []
self._cache = shelve.open("_therapydb.cache")
def get_lat_lon_location_list(self, location):
"""
@ -57,34 +60,12 @@ class APIHandler:
except JSONDecodeError:
return None
def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age,
therapy_setting) -> ArztPraxisDatas:
"""
:param lat: Latitude as given by location API
:param lon: Longitude as given by location API
:param req_val_base64: base64 value required for API access (is this a token?)
:param therapy_types: Therapy types of interest
:param therapy_age: Therapy age range of interest
:param therapy_setting: Therapy setting of interest
:return: Relevant doctor/therapist data
"""
# API path for doctor data
api_path = self.base_api_url + "data"
headers = {
"Accept": "application/json",
"Accept-Language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7",
# Authorization header gathered by initial cURLing
"Authorization": "Basic YmRwczpma3I0OTNtdmdfZg==",
"Connection": "keep-alive",
# Calculated base64 value based on latitude and longitude
"req-val": req_val_base64,
}
def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age, therapy_setting,
amount_of_weeks) -> ArztPraxisDatas:
# Data object as built by the original website, some fields might not be plausible or known (since there is no
# API documentation itself available
json_data = {
self.json_data = {
# TODO: Find out what r means
"r": 900,
"lat": lat,
@ -122,7 +103,46 @@ class APIHandler:
"viaDeeplink": False,
}
response = requests.post(api_path, headers=headers, json=json_data)
amount_of_days = amount_of_weeks * 7
cache_data = self.get_current_doctor_information_data_in_cache_with_time_check(amount_of_days)
if cache_data:
print("using cached data")
self.phone_times = cache_data
else:
print("call api")
self.get_list_of_doctors_from_api(lat, lon, req_val_base64, therapy_types, therapy_age, therapy_setting)
self.set_current_doctor_information_data_in_cache()
def get_list_of_doctors_from_api(self, lat, lon, req_val_base64, therapy_types, therapy_age,
therapy_setting) -> ArztPraxisDatas:
"""
:param lat: Latitude as given by location API
:param lon: Longitude as given by location API
:param req_val_base64: base64 value required for API access (is this a token?)
:param therapy_types: Therapy types of interest
:param therapy_age: Therapy age range of interest
:param therapy_setting: Therapy setting of interest
:return: Relevant doctor/therapist data
"""
# API path for doctor data
api_path = self.base_api_url + "data"
headers = {
"Accept": "application/json",
"Accept-Language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7",
# Authorization header gathered by initial cURLing
"Authorization": "Basic YmRwczpma3I0OTNtdmdfZg==",
"Connection": "keep-alive",
# Calculated base64 value based on latitude and longitude
"req-val": req_val_base64,
}
response = requests.post(api_path, headers=headers, json=self.json_data)
# Check for HTTP errors
response.raise_for_status()
# Convert phone times to data format as input validation, save as class variable for further processing
@ -130,6 +150,19 @@ class APIHandler:
# Return result for processing by caller
return self.phone_times
def get_current_doctor_information_data_in_cache_with_time_check(self, amount_of_days):
cached_data = self._cache.get(str(self.json_data))
if cached_data:
cache_timestamp = cached_data["timestamp"]
current_date = datetime.now()
time_difference = current_date - cache_timestamp
if time_difference.days <= amount_of_days:
return cached_data["data"]
def set_current_doctor_information_data_in_cache(self):
current_date = datetime.now()
self._cache[str(self.json_data)] = {"timestamp": current_date, "data": self.phone_times}
def get_general_doctor_information(self) -> List[DoctorInformation]:
"""
Transform and filter data to more usable format: Check for phone times and collect general doctor information