-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwellsky_get_patient_info.py
More file actions
152 lines (126 loc) · 5.25 KB
/
Copy pathwellsky_get_patient_info.py
File metadata and controls
152 lines (126 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from curl_cffi import requests
import re
import json
import os
import time
from urllib.parse import unquote
def run(headers, user_input):
"""Get detailed patient information for a given patient ID and episode ID."""
patient_id = user_input.get("patient_id")
episode_id = user_input.get("episode_id")
if not patient_id:
return {'status_code': 400, 'body': {'error': 'patient_id is required'}}
if not episode_id:
return {'status_code': 400, 'body': {'error': 'episode_id is required'}}
# Extract EHRTOKEN and sessionCacheKey from cookies
cookie_header = headers.get("Cookie", "")
ehr_token = ""
token_match = re.search(r'EHRTOKEN=([^;]+)', cookie_header)
if token_match:
ehr_token = unquote(token_match.group(1))
session_cache_key = ""
sck_match = re.search(r'sessionCacheKey=([^;]+)', cookie_header)
if sck_match:
session_cache_key = sck_match.group(1)
if not session_cache_key:
return {'status_code': 401, 'body': {'error': 'Session expired - no sessionCacheKey in cookies'}}
if not ehr_token:
return {'status_code': 401, 'body': {'error': 'Session expired - no EHRTOKEN in cookies'}}
try:
data = _call_api(patient_id, episode_id, cookie_header, ehr_token, session_cache_key)
except AuthError as e:
return {'status_code': 401, 'body': {'error': str(e)}}
except ApiError as e:
return {'status_code': e.status_code, 'body': {'error': str(e)}}
except Exception as e:
return {'status_code': 500, 'body': {'error': str(e)}}
# Return structured patient info
result = {
"first_name": data.get("FirstName", ""),
"last_name": data.get("LastName", ""),
"medical_record_number": data.get("MedicalRecordNumber", ""),
"dob": data.get("DOB", ""),
"address": data.get("Address", ""),
"address_line2": data.get("AddressLine2", ""),
"patient_phone": data.get("PatientPhone", ""),
"email_address": data.get("EmailAddress", ""),
"physician": data.get("Physician", ""),
"physician_phone": data.get("PhysicianPhone", ""),
"physician_fax": data.get("PhysicianFax", ""),
"insurance": data.get("Insurance", ""),
"pharmacy_name": data.get("PharmacyName", ""),
"pharmacy_phone": data.get("PharmacyPhone", ""),
"branch": data.get("Branch", ""),
"soc_date": data.get("SOCDate", ""),
"frequency": data.get("Frequency", "").strip(),
"referral_source": data.get("ReferralSource", "").strip(),
}
return {'status_code': 200, 'body': result}
# === PRIVATE ===
class AuthError(Exception):
pass
class ApiError(Exception):
def __init__(self, message, status_code=500):
super().__init__(message)
self.status_code = status_code
def _call_api(patient_id, episode_id, cookie_header, ehr_token, session_cache_key):
"""Fetch patient info from the EHR API."""
base_url = BASE_URL
params = {
"sessionCacheKey": session_cache_key,
"method": "getPatientInfoClick",
"patientKey": patient_id,
"episodeKey": episode_id,
"masterKey": patient_id,
"_": str(int(time.time() * 1000)),
}
api_headers = {
"Cookie": cookie_header,
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "en-US,en;q=0.9",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "kinnser.net",
"Origin": base_url,
"Pragma": "no-cache",
"Referer": f"{base_url}/AM/Patient/EditEpisode.cfm?sessionCacheKey={session_cache_key}&Episodekey={episode_id}",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"X-Requested-With": "XMLHttpRequest",
"token": ehr_token,
}
# Use proxy if available in environment
proxy = os.environ.get("PROXY_URL") or os.environ.get("HTTP_PROXY") or os.environ.get("HTTPS_PROXY")
proxy_kwargs = {"proxy": proxy} if proxy else {}
response = requests.get(
f"{base_url}/AM/Patient/EpisodeManagerProxy.cfc",
params=params,
headers=api_headers,
impersonate="chrome110",
timeout=30,
**proxy_kwargs,
)
# Check for auth failure
if response.status_code == 401:
raise AuthError('Session expired')
if response.status_code == 403:
raise AuthError('Access blocked - session may need refresh')
if response.status_code == 302 or "logout.cfm" in response.url:
raise AuthError('Session expired')
if response.status_code != 200:
raise ApiError(f'API returned status {response.status_code}', response.status_code)
# Strip the // JSON security prefix
body_text = response.text
if body_text.startswith("//"):
body_text = body_text[2:]
try:
data = json.loads(body_text)
except json.JSONDecodeError:
# If we get HTML back (login page), treat as auth failure
if "<html" in response.text.lower() or "login" in response.text.lower():
raise AuthError('Session expired')
raise ApiError('Failed to parse response JSON')
return data