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.
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250810.6
3
+ Version: 0.250811.0
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2
6
6
  Author: Daniel Vidaud
@@ -1,12 +1,12 @@
1
- MediBot/MediBot.bat,sha256=kWhQVJPIJ51w6pPsf9tQlw2mCoZU6VysiI9R-k4xmfk,25281
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=Qf3O9Wh1cbfGbYqObK5rVh99qRCboWnmVUpubEZeN3A,35763
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=26Dx_KlNuVEwBLwmQ-uJ2fvOAbwiIYruX3-iXMtPKFc,13419
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=_tB8FlJSNsRDHKL2X7XMmtLcxhCeXtiaddV-jOQWHi4,7723
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=IS6hhmMR02vmjdOLFak99mK0bA3w6qBEtm66CDLTz-Q,20686
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=SCaauKBSsBXBljfwqSxIfXEXd74nYTEBo20I9ZNJksI,36926
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.250810.6.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
77
- medicafe-0.250810.6.dist-info/METADATA,sha256=XznXEduQaqqFfkpxn116G1icQgQtCNDeXgk8Pn5cbwM,5501
78
- medicafe-0.250810.6.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
79
- medicafe-0.250810.6.dist-info/entry_points.txt,sha256=m3RBUBjr-xRwEkKJ5W4a7NlqHZP_1rllGtjZnrRqKe8,52
80
- medicafe-0.250810.6.dist-info/top_level.txt,sha256=U6-WBJ9RCEjyIs0BlzbQq_PwedCp_IV9n1616NNV5zA,26
81
- medicafe-0.250810.6.dist-info/RECORD,,
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,,