Skip to content

Instantly share code, notes, and snippets.

@ericswpark
Created August 28, 2025 20:02
Show Gist options
  • Select an option

  • Save ericswpark/d405fa6fe50885e7b2bb3b2360542316 to your computer and use it in GitHub Desktop.

Select an option

Save ericswpark/d405fa6fe50885e7b2bb3b2360542316 to your computer and use it in GitHub Desktop.
import os
import datetime
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from dotenv import load_dotenv
RETRY_MAX_COUNT = 30
RETRY_WAIT_SEC = 2
def retry_action(func, func_name):
for _ in range(RETRY_MAX_COUNT):
result = func()
if result:
return result
print(f"Error: function {func_name} did not succeed. Trying again...")
time.sleep(RETRY_WAIT_SEC)
def get_shadow_input(driver, outer_element_id):
def get_shadow_input_inner():
outer = driver.find_element(By.ID, outer_element_id)
return driver.execute_script("return arguments[0].shadowRoot.querySelector('input')", outer)
retry_action(get_shadow_input_inner, f"get_shadow_input | {outer_element_id}")
def get_shadow_button(driver, button_id):
def get_shadow_button_inner():
outer = driver.find_element(By.ID, button_id)
return driver.execute_script("return arguments[0].shadowRoot.querySelector('button'), arguments[0]", outer)[0] or outer
retry_action(get_shadow_button_inner, f"get_shadow_button | {button_id}")
def login(driver, wait, username, password):
# Username
wait.until(EC.presence_of_element_located((By.ID, "login-form_username")))
user_input = get_shadow_input(driver, "login-form_username")
user_input.send_keys(username)
# Next
wait.until(EC.presence_of_element_located((By.ID, "verifUseridBtn")))
next_button = driver.find_element(By.ID, "verifUseridBtn")
driver.execute_script("arguments[0].click();", next_button)
# Password
wait.until(EC.presence_of_element_located((By.ID, "login-form_password")))
pass_input = get_shadow_input(driver, "login-form_password")
pass_input.send_keys(password)
# Sign in
wait.until(EC.presence_of_element_located((By.ID, "signBtn")))
sign_in_btn = driver.find_element(By.ID, "signBtn")
driver.execute_script("arguments[0].click();", sign_in_btn)
def find_sdf_button(driver, wait, title):
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, f"sdf-button[title='{title}']")))
return driver.find_element(By.CSS_SELECTOR, f"sdf-button[title='{title}']")
def clock_in(driver, wait):
clock_in_button = find_sdf_button(driver, wait, "Clock In")
driver.execute_script("arguments[0].click();", clock_in_button)
print("✅ Successfully Clocked In!")
def clock_out(driver, wait):
clock_out_button = find_sdf_button(driver, wait, "Clock Out")
driver.execute_script("arguments[0].click();", clock_out_button)
print("✅ Successfully Clocked Out!")
def auto_clock(driver, wait):
now = datetime.datetime.now()
hour = now.hour
minute = now.minute
time_str = now.strftime("%I:%M %p")
print(f"🕒 Current time: {time_str}")
# Between 7:00 AM and 11:00 AM → Clock in
if 7 <= hour < 11:
clock_in(driver=driver, wait=wait)
# Between 5:30 PM and 6:00 PM → Ask user if they want to clock out early
elif hour == 17 and minute >= 30:
minutes_left = 60 - minute
choice = input(f"⏳ There's still {minutes_left} minutes left until 6 PM. Clock out anyway? (y/n): ").strip().lower()
if choice == 'y':
clock_out(driver=driver, wait=wait)
else:
print("⚠️ Keeping you clocked in.")
# Between 6:00 PM and 12:59 AM → Clock out
elif (hour >= 18 and hour <= 23) or (hour >= 0 and hour < 1):
clock_out(driver=driver, wait=wait)
# Other times → Ask the user what to do
else:
choice = input("❓Time is ambiguous. Would you like to clock in (i) or clock out (o)? ").strip().lower()
if choice == 'i':
clock_in(driver=driver, wait=wait)
elif choice == 'o':
clock_out(driver=driver, wait=wait)
else:
print("⚠️ No action taken.")
def main():
# Load .env for credentials
load_dotenv()
USERNAME = os.getenv("ADP_USER")
PASSWORD = os.getenv("ADP_PASS")
if not USERNAME or not PASSWORD:
raise ValueError("Set ADP_USER and ADP_PASS in your .env file")
# Edge WebDriver path
#EDGEDRIVER_PATH = "C:/path/to/msedgedriver.exe" # Update this
# Set up Edge driver
#service = EdgeService(executable_path=EDGEDRIVER_PATH)
service = EdgeService()
options = webdriver.EdgeOptions()
driver = webdriver.Edge(service=service, options=options)
wait = WebDriverWait(driver, 120)
try:
# Navigate to initial page
driver.get("https://workforcenow.adp.com/theme/index.html#/home")
# Sign in
login(driver=driver, wait=wait, username=USERNAME, password=PASSWORD)
# Auto clock-in/out based on schedule
auto_clock(driver=driver, wait=wait)
time.sleep(10)
finally:
driver.quit()
if __name__ == "__main__":
main()
selenium
python-dotenv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment