import os import sys from dotenv import load_dotenv from selenium import webdriver from selenium.webdriver.chrome.service import Service as ChromeService from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from webdriver_manager.chrome import ChromeDriverManager # Loading the .env file load_dotenv() GITHUB_USERNAME = os.environ.get('GITHUB_USERNAME', '') GITHUB_PASSWORD = os.environ.get('GITHUB_PASSWORD', '') SKIP_COUNT = int(sys.argv[1] if len(sys.argv) > 1 else '0') FETCH_COUNT = int(sys.argv[2] if len(sys.argv) > 2 else '100') sys.tracebacklimit = 0 # Set up the WebDriver service = ChromeService(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) wait = WebDriverWait(driver, 10) def login_with_github(): driver.get('http://localhost/#/login') # Replace with your actual login page URL try: print("Waiting for the GitHub login button to be clickable...") github_button = wait.until( EC.element_to_be_clickable((By.XPATH, '//*[@id="root"]/main/div/button[2]/span[1]')) ) print("GitHub login button is clickable now.") github_button.click() print("Clicked the GitHub login button.") print("Waiting for GitHub login page to load...") wait.until( EC.presence_of_element_located((By.ID, 'login_field')) ) print("GitHub login page loaded.") username_field = driver.find_element(By.ID, 'login_field') username_field.send_keys(GITHUB_USERNAME) password_field = driver.find_element(By.ID, 'password') password_field.send_keys(GITHUB_PASSWORD) sign_in_button = driver.find_element(By.NAME, 'commit') sign_in_button.click() print("Submitted GitHub login form.") except Exception as e: print(f"An error occurred during GitHub login: {str(e)}") sys.exit(1) # Wait for the Send SMS page try: print("Waiting for the Send SMS button to be clickable...") send_sms_button = wait.until( EC.presence_of_element_located((By.XPATH, '//*[@id="login"]/div[2]/div[2]/form/button')) ) print("Send SMS button is clickable now.") send_sms_button.click() print("Clicked the Send SMS button.") except Exception: print("No Send SMS page detected or an error occurred") # Wait for the 2FA page try: print("Waiting for the 2FA page...") wait.until( EC.presence_of_element_located((By.XPATH, '//*[@id="sms_totp"]')) ) print("2FA page loaded. Please complete the 2FA process manually.") # Pause the script until the user completes the 2FA process input("Complete the 2FA process and press Enter to continue...") # Verification process should be completed by now print("2FA process completed.") except Exception: print("No 2FA page detected or an error occurred") try: print("Waiting for authorization page to load...") authorize_button = wait.until( EC.element_to_be_clickable((By.NAME, 'authorize')) ) authorize_button.click() print("Clicked authorize button.") except Exception: print("An error occurred during GitHub authorization") def wait_for_gallery_load(): try: # Wait until the `window.loadGalleryComplete` flag is set to true wait.until(lambda driver: driver.execute_script('return window.loadGalleryComplete === true;')) except Exception as e: print(f"Error waiting for gallery load: {str(e)}") def main(): login_with_github() # After logging in, navigate to the gallery page driver.get("http://localhost/#/gallery") try: wait.until(EC.presence_of_element_located((By.CLASS_NAME, "MuiSelect-root"))) select = driver.find_element(By.CLASS_NAME, "MuiSelect-root") select.click() option = driver.find_element(By.XPATH, "//li[contains(text(), 'All Books')]") option.click() # Wait until the gallery page is loaded wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "a[target='_blank'][href*='/editor?id=']"))) # Find all "Launch in Editor" buttons buttons = driver.find_elements(By.CSS_SELECTOR, "a[target='_blank'][href*='/editor?id=']") count = len(buttons) print(f"Found {count} 'Launch in Editor' buttons.") savecount = 0 # Click each "Launch in Editor" button and save for i, button in enumerate(buttons): if i == SKIP_COUNT - 1: print(f"[{i + 1:3d}/{count}]: Skipping ") continue if i < SKIP_COUNT: continue if savecount >= FETCH_COUNT: print(f"[{i + 1:3d}/{count}]: Skipping ") break button.click() driver.switch_to.window(driver.window_handles[-1]) # Switch to the newly opened editor tab/window try: state = 0 # Wait for the page to load and the Save button to be clickable save_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="root"]/div/header/div[2]/div[1]/button[2]'))) state += 1 # Wait for the gallery to fully load wait_for_gallery_load() state += 1 # Click the "Save" button ActionChains(driver).move_to_element(save_button).click().perform() state += 1 # Optionally, you can verify the snackbar message if needed wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "MuiSnackbar-root"))) state += 1 # Verify the share button is displayed wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="root"]/div/header/div[1]/button[2]'))) state += 1 # Verify the "last saved" text is displayed last_saved_text = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="root"]/div/header/div[1]/p'))) state += 1 savecount += 1 print(f"[{i + 1:3d}/{count}]: {last_saved_text.text}") except Exception: print(f"[{i + 1:3d}/{count}]: Error while saving diagram {state}") # Close the editor tab/window and switch back to the gallery driver.close() driver.switch_to.window(driver.window_handles[0]) # Keep the browser window open except Exception as e: print(f"Error while saving diagram: {str(e)}") finally: print(f"[{savecount:3d}/{count}] 'Launch in Editor' buttons have been clicked and saved.") # Keep the browser open until manually closed input("Press Enter to close the browser...") driver.quit() if __name__ == "__main__": main()