medicafe 0.250529.2__tar.gz → 0.250610.1__tar.gz
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.
Potentially problematic release.
This version of medicafe might be problematic. Click here for more details.
- medicafe-0.250610.1/MANIFEST.in +4 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Gmail.py +50 -4
- medicafe-0.250610.1/MediLink/openssl.cnf +29 -0
- medicafe-0.250610.1/MediLink/webapp.html +473 -0
- {medicafe-0.250529.2/medicafe.egg-info → medicafe-0.250610.1}/PKG-INFO +1 -1
- {medicafe-0.250529.2 → medicafe-0.250610.1/medicafe.egg-info}/PKG-INFO +1 -1
- {medicafe-0.250529.2 → medicafe-0.250610.1}/medicafe.egg-info/SOURCES.txt +2 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/setup.py +2 -2
- medicafe-0.250529.2/MANIFEST.in +0 -2
- {medicafe-0.250529.2 → medicafe-0.250610.1}/LICENSE +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot.bat +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_Charges.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_Crosswalk_Library.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_Post.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_Preprocessor.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_Preprocessor_lib.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_UI.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_dataformat_library.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/MediBot_docx_decoder.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/PDF_to_CSV_Cleaner.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/__init__.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/update_json.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediBot/update_medicafe.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_837p_encoder.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_837p_encoder_library.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_API_Generator.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_API_v2.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_API_v3.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_APIs.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Azure.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_ClaimStatus.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_ConfigLoader.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_DataMgmt.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Decoder.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Deductible.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Down.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Mailer.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Parser.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Scan.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Scheduler.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_UI.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_Up.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/MediLink_batch.bat +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/Soumit_api.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/__init__.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/MediLink/test.py +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/README.md +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/medicafe.egg-info/dependency_links.txt +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/medicafe.egg-info/not-zip-safe +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/medicafe.egg-info/requires.txt +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/medicafe.egg-info/top_level.txt +0 -0
- {medicafe-0.250529.2 → medicafe-0.250610.1}/setup.cfg +0 -0
|
@@ -13,7 +13,19 @@ downloaded_emails_file = os.path.join(local_storage_path, 'downloaded_emails.txt
|
|
|
13
13
|
server_port = 8000
|
|
14
14
|
cert_file = 'server.cert'
|
|
15
15
|
key_file = 'server.key'
|
|
16
|
-
|
|
16
|
+
# Try to find openssl.cnf in various locations
|
|
17
|
+
openssl_cnf = 'MediLink\\openssl.cnf'
|
|
18
|
+
if not os.path.exists(openssl_cnf):
|
|
19
|
+
log("Could not find openssl.cnf at: " + os.path.abspath(openssl_cnf))
|
|
20
|
+
# Try one directory up
|
|
21
|
+
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
22
|
+
alternative_path = os.path.join(parent_dir, 'MediBot', 'openssl.cnf')
|
|
23
|
+
log("Trying alternative path: " + alternative_path)
|
|
24
|
+
if os.path.exists(alternative_path):
|
|
25
|
+
openssl_cnf = alternative_path
|
|
26
|
+
log("Found openssl.cnf at: " + openssl_cnf)
|
|
27
|
+
else:
|
|
28
|
+
log("Could not find openssl.cnf at alternative path either")
|
|
17
29
|
|
|
18
30
|
httpd = None # Global variable for the HTTP server
|
|
19
31
|
shutdown_event = Event() # Event to signal shutdown
|
|
@@ -321,13 +333,40 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|
|
321
333
|
def generate_self_signed_cert(cert_file, key_file):
|
|
322
334
|
log("Checking if certificate file exists: " + cert_file)
|
|
323
335
|
log("Checking if key file exists: " + key_file)
|
|
324
|
-
|
|
336
|
+
|
|
337
|
+
# Check if certificate exists and is not expired
|
|
338
|
+
cert_needs_regeneration = True
|
|
339
|
+
if os.path.exists(cert_file):
|
|
340
|
+
try:
|
|
341
|
+
# Check certificate expiration
|
|
342
|
+
check_cmd = ['openssl', 'x509', '-in', cert_file, '-checkend', '86400', '-noout'] # Check if expires in next 24 hours
|
|
343
|
+
result = subprocess.call(check_cmd)
|
|
344
|
+
if result == 0:
|
|
345
|
+
log("Certificate is still valid")
|
|
346
|
+
cert_needs_regeneration = False
|
|
347
|
+
else:
|
|
348
|
+
log("Certificate is expired or will expire soon")
|
|
349
|
+
# Delete expired certificate and key files
|
|
350
|
+
try:
|
|
351
|
+
if os.path.exists(cert_file):
|
|
352
|
+
os.remove(cert_file)
|
|
353
|
+
log("Deleted expired certificate file: {}".format(cert_file))
|
|
354
|
+
if os.path.exists(key_file):
|
|
355
|
+
os.remove(key_file)
|
|
356
|
+
log("Deleted expired key file: {}".format(key_file))
|
|
357
|
+
except Exception as e:
|
|
358
|
+
log("Error deleting expired certificate files: {}".format(e))
|
|
359
|
+
except Exception as e:
|
|
360
|
+
log("Error checking certificate expiration: {}".format(e))
|
|
361
|
+
|
|
362
|
+
if cert_needs_regeneration:
|
|
325
363
|
log("Generating self-signed SSL certificate...")
|
|
326
364
|
cmd = [
|
|
327
365
|
'openssl', 'req', '-config', openssl_cnf, '-nodes', '-new', '-x509',
|
|
328
366
|
'-keyout', key_file,
|
|
329
367
|
'-out', cert_file,
|
|
330
|
-
'-days', '365'
|
|
368
|
+
'-days', '365',
|
|
369
|
+
'-sha256' # Use SHA-256 for better security
|
|
331
370
|
#'-subj', '/C=US/ST=...' The openssl.cnf file contains default values for these fields, but they can be overridden by the -subj option.
|
|
332
371
|
]
|
|
333
372
|
try:
|
|
@@ -336,7 +375,14 @@ def generate_self_signed_cert(cert_file, key_file):
|
|
|
336
375
|
log("Command finished with result: " + str(result))
|
|
337
376
|
if result != 0:
|
|
338
377
|
raise RuntimeError("Failed to generate self-signed certificate")
|
|
339
|
-
|
|
378
|
+
|
|
379
|
+
# Verify the certificate was generated correctly
|
|
380
|
+
verify_cmd = ['openssl', 'x509', '-in', cert_file, '-text', '-noout']
|
|
381
|
+
verify_result = subprocess.call(verify_cmd)
|
|
382
|
+
if verify_result != 0:
|
|
383
|
+
raise RuntimeError("Generated certificate verification failed")
|
|
384
|
+
|
|
385
|
+
log("Self-signed SSL certificate generated and verified successfully.")
|
|
340
386
|
except Exception as e:
|
|
341
387
|
log("Error generating self-signed certificate: {}".format(e))
|
|
342
388
|
raise
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# OpenSSL configuration file for creating a self-signed certificate
|
|
2
|
+
|
|
3
|
+
[ req ]
|
|
4
|
+
default_bits = 2048
|
|
5
|
+
default_keyfile = server.key
|
|
6
|
+
distinguished_name = req_distinguished_name
|
|
7
|
+
x509_extensions = v3_req
|
|
8
|
+
string_mask = utf8only
|
|
9
|
+
prompt = no
|
|
10
|
+
|
|
11
|
+
[ req_distinguished_name ]
|
|
12
|
+
countryName = US
|
|
13
|
+
stateOrProvinceName = California
|
|
14
|
+
localityName = San Francisco
|
|
15
|
+
organizationName = MediLink
|
|
16
|
+
organizationalUnitName = Development
|
|
17
|
+
commonName = localhost
|
|
18
|
+
emailAddress = admin@medilink.local
|
|
19
|
+
|
|
20
|
+
[ v3_req ]
|
|
21
|
+
basicConstraints = CA:FALSE
|
|
22
|
+
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
|
23
|
+
subjectAltName = @alt_names
|
|
24
|
+
extendedKeyUsage = serverAuth, clientAuth
|
|
25
|
+
|
|
26
|
+
[ alt_names ]
|
|
27
|
+
DNS.1 = localhost
|
|
28
|
+
IP.1 = 127.0.0.1
|
|
29
|
+
DNS.2 = 127.0.0.1
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Select an Email</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Montserrat:wght@400;600&display=swap" rel="stylesheet">
|
|
8
|
+
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.12.1/polyfill.min.js"></script> -->
|
|
9
|
+
<style>
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
--espresso-dark: #3B2323; /* Darkened color */
|
|
13
|
+
--espresso-medium: #4E3B3B; /* Adjusted for a more coffee-like tone */
|
|
14
|
+
--espresso-light: #7A4B4B; /* Darkened color */
|
|
15
|
+
--cream: #EDE0D4; /* Darkened color */
|
|
16
|
+
--background: #dcd6c9; /* Darkened color */
|
|
17
|
+
--accent: #C65D1E; /* Darkened color */
|
|
18
|
+
--error-red: #D9534F;
|
|
19
|
+
--loading-orange: #F0AD4E;
|
|
20
|
+
--text-color: #222222; /* Darkened color */
|
|
21
|
+
--button-hover: #4B2E2E; /* Darkened color */
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
* {
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
body {
|
|
29
|
+
font-family: 'Montserrat', sans-serif;
|
|
30
|
+
margin: 0;
|
|
31
|
+
padding: 0;
|
|
32
|
+
background-color: var(--background);
|
|
33
|
+
color: var(--text-color);
|
|
34
|
+
display: flex;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
align-items: center;
|
|
37
|
+
min-height: 100vh;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main {
|
|
41
|
+
width: 90%;
|
|
42
|
+
max-width: 800px; /* Reduced max-width */
|
|
43
|
+
margin: 20px auto; /* Reduced margin */
|
|
44
|
+
padding: 20px; /* Reduced padding */
|
|
45
|
+
background: var(--cream);
|
|
46
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Reduced shadow */
|
|
47
|
+
border-radius: 8px; /* Reduced border-radius */
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
gap: 20px; /* Reduced gap */
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
h1 {
|
|
54
|
+
text-align: center;
|
|
55
|
+
font-family: 'Roboto', sans-serif;
|
|
56
|
+
font-weight: 600; /* Reduced font weight */
|
|
57
|
+
color: var(--espresso-dark);
|
|
58
|
+
margin-bottom: 15px; /* Reduced margin */
|
|
59
|
+
font-size: 1.8em; /* Reduced font size */
|
|
60
|
+
position: relative;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
h1::after {
|
|
64
|
+
content: '';
|
|
65
|
+
display: block;
|
|
66
|
+
width: 50px; /* Reduced width */
|
|
67
|
+
height: 3px; /* Reduced height */
|
|
68
|
+
background-color: var(--espresso-medium);
|
|
69
|
+
margin: 8px auto 0; /* Reduced margin */
|
|
70
|
+
border-radius: 2px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
ul {
|
|
74
|
+
list-style-type: none;
|
|
75
|
+
padding: 0;
|
|
76
|
+
margin: 0;
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
gap: 10px; /* Reduced gap */
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
li {
|
|
83
|
+
background-color: var(--espresso-light);
|
|
84
|
+
padding: 8px; /* Reduced padding */
|
|
85
|
+
border-radius: 6px; /* Reduced border-radius */
|
|
86
|
+
font-size: 1.1em; /* Reduced font size */
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* New styling for docxEmailList */
|
|
90
|
+
#docxEmailList li {
|
|
91
|
+
background-color: transparent; /* Plain background */
|
|
92
|
+
padding: 8px; /* Keep padding */
|
|
93
|
+
border: none; /* No border */
|
|
94
|
+
box-shadow: none; /* No shadow */
|
|
95
|
+
transition: none; /* No transition */
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
button {
|
|
99
|
+
width: 100%;
|
|
100
|
+
padding: 4px 8px; /* Reduced padding */
|
|
101
|
+
background-color: var(--espresso-medium);
|
|
102
|
+
color: #ffffff;
|
|
103
|
+
border: none;
|
|
104
|
+
border-radius: 6px; /* Reduced border-radius */
|
|
105
|
+
cursor: pointer;
|
|
106
|
+
font-size: 1.1em; /* Reduced font size */
|
|
107
|
+
font-weight: 500; /* Reduced font weight */
|
|
108
|
+
transition: background-color 0.3s, transform 0.2s;
|
|
109
|
+
display: flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: center;
|
|
112
|
+
margin-bottom: 8px; /* Reduced margin */
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
button:hover {
|
|
116
|
+
background-color: var(--espresso-dark);
|
|
117
|
+
transform: scale(1.01); /* Reduced scale effect */
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.error-message {
|
|
121
|
+
color: var(--error-red);
|
|
122
|
+
text-align: center;
|
|
123
|
+
font-weight: bold;
|
|
124
|
+
margin-top: 15px; /* Reduced margin */
|
|
125
|
+
padding: 8px; /* Reduced padding */
|
|
126
|
+
border: 1px solid var(--error-red);
|
|
127
|
+
border-radius: 6px;
|
|
128
|
+
background-color: #fdecea;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.loading-message {
|
|
132
|
+
color: var(--loading-orange);
|
|
133
|
+
text-align: center;
|
|
134
|
+
font-weight: bold;
|
|
135
|
+
margin-top: 15px; /* Reduced margin */
|
|
136
|
+
padding: 8px; /* Reduced padding */
|
|
137
|
+
border: 1px solid var(--loading-orange);
|
|
138
|
+
border-radius: 6px;
|
|
139
|
+
background-color: #fff4e6;
|
|
140
|
+
display: flex;
|
|
141
|
+
align-items: center;
|
|
142
|
+
justify-content: center;
|
|
143
|
+
gap: 8px; /* Reduced gap */
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Responsive Design */
|
|
147
|
+
@media (max-width: 600px) {
|
|
148
|
+
main {
|
|
149
|
+
padding: 15px; /* Reduced padding */
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
h1 {
|
|
153
|
+
font-size: 1.1em; /* Reduced font size */
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
button {
|
|
157
|
+
font-size: 1em; /* Reduced font size */
|
|
158
|
+
padding: 4px 6px; /* Reduced padding */
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
</style>
|
|
162
|
+
</head>
|
|
163
|
+
<body>
|
|
164
|
+
<main>
|
|
165
|
+
<!-- <h1>Please Select the Correct Email</h1> -->
|
|
166
|
+
<!-- <ul id="emailList"></ul> -->
|
|
167
|
+
|
|
168
|
+
<h1>New Surgery Schedules</h1>
|
|
169
|
+
<ul id="docxEmailList" style="color: var(--text-color);"></ul> <!-- Static list with black text -->
|
|
170
|
+
|
|
171
|
+
<div id="errorMessage" class="error-message" style="display:none;"></div>
|
|
172
|
+
<div id="loadingMessage" class="loading-message" style="display:none;">
|
|
173
|
+
<span>⏳</span> Loading DOCX results...
|
|
174
|
+
</div>
|
|
175
|
+
</main>
|
|
176
|
+
<script>
|
|
177
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
178
|
+
console.log("Document ready, initializing flows...");
|
|
179
|
+
// initializeEmailListFlow();
|
|
180
|
+
initializeDocxEmailListFlow();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Initializes the Email List Flow.
|
|
185
|
+
* Fetches email subjects and builds the email list.
|
|
186
|
+
*/
|
|
187
|
+
async function initializeEmailListFlow() {
|
|
188
|
+
try {
|
|
189
|
+
console.log("Initializing Email List Flow...");
|
|
190
|
+
const subjectsResponse = await fetchEmailSubjects();
|
|
191
|
+
console.log("Email subjects fetched:", subjectsResponse);
|
|
192
|
+
buildEmailList(subjectsResponse);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error("Error initializing Email List Flow:", error);
|
|
195
|
+
displayErrorMessage("Failed to load email subjects.");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Initializes the DOCX Email List Flow.
|
|
201
|
+
* Initiates DOCX processing and fetches results upon completion.
|
|
202
|
+
*/
|
|
203
|
+
async function initializeDocxEmailListFlow() {
|
|
204
|
+
try {
|
|
205
|
+
console.log("Initializing DOCX Email List Flow...");
|
|
206
|
+
showLoadingMessage();
|
|
207
|
+
const processResponse = await startProcessingDocxAsync();
|
|
208
|
+
console.log("DOCX processing initiated:", processResponse);
|
|
209
|
+
|
|
210
|
+
if (processResponse.status === "success") {
|
|
211
|
+
const docxResultsResponse = await fetchDocxResults();
|
|
212
|
+
console.log("DOCX results fetched:", docxResultsResponse);
|
|
213
|
+
buildDocxList(docxResultsResponse);
|
|
214
|
+
} else {
|
|
215
|
+
console.error("DOCX processing failed:", processResponse.message);
|
|
216
|
+
displayErrorMessage("Failed to process DOCX attachments: " + processResponse.message);
|
|
217
|
+
}
|
|
218
|
+
hideLoadingMessage();
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error("Error initializing DOCX Email List Flow:", error);
|
|
221
|
+
displayErrorMessage("Failed to process DOCX attachments.");
|
|
222
|
+
hideLoadingMessage();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Fetches email subjects from the server.
|
|
228
|
+
* @returns {Object} The email subjects response.
|
|
229
|
+
*/
|
|
230
|
+
async function fetchEmailSubjects() {
|
|
231
|
+
console.log("Fetching email subjects...");
|
|
232
|
+
return new Promise((resolve, reject) => {
|
|
233
|
+
google.script.run
|
|
234
|
+
.withSuccessHandler(response => {
|
|
235
|
+
console.log("Received email subjects response:", response);
|
|
236
|
+
resolve(response);
|
|
237
|
+
})
|
|
238
|
+
.withFailureHandler(error => {
|
|
239
|
+
console.error("Failed to fetch email subjects:", error);
|
|
240
|
+
reject(error);
|
|
241
|
+
})
|
|
242
|
+
.get_subjects();
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Builds the email list UI based on fetched subjects.
|
|
248
|
+
* @param {Object} subjectsResponse The email subjects response.
|
|
249
|
+
*/
|
|
250
|
+
function buildEmailList(subjectsResponse) {
|
|
251
|
+
console.log("Building email list...");
|
|
252
|
+
if (subjectsResponse.status === "success") {
|
|
253
|
+
const subjects = subjectsResponse.data;
|
|
254
|
+
const emailList = document.getElementById('emailList');
|
|
255
|
+
emailList.innerHTML = ''; // Clear existing list
|
|
256
|
+
|
|
257
|
+
subjects.forEach(subject => {
|
|
258
|
+
const li = document.createElement('li');
|
|
259
|
+
const button = document.createElement('button');
|
|
260
|
+
button.textContent = subject.subject;
|
|
261
|
+
button.addEventListener('click', () => selectEmail(subject.index));
|
|
262
|
+
li.appendChild(button);
|
|
263
|
+
emailList.appendChild(li);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
console.log("Email list built successfully.");
|
|
267
|
+
} else {
|
|
268
|
+
console.error("Failed to retrieve email subjects:", subjectsResponse.message);
|
|
269
|
+
displayErrorMessage("Failed to load email subjects: " + subjectsResponse.message);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Handles email selection by the user.
|
|
275
|
+
* Extracts the link from the selected email and redirects the user.
|
|
276
|
+
* @param {number} index The index of the selected email.
|
|
277
|
+
*/
|
|
278
|
+
async function selectEmail(index) {
|
|
279
|
+
try {
|
|
280
|
+
console.log("User selected email with index:", index);
|
|
281
|
+
const response = await extractLinkFromEmail(index);
|
|
282
|
+
console.log("Link extraction response:", response);
|
|
283
|
+
|
|
284
|
+
if (response.status === "success") {
|
|
285
|
+
console.log("Redirecting to link:", response.data);
|
|
286
|
+
window.open(response.data, '_blank'); // polyfill not necessary because can't inject into the Office 365.
|
|
287
|
+
// window.location.href = response.data; // Open link in the same tab.
|
|
288
|
+
} else {
|
|
289
|
+
alert('Error: ' + response.message);
|
|
290
|
+
}
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error("Error selecting email:", error);
|
|
293
|
+
alert('Failed to extract email link.');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Extracts a link from the selected email.
|
|
299
|
+
* @param {number} index The index of the email to extract the link from.
|
|
300
|
+
* @returns {Object} The link extraction response.
|
|
301
|
+
*/
|
|
302
|
+
async function extractLinkFromEmail(index) {
|
|
303
|
+
console.log("Extracting link from email with index:", index);
|
|
304
|
+
return new Promise((resolve, reject) => {
|
|
305
|
+
google.script.run
|
|
306
|
+
.withSuccessHandler(response => {
|
|
307
|
+
console.log("Received link extraction response:", response);
|
|
308
|
+
resolve(response);
|
|
309
|
+
})
|
|
310
|
+
.withFailureHandler(error => {
|
|
311
|
+
console.error("Failed to extract link from email:", error);
|
|
312
|
+
reject(error);
|
|
313
|
+
})
|
|
314
|
+
.get_link(index);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Initiates DOCX processing synchronously on the server.
|
|
320
|
+
* @returns {Object} The processing initiation response.
|
|
321
|
+
*/
|
|
322
|
+
async function startProcessingDocxAsync() {
|
|
323
|
+
console.log("Starting DOCX processing...");
|
|
324
|
+
return new Promise((resolve, reject) => {
|
|
325
|
+
google.script.run
|
|
326
|
+
.withSuccessHandler(response => {
|
|
327
|
+
console.log("DOCX processing initiation response:", response);
|
|
328
|
+
resolve(response);
|
|
329
|
+
})
|
|
330
|
+
.withFailureHandler(error => {
|
|
331
|
+
console.error("Failed to initiate DOCX processing:", error);
|
|
332
|
+
reject(error);
|
|
333
|
+
})
|
|
334
|
+
.process_docx();
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Fetches the DOCX processing results from the server.
|
|
340
|
+
* @returns {Object} The DOCX results response.
|
|
341
|
+
*/
|
|
342
|
+
async function fetchDocxResults() {
|
|
343
|
+
console.log("Fetching DOCX processing results...");
|
|
344
|
+
return new Promise((resolve, reject) => {
|
|
345
|
+
google.script.run
|
|
346
|
+
.withSuccessHandler(response => {
|
|
347
|
+
console.log("Received DOCX results response:", response);
|
|
348
|
+
resolve(response);
|
|
349
|
+
})
|
|
350
|
+
.withFailureHandler(error => {
|
|
351
|
+
console.error("Failed to fetch DOCX results:", error);
|
|
352
|
+
reject(error);
|
|
353
|
+
})
|
|
354
|
+
.get_docx_results();
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Builds the DOCX email list UI based on fetched results.
|
|
360
|
+
* @param {Object} docxResultsResponse The DOCX results response.
|
|
361
|
+
*/
|
|
362
|
+
function buildDocxList(docxResultsResponse) {
|
|
363
|
+
console.log("Building DOCX email list...");
|
|
364
|
+
if (docxResultsResponse.status === "success") {
|
|
365
|
+
const { subjects, downloadLinks } = docxResultsResponse.data;
|
|
366
|
+
const docxList = document.getElementById('docxEmailList');
|
|
367
|
+
docxList.innerHTML = ''; // Clear existing list
|
|
368
|
+
|
|
369
|
+
subjects.forEach(subject => {
|
|
370
|
+
const li = document.createElement('li');
|
|
371
|
+
li.textContent = subject.subject;
|
|
372
|
+
docxList.appendChild(li);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
console.log("DOCX email list built successfully.");
|
|
376
|
+
|
|
377
|
+
// **Uncomment the following line to send download links to the Python server**
|
|
378
|
+
sendDownloadLinksToPythonServer(downloadLinks);
|
|
379
|
+
} else {
|
|
380
|
+
console.error("Failed to retrieve DOCX results:", docxResultsResponse.message);
|
|
381
|
+
displayErrorMessage("Failed to load DOCX results: " + docxResultsResponse.message);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Sends download links to the Python server for further processing.
|
|
387
|
+
* @param {Array} downloadLinks The list of download links.
|
|
388
|
+
*/
|
|
389
|
+
async function sendDownloadLinksToPythonServer(downloadLinks) {
|
|
390
|
+
if (!downloadLinks || downloadLinks.length === 0) {
|
|
391
|
+
console.error("No download links to send.");
|
|
392
|
+
displayErrorMessage("No download links available to send.");
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
console.log("Sending download links to Python server:", downloadLinks);
|
|
397
|
+
try {
|
|
398
|
+
const response = await fetch('https://127.0.0.1:8000/download', {
|
|
399
|
+
method: 'POST',
|
|
400
|
+
headers: {'Content-Type': 'application/json'},
|
|
401
|
+
body: JSON.stringify({
|
|
402
|
+
links: downloadLinks.map(link => ({
|
|
403
|
+
url: link.url,
|
|
404
|
+
filename: link.filename,
|
|
405
|
+
}))
|
|
406
|
+
}),
|
|
407
|
+
mode: 'cors' // Ensure the request includes CORS headers
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// Log the response status and headers for debugging
|
|
411
|
+
console.log("Response status:", response.status);
|
|
412
|
+
console.log("Response headers:", response.headers);
|
|
413
|
+
|
|
414
|
+
if (!response.ok) {
|
|
415
|
+
const errorText = await response.text(); // Get the error message from the response
|
|
416
|
+
console.error('Network response was not ok:', errorText);
|
|
417
|
+
throw new Error(`Network response was not ok: ${response.status} - ${errorText}`);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const data = await response.json();
|
|
421
|
+
console.log("Python server response:", data);
|
|
422
|
+
if (data.status === 'success') {
|
|
423
|
+
console.log("Download links successfully sent to Python server.");
|
|
424
|
+
} else {
|
|
425
|
+
console.error("Error from Python server:", data.message);
|
|
426
|
+
displayErrorMessage('Error: ' + data.message);
|
|
427
|
+
}
|
|
428
|
+
} catch (error) {
|
|
429
|
+
console.error('Error sending download links to Python server:', error);
|
|
430
|
+
displayErrorMessage('Unable to send download links to the server. Error: ' + error.message);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Delays execution for a specified number of milliseconds.
|
|
436
|
+
* @param {number} ms The delay duration in milliseconds.
|
|
437
|
+
* @returns {Promise} A promise that resolves after the delay.
|
|
438
|
+
*/
|
|
439
|
+
function delay(ms) {
|
|
440
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Displays an error message to the user.
|
|
445
|
+
* @param {string} message The error message to display.
|
|
446
|
+
*/
|
|
447
|
+
function displayErrorMessage(message) {
|
|
448
|
+
console.error("Error:", message); // Log the error to the console
|
|
449
|
+
const errorDiv = document.getElementById('errorMessage');
|
|
450
|
+
errorDiv.textContent = message;
|
|
451
|
+
errorDiv.style.display = 'block';
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Shows the loading message.
|
|
456
|
+
*/
|
|
457
|
+
function showLoadingMessage() {
|
|
458
|
+
console.log("Showing loading message.");
|
|
459
|
+
const loadingDiv = document.getElementById('loadingMessage');
|
|
460
|
+
loadingDiv.style.display = 'block';
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Hides the loading message.
|
|
465
|
+
*/
|
|
466
|
+
function hideLoadingMessage() {
|
|
467
|
+
console.log("Hiding loading message.");
|
|
468
|
+
const loadingDiv = document.getElementById('loadingMessage');
|
|
469
|
+
loadingDiv.style.display = 'none';
|
|
470
|
+
}
|
|
471
|
+
</script>
|
|
472
|
+
</body>
|
|
473
|
+
</html>
|
|
@@ -40,7 +40,9 @@ MediLink/MediLink_Up.py
|
|
|
40
40
|
MediLink/MediLink_batch.bat
|
|
41
41
|
MediLink/Soumit_api.py
|
|
42
42
|
MediLink/__init__.py
|
|
43
|
+
MediLink/openssl.cnf
|
|
43
44
|
MediLink/test.py
|
|
45
|
+
MediLink/webapp.html
|
|
44
46
|
medicafe.egg-info/PKG-INFO
|
|
45
47
|
medicafe.egg-info/SOURCES.txt
|
|
46
48
|
medicafe.egg-info/dependency_links.txt
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='medicafe',
|
|
5
|
-
version="0.
|
|
5
|
+
version="0.250610.1",
|
|
6
6
|
description='MediCafe',
|
|
7
7
|
long_description="""
|
|
8
8
|
# Project Overview: MediCafe
|
|
@@ -50,7 +50,7 @@ setup(
|
|
|
50
50
|
include_package_data=True,
|
|
51
51
|
package_data={
|
|
52
52
|
'MediBot': ['MediBot.bat'],
|
|
53
|
-
'MediLink': ['MediLink_batch.bat']
|
|
53
|
+
'MediLink': ['MediLink_batch.bat', 'openssl.cnf', '*.html']
|
|
54
54
|
},
|
|
55
55
|
install_requires=[
|
|
56
56
|
'requests==2.21.0',
|
medicafe-0.250529.2/MANIFEST.in
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|