theraPy/arztapi/APIHandler.py

205 lines
7.9 KiB
Python
Raw Normal View History

2024-08-26 21:05:34 +02:00
from typing import List
import requests
from requests import JSONDecodeError
import base64
from datetime import datetime
from arztapi.ArztPraxisDatas import ArztPraxisDatas
from arztapi.DoctorInformation import DoctorInformation, PhoneTime
from arztapi.DoctorPhoneTime import DoctorPhoneTime
class APIHandler:
def __init__(self):
self.base_api_url = "https://arztsuche.116117.de/api/"
self.phone_times = []
self.general_information = []
def get_lat_lon_location_list(self, location):
api_path = self.base_api_url + "location"
headers = {
"Accept": "application/json, text/plain, */*",
"Accept-Language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7",
"Authorization": "Basic YmRwczpma3I0OTNtdmdfZg==",
"Connection": "keep-alive",
}
params = {
"loc": location,
}
response = requests.get(api_path, params=params, headers=headers)
try:
return response.json()
except JSONDecodeError:
print("foo")
print(response.text)
def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age, therapy_setting) -> ArztPraxisDatas:
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": "Basic YmRwczpma3I0OTNtdmdfZg==",
"Connection": "keep-alive",
"req-val": req_val_base64,
}
json_data = {
# TODO: Find out what r means
"r": 900,
"lat": lat,
"lon": lon,
"filterSelections": [
{
"title": "Fachgebiet Kategorie",
"fieldName": "fgg",
"selectedCodes": [
"12",
],
},
{
"title": "Psychotherapie: Verfahren",
"fieldName": "ptv",
"selectedCodes": therapy_types,
},
{
"title": "Psychotherapie: Altersgruppe",
"fieldName": "pta",
"selectedCodes": [
therapy_age
],
},
{
"title": "Psychotherapie: Setting",
"fieldName": "pts",
"selectedCodes": [
therapy_setting
],
},
],
"locOrigin": "USER_INPUT",
"initialSearch": False,
"viaDeeplink": False,
}
response = requests.post(api_path, headers=headers, json=json_data)
response.raise_for_status()
self.phone_times = ArztPraxisDatas(**response.json())
return self.phone_times
def get_general_doctor_information(self) -> List[DoctorInformation]:
general_doctor_information = []
for data in self.phone_times.arztPraxisDatas:
doctor_day_times = data.tsz
phone_times = []
for day in doctor_day_times:
if day.tszDesTyps:
for contact_times in day.tszDesTyps:
if contact_times.typ == "Telefonische Erreichbarkeit":
phone_times_day = contact_times.sprechzeiten
for phone_time_day in phone_times_day:
start_time_str, end_time_str = phone_time_day.zeit.split("-")
start_date_time = self.parse_date_string(f"{day.d} {start_time_str}")
end_date_time = self.parse_date_string(f"{day.d} {end_time_str}")
current_phone_time_dict = {
"start": start_date_time,
"end": end_date_time
}
current_phone_time = PhoneTime(**current_phone_time_dict)
phone_times.append(current_phone_time)
doctor_information_dict = {
"name": data.name,
"tel": data.tel,
"fax": data.fax,
"anrede": data.anrede,
"email": data.email,
"distance": data.distance,
"strasse": data.strasse,
"hausnummer": data.hausnummer,
"plz": data.plz,
"ort": data.ort,
"telefonzeiten": phone_times
}
doctor_information = DoctorInformation(**doctor_information_dict)
general_doctor_information.append(doctor_information)
self.general_information = general_doctor_information
return self.general_information
2024-08-27 23:09:19 +02:00
def filter_doctor_information_for_distance(self, distance):
"""
:param distance: in meters
:return:
"""
self.general_information = [doctor_information for doctor_information in self.general_information
if doctor_information.distance <= distance]
2024-08-26 21:05:34 +02:00
def get_doctor_phone_times_sorted(self):
doctor_phone_times = []
for doctor_information in self.general_information:
for phone_time in doctor_information.telefonzeiten:
doctor_phone_time_dict = {
"phone_time": phone_time,
"doctor_name": doctor_information.name,
"doctor_address": f"{doctor_information.plz} {doctor_information.ort} "
f"{doctor_information.strasse} {doctor_information.hausnummer}",
"doctor_phone_number": doctor_information.tel
}
doctor_phone_time = DoctorPhoneTime(**doctor_phone_time_dict)
doctor_phone_times.append(doctor_phone_time)
return sorted(doctor_phone_times, key=lambda dpt: dpt.phone_time.start)
@staticmethod
def calculate_req_value_base64(lat, lon):
"""
This function is based on the initial Javascript code found in app.js.
It is rewritten in Python to calculate the HTTP header req_val for proper requests with the correct location.
:param lat:
:param lon:
:return:
"""
# Adjust lat and lon values slightly
adjusted_lat = lat + 1.1
adjusted_lon = lon + 2.3
# Get the current time in milliseconds since epoch
current_time = datetime.now()
timestamp_str = str(int(current_time.timestamp() * 1000)) # Convert to milliseconds
# Extract digits from latitude
lat_integer_part = str(adjusted_lat).split(".")[0]
lat_last_digit = lat_integer_part[-1]
lat_first_fraction_digit = str(adjusted_lat).split(".")[1][0] if len(str(adjusted_lat).split(".")) > 1 else "0"
# Extract digits from longitude
lon_integer_part = str(adjusted_lon).split(".")[0]
lon_last_digit = lon_integer_part[-1]
lon_first_fraction_digit = str(adjusted_lon).split(".")[1][0] if len(str(adjusted_lon).split(".")) > 1 else "0"
# Create the final string by combining digits
combined_string = (
lat_last_digit +
timestamp_str[-1] +
lon_last_digit +
timestamp_str[-2] +
lat_first_fraction_digit +
timestamp_str[-3] +
lon_first_fraction_digit
)
# Encode the combined string in Base64
encoded_value = base64.b64encode(combined_string.encode()).decode()
return encoded_value
@staticmethod
def parse_date_string(date_string):
format_string = "%d.%m. %H:%M"
# TODO: handle turn of year
parsed_date = datetime.strptime(date_string, format_string).replace(year=datetime.now().year)
return parsed_date