medicafe 0.250810.6__py3-none-any.whl → 0.250811.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- MediBot/MediBot.bat +1 -1
- MediBot/MediBot_Crosswalk_Utils.py +75 -30
- MediBot/MediBot_UI.py +35 -7
- MediCafe/MediLink_ConfigLoader.py +32 -15
- MediCafe/core_utils.py +157 -6
- MediLink/MediLink_Gmail.py +57 -308
- MediLink/gmail_http_utils.py +88 -0
- MediLink/gmail_oauth_utils.py +98 -0
- {medicafe-0.250810.6.dist-info → medicafe-0.250811.0.dist-info}/METADATA +1 -1
- {medicafe-0.250810.6.dist-info → medicafe-0.250811.0.dist-info}/RECORD +14 -12
- {medicafe-0.250810.6.dist-info → medicafe-0.250811.0.dist-info}/LICENSE +0 -0
- {medicafe-0.250810.6.dist-info → medicafe-0.250811.0.dist-info}/WHEEL +0 -0
- {medicafe-0.250810.6.dist-info → medicafe-0.250811.0.dist-info}/entry_points.txt +0 -0
- {medicafe-0.250810.6.dist-info → medicafe-0.250811.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
import json
|
2
|
+
import os
|
3
|
+
import ssl
|
4
|
+
import requests
|
5
|
+
from http.server import BaseHTTPRequestHandler, HTTPServer
|
6
|
+
|
7
|
+
|
8
|
+
def generate_self_signed_cert(openssl_cnf_path, cert_file, key_file, log, subprocess_module):
|
9
|
+
log("Checking if certificate file exists: " + cert_file)
|
10
|
+
log("Checking if key file exists: " + key_file)
|
11
|
+
|
12
|
+
cert_needs_regeneration = True
|
13
|
+
if os.path.exists(cert_file):
|
14
|
+
try:
|
15
|
+
check_cmd = ['openssl', 'x509', '-in', cert_file, '-checkend', '86400', '-noout']
|
16
|
+
result = subprocess_module.call(check_cmd)
|
17
|
+
if result == 0:
|
18
|
+
log("Certificate is still valid")
|
19
|
+
cert_needs_regeneration = False
|
20
|
+
else:
|
21
|
+
log("Certificate is expired or will expire soon")
|
22
|
+
try:
|
23
|
+
if os.path.exists(cert_file):
|
24
|
+
os.remove(cert_file)
|
25
|
+
log("Deleted expired certificate file: {}".format(cert_file))
|
26
|
+
if os.path.exists(key_file):
|
27
|
+
os.remove(key_file)
|
28
|
+
log("Deleted expired key file: {}".format(key_file))
|
29
|
+
except Exception as e:
|
30
|
+
log("Error deleting expired certificate files: {}".format(e))
|
31
|
+
except Exception as e:
|
32
|
+
log("Error checking certificate expiration: {}".format(e))
|
33
|
+
|
34
|
+
if cert_needs_regeneration:
|
35
|
+
log("Generating self-signed SSL certificate...")
|
36
|
+
cmd = [
|
37
|
+
'openssl', 'req', '-config', openssl_cnf_path, '-nodes', '-new', '-x509',
|
38
|
+
'-keyout', key_file,
|
39
|
+
'-out', cert_file,
|
40
|
+
'-days', '365',
|
41
|
+
'-sha256'
|
42
|
+
]
|
43
|
+
try:
|
44
|
+
log("Running command: " + ' '.join(cmd))
|
45
|
+
result = subprocess_module.call(cmd)
|
46
|
+
log("Command finished with result: " + str(result))
|
47
|
+
if result != 0:
|
48
|
+
raise RuntimeError("Failed to generate self-signed certificate")
|
49
|
+
verify_cmd = ['openssl', 'x509', '-in', cert_file, '-text', '-noout']
|
50
|
+
verify_result = subprocess_module.call(verify_cmd)
|
51
|
+
if verify_result != 0:
|
52
|
+
raise RuntimeError("Generated certificate verification failed")
|
53
|
+
log("Self-signed SSL certificate generated and verified successfully.")
|
54
|
+
except Exception as e:
|
55
|
+
log("Error generating self-signed certificate: {}".format(e))
|
56
|
+
raise
|
57
|
+
|
58
|
+
|
59
|
+
def start_https_server(port, handler_cls, cert_file, key_file, log):
|
60
|
+
server_address = ('0.0.0.0', port)
|
61
|
+
httpd = HTTPServer(server_address, handler_cls)
|
62
|
+
log("Attempting to wrap socket with SSL. cert_file=" + cert_file + ", key_file=" + key_file)
|
63
|
+
httpd.socket = ssl.wrap_socket(httpd.socket, certfile=cert_file, keyfile=key_file, server_side=True)
|
64
|
+
log("Starting HTTPS server on port {}".format(port))
|
65
|
+
httpd.serve_forever()
|
66
|
+
return httpd
|
67
|
+
|
68
|
+
|
69
|
+
def inspect_token(access_token, log, delete_token_file_fn=None, stop_server_fn=None):
|
70
|
+
info_url = "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token={}".format(access_token)
|
71
|
+
try:
|
72
|
+
response = requests.get(info_url)
|
73
|
+
log("Token info: Status code {}, Body: {}".format(response.status_code, response.text))
|
74
|
+
if response.status_code == 200:
|
75
|
+
return response.json()
|
76
|
+
else:
|
77
|
+
log("Failed to inspect token. Status code: {}, Body: {}".format(response.status_code, response.text))
|
78
|
+
if response.status_code == 400 and "invalid_token" in response.text:
|
79
|
+
log("Access token is invalid. Deleting token.json and stopping the server.")
|
80
|
+
if delete_token_file_fn:
|
81
|
+
delete_token_file_fn()
|
82
|
+
if stop_server_fn:
|
83
|
+
stop_server_fn()
|
84
|
+
return None
|
85
|
+
return None
|
86
|
+
except Exception as e:
|
87
|
+
log("Exception during token inspection: {}".format(e))
|
88
|
+
return None
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import json
|
2
|
+
import os
|
3
|
+
import time
|
4
|
+
import requests
|
5
|
+
|
6
|
+
|
7
|
+
def get_authorization_url(credentials_path, redirect_uri, scopes, log):
|
8
|
+
"""
|
9
|
+
Build the Google OAuth authorization URL using the provided credentials file, redirect URI, and scopes.
|
10
|
+
"""
|
11
|
+
with open(credentials_path, 'r') as credentials_file:
|
12
|
+
credentials = json.load(credentials_file)
|
13
|
+
client_id = credentials['web']['client_id']
|
14
|
+
auth_url = (
|
15
|
+
"https://accounts.google.com/o/oauth2/v2/auth?"
|
16
|
+
"response_type=code&"
|
17
|
+
"client_id={}&"
|
18
|
+
"redirect_uri={}&"
|
19
|
+
"scope={}&"
|
20
|
+
"access_type=offline&"
|
21
|
+
"prompt=consent"
|
22
|
+
).format(client_id, redirect_uri, scopes)
|
23
|
+
log("Generated authorization URL: {}".format(auth_url))
|
24
|
+
return auth_url
|
25
|
+
|
26
|
+
|
27
|
+
def exchange_code_for_token(auth_code, credentials_path, redirect_uri, log, retries=3):
|
28
|
+
"""
|
29
|
+
Exchange an authorization code for tokens using credentials; retries a few times on failure.
|
30
|
+
"""
|
31
|
+
for attempt in range(retries):
|
32
|
+
try:
|
33
|
+
with open(credentials_path, 'r') as credentials_file:
|
34
|
+
credentials = json.load(credentials_file)
|
35
|
+
token_url = "https://oauth2.googleapis.com/token"
|
36
|
+
data = {
|
37
|
+
'code': auth_code,
|
38
|
+
'client_id': credentials['web']['client_id'],
|
39
|
+
'client_secret': credentials['web']['client_secret'],
|
40
|
+
'redirect_uri': redirect_uri,
|
41
|
+
'grant_type': 'authorization_code'
|
42
|
+
}
|
43
|
+
response = requests.post(token_url, data=data)
|
44
|
+
log("Token exchange response: Status code {}, Body: {}".format(response.status_code, response.text))
|
45
|
+
token_response = response.json()
|
46
|
+
if response.status_code == 200:
|
47
|
+
token_response['token_time'] = time.time()
|
48
|
+
return token_response
|
49
|
+
else:
|
50
|
+
log("Token exchange failed: {}".format(token_response))
|
51
|
+
if attempt < retries - 1:
|
52
|
+
log("Retrying token exchange... (Attempt {}/{})".format(attempt + 1, retries))
|
53
|
+
except Exception as e:
|
54
|
+
log("Error during token exchange: {}".format(e))
|
55
|
+
return {}
|
56
|
+
|
57
|
+
|
58
|
+
def refresh_access_token(refresh_token, credentials_path, log):
|
59
|
+
"""
|
60
|
+
Refresh an access token using the stored client credentials.
|
61
|
+
"""
|
62
|
+
log("Refreshing access token.")
|
63
|
+
with open(credentials_path, 'r') as credentials_file:
|
64
|
+
credentials = json.load(credentials_file)
|
65
|
+
token_url = "https://oauth2.googleapis.com/token"
|
66
|
+
data = {
|
67
|
+
'client_id': credentials['web']['client_id'],
|
68
|
+
'client_secret': credentials['web']['client_secret'],
|
69
|
+
'refresh_token': refresh_token,
|
70
|
+
'grant_type': 'refresh_token'
|
71
|
+
}
|
72
|
+
response = requests.post(token_url, data=data)
|
73
|
+
log("Refresh token response: Status code {}, Body:\n {}".format(response.status_code, response.text))
|
74
|
+
if response.status_code == 200:
|
75
|
+
log("Access token refreshed successfully.")
|
76
|
+
return response.json()
|
77
|
+
else:
|
78
|
+
log("Failed to refresh access token. Status code: {}".format(response.status_code))
|
79
|
+
return {}
|
80
|
+
|
81
|
+
|
82
|
+
def is_valid_authorization_code(auth_code, log):
|
83
|
+
"""
|
84
|
+
Validate auth code shape without side effects.
|
85
|
+
"""
|
86
|
+
if auth_code and isinstance(auth_code, str) and len(auth_code) > 0:
|
87
|
+
return True
|
88
|
+
log("Invalid authorization code format: {}".format(auth_code))
|
89
|
+
return False
|
90
|
+
|
91
|
+
|
92
|
+
def clear_token_cache(token_path, log):
|
93
|
+
"""
|
94
|
+
Delete token cache file if present.
|
95
|
+
"""
|
96
|
+
if os.path.exists(token_path):
|
97
|
+
os.remove(token_path)
|
98
|
+
log("Cleared token cache.")
|
@@ -1,12 +1,12 @@
|
|
1
|
-
MediBot/MediBot.bat,sha256=
|
1
|
+
MediBot/MediBot.bat,sha256=GUmRX7D02jkR0Jiqckj4jE-P0fzJsgEe9KXKPigHEwU,25282
|
2
2
|
MediBot/MediBot.py,sha256=G3QuSgyEizas4plYez1n-u8xigbbtYEgl1x6ZSTWsAw,34306
|
3
3
|
MediBot/MediBot_Charges.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
MediBot/MediBot_Crosswalk_Library.py,sha256=HZHbjKHhjLW2jERmLS6pEZOl-MUxUu1YwA6oUltfdkE,24693
|
5
|
-
MediBot/MediBot_Crosswalk_Utils.py,sha256=
|
5
|
+
MediBot/MediBot_Crosswalk_Utils.py,sha256=HQXZUWDZF_LvOMLsdjlsDQ79Yi_IiqNVRKX2Cd0A6x8,38762
|
6
6
|
MediBot/MediBot_Post.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
MediBot/MediBot_Preprocessor.py,sha256=zAcfyuE8wl9JRzLGsUnnXiHxAr-hbCCIB2M-Jb3LUqI,16203
|
8
8
|
MediBot/MediBot_Preprocessor_lib.py,sha256=L5VkBoSWuvvKNs0YoHz_-KQ5Z2hnqLJyM_j7yeKb9CM,72423
|
9
|
-
MediBot/MediBot_UI.py,sha256=
|
9
|
+
MediBot/MediBot_UI.py,sha256=YgNr_E8ahf7Y-Emkq04PavJH37LShs83wVxp9i6EVgw,14191
|
10
10
|
MediBot/MediBot_dataformat_library.py,sha256=XCkwhpkDbhiSDQ_21xPafqJzZLoq-C0dczoN2Xl5tHE,10260
|
11
11
|
MediBot/MediBot_docx_decoder.py,sha256=gn7I7Ng5khVIzU0HTTOqi31YSSn1yW8Pyk-i_P9r1oA,32472
|
12
12
|
MediBot/MediBot_smart_import.py,sha256=_ggP0I9djNwMGck04U6fNahrH7frVkoM8OzjtHbLUc0,6727
|
@@ -16,14 +16,14 @@ MediBot/__init__.py,sha256=6IdVLXaWxV5ZdpefonWrC1R8RsJn4V26K0PmUEZ_vU8,3192
|
|
16
16
|
MediBot/get_medicafe_version.py,sha256=uyL_UIE42MyFuJ3SRYxJp8sZx8xjTqlYZ3FdQuxLduY,728
|
17
17
|
MediBot/update_json.py,sha256=vvUF4mKCuaVly8MmoadDO59M231fCIInc0KI1EtDtPA,3704
|
18
18
|
MediBot/update_medicafe.py,sha256=i2-6b2y9XXaroPG8uP_RPFwOOsQSY_dTiuhl6vG8uoo,25693
|
19
|
-
MediCafe/MediLink_ConfigLoader.py,sha256=
|
19
|
+
MediCafe/MediLink_ConfigLoader.py,sha256=Ia79dZQBvgbc6CtOaNZVlFHaN-fvUmJRpmmVHz_MFv8,8205
|
20
20
|
MediCafe/__init__.py,sha256=DF0XUu3G43AejXvEmd5aCyy0GDQahQD0pMwexmxem-E,5477
|
21
21
|
MediCafe/__main__.py,sha256=mRNyk3D9Ilnu2XhgVI_rut7r5Ro7UIKtwV871giAHI8,12992
|
22
22
|
MediCafe/api_core.py,sha256=AwnB2BMiBOMS_LKJlkHgd_lQPpE57WEYMfS-O-DeOzo,63851
|
23
23
|
MediCafe/api_core_backup.py,sha256=Oy_Fqt0SEvGkQN1Oqw5iUPVFxPEokyju5CuPEb9k0OY,18686
|
24
24
|
MediCafe/api_factory.py,sha256=I5AeJoyu6m7oCrjc2OvVvO_4KSBRutTsR1riiWhTZV0,12086
|
25
25
|
MediCafe/api_utils.py,sha256=KWQB0q1k5E6frOFFlKWcFpHNcqfrS7KJ_82672wbupw,14041
|
26
|
-
MediCafe/core_utils.py,sha256=
|
26
|
+
MediCafe/core_utils.py,sha256=yftnn2pMhfUMEHfGl9ocvLoI8kQvsDjqrRZAR3uHdWo,26317
|
27
27
|
MediCafe/graphql_utils.py,sha256=5i_pNCNRUXox2v5zraPzUw4n7rUt9ZEAkLqVa59LWAc,45713
|
28
28
|
MediCafe/logging_config.py,sha256=auT65LN5oDEXVhkMeLke63kJHTWxYf2o8YihAfQFgzU,5493
|
29
29
|
MediCafe/logging_demo.py,sha256=TwUhzafna5pMdN3zSKGrpUWRqX96F1JGGsSUtr3dygs,1975
|
@@ -49,7 +49,7 @@ MediLink/MediLink_Deductible_Validator.py,sha256=2g-lZd-Y5fJ1mfP87vM6oABg0t5Om-7
|
|
49
49
|
MediLink/MediLink_Display_Utils.py,sha256=Bl15Ofqh09KIYsNXzM6WIE97Gp_4RVUw43J0NUzIERY,3121
|
50
50
|
MediLink/MediLink_Down.py,sha256=vZEFNWa6drpXK8DCzt3DAlHdPGdhv3HoLnQh9cppT8o,11793
|
51
51
|
MediLink/MediLink_ERA_decoder.py,sha256=MiOtDcXnmevPfHAahIlTLlUc14VcQWAor9Xa7clA2Ts,8710
|
52
|
-
MediLink/MediLink_Gmail.py,sha256=
|
52
|
+
MediLink/MediLink_Gmail.py,sha256=C6tjw4Pd1wVHbCs97cvn4GCWIvwLT2Epc5ls0OoJ3Tg,23890
|
53
53
|
MediLink/MediLink_GraphQL.py,sha256=O6OCaumT0zIC7YcIAwLOOYxiQnYhoMc48UL8ilNIBec,45720
|
54
54
|
MediLink/MediLink_Mailer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
55
|
MediLink/MediLink_Parser.py,sha256=w2ZD4minjwkaMz7nzP_r8v_Ow_uM5KHjpPSY8mIHcdE,9787
|
@@ -66,6 +66,8 @@ MediLink/MediLink_main.py,sha256=rvKHuZUus8RvMC5-flws2q-EvXETXiJmgU2USjzMu3g,134
|
|
66
66
|
MediLink/MediLink_smart_import.py,sha256=B5SfBn_4bYEWJJDolXbjnwKx_-MaqGZ76LyXQwWDV80,9838
|
67
67
|
MediLink/Soumit_api.py,sha256=5JfOecK98ZC6NpZklZW2AkOzkjvrbYxpJpZNH3rFxDw,497
|
68
68
|
MediLink/__init__.py,sha256=Z4Uxt4XZk4n-GwAkUoEeFiL-D7xHbttYiiWGjgKT_ng,3391
|
69
|
+
MediLink/gmail_http_utils.py,sha256=gtqCCrzJC7e8JFQzMNrf7EbK8na2h4sfTu-NMaZ_UHc,4006
|
70
|
+
MediLink/gmail_oauth_utils.py,sha256=MLuzO6awBanV7Ee2gOUrkWrxz8-Htwz2BEIFjLw9Izs,3734
|
69
71
|
MediLink/insurance_type_integration_test.py,sha256=pz2OCXitAznqDciYn6OL9M326m9CYU7YiK-ynssdQ5g,15172
|
70
72
|
MediLink/openssl.cnf,sha256=76VdcGCykf0Typyiv8Wd1mMVKixrQ5RraG6HnfKFqTo,887
|
71
73
|
MediLink/test.py,sha256=DM_E8gEbhbVfTAm3wTMiNnK2GCD1e5eH6gwTk89QIc4,3116
|
@@ -73,9 +75,9 @@ MediLink/test_cob_library.py,sha256=wUMv0-Y6fNsKcAs8Z9LwfmEBRO7oBzBAfWmmzwoNd1g,
|
|
73
75
|
MediLink/test_timing.py,sha256=yH2b8QPLDlp1Zy5AhgtjzjnDHNGhAD16ZtXtZzzESZw,2042
|
74
76
|
MediLink/test_validation.py,sha256=FJrfdUFK--xRScIzrHCg1JeGdm0uJEoRnq6CgkP2lwM,4154
|
75
77
|
MediLink/webapp.html,sha256=JPKT559aFVBi1r42Hz7C77Jj0teZZRumPhBev8eSOLk,19806
|
76
|
-
medicafe-0.
|
77
|
-
medicafe-0.
|
78
|
-
medicafe-0.
|
79
|
-
medicafe-0.
|
80
|
-
medicafe-0.
|
81
|
-
medicafe-0.
|
78
|
+
medicafe-0.250811.0.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
|
79
|
+
medicafe-0.250811.0.dist-info/METADATA,sha256=tnhM2Rn4jbS9mJ7VGw4ncPYfdb-Do_izp0kzOImKs0c,5501
|
80
|
+
medicafe-0.250811.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
81
|
+
medicafe-0.250811.0.dist-info/entry_points.txt,sha256=m3RBUBjr-xRwEkKJ5W4a7NlqHZP_1rllGtjZnrRqKe8,52
|
82
|
+
medicafe-0.250811.0.dist-info/top_level.txt,sha256=U6-WBJ9RCEjyIs0BlzbQq_PwedCp_IV9n1616NNV5zA,26
|
83
|
+
medicafe-0.250811.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|