sonuprasad23 commited on
Commit
51ddbb2
·
1 Parent(s): 1d8ff49

Bug-Fixed

Browse files
Files changed (2) hide show
  1. server.py +32 -15
  2. worker.py +10 -15
server.py CHANGED
@@ -39,6 +39,7 @@ class EmailService:
39
  self.smtp_server = "smtp.gmail.com"; self.smtp_port = 587
40
  if not self.sender_email or not self.password:
41
  print("[Email] WARNING: Email credentials not found in secrets.")
 
42
  def send_report(self, recipients, subject, body, attachments=None):
43
  if not self.sender_email or not self.password: return False
44
  try:
@@ -52,7 +53,8 @@ class EmailService:
52
  with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
53
  server.starttls(); server.login(self.sender_email, self.password); server.send_message(msg)
54
  print(f"Email sent successfully to {', '.join(recipients)}"); return True
55
- except Exception as e: print(f"Failed to send email: {e}"); return False
 
56
 
57
  class GoogleDriveService:
58
  def __init__(self):
@@ -62,12 +64,15 @@ class GoogleDriveService:
62
  from google.oauth2 import service_account
63
  from googleapiclient.discovery import build
64
  base64_creds = os.getenv('GDRIVE_SA_KEY_BASE64')
65
- if not base64_creds or not self.folder_id: raise ValueError("Google Drive secrets not found.")
 
66
  creds_json = base64.b64decode(base64_creds).decode('utf-8'); creds_dict = json.loads(creds_json)
67
  self.creds = service_account.Credentials.from_service_account_info(creds_dict, scopes=['https://www.googleapis.com/auth/drive'])
68
  self.service = build('drive', 'v3', credentials=self.creds)
69
  print("[G-Drive] Service initialized securely from secrets.")
70
- except Exception as e: print(f"[G-Drive] CRITICAL ERROR: Could not initialize Google Drive service: {e}")
 
 
71
  def upload_file(self, filename, file_content):
72
  if not self.service: return False
73
  try:
@@ -77,15 +82,18 @@ class GoogleDriveService:
77
  self.service.files().create(body=file_metadata, media_body=media, fields='id').execute()
78
  print(f"[G-Drive] File '{filename}' uploaded successfully.")
79
  return True
80
- except Exception as e: print(f"[G-Drive] ERROR: File upload failed: {e}"); return False
 
81
 
82
  email_service = EmailService()
83
  drive_service = GoogleDriveService()
84
 
85
  def get_email_list():
86
  try:
87
- with open('config/emails.conf', 'r') as f: return [line.strip() for line in f if line.strip()]
88
- except FileNotFoundError: return []
 
 
89
 
90
  def run_automation_process(session_id):
91
  global bot_instance
@@ -94,7 +102,7 @@ def run_automation_process(session_id):
94
  data = session_data.get(session_id, {}); csv_content = data.get('csv_content')
95
  df = pd.read_csv(io.StringIO(csv_content));
96
  if 'Status' not in df.columns: df.insert(1, 'Status', '')
97
- patient_list = df[ (df['Status'] != 'Done') & (df['Status'] != 'Bad') ]['Name'].tolist()
98
  socketio.emit('initial_stats', {'total': len(patient_list)})
99
  results = bot_instance.process_patient_list(patient_list)
100
  is_terminated = bot_instance.termination_event.is_set()
@@ -133,13 +141,15 @@ def status_page():
133
 
134
  @socketio.on('connect')
135
  def handle_connect():
136
- print(f'Frontend connected. Allowed origin: {FRONTEND_ORIGIN}'); emit('email_list', {'emails': get_email_list()})
 
137
 
138
  @socketio.on('initialize_session')
139
  def handle_init(data):
140
  session_id = 'user_session'; global bot_instance
141
  session_data[session_id] = {'csv_content': data['content'], 'emails': data['emails'], 'filename': data['filename']}
142
- if bot_instance: bot_instance.shutdown()
 
143
  bot_instance = QuantumBot(socketio, app)
144
 
145
  is_success, error_message = bot_instance.initialize_driver()
@@ -150,24 +160,31 @@ def handle_init(data):
150
 
151
  @socketio.on('start_login')
152
  def handle_login(credentials):
153
- if not bot_instance: return emit('error', {'message': 'Bot not initialized.'})
 
154
  is_success, error_message = bot_instance.login(credentials['username'], credentials['password'])
155
- if is_success: emit('otp_required')
156
- else: emit('error', {'message': f'Login failed: {error_message}'})
 
 
157
 
158
  @socketio.on('submit_otp')
159
  def handle_otp(data):
160
- if not bot_instance: return emit('error', {'message': 'Bot not initialized.'})
 
161
  is_success, error_message = bot_instance.submit_otp(data['otp'])
162
  if is_success:
163
  emit('login_successful')
164
  session_id = 'user_session'
165
  socketio.start_background_task(target=run_automation_process, args=(session_id,))
166
- else: emit('error', {'message': f'OTP failed: {error_message}'})
 
167
 
168
  @socketio.on('terminate_process')
169
  def handle_terminate():
170
- if bot_instance: print("Termination signal received."); bot_instance.stop()
 
 
171
 
172
  if __name__ == '__main__':
173
  print("====================================================================")
 
39
  self.smtp_server = "smtp.gmail.com"; self.smtp_port = 587
40
  if not self.sender_email or not self.password:
41
  print("[Email] WARNING: Email credentials not found in secrets.")
42
+
43
  def send_report(self, recipients, subject, body, attachments=None):
44
  if not self.sender_email or not self.password: return False
45
  try:
 
53
  with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
54
  server.starttls(); server.login(self.sender_email, self.password); server.send_message(msg)
55
  print(f"Email sent successfully to {', '.join(recipients)}"); return True
56
+ except Exception as e:
57
+ print(f"Failed to send email: {e}"); return False
58
 
59
  class GoogleDriveService:
60
  def __init__(self):
 
64
  from google.oauth2 import service_account
65
  from googleapiclient.discovery import build
66
  base64_creds = os.getenv('GDRIVE_SA_KEY_BASE64')
67
+ if not base64_creds or not self.folder_id:
68
+ raise ValueError("Google Drive secrets not found.")
69
  creds_json = base64.b64decode(base64_creds).decode('utf-8'); creds_dict = json.loads(creds_json)
70
  self.creds = service_account.Credentials.from_service_account_info(creds_dict, scopes=['https://www.googleapis.com/auth/drive'])
71
  self.service = build('drive', 'v3', credentials=self.creds)
72
  print("[G-Drive] Service initialized securely from secrets.")
73
+ except Exception as e:
74
+ print(f"[G-Drive] CRITICAL ERROR: Could not initialize Google Drive service: {e}")
75
+
76
  def upload_file(self, filename, file_content):
77
  if not self.service: return False
78
  try:
 
82
  self.service.files().create(body=file_metadata, media_body=media, fields='id').execute()
83
  print(f"[G-Drive] File '{filename}' uploaded successfully.")
84
  return True
85
+ except Exception as e:
86
+ print(f"[G-Drive] ERROR: File upload failed: {e}"); return False
87
 
88
  email_service = EmailService()
89
  drive_service = GoogleDriveService()
90
 
91
  def get_email_list():
92
  try:
93
+ with open('config/emails.conf', 'r') as f:
94
+ return [line.strip() for line in f if line.strip()]
95
+ except FileNotFoundError:
96
+ return []
97
 
98
  def run_automation_process(session_id):
99
  global bot_instance
 
102
  data = session_data.get(session_id, {}); csv_content = data.get('csv_content')
103
  df = pd.read_csv(io.StringIO(csv_content));
104
  if 'Status' not in df.columns: df.insert(1, 'Status', '')
105
+ patient_list = df[(df['Status'] != 'Done') & (df['Status'] != 'Bad')]['Name'].tolist()
106
  socketio.emit('initial_stats', {'total': len(patient_list)})
107
  results = bot_instance.process_patient_list(patient_list)
108
  is_terminated = bot_instance.termination_event.is_set()
 
141
 
142
  @socketio.on('connect')
143
  def handle_connect():
144
+ print(f'Frontend connected. Allowed origin: {FRONTEND_ORIGIN}')
145
+ emit('email_list', {'emails': get_email_list()})
146
 
147
  @socketio.on('initialize_session')
148
  def handle_init(data):
149
  session_id = 'user_session'; global bot_instance
150
  session_data[session_id] = {'csv_content': data['content'], 'emails': data['emails'], 'filename': data['filename']}
151
+ if bot_instance:
152
+ bot_instance.shutdown()
153
  bot_instance = QuantumBot(socketio, app)
154
 
155
  is_success, error_message = bot_instance.initialize_driver()
 
160
 
161
  @socketio.on('start_login')
162
  def handle_login(credentials):
163
+ if not bot_instance:
164
+ return emit('error', {'message': 'Bot not initialized.'})
165
  is_success, error_message = bot_instance.login(credentials['username'], credentials['password'])
166
+ if is_success:
167
+ emit('otp_required')
168
+ else:
169
+ emit('error', {'message': f'Login failed: {error_message}'})
170
 
171
  @socketio.on('submit_otp')
172
  def handle_otp(data):
173
+ if not bot_instance:
174
+ return emit('error', {'message': 'Bot not initialized.'})
175
  is_success, error_message = bot_instance.submit_otp(data['otp'])
176
  if is_success:
177
  emit('login_successful')
178
  session_id = 'user_session'
179
  socketio.start_background_task(target=run_automation_process, args=(session_id,))
180
+ else:
181
+ emit('error', {'message': f'OTP failed: {error_message}'})
182
 
183
  @socketio.on('terminate_process')
184
  def handle_terminate():
185
+ if bot_instance:
186
+ print("Termination signal received.")
187
+ bot_instance.stop()
188
 
189
  if __name__ == '__main__':
190
  print("====================================================================")
worker.py CHANGED
@@ -1,9 +1,7 @@
1
  # worker.py
2
  import time
3
- import os
4
  import threading
5
- import tempfile
6
- import shutil
7
 
8
  from selenium import webdriver
9
  from selenium.webdriver.chrome.service import Service as ChromeService
@@ -21,8 +19,6 @@ class QuantumBot:
21
  self.driver = None
22
  self.DEFAULT_TIMEOUT = 30
23
  self.termination_event = threading.Event()
24
- self.chrome_user_data_dir = None
25
- self.chrome_cache_dir = None
26
 
27
  def initialize_driver(self):
28
  try:
@@ -32,11 +28,9 @@ class QuantumBot:
32
  # Use system Chromium installed in the image
33
  options.binary_location = "/usr/bin/chromium"
34
 
35
- # Per-run, unique profile and cache to avoid "already in use" locks
36
- self.chrome_user_data_dir = tempfile.mkdtemp(prefix="chrome-user-data-")
37
- self.chrome_cache_dir = tempfile.mkdtemp(prefix="chrome-cache-")
38
- options.add_argument(f"--user-data-dir={self.chrome_user_data_dir}")
39
- options.add_argument(f"--disk-cache-dir={self.chrome_cache_dir}")
40
 
41
  # Stable/headless startup flags
42
  user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
@@ -138,6 +132,7 @@ class QuantumBot:
138
  try:
139
  self.micro_status(f"Navigating to Void page for '{patient_name}'")
140
  self.driver.get("https://gateway.quantumepay.com/credit-card/void")
 
141
  search_successful = False
142
  for attempt in range(15):
143
  try:
@@ -155,8 +150,10 @@ class QuantumBot:
155
  break
156
  except Exception:
157
  time.sleep(1)
 
158
  if not search_successful:
159
  raise Exception("Failed to search for patient.")
 
160
  time.sleep(3)
161
  self.micro_status("Opening transaction details...")
162
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
@@ -165,6 +162,7 @@ class QuantumBot:
165
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
166
  EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))
167
  ).click()
 
168
  self.micro_status("Adding to Vault...")
169
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
170
  EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))
@@ -172,6 +170,7 @@ class QuantumBot:
172
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
173
  EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))
174
  ).click()
 
175
  try:
176
  self.micro_status("Verifying success and saving...")
177
  company_input = WebDriverWait(self.driver, 10).until(
@@ -200,8 +199,4 @@ class QuantumBot:
200
  def shutdown(self):
201
  if self.driver:
202
  self.driver.quit()
203
- # Cleanup per-run temp dirs
204
- for d in [self.chrome_user_data_dir, self.chrome_cache_dir]:
205
- if d and os.path.exists(d):
206
- shutil.rmtree(d, ignore_errors=True)
207
- print(f"[Bot] Cleaned up temporary Chrome profile and cache.")
 
1
  # worker.py
2
  import time
 
3
  import threading
4
+ import os
 
5
 
6
  from selenium import webdriver
7
  from selenium.webdriver.chrome.service import Service as ChromeService
 
19
  self.driver = None
20
  self.DEFAULT_TIMEOUT = 30
21
  self.termination_event = threading.Event()
 
 
22
 
23
  def initialize_driver(self):
24
  try:
 
28
  # Use system Chromium installed in the image
29
  options.binary_location = "/usr/bin/chromium"
30
 
31
+ # Do NOT set --user-data-dir; let ChromeDriver create a temp profile
32
+ # Use an ephemeral DevTools port to avoid collisions
33
+ options.add_argument("--remote-debugging-port=0")
 
 
34
 
35
  # Stable/headless startup flags
36
  user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
 
132
  try:
133
  self.micro_status(f"Navigating to Void page for '{patient_name}'")
134
  self.driver.get("https://gateway.quantumepay.com/credit-card/void")
135
+
136
  search_successful = False
137
  for attempt in range(15):
138
  try:
 
150
  break
151
  except Exception:
152
  time.sleep(1)
153
+
154
  if not search_successful:
155
  raise Exception("Failed to search for patient.")
156
+
157
  time.sleep(3)
158
  self.micro_status("Opening transaction details...")
159
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
 
162
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
163
  EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))
164
  ).click()
165
+
166
  self.micro_status("Adding to Vault...")
167
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
168
  EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))
 
170
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(
171
  EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))
172
  ).click()
173
+
174
  try:
175
  self.micro_status("Verifying success and saving...")
176
  company_input = WebDriverWait(self.driver, 10).until(
 
199
  def shutdown(self):
200
  if self.driver:
201
  self.driver.quit()
202
+ print("[Bot] Chrome session closed.")