├── .env_demo ├── .gitignore ├── LICENSE ├── README.md ├── api.py ├── api_backend.py ├── chrome_d_download.py ├── chrome_handler.py ├── dev_notes ├── helper_fn.py ├── helper_funcs.py ├── req.txt ├── testing_apis.py ├── unzipper.py └── utils.py /.env_demo: -------------------------------------------------------------------------------- 1 | # NGROK - xyz@email 2 | NGROK_AUTH_TOKEN= 3 | 4 | # MongoDB 5 | MONGO_URI= 6 | MONGO_DB_NAME= 7 | MONGO_COLLECTION_NAME= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | chromedata 3 | venv 4 | LICENSE.chromedriver 5 | chromedriver 6 | chromeDriver_zips 7 | .env 8 | .idea 9 | THIRD_PARTY_NOTICES.chromedriver 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Nat Friedman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChatGPT Unofficial API Selenium 2 | 3 | ## ⭐ Video. 4 | 5 | **Link** - https://youtu.be/cMCn2cljlls 6 | 7 | ## ⭐ Why this API? 8 | 9 | This is an unofficial API for ChatGPT using Selenium. it is not recommended to use this API for production. This API is only for testing purposes. 10 | 11 | This API is for projects that just need to use the ChatGPT API for testing purposes. And don't want to pay for the official API just for testing. 12 | 13 | #### **Note**: This API is extremely slow than the official API. So, it is not recommended to use this API for production. This API is only for testing purposes. 14 | 15 | ## ⭐ File Structure 16 | 17 | 18 | ### 1. Chromedriver handler 19 | * **chrome_d_download.py** # use to download chrome driver. 20 | * **unzipper.py** # use to unzip chrome driver. 21 | 22 | ### 2. Use to handle remote chrome browser. 23 | * **chrome_handler.py** # use to handle chrome browser. 24 | 25 | ### 3. Use to handle ChatGPT and core functions. 26 | * **api_backend.py** # use to handle ChatGPT with selenium. 27 | * **helper_funcs.py** # use to handle core functions of selenium. 28 | 29 | ## ⭐ Installation. 30 | 31 | ### 1. Create a virtual environment and activate it. 32 | #### For Linux 33 | ``` 34 | python3 -m venv venv 35 | source venv/bin/activate 36 | ``` 37 | #### For Windows 38 | ``` 39 | python -m venv venv 40 | venv\Scripts\activate 41 | ``` 42 | 43 | ### 2. Install requirements 44 | ``` 45 | pip install -r req.txt 46 | ``` 47 | 48 | ### 3. Download chrome driver (this will automatically download chrome driver for your OS) 49 | ``` 50 | python chrome_d_download.py 51 | ``` 52 | 53 | ## ⭐ Loggging in to chatgpt with remote chrome browser. 54 | 55 | ### 1. Start the remote chrome browser. 56 | ``` 57 | python chrome_handler.py s 58 | ``` 59 | 60 | ***Now you can see a chrome browser window opened. You can use this browser to login to chatgpt. And accept the promepts which are asking for your permission on chatapt page.*** 61 | 62 | #### https://chat.openai.com/chat paste this link to the remote chrome browser and login to chatgpt. 63 | 64 | ### 2. Close the remote chrome browser. 65 | ``` 66 | python chrome_handler.py k 67 | ``` 68 | 69 | ## ⭐ Using the API. 70 | 71 | ### 1. Directly using the API via terminal. 72 | ``` 73 | python api_backend.py 74 | ``` 75 | This will open in a terminal where you can type your message and get the response from chatgpt. 76 | 77 | To exit the program, in terminal type `!quit` and press enter. 78 | 79 | ### 2. Using the API in your project via function calls. 80 | ``` 81 | import api_backend 82 | ``` 83 | 84 | To Start start remote chrome browser and go to chatgpt site. **(Only once)** 85 | ``` 86 | api_backend.start_chat_gpt() 87 | ``` 88 | 89 | To get response from chatgpt and store it in a variable. **(You can use this function as many times as you want)** 90 | ``` 91 | variable = api_backend.make_gpt_request("what is gpt model?") 92 | ``` 93 | 94 | To close the remote chrome browser. **(Only once)** 95 | ``` 96 | api_backend.stop_chat_gpt() 97 | ``` 98 | #### **Note**: You can run `testing_api.py` file to see how to use the API in your project. 99 | 100 | ## ⭐ Extras. 101 | 102 | * `gmail_xpath` in `start_chat_gpt` function in `api_backend.py` file is the xpath of which search by email holder's name this can be changed to the users name. this will enable auto login to chatgpt if the user is already logged in to `google` in the remote chrome browser. 103 | 104 | ## ⭐ Improvements. 105 | 106 | * `make_gpt_request()` should fuction should be improved to handle errors. 107 | * `make_gpt_request()` should return good formatted response in json format. 108 | * Instead of using `time.sleep()` we should use `implicit wait` and `explicit wait` in selenium. 109 | * We can use `threading` if we want to use the API in multiple projects at the same time. 110 | * The speef of the API should be improved. We can use requests module to improve the speed of the API. Or we can use `asyncio` to improve the speed of the API. 111 | 112 | ## ⭐ License. 113 | 114 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 115 | 116 | ## ⭐ Contributing. 117 | 118 | You can contribute to this project by making a pull request. If you want to contribute to this project, you can fork this project and make a pull request. 119 | 120 | Any type of contribution is welcome. You can contribute to this project by improving the code, adding new features, fixing bugs, etc. 121 | 122 | Thank you. 123 | 124 | ## Star History 125 | 126 | 127 | 128 | 129 | 130 | Star History Chart 131 | 132 | 133 | -------------------------------------------------------------------------------- /api.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | from flask_restful import Resource, Api 3 | from flask_autoindex import AutoIndex 4 | from api_backend import * 5 | import json 6 | from utils import update_remote_ip_ngrok_mongo 7 | from dotenv import load_dotenv 8 | load_dotenv() 9 | 10 | app = Flask(__name__) 11 | 12 | api = Api(app) 13 | 14 | class SingleQ(Resource): 15 | def get(self): 16 | req_json = json.loads(request.data.decode('utf-8')) 17 | text = req_json['prompt'] 18 | return {"response": make_gpt_request(text)} 19 | 20 | 21 | api.add_resource(SingleQ, '/singleQuery') 22 | 23 | if __name__ == '__main__': 24 | port = 5000 25 | try: 26 | update_remote_ip_ngrok_mongo(os.getenv("MONGO_DB_NAME"), os.getenv("MONGO_COLLECTION_NAME"),port=5000 , currStatus=1) 27 | start_chat_gpt() 28 | app.run(debug=False, port=5000) 29 | except KeyboardInterrupt as e: 30 | print("KeyboardInterrupt detected, exiting...") 31 | finally: 32 | stop_chat_gpt() 33 | update_remote_ip_ngrok_mongo(os.getenv("MONGO_DB_NAME"), os.getenv("MONGO_COLLECTION_NAME"), port=5000, currStatus=0) -------------------------------------------------------------------------------- /api_backend.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from selenium import webdriver 4 | from selenium.webdriver.common.by import By 5 | from selenium.webdriver.support.ui import WebDriverWait 6 | from selenium.webdriver.support import expected_conditions as EC 7 | from selenium.common.exceptions import TimeoutException, WebDriverException 8 | from selenium.webdriver.chrome.service import Service 9 | from selenium.webdriver.chrome.options import Options 10 | import undetected_chromedriver as uc 11 | import helper_fn 12 | import logging 13 | 14 | # Configure logging 15 | logging.basicConfig( 16 | level=logging.INFO, 17 | format='%(asctime)s - %(levelname)s - %(message)s', 18 | datefmt='%m/%d/%Y %I:%M:%S %p' 19 | ) 20 | 21 | class ChromeDriverManager: 22 | def __init__(self): 23 | self.driver = None 24 | self.max_retries = 3 25 | self.retry_delay = 5 26 | self.setup_chrome_options() 27 | 28 | def setup_chrome_options(self): 29 | """Set up Chrome options for optimal stability.""" 30 | self.options = uc.ChromeOptions() 31 | 32 | # Create user data directory if it doesn't exist 33 | user_data_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'chrome_user_data') 34 | os.makedirs(user_data_dir, exist_ok=True) 35 | 36 | # Add user data directory argument 37 | self.options.add_argument(f'--user-data-dir={user_data_dir}') 38 | 39 | # Existing options 40 | self.options.add_argument('--no-sandbox') 41 | self.options.add_argument('--disable-dev-shm-usage') 42 | self.options.add_argument('--disable-gpu') 43 | self.options.add_argument('--disable-software-rasterizer') 44 | self.options.add_argument('--disable-extensions') 45 | self.options.add_argument('--disable-notifications') 46 | self.options.add_argument('--disable-popup-blocking') 47 | self.options.add_argument('--ignore-certificate-errors') 48 | self.options.add_argument('--start-maximized') 49 | self.options.add_argument('--disable-blink-features=AutomationControlled') 50 | self.options.add_argument('--disable-logging') 51 | self.options.add_argument('--log-level=3') 52 | self.options.add_argument('--silent') 53 | self.options.add_argument('--disable-automation') 54 | self.options.add_argument('--disable-infobars') 55 | self.options.add_argument('--disable-blink-features') 56 | self.options.add_argument('--disable-blink-features=AutomationControlled') 57 | self.options.add_argument('--disable-web-security') 58 | self.options.add_argument('--allow-running-insecure-content') 59 | 60 | def initialize_driver(self): 61 | """Initialize Chrome driver with retries.""" 62 | for attempt in range(self.max_retries): 63 | try: 64 | if self.driver: 65 | try: 66 | self.driver.quit() 67 | except: 68 | pass 69 | 70 | self.driver = uc.Chrome(options=self.options) 71 | self.driver.set_page_load_timeout(30) 72 | helper_fn.set_driver(self.driver) # Set the driver in helper_fn 73 | logging.info("Chrome driver initialized successfully") 74 | return True 75 | except Exception as e: 76 | logging.error(f"Attempt {attempt + 1} failed to initialize Chrome driver: {str(e)}") 77 | if attempt < self.max_retries - 1: 78 | time.sleep(self.retry_delay) 79 | else: 80 | logging.error("Failed to initialize Chrome driver after all retries") 81 | raise 82 | 83 | def ensure_driver_alive(self): 84 | """Check if driver is alive and reconnect if necessary.""" 85 | try: 86 | # Try to get window handles to check if driver is responsive 87 | self.driver.window_handles 88 | return True 89 | except: 90 | logging.warning("Chrome driver appears to be dead, attempting to reconnect...") 91 | return self.initialize_driver() 92 | 93 | def quit(self): 94 | """Safely quit the Chrome driver.""" 95 | if self.driver: 96 | try: 97 | self.driver.quit() 98 | except: 99 | pass 100 | self.driver = None 101 | 102 | # Initialize the global ChromeDriverManager 103 | driver_manager = ChromeDriverManager() 104 | driver = None 105 | 106 | def initialize_chrome(): 107 | """Initialize Chrome and navigate to ChatGPT.""" 108 | global driver 109 | try: 110 | if driver_manager.initialize_driver(): 111 | driver = driver_manager.driver 112 | driver.get("https://chat.openai.com/") 113 | logging.info("Successfully navigated to ChatGPT") 114 | return True 115 | return False 116 | except Exception as e: 117 | logging.error(f"Failed to initialize Chrome: {str(e)}") 118 | return False 119 | 120 | def ensure_chrome_alive(): 121 | """Ensure Chrome is alive and reconnect if necessary.""" 122 | global driver 123 | if driver_manager.ensure_driver_alive(): 124 | driver = driver_manager.driver 125 | return True 126 | return False 127 | 128 | def is_response_complete(): 129 | """Check if the response is complete using multiple methods.""" 130 | try: 131 | # Method 1: Check for the presence of typing indicators 132 | typing_indicators = driver.find_elements(By.XPATH, "//div[contains(@class, 'result-streaming')]") 133 | if not typing_indicators: 134 | logging.info("No typing indicators found") 135 | return True 136 | 137 | # Method 2: Check if the response text has stopped changing 138 | response_container_xpath = "//div[contains(@class, 'markdown prose w-full break-words')]" 139 | current_response = driver.find_elements(By.XPATH, response_container_xpath)[-1].text 140 | time.sleep(2) # Brief wait 141 | new_response = driver.find_elements(By.XPATH, response_container_xpath)[-1].text 142 | if current_response == new_response and current_response != "": 143 | logging.info("Response text has stabilized") 144 | return True 145 | 146 | logging.info("Response still in progress...") 147 | return False 148 | 149 | except Exception as e: 150 | logging.warning(f"Error checking response completion: {str(e)}") 151 | return False 152 | 153 | def make_gpt_request_and_copy(text): 154 | """ 155 | Function to interact with ChatGPT web interface and copy formatted response 156 | Args: 157 | text: Query text to send to ChatGPT 158 | Returns: 159 | str: Formatted response text from clipboard 160 | """ 161 | global driver 162 | 163 | try: 164 | if not ensure_chrome_alive(): 165 | raise Exception("Failed to ensure Chrome is alive") 166 | 167 | logging.info("Starting GPT request process...") 168 | # Initial pause to ensure page is loaded 169 | time.sleep(1.5) 170 | 171 | try: 172 | # 1. Check for "Stay logged out" button first 173 | logging.info("Step 1a: Checking for 'Stay logged out' button...") 174 | try: 175 | stay_logged_out_xpath = "//a[contains(text(), 'Stay logged out')]" 176 | if helper_fn.is_element_present(stay_logged_out_xpath, timeout=1): 177 | logging.info("'Stay logged out' button found, clicking it...") 178 | helper_fn.click_element(stay_logged_out_xpath) 179 | time.sleep(1) 180 | logging.info("Clicked 'Stay logged out'") 181 | except Exception as logout_error: 182 | logging.warning(f"Stay logged out check encountered an error: {str(logout_error)}") 183 | 184 | # 1b. Text input logic 185 | logging.info("Step 1b: Finding text input area...") 186 | text_area_xpath = "//*[@id='prompt-textarea']" 187 | if helper_fn.send_keys(text_area_xpath, text): 188 | logging.info("Text input successful") 189 | else: 190 | raise Exception("Failed to input text") 191 | 192 | except Exception as e: 193 | logging.error(f"Error in Step 1 (Text Input): {str(e)}") 194 | raise 195 | 196 | try: 197 | # 2. Find and click send button 198 | logging.info("Step 2: Finding and clicking send button...") 199 | send_btn_xpath = "//*[@data-testid='send-button']" 200 | if helper_fn.click_element(send_btn_xpath): 201 | logging.info("Send button clicked") 202 | else: 203 | raise Exception("Failed to click send button") 204 | 205 | except Exception as e: 206 | logging.error(f"Error in Step 2 (Send Button): {str(e)}") 207 | raise 208 | 209 | try: 210 | # 3. Wait for response container 211 | logging.info("Step 3: Waiting for response container...") 212 | try: 213 | canvas_button_xpath = "//button[contains(., 'Answer in chat instead')]" 214 | if helper_fn.is_element_present(canvas_button_xpath, timeout=5): 215 | logging.info("Canvas mode detected, switching to chat mode...") 216 | helper_fn.click_element(canvas_button_xpath) 217 | time.sleep(2) 218 | logging.info("Switched to chat mode") 219 | else: 220 | logging.info("Already in chat mode") 221 | except Exception as canvas_error: 222 | logging.warning(f"Canvas check encountered an error: {str(canvas_error)}") 223 | 224 | # 4. Wait for response to appear and complete 225 | logging.info("Step 4: Waiting for response...") 226 | try: 227 | # First, wait for response container to appear 228 | response_container_xpath = ( 229 | "//div[contains(@class, " 230 | "'markdown prose dark:prose-invert w-full break-words dark')]" 231 | ) 232 | if helper_fn.wait_for_element(response_container_xpath, timeout=30): 233 | logging.info("Initial response detected") 234 | 235 | # Wait for response completion with timeout 236 | start_time = time.time() 237 | timeout = 180 # 3 minutes timeout 238 | last_length = 0 239 | stable_count = 0 240 | 241 | while time.time() - start_time < timeout: 242 | if not ensure_chrome_alive(): 243 | raise Exception("Chrome driver died during response wait") 244 | 245 | try: 246 | # Get current response 247 | responses = helper_fn.find_elements(response_container_xpath) 248 | if responses: 249 | current_text = responses[-1].text 250 | current_length = len(current_text) 251 | 252 | logging.debug(f"Current response length: {current_length}, Last length: {last_length}") 253 | 254 | # If text length hasn't changed and response seems complete 255 | if current_length > 0 and current_length == last_length: 256 | if is_response_complete(): 257 | stable_count += 1 258 | logging.info(f"Response stable for {stable_count} checks") 259 | if stable_count >= 3: # Require 3 consecutive stable checks 260 | time.sleep(2) # Final verification wait 261 | if current_length == len(responses[-1].text): 262 | logging.info("Response completion confirmed") 263 | break 264 | else: 265 | stable_count = 0 # Reset stable count if response is not complete 266 | else: 267 | stable_count = 0 # Reset stable count if length changed 268 | 269 | last_length = current_length 270 | 271 | except Exception as e: 272 | logging.warning(f"Error while checking response: {str(e)}") 273 | stable_count = 0 # Reset stable count on error 274 | 275 | time.sleep(2) # Increased wait time to reduce CPU usage 276 | 277 | if time.time() - start_time >= timeout: 278 | logging.warning("Response timeout reached") 279 | raise TimeoutException("Response generation timed out") 280 | 281 | else: 282 | raise Exception("Response container not found") 283 | 284 | except TimeoutException as te: 285 | logging.error(f"Timeout while waiting for response: {str(te)}") 286 | raise 287 | except Exception as e: 288 | logging.error(f"Error in Step 4 (Response Detection): {str(e)}") 289 | raise 290 | 291 | # Short wait for UI to stabilize 292 | time.sleep(2) 293 | 294 | except Exception as e: 295 | logging.error(f"Error in Step 3 (Response Container): {str(e)}") 296 | raise 297 | 298 | # 5. Get response text directly 299 | logging.info("Step 5: Getting response text...") 300 | try: 301 | response_elements = helper_fn.find_elements(response_container_xpath) 302 | if response_elements: 303 | last_response = response_elements[-1] 304 | # Use JavaScript to get formatted text 305 | formatted_text = driver.execute_script(""" 306 | var element = arguments[0]; 307 | var text = ''; 308 | var lastWasNewline = false; 309 | var lastWasSpace = false; 310 | 311 | function extractText(node) { 312 | if (node.nodeType === Node.TEXT_NODE) { 313 | var content = node.textContent.trim(); 314 | if (content) { 315 | if (lastWasNewline) { 316 | text += '\\n'; 317 | } 318 | text += content; 319 | lastWasNewline = false; 320 | lastWasSpace = false; 321 | } 322 | } else if (node.nodeName === 'PRE') { 323 | // Handle code blocks 324 | if (lastWasNewline) { 325 | text += '\\n'; 326 | } 327 | text += '```\\n' + node.textContent + '\\n```\\n'; 328 | lastWasNewline = true; 329 | lastWasSpace = false; 330 | } else if (node.nodeName === 'CODE') { 331 | // Handle inline code 332 | text += '`' + node.textContent + '`'; 333 | lastWasNewline = false; 334 | lastWasSpace = false; 335 | } else if (node.nodeName === 'STRONG' || node.nodeName === 'B') { 336 | // Handle bold text 337 | if (!lastWasSpace) { 338 | text += ' '; 339 | } 340 | text += '**' + node.textContent + '**'; 341 | lastWasNewline = false; 342 | lastWasSpace = true; 343 | } else if (node.nodeName === 'EM' || node.nodeName === 'I') { 344 | // Handle italic text 345 | if (!lastWasSpace) { 346 | text += ' '; 347 | } 348 | text += '*' + node.textContent + '*'; 349 | lastWasNewline = false; 350 | lastWasSpace = true; 351 | } else if (node.nodeName === 'BLOCKQUOTE') { 352 | // Handle blockquotes 353 | if (lastWasNewline) { 354 | text += '\\n'; 355 | } 356 | text += '> ' + node.textContent.trim().replace(/\\n/g, '\\n> ') + '\\n'; 357 | lastWasNewline = true; 358 | lastWasSpace = false; 359 | } else if (node.nodeName === 'HR') { 360 | // Handle horizontal rules 361 | if (lastWasNewline) { 362 | text += '\\n'; 363 | } 364 | text += '\\n---\\n\\n'; 365 | lastWasNewline = true; 366 | lastWasSpace = false; 367 | } else if (node.nodeName === 'UL' || node.nodeName === 'OL') { 368 | // Handle lists 369 | if (lastWasNewline) { 370 | text += '\\n'; 371 | } 372 | var items = node.getElementsByTagName('li'); 373 | for (var i = 0; i < items.length; i++) { 374 | text += (node.nodeName === 'OL' ? (i + 1) + '. ' : '- ') + items[i].textContent.trim() + '\\n'; 375 | } 376 | lastWasNewline = true; 377 | lastWasSpace = false; 378 | } else if (node.nodeName === 'P') { 379 | // Handle paragraphs 380 | if (lastWasNewline) { 381 | text += '\\n'; 382 | } 383 | for (var child of node.childNodes) { 384 | extractText(child); 385 | } 386 | text += '\\n'; 387 | lastWasNewline = true; 388 | lastWasSpace = false; 389 | } else if (node.nodeName === 'BR') { 390 | // Handle line breaks 391 | text += '\\n'; 392 | lastWasNewline = true; 393 | lastWasSpace = false; 394 | } else { 395 | // Process child nodes 396 | for (var child of node.childNodes) { 397 | extractText(child); 398 | } 399 | } 400 | } 401 | 402 | extractText(element); 403 | 404 | // Clean up excessive newlines 405 | text = text.replace(/\\n{3,}/g, '\\n\\n'); 406 | 407 | // Ensure proper spacing around horizontal rules 408 | text = text.replace(/\\n---\\n/g, '\\n\\n---\\n\\n'); 409 | 410 | // Clean up any double spaces 411 | text = text.replace(/ +/g, ' '); 412 | 413 | return text.trim(); 414 | """, last_response) 415 | logging.info("Successfully extracted response text") 416 | return formatted_text 417 | else: 418 | raise Exception("No response elements found") 419 | except Exception as e: 420 | logging.error(f"Error extracting response text: {str(e)}") 421 | raise 422 | 423 | except Exception as e: 424 | logging.error(f"Process failed: {str(e)}") 425 | if not ensure_chrome_alive(): 426 | logging.error("Chrome driver died during process") 427 | return f"Error occurred: {str(e)}" 428 | 429 | def cleanup(): 430 | """Clean up resources.""" 431 | driver_manager.quit() 432 | 433 | if __name__ == "__main__": 434 | initialize_chrome() 435 | try: 436 | response = make_gpt_request_and_copy("Hello, how are you?") 437 | print(response) 438 | finally: 439 | cleanup() 440 | -------------------------------------------------------------------------------- /chrome_d_download.py: -------------------------------------------------------------------------------- 1 | from platform import machine 2 | from sys import platform 3 | from typing import Literal 4 | import subprocess, requests, os 5 | import requests, xml.etree.ElementTree as ET 6 | try: 7 | import selenium 8 | except ModuleNotFoundError: 9 | print("No selenium found, Installing selenium, Please Wait!!!") 10 | if platform == "linux": 11 | subprocess.call("pip3 install selenium", shell=True) 12 | if platform == "darwin": 13 | subprocess.call("pip3 install selenium", shell=True) 14 | if platform == "win32": 15 | subprocess.call("pip install selenium", shell=True) 16 | 17 | curPlt = platform 18 | # https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json - download -> chrome -> {versions} 19 | version_dict = {'linux':0, 20 | 'darwin':2, 21 | 'win32':4 22 | } # need to improve this 23 | 24 | def front_version_extractor(vrsn): 25 | vrsn = str(vrsn).split(".") 26 | n_version = "" 27 | for i in range(len(vrsn)-1): 28 | n_version+=vrsn[i] 29 | return n_version 30 | 31 | def get_download_version(c_version): 32 | r = requests.get("https://chromedriver.storage.googleapis.com/?delimiter=/&prefix=") 33 | 34 | version_info = ET.fromstring(r.content) 35 | 36 | for i in version_info.iter('{http://doc.s3.amazonaws.com/2006-03-01}Prefix'): 37 | curr_version = i.text 38 | if curr_version != None: 39 | if front_version_extractor(c_version) == front_version_extractor(curr_version): 40 | return str(curr_version[:-1]) 41 | else: 42 | return str(c_version) 43 | 44 | def json_version_extractor(vrsn): 45 | r = requests.get("https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json") 46 | data = r.json() 47 | 48 | for i in data['versions']: 49 | curr_version = i['version'] 50 | 51 | if curr_version != None: 52 | if front_version_extractor(vrsn) == front_version_extractor(curr_version): 53 | down_link = i['downloads']['chromedriver'][version_dict[curPlt]]['url'] 54 | return (str(curr_version), down_link) 55 | 56 | def versionChk(): 57 | chrome_version = subprocess.run(['google-chrome',' --version'], capture_output=True).stdout.decode().split(" ")[2] # chrome version check 58 | chrome_driver_version = subprocess.run(['./chromedriver',' --version'], capture_output=True).stdout.decode().split(" ")[1] # chromeDriver check 59 | print(get_download_version(chrome_version), get_download_version(chrome_driver_version)) 60 | return get_download_version(chrome_version) == get_download_version(chrome_driver_version) 61 | 62 | 63 | # todl = subprocess.run(['google-chrome',' --version'], capture_output=True).stdout.decode() 64 | # vrsn = (todl.split(" "))[2] 65 | # print(vrsn) 66 | 67 | # print(json_version_extractor(vrsn)) 68 | # print(get_download_version('115.0.5763.0')) 69 | 70 | 71 | def get_chrome_driver_url( 72 | version: str, 73 | platform_type: Literal['mac-x64', 'mac-arm64', 'linux64', 'win32', 'win64'], 74 | ) -> str: 75 | url = 'https://storage.googleapis.com/chrome-for-testing-public' 76 | return f'{url}/{version}/{platform_type}/chromedriver-{platform_type}.zip' 77 | 78 | 79 | def chromeDriverDownloader(): 80 | if curPlt == 'linux': 81 | print("[+] Detected System: Linux") 82 | if not os.path.exists('./chromedriver'): 83 | try: 84 | todl = subprocess.run(['google-chrome',' --version'], capture_output=True).stdout.decode() 85 | vrsn = (todl.split(" "))[2] 86 | 87 | if front_version_extractor(vrsn) == front_version_extractor("115.0.5762.4"): 88 | print("[-]Error Found: manual download required, please download it or update your chrome version!!") 89 | exit(0) 90 | 91 | if front_version_extractor(vrsn) < front_version_extractor("115.0.5763.0"): 92 | print("Downloading Chromedriver for your system of version:",get_download_version(vrsn)) 93 | url = get_chrome_driver_url(get_download_version(vrsn)) 94 | r = requests.get(url, allow_redirects=True) 95 | r.raise_for_status() 96 | 97 | if "chromeDriver_zips" not in os.listdir(): 98 | print("Creating chromeDriver_zips folder") 99 | os.mkdir("chromeDriver_zips") 100 | 101 | open("chromeDriver_zips/chromedriver_linux64.zip","wb").write(r.content) 102 | else: # if version > 115.x.x.x 103 | print("Downloading Chromedriver for your system of version:",json_version_extractor(vrsn)[0]) 104 | url = json_version_extractor(vrsn)[1] 105 | r = requests.get(url, allow_redirects=True) 106 | 107 | if "chromeDriver_zips" not in os.listdir(): 108 | print("Creating chromeDriver_zips folder") 109 | os.mkdir("chromeDriver_zips") 110 | 111 | open("chromeDriver_zips/chromedriver_linux64.zip","wb").write(r.content) 112 | except FileNotFoundError as fnf: 113 | print("[-]Error Found:",fnf) 114 | print("[+] Google Chrome is not installed, Please install it!! - https://www.google.com/chrome/") 115 | exit(0) 116 | except Exception as e: 117 | print("[-]Error Found:",e) 118 | exit(0) 119 | else: 120 | if versionChk(): 121 | print("[+] 'Google Chrome' and 'Chromedriver' Version Matched!!") 122 | else: 123 | # print("[-] chromedriver version not matched, please install it - https://chromedriver.chromium.org/") # rare case 124 | print("Removing old chromedrivers!") 125 | subprocess.run(['rm','chromedriver']) 126 | subprocess.run(['rm','-rf','chromeDriver_zips']) 127 | subprocess.run(['mkdir','chromeDriver_zips']) 128 | chromeDriverDownloader() 129 | if curPlt == 'darwin': 130 | print("[+] Detected System: Apple Mac") 131 | if not os.path.exists('./chromedriver'): 132 | try: 133 | todl = subprocess.run(['google-chrome',' --version'], capture_output=True).stdout.decode() 134 | vrsn = (todl.split(" "))[2] 135 | print("Downloading Chromedriver for your system of version:",get_download_version(vrsn)) 136 | platform_type: Literal['mac-x64', 'mac-arm64'] 137 | if machine() == 'arm64': 138 | # M1/M2... 139 | platform_type = 'mac-arm64' 140 | else: 141 | # Intel chip 142 | platform_type = 'mac-x64' 143 | url = get_chrome_driver_url(vrsn, platform_type) 144 | r = requests.get(url, allow_redirects=True) 145 | r.raise_for_status() 146 | 147 | if "chromeDriver_zips" not in os.listdir(): 148 | print("Creating chromeDriver_zips folder") 149 | os.mkdir("chromeDriver_zips") 150 | 151 | open("chromeDriver_zips/chromedriver_mac64.zip","wb").write(r.content) 152 | except FileNotFoundError as fnf: 153 | print("[-]Error Found:",fnf) 154 | print( 155 | "[+] Google Chrome is not installed (https://www.google.com/chrome/), " 156 | "or not included in the system PATH" 157 | ) 158 | exit(0) 159 | else: 160 | if versionChk(): 161 | print("'Google Chrome' and 'Chromedriver' Version Matched!!") 162 | else: 163 | # print("[-] chromedriver version not matched, please install it - https://chromedriver.chromium.org/") # rare case 164 | print("Removing old chromedrivers!") 165 | subprocess.run(['rm','chromedriver']) 166 | subprocess.run(['rm','-rf','chromeDriver_zips']) 167 | subprocess.run(['mkdir','chromeDriver_zips']) 168 | chromeDriverDownloader() 169 | if curPlt == 'win32': 170 | print("[+] Detected System: Windows") 171 | if not os.path.exists('./chromedriver'): 172 | try: 173 | todl = os.popen('reg query "HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon" /v version') 174 | vrsn = todl.read().split(" ")[-1].strip() 175 | print("Downloading Chromedriver for your system of version:",get_download_version(vrsn)) 176 | url = get_chrome_driver_url(get_download_version(vrsn), 'win32') 177 | r = requests.get(url, allow_redirects=True) 178 | r.raise_for_status() 179 | 180 | if "chromeDriver_zips" not in os.listdir(): 181 | print("Creating chromeDriver_zips folder") 182 | os.mkdir("chromeDriver_zips") 183 | 184 | open("chromeDriver_zips/chromedriver_win32.zip","wb").write(r.content) 185 | except FileNotFoundError as fnf: 186 | print("[-]Error Found:",fnf) 187 | print("[+] Google Chrome is not installed, Please install it!! - https://www.google.com/chrome/") 188 | exit(0) 189 | else: 190 | if versionChk(): 191 | print("'Google Chrome' and 'Chromedriver' Version Matched!!") 192 | else: 193 | # print("[-] chromedriver version not matched, please install it - https://chromedriver.chromium.org/") # rare case 194 | print("Removing old chromedrivers!") 195 | subprocess.run(['del','chromedriver']) 196 | subprocess.run(['rmdir','/S','/Q','chromeDriver_zips']) 197 | subprocess.run(['mkdir','chromeDriver_zips']) 198 | chromeDriverDownloader() 199 | chromeDriverDownloader() 200 | 201 | subprocess.call 202 | 203 | print("Unzipping chromedriver") 204 | 205 | from unzipper import * 206 | -------------------------------------------------------------------------------- /chrome_handler.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import time 4 | import sys 5 | import platform 6 | 7 | def get_chrome_path(): 8 | os_name = platform.system().lower() 9 | 10 | if os_name == "darwin": 11 | return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 12 | 13 | elif os_name == "windows": 14 | chrome_32bit_path = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" 15 | chrome_64bit_path = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" 16 | 17 | if os.path.exists(chrome_32bit_path): 18 | return chrome_32bit_path 19 | elif os.path.exists(chrome_64bit_path): 20 | return chrome_64bit_path 21 | else: 22 | raise FileNotFoundError("Chrome executable not found in either 32-bit or 64-bit directories.") 23 | 24 | elif os_name == "linux": 25 | return "/usr/bin/google-chrome" 26 | 27 | else: 28 | raise Exception(f"Unsupported OS: {os_name}") 29 | 30 | def start_chrome(): 31 | chrome_path = get_chrome_path() 32 | subprocess.Popen([f'{chrome_path}','--remote-debugging-port=9222','--user-data-dir=chromedata'],stdout = subprocess.PIPE, stderr = subprocess.PIPE) 33 | 34 | def kill_chrome(): 35 | subprocess.run(['killall','chrome']) 36 | 37 | if __name__ == "__main__": 38 | if sys.argv[1] == "s": 39 | start_chrome() 40 | elif sys.argv[1] == "k": 41 | kill_chrome() -------------------------------------------------------------------------------- /dev_notes: -------------------------------------------------------------------------------- 1 | any type of stractrace error like : 2 | Stacktrace: 3 | GetHandleVerifier [0x0104EC13+23731] 4 | (No symbol) [0x00FD4FD0] 5 | BaseThreadInitThunk [0x772BFCC9+25] 6 | RtlGetAppContainerNamedObjectPath [0x7748806E+238] 7 | 8 | Shows that the synchronous code, at that specific moment, can't find the element, so it's failing 9 | Solution : Delay the timer a more, or check if the x-path is correct, or check the browser - if any overlayfrom the chatgpt is there or not, or the chrome / chatgpt has went to power saving mode so we need to focus to the tab 10 | 11 | needs to add error fixes and retry to the query... 12 | 13 | 14 | ------------- 15 | 16 | # 4. Wait for response to appear and complete 17 | print("Step 4: Waiting for response...") 18 | try: 19 | # First, wait for initial response 20 | response_container_xpath = "//div[contains(@class, 'markdown prose w-full break-words')]" 21 | initial_response = WebDriverWait(driver, 30).until( 22 | EC.presence_of_element_located((By.XPATH, response_container_xpath)) 23 | ) 24 | 25 | print("✓ Initial response detected") 26 | 27 | # Function to check if response is complete 28 | def is_response_complete(): 29 | try: 30 | # Method 1: Check if the send button is enabled again 31 | send_button = driver.find_element(By.XPATH, "//*[@data-testid='send-button']") 32 | if send_button.is_enabled(): 33 | return True 34 | 35 | # Method 2: Check for the presence of typing indicators 36 | typing_indicators = driver.find_elements(By.XPATH, "//div[contains(@class, 'result-streaming')]") 37 | if not typing_indicators: 38 | return True 39 | 40 | # Method 3: Check if the response text has stopped changing 41 | current_response = driver.find_elements(By.XPATH, response_container_xpath)[-1].text 42 | time.sleep(2) # Brief wait 43 | new_response = driver.find_elements(By.XPATH, response_container_xpath)[-1].text 44 | return current_response == new_response and current_response != "" 45 | 46 | except Exception as e: 47 | return False 48 | 49 | # Wait for response completion with timeout 50 | start_time = time.time() 51 | timeout = 180 # 3 minutes timeout 52 | last_length = 0 53 | 54 | while time.time() - start_time < timeout: 55 | try: 56 | # Get current response 57 | responses = driver.find_elements(By.XPATH, response_container_xpath) 58 | if responses: 59 | current_text = responses[-1].text 60 | current_length = len(current_text) 61 | 62 | # If text length hasn't changed for 5 seconds and response seems complete 63 | if current_length > 0 and current_length == last_length and is_response_complete(): 64 | time.sleep(5) # Final verification wait 65 | if current_length == len(responses[-1].text): 66 | break 67 | 68 | last_length = current_length 69 | 70 | 71 | except Exception as e: 72 | print(f"Warning: Error while checking response: {str(e)}") 73 | 74 | time.sleep(1) # Prevent excessive CPU usage 75 | 76 | print("✓ Response completion confirmed") 77 | 78 | # else: # Timeout occurred 79 | # raise TimeoutException("Response generation timed out") 80 | 81 | except TimeoutException as te: 82 | print(f"Timeout while waiting for response: {str(te)}") 83 | raise 84 | except Exception as e: 85 | print(f"❌ Error in Step 4 (Response Detection): {str(e)}") 86 | raise 87 | 88 | 89 | 90 | # Short wait for UI to stabilize 91 | time.sleep(2) 92 | 93 | ------------------------------------- 94 | -------------------------------------------------------------------------------- /helper_fn.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.support.ui import WebDriverWait 2 | from selenium.webdriver.support import expected_conditions as EC 3 | from selenium.webdriver.common.by import By 4 | from selenium.common.exceptions import TimeoutException, NoSuchElementException 5 | import logging 6 | from selenium.webdriver.common.keys import Keys 7 | 8 | # Global variables 9 | driver = None 10 | DEFAULT_TIMEOUT = 10 11 | 12 | def set_driver(webdriver): 13 | """Set the global driver instance.""" 14 | global driver 15 | driver = webdriver 16 | 17 | def wait_for_element(xpath, timeout=DEFAULT_TIMEOUT): 18 | """Wait for an element to be present and visible.""" 19 | try: 20 | element = WebDriverWait(driver, timeout).until( 21 | EC.presence_of_element_located((By.XPATH, xpath)) 22 | ) 23 | return element 24 | except TimeoutException: 25 | logging.warning(f"Timeout waiting for element: {xpath}") 26 | return None 27 | except Exception as e: 28 | logging.error(f"Error waiting for element {xpath}: {str(e)}") 29 | return None 30 | 31 | def is_element_present(xpath, timeout=DEFAULT_TIMEOUT): 32 | """Check if an element is present on the page.""" 33 | try: 34 | WebDriverWait(driver, timeout).until( 35 | EC.presence_of_element_located((By.XPATH, xpath)) 36 | ) 37 | return True 38 | except (TimeoutException, NoSuchElementException): 39 | return False 40 | except Exception as e: 41 | logging.error(f"Error checking element presence {xpath}: {str(e)}") 42 | return False 43 | 44 | def find_element(xpath, timeout=DEFAULT_TIMEOUT): 45 | """Find an element by xpath with wait.""" 46 | try: 47 | element = WebDriverWait(driver, timeout).until( 48 | EC.presence_of_element_located((By.XPATH, xpath)) 49 | ) 50 | return element 51 | except TimeoutException: 52 | logging.warning(f"Element not found: {xpath}") 53 | return None 54 | except Exception as e: 55 | logging.error(f"Error finding element {xpath}: {str(e)}") 56 | return None 57 | 58 | def find_elements(xpath, timeout=DEFAULT_TIMEOUT): 59 | """Find all elements matching xpath with wait.""" 60 | try: 61 | elements = WebDriverWait(driver, timeout).until( 62 | EC.presence_of_all_elements_located((By.XPATH, xpath)) 63 | ) 64 | return elements 65 | except TimeoutException: 66 | logging.warning(f"No elements found: {xpath}") 67 | return [] 68 | except Exception as e: 69 | logging.error(f"Error finding elements {xpath}: {str(e)}") 70 | return [] 71 | 72 | def click_element(xpath, timeout=DEFAULT_TIMEOUT): 73 | """Click an element with wait and retry.""" 74 | try: 75 | element = WebDriverWait(driver, timeout).until( 76 | EC.element_to_be_clickable((By.XPATH, xpath)) 77 | ) 78 | element.click() 79 | return True 80 | except Exception as e: 81 | logging.error(f"Error clicking element {xpath}: {str(e)}") 82 | try: 83 | # Fallback to JavaScript click 84 | element = find_element(xpath) 85 | if element: 86 | driver.execute_script("arguments[0].click();", element) 87 | return True 88 | except Exception as js_error: 89 | logging.error(f"JavaScript click failed for {xpath}: {str(js_error)}") 90 | return False 91 | 92 | def send_keys(xpath, text, timeout=DEFAULT_TIMEOUT): 93 | """Send keys to an element with wait using clipboard to handle non-BMP characters.""" 94 | try: 95 | element = WebDriverWait(driver, timeout).until( 96 | EC.presence_of_element_located((By.XPATH, xpath)) 97 | ) 98 | element.clear() 99 | element.send_keys(text) 100 | return True 101 | except Exception as e: 102 | logging.error(f"Error sending keys to element {xpath}: {str(e)}") 103 | return False 104 | 105 | def wait_for_text_present(xpath, text, timeout=DEFAULT_TIMEOUT): 106 | """Wait for text to be present in element.""" 107 | try: 108 | return WebDriverWait(driver, timeout).until( 109 | EC.text_to_be_present_in_element((By.XPATH, xpath), text) 110 | ) 111 | except TimeoutException: 112 | logging.warning(f"Text '{text}' not found in element: {xpath}") 113 | return False 114 | except Exception as e: 115 | logging.error(f"Error waiting for text in element {xpath}: {str(e)}") 116 | return False 117 | 118 | def wait_for_element_invisible(xpath, timeout=DEFAULT_TIMEOUT): 119 | """Wait for an element to become invisible.""" 120 | try: 121 | return WebDriverWait(driver, timeout).until( 122 | EC.invisibility_of_element_located((By.XPATH, xpath)) 123 | ) 124 | except TimeoutException: 125 | logging.warning(f"Element still visible: {xpath}") 126 | return False 127 | except Exception as e: 128 | logging.error(f"Error waiting for element invisibility {xpath}: {str(e)}") 129 | return False 130 | 131 | def get_element_text(xpath, timeout=DEFAULT_TIMEOUT): 132 | """Get text from an element with wait.""" 133 | try: 134 | element = WebDriverWait(driver, timeout).until( 135 | EC.presence_of_element_located((By.XPATH, xpath)) 136 | ) 137 | return element.text 138 | except Exception as e: 139 | logging.error(f"Error getting text from element {xpath}: {str(e)}") 140 | return None 141 | 142 | def is_element_enabled(xpath, timeout=DEFAULT_TIMEOUT): 143 | """Check if an element is enabled.""" 144 | try: 145 | element = WebDriverWait(driver, timeout).until( 146 | EC.presence_of_element_located((By.XPATH, xpath)) 147 | ) 148 | return element.is_enabled() 149 | except Exception as e: 150 | logging.error(f"Error checking if element is enabled {xpath}: {str(e)}") 151 | return False 152 | 153 | def scroll_into_view(xpath, timeout=DEFAULT_TIMEOUT): 154 | """Scroll element into view.""" 155 | try: 156 | element = WebDriverWait(driver, timeout).until( 157 | EC.presence_of_element_located((By.XPATH, xpath)) 158 | ) 159 | driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", element) 160 | return True 161 | except Exception as e: 162 | logging.error(f"Error scrolling element into view {xpath}: {str(e)}") 163 | return False 164 | -------------------------------------------------------------------------------- /helper_funcs.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.common.exceptions import NoSuchElementException 3 | from selenium.common.exceptions import TimeoutException 4 | from selenium.webdriver.common.by import By 5 | from selenium.webdriver.support import expected_conditions as EC 6 | from selenium.webdriver.support.ui import WebDriverWait 7 | import logging 8 | 9 | logging.basicConfig(format='%(asctime)s - %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') 10 | 11 | # logging.basicConfig(format='%(asctime)s - %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', 12 | # level=logging.INFO) # For logging to console, Debugging purposes. 13 | 14 | class HelperFn: 15 | def __init__(self, driver): 16 | self.driver = driver 17 | 18 | def wait_for_element(self, xpath, timeout=22): 19 | try: 20 | WebDriverWait(self.driver, timeout).until(EC.presence_of_element_located((By.XPATH, xpath))) 21 | logging.info("# Element '%s' is present." % xpath) 22 | except TimeoutException: 23 | logging.error("# Element '%s' is not present." % xpath) 24 | 25 | def is_element_present(self, xpath): 26 | try: 27 | self.driver.find_element(By.XPATH, xpath) 28 | logging.info("# Element '%s' is present." % xpath) 29 | except NoSuchElementException: 30 | logging.error("# Element '%s' is not present." % xpath) 31 | return False 32 | return True 33 | 34 | def wait_for_element_visible(self, xpath, timeout=22): 35 | try: 36 | WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located((By.XPATH, xpath))) 37 | logging.info("# Element '%s' is visible." % xpath) 38 | except TimeoutException: 39 | logging.error("# Element '%s' is not visible." % xpath) 40 | 41 | def is_element_visible(self, xpath): 42 | try: 43 | logging.info("# Element '%s' is visible." % xpath) 44 | return self.driver.find_element(By.XPATH, xpath).is_displayed() 45 | except NoSuchElementException: 46 | logging.error("# Element '%s' is not visible." % xpath) 47 | return False 48 | 49 | def find_element(self, xpath): 50 | try: 51 | element = self.driver.find_element(By.XPATH, xpath) 52 | logging.info("# Element '%s' is found." % xpath) 53 | except NoSuchElementException: 54 | logging.error("# Element '%s' is not found." % xpath) 55 | return False 56 | return element 57 | 58 | def find_elements(self, xpath): 59 | try: 60 | elements = self.driver.find_elements(By.XPATH, xpath) 61 | logging.info("# Element '%s' is found." % xpath) 62 | except NoSuchElementException: 63 | logging.error("# Element '%s' is not found." % xpath) 64 | return False 65 | return elements 66 | 67 | def wait_for_x_seconds(self, seconds): 68 | logging.info("# Waiting for %s seconds." % seconds) 69 | self.driver.implicitly_wait(seconds) 70 | logging.info("# Done waiting for %s seconds." % seconds) -------------------------------------------------------------------------------- /req.txt: -------------------------------------------------------------------------------- 1 | selenium>=4.10.0 2 | requests>=2.31.0 3 | undetected-chromedriver 4 | Flask 5 | flask-restful 6 | Flask-AutoIndex 7 | setuptools 8 | 9 | ngrok 10 | firebase_admin 11 | pymongo[srv]==3.11.1 12 | python-dotenv 13 | -------------------------------------------------------------------------------- /testing_apis.py: -------------------------------------------------------------------------------- 1 | from api_backend import load_chrome, start_chat_gpt, make_gpt_request, stop_chat_gpt 2 | 3 | start_chat_gpt() 4 | a = make_gpt_request("This just a test promt for the prosing") 5 | print(a) 6 | stop_chat_gpt() -------------------------------------------------------------------------------- /unzipper.py: -------------------------------------------------------------------------------- 1 | from zipfile import ZipFile 2 | from sys import platform 3 | import os 4 | import subprocess 5 | 6 | def move_to_base_project(): 7 | if platform == "linux" or platform == "darwin": 8 | subprocess.call("mv chromedriver*/* .",shell=True) 9 | if platform == "win32": 10 | subprocess.call("move chromedriver*\\* .",shell=True) 11 | 12 | def sys_chk_with_path(): 13 | if platform == "linux": 14 | with ZipFile("chromeDriver_zips/chromedriver_linux64.zip") as toUnzip: 15 | toUnzip.extractall('.') 16 | move_to_base_project() 17 | subprocess.call("chmod +x chromedriver",shell=True) 18 | if platform == "win32": 19 | with ZipFile("chromeDriver_zips\\chromedriver_win32.zip") as toUnzip: 20 | toUnzip.extractall('.') 21 | move_to_base_project() 22 | if platform == "darwin": 23 | with ZipFile("chromeDriver_zips/chromedriver_mac64.zip") as toUnzip: 24 | toUnzip.extractall('.') 25 | move_to_base_project() 26 | subprocess.call("chmod +x chromedriver",shell=True) 27 | 28 | if platform == "linux" or platform == "darwin": 29 | if "chromedriver" not in os.listdir(): 30 | sys_chk_with_path() 31 | if platform == "win32": 32 | if "chromedriver.exe" not in os.listdir(): 33 | sys_chk_with_path() 34 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import ngrok 2 | from datetime import datetime 3 | import firebase_admin 4 | import os 5 | import certifi 6 | from pymongo import MongoClient 7 | from dotenv import load_dotenv 8 | load_dotenv() 9 | 10 | BASE_CURR_FILE_PATH = os.path.dirname(os.path.abspath(__file__)) 11 | 12 | class mongo_db_connection(): 13 | def __init__(self, db_name): 14 | self.uri = os.getenv("MONGO_URI") 15 | self.ca = certifi.where() 16 | self.client = MongoClient(self.uri, tlsCAFile=self.ca) 17 | try: 18 | self.client.admin.command('ping') 19 | print("Pinged your deployment. You successfully connected to MongoDB!") 20 | except Exception as e: 21 | print(e) 22 | 23 | self.db = self.client[db_name] 24 | 25 | def insert_one(self, collection_name, item): 26 | collection = self.db[collection_name] 27 | mongo_id = collection.insert_one(item) 28 | return mongo_id.inserted_id 29 | 30 | def get_all(self, collection_name): 31 | collection = self.db[collection_name] 32 | all_items = collection.find() 33 | return all_items 34 | 35 | def delete_item(self, collection_name, item): 36 | collection = self.db[collection_name] 37 | collection.delete_one(item) 38 | 39 | def find_one_by_uiqu_id(self, collection_name, id): 40 | all_items = self.get_all(collection_name) 41 | for item in all_items: 42 | if id in item: 43 | return item 44 | return None 45 | 46 | def is_uiqu_id_exist(self, collection_name, id): 47 | all_items = self.get_all(collection_name) 48 | for item in all_items: 49 | if id in item: 50 | return True 51 | return False 52 | 53 | def update_by_mongo_id(self, collection_name, mongo_id, new_json): 54 | collection = self.db[collection_name] 55 | collection.update_one({"_id": mongo_id}, {"$set": new_json}) 56 | 57 | 58 | def update_remote_ip_ngrok_mongo(db_name, collection, port, currStatus=0): 59 | """ 60 | currStatus: 1 to start server 61 | 0 to stop server 62 | """ 63 | 64 | conn = mongo_db_connection(db_name) 65 | 66 | ##getting all data 67 | for i in conn.get_all(collection): 68 | mongo_id = i['_id'] 69 | 70 | if currStatus == 1: 71 | listner = ngrok.forward(addr="localhost:"+str(port),authtoken=os.getenv("NGROK_AUTH_TOKEN")) 72 | 73 | 74 | conn.update_by_mongo_id(collection, mongo_id, {"ip_ep": listner.url(), "time": datetime.now(), "type": "server", "status": 1}) 75 | 76 | print(listner.url()) 77 | else: 78 | conn = mongo_db_connection(db_name) 79 | 80 | ##getting all data 81 | for i in conn.get_all(collection): 82 | mongo_id = i['_id'] 83 | 84 | conn.update_by_mongo_id(collection, mongo_id, {"status": 0}) 85 | 86 | 87 | --------------------------------------------------------------------------------