sonuprasad23 commited on
Commit
3e64ee6
·
1 Parent(s): d84c789
Files changed (3) hide show
  1. Dockerfile +1 -14
  2. requirements.txt +0 -1
  3. worker.py +13 -21
Dockerfile CHANGED
@@ -4,27 +4,14 @@ WORKDIR /app
4
 
5
  ENV DEBIAN_FRONTEND=noninteractive
6
  ENV TZ=Etc/UTC
7
- ENV WDM_PROGRESS_BAR=0
8
- ENV HOME=/home/appuser
9
- ENV PYTHONUSERBASE=/home/appuser/.local
10
 
11
  RUN apt-get update && apt-get install -y --no-install-recommends \
12
- wget \
13
- gnupg \
14
- unzip \
15
- ca-certificates \
16
  chromium \
17
  chromium-driver \
18
- libnss3 \
19
- libxss1 \
20
- libasound2 \
21
- libxtst6 \
22
- libatk-bridge2.0-0 \
23
- libgtk-3-0 \
24
  && rm -rf /var/lib/apt/lists/*
25
 
26
  RUN addgroup --system appuser && adduser --system --ingroup appuser appuser
27
- RUN mkdir -p /home/appuser/.local && chown -R appuser:appuser /app /home/appuser
28
 
29
  USER appuser
30
 
 
4
 
5
  ENV DEBIAN_FRONTEND=noninteractive
6
  ENV TZ=Etc/UTC
 
 
 
7
 
8
  RUN apt-get update && apt-get install -y --no-install-recommends \
 
 
 
 
9
  chromium \
10
  chromium-driver \
 
 
 
 
 
 
11
  && rm -rf /var/lib/apt/lists/*
12
 
13
  RUN addgroup --system appuser && adduser --system --ingroup appuser appuser
14
+ RUN chown -R appuser:appuser /app
15
 
16
  USER appuser
17
 
requirements.txt CHANGED
@@ -5,7 +5,6 @@ Flask-Cors
5
  eventlet
6
  python-dotenv
7
  selenium
8
- webdriver-manager
9
  google-api-python-client
10
  google-auth-httplib2
11
  google-auth-oauthlib
 
5
  eventlet
6
  python-dotenv
7
  selenium
 
8
  google-api-python-client
9
  google-auth-httplib2
10
  google-auth-oauthlib
worker.py CHANGED
@@ -3,16 +3,13 @@ import time
3
  import io
4
  import os
5
  import threading
6
- import tempfile
7
- import shutil
8
  from selenium import webdriver
9
  from selenium.webdriver.chrome.service import Service as ChromeService
10
  from selenium.webdriver.chrome.options import Options as ChromeOptions
11
- from webdriver_manager.chrome import ChromeDriverManager
12
- from webdriver_manager.core.os_manager import ChromeType
13
  from selenium.webdriver.common.by import By
14
  from selenium.webdriver.support.ui import WebDriverWait
15
  from selenium.webdriver.support import expected_conditions as EC
 
16
 
17
  class QuantumBot:
18
  def __init__(self, socketio, app):
@@ -21,35 +18,33 @@ class QuantumBot:
21
  self.driver = None
22
  self.DEFAULT_TIMEOUT = 30
23
  self.termination_event = threading.Event()
24
- self.wdm_cache_dir = None
25
 
26
  def initialize_driver(self):
27
  try:
28
  self.micro_status("Initializing headless browser...")
29
  options = ChromeOptions()
 
30
  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"
31
- options.add_argument(f'user-agent={user_agent}')
32
- options.add_argument("--headless")
33
  options.add_argument("--window-size=1920,1080")
34
  options.add_argument("--no-sandbox")
35
  options.add_argument("--disable-dev-shm-usage")
36
  options.add_argument("--disable-gpu")
 
 
 
37
 
38
- self.wdm_cache_dir = tempfile.mkdtemp()
39
- os.environ['WDM_LOCAL'] = self.wdm_cache_dir
40
-
41
- service = ChromeService(ChromeDriverManager(chrome_type=ChromeType.CHROMIUM).install())
42
  self.driver = webdriver.Chrome(service=service, options=options)
43
 
44
  self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
45
  'source': "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
46
  })
47
- # --- Definitive Fix: Return two values on success ---
48
  return True, None
49
  except Exception as e:
50
  error_message = f"Message: {str(e)}"
51
  print(f"CRITICAL ERROR in WebDriver Initialization: {error_message}")
52
- # --- Definitive Fix: Return two values on failure ---
53
  return False, error_message
54
 
55
  def micro_status(self, message):
@@ -72,12 +67,10 @@ class QuantumBot:
72
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.ID, "login"))).click()
73
  self.micro_status("Waiting for OTP screen...")
74
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.presence_of_element_located((By.ID, "code1")))
75
- # --- Definitive Fix: Return two values on success ---
76
  return True, None
77
  except Exception as e:
78
  error_message = f"Error during login: {str(e)}"
79
  print(f"[Bot] ERROR during login: {error_message}")
80
- # --- Definitive Fix: Return two values on failure ---
81
  return False, error_message
82
 
83
  def submit_otp(self, otp):
@@ -89,12 +82,10 @@ class QuantumBot:
89
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.ID, "login"))).click()
90
  self.micro_status("Verifying login success...")
91
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Payments']")))
92
- # --- Definitive Fix: Return two values on success ---
93
  return True, None
94
  except Exception as e:
95
  error_message = f"Error during OTP submission: {str(e)}"
96
  print(f"[Bot] ERROR during OTP submission: {error_message}")
97
- # --- Definitive Fix: Return two values on failure ---
98
  return False, error_message
99
 
100
  def process_patient_list(self, patient_list):
@@ -119,6 +110,7 @@ class QuantumBot:
119
  try:
120
  self.micro_status(f"Navigating to Void page for '{patient_name}'")
121
  self.driver.get("https://gateway.quantumepay.com/credit-card/void")
 
122
  search_successful = False
123
  for attempt in range(15):
124
  try:
@@ -132,13 +124,16 @@ class QuantumBot:
132
  break
133
  except Exception: time.sleep(1)
134
  if not search_successful: raise Exception("Failed to search for patient.")
 
135
  time.sleep(3)
136
  self.micro_status("Opening transaction details...")
137
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, f"//tr[contains(., \"{patient_name}\")]//button[@data-v-b6b33fa0]"))).click()
138
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))).click()
 
139
  self.micro_status("Adding to Vault...")
140
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))).click()
141
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))).click()
 
142
  try:
143
  self.micro_status("Verifying success and saving...")
144
  company_input = WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.NAME, "company_name")))
@@ -158,7 +153,4 @@ class QuantumBot:
158
 
159
  def shutdown(self):
160
  if self.driver:
161
- self.driver.quit()
162
- if self.wdm_cache_dir and os.path.exists(self.wdm_cache_dir):
163
- shutil.rmtree(self.wdm_cache_dir)
164
- print(f"[Bot] Cleaned up temporary WDM cache: {self.wdm_cache_dir}")
 
3
  import io
4
  import os
5
  import threading
 
 
6
  from selenium import webdriver
7
  from selenium.webdriver.chrome.service import Service as ChromeService
8
  from selenium.webdriver.chrome.options import Options as ChromeOptions
 
 
9
  from selenium.webdriver.common.by import By
10
  from selenium.webdriver.support.ui import WebDriverWait
11
  from selenium.webdriver.support import expected_conditions as EC
12
+ from selenium.common.exceptions import TimeoutException, NoSuchElementException, ElementNotInteractableException
13
 
14
  class QuantumBot:
15
  def __init__(self, socketio, app):
 
18
  self.driver = None
19
  self.DEFAULT_TIMEOUT = 30
20
  self.termination_event = threading.Event()
 
21
 
22
  def initialize_driver(self):
23
  try:
24
  self.micro_status("Initializing headless browser...")
25
  options = ChromeOptions()
26
+ options.binary_location = "/usr/bin/chromium"
27
  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"
28
+ options.add_argument(f"user-agent={user_agent}")
29
+ options.add_argument("--headless=new")
30
  options.add_argument("--window-size=1920,1080")
31
  options.add_argument("--no-sandbox")
32
  options.add_argument("--disable-dev-shm-usage")
33
  options.add_argument("--disable-gpu")
34
+ options.add_argument('--disable-blink-features=AutomationControlled')
35
+ options.add_experimental_option("excludeSwitches", ["enable-automation"])
36
+ options.add_experimental_option('useAutomationExtension', False)
37
 
38
+ service = ChromeService(executable_path="/usr/bin/chromedriver")
 
 
 
39
  self.driver = webdriver.Chrome(service=service, options=options)
40
 
41
  self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
42
  'source': "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
43
  })
 
44
  return True, None
45
  except Exception as e:
46
  error_message = f"Message: {str(e)}"
47
  print(f"CRITICAL ERROR in WebDriver Initialization: {error_message}")
 
48
  return False, error_message
49
 
50
  def micro_status(self, message):
 
67
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.ID, "login"))).click()
68
  self.micro_status("Waiting for OTP screen...")
69
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.presence_of_element_located((By.ID, "code1")))
 
70
  return True, None
71
  except Exception as e:
72
  error_message = f"Error during login: {str(e)}"
73
  print(f"[Bot] ERROR during login: {error_message}")
 
74
  return False, error_message
75
 
76
  def submit_otp(self, otp):
 
82
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.ID, "login"))).click()
83
  self.micro_status("Verifying login success...")
84
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Payments']")))
 
85
  return True, None
86
  except Exception as e:
87
  error_message = f"Error during OTP submission: {str(e)}"
88
  print(f"[Bot] ERROR during OTP submission: {error_message}")
 
89
  return False, error_message
90
 
91
  def process_patient_list(self, patient_list):
 
110
  try:
111
  self.micro_status(f"Navigating to Void page for '{patient_name}'")
112
  self.driver.get("https://gateway.quantumepay.com/credit-card/void")
113
+
114
  search_successful = False
115
  for attempt in range(15):
116
  try:
 
124
  break
125
  except Exception: time.sleep(1)
126
  if not search_successful: raise Exception("Failed to search for patient.")
127
+
128
  time.sleep(3)
129
  self.micro_status("Opening transaction details...")
130
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, f"//tr[contains(., \"{patient_name}\")]//button[@data-v-b6b33fa0]"))).click()
131
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.LINK_TEXT, "Transaction Detail"))).click()
132
+
133
  self.micro_status("Adding to Vault...")
134
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button/span[normalize-space()='Add to Vault']"))).click()
135
  WebDriverWait(self.driver, self.DEFAULT_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='modal-footer']//button/span[normalize-space()='Confirm']"))).click()
136
+
137
  try:
138
  self.micro_status("Verifying success and saving...")
139
  company_input = WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.NAME, "company_name")))
 
153
 
154
  def shutdown(self):
155
  if self.driver:
156
+ self.driver.quit()